From 29c0cded0557b0f42a33f65d486223efb0935b60 Mon Sep 17 00:00:00 2001 From: fewtarius Date: Sat, 5 Feb 2022 09:23:32 -0500 Subject: [PATCH] JELOS 20220205 - Release --- .dockerignore | 3 + .gitignore | 57 + Dockerfile | 22 + Makefile | 121 + README.md | 61 + config/addon/dummy.xml | 0 config/addon/xbmc.broken.xml | 34 + config/addon/xbmc.python.module.xml | 31 + config/addon/xbmc.python.script.xml | 31 + config/addon/xbmc.service.library.xml | 34 + config/addon/xbmc.service.pluginsource.xml | 33 + config/addon/xbmc.service.xml | 31 + config/arch.aarch64 | 29 + config/arch.arm | 64 + config/arch.x86_64 | 17 + config/blocklist | 2 + config/docker/changelog.txt | 2 + config/docker/package.mk | 30 + config/docker/source/bin/docker | 11 + config/docker/source/default.py | 20 + .../resources/language/English/strings.po | 10 + config/docker/source/resources/settings.xml | 6 + config/docker/source/system.d/docker.service | 14 + config/functions | 1472 + config/graphic | 130 + config/multithread | 165 + config/noobs/marketing/slides/A.png | Bin 0 -> 32028 bytes config/noobs/marketing/slides/B.png | Bin 0 -> 30527 bytes config/noobs/marketing/slides/C.png | Bin 0 -> 36963 bytes config/noobs/marketing/slides/D.png | Bin 0 -> 31986 bytes config/noobs/marketing/slides/E.png | Bin 0 -> 32845 bytes config/noobs/marketing/slides/noobs.psd | Bin 0 -> 503971 bytes config/noobs/marketing/slides_vga/A.png | Bin 0 -> 15194 bytes config/noobs/marketing/slides_vga/B.png | Bin 0 -> 15806 bytes config/noobs/marketing/slides_vga/C.png | Bin 0 -> 18000 bytes config/noobs/marketing/slides_vga/D.png | Bin 0 -> 15769 bytes config/noobs/marketing/slides_vga/E.png | Bin 0 -> 15919 bytes .../noobs/marketing/slides_vga/noobs_vga.psd | Bin 0 -> 303004 bytes config/noobs/os.json | 11 + config/noobs/partition_setup.sh | 53 + config/noobs/partitions.json | 20 + config/optimize | 95 + config/options | 112 + config/path | 108 + config/show_config | 167 + config/sources | 2 + distributions/JELOS/options | 237 + distributions/JELOS/splash/splash-1080.bmp | Bin 0 -> 8294538 bytes distributions/JELOS/splash/splash-1080.png | Bin 0 -> 32788 bytes distributions/JELOS/splash/splash-1152.bmp | Bin 0 -> 8847498 bytes distributions/JELOS/splash/splash-1152.png | Bin 0 -> 27160 bytes distributions/JELOS/splash/splash-1152l.bmp | Bin 0 -> 8847498 bytes distributions/JELOS/splash/splash-1152l.png | Bin 0 -> 28372 bytes distributions/JELOS/splash/splash-480.bmp | Bin 0 -> 614538 bytes distributions/JELOS/splash/splash-480.png | Bin 0 -> 8061 bytes distributions/JELOS/splash/splash-480l.bmp | Bin 0 -> 614538 bytes distributions/JELOS/splash/splash-480l.png | Bin 0 -> 8366 bytes distributions/JELOS/splash/splash-640.bmp | Bin 0 -> 1228938 bytes distributions/JELOS/splash/splash-640.png | Bin 0 -> 10157 bytes licenses/APSL.txt | 339 + licenses/ATI.txt | 188 + licenses/Apache2.txt | 67 + licenses/Artistic.txt | 131 + licenses/BSD.txt | 31 + licenses/BSD_2_Clause.txt | 20 + licenses/BSD_3_Clause.txt | 23 + licenses/BSD_4_Clause.txt | 31 + licenses/BSL.txt | 23 + licenses/CC_BY-NC-SA_4.0.txt | 97 + licenses/FDL.txt | 397 + licenses/FDL1_2.txt | 397 + licenses/FDL1_3.txt | 451 + licenses/GPL.txt | 340 + licenses/GPL2.txt | 340 + licenses/GPL3.txt | 676 + licenses/ISC.txt | 13 + licenses/Info-ZIP.txt | 60 + licenses/LGPL2.txt | 483 + licenses/LGPL2_1.txt | 515 + licenses/LGPL3.txt | 165 + licenses/LibPNG2.txt | 134 + licenses/MIT.txt | 22 + licenses/MIT_Modified.txt | 22 + licenses/MPL1_1.txt | 470 + licenses/NVIDIA.txt | 127 + licenses/OFL1_1.txt | 102 + licenses/Public_Domain.txt | 1 + licenses/Radeon_rlc.txt | 51 + metadata/RG351P/packages.cfg | 11 + metadata/RG351P/packages/blockattack.jpg | Bin 0 -> 36399 bytes metadata/RG351P/packages/cavestory.jpg | Bin 0 -> 33462 bytes metadata/RG351P/packages/cdogs-sdl.jpg | Bin 0 -> 23233 bytes metadata/RG351P/packages/drastic.jpg | Bin 0 -> 27778 bytes metadata/RG351P/packages/f2bgl.jpg | Bin 0 -> 25595 bytes metadata/RG351P/packages/iortcw.jpg | Bin 0 -> 28150 bytes metadata/RG351P/packages/openomf.jpg | Bin 0 -> 31298 bytes metadata/RG351P/packages/retrorun.jpg | Bin 0 -> 22115 bytes metadata/RG351P/packages/rpgmaker.jpg | Bin 0 -> 37014 bytes metadata/RG351P/packages/smw.jpg | Bin 0 -> 31434 bytes metadata/RG351P/packages/solarus.jpg | Bin 0 -> 32114 bytes metadata/RG351P/packages/supertux.jpg | Bin 0 -> 30092 bytes metadata/RG351P/packages/tyrian.jpg | Bin 0 -> 36933 bytes metadata/RG351P/packages/uqm.jpg | Bin 0 -> 37461 bytes metadata/RG351P/themes.cfg | 27 + metadata/RG351P/themes/351Noir.jpg | Bin 0 -> 55220 bytes metadata/RG351P/themes/Airen.jpg | Bin 0 -> 41246 bytes metadata/RG351P/themes/Alekfull.jpg | Bin 0 -> 61149 bytes metadata/RG351P/themes/Alt-Book.jpg | Bin 0 -> 63484 bytes metadata/RG351P/themes/Art-Book.jpg | Bin 0 -> 27575 bytes metadata/RG351P/themes/CRAZYBOY.jpg | Bin 0 -> 47107 bytes metadata/RG351P/themes/Carbon.jpg | Bin 0 -> 36226 bytes metadata/RG351P/themes/Chicuelo.jpg | Bin 0 -> 51947 bytes metadata/RG351P/themes/Comic-Book.jpg | Bin 0 -> 74213 bytes metadata/RG351P/themes/CosmicRise.jpg | Bin 0 -> 64501 bytes metadata/RG351P/themes/Crystal.jpg | Bin 0 -> 50722 bytes metadata/RG351P/themes/EpicBlancheNoir.jpg | Bin 0 -> 36801 bytes metadata/RG351P/themes/EpicCody.jpg | Bin 0 -> 51298 bytes metadata/RG351P/themes/EpicLikeSzalik.jpg | Bin 0 -> 57674 bytes metadata/RG351P/themes/Fundamental.jpg | Bin 0 -> 42466 bytes metadata/RG351P/themes/GBZ.jpg | Bin 0 -> 28205 bytes metadata/RG351P/themes/Handheld-Simple.jpg | Bin 0 -> 34406 bytes metadata/RG351P/themes/Horizontal.jpg | Bin 0 -> 50138 bytes metadata/RG351P/themes/Minimal.jpg | Bin 0 -> 38943 bytes metadata/RG351P/themes/Pixel.jpg | Bin 0 -> 56340 bytes metadata/RG351P/themes/Roleta.jpg | Bin 0 -> 69130 bytes metadata/RG351P/themes/SpinMaster.jpg | Bin 0 -> 60005 bytes metadata/RG351P/themes/SuperSweet.jpg | Bin 0 -> 58047 bytes metadata/RG351P/themes/Supreme.jpg | Bin 0 -> 55651 bytes metadata/RG351P/themes/Switch.jpg | Bin 0 -> 31188 bytes metadata/RG351V/packages.cfg | 11 + metadata/RG351V/packages/blockattack.jpg | Bin 0 -> 36399 bytes metadata/RG351V/packages/cavestory.jpg | Bin 0 -> 33462 bytes metadata/RG351V/packages/cdogs-sdl.jpg | Bin 0 -> 23233 bytes metadata/RG351V/packages/drastic.jpg | Bin 0 -> 27778 bytes metadata/RG351V/packages/f2bgl.jpg | Bin 0 -> 25595 bytes metadata/RG351V/packages/iortcw.jpg | Bin 0 -> 28150 bytes metadata/RG351V/packages/openomf.jpg | Bin 0 -> 31298 bytes metadata/RG351V/packages/retrorun.jpg | Bin 0 -> 22115 bytes metadata/RG351V/packages/rpgmaker.jpg | Bin 0 -> 37014 bytes metadata/RG351V/packages/smw.jpg | Bin 0 -> 31434 bytes metadata/RG351V/packages/solarus.jpg | Bin 0 -> 32114 bytes metadata/RG351V/packages/supertux.jpg | Bin 0 -> 30092 bytes metadata/RG351V/packages/tyrian.jpg | Bin 0 -> 36933 bytes metadata/RG351V/packages/uqm.jpg | Bin 0 -> 37461 bytes metadata/RG351V/themes.cfg | 9 + metadata/RG351V/themes/Art-Book-4-3.jpg | Bin 0 -> 72559 bytes metadata/RG351V/themes/Cody-Destroy.jpg | Bin 0 -> 115968 bytes metadata/RG351V/themes/Epic-Cody.jpg | Bin 0 -> 94203 bytes metadata/RG351V/themes/EpicBlancheNoir-V.jpg | Bin 0 -> 63413 bytes metadata/RG351V/themes/GBZ.jpg | Bin 0 -> 46188 bytes metadata/RG351V/themes/Handheld-Simple.jpg | Bin 0 -> 55697 bytes metadata/RG351V/themes/Kiwi.jpg | Bin 0 -> 88467 bytes metadata/RG351V/themes/Minimal.jpg | Bin 0 -> 62943 bytes .../disable-spdif-for-hd-audio.conf | 16 + .../audio/alsa-lib/modprobe.d/alsa-base.conf | 26 + .../alsa-lib/modprobe.d/intel-audio.conf | 2 + packages/audio/alsa-lib/package.mk | 39 + .../alsa-lib-asound.conf_configdir.patch | 14 + packages/audio/alsa-ucm-conf/package.mk | 22 + packages/audio/alsa-utils/package.mk | 38 + packages/audio/alsa-utils/scripts/soundconfig | 161 + .../alsa-utils/udev.d/90-alsa-restore.rules | 5 + packages/audio/espeak/package.mk | 31 + .../patches/espeak-1.47-ftbs-ld-libm.patch | 23 + .../patches/espeak-1.47-wav-close.patch | 23 + .../patches/espeak-1.48-gcc-6-fix.patch | 12 + packages/audio/flac/package.mk | 37 + packages/audio/fluidsynth/package.mk | 19 + packages/audio/lame/package.mk | 32 + .../patches/lame-3.99.5-am_path_gtk.patch | 233 + .../lame/patches/lame-3.99.5-automake.patch | 46 + packages/audio/libcdio/package.mk | 35 + packages/audio/libmodplug/package.mk | 15 + packages/audio/libogg/package.mk | 14 + packages/audio/libopenmpt/package.mk | 26 + packages/audio/libsamplerate/package.mk | 23 + packages/audio/libsndfile/package.mk | 31 + packages/audio/libvorbis/package.mk | 21 + packages/audio/openal-soft/package.mk | 34 + .../config/pulse-daemon.conf.d/README | 5 + .../pulseaudio/config/pulseaudio-system.conf | 33 + packages/audio/pulseaudio/config/system.pa | 68 + packages/audio/pulseaudio/package.mk | 95 + ...ppend-dirty-to-server-module-version.patch | 24 + .../patches/pulseaudio-100.02-check_uid.patch | 13 + .../pulseaudio/profile.d/99-pulseaudio.conf | 4 + .../pulseaudio/system.d/pulseaudio.service | 12 + .../config/rpi-cirrus-config.sh.sample | 36 + .../modprobe.d/rpi-cirrus.conf | 1 + packages/audio/rpi-cirrus-config/package.mk | 26 + .../scripts/rpi-cirrus-config | 24 + .../udev.d/90-alsa-restore.rules | 17 + packages/audio/sbc/package.mk | 18 + packages/audio/sidplay-libs/package.mk | 22 + .../patches/sidplay-libs-01-m4-tests.patch | 26 + .../patches/sidplay-libs-02-inherited.patch | 26 + .../patches/sidplay-libs-03-operator.patch | 11 + .../patches/sidplay-libs-04-includes.patch | 30 + packages/audio/soxr/package.mk | 28 + ...-Add-Libs.private-for-static-linking.patch | 43 + packages/audio/speex/package.mk | 12 + packages/audio/speexdsp/package.mk | 11 + packages/audio/taglib/package.mk | 25 + ...ID3v2_tag_in_MPEG_files_with_garbage.patch | 72 + packages/compat/lib32/package.mk | 89 + packages/compress/bzip2/package.mk | 56 + .../bzip2/patches/bzip2-1.0.8-cflags.patch | 11 + packages/compress/cpio/package.mk | 11 + .../cpio/patches/0001-Minor-fix.patch | 30 + packages/compress/gzip/package.mk | 13 + packages/compress/libarchive/package.mk | 28 + packages/compress/libzip/package.mk | 20 + packages/compress/lz4/package.mk | 23 + packages/compress/lzo/package.mk | 20 + packages/compress/minizip/package.mk | 19 + packages/compress/p7zip/package.mk | 31 + .../patches/0004-Fix-build-with-gcc-10.patch | 32 + packages/compress/pigz/package.mk | 25 + packages/compress/unzip/package.mk | 23 + packages/compress/xz/package.mk | 29 + .../xz-01-init-uninitialized-variables.patch | 27 + packages/compress/zip/package.mk | 23 + packages/compress/zlib/package.mk | 13 + packages/compress/zstd/package.mk | 23 + .../databases/mariadb-connector-c/package.mk | 24 + packages/databases/mysql/package.mk | 86 + ...-revert-floating-point-optimizations.patch | 38 + ...le-comp_err-even-when-crosscompiling.patch | 18 + ...le-comp_sql-even-when-crosscompiling.patch | 17 + ...char-fix-in-client-authtentification.patch | 11 + packages/databases/sqlite/package.mk | 55 + .../patches/sqlite-01_map_populate.patch | 22 + packages/debug/apitrace/package.mk | 14 + .../debug/apitrace/patches/001-no-x11.patch | 40 + packages/debug/edid-decode/package.mk | 21 + packages/debug/gdb/package.mk | 49 + .../debug/gdb/patches/gdb-001-notex.patch | 12 + packages/debug/libunwind/package.mk | 17 + packages/debug/libva-utils/package.mk | 25 + packages/debug/memtester/package.mk | 21 + .../patches/memtester-001-cross-compile.patch | 34 + packages/debug/valgrind/package.mk | 17 + .../patches/valgrind-0001-enable-armv8.patch | 12 + .../patches/valgrind-0002-no-mpi1.patch | 67 + packages/debug/vdpauinfo/package.mk | 11 + packages/devel/android-headers/package.mk | 12 + packages/devel/apache-ant/package.mk | 29 + packages/devel/arm-mem/package.mk | 47 + packages/devel/attr/package.mk | 33 + packages/devel/autoconf-archive/package.mk | 22 + packages/devel/autoconf/package.mk | 20 + .../autoconf-0100-backport-runstatedir.patch | 59 + .../patches/autoconf-0200-performance.patch | 60 + .../patches/autoconf-autoreconf-exclude.patch | 139 + packages/devel/automake/package.mk | 17 + .../patches/automake-01-fix-help2man.patch | 25 + packages/devel/binutils/package.mk | 82 + ...uses-of-system-directories-when-link.patch | 32 + packages/devel/binutils/patches/nodocs.patch | 12 + packages/devel/bison/package.mk | 22 + packages/devel/boost/package.mk | 60 + packages/devel/ccache/package.mk | 40 + packages/devel/cmake/package.mk | 24 + .../cmake-001-disable-free-comp-methods.patch | 14 + packages/devel/configtools/package.mk | 18 + packages/devel/crossguid/package.mk | 24 + packages/devel/dbus-glib/package.mk | 27 + ...us-glib-01-dont-build-tools-examples.patch | 38 + packages/devel/elfutils/package.mk | 52 + ...futils-001-make-executables-optional.patch | 46 + packages/devel/fakeroot/package.mk | 20 + .../fakeroot-001-disable-docs-tests.patch | 23 + packages/devel/flatbuffers/package.mk | 39 + packages/devel/flex/package.mk | 28 + ...6b17a2b091c560f6c4e6703e55f496bf74fa.patch | 28 + .../devel/flex/patches/flex-002-nocrap.patch | 13 + packages/devel/fribidi/package.mk | 26 + packages/devel/fribidi/scripts/fribidi-config | 13 + packages/devel/gettext/package.mk | 23 + .../gettext-0.18.2-non_interactive.patch | 18 + ...gettext-dont_build_docs_and_examples.patch | 24 + packages/devel/glib/package.mk | 47 + packages/devel/glibc/config/gai.conf | 65 + packages/devel/glibc/config/host.conf | 1 + .../devel/glibc/config/nsswitch-init.conf | 3 + .../devel/glibc/config/nsswitch-target.conf | 19 + packages/devel/glibc/package.mk | 170 + .../glibc-fix-dns-with-broken-routers.patch | 106 + packages/devel/gmp/package.mk | 20 + packages/devel/gnulib/package.mk | 12 + packages/devel/heimdal/package.mk | 35 + ...-upstream-check-libtinfo-for-tgetent.patch | 52 + .../0002-upstream-fix-configure-err-msg.patch | 24 + ...2b90e78e2d162b98b5ef6c84672c397be40a.patch | 29 + ...f6859d183a40fb35a76e2bc1ce084b3a6d67.patch | 22 + ...3f337bac0411d0bb1c924fd857603a258d2f.patch | 22 + .../yyerror-match-posix-standard.patch | 83 + packages/devel/intltool/package.mk | 16 + .../intltool-0001-fix-regex-expressions.patch | 45 + packages/devel/libaio/package.mk | 24 + packages/devel/libcap/package.mk | 70 + packages/devel/libcec-4.0.5/package.mk | 60 + .../cec-framework/libcec-0001-PR380.patch | 887 + packages/devel/libcec-4.0.7/package.mk | 60 + .../cec-framework/libcec-0001-PR380.patch | 887 + packages/devel/libcec/package.mk | 42 + packages/devel/libdaemon/package.mk | 16 + packages/devel/libffi/package.mk | 22 + ...-Fix-installation-location-of-libffi.patch | 50 + .../libffi/patches/libffi-fix-pkgconf.patch | 23 + packages/devel/libfmt/package.mk | 14 + packages/devel/libfstrcmp/package.mk | 23 + packages/devel/libftdi1/package.mk | 30 + packages/devel/libirman/package.mk | 21 + .../libirman-0001-fix-poll-include.patch | 35 + packages/devel/libplist/package.mk | 23 + packages/devel/libpthread-stubs/package.mk | 11 + packages/devel/librga/package.mk | 12 + packages/devel/libsodium/package.mk | 14 + packages/devel/libtool/package.mk | 21 + .../libtool-01_dont_relink_against_host.patch | 13 + .../libtool/patches/libtool-02-use_ld.patch | 13 + ...ibtool-03-remove-help2man-dependency.patch | 26 + packages/devel/m4/package.mk | 17 + packages/devel/make/package.mk | 20 + .../make-01-disable-inheritance-of-fds.patch | 42 + packages/devel/mpc/package.mk | 17 + packages/devel/mpfr/package.mk | 18 + packages/devel/ncurses/package.mk | 75 + .../patches/ncurses-001-terminfo-xterm.patch | 16 + .../patches/ncurses-002-alloc-fallbacks.patch | 24 + packages/devel/parallel/package.mk | 11 + packages/devel/pcre/package.mk | 33 + packages/devel/pcre2/package.mk | 32 + packages/devel/pkg-config/package.mk | 20 + ...01-Add-support-for-multiple-sysroots.patch | 256 + packages/devel/popt/package.mk | 22 + packages/devel/rapidjson/package.mk | 19 + ...pidjson-0001-remove_custom_cxx_flags.patch | 29 + packages/devel/readline/package.mk | 22 + packages/devel/slang/package.mk | 27 + packages/devel/spdlog/package.mk | 14 + packages/devel/swig/package.mk | 44 + packages/devel/yajl/package.mk | 19 + .../PPSSPPSDL/config/PSP/Cheats/NPEG00023.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/NPEG00044.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/NPUG80325.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/UCES00019.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/UCES00842.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/UCES01184.ini | 24 + .../PPSSPPSDL/config/PSP/Cheats/UCES01401.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/UCES01473.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/UCUS98640.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/UCUS98653.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/UCUS98668.ini | 24 + .../PPSSPPSDL/config/PSP/Cheats/UCUS98737.ini | 40 + .../PPSSPPSDL/config/PSP/Cheats/ULES00033.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULES00034.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULES00035.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULES00125.ini | 15 + .../PPSSPPSDL/config/PSP/Cheats/ULES00483.ini | 7 + .../PPSSPPSDL/config/PSP/Cheats/ULES00625.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULES00626.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULES00703.ini | 14 + .../PPSSPPSDL/config/PSP/Cheats/ULES00968.ini | 6 + .../PPSSPPSDL/config/PSP/Cheats/ULES00981.ini | 30 + .../PPSSPPSDL/config/PSP/Cheats/ULES00982.ini | 30 + .../PPSSPPSDL/config/PSP/Cheats/ULES01214.ini | 11 + .../PPSSPPSDL/config/PSP/Cheats/ULES01402.ini | 8 + .../PPSSPPSDL/config/PSP/Cheats/ULES01406.ini | 6 + .../PPSSPPSDL/config/PSP/Cheats/ULUS00125.ini | 15 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10014.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10189.ini | 9 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10197.ini | 10 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10213.ini | 7 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10236.ini | 14 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10328.ini | 6 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10345.ini | 30 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10390.ini | 12 + .../PPSSPPSDL/config/PSP/Cheats/ULUS10507.ini | 6 + .../PSP/SYSTEM/CACHE/UCAS40015.glshadercache | Bin 0 -> 1956 bytes .../PSP/SYSTEM/CACHE/ULJM05600.glshadercache | Bin 0 -> 172 bytes packages/games/emulators/PPSSPPSDL/package.mk | 70 + .../PPSSPPSDL/patches/000-disable-mouse.patch | 46 + .../patches/006-fix-window-size.patch | 22 + .../PPSSPPSDL/patches/008-exit-to-jelOS.patch | 55 + .../patches/ppsspp-patch-005-build-flag.patch | 18 + packages/games/emulators/PPSSPPSDL/ppsspp.sh | 9 + .../PPSSPPSDL/sources/RG351/controls.ini | 23 + .../PPSSPPSDL/sources/RG351/ppsspp.ini | 424 + .../PPSSPPSDL/sources/RG552/controls.ini | 18 + .../PPSSPPSDL/sources/RG552/ppsspp.ini | 512 + .../emulators/advancemame/bin/advmame.sh | 30 + .../advancemame/config/RG351MP/advmame.rc | 58 + .../advancemame/config/RG351P/advmame.rc | 58 + .../games/emulators/advancemame/package.mk | 59 + .../patches/advancemame-002-fix-vfb.patch | 20 + .../patches/advancemame-fix-slang.patch | 108 + .../advancemame-return-0-on-terminate.patch | 11 + .../config/conf/AmigaA1200-default.uae | 174 + .../config/conf/AmigaA500-default.uae | 173 + .../amiberry/config/conf/adfdir.conf | 35 + packages/games/emulators/amiberry/package.mk | 76 + .../emulators/amiberry/scripts/amiberry.start | 145 + .../dosbox-sdl2/config/dosbox-SDL2-MT32.conf | 344 + .../dosbox-sdl2/config/dosbox-SDL2.conf | 327 + .../dosbox-sdl2/config/dosbox-SVN.conf | 357 + .../config/games/_Scan DOSBox Games.sh | 72 + .../games/emulators/dosbox-sdl2/package.mk | 47 + ...-sdl2.995.01-add-mt32emu-MIDI-device.patch | 530 + .../dosbox-sdl2/scripts/dosbox.start | 26 + .../dosbox-x/config/dosbox-SDL2-MT32.conf | 344 + .../dosbox-x/config/dosbox-SDL2.conf | 335 + .../emulators/dosbox-x/config/dosbox-SVN.conf | 357 + .../emulators/dosbox-x/config/dosbox.conf | 335 + packages/games/emulators/dosbox-x/package.mk | 39 + .../dosbox-x/patches/000-arm_configure.patch | 17 + .../dosbox-x/patches/001-sdl-config.patch | 46 + .../dosbox-x/patches/003-dosboxconf.patch | 49 + .../emulators/dosbox-x/scripts/dosbox-x.start | 28 + .../games/emulators/ecwolf/config/ecwolf.cfg | 5 + packages/games/emulators/ecwolf/ecwolf.sh | 67 + packages/games/emulators/ecwolf/package.mk | 54 + .../patches/ecwolf-001-add-video-modes.patch | 12 + .../patches/ecwolf-002-add-exit-menu.patch | 13 + .../gzdoom/config/RG351MP/gzdoom.ini | 746 + .../emulators/gzdoom/config/RG351P/gzdoom.ini | 746 + packages/games/emulators/gzdoom/gzdoom.sh | 54 + packages/games/emulators/gzdoom/package.mk | 63 + .../gzdoom/patches/RG351P/0001_key_swap.patch | 19 + .../games/emulators/gzdoom/zmusic/package.mk | 40 + .../hatarisa/config/conf/Atari-ST-default.cfg | 252 + packages/games/emulators/hatarisa/package.mk | 43 + .../emulators/hatarisa/portaudio/package.mk | 11 + .../emulators/hatarisa/scripts/hatari.start | 76 + .../emulators/hypseus/config/hypinput.ini | 31 + packages/games/emulators/hypseus/package.mk | 30 + .../patches/hypseus-003-controller.patch | 262 + .../patches/hypseus-004-install_fix.patch | 11 + .../patches/hypseus-005-external-mpeg2.patch | 70 + .../lzdoom/config/RG351MP/lzdoom.ini | 2601 + .../emulators/lzdoom/config/RG351P/lzdoom.ini | 2600 + .../games/emulators/lzdoom/config/lzdoom.ini | 2599 + packages/games/emulators/lzdoom/lzdoom.sh | 54 + packages/games/emulators/lzdoom/package.mk | 54 + .../lzdoom/patches/RG351MP/MP_key_swap.patch | 19 + .../mupen64plussa-audio-sdl/package.mk | 41 + .../config/mupen64plus-RG351MP.cfg | 630 + .../config/mupen64plus-RG351P.cfg | 630 + .../config/mupen64plus-RG351V.cfg | 630 + .../mupen64plussa/mupen64plussa-core/m64p.sh | 23 + .../mupen64plussa-core/package.mk | 55 + .../config/InputAutoCfg.ini | 2151 + .../mupen64plussa-input-sdl/package.mk | 45 + .../mupen64plussa-rsp-hle/package.mk | 41 + .../mupen64plussa-ui-console/package.mk | 56 + .../mupen64plussa-video-glide64mk2/package.mk | 45 + .../mupen64plussa-video-rice/package.mk | 45 + .../games/emulators/mupen64plussa/package.mk | 12 + .../openbor/config/Saves/default.cfg | Bin 0 -> 352 bytes .../games/emulators/openbor/config/master.cfg | Bin 0 -> 320 bytes packages/games/emulators/openbor/package.mk | 36 + .../patches/openbor-02-addplatform.patch | 75 + .../emulators/openbor/scripts/openbor.sh | 44 + .../emulators/raze/config/RG351MP/raze.ini | 783 + .../emulators/raze/config/RG351P/raze.ini | 944 + .../games/emulators/raze/libvpx/package.mk | 39 + packages/games/emulators/raze/package.mk | 61 + .../raze/patches/RG351P/0001_key_swap.patch | 19 + packages/games/emulators/raze/raze.sh | 46 + .../retroarch/modprobe.d/usbhid.conf | 51 + packages/games/emulators/retroarch/package.mk | 102 + .../patches/0001-Increase-glui-size.patch | 22 + .../patches/0001-Increase-ozone-size.patch | 22 + .../0001-Increase-ozone-widget_size.patch | 14 + ...pper-implement-RETRO_ENVIRONMENT_GET.patch | 55 + .../patches/008-drm-resolution.patch | 27 + ...10-disable-drm-resolution-adaptation.patch | 70 + .../patches/RG351V/0001-remove_rotation.patch | 23 + .../patches/retroarch-01-xkb-fix.patch | 30 + .../patches/retroarch-02_disable_search.patch | 13 + .../patches/retroarch-04-enablecontent.patch | 26 + ...retroarch-05-disable_updater_entries.patch | 149 + .../patches/retroarch-10-Exit_menu.patch | 68 + .../retroarch-12-input_sort_devices.patch | 50 + .../retroarch/scripts/retroarch-config | 6 + .../sources/retroarch-core-options.cfg | 83 + .../emulators/retroarch/sources/retroarch.cfg | 2743 + .../sources/retroarch32bit-append.cfg | 2 + .../sources/retroarch64bit-append.cfg | 2 + .../retroarch/system.d/retroarch.service | 19 + .../retroarch/system.d/tmp-assets.mount | 13 + .../retroarch/system.d/tmp-cores.mount | 13 + .../retroarch/system.d/tmp-database.mount | 13 + .../retroarch/system.d/tmp-joypads.mount | 13 + .../retroarch/system.d/tmp-overlays.mount | 13 + .../retroarch/system.d/tmp-shaders.mount | 13 + .../tmpfiles.d/retroarch-userdirs.conf | 32 + .../99-8bitdo-bluetooth-controllers.rules | 43 + .../udev.d/99-ION-iCade-bluetooth.rules | 1 + .../udev.d/99-bluetooth-power-on.rules | 1 + .../emulators/retroarch/udev.d/99-evdev.rules | 2 + .../udev.d/99-gen-game-s3-controller.rules | 1 + .../udev.d/99-juyao-dual-arcade.rules | 2 + .../udev.d/99-nintendo-wii-remote.rules | 2 + .../udev.d/99-ninteno-wii-remote.rules | 2 + .../udev.d/99-nv-shield-controller.rules | 1 + .../retroarch/udev.d/99-ouya-controller.rules | 1 + .../retroarch/udev.d/99-terios-t3.rules | 2 + .../emulators/scummvmsa/bin/scummvm.start | 64 + .../config/games/_Scan ScummVM Games.sh | 22 + .../emulators/scummvmsa/config/scummvm.ini | 20 + packages/games/emulators/scummvmsa/package.mk | 42 + .../emulators/scummvmsa/scummremastered.zip | Bin 0 -> 92994 bytes .../emulators/solarus/config/RG351MP/pads.ini | 9 + .../emulators/solarus/config/RG351P/pads.ini | 9 + packages/games/emulators/solarus/package.mk | 31 + .../solarus/patches/solarus-002-pad.patch | 72 + .../solarus/patches/solarus-003-dirs.patch | 31 + .../games/emulators/solarus/physfs/package.mk | 28 + .../physfs/patches/0001-build_fix.patch | 13 + .../emulators/solarus/scripts/solarus.sh | 18 + packages/games/libretro/2048/package.mk | 43 + packages/games/libretro/81/package.mk | 46 + packages/games/libretro/TIC-80/package.mk | 49 + packages/games/libretro/atari800/package.mk | 42 + .../atari800-01-add-emuelec-platform.patch | 34 + packages/games/libretro/beetle-gba/package.mk | 43 + .../games/libretro/beetle-lynx/package.mk | 43 + packages/games/libretro/beetle-ngp/package.mk | 43 + packages/games/libretro/beetle-pce/package.mk | 43 + .../games/libretro/beetle-pcfx/package.mk | 51 + .../libretro/beetle-supafaust/package.mk | 41 + .../libretro/beetle-supergrafx/package.mk | 43 + packages/games/libretro/beetle-vb/package.mk | 43 + .../games/libretro/beetle-wswan/package.mk | 43 + packages/games/libretro/bluemsx/package.mk | 47 + packages/games/libretro/cannonball/package.mk | 43 + packages/games/libretro/cap32/package.mk | 43 + .../games/libretro/common-shaders/package.mk | 54 + packages/games/libretro/core-info/package.mk | 35 + packages/games/libretro/crocods/package.mk | 43 + .../crocods/patches/001-keyboard.patch | 22 + packages/games/libretro/daphne/package.mk | 19 + packages/games/libretro/dinothawr/package.mk | 48 + .../games/libretro/dosbox-pure/package.mk | 45 + .../dosbox-pure-add-emuelec-platform.patch | 33 + packages/games/libretro/dosbox-svn/package.mk | 47 + .../patches/dosbox-svn-use-sdl-config.patch | 13 + packages/games/libretro/dosbox/package.mk | 47 + .../games/libretro/duckstation/package.mk | 20 + packages/games/libretro/easyrpg/easyrpg.sh | 67 + .../games/libretro/easyrpg/liblcf/package.mk | 37 + .../liblcf-02-add-icu-compile-defs.patch | 12 + .../libretro/easyrpg/libspeexdsp/package.mk | 38 + .../libretro/easyrpg/libxmp-lite/package.mk | 40 + .../libxmp-lite/sources/CMakeLists.txt | 65 + packages/games/libretro/easyrpg/package.mk | 54 + .../libretro/easyrpg/wildmidi/package.mk | 35 + .../easyrpg/wildmidi/sources/CMakeLists.txt | 303 + .../games/libretro/fbalpha2012/package.mk | 43 + .../fbalpha2019/fbalpha2019_libretro.info | 20 + .../games/libretro/fbalpha2019/package.mk | 46 + packages/games/libretro/fbneo/package.mk | 34 + packages/games/libretro/fceumm/package.mk | 47 + packages/games/libretro/flycast/package.mk | 82 + packages/games/libretro/fmsx/package.mk | 47 + packages/games/libretro/freechaf/package.mk | 23 + packages/games/libretro/freeintv/package.mk | 43 + packages/games/libretro/freej2me/freej2me.sh | 48 + packages/games/libretro/freej2me/package.mk | 35 + .../games/libretro/fuse-libretro/package.mk | 47 + packages/games/libretro/gambatte/package.mk | 48 + .../games/libretro/gambatte/patches/RG351MP | 1 + .../RG351P/disable_palette_switching.patch | 31 + .../gambatte/patches/RG351P/rumble.patch | 35 + .../games/libretro/gambatte/patches/RG351V | 1 + packages/games/libretro/gearboy/package.mk | 42 + packages/games/libretro/gearcoleco/package.mk | 42 + packages/games/libretro/gearsystem/package.mk | 46 + .../libretro/genesis-plus-gx-wide/package.mk | 50 + .../games/libretro/genesis-plus-gx/package.mk | 50 + .../games/libretro/glsl-shaders/package.mk | 53 + .../libretro/glsl-shaders/removeshaders.sh | 122 + .../glsl-shaders/shaders/_redraw.glslp | 11 + .../shaders/crt/crt-nes-mini.glslp | 3 + .../shaders/crt/crt-pi-vertical.glslp | 8 + .../glsl-shaders/shaders/crt/crt-pi.glslp | 8 + .../glsl-shaders/shaders/crt/fakelottes.glslp | 4 + .../glsl-shaders/shaders/crt/scanline.glslp | 4 + .../shaders/crt/shaders/crt-nes-mini.glsl | 106 + .../shaders/crt/shaders/crt-pi-vertical.glsl | 242 + .../shaders/crt/shaders/crt-pi.glsl | 234 + .../shaders/crt/shaders/fakelottes.glsl | 280 + .../shaders/crt/shaders/scanlines.glsl | 106 + .../shaders/crt/shaders/zfast_crt.glsl | 199 + .../glsl-shaders/shaders/crt/zfast-crt.glslp | 4 + .../shaders/kurg/kurg-ROPi-scanlines-3x.glsl | 47 + .../shaders/kurg/kurg-ROPi-scanlines-3x.glslp | 9 + .../kurg/kurg-ROPi-scanlines-3x_v2.glsl | 45 + .../kurg/kurg-ROPi-scanlines-3x_v2.glslp | 9 + .../shaders/kurg/kurg_scanlines_source.glsl | 111 + .../kurg/kurg_scanlines_source_nearest.glslp | 11 + .../shaders/rpi/shaders/aa/aa-shader-4.o.glsl | 518 + .../shaders/rpi/shaders/aa/advanced-aa.glsl | 293 + .../shaders/rpi/shaders/aa/fx-aa.glsl | 220 + .../rpi/shaders/aa/fxaa-edge-detect.glsl | 180 + .../shaders/rpi/shaders/aa/reverse-aa.glsl | 267 + .../shaders/rpi/shaders/xbr/2xbr-v2.2.glsl | 467 + .../shaders/rpi/shaders/xbr/2xbr-v3.5a.glsl | 687 + .../shaders/rpi/shaders/xbr/2xbr-v3.7c.glsl | 538 + .../shaders/rpi/shaders/xbr/2xbr-v3.8d.glsl | 479 + .../shaders/rpi/shaders/xbr/2xbr.glsl | 202 + .../shaders/rpi/shaders/xbr/3xbr-v2.glsl | 379 + .../shaders/rpi/shaders/xbr/3xbr-v3.8d.glsl | 479 + .../shaders/rpi/shaders/xbr/3xbr.glsl | 253 + .../shaders/rpi/shaders/xbr/4xbr-v1.1.glsl | 328 + .../rpi/shaders/xbr/4xbr-v3.5-plus-crt.glsl | 705 + .../shaders/rpi/shaders/xbr/4xbr-v3.9c.glsl | 582 + .../shaders/rpi/shaders/xbr/4xbr-v4.0.glsl | 613 + .../shaders/rpi/shaders/xbr/4xbr.glsl | 295 + .../shaders/rpi/shaders/xbr/5xbr-v1.1.glsl | 241 + .../shaders/rpi/shaders/xbr/5xbr-v2.1.glsl | 265 + .../shaders/rpi/shaders/xbr/5xbr-v2.glsl | 229 + .../shaders/rpi/shaders/xbr/5xbr-v3.2.glsl | 629 + .../shaders/rpi/shaders/xbr/5xbr-v3.3.glsl | 689 + .../rpi/shaders/xbr/5xbr-v3.5-plus-crt.glsl | 675 + .../shaders/rpi/shaders/xbr/5xbr-v3.5.glsl | 626 + .../shaders/rpi/shaders/xbr/5xbr-v3.5a.glsl | 626 + .../shaders/rpi/shaders/xbr/5xbr-v3.6c.glsl | 388 + .../shaders/rpi/shaders/xbr/5xbr-v3.7d.glsl | 519 + .../shaders/rpi/shaders/xbr/5xbr-v3.8d.glsl | 479 + .../rpi/shaders/xbr/5xbr-v4.0-noblend.glsl | 551 + .../shaders/rpi/shaders/xbr/5xbr.glsl | 352 + .../shaders/rpi/shaders/xbr/xbr-dilation.glsl | 543 + .../rpi/shaders/xbr/xbr-v3.8c-gamma.glsl | 594 + .../shaders/sharp-bilinear-scanlines.glsl | 150 + .../sharp/shaders/sharp-bilinear-simple.glsl | 123 + .../shaders/sharp/shaders/stock.glsl | 111 + .../sharp/sharp-bilinear-2x-prescale.glslp | 7 + .../sharp/sharp-bilinear-scanlines.glslp | 4 + .../shaders/sharp/sharp-bilinear-simple.glslp | 4 + packages/games/libretro/gme/package.mk | 44 + packages/games/libretro/gpsp/package.mk | 51 + .../games/libretro/gw-libretro/package.mk | 47 + packages/games/libretro/handy/package.mk | 47 + .../aarch64/handy-01-add-emuelec.patch | 23 + .../hatari/config/conf/Atari-ST-default.cfg | 252 + .../games/libretro/hatari/config/hatari.nvram | 0 packages/games/libretro/hatari/package.mk | 59 + .../hatari/patches/findcapsimage.patch | 48 + .../libretro/libretro-database/package.mk | 46 + packages/games/libretro/mame/package.mk | 58 + .../mame/patches/mame-crosscompile.patch | 54 + .../mame/patches/mame-remove-bgfx.patch | 80 + packages/games/libretro/mame2000/package.mk | 47 + .../games/libretro/mame2003-midway/package.mk | 48 + .../games/libretro/mame2003-plus/package.mk | 47 + .../games/libretro/mame2003-xtreme/package.mk | 39 + .../sources/km_mame2003_xtreme_libretro.info | 14 + packages/games/libretro/mame2003/package.mk | 47 + packages/games/libretro/mame2010/package.mk | 55 + packages/games/libretro/mame2015/package.mk | 57 + packages/games/libretro/mame2016/package.mk | 61 + .../mame2016-libretro-crosscompile.patch | 52 + packages/games/libretro/meowpc98/package.mk | 46 + packages/games/libretro/mgba/package.mk | 53 + packages/games/libretro/mgba/patches/RG351MP | 1 + .../RG351P/libretro-mgba-0001-rumble.patch | 27 + packages/games/libretro/mgba/patches/RG351V | 1 + packages/games/libretro/mrboom/package.mk | 47 + .../games/libretro/mupen64plus-nx/package.mk | 32 + .../mupen64plus-nx-01-add-amlogic64.patch | 19 + .../games/libretro/mupen64plus/package.mk | 78 + .../libretro/mupen64plus/patches/RG351MP | 1 + .../RG351P/mupen64plus-fix-rumble.patch | 25 + .../games/libretro/mupen64plus/patches/RG351V | 1 + .../patches/mupen64plus-fixdouble.patch | 12 + .../patches/mupen64plus-inc-string.patch | 11 + .../patches/mupen64plus-sx05re-neonfix.patch | 11 + .../games/libretro/neocd_libretro/package.mk | 29 + packages/games/libretro/nestopia/package.mk | 48 + packages/games/libretro/np2kai/package.mk | 44 + packages/games/libretro/nxengine/package.mk | 46 + packages/games/libretro/o2em/package.mk | 42 + packages/games/libretro/opera/package.mk | 44 + .../games/libretro/parallel-n64/package.mk | 48 + .../libretro/parallel-n64/patches/RG351MP | 1 + .../RG351P/parallel-n64-add_rumble.patch | 30 + .../libretro/parallel-n64/patches/RG351V | 1 + .../patches/aarch64/01-gcc-10.patch | 11 + .../aarch64/parallel-n64-add_platform.patch | 80 + .../parallel-n64/patches/arm/01-gcc-10.patch | 11 + .../arm/parallel-n64-add_platform.patch | 62 + .../libretro/parallel-n64_gln64/package.mk | 51 + .../parallel-n64_gln64/patches/RG351MP | 1 + .../RG351P/parallel-n64-add_rumble.patch | 30 + .../parallel-n64_gln64/patches/RG351V | 1 + .../patches/aarch64/01-gcc-10.patch | 11 + .../aarch64/parallel-n64-add_platform.patch | 80 + .../patches/arm/01-gcc-10.patch | 11 + .../arm/parallel-n64-add_platform.patch | 62 + .../games/libretro/pcsx_rearmed/package.mk | 35 + .../libretro/pcsx_rearmed/patches/RG351MP | 1 + .../libretro-pcsx-rearmed-0002-rumble.patch | 26 + .../libretro/pcsx_rearmed/patches/RG351V | 1 + packages/games/libretro/picodrive/package.mk | 33 + packages/games/libretro/pokemini/package.mk | 43 + .../games/libretro/pokemini/patches/RG351MP | 1 + .../pokemini/patches/RG351P/rumble.patch | 33 + .../games/libretro/pokemini/patches/RG351V | 1 + packages/games/libretro/potator/package.mk | 24 + packages/games/libretro/ppsspp/package.mk | 60 + .../ppsspp/patches/ppsspp-x86_64-fix.patch | 12 + packages/games/libretro/prboom/package.mk | 42 + .../prboom/patches/01_351p_resolution.patch | 34 + packages/games/libretro/prosystem/package.mk | 42 + packages/games/libretro/puae/package.mk | 46 + packages/games/libretro/px68k/package.mk | 43 + packages/games/libretro/px68k/patches/RG351MP | 1 + .../px68k/patches/RG351P/rumble.patch | 26 + packages/games/libretro/px68k/patches/RG351V | 1 + packages/games/libretro/quasi88/package.mk | 22 + packages/games/libretro/quicknes/package.mk | 50 + packages/games/libretro/race/package.mk | 42 + .../games/libretro/reminiscence/package.mk | 49 + packages/games/libretro/sameboy/package.mk | 48 + packages/games/libretro/sameduck/package.mk | 48 + packages/games/libretro/scummvm/package.mk | 57 + packages/games/libretro/smsplus-gx/package.mk | 50 + packages/games/libretro/snes9x/package.mk | 50 + packages/games/libretro/snes9x2002/package.mk | 42 + .../games/libretro/snes9x2005_plus/package.mk | 41 + .../01-snes9x2005_plux-01-fix-fpic.patch | 26 + packages/games/libretro/snes9x2010/package.mk | 46 + .../patches/snes9x2010-add-oga.patch | 32 + .../games/libretro/stella-2014/package.mk | 42 + .../patches/stella-2014-01-makefile.patch | 19 + packages/games/libretro/stella/package.mk | 46 + .../patches/stella-01-emuelec-platform.patch | 30 + .../games/libretro/swanstation/package.mk | 25 + packages/games/libretro/tgbdual/package.mk | 43 + packages/games/libretro/tyrquake/package.mk | 49 + .../games/libretro/tyrquake/patches/RG351MP | 1 + .../patches/RG351P/01_351p_resolution.patch | 43 + .../tyrquake/patches/RG351P/rumble.patch | 32 + .../games/libretro/tyrquake/patches/RG351V | 1 + packages/games/libretro/uae4arm/package.mk | 46 + packages/games/libretro/uzem/package.mk | 43 + packages/games/libretro/vba-next/package.mk | 47 + packages/games/libretro/vbam/package.mk | 48 + packages/games/libretro/vecx/package.mk | 46 + packages/games/libretro/vice/package.mk | 63 + .../games/libretro/virtualjaguar/package.mk | 42 + packages/games/libretro/xmil/package.mk | 27 + packages/games/libretro/xrick/package.mk | 46 + .../games/libretro/yabasanshiro/package.mk | 47 + .../games/native/moonlight/enet/package.mk | 12 + packages/games/native/moonlight/package.mk | 14 + .../moonlight/patches/001-rotation.patch | 222 + packages/games/tools/351files/package.mk | 28 + .../351files/patches/RG351MP/rg351mp.patch | 64 + .../tools/351files/patches/RG552/rg552.patch | 64 + packages/games/tools/axe11/X11/.gitignore | 2 + packages/games/tools/axe11/X11/ImUtil.h | 30 + packages/games/tools/axe11/X11/XKBlib.h | 1149 + packages/games/tools/axe11/X11/Xcms.h | 815 + packages/games/tools/axe11/X11/Xlib-xcb.h | 20 + packages/games/tools/axe11/X11/Xlib.h | 4025 ++ packages/games/tools/axe11/X11/XlibConf.h.in | 37 + packages/games/tools/axe11/X11/Xlibint.h | 1444 + packages/games/tools/axe11/X11/Xlocale.h | 37 + packages/games/tools/axe11/X11/Xregion.h | 190 + packages/games/tools/axe11/X11/Xresource.h | 358 + packages/games/tools/axe11/X11/Xutil.h | 838 + packages/games/tools/axe11/X11/cursorfont.h | 111 + .../tools/axe11/X11/extensions/XKBgeom.h | 662 + .../tools/axe11/X11/extensions/xf86vmode.h | 298 + packages/games/tools/axe11/package.mk | 21 + .../tools/axe11/patches/01-compile-fix.patch | 12 + packages/games/tools/box64/package.mk | 23 + packages/games/tools/box86/package.mk | 22 + packages/games/tools/capsimg/package.mk | 30 + .../games/tools/gamecontrollerdb/package.mk | 35 + .../sources/gamecontrollerdb.txt | 1521 + packages/games/tools/gl4es/package.mk | 18 + packages/games/tools/gptokeyb/Makefile | 12 + packages/games/tools/gptokeyb/package.mk | 24 + .../gptokeyb/patches/0001-build_fix.patch | 16 + packages/games/tools/jstest-sdl/package.mk | 21 + packages/games/tools/libglu/gl.pc | 10 + packages/games/tools/libglu/package.mk | 27 + packages/games/tools/libgo2/package.mk | 34 + .../patches/RG351V/0001-remove_rotation.patch | 32 + .../games/tools/retroarch-assets/package.mk | 38 + .../games/tools/retroarch-overlays/package.mk | 41 + .../games/tools/rg351p-js2xbox/package.mk | 18 + .../tools/rs97-commander-sdl2/package.mk | 36 + .../RG351P/001-rs97-commander-path.patch | 12 + .../patches/RG351P/002-button-reverse.patch | 27 + .../patches/RG351P/003-linespacing-fix.patch | 34 + .../RG351V/001-rs97-commander-path.patch | 12 + .../patches/RG351V/002-button-reverse.patch | 27 + .../patches/RG351V/003-linespacing-fix.patch | 34 + .../patches/RG351V/004-resolution.patch | 32 + packages/graphics/SDL/SDL_net/package.mk | 34 + packages/graphics/SDL/SDL_sound/package.mk | 29 + packages/graphics/SDL/package.mk | 119 + packages/graphics/SDL/yasm/package.mk | 46 + packages/graphics/SDL2-14/package.mk | 68 + packages/graphics/SDL2/package.mk | 78 + ...d-missing-gbm_bo_get_offset-and-SDL_.patch | 52 + .../patches/0002-egl_swapinterval_fix.patch | 25 + .../RG351P/0005-SDL-2.0.16.rotation.patch | 360 + .../RG552/0005-SDL-2.0.16.rotation.patch | 360 + packages/graphics/bcm2835-driver/package.mk | 96 + .../system.d/unbind-console.service | 11 + packages/graphics/cairo/package.mk | 96 + packages/graphics/ftgl/package.mk | 13 + .../graphics/ftgl/patches/ftgl-01-cmake.patch | 35 + .../patches/ftgl-01-ftgl-disable-docs.patch | 12 + packages/graphics/giflib/package.mk | 19 + ...giflib-01-fix-reallocarray-exception.patch | 34 + packages/graphics/glew/package.mk | 29 + .../glew/patches/glew-01-fix-pkgconf.patch | 11 + packages/graphics/glfw/package.mk | 24 + packages/graphics/glm/package.mk | 12 + packages/graphics/glu/package.mk | 17 + packages/graphics/gpu-viv-bin-mx6q/package.mk | 46 + packages/graphics/imagemagick/package.mk | 22 + packages/graphics/imx-gpu-viv/package.mk | 60 + packages/graphics/kmscube/package.mk | 19 + packages/graphics/lcms2/package.mk | 11 + packages/graphics/libde265/package.mk | 23 + packages/graphics/libdrm/package.mk | 54 + packages/graphics/libepoxy/package.mk | 35 + packages/graphics/libheif/package.mk | 19 + packages/graphics/libhybris/package.mk | 26 + packages/graphics/libjpeg-turbo/package.mk | 38 + packages/graphics/libmali/package.mk | 85 + .../RG351/mali-bitfrost-001-gbminclude.patch | 12 + .../RG552/mali-bitfrost-001-gbminclude.patch | 12 + .../libmali/system.d/libmali-setup.service | 12 + packages/graphics/libpng/package.mk | 36 + packages/graphics/libpng17/package.mk | 36 + packages/graphics/libprojectM/package.mk | 26 + packages/graphics/libraw/package.mk | 20 + packages/graphics/mesa/package.mk | 104 + packages/graphics/opengl-mali/package.mk | 33 + .../graphics/opengl-meson-t82x/package.mk | 22 + .../system.d/unbind-console.service | 11 + packages/graphics/opengl-meson/package.mk | 41 + .../scripts/libmali-overlay-setup | 19 + .../opengl-meson/system.d/libmali.service | 11 + packages/graphics/soil/package.mk | 20 + .../soil/patches/soil-0001_fix-makefile.patch | 47 + packages/graphics/tiff/package.mk | 26 + packages/graphics/vsxu/package.mk | 34 + .../vsxu/patches/vsxu-01-fix-order.patch | 75 + .../vsxu/patches/vsxu-02-fix-glfw.patch | 27 + .../vsxu/patches/vsxu-03-fix-exr.patch | 11 + .../vsxu/patches/vsxu-04-fix-freetype.patch | 11 + packages/graphics/vulkan-headers/package.mk | 13 + packages/graphics/vulkan-loader/package.mk | 17 + packages/graphics/vulkan-tools/package.mk | 18 + .../distribution/configs/all/autoconf.cfg | 1 + .../distribution/configs/all/bluetooth.cfg | 1 + .../config/distribution/configs/atari800.cfg | 109 + .../distribution/configs/distribution.conf | 187 + packages/jelos/config/distribution/configs/tz | 593 + .../config/distribution/modules/351Files.sh | 12 + .../distribution/modules/Remove ._ Files.sh | 14 + .../modules/Start 32bit Retroarch.sh | 14 + .../modules/Start 64bit Retroarch.sh | 12 + .../distribution/modules/Start PPSSPP.sh | 13 + .../distribution/modules/Start ScummVM.sh | 11 + .../modules/downloaded_images/clean-thumb.png | Bin 0 -> 16952 bytes .../modules/downloaded_images/clean.png | Bin 0 -> 24024 bytes .../downloaded_images/filemanager-thumb.png | Bin 0 -> 12922 bytes .../modules/downloaded_images/filemanager.png | Bin 0 -> 21002 bytes .../downloaded_images/ppsspp-thumb.png | Bin 0 -> 21091 bytes .../modules/downloaded_images/ppsspp.png | Bin 0 -> 26263 bytes .../downloaded_images/retroarch32-thumb.png | Bin 0 -> 16291 bytes .../modules/downloaded_images/retroarch32.png | Bin 0 -> 22279 bytes .../downloaded_images/retroarch64-thumb.png | Bin 0 -> 16339 bytes .../modules/downloaded_images/retroarch64.png | Bin 0 -> 22028 bytes .../downloaded_images/scummvm-thumb.png | Bin 0 -> 14519 bytes .../modules/downloaded_images/scummvm.png | Bin 0 -> 24180 bytes .../modules/downloaded_images/template.png | Bin 0 -> 7568 bytes .../config/distribution/modules/gamelist.xml | 82 + packages/jelos/gamepads/GO-Super Gamepad.cfg | 53 + .../OpenSimHardware OSH PB Controller.cfg | 51 + .../OpenSimHardware OSH PB Controller_SDL.cfg | 41 + packages/jelos/gamepads/retrogame_joypad.cfg | 29 + packages/jelos/package.mk | 128 + packages/jelos/profile.d/02-distribution | 83 + packages/jelos/profile.d/98-jslisten | 81 + packages/jelos/profile.d/99-freqfunctions | 25 + .../jelos/sources/asound/rg351/asound.conf | 20 + .../jelos/sources/asound/rg552/asound.conf | 24 + .../jelos/sources/asound/rg552/asound.state | 472 + .../jelos/sources/autostart/RG552/001-alsa | 38 + packages/jelos/sources/autostart/autostart | 34 + .../jelos/sources/autostart/common/001-setup | 35 + .../jelos/sources/autostart/common/002-kernel | 5 + .../sources/autostart/common/003-logging | 17 + .../jelos/sources/autostart/common/004-pico8 | 11 + .../sources/autostart/common/005-brightness | 21 + .../jelos/sources/autostart/common/006-rootpw | 30 + .../sources/autostart/common/007-deviceutils | 33 + .../jelos/sources/autostart/common/008-wifi | 13 + .../autostart/common/009-networkservices | 35 + .../jelos/sources/autostart/daemons/001-ssh | 4 + .../jelos/sources/autostart/daemons/002-samba | 4 + .../sources/autostart/sounds/silence.ogg | 0 packages/jelos/sources/issue | 8 + packages/jelos/sources/pico-8.sh | 36 + packages/jelos/sources/scripts/backuptool | 30 + .../jelos/sources/scripts/batocera-bluetooth | 110 + .../sources/scripts/batocera-bluetooth-agent | 461 + .../jelos/sources/scripts/batocera-brightness | 52 + .../jelos/sources/scripts/batocera-config | 358 + .../scripts/batocera-es-thebezelproject | 339 + packages/jelos/sources/scripts/batocera-info | 1 + .../jelos/sources/scripts/batocera-resolution | 18 + .../scripts/batocera-retroachievements-info | 104 + .../jelos/sources/scripts/batocera-scraper | 79 + .../jelos/sources/scripts/batocera-settings | 267 + .../jelos/sources/scripts/batocera-systems | 612 + packages/jelos/sources/scripts/batocera-wifi | 38 + packages/jelos/sources/scripts/bezels.sh | 217 + packages/jelos/sources/scripts/brightness | 64 + .../jelos/sources/scripts/emustation-config | 44 + packages/jelos/sources/scripts/error.sh | 19 + packages/jelos/sources/scripts/factoryreset | 20 + packages/jelos/sources/scripts/find.sh | 6 + packages/jelos/sources/scripts/getfilters | 10 + packages/jelos/sources/scripts/getshaders | 10 + packages/jelos/sources/scripts/jelos-info | 77 + packages/jelos/sources/scripts/manage_mpv.sh | 29 + packages/jelos/sources/scripts/mpv_video.sh | 4 + packages/jelos/sources/scripts/rr_audio.sh | 157 + packages/jelos/sources/scripts/runemu.sh | 489 + packages/jelos/sources/scripts/setemu.sh | 30 + packages/jelos/sources/scripts/setsettings.sh | 734 + packages/jelos/sources/scripts/show_splash | 39 + packages/jelos/sources/scripts/timeinfo | 22 + packages/jelos/sources/shutdown.sh | 10 + .../jelos/system.d/jelos-autostart.service | 13 + packages/jelos/system.d/jelos.target | 9 + packages/jelos/system.d/jslisten.service | 12 + packages/jelos/system.d/jslisten.target | 8 + packages/jelos/tmpfiles.d/jelos-dirs.conf | 108 + packages/jelos/udev.d/99-pandora_pk7.rules | 2 + .../dvb/crazycat/changelog.txt | 2 + .../dvb/crazycat/icon/icon.png | Bin 0 -> 68596 bytes .../dvb/crazycat/package.mk | 61 + ...iver.dvb.crazycat-02-disable-modules.patch | 15 + ...er.dvb.crazycat-03-config_mycompat_h.patch | 12 + ...iver.dvb.crazycat-01-remove-rmmod.pl.patch | 13 + .../dvb/crazycat/source/default.py | 2 + .../dvb/crazycat_aml/changelog.txt | 2 + .../dvb/crazycat_aml/icon/icon.png | Bin 0 -> 68596 bytes .../dvb/crazycat_aml/package.mk | 68 + ....dvb.crazycat_aml-02-disable-modules.patch | 13 + ...vb.crazycat_aml-03-config_mycompat_h.patch | 15 + ....dvb.crazycat_aml-01-remove-rmmod.pl.patch | 13 + .../dvb/crazycat_aml/source/default.py | 2 + .../dvb/depends/media_tree/package.mk | 35 + .../amlogic-4.9/media_tree-06-of-node.patch | 23 + .../media_tree_01-m2m-job-resume-pause.patch | 74 + .../patches/media_tree-01-m88ds3103b.patch | 746 + .../patches/media_tree-02-add-t230c2.patch | 217 + .../media_tree-04-fix-blocking-demux.patch | 140 + ...media_tree-06-fix-si2168-cmd-timeout.patch | 17 + .../media_tree-07-fix-si2157-init.patch | 16 + ...a_tree-08-fix-dvbsky-frontend-detach.patch | 20 + .../media_tree-09-revert-access_ok.patch | 215 + ...t-messages-in-m88ds3103_set_frontend.patch | 28 + .../dvb/depends/media_tree_aml/package.mk | 28 + .../dvb/depends/media_tree_cc/package.mk | 34 + .../media_tree_01-m2m-job-resume-pause.patch | 74 + .../media_tree_cc-06-of-node.patch | 23 + .../patches/media_tree_cc-01-m88ds3103b.patch | 746 + .../dvb/depends/media_tree_cc_aml/package.mk | 36 + .../media_tree_cc_aml-01-m88ds3103b.patch | 746 + ...-linux-901-extend-rc6-toggle-support.patch | 53 + ...-extend-rc6-toggle-support-for-zotac.patch | 41 + .../media_tree_cc_aml-04-fix-tbs5520se.patch | 22 + ...ia_tree_cc_aml-05-fix-si2168-timeout.patch | 18 + .../media_tree_cc_aml-06-dmxdev-buffer.patch | 19 + .../media_tree_cc_aml-99-build-fix.patch | 860 + .../dvb/digital_devices/changelog.txt | 2 + .../dvb/digital_devices/icon/icon.png | Bin 0 -> 32470 bytes .../dvb/digital_devices/package.mk | 29 + .../dvb/digital_devices/source/default.py | 2 + .../dvb/dvb-latest/changelog.txt | 2 + .../dvb/dvb-latest/icon/icon.png | Bin 0 -> 36366 bytes .../dvb/dvb-latest/package.mk | 79 + ....dvb.dvb-latest-01-config_mycompat_h.patch | 15 + ...er.dvb.dvb-latest-02-disable-modules.patch | 14 + ....dvb.dvb-latest-01-config_mycompat_h.patch | 12 + ...er.dvb.dvb-latest-02-disable-modules.patch | 17 + .../driver.dvb.dvb-latest-03-versions.patch | 13 + ...r.dvb.dvb-latest-06-sched_signal-fix.patch | 72 + ...er.dvb.dvb-latest-01-remove-rmmod.pl.patch | 11 + ...r.dvb.dvb-latest-02-add-to-backports.patch | 17 + .../dvb/dvb-latest/source/default.py | 2 + .../kernel/linux-drivers/RTL8188EU/package.mk | 32 + .../kernel/linux-drivers/RTL8192CU/package.mk | 31 + .../RTL8192CU-0001-add_device_ID_330d.patch | 12 + .../RTL8192CU-0002-fix_310_proc2.patch | 29 + .../patches/RTL8192CU-0101-gcc-4.9.patch | 22 + .../patches/RTL8192CU-0102-gcc-5.patch | 25 + .../kernel/linux-drivers/RTL8192DU/package.mk | 31 + ...L8192DU-0001-remove_overlapping_pids.patch | 12 + .../patches/RTL8192DU-0002-PR61.patch | 64 + .../patches/RTL8192DU-0003-fix-vfs-read.patch | 27 + ...92DU-0004-revert-fix-for-old-kernels.patch | 29 + .../patches/aarch64/RTL8192DU-0101-PR63.patch | 25 + ...8192DU-0102-fix-multiple-definitions.patch | 26 + .../kernel/linux-drivers/RTL8192EU/package.mk | 32 + .../patches/RTL8192EU-0101-gcc-5.patch | 25 + .../kernel/linux-drivers/RTL8812AU/package.mk | 31 + ...TL8812AU-02-fix-multiple-definitions.patch | 38 + .../kernel/linux-drivers/RTL8814AU/package.mk | 35 + ...TL8814AU-01-fix-multiple-definitions.patch | 38 + .../kernel/linux-drivers/RTL8821CU/package.mk | 43 + .../amlogic/RTL8152-aml/package.mk | 28 + .../amlogic/RTL8188EU-aml/package.mk | 34 + ...01-Add-support-for-a-few-USB-dongles.patch | 29 + .../amlogic/RTL8189ES-aml/package.mk | 38 + .../amlogic/RTL8189FS-aml/package.mk | 39 + .../amlogic/RTL8723BS-aml/package.mk | 38 + .../amlogic/RTL8723DS-aml/package.mk | 38 + .../amlogic/RTL8822BS-aml/package.mk | 40 + .../amlogic/RTL8822BU-aml/package.mk | 39 + .../RTL8822BU-aml-01-add_device_ids.patch | 26 + .../amlogic/RTL8822CS-aml/package.mk | 40 + .../amlogic/ap6xxx-aml/modprobe.d/dhd.conf | 1 + .../ap6xxx-aml/modprobe.d/dhd_sdio.conf | 1 + .../amlogic/ap6xxx-aml/package.mk | 58 + .../ap6xxx-aml/udev.d/80-dhd_sdio.rules | 18 + .../amlogic/kvimfan-aml/package.mk | 31 + .../amlogic/kvimfan-aml/sources/Makefile | 2 + .../amlogic/kvimfan-aml/sources/khadas-fan.c | 360 + .../kvimfan-aml/system.d/kvimfan.service | 12 + .../modules-load.d/media_modules.conf | 17 + .../amlogic/media_modules-aml/package.mk | 45 + .../patches/002-fix-building.patch | 100 + ...ders-limit-maximum-number-of-decoder.patch | 43 + .../amlogic/mt7601u-aml/package.mk | 33 + .../mt7601u-aml-001-firmware-path.patch | 13 + .../amlogic/mt7603u-aml/package.mk | 35 + .../mt7603u-aml-001-firmware-path.patch | 38 + .../mt7603u-aml-002-fix-building.patch | 13 + ...03u-aml-003-fix-build-the-vpeter-way.patch | 67 + .../amlogic/mt7610u-aml/package.mk | 33 + .../mt7610u-0001-fix-cross-compiling.patch | 29 + .../mt7610u-0002-support-more-cards.patch | 33 + ...10u-aml-003-fix-build-the-vpeter-way.patch | 116 + .../amlogic/mt7668-aml/package.mk | 35 + .../amlogic/qca9377-aml/package.mk | 39 + ...firmware-handling-to-support-chips-u.patch | 538 + ...ml-001-fix-amlogic-4.9-compatibility.patch | 42 + .../udev.d/99-qca9377-wireless.rules | 1 + .../amlogic/ssv6xxx-aml-3.14/package.mk | 47 + ...3.14-001-fix-build-and-firmware-path.patch | 86 + .../amlogic/ssv6xxx-aml/package.mk | 43 + ...-aml-001-fix-build-and-firmware-path.patch | 134 + .../modules-load.d/wifi_dummy.conf | 1 + .../amlogic/wifi_dummy-aml/package.mk | 27 + .../amlogic/wifi_dummy-aml/sources/Makefile | 1 + .../wifi_dummy-aml/sources/wifi_dummy.c | 30 + .../kernel/linux-drivers/bcm_sta/package.mk | 29 + .../bcm_sta-0001-change-eth-to-wlan.patch | 25 + .../patches/bcm_sta-0002-user_ioctl.patch | 15 + ...bcm_sta-0003-remove-date-time-macros.patch | 22 + .../bcm_sta-0004-null-pointer-crash.patch | 11 + .../bcm_sta/patches/bcm_sta-0005-rdtscl.patch | 15 + .../patches/bcm_sta-0006-kernel-4.7.patch | 198 + .../patches/bcm_sta-0007-kernel-4.8.patch | 96 + .../patches/bcm_sta-0008-kernel-4.11.patch | 68 + .../patches/bcm_sta-0009-kernel-4.12.patch | 75 + .../patches/bcm_sta-0010-kernel-4.15.patch | 61 + .../bcm_sta-0011-fix-kernel-warnings.patch | 177 + .../bcm_sta-0200-kernel-5.1-rc1-fix.patch | 68 + .../linux-drivers/dvbhdhomerun/package.mk | 46 + .../patches/dvbhdhomerun-001-conf_file.patch | 52 + .../dvbhdhomerun-002-auto_detect.patch | 34 + ...erun_discover_find_devices_custom_v2.patch | 12 + .../patches/dvbhdhomerun-linux-3.8.4.patch | 22 + .../patches/dvbhdhomerun-linux-4.2.patch | 73 + .../linux-drivers/gpu-aml-ng/package.mk | 42 + .../patches/gpu-aml-ng-01-fix-cp-error.patch | 12 + .../gpu-aml-ng-02-disable-tracepoints.patch | 75 + .../kernel/linux-drivers/gpu-aml/package.mk | 52 + .../patches/gpu-aml-01-fix-cp-error.patch | 12 + .../linux-drivers/intel_nuc_led/package.mk | 27 + .../linux-drivers/mali-midgard/package.mk | 45 + .../linux-drivers/mali-utgard/package.mk | 42 + .../linux-drivers/openvfd-driver/package.mk | 38 + .../openvfd-driver/system.d/openvfd.service | 15 + .../linux-drivers/slice-drivers/package.mk | 27 + .../linux-firmware/RTL8188FU/package.mk | 18 + .../brcmfmac_sdio-firmware-aml/package.mk | 25 + .../brcmfmac_sdio-firmware-aml.service | 11 + .../system.d/brcmfmac_sdio-firmware@.service | 9 + .../udev.d/80-brcmfmac_sdio.rules | 12 + .../amlogic/qca9377-firmware-aml/package.mk | 18 + .../system.d/qca9377-firmware-aml.service | 16 + .../udev.d/80-qca9377-firmware-aml.rules | 6 + .../amlogic/rtkbt-firmware-aml/package.mk | 19 + .../system.d/rtkbt-firmware-aml.service | 11 + .../udev.d/80-rtkbt-firmware-aml.rules | 11 + .../amlogic/rtl8723bs_bt/package.mk | 11 + .../patches/rtl8723bs_bt-001-Makefile.patch | 26 + .../rtl8723bs_bt-002-firmware_path.patch | 20 + .../system.d/rtl8723bs_bt-firmware.service | 11 + .../rtl8723bs_bt/udev.d/80-rtl8723_bt.rules | 9 + .../amlogic/rtl8822b_bt/package.mk | 26 + .../system.d/rtl8822b_bt-firmware.service | 11 + .../rtl8822b_bt/udev.d/80-rtl8822b_bt.rules | 9 + .../amlogic/wlan-firmware-aml/package.mk | 36 + .../brcmfmac_sdio-firmware-imx/package.mk | 19 + .../system.d/brcmfmac_sdio-firmware@.service | 8 + .../udev.d/80-brcmfmac_sdio.rules | 19 + .../brcmfmac_sdio-firmware-rpi/package.mk | 27 + .../scripts/rpi-btuart | 26 + .../system.d/brcmfmac_sdio-firmware.service | 13 + .../udev.d/90-rpi-add-serial.rules | 21 + .../brcmfmac_sdio-firmware/firmwares/any.dat | 1 + .../brcmfmac_sdio-firmware/package.mk | 48 + .../scripts/brcmfmac-firmware-setup | 12 + .../system.d/brcmfmac-firmware.service | 11 + .../linux-firmware/dvb-firmware/package.mk | 20 + .../linux-firmware/firmware-imx/package.mk | 25 + .../linux-firmware/intel-ucode/package.mk | 12 + .../sources/intel-microcode2ucode.c | 154 + .../iwlwifi-firmware/package.mk | 17 + .../kernel-firmware/firmwares/any.dat | 22 + .../kernel-firmware/firmwares/x86_64.dat | 13 + .../linux-firmware/kernel-firmware/package.mk | 64 + ...rmware-02-add-brcmfmac-43xxx-configs.patch | 188 + .../linux-firmware/misc-firmware/package.mk | 17 + .../rockchip-firmware/modprobe.d/bcmdhd.conf | 1 + .../rockchip-firmware/package.mk | 44 + .../scripts/hciattach-realtek-config | 17 + .../system.d/btattach@.service | 11 + .../system.d/hciattach-realtek.service | 12 + .../system.d/hciattach@.service | 11 + .../udev.d/80-rockchip-firmware.rules | 32 + .../linux-firmware/slice-firmware/package.mk | 26 + .../linux-firmware/wlan-firmware/package.mk | 16 + packages/kernel/linux/package.mk | 302 + .../linux-010_sx05re_set_colordepth.patch | 19 + ...ix-confusion-on-conflicting-mappings.patch | 143 + ...-conflicting-keyboard-mappings-quirk.patch | 34 + .../linux-010_sx05re_set_colordepth.patch | 31 + .../linux-051-ouya_controller_support.patch | 206 + ..._sony-add_autorepeat_for_PS3_remotes.patch | 72 + .../linux-062-imon_pad_ignore_diagonal.patch | 21 + ...-improve-xbox-dvd-remote-performance.patch | 158 + .../linux-999-no-lzma-in-x86-perf-build.patch | 13 + ...able-async-suspend-resume-by-default.patch | 25 + ...-with-clockfreq-changes-on-Bay-Trail.patch | 89 + ...dle-Disable-C6N-and-C6S-on-Bay-Trail.patch | 53 + ...nux-004_lower_undefined_mode_timeout.patch | 24 + .../patches/linux-007_die_floppy_die.patch | 30 + ...009_disable_i8042_check_on_apple_mac.patch | 59 + .../patches/linux-010-usbhid-quirks.patch | 58 + .../linux-051-ouya_controller_support.patch | 206 + .../linux-052-xbox_dvd_remote_support.patch | 466 + ..._sony-add_autorepeat_for_PS3_remotes.patch | 72 + .../linux-062-imon_pad_ignore_diagonal.patch | 21 + ...-extend-rc6-toggle-support-for-zotac.patch | 41 + .../linux-903-backport-rcmm-ir-decoder.patch | 506 + ...-improve-xbox-dvd-remote-performance.patch | 158 + ...able-async-suspend-resume-by-default.patch | 25 + packages/kernel/linux/sysctl.d/network.conf | 1 + packages/kernel/linux/sysctl.d/qdisc.conf | 1 + .../linux/udev.d/30-disable-wakeup.rules | 8 + .../kernel/linux/udev.d/40-modeswitch.rules | 11 + packages/lang/Python2/package.mk | 125 + .../patches/Python2-2.7.11-001_xcompile.patch | 50 + .../Python2-2.7.11-002_xcompile_path.patch | 49 + ...-2.7.11-003_xcompile_disable_modules.patch | 16 + ...11-004_xcompile_fix_libffi_configure.patch | 24 + ...-005_dont_generate_pyo_and_pyc_files.patch | 29 + ...thon2-2.7.11-006_fix_ncurse_cppflags.patch | 12 + ....11-008-distutils-use-python-sysroot.patch | 54 + ...ython2-2.7.11-008-reread-environment.patch | 34 + .../Python2-2.7.11-009-distutils-rpath.patch | 21 + ...Python2-2.7.11-010-fix-python-config.patch | 208 + ...2-2.7.11-014-abort-on-failed-modules.patch | 21 + .../Python2-2.7.11-015_no_static_lib.patch | 51 + ...hon2-2.7.11-016-default-is-optimized.patch | 13 + ...Python2-2.7.11-017-dont-install-2to3.patch | 12 + ...2-2.7.15-001_disable_restricted_mode.patch | 11 + ...orm_machine_func_for_32bit_userspace.patch | 14 + packages/lang/Python3/package.mk | 140 + .../Python3-0000-default-is-optimized.patch | 19 + .../Python3-0100-buildroot-patches.patch | 1844 + .../patches/Python3-0201-xcompile.patch | 53 + .../patches/Python3-0202-xcompile.patch | 48 + ...n3-0300-generate-legacy-pyc-bytecode.patch | 42 + .../patches/Python3-0400-fix-bpo5537.patch | 27 + .../patches/Python3-0500-fix-bpo45262.patch | 26 + packages/lang/dotnet-runtime/changelog.txt | 32 + packages/lang/dotnet-runtime/icon/icon.png | Bin 0 -> 51118 bytes packages/lang/dotnet-runtime/package.mk | 54 + .../lang/dotnet-runtime/source/bin/le_dotnet | 10 + .../lang/gcc-arm-aarch64-none-elf/package.mk | 36 + .../gcc-arm-aarch64-none-linux-gnu/package.mk | 36 + packages/lang/gcc/package.mk | 145 + ...-4.8.2-disable_multilib_i386_linux64.patch | 13 + .../patches/gcc-allow-newer-autoconf.patch | 32 + .../patches/gcc-crosscompile-badness.patch | 31 + packages/lang/jdk-x86_64-zulu/package.mk | 15 + packages/lang/jre.zulu/changelog.txt | 2 + packages/lang/jre.zulu/icon/icon.png | Bin 0 -> 18090 bytes packages/lang/jre.zulu/package.mk | 42 + packages/lang/jre.zulu/profile.d/jre.profile | 8 + packages/lang/jre.zulu/source/default.py | 2 + packages/lang/llvm/package.mk | 71 + packages/lang/llvm/patches/llvm-config.patch | 13 + packages/lang/llvm/patches/no-z3.patch | 47 + packages/lang/mono/package.mk | 25 + packages/lang/nasm/package.mk | 13 + packages/lang/ruby/package.mk | 21 + .../mediacenter/CoreELEC-settings/package.mk | 37 + .../CoreELEC-settings/scripts/backup-restore | 63 + .../CoreELEC-settings/scripts/factory-reset | 88 + .../system.d/backup-restore.service | 10 + .../system.d/backup-restore.target | 5 + .../system.d/factory-reset.service | 10 + .../system.d/factory-reset.target | 5 + .../mediacenter/JsonSchemaBuilder/package.mk | 21 + .../mediacenter/LibreELEC-settings/package.mk | 38 + .../LibreELEC-settings/scripts/backup-restore | 61 + .../LibreELEC-settings/scripts/factory-reset | 85 + .../system.d/backup-restore.service | 10 + .../system.d/backup-restore.target | 5 + .../system.d/factory-reset.service | 10 + .../system.d/factory-reset.target | 5 + packages/mediacenter/TexturePacker/package.mk | 25 + packages/mediacenter/p8-platform/package.mk | 21 + .../p8-platform-01-revert-cc-badness.patch | 28 + ...rm-02-cmake_install_prefix_toolchain.patch | 32 + packages/multimedia/aom/package.mk | 25 + packages/multimedia/dav1d/package.mk | 18 + packages/multimedia/ffmpeg/package.mk | 213 + .../libreelec/ffmpeg-001-libreelec.patch | 73 + .../ffmpeg/patches/rpi/ffmpeg-001-rpi.patch | 58558 ++++++++++++++++ .../ffmpeg-001-v4l2-drmprime.patch | 970 + .../ffmpeg-001-v4l2-request.patch | 5843 ++ .../multimedia/intel-vaapi-driver/package.mk | 25 + packages/multimedia/libaacs/package.mk | 24 + packages/multimedia/libamcodec/package.mk | 22 + packages/multimedia/libass/package.mk | 23 + packages/multimedia/libbdplus/package.mk | 25 + packages/multimedia/libbluray/package.mk | 41 + ...-with-autoconf-archive-2016-or-later.patch | 30 + ...ray-01-bump_to_Nevcairiel_vL20170904.patch | 2247 + ...bbluray-02-install-extra-MVC-headers.patch | 42 + packages/multimedia/libdvbpsi/package.mk | 19 + packages/multimedia/libdvdcss/package.mk | 13 + packages/multimedia/libdvdnav/package.mk | 13 + packages/multimedia/libdvdread/package.mk | 17 + packages/multimedia/libhdhomerun/package.mk | 28 + packages/multimedia/libmpeg2/package.mk | 19 + .../patches/libmpeg2-0.5.1-altivec.patch | 23 + .../libmpeg2-0.5.1-arm-private-symbols.patc | 44 + .../patches/libmpeg2-0.5.1-armv4l.patch | 19 + .../libmpeg2-0.5.1-global-symbol-test.patch | 60 + packages/multimedia/libva/package.mk | 29 + packages/multimedia/libvdpau/package.mk | 16 + packages/multimedia/mpv/package.mk | 29 + packages/multimedia/mpv/waf/waf | 170 + packages/multimedia/opus/package.mk | 23 + packages/multimedia/opusfile/package.mk | 35 + packages/multimedia/rkmpp/package.mk | 21 + packages/multimedia/rtmpdump/package.mk | 71 + .../patches/001_fix-racing-build-issue.patch | 10 + .../patches/002_build-with-openssl11.patch | 249 + packages/multimedia/vlc/package.mk | 144 + packages/multimedia/x264/package.mk | 42 + packages/multimedia/x265/package.mk | 18 + packages/network/avahi/debug.d/avahi.conf | 1 + packages/network/avahi/default.d/avahi.conf | 0 packages/network/avahi/package.mk | 96 + .../avahi/system.d/avahi-daemon.service | 18 + .../avahi/system.d/avahi-defaults.service | 11 + packages/network/bluez/debug.d/bluez.conf | 1 + packages/network/bluez/debug.d/obexd.conf | 1 + packages/network/bluez/default.d/bluez.conf | 0 packages/network/bluez/package.mk | 71 + .../patches/bluez-01_add-obexd-policy.patch | 41 + .../bluez-02_obexd-use-system-bus.patch | 25 + .../bluez/patches/bluez-03_storagedir.patch | 21 + ...tech-diNovo-Edge-keyboard-firmware-i.patch | 29 + ...c52b-Logitech-Inc.-Unifying-Receiver.patch | 26 + .../patches/bluez-06-broadcom-fixes.patch | 51 + ...oadcom-dont-set-speed-before-loading.patch | 21 + ...-retry-device-reset-when-no-response.patch | 62 + .../bluez-09-hciattach-more-verbose.patch | 11 + ...ixaxis-fix-PID-navigation-controller.patch | 48 + .../bluez-12-fix-obexd-after-5_50.patch | 40 + .../patches/bluez-20-sixaxis-autotrust.patch | 10 + ...iattach-add-QCA9377-Tuffello-support.patch | 2376 + .../bluez/system.d/bluetooth-defaults.service | 11 + .../network/bluez/system.d/bluetooth.service | 21 + packages/network/bluez/system.d/obex.service | 17 + .../network/bluez/tmpfiles.d/z_05_bluez.conf | 4 + packages/network/connman/config/settings | 8 + packages/network/connman/debug.d/connman.conf | 2 + packages/network/connman/package.mk | 94 + .../connman-01-do-not-cleanup-routes.patch | 13 + .../connman-04-ipv6-disabled-by-default.patch | 22 + .../connman-05_link-against-ncurses.patch | 25 + .../network/connman/scripts/connman-setup | 25 + .../connman/system.d/connman-vpn.service | 14 + .../network/connman/system.d/connman.service | 21 + .../connman/system.d/network-online.service | 17 + .../connman/tmpfiles.d/z_03_connman.conf | 5 + packages/network/ethtool/package.mk | 12 + .../ethtool/udev.d/99-wakeup-eth.rules | 12 + packages/network/fping/package.mk | 17 + packages/network/iptables/config/README | 17 + packages/network/iptables/config/home.v4 | 44 + packages/network/iptables/config/home.v6 | 34 + packages/network/iptables/config/public.v4 | 31 + packages/network/iptables/config/public.v6 | 30 + packages/network/iptables/package.mk | 34 + .../network/iptables/scripts/iptables_helper | 99 + .../iptables/system.d/iptables.service | 17 + packages/network/iw/package.mk | 21 + packages/network/iw/scripts/setregdomain | 8 + .../network/iw/udev.d/60-iw-regdomain.rules | 1 + packages/network/libdnet/package.mk | 29 + packages/network/libmnl/package.mk | 11 + packages/network/libnfs/package.mk | 19 + packages/network/libnftnl/package.mk | 14 + packages/network/libnl/package.mk | 16 + packages/network/libshairplay/package.mk | 22 + ...ibshairplay-read_airportkey_from_etc.patch | 19 + packages/network/libssh/package.mk | 35 + packages/network/libssh2/package.mk | 15 + packages/network/libtirpc/package.mk | 19 + packages/network/netbase/package.mk | 18 + .../network/nss-mdns/config/nsswitch.conf | 19 + packages/network/nss-mdns/package.mk | 18 + packages/network/openssh/package.mk | 58 + .../patches/openssh-7.9p1-keydir.patch | 119 + .../network/openssh/system.d/sshd.service | 20 + .../openssh/tmpfiles.d/z_04_openssh.conf | 6 + packages/network/openvpn/package.mk | 26 + packages/network/rfkill/package.mk | 11 + .../patches/rfkill-0001-fix-version-sh.patch | 23 + packages/network/rpcbind/package.mk | 22 + ...cbind-01-drop-warm-start-as-it-fails.patch | 18 + packages/network/rsync/package.mk | 15 + .../network/samba/config/samba4-cache.txt | 46 + packages/network/samba/config/smb.conf | 89 + packages/network/samba/default.d/samba.conf | 7 + packages/network/samba/package.mk | 207 + .../samba-200-4.11-fix-ASN1-bso14164.patch | 86 + .../samba/patches/samba-950-no-man.patch | 39 + .../samba/patches/samba-951-no-man-4.13.patch | 32 + .../network/samba/scripts/samba-autoshare | 13 + packages/network/samba/scripts/samba-config | 41 + packages/network/samba/scripts/smbd-config | 77 + .../network/samba/system.d.opt/nmbd.service | 19 + .../network/samba/system.d.opt/smbd.service | 20 + .../samba/system.d/samba-config.service | 10 + .../modules-load.d/wireguard.conf | 1 + .../network/wireguard-linux-compat/package.mk | 27 + .../config/system.d/wireguard.service.sample | 13 + .../config/wireguard/wireguard.config.sample | 14 + packages/network/wireguard-tools/package.mk | 31 + .../network/wireguard-tools/scripts/wg-keygen | 25 + .../tmpfiles.d/z_03_wireguard.conf | 4 + packages/network/wireless-regdb/package.mk | 12 + .../wpa_supplicant/config/makefile.config | 35 + packages/network/wpa_supplicant/package.mk | 36 + .../wpa_supplicant-2.4-libnl3-includes.patch | 12 + packages/oem/package.mk | 11 + packages/print/freetype/package.mk | 33 + packages/print/poppler/package.mk | 23 + packages/python/devel/Mako/package.mk | 17 + packages/python/devel/MarkupSafe/package.mk | 17 + .../python/devel/distutilscross/package.mk | 17 + .../distutilscross-0000-fix-python3.patch | 57 + packages/python/devel/meson/package.mk | 24 + packages/python/devel/ninja/package.mk | 18 + packages/python/devel/pathlib/package.mk | 16 + packages/python/devel/pygobject/package.mk | 26 + ...ct-0001-add-PYTHON_INCLUDES-override.patch | 32 + .../pygobject-2.28.6-automake-1.13.patch | 20 + packages/python/devel/setuptools/package.mk | 21 + packages/python/devel/waf/package.mk | 21 + packages/python/graphics/Pillow/package.mk | 32 + .../patches/Pillow-0001-crosscompiling.patch | 13 + .../python/security/pycryptodome/package.mk | 39 + packages/python/system/dbus-python/package.mk | 23 + packages/python/system/dbussy/package.mk | 24 + packages/python/system/simplejson/package.mk | 31 + packages/security/gnupg/package.mk | 28 + packages/security/gnutls/package.mk | 27 + packages/security/libgcrypt/package.mk | 31 + ...pt-01-dont_replace_parts_of_path-0.1.patch | 24 + ...ibgcrypt-ac_cv_sys_symbol_underscore.patch | 27 + packages/security/libgpg-error/package.mk | 42 + packages/security/nettle/package.mk | 23 + packages/security/nspr/package.mk | 42 + packages/security/nss/package.mk | 80 + .../patches/nss-02_3.15.5-standalone-1.patch | 241 + .../nss/patches/nss-04-skip_shlibsign.patch | 12 + .../patches/nss-05-disable_host_cflags.patch | 12 + .../patches/nss-06-always-include-fstar.patch | 15 + packages/security/openssl/cert/cacert.pem | 3512 + packages/security/openssl/package.mk | 111 + .../security/openssl/scripts/openssl-config | 10 + .../openssl/system.d/openssl-config.service | 11 + packages/sysutils/amremote/package.mk | 34 + .../sysutils/amremote/scripts/remote-config | 84 + .../amremote/system.d/remote-config.service | 13 + packages/sysutils/autossh/package.mk | 23 + packages/sysutils/bash/package.mk | 16 + packages/sysutils/bkeymaps/package.mk | 20 + .../sysutils/busybox/config/busybox-host.conf | 1162 + .../sysutils/busybox/config/busybox-init.conf | 1186 + .../busybox/config/busybox-target.conf | 1182 + packages/sysutils/busybox/config/httpd.conf | 46 + packages/sysutils/busybox/config/inputrc | 66 + packages/sysutils/busybox/config/profile | 34 + .../busybox/config/suspend-modules.conf | 1 + .../sysutils/busybox/default.d/crond.conf | 0 packages/sysutils/busybox/package.mk | 231 + .../patches/busybox-00_halt_no_init.patch | 12 + ...box-02_silence-crond-startup-logging.patch | 20 + .../busybox-03-make_unicode_printable.patch | 26 + .../busybox-04-revert-dd-fsync-change.patch | 34 + ...-05-update-shadow-or-passwd-not-both.patch | 12 + .../busybox-06-prevent-root-weak-passwd.patch | 12 + ...IND-option-when-remouting-bind-mount.patch | 86 + .../busybox/profile.d/98-busybox.conf | 19 + packages/sysutils/busybox/scripts/createlog | 180 + packages/sysutils/busybox/scripts/dtfile | 20 + packages/sysutils/busybox/scripts/dtname | 21 + packages/sysutils/busybox/scripts/fs-resize | 55 + packages/sysutils/busybox/scripts/functions | 156 + packages/sysutils/busybox/scripts/getedid | 256 + packages/sysutils/busybox/scripts/init | 1403 + packages/sysutils/busybox/scripts/lsb_release | 7 + packages/sysutils/busybox/scripts/pastebinit | 8 + .../busybox/scripts/rpi-flash-firmware | 42 + .../sleep.d.serial/99-suspend-modules.sh | 93 + .../busybox/sysctl.d/99-coredump.conf | 1 + packages/sysutils/busybox/sysctl.d/cdrom.conf | 2 + .../sysutils/busybox/sysctl.d/memory.conf | 1 + .../system.d.opt/cron-defaults.service | 11 + .../busybox/system.d.opt/cron.service | 16 + .../busybox/system.d/fs-resize.service | 10 + .../busybox/system.d/fs-resize.target | 5 + .../system.d/rpi-flash-firmware.service | 12 + .../system.d/rpi-flash-firmware.target | 5 + .../sysutils/busybox/system.d/shell.service | 23 + .../busybox/system.d/show-version.service | 13 + .../busybox/system.d/storage-log.service | 9 + .../sysutils/busybox/system.d/textmode.target | 6 + .../sysutils/busybox/system.d/var-log.mount | 14 + packages/sysutils/busybox/system.d/var.mount | 21 + .../busybox/tmpfiles.d/z_01_busybox.conf | 10 + packages/sysutils/dbus/package.mk | 48 + .../sysutils/dbus/tmpfiles.d/z_02_dbus.conf | 7 + packages/sysutils/depends/efivar/package.mk | 33 + .../efivar/patches/efivar-01-static_lib.patch | 11 + packages/sysutils/depends/libmtp/package.mk | 17 + ...mtp-0001-dont-execute-compiled-tools.patch | 99 + .../sysutils/depends/oniguruma/package.mk | 11 + packages/sysutils/diffutils/package.mk | 21 + .../patches/diffutils-001-no-man.patch | 11 + ...-explicitly-disable-replacing-getopt.patch | 26 + packages/sysutils/diskdev_cmds/package.mk | 29 + .../patches/diskdev_cmds-332.14-main.patch | 2713 + packages/sysutils/dosfstools/package.mk | 38 + ...s-01-silence_backup_boot_sector_diff.patch | 23 + packages/sysutils/dstat/package.mk | 16 + packages/sysutils/dtach/package.mk | 15 + packages/sysutils/e2fsprogs/package.mk | 117 + ...emove-64bit-from-default-ext4-config.patch | 11 + packages/sysutils/efibootmgr/package.mk | 25 + packages/sysutils/encfs/package.mk | 19 + packages/sysutils/entropy/package.mk | 24 + packages/sysutils/entropy/sources/add-entropy | 24 + .../entropy/sources/add-random-at-shutdown | 2 + .../entropy/system.d/add-entropy.service | 13 + .../system.d/add-random-at-shutdown.service | 12 + packages/sysutils/ethmactool/package.mk | 17 + .../ethmactool/scripts/ethmactool-config | 73 + .../system.d/ethmactool-config.service | 13 + .../eventlircd/evmap/03_03eb_0002.evmap | 8 + .../eventlircd/evmap/03_0419_0001.evmap | 17 + .../eventlircd/evmap/03_046d_c101.evmap | 14 + .../eventlircd/evmap/03_05a4_9881.evmap | 57 + .../eventlircd/evmap/03_05ac_8241.evmap | 4 + .../eventlircd/evmap/03_0709_9137.evmap | 17 + .../eventlircd/evmap/03_0755_2626.evmap | 56 + .../eventlircd/evmap/03_0bc7_0006.evmap | 13 + .../eventlircd/evmap/03_1241_e000.evmap | 47 + .../eventlircd/evmap/03_13ec_0006.evmap | 16 + .../eventlircd/evmap/03_147a_e02d.evmap | 15 + .../eventlircd/evmap/03_18b1_0037.evmap | 24 + .../eventlircd/evmap/03_1d57_ac01.evmap | 27 + .../eventlircd/evmap/aboxwireless.evmap | 6 + .../eventlircd/evmap/aftvsremote.evmap | 11 + .../eventlircd/evmap/bdremoteng.evmap | 7 + .../sysutils/eventlircd/evmap/cypress.evmap | 40 + .../sysutils/eventlircd/evmap/default.evmap | 1 + .../sysutils/eventlircd/evmap/mcekbd.evmap | 28 + .../sysutils/eventlircd/evmap/osmc_rf.evmap | 13 + .../sysutils/eventlircd/evmap/osmc_rf2.evmap | 13 + .../sysutils/eventlircd/evmap/ps3remote.evmap | 29 + .../eventlircd/evmap/spinelplus.evmap | 19 + .../eventlircd/evmap/tevii_s660.evmap | 26 + .../sysutils/eventlircd/evmap/topseed.evmap | 25 + .../sysutils/eventlircd/evmap/wiimote.evmap | 9 + .../eventlircd/evmap/xiaomibtremote.evmap | 4 + .../eventlircd/evmap/xiaomibtremoteAM.evmap | 4 + packages/sysutils/eventlircd/package.mk | 29 + .../eventlircd/system.d/eventlircd.service | 11 + .../tmpfiles.d/z_62_eventlircd.conf | 4 + .../eventlircd/udev.d/98-eventlircd.rules | 240 + packages/sysutils/evtest/package.mk | 16 + packages/sysutils/exfat/package.mk | 24 + .../sysutils/exfat/patches/01-no-fuse.patch | 119 + packages/sysutils/exfatprogs/package.mk | 13 + packages/sysutils/fdupes/package.mk | 15 + packages/sysutils/file/package.mk | 16 + .../file-move-magic.mgc-to-addon-data.patch | 25 + packages/sysutils/fuse-exfat/package.mk | 13 + packages/sysutils/fuse/package.mk | 27 + .../patches/fuse-0001_aarch64-support.patch | 33 + .../fuse-0002-dont-run-update-rc.d.patch | 13 + packages/sysutils/getscancodes/package.mk | 19 + packages/sysutils/gptfdisk/package.mk | 20 + packages/sysutils/grep/package.mk | 13 + packages/sysutils/hd-idle/package.mk | 16 + .../hd-idle/patches/hd-idle-makefile.patch | 15 + packages/sysutils/hddtemp/db/hddtemp.db | 523 + packages/sysutils/hddtemp/package.mk | 21 + packages/sysutils/hid_mapper/package.mk | 15 + .../patches/hid_mapper-01_crosscompile.patch | 21 + .../hid_mapper-02_include-sys-time.patch | 12 + .../patches/hid_mapper-03_fix-parser.patch | 14 + packages/sysutils/htop/package.mk | 20 + packages/sysutils/i2c-tools/package.mk | 28 + .../sysutils/inject_bl301/config/bl301.conf | 25 + packages/sysutils/inject_bl301/package.mk | 40 + .../inject_bl301/scripts/check-bl301.sh | 36 + .../inject_bl301/scripts/update-bl301.sh | 54 + .../system.d/update-bl301.service | 10 + packages/sysutils/inotify-tools/package.mk | 22 + packages/sysutils/irqbalanced/package.mk | 21 + .../irqbalanced/system.d/irqbalance.service | 10 + packages/sysutils/jq/package.mk | 21 + packages/sysutils/kbd/package.mk | 21 + packages/sysutils/keyutils/package.mk | 22 + .../keyutils/patches/keyutils-02-cflags.patch | 23 + .../sysutils/kmod/modprobe.d/aliases.conf | 172 + packages/sysutils/kmod/modprobe.d/i2c.conf | 1 + packages/sysutils/kmod/package.mk | 55 + .../kmod/patches/kmod-02_fix-pkgconf.patch | 27 + packages/sysutils/libevdev/package.mk | 21 + packages/sysutils/libhid/package.mk | 21 + .../patches/libhid-0.2.16-automake-1.13.patch | 12 + .../patches/libhid-0.2.16-autoreconf.patch | 531 + .../libhid/patches/libhid-use_pkgconfig.patch | 14 + packages/sysutils/libusb-compat/package.mk | 18 + packages/sysutils/libusb/package.mk | 21 + .../sysutils/lirc/config/lirc_options.conf | 43 + packages/sysutils/lirc/default.d/lircd.conf | 0 packages/sysutils/lirc/package.mk | 57 + .../patches/lirc-0001-fix-zotac-poll.patch | 29 + ...on-t-use-broken-LOG_CONS-syslog-flag.patch | 24 + ...Fix-connect-option-parsing-error-343.patch | 22 + ...Notify-systemd-on-successful-startup.patch | 43 + .../patches/lirc-0100-disable-python.patch | 128 + packages/sysutils/lirc/scripts/lircd_helper | 10 + .../sysutils/lirc/scripts/lircd_uinput_helper | 10 + .../lirc/system.d/lircd-uinput.service | 12 + packages/sysutils/lirc/system.d/lircd.service | 12 + packages/sysutils/lirc/system.d/lircd.socket | 6 + .../sysutils/lirc/tmpfiles.d/z_61_lirc.conf | 4 + packages/sysutils/lm_sensors/package.mk | 25 + .../patches/lm_sensors-01_link-static.patch | 25 + packages/sysutils/lshw/package.mk | 19 + packages/sysutils/mc/package.mk | 48 + packages/sysutils/mc/wrapper/mc | 4 + packages/sysutils/mc/wrapper/mcedit | 4 + packages/sysutils/mc/wrapper/mcview | 4 + packages/sysutils/mrxvt/package.mk | 53 + .../mrxvt/patches/mrxvt-01_xterm.patch | 11 + packages/sysutils/mtpfs/package.mk | 23 + packages/sysutils/nmon/package.mk | 26 + .../sysutils/ntfs-3g_ntfsprogs/package.mk | 41 + ...mounting-after-Win10-Creators-Update.patch | 28 + packages/sysutils/open-iscsi/package.mk | 32 + ...n-iscsi-01_dynamic_linked_iscsistart.patch | 11 + .../patches/open-iscsi-02-cross_compile.patch | 64 + .../open-iscsi-03_enable-multicast.patch | 26 + .../patches/open-iscsi-04-no_iscsiuio.patch | 25 + packages/sysutils/open-vm-tools/package.mk | 53 + .../open-vm-tools/system.d/vmtoolsd.service | 9 + .../system.d/vmware-vmblock-fuse.service | 12 + packages/sysutils/parted/package.mk | 35 + .../parted/patches/parted-0001-buildfix.patch | 45 + .../parted-0002-buildfix-glibc-2.28.patch | 29 + packages/sysutils/patch/package.mk | 17 + packages/sysutils/pciutils/package.mk | 38 + .../patches/pciutils-01-fix-pkgconf.patch | 27 + packages/sysutils/pv/package.mk | 17 + .../sysutils/rclone/cloud-sync-rules.conf | 32 + packages/sysutils/rclone/cloud-sync.conf | 5 + packages/sysutils/rclone/package.mk | 23 + packages/sysutils/screen/package.mk | 31 + .../screen/patches/screen-cross-compile.patch | 64 + .../screen-dont_link_against_libelf.patch | 22 + packages/sysutils/sed/package.mk | 13 + packages/sysutils/smartmontools/package.mk | 23 + packages/sysutils/squashfs-tools/package.mk | 30 + packages/sysutils/strace/package.mk | 14 + .../patches/strace-0001-autoreconf.patch | 17 + .../strace-0002-fix-autoconf-archive.patch | 39 + packages/sysutils/stress-ng/package.mk | 11 + packages/sysutils/systemd/config/hosts.conf | 10 + .../sysutils/systemd/config/hwdb.d/README | 10 + .../systemd/config/logind.conf.d/README | 233 + .../systemd/config/modules-load.d/README | 33 + .../systemd/config/sleep.conf.d/README | 59 + .../config/sleep.conf.d/sleep.conf.sample | 3 + .../sysutils/systemd/config/sysctl.d/README | 35 + .../sysutils/systemd/config/system.d/README | 232 + .../systemd/config/system.d/cifs.mount.sample | 50 + .../systemd/config/system.d/nfs.mount.sample | 50 + .../config/system.d/openvpn.service.sample | 44 + .../systemd/config/timesyncd.conf.d/README | 86 + .../sysutils/systemd/config/tmpfiles.d/README | 109 + .../systemd/config/udev.rules.d/README | 25 + .../systemd/hwdb.d/70-local-keyboard.hwdb | 3 + packages/sysutils/systemd/package.mk | 292 + ...03-syscall_397_doesnt_exists_on_3.14.patch | 42 + .../amlogic/systemd-9999.1-backport.patch | 14185 ++++ .../amlogic/systemd-9999.2-backport.patch | 41 + .../amlogic/systemd-9999.3-backport.patch | 648 + .../amlogic/systemd-9999.4-backport.patch | 235 + ...d-system-to-storage-.config-system.d.patch | 19 + .../systemd-0002-move-hwdb.bin-to-run.patch | 53 + ...d-0003-remove-nonexistant-dependency.patch | 24 + ...0200-persist-persistent-timer-stamps.patch | 29 + ...ystemd-0300-config-env-unhide-cursor.patch | 27 + ...00-hide-useless-shutdown-log-message.patch | 46 + ...ng-directory-storage-for-debug-shell.patch | 24 + .../systemd/profile.d/90-systemd.conf | 4 + .../systemd/scripts/kernel-overlays-setup | 85 + .../systemd/scripts/network-base-setup | 30 + .../systemd/scripts/systemd-machine-id-setup | 20 + .../systemd/scripts/systemd-timesyncd-setup | 22 + .../sysutils/systemd/scripts/usercache-setup | 27 + .../sysutils/systemd/scripts/userconfig-setup | 27 + .../systemd/system.d/debugconfig.service | 14 + .../system.d/flash.mount.d/dependencies.conf | 2 + .../sysutils/systemd/system.d/hwdb.service | 12 + .../systemd/system.d/kernel-overlays.service | 12 + .../systemd/system.d/machine-id.service | 12 + .../systemd/system.d/network-base.service | 12 + .../storage.mount.d/dependencies.conf | 2 + .../system.d/systemd-timesyncd-setup.service | 12 + .../depend-on-kernel-ip-config.conf | 3 + .../systemd/system.d/usercache.service | 12 + .../systemd/system.d/userconfig.service | 12 + .../systemd/tmpfiles.d/z_01_openelec.conf | 5 + .../udev.d/51-these-are-not-joysticks.rules | 107 + .../systemd/udev.d/60-not-joysticks.rules | 2 + .../sysutils/systemd/udev.d/80-clock.rules | 2 + packages/sysutils/terminus-font/package.mk | 52 + packages/sysutils/tz/package.mk | 32 + packages/sysutils/tz/system.d/tz-data.service | 16 + packages/sysutils/udevil/config/udevil.conf | 332 + packages/sysutils/udevil/package.mk | 33 + .../udevil/patches/udevil-fix-build.patch | 11 + .../udevil/system.d/udevil-mount@.service | 10 + .../udevil/udev.d/95-udevil-mount.rules | 30 + packages/sysutils/unrar/package.mk | 34 + packages/sysutils/usb-modeswitch/package.mk | 15 + packages/sysutils/usbutils/package.mk | 16 + packages/sysutils/util-linux/config/swap.conf | 6 + packages/sysutils/util-linux/package.mk | 96 + .../patches/util-linux-01-fix-pkgconf.patch | 75 + ...-LOOP_CONFIGURE-in-a-more-robust-way.patch | 36 + .../sysutils/util-linux/scripts/mount-swap | 50 + .../util-linux/sysctl.d/swappiness.conf | 1 + .../sysutils/util-linux/system.d/swap.service | 21 + .../v4l-utils/config/rc_keymaps/README | 3 + .../v4l-utils/config/rc_maps.cfg.sample | 20 + packages/sysutils/v4l-utils/keymaps/a95x | 35 + .../sysutils/v4l-utils/keymaps/beelink_bt_ir | 16 + .../v4l-utils/keymaps/beelink_pwr_only | 3 + packages/sysutils/v4l-utils/keymaps/cubox_i | 10 + packages/sysutils/v4l-utils/keymaps/kvim | 13 + packages/sysutils/v4l-utils/keymaps/kvim2 | 46 + packages/sysutils/v4l-utils/keymaps/mecool | 46 + packages/sysutils/v4l-utils/keymaps/minix_neo | 13 + .../v4l-utils/keymaps/minix_neo_pwr_only | 2 + packages/sysutils/v4l-utils/keymaps/odroid | 13 + packages/sysutils/v4l-utils/keymaps/pine64 | 26 + packages/sysutils/v4l-utils/keymaps/tanix | 14 + packages/sysutils/v4l-utils/keymaps/wetek_hub | 13 + .../sysutils/v4l-utils/keymaps/wetek_play_2 | 44 + packages/sysutils/v4l-utils/keymaps/xbox_360 | 66 + packages/sysutils/v4l-utils/keymaps/xbox_dvd | 28 + packages/sysutils/v4l-utils/keymaps/xbox_one | 22 + packages/sysutils/v4l-utils/keymaps/zotac | 44 + packages/sysutils/v4l-utils/package.mk | 109 + ...utils-0001-fix-build-with-glibc_2.28.patch | 37 + ...v4l-utils-0002-add-power-on-argument.patch | 201 + ...kport-imon-and-rcmm-protocol-support.patch | 35 + ...v4l-utils-0003-add-xbox-dvd-protocol.patch | 33 + ...ils-0004-add-power-on-argument-fixup.patch | 91 + .../v4l-utils/udev.d/70-infrared.rules | 19 + .../v4l-utils/udev.d/70-input-repeat.rules | 18 + packages/sysutils/v86d/package.mk | 25 + .../patches/v86d-0.1.10-crosscompiling.patch | 12 + ...6d-0.1.10-dont-include-kernelheaders.patch | 18 + packages/sysutils/wait-time-sync/package.mk | 15 + .../sysutils/wait-time-sync/sources/Makefile | 12 + .../wait-time-sync/sources/wait-time-sync.c | 23 + .../system.d/wait-time-sync.service | 28 + packages/sysutils/wget/package.mk | 17 + packages/testing/package.mk | 12 + packages/textproc/expat/package.mk | 15 + packages/textproc/harfbuzz/package.mk | 22 + packages/textproc/icu/package.mk | 30 + .../textproc/icu/patches/icu-01_ldflags.patch | 12 + packages/textproc/jsoncpp/package.mk | 16 + packages/textproc/libiconv/package.mk | 24 + packages/textproc/libidn2/package.mk | 19 + packages/textproc/libxml2/package.mk | 33 + packages/textproc/libxslt/package.mk | 37 + packages/textproc/nlohmann-json/package.mk | 14 + packages/textproc/rapidxml/package.mk | 17 + packages/textproc/textviewer/package.mk | 36 + packages/textproc/tinyxml/package.mk | 19 + packages/textproc/tinyxml2/package.mk | 18 + ...ml2-0001-really-disable-shared-build.patch | 30 + packages/textproc/xmlstarlet/package.mk | 40 + ...sage2c.awk-fix-wrong-basename-regexp.patch | 37 + packages/tools/SDL2_gfx/package.mk | 18 + packages/tools/SDL2_image/package.mk | 13 + packages/tools/SDL2_mixer/package.mk | 15 + packages/tools/SDL2_net/package.mk | 12 + packages/tools/SDL2_ttf/package.mk | 19 + .../SDL2_ttf-001-opengl-only-with-x.patch | 45 + packages/tools/aml-dtbtools/package.mk | 18 + packages/tools/atf/package.mk | 21 + ...6-add-wdt_quirk-to-use-r_wdt-instead.patch | 36 + .../files/3rdparty/bootloader/config.txt | 60 + .../3rdparty/bootloader/distroconfig.txt | 4 + packages/tools/bcm2835-bootloader/package.mk | 44 + packages/tools/bcm2835-bootloader/release | 23 + packages/tools/bcmstat/package.mk | 17 + packages/tools/bl301/package.mk | 47 + packages/tools/ceemmc/package.mk | 17 + packages/tools/dtc/package.mk | 32 + .../dtc-0001-libfdt-soname-version.patch | 13 + packages/tools/entware/package.mk | 23 + .../tools/entware/profile.d/99-entware.conf | 10 + packages/tools/entware/scripts/installentware | 21 + .../tools/entware/system.d/entware.service | 15 + packages/tools/flashrom/package.mk | 22 + packages/tools/grub/package.mk | 50 + .../001-gcc8-fix-packed-not-aligned.patch | 72 + packages/tools/hdparm/package.mk | 17 + .../hdparm/patches/hdparm-9.42-cflags.patch | 12 + packages/tools/hdparm/udev.d/61-cdrom.rules | 13 + .../tools/installer/config/installer.conf | 28 + packages/tools/installer/package.mk | 28 + packages/tools/installer/scripts/installer | 490 + .../installer/system.d/installer.service | 18 + .../tools/installer/system.d/installer.target | 6 + packages/tools/led_tools/package.mk | 24 + packages/tools/luajit/package.mk | 53 + .../luajit/patches/luajit-crosscompile.patch | 15 + packages/tools/miniupnpc/package.mk | 13 + packages/tools/mkbootimg/package.mk | 17 + packages/tools/mtools/package.mk | 13 + .../patches/mtools-05-fix-install.patch | 16 + packages/tools/nano/config/nanorc | 1 + packages/tools/nano/package.mk | 39 + packages/tools/nano/profile.d/52-nano.conf | 4 + packages/tools/newt/package.mk | 28 + packages/tools/plymouth-lite/package.mk | 53 + .../plymouth-lite-0.6.0-01-fix-build.patch | 10 + .../plymouth-lite-0.6.0-02-libpng_1.4.0.patch | 12 + .../plymouth-lite-0.6.0-11-cursor.patch | 11 + .../plymouth-lite-0.6.0-12-resize.patch | 110 + .../plymouth-lite-0.6.0-21-16bpp.patch | 78 + .../plymouth-lite-0.6.0-22-link-static.patch | 18 + packages/tools/populatefs/package.mk | 23 + .../patches/fix-compilation-issue.patch | 11 + packages/tools/procps-ng/package.mk | 31 + packages/tools/qemu/package.mk | 30 + packages/tools/rkbin/package.mk | 17 + .../tools/rpi-eeprom/config/rpi-eeprom-update | 4 + packages/tools/rpi-eeprom/package.mk | 49 + .../tools/rpi-eeprom/source/rpi-eeprom-update | 10 + packages/tools/rtk_hciattach/package.mk | 17 + .../patches/rtk_hciattach-01-Makefile.patch | 19 + ...02-dont-read-mac-from-vendor-storage.patch | 13 + .../scrapers/Skyscraper/config/artwork.xml | 16 + .../scrapers/Skyscraper/config/config.ini | 23 + packages/tools/scrapers/Skyscraper/package.mk | 42 + .../scrapers/Skyscraper/scripts/skyscraper | 20 + packages/tools/scrapers/scraper/package.mk | 56 + packages/tools/socat/package.mk | 18 + .../fluidsynth-git/config/fluidsynth.conf | 8 + .../tools/sound/fluidsynth-git/package.mk | 34 + .../system.d/fluidsynth.service | 10 + packages/tools/sound/libmad/package.mk | 35 + .../libmad-0.15.1b-automake_1.13.patch | 12 + .../patches/libmad-0.15.1b-cflags-O2.patch | 12 + .../patches/libmad-0.15.1b-cflags.patch | 146 + packages/tools/sound/libvorbisidec/package.mk | 20 + packages/tools/sound/mpg123/package.mk | 17 + .../sound/munt_neon/math_neon/package.mk | 29 + packages/tools/sound/munt_neon/package.mk | 48 + .../sound/soundfont-generaluser/package.mk | 18 + .../sound/timidity/config/GeneralUser.cfg | 1796 + .../sound/timidity/config/fluidr3_gm.cfg | 2830 + .../sound/timidity/config/fluidr3_gs.cfg | 97 + .../tools/sound/timidity/config/freepats.cfg | 135 + .../timidity/config/soundfont_readme.txt | 9 + .../tools/sound/timidity/config/timidity.cfg | 42 + packages/tools/sound/timidity/package.mk | 37 + .../patches/02-calcnewt-host-build.patch | 28 + .../timidity/patches/03-ar-cru-fix.patch | 11 + packages/tools/syslinux/package.mk | 76 + ...linux-0001-fix-build-with-glibc_2.28.patch | 33 + packages/tools/sysutils/MC/etc/edit.indent.rc | 31 + packages/tools/sysutils/MC/etc/edit.spell.rc | 11 + .../tools/sysutils/MC/etc/filehighlight.ini | 47 + packages/tools/sysutils/MC/etc/ini | 159 + packages/tools/sysutils/MC/etc/mc.ext | 684 + packages/tools/sysutils/MC/etc/mc.keymap | 429 + .../tools/sysutils/MC/etc/mc.keymap.default | 429 + .../tools/sysutils/MC/etc/mc.keymap.emacs | 432 + packages/tools/sysutils/MC/etc/mc.menu | 383 + packages/tools/sysutils/MC/etc/mc.menu.sr | 344 + packages/tools/sysutils/MC/etc/mcedit.menu | 486 + packages/tools/sysutils/MC/etc/panels.ini | 31 + packages/tools/sysutils/MC/etc/sfs.ini | 28 + packages/tools/sysutils/MC/package.mk | 49 + .../sysutils/MC/patches/MC-01-utf8.patch | 33 + .../tools/sysutils/MC/profile.d/52-mc.conf | 4 + packages/tools/sysutils/bluetool/package.mk | 29 + packages/tools/sysutils/coreutils/package.mk | 21 + packages/tools/sysutils/dialog/package.mk | 16 + packages/tools/sysutils/empty/package.mk | 26 + .../tools/sysutils/evdev_tools/package.mk | 32 + .../sysutils/evdev_tools/sources/evkill.c | 173 + .../sysutils/evdev_tools/sources/evtest.c | 364 + .../sysutils/evdev_tools/sources/remap.c | 118 + .../tools/sysutils/evdev_tools/sources/send.c | 68 + packages/tools/sysutils/fbterm/package.mk | 29 + ...roxy.cpp-fbterm.cpp-fix-musl-compile.patch | 70 + .../fbterm/patches/gcc-6-build-fixes.patch | 104 + .../tools/sysutils/fbterm/terminfo/E/Eterm | Bin 0 -> 2267 bytes .../sysutils/fbterm/terminfo/E/Eterm-color | 1 + .../tools/sysutils/fbterm/terminfo/a/ansi | Bin 0 -> 1481 bytes .../tools/sysutils/fbterm/terminfo/c/cons25 | Bin 0 -> 1502 bytes .../sysutils/fbterm/terminfo/c/cons25-debian | Bin 0 -> 1519 bytes .../tools/sysutils/fbterm/terminfo/c/cygwin | Bin 0 -> 1518 bytes .../tools/sysutils/fbterm/terminfo/d/dumb | Bin 0 -> 308 bytes .../tools/sysutils/fbterm/terminfo/h/hurd | Bin 0 -> 1570 bytes .../tools/sysutils/fbterm/terminfo/l/linux | Bin 0 -> 1788 bytes .../tools/sysutils/fbterm/terminfo/m/mach | Bin 0 -> 617 bytes .../sysutils/fbterm/terminfo/m/mach-bold | Bin 0 -> 652 bytes .../sysutils/fbterm/terminfo/m/mach-color | Bin 0 -> 1095 bytes .../tools/sysutils/fbterm/terminfo/m/mach-gnu | Bin 0 -> 1056 bytes .../sysutils/fbterm/terminfo/m/mach-gnu-color | Bin 0 -> 1318 bytes .../tools/sysutils/fbterm/terminfo/p/pcansi | Bin 0 -> 1198 bytes .../tools/sysutils/fbterm/terminfo/r/rxvt | Bin 0 -> 2078 bytes .../sysutils/fbterm/terminfo/r/rxvt-basic | Bin 0 -> 2034 bytes .../tools/sysutils/fbterm/terminfo/r/rxvt-m | 1 + .../sysutils/fbterm/terminfo/r/rxvt-unicode | Bin 0 -> 2508 bytes .../tools/sysutils/fbterm/terminfo/s/screen | Bin 0 -> 1594 bytes .../fbterm/terminfo/s/screen-256color | Bin 0 -> 1912 bytes .../fbterm/terminfo/s/screen-256color-bce | Bin 0 -> 1924 bytes .../sysutils/fbterm/terminfo/s/screen-bce | Bin 0 -> 1590 bytes .../tools/sysutils/fbterm/terminfo/s/screen-s | Bin 0 -> 1612 bytes .../tools/sysutils/fbterm/terminfo/s/screen-w | Bin 0 -> 1594 bytes packages/tools/sysutils/fbterm/terminfo/s/sun | Bin 0 -> 1004 bytes .../tools/sysutils/fbterm/terminfo/v/vt100 | Bin 0 -> 1194 bytes .../tools/sysutils/fbterm/terminfo/v/vt102 | Bin 0 -> 1188 bytes .../tools/sysutils/fbterm/terminfo/v/vt220 | Bin 0 -> 1377 bytes .../tools/sysutils/fbterm/terminfo/v/vt52 | Bin 0 -> 470 bytes .../tools/sysutils/fbterm/terminfo/w/wsvt25 | Bin 0 -> 1597 bytes .../tools/sysutils/fbterm/terminfo/w/wsvt25m | Bin 0 -> 1607 bytes .../tools/sysutils/fbterm/terminfo/x/xterm | Bin 0 -> 3360 bytes .../sysutils/fbterm/terminfo/x/xterm-256color | Bin 0 -> 3430 bytes .../sysutils/fbterm/terminfo/x/xterm-color | Bin 0 -> 1569 bytes .../sysutils/fbterm/terminfo/x/xterm-debian | 1 + .../sysutils/fbterm/terminfo/x/xterm-mono | Bin 0 -> 1515 bytes .../tools/sysutils/fbterm/terminfo/x/xterm-r5 | Bin 0 -> 1301 bytes .../tools/sysutils/fbterm/terminfo/x/xterm-r6 | Bin 0 -> 1491 bytes .../sysutils/fbterm/terminfo/x/xterm-vt220 | Bin 0 -> 2316 bytes .../sysutils/fbterm/terminfo/x/xterm-xfree86 | Bin 0 -> 2265 bytes packages/tools/sysutils/freeimage/package.mk | 17 + .../patches/freeimage-02-makefix.patch | 15 + packages/tools/sysutils/git/package.mk | 35 + packages/tools/sysutils/jinja2/package.mk | 20 + packages/tools/sysutils/joyutils/package.mk | 36 + packages/tools/sysutils/jslisten/package.mk | 26 + .../jslisten/patches/001-jslisten-path.patch | 16 + packages/tools/sysutils/patchelf/package.mk | 16 + .../tools/sysutils/python-evdev/package.mk | 38 + packages/tools/sysutils/pyudev/package.mk | 30 + .../patches/pyudev-001-libraryfix.patch | 11 + packages/tools/sysutils/pyyaml/package.mk | 38 + packages/tools/sysutils/sdljoytest/package.mk | 22 + packages/tools/sysutils/six/package.mk | 30 + packages/tools/sysutils/sixaxis/package.mk | 28 + .../sixaxis/system.d/sixaxis@.service | 9 + .../sysutils/sixaxis/udev.d/99-sixaxis.rules | 7 + packages/tools/sysutils/sixpair/package.mk | 27 + packages/tools/sysutils/tcpbridge/package.mk | 29 + .../tools/sysutils/triggerhappy/package.mk | 12 + packages/tools/sysutils/xow/package.mk | 23 + packages/tools/texturecache.py/package.mk | 18 + packages/tools/u-boot-script/package.mk | 25 + .../u-boot-tools-aml/config/fw_env.config | 31 + packages/tools/u-boot-tools-aml/package.mk | 37 + .../u-boot-tools-0001-dummy_defconfig.patch | 5 + ...ot-tools-0002-allow-multiple-entries.patch | 23 + .../u-boot-tools-0003-nand_env-hack.patch | 52 + packages/tools/u-boot-tools/package.mk | 30 + packages/tools/unused/boost_locale/package.mk | 59 + packages/tools/unused/eigen/package.mk | 29 + packages/tools/unused/fbida/package.mk | 31 + packages/tools/unused/fbpad/package.mk | 40 + packages/tools/unused/fbpad/sources/Makefile | 7 + packages/tools/unused/fbpad/sources/conf.h | 63 + packages/tools/unused/fbpad/sources/courr.tf | Bin 0 -> 136976 bytes packages/tools/unused/fbpad/sources/draw.c | 148 + packages/tools/unused/fbpad/sources/fbpad-256 | 6 + packages/tools/unused/munt/package.mk | 16 + .../tools/unused/steam-controller/package.mk | 52 + ...steamcontroller-0001-fix-include-dir.patch | 24 + ...amcontroller-0002-append-python-path.patch | 92 + ...-0003-wait-for-controller-connection.patch | 62 + ...oller-0004-use-run-for-pid-directory.patch | 54 + ...5-steam-client-will-never-be-running.patch | 41 + .../system.d/driver.steam-controller.service | 14 + packages/tools/vim/package.mk | 54 + .../ui/emulationstation/bluez/bluezutils.py | 47 + .../emulationstation/config/es_features.cfg | 149 + .../ui/emulationstation/config/es_input.cfg | 90 + .../emulationstation/config/es_settings.cfg | 82 + .../ui/emulationstation/config/es_systems.cfg | 2069 + .../emulationstation/config/scripts/es_env.sh | 4 + packages/ui/emulationstation/package.mk | 73 + .../system.d/emustation.service | 17 + .../themes/alekfull-nx/package.mk | 18 + .../themes/es-theme-art-book-3-2/package.mk | 23 + .../themes/es-theme-art-book-4-3/package.mk | 23 + .../themes/es-theme-art-book-next/package.mk | 20 + packages/virtual/alsa/package.mk | 11 + packages/virtual/arm32/package.mk | 9 + packages/virtual/autotools/package.mk | 11 + packages/virtual/corefonts/package.mk | 17 + packages/virtual/debug/package.mk | 26 + packages/virtual/image/package.mk | 47 + packages/virtual/initramfs/package.mk | 38 + packages/virtual/libc/package.mk | 18 + packages/virtual/linux-drivers/package.mk | 15 + packages/virtual/linux-firmware/package.mk | 11 + packages/virtual/mediacenter/package.mk | 46 + packages/virtual/misc-packages/package.mk | 18 + packages/virtual/network/package.mk | 33 + packages/virtual/remote/package.mk | 15 + packages/virtual/toolchain/package.mk | 13 + packages/virtual/virtual/package.mk | 15 + packages/virtual/x11/package.mk | 38 + packages/wayland/libinput/package.mk | 16 + packages/wayland/libxkbcommon/package.mk | 31 + packages/wayland/mtdev/package.mk | 14 + packages/wayland/wayland-protocols/package.mk | 17 + packages/wayland/wayland/package.mk | 31 + packages/wayland/waylandpp/package.mk | 28 + packages/wayland/weston/config/weston.ini | 16 + packages/wayland/weston/package.mk | 55 + .../wayland/weston/profile.d/04-weston.conf | 4 + packages/wayland/weston/scripts/weston-config | 15 + .../wayland/weston/system.d/weston.service | 18 + packages/web/curl/package.mk | 80 + packages/web/libmicrohttpd/package.mk | 21 + packages/web/nghttp2/package.mk | 18 + packages/x11/app/setxkbmap/package.mk | 12 + .../app/setxkbmap/udev.d/98-xorg-xkb.rules | 8 + packages/x11/app/xkbcomp/package.mk | 14 + packages/x11/app/xrandr/package.mk | 16 + packages/x11/data/xkeyboard-config/package.mk | 34 + ...config-0001-dont-require-util-macros.patch | 39 + .../x11/driver/xf86-input-evdev/package.mk | 17 + .../x11/driver/xf86-input-libinput/package.mk | 20 + .../driver/xf86-input-synaptics/package.mk | 14 + .../x11/driver/xf86-video-amdgpu/package.mk | 24 + .../xf86-video-ati/config/xorg-radeon.conf | 8 + packages/x11/driver/xf86-video-ati/package.mk | 22 + .../xf86-video-ati-999.01-fix-gcc-10.patch | 33 + ...terminology-to-use-primary-secondary.patch | 365 + .../x11/driver/xf86-video-intel/package.mk | 40 + .../config/xorg-nvidia-legacy.conf | 33 + .../xf86-video-nvidia-legacy/package.mk | 71 + ...video-nvidia-legacy-0001-fix-5.6-rc1.patch | 487 + ...video-nvidia-legacy-0002-fix-5.7-rc1.patch | 37 + ...fix-5.7-rc1-reinstate-legacy-support.patch | 156 + ...f86-video-nvidia-legacy-0004-fix-5.8.patch | 57 + ...f86-video-nvidia-legacy-0005-fix-5.9.patch | 76 + ...86-video-nvidia-legacy-0006-fix-5.10.patch | 14 + ...86-video-nvidia-legacy-0007-fix-5.14.patch | 231 + .../driver/xf86-video-nvidia-legacy/udev.d | 1 + .../xf86-video-nvidia/config/xorg-nvidia.conf | 33 + .../x11/driver/xf86-video-nvidia/package.mk | 73 + .../patches/nvidia-fix-linux-5.14.patch | 63 + .../scripts/compare_nvidia.py | 102 + .../scripts/make_nvidia_udev.py | 65 + .../xf86-video-nvidia/udev.d/96-nvidia.rules | 364 + .../x11/driver/xf86-video-vmware/package.mk | 17 + packages/x11/font/encodings/package.mk | 16 + .../x11/font/font-bitstream-type1/package.mk | 19 + packages/x11/font/font-cursor-misc/package.mk | 18 + packages/x11/font/font-misc-misc/package.mk | 42 + packages/x11/font/font-util/package.mk | 20 + .../x11/font/font-xfree86-type1/package.mk | 18 + .../x11/font/liberation-fonts-ttf/package.mk | 23 + packages/x11/lib/libICE/package.mk | 17 + packages/x11/lib/libSM/package.mk | 18 + packages/x11/lib/libX11/package.mk | 32 + .../patches/libX11-disable_nls_tests.patch | 18 + packages/x11/lib/libXau/package.mk | 15 + packages/x11/lib/libXcomposite/package.mk | 15 + packages/x11/lib/libXdamage/package.mk | 15 + packages/x11/lib/libXext/package.mk | 14 + packages/x11/lib/libXfixes/package.mk | 15 + packages/x11/lib/libXfont2/package.mk | 22 + packages/x11/lib/libXi/package.mk | 24 + packages/x11/lib/libXinerama/package.mk | 14 + packages/x11/lib/libXmu/package.mk | 15 + packages/x11/lib/libXrandr/package.mk | 14 + packages/x11/lib/libXrender/package.mk | 15 + packages/x11/lib/libXt/package.mk | 24 + packages/x11/lib/libXtst/package.mk | 14 + packages/x11/lib/libXxf86vm/package.mk | 15 + packages/x11/lib/libfontenc/package.mk | 15 + packages/x11/lib/libpciaccess/package.mk | 20 + packages/x11/lib/libxcb/package.mk | 28 + packages/x11/lib/libxcvt/package.mk | 12 + packages/x11/lib/libxkbfile/package.mk | 14 + packages/x11/lib/libxshmfence/package.mk | 16 + packages/x11/lib/pixman/package.mk | 44 + packages/x11/lib/xtrans/package.mk | 19 + packages/x11/other/fluxbox/config/apps | 3 + packages/x11/other/fluxbox/config/init | 13 + packages/x11/other/fluxbox/config/keys | 19 + packages/x11/other/fluxbox/package.mk | 45 + ...-potential-SIGFPE-in-Menu-updateMenu.patch | 20 + .../fluxbox-02_hide-useless-errors.patch | 39 + .../patches/fluxbox-dont_build_fbrun.patch | 11 + .../fluxbox/system.d/windowmanager.service | 18 + packages/x11/other/fontconfig/package.mk | 32 + packages/x11/proto/xcb-proto/package.mk | 16 + packages/x11/proto/xorgproto/package.mk | 14 + packages/x11/util/util-macros/package.mk | 15 + .../x11/util/xorg-launch-helper/package.mk | 23 + .../xorg-launch-helper-automake-1.14.patch | 12 + ...per-dont-check-for-libsystemd-daemon.patch | 26 + .../xorg-launch-helper-increase-timeout.patch | 33 + .../xorg-launch-helper/scripts/xorg-launch | 27 + .../x11/xserver/xorg-server/debug.d/xorg.conf | 1 + packages/x11/xserver/xorg-server/package.mk | 109 + .../xorg-server-100.01-detect-radeon.patch | 22 + ...r-100.02-add-fedora-extra-modes-list.patch | 90 + .../xorg-server/profile.d/11-xorg-server.conf | 6 + .../xorg-server/scripts/xorg-configure | 98 + .../system.d/xorg-configure@.service | 9 + .../xserver/xorg-server/system.d/xorg.service | 16 + .../tmpfiles.d/z_90_xorg-server.conf | 4 + .../xserver/xorg-server/udev.d/97-xorg.rules | 19 + projects/Rockchip/bootloader/canupdate.sh | 9 + projects/Rockchip/bootloader/install | 60 + projects/Rockchip/bootloader/mkimage | 50 + projects/Rockchip/bootloader/release | 32 + projects/Rockchip/bootloader/update.sh | 110 + .../Rockchip/devices/RG351MP/device.config | 51 + projects/Rockchip/devices/RG351MP/device.init | 15 + .../devices/RG351MP/linux/linux.aarch64.conf | 4647 ++ projects/Rockchip/devices/RG351MP/options | 234 + .../devices/RG351P/bootloader/canupdate.sh | 9 + .../devices/RG351P/bootloader/install | 102 + .../devices/RG351P/bootloader/mkimage | 41 + .../devices/RG351P/bootloader/release | 56 + .../devices/RG351P/bootloader/update.sh | 109 + .../Rockchip/devices/RG351P/device.config | 51 + projects/Rockchip/devices/RG351P/device.init | 15 + .../devices/RG351P/linux/linux.aarch64.conf | 4647 ++ projects/Rockchip/devices/RG351P/options | 227 + .../RG351P/packages/python-evdev/package.mk | 44 + .../devices/RG351V/bootloader/canupdate.sh | 9 + .../devices/RG351V/bootloader/install | 102 + .../devices/RG351V/bootloader/mkimage | 41 + .../devices/RG351V/bootloader/release | 56 + .../devices/RG351V/bootloader/update.sh | 109 + .../Rockchip/devices/RG351V/device.config | 51 + projects/Rockchip/devices/RG351V/device.init | 15 + .../devices/RG351V/linux/linux.aarch64.conf | 4647 ++ projects/Rockchip/devices/RG351V/options | 227 + projects/Rockchip/devices/RG552/device.config | 49 + projects/Rockchip/devices/RG552/device.init | 10 + .../devices/RG552/linux/linux.aarch64.conf | 6246 ++ projects/Rockchip/devices/RG552/options | 230 + projects/Rockchip/options | 87 + projects/Rockchip/packages/linux/package.mk | 296 + .../linux/patches/RG351V/001-vdeadzone.patch | 32 + .../packages/linux/sysctl.d/network.conf | 1 + .../packages/linux/sysctl.d/qdisc.conf | 1 + .../linux/udev.d/30-disable-wakeup.rules | 8 + .../packages/linux/udev.d/40-modeswitch.rules | 11 + .../linux/udev.d/99-powertargets.rules | 2 + projects/Rockchip/packages/sleep/package.mk | 19 + .../packages/sleep/sources/sleep.conf | 25 + .../Rockchip/packages/sleep/sources/sleep.sh | 33 + .../Rockchip/packages/system-utils/package.mk | 25 + .../packages/system-utils/sources/battery | 57 + .../packages/system-utils/sources/fancontrol | 37 + .../system-utils/sources/fancontrol.conf | 19 + .../system-utils/sources/headphone_sense | 35 + .../system-utils/sources/system_utils | 86 + .../system-utils/sources/volume_sense | 139 + .../system-utils/system.d/battery.service | 13 + .../system-utils/system.d/fancontrol.service | 13 + .../system-utils/system.d/headphones.service | 12 + .../system-utils/system.d/volume.service | 15 + projects/Rockchip/packages/u-boot/package.mk | 64 + ...drm-0001-add-rochchip-10bits-formats.patch | 16 + scripts/autoreconf | 35 + scripts/build | 496 + scripts/build_distro | 58 + scripts/build_mt | 16 + scripts/ccache_stats | 9 + scripts/checkdeps | 186 + scripts/clean | 44 + scripts/create_addon | 188 + scripts/create_docker_package | 184 + scripts/extract | 77 + scripts/genbuildplan.py | 388 + scripts/get | 54 + scripts/get_archive | 61 + scripts/get_file | 6 + scripts/get_git | 145 + scripts/image | 466 + scripts/install | 152 + scripts/install_addon | 91 + scripts/mkimage | 333 + scripts/uboot_helper | 128 + scripts/unpack | 219 + scripts/update_packages | 65 + tools/dashboard | 46 + tools/docker/README.md | 26 + tools/docker/aarch64/README.md | 68 + tools/docker/aarch64/bionic/Dockerfile | 33 + tools/docker/ubuntu-focal/Dockerfile | 35 + tools/pkgcheck | 165 + tools/pkginfo | 27 + tools/sync | 16 + tools/viewplan | 29 + 2187 files changed, 269598 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 config/addon/dummy.xml create mode 100644 config/addon/xbmc.broken.xml create mode 100644 config/addon/xbmc.python.module.xml create mode 100644 config/addon/xbmc.python.script.xml create mode 100644 config/addon/xbmc.service.library.xml create mode 100644 config/addon/xbmc.service.pluginsource.xml create mode 100644 config/addon/xbmc.service.xml create mode 100644 config/arch.aarch64 create mode 100644 config/arch.arm create mode 100644 config/arch.x86_64 create mode 100644 config/blocklist create mode 100644 config/docker/changelog.txt create mode 100644 config/docker/package.mk create mode 100644 config/docker/source/bin/docker create mode 100644 config/docker/source/default.py create mode 100644 config/docker/source/resources/language/English/strings.po create mode 100644 config/docker/source/resources/settings.xml create mode 100644 config/docker/source/system.d/docker.service create mode 100644 config/functions create mode 100644 config/graphic create mode 100644 config/multithread create mode 100644 config/noobs/marketing/slides/A.png create mode 100644 config/noobs/marketing/slides/B.png create mode 100644 config/noobs/marketing/slides/C.png create mode 100644 config/noobs/marketing/slides/D.png create mode 100644 config/noobs/marketing/slides/E.png create mode 100644 config/noobs/marketing/slides/noobs.psd create mode 100644 config/noobs/marketing/slides_vga/A.png create mode 100644 config/noobs/marketing/slides_vga/B.png create mode 100644 config/noobs/marketing/slides_vga/C.png create mode 100644 config/noobs/marketing/slides_vga/D.png create mode 100644 config/noobs/marketing/slides_vga/E.png create mode 100644 config/noobs/marketing/slides_vga/noobs_vga.psd create mode 100644 config/noobs/os.json create mode 100755 config/noobs/partition_setup.sh create mode 100644 config/noobs/partitions.json create mode 100644 config/optimize create mode 100644 config/options create mode 100644 config/path create mode 100644 config/show_config create mode 100644 config/sources create mode 100644 distributions/JELOS/options create mode 100644 distributions/JELOS/splash/splash-1080.bmp create mode 100644 distributions/JELOS/splash/splash-1080.png create mode 100644 distributions/JELOS/splash/splash-1152.bmp create mode 100644 distributions/JELOS/splash/splash-1152.png create mode 100644 distributions/JELOS/splash/splash-1152l.bmp create mode 100644 distributions/JELOS/splash/splash-1152l.png create mode 100644 distributions/JELOS/splash/splash-480.bmp create mode 100644 distributions/JELOS/splash/splash-480.png create mode 100644 distributions/JELOS/splash/splash-480l.bmp create mode 100644 distributions/JELOS/splash/splash-480l.png create mode 100644 distributions/JELOS/splash/splash-640.bmp create mode 100644 distributions/JELOS/splash/splash-640.png create mode 100644 licenses/APSL.txt create mode 100644 licenses/ATI.txt create mode 100644 licenses/Apache2.txt create mode 100644 licenses/Artistic.txt create mode 100644 licenses/BSD.txt create mode 100644 licenses/BSD_2_Clause.txt create mode 100644 licenses/BSD_3_Clause.txt create mode 100644 licenses/BSD_4_Clause.txt create mode 100644 licenses/BSL.txt create mode 100644 licenses/CC_BY-NC-SA_4.0.txt create mode 100644 licenses/FDL.txt create mode 100644 licenses/FDL1_2.txt create mode 100644 licenses/FDL1_3.txt create mode 100644 licenses/GPL.txt create mode 100644 licenses/GPL2.txt create mode 100644 licenses/GPL3.txt create mode 100644 licenses/ISC.txt create mode 100644 licenses/Info-ZIP.txt create mode 100644 licenses/LGPL2.txt create mode 100644 licenses/LGPL2_1.txt create mode 100644 licenses/LGPL3.txt create mode 100644 licenses/LibPNG2.txt create mode 100644 licenses/MIT.txt create mode 100644 licenses/MIT_Modified.txt create mode 100644 licenses/MPL1_1.txt create mode 100644 licenses/NVIDIA.txt create mode 100644 licenses/OFL1_1.txt create mode 100644 licenses/Public_Domain.txt create mode 100644 licenses/Radeon_rlc.txt create mode 100644 metadata/RG351P/packages.cfg create mode 100644 metadata/RG351P/packages/blockattack.jpg create mode 100644 metadata/RG351P/packages/cavestory.jpg create mode 100644 metadata/RG351P/packages/cdogs-sdl.jpg create mode 100644 metadata/RG351P/packages/drastic.jpg create mode 100755 metadata/RG351P/packages/f2bgl.jpg create mode 100644 metadata/RG351P/packages/iortcw.jpg create mode 100644 metadata/RG351P/packages/openomf.jpg create mode 100644 metadata/RG351P/packages/retrorun.jpg create mode 100644 metadata/RG351P/packages/rpgmaker.jpg create mode 100644 metadata/RG351P/packages/smw.jpg create mode 100644 metadata/RG351P/packages/solarus.jpg create mode 100644 metadata/RG351P/packages/supertux.jpg create mode 100644 metadata/RG351P/packages/tyrian.jpg create mode 100644 metadata/RG351P/packages/uqm.jpg create mode 100644 metadata/RG351P/themes.cfg create mode 100644 metadata/RG351P/themes/351Noir.jpg create mode 100644 metadata/RG351P/themes/Airen.jpg create mode 100644 metadata/RG351P/themes/Alekfull.jpg create mode 100644 metadata/RG351P/themes/Alt-Book.jpg create mode 100755 metadata/RG351P/themes/Art-Book.jpg create mode 100644 metadata/RG351P/themes/CRAZYBOY.jpg create mode 100644 metadata/RG351P/themes/Carbon.jpg create mode 100644 metadata/RG351P/themes/Chicuelo.jpg create mode 100644 metadata/RG351P/themes/Comic-Book.jpg create mode 100644 metadata/RG351P/themes/CosmicRise.jpg create mode 100644 metadata/RG351P/themes/Crystal.jpg create mode 100644 metadata/RG351P/themes/EpicBlancheNoir.jpg create mode 100644 metadata/RG351P/themes/EpicCody.jpg create mode 100644 metadata/RG351P/themes/EpicLikeSzalik.jpg create mode 100644 metadata/RG351P/themes/Fundamental.jpg create mode 100644 metadata/RG351P/themes/GBZ.jpg create mode 100644 metadata/RG351P/themes/Handheld-Simple.jpg create mode 100644 metadata/RG351P/themes/Horizontal.jpg create mode 100644 metadata/RG351P/themes/Minimal.jpg create mode 100644 metadata/RG351P/themes/Pixel.jpg create mode 100644 metadata/RG351P/themes/Roleta.jpg create mode 100644 metadata/RG351P/themes/SpinMaster.jpg create mode 100644 metadata/RG351P/themes/SuperSweet.jpg create mode 100644 metadata/RG351P/themes/Supreme.jpg create mode 100644 metadata/RG351P/themes/Switch.jpg create mode 100644 metadata/RG351V/packages.cfg create mode 100644 metadata/RG351V/packages/blockattack.jpg create mode 100644 metadata/RG351V/packages/cavestory.jpg create mode 100644 metadata/RG351V/packages/cdogs-sdl.jpg create mode 100644 metadata/RG351V/packages/drastic.jpg create mode 100755 metadata/RG351V/packages/f2bgl.jpg create mode 100644 metadata/RG351V/packages/iortcw.jpg create mode 100644 metadata/RG351V/packages/openomf.jpg create mode 100644 metadata/RG351V/packages/retrorun.jpg create mode 100644 metadata/RG351V/packages/rpgmaker.jpg create mode 100644 metadata/RG351V/packages/smw.jpg create mode 100644 metadata/RG351V/packages/solarus.jpg create mode 100644 metadata/RG351V/packages/supertux.jpg create mode 100644 metadata/RG351V/packages/tyrian.jpg create mode 100644 metadata/RG351V/packages/uqm.jpg create mode 100644 metadata/RG351V/themes.cfg create mode 100644 metadata/RG351V/themes/Art-Book-4-3.jpg create mode 100644 metadata/RG351V/themes/Cody-Destroy.jpg create mode 100644 metadata/RG351V/themes/Epic-Cody.jpg create mode 100644 metadata/RG351V/themes/EpicBlancheNoir-V.jpg create mode 100644 metadata/RG351V/themes/GBZ.jpg create mode 100644 metadata/RG351V/themes/Handheld-Simple.jpg create mode 100644 metadata/RG351V/themes/Kiwi.jpg create mode 100644 metadata/RG351V/themes/Minimal.jpg create mode 100644 packages/audio/alsa-lib/config/modprobe.d/disable-spdif-for-hd-audio.conf create mode 100644 packages/audio/alsa-lib/modprobe.d/alsa-base.conf create mode 100644 packages/audio/alsa-lib/modprobe.d/intel-audio.conf create mode 100644 packages/audio/alsa-lib/package.mk create mode 100644 packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch create mode 100644 packages/audio/alsa-ucm-conf/package.mk create mode 100644 packages/audio/alsa-utils/package.mk create mode 100755 packages/audio/alsa-utils/scripts/soundconfig create mode 100644 packages/audio/alsa-utils/udev.d/90-alsa-restore.rules create mode 100644 packages/audio/espeak/package.mk create mode 100644 packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch create mode 100644 packages/audio/espeak/patches/espeak-1.47-wav-close.patch create mode 100644 packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch create mode 100644 packages/audio/flac/package.mk create mode 100644 packages/audio/fluidsynth/package.mk create mode 100644 packages/audio/lame/package.mk create mode 100644 packages/audio/lame/patches/lame-3.99.5-am_path_gtk.patch create mode 100644 packages/audio/lame/patches/lame-3.99.5-automake.patch create mode 100644 packages/audio/libcdio/package.mk create mode 100644 packages/audio/libmodplug/package.mk create mode 100644 packages/audio/libogg/package.mk create mode 100644 packages/audio/libopenmpt/package.mk create mode 100644 packages/audio/libsamplerate/package.mk create mode 100644 packages/audio/libsndfile/package.mk create mode 100644 packages/audio/libvorbis/package.mk create mode 100644 packages/audio/openal-soft/package.mk create mode 100644 packages/audio/pulseaudio/config/pulse-daemon.conf.d/README create mode 100644 packages/audio/pulseaudio/config/pulseaudio-system.conf create mode 100644 packages/audio/pulseaudio/config/system.pa create mode 100644 packages/audio/pulseaudio/package.mk create mode 100644 packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch create mode 100644 packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch create mode 100644 packages/audio/pulseaudio/profile.d/99-pulseaudio.conf create mode 100644 packages/audio/pulseaudio/system.d/pulseaudio.service create mode 100644 packages/audio/rpi-cirrus-config/config/rpi-cirrus-config.sh.sample create mode 100644 packages/audio/rpi-cirrus-config/modprobe.d/rpi-cirrus.conf create mode 100644 packages/audio/rpi-cirrus-config/package.mk create mode 100755 packages/audio/rpi-cirrus-config/scripts/rpi-cirrus-config create mode 100644 packages/audio/rpi-cirrus-config/udev.d/90-alsa-restore.rules create mode 100644 packages/audio/sbc/package.mk create mode 100644 packages/audio/sidplay-libs/package.mk create mode 100644 packages/audio/sidplay-libs/patches/sidplay-libs-01-m4-tests.patch create mode 100644 packages/audio/sidplay-libs/patches/sidplay-libs-02-inherited.patch create mode 100644 packages/audio/sidplay-libs/patches/sidplay-libs-03-operator.patch create mode 100644 packages/audio/sidplay-libs/patches/sidplay-libs-04-includes.patch create mode 100644 packages/audio/soxr/package.mk create mode 100644 packages/audio/soxr/patches/0001-Add-Libs.private-for-static-linking.patch create mode 100644 packages/audio/speex/package.mk create mode 100644 packages/audio/speexdsp/package.mk create mode 100644 packages/audio/taglib/package.mk create mode 100644 packages/audio/taglib/patches/taglib-01-efficient_lookup_for_an_ID3v2_tag_in_MPEG_files_with_garbage.patch create mode 100644 packages/compat/lib32/package.mk create mode 100644 packages/compress/bzip2/package.mk create mode 100644 packages/compress/bzip2/patches/bzip2-1.0.8-cflags.patch create mode 100644 packages/compress/cpio/package.mk create mode 100644 packages/compress/cpio/patches/0001-Minor-fix.patch create mode 100644 packages/compress/gzip/package.mk create mode 100644 packages/compress/libarchive/package.mk create mode 100644 packages/compress/libzip/package.mk create mode 100644 packages/compress/lz4/package.mk create mode 100644 packages/compress/lzo/package.mk create mode 100644 packages/compress/minizip/package.mk create mode 100644 packages/compress/p7zip/package.mk create mode 100644 packages/compress/p7zip/patches/0004-Fix-build-with-gcc-10.patch create mode 100644 packages/compress/pigz/package.mk create mode 100644 packages/compress/unzip/package.mk create mode 100644 packages/compress/xz/package.mk create mode 100644 packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch create mode 100644 packages/compress/zip/package.mk create mode 100644 packages/compress/zlib/package.mk create mode 100644 packages/compress/zstd/package.mk create mode 100644 packages/databases/mariadb-connector-c/package.mk create mode 100644 packages/databases/mysql/package.mk create mode 100644 packages/databases/mysql/patches/mysql-0002-revert-floating-point-optimizations.patch create mode 100644 packages/databases/mysql/patches/mysql-0003-compile-comp_err-even-when-crosscompiling.patch create mode 100644 packages/databases/mysql/patches/mysql-0004-compile-comp_sql-even-when-crosscompiling.patch create mode 100644 packages/databases/mysql/patches/mysql-0005-pchar-fix-in-client-authtentification.patch create mode 100644 packages/databases/sqlite/package.mk create mode 100644 packages/databases/sqlite/patches/sqlite-01_map_populate.patch create mode 100644 packages/debug/apitrace/package.mk create mode 100644 packages/debug/apitrace/patches/001-no-x11.patch create mode 100644 packages/debug/edid-decode/package.mk create mode 100644 packages/debug/gdb/package.mk create mode 100644 packages/debug/gdb/patches/gdb-001-notex.patch create mode 100644 packages/debug/libunwind/package.mk create mode 100644 packages/debug/libva-utils/package.mk create mode 100644 packages/debug/memtester/package.mk create mode 100644 packages/debug/memtester/patches/memtester-001-cross-compile.patch create mode 100644 packages/debug/valgrind/package.mk create mode 100644 packages/debug/valgrind/patches/valgrind-0001-enable-armv8.patch create mode 100644 packages/debug/valgrind/patches/valgrind-0002-no-mpi1.patch create mode 100644 packages/debug/vdpauinfo/package.mk create mode 100644 packages/devel/android-headers/package.mk create mode 100644 packages/devel/apache-ant/package.mk create mode 100644 packages/devel/arm-mem/package.mk create mode 100644 packages/devel/attr/package.mk create mode 100644 packages/devel/autoconf-archive/package.mk create mode 100644 packages/devel/autoconf/package.mk create mode 100644 packages/devel/autoconf/patches/autoconf-0100-backport-runstatedir.patch create mode 100644 packages/devel/autoconf/patches/autoconf-0200-performance.patch create mode 100644 packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch create mode 100644 packages/devel/automake/package.mk create mode 100644 packages/devel/automake/patches/automake-01-fix-help2man.patch create mode 100644 packages/devel/binutils/package.mk create mode 100644 packages/devel/binutils/patches/binutils-01-warn-for-uses-of-system-directories-when-link.patch create mode 100644 packages/devel/binutils/patches/nodocs.patch create mode 100644 packages/devel/bison/package.mk create mode 100644 packages/devel/boost/package.mk create mode 100644 packages/devel/ccache/package.mk create mode 100644 packages/devel/cmake/package.mk create mode 100644 packages/devel/cmake/patches/cmake-001-disable-free-comp-methods.patch create mode 100644 packages/devel/configtools/package.mk create mode 100644 packages/devel/crossguid/package.mk create mode 100644 packages/devel/dbus-glib/package.mk create mode 100644 packages/devel/dbus-glib/patches/dbus-glib-01-dont-build-tools-examples.patch create mode 100644 packages/devel/elfutils/package.mk create mode 100644 packages/devel/elfutils/patches/elfutils-001-make-executables-optional.patch create mode 100644 packages/devel/fakeroot/package.mk create mode 100644 packages/devel/fakeroot/patches/fakeroot-001-disable-docs-tests.patch create mode 100644 packages/devel/flatbuffers/package.mk create mode 100644 packages/devel/flex/package.mk create mode 100644 packages/devel/flex/patches/c5a26b17a2b091c560f6c4e6703e55f496bf74fa.patch create mode 100644 packages/devel/flex/patches/flex-002-nocrap.patch create mode 100644 packages/devel/fribidi/package.mk create mode 100644 packages/devel/fribidi/scripts/fribidi-config create mode 100644 packages/devel/gettext/package.mk create mode 100644 packages/devel/gettext/patches/gettext-0.18.2-non_interactive.patch create mode 100644 packages/devel/gettext/patches/gettext-dont_build_docs_and_examples.patch create mode 100644 packages/devel/glib/package.mk create mode 100644 packages/devel/glibc/config/gai.conf create mode 100644 packages/devel/glibc/config/host.conf create mode 100644 packages/devel/glibc/config/nsswitch-init.conf create mode 100644 packages/devel/glibc/config/nsswitch-target.conf create mode 100644 packages/devel/glibc/package.mk create mode 100644 packages/devel/glibc/patches/glibc-fix-dns-with-broken-routers.patch create mode 100644 packages/devel/gmp/package.mk create mode 100644 packages/devel/gnulib/package.mk create mode 100644 packages/devel/heimdal/package.mk create mode 100644 packages/devel/heimdal/patches/0001-upstream-check-libtinfo-for-tgetent.patch create mode 100644 packages/devel/heimdal/patches/0002-upstream-fix-configure-err-msg.patch create mode 100644 packages/devel/heimdal/patches/22352b90e78e2d162b98b5ef6c84672c397be40a.patch create mode 100644 packages/devel/heimdal/patches/c4cff6859d183a40fb35a76e2bc1ce084b3a6d67.patch create mode 100644 packages/devel/heimdal/patches/cc6a3f337bac0411d0bb1c924fd857603a258d2f.patch create mode 100644 packages/devel/heimdal/patches/yyerror-match-posix-standard.patch create mode 100644 packages/devel/intltool/package.mk create mode 100644 packages/devel/intltool/patches/intltool-0001-fix-regex-expressions.patch create mode 100644 packages/devel/libaio/package.mk create mode 100644 packages/devel/libcap/package.mk create mode 100644 packages/devel/libcec-4.0.5/package.mk create mode 100644 packages/devel/libcec-4.0.5/patches/cec-framework/libcec-0001-PR380.patch create mode 100644 packages/devel/libcec-4.0.7/package.mk create mode 100644 packages/devel/libcec-4.0.7/patches/cec-framework/libcec-0001-PR380.patch create mode 100644 packages/devel/libcec/package.mk create mode 100644 packages/devel/libdaemon/package.mk create mode 100644 packages/devel/libffi/package.mk create mode 100644 packages/devel/libffi/patches/libffi-Fix-installation-location-of-libffi.patch create mode 100644 packages/devel/libffi/patches/libffi-fix-pkgconf.patch create mode 100644 packages/devel/libfmt/package.mk create mode 100644 packages/devel/libfstrcmp/package.mk create mode 100644 packages/devel/libftdi1/package.mk create mode 100644 packages/devel/libirman/package.mk create mode 100644 packages/devel/libirman/patches/libirman-0001-fix-poll-include.patch create mode 100644 packages/devel/libplist/package.mk create mode 100644 packages/devel/libpthread-stubs/package.mk create mode 100644 packages/devel/librga/package.mk create mode 100644 packages/devel/libsodium/package.mk create mode 100644 packages/devel/libtool/package.mk create mode 100644 packages/devel/libtool/patches/libtool-01_dont_relink_against_host.patch create mode 100644 packages/devel/libtool/patches/libtool-02-use_ld.patch create mode 100644 packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch create mode 100644 packages/devel/m4/package.mk create mode 100644 packages/devel/make/package.mk create mode 100644 packages/devel/make/patches/make-01-disable-inheritance-of-fds.patch create mode 100644 packages/devel/mpc/package.mk create mode 100644 packages/devel/mpfr/package.mk create mode 100644 packages/devel/ncurses/package.mk create mode 100644 packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch create mode 100644 packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch create mode 100644 packages/devel/parallel/package.mk create mode 100644 packages/devel/pcre/package.mk create mode 100644 packages/devel/pcre2/package.mk create mode 100644 packages/devel/pkg-config/package.mk create mode 100644 packages/devel/pkg-config/patches/0001-Add-support-for-multiple-sysroots.patch create mode 100644 packages/devel/popt/package.mk create mode 100644 packages/devel/rapidjson/package.mk create mode 100644 packages/devel/rapidjson/patches/rapidjson-0001-remove_custom_cxx_flags.patch create mode 100644 packages/devel/readline/package.mk create mode 100644 packages/devel/slang/package.mk create mode 100644 packages/devel/spdlog/package.mk create mode 100644 packages/devel/swig/package.mk create mode 100644 packages/devel/yajl/package.mk create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00023.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00044.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPUG80325.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00019.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00842.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01184.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01401.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01473.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98640.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98653.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98668.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98737.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00033.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00034.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00035.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00125.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00483.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00625.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00626.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00703.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00968.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00981.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00982.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01214.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01402.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01406.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS00125.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10014.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10189.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10197.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10213.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10236.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10328.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10345.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10390.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10507.ini create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache create mode 100644 packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache create mode 100644 packages/games/emulators/PPSSPPSDL/package.mk create mode 100644 packages/games/emulators/PPSSPPSDL/patches/000-disable-mouse.patch create mode 100644 packages/games/emulators/PPSSPPSDL/patches/006-fix-window-size.patch create mode 100644 packages/games/emulators/PPSSPPSDL/patches/008-exit-to-jelOS.patch create mode 100644 packages/games/emulators/PPSSPPSDL/patches/ppsspp-patch-005-build-flag.patch create mode 100755 packages/games/emulators/PPSSPPSDL/ppsspp.sh create mode 100644 packages/games/emulators/PPSSPPSDL/sources/RG351/controls.ini create mode 100644 packages/games/emulators/PPSSPPSDL/sources/RG351/ppsspp.ini create mode 100644 packages/games/emulators/PPSSPPSDL/sources/RG552/controls.ini create mode 100755 packages/games/emulators/PPSSPPSDL/sources/RG552/ppsspp.ini create mode 100644 packages/games/emulators/advancemame/bin/advmame.sh create mode 100644 packages/games/emulators/advancemame/config/RG351MP/advmame.rc create mode 100644 packages/games/emulators/advancemame/config/RG351P/advmame.rc create mode 100644 packages/games/emulators/advancemame/package.mk create mode 100644 packages/games/emulators/advancemame/patches/advancemame-002-fix-vfb.patch create mode 100644 packages/games/emulators/advancemame/patches/advancemame-fix-slang.patch create mode 100644 packages/games/emulators/advancemame/patches/advancemame-return-0-on-terminate.patch create mode 100644 packages/games/emulators/amiberry/config/conf/AmigaA1200-default.uae create mode 100644 packages/games/emulators/amiberry/config/conf/AmigaA500-default.uae create mode 100644 packages/games/emulators/amiberry/config/conf/adfdir.conf create mode 100644 packages/games/emulators/amiberry/package.mk create mode 100755 packages/games/emulators/amiberry/scripts/amiberry.start create mode 100644 packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2-MT32.conf create mode 100644 packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2.conf create mode 100644 packages/games/emulators/dosbox-sdl2/config/dosbox-SVN.conf create mode 100644 packages/games/emulators/dosbox-sdl2/config/games/_Scan DOSBox Games.sh create mode 100644 packages/games/emulators/dosbox-sdl2/package.mk create mode 100644 packages/games/emulators/dosbox-sdl2/patches/dosbox-sdl2.995.01-add-mt32emu-MIDI-device.patch create mode 100755 packages/games/emulators/dosbox-sdl2/scripts/dosbox.start create mode 100644 packages/games/emulators/dosbox-x/config/dosbox-SDL2-MT32.conf create mode 100644 packages/games/emulators/dosbox-x/config/dosbox-SDL2.conf create mode 100644 packages/games/emulators/dosbox-x/config/dosbox-SVN.conf create mode 100644 packages/games/emulators/dosbox-x/config/dosbox.conf create mode 100644 packages/games/emulators/dosbox-x/package.mk create mode 100644 packages/games/emulators/dosbox-x/patches/000-arm_configure.patch create mode 100644 packages/games/emulators/dosbox-x/patches/001-sdl-config.patch create mode 100644 packages/games/emulators/dosbox-x/patches/003-dosboxconf.patch create mode 100755 packages/games/emulators/dosbox-x/scripts/dosbox-x.start create mode 100644 packages/games/emulators/ecwolf/config/ecwolf.cfg create mode 100644 packages/games/emulators/ecwolf/ecwolf.sh create mode 100644 packages/games/emulators/ecwolf/package.mk create mode 100644 packages/games/emulators/ecwolf/patches/ecwolf-001-add-video-modes.patch create mode 100644 packages/games/emulators/ecwolf/patches/ecwolf-002-add-exit-menu.patch create mode 100644 packages/games/emulators/gzdoom/config/RG351MP/gzdoom.ini create mode 100644 packages/games/emulators/gzdoom/config/RG351P/gzdoom.ini create mode 100644 packages/games/emulators/gzdoom/gzdoom.sh create mode 100644 packages/games/emulators/gzdoom/package.mk create mode 100644 packages/games/emulators/gzdoom/patches/RG351P/0001_key_swap.patch create mode 100644 packages/games/emulators/gzdoom/zmusic/package.mk create mode 100644 packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg create mode 100644 packages/games/emulators/hatarisa/package.mk create mode 100644 packages/games/emulators/hatarisa/portaudio/package.mk create mode 100755 packages/games/emulators/hatarisa/scripts/hatari.start create mode 100644 packages/games/emulators/hypseus/config/hypinput.ini create mode 100644 packages/games/emulators/hypseus/package.mk create mode 100644 packages/games/emulators/hypseus/patches/hypseus-003-controller.patch create mode 100644 packages/games/emulators/hypseus/patches/hypseus-004-install_fix.patch create mode 100644 packages/games/emulators/hypseus/patches/hypseus-005-external-mpeg2.patch create mode 100644 packages/games/emulators/lzdoom/config/RG351MP/lzdoom.ini create mode 100644 packages/games/emulators/lzdoom/config/RG351P/lzdoom.ini create mode 100644 packages/games/emulators/lzdoom/config/lzdoom.ini create mode 100644 packages/games/emulators/lzdoom/lzdoom.sh create mode 100644 packages/games/emulators/lzdoom/package.mk create mode 100644 packages/games/emulators/lzdoom/patches/RG351MP/MP_key_swap.patch create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-audio-sdl/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351MP.cfg create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351P.cfg create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351V.cfg create mode 100755 packages/games/emulators/mupen64plussa/mupen64plussa-core/m64p.sh create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-core/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/config/InputAutoCfg.ini create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-rsp-hle/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-ui-console/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-video-glide64mk2/package.mk create mode 100644 packages/games/emulators/mupen64plussa/mupen64plussa-video-rice/package.mk create mode 100644 packages/games/emulators/mupen64plussa/package.mk create mode 100755 packages/games/emulators/openbor/config/Saves/default.cfg create mode 100644 packages/games/emulators/openbor/config/master.cfg create mode 100644 packages/games/emulators/openbor/package.mk create mode 100644 packages/games/emulators/openbor/patches/openbor-02-addplatform.patch create mode 100755 packages/games/emulators/openbor/scripts/openbor.sh create mode 100644 packages/games/emulators/raze/config/RG351MP/raze.ini create mode 100644 packages/games/emulators/raze/config/RG351P/raze.ini create mode 100644 packages/games/emulators/raze/libvpx/package.mk create mode 100644 packages/games/emulators/raze/package.mk create mode 100644 packages/games/emulators/raze/patches/RG351P/0001_key_swap.patch create mode 100644 packages/games/emulators/raze/raze.sh create mode 100644 packages/games/emulators/retroarch/modprobe.d/usbhid.conf create mode 100644 packages/games/emulators/retroarch/package.mk create mode 100644 packages/games/emulators/retroarch/patches/0001-Increase-glui-size.patch create mode 100644 packages/games/emulators/retroarch/patches/0001-Increase-ozone-size.patch create mode 100644 packages/games/emulators/retroarch/patches/0001-Increase-ozone-widget_size.patch create mode 100644 packages/games/emulators/retroarch/patches/0001-video_thread_wrapper-implement-RETRO_ENVIRONMENT_GET.patch create mode 100644 packages/games/emulators/retroarch/patches/008-drm-resolution.patch create mode 100644 packages/games/emulators/retroarch/patches/010-disable-drm-resolution-adaptation.patch create mode 100644 packages/games/emulators/retroarch/patches/RG351V/0001-remove_rotation.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-01-xkb-fix.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-02_disable_search.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-04-enablecontent.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-05-disable_updater_entries.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-10-Exit_menu.patch create mode 100644 packages/games/emulators/retroarch/patches/retroarch-12-input_sort_devices.patch create mode 100755 packages/games/emulators/retroarch/scripts/retroarch-config create mode 100644 packages/games/emulators/retroarch/sources/retroarch-core-options.cfg create mode 100644 packages/games/emulators/retroarch/sources/retroarch.cfg create mode 100644 packages/games/emulators/retroarch/sources/retroarch32bit-append.cfg create mode 100644 packages/games/emulators/retroarch/sources/retroarch64bit-append.cfg create mode 100644 packages/games/emulators/retroarch/system.d/retroarch.service create mode 100644 packages/games/emulators/retroarch/system.d/tmp-assets.mount create mode 100644 packages/games/emulators/retroarch/system.d/tmp-cores.mount create mode 100644 packages/games/emulators/retroarch/system.d/tmp-database.mount create mode 100644 packages/games/emulators/retroarch/system.d/tmp-joypads.mount create mode 100644 packages/games/emulators/retroarch/system.d/tmp-overlays.mount create mode 100644 packages/games/emulators/retroarch/system.d/tmp-shaders.mount create mode 100644 packages/games/emulators/retroarch/tmpfiles.d/retroarch-userdirs.conf create mode 100644 packages/games/emulators/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-ION-iCade-bluetooth.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-bluetooth-power-on.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-evdev.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-gen-game-s3-controller.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-juyao-dual-arcade.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-nintendo-wii-remote.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-ninteno-wii-remote.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-nv-shield-controller.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-ouya-controller.rules create mode 100644 packages/games/emulators/retroarch/udev.d/99-terios-t3.rules create mode 100644 packages/games/emulators/scummvmsa/bin/scummvm.start create mode 100644 packages/games/emulators/scummvmsa/config/games/_Scan ScummVM Games.sh create mode 100644 packages/games/emulators/scummvmsa/config/scummvm.ini create mode 100644 packages/games/emulators/scummvmsa/package.mk create mode 100644 packages/games/emulators/scummvmsa/scummremastered.zip create mode 100644 packages/games/emulators/solarus/config/RG351MP/pads.ini create mode 100644 packages/games/emulators/solarus/config/RG351P/pads.ini create mode 100644 packages/games/emulators/solarus/package.mk create mode 100644 packages/games/emulators/solarus/patches/solarus-002-pad.patch create mode 100644 packages/games/emulators/solarus/patches/solarus-003-dirs.patch create mode 100644 packages/games/emulators/solarus/physfs/package.mk create mode 100644 packages/games/emulators/solarus/physfs/patches/0001-build_fix.patch create mode 100644 packages/games/emulators/solarus/scripts/solarus.sh create mode 100644 packages/games/libretro/2048/package.mk create mode 100644 packages/games/libretro/81/package.mk create mode 100644 packages/games/libretro/TIC-80/package.mk create mode 100644 packages/games/libretro/atari800/package.mk create mode 100644 packages/games/libretro/atari800/patches/atari800-01-add-emuelec-platform.patch create mode 100644 packages/games/libretro/beetle-gba/package.mk create mode 100644 packages/games/libretro/beetle-lynx/package.mk create mode 100644 packages/games/libretro/beetle-ngp/package.mk create mode 100644 packages/games/libretro/beetle-pce/package.mk create mode 100644 packages/games/libretro/beetle-pcfx/package.mk create mode 100644 packages/games/libretro/beetle-supafaust/package.mk create mode 100644 packages/games/libretro/beetle-supergrafx/package.mk create mode 100644 packages/games/libretro/beetle-vb/package.mk create mode 100644 packages/games/libretro/beetle-wswan/package.mk create mode 100644 packages/games/libretro/bluemsx/package.mk create mode 100644 packages/games/libretro/cannonball/package.mk create mode 100644 packages/games/libretro/cap32/package.mk create mode 100644 packages/games/libretro/common-shaders/package.mk create mode 100644 packages/games/libretro/core-info/package.mk create mode 100644 packages/games/libretro/crocods/package.mk create mode 100644 packages/games/libretro/crocods/patches/001-keyboard.patch create mode 100644 packages/games/libretro/daphne/package.mk create mode 100644 packages/games/libretro/dinothawr/package.mk create mode 100644 packages/games/libretro/dosbox-pure/package.mk create mode 100644 packages/games/libretro/dosbox-pure/patches/dosbox-pure-add-emuelec-platform.patch create mode 100644 packages/games/libretro/dosbox-svn/package.mk create mode 100644 packages/games/libretro/dosbox-svn/patches/dosbox-svn-use-sdl-config.patch create mode 100644 packages/games/libretro/dosbox/package.mk create mode 100644 packages/games/libretro/duckstation/package.mk create mode 100644 packages/games/libretro/easyrpg/easyrpg.sh create mode 100644 packages/games/libretro/easyrpg/liblcf/package.mk create mode 100644 packages/games/libretro/easyrpg/liblcf/patches/liblcf-02-add-icu-compile-defs.patch create mode 100644 packages/games/libretro/easyrpg/libspeexdsp/package.mk create mode 100644 packages/games/libretro/easyrpg/libxmp-lite/package.mk create mode 100644 packages/games/libretro/easyrpg/libxmp-lite/sources/CMakeLists.txt create mode 100644 packages/games/libretro/easyrpg/package.mk create mode 100644 packages/games/libretro/easyrpg/wildmidi/package.mk create mode 100644 packages/games/libretro/easyrpg/wildmidi/sources/CMakeLists.txt create mode 100644 packages/games/libretro/fbalpha2012/package.mk create mode 100644 packages/games/libretro/fbalpha2019/fbalpha2019_libretro.info create mode 100644 packages/games/libretro/fbalpha2019/package.mk create mode 100644 packages/games/libretro/fbneo/package.mk create mode 100644 packages/games/libretro/fceumm/package.mk create mode 100644 packages/games/libretro/flycast/package.mk create mode 100644 packages/games/libretro/fmsx/package.mk create mode 100644 packages/games/libretro/freechaf/package.mk create mode 100644 packages/games/libretro/freeintv/package.mk create mode 100644 packages/games/libretro/freej2me/freej2me.sh create mode 100644 packages/games/libretro/freej2me/package.mk create mode 100644 packages/games/libretro/fuse-libretro/package.mk create mode 100644 packages/games/libretro/gambatte/package.mk create mode 120000 packages/games/libretro/gambatte/patches/RG351MP create mode 100644 packages/games/libretro/gambatte/patches/RG351P/disable_palette_switching.patch create mode 100644 packages/games/libretro/gambatte/patches/RG351P/rumble.patch create mode 120000 packages/games/libretro/gambatte/patches/RG351V create mode 100644 packages/games/libretro/gearboy/package.mk create mode 100644 packages/games/libretro/gearcoleco/package.mk create mode 100644 packages/games/libretro/gearsystem/package.mk create mode 100644 packages/games/libretro/genesis-plus-gx-wide/package.mk create mode 100644 packages/games/libretro/genesis-plus-gx/package.mk create mode 100644 packages/games/libretro/glsl-shaders/package.mk create mode 100644 packages/games/libretro/glsl-shaders/removeshaders.sh create mode 100644 packages/games/libretro/glsl-shaders/shaders/_redraw.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/crt-nes-mini.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/crt-pi-vertical.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/crt-pi.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/fakelottes.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/scanline.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-nes-mini.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi-vertical.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/fakelottes.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/scanlines.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/shaders/zfast_crt.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/crt/zfast-crt.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source_nearest.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/aa-shader-4.o.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/advanced-aa.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fx-aa.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fxaa-edge-detect.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/reverse-aa.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v2.2.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.5a.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.7c.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.8d.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v2.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v3.8d.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v1.1.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.5-plus-crt.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.9c.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v4.0.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v1.1.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.1.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.2.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.3.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5-plus-crt.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5a.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.6c.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.7d.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.8d.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v4.0-noblend.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-dilation.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-v3.8c-gamma.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-scanlines.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-simple.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/shaders/stock.glsl create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-2x-prescale.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-scanlines.glslp create mode 100644 packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-simple.glslp create mode 100644 packages/games/libretro/gme/package.mk create mode 100644 packages/games/libretro/gpsp/package.mk create mode 100644 packages/games/libretro/gw-libretro/package.mk create mode 100644 packages/games/libretro/handy/package.mk create mode 100644 packages/games/libretro/handy/patches/aarch64/handy-01-add-emuelec.patch create mode 100644 packages/games/libretro/hatari/config/conf/Atari-ST-default.cfg create mode 100644 packages/games/libretro/hatari/config/hatari.nvram create mode 100644 packages/games/libretro/hatari/package.mk create mode 100644 packages/games/libretro/hatari/patches/findcapsimage.patch create mode 100644 packages/games/libretro/libretro-database/package.mk create mode 100644 packages/games/libretro/mame/package.mk create mode 100644 packages/games/libretro/mame/patches/mame-crosscompile.patch create mode 100644 packages/games/libretro/mame/patches/mame-remove-bgfx.patch create mode 100644 packages/games/libretro/mame2000/package.mk create mode 100644 packages/games/libretro/mame2003-midway/package.mk create mode 100644 packages/games/libretro/mame2003-plus/package.mk create mode 100644 packages/games/libretro/mame2003-xtreme/package.mk create mode 100644 packages/games/libretro/mame2003-xtreme/sources/km_mame2003_xtreme_libretro.info create mode 100644 packages/games/libretro/mame2003/package.mk create mode 100644 packages/games/libretro/mame2010/package.mk create mode 100644 packages/games/libretro/mame2015/package.mk create mode 100644 packages/games/libretro/mame2016/package.mk create mode 100644 packages/games/libretro/mame2016/patches/mame2016-libretro-crosscompile.patch create mode 100644 packages/games/libretro/meowpc98/package.mk create mode 100644 packages/games/libretro/mgba/package.mk create mode 120000 packages/games/libretro/mgba/patches/RG351MP create mode 100644 packages/games/libretro/mgba/patches/RG351P/libretro-mgba-0001-rumble.patch create mode 120000 packages/games/libretro/mgba/patches/RG351V create mode 100644 packages/games/libretro/mrboom/package.mk create mode 100755 packages/games/libretro/mupen64plus-nx/package.mk create mode 100644 packages/games/libretro/mupen64plus-nx/patches/mupen64plus-nx-01-add-amlogic64.patch create mode 100644 packages/games/libretro/mupen64plus/package.mk create mode 120000 packages/games/libretro/mupen64plus/patches/RG351MP create mode 100644 packages/games/libretro/mupen64plus/patches/RG351P/mupen64plus-fix-rumble.patch create mode 120000 packages/games/libretro/mupen64plus/patches/RG351V create mode 100644 packages/games/libretro/mupen64plus/patches/mupen64plus-fixdouble.patch create mode 100644 packages/games/libretro/mupen64plus/patches/mupen64plus-inc-string.patch create mode 100644 packages/games/libretro/mupen64plus/patches/mupen64plus-sx05re-neonfix.patch create mode 100644 packages/games/libretro/neocd_libretro/package.mk create mode 100644 packages/games/libretro/nestopia/package.mk create mode 100644 packages/games/libretro/np2kai/package.mk create mode 100644 packages/games/libretro/nxengine/package.mk create mode 100644 packages/games/libretro/o2em/package.mk create mode 100644 packages/games/libretro/opera/package.mk create mode 100644 packages/games/libretro/parallel-n64/package.mk create mode 120000 packages/games/libretro/parallel-n64/patches/RG351MP create mode 100644 packages/games/libretro/parallel-n64/patches/RG351P/parallel-n64-add_rumble.patch create mode 120000 packages/games/libretro/parallel-n64/patches/RG351V create mode 100644 packages/games/libretro/parallel-n64/patches/aarch64/01-gcc-10.patch create mode 100644 packages/games/libretro/parallel-n64/patches/aarch64/parallel-n64-add_platform.patch create mode 100644 packages/games/libretro/parallel-n64/patches/arm/01-gcc-10.patch create mode 100644 packages/games/libretro/parallel-n64/patches/arm/parallel-n64-add_platform.patch create mode 100644 packages/games/libretro/parallel-n64_gln64/package.mk create mode 120000 packages/games/libretro/parallel-n64_gln64/patches/RG351MP create mode 100644 packages/games/libretro/parallel-n64_gln64/patches/RG351P/parallel-n64-add_rumble.patch create mode 120000 packages/games/libretro/parallel-n64_gln64/patches/RG351V create mode 100644 packages/games/libretro/parallel-n64_gln64/patches/aarch64/01-gcc-10.patch create mode 100644 packages/games/libretro/parallel-n64_gln64/patches/aarch64/parallel-n64-add_platform.patch create mode 100644 packages/games/libretro/parallel-n64_gln64/patches/arm/01-gcc-10.patch create mode 100644 packages/games/libretro/parallel-n64_gln64/patches/arm/parallel-n64-add_platform.patch create mode 100644 packages/games/libretro/pcsx_rearmed/package.mk create mode 120000 packages/games/libretro/pcsx_rearmed/patches/RG351MP create mode 100644 packages/games/libretro/pcsx_rearmed/patches/RG351P/libretro-pcsx-rearmed-0002-rumble.patch create mode 120000 packages/games/libretro/pcsx_rearmed/patches/RG351V create mode 100644 packages/games/libretro/picodrive/package.mk create mode 100644 packages/games/libretro/pokemini/package.mk create mode 120000 packages/games/libretro/pokemini/patches/RG351MP create mode 100644 packages/games/libretro/pokemini/patches/RG351P/rumble.patch create mode 120000 packages/games/libretro/pokemini/patches/RG351V create mode 100644 packages/games/libretro/potator/package.mk create mode 100644 packages/games/libretro/ppsspp/package.mk create mode 100644 packages/games/libretro/ppsspp/patches/ppsspp-x86_64-fix.patch create mode 100644 packages/games/libretro/prboom/package.mk create mode 100644 packages/games/libretro/prboom/patches/01_351p_resolution.patch create mode 100644 packages/games/libretro/prosystem/package.mk create mode 100644 packages/games/libretro/puae/package.mk create mode 100644 packages/games/libretro/px68k/package.mk create mode 120000 packages/games/libretro/px68k/patches/RG351MP create mode 100644 packages/games/libretro/px68k/patches/RG351P/rumble.patch create mode 120000 packages/games/libretro/px68k/patches/RG351V create mode 100644 packages/games/libretro/quasi88/package.mk create mode 100644 packages/games/libretro/quicknes/package.mk create mode 100644 packages/games/libretro/race/package.mk create mode 100644 packages/games/libretro/reminiscence/package.mk create mode 100644 packages/games/libretro/sameboy/package.mk create mode 100644 packages/games/libretro/sameduck/package.mk create mode 100644 packages/games/libretro/scummvm/package.mk create mode 100644 packages/games/libretro/smsplus-gx/package.mk create mode 100644 packages/games/libretro/snes9x/package.mk create mode 100644 packages/games/libretro/snes9x2002/package.mk create mode 100644 packages/games/libretro/snes9x2005_plus/package.mk create mode 100644 packages/games/libretro/snes9x2005_plus/patches/01-snes9x2005_plux-01-fix-fpic.patch create mode 100644 packages/games/libretro/snes9x2010/package.mk create mode 100644 packages/games/libretro/snes9x2010/patches/snes9x2010-add-oga.patch create mode 100644 packages/games/libretro/stella-2014/package.mk create mode 100644 packages/games/libretro/stella-2014/patches/stella-2014-01-makefile.patch create mode 100644 packages/games/libretro/stella/package.mk create mode 100644 packages/games/libretro/stella/patches/stella-01-emuelec-platform.patch create mode 100644 packages/games/libretro/swanstation/package.mk create mode 100644 packages/games/libretro/tgbdual/package.mk create mode 100644 packages/games/libretro/tyrquake/package.mk create mode 120000 packages/games/libretro/tyrquake/patches/RG351MP create mode 100644 packages/games/libretro/tyrquake/patches/RG351P/01_351p_resolution.patch create mode 100644 packages/games/libretro/tyrquake/patches/RG351P/rumble.patch create mode 120000 packages/games/libretro/tyrquake/patches/RG351V create mode 100644 packages/games/libretro/uae4arm/package.mk create mode 100644 packages/games/libretro/uzem/package.mk create mode 100644 packages/games/libretro/vba-next/package.mk create mode 100644 packages/games/libretro/vbam/package.mk create mode 100644 packages/games/libretro/vecx/package.mk create mode 100644 packages/games/libretro/vice/package.mk create mode 100644 packages/games/libretro/virtualjaguar/package.mk create mode 100644 packages/games/libretro/xmil/package.mk create mode 100644 packages/games/libretro/xrick/package.mk create mode 100644 packages/games/libretro/yabasanshiro/package.mk create mode 100644 packages/games/native/moonlight/enet/package.mk create mode 100644 packages/games/native/moonlight/package.mk create mode 100644 packages/games/native/moonlight/patches/001-rotation.patch create mode 100644 packages/games/tools/351files/package.mk create mode 100644 packages/games/tools/351files/patches/RG351MP/rg351mp.patch create mode 100644 packages/games/tools/351files/patches/RG552/rg552.patch create mode 100644 packages/games/tools/axe11/X11/.gitignore create mode 100644 packages/games/tools/axe11/X11/ImUtil.h create mode 100644 packages/games/tools/axe11/X11/XKBlib.h create mode 100644 packages/games/tools/axe11/X11/Xcms.h create mode 100644 packages/games/tools/axe11/X11/Xlib-xcb.h create mode 100644 packages/games/tools/axe11/X11/Xlib.h create mode 100644 packages/games/tools/axe11/X11/XlibConf.h.in create mode 100644 packages/games/tools/axe11/X11/Xlibint.h create mode 100644 packages/games/tools/axe11/X11/Xlocale.h create mode 100644 packages/games/tools/axe11/X11/Xregion.h create mode 100644 packages/games/tools/axe11/X11/Xresource.h create mode 100644 packages/games/tools/axe11/X11/Xutil.h create mode 100644 packages/games/tools/axe11/X11/cursorfont.h create mode 100644 packages/games/tools/axe11/X11/extensions/XKBgeom.h create mode 100644 packages/games/tools/axe11/X11/extensions/xf86vmode.h create mode 100644 packages/games/tools/axe11/package.mk create mode 100644 packages/games/tools/axe11/patches/01-compile-fix.patch create mode 100644 packages/games/tools/box64/package.mk create mode 100644 packages/games/tools/box86/package.mk create mode 100644 packages/games/tools/capsimg/package.mk create mode 100644 packages/games/tools/gamecontrollerdb/package.mk create mode 100644 packages/games/tools/gamecontrollerdb/sources/gamecontrollerdb.txt create mode 100644 packages/games/tools/gl4es/package.mk create mode 100644 packages/games/tools/gptokeyb/Makefile create mode 100644 packages/games/tools/gptokeyb/package.mk create mode 100644 packages/games/tools/gptokeyb/patches/0001-build_fix.patch create mode 100644 packages/games/tools/jstest-sdl/package.mk create mode 100644 packages/games/tools/libglu/gl.pc create mode 100644 packages/games/tools/libglu/package.mk create mode 100644 packages/games/tools/libgo2/package.mk create mode 100644 packages/games/tools/libgo2/patches/RG351V/0001-remove_rotation.patch create mode 100644 packages/games/tools/retroarch-assets/package.mk create mode 100644 packages/games/tools/retroarch-overlays/package.mk create mode 100644 packages/games/tools/rg351p-js2xbox/package.mk create mode 100644 packages/games/tools/rs97-commander-sdl2/package.mk create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351P/001-rs97-commander-path.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351P/002-button-reverse.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351P/003-linespacing-fix.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351V/001-rs97-commander-path.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351V/002-button-reverse.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351V/003-linespacing-fix.patch create mode 100644 packages/games/tools/rs97-commander-sdl2/patches/RG351V/004-resolution.patch create mode 100644 packages/graphics/SDL/SDL_net/package.mk create mode 100644 packages/graphics/SDL/SDL_sound/package.mk create mode 100644 packages/graphics/SDL/package.mk create mode 100644 packages/graphics/SDL/yasm/package.mk create mode 100644 packages/graphics/SDL2-14/package.mk create mode 100644 packages/graphics/SDL2/package.mk create mode 100644 packages/graphics/SDL2/patches/0001-kmsdrm-Workaround-missing-gbm_bo_get_offset-and-SDL_.patch create mode 100644 packages/graphics/SDL2/patches/0002-egl_swapinterval_fix.patch create mode 100644 packages/graphics/SDL2/patches/RG351P/0005-SDL-2.0.16.rotation.patch create mode 100644 packages/graphics/SDL2/patches/RG552/0005-SDL-2.0.16.rotation.patch create mode 100644 packages/graphics/bcm2835-driver/package.mk create mode 100644 packages/graphics/bcm2835-driver/system.d/unbind-console.service create mode 100644 packages/graphics/cairo/package.mk create mode 100644 packages/graphics/ftgl/package.mk create mode 100644 packages/graphics/ftgl/patches/ftgl-01-cmake.patch create mode 100644 packages/graphics/ftgl/patches/ftgl-01-ftgl-disable-docs.patch create mode 100644 packages/graphics/giflib/package.mk create mode 100644 packages/graphics/giflib/patches/giflib-01-fix-reallocarray-exception.patch create mode 100644 packages/graphics/glew/package.mk create mode 100644 packages/graphics/glew/patches/glew-01-fix-pkgconf.patch create mode 100644 packages/graphics/glfw/package.mk create mode 100644 packages/graphics/glm/package.mk create mode 100644 packages/graphics/glu/package.mk create mode 100644 packages/graphics/gpu-viv-bin-mx6q/package.mk create mode 100644 packages/graphics/imagemagick/package.mk create mode 100644 packages/graphics/imx-gpu-viv/package.mk create mode 100644 packages/graphics/kmscube/package.mk create mode 100644 packages/graphics/lcms2/package.mk create mode 100644 packages/graphics/libde265/package.mk create mode 100644 packages/graphics/libdrm/package.mk create mode 100644 packages/graphics/libepoxy/package.mk create mode 100644 packages/graphics/libheif/package.mk create mode 100644 packages/graphics/libhybris/package.mk create mode 100644 packages/graphics/libjpeg-turbo/package.mk create mode 100644 packages/graphics/libmali/package.mk create mode 100644 packages/graphics/libmali/patches/RG351/mali-bitfrost-001-gbminclude.patch create mode 100644 packages/graphics/libmali/patches/RG552/mali-bitfrost-001-gbminclude.patch create mode 100644 packages/graphics/libmali/system.d/libmali-setup.service create mode 100644 packages/graphics/libpng/package.mk create mode 100644 packages/graphics/libpng17/package.mk create mode 100644 packages/graphics/libprojectM/package.mk create mode 100644 packages/graphics/libraw/package.mk create mode 100644 packages/graphics/mesa/package.mk create mode 100644 packages/graphics/opengl-mali/package.mk create mode 100644 packages/graphics/opengl-meson-t82x/package.mk create mode 100644 packages/graphics/opengl-meson-t82x/system.d/unbind-console.service create mode 100644 packages/graphics/opengl-meson/package.mk create mode 100755 packages/graphics/opengl-meson/scripts/libmali-overlay-setup create mode 100644 packages/graphics/opengl-meson/system.d/libmali.service create mode 100644 packages/graphics/soil/package.mk create mode 100644 packages/graphics/soil/patches/soil-0001_fix-makefile.patch create mode 100644 packages/graphics/tiff/package.mk create mode 100644 packages/graphics/vsxu/package.mk create mode 100644 packages/graphics/vsxu/patches/vsxu-01-fix-order.patch create mode 100644 packages/graphics/vsxu/patches/vsxu-02-fix-glfw.patch create mode 100644 packages/graphics/vsxu/patches/vsxu-03-fix-exr.patch create mode 100644 packages/graphics/vsxu/patches/vsxu-04-fix-freetype.patch create mode 100644 packages/graphics/vulkan-headers/package.mk create mode 100644 packages/graphics/vulkan-loader/package.mk create mode 100644 packages/graphics/vulkan-tools/package.mk create mode 100644 packages/jelos/config/distribution/configs/all/autoconf.cfg create mode 100644 packages/jelos/config/distribution/configs/all/bluetooth.cfg create mode 100644 packages/jelos/config/distribution/configs/atari800.cfg create mode 100644 packages/jelos/config/distribution/configs/distribution.conf create mode 100644 packages/jelos/config/distribution/configs/tz create mode 100644 packages/jelos/config/distribution/modules/351Files.sh create mode 100755 packages/jelos/config/distribution/modules/Remove ._ Files.sh create mode 100755 packages/jelos/config/distribution/modules/Start 32bit Retroarch.sh create mode 100755 packages/jelos/config/distribution/modules/Start 64bit Retroarch.sh create mode 100755 packages/jelos/config/distribution/modules/Start PPSSPP.sh create mode 100644 packages/jelos/config/distribution/modules/Start ScummVM.sh create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/clean-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/clean.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/filemanager-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/filemanager.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/ppsspp-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/ppsspp.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/retroarch32-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/retroarch32.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/retroarch64-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/retroarch64.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/scummvm-thumb.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/scummvm.png create mode 100644 packages/jelos/config/distribution/modules/downloaded_images/template.png create mode 100644 packages/jelos/config/distribution/modules/gamelist.xml create mode 100644 packages/jelos/gamepads/GO-Super Gamepad.cfg create mode 100755 packages/jelos/gamepads/OpenSimHardware OSH PB Controller.cfg create mode 100644 packages/jelos/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg create mode 100644 packages/jelos/gamepads/retrogame_joypad.cfg create mode 100644 packages/jelos/package.mk create mode 100644 packages/jelos/profile.d/02-distribution create mode 100644 packages/jelos/profile.d/98-jslisten create mode 100644 packages/jelos/profile.d/99-freqfunctions create mode 100644 packages/jelos/sources/asound/rg351/asound.conf create mode 100644 packages/jelos/sources/asound/rg552/asound.conf create mode 100644 packages/jelos/sources/asound/rg552/asound.state create mode 100755 packages/jelos/sources/autostart/RG552/001-alsa create mode 100755 packages/jelos/sources/autostart/autostart create mode 100755 packages/jelos/sources/autostart/common/001-setup create mode 100755 packages/jelos/sources/autostart/common/002-kernel create mode 100755 packages/jelos/sources/autostart/common/003-logging create mode 100755 packages/jelos/sources/autostart/common/004-pico8 create mode 100755 packages/jelos/sources/autostart/common/005-brightness create mode 100755 packages/jelos/sources/autostart/common/006-rootpw create mode 100755 packages/jelos/sources/autostart/common/007-deviceutils create mode 100755 packages/jelos/sources/autostart/common/008-wifi create mode 100755 packages/jelos/sources/autostart/common/009-networkservices create mode 100644 packages/jelos/sources/autostart/daemons/001-ssh create mode 100644 packages/jelos/sources/autostart/daemons/002-samba create mode 100644 packages/jelos/sources/autostart/sounds/silence.ogg create mode 100644 packages/jelos/sources/issue create mode 100644 packages/jelos/sources/pico-8.sh create mode 100755 packages/jelos/sources/scripts/backuptool create mode 100755 packages/jelos/sources/scripts/batocera-bluetooth create mode 100755 packages/jelos/sources/scripts/batocera-bluetooth-agent create mode 100755 packages/jelos/sources/scripts/batocera-brightness create mode 100755 packages/jelos/sources/scripts/batocera-config create mode 100755 packages/jelos/sources/scripts/batocera-es-thebezelproject create mode 120000 packages/jelos/sources/scripts/batocera-info create mode 100755 packages/jelos/sources/scripts/batocera-resolution create mode 100755 packages/jelos/sources/scripts/batocera-retroachievements-info create mode 100755 packages/jelos/sources/scripts/batocera-scraper create mode 100755 packages/jelos/sources/scripts/batocera-settings create mode 100755 packages/jelos/sources/scripts/batocera-systems create mode 100755 packages/jelos/sources/scripts/batocera-wifi create mode 100755 packages/jelos/sources/scripts/bezels.sh create mode 100755 packages/jelos/sources/scripts/brightness create mode 100755 packages/jelos/sources/scripts/emustation-config create mode 100755 packages/jelos/sources/scripts/error.sh create mode 100755 packages/jelos/sources/scripts/factoryreset create mode 100755 packages/jelos/sources/scripts/find.sh create mode 100755 packages/jelos/sources/scripts/getfilters create mode 100755 packages/jelos/sources/scripts/getshaders create mode 100755 packages/jelos/sources/scripts/jelos-info create mode 100755 packages/jelos/sources/scripts/manage_mpv.sh create mode 100755 packages/jelos/sources/scripts/mpv_video.sh create mode 100755 packages/jelos/sources/scripts/rr_audio.sh create mode 100755 packages/jelos/sources/scripts/runemu.sh create mode 100755 packages/jelos/sources/scripts/setemu.sh create mode 100755 packages/jelos/sources/scripts/setsettings.sh create mode 100755 packages/jelos/sources/scripts/show_splash create mode 100755 packages/jelos/sources/scripts/timeinfo create mode 100755 packages/jelos/sources/shutdown.sh create mode 100644 packages/jelos/system.d/jelos-autostart.service create mode 100644 packages/jelos/system.d/jelos.target create mode 100644 packages/jelos/system.d/jslisten.service create mode 100644 packages/jelos/system.d/jslisten.target create mode 100644 packages/jelos/tmpfiles.d/jelos-dirs.conf create mode 100644 packages/jelos/udev.d/99-pandora_pk7.rules create mode 100755 packages/kernel/linux-driver-addons/dvb/crazycat/changelog.txt create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/icon/icon.png create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-02-disable-modules.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-03-config_mycompat_h.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/patches/driver.dvb.crazycat-01-remove-rmmod.pl.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat/source/default.py create mode 100755 packages/kernel/linux-driver-addons/dvb/crazycat_aml/changelog.txt create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/icon/icon.png create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-02-disable-modules.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-03-config_mycompat_h.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/driver.dvb.crazycat_aml-01-remove-rmmod.pl.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/crazycat_aml/source/default.py create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree-06-of-node.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-m88ds3103b.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-02-add-t230c2.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-04-fix-blocking-demux.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-06-fix-si2168-cmd-timeout.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-07-fix-si2157-init.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-08-fix-dvbsky-frontend-detach.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-09-revert-access_ok.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-10-revert-serialize-reset-messages-in-m88ds3103_set_frontend.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_aml/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_cc-06-of-node.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/media_tree_cc-01-m88ds3103b.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-01-m88ds3103b.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-02-linux-901-extend-rc6-toggle-support.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-03-linux-902-extend-rc6-toggle-support-for-zotac.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-04-fix-tbs5520se.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-05-fix-si2168-timeout.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-06-dmxdev-buffer.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-99-build-fix.patch create mode 100755 packages/kernel/linux-driver-addons/dvb/digital_devices/changelog.txt create mode 100644 packages/kernel/linux-driver-addons/dvb/digital_devices/icon/icon.png create mode 100644 packages/kernel/linux-driver-addons/dvb/digital_devices/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/digital_devices/source/default.py create mode 100755 packages/kernel/linux-driver-addons/dvb/dvb-latest/changelog.txt create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/icon/icon.png create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/package.mk create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-01-config_mycompat_h.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-02-disable-modules.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-01-config_mycompat_h.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-02-disable-modules.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-03-versions.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-06-sched_signal-fix.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-02-add-to-backports.patch create mode 100644 packages/kernel/linux-driver-addons/dvb/dvb-latest/source/default.py create mode 100644 packages/kernel/linux-drivers/RTL8188EU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8192CU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0001-add_device_ID_330d.patch create mode 100644 packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0002-fix_310_proc2.patch create mode 100644 packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0101-gcc-4.9.patch create mode 100644 packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0102-gcc-5.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0001-remove_overlapping_pids.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0002-PR61.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0003-fix-vfs-read.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0004-revert-fix-for-old-kernels.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0101-PR63.patch create mode 100644 packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0102-fix-multiple-definitions.patch create mode 100644 packages/kernel/linux-drivers/RTL8192EU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8192EU/patches/RTL8192EU-0101-gcc-5.patch create mode 100644 packages/kernel/linux-drivers/RTL8812AU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8812AU/patches/aarch64/RTL8812AU-02-fix-multiple-definitions.patch create mode 100644 packages/kernel/linux-drivers/RTL8814AU/package.mk create mode 100644 packages/kernel/linux-drivers/RTL8814AU/patches/RTL8814AU-01-fix-multiple-definitions.patch create mode 100644 packages/kernel/linux-drivers/RTL8821CU/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8152-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/patches/RTL8188EU-aml-0001-Add-support-for-a-few-USB-dongles.patch create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8189ES-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8189FS-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8723BS-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8723DS-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8822BS-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/patches/RTL8822BU-aml-01-add_device_ids.patch create mode 100644 packages/kernel/linux-drivers/amlogic/RTL8822CS-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd.conf create mode 100644 packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd_sdio.conf create mode 100644 packages/kernel/linux-drivers/amlogic/ap6xxx-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/ap6xxx-aml/udev.d/80-dhd_sdio.rules create mode 100644 packages/kernel/linux-drivers/amlogic/kvimfan-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/Makefile create mode 100644 packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/khadas-fan.c create mode 100644 packages/kernel/linux-drivers/amlogic/kvimfan-aml/system.d/kvimfan.service create mode 100644 packages/kernel/linux-drivers/amlogic/media_modules-aml/modules-load.d/media_modules.conf create mode 100644 packages/kernel/linux-drivers/amlogic/media_modules-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/002-fix-building.patch create mode 100644 packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/003-multi-decoders-limit-maximum-number-of-decoder.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7601u-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/mt7601u-aml/patches/mt7601u-aml-001-firmware-path.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7603u-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-001-firmware-path.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-002-fix-building.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-003-fix-build-the-vpeter-way.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7610u-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0001-fix-cross-compiling.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0002-support-more-cards.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-aml-003-fix-build-the-vpeter-way.patch create mode 100644 packages/kernel/linux-drivers/amlogic/mt7668-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/qca9377-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-3.14/qca9377-aml-001-Modify-SDIO-and-firmware-handling-to-support-chips-u.patch create mode 100644 packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-4.9/qca9377-aml-001-fix-amlogic-4.9-compatibility.patch create mode 100644 packages/kernel/linux-drivers/amlogic/qca9377-aml/udev.d/99-qca9377-wireless.rules create mode 100644 packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/patches/ssv6xxx-aml-3.14-001-fix-build-and-firmware-path.patch create mode 100644 packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/patches/ssv6xxx-aml-001-fix-build-and-firmware-path.patch create mode 100644 packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/modules-load.d/wifi_dummy.conf create mode 100644 packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/package.mk create mode 100644 packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/Makefile create mode 100644 packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/wifi_dummy.c create mode 100644 packages/kernel/linux-drivers/bcm_sta/package.mk create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0001-change-eth-to-wlan.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0002-user_ioctl.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0003-remove-date-time-macros.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0004-null-pointer-crash.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0005-rdtscl.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0006-kernel-4.7.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0007-kernel-4.8.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0008-kernel-4.11.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0009-kernel-4.12.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0010-kernel-4.15.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0011-fix-kernel-warnings.patch create mode 100644 packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0200-kernel-5.1-rc1-fix.patch create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/package.mk create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-001-conf_file.patch create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-002-auto_detect.patch create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-hdhomerun_discover_find_devices_custom_v2.patch create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-3.8.4.patch create mode 100644 packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-4.2.patch create mode 100644 packages/kernel/linux-drivers/gpu-aml-ng/package.mk create mode 100644 packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-01-fix-cp-error.patch create mode 100644 packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-02-disable-tracepoints.patch create mode 100644 packages/kernel/linux-drivers/gpu-aml/package.mk create mode 100644 packages/kernel/linux-drivers/gpu-aml/patches/gpu-aml-01-fix-cp-error.patch create mode 100644 packages/kernel/linux-drivers/intel_nuc_led/package.mk create mode 100644 packages/kernel/linux-drivers/mali-midgard/package.mk create mode 100644 packages/kernel/linux-drivers/mali-utgard/package.mk create mode 100644 packages/kernel/linux-drivers/openvfd-driver/package.mk create mode 100644 packages/kernel/linux-drivers/openvfd-driver/system.d/openvfd.service create mode 100644 packages/kernel/linux-drivers/slice-drivers/package.mk create mode 100644 packages/kernel/linux-firmware/RTL8188FU/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware-aml.service create mode 100644 packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware@.service create mode 100644 packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/udev.d/80-brcmfmac_sdio.rules create mode 100644 packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/system.d/qca9377-firmware-aml.service create mode 100644 packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/udev.d/80-qca9377-firmware-aml.rules create mode 100644 packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/system.d/rtkbt-firmware-aml.service create mode 100644 packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/udev.d/80-rtkbt-firmware-aml.rules create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8822b_bt/package.mk create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8822b_bt/system.d/rtl8822b_bt-firmware.service create mode 100644 packages/kernel/linux-firmware/amlogic/rtl8822b_bt/udev.d/80-rtl8822b_bt.rules create mode 100644 packages/kernel/linux-firmware/amlogic/wlan-firmware-aml/package.mk create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/package.mk create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/system.d/brcmfmac_sdio-firmware@.service create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/udev.d/80-brcmfmac_sdio.rules create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/package.mk create mode 100755 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/scripts/rpi-btuart create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/system.d/brcmfmac_sdio-firmware.service create mode 100755 packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/udev.d/90-rpi-add-serial.rules create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware/firmwares/any.dat create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware/package.mk create mode 100755 packages/kernel/linux-firmware/brcmfmac_sdio-firmware/scripts/brcmfmac-firmware-setup create mode 100644 packages/kernel/linux-firmware/brcmfmac_sdio-firmware/system.d/brcmfmac-firmware.service create mode 100644 packages/kernel/linux-firmware/dvb-firmware/package.mk create mode 100644 packages/kernel/linux-firmware/firmware-imx/package.mk create mode 100644 packages/kernel/linux-firmware/intel-ucode/package.mk create mode 100644 packages/kernel/linux-firmware/intel-ucode/sources/intel-microcode2ucode.c create mode 100644 packages/kernel/linux-firmware/iwlwifi-firmware/package.mk create mode 100644 packages/kernel/linux-firmware/kernel-firmware/firmwares/any.dat create mode 100644 packages/kernel/linux-firmware/kernel-firmware/firmwares/x86_64.dat create mode 100644 packages/kernel/linux-firmware/kernel-firmware/package.mk create mode 100644 packages/kernel/linux-firmware/kernel-firmware/patches/kernel-firmware-02-add-brcmfmac-43xxx-configs.patch create mode 100644 packages/kernel/linux-firmware/misc-firmware/package.mk create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/modprobe.d/bcmdhd.conf create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/package.mk create mode 100755 packages/kernel/linux-firmware/rockchip-firmware/scripts/hciattach-realtek-config create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/system.d/btattach@.service create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach-realtek.service create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach@.service create mode 100644 packages/kernel/linux-firmware/rockchip-firmware/udev.d/80-rockchip-firmware.rules create mode 100644 packages/kernel/linux-firmware/slice-firmware/package.mk create mode 100644 packages/kernel/linux-firmware/wlan-firmware/package.mk create mode 100644 packages/kernel/linux/package.mk create mode 100644 packages/kernel/linux/patches/amlogic-3.14/linux-010_sx05re_set_colordepth.patch create mode 100644 packages/kernel/linux/patches/amlogic-3.14/linux-011-HID-input-fix-confusion-on-conflicting-mappings.patch create mode 100644 packages/kernel/linux/patches/amlogic-3.14/linux-012-HID-fixup-the-conflicting-keyboard-mappings-quirk.patch create mode 100644 packages/kernel/linux/patches/amlogic-4.9/linux-010_sx05re_set_colordepth.patch create mode 100644 packages/kernel/linux/patches/default/linux-051-ouya_controller_support.patch create mode 100644 packages/kernel/linux/patches/default/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch create mode 100644 packages/kernel/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch create mode 100644 packages/kernel/linux/patches/default/linux-904-improve-xbox-dvd-remote-performance.patch create mode 100644 packages/kernel/linux/patches/default/linux-999-no-lzma-in-x86-perf-build.patch create mode 100644 packages/kernel/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch create mode 100644 packages/kernel/linux/patches/default/linux-999.20-i915-pm-Be-less-agressive-with-clockfreq-changes-on-Bay-Trail.patch create mode 100644 packages/kernel/linux/patches/default/linux-999.21-intel_idle-Disable-C6N-and-C6S-on-Bay-Trail.patch create mode 100644 packages/kernel/linux/patches/linux-004_lower_undefined_mode_timeout.patch create mode 100644 packages/kernel/linux/patches/linux-007_die_floppy_die.patch create mode 100644 packages/kernel/linux/patches/linux-009_disable_i8042_check_on_apple_mac.patch create mode 100644 packages/kernel/linux/patches/linux-010-usbhid-quirks.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-051-ouya_controller_support.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-052-xbox_dvd_remote_support.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-062-imon_pad_ignore_diagonal.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-902-extend-rc6-toggle-support-for-zotac.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-903-backport-rcmm-ir-decoder.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-904-improve-xbox-dvd-remote-performance.patch create mode 100644 packages/kernel/linux/patches/raspberrypi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch create mode 100644 packages/kernel/linux/sysctl.d/network.conf create mode 100644 packages/kernel/linux/sysctl.d/qdisc.conf create mode 100644 packages/kernel/linux/udev.d/30-disable-wakeup.rules create mode 100644 packages/kernel/linux/udev.d/40-modeswitch.rules create mode 100644 packages/lang/Python2/package.mk create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-001_xcompile.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-002_xcompile_path.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-003_xcompile_disable_modules.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-004_xcompile_fix_libffi_configure.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-005_dont_generate_pyo_and_pyc_files.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-006_fix_ncurse_cppflags.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-008-distutils-use-python-sysroot.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-008-reread-environment.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-009-distutils-rpath.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-010-fix-python-config.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-014-abort-on-failed-modules.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-015_no_static_lib.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-016-default-is-optimized.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.11-017-dont-install-2to3.patch create mode 100644 packages/lang/Python2/patches/Python2-2.7.15-001_disable_restricted_mode.patch create mode 100644 packages/lang/Python2/patches/aarch64/Python2-001-fix_platform_machine_func_for_32bit_userspace.patch create mode 100644 packages/lang/Python3/package.mk create mode 100644 packages/lang/Python3/patches/Python3-0000-default-is-optimized.patch create mode 100644 packages/lang/Python3/patches/Python3-0100-buildroot-patches.patch create mode 100644 packages/lang/Python3/patches/Python3-0201-xcompile.patch create mode 100644 packages/lang/Python3/patches/Python3-0202-xcompile.patch create mode 100644 packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch create mode 100644 packages/lang/Python3/patches/Python3-0400-fix-bpo5537.patch create mode 100644 packages/lang/Python3/patches/Python3-0500-fix-bpo45262.patch create mode 100644 packages/lang/dotnet-runtime/changelog.txt create mode 100644 packages/lang/dotnet-runtime/icon/icon.png create mode 100644 packages/lang/dotnet-runtime/package.mk create mode 100644 packages/lang/dotnet-runtime/source/bin/le_dotnet create mode 100644 packages/lang/gcc-arm-aarch64-none-elf/package.mk create mode 100644 packages/lang/gcc-arm-aarch64-none-linux-gnu/package.mk create mode 100644 packages/lang/gcc/package.mk create mode 100644 packages/lang/gcc/patches/gcc-4.8.2-disable_multilib_i386_linux64.patch create mode 100644 packages/lang/gcc/patches/gcc-allow-newer-autoconf.patch create mode 100644 packages/lang/gcc/patches/gcc-crosscompile-badness.patch create mode 100644 packages/lang/jdk-x86_64-zulu/package.mk create mode 100644 packages/lang/jre.zulu/changelog.txt create mode 100644 packages/lang/jre.zulu/icon/icon.png create mode 100644 packages/lang/jre.zulu/package.mk create mode 100644 packages/lang/jre.zulu/profile.d/jre.profile create mode 100644 packages/lang/jre.zulu/source/default.py create mode 100644 packages/lang/llvm/package.mk create mode 100644 packages/lang/llvm/patches/llvm-config.patch create mode 100644 packages/lang/llvm/patches/no-z3.patch create mode 100644 packages/lang/mono/package.mk create mode 100644 packages/lang/nasm/package.mk create mode 100644 packages/lang/ruby/package.mk create mode 100644 packages/mediacenter/CoreELEC-settings/package.mk create mode 100755 packages/mediacenter/CoreELEC-settings/scripts/backup-restore create mode 100755 packages/mediacenter/CoreELEC-settings/scripts/factory-reset create mode 100644 packages/mediacenter/CoreELEC-settings/system.d/backup-restore.service create mode 100644 packages/mediacenter/CoreELEC-settings/system.d/backup-restore.target create mode 100644 packages/mediacenter/CoreELEC-settings/system.d/factory-reset.service create mode 100644 packages/mediacenter/CoreELEC-settings/system.d/factory-reset.target create mode 100644 packages/mediacenter/JsonSchemaBuilder/package.mk create mode 100644 packages/mediacenter/LibreELEC-settings/package.mk create mode 100755 packages/mediacenter/LibreELEC-settings/scripts/backup-restore create mode 100755 packages/mediacenter/LibreELEC-settings/scripts/factory-reset create mode 100644 packages/mediacenter/LibreELEC-settings/system.d/backup-restore.service create mode 100644 packages/mediacenter/LibreELEC-settings/system.d/backup-restore.target create mode 100644 packages/mediacenter/LibreELEC-settings/system.d/factory-reset.service create mode 100644 packages/mediacenter/LibreELEC-settings/system.d/factory-reset.target create mode 100644 packages/mediacenter/TexturePacker/package.mk create mode 100644 packages/mediacenter/p8-platform/package.mk create mode 100644 packages/mediacenter/p8-platform/patches/p8-platform-01-revert-cc-badness.patch create mode 100644 packages/mediacenter/p8-platform/patches/p8-platform-02-cmake_install_prefix_toolchain.patch create mode 100644 packages/multimedia/aom/package.mk create mode 100644 packages/multimedia/dav1d/package.mk create mode 100644 packages/multimedia/ffmpeg/package.mk create mode 100644 packages/multimedia/ffmpeg/patches/libreelec/ffmpeg-001-libreelec.patch create mode 100644 packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch create mode 100644 packages/multimedia/ffmpeg/patches/v4l2-drmprime/ffmpeg-001-v4l2-drmprime.patch create mode 100644 packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch create mode 100644 packages/multimedia/intel-vaapi-driver/package.mk create mode 100644 packages/multimedia/libaacs/package.mk create mode 100644 packages/multimedia/libamcodec/package.mk create mode 100644 packages/multimedia/libass/package.mk create mode 100644 packages/multimedia/libbdplus/package.mk create mode 100644 packages/multimedia/libbluray/package.mk create mode 100644 packages/multimedia/libbluray/patches/libbluray-00-fix-build-with-autoconf-archive-2016-or-later.patch create mode 100644 packages/multimedia/libbluray/patches/libbluray-01-bump_to_Nevcairiel_vL20170904.patch create mode 100644 packages/multimedia/libbluray/patches/libbluray-02-install-extra-MVC-headers.patch create mode 100644 packages/multimedia/libdvbpsi/package.mk create mode 100644 packages/multimedia/libdvdcss/package.mk create mode 100644 packages/multimedia/libdvdnav/package.mk create mode 100644 packages/multimedia/libdvdread/package.mk create mode 100644 packages/multimedia/libhdhomerun/package.mk create mode 100644 packages/multimedia/libmpeg2/package.mk create mode 100644 packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-altivec.patch create mode 100644 packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-arm-private-symbols.patc create mode 100644 packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-armv4l.patch create mode 100644 packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-global-symbol-test.patch create mode 100644 packages/multimedia/libva/package.mk create mode 100644 packages/multimedia/libvdpau/package.mk create mode 100644 packages/multimedia/mpv/package.mk create mode 100755 packages/multimedia/mpv/waf/waf create mode 100644 packages/multimedia/opus/package.mk create mode 100644 packages/multimedia/opusfile/package.mk create mode 100644 packages/multimedia/rkmpp/package.mk create mode 100644 packages/multimedia/rtmpdump/package.mk create mode 100644 packages/multimedia/rtmpdump/patches/001_fix-racing-build-issue.patch create mode 100644 packages/multimedia/rtmpdump/patches/002_build-with-openssl11.patch create mode 100644 packages/multimedia/vlc/package.mk create mode 100644 packages/multimedia/x264/package.mk create mode 100644 packages/multimedia/x265/package.mk create mode 100644 packages/network/avahi/debug.d/avahi.conf create mode 100644 packages/network/avahi/default.d/avahi.conf create mode 100644 packages/network/avahi/package.mk create mode 100644 packages/network/avahi/system.d/avahi-daemon.service create mode 100644 packages/network/avahi/system.d/avahi-defaults.service create mode 100644 packages/network/bluez/debug.d/bluez.conf create mode 100644 packages/network/bluez/debug.d/obexd.conf create mode 100644 packages/network/bluez/default.d/bluez.conf create mode 100644 packages/network/bluez/package.mk create mode 100644 packages/network/bluez/patches/bluez-01_add-obexd-policy.patch create mode 100644 packages/network/bluez/patches/bluez-02_obexd-use-system-bus.patch create mode 100644 packages/network/bluez/patches/bluez-03_storagedir.patch create mode 100644 packages/network/bluez/patches/bluez-04_work-around-Logitech-diNovo-Edge-keyboard-firmware-i.patch create mode 100644 packages/network/bluez/patches/bluez-05-046d-c52b-Logitech-Inc.-Unifying-Receiver.patch create mode 100644 packages/network/bluez/patches/bluez-06-broadcom-fixes.patch create mode 100644 packages/network/bluez/patches/bluez-07-broadcom-dont-set-speed-before-loading.patch create mode 100644 packages/network/bluez/patches/bluez-08-hciattach-retry-device-reset-when-no-response.patch create mode 100644 packages/network/bluez/patches/bluez-09-hciattach-more-verbose.patch create mode 100644 packages/network/bluez/patches/bluez-11_sixaxis-fix-PID-navigation-controller.patch create mode 100644 packages/network/bluez/patches/bluez-12-fix-obexd-after-5_50.patch create mode 100644 packages/network/bluez/patches/bluez-20-sixaxis-autotrust.patch create mode 100644 packages/network/bluez/patches/bluez-21-hciattach-add-QCA9377-Tuffello-support.patch create mode 100644 packages/network/bluez/system.d/bluetooth-defaults.service create mode 100644 packages/network/bluez/system.d/bluetooth.service create mode 100644 packages/network/bluez/system.d/obex.service create mode 100644 packages/network/bluez/tmpfiles.d/z_05_bluez.conf create mode 100644 packages/network/connman/config/settings create mode 100644 packages/network/connman/debug.d/connman.conf create mode 100644 packages/network/connman/package.mk create mode 100644 packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch create mode 100644 packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch create mode 100644 packages/network/connman/patches/connman-05_link-against-ncurses.patch create mode 100755 packages/network/connman/scripts/connman-setup create mode 100644 packages/network/connman/system.d/connman-vpn.service create mode 100644 packages/network/connman/system.d/connman.service create mode 100644 packages/network/connman/system.d/network-online.service create mode 100644 packages/network/connman/tmpfiles.d/z_03_connman.conf create mode 100644 packages/network/ethtool/package.mk create mode 100644 packages/network/ethtool/udev.d/99-wakeup-eth.rules create mode 100644 packages/network/fping/package.mk create mode 100644 packages/network/iptables/config/README create mode 100644 packages/network/iptables/config/home.v4 create mode 100644 packages/network/iptables/config/home.v6 create mode 100644 packages/network/iptables/config/public.v4 create mode 100644 packages/network/iptables/config/public.v6 create mode 100644 packages/network/iptables/package.mk create mode 100755 packages/network/iptables/scripts/iptables_helper create mode 100644 packages/network/iptables/system.d/iptables.service create mode 100644 packages/network/iw/package.mk create mode 100755 packages/network/iw/scripts/setregdomain create mode 100644 packages/network/iw/udev.d/60-iw-regdomain.rules create mode 100644 packages/network/libdnet/package.mk create mode 100644 packages/network/libmnl/package.mk create mode 100644 packages/network/libnfs/package.mk create mode 100644 packages/network/libnftnl/package.mk create mode 100644 packages/network/libnl/package.mk create mode 100644 packages/network/libshairplay/package.mk create mode 100644 packages/network/libshairplay/patches/libshairplay-read_airportkey_from_etc.patch create mode 100644 packages/network/libssh/package.mk create mode 100644 packages/network/libssh2/package.mk create mode 100644 packages/network/libtirpc/package.mk create mode 100644 packages/network/netbase/package.mk create mode 100644 packages/network/nss-mdns/config/nsswitch.conf create mode 100644 packages/network/nss-mdns/package.mk create mode 100644 packages/network/openssh/package.mk create mode 100644 packages/network/openssh/patches/openssh-7.9p1-keydir.patch create mode 100644 packages/network/openssh/system.d/sshd.service create mode 100644 packages/network/openssh/tmpfiles.d/z_04_openssh.conf create mode 100644 packages/network/openvpn/package.mk create mode 100644 packages/network/rfkill/package.mk create mode 100644 packages/network/rfkill/patches/rfkill-0001-fix-version-sh.patch create mode 100644 packages/network/rpcbind/package.mk create mode 100644 packages/network/rpcbind/patches/rpcbind-01-drop-warm-start-as-it-fails.patch create mode 100644 packages/network/rsync/package.mk create mode 100644 packages/network/samba/config/samba4-cache.txt create mode 100644 packages/network/samba/config/smb.conf create mode 100644 packages/network/samba/default.d/samba.conf create mode 100644 packages/network/samba/package.mk create mode 100644 packages/network/samba/patches/samba-200-4.11-fix-ASN1-bso14164.patch create mode 100644 packages/network/samba/patches/samba-950-no-man.patch create mode 100644 packages/network/samba/patches/samba-951-no-man-4.13.patch create mode 100755 packages/network/samba/scripts/samba-autoshare create mode 100755 packages/network/samba/scripts/samba-config create mode 100755 packages/network/samba/scripts/smbd-config create mode 100644 packages/network/samba/system.d.opt/nmbd.service create mode 100644 packages/network/samba/system.d.opt/smbd.service create mode 100644 packages/network/samba/system.d/samba-config.service create mode 100644 packages/network/wireguard-linux-compat/modules-load.d/wireguard.conf create mode 100644 packages/network/wireguard-linux-compat/package.mk create mode 100644 packages/network/wireguard-tools/config/system.d/wireguard.service.sample create mode 100644 packages/network/wireguard-tools/config/wireguard/wireguard.config.sample create mode 100644 packages/network/wireguard-tools/package.mk create mode 100755 packages/network/wireguard-tools/scripts/wg-keygen create mode 100644 packages/network/wireguard-tools/tmpfiles.d/z_03_wireguard.conf create mode 100644 packages/network/wireless-regdb/package.mk create mode 100644 packages/network/wpa_supplicant/config/makefile.config create mode 100644 packages/network/wpa_supplicant/package.mk create mode 100644 packages/network/wpa_supplicant/patches/wpa_supplicant-2.4-libnl3-includes.patch create mode 100644 packages/oem/package.mk create mode 100644 packages/print/freetype/package.mk create mode 100644 packages/print/poppler/package.mk create mode 100644 packages/python/devel/Mako/package.mk create mode 100644 packages/python/devel/MarkupSafe/package.mk create mode 100644 packages/python/devel/distutilscross/package.mk create mode 100644 packages/python/devel/distutilscross/patches/distutilscross-0000-fix-python3.patch create mode 100644 packages/python/devel/meson/package.mk create mode 100644 packages/python/devel/ninja/package.mk create mode 100644 packages/python/devel/pathlib/package.mk create mode 100644 packages/python/devel/pygobject/package.mk create mode 100644 packages/python/devel/pygobject/patches/pygobject-0001-add-PYTHON_INCLUDES-override.patch create mode 100644 packages/python/devel/pygobject/patches/pygobject-2.28.6-automake-1.13.patch create mode 100644 packages/python/devel/setuptools/package.mk create mode 100644 packages/python/devel/waf/package.mk create mode 100644 packages/python/graphics/Pillow/package.mk create mode 100644 packages/python/graphics/Pillow/patches/Pillow-0001-crosscompiling.patch create mode 100644 packages/python/security/pycryptodome/package.mk create mode 100644 packages/python/system/dbus-python/package.mk create mode 100644 packages/python/system/dbussy/package.mk create mode 100644 packages/python/system/simplejson/package.mk create mode 100644 packages/security/gnupg/package.mk create mode 100644 packages/security/gnutls/package.mk create mode 100644 packages/security/libgcrypt/package.mk create mode 100644 packages/security/libgcrypt/patches/libgcrypt-01-dont_replace_parts_of_path-0.1.patch create mode 100644 packages/security/libgcrypt/patches/libgcrypt-ac_cv_sys_symbol_underscore.patch create mode 100644 packages/security/libgpg-error/package.mk create mode 100644 packages/security/nettle/package.mk create mode 100644 packages/security/nspr/package.mk create mode 100644 packages/security/nss/package.mk create mode 100644 packages/security/nss/patches/nss-02_3.15.5-standalone-1.patch create mode 100644 packages/security/nss/patches/nss-04-skip_shlibsign.patch create mode 100644 packages/security/nss/patches/nss-05-disable_host_cflags.patch create mode 100644 packages/security/nss/patches/nss-06-always-include-fstar.patch create mode 100644 packages/security/openssl/cert/cacert.pem create mode 100644 packages/security/openssl/package.mk create mode 100755 packages/security/openssl/scripts/openssl-config create mode 100644 packages/security/openssl/system.d/openssl-config.service create mode 100644 packages/sysutils/amremote/package.mk create mode 100755 packages/sysutils/amremote/scripts/remote-config create mode 100644 packages/sysutils/amremote/system.d/remote-config.service create mode 100644 packages/sysutils/autossh/package.mk create mode 100644 packages/sysutils/bash/package.mk create mode 100644 packages/sysutils/bkeymaps/package.mk create mode 100644 packages/sysutils/busybox/config/busybox-host.conf create mode 100644 packages/sysutils/busybox/config/busybox-init.conf create mode 100644 packages/sysutils/busybox/config/busybox-target.conf create mode 100644 packages/sysutils/busybox/config/httpd.conf create mode 100644 packages/sysutils/busybox/config/inputrc create mode 100644 packages/sysutils/busybox/config/profile create mode 100644 packages/sysutils/busybox/config/suspend-modules.conf create mode 100644 packages/sysutils/busybox/default.d/crond.conf create mode 100644 packages/sysutils/busybox/package.mk create mode 100644 packages/sysutils/busybox/patches/busybox-00_halt_no_init.patch create mode 100644 packages/sysutils/busybox/patches/busybox-02_silence-crond-startup-logging.patch create mode 100644 packages/sysutils/busybox/patches/busybox-03-make_unicode_printable.patch create mode 100644 packages/sysutils/busybox/patches/busybox-04-revert-dd-fsync-change.patch create mode 100644 packages/sysutils/busybox/patches/busybox-05-update-shadow-or-passwd-not-both.patch create mode 100644 packages/sysutils/busybox/patches/busybox-06-prevent-root-weak-passwd.patch create mode 100644 packages/sysutils/busybox/patches/busybox-10-add-MS_BIND-option-when-remouting-bind-mount.patch create mode 100644 packages/sysutils/busybox/profile.d/98-busybox.conf create mode 100755 packages/sysutils/busybox/scripts/createlog create mode 100755 packages/sysutils/busybox/scripts/dtfile create mode 100755 packages/sysutils/busybox/scripts/dtname create mode 100755 packages/sysutils/busybox/scripts/fs-resize create mode 100755 packages/sysutils/busybox/scripts/functions create mode 100755 packages/sysutils/busybox/scripts/getedid create mode 100755 packages/sysutils/busybox/scripts/init create mode 100755 packages/sysutils/busybox/scripts/lsb_release create mode 100755 packages/sysutils/busybox/scripts/pastebinit create mode 100755 packages/sysutils/busybox/scripts/rpi-flash-firmware create mode 100755 packages/sysutils/busybox/sleep.d.serial/99-suspend-modules.sh create mode 100644 packages/sysutils/busybox/sysctl.d/99-coredump.conf create mode 100644 packages/sysutils/busybox/sysctl.d/cdrom.conf create mode 100644 packages/sysutils/busybox/sysctl.d/memory.conf create mode 100644 packages/sysutils/busybox/system.d.opt/cron-defaults.service create mode 100644 packages/sysutils/busybox/system.d.opt/cron.service create mode 100644 packages/sysutils/busybox/system.d/fs-resize.service create mode 100644 packages/sysutils/busybox/system.d/fs-resize.target create mode 100644 packages/sysutils/busybox/system.d/rpi-flash-firmware.service create mode 100644 packages/sysutils/busybox/system.d/rpi-flash-firmware.target create mode 100644 packages/sysutils/busybox/system.d/shell.service create mode 100644 packages/sysutils/busybox/system.d/show-version.service create mode 100644 packages/sysutils/busybox/system.d/storage-log.service create mode 100644 packages/sysutils/busybox/system.d/textmode.target create mode 100644 packages/sysutils/busybox/system.d/var-log.mount create mode 100644 packages/sysutils/busybox/system.d/var.mount create mode 100644 packages/sysutils/busybox/tmpfiles.d/z_01_busybox.conf create mode 100644 packages/sysutils/dbus/package.mk create mode 100644 packages/sysutils/dbus/tmpfiles.d/z_02_dbus.conf create mode 100644 packages/sysutils/depends/efivar/package.mk create mode 100644 packages/sysutils/depends/efivar/patches/efivar-01-static_lib.patch create mode 100644 packages/sysutils/depends/libmtp/package.mk create mode 100644 packages/sysutils/depends/libmtp/patches/libmtp-0001-dont-execute-compiled-tools.patch create mode 100644 packages/sysutils/depends/oniguruma/package.mk create mode 100644 packages/sysutils/diffutils/package.mk create mode 100644 packages/sysutils/diffutils/patches/diffutils-001-no-man.patch create mode 100644 packages/sysutils/diffutils/patches/diffutils-002-explicitly-disable-replacing-getopt.patch create mode 100644 packages/sysutils/diskdev_cmds/package.mk create mode 100644 packages/sysutils/diskdev_cmds/patches/diskdev_cmds-332.14-main.patch create mode 100644 packages/sysutils/dosfstools/package.mk create mode 100644 packages/sysutils/dosfstools/patches/dosfstools-01-silence_backup_boot_sector_diff.patch create mode 100644 packages/sysutils/dstat/package.mk create mode 100644 packages/sysutils/dtach/package.mk create mode 100644 packages/sysutils/e2fsprogs/package.mk create mode 100644 packages/sysutils/e2fsprogs/patches/e2fsprogs-0001-remove-64bit-from-default-ext4-config.patch create mode 100644 packages/sysutils/efibootmgr/package.mk create mode 100644 packages/sysutils/encfs/package.mk create mode 100644 packages/sysutils/entropy/package.mk create mode 100644 packages/sysutils/entropy/sources/add-entropy create mode 100644 packages/sysutils/entropy/sources/add-random-at-shutdown create mode 100644 packages/sysutils/entropy/system.d/add-entropy.service create mode 100644 packages/sysutils/entropy/system.d/add-random-at-shutdown.service create mode 100644 packages/sysutils/ethmactool/package.mk create mode 100755 packages/sysutils/ethmactool/scripts/ethmactool-config create mode 100644 packages/sysutils/ethmactool/system.d/ethmactool-config.service create mode 100644 packages/sysutils/eventlircd/evmap/03_03eb_0002.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_0419_0001.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_046d_c101.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_05a4_9881.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_05ac_8241.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_0709_9137.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_0755_2626.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_0bc7_0006.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_1241_e000.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_13ec_0006.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_147a_e02d.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_18b1_0037.evmap create mode 100644 packages/sysutils/eventlircd/evmap/03_1d57_ac01.evmap create mode 100644 packages/sysutils/eventlircd/evmap/aboxwireless.evmap create mode 100644 packages/sysutils/eventlircd/evmap/aftvsremote.evmap create mode 100644 packages/sysutils/eventlircd/evmap/bdremoteng.evmap create mode 100644 packages/sysutils/eventlircd/evmap/cypress.evmap create mode 100644 packages/sysutils/eventlircd/evmap/default.evmap create mode 100644 packages/sysutils/eventlircd/evmap/mcekbd.evmap create mode 100644 packages/sysutils/eventlircd/evmap/osmc_rf.evmap create mode 100644 packages/sysutils/eventlircd/evmap/osmc_rf2.evmap create mode 100644 packages/sysutils/eventlircd/evmap/ps3remote.evmap create mode 100644 packages/sysutils/eventlircd/evmap/spinelplus.evmap create mode 100644 packages/sysutils/eventlircd/evmap/tevii_s660.evmap create mode 100644 packages/sysutils/eventlircd/evmap/topseed.evmap create mode 100644 packages/sysutils/eventlircd/evmap/wiimote.evmap create mode 100644 packages/sysutils/eventlircd/evmap/xiaomibtremote.evmap create mode 100644 packages/sysutils/eventlircd/evmap/xiaomibtremoteAM.evmap create mode 100644 packages/sysutils/eventlircd/package.mk create mode 100644 packages/sysutils/eventlircd/system.d/eventlircd.service create mode 100644 packages/sysutils/eventlircd/tmpfiles.d/z_62_eventlircd.conf create mode 100644 packages/sysutils/eventlircd/udev.d/98-eventlircd.rules create mode 100644 packages/sysutils/evtest/package.mk create mode 100644 packages/sysutils/exfat/package.mk create mode 100644 packages/sysutils/exfat/patches/01-no-fuse.patch create mode 100644 packages/sysutils/exfatprogs/package.mk create mode 100644 packages/sysutils/fdupes/package.mk create mode 100644 packages/sysutils/file/package.mk create mode 100644 packages/sysutils/file/patches/file-move-magic.mgc-to-addon-data.patch create mode 100644 packages/sysutils/fuse-exfat/package.mk create mode 100644 packages/sysutils/fuse/package.mk create mode 100644 packages/sysutils/fuse/patches/fuse-0001_aarch64-support.patch create mode 100644 packages/sysutils/fuse/patches/fuse-0002-dont-run-update-rc.d.patch create mode 100644 packages/sysutils/getscancodes/package.mk create mode 100644 packages/sysutils/gptfdisk/package.mk create mode 100644 packages/sysutils/grep/package.mk create mode 100644 packages/sysutils/hd-idle/package.mk create mode 100644 packages/sysutils/hd-idle/patches/hd-idle-makefile.patch create mode 100644 packages/sysutils/hddtemp/db/hddtemp.db create mode 100644 packages/sysutils/hddtemp/package.mk create mode 100644 packages/sysutils/hid_mapper/package.mk create mode 100644 packages/sysutils/hid_mapper/patches/hid_mapper-01_crosscompile.patch create mode 100644 packages/sysutils/hid_mapper/patches/hid_mapper-02_include-sys-time.patch create mode 100644 packages/sysutils/hid_mapper/patches/hid_mapper-03_fix-parser.patch create mode 100644 packages/sysutils/htop/package.mk create mode 100644 packages/sysutils/i2c-tools/package.mk create mode 100644 packages/sysutils/inject_bl301/config/bl301.conf create mode 100644 packages/sysutils/inject_bl301/package.mk create mode 100755 packages/sysutils/inject_bl301/scripts/check-bl301.sh create mode 100755 packages/sysutils/inject_bl301/scripts/update-bl301.sh create mode 100644 packages/sysutils/inject_bl301/system.d/update-bl301.service create mode 100644 packages/sysutils/inotify-tools/package.mk create mode 100644 packages/sysutils/irqbalanced/package.mk create mode 100644 packages/sysutils/irqbalanced/system.d/irqbalance.service create mode 100644 packages/sysutils/jq/package.mk create mode 100644 packages/sysutils/kbd/package.mk create mode 100644 packages/sysutils/keyutils/package.mk create mode 100644 packages/sysutils/keyutils/patches/keyutils-02-cflags.patch create mode 100644 packages/sysutils/kmod/modprobe.d/aliases.conf create mode 100644 packages/sysutils/kmod/modprobe.d/i2c.conf create mode 100644 packages/sysutils/kmod/package.mk create mode 100644 packages/sysutils/kmod/patches/kmod-02_fix-pkgconf.patch create mode 100644 packages/sysutils/libevdev/package.mk create mode 100644 packages/sysutils/libhid/package.mk create mode 100644 packages/sysutils/libhid/patches/libhid-0.2.16-automake-1.13.patch create mode 100644 packages/sysutils/libhid/patches/libhid-0.2.16-autoreconf.patch create mode 100644 packages/sysutils/libhid/patches/libhid-use_pkgconfig.patch create mode 100644 packages/sysutils/libusb-compat/package.mk create mode 100644 packages/sysutils/libusb/package.mk create mode 100644 packages/sysutils/lirc/config/lirc_options.conf create mode 100644 packages/sysutils/lirc/default.d/lircd.conf create mode 100644 packages/sysutils/lirc/package.mk create mode 100644 packages/sysutils/lirc/patches/lirc-0001-fix-zotac-poll.patch create mode 100644 packages/sysutils/lirc/patches/lirc-0003-logging-Don-t-use-broken-LOG_CONS-syslog-flag.patch create mode 100644 packages/sysutils/lirc/patches/lirc-0004-lircd-Fix-connect-option-parsing-error-343.patch create mode 100644 packages/sysutils/lirc/patches/lirc-0005-systemd-support-Notify-systemd-on-successful-startup.patch create mode 100644 packages/sysutils/lirc/patches/lirc-0100-disable-python.patch create mode 100755 packages/sysutils/lirc/scripts/lircd_helper create mode 100755 packages/sysutils/lirc/scripts/lircd_uinput_helper create mode 100644 packages/sysutils/lirc/system.d/lircd-uinput.service create mode 100644 packages/sysutils/lirc/system.d/lircd.service create mode 100644 packages/sysutils/lirc/system.d/lircd.socket create mode 100644 packages/sysutils/lirc/tmpfiles.d/z_61_lirc.conf create mode 100644 packages/sysutils/lm_sensors/package.mk create mode 100644 packages/sysutils/lm_sensors/patches/lm_sensors-01_link-static.patch create mode 100644 packages/sysutils/lshw/package.mk create mode 100644 packages/sysutils/mc/package.mk create mode 100644 packages/sysutils/mc/wrapper/mc create mode 100644 packages/sysutils/mc/wrapper/mcedit create mode 100644 packages/sysutils/mc/wrapper/mcview create mode 100644 packages/sysutils/mrxvt/package.mk create mode 100644 packages/sysutils/mrxvt/patches/mrxvt-01_xterm.patch create mode 100644 packages/sysutils/mtpfs/package.mk create mode 100644 packages/sysutils/nmon/package.mk create mode 100644 packages/sysutils/ntfs-3g_ntfsprogs/package.mk create mode 100644 packages/sysutils/ntfs-3g_ntfsprogs/patches/ntfs-3g_ntfsprogs-001-fix-mounting-after-Win10-Creators-Update.patch create mode 100644 packages/sysutils/open-iscsi/package.mk create mode 100644 packages/sysutils/open-iscsi/patches/open-iscsi-01_dynamic_linked_iscsistart.patch create mode 100644 packages/sysutils/open-iscsi/patches/open-iscsi-02-cross_compile.patch create mode 100644 packages/sysutils/open-iscsi/patches/open-iscsi-03_enable-multicast.patch create mode 100644 packages/sysutils/open-iscsi/patches/open-iscsi-04-no_iscsiuio.patch create mode 100644 packages/sysutils/open-vm-tools/package.mk create mode 100644 packages/sysutils/open-vm-tools/system.d/vmtoolsd.service create mode 100644 packages/sysutils/open-vm-tools/system.d/vmware-vmblock-fuse.service create mode 100644 packages/sysutils/parted/package.mk create mode 100644 packages/sysutils/parted/patches/parted-0001-buildfix.patch create mode 100644 packages/sysutils/parted/patches/parted-0002-buildfix-glibc-2.28.patch create mode 100644 packages/sysutils/patch/package.mk create mode 100644 packages/sysutils/pciutils/package.mk create mode 100644 packages/sysutils/pciutils/patches/pciutils-01-fix-pkgconf.patch create mode 100644 packages/sysutils/pv/package.mk create mode 100644 packages/sysutils/rclone/cloud-sync-rules.conf create mode 100644 packages/sysutils/rclone/cloud-sync.conf create mode 100644 packages/sysutils/rclone/package.mk create mode 100644 packages/sysutils/screen/package.mk create mode 100644 packages/sysutils/screen/patches/screen-cross-compile.patch create mode 100644 packages/sysutils/screen/patches/screen-dont_link_against_libelf.patch create mode 100644 packages/sysutils/sed/package.mk create mode 100644 packages/sysutils/smartmontools/package.mk create mode 100644 packages/sysutils/squashfs-tools/package.mk create mode 100644 packages/sysutils/strace/package.mk create mode 100644 packages/sysutils/strace/patches/strace-0001-autoreconf.patch create mode 100644 packages/sysutils/strace/patches/strace-0002-fix-autoconf-archive.patch create mode 100644 packages/sysutils/stress-ng/package.mk create mode 100644 packages/sysutils/systemd/config/hosts.conf create mode 100644 packages/sysutils/systemd/config/hwdb.d/README create mode 100644 packages/sysutils/systemd/config/logind.conf.d/README create mode 100644 packages/sysutils/systemd/config/modules-load.d/README create mode 100644 packages/sysutils/systemd/config/sleep.conf.d/README create mode 100644 packages/sysutils/systemd/config/sleep.conf.d/sleep.conf.sample create mode 100644 packages/sysutils/systemd/config/sysctl.d/README create mode 100644 packages/sysutils/systemd/config/system.d/README create mode 100644 packages/sysutils/systemd/config/system.d/cifs.mount.sample create mode 100644 packages/sysutils/systemd/config/system.d/nfs.mount.sample create mode 100644 packages/sysutils/systemd/config/system.d/openvpn.service.sample create mode 100644 packages/sysutils/systemd/config/timesyncd.conf.d/README create mode 100644 packages/sysutils/systemd/config/tmpfiles.d/README create mode 100644 packages/sysutils/systemd/config/udev.rules.d/README create mode 100644 packages/sysutils/systemd/hwdb.d/70-local-keyboard.hwdb create mode 100644 packages/sysutils/systemd/package.mk create mode 100644 packages/sysutils/systemd/patches/amlogic/systemd-0203-syscall_397_doesnt_exists_on_3.14.patch create mode 100644 packages/sysutils/systemd/patches/amlogic/systemd-9999.1-backport.patch create mode 100644 packages/sysutils/systemd/patches/amlogic/systemd-9999.2-backport.patch create mode 100644 packages/sysutils/systemd/patches/amlogic/systemd-9999.3-backport.patch create mode 100644 packages/sysutils/systemd/patches/amlogic/systemd-9999.4-backport.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0001-move-etc-systemd-system-to-storage-.config-system.d.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0002-move-hwdb.bin-to-run.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0003-remove-nonexistant-dependency.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0200-persist-persistent-timer-stamps.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0300-config-env-unhide-cursor.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0400-hide-useless-shutdown-log-message.patch create mode 100644 packages/sysutils/systemd/patches/systemd-0500-Add-working-directory-storage-for-debug-shell.patch create mode 100644 packages/sysutils/systemd/profile.d/90-systemd.conf create mode 100755 packages/sysutils/systemd/scripts/kernel-overlays-setup create mode 100755 packages/sysutils/systemd/scripts/network-base-setup create mode 100755 packages/sysutils/systemd/scripts/systemd-machine-id-setup create mode 100755 packages/sysutils/systemd/scripts/systemd-timesyncd-setup create mode 100755 packages/sysutils/systemd/scripts/usercache-setup create mode 100755 packages/sysutils/systemd/scripts/userconfig-setup create mode 100644 packages/sysutils/systemd/system.d/debugconfig.service create mode 100644 packages/sysutils/systemd/system.d/flash.mount.d/dependencies.conf create mode 100644 packages/sysutils/systemd/system.d/hwdb.service create mode 100644 packages/sysutils/systemd/system.d/kernel-overlays.service create mode 100644 packages/sysutils/systemd/system.d/machine-id.service create mode 100644 packages/sysutils/systemd/system.d/network-base.service create mode 100644 packages/sysutils/systemd/system.d/storage.mount.d/dependencies.conf create mode 100644 packages/sysutils/systemd/system.d/systemd-timesyncd-setup.service create mode 100644 packages/sysutils/systemd/system.d/systemd-timesyncd.service.d/depend-on-kernel-ip-config.conf create mode 100644 packages/sysutils/systemd/system.d/usercache.service create mode 100644 packages/sysutils/systemd/system.d/userconfig.service create mode 100644 packages/sysutils/systemd/tmpfiles.d/z_01_openelec.conf create mode 100644 packages/sysutils/systemd/udev.d/51-these-are-not-joysticks.rules create mode 100644 packages/sysutils/systemd/udev.d/60-not-joysticks.rules create mode 100644 packages/sysutils/systemd/udev.d/80-clock.rules create mode 100644 packages/sysutils/terminus-font/package.mk create mode 100644 packages/sysutils/tz/package.mk create mode 100644 packages/sysutils/tz/system.d/tz-data.service create mode 100644 packages/sysutils/udevil/config/udevil.conf create mode 100644 packages/sysutils/udevil/package.mk create mode 100644 packages/sysutils/udevil/patches/udevil-fix-build.patch create mode 100644 packages/sysutils/udevil/system.d/udevil-mount@.service create mode 100644 packages/sysutils/udevil/udev.d/95-udevil-mount.rules create mode 100644 packages/sysutils/unrar/package.mk create mode 100644 packages/sysutils/usb-modeswitch/package.mk create mode 100644 packages/sysutils/usbutils/package.mk create mode 100644 packages/sysutils/util-linux/config/swap.conf create mode 100644 packages/sysutils/util-linux/package.mk create mode 100644 packages/sysutils/util-linux/patches/util-linux-01-fix-pkgconf.patch create mode 100644 packages/sysutils/util-linux/patches/util-linux-10-losetup-use-LOOP_CONFIGURE-in-a-more-robust-way.patch create mode 100755 packages/sysutils/util-linux/scripts/mount-swap create mode 100644 packages/sysutils/util-linux/sysctl.d/swappiness.conf create mode 100644 packages/sysutils/util-linux/system.d/swap.service create mode 100644 packages/sysutils/v4l-utils/config/rc_keymaps/README create mode 100644 packages/sysutils/v4l-utils/config/rc_maps.cfg.sample create mode 100644 packages/sysutils/v4l-utils/keymaps/a95x create mode 100644 packages/sysutils/v4l-utils/keymaps/beelink_bt_ir create mode 100644 packages/sysutils/v4l-utils/keymaps/beelink_pwr_only create mode 100644 packages/sysutils/v4l-utils/keymaps/cubox_i create mode 100644 packages/sysutils/v4l-utils/keymaps/kvim create mode 100644 packages/sysutils/v4l-utils/keymaps/kvim2 create mode 100644 packages/sysutils/v4l-utils/keymaps/mecool create mode 100644 packages/sysutils/v4l-utils/keymaps/minix_neo create mode 100644 packages/sysutils/v4l-utils/keymaps/minix_neo_pwr_only create mode 100644 packages/sysutils/v4l-utils/keymaps/odroid create mode 100644 packages/sysutils/v4l-utils/keymaps/pine64 create mode 100644 packages/sysutils/v4l-utils/keymaps/tanix create mode 100644 packages/sysutils/v4l-utils/keymaps/wetek_hub create mode 100644 packages/sysutils/v4l-utils/keymaps/wetek_play_2 create mode 100644 packages/sysutils/v4l-utils/keymaps/xbox_360 create mode 100644 packages/sysutils/v4l-utils/keymaps/xbox_dvd create mode 100644 packages/sysutils/v4l-utils/keymaps/xbox_one create mode 100644 packages/sysutils/v4l-utils/keymaps/zotac create mode 100644 packages/sysutils/v4l-utils/package.mk create mode 100644 packages/sysutils/v4l-utils/patches/v4l-utils-0001-fix-build-with-glibc_2.28.patch create mode 100644 packages/sysutils/v4l-utils/patches/v4l-utils-0002-add-power-on-argument.patch create mode 100644 packages/sysutils/v4l-utils/patches/v4l-utils-0002-backport-imon-and-rcmm-protocol-support.patch create mode 100644 packages/sysutils/v4l-utils/patches/v4l-utils-0003-add-xbox-dvd-protocol.patch create mode 100644 packages/sysutils/v4l-utils/patches/v4l-utils-0004-add-power-on-argument-fixup.patch create mode 100644 packages/sysutils/v4l-utils/udev.d/70-infrared.rules create mode 100644 packages/sysutils/v4l-utils/udev.d/70-input-repeat.rules create mode 100644 packages/sysutils/v86d/package.mk create mode 100644 packages/sysutils/v86d/patches/v86d-0.1.10-crosscompiling.patch create mode 100644 packages/sysutils/v86d/patches/v86d-0.1.10-dont-include-kernelheaders.patch create mode 100644 packages/sysutils/wait-time-sync/package.mk create mode 100644 packages/sysutils/wait-time-sync/sources/Makefile create mode 100644 packages/sysutils/wait-time-sync/sources/wait-time-sync.c create mode 100644 packages/sysutils/wait-time-sync/system.d/wait-time-sync.service create mode 100644 packages/sysutils/wget/package.mk create mode 100644 packages/testing/package.mk create mode 100644 packages/textproc/expat/package.mk create mode 100644 packages/textproc/harfbuzz/package.mk create mode 100644 packages/textproc/icu/package.mk create mode 100644 packages/textproc/icu/patches/icu-01_ldflags.patch create mode 100644 packages/textproc/jsoncpp/package.mk create mode 100644 packages/textproc/libiconv/package.mk create mode 100644 packages/textproc/libidn2/package.mk create mode 100644 packages/textproc/libxml2/package.mk create mode 100644 packages/textproc/libxslt/package.mk create mode 100644 packages/textproc/nlohmann-json/package.mk create mode 100644 packages/textproc/rapidxml/package.mk create mode 100644 packages/textproc/textviewer/package.mk create mode 100644 packages/textproc/tinyxml/package.mk create mode 100644 packages/textproc/tinyxml2/package.mk create mode 100644 packages/textproc/tinyxml2/patches/tinyxml2-0001-really-disable-shared-build.patch create mode 100644 packages/textproc/xmlstarlet/package.mk create mode 100644 packages/textproc/xmlstarlet/patches/xmlstarlet-0001-usage2c.awk-fix-wrong-basename-regexp.patch create mode 100644 packages/tools/SDL2_gfx/package.mk create mode 100644 packages/tools/SDL2_image/package.mk create mode 100644 packages/tools/SDL2_mixer/package.mk create mode 100644 packages/tools/SDL2_net/package.mk create mode 100644 packages/tools/SDL2_ttf/package.mk create mode 100644 packages/tools/SDL2_ttf/patches/SDL2_ttf-001-opengl-only-with-x.patch create mode 100644 packages/tools/aml-dtbtools/package.mk create mode 100644 packages/tools/atf/package.mk create mode 100644 packages/tools/atf/patches/01-plat-allwinner-h6-add-wdt_quirk-to-use-r_wdt-instead.patch create mode 100644 packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/config.txt create mode 100644 packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/distroconfig.txt create mode 100644 packages/tools/bcm2835-bootloader/package.mk create mode 100755 packages/tools/bcm2835-bootloader/release create mode 100644 packages/tools/bcmstat/package.mk create mode 100644 packages/tools/bl301/package.mk create mode 100644 packages/tools/ceemmc/package.mk create mode 100644 packages/tools/dtc/package.mk create mode 100644 packages/tools/dtc/patches/dtc-0001-libfdt-soname-version.patch create mode 100644 packages/tools/entware/package.mk create mode 100644 packages/tools/entware/profile.d/99-entware.conf create mode 100755 packages/tools/entware/scripts/installentware create mode 100644 packages/tools/entware/system.d/entware.service create mode 100644 packages/tools/flashrom/package.mk create mode 100755 packages/tools/grub/package.mk create mode 100644 packages/tools/grub/patches/001-gcc8-fix-packed-not-aligned.patch create mode 100644 packages/tools/hdparm/package.mk create mode 100644 packages/tools/hdparm/patches/hdparm-9.42-cflags.patch create mode 100644 packages/tools/hdparm/udev.d/61-cdrom.rules create mode 100644 packages/tools/installer/config/installer.conf create mode 100644 packages/tools/installer/package.mk create mode 100755 packages/tools/installer/scripts/installer create mode 100644 packages/tools/installer/system.d/installer.service create mode 100644 packages/tools/installer/system.d/installer.target create mode 100644 packages/tools/led_tools/package.mk create mode 100644 packages/tools/luajit/package.mk create mode 100644 packages/tools/luajit/patches/luajit-crosscompile.patch create mode 100644 packages/tools/miniupnpc/package.mk create mode 100644 packages/tools/mkbootimg/package.mk create mode 100644 packages/tools/mtools/package.mk create mode 100644 packages/tools/mtools/patches/mtools-05-fix-install.patch create mode 100644 packages/tools/nano/config/nanorc create mode 100644 packages/tools/nano/package.mk create mode 100644 packages/tools/nano/profile.d/52-nano.conf create mode 100644 packages/tools/newt/package.mk create mode 100644 packages/tools/plymouth-lite/package.mk create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-01-fix-build.patch create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-02-libpng_1.4.0.patch create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-11-cursor.patch create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-12-resize.patch create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-21-16bpp.patch create mode 100644 packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-22-link-static.patch create mode 100644 packages/tools/populatefs/package.mk create mode 100644 packages/tools/populatefs/patches/fix-compilation-issue.patch create mode 100644 packages/tools/procps-ng/package.mk create mode 100644 packages/tools/qemu/package.mk create mode 100644 packages/tools/rkbin/package.mk create mode 100644 packages/tools/rpi-eeprom/config/rpi-eeprom-update create mode 100644 packages/tools/rpi-eeprom/package.mk create mode 100755 packages/tools/rpi-eeprom/source/rpi-eeprom-update create mode 100644 packages/tools/rtk_hciattach/package.mk create mode 100644 packages/tools/rtk_hciattach/patches/rtk_hciattach-01-Makefile.patch create mode 100644 packages/tools/rtk_hciattach/patches/rtk_hciattach-02-dont-read-mac-from-vendor-storage.patch create mode 100644 packages/tools/scrapers/Skyscraper/config/artwork.xml create mode 100644 packages/tools/scrapers/Skyscraper/config/config.ini create mode 100644 packages/tools/scrapers/Skyscraper/package.mk create mode 100755 packages/tools/scrapers/Skyscraper/scripts/skyscraper create mode 100644 packages/tools/scrapers/scraper/package.mk create mode 100644 packages/tools/socat/package.mk create mode 100644 packages/tools/sound/fluidsynth-git/config/fluidsynth.conf create mode 100644 packages/tools/sound/fluidsynth-git/package.mk create mode 100644 packages/tools/sound/fluidsynth-git/system.d/fluidsynth.service create mode 100644 packages/tools/sound/libmad/package.mk create mode 100644 packages/tools/sound/libmad/patches/libmad-0.15.1b-automake_1.13.patch create mode 100644 packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags-O2.patch create mode 100644 packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags.patch create mode 100644 packages/tools/sound/libvorbisidec/package.mk create mode 100644 packages/tools/sound/mpg123/package.mk create mode 100644 packages/tools/sound/munt_neon/math_neon/package.mk create mode 100644 packages/tools/sound/munt_neon/package.mk create mode 100644 packages/tools/sound/soundfont-generaluser/package.mk create mode 100644 packages/tools/sound/timidity/config/GeneralUser.cfg create mode 100644 packages/tools/sound/timidity/config/fluidr3_gm.cfg create mode 100644 packages/tools/sound/timidity/config/fluidr3_gs.cfg create mode 100644 packages/tools/sound/timidity/config/freepats.cfg create mode 100644 packages/tools/sound/timidity/config/soundfont_readme.txt create mode 100644 packages/tools/sound/timidity/config/timidity.cfg create mode 100644 packages/tools/sound/timidity/package.mk create mode 100644 packages/tools/sound/timidity/patches/02-calcnewt-host-build.patch create mode 100644 packages/tools/sound/timidity/patches/03-ar-cru-fix.patch create mode 100644 packages/tools/syslinux/package.mk create mode 100644 packages/tools/syslinux/patches/syslinux-0001-fix-build-with-glibc_2.28.patch create mode 100644 packages/tools/sysutils/MC/etc/edit.indent.rc create mode 100644 packages/tools/sysutils/MC/etc/edit.spell.rc create mode 100644 packages/tools/sysutils/MC/etc/filehighlight.ini create mode 100644 packages/tools/sysutils/MC/etc/ini create mode 100644 packages/tools/sysutils/MC/etc/mc.ext create mode 100644 packages/tools/sysutils/MC/etc/mc.keymap create mode 100644 packages/tools/sysutils/MC/etc/mc.keymap.default create mode 100644 packages/tools/sysutils/MC/etc/mc.keymap.emacs create mode 100644 packages/tools/sysutils/MC/etc/mc.menu create mode 100644 packages/tools/sysutils/MC/etc/mc.menu.sr create mode 100644 packages/tools/sysutils/MC/etc/mcedit.menu create mode 100644 packages/tools/sysutils/MC/etc/panels.ini create mode 100644 packages/tools/sysutils/MC/etc/sfs.ini create mode 100644 packages/tools/sysutils/MC/package.mk create mode 100644 packages/tools/sysutils/MC/patches/MC-01-utf8.patch create mode 100644 packages/tools/sysutils/MC/profile.d/52-mc.conf create mode 100755 packages/tools/sysutils/bluetool/package.mk create mode 100644 packages/tools/sysutils/coreutils/package.mk create mode 100644 packages/tools/sysutils/dialog/package.mk create mode 100644 packages/tools/sysutils/empty/package.mk create mode 100644 packages/tools/sysutils/evdev_tools/package.mk create mode 100644 packages/tools/sysutils/evdev_tools/sources/evkill.c create mode 100644 packages/tools/sysutils/evdev_tools/sources/evtest.c create mode 100644 packages/tools/sysutils/evdev_tools/sources/remap.c create mode 100644 packages/tools/sysutils/evdev_tools/sources/send.c create mode 100644 packages/tools/sysutils/fbterm/package.mk create mode 100644 packages/tools/sysutils/fbterm/patches/0001-fbio.cpp-improxy.cpp-fbterm.cpp-fix-musl-compile.patch create mode 100644 packages/tools/sysutils/fbterm/patches/gcc-6-build-fixes.patch create mode 100644 packages/tools/sysutils/fbterm/terminfo/E/Eterm create mode 120000 packages/tools/sysutils/fbterm/terminfo/E/Eterm-color create mode 100644 packages/tools/sysutils/fbterm/terminfo/a/ansi create mode 100644 packages/tools/sysutils/fbterm/terminfo/c/cons25 create mode 100644 packages/tools/sysutils/fbterm/terminfo/c/cons25-debian create mode 100644 packages/tools/sysutils/fbterm/terminfo/c/cygwin create mode 100644 packages/tools/sysutils/fbterm/terminfo/d/dumb create mode 100644 packages/tools/sysutils/fbterm/terminfo/h/hurd create mode 100644 packages/tools/sysutils/fbterm/terminfo/l/linux create mode 100644 packages/tools/sysutils/fbterm/terminfo/m/mach create mode 100644 packages/tools/sysutils/fbterm/terminfo/m/mach-bold create mode 100644 packages/tools/sysutils/fbterm/terminfo/m/mach-color create mode 100644 packages/tools/sysutils/fbterm/terminfo/m/mach-gnu create mode 100644 packages/tools/sysutils/fbterm/terminfo/m/mach-gnu-color create mode 100644 packages/tools/sysutils/fbterm/terminfo/p/pcansi create mode 100644 packages/tools/sysutils/fbterm/terminfo/r/rxvt create mode 100644 packages/tools/sysutils/fbterm/terminfo/r/rxvt-basic create mode 120000 packages/tools/sysutils/fbterm/terminfo/r/rxvt-m create mode 100644 packages/tools/sysutils/fbterm/terminfo/r/rxvt-unicode create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen-256color create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen-256color-bce create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen-bce create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen-s create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/screen-w create mode 100644 packages/tools/sysutils/fbterm/terminfo/s/sun create mode 100644 packages/tools/sysutils/fbterm/terminfo/v/vt100 create mode 100644 packages/tools/sysutils/fbterm/terminfo/v/vt102 create mode 100644 packages/tools/sysutils/fbterm/terminfo/v/vt220 create mode 100644 packages/tools/sysutils/fbterm/terminfo/v/vt52 create mode 100644 packages/tools/sysutils/fbterm/terminfo/w/wsvt25 create mode 100644 packages/tools/sysutils/fbterm/terminfo/w/wsvt25m create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-256color create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-color create mode 120000 packages/tools/sysutils/fbterm/terminfo/x/xterm-debian create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-mono create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-r5 create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-r6 create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-vt220 create mode 100644 packages/tools/sysutils/fbterm/terminfo/x/xterm-xfree86 create mode 100644 packages/tools/sysutils/freeimage/package.mk create mode 100644 packages/tools/sysutils/freeimage/patches/freeimage-02-makefix.patch create mode 100644 packages/tools/sysutils/git/package.mk create mode 100644 packages/tools/sysutils/jinja2/package.mk create mode 100644 packages/tools/sysutils/joyutils/package.mk create mode 100644 packages/tools/sysutils/jslisten/package.mk create mode 100644 packages/tools/sysutils/jslisten/patches/001-jslisten-path.patch create mode 100644 packages/tools/sysutils/patchelf/package.mk create mode 100644 packages/tools/sysutils/python-evdev/package.mk create mode 100644 packages/tools/sysutils/pyudev/package.mk create mode 100644 packages/tools/sysutils/pyudev/patches/pyudev-001-libraryfix.patch create mode 100644 packages/tools/sysutils/pyyaml/package.mk create mode 100644 packages/tools/sysutils/sdljoytest/package.mk create mode 100644 packages/tools/sysutils/six/package.mk create mode 100644 packages/tools/sysutils/sixaxis/package.mk create mode 100644 packages/tools/sysutils/sixaxis/system.d/sixaxis@.service create mode 100644 packages/tools/sysutils/sixaxis/udev.d/99-sixaxis.rules create mode 100644 packages/tools/sysutils/sixpair/package.mk create mode 100644 packages/tools/sysutils/tcpbridge/package.mk create mode 100644 packages/tools/sysutils/triggerhappy/package.mk create mode 100644 packages/tools/sysutils/xow/package.mk create mode 100644 packages/tools/texturecache.py/package.mk create mode 100644 packages/tools/u-boot-script/package.mk create mode 100644 packages/tools/u-boot-tools-aml/config/fw_env.config create mode 100644 packages/tools/u-boot-tools-aml/package.mk create mode 100644 packages/tools/u-boot-tools-aml/patches/u-boot-tools-0001-dummy_defconfig.patch create mode 100644 packages/tools/u-boot-tools-aml/patches/u-boot-tools-0002-allow-multiple-entries.patch create mode 100644 packages/tools/u-boot-tools-aml/patches/u-boot-tools-0003-nand_env-hack.patch create mode 100644 packages/tools/u-boot-tools/package.mk create mode 100644 packages/tools/unused/boost_locale/package.mk create mode 100644 packages/tools/unused/eigen/package.mk create mode 100644 packages/tools/unused/fbida/package.mk create mode 100644 packages/tools/unused/fbpad/package.mk create mode 100644 packages/tools/unused/fbpad/sources/Makefile create mode 100644 packages/tools/unused/fbpad/sources/conf.h create mode 100644 packages/tools/unused/fbpad/sources/courr.tf create mode 100644 packages/tools/unused/fbpad/sources/draw.c create mode 100644 packages/tools/unused/fbpad/sources/fbpad-256 create mode 100644 packages/tools/unused/munt/package.mk create mode 100644 packages/tools/unused/steam-controller/package.mk create mode 100644 packages/tools/unused/steam-controller/patches/steamcontroller-0001-fix-include-dir.patch create mode 100644 packages/tools/unused/steam-controller/patches/steamcontroller-0002-append-python-path.patch create mode 100644 packages/tools/unused/steam-controller/patches/steamcontroller-0003-wait-for-controller-connection.patch create mode 100644 packages/tools/unused/steam-controller/patches/steamcontroller-0004-use-run-for-pid-directory.patch create mode 100644 packages/tools/unused/steam-controller/patches/steamcontroller-0005-steam-client-will-never-be-running.patch create mode 100644 packages/tools/unused/steam-controller/system.d/driver.steam-controller.service create mode 100644 packages/tools/vim/package.mk create mode 100644 packages/ui/emulationstation/bluez/bluezutils.py create mode 100644 packages/ui/emulationstation/config/es_features.cfg create mode 100644 packages/ui/emulationstation/config/es_input.cfg create mode 100644 packages/ui/emulationstation/config/es_settings.cfg create mode 100644 packages/ui/emulationstation/config/es_systems.cfg create mode 100755 packages/ui/emulationstation/config/scripts/es_env.sh create mode 100644 packages/ui/emulationstation/package.mk create mode 100644 packages/ui/emulationstation/system.d/emustation.service create mode 100644 packages/ui/emulationstation/themes/alekfull-nx/package.mk create mode 100644 packages/ui/emulationstation/themes/es-theme-art-book-3-2/package.mk create mode 100644 packages/ui/emulationstation/themes/es-theme-art-book-4-3/package.mk create mode 100644 packages/ui/emulationstation/themes/es-theme-art-book-next/package.mk create mode 100644 packages/virtual/alsa/package.mk create mode 100644 packages/virtual/arm32/package.mk create mode 100644 packages/virtual/autotools/package.mk create mode 100644 packages/virtual/corefonts/package.mk create mode 100644 packages/virtual/debug/package.mk create mode 100644 packages/virtual/image/package.mk create mode 100644 packages/virtual/initramfs/package.mk create mode 100644 packages/virtual/libc/package.mk create mode 100644 packages/virtual/linux-drivers/package.mk create mode 100644 packages/virtual/linux-firmware/package.mk create mode 100644 packages/virtual/mediacenter/package.mk create mode 100644 packages/virtual/misc-packages/package.mk create mode 100644 packages/virtual/network/package.mk create mode 100644 packages/virtual/remote/package.mk create mode 100644 packages/virtual/toolchain/package.mk create mode 100644 packages/virtual/virtual/package.mk create mode 100644 packages/virtual/x11/package.mk create mode 100644 packages/wayland/libinput/package.mk create mode 100644 packages/wayland/libxkbcommon/package.mk create mode 100644 packages/wayland/mtdev/package.mk create mode 100644 packages/wayland/wayland-protocols/package.mk create mode 100644 packages/wayland/wayland/package.mk create mode 100644 packages/wayland/waylandpp/package.mk create mode 100644 packages/wayland/weston/config/weston.ini create mode 100644 packages/wayland/weston/package.mk create mode 100644 packages/wayland/weston/profile.d/04-weston.conf create mode 100755 packages/wayland/weston/scripts/weston-config create mode 100644 packages/wayland/weston/system.d/weston.service create mode 100644 packages/web/curl/package.mk create mode 100644 packages/web/libmicrohttpd/package.mk create mode 100644 packages/web/nghttp2/package.mk create mode 100644 packages/x11/app/setxkbmap/package.mk create mode 100644 packages/x11/app/setxkbmap/udev.d/98-xorg-xkb.rules create mode 100644 packages/x11/app/xkbcomp/package.mk create mode 100644 packages/x11/app/xrandr/package.mk create mode 100644 packages/x11/data/xkeyboard-config/package.mk create mode 100644 packages/x11/data/xkeyboard-config/patches/xkeyboard-config-0001-dont-require-util-macros.patch create mode 100644 packages/x11/driver/xf86-input-evdev/package.mk create mode 100644 packages/x11/driver/xf86-input-libinput/package.mk create mode 100644 packages/x11/driver/xf86-input-synaptics/package.mk create mode 100644 packages/x11/driver/xf86-video-amdgpu/package.mk create mode 100644 packages/x11/driver/xf86-video-ati/config/xorg-radeon.conf create mode 100644 packages/x11/driver/xf86-video-ati/package.mk create mode 100644 packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.01-fix-gcc-10.patch create mode 100644 packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.02-cleanup-terminology-to-use-primary-secondary.patch create mode 100644 packages/x11/driver/xf86-video-intel/package.mk create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/config/xorg-nvidia-legacy.conf create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/package.mk create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0001-fix-5.6-rc1.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0002-fix-5.7-rc1.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0003-fix-5.7-rc1-reinstate-legacy-support.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0004-fix-5.8.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0005-fix-5.9.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0006-fix-5.10.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0007-fix-5.14.patch create mode 120000 packages/x11/driver/xf86-video-nvidia-legacy/udev.d create mode 100644 packages/x11/driver/xf86-video-nvidia/config/xorg-nvidia.conf create mode 100644 packages/x11/driver/xf86-video-nvidia/package.mk create mode 100644 packages/x11/driver/xf86-video-nvidia/patches/nvidia-fix-linux-5.14.patch create mode 100755 packages/x11/driver/xf86-video-nvidia/scripts/compare_nvidia.py create mode 100755 packages/x11/driver/xf86-video-nvidia/scripts/make_nvidia_udev.py create mode 100644 packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules create mode 100644 packages/x11/driver/xf86-video-vmware/package.mk create mode 100644 packages/x11/font/encodings/package.mk create mode 100644 packages/x11/font/font-bitstream-type1/package.mk create mode 100644 packages/x11/font/font-cursor-misc/package.mk create mode 100644 packages/x11/font/font-misc-misc/package.mk create mode 100644 packages/x11/font/font-util/package.mk create mode 100644 packages/x11/font/font-xfree86-type1/package.mk create mode 100644 packages/x11/font/liberation-fonts-ttf/package.mk create mode 100644 packages/x11/lib/libICE/package.mk create mode 100644 packages/x11/lib/libSM/package.mk create mode 100644 packages/x11/lib/libX11/package.mk create mode 100644 packages/x11/lib/libX11/patches/libX11-disable_nls_tests.patch create mode 100644 packages/x11/lib/libXau/package.mk create mode 100644 packages/x11/lib/libXcomposite/package.mk create mode 100644 packages/x11/lib/libXdamage/package.mk create mode 100644 packages/x11/lib/libXext/package.mk create mode 100644 packages/x11/lib/libXfixes/package.mk create mode 100644 packages/x11/lib/libXfont2/package.mk create mode 100644 packages/x11/lib/libXi/package.mk create mode 100644 packages/x11/lib/libXinerama/package.mk create mode 100644 packages/x11/lib/libXmu/package.mk create mode 100644 packages/x11/lib/libXrandr/package.mk create mode 100644 packages/x11/lib/libXrender/package.mk create mode 100644 packages/x11/lib/libXt/package.mk create mode 100644 packages/x11/lib/libXtst/package.mk create mode 100644 packages/x11/lib/libXxf86vm/package.mk create mode 100644 packages/x11/lib/libfontenc/package.mk create mode 100644 packages/x11/lib/libpciaccess/package.mk create mode 100644 packages/x11/lib/libxcb/package.mk create mode 100644 packages/x11/lib/libxcvt/package.mk create mode 100644 packages/x11/lib/libxkbfile/package.mk create mode 100644 packages/x11/lib/libxshmfence/package.mk create mode 100644 packages/x11/lib/pixman/package.mk create mode 100644 packages/x11/lib/xtrans/package.mk create mode 100644 packages/x11/other/fluxbox/config/apps create mode 100644 packages/x11/other/fluxbox/config/init create mode 100644 packages/x11/other/fluxbox/config/keys create mode 100644 packages/x11/other/fluxbox/package.mk create mode 100644 packages/x11/other/fluxbox/patches/fluxbox-01_hack-avoid-potential-SIGFPE-in-Menu-updateMenu.patch create mode 100644 packages/x11/other/fluxbox/patches/fluxbox-02_hide-useless-errors.patch create mode 100644 packages/x11/other/fluxbox/patches/fluxbox-dont_build_fbrun.patch create mode 100644 packages/x11/other/fluxbox/system.d/windowmanager.service create mode 100644 packages/x11/other/fontconfig/package.mk create mode 100644 packages/x11/proto/xcb-proto/package.mk create mode 100644 packages/x11/proto/xorgproto/package.mk create mode 100644 packages/x11/util/util-macros/package.mk create mode 100644 packages/x11/util/xorg-launch-helper/package.mk create mode 100644 packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-automake-1.14.patch create mode 100644 packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-dont-check-for-libsystemd-daemon.patch create mode 100644 packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-increase-timeout.patch create mode 100755 packages/x11/util/xorg-launch-helper/scripts/xorg-launch create mode 100644 packages/x11/xserver/xorg-server/debug.d/xorg.conf create mode 100644 packages/x11/xserver/xorg-server/package.mk create mode 100644 packages/x11/xserver/xorg-server/patches/xorg-server-100.01-detect-radeon.patch create mode 100644 packages/x11/xserver/xorg-server/patches/xorg-server-100.02-add-fedora-extra-modes-list.patch create mode 100644 packages/x11/xserver/xorg-server/profile.d/11-xorg-server.conf create mode 100755 packages/x11/xserver/xorg-server/scripts/xorg-configure create mode 100644 packages/x11/xserver/xorg-server/system.d/xorg-configure@.service create mode 100644 packages/x11/xserver/xorg-server/system.d/xorg.service create mode 100644 packages/x11/xserver/xorg-server/tmpfiles.d/z_90_xorg-server.conf create mode 100644 packages/x11/xserver/xorg-server/udev.d/97-xorg.rules create mode 100644 projects/Rockchip/bootloader/canupdate.sh create mode 100644 projects/Rockchip/bootloader/install create mode 100644 projects/Rockchip/bootloader/mkimage create mode 100644 projects/Rockchip/bootloader/release create mode 100644 projects/Rockchip/bootloader/update.sh create mode 100644 projects/Rockchip/devices/RG351MP/device.config create mode 100644 projects/Rockchip/devices/RG351MP/device.init create mode 100644 projects/Rockchip/devices/RG351MP/linux/linux.aarch64.conf create mode 100644 projects/Rockchip/devices/RG351MP/options create mode 100644 projects/Rockchip/devices/RG351P/bootloader/canupdate.sh create mode 100644 projects/Rockchip/devices/RG351P/bootloader/install create mode 100644 projects/Rockchip/devices/RG351P/bootloader/mkimage create mode 100644 projects/Rockchip/devices/RG351P/bootloader/release create mode 100644 projects/Rockchip/devices/RG351P/bootloader/update.sh create mode 100644 projects/Rockchip/devices/RG351P/device.config create mode 100644 projects/Rockchip/devices/RG351P/device.init create mode 100644 projects/Rockchip/devices/RG351P/linux/linux.aarch64.conf create mode 100644 projects/Rockchip/devices/RG351P/options create mode 100644 projects/Rockchip/devices/RG351P/packages/python-evdev/package.mk create mode 100644 projects/Rockchip/devices/RG351V/bootloader/canupdate.sh create mode 100644 projects/Rockchip/devices/RG351V/bootloader/install create mode 100644 projects/Rockchip/devices/RG351V/bootloader/mkimage create mode 100644 projects/Rockchip/devices/RG351V/bootloader/release create mode 100644 projects/Rockchip/devices/RG351V/bootloader/update.sh create mode 100644 projects/Rockchip/devices/RG351V/device.config create mode 100644 projects/Rockchip/devices/RG351V/device.init create mode 100644 projects/Rockchip/devices/RG351V/linux/linux.aarch64.conf create mode 100644 projects/Rockchip/devices/RG351V/options create mode 100644 projects/Rockchip/devices/RG552/device.config create mode 100644 projects/Rockchip/devices/RG552/device.init create mode 100644 projects/Rockchip/devices/RG552/linux/linux.aarch64.conf create mode 100644 projects/Rockchip/devices/RG552/options create mode 100644 projects/Rockchip/options create mode 100644 projects/Rockchip/packages/linux/package.mk create mode 100644 projects/Rockchip/packages/linux/patches/RG351V/001-vdeadzone.patch create mode 100644 projects/Rockchip/packages/linux/sysctl.d/network.conf create mode 100644 projects/Rockchip/packages/linux/sysctl.d/qdisc.conf create mode 100644 projects/Rockchip/packages/linux/udev.d/30-disable-wakeup.rules create mode 100644 projects/Rockchip/packages/linux/udev.d/40-modeswitch.rules create mode 100644 projects/Rockchip/packages/linux/udev.d/99-powertargets.rules create mode 100644 projects/Rockchip/packages/sleep/package.mk create mode 100644 projects/Rockchip/packages/sleep/sources/sleep.conf create mode 100755 projects/Rockchip/packages/sleep/sources/sleep.sh create mode 100644 projects/Rockchip/packages/system-utils/package.mk create mode 100755 projects/Rockchip/packages/system-utils/sources/battery create mode 100755 projects/Rockchip/packages/system-utils/sources/fancontrol create mode 100644 projects/Rockchip/packages/system-utils/sources/fancontrol.conf create mode 100755 projects/Rockchip/packages/system-utils/sources/headphone_sense create mode 100755 projects/Rockchip/packages/system-utils/sources/system_utils create mode 100755 projects/Rockchip/packages/system-utils/sources/volume_sense create mode 100644 projects/Rockchip/packages/system-utils/system.d/battery.service create mode 100644 projects/Rockchip/packages/system-utils/system.d/fancontrol.service create mode 100644 projects/Rockchip/packages/system-utils/system.d/headphones.service create mode 100644 projects/Rockchip/packages/system-utils/system.d/volume.service create mode 100644 projects/Rockchip/packages/u-boot/package.mk create mode 100644 projects/Rockchip/patches/libdrm/libdrm-0001-add-rochchip-10bits-formats.patch create mode 100755 scripts/autoreconf create mode 100755 scripts/build create mode 100755 scripts/build_distro create mode 100755 scripts/build_mt create mode 100755 scripts/ccache_stats create mode 100755 scripts/checkdeps create mode 100755 scripts/clean create mode 100755 scripts/create_addon create mode 100755 scripts/create_docker_package create mode 100755 scripts/extract create mode 100755 scripts/genbuildplan.py create mode 100755 scripts/get create mode 100755 scripts/get_archive create mode 100755 scripts/get_file create mode 100755 scripts/get_git create mode 100755 scripts/image create mode 100755 scripts/install create mode 100755 scripts/install_addon create mode 100755 scripts/mkimage create mode 100755 scripts/uboot_helper create mode 100755 scripts/unpack create mode 100755 scripts/update_packages create mode 100755 tools/dashboard create mode 100644 tools/docker/README.md create mode 100644 tools/docker/aarch64/README.md create mode 100644 tools/docker/aarch64/bionic/Dockerfile create mode 100644 tools/docker/ubuntu-focal/Dockerfile create mode 100755 tools/pkgcheck create mode 100755 tools/pkginfo create mode 100755 tools/sync create mode 100755 tools/viewplan diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..1033c44da --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +build.* +sources +release diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b5d3935db --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +* text=auto eol=lf +*.patch -text + +# build directorys +/build.*/ +/.fakeroot.* +/.ccache-* +/.env + +# automatically downloaded source files +/sources/ +/.stamps/ + +# prebuild target binarys to provide +/target/ + +# mkpkg temp +mkpkg-temp + +# options +/.libreelec + +# private working directory +/.work/ + +# dedicated filesystem +/lost+found/ + +# symlinks... +/sources +/.work + +# ccache +/.ccache/ + +# backup files +*.orig + +# vim swap files +*.swp + +# crap +.DS_Store +.directory + +repo/ +repo +local.conf +sx05re-kodi*.log + +packages/sx05re/experimental/ + +release/ + +.lastbuild + +SOURCES diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..776f6630e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:20.04 + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive \ + apt-get install -y \ + gcc make git unzip wget \ + xz-utils libsdl2-dev libsdl2-mixer-dev libfreeimage-dev libfreetype6-dev libcurl4-openssl-dev \ + rapidjson-dev libasound2-dev libgl1-mesa-dev build-essential libboost-all-dev cmake fonts-droid-fallback \ + libvlc-dev libvlccore-dev vlc-bin texinfo premake4 golang libssl-dev curl patchelf \ + xmlstarlet patchutils gawk gperf xfonts-utils default-jre python xsltproc libjson-perl \ + lzop libncurses5-dev device-tree-compiler u-boot-tools rsync p7zip unrar libparse-yapp-perl \ + zip binutils-aarch64-linux-gnu dos2unix p7zip-full libvpx-dev bsdmainutils bc meson \ + && apt-get autoremove --purge -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +RUN adduser --disabled-password --gecos '' docker + +RUN mkdir -p /work && chown docker /work + +WORKDIR /work +USER docker diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..ff62d2026 --- /dev/null +++ b/Makefile @@ -0,0 +1,121 @@ +BUILD_DIRS=build.* + +all: + +system: + ./scripts/image + +release: + ./scripts/image release + +image: + ./scripts/image mkimage + +noobs: + ./scripts/image noobs + +clean: + rm -rf $(BUILD_DIRS) + +distclean: + rm -rf ./.ccache* ./$(BUILD_DIRS) + +src-pkg: + tar cvJf sources.tar.xz sources .stamps + +world: + DEVICE=RG351P ARCH=arm ./scripts/build_distro + DEVICE=RG351P ARCH=aarch64 ./scripts/build_distro + DEVICE=RG351V ARCH=arm ./scripts/build_distro + DEVICE=RG351V ARCH=aarch64 ./scripts/build_distro + DEVICE=RG351MP ARCH=arm ./scripts/build_distro + DEVICE=RG351MP ARCH=aarch64 ./scripts/build_distro + +RG351P: + DEVICE=RG351P ARCH=arm ./scripts/build_distro + DEVICE=RG351P ARCH=aarch64 ./scripts/build_distro + +RG351V: + DEVICE=RG351V ARCH=arm ./scripts/build_distro + DEVICE=RG351V ARCH=aarch64 ./scripts/build_distro + +RG351MP: + DEVICE=RG351MP ARCH=arm ./scripts/build_distro + DEVICE=RG351MP ARCH=aarch64 ./scripts/build_distro + +RG552: + DEVICE=RG552 ARCH=arm ./scripts/build_distro + DEVICE=RG552 ARCH=aarch64 ./scripts/build_distro + +update: + DEVICE=RG351P ARCH=aarch64 ./scripts/update_packages + +package: + ./scripts/build ${PACKAGE} + +package-clean: + ./scripts/clean ${PACKAGE} + +## Docker builds - overview +# docker-* commands just wire up docker to call the normal make command via docker +# For example: make docker-RG351V will use docker to call: make RG351V +# All variables are scoped to docker-* commands to prevent weird collisions/behavior with non-docker commands + +docker-%: DOCKER_IMAGE := "jelos/jelos-build:latest" + +# DOCKER_WORK_DIR is the directory in the Docker image - it used to be /work +# Anytime this directory changes, you must run `make clean` similarly to moving the 351ELEC directory +docker-%: DOCKER_WORK_DIR := $(shell if [ -n "${DOCKER_WORK_DIR}" ]; then echo ${DOCKER_WORK_DIR}; else echo $$(pwd); fi) + +# DEVELOPER_SETTINGS is a file containing developer speicific settings. This will be mounted into the container if it exists +docker-%: DEVELOPER_SETTINGS := $(shell if [ -f "${HOME}/developer_settings.conf" ]; then echo "-v \"${HOME}/developer_settings.conf:${HOME}/developer_settings.conf\""; else echo ""; fi) + +# UID is the user ID of current user - ensures docker sets file permissions properly +docker-%: UID := $(shell id -u) + +# GID is the main user group of current user - ensures docker sets file permissions properly +docker-%: GID := $(shell id -g) + +# PWD is 'present working directory' and passes through the full path to current dir to docker (becomes 'work') +docker-%: PWD := $(shell pwd) + +# Command to use (either `docker` or `podman`) +docker-%: DOCKER_CMD:= $(shell if which docker 2>/dev/null 1>/dev/null; then echo "docker"; elif which podman 2>/dev/null 1>/dev/null; then echo "podman"; fi) + +# Podman requires some extra args (`--userns=keep-id` and `--security-opt=label=disable`). Set those args if using podman +docker-%: PODMAN_ARGS:= $(shell if ! which docker 2>/dev/null 1>/dev/null && which podman 2> /dev/null 1> /dev/null; then echo "--userns=keep-id --security-opt=label=disable -v /proc/mounts:/etc/mtab"; fi) + +# Use 'sudo' if docker ps doesn't work. In theory, other things than missing sudo could cause this. But sudo needed is a common issue and easy to fix. +docker-%: SUDO := $(shell if which docker 2> /dev/null 1> /dev/null && ! docker ps -q 2> /dev/null 1> /dev/null ; then echo "sudo"; fi) + +# Launch docker as interactive if this is an interactive shell (allows ctrl-c for manual and running non-interactive - aka: build server) +docker-%: INTERACTIVE=$(shell [ -t 0 ] && echo "-it") + +# By default pass through anything after `docker-` back into `make` +docker-%: COMMAND=make $* + +# Get .env file ready +docker-%: $(shell env | grep "=" > .env) + +# If the user issues a `make docker-shell` just start up bash as the shell to run commands +docker-shell: COMMAND=bash + +# Command: builds docker image locally from Dockerfile +docker-image-build: + $(SUDO) $(DOCKER_CMD) build . -t $(DOCKER_IMAGE) + +# Command: pulls latest docker image from dockerhub. This will *replace* locally built version. +docker-image-pull: + $(SUDO) $(DOCKER_CMD) pull $(DOCKER_IMAGE) + +# Command: pushes the latest Docker image to dockerhub. This is *not* needed to build. It updates the latest build image in dockerhub for everyone. +# Only 351elec admins in dockerhub can do this. +# +# You must login with: docker login --username and provide either a password or token (from user settings -> security in dockerhub) before this will work. +docker-image-push: + $(SUDO) $(DOCKER_CMD) push $(DOCKER_IMAGE) + +# Wire up docker to call equivalent make files using % to match and $* to pass the value matched by % +docker-%: + $(SUDO) $(DOCKER_CMD) run $(PODMAN_ARGS) $(INTERACTIVE) --init --env-file .env --rm --user $(UID):$(GID) $(DEVELOPER_SETTINGS) -v $(PWD):$(DOCKER_WORK_DIR) -w $(DOCKER_WORK_DIR) $(DOCKER_IMAGE) $(COMMAND) + diff --git a/README.md b/README.md new file mode 100644 index 000000000..e44f7ff3f --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# JELOS - Just enough Linux Operating System +Just Enough Linux Operating System (JELOS) is a simple Linux distribution for ARM based devices that specializes in handhelds. My goal is to build an operating system that has the features and capabilities that I need, and to have fun building it. + +## Features +* A 64bit Operating System. +* Support for FAT32, ExFAT, and EXT4 file systems. +* Filesystem compatibility with Android + +## Licenses +JELOS is a Linux distribution that is made up of many open-source components. Components are provided under their respective licenses. This distribution includes components licensed for non-commercial use only. + +### JELOS Branding +JELOS branding and images are licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/). + +#### You are free to +* Share — copy and redistribute the material in any medium or format +* Adapt — remix, transform, and build upon the material + +#### Under the following terms +* Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. +* NonCommercial — You may not use the material for commercial purposes. +* ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. + +### JELOS Software +Copyright 2021-present Fewtarius + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +## Installation +* Download the latest [version of JELOS](https://github.com/JustEnoughLinuxOS/distribution/releases) (.img.gz) for your device. +* Decompress the image. +* Write the image to an SDCARD using an imaging tool. Common imaging tools include [Balena Etcher](https://www.balena.io/etcher/), [Raspberry Pi Imager](https://www.raspberrypi.com/software/), and [Win32 Disk Imager](https://sourceforge.net/projects/win32diskimager/). If you're skilled with the command line, dd works fine too. + +## Upgrading JELOS +* Download the latest [version of JELOS](https://github.com/JustEnoughLinuxOS/distribution/releases) (.tar or .img.gz) for your device. +* Copy the update to your device over the network or to the sdcard's update folder. +* Reboot the device, and the update will begin automatically. + +## Network Access +* The username for ssh and samba access is "root". The default password is generated on boot. It can be found in the Network Settings menu. + +## Frequently Asked Questions +* Does JELOS offer any support? + * No. JELOS is something that I develop for fun, it is provided as-is. If you require a distribution with support, I recommend you choose a community supported distribution instead. +* Do you plan to add additional ports, software, or emulators? + * I add things to JELOS as I have an itch to scratch. The community has updated PortMaster to work with JELOS. +* What about N64, Dreamcast, Saturn, Jaguar, PSP, etc on the 552? + * Those platforms perform best in Android on the 552, and I have no interest in them. I recommend that you use Android instead for those. +* Will you support my device? + * If you send me a device and source code, I'll consider it. + diff --git a/config/addon/dummy.xml b/config/addon/dummy.xml new file mode 100644 index 000000000..e69de29bb diff --git a/config/addon/xbmc.broken.xml b/config/addon/xbmc.broken.xml new file mode 100644 index 000000000..16e31af19 --- /dev/null +++ b/config/addon/xbmc.broken.xml @@ -0,0 +1,34 @@ + + + + +@REQUIRES@ + + + @PKG_ADDON_PROVIDES@ + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + +@PKG_ADDON_BROKEN@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/addon/xbmc.python.module.xml b/config/addon/xbmc.python.module.xml new file mode 100644 index 000000000..662c16342 --- /dev/null +++ b/config/addon/xbmc.python.module.xml @@ -0,0 +1,31 @@ + + + + +@REQUIRES@ + + + + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/addon/xbmc.python.script.xml b/config/addon/xbmc.python.script.xml new file mode 100644 index 000000000..b90f1517d --- /dev/null +++ b/config/addon/xbmc.python.script.xml @@ -0,0 +1,31 @@ + + + + +@REQUIRES@ + + + @PKG_ADDON_PROVIDES@ + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/addon/xbmc.service.library.xml b/config/addon/xbmc.service.library.xml new file mode 100644 index 000000000..1bc985c30 --- /dev/null +++ b/config/addon/xbmc.service.library.xml @@ -0,0 +1,34 @@ + + + + +@REQUIRES@ + + + @PKG_ADDON_PROVIDES@ + + + + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/addon/xbmc.service.pluginsource.xml b/config/addon/xbmc.service.pluginsource.xml new file mode 100644 index 000000000..948c5ea9c --- /dev/null +++ b/config/addon/xbmc.service.pluginsource.xml @@ -0,0 +1,33 @@ + + + + +@REQUIRES@ + + + @PKG_ADDON_PROVIDES@ + + + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/addon/xbmc.service.xml b/config/addon/xbmc.service.xml new file mode 100644 index 000000000..b037df084 --- /dev/null +++ b/config/addon/xbmc.service.xml @@ -0,0 +1,31 @@ + + + + +@REQUIRES@ + + + @PKG_ADDON_PROVIDES@ + + + @PKG_SHORTDESC@ + +@PKG_LONGDESC@ + + +@PKG_DISCLAIMER@ + + all + +@PKG_ADDON_NEWS@ + + + resources/icon.png + resources/fanart.png +@PKG_ADDON_SCREENSHOT@ + + + diff --git a/config/arch.aarch64 b/config/arch.aarch64 new file mode 100644 index 000000000..f77ae507e --- /dev/null +++ b/config/arch.aarch64 @@ -0,0 +1,29 @@ +# determines TARGET_CPU, if not forced by user + if [ -z "$TARGET_CPU" ]; then + TARGET_CPU=cortex-a53 + fi + +# TARGET_CPU: +# generic cortex-a35 cortex-a53 cortex-a57 cortex-a72 +# exynos-m1 qdf24xx thunderx xgene1 cortex-a57.cortex-a53 +# cortex-a72.cortex-a53 + +# determine architecture's family + case $TARGET_CPU in + generic|cortex-a35|cortex-a53|cortex-a57|cortex-a72|exynos-m1|qdf24xx|thunderx|xgene1|cortex-a57.cortex-a53|cortex-a72.cortex-a53) + TARGET_SUBARCH=aarch64 + TARGET_VARIANT=armv8-a + TARGET_ABI=eabi + TARGET_FEATURES+=" neon" + ;; + esac + + TARGET_GCC_ARCH=${TARGET_SUBARCH/-} + TARGET_KERNEL_ARCH=arm64 + +# setup ARCH specific *FLAGS + TARGET_CFLAGS="-march=${TARGET_VARIANT}${TARGET_CPU_FLAGS} -mabi=lp64 -Wno-psabi -mtune=$TARGET_CPU" +# Disable runtime checking support of ARMv8.0's optional LSE feature. Breaks gdb and mesa compile. + TARGET_CFLAGS="${TARGET_CFLAGS} -mno-outline-atomics" + TARGET_LDFLAGS="-march=${TARGET_VARIANT}${TARGET_CPU_FLAGS} -mtune=$TARGET_CPU" + GCC_OPTS="--with-abi=lp64 --with-arch=$TARGET_VARIANT" diff --git a/config/arch.arm b/config/arch.arm new file mode 100644 index 000000000..88086e35f --- /dev/null +++ b/config/arch.arm @@ -0,0 +1,64 @@ +# determines TARGET_CPU, if not forced by user + if [ -z "$TARGET_CPU" ]; then + TARGET_CPU=cortex-a8 + fi + +# TARGET_CPU: +# arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm7m arm7d +# arm7dm arm7di arm7dmi arm70 arm700 arm700i arm710 arm710c +# arm7100 arm720 arm7500 arm7500fe arm7tdmi arm7tdmi-s arm710t +# arm720t arm740t strongarm strongarm110 strongarm1100 +# strongarm1110 arm8 arm810 arm9 arm9e arm920 arm920t arm922t +# arm946e-s arm966e-s arm968e-s arm926ej-s arm940t arm9tdmi +# arm10tdmi arm1020t arm1026ej-s arm10e arm1020e arm1022e +# arm1136j-s arm1136jf-s mpcore mpcorenovfp arm1156t2-s +# arm1176jz-s arm1176jzf-s cortex-a8 cortex-a9 cortex-r4 +# cortex-r4f cortex-m3 cortex-m1 xscale iwmmxt iwmmxt2 ep9312. + +# TARGET_FPU: +# This specifies what floating point hardware (or hardware emulation) is +# available on the target. Permissible names are: +# fpa fpe2 fpe3 maverick vfp vfpv3 vfpv3-fp16 vfpv3-d16 vfpv3-d16-fp16 +# vfpv3xd vfpv3xd-fp16 neon neon-fp16 vfpv4 vfpv4-d16 fpv4-sp-d16 +# neon-vfpv4. + +# determine architecture's family + case $TARGET_CPU in + arm1176jzf-s) + TARGET_SUBARCH=armv6zk + TARGET_ABI=eabi + TARGET_FPU_FLAGS="-mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU" + ;; + cortex-a7|cortex-a15|cortex-a17|cortex-a15.cortex-a7|cortex-a17.cortex-a7) + TARGET_SUBARCH=armv7ve + TARGET_ABI=eabi + TARGET_FPU_FLAGS="-mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU" + TARGET_FEATURES+=" neon" + ;; + cortex-a5|cortex-a8|cortex-a9) + TARGET_SUBARCH=armv7-a + TARGET_ABI=eabi + TARGET_FPU_FLAGS="-mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU" + TARGET_FEATURES+=" neon" + ;; + cortex-a35|cortex-a53|cortex-a72.cortex-a53) + TARGET_SUBARCH=armv8-a + TARGET_ABI=eabi + TARGET_FPU_FLAGS="-mfloat-abi=$TARGET_FLOAT -mfpu=$TARGET_FPU" + TARGET_FEATURES+=" neon" + ;; + esac + +# if [ "${TARGET_FLOAT}" = "hard" ]; then +# TARGET_ABI+="hf" +# fi + + TARGET_VARIANT="${TARGET_SUBARCH}${TARGET_CPU_FLAGS}" + TARGET_GCC_ARCH=${TARGET_SUBARCH/-} + TARGET_KERNEL_ARCH=${TARGET_KERNEL_ARCH:-arm} + +# setup ARCH specific *FLAGS + TARGET_CFLAGS="-march=$TARGET_VARIANT -mtune=$TARGET_CPU -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated" + [ -n "$TARGET_FPU" ] && TARGET_CFLAGS="$TARGET_CFLAGS $TARGET_FPU_FLAGS" + TARGET_LDFLAGS="-march=$TARGET_VARIANT -mtune=$TARGET_CPU" + GCC_OPTS="--with-abi=aapcs-linux --with-arch=$TARGET_SUBARCH --with-float=$TARGET_FLOAT --with-fpu=$TARGET_FPU" diff --git a/config/arch.x86_64 b/config/arch.x86_64 new file mode 100644 index 000000000..a7d1b3958 --- /dev/null +++ b/config/arch.x86_64 @@ -0,0 +1,17 @@ +# determines TARGET_CPU, if not forced by user + if [ -z "$TARGET_CPU" ]; then + TARGET_CPU=core2 + fi + +# determine architecture's family + TARGET_SUBARCH=x86_64 + + TARGET_GCC_ARCH="${TARGET_SUBARCH/-/}" + TARGET_KERNEL_ARCH=x86 + +# setup ARCH specific *FLAGS + TARGET_CFLAGS="-march=$TARGET_CPU -m64 -mmmx -msse -msse2 -mfpmath=sse" + TARGET_LDFLAGS="-march=$TARGET_CPU -m64" + +# build with SIMD support ( yes / no ) + TARGET_FEATURES+=" mmx sse sse2" diff --git a/config/blocklist b/config/blocklist new file mode 100644 index 000000000..28efcc950 --- /dev/null +++ b/config/blocklist @@ -0,0 +1,2 @@ +amiberry # releases 4.x don't work, needs testing if reenabled +np2kai # Last major commit before hiatus is broken \ No newline at end of file diff --git a/config/docker/changelog.txt b/config/docker/changelog.txt new file mode 100644 index 000000000..ffbebe843 --- /dev/null +++ b/config/docker/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial addon diff --git a/config/docker/package.mk b/config/docker/package.mk new file mode 100644 index 000000000..b34a83a8f --- /dev/null +++ b/config/docker/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="@NAME@" +PKG_VERSION="@VERSION@" # Update bin/docker.@NAME@ accordingly +PKG_REV="100" +PKG_ARCH="@ARCH@" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="docker" +PKG_SITE="" +PKG_SHORTDESC="" +PKG_LONGDESC="" + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME=" (@IMAGE@:$PKG_VERSION)" +PKG_ADDON_PROJECTS="@PROJECTS@" +PKG_ADDON_REQUIRES="service.system.docker:0.0.0" +PKG_ADDON_TYPE="xbmc.service" + +make_target() { + : # +} + +makeinstall_target() { + : # +} + +addon() { + : # +} diff --git a/config/docker/source/bin/docker b/config/docker/source/bin/docker new file mode 100644 index 000000000..41e4bf33a --- /dev/null +++ b/config/docker/source/bin/docker @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +name="$(basename $0)" +. /etc/profile +oe_setup_addon "$name" + +docker rm "$name" 2>/dev/null +docker run --name="$name" \ diff --git a/config/docker/source/default.py b/config/docker/source/default.py new file mode 100644 index 000000000..3b7ab1a1e --- /dev/null +++ b/config/docker/source/default.py @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +import subprocess +import xbmc +import xbmcaddon + + +class Monitor(xbmc.Monitor): + + def __init__(self, *args, **kwargs): + xbmc.Monitor.__init__(self) + self.id = xbmcaddon.Addon().getAddonInfo('id') + + def onSettingsChanged(self): + subprocess.call(['systemctl', 'restart', self.id]) + + +if __name__ == '__main__': + Monitor().waitForAbort() diff --git a/config/docker/source/resources/language/English/strings.po b/config/docker/source/resources/language/English/strings.po new file mode 100644 index 000000000..23c8b7c56 --- /dev/null +++ b/config/docker/source/resources/language/English/strings.po @@ -0,0 +1,10 @@ +msgid "" +msgstr "" + +msgctxt "#30000" +msgid "Configuration" +msgstr "" + +msgctxt "#30001" +msgid "Note: Kodi remote sources can not be used as Docker volume host sources" +msgstr "" diff --git a/config/docker/source/resources/settings.xml b/config/docker/source/resources/settings.xml new file mode 100644 index 000000000..bafc603a7 --- /dev/null +++ b/config/docker/source/resources/settings.xml @@ -0,0 +1,6 @@ + + + + +@SETTINGS@ + diff --git a/config/docker/source/system.d/docker.service b/config/docker/source/system.d/docker.service new file mode 100644 index 000000000..1250444d2 --- /dev/null +++ b/config/docker/source/system.d/docker.service @@ -0,0 +1,14 @@ +[Unit] +Description=%p container +Requires=service.system.docker.service +After=service.system.docker.service + +[Service] +Restart=always +RestartSec=10s +TimeoutStartSec=0 +ExecStart=/bin/sh /storage/.kodi/addons/%p/bin/%p +ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker kill %p + +[Install] +WantedBy=multi-user.target diff --git a/config/functions b/config/functions new file mode 100644 index 000000000..8d2660473 --- /dev/null +++ b/config/functions @@ -0,0 +1,1472 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +### FUNCTION HELPERS ### +# die (message, code) abort with optional message and code +die() { + if [ -n "$1" ]; then + echo -e "$1" >&2 + fi + exit "${2:-1}" +} + +# return 0 if $2 in space-separated list $1, otherwise return 1 +listcontains() { + if [ -n "$1" -a -n "$2" ]; then + [[ ${1} =~ (^|[[:space:]])${2}($|[[:space:]]) ]] && return 0 || return 1 + else + return 1 + fi +} + +# remove item(s) from list. +# looping makes it greedy (eg. listremoveitem "abc def ghi" "(abc|def)" removes both "abc" and "def"). +listremoveitem() { + local data="${1}" odata tmp_array + if [ -n "$1" -a -n "$2" ]; then + while [ : ]; do + odata="${data}" + data="$(echo "${data}" | sed -E "s (^|[[:space:]])${2}($|[[:space:]]) \ g")" + [ "${odata}" = "${data}" ] && break + done + fi + # Use array word splitting to squash spaces + tmp_array=(${data}) + echo "${tmp_array[@]}" +} + +print_color() { + local clr_name="$1" clr_text="$2" clr_actual + local black red green yellow blue magenta cyan white endcolor + local boldblack boldred boldgreen boldyellow boldblue boldmagenta boldcyan boldwhite + + [ -z "${clr_name}" ] && return 0 + + if [ "$DISABLE_COLORS" = "yes" ]; then + [ $# -eq 2 ] && echo -en "${clr_text}" + return 0 + fi + + black="\e[0;30m" + boldblack="\e[1;30m" + red="\e[0;31m" + boldred="\e[1;31m" + green="\e[0;32m" + boldgreen="\e[1;32m" + yellow="\e[0;33m" + boldyellow="\e[1;33m" + blue="\e[0;34m" + boldblue="\e[1;34m" + magenta="\e[0;35m" + boldmagenta="\e[1;35m" + cyan="\e[0;36m" + boldcyan="\e[1;36m" + white="\e[0;37m" + boldwhite="\e[1;37m" + endcolor="\e[0m" + + # $clr_name can be a color variable (boldgreen etc.) or a + # "standard" color determined by an indirect name (CLR_ERROR etc.) + # + # If ${!clr_name} doesn't exist then assume it's a standard color. + # If ${!clr_name} does exist then check it's not a custom color mapping. + # Custom color mappings can be configured in options files. + # + clr_actual="${!clr_name}" + + if [ -n "${clr_actual}" ]; then + clr_actual="${!clr_actual}" + else + case "${clr_name}" in + CLR_ERROR) clr_actual="${boldred}";; + CLR_WARNING) clr_actual="${boldred}";; + CLR_WARNING_DIM) clr_actual="${red}";; + + CLR_APPLY_PATCH) clr_actual="${boldgreen}";; + CLR_AUTORECONF) clr_actual="${boldmagenta}";; + CLR_BUILD) clr_actual="${boldyellow}";; + CLR_TOOLCHAIN) clr_actual="${boldmagenta}";; + CLR_CLEAN) clr_actual="${boldred}";; + CLR_FIXCONFIG) clr_actual="${boldyellow}";; + CLR_GET) clr_actual="${boldcyan}";; + CLR_INFO) clr_actual="${boldgreen}";; + CLR_INSTALL) clr_actual="${boldgreen}";; + CLR_PATCH_DESC) clr_actual="${boldwhite}";; + CLR_TARGET) clr_actual="${boldwhite}";; + CLR_UNPACK) clr_actual="${boldcyan}";; + + CLR_ENDCOLOR) clr_actual="${endcolor}";; + + *) clr_actual="${endcolor}";; + esac + fi + + if [ $# -eq 2 ]; then + echo -en "${clr_actual}${clr_text}${endcolor}" + else + echo -en "${clr_actual}" + fi +} + +# print build progress messages +# param1: message color, p2: label, p3: text, p4: indent (optional) +build_msg() { + local spaces + + [ -n "${BUILD_INDENT}" ] && spaces="$(printf "%${BUILD_INDENT}c" " ")" || spaces="" + + if [ -n "${3}" ]; then + echo -e "${spaces}$(print_color "${1}" "${2}") ${3}" >&${SILENT_OUT} + else + echo -e "${spaces}$(print_color "${1}" "${2}")" >&${SILENT_OUT} + fi + + # pad left space to create "indent" effect + if [ "${4}" = "indent" ]; then + export BUILD_INDENT=$((${BUILD_INDENT:-0}+${BUILD_INDENT_SIZE})) + elif [ -n "${4}" ]; then + die "ERROR: ${0} unexpected parameter: ${4}" + fi +} + +# prints a warning if the file slated for removal doesn't exist +# this allows us to continue instead of bailing out with just "rm" +safe_remove() { + local path="$1" + + [ -z "${path}" ] && return 0 + + if [ -e "${path}" -o -L "${path}" ]; then + rm -r "${path}" + elif [ -n "${PKG_NAME}" ]; then + print_color CLR_WARNING "safe_remove: path does not exist: [${PKG_NAME}]: ${path}\n" + else + print_color CLR_WARNING "safe_remove: path does not exist: ${path}\n" + fi +} + +### BUILDSYSTEM HELPERS ### +# check if a flag is enabled +# $1: flag-name, $2: default (yes/no), $3: ingenious check (none,only-disable,only-enable) +# set variable PKG_[FLAG]_[HOST/TARGET]_ENABLED=(yes/no) +# return 0 if flag is enabled, otherwise 1 +flag_enabled() { + # make flag name upper case and replace hyphen with underscore, to use as variable name + local flag_name=${1^^} + [[ $flag_name =~ : ]] || flag_name+="_TARGET" + flag_name="PKG_${flag_name//[:-]/_}_ENABLED" + + # check flag + if [ -n "${PKG_BUILD_FLAGS}" ] && listcontains "${PKG_BUILD_FLAGS}" "[+]?$1"; then + if [ "${3:none}" = "only-disable" ]; then + die "ERROR: $1 cannot enable via PKG_BUILD_FLAGS (found in $PKG_NAME)" + fi + declare ${flag_name}="yes" + return 0 + elif [ "$2" = "yes" ] && ! listcontains "${PKG_BUILD_FLAGS}" "-$1"; then + declare ${flag_name}="yes" + return 0 + else + if [ "${3:none}" = "only-enable" ]; then + die "ERROR: $1 cannot disable via PKG_BUILD_FLAGS (found in $PKG_NAME)" + fi + declare ${flag_name}="no" + return 1 + fi +} + +setup_pkg_config_target() { + export PKG_CONFIG="$TOOLCHAIN/bin/pkg-config" + export PKG_CONFIG_PATH="" + export PKG_CONFIG_LIBDIR="$SYSROOT_PREFIX/usr/lib/pkgconfig:$SYSROOT_PREFIX/usr/share/pkgconfig" + export PKG_CONFIG_SYSROOT_DIR="$SYSROOT_PREFIX" + export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 + export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 +} + +setup_pkg_config_host() { + export PKG_CONFIG="$TOOLCHAIN/bin/pkg-config" + export PKG_CONFIG_PATH="" + export PKG_CONFIG_LIBDIR="$TOOLCHAIN/lib/pkgconfig:$TOOLCHAIN/share/pkgconfig" + export PKG_CONFIG_SYSROOT_DIR="" + unset PKG_CONFIG_ALLOW_SYSTEM_CFLAGS + unset PKG_CONFIG_ALLOW_SYSTEM_LIBS +} + +setup_toolchain() { + if [ "$LTO_SUPPORT" = "yes" ]; then + if flag_enabled "lto-parallel" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO_PARALLEL $FLAGS_OPTIM_LTO_NO_FAT" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO_PARALLEL $FLAGS_OPTIM_LTO_NO_FAT" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO_COMMON $FLAGS_OPTIM_LTO_PARALLEL" + elif flag_enabled "lto-fat" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO_NO_PARALLEL $FLAGS_OPTIM_LTO_FAT" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO_NO_PARALLEL $FLAGS_OPTIM_LTO_FAT" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO_COMMON $FLAGS_OPTIM_LTO_NO_PARALLEL" + elif flag_enabled "lto" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO_NO_PARALLEL $FLAGS_OPTIM_LTO_NO_FAT" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO_NO_PARALLEL $FLAGS_OPTIM_LTO_NO_FAT" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_LTO_COMMON $FLAGS_OPTIM_LTO_NO_PARALLEL" + fi + fi + + if flag_enabled "lto-off" "no"; then + TARGET_CFLAGS+=" $FLAGS_OPTIM_LTO_OFF" + TARGET_CXXFLAGS+=" $FLAGS_OPTIM_LTO_OFF" + TARGET_LDFLAGS+=" $FLAGS_OPTIM_LTO_OFF" + fi + + # gold flag + if flag_enabled "gold" "$GOLD_SUPPORT" "only-disable"; then + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_GOLD" + fi + + # position-independent code + if flag_enabled "pic" "no"; then + TARGET_CFLAGS+=" $CFLAGS_OPTIM_PIC" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_PIC" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_PIC" + fi + if flag_enabled "pic:host" "no"; then + HOST_CFLAGS+=" $CFLAGS_OPTIM_PIC" + HOST_CXXFLAGS+=" $CXXFLAGS_OPTIM_PIC" + HOST_LDFLAGS+=" $LDFLAGS_OPTIM_PIC" + fi + + # hardening support + if flag_enabled "hardening" "$HARDENING_SUPPORT"; then + TARGET_CFLAGS+=" $CFLAGS_OPTIM_HARDENING" + TARGET_CXXFLAGS+=" $CXXFLAGS_OPTIM_HARDENING" + TARGET_CFLAGS+=" $CPPFLAGS_OPTIM_HARDENING" + TARGET_LDFLAGS+=" $LDFLAGS_OPTIM_HARDENING" + fi + + # parallel + if flag_enabled "parallel" "yes"; then + NINJA_OPTS="$NINJA_OPTS -j$CONCURRENCY_MAKE_LEVEL" + export MAKEFLAGS="-j$CONCURRENCY_MAKE_LEVEL" + else + NINJA_OPTS="$NINJA_OPTS -j1" + export MAKEFLAGS="-j1" + fi + + # verbose flag + if flag_enabled "verbose" "no"; then + NINJA_OPTS="$NINJA_OPTS -v" + export MAKEFLAGS="$MAKEFLAGS V=1 VERBOSE=1" + fi + + case "$1" in + target|init) + export DESTIMAGE="target" + export CC="${TARGET_PREFIX}gcc" + export CXX="${TARGET_PREFIX}g++" + export CPP="${TARGET_PREFIX}cpp" + export LD="${TARGET_PREFIX}ld" + export AS="${TARGET_PREFIX}as" + export AR="${TARGET_PREFIX}ar" + export NM="${TARGET_PREFIX}nm" + export RANLIB="${TARGET_PREFIX}ranlib" + export OBJCOPY="${TARGET_PREFIX}objcopy" + export OBJDUMP="${TARGET_PREFIX}objdump" + export STRIP="${TARGET_PREFIX}strip" + export CPPFLAGS="$TARGET_CPPFLAGS" + export CFLAGS="$TARGET_CFLAGS" + export CXXFLAGS="$TARGET_CXXFLAGS" + export LDFLAGS="$TARGET_LDFLAGS" + setup_pkg_config_target + export CMAKE_CONF=$TOOLCHAIN/etc/cmake-$TARGET_NAME.conf + export CMAKE="cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_CONF -DCMAKE_INSTALL_PREFIX=/usr" + if [ ! -f $CMAKE_CONF ] ; then + mkdir -p $TOOLCHAIN/etc + echo "SET(CMAKE_SYSTEM_NAME Linux)" >> $CMAKE_CONF + echo "SET(CMAKE_SYSTEM_VERSION 1)" >> $CMAKE_CONF + echo "SET(CMAKE_SYSTEM_PROCESSOR $TARGET_ARCH)" >> $CMAKE_CONF + echo "SET(CMAKE_C_COMPILER $CC)" >> $CMAKE_CONF + echo "SET(CMAKE_CXX_COMPILER $CXX)" >> $CMAKE_CONF + echo "SET(CMAKE_CPP_COMPILER $CPP)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH $SYSROOT_PREFIX)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)" >> $CMAKE_CONF + fi + export HOST_CC="$TOOLCHAIN/bin/host-gcc" + export HOST_CXX="$TOOLCHAIN/bin/host-g++" + export HOSTCC="$HOST_CC" + export HOSTCXX="$HOST_CXX" + export CC_FOR_BUILD="$HOST_CC" + export CXX_FOR_BUILD="$HOST_CXX" + export BUILD_CC="$HOST_CC" + export BUILD_CXX="$HOST_CXX" + export _python_sysroot="$SYSROOT_PREFIX" + export _python_prefix=/usr + export _python_exec_prefix=/usr + ;; + host|bootstrap) + export DESTIMAGE="host" + export AWK="gawk" + export CC="$TOOLCHAIN/bin/host-gcc" + export CXX="$TOOLCHAIN/bin/host-g++" + export CPP="cpp" + export LD="ld" + export AS="as" + export AR="ar" + export NM="nm" + export RANLIB="ranlib" + export OBJCOPY="objcopy" + export OBJDUMP="objdump" + export STRIP="strip" + export CPPFLAGS="$HOST_CPPFLAGS" + export CFLAGS="$HOST_CFLAGS" + export CXXFLAGS="$HOST_CXXFLAGS" + export LDFLAGS="$HOST_LDFLAGS" + setup_pkg_config_host + export CMAKE_CONF=$TOOLCHAIN/etc/cmake-$HOST_NAME.conf + export CMAKE="cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_CONF -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN" + if [ ! -f $CMAKE_CONF ] ; then + mkdir -p $TOOLCHAIN/etc + echo "SET(CMAKE_SYSTEM_NAME Linux)" >> $CMAKE_CONF + echo "SET(CMAKE_SYSTEM_VERSION 1)" >> $CMAKE_CONF + echo "SET(CMAKE_SYSTEM_PROCESSOR ${MACHINE_HARDWARE_NAME})" >> $CMAKE_CONF + echo "SET(CMAKE_C_COMPILER $CC)" >> $CMAKE_CONF + echo "SET(CMAKE_CXX_COMPILER $CXX)" >> $CMAKE_CONF + echo "SET(CMAKE_CPP_COMPILER $CXX)" >> $CMAKE_CONF + echo "SET(CMAKE_AR $AR CACHE FILEPATH "Archiver")" >> $CMAKE_CONF # hum? + echo "SET(CMAKE_FIND_ROOT_PATH $TOOLCHAIN)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)" >> $CMAKE_CONF + echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)" >> $CMAKE_CONF + fi + export HOST_CC="$CC" + export HOST_CXX="$CXX" + export HOSTCC="$CC" + export HOSTCXX="$CXX" + export CC_FOR_BUILD="$CC" + export CXX_FOR_BUILD="$CXX" + export BUILD_CC="$CC" + export BUILD_CXX="$CXX" + export _python_sysroot="$TOOLCHAIN" + export _python_prefix=/ + export _python_exec_prefix=/ + ;; + esac +} + +create_meson_conf() { + local endian root properties + case "$1" in + target|init) root="$SYSROOT_PREFIX/usr" + ;; + host|bootstrap) root="$TOOLCHAIN" + ;; + esac + + properties="PKG_MESON_PROPERTIES_${1^^}" + + cat > $2 </dev/null || : + fi +} + +init_package_cache() { + local _ANCHOR="@?+?@" + local temp_global temp_local + + # If the package caches are unset, then populate them + if [ -z "${_CACHE_PACKAGE_LOCAL}" -o -z "${_CACHE_PACKAGE_GLOBAL}" ]; then + temp_global="$(mktemp)" + temp_local="$(mktemp)" + + # cache project/device folder for packages + if [ -n "${DEVICE}" ]; then + find "${ROOT}/projects/${PROJECT}/devices/${DEVICE}/packages" -type f -name package.mk 2>/dev/null | sed "s#/package\.mk\$#${_ANCHOR}#" >> "${temp_local}" + fi + + # cache project folder for packages + find "${ROOT}/projects/${PROJECT}/packages" -type f -name package.mk 2>/dev/null | sed "s#/package\.mk\$#${_ANCHOR}#" >> "${temp_local}" + + # cache packages folder + find "${ROOT}/${PACKAGES}" -type f -name package.mk 2>/dev/null | sed "s#/package\.mk\$#${_ANCHOR}#" >> "${temp_global}" + + _CACHE_PACKAGE_LOCAL="${BUILD}/.cache_package_local" + _CACHE_PACKAGE_GLOBAL="${BUILD}/.cache_package_global" + export _CACHE_PACKAGE_LOCAL _CACHE_PACKAGE_GLOBAL + + # overwrite existing cache files only when they are invalid, or not yet created + mkdir -p "$(dirname "${_CACHE_PACKAGE_GLOBAL}")" + if [ -f "${_CACHE_PACKAGE_LOCAL}" ] && cmp -s "${temp_local}" "${_CACHE_PACKAGE_LOCAL}"; then + rm "${temp_local}" + else + mv "${temp_local}" "${_CACHE_PACKAGE_LOCAL}" + fi + if [ -f "${_CACHE_PACKAGE_GLOBAL}" ] && cmp -s "${temp_global}" "${_CACHE_PACKAGE_GLOBAL}"; then + rm "${temp_global}" + else + mv "${temp_global}" "${_CACHE_PACKAGE_GLOBAL}" + fi + fi + + if [ -z "${_DEBUG_DEPENDS_LIST+x}" ]; then + set_debug_depends + fi +} + +load_build_config() { + if [ -d "${1}" -a -f ${1}/.build.conf ]; then + source ${1}/.build.conf + return 0 + fi + return 1 +} + +save_build_config() { + local var + mkdir -p ${BUILD} + rm -f ${BUILD}/.build.conf + for var in PROJECT DEVICE ARCH DEBUG BUILD_SUFFIX; do + echo "export ${var}=\"${!var}\"" >> ${BUILD}/.build.conf + done +} + +check_path() { + local dashes="===========================" path_err_msg + if [ "${PWD##/usr}" != "${PWD}" ]; then + path_err_msg="\n $dashes$dashes$dashes" + path_err_msg="${path_err_msg}\n ERROR: Detected building inside /usr" + path_err_msg="${path_err_msg}\n $dashes$dashes$dashes" + path_err_msg="${path_err_msg}\n This is not supported with our buildsystem." + path_err_msg="${path_err_msg}\n Please use another dir (for example your \$HOME) to build ${DISTRONAME}" + + die "${path_err_msg}" + fi +} + +check_distro() { + local dashes="===========================" distro_err_msg + if [ -z "${DISTRO}" -o ! -d "${DISTRO_DIR}/${DISTRO}" ]; then + distro_err_msg="\n $dashes$dashes$dashes" + distro_err_msg="${distro_err_msg}\n ERROR: Distro not found, use a valid distro or create a new config" + distro_err_msg="${distro_err_msg}\n $dashes$dashes$dashes" + distro_err_msg="${distro_err_msg}\n\n Valid distros:" + + for distros in ${DISTRO_DIR}/*; do + distro_err_msg="${distro_err_msg}\n - ${distros##*/}" + done + die "${distro_err_msg}" + fi +} + +check_project() { + local dashes="===========================" project_err_msg + if [ -z "${PROJECT}" -o ! -d "${PROJECT_DIR}/${PROJECT}" ]; then + project_err_msg="\n $dashes$dashes$dashes" + project_err_msg="${project_err_msg}\n ERROR: Project not found, use a valid project or create a new config" + project_err_msg="${project_err_msg}\n $dashes$dashes$dashes" + project_err_msg="${project_err_msg}\n\n Valid projects:" + + for projects in ${PROJECT_DIR}/*; do + project_err_msg="${project_err_msg}\n - ${projects##*/}" + done + die "${project_err_msg}" + fi +} + +check_device() { + local dashes="===========================" device_err_msg + if [ \( -z "${DEVICE}" -a -d "${PROJECT_DIR}/${PROJECT}/devices" \) -o \ + \( -n "${DEVICE}" -a ! -d "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}" \) ]; then + device_err_msg="\n $dashes$dashes$dashes" + device_err_msg="${device_err_msg}\n ERROR: You need to specify a valid device for the $PROJECT project" + device_err_msg="${device_err_msg}\n $dashes$dashes$dashes" + device_err_msg="${device_err_msg}\n\n Valid devices for project: ${PROJECT}" + + for device in ${PROJECT_DIR}/${PROJECT}/devices/*; do + device_err_msg="${device_err_msg}\n - ${device##*/}" + done + die "${device_err_msg}" + fi +} + +check_arch() { + local dashes="===========================" arch_err_msg linux_config_dir + if [ -d "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/linux" ]; then + linux_config_dir="${PROJECT_DIR}/${PROJECT}/devices/$DEVICE/linux" + else + linux_config_dir="${PROJECT_DIR}/${PROJECT}/linux" + fi + + if [ ! -e "$linux_config_dir/linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf" ] && + ! ls "$linux_config_dir/"*/linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf &>/dev/null; then + arch_err_msg="\n $dashes$dashes$dashes" + arch_err_msg="${arch_err_msg}\n ERROR: Architecture not found, use a valid Architecture" + arch_err_msg="${arch_err_msg}\n for your project or create a new config" + arch_err_msg="${arch_err_msg}\n $dashes$dashes$dashes" + arch_err_msg="${arch_err_msg}\n\n Valid Architectures for your project: ${PROJECT}" + + for arch in $linux_config_dir/*.conf $linux_config_dir/*/linux.$TARGET_ARCH.conf; do + [[ ${arch} =~ .*\*.* ]] && continue #ignore unexpanded wildcard + arch_err_msg="${arch_err_msg}\n - $(basename $arch | cut -f2 -d".")" + done + die "${arch_err_msg}" + fi +} + +check_config() { + check_path + check_distro + check_project + check_device + check_arch +} + +do_autoreconf() { + export ACLOCAL_DIR=$SYSROOT_PREFIX/usr/share/aclocal + + if [ -e "$TOOLCHAIN/bin/autoconf" ]; then + export AUTOCONF=$TOOLCHAIN/bin/autoconf + fi + + if [ -e "$TOOLCHAIN/bin/automake" ]; then + export AUTOMAKE=$TOOLCHAIN/bin/automake + fi + + if [ -e "$TOOLCHAIN/bin/autopoint" ]; then + export AUTOPOINT=$TOOLCHAIN/bin/autopoint + fi + + if [ -e "$TOOLCHAIN/bin/libtoolize" ]; then + export LIBTOOLIZE=$TOOLCHAIN/bin/libtoolize + fi + + if [ -e "$TOOLCHAIN/bin/intltoolize" ]; then + export INTLTOOLIZE=$TOOLCHAIN/bin/intltoolize + fi + + if [ -e "$TOOLCHAIN/bin/aclocal" ]; then + export ACLOCAL="$TOOLCHAIN/bin/aclocal -I $ACLOCAL_DIR" + fi + + if [ -e "$TOOLCHAIN/bin/autoheader" ]; then + export AUTOHEADER=$TOOLCHAIN/bin/autoheader + fi + + if [ -e "$TOOLCHAIN/bin/libtool" ]; then + export LIBTOOL=$TOOLCHAIN/bin/libtool + fi + + if [ -e "$TOOLCHAIN/bin/autoreconf" -a -e "$INTLTOOLIZE" ]; then + mkdir -p $ACLOCAL_DIR + if [ -e "$LIBTOOLIZE" ]; then + export AUTORECONF="$TOOLCHAIN/bin/autoreconf --verbose --force --install -I $ACLOCAL_DIR" + else + export AUTORECONF="$TOOLCHAIN/bin/autoreconf --verbose --force -I $ACLOCAL_DIR" + fi + $AUTORECONF $@ + fi +} + + +### PACKAGE HELPERS ### +# get variable ($2) for package ($1). +# avoid infinite recursion if required package is already loaded. +get_pkg_variable() { + if [ -n "$1" -a -n "$2" ] ; then + if [ "$1" != "$PKG_NAME" ]; then + source_package "${1}" + fi + echo "${!2}" + fi +} + +# get package's build dir +get_build_dir() { + local _PKG_NAME="${1%:*}" _PKG_VERSION="$(get_pkg_version "$1")" + if [ -n "$_PKG_NAME" -a -n "$_PKG_VERSION" ]; then + echo $BUILD/${_PKG_NAME}-${_PKG_VERSION} + fi +} + +get_pkg_version() { + get_pkg_variable "$1" PKG_VERSION +} + +get_pkg_version_maj_min() { + local pkg_version + + [ -n "${1}" ] && pkg_version="$(get_pkg_version "${1}")" || pkg_version="${PKG_VERSION}" + + if [[ ${pkg_version} =~ ^[0-9A-Za-z]*\.[0-9A-Za-z]*\.[0-9A-za-z]*$ ]]; then + echo "${pkg_version%.*}" + elif [[ ${pkg_version} =~ ^[0-9A-Za-z]*\.[0-9A-Za-z]*$ ]]; then + echo "${pkg_version}" + else + echo "${pkg_version}" + fi +} + +get_pkg_directory() { + local _PKG_ROOT_NAME=${1%:*} _ALL_DIRS _FOUND=0 _ANCHOR="@?+?@" _PKG_DIR _DIR + + # Check for any available local package in preference to a global package + for _DIR in $(grep -F "/${_PKG_ROOT_NAME}${_ANCHOR}" "${_CACHE_PACKAGE_LOCAL}"); do + _DIR="${_DIR%${_ANCHOR}}" + # found first, set $_PKG_DIR + _PKG_DIR="$_DIR" + # keep track of dirs with package.mk for detecting multiple folders + _ALL_DIRS+="${_DIR}\n" + _FOUND=$((_FOUND+1)) + done + + # If there's no local package available, use the global package + if [ $_FOUND -eq 0 ]; then + for _DIR in $(grep -F "/${_PKG_ROOT_NAME}${_ANCHOR}" "${_CACHE_PACKAGE_GLOBAL}"); do + _DIR="${_DIR%${_ANCHOR}}" + # found first, set $_PKG_DIR + _PKG_DIR="$_DIR" + # keep track of dirs with package.mk for detecting multiple folders + _ALL_DIRS+="${_DIR}\n" + _FOUND=$((_FOUND+1)) + done + fi + + # _FOUND multiple packages? fail + if [ $_FOUND -gt 1 ]; then + echo "Error - multiple package folders for package ${_PKG_ROOT_NAME}:" >&2 + echo -e "$_ALL_DIRS" >&2 + die + fi + + echo "$_PKG_DIR" +} + +calculate_stamp() { + local stamp data + + stamp="$PKG_DIR $PROJECT_DIR/$PROJECT/patches/$PKG_NAME" + [ -n "$DEVICE" ] && stamp+=" $PROJECT_DIR/$PROJECT/devices/$DEVICE/patches/$PKG_NAME" + [ -n "$PKG_NEED_UNPACK" ] && stamp+=" $PKG_NEED_UNPACK" + if [ -n "$PKG_STAMP_VAR" ]; then + local TMP_VAR="$(get_build_dir $PKG_NAME)/.pkg_stamp_var" + echo "$PKG_STAMP_VAR" > $TMP_VAR + stamp+=" $TMP_VAR" + fi + + data="$(find ${stamp} -exec sha256sum {} \; 2>/dev/null | sed "s/ ${ROOT//\//\\/}\// /")" + [ -n "${PKG_STAMP}" ] && data+=$'\n'"$(echo "${PKG_STAMP}" | sha256sum)" + + echo "${data}" | sort | sha256sum | cut -d" " -f1 +} + +target_has_feature() { + listcontains "$TARGET_FEATURES" "$1" +} + +# find path for matching file or directory, searching standard directory hierarchy, using optional default +# if a path is located it will be set in FOUND_PATH and exit code will be 0. +find_path() { + local test_func="$1" search="$2" default="$3" + local dir match wildcard=0 ftype + + # support wildcard matches + [[ $search =~ \* || $search =~ \? ]] && wildcard=1 + + [ "$test_func" = "-f" ] && ftype="file" || ftype="dir" + + for dir in $PROJECT_DIR/$PROJECT/devices/$DEVICE/packages/$PKG_NAME \ + $PROJECT_DIR/$PROJECT/devices/$DEVICE \ + $PROJECT_DIR/$PROJECT/packages/$PKG_NAME \ + $PROJECT_DIR/$PROJECT \ + $DISTRO_DIR/$DISTRO/packages/$PKG_NAME \ + $DISTRO_DIR/$DISTRO \ + $PKG_DIR \ + ; do + # ignore directories with missing DEVICE or PKG_NAME components + [[ $dir =~ /packages/$ ]] && continue + [[ $dir =~ /devices/$ ]] && continue + [[ $dir =~ /devices//packages/$PKG_NAME$ ]] && continue + + if [ $wildcard -eq 1 ]; then + ls $dir/$search 1>/dev/null 2>&1 && match="$dir/$search" && break + else + [ $test_func "$dir/$search" ] && match="$dir/$search" && break + fi + done + + if [ -z "$match" -a -n "$default" ]; then + if [[ $default =~ \* || $default =~ \? ]]; then + ls $default 1>/dev/null 2>&1 && match="$default" + else + [ $test_func "$default" ] && match="$default" + fi + fi + + if [ -n "$match" ]; then + FOUND_PATH="$match" + [ "${VERBOSE_FIND_PATH,,}" = "yes" ] && echo "find_path: Searching for $ftype: \"$search\", found: \"$FOUND_PATH\"" >&2 + return 0 + else + unset FOUND_PATH + [ "${VERBOSE_FIND_PATH,,}" = "yes" ] && echo "find_path: Searching for $ftype: \"$search\" - not found" >&2 + return 1 + fi +} + +find_file_path() { + find_path -f "$1" "$2" +} + +find_dir_path() { + find_path -d "$1" "$2" +} + +# p1: name of function to test for +# return 0 if function exists, 1 if not +pkg_call_exists() { + [ "$(type -t ${1})" = "function" ] && return 0 || return 1 +} + +# p1: name of function to execute unconditionally +# testing the exit code value of this function is likely to break set -e fail-on-error behaviour +pkg_call() { + [ -n "${PKG_NAME}" ] || die "$(print_color CLR_ERROR "FAILURE: Cannot call ${1} package function when package is not known!")" + + ${1} +} + +unset_functions() { + local target + + unset -f configure_package + + unset -f pre_unpack unpack post_unpack + unset -f pre_patch post_patch + + for target in target host init bootstrap; do + unset -f pre_build_${target} + unset -f pre_configure_${target} configure_${target} post_configure_${target} + unset -f pre_make_${target} make_${target} post_make_${target} + unset -f pre_makeinstall_${target} makeinstall_${target} post_makeinstall_${target} + done + + unset -f pre_install post_install + + unset -f addon +} + +# p1: name of package to be sourced +source_package() { + local opwd="${PWD}" + + # Don't use BUILD_WITH_DEBUG in "global" package.mk - instead, call the function + # build_with_debug() directly as the function depends on various package.mk + # variables that will be in the process of being configured. Once package.mk is + # fully sourced we can set this variable and use it in situations where we know the + # package has already been sourced. + unset BUILD_WITH_DEBUG + + reset_pkg_vars + unset_functions + + if [ -n "${1}" ]; then + [ -f "${1}" ] && PKG_DIR="$(dirname "${1}")" || PKG_DIR="$(get_pkg_directory "${1}")" + + [ -n "$PKG_DIR" -a -r $PKG_DIR/package.mk ] || die "FAILURE: unable to source package - ${1}/package.mk does not exist" + + cd "${ROOT}" + . ${PKG_DIR}/package.mk || die "FAILURE: an error occurred while sourcing ${PKG_DIR}/package.mk" + cd "${opwd}" + + PKG_SHORTDESC="${PKG_SHORTDESC:-${PKG_NAME} (autogenerated)}" + PKG_LONGDESC="${PKG_LONGDESC:-${PKG_NAME} (autogenerated)}" + + if [ "$PKG_IS_ADDON" = "yes" -o "$PKG_IS_ADDON" = "embedded" ] ; then + [ -z $PKG_SECTION ] && PKG_ADDON_ID="$PKG_NAME" || PKG_ADDON_ID="${PKG_SECTION//\//.}.$PKG_NAME" + [ "$PKG_ADDON_IS_STANDALONE" != "yes" ] && PKG_NEED_UNPACK="${PKG_NEED_UNPACK} $(get_pkg_directory $MEDIACENTER)" + fi + + if [ -n "${PKG_DEPENDS_UNPACK}" ]; then + for _p in ${PKG_DEPENDS_UNPACK}; do + PKG_NEED_UNPACK+=" $(get_pkg_directory ${_p})" + done + fi + + # Automatically set PKG_SOURCE_NAME unless it is already defined. + # PKG_SOURCE_NAME will be automatically set to a name based on + # the $PKG_NAME-$PKG_VERSION convention. + # + # Any $PKG_URL that references more than a single url will abort + # the build as these are no longer supported - use mkpkg instead. + if [ -n "$PKG_URL" -a -z "$PKG_SOURCE_NAME" ]; then + if [[ $PKG_URL =~ .*\ .* ]]; then + echo "Error - packages with multiple urls are no longer supported, use mkpkg." + echo "$PKG_URL" + die + fi + if [[ ${PKG_URL} =~ .git$ || ${PKG_URL} =~ ^git:// ]]; then + PKG_SOURCE_NAME=${PKG_NAME}-${PKG_VERSION} + elif [[ ${PKG_URL} =~ ^file:// ]]; then + PKG_SOURCE_NAME=${PKG_URL#file://} + # if no specific PKG_TAR_COPY_OPTS then default to excluding .git and .svn as they can be huge + [ -z "${PKG_TAR_COPY_OPTS+x}" ] && PKG_TAR_COPY_OPTS="--exclude=.git --exclude=.svn" + else + PKG_SOURCE_NAME="${PKG_URL##*/}" + case $PKG_SOURCE_NAME in + ${PKG_NAME}-${PKG_VERSION}.*) + PKG_SOURCE_NAME=$PKG_SOURCE_NAME + ;; + *.tar | *.tbz | *.tgz | *.txz | *.7z | *.zip) + PKG_SOURCE_NAME=${PKG_NAME}-${PKG_VERSION}.${PKG_SOURCE_NAME##*\.} + ;; + *.tar.bz2 | *.tar.gz | *.tar.xz) + PKG_SOURCE_NAME=${PKG_NAME}-${PKG_VERSION}.tar.${PKG_SOURCE_NAME##*\.} + ;; + *.diff | *.patch | *.diff.bz2 | *.patch.bz2 | patch-*.bz2 | *.diff.gz | *.patch.gz | patch-*.gz) + PKG_SOURCE_NAME=$PKG_SOURCE_NAME + ;; + *) + PKG_SOURCE_NAME=${PKG_NAME}-${PKG_VERSION}.${PKG_SOURCE_NAME##*\.} + ;; + esac + fi + fi + + PKG_BUILD="$BUILD/${PKG_NAME}-${PKG_VERSION}" + fi + + build_with_debug && BUILD_WITH_DEBUG="yes" || BUILD_WITH_DEBUG="no" + + # Late variable binding - allow the package to now evaluate any variables + # that we may have initialised after sourcing the package, typically + # PKG_BUILD etc. + if [ -n "${PKG_NAME}" ]; then + if pkg_call_exists configure_package; then + pkg_call configure_package + fi + fi +} + +# arg1: file, or directory to recursively compile. +python_compile() { + local path="${1:-${INSTALL}/usr/lib/${PKG_PYTHON_VERSION}}" + ${TOOLCHAIN}/bin/python3 -Wi -t -B ${TOOLCHAIN}/lib/${PKG_PYTHON_VERSION}/compileall.py -f -d "${path#${INSTALL}}" "${path}" + python_remove_source "${path}" +} + +# arg1: file, or directory from which to recursively remove all py source code +python_remove_source() { + local path="${1:-${INSTALL}/usr/lib/${PKG_PYTHON_VERSION}}" + if [ -d "${path}" ]; then + find "${path}" -type f -name '*.py' -delete + else + rm -f "${path}" + fi +} + +# arg1: directory to process recursively +# strip incorrect build-host ABI from native Python3 modules (see PEP3149) +python_fix_abi() { + local pymodule pyname + + for pymodule in $(find ${1} -type f -name '*.cpython-*.so' 2>/dev/null); do + pyname=${pymodule##*/} + pyname=${pyname%.so} # strip extension + pyname=${pyname%.*} # strip incorrect ABI + echo "python_fix_abi: Removing ABI from ${pymodule} -> ${pyname}.so" + mv ${pymodule} ${pymodule%/*}/${pyname}.so + done +} + +### KERNEL HELPERS ### +kernel_path() { + get_build_dir linux +} + +kernel_version() { + get_pkg_version linux +} + +kernel_config_path() { + local cfg pkg_linux_dir pkg_linux_version config_name + + pkg_linux_version="$(get_pkg_version linux)" + pkg_linux_dir="$(get_pkg_directory linux)" + + config_name="linux.${TARGET_PATCH_ARCH:-$TARGET_ARCH}.conf" + + for cfg in $PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$pkg_linux_version/$config_name \ + $PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$LINUX/$config_name \ + $PROJECT_DIR/$PROJECT/devices/$DEVICE/linux/$config_name \ + $PROJECT_DIR/$PROJECT/linux/$pkg_linux_version/$config_name \ + $PROJECT_DIR/$PROJECT/linux/$LINUX/$config_name \ + $PROJECT_DIR/$PROJECT/linux/$config_name \ + $pkg_linux_dir/config/$pkg_linux_version/$config_name \ + $pkg_linux_dir/config/$LINUX/$config_name \ + $pkg_linux_dir/config/$config_name \ + ; do + [[ $cfg =~ /devices//linux/ ]] && continue + [ -f "$cfg" ] && echo "$cfg" && return + done + + die "ERROR: Unable to locate kernel config for ${LINUX} - looking for ${config_name}" +} + +kernel_make() { + ( + setup_pkg_config_host + + LDFLAGS="" make CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + ARCH="$TARGET_KERNEL_ARCH" \ + HOSTCC="$TOOLCHAIN/bin/host-gcc" \ + HOSTCXX="$TOOLCHAIN/bin/host-g++" \ + HOSTCFLAGS="$HOST_CFLAGS" \ + HOSTLDFLAGS="$HOST_LDFLAGS" \ + HOSTCXXFLAGS="$HOST_CXXFLAGS" \ + DEPMOD="$TOOLCHAIN/bin/depmod" \ + "$@" + ) +} + +# get kernel module dir +get_module_dir() { + if [ -n "${_CACHED_KERNEL_MODULE_DIR}" ]; then + echo "${_CACHED_KERNEL_MODULE_DIR}" + else + basename $(ls -d $(get_build_dir linux)/.install_pkg/usr/lib/kernel-overlays/base/lib/modules/*) + fi +} + +# get base path to kernel modules and firmware +get_kernel_overlay_dir() { + echo "usr/lib/kernel-overlays/${1:-base}" +} + +# get full path to kernel module dir +# optional parameter specifies overlay level (default is base) +get_full_module_dir() { + echo "$(get_kernel_overlay_dir $1)/lib/modules/$(get_module_dir)" +} + +# get full path to firmware dir +# optional parameter specifies overlay level (default is base) +get_full_firmware_dir() { + echo "$(get_kernel_overlay_dir $1)/lib/firmware" +} + +fix_module_depends() { + # modify .modinfo section in kernel module to depends on other required modules + local MODULE="$1" + local DEPENDS="$2" + local OLD_DEPENDS="" + cp ${MODULE} ${MODULE}_orig + $OBJDUMP -s -j .modinfo ${MODULE}_orig | awk 'BEGIN{v=0;} /Contents/ {v=1; next;} {if (v==1) print $0;}' >new.modinfo1 + cat new.modinfo1 | cut -c7-41 | awk '{printf($0);}' | sed 's/ //g;s/../\\\x&/g;' >new.modinfo2 + /bin/echo -ne `cat new.modinfo2` | tr '\000' '\n' >new.modinfo3 + cat new.modinfo3 | awk '/^depends=/ {next;} {print $0;}' | tr '\n' '\000' >new.modinfo + OLD_DEPENDS=$(awk '{FS="="} /depends=/ {print $2}' new.modinfo3) + [ -n "$OLD_DEPENDS" ] && DEPENDS="$OLD_DEPENDS,$DEPENDS" + /bin/echo -ne "depends=$DEPENDS\0" >>new.modinfo + $OBJCOPY --remove-section=.modinfo --add-section=.modinfo=new.modinfo --set-section-flags .modinfo=contents,alloc,load,readonly,data ${MODULE}_orig ${MODULE} + rm new.modinfo* +} + + +### ADDON HELPERS ### +install_binary_addon() { + local addon_id="$1" addon_so + + mkdir -p $ADDON_BUILD/$addon_id/ + cp -R $PKG_BUILD/.install_pkg/usr/share/$MEDIACENTER/addons/$addon_id/* $ADDON_BUILD/$addon_id/ + + addon_so=$(xmlstarlet sel -t -v "/addon/extension/@library_linux" $ADDON_BUILD/$addon_id/addon.xml || :) + if [ -n "$addon_so" ]; then + cp -L $PKG_BUILD/.install_pkg/usr/lib/$MEDIACENTER/addons/$addon_id/$addon_so $ADDON_BUILD/$addon_id/ + chmod +x $ADDON_BUILD/$addon_id/$addon_so + fi + + if [ -d $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id ] ; then + mkdir -p $ADDON_BUILD/$addon_id/kernel-overlay + cp -PR $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id/* $ADDON_BUILD/$addon_id/kernel-overlay + fi +} + +install_addon_source() { + if [ -d $PKG_DIR/source ]; then + cp -R $PKG_DIR/source/* "$1" + fi +} + +install_addon_images() { + local dest_dir="$1" + + if [ -f "$PKG_DIR/icon/icon.png" ]; then + mkdir -p "$dest_dir/resources" + cp "$PKG_DIR/icon/icon.png" "$dest_dir/resources" + fi + + if [ -f "$DISTRO_DIR/$DISTRO/addons/fanart.png" ]; then + mkdir -p "$dest_dir/resources" + cp "$DISTRO_DIR/$DISTRO/addons/fanart.png" "$dest_dir/resources" + fi +} + +create_addon_xml() { + local addon_xml addon_version addon_name provider_name requires requires_addonname requires_addonversion screenshots + local tmp_changelog + + addon_xml="$1/addon.xml" + + IFS=" " +for i in $PKG_ADDON_REQUIRES; do + requires_addonname=`echo $i | cut -f1 -d ":"` + requires_addonversion=`echo $i | cut -f2 -d ":"` + requires="$requires\n " +done + unset IFS + + if [ ! -f "$addon_xml" ] ; then + cp $ROOT/config/addon/${PKG_ADDON_TYPE}.xml "$addon_xml" + addon_version=${PKG_ADDON_VERSION:-${ADDON_VERSION}.${PKG_REV}} + else + if ! command -v xmlstarlet >/dev/null ; then + die "*** ERROR: $ADDON has addon.xml shipped, you need 'xmlstarlet' ***" "255" + fi + addon_version="${PKG_ADDON_VERSION:-$(xmlstarlet sel -t -v "/addon/@version" "$addon_xml").$PKG_REV}" + xmlstarlet ed --inplace -u "/addon[@version]/@version" -v "$addon_version" "$addon_xml" + fi + + if [ -f $PKG_DIR/changelog.txt ]; then + tmp_changelog="$(mktemp)" + cat ${PKG_DIR}/changelog.txt | xmlstarlet esc >"${tmp_changelog}" + sed -e "/@PKG_ADDON_NEWS@/ \ + { + r ${tmp_changelog} + d + }" -i "$addon_xml" + rm -f "${tmp_changelog}" + else + sed -e "s|@PKG_ADDON_NEWS@||g" -i "$addon_xml" + fi + + provider_name=${PKG_MAINTAINER:-"Team CoreELEC"} + addon_name=${PKG_ADDON_NAME:-"$PKG_NAME"} + + for f in $PKG_DIR/source/resources/screenshot-*.{jpg,png}; do + if [ -f "$f" ]; then + screenshots+="resources/$(basename $f)\n" + fi + done + + sed -e "s|@PKG_ADDON_ID@|$PKG_ADDON_ID|g" \ + -e "s|@ADDON_NAME@|$addon_name|g" \ + -e "s|@ADDON_VERSION@|$addon_version|g" \ + -e "s|@REQUIRES@|$requires|g" \ + -e "s|@PKG_SHORTDESC@|$PKG_SHORTDESC|g" \ + -e "s|@OS_VERSION@|$OS_VERSION|g" \ + -e "s|@PKG_LONGDESC@|$PKG_LONGDESC|g" \ + -e "s|@PKG_DISCLAIMER@|$PKG_DISCLAIMER|g" \ + -e "s|@PROVIDER_NAME@|$provider_name|g" \ + -e "s|@PKG_ADDON_PROVIDES@|$PKG_ADDON_PROVIDES|g" \ + -e "s|@PKG_ADDON_SCREENSHOT@|$screenshots|g" \ + -e "s|@PKG_ADDON_BROKEN@|$PKG_ADDON_BROKEN|g" \ + -i "$addon_xml" +} + +install_addon_files() { + mkdir -p "$1" + + install_addon_source "$1" + install_addon_images "$1" + create_addon_xml "$1" +} + +install_driver_addon_files() { + if [ "$#" -eq 0 ] ; then + die "$(print_color CLR_ERROR "no module search path defined")" + fi + + PKG_MODULE_DIR="$INSTALL/$(get_full_module_dir $PKG_ADDON_ID)/updates/$PKG_ADDON_ID" + PKG_ADDON_DIR="$INSTALL/usr/share/$MEDIACENTER/addons/$PKG_ADDON_ID" + + mkdir -p $PKG_MODULE_DIR + find $@ -name \*.ko -exec cp {} $PKG_MODULE_DIR \; + + find $PKG_MODULE_DIR -name \*.ko -exec ${TARGET_KERNEL_PREFIX}strip --strip-debug {} \; + + mkdir -p $PKG_ADDON_DIR + cp $PKG_DIR/changelog.txt $PKG_ADDON_DIR + install_addon_files "$PKG_ADDON_DIR" +} + + +### TARGET CONFIGURATION HELPERS ### +add_user() { + # Usage: add_user "username" "password" "userid" "groupid" "description" "home" "shell" + mkdir -p ${INSTALL}/etc + touch ${INSTALL}/etc/passwd + if ! grep -q "^$1:" ${INSTALL}/etc/passwd; then + echo "$1:x:$3:$4:$5:$6:$7" >> ${INSTALL}/etc/passwd + fi + + mkdir -p ${INSTALL}/usr/cache + touch ${INSTALL}/usr/cache/shadow + ln -sf /storage/.cache/shadow ${INSTALL}/etc/shadow 2>/dev/null || true + + PASSWORD="$2" + if [ "$PASSWORD" = "x" ]; then + PASSWORD="*" + fi + if ! grep -q "^$1:" ${INSTALL}/usr/cache/shadow; then + echo "$1:$PASSWORD:::::::" >> ${INSTALL}/usr/cache/shadow + fi +} + +add_group() { + # Usage: add_group "groupname" "groupid" ("members") + mkdir -p ${INSTALL}/etc + touch ${INSTALL}/etc/group + if [ -z "`grep "$1:" ${INSTALL}/etc/group`" ]; then + echo "$1:x:$2:$3" >> ${INSTALL}/etc/group + fi +} + +# Usage: enable_service [target] +enable_service() { + local unit="$1" + local unit_dir="/usr/lib/systemd/system" + local target="$2" + local target_dir=$INSTALL + + [ -f "$target_dir/$unit_dir/$unit" ] || die + if [ -z "$target" ] ; then + for target in `grep '^WantedBy' $target_dir/$unit_dir/$unit | cut -f2 -d=` ; do + if [ -n "$target" ]; then + mkdir -p ${target_dir}/$unit_dir/${target}.wants + ln -sf ../${unit} ${target_dir}/$unit_dir/${target}.wants/ + fi + done + fi + for target in `grep '^Alias' $target_dir/$unit_dir/$unit | cut -f2 -d=` ; do + if [ -n "$target" ]; then + ln -sf ${unit} ${target_dir}/$unit_dir/${target} + fi + done +} + + +### MULTI-THREADED FUNCTION HELPERS ### +# Test MTWITHLOCKS so that these functions are a no-op during non-multithreaded builds. + +# Prevent concurrent modifications to a package (unpack) or +# package:target (install/build). +# +# If a package is already locked and the owner is ourselves +# then assume we already have the required lock. +pkg_lock() { + [ "${MTWITHLOCKS}" != "yes" ] && return 0 + + local pkg="$1" task="$2" parent_pkg="$3" + local this_job="${MTJOBID}" + local lock_job lock_seq lock_task lock_pkg locked=no idwidth + local fail_seq + + exec 98>"${THREAD_CONTROL}/locks/${pkg}.${task}" + while [ : ]; do + read -r lock_job lock_seq lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/${pkg}.${task}.owner" 2>/dev/null) + [ -n "${lock_job}" ] && break + flock --wait 1 --exclusive 98 && locked=yes && break + done + + if [ "${locked}" = "no" -a "${lock_job}/${lock_seq}" != "${this_job}/${PARALLEL_SEQ}" ]; then + [ "${THREADCOUNT}" = "0" ] && idwidth=${#MTMAXJOBS} || idwidth=2 + pkg_lock_status "STALLED" "${parent_pkg}" "${task}" "$(printf "waiting on [%0*d] %s %s" ${idwidth} ${lock_job} "${lock_task}" "${lock_pkg}")" + flock --exclusive 98 + fi + + # As we now have the lock, if .failed still exists then a previous process must have failed + if [ -f "${THREAD_CONTROL}/locks/${pkg}.${task}.failed" ]; then + fail_seq="$(< "${THREAD_CONTROL}/locks/${pkg}.${task}.failed")" + print_color CLR_ERROR "FAILURE: ${pkg}.${task}.failed exists, a previous dependency process has failed (seq: ${fail_seq})\n" + if [ -d "${THREAD_CONTROL}/logs" ]; then +cat < [%0*d/%0*d] %-7s %-7s %-35s" \ + "$(date +%Y-%m-%d\ %H:%M:%S.%N)" $$ ${idwidth} ${this_job} ${#MTMAXJOBS} ${PARALLEL_SEQ:-0} "${status}" "${task}" "${pkg}" + [ -n "${msg}" ] && line+=" (${msg})" + + echo "${line}" >>"${THREAD_CONTROL}/history" + + if [ "${DASHBOARD}" != "no" ]; then + update_dashboard "${status}" "${pkg}" "${task}" "${msg}" + fi + ) 94>"${THREAD_CONTROL}/locks/.history" + + if [ "${status}" = "LOCKED" ]; then + echo "${PARALLEL_SEQ}" > "${THREAD_CONTROL}/locks/${pkg}.${task}.failed" + echo "${this_job} ${PARALLEL_SEQ} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/${pkg}.${task}.owner" + elif [ "${status}" = "UNLOCK" ]; then + rm -f "${THREAD_CONTROL}/locks/${pkg}.${task}.owner" || : # + rm -f "${THREAD_CONTROL}/locks/${pkg}.${task}.failed" || : # + fi + + return 0 +} + +update_dashboard() { + [ "${MTWITHLOCKS}" != "yes" ] && return 0 + + local status="$1" pkg="$2" task="$3" msg="$4" + local line sedline preamble num elapsed projdevarch + local boldred boldgreen boldyellow endcolor idwidth + + sedline=$((MTJOBID + 2)) + + [ "${THREADCOUNT}" = "0" ] && idwidth=${#MTMAXJOBS} || idwidth=2 + + num=$(< "${THREAD_CONTROL}/status.max") + if [ ${num} -lt ${sedline} ]; then + echo ${sedline} >"${THREAD_CONTROL}/status.max" + for i in $(seq $((num + 1)) ${sedline}); do echo "" >>"${THREAD_CONTROL}/status"; done + fi + + num=$(< "${THREAD_CONTROL}/progress.prev") + projdevarch="${PROJECT}/" + [ -n "${DEVICE}" ] && projdevarch+="${DEVICE}/" + projdevarch+="${TARGET_ARCH}" + [ -n "${BUILD_SUFFIX}" ] && projdevarch+=", ${BUILD_SUFFIX}" + TZ=UTC0 printf -v elapsed "%(%H:%M:%S)T" $(($(date +%s) - MTBUILDSTART)) + printf -v preamble "%s Dashboard (%s) - %d of %d jobs completed, %s elapsed" "${DISTRONAME}" "${projdevarch}" $((num + 1)) ${MTMAXJOBS} "${elapsed}" + printf -v preamble "%b%-105s %s" "\e[2J\e[0;0H" "${preamble//\//\\/}" "$(date "+%Y-%m-%d %H:%M:%S")" + + if [ "${DISABLE_COLORS}" != "yes" ]; then + boldred="\e[1;31m" + boldgreen="\e[1;32m" + boldyellow="\e[1;33m" + white="\e[0;37m" + endcolor="\e[0m" + + case "${status}" in + IDLE) color="${white}";; + STALLED) color="${boldyellow}";; + MUTEX/W) color="${boldyellow}";; + FAILED ) color="${boldred}";; + *) color="${boldgreen}";; + esac + fi + + printf -v line "[%0*d\/%0*d] %b%-7s%b %-7s %-35s" ${idwidth} ${MTJOBID} ${#MTMAXJOBS} ${PARALLEL_SEQ:-0} "${color}" "${status//\//\\/}" "${endcolor}" "${task}" "${pkg}" + [ -n "${msg}" ] && line+=" ${msg//\//\\/}" + + sed -e "1s/.*/${preamble}/;${sedline}s/.*/${line}/" -i "${THREAD_CONTROL}/status" +} + +# Thread concurrency helpers to avoid concurrency issues with some code, +# eg. when Python installs directly into $TOOLCHAIN. +acquire_exclusive_lock() { + [ "${MTWITHLOCKS}" != "yes" ] && return 0 + + local pkg="$1" task="$2" lockfile="${3:-global}" + local this_job="${MTJOBID}" + local lock_job lock_seq lock_task lock_pkg locked=no idwidth + + exec 96>"${THREAD_CONTROL}/locks/.mutex.${lockfile}" + while [ : ]; do + read -r lock_job lock_seq lock_task lock_pkg <<<$(cat "${THREAD_CONTROL}/locks/.mutex.${lockfile}.owner" 2>/dev/null) + [ -n "${lock_job}" ] && break + flock --wait 1 --exclusive 96 && locked=yes && break + done + + if [ "${locked}" = "no" -a "${lock_job}/${lock_seq}" != "${this_job}/${PARALLEL_SEQ}" ]; then + [ "${THREADCOUNT}" = "0" ] && idwidth=${#MTMAXJOBS} || idwidth=2 + pkg_lock_status "MUTEX/W" "${pkg}" "${task}" "$(printf "mutex: %s; waiting on [%0*d] %s %s" "${lockfile}" ${idwidth} ${lock_job} "${lock_task}" "${lock_pkg}")" + flock --exclusive 96 + fi + + pkg_lock_status "MUTEX" "${pkg}" "${task}" "mutex: ${lockfile}" + + echo "${this_job} ${PARALLEL_SEQ} ${task} ${pkg}" >"${THREAD_CONTROL}/locks/.mutex.${lockfile}.owner" +} + +release_exclusive_lock() { + [ "${MTWITHLOCKS}" != "yes" ] && return 0 + + local pkg="$1" task="$2" lockfile="${3:-global}" + + pkg_lock_status "ACTIVE" "${pkg}" "${task}" + + rm -f "${THREAD_CONTROL}/locks/.mutex.${lockfile}.owner" || : # + flock --unlock 96 2>/dev/null +} + +# Execute single command using mutex +exec_thread_safe() { + local result + acquire_exclusive_lock "${PKG_NAME:exec}" "execcmd" + $@ + result=$? + release_exclusive_lock "${PKG_NAME:exec}" "execcmd" + return ${result} +} + +# Use distribution functions if any +if [ -f "distributions/$DISTRO/config/functions" ]; then + . distributions/$DISTRO/config/functions +fi diff --git a/config/graphic b/config/graphic new file mode 100644 index 000000000..f80b3c7c3 --- /dev/null +++ b/config/graphic @@ -0,0 +1,130 @@ +if [ "${OPENGL}" = no ]; then + OPENGL_SUPPORT="no" +else + OPENGL_SUPPORT="yes" +fi + +if [ "${OPENGLES}" = no ]; then + OPENGLES_SUPPORT="no" +else + OPENGLES_SUPPORT="yes" +fi + +get_graphicdrivers() { + + # set defaults + GALLIUM_DRIVERS="" + DRI_DRIVERS="" + XORG_DRIVERS="" + LLVM_SUPPORT="no" + COMPOSITE_SUPPORT="no" + VDPAU_SUPPORT="no" + VAAPI_SUPPORT="no" + V4L2_SUPPORT="no" + + if [ "${GRAPHIC_DRIVERS}" = "all" ]; then + GRAPHIC_DRIVERS="i915 i965 r200 r300 r600 radeonsi nvidia nvidia-legacy vmware virtio vc4" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "etnaviv"; then + GALLIUM_DRIVERS+=" etnaviv imx" + V4L2_SUPPORT="yes" + VAAPI_SUPPORT="no" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "freedreno"; then + GALLIUM_DRIVERS+=" freedreno" + V4L2_SUPPORT="yes" + VAAPI_SUPPORT="no" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "i915"; then + DRI_DRIVERS+=" i915" + XORG_DRIVERS+=" intel" + COMPOSITE_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "i965"; then + DRI_DRIVERS+=" i965" + XORG_DRIVERS+=" intel" + COMPOSITE_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "lima"; then + GALLIUM_DRIVERS+=" kmsro lima" + V4L2_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "nvidia"; then + XORG_DRIVERS+=" nvidia" + VDPAU_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "nvidia-legacy"; then + XORG_DRIVERS+=" nvidia-legacy" + VDPAU_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "panfrost"; then + GALLIUM_DRIVERS+=" kmsro panfrost" + V4L2_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "r200"; then + DRI_DRIVERS+=" r200" + XORG_DRIVERS+=" ati" + COMPOSITE_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "r300"; then + GALLIUM_DRIVERS+=" r300" + XORG_DRIVERS+=" ati" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "r600"; then + GALLIUM_DRIVERS+=" r600" + XORG_DRIVERS+=" ati" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "radeonsi"; then + GALLIUM_DRIVERS+=" radeonsi" + XORG_DRIVERS+=" ati amdgpu" + LLVM_SUPPORT="yes" + COMPOSITE_SUPPORT="yes" + VDPAU_SUPPORT="yes" + VAAPI_SUPPORT="yes" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "vc4"; then + GALLIUM_DRIVERS+=" vc4 v3d kmsro" + V4L2_SUPPORT="yes" + VAAPI_SUPPORT="no" + VDPAU_SUPPORT="no" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "virtio"; then + GALLIUM_DRIVERS+=" virgl" + fi + + if listcontains "${GRAPHIC_DRIVERS}" "vmware"; then + GALLIUM_DRIVERS+=" svga" + XORG_DRIVERS+=" vmware" + COMPOSITE_SUPPORT="yes" + fi + + # remove duplicate entries + GALLIUM_DRIVERS="$(echo ${GALLIUM_DRIVERS} | xargs -n1 | sort -u | xargs)" + XORG_DRIVERS="$(echo ${XORG_DRIVERS} | xargs -n1 | sort -u | xargs)" + DRI_DRIVERS="$(echo ${DRI_DRIVERS} | xargs -n1 | sort -u | xargs)" +} diff --git a/config/multithread b/config/multithread new file mode 100644 index 000000000..4d7e848fd --- /dev/null +++ b/config/multithread @@ -0,0 +1,165 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +THREADCOUNT=${THREADCOUNT:-100%} + +# This function is passed a list of package.mk paths to be processed. +# Each package.mk is sourced with relevant variables output in JSON format. +json_worker() { + local packages="$@" + local pkgpath hierarchy exited + + exit() { exited=1; } + + . config/options "" + + for pkgpath in ${packages}; do + pkgpath="${pkgpath%%@*}" + + exited=0 + if ! source_package "${pkgpath}/package.mk" &>/dev/null; then + unset -f exit + die "$(print_color CLR_ERROR "FAILURE: sourcing package ${pkgpath}/package.mk")" + fi + + [ ${exited} -eq 1 ] && continue + + [[ ${pkgpath} =~ ^${ROOT}/${PACKAGES}/ ]] && hierarchy="global" || hierarchy="local" + + cat <" or "install ". +# ${slot} is the job slot number, ie. 1-8 when THREADCOUNT=8. +# ${job} is the sequence within the total number of ${jobs}. +package_worker() { + local slot=$1 job=$2 jobs=$3 args="$4" + local task pkgname result status + local addon istarget isaddon + + export MTJOBID=${slot} MTMAXJOBS=${jobs} + + read -r task pkgname <<< "${args}" + + . config/options "${pkgname}" + + [ ! -f "${THREAD_CONTROL}/parallel.pid" ] && echo "${PARALLEL_PID}" >"${THREAD_CONTROL}/parallel.pid" + + ${SCRIPTS}/${task} ${pkgname} 2>&1 && result=0 || result=1 + + [[ ${pkgname} =~ :target$ || "${pkgname//:/}" = "${pkgname}" ]] && istarget="yes" || istarget="no" + + [[ "${MTADDONBUILD}" = "yes" && ( "${PKG_IS_ADDON}" = "yes" || "${PKG_IS_ADDON}" = "embedded" ) ]] && isaddon="yes" || isaddon="no" + + if [ "${isaddon}" = "yes" -a "${istarget}" = "yes" ]; then + if [ ${result} -eq 0 ]; then + ${SCRIPTS}/install_addon ${pkgname} 2>&1 && result=0 || result=1 + fi + + if [ ${result} -ne 0 ]; then + if [ -d "${THREAD_CONTROL}/logs" ]; then + echo "${PKG_NAME} ${THREAD_CONTROL}/logs/${job}/stdout" >>"${THREAD_CONTROL}/addons.failed" + else + echo "${PKG_NAME}" >>"${THREAD_CONTROL}/addons.failed" + fi + fi + fi + + ( + flock --exclusive 95 + [ ${result} -eq 0 ] && status="DONE" || status="FAIL" + num=$(< "${THREAD_CONTROL}/progress") + mv "${THREAD_CONTROL}/progress" "${THREAD_CONTROL}/progress.prev" + num=$((num + 1)) + echo ${num} >"${THREAD_CONTROL}/progress" + printf "[%0*d/%0*d] [%-4s] %-7s %s\n" ${#jobs} ${num} ${#jobs} ${jobs} "${status}" "${task}" "${pkgname}" >&2 + ) 95>"${THREAD_CONTROL}/locks/.progress" + + if [ ${result} -eq 0 ]; then + pkg_lock_status "IDLE" + else + pkg_lock_status "FAILED" "${pkgname}" "${task}" + + print_color CLR_ERROR "FAILURE: $SCRIPTS/${task} ${pkgname} has failed!\n" + + if [ -d "${THREAD_CONTROL}/logs" ]; then + cat >&2 <"${THREAD_CONTROL}/progress.prev" + echo 0 >"${THREAD_CONTROL}/progress" + echo 0 >"${THREAD_CONTROL}/status.max" + touch "${THREAD_CONTROL}/status" + + # Increase file descriptors if building one thread/package + [ "${THREADCOUNT}" = "0" ] && ulimit -n ${ULIMITN:-10240} + + # Bootstrap GNU parallel + MTWITHLOCKS=no $SCRIPTS/build parallel:host 2>&1 || die "Unable to bootstrap parallel package" + + # determine number of available slots for the given THREADCOUNT - optimise logging for single threaded builds + [ $(seq 1 32 | ${TOOLCHAIN}/bin/parallel --plain --no-notice --max-procs ${THREADCOUNT} echo {%} | sort -n | tail -1) -eq 1 ] && singlethread=yes || singlethread=no + + # create a single log file by default for a single threaded build (or the builder is a masochist) + if [ "${singlethread}" = "yes" -a "${ONELOG,,}" != "no" ] || [ "${ONELOG,,}" = "yes" ]; then + buildopts+=" --ungroup" + else + mkdir -p "${THREAD_CONTROL}/logs" + buildopts+=" --group --results ${THREAD_CONTROL}/logs/{#}/" + fi + + # When building addons, don't halt on error - keep building all packages/addons + [ "${MTADDONBUILD}" = "yes" ] && buildopts+=" --halt never" || buildopts+=" --halt now,fail=1" + + # pipefail: return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status + set -o pipefail + + cat ${_CACHE_PACKAGE_GLOBAL} ${_CACHE_PACKAGE_LOCAL} | \ + ${TOOLCHAIN}/bin/parallel --plain --no-notice --max-args 30 --halt now,fail=1 json_worker | \ + ${SCRIPTS}/genbuildplan.py --no-reorder --show-wants --build ${@} > "${THREAD_CONTROL}"/plan || result=1 + + if [ ${result} -eq 0 ]; then + save_build_config + + cat "${THREAD_CONTROL}"/plan | awk '{print $1 " " $2}' | \ + MTBUILDSTART=$(date +%s) MTWITHLOCKS=yes ${TOOLCHAIN}/bin/parallel \ + --plain --no-notice --max-procs ${THREADCOUNT} --joblog="${THREAD_CONTROL}/joblog" --plus ${buildopts} \ + package_worker {%} {#} {##} {} || result=1 + + rm -f "${THREAD_CONTROL}/parallel.pid" + fi + + set +o pipefail + + return ${result} +} diff --git a/config/noobs/marketing/slides/A.png b/config/noobs/marketing/slides/A.png new file mode 100644 index 0000000000000000000000000000000000000000..0925fbdff8a47f0e0efb34a1cea2553dccb888a9 GIT binary patch literal 32028 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
UC4`_HoQrQ8a0Iw`i4#lr*j-F8nChIc^({w=)1 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 literal 0 HcmV?d00001 diff --git a/config/noobs/marketing/slides/C.png b/config/noobs/marketing/slides/C.png new file mode 100644 index 0000000000000000000000000000000000000000..2882069a801039d7686d9141f72e009ed31280ed GIT binary patch literal 36963 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 XOs(bn?H_`>hbSwkKdpFT`RacFA{H__ literal 0 HcmV?d00001 diff --git a/config/noobs/marketing/slides/E.png b/config/noobs/marketing/slides/E.png new file mode 100644 index 0000000000000000000000000000000000000000..a993980af42314bc117dff3fa747b7bf0e505549 GIT binary patch literal 32845 zcmeFZbySqy`!76TAflk4A|W6l-O{Nvh#(*#E#2KQmJ>!vKk1) zY4{dj_Z&X_<>q?I9sZ(lm(z9Ebh32!GIg~;+%b20Y(b~wU}|NdVPR_SVlem-2QtHM6sDr+aK+W#cG8zg~l)r?WAapw|&l z1RJ+)`9SR{r06!A}zO*6!}kqTJkGUS3>Y{9I11R@}TIA|l*8 zeB69|obV1#Hy=lLQ*Ta3H-`UQLDs^}%+F&8!E<2Ms}EO47s=rK$i zpV@6bPGJFy$D9`Y`~v2D{6fO~7LWgPo&WCh{Bp7acjaaIc=&nbczNXnMegwP%ik5c zEhBg5ww#P0|9?KKS$*1pL^TDz5o3z@Bi_$qB5=)rtVIzT24;(|JeoV)=utD zZq`oDbTXO(T)cFure-#dxL0tC^v^TPTDaPHTA0hbIyun&on=v*|7HX{A~HO@vVy!k za(q03!o0k~!ZL!wvhs3#0>T19{C5TD|NX4_|Lx3i!+^MP+vI=QHvf4E_9E`v{|W;5 z;lIMj!VzM}6@sMg;M*ev!rx6v_KueK@X8p0_m$a!hRvPl&!t(E&fSP1){u#f2zrsJ zNOorJq13L?;^`v92UfwEM+FzJW`t=Gg`Q`tJEurgw@-E8@N&-u(Sa_xBZPT*g2I;nD{JLHPG8 z>EEx6f4~0kANb#2`Ty)CSkAyR{=azi|ECB2|1a@B_f630e`e$Va(Df&Qw*1wWKt-k z5sUX-b3K}!44Qm=CN%ani(aiXFE?#($IMDDL8+!1+TzpE3)w@3m>q8S3S$!%av}r* zws66Shs(ZDaQ#>yrYk0KuurH>HqPb>`NV9&{RbZ&7ztf zlOOnO;?!EmBx957r_a(<~)JE7Cf4KjJbRyYEd*NE;%aQYlp&To|0i_*maMX)a zY?72($UI}|bMf$a@Q1j4qGqy9qVzSlajo=b)aLixYxz?{3&@jSE8B_Tg{0~q{M4Uq z2IAc@Q2+Zpzauag%Z`g@y1z)@A46mPh^6)E{`rT!{`x|uqpm%-*iP1QHKWU&=)h++JH9*oUOAEO&e7)dj3VqO06;n=m431PcXOtQ_P852SFMo|^# zB@x&RkUaVpCNkorwB3T9pZz}8bB#r8SF36GCX#ApVwO71zas5yNZA>DT=WIC)Ychy z4D&aa$4SM7lC#8Jk`fQ@!n@avt^UAOaafO<4=A$#G-Ky{quqW26-S#`<7bfaP zZkM0=ELHZ1m)s2z?{^~l6R*`vp#03#KLcpEv78%Vj4bxcWd33R^YdVn!N8hmrU}O6 z8gxGLUGtgqvpuJ9t2OE}w|Zhbmok(xQcvXYq}>d2!9#e^>AqXgS+aMu@HC`|$X20GyGm%o;rob=+Ku}Z}dAq z|2~hPallPZ8t0{d-t^e9=U7k4&DAaP2hkO(ZWGq<)_|EfF^GzgIdCBs^il+bCa{7`WX~;TF`V znK_RbPq`$WdMakwJcTxB9<~OQ()w0reN5x)P}&c6xY_0@KSLQE;F1_Qi}-hgZ#*PD zQo*0p48B4|Blhv@FE%-LD!t!**Q{6RQXvRaP5uU<@!QpS3BRtxt!7 z5rt!Dug|lQ<DJ(sDD@b&wwaXVM~gPqk6OEY8;;2Iy&=0b02|=t=a~H z=3~~&mlJ=PcoU~%M?@OJw<+vW_kYYIHp!0hzh?*jedMZE0(fM|Y>gytp9c${;RfOp z7{nlP;VEzzMDBOwqP#~yeM8FR3+vokQrNKRrfm?xGIu87nm zhSy)D|G6mn33|K^OM1DOf$~DG!KdhxAC6`)Z7Ee&d&hM|{!7`9znRH5k$7D{$;!yc$jZ{Mr=_MgNR!4xB9VT~j=sb^ z?eoLm|Rfqeh2vUey+=dM0Iy{CEYbezs&mp>heLaW?nECiJKcoJ$vDmns=>OD)Bqz(7Q@3YTIUt`hBWCKaPq zQbiei4Nw;qv_h-J=DSg3B0)|OL|XNUtOOe*wdqSUV(Yd1&Xdw&L}j-9wu?O(QBhI; zfp`#yL2jM~zePM(5A^ja{O8}?n?7kK@iN<4mnEKj8}RfQp%LPEl7q5bs<0YtGFrKU3fZ-{wrPRXryx9;oy`SzkM zhPAiSWqKfAe=z&OcaswWMMRL;@K9fA4n>ZnE04=%Ceo>3KdvJ$dV+J@6n!gF6m|sY zR=1#)c0eq(CG#&YQqhQe|N8To=o-gDPexeHV|6hzQ5&V&cX4q|S--8*wATNxnUSKg(}_%~3pMKE=;*AWx5mv)>qbQf||m*=ckx|L2G3-Q~e5w|U$C&kqvtV7Fz??3mMvME`c~wKpbK zIBqw^?UPH_ZuHG?(%KTm1pZ*Ji7jdU`ICpVyoP_`Lu}^$_1Y^ie$i1=vDUD;-uYc7F{V4>GI*e^T}REd#hs3lMT^KDjKPHobr)p9f=4xLS9~i znYm|%@y;AW<+I3svBU-sjb2+&#ZK+|PidU-wPI99pD>BvWMRoxj%AaNE0YiY5nnP?GPvYDeAdm{V6f=$1_l-TXlobO8YTDQb* zr($Z3*$*`|*&1afLLafDkY9Iq-bp#O;hmQy5J;Yj{UVJq?S4}Ja@2+&FP_Wr5k7fH z=%aGmj0j4KD_69tTxYFPeCD!J1DE=9$!U#dJQ5NTxa$u-nwQdywZUtt{#z|EF;~u0 zdkM?q;bTZ?u1J0wPg9~Yl1Pd6iwuc1Le*b7$rTAooj$~S{FD-vP#mc17(p~ctIbi= zZHI}vy4LWX;@UMq^Pg{!nC(=BNE+4q_d9?7eD(VE>xc+0{VyD}`ZFY{fk%sdIht;! z3Xqg(gd9f`o$8emo}ETCIAolUqaJf^v`ZWpcipuvkj1*BQxfkdFHD3`)78qV_u4=J z&T0@}(h%ms#0HUetj)CQWvhRHN8G$Ahbe`Kg5{|aAC4>?_g&6E+FjmX>}vVlb^J4v0dR>f7Xo>6m|K1 zjiqRlYH0bTdFsSU&h$A>%D#>Mpvr4nDkOv#YR9tZ1q60su7inhDBr&iVdrjbZC(8M z2R#GBI&6lgXNcrwWxbCSxr}Nnt-5GLUIqmrLat0tO+kVuyLvT)=EG%JHP_?C#YHi% zHF3AO*TKBGe)O=hW(&e&SQ)tv;~%BAB@f7l&Jj zW!c*IW~!q1*Nstu0Xb}2orl}=(NRV`OHB8T|r_GhJKbXOe@q@Z|<70uC?Pa9??=r9T%_|+aFFpCN{Ap z+R>gnx~w-pP~$f7K@N5djrzyKWCKFv(P9=Bjl#NB>Oz*@Um2Pn=CbTe5`hI4`(B`O zWZ=b_YqrhxANNj&_yt-y|fkQu$*~_6rSbEUVs8_v=`O zgoMCM6qgH#;3|NU-Vm+0Bqygs{t%T@?M)@QyLX>{^>3;-u&Y{QSgE++elvhCdWsF6 zhR3RtT7Oad!`&C31_YeOk8`q8L|vwy&*Jyz>L6Fk2Wk8_?gWk@ju41F7KbOTlF#J4%*7hdTLZc#r*4CFb+fv2Ej`mBt&A(|ty)+zu@m%>Vv!Sw*Qk4A% zNUjjdIVVi)4?mkDpL`D{X~XvR_NE5x>4mi9$zvbQw#JrvY+w(XrG~#au)BQN%t>b? z)2(*TnL$JoZg9>U!dnx*zNQxx+3mR>0ehg-s_Tor(e6)%NX1aa9TLFhFJmG& zVlPSM8Qc_lU7`Egqy-pq0BSZeS48?Aqy#+P@UbG)CgfA|>?6nvDz-k=EU8Xeyj{HlV{6J-(xwHQus{*?#`#d$3xnJWCX4AVrfi%`=K6{Z8w{^Otu;LjPVao2a-_Ton@si=jcx^?7*4OBC%3E3- z1~((+vG->XnUY_74Z85|hMg8ny4yxO5g!{XVE?;lb)-W7WRR3eSyn+|MDGNu1f_s& z%vTql_3CA=UB`mQumK{aFqQgeBVvxk9Y=)+Q*P1)2VzgWo~#qp!|>-}2pY5+~Ro;-vgN!>KcjpU`ydlYCifJ9K7d z2G&Ub21@R+0Q%XULAAS0TO8+EFRglipVi;VfDq%Hf0rI~S3;S-EU zUHbJ{4BDywuxaZgEsZWX-IFpa8LK;m0Zg{GHQVMW9tIm{wk^I!{GA#^(^_^I&9!TD zajVo~o+}5N)ADhzBO{q32u8z9rSaxt*mP~pk6#T6p?ri7Up;xD()x{<;Bu=>H|qVV z1B!RFbd^I$zJZIKqIM?szutUk@-bBe0*nwr~MA`rALkK>!`*$El#H#!;%j{(I_s+S&tw$ zO`uR*-`)m|FRZJpzoGt~{UF_TATK8X`Tga^uxp$e^TI01%12ANh18C#z|^|sv7vrz zRauHr^yFLyMLG{wBlOQ#@N1OEn1^hl@%FQ3ui#CV;8Ivq0Xn$wG`B(__E-KfE#rSHR#f%aBMsD{1)xqAEdt%nmO_4tDe z*Lfzxxa)t(VLv`dm&a|7jX&RG58aX1e8bIr!a=H<7T zAO!ktD;_`&SN)u)ObSBx)Txf**>siBJrT8m>&9MO+Raao^(&3(ZWR?<+N&!O-s42R zfAFHVv$K4;KQ}%KJw-rF?d+q7dH3!e(0rvgR(5zEJNrJ{b0XPh7)-#?4y$@v(5zI) zdx190iKX6PCvO9p<7lO+d2vxuQFb;J*Qv^`u7`su&#U9Jr(}bQNxPFPKk?)oBN=q97QiDd9u?BQ8jPQ5GlU( zN>uO3opQUu&YFjJiR%MTj_&7^Ubflow zH-JG4mAvCFyW*-087&ZVI3G+KC_JC&DlDNV`S$($rMT6`A3ugtWev(9gn=q6hus|Dh%sQfwbnzL#OX zYmivaFfogG`4LN`Qy89TwlPrObL|y%0|5nfZm~g?Yl_%Q`_d%)n>;)`qM}D3%qhBG z?1!Krr}{3jo;}&AhH4ByQR(q14XG8CNu= zooZ$y`yYA}PuelA2=W=Jnwx+6dh>>1fvbE|LVq;dqZ0ELTnY!p5)ucgB#orMchhSM z5{VskE|P;&iJJ=2()o|dFK``qE6`SnyGLg+=ODJ|A@Jo_1uKqS*p77Ef|>`!XvkUA zb_fNBx2(R^>W>hM)oiZBPz~PdWIuRJGDon1!`qURweRyyO(9a0(IBaA(jQlW!38>Ybfu zu^Ll1GIuU#ryHX zuMeP*#>WF2P`r2VQv;3-u=Ku@S~dVHO(}tvjyr{9}4P3xLNXG^3-(y)?!vFX5%}_?6ZMPRjQ%1t^Sy}I8P{rgq!gkdah9A z+OG2R@j-#m0x3n*V`-xo2W|ydD<50eBFSBYAQM^%5$4B}yCPuc-D-C;+bMJuWO8ww zX_I(LrPV6ae~Y>I?vEcoeEwK93`?g9IgQ^_ROI11m3!Ls=FOWal0Sd_`b9wFE$yW? z_!(I07!rGut`NC4QsLz8UbbeemLh%#bEUL`{y}ccLL#JHV8EK?vp-g_FDB)+mejU9 zXC9cF)OWirns@Deg59!FmFthKgy_>dFtbYc?+ex^b6RfIG15{X`B{~M(@&CwU8aVt zQe(^FI&UIWgAmJ}Ribl|U#Zj7jKKSB^v145V6Fm2FZ2(v>&1wD8la$dpQ!U(8}&Ip za48Qnx3tVW-3TxX4ea4Yfqt2FH_SSlSA-_M?=zJYDP$mQ+vo&{88pDd1YWZyzx6sH z``zAJdpl;guu zIEN@ncaRj}dILFVdVbcqotB}bFf;RBlGnUA!Os8ypdg3E3m^2VNsWDRNc_5h0_B=i zZg%*Nyu7^R;mq5VbHgB5$8j6q7ufg+DRHqki;9-?b}-~%hN~%$2?!BE*cbS$nMSCZ zLd)6CHAaGkML&_C4+~iTlKDp%-4?uP&BD5)a{ZUrpZW!gdjWRx>aRcJM*vLge%4}br3O3xUcqQ9P0`mAFlxoD zJMjdKw_>RqtlLsUw%s^kdV5t^2XA$BiMvFFE)l`twinVP=eF+4+`XH5Kl%Mz;+iiU zdL_^GzZnhI`fLL9R_r;hktOW~>$v?Bp>4li z`t;9uxbW%7nWwawsvnoP8)UJcz`wYps-P zO#km{X@us?cI|yP;>duyNFf&KV>Ot9+?w3t$}9K{0S|g@V`F3G^2Qp_KoIllH@*=$ zCJ_ykYdZc)`wH^NK|6n!?hWmpA@{p?zZ(Z0W&qcgbp5ejcJk;v2?;H~Wjm}a@RaLR zREcjTpq#pa_E?gGcj~M+uiY8{i?nAaznJBWJL!IGzbwc+*nC#NdtJ)nxb}6jLY+RQ@PgU@w_OJUiqVVIm)5x!P6O5I^SeslDpr^=N^|QgMV`O#d#(3 zQOH-2nA3o1c1n8Tj4nRoycHGCnDpm7>~>hpN%WuNgXu`-`$@u3T0m$sU$6dQ&aEK} zN*ny-I8lEB2$vfjM+22a53 z4_;(mBQ_)S%wWEv$C3A2~(ht<)%)w!J$CzZK?GF*LSYIux)Fo2JsQ@DQST+!p>g2ZXB zv8^1L&)5G*RoLhfH=p4X9Y;=$zBX+3U)qrw87JedO+@ORizWN(sh`Yf@_IIRwD|e6 z6Rc_FUtb4i{sb>pZechR=Pr1{82PE@eI*5gIezg0Ye{Tf`Jcf za>U{Miog@!T?=saWJn|!X@kXmMVljOQ^BtR39B*+rC%q z#0_b5p@u=rWb)nMlZk2% zb`cT10E+9^bw4Ra8T?+amCV1v^f1xo7z?%H$@D=y1 znHFZXl)n0e_wRihIk>pEyhsruTaaCkdaq*c$jSg;4l`>A`3Wd~j0{MfqY8)URv=77_nc1O$B>`;dmct@X-VmHAhpvct zM`>zFV8qh97Qmj9MBK`{vA;gZWJvdUF{UABV|Cbod0O5v4%qF7oXhQkT1(#npx@ls zD8BdG47B&bRjpP}SQ*a<<-HzgN&rBnqj9cn<^$}eVK4J_|Jyk7SR8M6+RDNT-RFkr zJx18|&Ixqb5Wn%*Q*J$-YJbT8DQvw0Jt+6~$&)Akx?8-2)KHMjR#zR8p)k;hx?A^U zKM=6(`&BOmt`woELq3z<*U>7s!8|<%7h7=8^D|j=3JiwI?c(>6U1wVb>;~=)oWLl< zKneO{uU8loQqZaLt{@yEhYCFDTfjnJjZ@w30Okbk;IIl80#X8#x&ox6AYkIp_jb_i zmDzUNxKWC1Od{{ro;;)eWUj7df+J^qo%~V+8{5TSq!lzv{R&kQhlKMU;2HpXU!_X^ z-kPr$1%dplzu4E{W5E6Ewc8Qjjog3`;i^9X?Hgod>9wV1S zv<=Grf+jC%2Z#!HU$d(Jo*WhRhe!^D%1j6Yn+co#&#|&Iw$9jA_QHjpQ@NI1DL1ZO z?a$FJYa}Fa6JDW6eChgRYGrTmF#e7Dl#|~_WmR0|XR0Lz*Vm@& zubxyCQt_4%b)!!6g5Mqr8y;-i?<1+ErlwpgQxJS5@gR+XsiJ#P)Pr#^c3~BS2&g>T zRJL|Z%*-kcY`IrBba}YAI%P6qQc}1~Egn63-xyZHz+m;^_IV&OebDX^c7^qEk;nl+ zP8_=n!$7cc$T9m(08qUWwl^GbI2#YT?>7HF=^^kWcm20lGwv}y{0-7wwW`QF=p+~) zU?C+<~p3TyQ55D2I>QrpG!mfQUv@gf*CTlBvsz6oF z9Cd=;*P*pm#9R7^6tQSA{p3q4>aI9gZ3E6GND;B$i>eDDWweEoPPN&zhC-G7g;@p! zVb_=4U2dlnSc;oN38T+6NeQ$14o@Q9jo^3KOr@z6Ngher(X3Alenf)D*m-Eus1~9K z5f$EUfGb^b;g+EKf$!PGzT^b;jXzU{69@1bzDT6qhi7qmGp_Wbqkb}H_snK zj==!2m`&y5=eID%bxeVhEbARN5>FQMMrTS<S%Wet?c=UWyvOQoo zodO>uZO7p^3W>E!4anqTJ#0$5^UOVqt{LUI`lyB1oSXDaYiJ2W2syh}Hr-d_WKj?I zd~AQ6Jy0IdDS}C8<0f?nqIs&JX`waWUF=ii%xL+#qCYDWo!rfv>rfV;g@JR{|0)<0 z;=Vi9(7f@9I)WBEl9i|Q_Li$?$;T`89HoFa0O+cYW9Ox?tQodNPnE{5i+SdWZtsKT zk|S6eH5Pzgt%!c~b2oNJhE%+&9(?tc(W+7{K@Xy6{5ten%~Bg6rqh_biQ(Vxse z4U}7VPZc-Q@Egr%siktc)E;Rp_49X$r|;PcLod+hhq+~KZL!LVif`zn!|1D8AyHM> z^xkqH#Ra-~xA;&t+H4T-Y{(A){{v(;5=G;K-tBiVu|~Esuep7i zR#iZPfM@&~%ksB}#`gOY^^T1j1&7n)s75PD(GQJn(JRW687IsRGB3c7)tpi!d|77t z<`}s?UI(cy{q*fb2NUrP555VvQH_(HRuO00Og&u>#p&UA%&%3z z^S`(<$Hn7T?ZOlX1+;rk4TUAW+EcYKpkyT=q-RR=-}p*^-7Q4wrPSw%xlGBHqjT~+ zph7~O0L5QkTrFWLEyag7&hjR zq%UtWF2!*fvI(fyogTIxzu966vge0@EI`e}4?-9hd-jfEe;cwr8`giswFz~J$@G_J zGzNe#lThg}!`*SMBbuL8z-)HbCyXUsqW7|iep3E|Q9kSGq88aBzrp6 z?keBPw4JE0kkluXq0tiS3(?`xjrwvP zf?RPmT)oKT&Z@N>Btxxqq#Pjm@RdhgapvTumK{BoDPCh9gF$$w`r^SAtA3;d%`uZank+sc5D23G+3j6bRx*+MhDXKVKWCKJ z^|7x$VOjV{mLAiAlH2Y4(I(b1J`O*~G=wsHBEf#A^m!KcXb@%ZQJ4Q9{bi3K9|uRf_6mBr5M{gm4Wey=HDm8_URe(3r`pjHDoX)Qp?-3-1 zGSmT})Lm17q72-pRS+tDgD+6@fEdZNaGURxjH2RCxXLhiVo(+9zgnerG>TlcmKZ2A0#KWLtj6`Vf)C%$+!3@WXFrEykqSly zG#pXUY8{s|UthEpk&+%rXsZ{VvZ@)r{7h`@PdAEmdBJfU3s{;|Sb63K6%~6__4DB` z^0JrJ#5Wry_D9XE(4-}H>CQuWrx#i|b;r)JX*UPv7^CWY#APrnzyN%+NljQ~dRK-@ z=fP=T+H!4&da8k0>rM~$94t8o2iYTB;=*vHOZuJ#sQ5`89V(G6Tr|I zZ$m0>}rPW(?ebyxCD~GzOJQyY|u`gJ$Q6Vk@%OJ!*DebQq|wg_Hg=H zHxgZanUG}S4=3^p$i>xX8FRJskM=={1XETAk|4t>t_Qk_bgu&W=i3kfNcFvp)fS`3-M6#g%zc}DL&8@}Owj^b-C_d^TC1y{RrGg#l?>7IAW`C& z_xE5C7dKGyo8fTpWfr5hdq{;6^>YDD>36OUx7cQ#Y&)(0#*@uC>1q=lwxHpc3Lhfu z7_C0r(R%DIJ@`^PpalAU@T1YO{z) zC&dZtH4>Bet9GLX#;-9H>&9d?qfqUuM?R9KfkWZ`^UY1DFJtuqei2LGyVHlQ*C9bb z$C?jFZS(C3=@&-<+c*d)J{$@CNvpj+wnW*YXrKROBhFcUFkQN$=#J}g^|e3M-A`V> zDU%IBGqLDsUI{Mi7&>W}SUMI3kblXC;=6- zNG#X;L8Dt^YZ@9Fd6H|+(*{+5Ko0=W^~VDOA2xf#W?J4>9`pH&Als>TloL4xiBGgh z=I~EJQtt9CuI`c`5O$S7{}HgkN;tF6X6RA)`R5I;2Y75Xdt;lX(WrVihtb%)hq(i| zh19#zWHs`|0lM;tgApauz;}lIn&LqbR#xtb2qwFHdGi>!(!u02Z5^-QmEZm_oYT+v z?VKLLr(66|N5522OgD2r;kmLJ`>mEY)A-#JvJL-T>r-l{z_MAE zY-fI`=E&Uw>eeFL9`p$3%OAGhb{L-Sj*Wf9S)Tlk=^?*lL>Aws9`UveZpGey2sspK z(53YweiOS&PCdCEpD?SbV6n6-MxXln(5xu@4!8lncA8XE3!}hcooYAbp+|(nj69@B z>Trf^kh1GQZ}gOQ(`ZZ@uD=aBZyq)kAt#>@@&zl*3Fv>6;e0SHjj@?s$89LkYrlj{|ZwtoH(^X3+6_ zTZB84iIvzNOGggcs@q@>Ie>V`rK&+N7k@!{aM=rbx#H9w?5zx?i?L3-DLRc+KSY}= zDSz*5^ucL5UcObn8wZc-NeAPI_KkbQS6V{voN3-C{A|#w^AWq}vEA#9^*kFnsH~=@ zlTJ4FyhIdeYfR-v`JfRvr}NNsntqbyHs7iAduG^0`E;h=d0y`glUeN@XhufwET&Uk zYSOFL#sC9;kV>d{D^1K|bz{4_Og8*kJ|?#S`Bd2da;a3bVxaLlURbYb^Q_+emb~zn<(gN}2_r6xN9^+pU=+EcrLJ5*D|_4ZjBw3mHy zE80DZWA@hSlU_BN<79)T6KGZJFaPMtCOhz@Leh2SRW}zO0;_fWxpBx)Wp<9JT0|CKdx_&L|MT@G#;w zc*+pytrHriI6pAn$kzrCArQ2GqK$1Xq%0XyGAtAS2sP;MK$ezvk zCf@1BtE>kaksPRp$#5fiNW$5_@Y3vaINx}|pgUU2JqJpM}mo1l^ z6G-upz|^6>>7xScxHKNL;93tYGn8X#yeFT4L!o>?{~+qQ!mveO(?T^>56E!QV}>=J zs^9F!+)l|sN62UGd^VTQN1c#^nVIQDf*K>{JComfyR<|zK?^mmy}^)$B4p8m+%}M2 zfj;K}kR+znD6&C0%U1iduGy~b!!~wOK+r(ng9g5)fg}T5Y5n$qDozm}G)NZ0_e`gE z7RV4)dB9%`Kq1>Jet9L{oKEAjYr>};_o~#>g~|xF!^oZ|`qxIRGY81p+`C-^dDEq4 z?%V-^X@K~2ng5|HD_0JW>ziS}RgHsc9*KFvpdNLF`%BP*7_HG`6b2fM((o;@Sodsb z1Rth2HDeuok?NLHD{Ad`v5e4wEu@W^*Y>OKkPD!pINn^T=La~$cADH$+v1I`jK`#S za8A+D4^-#lZ;`uA)TUSIkLPc9tKm;(i4$D!Ww#hjdL6)Acj>P%Q|XoxfnmBfQDpk8 zXKwy|!Ym(9FAWSh*KB}h;p9m_@{ygT)pRt~K>~AfGH^$}V^rhpaNYCZ;5I?0`1y&% z2oQ7*pfTmmhStE*%v&`M0;#CUJe7E^;nUJn4~8Cq`#VFLbw63-{cG&rh!ZJnQE3D1 zC}AhqtxICSS+^kudU|`ypCmKhcfH;^@%8Ih;NX4Nx^4N%+4Gfe0!{-KvuK!<$G((fF`_&|h-ic8PDdgMFB-ddTRE6O3j(8JWDHlfy%= zAa1rOi>;*wOmlO)R&fN|djuZM=3@_TI1)j=CRJJ-yMW!xk|FD&9h?9RsH$i7da{_8Hq}>s!66;T z`>6m~fln7*rF--x=MB#$h<3KY-KQ)IV$~oadL;jCf(^$oorVqzR5h6IulV|l^Iv~k zLd%6-p#W*NF@(&+P<-`t*cyFRumOH>n1JJ`Hwc=oOmRH0ma@nCJ&N zKqUzfUC1Ur5YP?dj8!moU4&sS6%kc3b}`7m&ekiVuJSiaDGrY9vE6XaY8-o>>>NQ~=SBjciS-VsRBtbn;_J<>-yq68Hig3*Zn$9jbnD z967$eOLhJFZ&0cxCr#Q?DoHngNP$EAf!+KYBmX4_r&d+GoST0?Gh7d@R%Kn*D z1DYd$9>&LITQQ5MfeixA++z z@9ba))eeT(p(!E-4xLY*kSxDXZ9=QT85`G`pCM$-#I%weNEP9S1qM~EvFwANAGX=f z+%&B|Ed$m}{6P(P5}TWw5J9o=OSQESS31FAQ5`tZ9L|cu(>=6I3=Ij13Lk{Sf?F@M zpLe1#N4YbkTfz3V*4-Z=Br76$)s&yI5nKmdNOYbEHct!nH6mois!BL)X2z>#%!WP1 zwl4qjFnkjoWt$ha;^7yMAM^b!$x}X=7fBI)GC7uCLhquZx}#n{U_<49$T)6aU4}CB zsY8Esga{wkaWM92tU`R4HZAFiANGiPvVAs&aGTH5&-rQ5FZ41w_3#gF79Nz5_TkoT z;rF3i0(SljR|)lSs%<_Uzu({{@@SRqj8`hGyWiYPkW*c~zb7RO!*JHCv$-3k`5=sMGj5Yp z<<~VzN=i5^t&POQBhPBw}#5_VYpa|~9pzQm=4>p}{QXt+M0W?1EpO-x2!hFF+E z;+cW+pZ!BeldWnsRgV=pw`Lclyh8DDuB1Tv=QEMp(y5c@FK1qsS|<0HeP-W^C(bVw zlry-VcHhUho%SFTprePi7NJ9b=dWQsZ>Bw<*lZSOaL0-F>$D_HW!Lc`& zFyfyQ+}c7Nm-n`ag?0$Cty7jO?sO;3ZDbbTY2LY~&{o%%v+=ZnWls={*tgrrO zC{%oC)4MC=uL@|z%~VT$y{F?60pdRPNb|I`Bc&myw|@ls6pI;VM*IkM!m0jETuM5; zL?j#|HV}4w;DsM{BMG`27MuLQZiD843jR|v<5#Jvsq;T{5?(|Um|mf4ATk^16EAUB7VOD)b0aPp(|m)Tf&VUkZL(LUPr9o(-~@vk#{fcY(2h)N)gHTXyCi0-*+FVkGRxOm`gv0A+&1$sqVuqB zCepvZtJ0?|E|51UKK^?;-+BB!QNsFa*TJIw98<@nw7_`+ch0K^{uz@~A23x&#UUa7 z|54t1Mm5!SZKFZ3Qv{_6f`CW|K@sVSG^q-N-Vu;q0|HX4sC1=Q>5!06LkU%Bl2D|C z(0dR*R+|L=$81Hz__r32qzs?wE|8Qi4?b>_IwfCBHUh|q)`VyQ~EovT*3JuBM zdr;u>zT`a1yNZJEQ1a7zdKkH^)-46HW@mq&7a3g(-tC-@@!z&y&i4)Z+{g?OidLGt^!4E8fcx&k&xyyaxSYwHaX1_oIDK zojvC{-#OePDm3>#VP10QY6w_^1#92g$i|&xeWY@?-q`N>} z10Gn@w+tF%{Bn=9kMmYkXK`tc;h_GWnwH>xf7=nba6BlW&@qMLAXC5xs6|`-PG{dx zyp>rWYpR)127->37R6kekfVT(hGGy3oW>{zkhz*;%8lNqqkAtGq<`s$-54iq#BizH z+OK-WnNuXZ<|IELgFS`6+U4%{H)JnaNrDELI<}8Z3?}PTbxhuB)X{EQ_CSt6_Aj7y z`(vKee}8@T93|7Y%S%KjzhB=Tk$xL6lT=2FjZ<#D2z8v|I;GjNamXtH^XiWr_$>Cd z9wWtw6LBNFxq#16R;LTtYO@Bmia$XC%y(r3zl&1|ii#uGk2LBg*pqwINO@K`F1gr; z(#FDwGg#ZWrI~^9+qO#fzWm}=2Rkc4^Mkj`R6=w4<5YZdin5BhrNv&R3de@;^rmUH5e&`ro{=#8snYrCF6%&Gd_=JDK#VXlX!>WP8egG-WDnK*8mz`a_i2qbAeEC~ zMkgeB1PqtHNET^JUh=J$52O(fOw=8NRfubV5o01pOt8oX!I<%Q7}C-#XdAhz7pTK= znRhf*3I-Qej7|X9Sy{01hR#twNKl=6tU+nPM@>1vr!rnIp;U&>&ta*`=(9p(i>K4b zGhIQP;-yDaf9GfrL}w%a$_46&KKA0tv72AAzc{)0-65f)0~bH5YyGm^{(5BmArQlF z<@YGpStx2y3m=z_h91pbcX0ZM=kkU>j~zFnk`gLT-norh{fkdi`);gnhE7GYg`_nP zmRY<{-S>PN`P4)nO|RiwJVJt1?Hg4Jo_A@DhkBp4M32WH-I$~;uK6sW-ZYa|oUdd_ zpCuMW^shdnj$?n&bdO0`2~sUU7Hwf`(u)*ps!OwYgb)n=UE$R6Xv9IM=zv(cS&KSY zuVnwVprDLXRVPI0e*&o3XA>cA+#mG>YvL_)55sv9$&-QFjT3tY(@$UvUsm^RQ0Al= z{&r+i?)acU+Cw@jaM}Kg&x_);oeKb{aB+P8#6ZjkRlO4^Jz62?$Q9~xXAZ_sR-!8p zL-%&)H*YAs=o#41xi08KR3m<(c<9SO{q-K86L0`+g0bPU*1?6V*r91m=m;jdwM_Ee z(X`<6w?5~VS?*Yd#Mo$QXbiA@YKhqy6#yxg5@D*P?BZv9lb+9<`^!gsxuEjH!u)ou zAH+BF?l);|HRz-@Jt(R3U;Oqo)G_fG67ey62N%#8ejh{Pz!|y@qQCS;9H8!b;yNzK zS7P45c?twxjSt0O+q?1`WS0jRq_gJ*Y)CAEoVi2j?-jA1kodq*snLYy13^eQ7mz~I zNNQ{=^NS)@h?9N*$XH)FYYYQJtWu|@F=Jyxl>K5woEBFR!yU>M9$$Qf_KaXJZK}aL zJp%c$@uy;~z~vXwvO@Zc1U@Ah6VI`sF7l`(R9F)fz}k`)&n2_&%41_*@VIRp1Ozad z-DMe%{u6J|z81WBRVhi5(t83hVNDL8Z_+{5JK88!_Bj^mYJtJzhaD4J;#hV76JbzO zH#dyhOn^Ceym4RK^QD?>!gvQe=DMv6+0!=)w*F?gJlhfff~}5cBB5oz#M!)Yv~x@C zRenTzDqg+hq!LylK3pWZpSlUZ!B)7|U?gOwejjAfjMBiDVL zvf8=PSw}({{#b=kpOijj!uBaN8Nxi4cmGE;dAV~})_8WMZ6opJ?UDVdl9#ZvPQzT* z0PQ6y3+~$f_H-KkvUqMN#%08fm|Jg%iVI)0^z?)YUS)F;>O0rv`EtZlcai`z?LGc# z`)tnc>dkR`BZEXtrBr;#fVL1_Nu7D{%^0%{lN=Dxo zJ{}|X_nWPIVdY6oh&f9HV7K*6e|qV`sXdND-oF4^fGcCN(X8J(sJU{V*WDf}q{QU? zp+=Nq>TulIPQJp-Ht#RdgJ*7q)o15U5EkQEnLP0_%~rzoEnY+C0WRy;4t*&s4tZPs zT;qc0bZspAH4y&&teVT05ETWjeS>s#dnZvbDsz%K^)4dclghgsVY|2EAPUSsOam=e zgo`el7Okr9<}t3dlKh9SOB$PK7Nj|jpai&k&OXE#Mc-%}Bn=aDo_ovU;!p^k-{`1J z8I@5lv(Zv>!u#go99+MrPFID29|&cR87PA~3|(~doh)J>>$C6-Er!qi5NsR~z$sdu zrd_sbl(!mNHZG^(9#1apk4s6@eMBK+=ypdPPsl0RWDE&qs#NWu_P;ctm8;L?fc~NG zk|0}o|Ev7Ki@xFE-DoFDxr<~|*X+)mtFr;TLQJ(vgnY%_IRBqRr8ek*7_OMaiI7I$)Wl2{0flOgD%!`!PrR1Li z%{oNF7vH}hdmLTorM>ANqtXVL8_YvkXTWWr#Z;ch&J_xrv`@b?a?K2TnYxl(7o*$$JL$+>!}$~~xlu4Vk*p}0)U7;!^Rt|X5&{m9BC!uin`R@(xL z@qTr%q7PSlsq$9!+@ATKGVWXluH~PbGC25aJWqpJH}sxW6bSs`ld2HfS zzpC%^l>)wa*~alQiyo@ZEa0+kng@iMYqpI+#T+}4firWxJ~u`_BPl}=-Q+ieO|(*` zw$~_d7$KDfy)#pP_l()`VB>`i}+9ey8tFBh-dHezKz zpoAMd8Sxd&mx!PAT%ocY=Y5QsRs-9vvzoM5eC-COOVSH_U7g}cS3O;cRpTQQpUkie z#If-{Q}Y9N@RcWT~SAh zeB^(e0wB1aobO2?hn>ifqH_!*S9Aka0(3UGWML#d?uW5n3FNbzA~l z>~v;{GPQmSPFBU=G-y|Y0L|e3>6!X6+TMQ{fL*}W2~+u=jvE)M8sFPRmCt>7$e$^fW%!A@Rtt&n zhM03T{$f5Hz{Mmo+}STMbO)TZj$(hKVM9DigDtD=2s5CkWr1`q8v=}DKWfOGt9Pa< zlR_eTbe$w4(~*xdrK0_u{h7)`y^(!y zrcMX+<|URB&l05?&eLx#;24LH8}V=Pd>QEXZuT?gvwMv@rr~p1q}+RQou#e~?)i4A z6?dPNUS`(_NeUsWe%;cAxv8MU3h=J-jvCZtaTeIG5~LugDc9C{=Ii_7#>%uy0y@rP zRone>p-eT(5>zFt3f1=&VqEi{yG#do^6yTkw53{(#X%$VxrkyMpM4B3J=&)Wz%>e12TN;4Pc0%_S5&Ks2dzc9_ey+Fr~`jZAy~Wbb*v31Mk`^M{;*`0l4W1b<@ylj{1`g*xpF+j@OZqODE7XrAz0mOC4~5@<8}Br? zNV|k*)lhpPX*8=e_r}G}k#Oc>H|2yZ49uq86bnlrE+rBbp6C}meT2-2M<(7{AVgXb z$Is1-aDFKmF(Y!lziFa>e(KBh+-pG-H#9ALm8lV5O>J|(fMh(1`X6|sO35H-UOIB` zr2_Yy5+D+gX1RzTFs@`B{M?_Q7Ha2kw{#&JvY-&-p61%bY2VII=GhPEOWs|h0JYA# z@xINhTnZ8rWyACof=Us!`LJK*Y6odzd{KKzwc4V})eJ2gcZ>YXcgNbgrRy!^4}+Ah z-h>G2e3;R<=sP~&@MKi8H4-Qz)C3yxK>ldnBReyd1!_?*{`sRrZ*y!RupnnrU zsetZ?yxI#i^M!;(vPx#%C-a>B$Q=^O8weT5v^ng|W+N_scmKZuZotledi;-po8yf7 z+HE*Ok`bb{TAu}dVv0~THKQ{~U?jjP@KSFaZ+tU8Uoc1phrMouJdK-!nn5|>uv;i7 z2MW3tIG7Y?)IZE_pCR(#-K2I&x8!oqutiV#?lSW~H}DU{1aQ57VNItW{<*t=K>#vqpF7@Q&LhERl{kBb}M@ZJ*%RNyw6Mf^XdtuH0smmEhm69SM95ht@dX< zc}&gBWc{~zUC@88SR}Yy%#aUG-$nHI>!t__h&U2yeLXy$9Sby2?-?ZUDRX=p7f&!* zZi@`8hNVN?&pW%i%Kaq)vbfpX8*FUz-{CB;;}TWbHa0eNE?(8r(%R^1JRNmqBDkiQ z?Zyou|45=0T}CaN^jz)QVzt-9UcFURX{g|+R|vQKjuq{(Hf_lv*1l{}($g=je*5}Y ztr^e_;!2e>@U1%3I{Ww1ep_4HS03$#QhFIVx#O)x-B*TYW`UraVEJlzwqRb8x=3U( z0O99LnLqg+?=SRbZ-}-c|L#-@Rt1rLCZ7g5_xc{t*g+bwM?;zpTP3UN(g1C6QbPN? zM|gnIh@q@H+1=gU{0*psBM}MxUwG`)gO=Y?gaiN}n?Owa zIgdOVyd)n(@9gH5(Ae_P_Gh1Q9IxFL@RfR*ymV2jbk?h31%|Aby@GfjBI0->eA+7+gTWXhjeFvS z7^M^Z(h2P``~v9&8x)D-VJENLZ&lQ*rM&IIfSQaPt3JCG3|Xp#+LBnlI1AWW9TwJCHPgn2?V0+ z`tP=TuQZS+dePLsAJFF%d(aj5lnm<5L@TJ`#-KHNR648osW?1%^dxqusj0CiLC1$R z0^v(ZTB$_Di87=YmiAGRb6%|2?xBdVus_P)11<0yir05@$wGzK!zI(x(|x)GKBQKB zuLT0CzM4Xx3j{k30|bM^p$yK4zVX&k7k66xL<@(o#53ByuHm$``aBGU;%)ru->%gz z4gIxI^(rMQZgAYWKLR=oF${Ew*l*j>g1A@9{07nwHw!++T_2*bXG5SpI#^uK-NVA| zd&0SkDwVX!Dj7Usx4^Y4d;i>4L&Q0*3d!1+r)On$!nG~Lk-Tu{N{^Y z*C{6_;q(qd?~a=*{Q_Ut4)~XGPH7cnMUzN6;$q`ovI68pM^2lJr!;Q8jq+qnI_eyQ zoaYnLJ)v>&AN_Qng}fy#yb_ZU_~(e`N?j^LTf3%}H47+$f;T z#Nt2k?T+m@xu(4qXaBHlhO~XKlfJv$g*QM%-!^1Wh*PIAB9azZ0tPD1P44|#aI8JL zeKmw1w<0x$y{kj8N{JgbV|JxZA~dbYRkC6#)rWnKhepGQw0cK~)Swf8D9`2t52`vc z`TJxG{1jDBdubqJWu#$mXfT)jp_zl8BI?7kKbd84aHD^myIW3OQ%kk2%WNUyC>Dt> zdgW4*i}})OxwNz-$;?ZrA6AAzi$ULpf!}MKUuzsJAV69l9?oywB9mRZt=%T<=X3y< zmX)I~-wp zLsvybC4mb`&dSCXk4W{I8j`{zXPE4Evib5}iPC*vSgAZtip=(ukFs{t7loM?~a^xfiL0y*|{pN-5TX-?gP~OFTC>TVXOnol)YS-e(h6yyF_dKq;F+!@w2Qf*++|H=oxs@ z{I;g3b&}p(Q>mV~=j1lUw^W7Xm-Odjx#DTfjjV0=B-Y+*Z&BR5lvDF(UA&lJ8ri__ zz~_tfT+$o8Czo*fsq7eV3RlTulkQRfL&E$`U`~F6q#Bajc z`1E{#nIO74mo7eZdS4;awl<} zoGw&$Fel(jjS=+Q17eQI;y$QD!;+c|tkl=#4g4hn%C=$M*7OG@pTd8+{I{!m(sI`q zNGBaT4MBGkK2`>Oc8@Wezhi^9q5tB;8u66N7DOdtM?TMaVcpdYnZZpdO>uoEbe11C zM7B`9{}08tMmsyX9bD^bA@_rl3AzNtjt-o?RffFOA9tw zg5FpQxnGaTG!fsvqt3Hq>uV>Fy;G91WY{er;s?FFaClf(M5n9Y#=CT)ho<$%mZNF$ z>Bhy#%RwWMc&^fQ$Jl2>WM8tQ*zKwr*`wW>9J)!sL@=kkS_^r=}cu<{e zQ2uDtv*>*T`BU+(y2{G<>&-}Wr9|RSlB5)N5@8U9ZFwRFSnCaEJvurFjf1?B7XCIr zUorozC##?~GLw%~VW>DHhGSd}e2>@+2FnO|!&-0c(z@Tql_log0$6_Go^nAy(hskO z1iaB_*=_zSEEU`6+1wGEO@Cx@asF*1n3dg#5i-V90do_!qbR zvLUXVp#3d}Ve)~#&v$qeTw0V%hky{>$3`>Fg)t=g)1JajEFG?;L8{5%I;=B(u3Ag8 zxN;|#$!G=?Vi@)hIc#qdC8vSzv4?xy$^{tSgj`>SY|7Q4;oQ^uq>+8e`g2bQuaRoL z?f70`w_1n}vS(oAoePEVWfbyL`63BJm#v)Aj#(zk$irmyYaB-_mboj?+nFWb#>>$rG`BI=9Jk1b_qlvqr1TU6bWk4dpb3!7YJ zP;d`hkP4Ng6nu9Xk@p$*6-v=hyi9I;lrdiyKfV48JHZtfVRKjOsh<)jx8c}Kt7|-B zKj${Z28^RYdHyaAalxIv;7rR6UHl542m+rr0FO&aFUe*t#pKIbbTN`4$lwP1aB;`M zGo%_#@H(GMS@(E_zGXWTv+W%v?vvacR&Poyd(%b7-`{;fWuhU_WM`F?te;Bdq?AUn zv*Lc)H%2q~{i5UmGjt|`E6d&@xt>tcS{NBQcpr_Wcaz&JbR^rBK^3*79qhsR_k6h? zD~EH5Mz)t3cPlt8C?&`4q7vPPsTYA(&CbpaRR*&TO_axT@aRsyDyO(fHZ@9cp60O# zf~(ua@mK6L46}-L&xT0{8k7rL=sO+d4yRj6z9-QSInF>I#YuGMU-rOWCQVOU(eo<4 z+5!ElpFBf`!|Feagq}wuOBWS#k3A*>(F;|K#x}o(YOO{4&TQ@4%b>+BN6?|Nc1Q`N z2_L`1wrHZj+NPterw0gfajjnrMkVeC8jW<#Vg#$0s(4C^BU_lGmh6;iuXcti53~C% z36GCOxN&m;HFmnpSMEalzg)-Zv%mF`v8judxWTGzF$z=N4)tyKYU>L9e_)f-%*AU( z#z#j54lZg{#m-!p&#_5kzrA?z0XpDDzr3t0@)(aF);DnMZDbP2PWffaXk2(ObWNMm zsL*aDd7#{lKWR&S^`X5gL9(AdfZ2h#`qHLoeg;~MVKO%J| z?7OF=-jPc}=t@&$(+6J&Va$You{EC~Fg0qNIa$^)f75&zxDVenit@u-kTF@LLEhkt zyzS%>e@C_e$;FFU9yN&d>SNb0xeWI|m?FOpvaOx(cAAO^`DomxZ5p||;{xy&R%A(t~(F3bP1T}5emnP@vf ztE#_tJ6ZB=ujLZoz_ux5d{(`*A;||`1lPN_7}h44lZRnmO1B^j7nvAPXouf}VUIT3 z?KCrA#jwy-cOHjGk5{Z_XtfNBYG^l4lLxbk6;BJ$zum5aufKYp)t8txR8?7tnWt+^ zfJUb%d2g<)6roVmd=oW#Kba4H*rHX07S4`wjNY>|dvEF>;2V)>oMJRT|K)?AmGO5} z9>&;Y+2P3Jr30l*g-y?5vT@Jga^sCFHbVPUYaHCs{=6xHvym=`NWlmcf>JQ<#H>>J zu4T~!{4r>e-Rq4C+L}XDs~v%EF<0un@{A+F4;pDvA0F_v=L!ccV^UkZ8vt(tY@ETM zJ+mvC8#P8gDHUOL44OQ1lU$vh^%&n~9M17H9<8{YvKQOK;Uu`|+*;6XEf~E=mXVMF zq=7}(>vS^n`8v}5a)*y*7#sgKvmf92<1%m$ofrUB6!iy!z+3t9#2-(%uQcahk`YZv zNBmW6WgC^PgcUtg?DYHlcMa&X92kZqj)Ur4UuEQXcm#c8iw;!wN;@gvj8n*qe<;yS z5ZZ~Tky;P9TXrf6$sd}y<`%S>!sKbI_kKU2@zB=zXW|bF&=xmT7Qj`iBY(80jl;IA z!f41+teDA%dW~f`g;rdWB4GoRg zus-6-WoDBC+0wx;vDj2Rh->9}X7qCc4{p`us@F`nnR&OsV_>jx3I8jy5omIbZsNYycf$n!k zotbrPVgStgll3RAQmmK1)&=6QSlH7u+gKnpt0KGlg5y|+ToYwRNtG<8;z76xO2n-sHW}Q(H#23vzYq+0A!uC`# zG1jYSVt`%pa*f|FR`@)vUhqS99$MOee$3@o#8SI?L*)pN)xBmsU@&N$`{5FJjP{%q z=Qc@=wj?iVfHbYPFT%VZOVm_Xzfh*6ZJC>T>E^aZ4ZBELm0}u4ACPRN!K&}!zRe!! z-s5*3VmS>II&sN#>waEd<<3f_+g%KnMeyyp2SwNq5AZ)j^??+@2K^-6a zmv!l+Dew>AFO$aKdPg-DEhKi99@Bv9GI5Q6VjZpP0pvbT<(h2q@o9a$?LhmDm7P5!HT7P9$UwVPUbhy!`6$uc+K4TtQ4C?RT74TMHbGooE)t9Ys(-sQ85#7kM=H}rZ=oDHKiRZ1t;c$mA8yg$v zb>*=}fJ(`+v$2`~3;PQ^0^FeOZP@-HpyEoKg-`ZjPMe_Gr2i|(cEfn1yu94*q5Siy z3+o4y3@?rYgWi(dZwjKlsq<65y8^ZYbxLtS(qLn5pJmHpG$1ZRv$dl$T zVf7NZRzQO6bNwz5G{#Z@LvBgR%lG&;a78=b22EFZY>1pe_oCW6tlFUsJL4^oqwH}! ze3$NeGFfMOR=@>BcBfBJKB~AF$1e+70!Zw~b91+XgFqjA(*v=M&jB^2J zi|q#kF~=bTM(i|j0v~!7IzFB`57um~Y<6}wJ3D)zNK>%@0E`pk<3fn?>LK zthrW~ms=F_99N+R=S0y%jtN|g35Ma|X9;qtdeL|KBk(q)){kPJpz1cQ(SAjxb9IN=aE+7vy)k-W~uWZW@+n3|coh=-A3G zhs6vgio}zEatZNEJ0Tr=zmyZ-B>5wf2A`v5U|=BI@4(;OV3>Y9)8%A_dynL0 zx6cUd+0HZyu$^?Fia86g-&dEXwU(}NYG||Tz#<(JeYyOsuu?3vdHMP0!GVlAt0NmB z2whoFQ^0maMjZ1v3VBO8FxcR7=w8DNwt{7JT$ex>sGdLZ>RbNWMAss=e$6}g17Vj> ziNNc)ogE*LlhSMJ8yFlg3Q|3F?Sg0K-wSi3@$Q4ncRs!{We0~K!yTUjG+lhDs^}H+ zx@et`iuT#W^nE5;bz-s*{!B|_vJG0lj!!^P{I?ELmBA+NE%fTC;p?2eiqFJakD$6VA$Opg7Ek=fE)=igqV!;8)Jsn0Aa)?NzX zf7tZpv!&FVR@NjaIaho;EgjMo&UtH<}Q>jWcGYRY4(< z+dMq9S!QNtxsD3!nTSie%o^GQ`}WrcX82!I3VzLF-P%<|b!G8Zy%fg(YrzqGG|OHt z@dJplFo0;<681qn2oo0}`YVB#QjcWY7qoN50_#`!V)WfkK4 zuhI?;n6|&OyHUN+orK!%^4KR{ErX$S_{(KoZ6+qoyQkwPv>JN*Tt9fY7wJiH#FzQG zmG|pwrQaOD4@@=WQ!KUvaNO0^HQvMU-C96E0Bxx_OC5U_d; zk%{6JNCgaBz1U8WiEJ1shjP6MzxS=^30>*PpU)3%Sww6Ewp6q{zj9cXYhWc_@K9A} zS7TX*$lKGvnA#=&dmMQs3oL)Sj33%6!;fi79)KzBDnVg9){|w!?dg^R3UlCb@eF}C z`~|QanHXw{zWBlTQd-KBNy9}53Kd5KD2${Z9W>f>8!yoZ}KrqKw!1% zHl^QBJ$RQL6vrb2J>Nt+0f5d_5Rk>OrEgaHyKS8#{xgh8;F!KyCUC!kM>VlY{rS3RAV9$bzC1Pq0h2Xd4?F8yeW&XH?A&*mMPo>MNTCLIceBlb8hM^dds_ zwO_+e;t%Yd`|G^)xlP3{#`TkL2Zy}hpoWx$a|V4jtf?~_ajuok`m+(_7kO}CVS`*P zzYXlsmEa$xlB_#4F~RotoV#MsRoH^b;0g1n@xn5vnwG$WI*m4|2M?-QJGk%U^yZw} zha&qSsI6eL{yq@9v&7rjR_U6iRbJXV6oFHr>Y}`Axe9(qF<#GUR)~0G3oI_`!=VY! zOMm~7{o)G;Sd&KJ!&q7LW*+vg>bAA2#yXH^PLGF003}>$%H(&gnI4k}+rfRf?za4=e8Ybe_-2SJKsh<-a zDc5T#i;$ePZh786sBKHf!U@pp?b^x!^SXf#&dIQ3)#p)NlJkpmrq;bjSIFr=xcA2e zL^TqUyBE+vSSq=(A^4=BQQy~}cr!4vX=`h1fPuo2R*&qA;m0zg#L_iya|;XYt;&Bi z1>@EC&a6j|oDgeq6J%#W%;KJ)G4k!VBJ%y2CPAW1YEQ8jPs6zXW9|7rV%dMy(@+1~f30i(w{i0Sn*bbKJz`d?@E|LpAlZ(HqjX8-MS{HGoMt3m!pE4N?M9214ngHIeJZU=@1}rF(=zbM8`NF2%j2txtEEwPSbAIUkP&L)FVQgrb3#Eb^UU$MOA9> z%F=3=6HFCXX9;mlXk7oU9XgFlS141}CRw67S)=RN=-#F+jbs{C$432wV&pODk?Isp z_b~=_{FvSe$}y?RcB)35!rVHH3LTY}o~AY_WTVowI%DXlj*S#5eWE%P&otP#kxWQp zO6}OFGmVf9i0LDX)Em^YARoE6QXcFl3l8-03zWADY}ZESFZYxC`uY3HL%jXup+O;` zazB~*(pODfNS~1bK6*p4uV1@%?R@3_zW)B+ zNa1Z9turY`dFzagMIaV9QEH>oph-7r^g0=Zt4P#mm^wCUL<_Qh%y^}xTMN<|eFPkR zl=?K^QHpe5KOecT6*4k*08K(84Qho+Z%EMVwP7OWeNyx$y)i|fE{lv0^6`_!D3lr< z4e8)pJcF$UHdyK?g-IO-3I%)11HJv_34Z>e0c}B~)^h()x!ewjn6em*7_^2;VNw)@ z5|rQ<5*p+e8W_}C9%zM9ByDjxdX*+=^m9S6r8L9n;7iGDM|Po2DaDF~|50G=5;HVf zlgy--88URTp0QEUGFi0g;>5W|nM!TcBGZN*8ePUHnR-;Z+MrSElxllg3e^*eEnYp5p|qO6n_B)Qsw0rHcy&r4c`<4kGt$%b z29r^y0On{0gF=_Amg$pZDGGyXqylPDX4K0@qe(%#OpQ`)l#SFIQe_t>egfS@6Pi-g zvPAu;ixcO|WU=wGjC2S!Qqio643j=hVbUl|)b<}GUJ>#7E3Bqe=qML~|I|7am`dOs zk>3<5mA768GU!yYC_VZygG`a0Zj{OTt7Yj1eI})KRKExzKDtjrKba*%5?IloR_YBZ zjV@V;9;q-XQ|L=VzyDiw3@lNdaxr0dwKiQq(9DA(%Va7vT16rRG0C7$3zf-eXKF-m z3c6&Z`Dm$_tF>ySk110oYixa$p~p-@j1KBk79AH^qGtan!v&S7PPqt`kfP9~QW=y{ z=1`{S^+w7LR+ZOK;3};?Q!P`{PM$_;Og^%K`V1&NtyU&PWeAyQxRs_>@`0Kqs#p$+ ziCV8{Ct(kdf)eD++PA#0j#s6$_PFU82CZOisg%B8kue|IWsBKV4Km^#hL{?jmV+IRlmqAHy2CD*Cg@1rDBrzz^J0uZyw7)XY-@9#) zI?-Dl5D=vD4+v=+piZ=aw#!}ubgV&xk$^&Lmxk87yhW4(rbJQQHAdLVql>gvKIX{I+cE;v89CoMY9zL|6;AIA|y8|GXGjL zB(-gqBu@S#YSoA8WH0 z+h#$3Z<}GRmbIDL40>VxS@7T7W+9<|tUnVw-51toA%AC^p~2*#a@L={;5KXfH@BHz zs9yl<&t7bQ*6#0ZGkX#u_{jW{`vU!kDdE39a%>qLMSew0IIs3zPvcIMqi}*kN>*Y*b zttq;0W?Aklw$4`i0;?DbCp-A}`C1+PO02?J*T`PvLn*WSFA}^6ixpBXnlf@Ra+Qk$ z#$AkD<)T2j5;N{%C{V7%jJp`Q%0+>4C1%{k z$W<;1lq)ggE=I0$QJ`Fj8Fw*qm5T!9O3b*6k*i!3C|6>}U5s4iqCmM4Gwx#KDi;OH zm6&lCBUia7P_D#`yBN93MS*f9X57WdRW1sYD>36PMy_&Epj?R=cQJC6ivs0J%(#n@ zt6UT)S7OFpj9lfSK)Dh>le^q(N9N)pQO~B#6r4<{m)QaJK49f6<6oS}#(mTRqMbaI=9FbUl zg_dn5#8nW!g|AK%&28=}yiz8dBBZQkeXmd7rH_PnSK%99oWLo~DSr^+W@!Q<5z=N0 zq1}mZQW9dc_;wOPICIFtxgT3Y{1L;Em+@^$6C{Lq+d>4GPw-AiIw5?iAL(@(U1}8n zSK=IZbY$}52GPG0+Q35&P+-#l7SWH5dCO^apnvSxyR6l;bGG0Wj50&caJ{lpSp6WP?5-S|s!(xzF# zn;V4^zi3E|G1<}yh-sV@T2q1|xk#!CN;UG~bkJyH_k@^U7FFe92`-Y@HAQb2(^*T; zZx;I{FA@3fmSAA+tWqZ_G6dD>nyEIJN=e?&5?nO7dt$P10Jj}+D~a$Ux>+NTh4j|z zD6L&h`gC-kMzuZTxM{&iB|<$C^(HV>iEwu`drI--f-JS51rZPYOFG>bo<*7S5`v*y zJ-Xw3YP|&PpN4*kp8Gvu;L9@Sy;=$ zNIp5_-Mx=YW*7H7kCl|^26RwdA0!UIsoF|BPrq;X3J>{(=URSMo%bx&lZ+Amyq?Z6H@b}Ev(6BFz2QavTmOpKGi9|*j-|v z!Ewu!pw`bHCa|U~`@ya}A6lOE(0W;vD8e$z)k>U+kE6$pxC%lo^DfTBe>$UGwe0HA zCQhBCHqgV~W&OZq^cdwxy-uYO?qksCiX5$P2jNdQEn2abHy; zy|afnRBVo3rSNM0dIk^;lsKt_^R$s{tBOe61+ zkI2Vl0a-$plT~C5Sx^kxGr2TE{+?>4daqI9hbqq%Du)-<7RRna|^lU+&A0?ZX5S2cYr&=UEpqT54l{4 zRN^72Dyb)FCh?WDm2{T$lq5)oNRlNZBx58~B=1V*NES&}O4doXNq&pHe}40Vil9N?JjIMQ*d<1ELe zj%yuvIv#Pn;`rFf$*H+|fa-Qlu*LkJ$7UzS`SDc@?xVtoP@ptL!^0JH0WwOgGmoHs@bUEm9%_YyZqH9yv zP}f*jmFsBN8LmrQH@fa~z2chZR>`foTSvD9x8ZJ++~&Bga@*;4+U=3MyL%(|cJ42^ zYuqQg&vF0S{TKHO?oT}`d$jV1^cd`s;qk7=GLNkuCp;c`dU`hV4EKE5)8zTC=W@>- zo@YIuRH#zHr$TfERfP!^=2ci%;b4WkUanqEy*hin;x)!=me;pl`@C*fbgkH|Vq`@{ z#qkyARoqbVSjFs0RVw*aimjAZ>77bnR{FKl^~%nbn^o>oSyg#T<;9hERK8S2TBUK7 z$STSzuT@!6WoMNuRh_CfuNqx-c-3iDzpA>o>iue!s|8l;S8Y_adDS*oJ6~N|y;=3> z>e}ivs;{Yjw0drhdNn%NP}g{?#;O_zYvk0dQ!~7#y5`$8SJymJGq;wkR+n0-wcf9_ zzSf!A4z*j=eyR4z+Mm|mS^IXKs&(4eQPz38&YC(W>q_djsvB2#Y~96m_ted)&Wlr9oH&O@j{`Y-w;)R!!Dfrj^Z+{Up2Jux`Wd z4Ko@pY`C{!UZduX`Zk)}Xmz7AjolizZJgBj!^Ybi-*3{ONlcSho2+PZvZ-s+woOx- z&ThJ^X->1|&H6WcquKgq*PGXD9^HIQ^A*icxA1Jysl|vEi&`9R>D01q%hZ7+UVLWYIDrn!@IM0ruPc(3qI9-dihNDS?_b# zw~6n|zVG|)@-37H$+hw&@>715{d)LK_S@+9(7%$Ma#buwh}Jg`Mxzu#=+GqD~jX z8;7gHmxf>K+_LlV&MQ0LjgUteBGyLaM21F=i`*I|jp`QlcGTW3mAmxq@^P25T^n^x z?z*Du{cb_s#&+A<-LZSm?(cU$7F{n|8NEFEevgnI<9htm)1zm6&yRav?A5B5q1VP3 zNlcHJ4`NRDZrWSddwnd4jgI{w_DrAVeMa=z^pev{eO{XP($zS>xL4zL#aD?R8vkYd z7&qXzfwc!}27dpt^UM8SUixzO zpe};y@o1=eml%@SpQ*P4$D`>Di$fS6QdJ9 zNxZL&RL)l3QiZENRNYW_RL@jjOX`?3GwFJA$K(%^Z=`fenU!)|6RG)F^I&-Q;R}Z6 zq{gN$OXaowwX4%y(uSpN&{fu@>VDGK*N@U4NN=4!HU0dE&=DVvxNqobSZd^qLyX^> zs=}DslhGpM^^6OdVVUzXpN#A`^4n3BM(IZF8Qp61TcfXy={n}~u?}OEW4FKB@YPAL zUKrPT+`{qP_{8zsCp4ZgWx|z--6no9$!${Vq~9mYC(oRm^;-YeHcqKGW#W`euXlTW z#ncK@4O5T3(f*AEZ#ulGd2{bu0dLKHtMF~r+q5A7*_t^rK&A1sP_t4sPV+4Xtb&zCQ)y>!~rf@Qj8=f8;i;-}>y%a?yy_sbb8Br7sj+*mny z<^HdtzWRQZ_o{`ftFNB+HTgQ@>zm&U`{wAHo@=&$+xFX4-!=X2leJaWzP*lHH+tRu z^(pJme?Rd10~>m5*uJs-#G;bJzlQ$0VRzfz>wgRWZQY)rJ!^jt z`hD%*;Jxeih3xx&f4lt~4|F*29_K3PrXy=&L?+U-2Lue_`N;%2i(8%!0>>7 z_|BtRkCtTxW^K>zlYRDa+T*;Ox1ZE{^2O7(Pj}_^&%Ks6GT%9WPC?6pjfFi6PxEO! zFN`&+T8)7=!aKE~iAPI(QG4Pu{J(<7^MrgIj&M&>lW_cT{todFE|D4<8H4w`q=N89 zR1*mj^QXuZ;^E@r;_Bkz>grL+-OasHH7^ejuWB``RH;^_O3g|h!pHn0z7+rFJl)+r zD|l9{P@!Vg3Kc3;rC$}QidiZ>4*-5EspNvne z9PE2h{qWl$-B^K9Eb?F;yQeU)Iq3jwow^e~ZNj#)NnUzQwfi`|lWzvy~)+uFfvum0hdac|}gTAy@aU9fhB?%d)Vw+r@NZli6M z_1dxdQ}?{J=FM@Y)co@^a~*lo^_X&8$g%uu1>cTY{y~Evk0;mO9e*{T&#$gyq9&}) z->iGX+ok9151UqLd2vRAO_g@~-v9LdroW9FceBQ@_yaykJ-=x+a=^}{n8`chW10-U zHFxZeIp@B;qrWjO_Q0wMw|2$v{B_U1Et1_|X|BhP8xmQ6SB-ibK1#@~mC>(Y-l20@ zJn3?4!fV+R{D!24&7ApYQ`q+f%AbG8`uMAzzx?>);z^TU8M)+M^q#$oP7T>O>nu+W zUN|)b_6LPFN5f`+1We#(I5~QQg#`*RpGu`(3-1b@cM-!Y}+kpP}pd&~t6S0fn>s zzMrdobw#Iu!du=GRu38RIAhhEyK_IyOV{oCVbksT(Q|@2-Zo8$@yQHXKJ;#rWd~=z zlJ>?2(-s^ZGc9z%(GKr^9IAYfdSl^+#C02|e>K+d$?fUc88wpj-7t8o&n{bDICb}m zS7y%q5Iprc_^TyN9eZOF>*uB#EgTnO>pYmkDm2t|S zGKa>d_07r+o&V!kI(55VUu6e--AEg?`S(+~Uj3Gat&ThMm?uHsj`?|o^oxmCXRP=> zVgH_<$M+1|Givmxq%JjM$7)Z-WU7PDeK-Ey+i5&`d}o{?`m2%euc)z7d3blL-1QS% zF1`2Nks+^4tL?4KJT@-luIFmsQ@O3T+zMOOY1yrXhhks4*|B&2yig~yVbSeZ=dE78 z>61tA*6DvMGvw&6Kab36U(jm7pzFVYx906CP_Bt?+M)HB=6#a9kKesMC#dgxC&L@N z*PWz4=_onSDQ}6WZp@u|3OIMtb5nCbSr2;ArHJUf6R`Uby;Db<~?|M;5*k2bj~_4;7m-y ziO2J^)=b;HxznNK8!ZbzdR%9A3fdexrAHjT7VrnHjUN-XBDT+_iUG@BKIz}(yG@5j zHT`j(_o_X!HcZdyba+?V+S})b=BEvfF|OL4%agvfzCDurTkD^1&5Z6{e@KHt=jM*y@ypH?RcpU1|GGwvH2tkMYZq-f za47BF{8QRZSrhghyD2*|J$w5*gNL13zVZI8+rQNa8|ggww{M28x_W8)rV-<`dUdt< z{>yJpn0UgpaoJIy<*&_se@1N2@k6vHuD^Wn@!GxV$;$_wKB+%-Z{4~h-~0&qoDg)Q z#jt|(TA6SE?D^HOvA4dJRlYgr=8l4{n+rdEd}qzFg3#l;SLAg%+0kQK;qI9qXHU2^ z`IV#JU;1u#*wA76B^?94S!Env(CNgQ6$MR$)@Lsml(l~7jM$q!uKI)=J$fqUM7yBP z)3a;e9yVZq=au6=dKyyj(cW=)em#A9#+orzC%nFD#(lTXa!(u{d{hjN6hme%Yhy19>uk_KxODl7e!&FIuy2#L069L(c?X z`et3bch2b#DGL%l{IOnxA&%ec_WZgt=-xZKkN?_UI%s|BwBZF!XJnjRwJ&dldg$W3 zF5Sn^IJPh5+|un8e40+5UHRNWub3GVPMkcoJg?o@1-Y$!9``RW9V^h>9GbLhcWB=` zKYTx}#W?+FPov}akAn`cSALw+{?Ph@Dg}L;jnn=abaREzqJ#JPk6c;s@RZ+5bx_#p)N#$m zB&hl)FTZtUX-wU5F+WkrMVVb0{b*I*zy16QERc6fb?34Mg#`ZY( z?U)6c74-``4QQZ`&vV)K!_mB$gey*)4xKzXeD@kCykn1(^lP6S=gHo2i*9;H$Alyn zj2>}3z;8hCck_bxZA!Z4zi!Mc=Z+TixIOOEWy@cGJhbQjUspH3Q>UIE)a$7+AHB0) zRx#vQR(B6&&vmy~=<*zAoZ`tM^ijXPC8|v-LKFByR`H?zbo>W%vllE@Ts|``ZB@vn zZYzKOW|!{jnARkBmL18yS;r@P!l#eNEa=>{(dt{VNAl{PKYemigRX-+b(aqRHnVMRf1ZTx z-qNkG!I5Q8cdzWWWmVRzuf8^YygKOYv31`L`h-K5cJ)MoTAFQKIJc8>^@w4LQSUvh zb0c@c=gx<-TV=Hx7koEc^UbH94_y-V?ZT{S`fr=<>2WS&=_@&|AJp;c)NSm9Pfq1u zdlL2Gqy+BjTqPWyn?6AEi? zDrnRo|Mc}&rnStg7O`FAfzz@P! zn|dth`;p>U{DadC;#bsh?>X}4wRavDev~)&>5Y~LzzD)EmewB-KHAL%5UHr7<0;LH}B`ka< z{ph<*eD4M_!YyLhMEWXx0J!vJR0|{rnyjm_$a*R2V=ynznxPoG8Z7mpORbg?dqwK( z>P>Nt(+i8lE@D1$CEIJE@K!f1$$-@)fhX+fV5Wy-uPMYK}z5Tn^ zn4VPRU8yzT-NnKc6oxS+jh12MD`kdJSUp1+#nDDP7kc3~Zi7`Ilvco1OYav>(4?s; z8+1OhYs#L}F784-l13S*QlNRC{Sl}wv=MD73RNP!3D}C%rUc^TW-!l9?Ft=yg)1s$ z!uoueJ;h~!Re^LMzHnDkkkLeql@J*mm<&*88Sn}bysU89IHi<>7AwNVTB4QkZd6h# zQGS++?`2RL3Fzm=QhI9Y{<&U%MCsF@+XfV!2ci}bfznkj(7JGKDW&mEHE3H}GaFw! zfWpG(xhY+*2N*_%t6DRXQ|OJs^iosd(%eCDo#Tgym}`?p`J*gB`T^a>Qx?4-=%v!U zkdV4Un!;#O8@djN$A!Gg6pL2@iPv}46!Fy%LXbfyMy*pMT9d}Wh0EeA6`|F|Pz-xR z>CoTUbfwwl%I5n-!{Hq#D+<0;r?8hWTW0=Pox<$GtWIIpFo9cu4e0R>GCI?DWtuLY zK2tzw8XBZBs<1Fl0`M;pIzJjmg`IYa)(=gYmZ6mqZi_Wc$gcTo+4adIP(w68gWV4_MG%0dM6k|nF$VIiS?IYQ; zMNk_QUeOpKH*Qi#+D7=dY80qC;e$G$9+qb_pNcv;9O>&}y)**`j)};iA*i=g26RLU z-eO_M$Vd`GsNU#__b3vLr$Nx&)G^Y+^ETb>PV1tHO;-S}z?}5`|F$lF-7)gpMMX5s z))ZrO)`IA)t;6*L_UHcmCUBVxZrzCALv+5?tYOyRojC5Mje>7z7{}cdTbqWF=F=4T zJhz7NvR;iW6LboN_uthhB5}lTi$<{zvuG4sm_QGvQ6T>oMfAVcD3-RM8pZYz+C|hT zO%Un@dqV?{Ndxpr7d&@?#rG_&;X(8N>$Jvq{malAz80+kjluQ8KWN2$AZiVVa7s0a zpvvJ32Cd<6m|}0IH7?T>_&m4PaPAe`E!HO@PH2VyuKkfV;o?MrFoamNMR+WK-W)_M z+9Ldw2^Yk40zH_v_y@Jc?OWmDW5$T~hvm75{ZSRI=L`)Ii}7GArc5GWSqM^PHy(8S z_i2ZzgV(0Wi)x3Fqx;g&*5OZJQoL~#cvI~F8%fX(y+rLGT}HWC5=?Ch=}&@o=>3AU zL$Ck1c5u$QPiaR#R_&l}@S7MyY}!G`v;(>uI@lmvz-4qS@lV+jQpxgVS&u~RV0r!n z?SS4?;A7i}!|C6t9WEEq4&hU81<=pdiCwa%d#y|X*J4gam_-n62w_e``ZeWdNvNP5 zz7n*<;1{DE68`JjAr5{&=8sJ~oZB644zt=0@%(KuNZ>MNJN$#%p;xcfU-juDY6r{n zGqpnk?1Utrib3m=0+sdfOif(>CAS@fiw zE7?i4gM*u(9j?3}?eJe8S?C*VqqL(Rt9DTFx5N-T+aY3tP7Gt(;h(l0p5}b9tSROi z=sbkw`46;1$&rN%ZO4C~cE~QG9k#wSee!Yd$;ZQ|ouRe^oduo+?a&gxXYi{xk1W2U zoGWP~%vO3+?I2xKOgmhsDe!sjc?TC^-XSJB3Yi3n_z%xL@D~Nz;LEBZ(rjT?`@tH< zG{irxA@1L!f1-x4JeSZAE_QPdF<9Fuz83BJFVql;A;Sh0)es}=930pD;JB^By(}}6 z7G@TIpLcEA!<_B8HG~7z5XdA*gE&7-VK`W*E`;00axH~-alM(Q$__GsOGXaeUiX^)0) z^k~jsQa%x9(%lf}{UJ?(&vWyuGfps2sbzi?PQvK;6hhhzCY)s_y9mtoZ3z#buvG{Q z&m1O3`s1e}{!ugfNf^}&_B!>BqR%Fo`EY64I-%(qcr8WTa8UflVejtx-7Cjg7{n!QVrRHy^xrHLvKV<6UnK z_rxAq4RXQUy?D5wjCTNhoj zMyICd#F$jnQK#i4H@6NQ++2Ol5gMh*&6Nfq1UsSi20RI`uD%qWtVJRJFQ>m}OP~}M zMltN8Fes7@iu9DY44n;6^L})MQ8FRiOaQy|@hNIG=wyp>^)=^;H;vY+g=m>vNPt`h zeLBvd(5Q`KfJjbr9jrgTomIo(CzGbunZ$IKWWJq8X^gT#GCv==Opbs0JH!lnz(7RM zK>9BR3Ydxbx%vW!&IW^Gv}_Q~V1{Tz`-Pz4>P!85G)WqzLfAO(FV@Y~x2wirG~w6^ zHDyAbiPq5)6>m})1l}wf+(oA?xWLF;M`+U z%S?t0wWUaFsH(r-po-UwQOklYaeWMGF_5hR6Goa0~poH43j3)oZKjDYXR{x zP6?3(1lv#)NS6_;CFSUXy6GU2ZFbB~SPAtsm>f2pGH9)c~NdeC_OYI{v3<{$nSz*u=4ezPZ z8TF|du?7_-vn6#GoU}5UHY`0HLvKWs9Wasq%nXRCy?Cx>Y)qM(u`y%gQaTl;jnUEh zGHq;D?MxfPuw_O?5etzS6{VQUf-ObuC4I5r2QN zS%g60U`5In77h@`CRC81l=>;O8EQJxwI2srN4p~D*n{q>(Q5xXK;gtlI+*FMrl&I| z=qWl~wTfh;6-ALem}=1=vBD?|Kz)7t8r5A53MC!#Dzw5Nt-nTPN-Gi1^vt41XGD7>L=uLWKiauRv zL~F~^1{E;0uOCeg?P-co7}a*|Y#GP8`qBt994ne-K*D^KL7_8ZS|Ck;DF;BxEcSzE zlvgy7pSe^kS5d|*p2)wns#&OD(Z!ZubGU$l@JzqxKic1jqYRbmD7z^&^LRR5Z4%nj zEN1llY++)p9nzFjQi@Yk|o*yK4k-Nz~0{)1T&Vu!aI<~yo@Z9 zSLUT+&Yo&@x{$G&tf?4cnW!-1hXUKs2!Y7uC0slRm_$sLNde?&A3h-cy{CMq9F zl!JU@^uskhamZ;g2BGJ%8=z*M!6?Bb1~?7}yYvL3q~SLnbIm5=SDa>l0ha#@gca}t zVFg-Y2}DdtQTK*cP-t!Dg`i1&tr6CFU)w}&u}RTl4PYgF92~AAFtP8A|K1?D0i;$C zEv-PAQ^3V0fGyg-=&Y$()t5DA>RZ~3X(>Y+UpiA*e6~~!EIL;z%o$qeL@k{bkg$do zpI`zSMQ2H&%ZtsCqKhbFhP2p--1m=WN1tPE^p9soOPv=5WMQJzu3su;PSm&58ByO- z=0km-F&k>_5L^YuwDIGgVlP{E%Lu{3N`n0^PWuYByl9P?4KJAYii}YadR!=Ao2C`Q zqD=~%JZ>LqKap&;@+}mz&a?aC1a8e3j1nMXN(CJWnJsT$de%190g4Bs6IQ0uk%O7b zOEu4Ziw-3OTR;orB|b%yWLrEC@QYNW8!fOX?$m6cNiAW0spTaE*kK%RGH6oOrW72< zj(x~>5xq3Y3R8vwrl$?%C|jUiN=rF53(ZXQ1Y-ueaF`xc55VxDi$HYkg&tl`S9Hwl z3fOUO9vqny_SQ!j)QVL5+7z*BtwxZqouO=JDO(I4i^VLMAr{jF)iCH&F-fl#R`G16 z*`ESN>qX6CJ0gkjg+MzZ2?^=ak6p@vwiYoP`#2n(HjrR5+xRCk1uJq&baplhn<>>@ zgM*oSXQU;qf&@AHB_)hp`=!{61qtwdNCOk2DfFHUy)RmqvxbM@H9~I z5m4}2i@6mKxasCmvcQD47V(WAtuv*lQL4azrCKPq<58kv&}9O?QCLsbS*()M;S1P5 z5BwOMQ$TC2z$$hhJn2#YI9LG5um-f$Y!thwa+V^htqd$*V&?}b0#oY~PKRUr`!bn+$5v)w`v=-agfOmSOC~a>#voC}HwXigTH1wB-dkV`YGK`Dq z$z1d#E}EB)yr~y9g*j4ypGsu1xJ`yy#Mh zVAq&umCIbuzyxPmF73?wkXp#h`;d7biX#NNt%i9Y7W2yZTDWv29__vMeYpPf-bDJ9EGuAVg^{6PDnjP7{=BY=hZDc@(%5=21I8IY-WKUeH zKMKN&ddK`HXrMeC5- zhV-8~uQTWM^7!Kmeqzjd{m(e)Gp8HobR+IuqRzbZUoeA8p8>PDVl(IUQOtRrcHP+C z$DG&gPe&@<6P`KUFsGaUtzVU9+XRYf8)iq7vK-FYCQ!Bs)Oz||$s_XECeV_5 zj7!chTV|x$CQ!Bsln$lM<44OfFWUr)VUj=$;Y*mQVw*rq*~(hxR#SmwcAGu_r<*|k zd(P|6_FjkAbTRLBumAhr>#u)SZC=s4fWybisQ)twkC-U@!fQPg4>$1pz;+gSQU@C8 z=0LsI@eOxnH;1C$>+(6~?B(@d53qT!`wlCI_j-otbx)qpd;Qf?z1NlS0jFnHXw zGr+00xK8jtr)P}YP7Jr*4eg0MD*SoFhnybxLp|PU4jJx_*27~x6%eQoyF&1bHwqr< z{RJQObcE{#zjo0#K8o}cjwrF@kH!wr1ccGN_9b{)Z>XmJ@=CzK(L(TCr+)Re(y2ea z39%{G7z&Gi{!ZU^Qq~#f911RRhIyNnFUF(&zu#`m-<|opv$N0b&JV#1dZ{PS()^v399D%h_T4c9)d0{S0(0&JN?Z-bKsy zGnntddiKfwY(E3r&%pLGuuHAjrB)s2G?Xv9)JmZ(x|S;3M8Yn$5+|R_p5!kv#b0uQ zzwGJ#Vw3yqQmfK$HGJlsX}0-f%Xv8#-vG9sf$e8t`x$8O#xAvjWAcCGQmg;qeg^Z7 zg$$hr&eYX02Dpxo$d_~PuN#r*MS220_gp6iTI``<|hfe5z=ruFg-Ir1$zfffMvwHFaDB* zT?X`iS|8!Y271$;S}2e1K=47@Od((6Qex@Z{B&0ZErI6I;a%ME5RIGeA_Zjskv$2t zI@@!W@(Xm%i&j@yIGo9mRo>L+f*scQR$7)c~4H5J{z}3Bvp( zreT{3l8d#c+MuIWu5hx9#Z)WRVzaFR6&*X~{UQKD%x=FBrlQ#G7wq`3$0YTjuEu zY_|xu?pbEA1xx2S=B`V<|CQ|)p&d8dEy8w-h*L?v{S<7sh+2jXoN)h8SY1XmI7Bl7 z&LLW&5_|J_CEG2+c8jpxB5bz^+bxo!?yWbZvE3rnkSgOYZ?;=RFfU3!7`3!xQJ-}v zsxV_Md{NUMVQ zB7r4#i&Xj->=rrj`@=Vj?iLv*?!MUC$AUc99#0psTjVr$i!=~-i^O2(2q7-}>248x zgSD!O&ZW`zd5( zGzQ%n!VV33mxN5XHA0UtqxJ5HUU(Ase00Ih8C@`JZ)kUug%)Wuv9p8bqKTyv7u z`vb)JSJ}p8czFlV%P9f_sH3-E$r}OuuxcVmn7DKjm!U&|XrB0*PZmI!#be!Kx7e0h zgryv-MPv)N;Ww<5M_BV^udyd9?KPU;e$S< zlb*sdh7r%HSRm<+g$-P_ZP|7qT-`^V80DN?!h7%)O zVlHeJlF>N}%f*4rg-wxaHz|hAU|MaYUaL109djm7cBMmle4cmr2AuZvshD|tA;8$h zA#5uM+X}+$Xl6$nsmLC5n}OR)txyT4TKQPU z9eRUi3>G&O+IXcx3;WIz(T|=SfS_W*2?m8S)pjnHPzk)nd`H*e7EsmZscWL7ur2B&ftrkjnq}cY;iP zl=8-pMR$UX4F}n=vm)`l@LS?bxHp9E{lG^;cY@%XzDaC5L2BZa6E~EUV<(7He6Q%J zF7ZNb%=>L93?~wgy%*6W3i~hOg%%jCQ6ZdeMQAO&8XN2C5^)Bj(;Jq5}uiOrXTF=A+&soA#$auO$wF5q%eoLY89i^h6GKT zz<8aH?3()eP{oxZloayWe{rNT`(qSf6krticTivwKZ$=I|Ca9ycF$rs3t{wOoWP`j zNdc1rCIw6im=rK6U{b)OfJp(90wx7a3YZiyDPU5-q<~2QlL96MObVD3FezYCz@&gl z0h0nI1xyN<6fh}ZQoy8uNdc1rCIw6im=ye*r2xM2%)^~gfKh-^;9o+4Nmk$Xf3x0Y zSlB4QY$#?!F|DV3O6p``@g085TAQFdK^5P)wGY6fh}ZQoy8uNdc1rCIw6im=rK6U{b)O zfJp(90wx7a3YZiyDPU5-q<~2QlL96MObVD3FezYCz@&gl0h0nI1xyN<6fh}ZQoy8u zNkLI5AeIkDnh`DjhU4!$&YfH*hsa}&kZh8J|146#5zd|C$X@a*xkPT0SBQ)>#D85< zn^YlH4ib`4@E&Qij@%=pbHRIDy3-CKX}S1fAuoM!@bg|5$pvzT zl}|{;g1TG-&wS$8X!tjKkL;2x98v|qE9BHA)t(YgQm3FUUOS$aCAbkVxu&@Fbt- zdG11D9w8HRc*(6#d*G>JK991(ko;6BW!)uQ(xV)nyVL=-p8lAZ9P7vB60XjP0^Z^9 zYkxE(zRDDdO)%*h*-$ctgxU~qZ=ZR#XvE$ED(j>5M7U3FS z%IBrKmw)#-pLh5St-pc3F56L9hzHo^Pgz!xciR z?ni<%GGMd-Ij?>7<;i^Htb_OQAmGi_U#>Zx#}j>#I!jLx(!5|3S&CE%_#IzBTsSJ+Uv$zh`xA%O*(xOt?2RPY%3_3syMoZPqejh?Oo(#|`3u0DI?#MkW~ z6EZcQcbrj;IQ6=XvTn5|EiV@EE~~4NilNJS{*@<$gaWPHp9(h-FqTWp_xD`9ab@q9 zVW?b_f=y0Usx3Kv?Z|`zGaaO$!+fOAj{%zgPXO_Nw*;cM7R@$Nq=e%SuEencE%jtw zaHN${C@I>a+3q3PDEzJkgz$5@ykp+7Rv<(!fI5KhgAe5L4rc<0*I~5F%0+n)$QD4_ z{WFNexhUkV3gTBIq$g@|4z=O}etE(>6n-S&%|j}4_FmV z&TVo))GTmQTyZ>ukna-e3jT9g2|`}X;iVHqB=0#uDTH2m!b^YgbXb?oJI<3rl`PNU z9j~_}q)I^{kf};YH^4tkc%XObF)#fbpdd~^R{)!ag4Bb7M?HwGbS{zKLdsJy4+NZ~ zok)CE4(~9EkQ#>yd2)z0iv=Oc1wX1k_ErMX+;-w=wIeVh@1c%2>WCQq;EWKTI|!Nn z43wlmX>tMYc607`_j&#Y)OIhFq5~wn#(@G}^7C}mOwx*ckq>Qg{V9N*1^5(%r zY5|#IXi7+>pMXs6hUrJ~vlz&t*{^4#ijTvAu?`RURr3g0jo8gj754#1&bG8>(rf`~ zN&9M-0Q}hchbZb!Gvcy7kC#F_cCsMO-J{sv21|3z&!J^TfO@1i5@$zR(1vpR4FSs~ z#TeGEA%V5SR|ULN5+Slr_BKcBQsLdPeEFwR=-hNvZIL4hM@0sZFA;J7WunVRV?OaA z?uQX+gxWxGPOaj|bEGfA^9B<#+KfD2A5SDb9-yj2f&Mg9{;V6&e;e^fs*}-Ac}c;S zu@G%YF3Bob&NUj2EWf#vZjX>+G?C1O+RIszpj=o{w`#ya6mqh5cw0- zjTTB7`3Gm9KuQW0o1*^gd_v`&I0mZKi0HWs=8XlF{>q$KKAXpFF7o)(vuD~7f4%ZtH*H3}V$2CN) zMb4nwyAd&r5QlF8;2SA=ex9s*B4{h5EHnY@o_WAJzctz1F;=wG?a-!ez1^wowx&v}Q#Mrc4-w{urdaoYa*|xz1syBZ5{ff1pa$qpfb(>` zeSuQFs07a`fwOZK;$w^8Ojh6(5-s5T0owVZJ8+(YhlAA$h*UOZdrmI$*dg5peF>?H zTu?sJV=@8hB_h(vIp^S_xauOv6j@n7B=RrL+qp1H< z$sTp|Do=ZTiY{OzA@08*;~FV2CF6k9&DwUj_oCKjVYC(bXdCkPnhISySqYoFe(De4 z=e}0lxd?E%G%vA3JyfSC=FlyU+d%M2sID~5jCo~3Mu?b`k5T7Ys55xjtjp{%=W0L( zxUIB@9h?J53PSqK3ZNbN4TNu@orp!cy(sn_0SR`8bfv@|dth1cIthUIJDjLN$mhtK z9SV?@Paw-SWDyM$aI)Jb6mk?4p(dC!aTqbk%eCe<06Z;nz(a51LX$w$>vVTV1`d5A zRgRSLyF%P+<>H}#K5>u%h#e)Q!6b(2zq>66?e84&s*)daD)hzE@cw*(D1f{+;S#6f>Yt}6KwJT_3Ih2xJEUELb3M!Xr?{#@|96ic+Hj z1W>xDnKy_lC>YpJk`;Xx!W5+z9Bo8N*1;@PvN$DRr*?XT@QYt=E_wcuf?B`7|1Q!#@Fs)~iyrdloWPF>dA!TTqj^04dxc^s zlh*<9>@~2@-9R)A0EyOW&Bd@*i=&xC$m?0W!v;4DRWTO)Nw8wkis!)m{^&Bf>=S68 zH&NdrZ7ZP0EdycDbp_se$|L11IxZOxAeRHc^t3s-CI`?t?yid5YFMG!5Z;xfQ2{V~ zT}sF&20DZ?{SPl|tx1Uiv(6kgxIHwOD^G@GD z>K#6NimvvgpV<~U2W9>$OpaBQ?#1vxRXY@dRu?N0())TYkAiMQqhT?g=6>=86(}MS z+34MQurmUV zC>3gngd$1vZ_$Sxk4G=)^i~1DJkq{~5-(w-=oGM@=krIuEuuCC>Ay$5&G^m0+(zQh zDCNKyH}t*^y}vj^ry}MyLgNW)398a@)E!jt@eCxOT`>7t=zBx(lnrFIift$fSo#ng z#9v<~2Swh%IOobYN;+h(1kNTd)gn@6uUM2Bfe;riV&WIeCbcCk3*$%##-7dl&)j_I z$ok105!ZCw>LZ6Yz1g!;4sr2G{e1h8ujVGoQP<#tIMNiq-SG?S*2O(`_Ku^!E>$A992bR#*x0`0|9|rWjhxn83rNj?KlR|Hiv`xb72)S$n&Uqe$?0o5p zn1F(dscKIuRld!S;0)GbI|9|~5 zy8XHKW_0`0bc1O}Dv?^G5$Q>~lP)BRMBpzHznw@R2_kxuNm5B78A^tc!6bpikrblF z)O{*RCMrB75hYQO0f_BS29lS_AiUF%VVK$gr>jWJ2>c%?=@TcUvRK z2z0dj=>UEW28wTp5m2!1)eEbUDwsN}kX?~D-oT{$N+i7HkA%ySaN=%q8fLK+Ia|wKJGAmlhr!*%CIz8C0MTh4Wo0aI!D*ld|BmT4*2sa%-&etqjnJfS~k3+%G|U5o%5Xm3^BT{+?*d!F0>O0|8titP=LCU_(=YSf zH}%ll3lOdmuI@(60$(41N3p`4sc8xxb8UpGAmY&LE7JiKN3kjJu>azf?8Ea!o+eimSO8uN(P%Exawo2iLXlThhnVyWDvn^>WGxVR&j1moZCm!NQt^t7-aiW-WdexXHO zftE-_`wzvu{s7|qF~WzUc6C3^x{uL}2{Zi9C}AlNVZ0sy+pptgjG|W7vWbYTgiDyF zMnwbipYW22(sz*~w_P4;cl=rxFr7J%gI9TO37uFHAl53uDz5@!)6)XP z@7+p+_>h+z{`u@fp8JXpekR_;_$`te7^Yz?}36RFwZH%PkRuLC8^@9zw$vm z7w42uq!Ac`gNxt2QcBIUc&GjS>bN)W`#XqywKd90MOjzsU<%ad5r(P{$F*^B?R*TF z=Qb0HyUdfVMT-JURYlh@tdJIxT3R7sk4vpVUfJF(o+wa8|A)NWou9t=^7~T{_~Qga zmASy@UKb=8k`ExQEG2zgw4^&=yDBJZLLpB_-hE0hi@XEQ34MS1S8UOmOqJgwzb1dJ*)?j}yeb zY-)WX6j5fwPXuRvf)Wz!O86RmM&Ysdm;YXf{^loe#50@YL!p2NVP)Zf0v6a8fIiOo zS6DO;+oCaqb}n5G-xA;!4t@sQ*NegR+K(RTZXZj(u=2rtqAMzS=t=iKn9t4g0J>uY zLC<&w{Iufm_dy-ri?j4=)k~n1n>=BvRy4fFaC@kq0S)za*qEqAX64;Y6rRE{yV%w{>_EG zDx&{>25iZCp%)up7HE)?TMkKiXx0bhEa>6>`$OL8@s$Ic-|FuEux#+?|_T&oD?7^_oYX$S3)czWid?S z!TJ~|nGMsH4rG08H?RRTw4=8;mpXDX9ODiG^&J8EOnZNHLY>_GGzRmDC&#h2`heWN7 z%9jq7bKi9qHlCzp&0(@0uW17(A%hE`^zz^>0ZuLx9()QeVsv-Ec}alO#_kK{WUilt zIITtnmx^6unE+vYcD#B4)9e`@rGX?9FzhfxL{ix))G@oc(A$;?5*Bj%%a?fRg_u&v zxdJ`XTn8IaBo4W770vT(n242c0Xi#MnOV-B3#MF!wL6BxD9l__qz>E*8-1()v!PRWXNDD5_L*RPnB@cH}(4D=llU|tINToyrwsa1Z|l3+KfAY>0GKfRhgV| zvn%sgW-2osm4(H{>hH~5m^n4`*YNz}t>911q$<tu6Ts^Z1GlR-?Kol=k+Bdj5ld4`QUOg9F-=x8nnc(KR`SZcK;?lW# zv3@?dP&wUps4FwBGB=Z+x^&^}TCwA7@$#keiM9<-&ZH~V>1%6K>1)@kmE&#O9G_XL z98El#UswpI$EU*D_t|8jR9UHBnenCfh1XBatd^s?PtF9DmGxD(lBg)pCo4Wavlh1& zgel7FOvH}^<*Jp}=Uh!SpO^{gx)dywuTg)Uu?fR1muIZ8s}dMnYdl#^FW8g(OvmEV z(tLS-#+7G1xGEj#lV_m08MheLhJy^uxRtf?qP46qb}Y>q6lz!37lYaI(#8i$v|6u~ zm)krc;=NuAA1rh%&PK3EAP82=D;}N3z^Yz}s%uaLmW0iGJ5}@YGt56#aOU1%-R4P`EZ<^Pm-Ag;ZSg&9G{*vPr zjF*2NBk@YM?2fwBOTNGxwZV;lJmZeJ^vfP3^MyydEABY?{a;wGWAIFUU)7y(!Ar;j z<_Ns8yGFKE@Cved3D8~LJxlgg@b|yCVxjZhbM7=P3(E>VOnv{n(xYBcSduUQ>h1;7 zQiE^!;-Wn7H@|<;oduDH7V1ROrhZ__6>0g!`8x6NYvj|Pqvb<$^$IP2V1=B};1v(g z)=8bX`u0`wy@Hn)YW1?9tnq#~Evxksn7w_S^w;2(4^`^Zyng$A&Ry0BGj+UwSH9U@ zfuKjqb*X^(0 z$XkYEmR zpqCvkif^B~eTg^TgI6CuE1nMBxrmn$3MR$xPwiO1YZ$!h@iUUeCtom+vod(~qo*aO zp*!Xr&h=LuJ|!7`Vu#$M!K)uXDfu4c#b$i4_Z&VU*$=*;s{DypJa%03;^Vhfl>3l* z?3m`v!8?fkxO*Nus=WJ8?tt!BKJlzl*FSN4$+>Z2XJEnm>+Y!|^;G@iJ7C^7jz3G& z+i%eCHBTJlH4S(BbwT{bCr{La{B2Vj>ow!2>Zwn@z)cB_%oAto=}*AADWUk9CvnYx z?6!4Ep#SPGonrv9My5ns=5hSxDCaPqg$Q9^XDK8!g2 zaN8^;#QN&T5x^hps8K@XuX+rY=Wnl45?B6=_c2#Kl&(-Lxzug%;hm(^{Gb2RGUc0Y z`-{K(Cw~6N-VDp895(%q|CPMw=h1gNZS?>1`PcDG5Co|k!80V9r&2eABY{h;rKat= znkog)2GEr%2gic7)N*RZu1l#(a6DK|EvBl$iC`tQkg5eIgXPqGYBo3>ET(2t^YQge zz|+)1a5k7rRa1+0t)!NMVlbPUNi7HGgKDarTCr;>wHjOuW>Pm(>+$tcP)^-Qv0Vkz zsp}~hU#|u?tvnT6Z@S(Hu30&{-VCl<|59+-;OaV^S_{g-rIg021Q%?4U4>6IIG+-J zvq91D)m8Y<2a`sZu5+omU?DhT^ezRbjDB6kkLBQGO8i+3jvK#p75~ zb@=^EiqAIiDT^a1m%1LPc8a#gpmZu&3r;}!6tGT%@l>$Fn7S?pXTf|bSPIU;xv5|g z+?Tm7K+_V}`QQqio(ksR#RAt^cr?$o2G8cWR)Z3fnu7KU7*7Q=$UxUJGO2Ja1@lOH zDwsx=Wv(}oZHenM{Ll2g(+)fxWjcUf*z_+d>(JA&_(HC{$r~PgFO2VfUG!JSp8olx z?{=HM+nK_*{?|ol;w4A+x_74D{qg(DL+iuO?hW4gv+09}hKFY;9o?JidH1Jy+h@2! z>Db=%JAd}z$jWe)!tuQw?|e7ymWOMUPVC**^X`Kq!^2C%vlLJ5?RXbYN7jcIhv%%E zR&i~3VR)Y6>AmTmpF4PHb$EVwf#Mn9zIzb3bHj@iCsjN+vOGLHyhQP=H6B?St_?3! zEb{c{21gc$tHUc4&-ted!=cz!|N0;(i+gS!=>Rm#Y=*9 zaHKXoJ^(jsENF4A;YO zB^CeVpI#S$!I5ct-4I@bBR7Yy1Nx>1aYKcJ)4tJl6$VRw9NGhXu9ynozj=h3* z-0rQzF}qFu%b^F3+FkI;k!S73J#fUX&wL&KmSObpXP1V9!J&!`TOQsv^vS*lM(r;?sV>TC15eIZX@q;KxD{iiUY z?<=MD4pVErGTiR(-&5G}$RRhB`m^cTay3;cm7YBm4F7q0X1-RNvGUPFsi8lgar0}n zij|KYN)P?n%=}8NYQ^J+I)?w8*2}e;l}{YnMss>E)n={Yq}o^J*K3QlIjcBD#h+Jz zw@{n6iqoo?nP08V*A}ee%%QYkuGHpgi&in|TP)XRYfDyf)>kamYPDsnD5^_kez8`q ztysl5-(sOwsjXVYc~w;A=W8>yHLJMbE9PqD+PYO-^j&6arCQx8F8LO<+H@^lg*BHc z|3ziKTDw^jr>^*7rFNrMFI_bR=4L2hm0#1NnfbCx%YQiK8OE zoxco49aW-*)3rnCK`6Kc&D*LK)y!Ixxr?xcKotkn^z@wXbph7#dZSg%(~l9)!(LZi zwW_>1cNIYi*9D^|6rj+OZ$Vsh1Gt6EaW>ik(m>8eXswJhwb^OK0%RTr&l#dkcz zlyKDrt6KF)oMzg%>bzC0QT4g%{3)iEtIk=~x^H!o>F27mR#mrFb0=ymRMo7i_b0et4ew8KzY^Y`;(j^2Kh6D8cz=fb#qfTT`-SlS zEcf%_eUbaQ@ctb4v*G=D?rY)w1@0p}FLEE@S!RMWW0v{9QMIi)^{IvR*)=BnOk7>6 z-Esac_4i(=RBP2lHGA6a&$-)Z2lB@D?X=cEzehzTyT5AB(w+Ys)v2Z0NA-=T$=14; zzJ!UCe#5D=-A`j3Z2MNsrW4=xjO>Ot@TH94)VCjzMe)XGF~3fBKPy|~4M#B3PJY`_ zSs`y!-u9_CACrCZ#v_=0C%^r;ESEPN!#q6oZ6{>Yyzv-jJ&yUh-7b$o@kC}M(UJRo9j;ID>{7n_^Ccgt)eA{QA z;qKm>fc-~Hy8X^+rOp3`r}^B|ca}iHy`S5&Zz+SD`%m0X?jn>*uFP+!#ak+nVl5`$ zQiVeIJ~iG|gK(=YzI7IUxSaakJ15oz0(b7-dD!P6zfB*RbH6TV_b!UTzQtRY5P}VO z_HE0^#$XhACx$E@4RY?gR*|IjJNMQ#1Z)k?-Mfz1b(=o--Ogbx|Ju{_RPn9c1%a@* z`inQ{1f5eqPYUg?JX=qldy7oP+_8GP_%_G4?}A@jho={KK^hkR>M3z<4R440^)n3m zwpDpSet8|STzJb0{t@?USk04fS;leVeif7X9A7rOzzgZv%SGN`K2HOT<+E>HaOYg` ztLsdK^KY5QJL7&CJ6S9_3l0f3{KJlyZFq#Wx133D$L@EH1v+OIN zI(QBx|JEkJU-wg)VyUMvc9OFV`w>b1k-4VzcUy{M=_h`_*)HXsbiQ_GpQ38 zSY`gsVP2iW_`04tjVU(8-$e|uNzAlMsk0bu7x}w_$#xEduE^gt%()8~d#6$tG5k*Q z*J1cw=I_zemH6+G)HUw?-={GVUGNlG)`O?{yT;#X{yv3yw#q%Y@^^;6PhrR{abE$4 zr!dbKxUYfX(-?qr)XanP)BLUScagtOVK`Q}UxL!7F)IDvY3|qH!&4aKH@ROAuJhON z7qb;(5EC}Iih;Yv-xHXmmoZdV_0lXZEU48t!;t$^V&3>upj1?}~llvyEaB;XpPO05{?z_4-_|E@v!Z*9N z_b8Qz-qSO+*WJ(U1Bc#o-}Svm{KFf2pYacG?!}A=E2nj@df=A!t`CN{<-PSmckpRJ z_;>fsSm7yk{&zhUD@+)q`>Iy>s&7`a!dLtlvsM`QPv)%fWnY-L!jm4_f)&1GPkwaK z3QzbaOICQ?3imBr;W0IP?|my)IIJh{?OCsN5D==#;+vRx;JOLjdY zC%}AIIE}ABK8xUw?q83qZaX+MIDByM{vY|c>TC^fwgNZSd!u8;`)rSY4;mcOuCy?A$|x&syQ8 zo;*B=Axg6wJehxZ=$I9*TVe3H6{c$Gx%r0%PgvoaZ+6lOSM}uK!BbYa;tQv(a9PbB z8a!i#ONPP0Nh@6R0M1(Bf^Sx|!g&FBWbm97&iQ8Ntx)u!FIeHMZ+6iNlfKy{3cpf6 z?5m4+TH6e!>I0cF4^gv+AL#LvH4%?|c2w5r1>z z&@=ww%|ourtuUKD6wFkt`q9DCq58Bv&>&?Bb>HgIgEJH`R8*W@cyy>j5hFJ$4_2+? zdL@MV=wQt%Rt+%iXRWxR;@rZc2j{|~A8X;!!Fj7#_Wd=$f>kWV01qx&#bVrIaLFnb z8Wqb{F&}j~Jh);Nb5V=KL#tLX8@5mN0ncs1;!s!=o*i>^7!iMF zqV|sssaUpRYPL41Qprle?7Rxo6pol}Ez8eUu^F+mUG)a{$8jv^eyVa3pM&nMRZioM z@OQ2{iLXNUS7}?sk)iu5+@HtGq5I3+U&IBX`%Bzk#y_I_i`-wud7}ICl_~rxx;t07 zfy>3;ffw!=-4|(F##5vFv)otk;^=;o`&zAR_h-1DtCj4YS4pc&vR!@gOr@hbGgGUs z*E-f~@FA+blUfYEnc4SDSuMMX9M0a{Y8Y#N*Jv(#vrUFu|0)#c*b%CQ!G{;e~Sa(&^uDv`=v zd|Nfv#4mkUEmF|WefMmnwx4_3T&&Gs{O?_(_;V z2}3DiJ|&E*gsGLZz!HX8!dy#QaS7utVe%ym!Gw93v>Fq}WWvNu7@jGYT@209VB4tf zuu&U!tNYQ=lyyHB8Mi+bnY;fmG=PJbJ`>u+eCH{&lT+^Q$3x>8oBCUhhBh^}_8XoF zZEete{n5|{$2NcckDXcsBDDYjp{;AM+ zfluRG_*S3!G;npimQRhz)q(rtwZ|rLf55JH|I$;k`*;=VZ_&ThUxwC&w=}%f;Vlqv zjd;t%TPfaR@z#sCWV}`5EgWy{c+1CILEa+r){(cAyw&6_C~r-9%gS3>-s1AsSJEEy z7Mi!#yyfPtIB(H;>&{zx-sn&k#6?+TWTg%>Z_ExmFsJ(UVEp2agdkfrKqcYkS^+VdN&TJ1{z1jnAcL)!4^;X4iv4Gj<9fB%pC(Odr0 zAwqOk85|s19qt(YO#gqo-&dKIygZy98XXz(HJ`VpU!T7+9zHG1%%1oy-6f2Sr0vmU zlr)(uO@>U9iPL2KG?_(B22+zM)nsHfnO{wYS(C}uWXv_0c})gjY#Js^M&uD&l1U5G z4PtD{D!sYaed<}PGpyDdd);7cpt}2y`36&agL^+4+p@vC{^%t2-o_op-i@qZYQ0fx zCU9TRrM>IKQe{z_5xq_bH#EF2@MLWWYh4EVc`IPYW7OYwj>75?<~~m_*4HuYreZsO z9kUMaf!a;-XlZC#?PUBDw;sY7;oSo3Sa}r{e(AnbJeeDs^#h%>!km9{g2L?3f)#K- ztYh&pMZIG}g%#iIC{HRwYmqZ!U4~%n=UB%a3>_eLJM!D_{PAb@vdzELy%+;cYLx#c zr%H6MYopxAC}?NU$;|U{#JgB@&5P9=gvvI!^*i8)^=y0r9Cv5KyGgsAubi=~ zl;_iSCzbk?-AU0tX?Ie;PuQK5^5b@QjXPZZpm?ov)UHz%VnLLp7+P~J z)?SM(*kUWT8j~%yW|JN2twwL5&cv2$P=VW_MJvY3P#%(<`)p+UChTE18(Yaq<2m^C z<&)NN5Tm+Y2@UKkhw3Hfr3Z6ag_+nwua_9tEcr(UFY+kGn`373KRkFrEh}r)OM>|D z(D|^46Tv$K^mG+d&3p<)d%9A^EuqF|t+-qzN{gEVCxaRz= zIA2sOS3|cU_7-I=ypX?}|MN+>+Go7mX!Dl-iErP$yF^(JoAvd5P!~w_ zd(n6Q#LvC+&9^Dhk2Js?|Aub}r{@3c$CL($X8iI$B};JGX9=P-zv7WNg-}_ekH+bR zDB7=lnCOa6Jwye6<>5Fj5#{_|A9H%p)(BJb|oa%_Gf6t?F8YD)*D-Xvh zl9&hgJQk-^OC+H(R3bqYG!n_HpqNN(1^qiblU2DH!o=;;53MAUy05=|Ig#*vx|MoqqNT`4Kzv%jnYJ;w9zPyG)gOt(oCbY(P=i>9kRLZIo^srQb&BxKVm;l&%}4??&mo zQF?Eb?i;25M(M!OwKZ)xN+)hjGmg@aTho%2wygBwD1A9fXI7fC(ubpT=P3QTH7zqjYMeSu1@wO1F;Eua%aqbnGZSJ4)A%v$riXmwZ@E){PUYT}`uT+-lxNWq-Ox zj?z}`TBmRFpFfS`^OC^O@a>%T~SDTVro6=pI z5@DNCWak*@=cDA==Dgabl-s6c+@>_$mK5Hm{N9$_-#9IJYB)|8o@%5KPYoxMi(Ar; z3ku_MsC~4#q^3e=RQKn%HbEc7lIE$^*$WENY5NhNt&SNDtG8*TrS13ifj*A4r z8d;D_7+;P2$R#ZQM&{%SA+<(M7NY- zO>yOkpNtc?Db_#Zl4;%R|HH*u-#n!lXNCJ>oHg!?aaOr6##!gS7-yyXVw|<^i*Z)F zFUDE#z8Gi4`(m6m?~8F(y)VXD_r4e<<@-{YvF{5}I{&m0XUYD-%zVj8@rwXaX(V;< znZ>e|*yOYoZ61Za^%INH@+My6pU*7uk$^_uC^FEf(OqjT8{>Jm?REd+SAL)Rn^povHu^q<1&HPV8`!Z{ePzO ziXyG)4`cg3@WQJ&4T5bS#q$5m9oGo820K2C-T&#%DT1v*>UXgENAA9^fZC3aV)Ose z-8W=8Zu>A6|ED`|;(iEHAI0AP^qtdkJ>2$Dto=XYbDtQY9efWzIMi8IqH)JZvGhNE z=Zq4KZ~G{A{%5-?N;FP=gv`=Uzp$!A3NQ{aEsq7sd7``xb!{*n@n(;pody~|28 z-u`<}0+UbMVb<^X=o5mkpWF>nzxx<%_{~aO0k{3PM}gnT4>P&#zx!}KJ=&#X?zbQ0 zN49o2_hVnI2Ynsx3tY~8vpdIS@u%E1E=%vR(!x)=F-oVt(fufwf7KDV|4Pq;9YE{& zEuh_hx6>fo2N-1Ju61P&P7|q9OPYGz{~j#?ZF? zL(ujBKWYWd=?_8k@C)os-PCWwi($U~2amQ7z@w47=i#IKAgt3Xy0En41F&?M4*#U$xB(d}dk=XFQL14wd^55OYf?fRjF`|m1A z^1*K*`JvmVH6zl$$&47h>!xPPw%=l=+<)f{1@1q<1Uh)fbxo{}-(+G9-ZiBOm;N9V zZs_)FivIs5^YBx5Ue)~E_Ce<7@Lg9lZ-d`t-hS$~%bL%r{mkcscV5yw@AwVo`N!_O zs0Hwjv2!;rKK4_AerJ2zH~z$X|HT_pq#ghDM14E3);pe8{O{H=!qixBE?7?$vEo)z z#BRy%y%_$zOz!C=UN)_eiF=hC-z&j2@>8#3mEYh6&Fkc?%09nBHmd(SO>XN=a)r-h zqm{|=Es-mHmK@d!8L<`eYftfamh9dde~*&+I!Es8ELpkA#Pxp{gRhb!yA*sG>v1`F zlE16LV`S5=28XdT*Mdj+%eOPhxJ~|b!57KI{X99j(f__C*@iEelcDP&L@*yGL)VY8 z6pWLhyBJKwm?(m*EMZ|7;e4D7T~9@Y?A{ruE5?+T$nKpcOZalk4O!jr$hZWb$Y8!k zhIGWqE7;DL$r7H6xqXQoU*hE^1uu~?<@m~+-53gLSEHBL8nIg4N%Gp;d9Bvw$~H5L zn|JX}du{E-1gQK!|K&@4^Ro5dJuVXr4PP2c4Sw?A8iBlNjL8&l(1n#lM8%paFAps> zS6sosbwi~_w<|;QRFoSPR|(Czp_xX-wV^5%l}5$X&KO`QdFZRe zL&L(#(3gpuhK1FkCmV(Jp~rZYHhi)^beJft3OFK$h8_(IZs?2LHU0)e2UQ4$J~1{t zHvDGg;{It+QkdBHnTIv-Dp4~xM0gtRHC1^I>*e6648y}E!FmwejeQi(Hna8Vb`>YWK-|WdvINffX6&BJ` z+b7Ee%iBL$VtFpK?X$>Ap8p!3EDY)0@^-k*5Ak!Zq=d|F`g9%H=Ubm^vs9ejCn|oe zf4vgCosCkPrAqP`Mqa<>t52;~G`^8|EgzuDzUIa5CFJ{7Na^I;CNsRbN-pSS(o(}p zzI|E6f?rS8VP2#1#EqVcT7Ug+s?`ZUXs!BHe=}SCiocn!e!1mlq57n+S*kwKa)x-W~z4}Pmov(ZAS1viov^Ofn^jmGo2%1mu4SyWnbqM}xrtzB(AuU6)3SCU2CM#&0gPb}3g zH(FH48d;MNFE!V7;H#?4T(nBp`d{F_(fxq?i2JDf9rs!Oel_@e*cJ0ZCb%O=VVo>r zm0@)R9l@Q!HxaBW23_vo{*}$&W<@9}{UAT-_has-?cWavzZkqD_{QL!!TrJegZBpS z4(<)!6uh0kZx4Pp7yygc2mitSv3sNIc5mXN;@x~!Jc84FeX)B3zZ%fZ4+Xx(-Q)gq za2J-#O7Pm?oA{CDCBlHGu}rRDhSY)=VY{3Tw)2yLkxIt(kW2UGa=oW%`@60qo6Gfe zR%zeS*_X>@KjA*?o^pTcItJ?XqJH>*-=cO|z2f?W?B{t zz{{=GKjFS?tz2dtD34ILUT{5R4|mggGzpC#aVa>g&u!hKg+jg)BR4ZTUvPPT^C6or z^P!|dFGihy$iDk(Jd`g3#)jf2QF;KMTLDPEP#EQxaZ|mcW%6c6dl@pnR7mA>*@b9` zS;Gi`1s;m3LIWQ%nX~-vLDqvNCz&B;>sX|nqon6fbn*@O0zI+`RIKdV^IKA#*=+ZW zOJ}m#OaUuStx1XI$Jkvj_HOqC_FYlG+?(Z>)XF)mbdkWANt`m&8{GJ^ZSu&FixfYZbTt|;&(~OdO zFPZ2(31SuBI74)Rn&3BTCkh4H@Pi5+ok*o8F;T4SC(3FlQ$M{T?05#YL790MbTbJ$ z3c1|C1e2kh;gMuEfxwGMxZE95l3*d3@M^+jl{j_B3^JNLj{Lqs4p^g^bx`Xq*K@~1 zB*@UG*`_FkQj|1kAVj}c1PO)iRVGp-W{~UF;JJ;|AX9$st=!|Arm{UnI%@r~ zBjoiWJr73SQ7lo#7$;bxn3{8&mKv%z)$~>+mq`qNJi>B0K6PO2Ce-@ zTaj z@1{WocJCsv#D-wBEMhdF3UC1?c~&w`ZmsUI0O=g0=fJhVReM)2zv=*-h6Or!)ICkTych(jAwl9#h88-} zHFRPVZp;cG^-8edpo4z3zN6gja4WeYtYMXaqR@mzbM+*1n8Sr|oI=c+9Bm6FfY`n( zrii&4h=?Xg^Ii^gNwbfudUit#bf)uQ(;kRP!6=gwB3^)VQ0(LYH*x_$Wr!r31r3C< zJ=4FUV1rm*h6;_%lsAk= z+1%PNl5HSt7qXx%eE%0XAX>Gx^brlHy8$2}6#iyCClPy*7RE!Z5z6_H!;NXcL6s`> zqOJ;m`bx*qBy5BKCLG{YaH80Hh8)ll*aiaO6GjQC?_QwrxP5@XZa7MgPhrq@Z zVvv~dwK{0Q6gS~#KZJ~;R-rY{Mr0eZUklk9IU>>%%?f@Fk^`Igxdh4LT{)DAwg5>} zGBVURnfG5C*`2HPi0Gg*&khVV*+E*5FYq!==UoX0)Ofa5KYm;iI1`I?fBW-P+QZjBS?Qo4lYKT4S zM&Z0o2p7z}Cmh2sBQ@If7}KNGt@+hvqHeOfZB>V>d*Jy_bVevLZXcmZ&RF99vpT?B-)4ps^R+odr;o8y4+@gmrS z0b*5=Nh6GPW&<`{=`H<}n;Q@r2_uUeNhBAp?IMF13uF?AMfqFt0BR7sCjn*&&a(dI zH)8>M81fFvJ+hy3by>8aD-fA*+QSK;YSaRN;H*hT95CK-r9*-fdCXlQEM<#{7oYf@ zF(>lWw)9VO0$Ad)t$5Lsw1tclw=(w1%Y_uGDE+lVWE=V+1gMgU!0UpAM87n!yC_Hs`)k7l@5-&XG9D!J$VF@*Ftf@$WGH&1&Qp|FbP+n3Gu z=HZu=5|Lz9`Z7zIGAKm)A-<1XgFiY<2zARiq6ypyGBO_ub~Fq5*dxPF)dFX>4zxUa ze#{B@Tu&7X6Le?06g=#p9th5G)nV1j0!|b=(2L7;84UxxhF$KAiEinYq?nO=#3{7b zPTVFSElPF66uA|NK~AO?^HC(S*1O9~^$@WQ`QFv)`qjK=I`-lOjq@m6JkoJBevMc|gD>LKnd279WU z&&+$veu7k#&VjOA0bsqoSg+?@k8Kc|8yaLsG3(5F4}AfgR^}6!V43zZcQnu3fZRna zv7i^P0^s@KN#96Z-3X%)qTQou09PponIbni9232m@4-Yba_cNE)zgL1J`AjFa$6KL z(su@3M@F6%vOGGoYdM#7@astx@WAwC`6i!vd9ZS~b;|$KxrE=@J7Y-Vu&PYeZ8I1s zp+R@=IzY~aP3GNKzy-KLw(~2D_CB}7|L-#g?biL@4L)3F1~JnMXI)25F6=Wdg%5ce zNgrp+VKeOcO88`oyq`J~Y#fI>F7w=3=E1e_zNGXcTc$P;{qHim08wC&FHkjUg3ODz|~ew-B>D1G0z2me{AI{VDJYA<~!H46{1J zsUoYCogaBxKVu8!2$TNTyO*Jac7H_51=q&y}MM)O6_@VLX0;E=gUsQb zm4Bq3P2slL?y@u==w5I;GC4(TdQn<;^iqfNU=mnh_s&XQc`)GoNM-s)89LWpfvnqd zuCq_W(JSa3U|#1O@sb_1F<4;)h2I?p1A;=C0S&gs9!al!@3Om-RiVSz1JN-k#nwPE z#B|7G68l7N3bNQ~vpYaMlP~Cmfjg*=+l&Z8LNO5}UG{)Z8hRY`Ljla&)~f|3CDf0S z^*mfNIiiYmFVxecOitL1wh?p|%vVdYp$?&7q8ldUI7V{v;SNX$VG9oBKKhhZ!%6RQ zQfru}P$rXaK%D2~49a~v3ySzU$~_@(iT9X=5@ZTGlDZWMNabw2VmGbjLQmBTL`3Xr`4nFUW2h&ux+YA&P zr7Cq6Ks(<+8;SIx;6!F?%5{TQt#fXzWXkwqfstZd^RAaL&M z1eOwG-fw#bEeJ#$R|G8LUJr+~G<|AmtYbSP9E4~=h^i9xqZ{?Z^dTVYST_|8rHbEM zF&%I~zIU&RdY+l;7W7E(DtMoM-nzkAumCp#5On4DW{n&W$Nlbo_7ZBZk>EMyxdM$L zj?ApQ{9Eb?nsWOykvv$BC_E}yT!Oi_jk%V|c56iRc0ytk^*UNS`13Ag7FPwGdy13+#PZx3nMY?B!RsgCP$BgUfb3_N2Y2`w})GBk$=V_G1 zu?)P?y0{!#6rg}4n|LS<-?Vb(BTjwwgm=Eb@EK*yLc~G9$iIg|k1AJCQ(G($B`(rE zLmga6BHKrYi2^7F8rX0zs;8eOh#;NM<(UcyN?n_`Nx+UW#3)8xMw^7po{ou(%L)O_ z88gT8z{}ID2s0DSW7Y!Qo2IOYUS&N?&Fq-Sa%hU9w1ZjRG@hVoo(gt|jxzi7s0dAN zoN4wraNmYy<~qUG^;sMM7e0hW-fHF;Fpx5K4md+xkqUy4%pod49KW&+kY)L$`&`Cm z#+ppU0S}2yE))dwF9EL-PUhvTA50i%?G(A`Rv#I)xrrVLgdvL1AlRa*l}KY=P!|2@ zB0*jL6DCndA>$d-D{$UCm3V;8%!fa{l2f=a3JT9rH-J(iM9a|05(4>B&bB*i5@iqzdyK?FzX_vDyn`+iCu`f3B{??LLQ5dewGew-i(o)2KN}|IMi}5a+9H8bTK4fZ zaN5%%!!;L-9phC$;@nGerFT&I~fRBS$7S{rmb=$yCTqx*Pin{6hmZS53JSA z9Xc9z$l0{FNQNP-WdJLbMiPP-b=p!joSiM=i!F~3h9TjRWgay^#cbCYbe0wXiA*k| zO(`#;(IPmYMQsZuqcnz+RHt!VoMK-3&_MzY)gn%tI;(>$nnKg0XSSq@1K5}m3ur4) zVo!c0YfJ~huo)RRQJMm4vo4;l{F2MX)e+At-u;NKZJIko?sWvb&%<$iAdI! zGe*NwVpx;~+XW{WJ+ChCJR=PypEWO^umiFtn>qo?0Q()ugNS%YOF@VsC0VWq_y)8B zX$Dm!E%4W4l*%@fP^7W6kD}&wf%Y~eZR6h5K?x{Jl!XS15u%i~yc~muwfBbb^Kzcg z{vn)XZ2mG(2U~I$o~4-Ut$fW^>!4Sjp;?N)(-qv;?`)yEr>8)J_oBpOrMig2%>2b z^DBRu0d#F!C{5gw%olSk#JEMwG891~UMMLx@m#!c)jv-k_HPmWHBB-tsFmDW&JjLL zb@mlakMnRC*D%{;sx@y{VpeehFwcvDJ$|k=9y zUfBX|IL7(=91E2ec2e7NG5}W)r$}Ss>)soHeCX0MycguOi&9{!xzT5iD`SPBYd@+T3p+^xY2q`m>rPSojQiUwj zY;P~;pu00WP#j%vZtj8e7hAlen5WeSZfDo(w-A!|ixYA{jrpqOV5=tkcN@>#7jIx5GKY3QFu z0DLI1g&7)^#*Bi^3JA=0V@Hr7$R$ovtpFdEoDM7v6Gohu>(N@^xw1fS#TCRkT2xoY zgEbhca&_TBV|e<-OPh_V8?K{Z_=f(>F|BQaZOY>+0woB?o+=Y9grAb-h|DL zf^4=2icBWCo_Vdly8s5o3{>}mfsCfA+pcFW zqbG$dc_p1Ww4QW*B9C`5=wbb&iaCJU0IZ~K%1c+evL8__fV>`YJ(V*GMTbRQ$XXLL z=m8kfNA>iFlW{~Emc~j=^ubZz!?QW%dRUc8;=)H76Xdx=d;Ic90DfZ^h{B-A*6#bG zH1#qg(?#0UTs`Z$FcJ!_sIDq+9*tl)Wy5-uyV29`gV3pC-VZOCbU(?P zFBVEU;+Em*slPRmTQ+@r$>+a@QREM}4&H+(_pXAyKOa6FzW8&|?I*fl#4+zI-uwZt zQk5Gm$B>_v35vNiiBa{Ch7@#%9ahl6?H~jkVVj%|-*TK+Jm~aGa?v zoiu^+)+tY?OxQ_lWVD;DF3aO=bEoM26{E%8J@K@>zisPhL!PugjRN*WYW3PhhQraK z`-HDV&egEGrjIIS6gSIWAg0Uf8f-S(vRw7rMmkH+Mdo_+-Umqu_D+U}=Fl#;brV$V z>wbnn|FE<09m~hR^1$+8+R4k7Td!}^-dD$W9~wO=HVhb2?%~A;yg=+N&e% zyg`wdfP`uE^2S7b|#>%yW9M$7B&v9TQ;~X_S6JtU6kAg%niw}*KfxaWv_Z*^lO6@Qrd2t-^8GAj^)fC+VTrRyysbC z1_KU&C1N*!8Cye`-oLHDj$^FI+5~f>L^QDP;?uMMC_4=EikFE6{Dp`{1K_gjrU1lr zgEXn|q7Y3)52Op(sfj9s?8>$)X=3uoR3a+6IehW)BBVSgC&z|d&jgPE2H2dUIPp=R z;VFH?7ck^gE}&$nk51izqeibeaf@J91QA%Ry)*QYHdBlWQ*3Bcz0xyKie$7k6YI4t zo;TBKT4ce~++&n+j%S!mL{#`2*{>Z;jSQ6g=3J$^6*O&VSyuKH){3~tBX;5h(NeAn z=ZK66Pq=>pLwz9^4TvCfz0Q1fJ;yxhGA{%SC7sO#wg9w98Ci(-${0-T}C?3R$bl_2*LR($MP&VrwVW(vHP;h~;n0 zrlzI<1$dHC)WDD+tMjl3n}iYPh_S5~$h|zwK?)D(OTmIx8b?eK^EAUF@n%WPG8?zS zCFnN2Q%yx26eLIy3;}10Bmu!#seyz=<~UPn2sNILqiTn;4L9rz7rP;3BbUsuP;VAI zf5j8v(;7OI#A|dFnmN>H*Oom%3kpmYdoKwv+8{&=jiD_l3lHsUTzxQ_S_*!s91j4X zJw6MZ=+zTGsbn;AG{n4vF%9g)?s=In0vBT58}fuDiwVol%~gPfyT~TWv5lELWg4)=XR4 zt))leYoVOQrU{6WY|eU7N;$$$0)hl~1^n_6sYFzKC0UQv79tJL1&dRNv_YHKsR7Lf z)0*)fivDo3f1YCfE0G4~QoQ9Ri%A<0sUhqC8c54y>rF`8nb6GRby&?SacEI~kJu zSp5@#(zO_^6UNH0i|ciRFuP^rLZwX+?P?(79jc(gu;s?<6y5;__du4mec)d1MTypK zBM$1w=#=8*IHLXO%Dhc=59s`del}MBl5?jBMcpd)W(VL_hGH+kM%h%-oxP({4`^=h z{4kVhYk8h0U)iAE6X5&402MSlP_F0vT$Dx*)RzTC67%`qO-;(U;0{_y*LIEUPLDYTaQ2K{(?(A=#`WqS5!)F8Lma7jYGHY>C>54^g0t{WAvEMRYsPamK(@K5041y(jjtlol(t$p}?N4=Q!FFQb#q$EaY2kXWn%@&pjcl3oi9yn+VOZVC$P8B+t z;TYI*0Oatl+XpYU>1a`==yoBA{sSeMyz&|I;Y$=8*AX5;#+%<*&%H(3Ok^eC_p!%> zuPS_*&bT@_kRR5%$>m(nNne%fGp`~1-%;SCkoQCQ_Ng%+axn+US}w?DE_qme-6RC- zwTGZLd&CBjAMJB~J0i1OAEWW_I{XdPSzfvy12Hy#V`r-ra$xIClfN5pnrz8&OO9J} zU~3Ni?>+~%PU_7xmH*u(yM_PO?zA-rw&uXr9QeC22ewY?t&{ri#!TMYk+$TxH3zol zz~9w5z)Ags?ibxJxc9h!@BSb6?%=WDw}XEb+{Z5zJs3O`d_4F_@OwdlyXoKu`BwdZ z4*s04)W3oMznOpEve_v|{ZG0dcYA>QFWob>L^RMDd`ETNP0J2b+4buFo)-&#Nd@DcgR!OIxaiyR$ zcqQ@EFYt@jv%#wp7`&J`O+S&BJ%p7GaP9w?dyrTJInh>2@OT&Tn8~isx`$n`Z;bnq zT_nR=)64ocw}1R+&h4>w_HJ?sU^I0Hp5-~YdLu-#{A0q$RZAGxh$bFjCCvvXB((rBQ52AX6bd&)RgCO+5YMtC2f zw0oRkcxQ}GjbTX7-bW6^t%vCnYR@$g;i+AdV9@my7zG}6xBIY$v(8Nej@)`cD30Wj zq)aSKQZ_=8>CRG}5qD}tP~3MoDYcM~5C|?ElU;7-?#+2gCQ>|>cuROS9!uppml~_r zk?(6-}cxdvk3-RpHio%?tppuaR8Q7V2I=o;CfT z>5&N;=6NJsqmdB{NNL)&BH5;+XKuQ*+l9DD3%4k*=V7p;Vh zme075lgydxJ4;}0LKn6qRfHhnz5$5_VPGxJ{cNu3eIae^;2@IT6LTI=nt9f-!HfcN3!8^lvXWFRi4+HFvca*aoDbg&xe+R%q)toXfWo_in_^ zUJ{IV0lCe_W!og#SsG(ZV`xxKeJavpek|z>5)o>f$H6`)BQbl(ym@H*1%i>rXj2l& zl>jGgFjhY)3w4%Z(1l_lrZtfw!Rk3$y}=8Ii)IcpA=NLDs$w63V^+}L;5X0} zG|7`|427~mZ((Q>tF}~Z(k~vpo&2x^{FWo#Ub9C*=Vh30af-=Hfz$y}p(roJL869fE z)gZ!OR1k@;i4=*C=3|`nx@zI+D$Pe?iNz;)%nOOHwSNo3k@%8OBu+t3GE`)Gq-?u@ zj`YYzGTQY7(s(3_O$Erd8jf}VDd@z|O0mrqn(eyKeC@{s9Y<>#-v?Toi!A|IQnHr} z#PM;40c^;?172d(d5~3?+S5OdPAHj)gC%69g%&bZvs)H%#3s$NNy*#G%_5!xc)GnQR(jpL_j_{~w6N(8LNjJ5=yfhtRnB-dn4U-a>r%M|VZ{Jru-&8&v zD~WN&Xd4@xZR8{Ec|X40n2CI8pnE!R(;>>u5c;V~gIfM~qiHsmNk7tP;#h%ncLD zCfIK5Xn1Za5!-MQ!;FBVj)l$EjF?j56WzN<iZ@9pi8SKw9st$1Y1mV6Z(-*uvtBvwnD+G8`qpNis{mXS39X- z=6G-kb|r>4ou3uG5nY|4Mo*%njk>8+v=PNN1>1@3z8D8>r2_5@%VEpuj>am3aPy5! zTTToap-@hb+k%PDpUH?_UM#E(>A})UV17`NZf+YE(t&5exI78Fgkm7eU#^6BLu+>k zvEf>G25*KJ!Ht#<``Vs*Jyk!zDG`ile>OJIU)pJOT7qqRVYNU{@IHZ+39T&^VAG6V z5`dTp+f5wp^gx}W+S!aye?+*Q@M|;qK^Wes-DH{Xt9NlKOQmBQH)TPyM`}^zM<{XF zbBt(n42ST#rw$FyQVk&yXrV?2yFZuA>qBkqp^F3sVz^Cr)NxR-&C7$jU(;k)^c+GA zsxS$)K_di>Cz7OHqxNkC$*vmIyCRm+u?0;b4H^-c@LY?_R^P(UNDVZ`!0_#@=qJ!< z*WXN9#%(p-q^n|Wm>r8R{2N6KND!Pq<3uzua&B%kg?0A9i~G zc)u(ox|o{At2s!?8%)A5wBT$=S<_U=f>T)sI(}rPJw9=vWQH!1F?qgVyvyyDW*5VE za+!njwn?VQZp|6(pk3>AKQp*7eOhW%#1NbqGM4vYziInyqLYPh&3y9&&;(;61q5F$ z8xS06h0uyWNNpnM!~h9NClEA2ck%iQ{EKPvbFO{g2$v2?4GHl5S1v}ANWcY<*y`NK ztkgI;KTKytDbPM?Wh_+88J-w}aeJ7-#8G2wav6UT?hPSrehzL9gzg0!ix9#jSTnE2 z)RpP7pT`Gk=Is_g)Kf00NG?K7z^MnRgcz(}8}2jn`Sp*kw7tMj{In52`{C!Vke>(%isi59hmze1e(q9i#ztT`k6wbW z)<43ZVWL^RbF$7C!^b#KeHXsnp&P?x6V@821Zx`u16NqZ*imk2?14+uZsoA4tBsQt zO=;&iyu;zuj>XWu$HCH|v`3Q--pa$dTT^70#1@?-2iTR_Ucv)AIG~UbUJGE;cWh_G zJ_On|$%h`8zy=G(?Zc+gVXR4v?ZKU-Esto4-O{E8BNFp!j2L1Zah+x{kT#s}8mmhy zm#~abK28;5)sFLkh`~kNXM!a#5W9t60?#%*Y`9>Iwtlmae#b$x15Ql>PMXO6T`sGWnJwsTmS6W#6GFSo!xqFY`4XfCOeTm->R_;=elJk_xkni;sV z_P{(p1UHQ`65nHBb~F2JaB8|ZQ?|>y7sG{3yU=b@`*&%B#61&?NjMU}`D@_1byhSd z8lOc|LYaz5(e9znh&>4lzF9S(c7kF_P6D{1mCO>2_%M^iQ|oPC1TOBUI7I?SIA(BB z`dd*loMYTu@QM0`Lg+vUj?n89;q+T~97Z+~KkWWrCO;_Gr7`R>RqA8>So@}JWn$=z zloHqVTrEA+eIj-24{rq(rV+*|?cBW4ZxFXCVJimXyZ#`8WUMh-?C!(v{j7LGOWN&s z|Gu?S99`KYqUdki{bMW#I6v8S8nj{2o=>}Tp}hHc8Z)2WFip&N=aaO4+X3Lt56DLX}~*AOZzVwSd%tC)QvNlGbhcw9{ZBMwPq3i$m#&7 zwG&W52puw$NtkCCXSLpddBg3{xXdqv==OX`KNe&0{I3zH1?iJuU%&z)DB;i)Cy#rp zZTEtpTkxK}Thj`wz@yxZI=cfqlFij5?oEs~N>R4uf<>oPk7sbEXi=!~POlcm=duLNkfg?rG<+@t(bm>&|;rI2X zDD+%Y6xwl0M$v6LL_lGeP%zl+^}8vv?RUvb#GXw$0K0b>m1mpMFm2-45mFY`zmvrh zWfge7vmrww9hoO6EI#mxPcEXdnT|BM85Y&m$MxbipllH_+S)^ZbRuxeG_V+c9QD_z z(UY-#{Ln@;kjz4fUQR_(jJc9#Vxv84X^)JvR>N4fIE31=2PHrjloT{|qyuc11*|x@ z=6oDG_XwdFskxkWQJgsu;Z|=R>sSVwCc4c_&Y7+;^c1=MqY!?G2OQJp-V&r%=0LHYRm(i@-Si~ zDG||5C(Ic+1=xeMYId_~c8HyO6p zVwV3vXRm-z3|VTbzJ-aO%>LTFsO8+}0ZiZeS!5VCOc!yBYhT-J^EO)6n)AM}6pzDXM|OR+=NSo#j0< zt4T^Zt)y-ClTMfnpL_0UOSTa5l?dHtq~MlKycH7j)IAP;C#MzsiVX#oEcnGvD4i8lAM9CkcbXOdL~$9j5=5lpvsNYGSUIIn#p zj(Re>?I)gX4c`@I>xaFYXs<28V^^`AWMiB)#Yx$WH<(G7icN{}BN}f1rHzd?V|)vl z&5Q?D7+~Hk9-R!qH-WNqM$U;b>HR*o3a;XH7=VT2=s7bc|(LWwFmw-<6%oh+*O_+jBS3p8C#oLZD48` z%hfI!g?()pO-2j1HgzZG2a-Q0olIfX4mr0XnKQT1Lck(5ro|l{`*Emp;i-XMB9;;lwrkWwc+4m*vjxAyo(5F-x`5UfnO5A2u?Uf$Jh*6i);=FB3cC=?aN`` zn4Vj)(vS;v0L@F*bA&oW!zqAu!OF4E$-+?F($3_@jD(Z4@&QX7{moKn5_Jf;9VabJ z=;=v~n0YbD_K@V{IGnUr=(|3A%E)kKV;FJ+5(Xw@<}iles2N1g`|&{R^S zq6q}$o$N8=W9~t39qzW1D-H~@XNdtatIQ#-0b!L+S}EXSHAJyAsgOcz;)8dZC5^zF zoF{4kH1*V}wIOK8m$>$boodI`T0=fnD9$tQlY9D_SLl zw7>%iuL{WSGT4lzgM-b}FvM9xwO0Xj^hB)Z)4+#^}b0&aD)9#XoIKJU}%a%vB|+DF1b8*o8Mv5 zG%<^<0oEd4IKI2^6xf``=7wEL_U#XYYDOMfQ6k6&GnM<_6oMlHfSpauOUPoP>Aj(* z2pJ0`3bc7qM3agRwzA+^6bZDkVGEH!c?Q5H5uyXI)i-m+jQ%hHXf$Z+w_bve#t}vP z%{Yrj0^5pkqIpW4x#HCXQXPIX0Rwx*VDK?gg36i~t{+09;$B1z2>`6gpKK{ydDi$8D&R+7X1P7s}Z##0uu(I@XP9ilN(btge35O zw1l)6UFvmz8Lu5@mc_bSV@(*X*eI|yYzrp+2$G1Je5FxPi76FFxDbNQq&O&Ic*2JG50>>?W)8ac#i(s+IzUG-_-`NlfT0|{~8!k6Ro!CFZ=9OfVBpz{u z2Ov>sX4&1Q{DMigAutXO=)}}!9E|ND8W!P%oc7J2>$2rWk*f2?Lf)g5VD*xwNVhnR z1kuHh;CR`$25S6Ujf#mi0yQ+{-9I~xE&f5dB_2bfskMo92F`EBQ_v%RiP674s3`^O z!(pSK0KFroiX-MxNcDS-jvl_NzEyIGBDV*$GX9#deUr zGKfIphzXNi@qswF(-ayp+O!NJ!(FL%=&wow|GeWyi~)AqOM1x&g{OoXOGC7`?<|6WHW9sr z*GxnNB+QC~i0csG#}ErN>0~++4T&+AT}7aezp_7f>V;ZF(++Q+Cn-0%oYGAJ1gxdx zyI|hVW|!fNjeYGxAQ>JIbuGPQgM?v#WKZGO+A=}7xG45(yoBpst_wKeLmvBa7olxw z;t}v^0%pG-tS!-elk`c3IAS(QH}q^GKo#s{KC^bbfEvpqnz0*S6N9zhyYGEPQuu^2 zYegs}eEr%h#=B~+(asbQZGDNBuAfa?3XFUQZCDYuRxivv8P#w?1FAV!brVH=0l~FZx=fr@pon6Oh zk!a}-z<}s^dj^;{ieB=Z$%?Y(a)?XLiZY6yVt|3!zyRxhI@+<4>w6p}e3#yvK##u# z@&279n^a(7v^QShiK%b)Y%gG2MDGUy+AtGq*eb^Onn3vGQ0t&Eu!NH^B3K)@^cii2 zvIR-%jKFLl*}9)flB`Wyy%gNqrHO;l);fAZ-b^VRC`}|Y@uT;2=&lLh;)T{4ikrj~ zhu+}EgZ45OgF^4}rUdiAW3Yi<>mAc8I_2Ay;QN^tS~w(E-hy2Cr65ETy^I#U0u$2P z>?_t!6~--Ma;*(kOw@IgHT~T3^`CH+sL@|P}{7VU7Em~r}gbY*E79ZfF)piTHDkP<#% zUqbKJo+K4H0SB#%CFW%g>WQOG6j^UoH&GONQvH0!uHL6N3dr*0NF(`olGn57vcdlt zr{_02AscD$TI%KzWX5>UBqW;Ok&k6DiZp2mkgjFoVz>3pI9%d~%_BF1w3h-{itVU1 zRWkv_P>H2TC+`yVG*7v@!hF21GOyDgEt&NAdGlj}VIwKtuS>MBFex64n>~rZO{S7l z483*SwR0XSHK(ZuywG_>tSD~Zl0q-%Y7QM4jTR zN~GN?YhRNEZ6Wq}dYk(}cRdu)AL7l4(z^c!>WuJc3<&sIJ_PrFNZT#1WMc+KuIeqG zZ1H4k4s6YVtvT>FHwU&(<96D}){Og`n{ivb-Qw-m9N3xzTXSIJ9N0RIw@%}~jW5@4 zWlu%ku`S=k*8JR>1OI2t0Z!vLyB~JH<32(>Yt(%#cxmu6!9NJH_CqN9f}afD8hj@| zg!1;_CxU++d^Gq`O8aR2+#c(1cHip0oquoQ-@Ps$q}-(YLU2#;N>_3hUB#W{U)?Rb z_23om3_pBQBAD><_}{CZ#|Y1b!yDbV;qc$@e#3p#{rBJ{!4C(!pyuBNzYzRL@Q;J< z4eky85r4lY_&)w_cWXhn`!)BX_}_~+!Ql1od*RnR_$1VixgT;P!8?N&xn;QXuHZZP z`Iv7HUKPA3cwO)<{AkR*!5u*=cw_K#evC%Ec$LezZ<=x)oqf4n_G50@{m=0J8TWwe z$mVi=o#$ODlgkCU%%d*NPuKT8OG;xE9@H@UU?$A~_qy0cl={byEIXM(yp zy3#7B7f!j3-g3R%%bN&U9%PRyT$NeRy39!+EA+-#j7Ww)DHsnaU|xe%92F5Q{U zc0bw5fYmyK>IpGa;{jnofzJ|18V~?D0x$xF#ctqc$e#BQAsXY9mzu^ngp5<7m2=UzYe?Rh)H=ezcv`OWWle&;;T^}V*^ zaPHM}<~K8Yuf5iHuf6u#Yro9Ilq{gR;$CEL!_>>}tnt1fJr9KvREGPZ?tDP%@ytB} z?y?EiX72`-v}cgJ<_de~)LEa~YJujMIe1D(a)HDypJq0I_@-$GRt-#9VB8JV^GF3x zkl13#g4br{vtVM>FFdl`32kM`Ns~Hv$7Rht-^`;eZ9c)0a@lVnN*ZmzHwP2g^(QP9-N^aXcTGb|fsq)Xe^PDFc`%{p9rT>z@EuU7+l421FB)q$3+L* zE^Q$?(DIX9#TS&#PDsAX-%oi(7x(%s4+ z+ZE*qfDPNH00xLt8Z$Z%YrUi`WZfuDX4N!Dh;u(3svW89ZNL|MXktjOl1AA*4KANp zA2G-X@Zg}~0JBP+X=xk|mydj7gcjsk)KNWhRJ4~#az0=hh$B)5RwaB_k7rgkwvj;( zW1c(>I*44`a(SGjs;w!FX3p$L153iam38O!*#vloB7E}D@gO^&j2zLcN zmY}GR@gd+*^xxiP~O8mo-&IGpX@%FB${+R@xcq0Rq@V zJs^mgNuJBn$$*l{D&h`2928z4Sr1ixipAy@#_y@+D&s1BtX)lRA0q%1H-LKgs#s#B+~ z+cENdP+}Ky2DxD$F_O$dTnwmR=%jm?Ni`&u2N%b@d6HP~!w<`&+CZ$>=RgFiHAW>?d4-a54^8LEKv`#1zz`#MmeSLKF)RVL=^|b9 zN}wbol(#5Du7)gRoN@`-Nkx32D3g!+mT?oOh)16kIBj%=fdYLVDU!;Q|IeMUSHTnt z&LzLH1Dpj9?*n_GfL-oV(iH|DLk@{cZzqf;po~GQ-jYR|+>!s7iwJ|bluMP7tPXVn zGr~>?kVw7T$SsC2j>2H0l@^`RLGtFTHBn>1ey_h`Phv{!h-{5c=RufPufOmUndKtM zou|VvM0HOQ5z)t5S}HtS!;@cffLky3At>%Kpb*>@uJ}A;UUm;=b>z5TDI+_Fb%ByH zETx%1+#fQdM3?UKp%VDLg)2Am89>MZ8(>a=J`G|?Avplmome>fwfFYpl&LX3(13YQg;fB z?N)6A`80?R`W8Lfb^!xDR3|7qEq%QX(;8coMf_09UM1kVL;JA#f-SY5%s6G>NiMg< zb(Z=+4JavhnQ>UK02~sshzLFiJE$-M=C9iFQuGm$Ij{Ft5CZ1V>$*38(5qPVuaRVn z#Bipz^aW>1L)EQ%CBxvUMpcVVU5x-pHWKg}Bs*Z36(FFdb1F_H z)s!p<+Q{_@I9J1_{!x~jV- zl0!XfOqY_PML|m{Zl1@E1ZH#tIb{!qY~?HJ<~f+As$8LnOvy}G!E|6$8{!2$1*1uR zbUe6LJ%eYe^!-vDvA_!MjLx>n^E+3#gz@+#!QQj1p8?lum2D=)l$nU&N`y(Gn7<@} zV1T^*JuFawj9{!687GokHq_Tk0Mn_C%wj|AD7BCGYIL$S@UizmA!9?SmTSFtJy8)W zh+YW$APo?6>X9Qwl2fHY+~sLt*BUp~c+Ox@YESg1+QwN7q3Z%t;{%TYw z*yujIBol3Zm$&L1mAtzTasuIjx4;D+R@_VvfiXvf7W$sF@mXV<4HXBbBg_+m|Oqmgc{>R7JptwiDxycYIwGRfne~o1`oQ zz0gQ!QgYvjgdF`HfAyOJ8vwMZ45aKCb-^fJy_cO{w+5`)z3xe_&!6nlfiH=W2;`G& zvUo#9*YAmAU&VVV00!_6&IW=KJZjLaRs&k^sY3-hY~Y3@!7Rc~MTTr5Q=3OJs7mdi_R+uhjF<>Wizr+)FczA#IGl` z|2j02k^oW&pBYsQQuQLB?L+@7k{ZSO2eWF4GOJf;Ul}0bfwn;;-fYYUEhN&mFqM2W z%t1%{u&Uul7~XRoRh~RvL=L4d0vk`fE!hh`5Z|!^I%okI;zDZ5%`DUTj#P0;TDxvQ zgYpvhx}uR$%{+D|8;Ah;l#D1*(q(8?18)W9?WOr{<}4nI<+`YdROV?f4Z<9SI4zw% zu}zp9aplOtMy?EDY7T7bAUMJCNYJxFrTF^S*br__iV$Cw$)gEejHP-L492;q02)9D zg}!)LAhSWl(J83U?zyvSoCzhK4}~@GfW9nK4inWRmFLIGm$e>hD2A4)7KKtT+SEeI zSjcJ=%z$K3TcWdWoQWTEU{H`#2B?$InTg=;Ukr6R823sJBs9v_%Vz2 zBE860gqBkZI`e&<5$6ucK1#S=QFp$=ml1~F)kXSFIxD*&nm-YKx3K*KqVt5`%lF0f z92is71pLeVb8ubpt15mY%m!3c;Y#e+fipzrmsBsu34%xNXP5Lk**nRK$4yeCA7G=> z1O930)O)_-fBz+SSv zlKp5uu*pOVPA?0WFV+23FMtpi1MzW(^2=g!bK&wA!P=!nMR@X@J0nZV*%~e{ zFdhLS6>VwK=f4U9Z>I#lLo?-|M;AE{rkYeHrW%>1 zUWmGuDHE7vWZ*SxVj~KAF~^i%l8t&9j8{@r>Jl+!@*LCyZ)FV;TLuI+?PFyoxjMmq zk<(mU^VQf~I%10DgCPC+<2lM&Wxx+U)@1#kYP znb+lo@#IF;e&nLhx7a zc*nKkt%Z;gf~aPc;h+SSZe2Jjn9i}DkNK&<{LFkto5LEF0OzO>PRhZ$`>zn|byX?XOaoBsaWyD9T>V3eI7e zzP4+;+`Ql=AvT__g>^jz`Ld`6?mc;1TxH$U`34MT%E6topg#qulTDSm7HOO{tIO+n zK*6n)0s$mj6adA%7&0bj{DMy7XazQ+6kT*gg4*B+bYLM{SfF76Pmd5NM7vG0e<;PqNmmXIOiGcA-{Ae zsT*>jK0A9v)LXY=3D3ZkO-vN{6x32qrDF!Jvaty2L)tj!q%bX|7L=MvbG|1^L!yr7 zDgdqmD1xcPj%Y;$-g3$`!u_7OmM?f_p400?gFog*G zSqC9*CYce^3z*zS^`()4Y3MpSjID%$mo;J*F{@025?}rbB7QIZR@wBIK8%0@*IPM_ zg;mm?Q%iGkKu4(pF;)Cs#l&o3K)Q^Ru#+)0fuSe_CN-U-j#Ae=G{67F6wjYi~wy4`I7C!_=D!oy4PA?oh?FpM z)R$s}!7iDsq@Z++u*$?jsAExw!(D8vgu9fISzmQ#ly)Tcf^Fm^%B`WB*imPpq6bKm zU1r$I4ODlm@=*5^pjNn1Y|vf->Ple_k4}9F6qTytu2O1^N0A}Qt-{2)%&_Dp1Ig{W z?|d2_&~e7T#|swtP=`$FD7P&Hk<=6hy>eUCMp-~==}ee^iE`V38qKq=wN=^VMPiv& zNT{bt@(#XuHaoMg@NpKsXAIttIBp`5 z3lFu#8XB-~F60Gk7PVk8Kp_YKsSMg-+FUD#m1^p6T)sS~!sTLII)>B2@)Vb;x_g*s zEJeu;l{!XfC|s`GC?0t=F5Y-2Z(N?MMqpmfC(Q;bQ4I(f;ZhE5SXD-gMSh%8Mp&XB zjGaN9iB1roQ7c9OKVfDWl?qg&Y3%b_P%Po%GDa2ESO(F#Ums2&ZgrC%R& z^noJn?LKwVirA1BQ9_13yRlQSIb{%+jF=+~j1fXg)JUEy^`pjM*ij{Bgh@z4*_H$( zv@H!`Wvx)*r0i%E7y(y9+NbJ?zt_E?Vr1Q7AqW~ga9^F)jI-6fDD>c9w0Z-h?3(w) zD_E|Pl+C5zbrqxZxIWv0Lf};5NhMABy!)!G5si?8$u9_l&$603J8xNBUTW=aQD6k~ z2Zdvu=q{@}<=223sC?4WAw<$4$e{@nxq!R2E_kJY$9+cq2c-q|VZm<2YUo6VG#4k5$^>aS#3e$9n_ zA3xxJD(>}ohx-}Y$z|gRr-yeRj>_{q@!^q)bCe3zQVtnROOM&G)c`zKY7Mo}b_TPI(Nr4M7SH*_3aQCRb94CzgNNh;qmdzs(iqK#u%r3|8K=mO=bhZdz>e3nhrA4X zj9*1kEtI0aVPScYI*b-+h`d#xO@_JQpkrF5)57Ph*7BBC8S zo9glW_pS7EwNkCdjwmSiWBLCbvSn~KLbK!PC|R-Ao;U$T74JOag`^WNC;9-^06jnN zrmPZA9r;J{cc*wVurt|o_|mXKC3$i7Yg>*yHn|XV0(_t(HaJ*S;&h2AdXj8VVeJX7 zyuc)HYLR(QC8SC^LBi_mBwsa!sIO_@OQRb}(BPD6QpOdZ#<*$rh3PBXrUA|3vN@}% zrw8uim}cf!f)B>TPS|IG`g_SnQtI2L$1e7 zF6AVTA&3JIQUyxmc8im0M-K%tPw1(iVH}v$ zEZn4;&~VG!CK55*(hbOmU8YeMs_7nca;NfFj_W{1Pt%m^hh=4 zrl^uj;7KPknH8i6AnA>|6-iVHZ5bxXB4wf`HF}QwD^i|N4D7=@tyFAg4KubpJ%<%oy9)bLC38Dsrji2`mLI zjvGJ30LbB7@mEk=2uM062};7X+Qw)Cih-JkwQ#2~!CiO}`3GzG3Y!Q3L@O6(M~!q! zKS?4RX%qaPw7stAWX@IncgcGjvIXu6XO&MC}KrcL$4c(P?2ibygfp8 zq$|d1;qyA)dAefQmnvE1PM_9OA=*P>l3^7o@GyuYzx13cs1_Cql+DVd;tg6K5(H=ZXhT)S`mhX?tOrhJ78JDrzN*agnx+zqnwFcogQ#4BiD@;X-`GV z?x?jGw=YgWskc28WD6De6qNI@g>ngzMnsjm7f)a6tOGBtTF+|*%*pb3$mRED|7|W6`{@< z|A*3nu9+`YE6`B{PrM94V?;n43WK1++V`+QObt}cnyV(?1`?~zNz6K`tTB@imR;F`z~6319YQ#OqH4TOfUxAm}&DNtm&iYw~p(wmwoj9YnKWisgZigz{b+Xg1D~6PiB9FhkXRr)O>2JjoAZc^G0# zV^j~e^WkX}j`V2SZZr!m9iqmr>KnieuXx)IX|)^&Po8$5s_R1=)p)}k_hBZAi=hfD zM=|w*?u{BJU7Hq-Q(H29a0DJgzcXrW>k|QNwH7kFR_(C%)u6Ga0ocm^WuT=F2)V+> zfR>w{hd!K$5cFZ4)8$q#S5qgz;Wo)3X5LJ|&(egfpqYzv$Sv5Zy{dtdYBw1@T)>E( z57CY?;k(RJAIggN)o0ZrrpSCV_r<-3K{jW+bH=S#ZERR9Xy$HR1JY zR+UJ7n5hoG>jgYuYT-exwBot`Wh->Db8d`*m=s=MQXI({AYo$`OWhw8c0G8V=)&}f zKOzWA3-k*)6NRoe(_{4)8#aNC(kzk>ptPq0>@<+(ZSlPOb#XG1p9-;O`W<<76`dP2 zgHNao>i#Sv@~YlpK6r$JI*EM*5UjvSGHG*g2gUHXKnLR?hyq?|WMZHp8$7!X>}VH( zQOMQD(5Wu2^#YfMn;5hbspUIzK}hi}^jfY5uHS~&0QKJWBk*Rv%G%K;S!#7?2r2^c z&@mWQk4Rzb9t4d7G=tR?8uObUX6PaDs0o#f89S2CBUlg~p}_`)1TfO?M=lk0ux>Ai zZuDefu>ohgCu1FeV}7oM0gzLyM3SOp3O609ozT2)tg=8i!vlmlu|rySr>7q;B!r;L z4~HjvUP;_BJn=crfv0pgN4TANmSI4FN>;=Db(q8a2{*=Qwi=_PIZd*y0uP@_25kYY z)M)?={ly!}WwIb7*$6r?x|SvKxh0_No&hyW!)+le9|MDQGM2S^35wcf?bTLBM6@|G~QabtOHR z0Xjj(czwwsoHvPd2#JRkpEJDI`9JYClatgPF-l@Bx?!oW^m{2Y@W6mGqm?soo7_A2 zP1ILQ@q-j3=470DS)+f(Ooda}H=LKVL~hIcM_3wWCuwCLMl`Lu|8X=gtnVkPYXMfS z&}wo%1)VC=s`(JU>zYy^vEScxKWMnUANtD@{MYYEnCIEj{;e>#^;3>crg2POK41dK z=0<iakL%t^%6E_pRi@e6nN&aPehJ+}OQydq?XX`Q zXjE!K@^6y&9{{n;h>v;A-jNWy@2YnzGumodxl-#H&%0mX{qs}{bz{LB>dWQt)kk@2 zY~3*_GP>pjDHY{^!7*o}LtJcs=Ln;n5kj%gr`+Y)5nps4u3m_}3+_S#faAcQWbXsf zR!K2DdQ^%i*X}0*L@Jx^Bp%_mp{E9g#R>EPs-5RCN8agqHF|Q%l(oWB*m2)%DZV2D z24e?=JX}1&Dv-W@RP0i90oEss5_q9RznNYZ&XzD1v^OTxnUQz-%rh1BE`@g)`%sfHZ{e}c;(z3$7vBnMrlH@G@Fz8s>!Q?xOL@gt9RBHv@ zfuYFNP<)U3X}4oB0UiROSS;&)fj_55@uG97sN(``@6g2zi>N>Vi*y*@7d>WG%aOxI zg=E0#f0pUD+G&Or1BgMQhx7SbPrU5ty^r@FP`=6=A9-~;JKM|oay#*$h4XSaInU8r~DoN*997(4KfzV=*g~RI7jjUOOjxxJD1%c>^(k zJT8&-3b^4Dto1l2O~g|;YVM1cm`pUlpQb*v%6{2B@W|>XLe;oDsS8W|~0JT!A_``aPNM6~gWU_)>~C=!Psc>*B%t*{ZJYB?7+XsBUBMafZ#;;66EF?0-P>}5kNW7?A^Kv0lY5f zud=-o(@X`WD8qSIgaJUK)ljol4jU*mHFpRJQ+4}|60LSOWb8kdPBkSP0JK$B$_GHp%lVD?C`KcaxZr-@zG7_gBJO}T5cdq( zaNV?MU!*EpJp?dxFgZ5$MxoTiG`6LQ5mT^EPL%S4d;29XVIbeAcRi<*U1=rQ$SQy2o}K;HxsWO{O9WNgf<(o>)u z2}NpI70i{q#*Ap@gW+r_sO5@wgiR;IBcUr9M9oGkWJ7)pjycAYHe@tZA3U_7jd-Fp zXjueuY#G_ZdQ_eWs!mnY^hH5>x{Z;7WhS7#LpzsVizm|K6j*6PfKCdo9Tj5N(6U(y z;dql%X)|7;Xsgxf8b_XzUHpaiU~@78tRR=@>Z*DWXMzBQu(1c+Jm=Q9gi@-4C($QI z#eJz}4)b)LBaa1bi~0*{-7_L1Q4s{Q5kxBT_SwsW0{4I&6#@&EztMFASgpb-1$r2Z zEnvz)Cm=e!=Z^8d@UkBo-7CFp*x8I?k*u}|bOV+JcT_)r6}c+877_U)r1pWHfX5L^ z%4KW_4x1xFSRm?PZKC%Z=(;Gs4rr%WKoTDeg2+w2P}TuJTly+T0QW}#WzY}+70<`Z z4M04n0#^QvPtEd@PFhXbnpu9#y#Nv`ab2}s7G+)|^2S_9K|z*s%QC;Ef>K(ng&Q<% zu8_!!j7Q-YX_=A+OFxuy5>*1c~*aPGe|E`8-%Y*6gwY@4h80Gwa8AB0ACP3 z8J&%14;^s$=l1Z_6jiFRscG-6llZ+!mkb%!_-+ZGsA z1V#M|6r=T#Es|npH(MY1sVt=?>VuSS;tXwTn%Ak#7^sq*+Pq-5?cAC2v}lkzTTx*< zRU~q#JuZ7nbHsXfCKT`ttYHQ3jxeL3#fp?vWJk}NP9E!e;a zB|{q|*pk>lWSl%5M9+>hYtmTQr(=;|CwKvwTq9g;m!!`;h{kCzz zd5ebGjr<1TO65XFh)F1qg|IaitD+o2R*<9rta7NSsLihlH(*tw$a}^Kgf1vf|1@S+ zfx5*t*pi4~$AIh4Sr-LaZ@mVW2S3babZd6fi#8v^)7N4Bp5M zk`nP)p_DzT9Ydsyk#Las4YuHBkV8+dJ05N{rd?Q}9S?HzQ=;B@Pb&&XaFJoW^k*Hx zI+r9tUL-&dFDi3?J-_geb6WE&&S&p9&6^ z=SVr0?j9%nfDmeoQ8tSZf`K@pA_ki_ z*f4SqLtzA$`mSl0GSzWwXxvc`*eU^3A*)?Uqn$#Qk7pSSdEjXo73WXUgiJaHP>`h= z*r9rvbnoG!49vMK8)&c+eN+Uy5=+nFNGhsUnb-zd)QG1r>j~1>h=9}82tF{1>^1pi z($OUCiWRk~--#>mnG`*t=U)27G{%`uq)^{e$@B;p<)nIy5vm{m2EvV+G!k?GlSxxh zzKP&Q+;9{!lc|#K@V-%;q=MQ(`9hRZXrzawaNqKLfUj<(c#W}SN@&w+CbFJtI2PD@ z#jU$<_?ibzOwq%gZMHdMvkm4r?whHZo4U($f>`=#nRO^WA+i=5G#8T6qR)rheqcr* zN_1Or#cEliasBKsYHSpt#h8m8hw$51v3Y0RafIgPmxTp=?8<9$@;+pI;4W;pQJp?= z&t!VR)+84L-f`0r#1+2WlmS0f4NV<*sRTE0PCXHF&P;iX2oFH!tqA?U251X3LWw}| zt-P^HRNo_s#-Cr)s_r4DswTi-DJ_>|9wq!fsfNdQ+LD7Rs5ooRCrT-dJoWZIO$@8p^j4-3pPxv3yT_|JU8lw$1Oln!Q_Zb?;WScI=^I z3)Ig^nA@+MKj|AZuj_lM)iNh_`}?=Y@mRO@cw3LRI&iB4w>ogE17C?caO(qJ^PRxg z)$`kz@s+3}w>;n4wp$&z)qz_bxYdDM9r*311Ghfl-aq?N{JL#Jzx~?KZJplM>8%dj z>cFiI-0Hwrq7L8#{vr3TxPR0AJMJ6ZA9H^s*(GmI{;lNOlJ86YYEmU-@(oFm{HOf? zpC|uK@;@ivnEcV?&$}OSzi<8jYup=N)BnHA{p0Q%+#lxuZ*hOh{d?|@CvS9*+(+F@ z$-j{N6Ujf~F4=|oF}4SOGPy{8XY$XnE%3P{bKl|qsrdizaOrC*U)=u=_jT^yrR;BU z|Gs;Z`wxOX4^rY+C(pPKva9ZMY&Lw6Xa5*?zn=WQ_s6pz|BhpIUgNUw zWQKQ+zdsZ9GHMT`z5B4c;M;4gmMA{QZ2kLf`3m{8P{4nu`yV*_jn#B4eC4>PES+%s4Xn#2#?XYx{lm;*~$p`fgI}`sJCm$wa~~va|3J8Vi_77ftMY`cpYBw zCftTkKMgUfv=g95BL0wwRtFWVttnI1i8cBXZ#>+P!|dXzf!aE${i`pt+l%Fqd8~-f zb22CEH>>O;VHYcB;Kr=_luTtb`JPW&H>H-Tn4mi8O{LW&wl@!!6B3sXSC!c(-2U*x z1zWbyWhMD4j(+4MvW80FfI=3y1f4(#z1ERu;lYb;b24L6v%boXQOw!6hA29@abLe- z%QA=2=*&Pt@OU{nP^S^HQc34y#nb;dRFJa^=gJjQUzXO{=I32J43MSJB@3chPRA}w z+timqQLC3&Vtc{b@sVYWwwG-^oG=!F0QQ+UZLJFlwdRxqH}20mTmV3e{sFwOTxb89 zB|5B{u>v{gW91RBD~jv^r{^SriWa*biFjdqtoLfhnx2aG!y#a{0i&@K68mK}k=Gva z4uK|ZZs$bjXEGPW?^J+xLdG*4`AAZwJ=b>lD$2M_PCfmTRWkiE5+SXFA zaGU_5hNBMk;jFNRkC$56)KqLxYb=lCA1T+17uMWqr5IYZUy(`{)E>*ClwhNUO_46E zoVvI)Fr-n5j4tXO9z7x^J)de zL|Cv$3H<~sw#^X2+GfKFMXeTOwPj;pU^Eds=_0#N1g*B?QGz%xx(D-)1<5=r5 zZ55=oTw3lY(FU}71E&{7J(P+r3A7@#h2!OD#RLA%dKXrlAy!2q`{;@GyFjB>Y2o}b zqs1a(c(}jkQOo2^PHV3LVH{t17cc^BvAqq(2ORt99C*xn1c+ zno2sXUo}l#!;;{`ih-_u1WZ}ji*!^F z4_aQJ@nM~$L4X8QR;&todVRkJqiAa{B?0=)QgZw~lR-L&cIfQJmFd`QSe%d6-@&Ci zI;(MOdXln$wyL(#SFub#R2wC{c}c|;1+w*>Blm0r49_VSTn^8kT#(s|sm3Vi0N7SQ zcU&`7MI>7+?1wa=Dwd-c!^Q>PNZ)HxiUH+B)zpf^f?C60R72jv00oI({SI(k7uWoXDQMA-6yO(|#?+(^cfYaUEgkYkUt z79K0B?TZ*9fkq{&0IqPL4u`vL3ov|a51u>_1FbQ}Yp&u4;&y_5$x#tT6Mmpsn54)Z zc;bn4F&FbDGw=5*3nvm$m>6eBlk4Q-inZBR3#u=B12wzy+-ifIlo6h%Fq+jwxq{6@D8#VtoD^sX|srv0%1eL3fGkD!dX{5jgA)aQ$cAKxJIi*-HJM!un9 z+rma2({-wuZ#m< z^rpjFuhUqyF;xWgLqpnS!H9AvW4iXsYx74sUa)yoxybD|cq>QoSu<`cm%PU4apJ>3 zV!5=Scyw^&UYVhZ?ACRQvpv{kGXF_WJ*j$KKOJqv((K`x=X?7)1i_ZqVbfJOG&YP- zcrReIQD+5v?Va=mI2B9(EwN(SwMXJ!%*Zdul#Jtv%t6rBQ4y`o(btOrP&n|x_T;F; zP=zkE=m)s#U|+&#kusJ`gy_G3T#BlW`~Yz?&^35(*rYJkLd8E>D*cY8pEneGfHi2@ zi4J?LeFUpsm=LR^;yCAEj~6h5w%9qBD!o&>WsZ z?uIuq3#nDpaoL2}xbAcn%Bswfr-R-=3Xyn1g`U7&xtpb2endyuiyhd~Ybm)>+i z7>^0Ya}>$8*cwqGL^Y6me-7pq<^iR}vyjmdWDUjDk4)yP?cmOsQKpz^wxh&x;fO1> zOT0+m#%lZMVK2=^gPIW@+l&pm&`>t6S8B!cPOPkzg6*)LOKnIhPbOv6F_&mxNADlc zljNNMUQC7;U&I8IFOCQaw1|Bb&5;A9hn5OjLcnOkkPb2s+oohdOFb#X#IKAH$-rQJ zujo_*Aqn-2$W93AfFo$+pqq0Y;d66z=7Ei&Yvm+4s5Uw|Mc*aT{_apb*Al&;Z?%2% z#uDUAP!KKo05+_N`D?IL%7~?fuJD64DDrZ!NE?II&DoS!p^R_y2xhI|pVdWEmo`kfHMZ9P^ZjU$6 zrNo_2NxsInmtyoa)<)Sz?GYDc#mic>ZJyW=ZXe^hm>SmyLY9CXw)^uv54g1bzSf3` zikBm1Y&qD|g3iqI5bQA;GR+-4VweazVwEn$D&GK-O#+;d3VHE}j}uEY+fZc!X`i1HNelAV`6u0(rbU=Rd4Vx|shN^x3ZrB_67%7ujLC}~Cyf3wW&$fOTED1GtrYj8O!=7Bcm_1w|G!MieK*g(d~d_S zp~hEs+3Y_Vw{Z3s1n*`{pd21k_U+|-sgS+{p^V!)2hc39Vs8?M9=B)D5nt>UAHto;V$XyprbIReEgAXO}>K8Y(qzm!gVy5tW#T2 zl*;6~FM8sT<7TY)%AnWD4{G{m&)P9bL}%`?Dc-#i(M~0oi7|oiyY~V%Y;fA2h3hm1 z5W~ZJ_5xeVLuLaQPoS$Y#WKjLgX6fTD$eTk3!pkcRaP2>(CKr6aG@H`I9V#?n8#i&8 zJm#|^Xct3>q?oBLKvj>nE7S?=^UBtybc{u4QKsXPhi_X>ur=mrp=Gd18vN=I8=E+E zo<5n$5IXlDKSfyBOt0jOlNT15t|K4-1veu3$hG;{Dm!03ob6~5BMAa5DKy_%VnnhhcfH={oEHbFVg>7gjQQ^&%l3#iTmxrB-pzRa>aT zosQ2|&l0a7J#M1qqpvq3)A5`tJ)6jjXBE!gX(GSW%5_58+$gBI=~zO-sv?STL@{g# z?NJVna2qMU&>L>YrWv@Upzs%H4%6r~A5G2rwO*}qkh&&Ewn$9@%$&jbe4=sN5vDWv zP8@L5k!=K#3BIt)%re8uf=I{1fs#~4iJh>9exZi$6j}+hcrra`zJ{K6r?wqv@>Zz_ z)el3ws2);i;R-5u`PQm31{Kg8YAT*>daQY<8X7oXmb6qEHBPclKg6oI6nA4l3IUGO zsbwZZhIy(d6lAdh(sfaiX}9ZQ1}Mgea?JzLrCX5aIZIlet3n9cIa1L{1YYFFi>Df- z%*tE1t08ekGOU@Z)&}cjhRQ=l4CZmCgVBmB^f7MiYAPi7LgS2T)jXO;ZjATs3NwA5TT*gC>&KS z3<>n&Wv5x)3S^W^tx8~bD>CAEgo?@$YhJXmPFFRD7bzl(3@R8h9K*sp%t`nUi`1|^bOMP?f~1a`r@Yv53wlT~rDPS&I5i>aor^2tQg zmMu|6u&G@%%U(dhoQ%;aAeKTyKYs!Q2|bDcgf;>^gjH3IUUd%(0|3wigJP%Nrf7ro z@FbuHNOih?WbHCc)gXDT^qT223$($j}Bza zuvxX~D{J%i{{5m(r<=5N*jlH|RHuj%GO7t-OhZ@sC6Wp+6PkwoR)na%F{O@1I zI;HKPx4YgvwBf_AO5TDJ$`A%Y(2*`&2w>;~v2gxyY_$H$gsth{kx^eTzNyJlM0?O+ znb|chYA7&@nvrOE?1SGjjgDMQ&oEyJO!)VG+S#&8@AP*zc?ak>)nltSXD znNCRSXP_zq|A*2lnAPL60~k$`zXp&bva<-S!B{V59|fEs(;~Q344)$?C1lsP2?R<~z6+n-_Q*%+CJCK6X*)>gTu0h)odx+8=R&>N02|VDiB0## zUs|)V%wQ%sBj)swOy;^J0c~*C*{ZISa8RHa?T_IgGRDcfPN#E+n7zRP3~;NtC>}F} zUhz110kK^^Fa|Sy5kta(qvnkNQBaO2F~Pl`FZ#w;#`;~(dF<%XX52K+vzL2@ZJY7H zu%LyYP!R=>Jw-?gI(X|AeE2egAR*UzUosV;+$6Kwh7&^49GMI+khu;Rk&fIiIc;7* zr}W2C5sc1)gwKu@aAjpT0l0Z!&vFrt+ z4fMf2>MSP|EC9BHuqmbH7=qxuTb}A$5PLz>`!lR$$e5j$G0Etx4Y>g)-AfrL(U$X? z-#apY?gFv$vL#{*tE9m%>@$~P+odXF54<9t?VXPEkl$^ zhdM2yEQ8Fu!d@uUKooss0IqMegmFIw$Y$iot@`Wvax~EqeFtmDnrbDj&{36yvy*6& z?Tp2h#q60jlhq<{fkvz>gv>IN1Qjx_N+58Jf|iKuYcQGk^y0x@i*V0aN#7RLDeJ1D zoo|(0u{_dk-!teo2?B9@t3?W`tR(L*VJsIuf6bjKSfkJBX!K*_ojbIB27Da*$zKB3 zOCK2eM849RT^66Pm+52oqk#b5WzR1QN90>?Q5FT!?Fp7Fy=3(l~@amBBO zO4H!UVub%sjB~CDJ_H_cj1dk-`BZ|A+VCWhG8HEhoMV?K`tftEsrEm{5jf{xW_dwL&p)-B5v6PMZzO-ie@&)jwCZ$R~j&?D$#kj_xN z@kYXvKH*XpO};P-aoEt{igkEcD6C7E!Ss=I0qFwLAOnyQh?a+#jzb_mMdRa1-9;R> zr1^Tb{5nX#Fh{~_f7mH~_M!`fmuZ44WD9Y4imc+SN!ej|Tg-5eb2HXOQDH7)AqF%B zHKBwMrQSmg%Qw)5q}~eAf+9K$U_MNu{P*14sP}jb{X4$Fb_E5oxf9_+K)ImrpEO7K z24WMOvs;eyh(g`1JUTgc_%wHmepDLFxI`wNygcBYeadQRnK$HAVTw8<9VS@*bNx)p zQUtONglu+I(>So}F}P#g5oK)2l^4ozHx7>zJVsFAi#A zp_|bf1T9COaCCe_aBx2iOrM{10(Srdrh})DG}7k^I2(HTqLQ$5g!zbT(jybYT7C_A zXg<=CaL=1e!QoQD2j=ZJvFXu5TL;aiUwpKx=BnY!n5)rrlMtvO4tW6d((Wpm66U%rI}M7@39`Z6ZGzO9{IX; z$U^(=M#AeUB82ZGR0hOy01aweV6iDFMBO%Wjc_?)jMU!^zZ$h#b#`gGJvWNt98{%( z51^3*OF+OH0imLA-j-5@3fVikA)Lv~ZMO(}^bn6~b&i>&D;WnUJWdWZHNd03CXa^` zA{>;{@%U+qdqA6zF#z9ef)P)ITlI#NtbhsYScLuoLx;csVGSp7jO-c#^FvM*8tk^T zc-t8$4h>G~>WP1=Bx?SGjU#Pt?yAf-_Q=LG8H8)@ZSWhw5og<{@gAQOTf-_6;cFpU z8U^Xfz{EW3`vd8~6V4bnD}`x!`jRyj1k=)dAJDM6Q>968T|0fpO_o)1AFz0cmlx z+My;Ysy6)215Erp`(sQ<*7BuaY0;v5rHNkYuY@&hLTo`uNHX}@JXL$tE$dZ)y4BZud#(c}AI-iA z3q*TT87mew%+PtseC`S%lawy>V3e?7;}8kPlZ~oy!QqEDp2QAMBFK6L2!9Afj4dzW zX6XTuSmcGQ#5EKV7pR^f?iEU_eB^}!az*KiRXP>B)pV966>J4o+2ocDs8z-PH@Qjb zpHifI^VyVHco`!nS|$_Y8c{K&F(u)8(n8T*PS9IL6}JQ;L~XW| zhepX*2&XaxV`S@1rLEM8zP#gVxpjYc)5k-M3g0$DGv&L+q_jTRI3M9yE8aV<#P1}xntFRe#mfonRuxaUy)a=&MuZS!CRjdb|5Jg^a z7sfGw003CwmXXM@+=sqRDy1~JO)`k&dL+qemd#{~X78Vbx68b^LMGIsc?t{!$)*aB zex0m!fViogfCwUqP#HwCpqw&wTjynE@KE0&VBAOsJ}C4I{+i1wKikmp?_s-O40X4G z?=di|BdpdEFu}ikrYjkIvd*L7>Bu0^S4B}a!|VezSD)GnZEs5~usv{oKH&*ZNTABP z37V%UZbhil0u6ROLw0~{ao`Cb@Og+3Qp1vYtj)azmJ(QUV8PO9db`=S6HEl-HAebk z-lE1DjerI_wCMO&7}i@N`#ff~uNF zAlRr}kQ`%E0B;3@t%E+2Yv)rU)x;N70Pk3#R%y9AO`35mKe|xG>n%SjLdtNYGaNjl zS3B6^+A6)Cpo#I-1Efj{N{1WEKa@~b1PNt+YKE5#or8>LT1(6<97_{3 zV!T?SsJ5fHMgG{u*Z>+k^V#s_J*z8N9EYJf8~EPMeYdOnk(<#sB@wfNkV8gDdjC-I z=@uplDez66UD4_H&|-CT=n8!Zgq4f=COa1e&oeOc1FLJA(7yUX{y8qI>+12j9 zbKlNM_y2bC&nEwL^4})^2`BG=WAZO2|6=m5aXSCkCx0sW_T+1l-Eu65{-fl- zNd5|({h{P91Ij<+{(1iWlkoAoUn2*<2PwYZ{j2Vea2o%g1dDIrvi0xLKvB1rs9-y83yq)nF&c>cpN6OtFKPG@4W_B;8F~zP=XgpVQp(l~O5>*=JVAk6Upb z&7ABYftimDQ)D(Xi$w3^Ih(?nRupCCLpiyLDV<#V%e4k(k@EWDTFvVGgFSR%S<*py zn(wTFl&8wmjM2ob7xO)9dEN6&?wpoSG7s?QQ+bp=+z-e` z8JP(LSX-0FNzmSAY;9SP>hyyl3k#}G!fTMP#s8I5O_{2=Pg#Y~X#SNdTmZz1WaG?< zRiO>+SP^BS@tnsUZ3F8gZR~8rFfH^npdIyL2W61nAFEC>Vs7G0H&fecys*dKRn{v@ z-;5*-pq84X{tN2u6gte@BrAn98Sc;Dug+4W_npeO@5myXEHe+ z`7maN@@qiwv9X zQU6CU*{VoHv1JX&sl~ov#9lF5n_N7ckt9gjQ~xfQjxS=k56XNtm=1vMMN5nt9~_{f5`9vF4(s z7oxr^^cU@T=#YxJc{m2Lo_YD+X%+0zG5wNoslMYg@GD_a(36cqUi59l*QDbEVEGO9 zZkX%vV)?cJQj-3hLo~8ha&f;UbXFM~qPNRCm|IYWwlB+pELy&lv427zx6olTNvZX- zh;^)y;aJH^;MR}bgZU2Kt=S}Y?Wi5`98+&OyN8V}v+|*LWwla+H3oaSY1f~|-f$#8 zdEf_S$BNp5QRzk_(;?9L5x^1nI#iU#|3Kh(vG^2qMQDM6j&Dxk-(oMT9q(BcVfz70 zErbOI{M`2Dg1d-jEOubuNHFY+d|V|;O~JiN;(kj=wGV>e7?m28>1-h*rH&-lqFZUG zt~K18fP0acx>sA#YIbUfdgdOhU>=95$%`|0J|NBF8!wy%Q*#>UMc#@e>aiOE5g-;~ zMju-wme^D%fLUxp3F4#XIr(G{fZh()Ffu$|@Fbg&je;Aw8q)}rk?5!oNGW?4EMHQ~ z-spiRMaNYu;4+G70yi-`Vu`qNMdIA`a27~6WNaXWm0p*cBgfLOKw6;4`jFlZgw6R4 z`(lnfo!EQTSnk{NA(UZ>caYfBi0+hvMhY5u3a-)-l=aG?`m2FhloXkyYxo}WoX=1K z!BED73aSWVArK80$fJw)?Vl+WbCjJHyc@MzXoF(|7T`l(;V9K?xh`weuizMXk>0~f z%biktuFCBtHa+18O~2}8_e8ziW65Fmn*;FSYY(R_Y%?r*yvqck+PffOQ4xRPHONKj z_H=_IS%OEY9?M>WqFqm*C|UudxS497wZ`cP3+W~9vgRxTm~V{fx-aAuf>y90DBr>B z41OUeNyPJFJ6~CVYiZD?-N#B*J}k$dheeM8fr44%M~8^cOj<=v+>(#nQo>bxtiQr>kgF=veEAl_LNd`e6+W zze>HzOwlFD$+wz6-FvmB6V0|J-D3XK6RS38xR(7y!wrrYl_m4nn$=vgYcc*VtyG`w zQs7nz#S}~ow2-M&KXsiNiX|$7ziPX^7+*}uA&yYQ-nuFVX0q$ru5gq$AouqTXq&3o->tb+g&=?h)fxdGQKSZn<)`{REvaRcw+31FlIp7ahP&4xx-0QGgR`3 z&PZ}_KC6y$lYX1**aiZ~oX&;Q5dtdZN=vpux+qKmeu|OQIzi94x&mSccT-AuBLBrJ z!HS?VLQpiMK~^DG6_F%5vP5U<>nsgBK)O?Mo~_;@&Q|ELfq-$>9zhbKQG0Ju8WbTk z>ssho%ON0jh@>iJ@fFohu8@&-8}AYJV?2eFK0|O4%itO7RlkC%yDHj(quzufXxX;W z_blsYZW*TAPoM)=QF4Wsf=prM>?CEuqYy`jS8hp2D$l)qO!-+F6fsUARWgosli!)UZ@fK^e&^hSG#nS*66i$$01d@4zq22P<&`Wj)!-lMT_>=4!tiZCVs$*fa^uv|iXSotKg_#nhDLe$R% z>gpct`=shmi7l=|Z(k-9OH8}UKa9gIlvPkgHD~(b zayStFQ{X`~S*O1LtW^OwNu|>uh&kgayjAL(k*E6$%oQ05I?o-(|3z!^igmLHW2ziu63u9ZJQJ^X~zsZZ(P=7OWa z+z)bsR5S{50y?~tcvO`>0&Pzoxwko;!gG%qNz40b2SJZQc@g|cngR0)Q}*5vcfczA zpv;*($bzf-E4#+1V(|z?f**|83(S7T%xsnHq_SumUNAEt{1|zVf8wAhQ^n@z14Y`x zZ-kzBM3QLBKKSIa&49j0*?}5G%Y7)+t8>*ilf~~r$;p>nN)ncspC13 z5Od7k_yMueEut^i0|<`T2*)EeazoUhv75FlR(*Q|5YxvuKrA!5q%mlJJ{C(KA4XTS zP#KP3b;NOH3{?vw%k_XEiXnpmV^n3q?W-}e3}$$6N#v=@GWMtVVHUDr^7%bZlVvz4 zk(r2&xU++tLC2Hy8 zms33|^lfl8Ox~SkMLi3UOMN6xtgFgLo{aFZ9Mdnxs4CiY#@mXwI1ks=1gD8}sJ;oH zbB`$Ieh?3W1p+5+`Fx=Dz{oD&3a z{cO%ja}1o?PhG>BSR7F&oqSKEfhJ;*iv#PBuv*4G$eS7QXj+M{z*q1%rjUx^xB34K z?rfo14zy_{Cq4CwD+(*-NCmRm+^$G_D!s*7sO1}KN{g&=?)%Fbit)P$XCoX6YDn67 zL2A2VQ0jtyUliQ3CwFPBk=bRM1>H_El|SH!i45r=C$>EzjLX0T1qfm<0(Bsykio>2 z;?7;pj#0H?C?u)kfUKvm(K|ycx#E+s%_u@S%>whALJc!L!?AUKL07orGifeFI$y(< zfa_tOxn(TH%Z{HVLy64bVy7+180iNxkjq}2&3^{cg2zCL!^>1)4QYAB0LplA4mLCZF1#RMXsD?On)~>l0XEP;3m7l=^~s5LG?O>9@QKWsMNQ zhpgBb{!$z%FK5OppcAHP1tpna&b`FG<2kk}<$-o7fcQP~TUrF2^;~~SGyZwaxLe;4 zgRXiWlo#6o9RyJd&ewl&WGTW*~uUOC36l(X?T`@z5C{w}(5_ zIt9ZY=dm)=9=-u6B0wS)#!O^%6uqigoY$~;_~nBL{2h3}afrR6>eDb>dJr(wX|`do zcs`*t9TZc<14udElI9E^xJ7rCZ2Kxu`u+DAnx!JpZq&B9f{wZV^JX?2P_O#I4?yf*iZd z&!+i&yWBona9D(FF&|(@K18_#C62(P=;2{u-MjE>G}BlxB7vapd)`CXtR3fBpzBoA z-k`@`RDz8{8;QcqE0w$0fTfk}bsT!f_0-JFP;hXS(^*!sW+G4qEm3=IL>L=rZ2%h( zDQv1rV507sxt&Wjwa7U4pI z#0-X-GSNC#4WN3$xh0qQBH~0K0H-VPL^G||AV(FMASd!fih<=D>xD5bywV$(CJp2i z^MbhLiutm839tM9YQ3mD8b+)T?m8+_?aC$%$>X7w>AF}z?n(WE%o#unP>jj0Gj#J% zPD{DH$^*oKYfZUJWz>`*ORVRMMN^~8pjBBV23Jkl)%U1+O56l1b&Z^_lwTC2*VKVE zN_a$5NENF1s0tV=$ij^XC5G{MOnb->7{0j*Oh2gs>X3{yaKR9-5|TNQdA6;R-{# z+0;PCbD|llWKu<=RgpIh+{@l5jbGd<3^)m?bTS0!r=H8c7>0C<6oMZy zL@9>@=|;s>=RES*IJE{4q@)?Zr>r^(w8Nf|B-H^}cG8xKu!w?aWaJK=KC5CA(MwI^ z3T)ouXGf?-!6xuV+^}mje1*89!yGb~p%0FQdeZsT%rMY_u#nVam^fhS$@n(Hmux0H z+)h6IDKoYt*m>1x^nlM>N+uD_!pcxzquwl?-=TOG;EMnGP!W7=9Vj{C7qyCo#-W@@8C%gZ3}Ll)rHZq z#!YU~Ah~gPwIkE;r+^|AO2R#+Isu9BO!Zul9h+c`TIjwcrL;~Y6_W5OVriaN;bn|U zKc+yyAono zWs4e+f=afpxP;HTPy@307Ng>tQ>;#@lb0Rwr-#zXbebrTDERn1d2tSbmXRQqTG)D6 zo?41N=dL<0`4Ehc&2Eos=wB$KvL+!FW=@L3tA6WH|CW1;Z~ zW5@>CG*~&;3wn3L;5?-Ahq*({_xd><=JmHO3$2`&!7LrglgB-3qOl$u2Q^9|H=m=|{sgzvr0G(45Pq!`NGrmmG5neEMT9 zTuw6SH`Qa^asL_2tfn&3U$Vsa!p*y=8xjAAdrXh1eBlL$HZr+mK^ZE;9FzJ}M*St5 z+Wz0A&R}hw4nBn@z0pO~lxLaVeQ-^OUaP%OpN=`YeM;;5G~&Z{E~)8Q&>8P(sr{!d zElrL(n>{@^Hs%A7YLcPtNtZ5Z5?kX?zu#W}Z&X38`kA`olSV|!)=C|z#9y&AZ*wRR zf`8oJE(>V?1V%$Cp$tj%`!tyTgbycL-@aSd|NH<1&@Z)6 z6zZ7{CB#V@Gp6FSu7rtZTVeB)@%l^a8V!^irF8`aI+;uepuV!u_E?>tDX4xto`2H* zUd{a*R!sE|gY#8EL>WOt{S*aUY+!pzdREQ! z4*SXjCU=*td{)QKdUd&o0xYGZuCWnw2&)1}+=XijoXljcF7Frh) z&8Q(jCoTgZNL+BI?z!P@pW0i^6`?&+ilm6pSvVDG_n-P(^6oVT3Ys_*{Z8hBxxc2U ztI#}qO0@jE5!&1PAl&g&(V_HRqm}KU8H1&0Q~?T?Z>3`(WiwF{+g}xrry7bbWv`Phinrv#asDhYS>Cl=FL;?y62-n z6tsxliGd$HXwo)dfb=!;NVO<|<=AKod(w3_HEtUUD4O`5>ITDb^Qts4vxX~rsc=yv z4#HI`xw%EYMVQUgbsV#iriB(xoHf?=)ks6RrFEy8B$4}1Eg5i#;bE+!j;=_tW(u#k z?M;TpDg+rew;LHYPbEYBcqRnn;9Naw4j1Sw7ni?E0pRbvKn|JBseX>805<~yWDt|R zJS70nRwshu3FM0>E*pm9Ln?b=6k;PfM@u!u{hO~sZzv@4VQXldcFs*OD!)m#Rs-Ls zWV8*8%HasAE=GBH$S687N2B;E`K-XL&^`i<#$1Mnf{vJzVX1(eC?j@?;UyDX80u7ys#M$j z>>AuM-Y!oCLAmf68hg@NC;2yCg%)6@;c_xWLgmmW*fA+sm6Re@KaFvfF&1D7;B9hm z_^!yt2wCRHW$+(#VtJbJR586;L+5^;eHP$G1VjtLpY~=EE^2@@cFsC}iKBg|a|gvM zZR05|L!}rWxIA`Uo#U(G>`B1Lz7~vMg-dX$tom5|%FU`h`}aH=5so4+SoeYjsJR19 z%mHE5H03=CWsNMqK|nf{oge64=+y^5=SXL+0=oYOq;BT9iy=~zJd|N3P9CXBU=7Z3 zU9HZB@)V?D(nVc#GS-*HnLhpucgOdQc^k)173H{*QrEXQR4v$>1wwdwP=Pd7s;B3=b6mz~xM+qXPAg*1!DjVu1os6p?w%KX*P z_Hwv0Q~KOyz`v%DTHw3|dqx~@zq4XZBAY-cG1!8uDLw?U5}p*jz?iPk_z(v*^_(IF zJhkGAhbcnT;D=)_m%PR!(cXBQ|8`%@UW;!djbHjm<1Oa5nBVHatq$Dk0CO3){>*Fk z$Zq|aTYu(O2X1xXRtIi%;8q8|ygG2}&%E~d(yb1Ed3E>}|6BZTb>LP9Zgt>R2i)er zf9dQ0=pQS;^(}AFBmMs7|LQG&(7BKO_u1F};WvNVpZha!`u4Z{$v6GkH~+cs__jCw z+3f4SF8kVlgIbtV4$O%g<_ZQ6g^UHjM_weQt1Nl1Y1Zg*6)K>|cUl&W{R}Qd>68{5xb$0(SXiV9(sYu*)U`yL|t`E}aZ)j~tF!<1WvaA;GKlyvllQ zR8?A{S6ij~9oi>Zxz?&_MZVh9euKVOe4YsUr;zIgxS=^R8QS+s!m?@IXK0?av=qi8dQXNm>X^l zTf1B1;?{6;t88!-FKj%mq1OIBKN4xOzgC4CRz(|D*-x2jXuNI6T@qte;Cz%`0|MKq zmx?TrX1$f>LQEZ}&i|-7kss*$xcX=HZ|VZ|d3CG*o&IC}@An6eD>&}RfD!NoiULOl z-V!(}@V3C)1Mdo)95^*_THup`d4UyyD*{&qt_j=_xH<5hz;^@R3w%FtTj2J<9f2PQ z?hR}Xyd2mTcs;Nyusbjk7!4!?KTf#jTfN)YU~Idv|hhMe;25NlpQNY-K+dY$Ga6tk-&$!Re83Yg@DDNP@X$ z9ZjN_b5tlR!JIoi+;-_HjrFzumEro9i1j?LHC!KE;gp=**4kJd3D=75ZEbF&jq?OQaqXa&cXBWvgEgb820f z2Cb3ivl?5&ttRdVQ8B?>UzE;n>!|c@tu3KliPc&5gAUVKTorOtU+5^aT$Rn8+A zG(>dw(;J)Dq`M$koGYR$Tr}LOMPMbTSGVBw=qe<}LJ2n4G&eRiGL=wVzaRofSGXa4bglk20a8Uz)ouV$-n3$LPy zf5sW%rf@@~CE_A)OSROU)*uI=bHdHhQ|sCsi1uSOGkj`en>C=P?33Xp>1vlOZd)!5 zPhO*2imK17umre7+eJ>*Inmn2OY9yXYj;@G+*B8C7*l*k8=POsTF`Pi3))Xzc6QU; z#!DJbuDyslO)~gUTpd~2dRBB*U2A5I6ra30>OV=ZEUSV0ct&(C>rV(;*mw%Agw+lg zPLI~tpW0a8Xt@tOZidCtHBI%Ans8LS4CxlO_h81-aD5vZ<2=2NWfeI8w33ojFJm>X zhP4M`>{IF^n0_)1V=&fLctZpQA@1~gj-S@Lv@p^Ijuw*!(Pj?QRtxE{=;BCoO|y_~ zH?q2oDb|8x35k3?qcMsuLMHjn%(vEA8g4<9C0!j|6K(a+6pbg5jK~e*07>c)TyX&VKwFR=^CvKYu(0D5u}=x6~j0|~n*Oa?-h3%~?>LRsctAvM3qb*TZ+!)@EEtl4(pz&9s ze;aD2EG;7Y@=v7EmBdUK-uZWRysOD%ZX&gAIa;7P(y)rzESK5Ks+C7?^Krqi5|@7IWhoM>*vb;mjrovipB&p5d!=clSkjYpl~!O}JUqBiMTPb$5t; zvR5q2gOS6ln!`t#Y0UU!Jv60jorNQxbY4s! zc1(!NoDryWj)b;$6!x$w$y~|laY^GUj4AkRDb!Qin!_#ORqVVDJ8fS8_KHjfoh;vg ze?~*Jo~Jgfv2X+>Cr;DFb+T#MfE+KXc52$qPeXHIVaX1@rm3-o5$(n_THM-*4aka- zonUTcWw@=rm10XbTTHi0t;KJ*bcH-^iGXDW7qD>Z8f*P*(hk_u#O0v1uy|&z@hpPm zd5L)E8AR8ujy5?+%Cn<~_hyZsg1z2?E24$Z<@#@{x;)!{&%pHX3epD=XK@`~K{^g` z09TMcaJ_ktkC;7^I4q`5ar=5MwEDR=R(e2N%^l*$!m)=s_FMPRHj`aaOtUE)eVIF( zW$7Hy<42|yZkyeZHYu}PwxvmJHdEPJ1d?SHTI`vE6}SZF1@4D6dly(dC33kFo37!6 zgbjS2dsOt!oA$8uHv3t0CcrZZi$fO5+O7u5lH#IPzUQHIss;ds@BJWR#Gxr z39Z-DVhM+XRe57{W0aHYK*$a4Y}Len0&Rspd_>gAKxx9+5Z-IpPQYxku&W7DTrx%2 zPF}!dVUMLdo$h1Jz}|A+$qkq+24kt;R}8dMI@iWD!Q7vMq}6MgYTfI()@cC1+9&%W zgGEzFOmH24PSV|?6RLwxT)O z)T%vxB^9&FGfLe+As#qgvph#@yDYmcSk&YCvj)bqbaqQ*@fvbn&TMN$-fVALxwY3#{`bL&Q|ob#WmmkP3h7|^`qCZ#-szBCajZMvE=*QL zE|@a(q+l|%)nPASa%{{2Q~lH#B8yJ-M=GXDC)0V*VG_H^0n`5vdFa#=or})*I32Qi z%S79H$DL1{$_E`LKII%RCqJKa^3nP6v2?P+a=<*WYh`v$n3Jb-GV62B8vwKP4N*jS zG|_?8ez{fAffb|D+`7nrKy_|u9%Xc3*_%fj9ax~b)zJZF?;D|yO5X^DRQg6}q_R93 z>40vfWqCBxfd!gJBOO?vc{Ea9p!>t}EX$*jCJi*Nd6dK4Ez7NuCclSI##SlIqmd4% z8Z3JwG*Ve^jg;Ty%_m5cI!@%)NP&F&X#fe!Hk-?HE11C1j!BwzCJAt$A2Y`O(ifAl z56koDivucKayZUqedk@ef{k>@KEUK%x;aiZ<+=66lnGzY4>*(F&>F2`H3kt z5aIHZ+SaDyPI5`5RhKu@M(Qu-UzFC804LEdKanxH0KSIXcE|8v9qn7`+rsk<{#&Up zy2!QV653nW;UgMegosuNZ7M1ptecr`NII3cs_hI8C)t4fPAe~2-?Kb8u+rB@ z4>(!apSFPnXAdw74?0=a;?Plty^tGEbRtV;T#?9>9v#AB!;nuMP|(?~u+#eg_>wbq zXr;5QY?(}GIhj0lV7W=lEj?3*cF2%sNs!!ln^=ID2WQIX=yt|ZXg_fYEE+RG1o+l3;R*s)ectw>+ z!XJ~j|8c}bn9iBM3i&lc8bK`bq zxm;v9Z9!E;?g`pgOy=58Wiv}=24>CT>|}`f}FtV^6I1?y^y^@y09a~5|M zqt3-;QHEM&x&5>}&1-N5&o5XfmCY(InORvjdyZ!I z%iyOM>f*XEcY(G2(c->Ms&%w*>CBSK*_9Pc=ol?rQBqMFK)A+J!WwK2?R1hmu4rLrqywRZ5g5I=_f-dr z5}&*Z%)CNiZRH+g=YVS8e5`fV?mlX~(%cG9NJYz+mZN>;d)cg#QY{yl#Cuh$!^b0YE-$xB__oyd7thh-j2P0i#tW=|@e!)tFU zW>*~AwqE({nJoNSBvp8)D6Mp6Vz?2r7Gq8fJ2Aax&#Kh_${dr7Pi^pN)66yuG3K-p zN1YgPj=`wE&njaa%ODivZyyyKLG9e8T$=Ia6(uvvDnTJ#G^?UyHiwWo^c}0`JaaZd z*DS4G#4sMD*XK^0FOyrHylwd~%juwnlX4Vj`93DuuBs(Um`z`aYXa zvnxw5ZQfw>Nh6U zb(Sj0XzN%|-q8;c4Kk^dV79(+xH^%#a2L#2b>S?Zsc4H*)KO(15WqTcRK^=+Mx{~7 zr8r!*c~ESrDVao-9AERO4tB{(TpQ)3m4~$Z3tOjT=IlyxjNB~=`E^aAITe;~s(b+2)Wl52Z5$C6(jZ zLvF)~I%lad&s?YB0tgpyIqNM0?wdiQaR#v#?nElhUCLusnk#Pkbee{c>kqkY`Yo90 z_YYXF_pqICIZ`I%@~OPpKcY_KYUXJqBlz_NT}fAv_wf7qcPYsYlC&Tx3zAfE34K~g zknr;!_eE+hNeq5cALJeSwY(ElQXN_-aZ)hmQnG^A9m~~UDV1x$Ejm@=9LoGWN!o?H z>)%R=n5&lRw~IRc=W%&?31!mP3*i_$CBv_=U%?o>N|{j_czb^u`X%&g1%91dBV+yF zOSmA(*%ku4#%`$ez$B973}hY{P-LARG_pv|)vf~m;J)S6xsLyx&wK&r2@?fyooD3h zIPP)z94F(VGAECx4sCy?CG0C{dP*%NI_b28QcKRQ-c!g+@Qx$%JwYyljk4=Wa2MD( zqLC*H0FQMJiO$nF_o~j*IH$f~2hIvie6 zSzc06KC6^7gOfkvJ&je8axmr~=BJdKK>9RQhPT;CP~ad&Vu5wwlD{)6X6m#AUBZ#f zIgZ(h42&yd>%;~8;N|{G+&C3}lrN_>Nqle+*-t45?tG-FFLTSh)Q<_!os@1jQQz!y zTF#zx=9C0x&i>oaK*;txx#=GV@|3nWVSdZa^hP_KG!{AbxU>w3X7Ebh{*T?^uAh>> zX`D#^Nu{%Amy`y|$%8nQHC*|uN)kC{1@ictbUu{!6A?C(3@gc}LRm>TE<5)M)ui1@ z=)CeuJ55VmPnHIhWGp+5w~xAu@hx%5PM=D1y0n}CTjiVzw6DYbikbMG^2glVb`x~X z)?8@-ZpX4fMM?SWa0c#SWuQq(GwUTH^IqJniVK1C&E@CR@WEs;qfNoge)5XRAI&eToRb&N{O(QzifNi?TSl)e|}n?j{ItUr({O>2l;fA&w}K<3*P ztRw&{UBC+MH|wN;RXXf1Kho>hZ~vCCy@ctlH!~bVazG}HBcXHMhNr)Q7Z4l>x7)bU?SmU=AJ+qTa8VhTD~DtL_D??Ki22J4wx)ET z;y{)s;(k&&`M!bjQdaSy>?f+64R)0vne#j~VaR{HHxPKDW_XsY0Ds!Eqz`BI+YIC& zW_zO~Q(K488IA5XJeme{|ey60I zMZ4$I&XS8$HWPozA+4P&aKX%+UB-`Zdex8X?$R1o99yJUadB8Y_~dBl_qVt{eAlNh z$yt(!rE?jyKDJ$AlD@#3UPRa1BUtZ`kta(RJ84;#j@Flrr6nm{+}+t%JzOphdQ5u~ zf3w~X<4#RF*}yIGCL4@Z!|7R_plh}k&ed_w?2?MI(!iT9!NKMHf%JpzjcfmKf&=e= zlNaSpP0z_MTjkMn={TgUw8>;wk9)k)8pt}6?hEL=FSl_u+dkTMPAEQ0r3e=)4ktM5 z?aQRb8b_9*o=9CBPH?ba$S3mV-LUt2N)+ccYsK%yYgpu`P4?q^SV&dQr)>1AIc5cB z&#~TfWC_h7qjTIib@^=GRZ==@4%rL2(%eaVB20=&rA;Z~gOUv4LuIkI zB{8dbKa16e9CnE!V(M5reo_e#`Ex*d;f=*;H;F;syJ8h(q#}&9kYHsO<>)DI zUYRp{Hak!T)I;Q~y1!q&axjjFde!9mvwz};Q61k~PE1bT%r0>~iOtCc-!`uGrmq{z z``PEIR{ycOy~Gw<=&_16)&*s&mvwzvYSwVcSl;no!WgGBqC^$tw}>0<@?$(#n&sW> ze*G)84M4q=?{Wd!`sLy%-y3us^3aG9mgn@?ADD33K?GH?lVb3y#=UFOYi0q*;8bKDTt!HuSkd-6TFsEo^% z!-2j0fjw0F)O;%A1op~GD@$<99@=rendRjr5_`;f#F;Rxr|;rgm)^L=t4~4_z~eRH zmTTBO=V)iM^+rlLGiBb|-KR4TGiPm1Sw5VTT(+mO5 z4DMXashoXidvz-_gAVE3AYx3sQMm%emRsT38JAj%=~pW0D{rEV ztMoTVZ;2LT5Us;RG1>`4`x?v2mv))vHcG|1%$qLCh$@X$VCjYv_085`IeL}_cxCQv z3EO2reKV*qmW#D{97q+WA>{fq`N-80eQT|OSK2za)a18=t*DZ`Xtt66B`hKI2}5p>Z_*J$xgGEJov31{^X-+2J zm>{D&7oJ$5Tjr&F>|r!Lj}!IHK8)tLd3(IXcLDw+` z*4U2ac>8DZ?#?-fV!U!cUtDqL;y}9p_r~Hn{F}l1#p0Tk|F_T`J$HzyK=*2>;OD&U z+R-bb`}Xl5mnT_Npyd4(;4yk-+}2sDB%`hKM)SkJ8N4`BAJMOGn;U6a5#dg|GsjcO z1Wo@??;HPCbM|oS=ZkYJth8Mx(&63O_j^{TT;|mV;@+5F`_=lIMT%J-)0Cvx(vq1K zrMx9v7?6WQQtbR=)lZ5o`_1|ytE*%VzlodqTT8C>CElx<1j?P?ZINH=nmwyh|I^l! zH#CvgJ#TGSj}6>SLD zFKldH6Ry`m$+5q4$`Q={ol|}i05|mM;kHXpX{@jHTfbYZpXarP>!T~2l9St78=d_7 z*5r;eZ>IutMYulV=Mp_H@rg9+pGEc*p)FRd=A9FMs!s{GMC#?o z2kW9MTeT`c354a9pONOX8e7Ay(Z&X=Sb$5^QQnFon4cPMYLOA-yEBUOyl6>HV@uTP zD?b=3SLs^onj70z)p;w%&f?x|J*j&@x*wn~WLUH|q z2pnDEwwxbs2s?l+fpM$OYFmDpQ{_z3+-S3fnqP8@TiVt{tO?ejcS0UiqB|+^DCn(ESa7K?WZm~yJ>FY zB@OAlK=7fsICyW7 zQyc3Wn{~Q~=M}MwqidS#BQ@bDti~VXv{-Uk6Kj{18?J9d;Lp?R*x97zQ)?uNy)#zh z>PWih{v7+1`ba}AlW(aYo*N0d6Eq!ERqzfD^CJmy^Ev9FYHNOMiI zkZm`zx{WE;f@2AZd_AKviY`JX`L16>Y-zX!QFK*xbWOC?PoAJvJ(s1KsXrPbQs!jp zprwV)rKdHlXk=BdTFBZHR#QHoX3<(+f6P!U6+x;wTFV-d$5qkR#iEnsdw9iC^p?CO zS-zj^1t$f|yah5!eYhz@Wn{>syQbWwE0fu}qApT9wn})2B@$)Djp6;+a%p`E8h;h~ zx1n~*(ju}i|1u;o6NY#GT^;XgGMR@+ty_*3uwM>dF0+?aE05ml#r3-Pry|XbY2mSz zDl?;J?NkI7JGxg2PF{&1TLa8R+v^P$J>cE-y}!7k^#mA5ebr@6b&-Z} zYs6kTWj=UyNTxHry3g~*wQjD?ueij z6|3a(NNpA{_9h^#j1U@H5%Hs`XK3J%COhMK{t`l_T6oH}Q=vN23cbP#t2$G~Syp)!xtbq|G%aadg((7`EroSTTXVQ2yo!Cx zVdwm4Lrdf8HgmK{00VTbrsj-C-?Z!0Xz3W&|h^NTj+{nssTYW3VmS(esM7ASus|785K#@d-8ilz9tIU(m8z zDRs0`rpc%LuS^;09sdXZJ3)O!eNcTs|N8)+$Mc_jTK`FnRd+nu%Ex8YIen})Cz9P< zqUNaCszQB&_wsy(_w+=`pI*t|i^y`mNQL*{)Sjk-=AStN&0p z@_D_wT3w;8QeReU)wTS)f)-a%djmDs((4ZOOHHuV^@&AnX8}BgQX}sNdoAGzX`;3nn$E(-XcB9BRij3`l1>=8F zvs5MH%z)kx!Ho~9kMZx|OTa1WG_^>bqn4<%)dJ%v<5J^HV~z0(W-HLYl3Yz3PwA1I&S2v=M{zKg~X?=CM zM_-AS5p5}&OLUi|ufDAH)klm>ef3sbUmd6QRU!K75|6%;-WD%Dd{|!{)>nu1;33C> zOnoKRlvgKNmWKQleRX_Bowcr=zoM^ZsHy5Jv8eXWzRJ{Bmaf`g`bxC$VSRPjzS=hn z;0^1w)?91e$Uo=rOP=pm`Qeho{5dQMhgZSjRd9F}99{)))>ZJhS@hyVzyH(YJJy>j zl}f7A9*-elP5V02_vDwCC98eWTY8=`jnU!JA!8&tJf_`~rt!|(`Ey0dIi`PY12F88!^YUfuf%*=&3d?e0r-idL7!vwAsiw-Hh|pE7GJJSZitH zRSVD3;#Gn4sr>L^#i2pkd?l;RR_5Z#>cY@dW@4!g}po8Ug$d@ZX@H>k=u8*I+?(&nbDHm{lL2h!$gdj@)F z^YyGYuRE~pnS7l#|B=0(J*JW7bnQla>Agamo3q;NvN^OtFW?`02b`HHbq>^`<#`Q&V(s9PHoqa>ED1Bd4Y^Vi)`28I&g zfYR>U)uV=4%p;2#?wx;SxTOsD#oJ+i@6MjS9@PiWc1j~O!mgKk)JQ)F7Y#i8wevsm zPstA!eW>EB>mJ@MOTYoB9spiMre=4y3vZXe8wK8ncNMB%0&ln)cyIrU2j1Y@b{6&( zsuO@$N~50w@4}Y~)nEEe(=6O`&*zRecBum6qhEeXmWd1O_fN7KHG^Muf$esH9SZx)z8tt#kIzV}}8vMeJPP<*{Z)hjNbK?l$Y zHlS29fc|ltm#VjDK>rA!5*yI@0%*WgPa9_z?oh`2zb{MCg|iObZEMc0_r@Q2X>>0^eY+q@gi|%AA+e`z zs>i;tc=((PDJd!|iG`;DJ+n9CGt~NHM%5;zZvVbZ3G{7>zQp)i7B)KLkEBGGCZ8H- z{P$#u^t~`;q`;Ju=UPM@9 zN56iodI)6h@QtV;HND_pzx&t|Pux}io&jZ?{74!zwB<{yUv?;e%EHVCX6#SNCvC)D zG1c?Ceqj90=5OJpk6iijX(OtjXx5dogdZLJf$C10zI$umHL42Ub@t6rS@6hzE;*K6 zWctTH7iY)Qh(2qY+dT>ZBtOUU+V$~aHLQ#e{dCy$^<93<9_2go(mm;^r}L(Zwt?Vt z!n!BjsbRNGu1n+hpQxOV*!UUmdlzgu=6sA%_1QsH^Z-lh;-d$ZTD!;eJ+SOu1Ijmj z;eE`B#%jYDtUfEc#TZs2%9!~q4EpW+!0%(fPOoUx$>w@YbZa`Fuy9f-g(a?%Po$B$ z1*B$aq*$o${4U18ErY7y4s%Zg+HZm0&EdE7D&wf@k-z-7sAX&#%J{oS0DI4S`L=j# zT8kkBn^y0rHdbl&Jm#_oD=GPSE=*WhH$eI$1u*)Hqn`o8qWck(KYX}bsjFBV`S4%^ zdF|bTi27>3S@f5`SL$6~ORMaDI1+sgj%X$KsGtF_&D6+iq6r?$jfmm<4uro@2qsJa zSOg}=J&(1}c?{cu@hfl|2bJ3l=u^gt!#mA_Ulh%JB)v&tZEjw}F>RH`-vJ<51TISXX&E-Z$hAH7`}r2}A;9}l&14``^bV!rL4*F}t~BT#WN{70@l{&O-7la=O^n77PDaT`asl3{eE&4(xSh&4 z3lD($;;YJd%l|M}O#`anegE?DVz&1Wz3QOxwV(a0|7Yqidonf1;=Z35KOcficOgb8 zr9LA^T#FN&7dBrs=*+@>f=&{2m<5h{$%k{{GoYr;`0PE3XXjeoWB05DtgZr z(|r8s-D=t~Us^Y~`%fPkWX(LI(b`Eyj`}w*N-VD(Z1^36g3Q;`$h^k1tik88N>9r@ zf=tRp=wuIIS{}-U4J+b(PeNLvbU>-^fy|F~s-xfW&*z-|$q&3$eb_XUD`8OaA82uF z0orYS8l`G4O6=OcZg7eXDih2*(@1ex+O%fGUMqut?p3=|COtA$=c z)S^tT`UASO@Vs@S=ClVcx!N?>zkRn---O4Hy%U6?vSi?*z(u3nYkSU3PSJCky{NMRPJ#y!){<3NT{*M?UbFml4Un*M`SqM3PgM`f(Z!wT87^ZJOKe zzU=+XPr=W%lGSTD=fYW`k?_hXg0a4&px|Rqcm<;<+1K6u`fy&sU}dcUk)L`HS%h_B ze57G%nbEI|e@1-KxcTuwbXdS|y*tee*30@6lLf{{9=F%akX|pzzGS!Y`f$GW@yCyj6*eGCL_4Z;FQ_KkEKuMOwZA%ei= zSqSvbz(#s|r(=OEUcS74xw?^t?tzgGGy0Yrwf!*gDy?6yOCy4QU0*T;B2Ne+Y5kh) z8xmIJ(XUD{`C2w60k*&5pF1|$_A%SvRru_Fq7hh`Mu6Ss$$uJTDjpRC(z{KvZ%`1( zx!nL*5coWwKXRmkx#$gWR6XUd;~1#yzxN)c_usPajQ#h?l3nmXq+!tBf03zV-!7Sr zoI9|M!i9YPF$0C|%J;9|PNMGeSwG;gJe;C4)p4+)XU1!)u;5*v{;wW1$2eFdtF#feHjM=K*OMpqIdhS=zmk1@!iby( zm>|KFri81LPQdvte(LAt)A$5|q_ zL2AmZ^aw|Cnxr-|BPW4OMX$pXl+7tV*tL zef>YZR$zQcFId-5M}-P9ISq9incc^*x7T8Y==lMcWgutV#<^e|G)9ioXP2Y@z?mU+ z!&}snVezI~_8CW)btmqCF?z)~N0(&Z4w<8zXBQijd)Z#qzk4uQix#gMMIiHG!U6Vj zoGr?D&ppV})8}Kee>RN>MNgizy}2n?OzwV#5 zfss_Z4;F2bMMhbK;a88rVY zD#vjjun}&RNfiG9ZoaZ?9Is%T8M**4U%(*J;>31-KBnZmZg_RXJYvfaFEo@o>REd; z>Q(B~f+8c82znfqjueak(YK9|5?^S%=e_Sc66$96q#a?X&L>aY?98a+Z;}1^W#Qj? z3$My7ypA|$6Gr3cv*$9}J2rbz``u1;#EIu#eaqLIt3EuU)a7Z!!Zu=MHezoTrhk3} zPnoJqqk~>q_tBReE;;U{WM8U#i?HdbT<8p_qUj%8xIAzSw*O}_aBVgjJO7P+@8ZcO^RlM*1&B~#`2(8N^OEJ%nG4Gw4Wgro6?w>iKO>f3y5 zjfHpEc1lj*fLZ^3@!uJ5+mHqh$DaPD=TSQvxZ^5J_KkLLk_p+63phjge!}*sDF^sa z4U{i)EXJI`Ve~!6rr^Hs$m{yk(80H7_On2LSV(vLqGF`H1oTnyi;f|kgIo-UjRua| zPkaE%kJ@0Ht2u%1F$?Z{uM(f^Kirv~dt_|wGY;1s?{BhqxckL!)t?LU5)84GBMxY` zvIqWQD>648Dt zUVxSO$b64~>fJb8{^c%Ifk5~7n7$o#Mcv9b>w8HNIARsBJ;eGtiLRx5600zd85%Hs z8yf!ZHRU@owl%%a0sgl2%(y1riB%+f2L=2tz<-#a${fJox~tImI0x~%XK4M8bL1SoFkFnF-V@@A^?fxszo^`^z zr;n&p8C4YX~_*=IsIerETrzO?=3s`d)sib=?GPCkJ<$`J7qLJ zB|_EPkJsnz!&`sYQeFDN_rLqy@BcvQ{MI|Sk4gyEouOZ?b6DgAsl-+Ux7|OWnK$-_ z1gv{Itv{$2uoFT{_6|tvp&YG;&wPT`nr`#e4@v=m$#m@^OdTgS#yCqti?0sFddVfk>*xu%>Xu;%zw4OFX zD0pZ8u*T&z*^~NHqA|S9!8ay|Bfy2p;XOl1-MCve*8bEFiNq$q69oMi9y!|9$;MD;sXO`*kd(=T{6>saxqaLhsiQ-GSr| zWBcw=bNaUbimhJRbp8MICB@&mYjB6^6&7_TcchgPi(7N}VT`q8@2lOf2r3**o=8@y z3mJ4ZsNk-Ls-J_(X9hXeJ=!`{WqctqV)~LlKWDhgcg`)ZAoZg+P+I*GT{hD7T*Px= zB|VltpF(YXW5IBh@#){E1drPWt9(muAQGYmMytGt7%5@O@egx^P4;f@#@6dkaY|dq zaLaRGg1Pe~wnE-{472 ztfAelrr>e=t}0*kf8hEs2IeO{h>+f(1@r*`Bzs@!epT?`xS9_SoUFf_H&|s>8Oyda z?4JgzjMclr3H#BZtTyy&va zjI|trkKWzcTD$DL)nCUGzT^7TWz+v+b~c^Atge0AusQwSFRog)EY#eA)Em1lPhD1c zIlI9|M*Qli`PSWkTwDL?b5~sS`R_f5X9lJm(fr`r(77wtu4j37j8;wiRlX!j|gh)MW~(p1$duYc4qVywz8&1G|@#mrd*Iy*9jT z(EIt)oI%JM)2WHWV9j2KngB)08Res-(Bo;HukNNyO<3E1ka8=R#YhE(V)vU8KMp=#qk%{n_$S`S6HPNK1$y{X0F#XA7qFNso2=Kr>bz?*ELVf1x)9XCm3a586;eS zm)`iVGoa~L<~k@*x3WFleFy4uJ$)WE%|D+l;Qw>PG&j-wzKdz{C6^0#&*SlHu;?c0 z7K**ra}FhI3RnY3i*XrY4RzCKRpEWvOd#<|m~aAH7EIXE{kkv#x1!C2XBg#t2w@Tn zuQbh;k-W6e1s8J z!M=^>@2)Di7Sea2;dY7iGfQ_tZ_Qv;;g3!8^}1A* zs*@SDsP%pNIZ=75`x$djGvC&dBB{OwlyeKZEov_vh5;{}4a(onCYM|=*Zo&W{KDd@s!O3nroCzurSp0eef^nlgSYP`^XgGF+%gnS zVF>WQrmVVc4V;ElFAoY=nPxxe7F1vU?Fb*&!3pGL*&--d_&DtNC11|yLy4@V_L7l- zix^{J>#w#X*~j3BZ+-9ij2-#hnLs*wi#hbUk*b0-s;Zu_xMD08RxD+e7@IGI7r$Vj z|K)R0L6^f5xU`18SEsU;0V#B%0*`+X%96dCx_gBs_vK;9=oQJTY5#4Sue7h;j9AFV z)pGUK#tr1Vs!kBUe#Cs7vOk+w0c!D|%wL{?7%X_f99%`^&rI{*DPH(m24@Q3%smv( zzsod#WOGJZ-DW;?78Lvu-rNjrp*@iF9qL#1m_Hh-^3A*IezXa?Le(U%Hn#m2UDgbm zkHDUSADO8e(FF^yz4v$5_X~dptBlA1tXaQ=bvh5vh4K6Xq-uTvAZ2-6DrbH{EjpCN z9C8q4c^v;Rf|~4osT)sPf9l>m%-M4(V|{r5zK|E7dGokwvPhB_!Gy)=pWncm$24n* z8f{(-svFEl*})1gM07TzEB-WwGhczg%NY?HMav9GuHJ3#W+qi9oVgB&tL5}fec`h0 z=Fkn$`qkGhEviD0)j-7`INyJf0b)t>r*!-rA|*VT_cM6%;Cy&;hPc3AVg(lb+`|!I zkL3tnV9k;HS%1mi7rS=~NAAhPk<>RJD)fz~aa?GAVC2A$?bVRnx^vt2A-&+-*EK`F zWty)7-?za;jEdHx=60P2I(K9Mc)K`QjyQ_@a9_X@o@_@sWP7hB+N?J#`ipz^6gLEor@!)LZ4WK8oBf_TR<#^JcP3JEo)*&K>G_j)X%|=eGztinj|&Eok6ZXs*PAp8Ub&@p;V^wX{77J$sU7q}-xWk& z(fqhp__3=>{SwfRpDD}cPp~6VqnAzG!;s5i$o1K37WZfhDe=Ac8@(@d4+ua0oWYL^ z0LDBEs@Rt>`6Nj7{VfSaA)k zxEyU#uxrC@XH)hy4=dKQ18Y`%Us$m{%?fn&QtFB>*kzh8fsMMIksjr|#vcOiKd?=$D=-@EvYz6!3HT=^+nX=SGRp{3wHn=3m_^A|j_-F%fXZ-O2cg{@S*Trpl}Q5kJwMBIg@ zDEhr=-hUGz8spV-DZf~@I@xwalgKnHk_pA`DqtE!ljxPhtj@c|+(`Gr6|bA-wRBu0 znF>3R57kNsn1oe^`0u$45E1l$rpS=VzZOT*31ZobnkAej8_%@SU;Jrc==D~>g)QMZ zGhq(N5U7^!hX-k$V*eL4z8d-YtJb%#VV$VEN6o@l0OMg4yUzonikEC6(*sQB_nCdj zc)_dYXg!ZGYMoed%Qo!U_-Ts8WMLqWdNEShVcgIA=0Iv>-MN_a$Akqy)zU9?CU*9I zjiJ;Hp0zbn$Dp@^Q4@n9F zxE%^JImN|@D+=*7`X6M9M%knH2&?Wfi@MLMTC(~aq!Ve{!e;CH(*4NlQ84O{Rcn6x zO!o`2!QcUCq3T;39#LHge+teXwe+`}wy(Q=DJW(#YZvRj;QB2I+Gv%Bh3UKU{_DXC z16M@AS5sF55!sBw)_mejsJh^)OXlgr;Ll9V-BA`b2e^A24zY4X9xr%&8(c12`f>(? z)Opao9=R+G_n9Nj09knH)yp_RG&1G-KzL@|MXMH4u)1#yhqzvH zho(Js4HL;myzy*23QO1NBRwOWx6xjOX&(m{Zoc#!CfftHi9amV-c24z6g!{+?x^45 z%UOi#xYFE)PoeM@&Moa?+lvL9x(VOK<6a^QNtGN}L*MFOqkVrz-?P{RSD~wuk9-E) znUoxq8YABrtU979hSC}RN;QVXisx*j>_RqgIv)CoTdMF87HlC zQJFHm9GRLWNib9JxqftYA)yUFzBP2jmTs~SWTW-H@}q_k4CF6w1IN^NQBl5{&g)so zpEY0o7Kd10&CQ~Co(Z$3RsE7UT=JG>oMX?qZj<>r=(z)ks7)nzh&F!_zSQ1}pL*oG zVCFmXSKo*B^GST#cu`f=89x#OidmM;>$7ybgwLPiE&KgvurQ*=9ec1hM*sKfkod1| z+$LvP8bH5qkvEPX^ zrr+z);-1zOFN%NBKE#g-5AHIj_dfRPo36b6Cy&u#dg`&;uD<5hr_D{N`_u+}3Y+i# z#wB$tKX>c85p&v>+t;pKb=h}~2m1%j=`Y-QZR^S_Zu~tULFYbgBRhf; zk;X6oR=gjn$G(5{HMg%fw=v+O%-Y6fteo4;pTG@{eJ|4kFzRVOw+@)ocRqaQH?O?u zCl7b;F{f{N;O949dCkrL^E?D=W(=7}JPQhSU$}KWq;00lMydw*z3=Tz2z=sfN?hs-DmtYfpm}DpS&+E_jvEF+=SdeWV?Nm_=SJVtwn?>#npz9J%fZ- z3X_9agFL2&2a_+8E;cxnVxJ`VVGK91BtDhAFi&dn*Tqh`D5nw){Q1gNRRUyPv_^Eysapv2W>B) zDV?vPv$_p&UC8O_D{?q_D0lDYOykNz0@%krWIHpB?*1#Jv#8Pk*m%!k`mP}8k_+;) zrn>r7#K!T+0#|qaBf^IYSHF73>2{tM;f)v?-6Cz;r`!#PRq9KCGX>i&p+MS!85qh6315JL44T<$ zJ%D!$;1{Hkw#SlV8a-(mUwu0%M`e$~e~E0VfsrwdxD$KdvUep5d?jDlu@NOS*qiM3 zz1BB0Jfsyat}%q4J)vL_6Fu*s!q>p7lNnS`vYw92$pJ%MntL!@j6LyG z%;@al=)w%`Hj8>XVzJI1qKI7`Qjyqc7IwyB9X*5Q5ecf8GCkf-v#1L(>qxw07A8dA zNZ_-&Vjv}SSH!FUQ6%nW6Hcy*hSpAFT{CPJ#q}UqH8wc*{dhZoKKo;C#VCFxQKlW^m;<0Ty0Kh&R|}5 z`WYyQf3!#zjz7VOP0VOh(wr9J*_7snU&hG*0U@2py-`Cj+iKWV%4NRy>siF?kOoWQ*EaXk=1p8oG{5UUl2wZs%}^BpA%76o^Nr3T%QA!lm{HsVv^c8J9}Eg*%%5;p z1)xr*ph@Sg2a&ZNs?A^lSma@?jEBSbIK27@K*8v@=9;9>fKr2bPSMR7J%duuU)w2?Iuy87Nd;@mL53hhnB+RHOVIJ@(i!r%{3GGNpT{ zhwiXLHD%#W2fyG5PtYny_;ClR;#dO861rR{&zuqDC)jBfLx%~f!Ol2bP{jgN#^N(1 z^a?2;sCvkgOvGX`o<9|1ZsFFn;$Sh7Ky^_~!t7}mz5*3hpgAE+Bc}PG<%&wrYz-)$ z1&WL)s|jfQ)0kR_XeWGxh7vh}q0Kn^%qq_S3Awi}&s#+GSD0H8BO6PcM#a0^n35)xq&<)wLtI=0Gr zhA-0s;L&6D(4vMCn=@%LWr+&wpqs^E&21vRh^%R`L5Or~QmpnCu3FDA<=v2?1zlJy zia_`!$RUD?b&jTz0+|Z|h4WAvW-J(yuY{+kG!!k$=!_%d)xf0=>Be)A&vvmMn6bDi z2B(Y9>*9*grmj=C_I+Ff@DlSGr6ofDW~2jHu+LRgJL>B z1-!Ru1)bQBy*oi*NNQx@*iL1&cKNFNkbm3}5_3jG%O1tzWy+M%fTTGKDm5d@R~%#Q zX13#5w-BVAx#K%y`LG#;LBo0^#@Fp!u9Ah9hy^i#Ea|lgkME>M23BaI0v5BM22G|{yT6hTq$D4wfFd|}J#2v8m$)20dQ|3_6GJ?WW7yofMY9I6%E)PdBPP+V9 zRTDB4yIjoLE{4)<0;p!tJ~NafZxeuno&hvBy%=>dEgjluVQCs2TvE^Gr09IH3J)G1 zlWH*NC}Rs7OMb-K)z&YIJSc*c&8bWg<&s4l8Kv?5VkjChG^$cTOQm_)3O0c~L9swG z5TprW>I<3e2& z+Jur)QI|FHNsg3$cGLklQ=Znp0gEuFT8>d!`ZujDWQlhnP%hKmy{VX8OTe?`3waje zZml3ANQfzskY+)=A7WD!V13G<&|+6uL~)3cB`i&4W08q<_Dl8)oK4h4yJy)Z#fkmO`r9EwX_#5Fc-|LQQYZ^hdApA zKMUiWBp@MUKIn}n43cnBcaA|G?lfVFh&B@5#Q@hns%aj(FpB&MWJ!=qibresF9`m_4vnO9G!`rYA^USNeRzlRG_V5539B@`?+itl8n_ zCI?QLJDeYW_Eo79330TE<}p49>1UrcaqI{of_sP>5l!8Sv4j^f857h3+>jFjG{<2w zGbX+*z9n$U1aJwYdCi320+CG=E{MCrixFdV!RIbM{ov^j;_4GPSzKlpHi7|0jd8gL zgvD1zGYy{4P9%hFIH_{*wlgVim$)@3U~C3JBx8Xkb-B2zy=S%&2sT!C2^*jfI1nc= zRE^>gxa44}UE3whgWPuUi)p1HozO2Xa}2*#k}5( z&|b_vOc@Vata@fe`T6YR*0jGSHHNW(#Sqsg7R^^9DDJV3h4SwKaIHy-vhAv1Jk=q?0pT2qfHHH-^HU$BSfuGifG!@JKccf23> zx*l14c1=j25)Y;!M$xq5m|0^DB%qskp%{I@y(WPGc(DX>2WyBGj<3GckCF@ZwChEr zUEu+}lj<=_UpjR`H zW$5y#5VhqM_1<{%q1(!e znQHtKshCRi<3wpEs+CQFMU9uH!zG8gkw2s0QL}(`B(|3ps|T_c#Er6G*Z`@QojjIZ ze;2i>pz7Qx?bskx4O&p_9rk0RlL8|cf6`pX`X!2w?)7!WsVR&FgEd|Eo9G$+P2M%* zEL29+3v{E&yIgu0sYCQCBm2?dO=1?vc%nm+RykG$tzt5oeC8U9jASee#uFE=oVEOX zw$ne3<=`1l?6Zl+B32uh6a{ugP4AG5D;S5sQ}(e0;ATghWfWTvEM(CEA$XiU>%kkS8&pCv)TLyi4biuT}X9}YS z7+tnU1W93&2#cN32lSIOdHHaj&h8<3Anh>M*AtI3LTDteMKX|zYumny;3WH4Q!p69 z!)|morGiEbpRs0Lm(4m(!*Wbyc0%#E?Dx{l7wRCp;7EqW3Xj(W5vY{d)CrT3xwsOS z15!~uWP#Tpn&Mn;L2?M(<41Iv1ha!7IvPf{njgb>yP?B0O8RTTqtqKW0#WC@S^s-8{ z?WaS_VvQAcf`c4o^g4nUdR@`4Mr?OXigv6L$I)w;9q@+(kH{29J|nL90&~T*@WsU% zDwOb@ti_OJ4IuG)EeKt{SVu8vN%DZzLC5Jh{#d@w;&!af7)GlPE6d`8n5*Ijl`1(i z(H9hn-Qv&zr1HZ7KcBJ9V|ZYKw_J;iK|dlQ^cziLkzy2L%JMoZYyL64tRWZ}9e{rX za)LyXSy33iut={pP5}<#!7Rdc;)AbPOi!IyWa*zEXazMD0JT#D7+%7vg)xqd612u* z)xrFrO|DpQPPxQz(HlhO&30s3c-F;ddp4!KPL%0&XPGmU%sOIH6pA(Zm5>>yAC|oC zZ+r2y3Ck206w?=zHxNW%5L=5_W+@-BI&cp6RIz0y**%~X_j!mXnHK2}jX{JZ2oivg zOAU|ySS-LJfULiAM#^ZzQ6wmFdkISdhIvlVvI**i3yEy%0Yp$03d|gfzfcyfg5SmM z))CzgXNtiO{Z38-C^?)7Q5XQC!0JSgXhkqh6oC${TLIoqDp?WYIXI%YsVTtddXh85 z0feaN7y)S9_Eot4C0isUsdUHW>>iIdBPX z?Ql%*4mxElM&k~eq4i{{wahQMG5Yh|z_8GVuto z4C;_#vq*<@sg~6ON01W|=o1)Ca7cQ|Y7^#%Tn-85a%>iOf?`m{MvG~Bvlv7pYnV1!C4km086hTE}MjsIafhj>y!KB?~PL4(axj3)cl3*m7>PboDV2dz6E~w{b zi^u>&h!O~ic4_C0ep-yh29&XNHXN`l-5avicu*JulA^3~F~k9C*$FwAA;kM-00#09 zG6JeHMN$Qr6f<%C|vM*-aEsl}n zC$s2Ut$U~z9>`xu1oj69H0xXr5ajbgJAqS|WV=YlXALY{p!W|K(si~B^ku&mSaZ!w4;6F>x- zjX|4_?4Ue3i#j+au&?DZOULcal4j5*SDX_(kpbY?Y!1oZ;-Dqe5R6b;(UkVd(<_QK z1TdykL|Nh!D0UP~#(~Hs83|wuqE9D%n3D`eRt(ia1%x3Y#a0oo9y#b3=R zq0I2h765c>_e(0&L@~oO!2ke?%_7b8PU4pH3?2ldQk<>RzPPPD05U#P%=daBcT%bCA%TFaV3PrF5c7QGWI&&_;0+%lt6%6L<3e?cc4 zYA_J=c7pF-8VhUaRanzWWXdXV1&6qVFBAh$hRMeu8QP{I%^(cS;-;7kCr~Z+(C|oq zM~`VHIzz=UUR!cUlK;q2B;MqQF9O{{HoGAdW4Gh34)TLK?A^3tmJ5nwO=2Cj<0xsL zfN31vL@#v?+h;NIZ2dhc4mX-GAwpvcp?=56#P1{+0f0DxHpBGvOF)8?ol(rRPL3>shxldBgv^&7HkKf_O$clluBT(1LOrQw3ZyYK_|ep2VTfr7@eu0BqbC{!d?he ziCT!lVnuRh=lEINY0>VB>k4ss5Ki&q0H`51#qv7SdAB*aC*>MZIMloArE5XTAJ&?CqV1{^hJLhuX< z4!T+fu8}1Z6wjT&C6g`KB;8}+LOX9ghkZ?fHMp*g>19u|u9_5xb$R*pL$g4fN4)wY zE`q1eRYm9q4w$@Hj=uyjoW0Z9OS!?6NX576N|gT}tO0npNLMPZh=52f!Xv>HU4q8z zNs(p9xsTIoT6NuI0aNkktjUzan)Y%2iAG+xx7+Y}_{3zOye(xuUc(Tx6{MjEU3{E| zg(1WU`=C&61O)FI3%W}&QkPux^5XP0MuuaF?BD%79I)_m=`c6;g&W+5XGwN_KSSVt ziOvuSWm(%E?ZTi)?vVMAX??rPHK>l__-!VRQ(Z4F<#mn^aZ~(8mRA^^lc9%M zCNUXHKJPNQSKgy{2^mO=Hkk!1-^7Ty2k)`b8PlHU#LF3jvrc4Ji8-NmagJDOwGe^wcOw6~Qs5X=G*2SgkYa1KV>3~Hhf6`jc-UbQ9rLVJhJALwvF@EbT{X9HqD zWdRWV#=cMxz!bFrIANtR!^Z{VT*Hfh-RKOl;We@S)nIJ;+vD*Lwx=v$dLjTAvmjZ~ ziu6=K!Z@Ivei2xRW0Mt2u>L5H zCha|3SyO%l@Q98evg{9GYaS7=@k<-FQDFgb1*d?zjvAT;nuy!`NWCI$jdpB-a?WX= z&h3a8T?4q}d>ye+QWb}YDYJ7;4C&|&-BM#0BC9~MppY6LF&arRs3|UFutYXOR=mIx zBkhCoYeR+=M=Sz)@G|FK*tSy@U|m^E0eKNA7H3T4zXSHdHY464L}QS2`7s%5pbhr~ z-vV9MvJ)w?o~cPlaG+D1N~F|yVibNIGTCkN>vjTff?!AH2jnD&D3p$zZC{D+DW2PLKjsAHwWs zv=3$;)|QxkmYY}T(xILv52g7>q;)VPW_SWti-E3LuCt*$kSs5&hdw`8`k_$ljKFgq z3Psvw4pUm@&6s%WGNx9XN^r-pGzWnT2xT-$5$qHZ>0l*=#5|10n|KU4L}wLZ@w$f@ zg1w!b+aydv55Fv9nI-bsuski#6>vfzvNzy{xu_;e13t@bJ%SoBc}5)(DO6VSnbs9v zEHfDdE8D@u_I0S3mqC9vWr8jJFVgKb@+BStzr@5cEr>|MG;Y~7b(tb@qW;le`Yf8@ zxt(Y2#ITqo7mEP#-RT_2=fr-g*63NgiXl6o96;?$seL}K<1vV;mj zTJQ^6bEoG}CQlfkCy`&0k&GrycLs`?eA5bBHfCWq6RbMDoZ}sh&c=hfloM+f^MpUX z4$ZrEp-o0YLFgk?h)+nfNEXMvkm0puH3-5XtD_I5u(WZp0yq+6EQN z8D%ONR8%ww1R)FsnL`4Vu_{TW>ioZJpE@-q0sFr9f1m&7f6))As&n>U!*8#>_S$Rj zbG9@e^MQ28l7WqfcF4ts;w8MJQ>@B1%7BKTT>gsEo}@(bi2zg(F*2@7Kb4>COV{$? zgZ1sAB&5tPrBXI5@+=cq55~n36(T_jQe22TNN<2?i69alD2m=5n!&RCF81~B0pIN)IGC^ zAp(m(7$&HAC>|+H#ES^f0Wb-gAY=qgYs7;?h8Wq1kPq-n>rgq%NY>&3MR|!t97H0P z&I17PWCN01W3ZPU#4gChqqj5+YHKu68^{i!_5eyLJ*f)?^h;_POlc`>GkXBr3WL09 zKzLJId_-AhKj1~kaIu^7kg9PMMnOm~GvEw`rq+#o$KS8p08-yfIoVW>_Ez^61R2u# zDVkm0+xz8 z2`iO+nL$uW!0dhi0WFQ_P#IJC#C>L{oDn?-AUh7?jwctORDdnL$-;)XHQyIt^2c=%adJ7Le3JqLL97_t&L>lj45Pbu7DWu9};}0)dfNT+D zgIN)FmYms0p*14u2-x453r~RdtF+PwvR%TT*?({$%n!*th!T1+O=dly!V{hhoF20SX3D&@HtP(4Aue;IAKY zk%2x(KZhsGiiIlBTg|w~PRVkaNz&z+Kl86rS-mvWXC=!`tF5cV)@*6-aJvWbT# zD54-x2_%XtWs;8LlZjZl7%T&Jl7F_Q;$_fO+*29TS;L)`Ay{KN<(UFjZP^M>Voh(U zmA)nUlghZ6%u!&;%IzmsvhK5chs~NeBxg~vpFJv$@?tkX+#Y{`j9-w{M~J0~^hH^x zC_z{UYX@XefQ|9Sx@TC_LrscDIDqD61Z z-d(i^I4E^C|7WVo0U52Iy&DfWR#f#=a{^EG@_2>g)z!5F56IxWjh%1z28@;Aog6c= zrnkcJN@b#d0KqC#ZI1+u5BBe-)QU)j@hL~X=5pQ2kt1((2aNX*a12QIimnRdvv^`a zsjoTwrh`KJIZ&i~Wk-ecQw~VVCAAHHZNiU3O1f9HRX8|(E4R#c${Yw7OZW3qj_wr) zgj;TrYIwB@88*H}R<>5CPgVRL2xVfm12X%h45w#zFW*;Ttna@!r^rsoG>OQZ1k=5u zxx!KLX*_p_=q}1MK&F+~vUjg&sxXC6?)K8%@TwC+9B0$Lys;u7K+enI7J^cZ6yl_v z?iCFcaSFxn%PF*nLVJWAZ$ar^USH8)VSLhme@>yju-h#Nkqz!%URMzlb`Rtf;$`<= z?}Q!a2f?nkq7T9259SnNAKbQT0f`lh?&UQVy`tSiIfd#dv<-HxWJbG|@2%(&b`R$i z;^eunw+cHJFuGUlsfdc;f66JuUgT|C0~dVbUo~#4a*zgSWmx1GPoi<$EeR zgwbO;g;+4sg$^XuZWm^c=M>^Cbygt&i~wMpuzMn>5RVU8?2=6p7Hs~UQ-}u|ElMG zEh6}nIfd9lrz!1E8b7`0leoO~A`?s=+OpWui@NAV&B9Lhv1S%x?N8V(J3w!Ytk_r4 zBoI8EQ;2-LMTu_Ry`rU}Q3^eiQ;0<%EjZ6MxZ=G%z5UV&R{XIr2p08FBNZAN#3?XBX2>V)`nIi*=;(K;cCiuR;R zhbwBO^b#{aRCfN4PXE{I*J^K>i3W-E6rV^WSu=t^tPz0U;H0xZpTH9?m+cV`npu%W zjqTF3!ZOm8V%c7?m*z{nX{yKAhT`eSsf7WzytxS&bhVBYzmAGM6>8^O91(ajOG*!z ztnpNLuUEBCWbtGTD!yK71EPww*|k@8Qrmd9=WSEXXFt%-qSU^S6{6dvHn4RyC-$jU z5q>ZKW}A>{e|s}z+Jwx3l-d;z_&(7XF3j@N7J2)Bn- zJGga7A)G|_-mr>wB642W=Z{VLw||Zo=KbKDOCJ0@B3;Jjs2YW#*19#xFuJn4B2=Na z!0(K1mwE$!eIwy_+(#MwqQ`c)+Fj~<@H>-2ufp$&y)N~U9K+%2S##HSjc(;M{^|a$ z(yLO;_H2<(C)({xffNyDU%>3Us1gun7Ytx_WQS^3>N_y|358yP*~Gm{t>at}^Hr}i ztQ@D_Rxh0{#i*vr)~YE5V^kPzgwgksj1o7&=pP$1wK_^O`bQZ3G|6a^Fp|D$T1Ye=EjBYdiDK6KP&!?B%7Vmo$gMTg+Ss@_v4HY#IQRQj~d#pqed z;9{|EkS~c|>%+=NP42KbXd8u-||k53BXx5?6JsjCP1Ove>b}*|}nut=jGshW+AB-e@G| z((LMpFgL9YZrI!Z4OuO8##OCSH>Ei-$aSm?*_?JJIYn2-#pS(TPY9?vZT}_=pj9=Z zU)3n}((@@*P_SdgUKr>;TWuq^Dj^>D^@gnnVQ@;0S+50_*vObLI48}32J2W^YiqF0 zV&IIdtdIdAP)|IZrNPnnaH4qQNAErJ;?i|ZU3<*ot!v+1`d(#ge}{Qw|Ne$$i=HYE zR5f)o8b^=nR*sWSKDqs5bxx)vbhM)noUA@WnwK3h)vNNI|N6|vO`BF;e+myC{PzuM z(eRlaE9-6Dw_2h(qAO)&d%a;xQZmAyUEMDl? zUOIx;r5tg4PrCW3+_9q3mT*g|br`1ujhoW~K8fe~VNyWjv=ael#H6kG#XF-akCVFl zZ#|mT|JiKaUq9i*F6GD{wT@=d0CH$*j#zh!i!pd;P#I_M0HUR*A>fbRN%w2KO2^7( zyG1uyLaB&aNgNWW-;|c>Ii&ifmWu9r!ZU;h&#?vnWwU1r+CPWJwO1b1ri>#W!U%^J zMor+sO=Wy*1ANz<%D2%CX>W!dbgXO%7|XT!ZcG9cT}5!Uq=8p!Y1^U&)1uJ7=A--u zCs^OzeDiT$Ii2=O6}F!pze8q!7IS3jT-gcpb_osE3v+fOqaG2I z@kYZJgE8Nu)SGybiLibYIXi#CU^bDdxutr;fL?MhtgFALS^r0Onl8~y-yiOtza8i3GanE?KkJLH_7+`=gC`w zJoegaov*2n2%9rK$>{dij3vFWS&1#N;pRq}E?ZbIkLXwtwHsoc2*g{6!6L|fG0^z= zU;=fiVLw}3*R}1Hv#^Adw;`GuW{^6@&_wQDTu3FDIwBOFV=~BQr%}2zM}_mXnuwk62zHEflk; zj#aT_n?*ltQ{4%Ze%TXbmj8O=r-RF+Zbs~njzPHVXkoPsuj-n(nbXbI-!{)QtBzww z*L_cTe zk@|qPn-cHk=wQ=)1cd%Af;b-^^9>N1uEjaw^Rzho%)HK3fxz;1=8IiO(-CLBkr!Q6 zQ4whPWC&sI2Ex}27#~|B(jeAJ^;G{gW@9X%r_GQrUmpUQE43)6?MRE#Y&ttvENf%n z?O54n^qCB{(Uq?^etZxq8eI%GoX#vlFe~7M@nP^jc@uanWLz}9-*gBmc<>UF`EFxc z3Wmr%JDG;JBSR0bbvJ6ad~^^A`hNuHw~`W^PVpBF_?{CXY-s)cFff`NKZFQZXc11@ zm=*yb+TVRg9w$!$5x(J~FAoMpoN1R@oEAgPq&JT=&BoPte4F-hE};({tm|B@g~+s1 z45RJ+#f#sQw|1lrBYdOBbIIpJ8V0@cY6N*TLy(JzQ;Z+Z8he(}sf>TYd=DxIrbBxi zvpNk1{iS_re6jJagaOiD81m>ZtvAIz#^}nS`pex&B3mp|k`Qk7`~pWY;uCBmiNs)j z?N%*-@j_Yvd`R2-vBk!FB0$=Qgl~*_jElY)%7=&mr8xq${fuDgxPTprjK1os&a2d; znVyUaKWo3rxTX^T=V}l8U|JA7Z2SAYwjgN_+j>JUP;3~&!zz*Fv0O=t7y}EI*uh!z zfH80`S-n@Z08`TfFyOSk7o{m=Di%!-IITBEJx1}DgAO<_76JaiXN7GQv_)GHbJyQ} zagb1zL3r(vdJsOVHER%Vd%xSpAUz0&Z|tTuHVirlCq=k|&*fPnG%LryE{qcg4;2F; zL*0+H4EbNAWgrG=U)q_p$Y?qSX}O`(V_dRf&=@2sgLIDS3>m^d+pk>C6EA<8UUo1k z;$9t!%}xtJ6xO!1-ENC?6t@4yc8_u4hC!n+5rQU9jKwXDNV;xyI<3)lR)-pP#3?`h z-K|Tz2r`F)gW1IIMGoWC4sxfFtiZJG{jl9C>A*Bx62>q-A2cvc3KRPY!kp7)V}i5! z9iGdW^626ZHt}A%gUDhmb?KP>&NkEWmUnknz~1)We!G2A0eefyercXT1NNjakr9mT z*AR!uaDp>e6A;dLf%(DEkQlMk^(5x#Wy~EC^N&)O_DL$%3elLuv@LA`7~Ny+In03@ zTRg_7&j+2uBqdqP@T&flA<1mKxVImJ97+;qLZ!VjvpZ!Cw)FKRBKJGff^eyAX|s)q zJ+W(5vzn!Wk`uc(vu0D4Br=c~BR)(^Vgwyr$$On?(USGHD@)ISUnAo-iK;RK-a0~N zz>a@d$m*M;^r*}Ih@U@R zRa0BLxoZVAQ76G5dBIr<{7)5oq_T za5^uB>ug(EYqzMKd}*2G@zi7HpH*3M{US%M;p1uu8vA#QhuZNhb*4mnze5fG@%VYq zJ#mxw3?4KnO$&BqQn0gPD0A3UeOuCb#d&!mS9*=R4&IaeQzLZF8YRu-%ShoH<4H(_QSj)?EJ(7pMv?|>(P-C@(wGA*xFIez(U zTr7^&3vl<*!G1#3Gx=oo!WhxZYd*Hk`qqBs__4nsJRIET zZ6w>K*R0yYsvBuKgc_f+X4S?sk>+uI4S&0N%Eb`nd;T}0(rkR z-!{e<7=c(V&FZLmaB{-yykyz~>z6~$ZfT-5O{$f^qj_eFhbZFS9%Avnc#Ar~b`f9P z>)^3tNWC2Q8dD>!W`57sr*4}%_0EM`R1B+ZdGDd=Q)kUzeSlbL*VVmVwTN0VYVXH( zyW%ZIbEMzQZ+zQ7V`|AmE82Nd4ypD0tHDUJs^SL^5FIB3kIv)G% zno5nayLdNe%U>?+^BR|bkPtauh>icy=3QLHGE%!O2m*XIGVaa0pEr9pPo>~nT98h!F(<~oY&q~URoa&E z`pwfDJ%r)&dYHj$Imo&k*x5{$TDQ+e-XLH)TX*b^beqn^o@(;V&bA%Z4YjOU*HrH# z<0g%lcVpbFuWljCZahVxy+na=v*+G@P0TB=cgazS z{VBSMTN%Kcu5a+PN*^XGf=bS-OtUtAhXNY4md}^sW`1k=%~K{^b;G0NEw!4{@3_O5 z%@p|PNZ^)hCQO|11nKaWhZ1+>e`E$qCQX=D*4Ss}uf6-)2@`xbm1FZpcWL4dS1E%* zH54D|H;;)dpMCx1tLWV2{oY{<+RWJcv4YCjJ!Z}1 zxHo?`=Rj4>^Lkg{TLhJnHzn>+*mQo)UuRApKXJy~%}7@tzhhW?+XGilnEE2#4V0Xq zG@sJvuLp!37Xtoup@iA=2h8vl3#Po=d(BugJoBz@G0p6zXTqxcr0fN2nNjayE;z4` zJXR8?uQBS;P+839AE5u$6@A{k3+~%%nltES=l9bYw_Vrgb@{5zu4`%0IS<8fA~gUK zeV9Ia#h27=r{UU6^HWG%!Hw!0dc3alp3s<>7t)%SZh}hJ1XQ?!m+Ja+A5XIO=sRHq8Um5?(b;TGZ0karsVhcr!Yo*>e-$X2)<$ z3*a)|*=lKfdmjMo9)rjWbJb<5nAJDHy?I702f{HVkjzcCd4{@9)Lj(!9y#vOKaTc# zZ$}epc5gpE=fHJ%>l+s$w_~q4uOA0D0e|E2!Tuetjr{#gkVe%^3|!ZmW+&o0N0u&} z!pDOkfxS$)2n|Mk1srei<@|Ph$ZYQ37VDZ0jZwF}Sr=y%0})46+azdDx$9y$jj1zx z?}~Yy=X<@IEL4oq0>xN*iBWq6SiBCQPx!n@&Jz#|xLu~TGpRc-k<$&>VkaK(?N&5v znNj0uBbw;t1uKI>(tmHs3wN8*Yq|NFY5s}JqxNSZ;{=&CT)tqXX;vhWky0<1pIw3m%faR;6!7(+($n0Z z8a69>y^izdevCK4SMZSiJfrb#s?3a<8-T}IVJ05M7mRvf?fVaP3O-SDR4xz>w0s*VUwbCkGC1{jm8;!J!I16M0vg2py2e}j-2;*feTv% zG&WzEvbGeT4hW<1Kkov~Mhy+CMzy06b({Gm1DNXyOs5uKv1$M^52Iiy6p2u@%^>8A zh#8?JImyvf55jSV%)Ytrn$T?a&PUfr4p?4PzYA#=Hyv;C0}!+Sxd}a9V;*Z`+E~O5M@CV&4jN)kH+6~CsfPuVh}XD=cXA{#S#M(!$iPIb zFc3%TBDHTPW?@{sbK*Tb8-1|lLZbkjw+k=r*W4a5TEGn}PkLJ1=R-e2HQ zOOTFn5jYm|i#}^~O+nbla^dJJ=Jv-~aHu)_#EED){(^l>j$$9r@nu>YuUBY#?v_z~ z)XBgjL}aFDPldm8PHED3JRo>STQld-nxOfd$#F=P3)H@6!qu=GttOCVr+_IpcQ>USLd;k=5 z{ewaA8e>QkNZbb!r8pC3_qG?taP6@SB&ryIH4@JY63uBOaMfeEmp8fFH1{HndI?Hj z@>%TMY=ePi^-5Gs;F}$2kpHaOwAk^+uB&%@Sd+M~FQ{!%f-wdh*JT7rbYC@x1;SnP zu84VEmp3umq|jIv_nPOqM*B)$Vq<{HhJy$gE$i1acI@^o-?bd?z;Mb zX+A*3i)5=p2lk*FGKy8*FZo;;n>dUz-5etMeyo-@|kl6mbzjh^Jo5vH)kGN78 zc*p)R5b9`q3{q--M&F7}gXl|0R01(9CKIenIM(q2+V^$STu-b%ZAUE8J{RK*T2STP z*45k7IGYPEpXUQdt5xW9Lenb&%W_tF{TFiwoAZZu%r^D(A+ zBseYi&Rn{^b+-&J%>HlY)`D#tIC&cE0QShSOKX}pzcdyJv$5)?+dChs3sFWpJmO2o zoR1$uD8gH@07vn(VsyyGiAZzP#V9p-?rrDknc!DP|p!i@F-0Pze;RkfszP_SWY zjfa)tc|B{`c=av;_LCUi4c!>88M~J;X!P_;VR8xi6{f1j#mr)2nETq8H-GY!3%uUz zyK^uxpQD&>0`_-lH7yGz9qS)>kXSz#2c|O5MVP?5O4;7>0@L!F^eg}?xq_zKA>sc; z%y88+sFYzFTKB|#G$g}t^%&9#V>j#hJQOBYCp%#}zrkZURXfETfW7g$T2G&ZC#x}y z>xcqofsR^A9_J!F#~ibfgo5iiW-VnB*?%eq@HmN!uQHW%Z3Cg1)E)T_&i8%lUcwM~ zEv`Dg;YMVqQ3lb}i2Wt%9q#3%A+!JCk%Sdj?@WedS1@k;jo9lRX}K&lQDqC$xV*{C zq(7O!JZn52Q<|3v(@nBfFx&2VNNMYCiA=^`eT>R$qs6L5ZPu0`C-t#LYdZLkK=(>|?xAFNZiLwuFB)quJc)5pQqyLk6 zK1p3Y+9(rQ3ZT9tws;H@j#@wgi8$13LXB;FUPK@Gy=4H7>iaLI%!K<$0YLg$W`q;{ z?@J=4Gc%dB2cmn#w3)#-O{@3xOIB^AncueYoyX@q^vXsm=1Fz>!aUz;_Fb!r<4 zh1%7Bxoz6iyB2MZnZxQ{nmzT}JDxEr7E)#f?v{T)f4DAFPX1^26Mi8YQRQ)&1XZGncwmGTYsJN z_$!}dkNI`$mpnS>zNc2~LSYR?uQ_}NB24?^qAFCYrAjroy7>GYEE@XP$wsE(+g3jJ z-~-RC!~~#Q)4R_2B7||rK8~+Tn?0Gksv5Bdaz2gI8$9fUc_8+_sS+4df+rnfJyF(H zT=6KeAU_j*(Kzqb?~C>(7$#ZyF#1a95`ReO)_e$Rq$8v%X*w+_FWQPnd-@qr*k78? zu!bn5o;6Nu^l+ZW1HJRi_ssmyM|!;%tT4^RH0+{kQ=E`A|GOELcX6#j#yC=d zP1iMfOmR$esjObWUPm!^dRV3=pABAnC$*bIV-lGS*EM?_o(E!cq_VitKUc3AP2H=b zgV)`G*!x6mvayZRNIl-ybFWlgj`iWf)tlRGfhT4PTurrBsV4bkQqt;v)prl|jL0+` z#N1w8t2#be-I!TxJGBmopgeEccpdqb2m5B5?@BTV3m@}z_qMF`_cltmu{t47a5i1n z=5gHL17z=*!#mbIb9UXSB{{F$IHw-^u7 zwtO6jFLu1YSstYAedW5i$MGMxuI?L9lIL>U>UZyHmgjQYwyb=6O?8iDV3`V7-w$8e zn*rZpG!CQjU#DL*Bww!hmVQN|3ds&cGx@zG`OZd`w)9~ed(2_HJ&}W?f(LYevFwD| zra!Kz?_ra=XRdj_IjqvHR0(8~*ILXtyC0yUOYD`mSn~WwL7K>XNF+Qu@1{RV4(5=Q z7k(OKT!)~jiuzP0Irwq5p8U-w^^lpz$uuDoA?5YnMsNs<1iQSEn3J&FSyB!~_F#7HrQgS<#H5N7g13q?3_tlaMpgjqzaESDP`q2dbg=1q>*86M&mO{VE}n0b}* zM$XV)(-q=NkPUoRRYIhYuF5tEc~>aQZb`-2s-n4-QCQ#UZ$EGVyIRuUKO;~f}*qA7 zM?5*p!NIl&=`cjt0XKv^g<)lejDTJa%VIz(=9ryw)8zO!DvNr<^np-m z^JB(TE_~eqIh?@Zuk;|Ee&elHNV1te=oiRY20XfwAJPYMl$$w28 zDLQgaOeU@#p{S2sl=es#a0c~(qa03y+*Hky&sj`oN6a!*E=Mi8BY%rLSg7@?>uj*K zi`SYL^qV~CHAU$XX=594kw;FmltbxJh)${%!YDaA4su`&0rRxleOtn>7#A@&;)?7zBl51}~u|CsdXLn@H#r0Ajr1+odXlejfn){H91$ ztT;0@N!xE1a;i$+5U=ulVX6a%D#?+Z3T`fYzyz-{+)YAAandT9h4gjNJiA4(A5Xx# zj2hIj!w_uL6T9SO9CadHus!0o(Zc|Ww^3RgLk zN05-N;n#R*yW(a>Yjr7p3m2g%y$Npo(~??(X{=?yS4H&iGQ6+;Ap-IGb^X42X#%NJ z#wShU2p1`lU3#v3Vow7a39O3*VX0DLvCCk@g%WNcuXT*Gh68PAxMZ^sDKL~&mRlZN zYk<`clL8XK>|*pFLdMv1*L+Y>LGrI_M3Q}pyj4S-vAdYEhlE_k;a_8 zZHOXpQ>G|Mz%Lwy0iWgiZSg*S`7*&q4tJR1+~yR7GytN8SiD>><1@r3#9cbPOb-qz zs1c3YL9H}(E%CS_ZC5FJq+m{=hft!ez@vpku}X<`*2Z| z8WKF{>wpU_ecTeXjRKPb8CoQ7g9?TGi!(=pqF$*ejpy$WW6H!;?r@^JqueLqjP@sT z1!_rQgc_XmFGMNkeBJ^-eRoJ?p>FY@7StWY3_@|hf%IGjRW{*;{2l@z%X&p&smFOh z*;3(&oH!LX1xor&Li1uygvbS!b>Lu$hY%)dzbU~HD5;L}Fy`iBN*l_3!y}lcB6kbpAfErGEogMdaeQz8u9QLcj) zx+dpHLqa-Y~sGW(s)CjWCEmKNR#wj`q z%pwX)d|V*iIb<0DKjE1kaN}KB$NnAF%Q`fi7DhPJ0XfL z$s3kZ`m7u)>X3m2ekoc7y2JQTLqHISw0fD)i{Z-HpM|`3;AP;RAtubEHOl!X9!$O` zhXzZ%EX<3citpC!EX+Mg(8_EfL{v%@41&3+5JG6-?vrx4kh8Q&p6$)dfiDTXHe@+x zD+Rk1{t0l!5si0Jk-=~;p%en9<7p!-asZluAL1^pV|8O~rI@V_szqQ?jL!^qTqx#- z_}#EuV7A&zQitN)jdET|VBronf|#Z$pG14`RBkKQv<0S=CL?#a1_`dvuzZJc7XDJ( zZ}a6#GM@H`IEW>;#m*q1%84lT?_>jsmyyOTwutKv3wisl6?4E+4sj|4U-WJl?8rXX(dTt!r;6Ioi*79nZ1fFtN*t|xf9f=pCUA*(&8O(qPL zNKpp{2oE|Xgd*aN1Uo$XF8M+-PV>H9iM4kB57e>G=)6Qq6<+(1Veq*Gk+fqTlw{8*rxBxs zC$0v;HlWW|4q8NElLP=Ip@o!)Js7GwdzK6Wk;bYn%Le!ZCd45ERinU{1Uv`SSgpdG3wb-Qn3cm@&^=wDuYIr35=d;=J$>D0bkkXuF1t^C(OFQv58`5GR&6tR5 z8}U<1Y=!8^2>B4Fz{fmN^2Fjpp<s^6!SL7k5C#LGCGU*3)(m%Pw#!W3R)I9k1NHCExu3cE{{P)l)`4_d{!qfNLY*X0 z%2?IP)!@I*I`UynGcET&i^i9xlYS(zmo}^QIUV9r=`aj{+?SEupL>5LcM~2JsFrdJ z5ULn2DDe*Cu@T^c;R$XrH`9Mv#mDzLDudi{`8}TE%8yO_jQ%F?nz1`76mz*kRMh(R3SE)dhnzBwg`n$`Fw|e{Pm7vM8c1~i{bCT+JG2lm&_MK>yhTpiW#Rt~>P1kO;Sobp#3TZ- zO}$J1vKwzGne!PvWFJTw;5x#=AQXJDpf<^(L{P`}l`Kv&j+J;kJ~He^pd{fj{N#)^ zbd^cym<`J`k=F4AgEHPrF^8|5-33QLmMA<}?7^TC5>tmvDD&h>P$o!uL7&B5vnUDj za3dzjKF*-%lkaC81Dh^`kQp3aX|kB@@lknr$dA}CV0S{e3=+jMMp{tzW!@bYDx+Wt z>$h|f%qI~fB@J~2MHNm2YX;bf!y}to2pME%(W+c5KLv@QS?Q&h=-5v$ElV`!3Lt|_ zWpqCR3*E1%S1hqRAw?NciJf>d%yRGvnx@zkQ$8c8_yV{RS~!9d4Y_3bPWqzHiUzQF z-4{eJhrhf4v1IdrRY9-QG5xV}odsn?n|^{;2T_)VgM_P+29;YfXQD15vUW>C2bRhW z0&YJ2wF59Pky{>%^rJr}BKjL85|I)V63X&AE35qpy(|(C#s`oeK^+e($@C}!Um((b zjah)LxF<((z45_OAfcz;SY-Jh4`O+=7BEe25rDibtGfJ58D-I$h*dA!OvDQ^^|c~h;-TuNFUGs)wCXSWhHgVZCE*Y%0Lbc6V$VS1Fa zfVzadMIHwqAO4*^ z35aAPE1pS%oCSa$D^I2&Tw}%y(A}Hw!T$ctSDQi-SLB^6vCR`$08Hnl8L2nuJQ@EUB zcsLftf0fK<*ep(keTm*3DYhCAI59yAHpkwPan zwfDj$QyjN4uo%}7&j^Jjmu4^U=`jKjRaq`XN%*AUF<>ETtCECBFX?hydJBkPCv2e) z5j262)RNvN;QLYtiR3bE7Jee4M`+{423is~!l*7}0(|NUx$tlgH=H6SFo}qWq9vn_ zn1S$=MNpBXECtRWg^CyxEm%TOqNr|^&>*k~_(94H0gKoGB*Y2$#JiO7Mn7%F5(5ft zy&Dc*mhbf?-MB{pK}c~{g8^bQwc><9z!2r#LI6S;io_6Ann-T>Vpebf_?CboPFZG& z5(@=n62OWe<&#fqvS|HXnUe3ID98%1cJ>8&3mSX;q!m+9YY(>t1Nm#4!2byZG;}Eh zSmbk{I}4{Nm6Ml*Z%WrP(4e1dtN2f59RltG08! z2!i@t%F;E2Pb)KnTw@F9Z2tedTGj4w;?8`MHbmEAu`G106q^5+bcL0#$1i@CZyvst zi79EFvu-8Zm_CI)JBrN`vF1JhDZK@XTZX~w#%GB z;G1-5h?bQ_ z#sV0Es1u+LZIb243eei4fK12A1M`}$KrwRyydh4DzZxjf%y7#P0C#Kji!0nj0c1)5 z0EQB?NHIN3{c01N@Cq^`gmE$ z($fx7%J^A?IMM?|eTF^$iXn*TOq#5qMh8z66Zc-i4f?3Vr#B7`3JVNH;9^UB{w84| z1**4ixw(msq7kqF2huXG)8?{RkisSF2E-hdMa=cI{fIzY>qzbh_CGQe z36{9QMYvnS<`zU_;&#&29?sWc?4}g0>@4t?NN`z3qNMB)pfPn5zZB?8&c)bg>kcQF z+-Su_2`wp#y6qs7ypu=-1J((26swzG79^P283i=!--inJ;g*R@rG*Ji?t?Hbpc%kl z*zwE0TE+w|t#Fuk{nCQy8alYH%q?Y10HY!%0Uj|9IO|>JI-YhTLOEQ@jyW5D5&%wL}?*NGfI2&SJ#vEEQhC(DYda&bR$j?&0e%SyJG|r9@&(TCmZ%;34~P(aai<7=Il&A3j&tz zj-b9FDG!!Y+#~>sSv9uu4loj*Qc0(f_AKr;U1VvBD;Z+g@-IbM^}w5YBxo{ZE!N5Y z-k|AWokYAFc@ZomC4yC17Jm>aBuf>NH~|e!L7reBQDcTgPLIf-ZwujK=`tS4+zDTH zvUy6Rx*u66mwBJbzSh7ZuJ8JFx2ITTaRR|AGjaNx>6GLV@BRpi;pur*9=?GIChwKw zFAEs<*lCTWJi!!71RL~Coc}V5052D*Oav7xAaWPuk;N2!1&w4T` zrh+@I#+1pL&T+1yP-c2KRd5$L(HJ;y%b6dnppVw_P*996c#wiFA7(^+;F2c-JSzvX zu2fK}ln1>sWqJ(CAQs9!NAy3N$`)8M=^v)^Ul$FYh^I?dKA&X}Z{Rb;Lh07YjJC@o zmfLH7W?J7?nw)AED#mpb1Ya;ooa+1XPF{QZ5HuxkWMzf%Iaz*~ZsHeO^10IF$?~us zC4`V%sxh5(-%!l#A$x2D{5ta-s?Q=$Kao+zZ!fjWJ{@b&$|S5vmny$ax7O6*kPLY| z0^}(2hw*lLo!J*|%%J`u{SEp!ekUE)ZA(8WgMtLPtw7LUnZX2IB^AK_S!KBK-qxl8 zPY#P9EP}8AIe<n2vhpN8=#gT<88{MW!=g*&FcAO7xZq@^+GjDa zmz4&P4~oQtk(d0s5%4kKl`#Aj6KuN6g28fzryORwAz83!1gYbZ~+!dsQ zu<|kRR2CIva#%y^T1N3WeDXYg#th4#^je(Y#lk|6n5;k+>yKn=QWoZsHRZ+thnIV> zWw(!5b9k`WEoB%+1p?L;>bxAFqk6i__3ks`outplWjrSqUBifR%&r0)( zUV5pgBtz4oDN@?wlQ294)Doa;$n|ch3{F;-HA6o)Qo7Ml;*6r585)YUOB*J%&6|G7 z)@3!VB$YtNusjC~7bprf*&-Ma6Dg-B`6N6H221$qvz5-dNW`0(%&^!SVBRLnB-C(A zH7*qzw}%*#P2eG>m-H+ zl1P|&HTj#l0X~V1UoscKNF=WJP%dBzVJa7)xZb25M2#SKa6Mu%-;A>?6(Y3A=ds#O zx1lti0H7O@BMxOplh!*+#BAKO!(P$4mxJ#L_=71;oILbA4Wulu< z!a?XMl#fqTvs9MEy{MT=p<^%BwWPT!wjb$%OL~I{?6WEwVvpMB{h3gGBSu#DEYj_b z6V+z~&>*@S711zmGl^c(IBX$lH#D*Oo;=nnMj*|{d>|dNWMJc=9dfaucnNQs5v#I| zGN2(Sm%pO4Cn=G9A^;UcjEt+&Pvs~3(zQJJV12tN2`RHnsgwn}B8Y?silVoNrZ6EKVi1DNV4z6v2op%qqr?KJB2%tojftWo z8u8$eAx1VLp-|?@%tskU>+G^#o<$5<+}~DBsZ0 z{;j{UM?<%vHeF1);83kN6x~dPQ&wA?j*-IBW?Fx(A;c=>l4w}QHm#6t@#!npU3;H} zq`suJB;sHqN;PQ^|3Lsb7#|B6R1-o0OGTZ8l}f(MASfkZc0YiCmPT}_jH!I$J~LF# zh@JzG9S3p8lM7HPz?R-*VME-S?+Y;bWgn5Bt8ONpp7LNY;4iWV!hu)y;~E~lg$Eyn z1}-L!B?V|Ajdw7Jz5%-wQsuJohZikCwg|GptOz?x&TOR68j*Aa?C;ElCqVmETImDX zF5%DYKe!O)hh!c^3B8ymvmQ|42~P%2k7Y3#KUwMFGTZ&-`3V-p52ie85ra{)wB@fg zOXCYYgm75;N1F2h1%oK)mRbnt&anXS*AKbKK%b+Z!xLu3LKWz(X53?^WVy^F>GI5< z`Qo#5O#S3bIZF$4MjlxRdzdxr_wEeY#6uGlQ4pvE5=E6VNyqWYM66s4mH|7-KU-7r zGH5F9sf_8Y;m*nstTCPPOaZI5Y=tMWrnl5e-;(@EW!y~WD6nMZ_7f{v_u0L}W=$ND zv#8k59u-G5lRub%b)4@IaR+mL&~OKFCGwqtP-5LTGEqvWBE! z(8N*X3uI;$59h)E>*m1^uZY-*`@_B9a4*=avm%Er;jkqfwuHmI;BYTE+zSr(g2TPw za4$IA3l8^!!@Xc&FW^Lry`L`&ZfcbiExvf?m1SE7InjaxGO8Y&6fbtnTokV6fQ&_B zZho12Q;qUJ2{tQN^ha#pXT-VXUs{gHmKrc>`1XOb^C6P_!u84 zG;WIyJiTM9X)L+8yV#hror6Fc$8{ANrM-y(q`rn!N3n6uHqI1joX}C|ykn3vMYd6> zP55z6N#nS-LdR{<0fe@j#%mXci;b(d@m7w8aR-FmY)WPJn`-E^BGK3Ed~2G}TBvSQ zz4zpl*+H3oA~nag)Q{a)XxtjTH>U{LymE0ftiI+rnEG+eg^t2I`f~S(?&2`t2I0kv z*&D|-6`F;{@1waJOm~~=wK}xl&XG3tV;c(-g~shY^K#gQO!Z2QaO1e0hVc!BaSFxm z%PF)6c6)>!??GuCTVL2;XxtLHKc^7K47_@AsMxsbYZAisW9tfI!ta5cQoQee@lN<{ zB~#isuC}lb$$KBnDa2N|SE}K+jYW(4F*Sv~6pB2QQ;6nTeDQYSM|QMs?B2p2Or_`H zoKhS=SFsgRTUo?t7`LY|T4>xH{ZmdM_9MT#rPy`N*Jj{&o z1`U8l+WN733OfXy$8rj>YNQM8Nb22=N|DEN3h}Bsm|o4$e(ix@l>O*o4SK$ts7HUi1FVX`AbeARtsOI(6!sKkfw3*{E4@9d@czH$2t z>%~ONbBgm!Na972fbuHZ*JgAl*ydV4{y*UW^2gt{%4ibRq%o5!~m)*x2z8ytG}=M#9+<+43yPDK_smWY7Z ziHdY3D>jU8FWigi^}lJV$JmbI>By;t4R0Q^iI&vWI+E4)jq51fQ>b2ki^Bp>W@+gG zHa&2n*m_m_M3%6uMfKm8s@;~X-E>(ewT*v2@V2SuvoGjpQEFevO40378`!#<6Z=%F zXl)HSklAzDW`x)!vL8s2sUP1ZWPbP_p1r+0torEUvC+^w;S1=Eh2GsS(JE~n;r6g< z2e%F>grn%*8&l+Eb<37sZ7d^Ja)$UT?gWs7HdKG?G>~*P+TGo;_KH=Uy*YzVWIU$*-!^{}M!awBCZ!sbF{(y9g2f2|Uu7h_PMcqi ztNCP8?eJc_1_X#b*zwfh&Qs>vCvsRa~JHiYP)R= zFY6a~@~d^kUfL$=%)ItZYl9p1_J2cG3!QOQtJFfF7NCh zp`hlp{hKg=R@I1pRio5P&!<#D!P=R7ZL6!ck(-nd4}A9Otp{OnN{(5t1(w*zm@qge z&4320omC5ikT`{H76WI~ghCk+eiA%-sogvtw&BT3Pi8pDKld&k7PBPXVVXQxka7b^ zc^7@T``kXoLi`V2WjVOLbOf)*IpX%7bn{cWc2=X^{9BT((=?fZ`j=~Xuabri0iVS4 z{4gn?aoULhGh)(K@V+yu@;I`)|JI|~1u&Z}{Oc#2*rgo#qt?+Z8bFRu%@ONPaWMuD z4=UsA9YD17Gz9$7JL!InSE(x@mbY4TlO>dDR+kZo{35t1E!A^K^-C=k-SvcLhz*`& zEB?!7&lI$O4vlNCJgQ9@M?QoR4lRtDzyqAh_|^vat~r%&qZ=edv3eqQP&=!o*qE++ z;>ILEEt3hae*Ph^*s=jii$edJkMbLwV10N0jfj}{F{ZNYj8>)Q(nW?6gpp+bNg|1Q zghQu3`Uj;>d@Sv|c}IEO%>8%-T3O=oBYpiqK73%H!I`JE@T>75;c|gF@XtT?K|}n&syz5 zP+T{w-8S6MM2bF>@PFTA;`*~!e>s>GdzEn>C&C)BbDNdA2L5Z0Yf^^ug@f=Xxb0#4 z3fs_*-yw5Ai#f8?&FZubbiFWVS27{|M5ZUdTK&af%=akuCSGJBtRF?r&Yv)tP3)(V zR=r_BFS!@i)!);s|D!w2ns<2DmN0{#uD#vI!djfav41kttFu>c7>qTWYybJzr*|mh zl76DiyZ0&Ms1pbu(grbPU2>M+>WEcvaWL&75+!{(e5& z5Ma!TCoQ;dRhxq&xp7*}my^i&^}6*#h%}qsXqO_<&)I>bKA`QU#CthJ*fbvjp?`}Y z&d0}m1B9k)aZdO=EzUkOudbxHcm{8{Rb5Ea5of-U*E+ed@RzGU8A6!5f$%j0#>du( zG>COlJ=K4W*%%AxX*1-@*M~snN-fH1JJO;wo6frHuieeS+p)6E=rb8?TPL2g_Tz&{ z(dc5h;h<&_f>{C34uki}o4{isg1nj`$VCJy#t&zWJLRtWvNIVit3XpapT~EhK zjX67qav~x?X^sGGKOmqj1;L-O?I^ zj>1V1uHbWdmI%$t@vjTx1j0iFLC8?|V=Y7e7ik#?LgJB5TZVKH(*9JZw8Nl5NKyvr z9Mu^zgnzbQxtu3n{x+LY4<<$2t7Ea*X(0&1;*oY+h;$g%@pOBsaqrGS!!QwoCQppT zEsaR}Zgo1X(REgb8g|4fKmFaUOS_0Nhk}FY#P3B8`6@L(=8b5jzK3eNlDf+zN$ZENHQBQ?(N4QhmwT3Vrj2T?M_*PEqy(S z(EZM|AY6(^nr%VsnO(bD*h~XeCueqVLL)t$vLum##2E2mS`s7Z;7Z=>%!`(+w_RC! z3j7)=w@Fl$De%@2G6i=0!@_=cZMQz`W`^fllAhsVc=1T1Et5S3ZhyM5)R?z3IR!qB z`TqGBN48k7ZTvn`{H8ZUuAbw8=sOz-8$KQ5y1PE^*SS{rKo$n$csRZK( zebAoPr+U;8KYzTcrnYv+`%}NgBL$~brYFVthj^sk7SqlpbS^Aypb@Jjmq6n0tXvuI zWti!m44Xd^5ovQ`IG;o;dE)$ioNHV6w<`>#j@*$PjM|jCTttM@PenW?Oh-u6|K+hU z6;UqZlv7VT0_}bkPAA52o$*MmEtZ{qX{$$JJ*9F(R7yD}-*SxLc;5zzk-BXg#vrNzOo#3OrcaqMhU`%{V1 zIeU^AEqM%Sf4gfGmhPsW)5QU z$S#|?ojPn=*k4*hgY4Qi7;{KCUSW9Dn!~)e7|kcx5#ylD0ea2J3D9>O@nC0~JMtzX zJ8bTDp0s^otaLBjTP06AKy~JFeo{A@Ic`7neKbFETQXc7lsWH>Sa+(D9PM}BO1C{W z*0&=!wuk@yM<=+rcg(40 zjeoY0bemqZY747wr0Ec9e9EF#8xKdC$MrS*?dFkZ7JmDrlfM1^GcUO1t>%7N$h8Jw zX`#(FME1H>$HH!rZRLv;%Unvt0^;42wyeosRtrDbCDwG;=G@|_6y0Q(ZcDa)`@&8s zUDiEF>He?m()PMx$CDkDR-e6)BMJKTr3%|?lWkA7OJ{y9o?E&PY*VEpWH~U`_9xrK z?<|fj${~%bOBe1*O5L^~EH1L5R~$+vB>1LuX;yI~V&UN@4~SQ<=*?Zlr9<1Lhs9VU z?&$18l#VC&%b2vdPdr8@ar&TL+!gQZ>7^4J;RUTSuvYZ`jWwqD0(s3f-!{e<7=c(V zjq0d*aB{-yykyz~>z6~$Zf9aOixgo;+mkJM=7h{XHiE$RS!MtpIvgQt%n^>W;6 zOpUaf`8`{ox^3#zI~Q(IF>JEsy@#exoi%^;0V1VcSND3=B5K8`y`N_8inkcek$yA3 z@ooQ%sU;7sXy<`FOfcG_+9aTEjklzI5`EihJA$>21^Y^yN{v_gn3!yed({;Xoq;H1 z?h$1PqTCo|TKDBGy(z0u>)J(+Pr02PIwHzMdexKtUiB{N)X+@IE#l|{Q@zyf zb&UKonGd7uf_R1;?0vB0fI-`nO{Mz)B*tuYC^^WqzJFfSYkG|d&5&KyrgQnQ+w&kCL|3YEHl74r4YG;G-jfTdtWfamEv5 z!&@Fo+>!s087P@FVOm*ZpP9e*?rSGZ@ZD67%^TgNi91}S3sfhb?F`W9!EXDr5JUHIw7s{Mj4_RW;A+U4d^A zR7T#ExI=YNc3U)=oMd5x1EM-GtEyS zaRoQ3Z|L#5&U->*VqQpVUb+b?T@z5@HuChw+vlUxo91RTQHvP*SHFz&tfJ1BrupF* zVgF>zG;1in?pBK2lR{zjdHj3~h#u$OD2dj>=U}UF&i|U}Ka$ zs2JhD)|DQ>NA`Z40%1E;CZPz8=$d1i^^>Ds=Zh8sqnW@NRTF!>&Kn~AcXfO79*LV~ zY+lrxH=zdO#mHUfwVUP!C|nDC)srG#=L4wTjeqMF0@y=FD+uQp9VD}hA zUYM&co5id)2lw!T+EP*xi~BwrOkF4HE{c1P9QWuSM|-`uqlq-Tw;!K#;5xkZjSG?6 zvDci}kAs_lzj66s{|?ti{(dG%qiQAwu4_%R6LFm*OBYVz<3W(XUM5_G2BW?LjyL#n zemg#7Hg|7}bxnuHs9WBwlT<5+II7wvL3_$w7sF{xo!NU=%)m9bVvH6j#?niS z+AF}~bqIaJ=S6a?fLOroGO3+O-FbeL+oW8_`6J_pBtlL52kYN&mfZ z@38kwv#D%GEoLFZ*3I+g8S~?a5kT;VV&+#|`_P;VtI?~>H_pclF5GQKujS@zruio> zkJ_Jwj1y$maQT9jrdg3hMoPV4es&2OEC-vXP{7xNN>6itYS^sk^*YX*`!U`GU%|8X z^Nhx~sWLNaZU7!)#&sR@Amc`W!EQ!RY?05MVEYd&u||R7#kf zcQ2Uy>U=Qy69vFup#{#}S3!ib*CRp<*brHz{f+K;dGUy>CVP5ph{$+5LM7XuBWz)K z;NpPC8y`aCYmOYe6Vc~Be%JuH!?`ypzp>Y$M)TKV=8jzoJKvuLWX&Y61M}x@cOYD9Km(mVnhs%?dZp4C(w_b{J7$6c3C*I z^O_5m$y322$1@9lPcH1;+~tQ1kDG7NdYd+9?Cfy9jA@Fo_{7RW^G^@a+f2~-#oB^9uX%COy_pfWWJpxa0V@mTcFj=@G9=b;sMYg!x_xAC ze(JDuH}RD1oSy%Vdj}n#d(*9cmRo>&T29>7y(jnmDUao`K&WC}!tpKm_UG+5I$nAD z<9PG`@slcG;gY`@U(#gl4ayIHRA;f0S}^)ZwaWjb&% zV0`T{RP}@4^p6XF@zdwudP&_2qyN9;)g62Pg#)O;4q!ic$xrvc@$}u7z+oM$V>J7@ zTMy)S)A}Re|r%^U3UGK&a;u=y$)x0l{U@jZFdO} z4M*yD*;5Arxp~QJHGG0g5&K!xviZq(+{zayx~m6qu>TIlyZRW)>sG!_A9V4RAEA&B6JKGd8eYUG zW(9SBWMyH?WtX47u<+SqGnlxYBuloUe;?UL%|gk1{lmB5>(AoAP-f?G2Jp>AR=3>6 zu>1=)3P4LfLDl_E?*E01aD(q4QbjjR_VJBWB;D}7j}lI}Hi>InW zHd!%w^e@Q!p`T!Ue@5O9(*=G8Q@!>tpNDrUWdljWmF*`MHZO4CkXya&L%0>6dZBR1 zK0&|nJ$$dPspe{8BFZxim4@8E1VQi>c~m!1M*J6s+t0D+v0M4;_Yww;xz! z;lX_?54*;pfB4)A-tkQbVR8H&3{;~txRqx7*Y3?b7{N9=-Y1mmawJnoocI8$YK=*m=|(#64W!U2|JbJhtsGFTeVxpDOe*e)7&6ZoKmIOpef3eTW7@oT*UnpR-nk1EfbRaKN5kLb zDEG=^YmZLVp2*$uej!23=kSi#7g+~$-|Ej?Fh-fieCV)p@&q$0&9xKwg4~XmPpq-M z{_=^XG2JBd9^rDACh=d#R-3m%jc|mr5~edw*>7v@#K~1U6qc7xBdjk`>;V-^^z88V zgNtJ+;SKJ8yDfV@w6JjgKRNdUDweMqFhWM>!Aj;A$^5!969OFVIJD?wn64*ta2NV| z0b{4zG&K43#<^c0_aWsbka>8=8;gy_`&O@0W|`4%?c04Zc|Ubx>T*S`MW9(ev=YssG@`4JK4dMOMn6Gn>z4FwrpLuQB>sOUE|NGpNS1RzGL*pD8e?0Bt z^(vt>tayzDlyha$&GWrwZ3cs*gTnXU!ok6EG~U+->m zn}$&kbRknb`@LgzR0!;~p#2n(VuNNGo(j2h=CPznX&Uryg;rEOXAh5y7n~ilgVxdK8?IyM%|)Mn2$KpWRE>g3T$%La_fR zqfjpzLg;mnF`H++G3S`suBHr%*(!912x5(0SS89}^gV!;s#og@XM2=#eo?4n-vq@P zXUU+`L#LzAIOT*XM-Go!4#Iedqp5Q#`Yw~&r?96J9U5_NrQ=`^biPVVcywM3C(5DN zrAE6tt&MvQ?q(@pBs#Ss5M+SfhaG0JeL@{39}YQ`gx$RPZiYkKc-=~?uTfOTF7PUF zSm6=S`xMy$qz;Ge^qu1nI5JDTO?E8QRQ(t*^;K>(&=CcVbQr^)?R#qiDVUi+zoiom z_;6)QZpU);U7`XQJB@U_Tp0COmp7GXzKyC3BEycYW5GXvU<2GKd(`IJs#eYr$6(if z%Hbg9;F>-|q!HWo`hyLCbC%L@#uf3&)^fN`;xrSWoG9MAp9N zrRs_ai1l?+LD*3RSQ=vx(T6&-rhS|e`Jgy+CSoF^#E#8UF{BkADRN{9OF^TN02ug3 zL2F|`wdFQvvjDyABRv6C$K12oGo^tO`~SvBt@=YcQX-wIplgfPZI5SOyI7lEp8{IZ z(E`D^TrH-aYAR4I&gi>+@$>H6X-1@WNE3;6YiIU5{EL&X)z?rUX%i>7p^Qb-n{DT(*&R$`%h^RL6fM?BO7TwyGHgK+c3Ds+j@2#gd9E z+92a)*kO+SbMC=qlO0&>Mx^NQq(DaX@5NLT?R&Xt9KLSzX(RI0QWTMuqWJWlSF>|e z`CEu$iY|y{2%>^HR8Z%+(nsil>O$NSJyb%GG$|m)6~j`=sf4nkP^U!E)8_bnW#c~P z+5;NMPziE4MPGFEf`rPDl0D}>|AWKoWZq0k-T@DX-iUcQrkJy|4ORpkLhil&9T!>j2qf>r4IEzjD_ih|I;8^4D?QoD30(j!mBzXp!nr-Ylo0Bm`dOg z%{ZHv#Yr%=Q zG{(MOy}0sraY9j{XdFwCW|6XEktQ|G7Zy5Jn#BKBfMOAo)nFW(k*UE7H|>+LJdhfL zaF3cc5~t(LBJTQhn)rk5^_D>X7LPFiaoNjpHxZ@^H?&$H#GxNvF-q<9Rr7vSx3?Cc zELCH`Z##z?vl2$QLfmcuw>MX%O1$G5xyGM!1Lqt11{y3)R)s*HZ2WEH-eu-a#&*)3 zPmC>6@*?bxl#AR|+?69^om-VlP{t@WTCPoE`Nu6a=iDm+x0E^U<9LefbV(k{sg9G$ zTqtXKr0S?-mPpxs1#q5E?QdHwazM;P-ymJLzf)_WCO$-=Nbi}NSlSl7mWrp#mw2A> z$=kBw$(6{JEGGIPpF$_vi72uZFT7B8VvhGZ)UiicWR zn*r~EdxcF3Q*HG5Ckv+EMc3fPt6|=ODz@8-^O(m4XuXmNu}Z4e2AE5P9Hv!zqI9#6 zGqXvY?Z?%QuK?Z@S*LAHVE68yfa@GLybD1#!o5o>7@Ydk;YfS{n!wL_OYQh(Y+8!i zno})?B^cLAaXjeoLUwl)31(kk3LVP0hkZ6A@VJAG5Hp&(;_Xpp5P4s-WSCS&MsIiq z37$}~{HEX<{>q(}}LTY4=$gGA8BqqO^?g498(ayy>5HCV`(Z@te!kvht$ zJ@x9yF{uJMvY{M@ISxIR){$RK>Oj&ov*A+Tw}JT%9esvL*{~Vl+SNv)b7_!>oY)?4 zl_}~lQboEL`Z2aQ;z(9*t`6x%1!~_*H9f3wAM_j39Vti=% zu-hrT^s@bEkQBjVH|O+dXeb-kb=4E|Za5v^a5t$QtcP`SYF-(fl3hgjY?A?}>W<(? zM8B$cf_ma1ibG-$%2$jv3G7G^F_G}5tv5;qEn#6aVXe*AaT37v43McY#kTmB6Ow5Y z5}0C5g%AQ!CkhI7#AJmdXbi!5$TfmbJMvfM%&0%Ta2U6tn%YrZ1nn3H6~%MqOk#wH z*MbeO9oPxWnI}py1po*MEx3g3jZn4dS>Xi2jnA%W1MC3<;v7dcY$XNYGoTi4hXt%X z#l_5MC=>Q&0!|qDCpGFCaS|>gVFlpS156;GyF@stJs}}2Aidl@T$u`6w0deqN82(_ zf=hs+`eLSbg?k)v8|@gbVXW|9QWndVBi3dir8awx z+p_31q=zWlCQjMZ8|YGEBOZ}_5_K<&VGA@Lj*keh8)e1px@cga2xcg!Xj3b79ZyI_ zciC2qJn-JhQGhC!l-#Ec(ZY$<4PSfXN&u#CXCIVJ$1=@_9k&40{Ku=Iw9 z+?-}_nCLm`=0^if=#(=pgW=mnDF^)YAO}8k>Y9=d-YygKk)7sP8og}v95#f`K(w@P zw4XD4(Te?rW2*|dVH{}pdw5@+egFSAl|Pow_|L~_kiSb1rN^w+tOS2N^T_8Ut!nQ3 zMdJxKM>~@5Woq^KOoRA_8VnsE@70s1v+sBDb{q$TeM(0M5p=ME@^|Qu!vPP%ID5uD zP5WgQAKTj)X1r;paoia`=CCvNOB>CU4Hb&kK=(N|av4FXFS`om2n*hoTOfL}A#46Q zUInRAQPXuJTC7OMvw)tW(Hd(-Tzllt@Ej`iwwf&vVPCC5H8IfOZglCcjR9zaNd_LEZ}EM=W}57JrE z??JB|g!a5cKcy~Cd!zpg>TRg2dqj~qK-r`#sUNkwvhq&F^A>s!tpn)+Zex^X&`DM@ zQ_1!?Gv9v5D9gu|YR1pkp+wVIsAYWEuURC2J&oRu_B#vUuTH zCq|*h@~LwNWtQM&8X(PQi7(!Y=w^J|hzhcdGm|`9Qsyzx=^lh!wt487%#IT>Z_ZQL zrT|tajCzphsE_neE?3`f%6la2GJi`GL4C# z>8A`Inwef&iTQpuwJdL}Ie-TZWvm^6g|#d4b>zF_QuOdj%D_|T`rwl}C!J!*7iIxJ z09UR>Ba=7O)byR&V&c64G~U{RX zgX)#WOyq?{=57h-P-GB+K*TkDbsYu{zV%gPiu|aE@NO1~rW!cNh*FUb8Cjnt> z0PzvTiJ3{JMdA1Yk+n5O0j1#ajNrELq0y4-X$yyl{LVQm?79CLtsLw{=|~-LwPkOA@39`KhPmY`rG&Vua`-GvI0&X5rx-W_UtOFo{K2G0w;%HBgzF z1QjQ}2{;=hYSSlrSaK+l)G8(402YCtk>(VzNCzMxBaq0t^w`eN)L1^CXxnNy%JQ~1 zDa?2*KwwhFY9m0(LcO1`0T>cK5&;NR1X+PqRgqpLE8aN(e9xfR=~Yv7Jqqw7z}k>X zboGNp|997fztf_i8DKN^ExO%S${Ih_;>2q`$!lStzoiQNTOeT2O%Py`uYv4LoK8e8 z9;w`ktUb`6otsv?Pf=9>vx9WgZBAb|-NCuB3Za+%_mUNbM^@8wn*>389@S*cv1vV* z@r)&)*Yf{+s@1Z=$($t$8zO5*nuV-G(foIkm7+808(f=26G?jLAfg%b-Zq3-}G{(6F8eD4bkpIopbJ30Z{sE zrO4ICu~%vYMydU5O7FePE5n*l7}Y6N*8Bv99RpJv5KTlz1L%UtGawIjQZr;Nq>ck1 zGhcaqT(ddoFebnnVzl^cKuNMNQWrq!zV}-TFcU4vbOC?@<+CW6^(2$$+`|WxQDer| zN!-Cki!N~FO3J_djA+Ej2^S_2&H#B5M3Qz#wDDf<jw2{>Zs}khB2aJh>0B{*j?b){VeLrF&*)6CyEwJK^e>({<>(NkuKswbHJf z%N~J}-Wfn+=q9@~ST4q5th0?qV+J=Sn1nD+5i}~DOyW-Bhys`=FfZ1sUlS6H?7|k+ z`rc4MKOzlWh8`2DJb^GZUgb-7Z%769pU&+LGhpzX0#okjSRXhLIwfUeORrl%2F1gS>VH-9ak z=Cc~{kRf$Bp#mk1YSm!-T#IVwu6(MAxjxK`Ev%LX-LTW9+S@PH8^&N9Yf-|y7VIUk z%B+P97A=x7JHyY`z{}pq?1e%eOs7Ny06NSX`?v!I$)*fx6sph8G1nwY(;3pmu;gD! znf1V$#&ViM&Be~KzBh9*^CYrv#6{4M2@5{6CVyZl*Hnc9C!k>z^aTTf8kdXDSUlKk z5$>qT#ERUhTvoEhU1d+=>T4E9X|Pu$+7*6c|(?2KV-SjFjkZcf1?w*JVZcs8z@ z$2Ks)WLr7@GJ#R{oxU&S3#NRWy>2ft{=e`9*jr>c&H`pY^cLmOWQsk(;*G|vGGyGx zXmx73w)w(>>;+$$8mw82^C1#d!^4w=FM<=5f${dn{B#KuYAYt8lrB3>!e)XR;U6^h zML@i3ebK`JN<)3c9>?8ik7asoIWhK zUP6TQXuq4I`Q|I`B+=t=kd9*_&-rUL;Drq^@u5~)T)2b2<2$u$FN%vJ}?vT1X zJ^^a9(-GFr=9!bx!3y<ZWS@Xyg;qmug#3uujrZ4I(?SSbWq6$)VeY!F6RZ@*|D zo+%=uh>RjY4xkHwx;(^0*8yUuE%gh%et{2iOp4$H9QoN4aWt4IK=zG(VUC&V#1~Lb zE3G4+iQ|pPE505M5<0vt-CqZ1GwNkopYCaig6OwE6(_}4ZCCn+) zbDg=Q|IoLT#$Cdy0hCxyT$DS{#9D^q~sQBfxef zn8UmBpuoITipH5r|NFoTY+=@y&^RQ+2$!*gY=kHH)gJn0CoS^#yva2=Fi=p5B{h{f zipZu+jyn#yQ+a0~D={5TQvl-Oz&usCFp0c)CS=6Vv{V(w6Kgppa*X!TpQ91^i_ya|w)` zO>xV7s3xNU&Up()VrDv2k4T#{kh8^SW-F>()&T;_9-I`hjv%c9^srL}d;2f#t~&Xe zj{q;ZSk9M-CT!x{vhL7H<7ED^Up5xax$kjrK@1O)IIKP`?im|klUVqru>eXUzdk12 zz%${3Ca$*Zs3OM}jb+D!xzvbt20Y=@=o@xD$tFq|2pd8rToKKStiZj*oP^NP7yqnK*MQ|m z)^Vvdh~dO%45g2z^l25Uvnt3p&$iV!M$`@nphBz}wW*lM73dYpQ8G!rA&GB$`m9w- zpz32hFm+if*u>PsEH)(XvPGw~s#MB>LD1J<2^|+4=?Vj65F3@JYNxtoUApmu4Yt?q z0#Zho%2bC%-!k#^bftJ!A(D}hCglS#G&2$qK)Pis~s|No^24MWymosOXk?Kx>(8x(GD>beJIG znaY@8A}b=G2Vjyp5DEv*_jr_0VWW-+@qkpdL*|;2Jc0$3@bW|&cp_frb%4ZmK#Dnr za@s+9K_nizRWXQdXd*U{ok8q%lqPbL7YfK%NSRHfRI$|-z_P-Ood#4kxn(1I)pqbG zRLByarDz<3(aLR_0b?kdCL8gN_b%HyQfDWe7L_BtZ{9+XE}dI7ay?GogK#s744Ogj zWTuWwg!lzfej#IdZ@*ZhVRdM#iz>IyREwvgTNQYswZj>$EsL%jex&W|4Odh>XjP?_ z)~XreQFO)u8oZI-;^H?(ffN_JTh6_TC?kkggpkwG*O8h8;c2&+s<)d`v~SZ@aqFm5Ena3$D+-{P4`lt4}Mr=!Xuu(|R zWZ>9sA&DyQbP%0IaTBEaTKL083y^I?HmiBqH9qS|AvG+S2b{h;3(tW18~X5pmP@47 z_Javwd`RR$LfB-QMm?ay7oK#SvDcW&Ei*klX1TwSg;C6?+4kKzWfh;Apjd&SE+pDR4bm}u8i@6!uyoi(`E^NUWsp?nsmE|O zjA{{r-EL0b6fkScQg{Muwxm{VOYxK8nk!-yXmSvx_)7jgt9Mwei9woccT(1Z zU@IerZj=y6Z}i*22ZE@}2VD}Z#tmOS=%LwYq|87FX+uqGC<_hzjJAsg(!#~v#0h~TWsWpOFeuoYSR!5{Ow2vs^&-S@ zaBv;1-)OsND=UeZA?>+L{?_60uy@3^#=#Mj^l&sWvqiWtm?A8#9mE;;8ZnFv*5=}j zS^~-tWk+d*m9;#|388^fd1HpMH4`>xl$2l)^AN!jut&I;S#t9T3k!2Y zc)59bIk7c3ojn~~OguOpoSFVZ0giAsbFy}Hu|_&D{H17Oiga}mXT);)Uqi5WR960P z!Vb>=78F)w+#V*5+&o+mZhQN`)yWJy9~Mmi zX^fTK|GuNY6|vlis5)6=C&k1Ljx=+%M>x1Bz{MG{|8SXGn~Rw6@|i(R1^79krdYA@ zn(^~;3JD-gIT3t(0_MDYP$52q>3`__Pwin)Szd^=6b!=0Bgn%eBM5`=2*dawGO{pX zDM6UD@PFDWI5@kQIG7>+)3-IY?|-+I`roz{k#<6uxFDV0Adz(J;T4GEMomXa3CuUmF3}q@+DjmAHQN;Q6v0)Q`}xNq=a0Pr*X|NmlR z^7+GOFVExp?m2SBOqXKLVux_3-EMI4P1Nh*#oIYp?cvW5eZ_ERPUPHVbx~z9p#cEQ zV?{ADGdov}!7R+TY!ojoOFOO*HCbJ&)>N&w@Q?3^Xm)pVCS@5UnvTb@)U z*v@Z%F&EW+%z*C6%M+LC9Pt3xx!kVq4t2WA_(_^q2F~A0-8RYu4u~#R-z;BlloqGb z|JJQdDf$3}$rGbKXla&^1!RglYwh}G&TM}+|FnPbBxtD#4zO6+ooKk|fCE)Dg8<;{ z9_1g#;3SDVUiT?J$3U#0iNJub;JLb-Mbr?QAGZ27L#Q@r>@Cn)` z3grM~cvz*)#?9bpF*p2;Hh$TUBgr`J)sd0j!g}c5`Qh!JBo)6^3}uAYgJtyFV7&ka zbPSbC2(al_{xhb4#yfA-TEcrAMlEwlmivMKkg7xi8>E4b)IORdQh+e2J49#SqY#6aYZ(7pSYsFywfW_Xk`z-7qpt?$LV5J zw-+ACQxqm812}zBF83CurUT4p4j4%S1<*jIN#+iCp-Y^iiB1h#hMt|()zz-N11;(- zeteRzNowbu!lBnZyY=gIwc{$H7sGP&K2=u-(SCD?%z3xjK?ARy>Sp9hgK1FVI>p2F ztS>}=aw9I;MD0DVcaVP0(UP}ySKX4g%ca7`-*L{mpe>{JEf;GJfh2-4VD`{CxUksa zb`A+G=*J7Z{V_%E3%|y?h??&Reg+WwD+$#LPWPQV-|zJwJC-`gRgZ&{Q=!{=n2SNA zo8;wa^c>B?esJ45YAxB4@aA;S?{4lX7=^hPkyU4UU8^2p!c%3eIdy;7d9hTX0v^`j2`a_Oj;u(yUsykF_Z? z@BL`yv!q*CBcWNMzd2rGHJY6=*3|=5((4H%mDo@b-Qhnw%3S9rzSyoDz6AXy_1(uk z`>N{GXW)I%`PLP3ncl1cGOwJVsV!>I(ooQ6iQ0FOS`&RXz$vu6C_S*AWoVA>_8hEQcSe_1x*V9uhjIJ2BfWWd! z*a@U``Tt72q4{*C|7KIw@1x0h&u5gNS9`w0oUGaW0INkjBVKoeSl^CtlNfko7j*v@ zukj6SN=3<}zO(Wfb|uUrG1sfy&4p$INj$q)8GEqShHQxEWbhB%JoVmh^I$QL^ zT&=K5ZaOrdXhs5`;ZHbkP-MEXYjU|uqW*L%KgWxIuQfM1GyVD2v*p4p6)70`Ps2N#pXRpRe&RB`8&G=z3`~EDa@^_`|ZVgf1LvHx4^7F z>Uy-xl2eR;r+x!HIppB!W)qm26*?w2$A0kITO(_IM@ z|B0*h+Afz{+sln}8zUEAiS}M$T0q1l3LdJ!W8VElB-UeRb8#IGXCkg z#+<~}_V2ZUiK?dp@`labebAU0d?5b>+GGISAeBK4SOKZpjH3?b|nlb)~9!F+#JY4Y|?=7E| z)UTy%2u~XM`J4^8w~YI>9QLu#uk^;{w52m2T4wsVWu3;+Q45k!$WqU{FZvt^rU2N* z@5DTMVn9<-qPuLkEKqebyw+-=vvyWw_^of-7qfYXcDEfKFd$NH0Kxz$LACsU4TKMHmHS06{Rl>G}kSk%dUgq^^Ve?4GcV0#-eDD`GKq~EE`uYro;g1V1!{U0B zZH2S>Ff0d@S>iifrvbZYfsu3UFN-M^G>K{aT0+#ObUIJt!^=#F^@2soPBPZ)E!N~ zXwCcvrudV}zeDzc5-=4Axi7p`RN1iIt}(k+Tx*E=MhSDNgiC)4VTsuis9@KdyGG15 z2KCq2T*fL{(D~N7Ran=hTVMqq?i)>yk>3;R4?Pf*O7L32?u^w}ZImrb3ui577Z0XQ znW!>+*m9gliiju*yiS}7SoE2kOpzB8IG?yul9mX2*WxSkq zg0mWp;Xu7y`=1l;b(Bc`)i`@2&k!1?j@@t56Xq8=;U(j72)jz}r6Q^n%3pnOHfNH} zQ3K+&r_-kEj0Q@kXP;8Pyq-zwsjYgqXTF+PPb)j${4Q21Op2a7AS?_xpnYru?|6Qs zbz(IZ@ZKm{){q}vW|t%uH4o`8d4*n@Eo~XU=%mr|Nnj{q+(JN4PQO$pyy`iO#Es<> zQ}1WAmodJ7jV4zK&5z&Puhu$(J10MNpL-{fTO&V1#R=Bu(RO(#B`-P1`3!#^8lj9{ zO8Nw(DzE?q$Q-%UGMG2xbw>m4gEyW5dc{Rnsaamz=sVYro z9tIRq;u}qugczzfgZ+g;OR3?9M#uiZv>Ft8L?b}05a8@4V_ zEc=pPDs>m~^(vaH7HR#pe=sGspb8PQt_ZHhN@H5&>WAjs^;kK&1NL_nBf7C8uZLD= zO@^+6n+4&T{od{e_L9)u z{%hRj7AhZo>j*J6Zn}owd4d$_Xk&9u5A0SH6tuK)W#qP~t3O|OXZ0sjM;x}nCB>!) z5UG#&NaNEp>g87GwT9JZ)6N@@%f!T~Phk9GkvpvEc$vY(t!;Tf0g*cnJk&8KK)(_< zAZ9Oo=VoK6pl3WPkO8yEPO>C(d^eJl_m5INaJTP>DBjrTSV7&6u{}x*r=pLCfBCXbj$4pdbr$AP=Zw7$Fex zjO!x2-@d0!wNSy1R7Ec>qzv13yA?1zGTEt~;<9I?biaR#(ieh%?a(LtKK4UrPo0a9 zXkrI*ce@~z2d;AY^W&>;c3mN)B|9nt%Dcf8ew=$sQiz?P?^f(9>_BE}C#yy@4>kml$ zQO2g500e$ZK6{;DBXl&tH$S_0d-^Tf?CVxh$mFGn9G$26Jd!Qvp$>+$A->+!hu{i?-^F204>f)>&!?0wM%36 z(;0K3e)bu?B?DCbA?Et*Rc*ye6od&+#q*T{SB?_6?wWPCbMH3$M^!DRsjXPMtcL_O z+?AIWO*hlHa8i<@Pe)~fnsnpf`k)M*ud>CZ7aHlF3lVp^-fdbq%nG6Vzy+sF;EZcN zFZ6tCM*Jr-Ucu9t!zGsCWjv!6fF`eCcxBrib7df@1!`7^6N`anK$mWYI8sUUqgP9k z{l0XHOFwD*)o0pip(QanEwE}-uwPyez*WOz)^(0OE*odPDDLtG#bu7*-mBUp)o6G^~Nm=3?62 zI9K(XDyeWo%fCz-8*^x9_$MX+2|D7wU~YDhq7k{&Y!PH}Ed$(WrjJ2Hl$SU3-uqIL z@2=a3xLx42j$-!%cxXi3iX(0M1Rinh5Yo*S*?keuaV z$x3YyfUR`QV)V9}q~|`{pX^5geMknWSIT~;>dwEzI%yz|HDHTj`%{=Iz#rql%Scr< z7;Hm@g?ldPjTBLPa>yTbU*m`0J_o3SNfBumy#oS(|uPMRn*;2mX6f0PI z%+%P{-3yayxen`Us@}e%(-lxpr$CRKchk9{z|^3oyw^5GZiOZDfd>^vvp?g8kIFYz8?O(g zZ?#+N5InxO#3%0aTMKg;AC0jb%o&k4J@@>FA6PD9PP$U8`o`+h{N!3m)8Q-RhFmn= zPUm~Xmz~F%`r&y(p$|=cUSt;%pGx-(3H>IG&fLLs4n_h2y9l)-`L9L*3n+ zU72D1sVkNBrMX;C;NW481%zkCTQ!u;nz1F_WsJrm7j{`}+3#B?CB%(+r@R(kBnIR= z1xMCdn{F}2Y9^E}c~eOyxUeXFvZRt{3a>mUqmZQsGn9%!rS|B5_hF9n$C(6(-Z3A4 za?t_2aA1Lnc)m_G6tSfNlO-Vkd{}1$K4JX5v3c|~)TA(BhNlLH)+CpM(qHe#qwv-84A5e^B%|?g48t{*$C#8b-ywtfITn~Xp$&%={m57ckp(*8fvLg!dk7LT zG}7(E5?-Ua`<&Ez zA8E(YL(vcp5h@Cz=c0}T>N~bRSP*bJ8iacJiFb`JREM`_X}!Aq3j(-f4?j0Fj#-t? z`>20@Y=l*0((l|X-d(KYdK^B6K6H4fhd9a(=Q`{XdHP^XPhzKPT%_auDi4t9DxEd! zY{6?!WmRU6{$R!3Fu-hB#(0G1!_oTinYHQBNh;Nd&*{%@8Yj5_jnZe+vP)K)P1!e? z<2-Ixlq>776y(?Uo=mK2w46no)T~PYKdKS8soyXB!26;@o*wI*8!~85{8%H9z=9#} zV*4SE5ZzY$4xZ)L({&U&JMnH(jV5p4_25q@CCn4ZCi)ivGv5&|+oCj-ZXX!*_pP+b zt?PhKCo5qw0yf`AlKndz#SS{icd=gHKJ0r%uUK+Fqq86{WaGKn#+W#a?hpn5Qb#<6 z`Inowis+RXAN=ZUfjT%mkfl1V<5>a_z{=J$yimBRB0!c1wW2fY-4}S_bhQNca_&v` zm#fR844y^(eo{Aho?ahw%u51bg+Skz&Xpy$K^U{3NYl{ov6iyrE7XaKbfM1>p$F*_ zJ`I%jWyPp$TFjnx-bX3z@}gc^f$q!lL=cX-n(miT!AL?s7iYYhzt5DkQ!`s)=11jdGT@K13fDdPp4{g}kLxqyeTawD9InaoA z?KnZcZV7eyT6A10!Li>Rafyaa&>OD0r9Zz@ExSwXf5#PVF*6Ui3N+-*Zk0z5qFOLm z*Sl%9bBvyA*f@ud{E>054eCZ_NFgPZ-x~0}<50DvX}J0LrmI*}cx8Vch4td*%a-@3q*3{k zapv>4VdSiC=Y#DT44FJ^%Lm87_M9}=BTe-07dY_~1&{;NW9{7xL0u2pZFVW}aDMmK z52~5;m=gU6%KqL_VA8x+6m+U&KEO=I&Pon}gC7x+3q^ss(}*aC>(?{39`v;FQ`<9` zdOC>qLGrK#cM}}@8z#Otbv8m6T1(kcUsi6D+)py6 zE1bm!1T-hcc**9_q?KyW{kTd19Tzi8-#g{<_o<+vd$~MjPh_igxEF3^Vx~EoWr!iG zFK>R{cM_w4T}(HAc+N)?hI2&E;;*O0SnbxqTgrTR#}fXm1cg)h#C1zF4(&`Iljs# z`zc;R^1PK4wJ1<3oNH;l^|FF$*EugD|Kj(>W<3ShA4F=x&gOGGmor0>lpBpnr z&hp-JO2-smSk$}D_?lLHn)6=kc1_q|`)cI+vJ|3gxaFjN6oG-hEaRt=@LrU+V%$vv7eR{9-<%ypN!r0jRLXY&5 z0IdYAGxE2q$6>KYrPjBiyuv(C+J|@CKrYeuIMIiIuYafOa&CwV~+DnHt*ON z*XTf)UunOIrgrgOIIjZXF**_xr&0401E+{02?EgfaxDAGBUp%AEGv?4l7YT|z7}{R zr|^iuOCE;@$-~}Va!epvX{7kJtFtn>L@G^rY>*EJvZRs(X{CA7 zN7ni|#J<_?B@TP@CD|8JmdfXniQwd75Rr_R-$NoqA_egw73 z%(_qnMA03&^#V~csa}ZXUxu7`Yb~EcLTn!d!blUQp8RTP{me(u8##b1k{f2j2}C35 zTR+$K`_^#p(&;lC4^Z1LwJklN5<$f+D=KdgkhAo*JRQF9m=5C~NqwfA7H;`;`X94F z+}HZ4M-Y%LNTrSuF!3xq>}ERihQl{g$dj0^n`hbP;PNSJns&gQ3x?%kK81F;V&q)hkFEGJPNR*6QclaA`Xtk=kR z*;0oeAVWPGE~jL_8_1ibqEJxpWtzj@@#*+A#ra*BcJ|X=_Ni=%=Vrc4l0QgcE*&5_ z7pF>ft(Ewjuk<3g1NRPAT(xBZc%yHs0*hQu+^YoDnXVV3rVw22<9FIO0Dn+xXBhCQ zkxBIrgx0+J5x}G;wy{xwbVla!MBvg#Q}gfgzp$w50gWPy@j&R$J!{9iG^f7jw|v&) z8jU{m$_!ALN!(7hdbRQkqc<-BBE*-i6ErRaQqIO%d3D137{1bb$6r$YN2(b!z3yH* z<43;!2?yodHQH=`$Yw%+eJjgMB5dl;EzZ3lqy-!4H^zIP8cJ8E+{TC});UMKMA)Vr z2wchs-Fzlz$Kst?j;a~8bIOGb0F5nxs)5@{`r`*uuo3TlINx%n(!<}~YtQE#!yaJc zdp>GFm2}LU@=g1Pv7pbP48WkOHGk1UMl_HtFv9}zx^G>qY0lvMoUqoen#iqLKzHtf z>7T}f_Wpy(W{)HB-Okiq*PT0^#|}{A`Kb%nU_(BKf8M?a!c0e$n9z%2jl4f+=9caa z?Of+;)^?6Kt?wIoZV&sKRhTZVA>DDIzJ-K_*q|j422iICN+1MdLx_O?H(dDB@)Q#r zDu*Rzm6Lfp{emx!)*Ju2ruL)RGB0x9>r`4?9Hxl6I}EN{y}9Tb6ZAYZ_oHp0%vK%e za!Q6G4MjVvhD5f`hpo9<&Q0$`|Hj1DF{yl(D&6khyHWffB^oX24tzw4+e1i)#V9eI zL+uGelAc&6PQSoMHuA}Yg!9_Kz>%KF(U@A8Y&?>~K1VM4bn&3Hhl|hl3V-MOOkg=S zHg;M$BvPnI^BdWs+Ach9AA|Zlm{+RxTs)ii3H76mi&@O6@H6Wk+RV7%MKkM&JWeG^ zvAgS|+r_2@mj&ct%<3zErRuMk`LP zGz5K4Znc{{-W7~~T6G=ERiNFmNwu$e7dE;#)^(n`cOm{vtf2Kvq@epoR!9SgN!I20 zxHbyTgZ~ZihiNkp(qNNv{H*y-rHf4ovTz|QukJI;2-*avyAALghS8 zq~#TWVRA*qJmKWB<`EXNBim(HvsFAdj#SrghcoPmI4;#N|25(ix;Zul?!tDTc8JIh zw3DMr+=?&xQ?_Xx#}sa~W_^Q=k*Y%ih|XuCr^yFzv># z4^pobP(Nv{%LKKLJ!X^!-cr{j7hNPd?iS0>$6AVN`8i^&hdxIGq&(tga+#p=musC2 zX#7bBwbRPfAYnoY=k|dN@y7nac#6=fMGRY-WYhEZ)ar$cP>%fv&a^{{68&6@yq|rs zF_PV=>vaM~PlbP|rf)wLQ!99{Bp5}AtQYM5gbc;Y*QTP-Lo?*|;m3~!s!a4YxqcUU z1~`rOd~QW|G4MNL(GU={qT)ukMLK;U%@4~1lD zAJ0vELh^woO>{>JcMcM;akb`CMg~(ivAFN^2i}nx%UF^|gs+M$Tl%>g;m8f%2;8ag zbk^&VjDNbv#9z;WPM7F*@rR1pVi%x5g!{+?!ygsp)2H zvWt~S+kydAoTS}!SzEg?s>y_VzNP|&u0Ca`_cservyYDS<~;=Xtfl41>-!e3&W`)8 zsjZA%RAKrBog#<$c49#Ru8-_8tXFzsX|Fog7pOPf5Bzgm{6XftW>toPA%_`Ndq z51sEReNNj-%sj!vGAt_L340@1(xNTD-N&rSk4|6>#StHVuukP&+Z~Rt`JOMV1=y9~ z*rXo;wnihkkAR-TexDxL2Oh_9_oaFV9qCt*Na%SjHAib2(p(F4^!map{U#o zU?!}9u@^pHEaI(loV1ZvtV~eoAxw_oJTS?M={T^AH=-&qQcQB>(1%`^B#g{vXZ4tP zRsB9{vocum^nbN8F_g~5R4_7@f}Ka%#rk^2woo#f=hN=Tw;QA5M_H_9;P=bs9P7r5 zNyxOLWoT{Z_`pru?ed5acO;m2s`8Y`;I+;!8WIVwkAb2xC|pf9dx(gtM*3OZIhY5Vu*ZFm3c~S=CS#1w&QW9r&a%?Axw+v zN`rMX)=kr^`jlQ#k3&40igRbMDgm3H6-p;X-t+%Zp5A2(l~RV-&+4kGI%!hzsvk!g zSZKiko9A$Qjo`DLX=($+pPXU6C|XDu*meNowawqd9U{X6Lm^Ph1VPu_*%A^&zD63q@~7 zN3OL@hth;^XY9Op3DyQvr(%O`X3UbOPliRdih>OSn|`{E(I6ORd@l5oj|EcP%*$Lh zU*91cSZn@9YZfHMyNb-naA$2hgh2Q1_P(g+pnSRm7RX$sxf{5pyeb3*oK|`yX14}u zPNtigFS&5N^a6_2^J!Q~e&YQa;2Yi+xKKdp`{eWJr2jo{eg3dWl_hfMj3FcL)5c+w zq3Xund%s{od()ApOYG?)t~T9^=cSv)$|?N4ku=buD`$UMyJkB)#^a+3Nm%R@kt%)r zMfk4mCIRv(@w3f`>v$Z4YvCE6KR8HCa33OHoGKR-r(74veDc`|Ucz5OiXuI5-x;z8GRCc2 z^DKEpksu}dHAcNB$21Q+z7xxe7~}>v5Ji4;HEe6Btyo2w=mZ5n^SM#08`M5XPv>h= zsXlwU`rXwo$9v3GYKD!ekH3_w=&8I}h6#r*h0GD{uH2h>ibR=LUBQ|_~eLjBA3t}1zE4%Tq$R7!B>^GIR3=+Uhk7M%x_R z=%~Mr_wG+H95c2?D9S}Y8uTkxf3fKj>_-`P27DzMB(CH18A(sC@&Yroh>Q~|6#`A@j0b;{S`u;e{quKaE!**dHJN>C1kzu zs@g0HTd;T$UU6iA6hA(_Djfdc z|MuZ10hKyxYHq_*)$#QO)%GzT@g^O7T0WE?;PtiKxq_4?z<88dpJ_4)Ymn-?;E8|C zk`B4F{V_AbX_UsKs`g}}9V5uUs+(4*nPWG_%xPk1m;2iO zmfd8k{P*@{+W4Oi*zIaGf zs%x(KX_4BHsK)SYyl=cOb2y8pQl6%?;4hoBZMJ6*yQeK-l7;qWCv!&1s>sxrDj{14 z8Rcm>=~amOJx_HC9q>mt@1z7rr(OiQ_~%7Z86oR>+n0D3iKDh3Lea{vEI7x3sY`u? z=`O-?WATSZ&$dTco*b1JJtrO;gD1Zw;~t);Jcjbr`hQKKw8n(-u(m13&7)-xC+A^WChd@U~Z=pZMdpD)$1-ExSV6ju`}^xD0XY+_R~wLqlg^Bi&*4*#?78-VjdjCe3+Wv zp8bMD*>3rwuEr-bDvxyB6zW42_Qw9!44khY=v@)yYB@#P|H6Pm=frBNX4uV}<5iB8 zM4>&qX8tB1>)2iA1SX!}58-dg<&J20MP$CMyX@H>g^%6(*Y~EI-yCNsPQ9C^<80mx z1uJTe0;g>HvaMR|F>2q>)1s&p<;a6hnX$AlzU9p;5W~49f#Y3b+pD21QmR}yUn;Ch zg;KVV$D0Hz3-Uq=A%1Z|qksawMYB>=lL27VHin9y8V=-n*ALf5ov2P~Y$}KE6M#{q zoQ14O@Hl@4bnNT$b!zxt@F+cqRp(&yMffh5*lTyVu<{i#8VK8<{l7L$l%qKT7X3zA z0sD1-o$%t?;=GKZ5KdOkH#OO*BiT5Eiq%NlEzanP*^e|jrBcL;se0BsjOuzn3+-gE zhHgsI{&K3LxSLm_?j^zM0{<`nqS5eGQE!D9wp!({c0qISX27I^QFD^<@#ENXE#lJ$ z9#Q~L!wU1TC;ok!*!U@a69+E6?~I)7VhA_5wP$<_nkh-+SNU`C+9G<$S>-mWxpZoc z#_nNOkEqX%?sEOliiOz$#g`n-cHUgScZ@%U89S$&&Zaruzk76kF2g_ad6gSoN6}AA7XQ zbM`;(He@he4BDdw)H+5z+q&L74)TQD)%zsYesWqM3N4ZlHd=5`Sa@~u3d0WGVt%ol z_Hk7*jlS%0hfseaLv6B!vhuBIBAav0IVjSpf{v$*xBWb5m8!)q_Y0L; zhNj@Qp3D7(F|rna_D4?a1(3ls?t~IYdM_Pv&+rKykEUv7TRs!fSD516Fu#FnFfBcK>OP5fmRj)CFshnq(Ya*W z3M@DSAbEE==v!XFnUb093e10ANc*TcUyWZq^TR^fm&nGwmd19ZEqTYOdtF3HvquwM z8^L--v;YQ)!tC$KsyIx=)$+%&DF69F->;SDE~_oRe8&2%zsAMo5lGaH>nbvl93gXn zUfiqb=SuGr^&V}Ii7P*-xN35GQL*hgiXCX+@z@r^K!cy6c`iRSJHYCg%15s@-F3Wv zIoTss+{>+7xgT@mseF>bAg&%E^@7YTx%$-Cs%Jb~`^WSu^+8fBH`ALcdEX~Lb^est z5{5}dOSQ`qL+~^TR8AI6_CW;MVnBjMFe(s;E?tW_IW?XxGf}qRZ||Y;`bv1Gi&iug zkMTRrxdluNY=QND0P)ifvr2xNuCJ$Q*0=y+fzHs}+@9BP#-yXEk?4Vj3?-AV7Nij~TLd4H-6 zg0E5A5*JZ3NA(lEt7_7@2)Q7LCJM6nn`-Qu{&0(*!!GG~#!Vk4ha_hnG*_B@`7gojMmz4_HSk`^x{N50KJw7mDWm4T%+&KP+9?OvKStA_KhRiegLnF!xi_kfVRH zj3!WJlQc?r%Tq<;jr7^LIP&a@puW}juBoRPdzw&OfA}SF8t===aq*Px#k#(rP1~T^ zCSr{0JaMmnH{bzLLs}v)!UZv<+!%Onx9ZSrU+6reHO)8tVqII9qF1%r^`+s@Xy=dg ziUrDFDF1SQ{LmbX0!Dz_s!^Xx?t@bJuu$#4@Y>P99_43nQd1(}FAeS^6OsRV!Rwo> y10xuV9pnCg^&$X){LIke0f6CmYj+Q*a9+MIow&`RdHDBjR|OdrcnQon;C}(NCToHK literal 0 HcmV?d00001 diff --git a/config/noobs/marketing/slides_vga/B.png b/config/noobs/marketing/slides_vga/B.png new file mode 100644 index 0000000000000000000000000000000000000000..d6657d3f5b201a0a6cd200c20152adb232f6a5f8 GIT binary patch literal 15806 zcmeIZWmKC_*EdQFrD;h^C30 zt82SzE6DRh9qd?4{?=jfv~xsLV_*o1csiOuZOmOMP0cN>?S-h1n%bx-t<8j}wYU`6 z6dc9Pt*m9doz2y}71g2MHc&n@Y7t>dK~H{k19s-FCX}9bw)QUkou9~lADtS!pX+R$;U*=&IVy)g|M@-@i0T! z__=ua*&vkv^`S=h=4@ucuPPz+Uwxr}2~k_Qx;pZ+vU+%Uuy}B=I5=CfLiqUjSlQTF z+1Z)VHJDwz>|ISfneAO@{?melxeL_U+R@e8!JhJOizcQHZmvSqXion<1Up9sh5v5Y z-sQgpg%%mBr->sggoTaO&hGEH{#Dz>Rn`3eX5)XX?V|4GXwIr??&9F)3`Ng}1S)iC&CHik(edl!uK2!VQ5)a*MG+_{2EaB&Edo zM7hPp`Tj#IYwzM}Vh=U{Pv6$)zWYKCVLndeCx6jqUxS=`{_^93?xx)mQ~MW)L)ahbLO8@i&m^qaArpytAsz! zk-;&*1F0Y9QNL1G1~79HNP;9ll5ts-;W32aobLdCa5|*uO{yNw($)=@($m!r7hOD# zEZSl-8B=|fk~uiG?nau=M&y-Xu!pulkXX2rf)XwE-2gUKFc=}PObDO~{sR6#g;iL@ zKw#WPX^2Od&qEF6`Q>@2TSk++w%tY|kN4eu$XVCdFne4fA*yphhaY2S`!(No!~hYZ zbz^V@(a7DfR@e8d2YSKrI^KuFWJW=nX3H32lbh)}8!>D#goENszboH&!E{8-cb_IW z#E*1u%rcW1FsLNn3*8Y9gpS~J6r3sIx=hT3A7^Fd8T^$vSG19gdcwFMcQmPs#4-ke|g0yk79quC- z-ckj7W2X}Zs&P=&TWG`IA5yVNIoi@n$oV{bg+WF6%!s!h8C;3aK3oO23Mi`JqNfi6W(L#n?j+2vq=?*B z)4(ldpL=7yr}F#=dil~TX@@M&T^R%xN9I4*2Sfybov5~V`n|Dy!t4wi+%_uYd;s|D zqDhNXqP#vjxT1lS!QCH#?L({a4hLx<`R(K{SAbft4b7ldx>Jvn)t@&M@+q9}iK6qc zRY=ND0Y?Xe1c_VIE&%@5y?avXfaM6fj6MnOu|DeW-6~4A&!MaDBzt+@u`i(~z?2>Q+YSaS}vgm_H1kZ*X?=IkB5%_eW zb!~SCCb2@7fKksL4)wT@{0|&o|=@PFb>T1|hub2QM|ii-?Ynrxa-< z7KVn1kFXUSBXH}(-BH+<@Kr-i*~M}Y?#%T;=EJQea*g7FcO4Au*T(FM2^TtU$E=C| z73TYkj??3CL9lHl5QhaIP3AWB<<#>e%80b}s^utTOK^*?rmW3sJg2T z=Yh_sx27Ray~lW!k@wEel};Sip~b)lWUojlsrcQjZPjpR>&+p_FNIXvAX*4GWBjm| zTvSNZIKdefrY|+T(VuyLp11Jj_w7~N!?4k%rsqYGkpXgkx2Wu1JtUL2qMU$#rrnA~ zyPWd9y_?<=VF5O-$gN|gpkqmmF1cI+Q~#v`H`-XR<{>YUTI+6EA z;M43d@&TV{1Zu>i^JeL)_4p^NU%^l8p86_}fk4w4pQT3Tx=)4O=7<+5f0qeldsz4g z|5KLKs4=rilb>T}fjpe<4b+&?^))F+K*F{?gQGX6cZNO(1cndSaMn6E&J70JjRn!{ zftHq-@6waj9NXE-Ga6!`s7-j={YCl3j9!???Fuft?JjZki0-HX$A0dr<5fwynYkY6r5Z#k)e0v0Y7+mCoQrV$L)8>qTC4-iASGyV{?U~;^ zH@aOV>T>EOqg$heSiNX0yeY2Jy7v$WY)9SLv2oxBGV{}7)p!GR_^&r%4SrPGTUn(n zberG>@4XUCFZ&X?d;i5fL!u1SkYz$fY*9@46vh2<*a~`%{S3K*rlnOQ{3fY(wa-Xw z%SBI{z0Ni_f)Z(I!E8OOh9{9)>*IVt$NOz*k%6b`vR$c&+f6~N8EiX0Ik33ooA79p zERwFvuZhiXMJ$U-YM+n#Usl;{Jq@ZuPrmueQEt39`y1wUkJhvFhQVJ4b-kd!=G{$UbS|SMEz*TeqY=LL&l4&5qYQdAK_!wsni{Cg>~PBpwV@0%=Pe`dk@| zPk24GEjRjeN-!zFf@KKueB>#LP3*e))U28TP#?I ztM&AI`ORSyuJ6@fyCg;1cLOMQfhI4_`J*;8hU@eOy1sWjQ`gGnAnQR>@+&4m*h_Qj zhrrE#mCIFJz?gkyKkdp32T$=omYII19)VXYNzl*zlH&GVflC#YS*<1rpBAAmceUCQ zzuN$k&&435roFQ=AAT@82(T6fyd=jLQ{LRnCf#km1xHgSJ}dDCp0YIUv%fXUlTT(} zN1|tdXGNUidJII>cUE2Jp}ans*mk>7eo#9fYE#GAzxQE6e_MZv|ZrZ~;X z9_@~ntEJT21EC|YQA(=gF-%GrT4mP+gD=smM?6RdD5VLK2h?iYt%tO?ITj?AdK}z+ zde*5*#p}4Qb&PG~A1%=H^CK{c#%Y9a>up)ZZedZVR?Dsi3gNOj^el|jSw^)!O5%Pp z^WL@O8vhE|6ruSe+P;1z)Rk;F_wbWpqQmSmv+9T(Je8Qh(vBdYB&>I+;seS&}$5~L7o zdt)t9Vto%RpOIf`9^-lF?m$%4Y*wCxoOGi-#i`@0d145>^|A(K_HIG2*!p#sM8n@T zbY=0#-{amvBET&sQuhid=%V0HSMAjGf@jEwF(fV;ofrM%y?K9 zgcRi~t+G_@py*H#@&@`(lHcAUZHvuO6X$@H4z5Y_^GEXO=(Kw7L-320FfAiLH|ONY z%)5O{Ow)fl7*dLVW3U(H&pq}8!=g#XKgwrB>Ub==o#|9sWZezz)L#hd*Gt!3kIJS> z2A?dkS;PlAGYt5kqZ}PkfZUUnxZhEopBUSi-eYOl2gP-ETlM(^&OsSSIJ?sy*g}H2 zpr^dV^KtsWo+*rU&|AO_c=lBII6#y!`<3oM7`aTLRy#(;vqwT-l>Bzp#6O$NT;doW z2Rdo61aA{Ygj&6PL5U0RW7&CjMrikHlU28D&xbu^)bVU!R(kOusb)r(5hdh*%U^Ov zP1EBWNPX4E3PTMZM=1GHH=o2f3=tX2T^J|bj7h9z=@Bt~_8FHHO7awx%(rCw#5D3I z{swXGiR{U&N<15-65O+n>IyUDct4xM$PT1=A{019Z5K7t${^@{ubOH5@U^IOy`@&U zgXKpbg@H$U1~pV~9n{_x-jmMuQ0OLS+SCDdA(inf=@zbhjV`@;z&&ofMtv@{nx9?rXT z^*_J;36ldQs8-JoJL*kI%DsDy>Ivv0wwS7v(IW$6h-_yCeYM^Y@I5FQvai`8+Xz+(Ik0&#T$lfvNa=Mf$G zfJZ`sXNO94hu4YE9zWb2)8mL`gVInxj<=uu_Tk^6j;k4?J*xWIot5=nm^5LVZ2@}LeFQucOG{Ru~jdSq+ zCscdCVyg$k%Lhkc_h&yzrY0x!%)e`#URb7pKSZxh6R*Fkq?;~;O{Ok!7W?2;Ue}cQ z+4Ws9Y4?`u7btiiqLXjmcZ!6%Mfkb{HK*R%?5!sA7VLPXz#R9_=%9AswB5Mshqi{- z7j7)H`;&ML5q}e4<~$os%+X0~nHDFQaPqX%4{}{UvF-K6NWKxOMiQkc#uiD~jQ=WV zPK@oWr?-oT+{$iGr0`lg@d70E5tQ;OP?Y7zzGSALOA(&isPAcfX0hPs**06l$zbr< z?(GfYA)}6T);Rrqqgd z!A`pOcg*nB=oE8gS=Vu_`@%BmfOSBhuhGI6< z;~&G+wo6_q|X06x2IM9~#~=S=Up^;|9o)&wUxpR|Y6P zn0TJ&WOAik-uDuP{jOW2plvyvj?s@LoU<`JOR3c-2b<{5xU;ZCa>4aote#}@LSh@P zn4NDAZ5_OB4(jNLa?ZR4jalzM)qau}ZKz;>kKfZAh4rW~QlHB9TY_*<6_J6fim+y! zuWXg&@@$er`~3)0>WhWgjZ$KmRj-ivo4a6^dvZmuKh8^Dj2una)<5jItE$ghl5q2SkdoQxNZOG;=>{hH}$^0>Gf=D3nKM^uR5OJjudnA+XNAGn%KyH ztS#MrE>>WZ-$CAy<#Sl;mDJo@EmitE<2TyoB#W>yp&h3{TV1iYAPyDS-JTIHSe8Q> z{0`fX*yvd3E9z`(s~6!s$c$<~`5U=`7CTV@K#whYprfO#foFewLo|ztRZ6?UkVxvF zP0=sfpx8ScM-3DqWak5C-5=8^-zJ#{(uE)w8Sx_Qg^51i2n7qD!h{+7$}h<>pLJ&2J@2#vh>k|acXEi-=_OUi(H;RRnzJE6ua-`4mmJ%R1nK~U zP=Jvw6llU3OxflzLz8qq_r4G;CIjrDFzVAi;?O!;7#oOVelDg8s2nj6mKqbKO1kZ+ z3;S--{4O(?Hdy=qOKLv0pUz7%-@!GLkw7{D_t>==BP!C?%`roOzlt!@5ifuW-y8JU z8|wuwAue9vRh!+=H=_6kmX`C0g=r~yzSf5dtb6B#pOh9EqB=b|yPdgAJ(S0BZQGKp zZ#X^em-Q^uun_!JK2hG;=!{uOnC5yVjAG>Oekk^jd7{Brxb5lendWY#6LydIJv!>z zf|WJy76$dmOH|RPIW8<=x%Q?Zcgzw6D827(^I-nD|w!XC^owGg?S)ho|2TVLYiOUbO z*Ag|}vwnUiBWZjM*$8x+?hG*|{xrWD?^E&m>9}aIlBDbR4ky6uxHLt2+3rUy;@;d3 z5?-{Mug7pI8-L$oMFeyk|1s9IP%@zMNcAWTJ3cWFbnH%vA4t&}{0{Q0`{yFmYIqTy zL87jz4N;#Rm4R>ZYi-5xqp|m{#=fpg=G7!$Z6?$_KWclpUkD%jxS5pHbkr)~5HR_% z=b!S{m+&r04)cL;&63`0F+7`Fe>0q*(vBKg8tl}KxM5?{K2!!sWkSMNU?-PLUMb{U zZ!lraG04%te=Q@LNXMVjf>ivC(`4?9By|asQO5$K5U{c9~FC8Yk9_s2#iECL>Us`R0$U*AXOq{4%Rc+7t{1A;^Qcy+IbFd??n zssg=)Sv1k#HmDt=Oq=l@pPGk}x%UwbLWO8r*E}WKH@{Hcf;}fhg(uG_&5%=SO2Z_C z!o^dYXJ~MjBk;=w2zg{p_9|G3$%Xjc6BEAIfnaYj96~0r74xYoRC)F^jtDj?bTve0 zJpQUDX||k5%Bt<|a*!^PnCZAD?8$6%6CkKd7wO+`6>L0HtkYn#{ugk$y8tWA+Ykkb z7kxW7@JDT|pz{_oz@r|kDhx9GDXR!){iXSvKfR}@M?=29V}eqvTpWbavB^@~t7zmo-2`a)-b) z_X+`f(5KX%p6YqFgpLAn<&omN+a=4~tE6qOxl1KAeSR7$J8TogIRG{s;a}hIEa94q z`Yf~0J!quk2uOk~7P-`I`B|`hqDw)qFW#`ZT2Mkruad~p8GnMhInZ;&hU)lu_ zs5<~|te5P2%NmRk*U?Ay8Z1XxT($9>+;cggnake(i8r{q9T+jdzGTY-n_QotugtmO~G2Xvj6jo?OeucI2BCo zD9F+BEQ2^vjyU|SSNMt0#y2%*s;u6i>`ei0Ri>=oWtNtw!Gu&3;|JQ$`sM2$pU+tDM`5y&mIc}s+DawgZ5|0 z#J-$f_`oBKuCT?WZNO`xk52vF6Y76y91_uW$r#rMglw^iRr8lj+Zsn7qY;g>5lqB5 zN5`FL5#e|iU1zUuD-Xig<?U-T6 z(Ks08c@XZ27c@PFV?7o%{wK*0fKsbv!5g)-xh@ZW>d1T=LdZ9!ONXlrOX@bI zB6~$TwpMvVjbSlnN6Gg&;|yN0r2CwL%skE$oe@w6mK%jV2?*Gr7-^sqygV2w(d6?Q z-TA?QrNLVKKn9f=oYMVTJl}TIdh-%F>?il74MKnKtJ_tZ@WS8f@@bY^REPO62}f=9 zF+^sm-dKBhF%ZMpx1pAp0jTpSfS>g_(D%*ECl+0+QHdUX>H=T(N8+!Wm6O_?UXFIw zIG+3qNx{%bqHTF0Q9NWPO@4g=+tw}I)Q(bYK+#$@Ve)*4L z_J~EEYRUlLgh7Ha`QHMXuNf~cg9&^D;El=6TC`Y4^S0_|V@e(sZZ5!RM(klAS&1z0 z_5DsP>~;;+&cZ5)`3qcI=%|m?8O>nxr(B#6`oxz_qV;=PN+@*P0Q^Dkp$|w<`li%j zD_Nx);YCRC-aJmoT+T+zq=h`1GH4$=sCh=**paZK>u2`|zS8%EjvTk>7=>7kV%nm_ z^M*CByLUpb7b70`TP8DQ?*izw_mY8jw3zO3G%Tt9WayqefxETo{(A4Jez4$`qZX8m z)ynKAmEr(aK;f*}H@uZ%qXowhM>aXr;4muB0B@ zOXAu|i>j+}MUl`9e9Uz4nV)w?aLtoWu-9tV5&PWUORO%Rad*kv;MD2X2;lmsL>22T2=)#b323G=@<$}ye`iEvwg zB6V~=sWkdR0JFHh>K{ji)jeW~-ul&#K09(oDY%LxwXZ%Ab6*Am*lWcy;*LI?gIW?b zbyspRugI+%_bUfaeZ|IzEqS-nTu!e$w6UlyU8I>}W!pC1vuQ_rf`-jTCDjS68T3Bt z%K-Uj#H|%_r700EuNVn3ux}OnJB!^DHp<(GT;1hI3kA zt7Uoe8ZoF9t0u!Sq^)hYH{oSVSOOY7)MV9JEd)nChy zn3RW;2oZJ4;bBpKZl+v$^%l3^(nUdq0;z4tK`3FSvLHu%NRBhe(UMt-6dDKUwdC^% zeru`YVX;Lh$;K{s!(S2x1`wW272~wjvkLM(1VEUvHe0ho!fc)diQy#Jy>MDI9wQE3 zm)zu;`H@HTk7#FItnt{~2Co322QCXpck`Uv(Zmt=ulBbUJYzQLe9M<`)<7PgE`wPj zJJDT}wAKy*+tA85Ih1yND3;`1iKJAI52yXS=J~k_>9@KL@l5Oer|9?I0exp_;0YoNml8;A9%iHY-31-X7<~8`JwlH>oJO4_Ae2CDdrts1{l=S-A zd)srSEDRV&qxf8X!%{jY#iUB8F|aW(JQ*$=3j*X68qXtw`ECPh9Ic0clc};-TSfJ z^{|&h=VP}H6Tftt21VX{I1KKz$i(Ndbx=lizY$|I9`mqU%#s5%V&X9W9u9a&cY2W} zx%k2p9_f3yh8aWb`q7+25_u{mmspxVFV0)=J3qJI$1YB8^v9MFBNZ4rhS{zlfwO>Z zg7?@0;(=Ko=r~Dl=6fC7wJC(Bczv+i6O#3r5)@KBG2)={@2%nCuS|)t4QmmOokCGv zIp!>Xh>HK@ za#~!jQprf$L=52I=kK7sr8E3_Ma1ih;tV&403YtJlZ4zQVq6OWy~3ml22ImftD}z& zbbt8&e<8tz-vm)X!``d?3Ql*QlYK|mP2cY0c`>cE z1v?}EwIu1^hT2R$Ym4Pw4Ofw+s|~Ey<*y*gNz1s8j%(dPLo}zIIXUvF+;)9OMP;qm z|A7DQE}%Rn^OQyziF-%W1?twU)A(F0GD2UYQSg37qBa-OKrWk^VzUr|d*s?v!;B=q z%UR35K{Hko6eg{If$uBRx7jQdUh8p~4=mn9cTPWy4Y9GFr9R44IZ{fz1hTXuR|5vV zF}&pn{;~L&VXq+xoRr;Lp4a^kBC5MxL|{~YqlQo;jZgy5iS(!^yjeaXAKc&(=q`D31XG9{*?= z3V8=uqOdA)CebS=e7hXVE*|-)?)lI~iHB)VOTP1&AHKg*#*c0O-0_S=qJx|$mN&>4 z7|{iPz#H-Derr1=$D#oC43M28RXKOKkK);wJdyV0bh5R zFz@N}*7d*5XTpsv-@3@1$lwp-bV{418Jy>b+j1Q>;|iCmwT8Xsc~hA2t`vvdXz7Fl zwd9z-mpJ{S(Q9TvVA$(K$oK9TUV7%&WIlM}8@bfmc;VW;P4T3jIkUJZ`BsQ=`PSo} z1eQqP3`+>WgfGWyMBazs5Yd)VAZ*Y%RnSO{k|rhdPrS{MbOA?F7~C%*Y5xgv{Yc;w z9NmGzVj`}$BEH^{6WeFB_bf%XUK!VWPPm5zB1Bv2-=A)&*cbR-p=_)-=G^_{Ja+XD z_2_U_kE12w=hm?&Uh7A*16)O?BjPRc29xmjrDTa(g+r>x!nvoPk1D15zci|+*sqpm+WQsa9vs>Hv#Hn95*M&T>0=f^2dBoYP7++D}pIeS5#Q8(>O@11vd z1HBkT48mClp+>QOcb6~321QDz?Pup&_TRMLJHHqhXpJKI@ha$zDTuMc{Fj4@7j!kY z=5e$Us7O%L%4y?_0w&LBsytN~6OyOlYxq-_=pZscWTuVHJ+^UUMbEBvV?*!LB{j18 z+E=lrQMW(nb-|h`rn33=s_RtCuTcT~V)eo4!;QU=jl2hz>7)}e)whwYHG7kXgG|#O z81M&qV{cLKq53?dkxM%{)xUNtA4W=7e2SM?y5Y7pwrjpuZu3!A3z)a`tIpNn1>WM1B1Jwk)FW(X`8Pe33Ub6%YK(>N4@l`{C2G< zQp00t4-^6vqCr&4^W}>K$GI5=cU!>Dc z>cB6fIidc1&wU>079796XD6D?!j12jDym!4^Ed!^74IeIW%{xO{c$CS_it66hWlV# z9??c?FnWD>bHKB@QF0qblaXHkOY)bp2vZt9p7AS`Ty>8wsogv>_W^Zn||g*yO4DBBJuwU?$hO6{t>zI*k`#6uFZ&*?f+ z3@#S)=o5A;(`j$UsI=|tke8v6RyoM#%KV7R)8k(DaPULZ;Xlo>uU7npBl8$=2Xd@@ zb5--feM&Ey>%50^9M_a-%-HKiJxHda#raAUT^=eePmY3q_DXa8MiI?{Kd|5ct>29f z9FpNa?sc1hzY|fWfVbsztkVu~`{OnrRM6);5i5LSS9}kViJ3SH?9TQQj?5}tW$Vmj zAA4O%vBCQBN148`>5sm#UK9K5w~DD-;cF+%=jHStX$de7UxW~UNB+FBW{v#zOeM*> z&@|qmBJT5GP<8I=#+s`)L`Jf``;4Htb*ew85b0fNV_l4|@GbH_-)A@{|D6DQ_X(=Q zL-Q%`5{ZowOx1;O7o0qGqwH!}WD44fo5pvb-`mug79flIrw-q#s}rsTYsq1oq#dZ; z7b^dWP4$wARLy4MRZX+bM4r8zfqZYKr3a=a^0>uyf7QVUVZ5<+@BxQIz?1_C@KFid(i#ak&s}!))mfO3XEYZWeEjC+ma(CsNnKXEAANo_^ZLtv+}>sLP#3L==ta`;DMm`a1FaPhM9kF)M-b&XqMgw0+Q|?Pf8d z@HD%S{rg5TLTC`d>hJDjAFlN%=1g$J0meL7HpS1cVV>HU$wPnX=j+Ege-IX3_?cvV_ z%ArtRCK1)U_sveF0a=Z#S!p>EGE~bzL~;`|FqSEotHh&J87$kZ>Zg6S&F}W-2%tbnyGO$8$)ULK5f5^?O)|)3sory(ZOyca0`**` z!?_q{JwMyR;4f?2TSG0r9rMaMoCk7pRdqgZLA;&}BUY6XakJOo8OF$S_oWsY8k>~^ zEmRKXcC}U!)fL*Rg))4Pz5ji&)zj-ePT8_hWfc@(Ss5|-CtBN9J(NQmp)R!6*1C`K z&s%bT&pi7VklZ`6_uPT zF1|gqg2t5+V7BRfbs+w!t9nvu=*AGC!H=j6_eeQq^%-wrwmS%a^gVANT>Fi$=77(Fp3Jo44hs5NilW5jWw^yTZZruSaTX=Y|5 zG3rSmYK2d;q!(HyjB3PjmTamp-WY!SNi{8|bn*D$O+`fwze+7fI)VkBm`ChCc$R~m zGfGkfZ9Vidv8K!U_;)X_eXR-FOUG?>)%vl`y5_3mHxxrMNom5jWJ$>iUhdOQSr!%+b%H)^x)f3gjY3QIdH|MbjC*Io-Pa| zIM?xStX=F$wEkW*JP|m|98JXB($4q;nPMclDzA1L(#Eac)`espvxks_lQ=Qq>fySA z<=ZiGa9eSn=)`$$iHfZp)%n3?#=6+c<%U#UIs^h?$U6u}A7D+?`h<9r5p*Q)$&WHk zL3)W2&=6%qDIC)D%duLd`yZoTU-p-iU}D5>Mnk%<7ciw-uu!IYNFlL?0(4EM#y-bt52Lv zgs2K%t!^mkkzS|*mvUo8Mop@8`YB=VE&(3@!DVP<4t(JBpKAwmd&GFwj@gm5zBGPv z8xI#D=!UtajAg^JL8p5|NGn!#7;6 z5u69xf=3%uNdcp*M_L;`BNuD<1(sEu>fi0~{If=GeD1&!42|!&T1{1iPU=;3uA#6N z*3?EQg~qs@!VE_ys|Hl9WL-r7ie12&JE5;}w0c537{rg+$DOdbSJ1*J>Bhr_O&ser z9YH^damx1eOTQTdl@uj6#>qF&=bf>)@MmkMLE;6E1dSlfmEF?i-PjfM`}Vx1ps*=a zcv$`8YtCb)TMO&YjGuNJ(W}gl2;U67zFd)>HeYv`Fk!Yzo^8}I>o3+dw5L~Z)i(58 zISy?mfP_DNHUCrXVu-?~jVMBs(QE26ICnx>3wYaPkAh|v2I#S7IIYnM!{G)#Fw^UuVDI^AV#cH0m<>dbb8T+VA)t_4Y*8@sM_1t+eMxJXjT(pSn_KyoJ&W8yZ*%vTC~zK4DV?NS;t|vErO!eX z;(=ls+ zU3DUZjUT<4H~_*z3@=K!cGGTjJE2FvA@Qu|qVT8dLlP&JWK{Gss%}r?g{BC!XSbS{ zL*pO+0zv*iES}La;7AAv-X3?Y3~`JOJy<+!qmc=EH3_{1-?L#azZ7n}6n1gb@>>^# z-_=G>e56D9Qx4V-pB~IPYSBlxF4{fR@)U<-53suiT}c082s>ZF;qHj27@j5GhnsMk z&)`4tXlyk>?(e~qM_t4&C%=idGNV`;>4~1=2kuPf;l6tL0gSXmC&W-;C5xdX$T8Ea zua|oSZh_d3TdM4Nt~o46hW2>f7J0nUP?Y{Z**sM3+vC?OZLN9jIKxqPCDe$ZWdYqK z_mYkGMnf_(z_}prE=#6*EqY7D;6=+~s(s^oq9;XLVy5N#reYtW!aq8cz_PfciIRz) zKt9kT7q0-wk$mqR1#Py{)}MVIw>^Uv@OH3^k&8<50|jy&F~p_!{{c(E_0qx_?u^IqQPDWx`J=te%A|r0yO2ebUdJzUkRmi^z=f2EmScEq%RI zXcNe7Y?02fN4*!wMZ_o^bC5z{=5QmEXQZs&KKC>j;mf~ItkwxiOe{+*@QK3SAtIyU zxW6-lWDe!i#rEsoWA>UYZrwKRzavHWyti7m(QlY_D}Y89diiFfL>$R8_kZpg)jO`V zSL6;p*!TWHxNMCK$Lf_EcYLw=J-RZvEs}iF2it1BpSxUXT+drM>l405neOJk@FZ+X z*ocGmO!=XPk~#9KZRsDTymI@u+;mcy$nFs*HHC+X#M^?byHl70Z#4|>b=2HwMmREK z%_$y+zPS}P>v~a0*r2iVa9G^_@9-1WT8(q0`PP$Cc5Za?OpG^jfj}jW7=9FZNfYP2 zgJSJ94j;1e>ay=ex|-^vJZx>fEPyW%dX2~tV3QJEucK{pc7A+qPV*LTYaXy!bX~x~ zwIwbF;#6_wOOAAf<6$0l9pw%We23|go$TZm_mO0d6nY!OFM3^Cr!g6y7P;KcCkByO zUQr1-VfMmQM{TXkIZ-!&h>m)^AY{m8Xn)=3R8Ua8`6pH?Y&Lt8mnefbH>?DS@|}x1 zedorC=vsAvDeNgsXDiO#dd%oWoB_KwA!}L|`KvxRd#IZ!ydd?WB`CF}dD1R(lHnl`=IeP8EkQykYU~FZE(`E+W`_RipYDPfIF?V9SmNV^2(#dIdu1gNEC7&QW_6-UaxCLr@&ywH4+s{XDCGD(vSXv2E56OhUf<_vR)g z_sOf_WJWAbxtc15y}hSRk|?C>Y0HL@3~=CAAkHq(j7ajX`=T)4-nse7v)scCnwI*o zMd@*gNZL1NfnU7)51vHQuzTvP9SaN8eh1Lv<3^3hL_A_OuvK4W)107)!hl!XBn7PU znL?MvU-@z3T^$E5XEGC<9cEIjz1fNl$w`nro08R2Iakw}4VG9}k-u%$@51WOBoRp! z(n^CDIG=2!ezatWRmD>%2^TH2*Pe=trTsYUS8gf0$f#kcG45*WdCtTLgotSqC9}9` zXf0wh?2(dqEbbJpy`+BwviLBUz~1g*f5mVHg&P=5loCiY5Nt@R@E`a~jv^HAtH0JZ z2KAL7@4c4zckImHDTxTwPYc>Q7Z)gcm)Oq?!v?o18<|o>P1zJ9et!T!TE{UeL1KVm z4saRBX_dw%7_>&x@Ygf;DZE9Orj-Ai7CB_J7MUFb4CEVb9u~Js)po$2wMonu>~7H?6t1#5uIdivt{xC)D29}og9()Wy&c2?`Vk5-^K=@5ieX@2I$CMy zxaue?iI_UraY6p3;ey#YqH|+lh)Kd6A*MD^S9%kug_XTH<6%n&BfXWGIHR_JGLN#O z4Aj!7wHc$N1ictc1YLj~)D=Pxv$M5#5rK&_{;OOO^!LBFxf$vI zmBiIXobkVm(ot5UmvL~0(hG3$aGLT6g6IYLxj_6pulZkd(DU+uc(_5l+&n^@ARZ9` zArT%B{l8y~=-Qmk%tb!FmHT&H=wITDmaeXjBHY{_9v)mCd|VFB7TloMuU~WX@N)C= za-vgkx_H{VLSUTsE=>O^;Vsm~)Y;0>)yl!1{%?s869+d}aYnSI|MduVj>^jaU9i2& zza52k88-~#$PMD+;kL8;`&|D@?c(|o`hT18Kc;rk@N|T7e}uX?xH+4m+rymcKbg_K z`(Ib|HzC>@5mjd^bfZ9Q-#VDO*+K1H-@g@SME}EOW@RP<;pH4$c}54z~a41!|TKt`07i4vzFP z>H=IKdS!^ImHpp4e;et)p7|}**~%SiCg<#6NB=J`i&*^+7RX5n$$>yZ{5(RuJc7a? z&}$ISYgry1L4H28?b3o$jQ`GS_W#v$+-QTi|8|rAN4NRUEp%V}`}MyE0s6;(4LK8 zJ(QQ%th6^Y_&8*pE|0fu&lK(78vQhKD{l7k^2&ND4PcnHZl*Mu$h8GZhu5Wl82*PL z82AkH|6Iy=z`8t@9M{u5Ym)`ExGM%LkR>uZVnO6;q8)z6wklz$rm6(6xmo(R*D=92 zo7^YEt_;Dw#)XyD7SP6vZ@WGFksUNydQFTs2O+!d^sU~zcipvR7gk|-!HI+hlv)zb z1^_s>-rY|TZoC!Z7+Y%jB8*^Qi0e7OnxLy8fXfI5ZFCv(_}W1yww6qRufS(7(3IrS5uj#HV zjoJdbZ#3zp!T|?M5)YIX4;shq+QesQEHPU9g#wZ@30E*+W$$ZWj`Hjv?#)P2{w8tnDgEXS z2sj7Yd;L6{hG!E;$$RmC(Pvjz9QnSpA;i$?`!-ZKbW-!OGA zH7u7L&$V<9S8?OB`@73pV6CmGRvf%|2MpF>|B_xvC(U!yK7#!YkTL0J>8^7%JtFE3 zKRA|0|E~srgGa)U(scI)a>$9Cozv;Kc+20)07x!Ed+=|oMG=j*JE%17YM+WuYueoA z%Evtm?0C}sgdyF0@f&TowUja58YY_~!|bzPFDVtICw~6?O+-y}L5ZrjKK8U!kpXVG za3TPon_$o%*Rt_TZOZnGRzJg}`_dH-A-+-B0Zb4NI{rL? z`VOci;WM^#gSIh_91y&E<@i2Vp66i>NvFo}X*JK*1%&0QHFX%grzT6P{arT z1)?7|n50CD-wP`_#Iu7E#sIrmu;61jD($$xhP0i}?%LFf9`K6T4&rua-=7s66{-5N zE&HNYAZNcP*Ek(K6=BF51exJcAXyq7?|+1Ta|mHzI`u+ zp5KcB-Myy^1y*FrOS3$;QjabgI>blQg(~JyHwP^ajccJ)Y2s|-dhI@*+#Xc17#)iI z=!RqVTqPt7CA>T8$pn?+2Ym*%+AU|*1?T7kx6Imt#|!70A!k(OfLuXub-h6E`>XAq z;Y4k{$U82vlR>66{|A(Rjdu*C09)&2A2-30ZH+SQ zYQ%_3MvEw#;`vbx3z=K3{6sOZ)9B%PZjX;N_`r@rhCHz?WA?s$%H`X3tR%rVWfRBl zCoE>6sbO;sQ$j1Q(?{nO{^G5_Wx0!~XNgtCKKyBryg!azo9noD%XZ;m?!m_sVyrhC zidT@EmXVkyZay6st+@@Qa%cr*IQ3Kb4sSrYy>%}a=h{i{?++i^oi9g{IB};7R0%uK zHiADdg;Lq4{KP-VOuk5WXn(!zI<1_lcSPuaDU^r_i znKF4bWnc{cf;WK1iK32M)$cSNX%@<{^?)wEI;@SL!tcDq#ed1Vr0ia6O+I$qE`&gc zCoNX|Lg(Xhaeb>@J|%}iGrulv^;WG9p3)RY^?{nN&M@epz*``kVt7awANUudx{UsM4OT9dxm3|fT zkV#~TwqeU|(_N6JKe#;kV7Y$v1dnH3O9)B9ai8pel`Mgz^SfMI%fA1UEoV!k-1Kx; zf61oU*~4RLICsT~@Ao&gS*SEHa%)=x)pS(f(8hVYqumh?QHSS95F7GKC?T!EjaQR; zi;P(Es$#rKE8l&kc_zfMdZ9BfMG1$hDf!HmF1yLv<7gzWCu4cF2NGVXcefzU%MI-b zK|WsMpr|`)*9j?IcooS(8wyeRaDNlFWZ$AJjuj#0OR#d$2I(u_?w<3%8e@2cwHfHB zKRC;~vrR57_|yuAnP!h=1q^BiqD*W$uYhG0fTJGv~le4XN zj*??HgKQs;2p{4M_}q48DktTrG{*_C9Z<_I@MUBK%efg3c<>N5Aj+Gp{9*Z>C|_U{ zdwC-x2e_718w>Gpj|#&i5Tn#o$!>*kus3#6sTQX;jg_qj`h#r_e*%xv0vFk z5HhzB)P8rd^p$fn*6%ELVZ??^-%;warQ@c>u)}wqID1fEJ&O-6#+TuD{U_C_`^8$* z{q=5-+nfQJ`Dn`I?E!i&uopgTJ>_M1*Cfx?vR7SsKC5Se8W_}GQ+DuDpN*&eJQGdD z>3hOaA@4CJFlTnag!yg7svxs_T=bAS20e}JrLKAkqkX|Q8Mnk!;8Ds^Xg?o2e^6No zPx985cxZf&$&S^Ym`<%>50FN=v-|`G5{HHWpEr53hOrS!Vl%;^(j~M(KC1yZ7ejNL z4a?Q=D?;%zHR0o4;v0ZeQo+hfo4JI6^Uw>(VH=9TW5rE-EyKqP_p;@%F?VscU{;a( zuZ5&w_tSJ1!qptlIfpf)2=&c|of*5pbU^z9AmL1+%Y5#oBFbH#a*a6$C7qt{*=( zp1!@$a2YSs@L$hbQ~Q3vkxO@f6!u4C5vT>empzJS5HA;MUBl-!Mn^7kKxu7&k@p_e z5HdE~RSCAc)k2sCgl&A`#REwHrXk5FExBF?I7ewfK8Jny;|;c#lqjUXKQA?ci)#cY+`wDfWWrDiwhvh#@3xEe zy>lp=2o3ll&+|MuM+5khy6-EQmIUm>;bBAiPiiBbbl4`l5ruuzW)hF*$*(==i)FD= ztLHtD&ZpaO!iVdMhqODo55@+$t+V2o@Zh0CCA$oMtBTB~|b9^n{z{7`bA<4B{?7_t5snsoesn6S_6PYsJr9Wz}45nVaB z-D^u_S=JHs=t!aJtNF_i3>hAB>D9y7N9+4~hk}0)=36_uayDK7n-XAWjOalMg`III z{xo67Y33nwa?xcMq2I)FOgt^b2pEsP=5sOUr?BIJMvz`aa)F8A&ElN7!%$klg@ejK z+4g<6cxdrMM&m*hPZm|b?MF2gPfu=UY)p0lq>f&!#zc4CCrFz)Bxlr)M=gc?e1R~4 zw%bLuj3~@>cCk7NCpPs4_K2+X>yDhe^P?~)3Om$OEEi#e!V)(alu`to#ktKXtwQy@XSg~ zDi1{Z#QXMA6TIyy7lnFqvdr{wZuCGRarTWc#K3*wh2AI5pFwLYVeb3{p*w+nPTV3D zIK;69fO9`;wMzUf|bNZb|v{R}0%ypVd-wFn?cSfLcH0I>O*-Keg~j2oX1S70!sV z2B{GC38%f7sOKN3ZI~g-QQu6>gr_^$*jxs%#dW_F75zEV!Rf3!CC>N|e0rD^Q4 zx=Gx$!XcrjJ$`rJ(d5)7Cv;Y0y)8^DUzMOUMrQH#~U|U1F^@!04f|i z5s*G=>g%KOrN=5L|HFWnL|@B>r7Wf6GHwj`=YIVgkH44$q_)~EW_WO^Ez$$0{W#j8 z_Qk<|hSl`JNgP4h&*pDyJfa&jP14jy#7 z{zFu-u4>^uKn@Y;A#I|j3y5j<@VvZ@_tJa#@KdrfKa58$aDt2B_a?8k*l*L=G?AQx zRCJWr^JDw?f;)Y#RtC?~?fxFs0SCv}R*qwEjJzA**{m6U27q!J;IWrDT@+hHH+O!w zX$={D13F}0UC)tK#7*&mG_xOaCv;uEqlW6k)10@XtB1?O|@Fq;~QkLEVIAxR3uFCK9yXEww-Yw8r*BYjb0QR;Z=iWcy! zOqy4}X(p(w=V~YJZIvm4V0A9WD+AFlT6MWvEg>TLsl0{ySd6Ohm_#L6hqEc&CoG(n z1^}-o-FNU1TsqwkO)rpw42{M9(yNcx7T}0Pd=5g3lYF=JYU8hzq_QK#|KwYf+6{jU zs~HzzZ(S#;DD#CPM)oGzma^|FG-kZrE{*JKI4IRv>`2_MHGA z4T)Wi^l0F`Z;aBqy_~EMnM0nZ-9B6KX2!Dcq%R zhPB({>tMT`8QvWUvi>N}qxBS)gt7$rmW?fM^HLaC2nn-EzimI8QmlJ$B5)=qIm(qR ze_FD*49pLE6UWjp1WjPa()ME)yZJ#^D{vq_q8&_v;wIQ_J@{$&B$jm1#_%*PNuQP+ z0-kl}_{u4R9CYvRT{=MMaTwX zB#!Ar7Fjucu`N2zesDugNru8|zhF=G-(c?@j#e*p-sv2q9fxTx^Yu=4O!Oh|UJ>ez zi`qa1yXoy`#@u_yf+FpP6JDX$P3?~BpSFD8X2>6zDkR`jtvccp6TFo$5Et)hMIxof zjcOS)u8b|TsM?Izo7WP`=HAzr7eAH$W>Xj~9%zUXgDH^Tw682ZBlRXV#Q>4I;bZp) zZc@zG2B*GhjkrcW+#!{jtgxTv_U3SJ;I_-3tOgO9ZzIt-W1;gH9m-8-taP6P0R6U$ zwN?w~o{lu>6%(HYm=uJmM`Pi9mb6$AkB{d&FtigLh=>W_x}b5)V14A-pH*6Y8R{KM z$4I6P<_q2>G&1`_F{?F#`N5>ad^pIE=zzluR2GiAW`~ZIL(2JwzlglOCw9PYrVx4~ zMr4AWjlAp^GFK0%YcA@|F}htPWbZjRy{F7NR3q?3(*!IHtbiZ}EQ8%LV#CX-pdJy? z-@* zEKdyo5qOM764B!Zf^rj54CLOw^}18;5OHn6FN4WF2bDDf5~Ha_*4j7Mb_TKz=f%g7 zek+bUm+fu9+watujzj?x+-LOYxqDGeXIUPAxY>fJ8@7(Rp#v(5a>1>HjT<_ZRc;I2 zr(2_ZtRpZfP1vhQ5WweGx?R0)MVAXEQe=bqa@Mm&sDkWzkSW&8;Vm~B`<>pL`t=6j z(5B$kWLm+&MK=8u7GM(!jNfYD1H}D*rl;%1h@4AuOh(>SF<0YOrY;1Q#tLK6%SW8+K<1#&|{Wu%F zrYzig&x)PMJ?nwfPIN|bnqRz`yndVLwZN_&T2j$2!gux;xxd8bkg?PAapq21H+Bc^ zs)JgFSH*(&M)}~QT5eEmitW5NZ{HIiKA*s?ZtlBz@(eRVs-vrPbirw5)DBTZ+l?~^ z=(gIJdu44H&B}0O|7aI~GVSJ%s(+fV>Tcp;3c=@qUm=`J6Ii)j*W$Izo)cDf=50*^ zW!-&|WEOJ4TD;r6Vz);_Aymxy|4d1tDBl_x-hnz8-NuC5x9tSr?x)|;S$n8{BZ zUz7_E{*hk2-UbK`O?9e0^Cax8)KuK3)cX`;mB&FAp!a+u8W_io=11V9Bc|d^?HfLC zI}r?0m!PBGAfNp0u7tG_?hY{QqUe?m-4|)WJn^ zQ$z#x9lIW<+Wg8-w;#SeCs$pvAq$czNw`GgZM(Han+iLXNBx#H7&P34lg~C=OB+xQ z4@qrwo#_>gPL3|~Z0TeMt{==xeYxXiPtcse;&aTTfj3cm9*AIsO+}m6CRv$(?^omk z)&L^1GspBf8JB)aUj!37GW5}k_hB2KObn}I))S4VS`WYI5#c-X5+`2_^*l~!vBU|Y zZU-bTs!GpeA@wK;;4^OQ_T*47(XhrWm2>D;#r)Mr|bR8G-G zPpRe@OWHni7Ydzy9ux|$?yz}ZCV(J>O4+RPifn0Srn`Tp*RL$Bn0M6&AcPvF#nmQJRfM9+eacV>!G16XJQ#B!`ZulYSl0%aqYfCj1|zRNVG>yS$-}WwIA!3sL0N#XIv@X&ui0kyWRV?4SzTV@ zFIhX|f7YJasqx$Qt$TI5naE|i4r~DGwTQ~B{oAfkpsZg+K^-rFfPXN1&!h*lzq>`e z%P#xV^NjY5&M#a}=bSnf+O)W54oM5b8&Q1m2d{GmpeR|4(VV3>&SKuREwF~AMv`m?PdQ$<|5pkL9rp+A>70T}(sm1Am8zo*#@? zrz^Ew5YpZ+dAFXu-~9T7{QGK1H&%?zJ6y=x`s=?0%cE+mv@=0q6=MU9=kK|PDw}=c zFVd{)*i8Up?%qzpUse33gLmnd_lMtK<@>=g`=w7#wBF$@5|{!8+}{CVX9KPtA?MAa zbIlaqFc|=%W+`XuoBvAR>==lroSdJ}we}@Q?Xo};4SdZpTf~m=QcUKD^EViQ<{G*^ zp)}Rx?5mx?D=p_80qXRXkVm!Wv7>5h#SA_z<5A!5RKT}NuhJLPYir#pW_P;)yo2^U zgErz=*cL=$`U-dn8)+twgnD8h^`?N%YZgmM9I^q=!ulFMKYB^WDyjD-#zSV1ZmA?i ztR@S2u=nvmt#}9-1n0GMlvI^-TAKY(9<>Mjqgj(#6O}T4J@kGzlvwAP z>C#*nRNTL)*5ApFLDiZUHpTdVsZ!Qd+FKLmQcs*Q-hi@ z22N8OxAdxkL%0&P55hdfigP`wOW0)aSaG`A!ph7GTUOK!^4spp%)A~bga@=Ir{~~) zgNNXCw8i`mpv0U$v%cI%)5wDosgI}GT6N?NjnB$kPliV;`8q#~;--`j-Fjh9g324G z4AGQ|MbLC;Sui*_x{W?Csw~dpmne^SI6^T~OZd36O+MoA$8|LMQbjA>VopIc9)iyxj3|pvuv0%t&vJuFvUiIv&hx(0AXeELo7j2q#sm`2jPl669Y`1){gZ$1MW7V!5_sVgMv|TH zlLVZggBjDS($lfYobI5FnzF#%cM z)yh_Lj__1jC+;5|-W*Y8&G7mw@9&&SE2W}h3o!e`JM~>Z1urZzv4Uo~wilWjy&VH4 zcncZ=aD%*!e_JYFD=S+*;Zu%xY05f+Ekp=Uq%o@m_lXi@1XXQ4es!QMjMuw}$D&W9 z^wUg^c-u*0d*Rl1YsmDdG3JqWdW9-`$}Fck8xbqGKQ9&r4U=gC1M{UM3)`iVfq3|~*01adZV#huFgSO)=vWp=nT3 zUeq0K7Osl|7Q|gLzksV{Yy6{B91u?&mYez~8;@XPV2e|~qc;%vEQp8|P{85CHF|&b zxgJ-FM9P?SDg_gf7YLMohlic68LcmYD)<-fB}yuD>S}jwD|fu_b?af!s~ylo?I|M( z;Ru+=@2k_DKkm7Lep2=06W7xoT8{t>%-AwTVUF;xC6oihl?R1D#9917<$mZsO^^Tm znvn%g5J_%>r!4v1PV%dbkpGesY+70u0i^*E0smVr;reofn}cKNLfp2slX8%$y!S&$ zndXdGFgp&tNDlt0BJ%2{rJ$gI6LPY*>^#D$OVhSn-Xe0MPwn;ln{H-a zX~VopWcMlj^>&6Mde78i8x4SJFYaLOu+Uq+?QGQpx&a11clGVwHEmx6$KKkBK6sNd zo}Z1iPD1pu2u)6k5?z8Ps;)0L|AvT@tQ_B82i$cDM z&FS*yM&qtPsTN63=+!J&Y5VcQA7LXj!9R95G%&+Af#lEM(Uj3hgTLx{A}-pQBSv$jPQNET+})mD1?=6mYB`+1^u3wZI} zf%hZXi55n2vE-gi2s`$3+Q&*{WFN?Fc_#SPZoh0lV+;ID5oUUjuv^g~AzJ!O2+X5< zz0Y^Rhzm-I7T95yPmL^8FBjmuY%JQ-<(q~RMpB__Q(I;LBfKU>>SJiGU3AF%lC8-01V_Yj@*#*Pk_2?`RUV>-U@ z8*9Gg?~|vN??y>zW}BbxpBS)l9MYAG_OFlN?9uwD`mo~O`0ve~^V3ckI-#tpoJg__ z*+mu8uaZx1hm+*GPdv9ygN1voR5nvl(68=_rid?W@b4m@{aaaEzc-t$U4dR7E;-aT zrXyWqIz05Z@7(SyD^L9@^eO-YC#gQi=R?WbhIhx?^THn%PIq^Q9BKK;t4!X=*5mMM z2KZiPC_*=U*djD-A97B7Cxf!Ihi*ha**d+Ws1VUfdsm|AJk^Vla;MyQzs69pmvzww zSELmwXAN9Bra6&*6LA zwjsRe+1nQh^U1Cj**P@bJUDGBZ2gEjI-fD3N>((?gnJVV?o?l1*m%jJ%x zONx|Z@b_M&=_5#q?9s#B70g!;ujZT#SB}3_pH!)Kzc?(T-jnbwXOuK>T!_SEvK}Wx@aOcVtO2oz2OnqR+8R+==_ri>HxY+! z()=m^XebB@azu9^ZcYLTxcZ-B#bQHEH@Mea(Plwm|L-qpmGj{riwawd6cW??sR`$` zDBfK3|Ij?~d5{qIJQPT{`mJtt9;em+qWJRH4Z8+()6|N;14iRt^2K zt0FQ>D~FH3a^hyqRu-(19J0oQkUnot%D%ciH?vE1AYdqR)e>SA#yOH@9j*Hnca zmDT-@77uNpnP%a{<1=%w&={$)rl~tE6mqA9Xzv?LRlk&I$1y&vkJH}DDrTFwv8 zBtNA9pD-t70Os`tr_(xeVCM~-G#6Jo5h{)t^FNyt0T~Y`q0ZI+3~$XW&Ab^uS8p$F z%?W+ zy?$)rC#kftneA>0nN#mvs7=u2Q+?L zbut*%lot!<4h`(Vd-SJs9`+JmRS)= z6Z$dVUCO)Er|NND<8@+AO7erde4Es;WhW7CD%moe6+%4&RQBEo+@fz$!_k;s*VvSV9OAaA(zQuF)1`Hyn_5pEJUZq+ zP1NS3%W<<2CqI;9+of1sT9Al+*8yj`SJk(Cr3YsafZ4irVb4BUS|4ILrpKSSE%k;*?xub?hW1#XEJGVOa^QKX|U;JwbMp_(N8XBZ0Sx*TnBGcXD)|z3Gd+RQ{LI5+~zNCi_Js z43o43bzUvT^`8VeUM@KlN>lIl2aL)2kbg7#`n~lsPmtvp`sZ|hAj11b8G4(~<4HBH zld&ERxy2S;?h*W0b#t5!=eviCe?|*K?B`$dk>+=V;s>mso(O(EUehz&%CtHEp6JE2 z7}jh2X?5+_qhnFVt6>M^jX~Kc@Wvpg)u}oxTeW<<^Y;u9CTTO|92Y*C0A%oeamI$PWyd5+OfnWZc%px8QY=WQm5;==+WEPp6jP$ zIACH7-SL2)qE16QIN;&jkSz+GlfePHz5Djb^4&uU6otVcI6>ygRCeEJh=1bEP6`CMn@w)TsU5JF?=C zBJX5AIM?7@t~RtE4;y%!ixA58vgo|6F0vy~-|pMa&lg<}gRV}~T{@h0zq{*TOyd>5`K zR-f1awP91eyGVBO9Po6|Ghg&9o1vPNILqq7AfR26>BC?qd`alaj@j<^e!s#Nb%<4u z1G+hgmpJHo!&I4VKa9Z;U!U!gdyaSx|0WEx^nNE(fNFe!CPdBiHg0QBv?lA~5hW&v z+Qtb@LfIGV1|-*~5=tvxO#Gk3INo2$s2|`T_NZRL%We)=2ocbA14*bUwkHJEkPs`+ zwyZ&E^07QptRWobPu3JMyuP}kk62k9&;UCTUmZU`B!jnP)8#Y-95r(Idge`S80a}& zn>1*UBx@zQv@KPRDknG_UHKe+#q>es?RaH+F`_obilGM zQ_?UP9lzcFU3R?dd^RW`w97WjV~`>2teMVf+fb|jms?NcIh*NtmCI|wIi;uhHDKMP z=c+B)O>?(X6z#XyOE(N+HksQ}nH$vX9*U-Wq>Sb6T%J~Lizh!M&*cg&cx=N99Kj>J z_Q#vbqP3*S4lg!CtT>C=IHizN$}2UcA*t4hHw#QfuYzBFoF?EjEIY$H=~lvzB0IZYPT`E-1>9()V9KyAD_vwv~)5 z`#bdHQ47#qneUuYbdnM_oFIDn$cR}Wry|$~t@2X5csQRklDx5dxI@9mHy-qRJk<+S z#;|8BkJt6aaBCp^)jU>EXZwYmH8izPX+EBj>dR%+-nyXIDR0y69dvWFRBJU|eQKxX zIGO@lK+RJA`r3F+dK@i;n2+*!I%Vs$+B&Tw%K2Az2B{en9668&@Afi~Y+Y?N5 z3GZ?)!&YI@%Pgen)>wM7??L^NJyUs(!(Ta;_r+diAE{n28oQStEqk<|W-eU)>Ot$E ze;#`4wNv#5z)_M`p;BE{^ac)R%d!F8PLfRh%@2E_kw({&m=koXalzn{{rv|q<#C<)|LY< zDF?aL!qhY@&Ure^gDZQV~@btvTb*Lq;t?hH2~kC<5`biNE@^(icyA;eMx^P&5i{ zSm=)ScD%@}z*NsydLPQCU&Rlm_!#@%R5!NM$iWk@0pVp+t^G!kI$t?GpY#;m9ZrnN z2h@!25K?0LDT~EtK04SuADy(C)AtAkz&DGLJIqU7libd5xhBtU935TRlx4C9#P!Q5 zHYJO8VVULeyT7BlvN({465{HVi|k14K%B3i`u>^v(MBmI>zR=Zmp0+yIO^|hNHW== zlf=4sKsQz0oXlU~kCw_O(p>tCS(4Pbzb2C`s8ibay00g#yi&eG+!nZJ#S)j9-(&?n z+%yui;P$xOozDrODFIclbsS{DOUa@eb`_Nhs=CFkNK7 z{%{tRx4SKM7;SOp$lV72oJ+{aj#w=onjB!`3s<^u>RK$|1c?s8aAcX&(w&zx6w z8KDq-d*m|ss>77dVNa;8(UY#Y!+(eRlz0hM6}z%-gDmi=MLc9}$ErjZ%?!oz8a2fx zUk&ds=ncMf85CtRKR))F@YXcIksuFHz7NhhR=>@~Z3hiH6 zJU1=QlU&b)kgSrDTFD~dqF7H2UwfbXyx|1lg5l{Y1zP+c$A$ItV_#UYs~Ga6y?TI> zofkPbPmM{)d(0gDhTm<9GcRWk4>SqVZ?oqK>0~I%)(bD(T_Fzo+%9q!F`6n0&Ch(i z_5)NR0)(22gs;LXe%`Y3DZJX)rn7V~Ys=Zjk0GP@^ZXaZu|hbRc$L9uY`MvpZm1c zI46?hIhpiWkSzBy2(n$|fN_U#u@i$8y4L6tTD1cFQ|^@TAAE=3+~B|);!I4p*lpO# zk1;LR@_RdJ#aB!>G~|B#4(=?{Dmfh%X>FeGBPBwhCXQ@HR} zhWZdSplZ4CSkTh^-t3g2f8#NNEFAufjs<4}!_C4k&u9KG=$#5XuyDz1hu?Jk81ZS7 zXp@yNYEku3*}02y|0RzgSA0sr{lDdaRd!r8tmv}^6YNqMjL(|K%U zTG%MEya;nmFAJEjjA!}6Cp*?jVkt$MNb{u3nx@2si})Y%=O`Svj&T?DI1E8R!{lQpR35AWpDP3;G65zy*V zdGks+Sw$&>6vEi}iD=fk9zRS>=PD^pY?bO$W=farMj(Y=Uaae4Fuu7Xde=07-uNv~ z+;Qy(hv&A7-~2azQi-yqX4ida_-TVWnLdB1lA&`Q=Vkh5!)6WEGZbV~!{x)?xED~5 zlfttfty3Ot@xGQ_@*}4rv9)C6;6wJMnq1kaH|n2^x$BynuP@V!hdjzC>sqTzu4y~p znBqT?Y-=c$*JVN8-T)KA5@pyVi)ZE6ldXL&Pm9Hb+`O-PBYF_ww8c<1(7W2_N_eH; zb^B_y_g*QLFt@Ke(mrg1qd2zpUgURk>Q?7DzJ7H0acvn*Y_wkG{4h*X5P$COPs`OC zbXd5m_2^G?J{Zc1r=8?itt zjPcPrE%S&`mnm7Cd2Z?rCA8J$g)z1>Oe(}yb0A>^Wz?31^jkBgNa12Vx~21FjlOkh zLtU^uGt>Fc9atJzjFqILnU3(&H3i^X|8pTpjKpRHp)E;UypijJFlW)9sN=o(nKtrp z#g!iHQ6CY#vDojMtkSg^(hK}u8qFivaaU!QT1q~#jmsY~2cgs8)9%`?8Fv-V{lgP7 zzfXc1`sH~l?LWE+C!Zf`?U+uw7@ar0-&AFLINh0hmkt&&@y4#jva(w=w%aqzIX5lS z^FcV-tlS3I@*HXFktHXoXm$v2YfdtLgG%G}B?TXqy}T`7mV~Pg-HlabJ?*(Ux$AV@ z8-BkMc?8o-o+Uf}^&qIzkDM*ucksJ(<^e2mm&DCk3v{@Ci3}GW@HByfXPH)MFISyp zC;!>>>CW9$$k@Mbt*-XIX;lb$504PrI%Iqhyn^D2g& zUud4<3&VFnZlSe#NwP)ibR)Mnnpx=@_l|A84#z$Caw26GHdZvBBN;Bj%CoZKUtr2| z+Ln=f1LSs2NTtKSgk12UgBk|VZ|40pJ+5G2rkp(^`bgyt1sa5-&s_Zv7mZLM4t4Lo zr+?27a(;S221`%5Q@N_W3znr^dPwc*C1$8=Ba~ats(NjO7Q{Fx$}A{ka0p3xR{vgp zvjuYE5P@mk@g6`S(er&<*IkxSDG9#_=qwXOM1SeZI>pAED+E8qozq`DVOlIjTt|X+Z4^UFg+LuQ+lrRo##iLtvKSyJ=!Q>a?eNL%{^8K;B4z3IQ%g=SBc4CU-gC}J z50{VFJ`?`Qd$F?-e7~l+MIFmek`tgzG8iQ!5oZ14RhjJ^$jc~? z{o=GOa`v0~6$qs7-h-WL3H(Lu^Thvq5PA`@u_cuD>T|5!OuWZ@KV8unTAJ{JSrDT-T6WOlK1PUZ zh^ajWuHm=f>FIP#)uy5BGTAR9(Yh)af~GWkkIyz&Pd}-S!%HgiUOOC>!pDIxgw9eIAQW6aRRTn zqEW+-R>5C+GR9bcL}qvm|LsmzFb&nS2aHqtc{lUtP5rc_9ijCQkZ6)1|Z@FPG(%#cfL5Az~HtKGDeb(>~bWft_xB zSGM;N@JA8fi#j@f1tg6Uj&c$a{Dru4RN&LAMp2q)JqN?H07(W_C?q>I-HF9W^Yj;Y@cr zaHckAqwZ!S{BQLTzF-PV?&i=g3tYMmk$cNi_T){Ldr0}QDU0mkqlCV;4y*bFc0cN2 zY_q%7eBZ-{{$DMy+gy9!GBC~!pYHcPu;fyh)AQl!{_w@uO`Qj(o>rcUxBRe-SOg!r zdG9|Mniruo<27G+_QWPG)J%mxo7c=QyGp!HPJJnO`C8}jGmoX!>FRzTOBAv9pOZFU zi{n%5G3>y*vtt9M#oFcJZ zEwC*$))Z+S((IY%TG-fjIkh_&&bofv%G#rm+LLa_wm-h}s;uN%r=5n6^zSGjMj5GY zl@hhZj;Ob79BV$E3@>Brs6%Il(V1wse!S2i|5S0K)HiJ<5LuXUP!pDW>V(mSQbIZ3 zULLoBX=*LW2l*sfIjzBrPP?JWE{%TMnI2qiWNSoR+YZft@_l`_YftuM*$;Y}mXi9AL@a+!maN^#Mv_90neeb@%6|A<|0!TObw)EB4*6dyRYdn|_m;;5 zmr7MV^M_Ns52{DFboEP>cJp4t`-IVl;motZia)z+L6188{;vr?oG4cJ+%7EaNb85>dF3N+*;{t(H+{7>3(UMitwp`RwmP2H&OdmhIE4ib`;E;s$T5;2!p0l$e z13D(`G&s9M`5nha2i;;t;P6A6pxM5})9E)HR{xy+cwUc$+|y2p51#o4`Co-gt`~YG z*|Ak1hJ8opBh7^!OuF8@9DMp3&M~e#{{QJwpM57FRc$u7;(nn}#T-e>P&%@2g*oXiC literal 0 HcmV?d00001 diff --git a/config/noobs/marketing/slides_vga/D.png b/config/noobs/marketing/slides_vga/D.png new file mode 100644 index 0000000000000000000000000000000000000000..50110992c15c228b9a62b3c3eb73f161002ab82e GIT binary patch literal 15769 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 N=ZdcsO65#~{|DdY1u6gl literal 0 HcmV?d00001 diff --git a/config/noobs/marketing/slides_vga/noobs_vga.psd b/config/noobs/marketing/slides_vga/noobs_vga.psd new file mode 100644 index 0000000000000000000000000000000000000000..22820db05a1d8199538ab1fd4dfd836cf2c25b63 GIT binary patch literal 303004 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

9c0M%n!S{WAeRU|QOQH9DW23jaH7M3o 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 literal 0 HcmV?d00001 diff --git a/config/noobs/os.json b/config/noobs/os.json new file mode 100644 index 000000000..2fb08c7f6 --- /dev/null +++ b/config/noobs/os.json @@ -0,0 +1,11 @@ +{ + "name": "@DISTRONAME@_@PROJECT@", + "version": "@LIBREELEC_VERSION@", + "release_date": "@RELEASE_DATE@", + "kernel": "@KERNEL_VERSION@", + "description": "@DESCRIPTION@", + "username": "root", + "password": "@ROOT_PASSWORD@", + "supported_hex_revisions": "@NOOBS_HEX@", + "supported_models": [@NOOBS_SUPPORTED_MODELS@] +} diff --git a/config/noobs/partition_setup.sh b/config/noobs/partition_setup.sh new file mode 100755 index 000000000..50577f5e6 --- /dev/null +++ b/config/noobs/partition_setup.sh @@ -0,0 +1,53 @@ +#!/bin/sh -x + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +MOUNTPOINT="/tmp/LibreELEC-System" + +md5sumCheck() { + ( cd $MOUNTPOINT + echo "checking MD5: $1" + md5sum -c $1.md5 + if [ "$?" = "1" ]; then + echo "#######################################################" + echo "# #" + echo "# LibreELEC failed md5 check - Installation will quit #" + echo "# #" + echo "# Your original download was probably corrupt. #" + echo "# Please visit libreelec.tv and get another copy #" + echo "# #" + echo "#######################################################" + exit 1 + fi + rm -rf $1.md5 + ) +} + +if [ -z $part1 -o -z $part2 -o -z $id1 -o -z $id2 ]; then + echo "error: part1, part2, id1 or id2 not specified" + echo "actual values:" + echo "part1:" $part1 + echo "part2:" $part2 + echo "id1 :" $id1 + echo "id2 :" $id2 + exit 1 +fi + +# create mountpoint + mkdir -p $MOUNTPOINT + +# mount needed partition + mount $part1 $MOUNTPOINT + +# check md5sum + md5sumCheck kernel.img + md5sumCheck SYSTEM + +# create bootloader configuration + echo "creating bootloader configuration..." + echo "boot=$id1 disk=$id2 quiet" > $MOUNTPOINT/cmdline.txt + +# cleanup mountpoint + umount $MOUNTPOINT + rmdir $MOUNTPOINT diff --git a/config/noobs/partitions.json b/config/noobs/partitions.json new file mode 100644 index 000000000..323bc6048 --- /dev/null +++ b/config/noobs/partitions.json @@ -0,0 +1,20 @@ +{ + "partitions": [ + { + "label": "System", + "filesystem_type": "FAT", + "partition_size_nominal": @SYSTEM_SIZE@, + "want_maximised": false, + "uncompressed_tarball_size": 1024, + "mkfs_options": "" + }, + { + "label": "Storage", + "filesystem_type": "ext4", + "partition_size_nominal": 512, + "want_maximised": true, + "uncompressed_tarball_size": 10, + "mkfs_options": "" + } + ] +} diff --git a/config/optimize b/config/optimize new file mode 100644 index 000000000..862a83a5c --- /dev/null +++ b/config/optimize @@ -0,0 +1,95 @@ +GCC_OPTIM="-Ofast" +# Linker hash-style is set to gnu via gcc default +LD_OPTIM="-Wl,--as-needed" + +if [ "${BUILD_WITH_DEBUG}" = "yes" ]; then + TARGET_CFLAGS="$TARGET_CFLAGS -ggdb" + TARGET_CXXFLAGS="$TARGET_CXXFLAGS -ggdb" + TARGET_LDFLAGS="$TARGET_LDFLAGS -ggdb" +else + TARGET_CFLAGS="$TARGET_CFLAGS -fomit-frame-pointer" + TARGET_CXXFLAGS="$TARGET_CXXFLAGS -fomit-frame-pointer" + TARGET_LDFLAGS="$TARGET_LDFLAGS" +fi + +NINJA_OPTS="" + +TARGET_CPPFLAGS="" +TARGET_CFLAGS="$TARGET_CFLAGS -Wall -pipe $GCC_OPTIM $PROJECT_CFLAGS" +TARGET_CXXFLAGS="$TARGET_CFLAGS" +TARGET_LDFLAGS="$TARGET_LDFLAGS $LD_OPTIM" +TARGET_LIBDIR="$SYSROOT_PREFIX/lib $SYSROOT_PREFIX/usr/lib" +TARGET_INCDIR="$SYSROOT_PREFIX/include $SYSROOT_PREFIX/usr/include" + +HOST_CPPFLAGS="" +HOST_CFLAGS="-march=native -O3 -Wall -pipe -I$TOOLCHAIN/include" +HOST_CXXFLAGS="$HOST_CFLAGS" +HOST_LDFLAGS="-Wl,-rpath,$TOOLCHAIN/lib -L$TOOLCHAIN/lib" +HOST_INCDIR="$TOOLCHAIN/include /usr/include" + +# work around Ubuntu default C*FLAGS +# see https://wiki.ubuntu.com/ToolChain/CompilerFlags#A-Wformat_-Wformat-security +HOST_CFLAGS="$HOST_CFLAGS -Wno-format-security" +HOST_CXXFLAGS="$HOST_CXXFLAGS -Wno-format-security" + +# lto flags +FLAGS_OPTIM_LTO_NO_PARALLEL="-flto" +FLAGS_OPTIM_LTO_PARALLEL="-flto=${CONCURRENCY_MAKE_LEVEL}" +FLAGS_OPTIM_LTO_NO_FAT="-fno-fat-lto-objects" +FLAGS_OPTIM_LTO_FAT="-ffat-lto-objects" +FLAGS_OPTIM_LTO_OFF="-fno-lto" +LDFLAGS_OPTIM_LTO_COMMON="-fuse-linker-plugin" + +# gold flags +LDFLAGS_OPTIM_GOLD="-fuse-ld=gold" + +# position-independent code +CFLAGS_OPTIM_PIC="-fPIC -DPIC" +CXXFLAGS_OPTIM_PIC="-fPIC -DPIC" +LDFLAGS_OPTIM_PIC="-fPIC" + +# hardening support +# TODO: basiclly copied from debian 9, should adjust for LE +CFLAGS_OPTIM_HARDENING="-fstack-protector-strong -Wformat -Werror=format-security -fPIE" +CXXFLAGS_OPTIM_HARDENING="-fstack-protector-strong -Wformat -Werror=format-security -fPIE" +CPPFLAGS_OPTIM_HARDENING="-D_FORTIFY_SOURCE=2" +LDFLAGS_OPTIM_HARDENING="-Wl,-z,relro -Wl,-z,now" + +# add distro specific library dirs +if [ -z "$HOST_LIBDIR" ]; then + HOST_LIBDIR="$TOOLCHAIN/lib" + + # ubuntu/debian specific "multiarch support" + export MACHINE_HARDWARE_NAME="$(uname -m)" + export MACHINE_HARDWARE_PLATFORM="$(uname -i)" + FAMILY_TRIPLET=${HOST_NAME/${MACHINE_HARDWARE_NAME}/${MACHINE_HARDWARE_PLATFORM}} + if [ -d /lib/$FAMILY_TRIPLET ]; then + HOST_LIBDIR="$HOST_LIBDIR /lib/$FAMILY_TRIPLET" + fi + if [ -d /usr/lib/$FAMILY_TRIPLET ]; then + HOST_LIBDIR="$HOST_LIBDIR /usr/lib/$FAMILY_TRIPLET" + fi + + # default multiarch support + case "${MACHINE_HARDWARE_NAME}" in + i*86) + if [ -d /lib32 ]; then + HOST_LIBDIR="$HOST_LIBDIR /lib32" + fi + if [ -d /usr/lib32 ]; then + HOST_LIBDIR="$HOST_LIBDIR /usr/lib32" + fi + ;; + x86_64) + if [ -d /lib64 ]; then + HOST_LIBDIR="$HOST_LIBDIR /lib64" + fi + if [ -d /usr/lib64 ]; then + HOST_LIBDIR="$HOST_LIBDIR /usr/lib64" + fi + ;; + esac + + # default dirs + export HOST_LIBDIR="$HOST_LIBDIR /lib /usr/lib" +fi diff --git a/config/options b/config/options new file mode 100644 index 000000000..d24345a11 --- /dev/null +++ b/config/options @@ -0,0 +1,112 @@ +# Do not build as root. Ever. +if [[ "${EUID}" -eq 0 ]]; then + echo "Building as the root user is NOT supported. Use a regular user account for the build." 1>&2 + exit 1 +fi + +# Spaces in paths are verboten +if [[ ${PWD} =~ [[:space:]] ]]; then + echo "Current PWD: \"${PWD}\"" 1>&2 + echo 1>&2 + echo "Building in a folder that includes spaces is NOT supported. Use a folder without spaces." 1>&2 + exit 1 +fi + +# set default language for buildsystem +export LC_ALL=C + +# set default independent variables +ROOT="${PWD}" +DISTRO_DIR="${ROOT}/distributions" +PROJECT_DIR="${ROOT}/projects" + +# determines DISTRO, if not forced by user +DISTRO="${DISTRO:-JELOS}" + +# determines PROJECT, if not forced by user +PROJECT="${PROJECT:-Rockchip}" + +# determines TARGET_ARCH, if not forced by user +ARCH="${ARCH:-arm}" +TARGET_ARCH="${ARCH}" + +# include helper functions +. config/functions + +# read DISTRO options if available +if [ -f "${DISTRO_DIR}/${DISTRO}/options" ]; then + . "${DISTRO_DIR}/${DISTRO}/options" +fi + +# read PROJECT options if available +if [ -f "${PROJECT_DIR}/${PROJECT}/options" ]; then + . "${PROJECT_DIR}/${PROJECT}/options" +fi + +# read DEVICE options if available +if [ -f "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" ]; then + . "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options" +fi + +# projects can set KERNEL_NAME (kernel.img) +KERNEL_NAME="${KERNEL_NAME:-KERNEL}" + +LINUX_DEPENDS="${PROJECT_DIR}/${PROJECT}/linux ${PROJECT_DIR}/${PROJECT}/patches/linux ${PROJECT_DIR}/${PROJECT}/packages/linux ${ROOT}/packages/linux" +[ -n "${DEVICE}" ] && LINUX_DEPENDS+=" ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/linux ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/patches/linux ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/packages/linux" +[ "${TARGET_ARCH}" = "x86_64" ] && LINUX_DEPENDS+=" ${ROOT}/packages/linux-firmware/intel-ucode ${ROOT}/packages/linux-firmware/kernel-firmware" + +# Need to point to your actual cc +# If you have ccache installed, take care that LOCAL_CC does not point to it +[ -z "${LOCAL_CC}" ] && export LOCAL_CC="$(command -v gcc)" + +if [ -z "${LOCAL_CC}" ]; then + die "***** Please install gcc *****" "127" +fi + +# Need to point to your actual g++ +# If you have ccache installed, take care that LOCAL_CXX does not point to it +[ -z "${LOCAL_CXX}" ] && export LOCAL_CXX="$(command -v g++)" + +# verbose compilation mode (yes/no) +VERBOSE="${VERBOSE:-yes}" + +# Concurrency make level (-j option) +# Try values between 1 and number of processor cores present. +# default: use all cores +[ -z "${CONCURRENCY_MAKE_LEVEL}" ] && export CONCURRENCY_MAKE_LEVEL=$(nproc) + +# cache size for ccache +# Set the maximum size of the files stored in the cache. You can specify a +# value in gigabytes, megabytes or kilobytes by appending a G, M or K to the +# value. The default is gigabytes. The actual value stored is rounded down to +# the nearest multiple of 16 kilobytes. Keep in mind this per project .ccache +# directory. +CCACHE_CACHE_SIZE="20G" + +# read local persistent options from $ROOT if available +if [ -f "${ROOT}/.coreelec/options" ]; then + . "${ROOT}/.coreelec/options" +fi + +# read global persistent options from $HOME if available +if [ -f "${HOME}/.coreelec/options" ]; then + . "${HOME}/.coreelec/options" +fi + +# overwrite OEM_SUPPORT via commandline +if [ "${OEM}" = "yes" -o "${OEM}" = "no" ]; then + OEM_SUPPORT="${OEM}" +fi + +check_config + +. config/graphic +. config/path $1 + +## package processing + +# If the package caches are unset, then populate them +init_package_cache + +# set package metadata +source_package "${1}" diff --git a/config/path b/config/path new file mode 100644 index 000000000..ec5f4a5d2 --- /dev/null +++ b/config/path @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +set -e + +# setup initial directorys (relative to root) + CONFIG=config + SCRIPTS=scripts + PACKAGES=packages + SOURCES=${SOURCES_DIR:-$ROOT/sources} + BUILD_ROOT=${BUILD_DIR:-$ROOT} + BUILD_BASE=build + TARGET_IMG=${TARGET_DIR:-$ROOT/target} + ADDONS=addons + +# include ARCH specific options + if [ -f config/arch.$TARGET_ARCH ]; then + . config/arch.$TARGET_ARCH + fi + +[ -z "${HOST_NAME}" ] && export HOST_NAME="$($LOCAL_CC -dumpmachine)" +TARGET_NAME=$TARGET_GCC_ARCH-libreelec-linux-gnu${TARGET_ABI} + +BUILD=${BUILD_ROOT}/${BUILD_BASE}.${DISTRONAME}-${DEVICE:-$PROJECT}.${TARGET_ARCH} +if [ "${LIBREELEC_VERSION}" = "devel" ] ; then + BUILD=${BUILD_ROOT}/${BUILD_BASE}.${DISTRONAME}-${DEVICE:-$PROJECT}.${TARGET_ARCH}-${OS_VERSION}-${LIBREELEC_VERSION} +fi + +if [ -n "$BUILD_SUFFIX" ]; then + BUILD=$BUILD-$BUILD_SUFFIX +fi + +THREAD_CONTROL=${BUILD}/.threads + +TARGET_ADDONS="$TARGET_IMG/$ADDONS/$ADDON_PATH" +ADDON_BUILD="$BUILD/$ADDONS/$1" +STAMPS=$BUILD/.stamps +STAMPS_INSTALL=$BUILD/image/.stamps +DOCS=DOCS +TOOLCHAIN=$BUILD/toolchain +SYSROOT_PREFIX=$TOOLCHAIN/$TARGET_NAME/sysroot +LIB_PREFIX=$SYSROOT_PREFIX/usr +TARGET_PREFIX=$TOOLCHAIN/bin/$TARGET_NAME- + +FAKEROOT_SCRIPT=$BUILD/.fakeroot + +if [ -z "$INSTALL" ]; then + INSTALL=$BUILD/image/system +fi + +. config/sources + +MAKE="$TOOLCHAIN/bin/make" + +XORG_PATH_DRI=/usr/lib/dri +XORG_PATH_XKB=/usr/share/X11/xkb +XORG_PATH_XKB_OUTPUT=/var/lib/xkb +XORG_PATH_RGB=/usr/lib/X11/rgb +XORG_PATH_MODULES=/usr/lib/xorg/modules +XORG_PATH_DRIVERS=/usr/lib/xorg/modules/drivers + +. config/optimize + +# use ARM toolchain on 64/32 split builds +if [ -z "$KERNEL_TOOLCHAIN" -a "$TARGET_KERNEL_ARCH" = "arm64" -a "$TARGET_ARCH" = "arm" ]; then + if [ "${MACHINE_HARDWARE_NAME}" = "x86_64" ]; then + KERNEL_TOOLCHAIN="aarch64-none-linux-gnu" + elif [ "${MACHINE_HARDWARE_NAME}" = "aarch64" ]; then + KERNEL_TOOLCHAIN="aarch64-none-elf" + else + die "No known toolchain available for ${MACHINE_HARDWARE_NAME}." + fi +fi +if [ -n "$KERNEL_TOOLCHAIN" ]; then + TARGET_KERNEL_PREFIX=$TOOLCHAIN/lib/gcc-arm-$KERNEL_TOOLCHAIN/bin/$KERNEL_TOOLCHAIN- +else + TARGET_KERNEL_PREFIX=$TARGET_PREFIX +fi + +if [ -z "$CCACHE_DIR" ]; then + export CCACHE_DIR=${BUILD_ROOT}/.ccache-${TARGET_ARCH} +fi + +if [[ -z "$PATH" || ( "$PATH" != "$TOOLCHAIN/bin:$TOOLCHAIN/sbin" && "$PATH" = "${PATH#$TOOLCHAIN/bin:$TOOLCHAIN/sbin:}" ) ]]; then + export PATH="$TOOLCHAIN/bin:$TOOLCHAIN/sbin${PATH:+":$PATH"}" +fi + +# redirect formatted output +export BUILD_INDENT_SIZE=4 +SILENT_OUT=3 +VERBOSE_OUT=4 + +if [ "$VERBOSE" = yes ]; then + exec 3>&1 + exec 4>&1 +else + exec 3>&2 + exec 4>/dev/null +fi + +unset LD_LIBRARY_PATH + +# multilib? nah +unset CONFIG_SITE + +# Ignore custom python installs... +unset PYTHONHOME PYTHONPATH PYTHONSTARTUP +export PYTHONNOUSERSITE=yes #disable PEP 370 diff --git a/config/show_config b/config/show_config new file mode 100644 index 000000000..f7bc75036 --- /dev/null +++ b/config/show_config @@ -0,0 +1,167 @@ +show_config() { + # load graphic configuration + get_graphicdrivers + + dashes="===========================" + config_message="$config_message\n $dashes$dashes$dashes" + config_message="$config_message\n Configuration for $DISTRONAME ($([ "$OFFICIAL" = "yes" ] && echo "official" || echo "community"))" + config_message="$config_message\n $dashes$dashes$dashes" + + # Build options + + config_message="$config_message\n\n Buildoptions:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - CPU (ARCH):\t\t\t\t $TARGET_CPU ($TARGET_ARCH)" + config_message="$config_message\n - FLOAT:\t\t\t\t $TARGET_FLOAT" + config_message="$config_message\n - FPU:\t\t\t\t\t $TARGET_FPU" + config_message="$config_message\n - CPU features:\t\t\t $TARGET_FEATURES" + config_message="$config_message\n - LTO (Link Time Optimization) support: $LTO_SUPPORT" + config_message="$config_message\n - GOLD (Google Linker) Support:\t $GOLD_SUPPORT" + config_message="$config_message\n - LLVM support:\t\t\t $LLVM_SUPPORT" + config_message="$config_message\n - DEBUG:\t\t\t\t ${DEBUG:-no}" + + # config_message="$config_message\n - CFLAGS:\t $TARGET_CFLAGS" + # config_message="$config_message\n - LDFLAGS:\t $TARGET_LDFLAGS" + + # Graphic configuration + + config_message="$config_message\n\n Graphic configuration:" + config_message="$config_message\n $dashes$dashes" + + if [ "$DISPLAYSERVER" = "x11" ] ; then + config_message="$config_message\n - Xorg Graphic Drivers:\t\t $GRAPHIC_DRIVERS" + config_message="$config_message\n - XORG Composite support:\t\t $COMPOSITE_SUPPORT" + config_message="$config_message\n - WindowManager:\t\t\t $WINDOWMANAGER" + fi + config_message="$config_message\n - OpenGL (GLX) support (provider):\t $OPENGL_SUPPORT ($OPENGL)" + config_message="$config_message\n - OpenGLES support (provider):\t\t $OPENGLES_SUPPORT ($OPENGLES)" + config_message="$config_message\n - uvesafb support:\t\t\t $UVESAFB_SUPPORT" + + # Hardware decoder support + + config_message="$config_message\n\n Hardware decoder configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - Kodi Player driver:\t\t\t $KODIPLAYER_DRIVER" + config_message="$config_message\n - VAAPI Support:\t\t\t $VAAPI_SUPPORT" + config_message="$config_message\n - VDPAU Support:\t\t\t $VDPAU_SUPPORT" + + # Input device configuration + + config_message="$config_message\n\n Input device configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - Remote support:\t\t\t $REMOTE_SUPPORT" + config_message="$config_message\n - CEC Adapter support:\t\t\t $CEC_SUPPORT" + config_message="$config_message\n - CEC Framework support:\t\t $CEC_FRAMEWORK_SUPPORT" + config_message="$config_message\n - Kodi Joystick support:\t\t $JOYSTICK_SUPPORT" + + # Misc. hardware configuration + + config_message="$config_message\n\n Misc. hardware configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - ALSA support:\t\t\t $ALSA_SUPPORT" + config_message="$config_message\n - Pulseaudio support:\t\t\t $PULSEAUDIO_SUPPORT" + config_message="$config_message\n - Bluetooth support:\t\t\t $BLUETOOTH_SUPPORT" + + for config_driver in $ADDITIONAL_DRIVERS; do + config_message="$config_message\n - Include driver:\t\t\t $config_driver" + done + + if [ "$DRIVER_ADDONS_SUPPORT" = "yes" ]; then + for config_driver_addons in $DRIVER_ADDONS; do + config_message="$config_message\n - Include driver add-ons:\t\t $config_driver_addons" + done + fi + + for config_firmware in $FIRMWARE; do + config_message="$config_message\n - Include firmware:\t\t\t $config_firmware" + done + + for config_modules in $INITRAMFS_MODULES; do + config_message="$config_message\n - Initramfs modules:\t\t\t $config_modules" + done + + # Network service configuration + + config_message="$config_message\n\n Network service configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - Avahi (Zeroconf) support:\t\t $AVAHI_DAEMON" + config_message="$config_message\n - NFS mounting support:\t\t $NFS_SUPPORT" + config_message="$config_message\n - SAMBA mounting support:\t\t $SAMBA_SUPPORT" + config_message="$config_message\n - SAMBA server support:\t\t $SAMBA_SERVER" + config_message="$config_message\n - SFTP server support:\t\t\t $SFTP_SERVER" + config_message="$config_message\n - OpenVPN support:\t\t\t $OPENVPN_SUPPORT" + config_message="$config_message\n - WireGuard support:\t\t\t $WIREGUARD_SUPPORT" + + # OS configuration + + config_message="$config_message\n\n OS configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - OEM Support:\t\t\t\t $OEM_SUPPORT" + config_message="$config_message\n - Default ROOT Password:\t\t $ROOT_PASSWORD" + config_message="$config_message\n - Bootloader:\t\t\t\t $BOOTLOADER" + config_message="$config_message\n - UDevil support:\t\t\t $UDEVIL" + config_message="$config_message\n - Installer support:\t\t\t $INSTALLER_SUPPORT" + for config_package in $ADDITIONAL_PACKAGES; do + config_message="$config_message\n - Include package:\t\t\t $config_package" + done + + # Misc. Filesystems + + config_message="$config_message\n\n Misc. Filesystems:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - Swap Support:\t\t\t $SWAP_SUPPORT" + if [ "$SWAP_SUPPORT" = "yes" ]; then + config_message="$config_message\n - Swapfile default size:\t\t $SWAPFILESIZE" + fi + config_message="$config_message\n - exFAT Support (via Fuse):\t\t $EXFAT" + config_message="$config_message\n - NTFS Support (via Fuse):\t\t $NTFS3G" + config_message="$config_message\n - Install HFS Tools:\t\t\t $HFSTOOLS" + + # Kodi configuration + if [ ! "$MEDIACENTER" = "no" ]; then + config_message="$config_message\n\n Kodi configuration:" + config_message="$config_message\n $dashes$dashes" + + config_message="$config_message\n - Kodi version:\t\t\t $MEDIACENTER" + config_message="$config_message\n - Kodi Blu-Ray support:\t\t $KODI_BLURAY_SUPPORT" + if [ "$KODI_BLURAY_SUPPORT" = "yes" ] ; then + config_message="$config_message\n - Bluray BD+ support:\t\t $BLURAY_BDPLUS_SUPPORT" + config_message="$config_message\n - Bluray AACS support:\t\t $BLURAY_AACS_SUPPORT" + fi + config_message="$config_message\n - Kodi DVDCSS support:\t\t\t $KODI_DVDCSS_SUPPORT" + config_message="$config_message\n - Kodi Airplay support:\t\t $KODI_AIRPLAY_SUPPORT" + config_message="$config_message\n - Kodi Airtunes support:\t\t $KODI_AIRTUNES_SUPPORT" + config_message="$config_message\n - Kodi NFS support:\t\t\t $KODI_NFS_SUPPORT" + config_message="$config_message\n - Kodi MySQL support:\t\t\t $KODI_MYSQL_SUPPORT" + config_message="$config_message\n - Kodi Optical Drive support:\t\t $KODI_OPTICAL_SUPPORT" + config_message="$config_message\n - Kodi SAMBA client support:\t\t $KODI_SAMBA_SUPPORT" + config_message="$config_message\n - Kodi UPNP support:\t\t\t $KODI_UPNP_SUPPORT" + config_message="$config_message\n - Kodi Webserver support:\t\t $KODI_WEBSERVER_SUPPORT" + + for config_skin in $SKINS; do + config_message="$config_message\n - Include Skin:\t\t\t $config_skin" + done + + config_message="$config_message\n - Default Skin:\t\t\t $SKIN_DEFAULT" + config_message="$config_message\n - Include extra fonts:\t\t\t $KODI_EXTRA_FONTS" + fi + + if [ "$(type -t show_distro_config)" = "function" ]; then + show_distro_config + fi + + config_message="$config_message\n" + config_message="$config_message\n $dashes$dashes$dashes" + config_message="$config_message\n End Configuration for $DISTRONAME" + config_message="$config_message\n $dashes$dashes$dashes" + config_message="$config_message\n\n\n" + + echo -e "$config_message" +} diff --git a/config/sources b/config/sources new file mode 100644 index 000000000..fe19a603f --- /dev/null +++ b/config/sources @@ -0,0 +1,2 @@ +# Sourceforge download site + SOURCEFORGE_SRC="https://prdownloads.sourceforge.net" diff --git a/distributions/JELOS/options b/distributions/JELOS/options new file mode 100644 index 000000000..e6a67840e --- /dev/null +++ b/distributions/JELOS/options @@ -0,0 +1,237 @@ +# LTO (Link Time Optimization) support + LTO_SUPPORT="yes" + +# GOLD (Google Linker) support + GOLD_SUPPORT="yes" + +# HARDENING (security relevant linker and compiler flags) support + HARDENING_SUPPORT="no" + +# Name of the Distro to build (full name, without special characters) + DISTRONAME="JELOS" + +# short project description + DESCRIPTION="An Open Source firmware." + +# Distribution Home URL + HOME_URL="https://www.jelos.org" + +# Documentation URL + WIKI_URL="https://www.jelos.org" + +# Where to report bugs + BUG_REPORT_URL="https://www.jelos.org" + +# Root password to integrate in the target system + ROOT_PASSWORD="jelos" + +# Install glibc locales to the build (yes / no) + GLIBC_LOCALES="yes" + +# Mediacenter to use (kodi / no) + MEDIACENTER="no" + +# Skins to install (Estuary) +# Space separated list is supported, +# e.g. SKINS="Estuary" + SKINS="Estuary" + +# Default Skin (Estuary) + SKIN_DEFAULT="Estuary" + +# Select whether to use default (upstream xbmc/xbmc) repo, or specific vendor repo + KODI_VENDOR="default" + +# install extra subtitle Fonts for KODI (yes / no) + KODI_EXTRA_FONTS="yes" + +# build and install PulseAudio support (yes / no) + PULSEAUDIO_SUPPORT="yes" + +# build and install espeak support (yes / no) + ESPEAK_SUPPORT="no" + +# build and install with BluRay support (yes / no) + KODI_BLURAY_SUPPORT="no" + +# build and install with BD+ support +# (BD+ decryption support in KODI) (yes / no) + BLURAY_BDPLUS_SUPPORT="no" + +# build and install with AACS support +# (BD decryption support in KODI) (yes / no) + BLURAY_AACS_SUPPORT="no" + +# build and install with DVDCSS support +# (DVD decryption support in KODI) (yes / no) + KODI_DVDCSS_SUPPORT="no" + +# additional drivers to install: +# for a list of additional drivers see packages/linux-drivers +# Space separated list is supported, +# e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2" +# ADDITIONAL_DRIVERS="RTL8192CU RTL8192DU RTL8192EU RTL8188EU RTL8812AU RTL8821CU" + +# build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="yes" + +# build and install with KODI webfrontend (yes / no) + KODI_WEBSERVER_SUPPORT="no" + +# build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="yes" + +# build with UPnP support (yes / no) + KODI_UPNP_SUPPORT="yes" + +# build with MySQL support (mysql / mariadb / none) + KODI_MYSQL_SUPPORT="none" + +# build xbmc with optical drive support (yes / no) + KODI_OPTICAL_SUPPORT="no" + +# build with AirPlay support (stream videos from iDevices to KODI) (yes / no) + KODI_AIRPLAY_SUPPORT="no" + +# build with AirTunes support (stream music from iDevices to KODI) (yes / no) + KODI_AIRTUNES_SUPPORT="no" + +# build with libnfs support (mounting nfs shares with KODI) (yes / no) + KODI_NFS_SUPPORT="no" + +# build with Samba Client support (mounting SAMBA shares with KODI) (yes / no) + KODI_SAMBA_SUPPORT="no" + +# build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="no" + +# build with Samba Client support (mounting samba shares via the OS) (yes / no) + SAMBA_SUPPORT="no" + +# build and install Samba Server (yes / no) + SAMBA_SERVER="no" + +# build and install SFTP Server (yes / no) + SFTP_SERVER="yes" + +# build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + +# build and install WireGuard support (yes / no) + WIREGUARD_SUPPORT="no" + +# build and install diskmounter support (udevil) +# this service provide auto mounting support for external drives in the +# mediacenter also automount internally drives at boottime via udev (yes / no) + UDEVIL="yes" + +# build and install exFAT fuse support (yes / no) + EXFAT="yes" + +# build and install NTFS-3G fuse support (yes / no) + NTFS3G="yes" + +# build and install hfs filesystem utilities (yes / no) + HFSTOOLS="yes" + +# Windowmanager to use (fluxbox / none) + WINDOWMANAGER="none" + +# Xorg Graphic drivers to use (all / i915,i965,r200,r300,r600,nvidia) +# Space separated list is supported, +# e.g. GRAPHIC_DRIVERS="i915 i965 r300 r600 radeonsi nvidia" + GRAPHIC_DRIVERS="" + +# build and install remote support (yes / no) + REMOTE_SUPPORT="yes" + +# build and install Joystick support (yes / no) + JOYSTICK_SUPPORT="yes" + +# build and install CEC adapter support (yes / no) + CEC_SUPPORT="no" + +# build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="no" + +# build and install iSCSI support - iscsistart (yes / no) + ISCSI_SUPPORT="no" + +# Support for partitioning and formating disks in initramfs (yes / no) +# This adds support for parted and mkfs.ext3/4 to initramfs for OEM usage + INITRAMFS_PARTED_SUPPORT="no" + +# build with swap support (yes / no) + SWAP_SUPPORT="yes" + +# swap support enabled per default (yes / no) + SWAP_ENABLED_DEFAULT="yes" + +# swapfile size if SWAP_SUPPORT=yes in MB + SWAPFILESIZE="384" + +# additional packages to install: +# Space separated list is supported, +# e.g. ADDITIONAL_PACKAGES="PACKAGE1 PACKAGE2" + +# build with installer (yes / no) + INSTALLER_SUPPORT="no" + +# Testpackages for development (yes / no) + TESTING="no" + +# OEM packages for OEM's (yes / no) + OEM_SUPPORT="no" + +# build and install nano text editor (yes / no) + NANO_EDITOR="yes" + +# cron support (yes / no) + CRON_SUPPORT="yes" + +# Distribution Specific source location + DISTRO_MIRROR="http://sources.libreelec.tv/mirror" + DISTRO_SRC="https://github.com/JELOS/JELOS" + +# Addon Server Url + ADDON_SERVER_URL="" + +# Addon ID of the default addon repository + ADDON_REPO_ID="" + +# Name of the default addon repository + ADDON_REPO_NAME="" + +# Version of the default addon repository + ADDON_REPO_VERSION="" + +# set the addon dirs + ADDON_PATH="$ADDON_VERSION/Amlogic/$TARGET_ARCH" + ADDON_URL="$ADDON_SERVER_URL/$ADDON_PATH" + +# Default size of system partition, in MB, eg. 512 + SYSTEM_SIZE=2048 +# Default system partition offset, in sectors, eg. 2048 + SYSTEM_PART_START=8192 + +# Configure debug groups (space delimited key=value pairs, with each value comma-delimited) and default group when DEBUG=yes +# Use ! or - prefix to prevent a dependent package from being built with debug. Add + suffix to build dependenencies with debug. + #DEBUG_GROUPS="kodi+=kodi+,kodi-platform+,p8-platform+,!mesa" + #DEBUG_GROUP_YES="kodi+" + +# Default supported get handlers (archive, git, file etc.) + GET_HANDLER_SUPPORT="archive git file" + +# Partition labels for USB/SD installation media + DISTRO_BOOTLABEL="JELOS" + DISTRO_DISKLABEL="STORAGE" + +# Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + +# IR remote protocols supported in default config + IR_REMOTE_PROTOCOLS="RC6 NEC" + +# IR remote keymaps supported in default config + IR_REMOTE_KEYMAPS="rc6_mce xbox_360 xbox_one" + diff --git a/distributions/JELOS/splash/splash-1080.bmp b/distributions/JELOS/splash/splash-1080.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8355fdf87ce07ee2a9b721ae1b7dd11de7f79d22 GIT binary patch literal 8294538 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

h^ZE-#*8>#MTY$@3r{+U+aHccVqiz7uz!C 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 z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb 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⁣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 z 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 zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000aMjyL2o70000m$lrPt`-&k4 z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ z2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvw zaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~ z0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv z9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p# zzySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^2OMy~0S6p#zySvwaKHfv9B{w^ c2OMy~0S6p#zySvwaKHfv9B{w^2OKyL1bu(kRsaA1 literal 0 HcmV?d00001 diff --git a/distributions/JELOS/splash/splash-1152.png b/distributions/JELOS/splash/splash-1152.png new file mode 100644 index 0000000000000000000000000000000000000000..fb0156caad89e149267ae0700866e7a267bf14de GIT binary patch literal 27160 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%0DiA}3~C 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 zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`>b H84P>_oP5OR literal 0 HcmV?d00001 diff --git a/distributions/JELOS/splash/splash-1152l.png b/distributions/JELOS/splash/splash-1152l.png new file mode 100644 index 0000000000000000000000000000000000000000..29b5aeff0126fab401298cb86037dec5db9a4ebc GIT binary patch literal 28372 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%0A(v#-zx{dz0)}?cbyB=Z(&e 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 literal 0 HcmV?d00001 diff --git a/distributions/JELOS/splash/splash-480.png b/distributions/JELOS/splash/splash-480.png new file mode 100644 index 0000000000000000000000000000000000000000..0bfa5404efc239b651af6d15bd4b8a1ac9ffc557 GIT binary patch literal 8061 zcmeHsc{tSV+xN@}*_#$gw#MCdV+NCLG9ww3JtQRSEXFc3nZejci$+3HX=E$OR+eN5 zF-02_QnDozMF@jz+1{_ZfA{kKe$V^<@jQP%$1!spbA8YA`kd$WIhX5uT@!0#Whx;m zD+&UEB#s`z+JZn}9`HT1Q3!Z~ds!R?0tq^j>>cTjmKG>4ia*=~NAbkN8U9p24g%>L zFsL40zIeKlC!RyHsIrJpKvUo_0o(niUM5`b6If@{ImVHi;*{Qw*R zWs5cWV=^#8!@TKqDhh!J4i1I~BjJ<)B0@t?PYGbQ0meP+yn)n>y8-LZ{HYDbzom`iF@>#s4-Dp!+{h zVR%sgld`4d|6ASP{~ybs(T#%u;{FK2KYaR^0h)aX6_2pR(evViYKq?K01{!uiSN;EzI{i(G)cl*&h~h^HumjQ%kA`XdoV3mz>Zrd55r2Y& zqkI2__Lsl{PbRKQ{)O~YvhJN<;Ceb7CzF8nX#R!f_?HZrq^^$mn*#uAsBtJk#vo$@ebkx{LTSHGl!w=PRM0SL00kH5g~$D55%B((ltv-Y zgFOQ9hD0E%&@e*+fds@aLDzItuS$6B3i!t=4mNw`A4ZM(H2)fU9Me)r8` zT~)XnFI6Jypg`vuCOHT~e-f?K=S~U0UDccse zG5g#UvSnk#xvw6F!dall^yY-ki%-H=e`~%{cu~i(0T;XB=mUCeHLOF+De#Tfj{Wb` zR@cT0bLMBOJA4~>5f$U}l6fCuK3w;YlJ5?hkZH=~Y1(n!Fy~gK-c(+6UIH&@^Og(p zo&|mK+>)v&@yveO_K`(mQA6+kcdrcxCF~JZXq7bDH0Vv>Vu5d0?**&ad9_v0@Ezhk zMGJ!pU{@2N9&w_9Kyc;tFPM>I5Cj6rV2)x9?HOs~eIaQ$e8|@+w}ui4A+YgQoRkpF zxOmf68>a(L1LMrL`YRdkN;Rq7r*jTFb^4XjnPWE8C)#i&FbcNOAmh1HcP12bdq~fBjNTum6%-Uk_P6F@-WnMU*S2!oX5TGk1cQ%W`R#u{|7`~B zah`1=M`RJu(mi}}_hh}|NA+&otF}45kL=SN9>cRkUVz#a%%G*x{LMT)&fDnt-g+|V zgV=}e$Ug8gs0xNG-f2c;V92#sCJu}gv>&zE%<8=C((qeR_7m84n`;5UP>h#kTDnas{Fh`L)B zNU8Q!2`orcQ62sLMze%GTWKCtQ?Cytf8*Pxxl(q1Z2ecelMTE9;1@ddF(aV5d}~*Q zQP(QqLGFCd^L-atfy~EFu5=y0ynJcu?&BJmgUDk4y!7ZemOpbIEDVbCsUAONe}18X zy;znyk$*UFMcHgKbjpY4?v8Ljt(ckya_x$g-vaFf5y5+LLx>-3k%KT#6`lZR_1#*= zV+>!Cm&IDprCJa^o}}$`KHnjf&b)IT0Smgs+Rf?A4}H9{uTG^*p1PHK3R}Au_Fln8 zp`68vh+cz8-szTn+rtTCDq5pag z38!1cvK$qwZme$acNzotvsea-HcMU&5Y>DYsD_A(@Um7%+n2*7$|b+SS`t{f;wbiU z5<&$f+!eyfSB2bF9#9r&@w(&0+`TQ1Revj0tL9A>ZRE`ulVaLfCY1j2BFq!Au({3G zdc~@sylzd1`_L@~ye6UFGl*W(gxw9Tb&y{WceMPWM}5nr$#moQue_UJr(+|`TZ?Xu z8ux#QRJ%DdyQ12E!|Uyw@7$RDNG-f3xnB^T$coUM83_4UXcZ+@o8RnPl$E+LXUQ8q zjvh{6b>wM(?Gn`8z;N2`FQ*7Sfg9>LHFQ@}mE+T%A9zpiy}NOviG9QEnwA-d69PmC zkucOQS!&>94EGgS6JrQ;{1})G<>HNaYbK4o$Qg6=$82rr)L|YA4ques#11)jluE#u z%7Io-3Q8+C0In@&y>*58XvlzSHx!+x}Z zfuZg@-g$o&xmHgP@`yz(&tjgMudqH!i*K+R_c0ULsAt&IM$=-gT zZ>Wm4(Yc+1ZS=4|c=B54R>ny}#s>?N$IaYKlg7BbJxPzV_z#|Ox}l|Zgpb`WL7Sk3 z0#WaF`R$;FCx>vau_wQsIQc+WHD3)DB#*L*#YJXGy(F06`oRnCQ;g8FInOb;bR)pUa_B!V)=e^FjUXHZ`)FrQJ!Fj2l}xg`y1<-juKL_B-5K zQQZe|=BYiAQ#<7AqD~r(`y6p(=1e&_yC{I?{O6Un*K+m2x;5(IlXC%gs{>^NzXmC9 zRZ|C$EQ}i`t}2?(PX)D}zFM0;`n6%R<@YlO$JNV?1^j(j>nO*a?G>_WW}k>14vXg# zMH}W>EOJYm+8a{LOoCQr?k+Fz_2)L&Z)U@Rd1aV`PnW=oV*2(ny{~D5n|0_5t8uUa zC#}l-U7moNU9Q?DB6>sk!&g|L{YXl7&r)?`26XD6mUh%JL#~Hb#V<6w5$-SoH>Tw=?&3O~;$dc1zlgomRvPfvD9zX3&n;ST)pNbMlVe5eRZi`8Yr0ypL z@8I`IdK7|lA6ANXuz=VO=00S(w13|5&}iu4)2b6#?8x2SyA#w{-Evh2U={aDPf38q zN)AN2I>`h_W;=z@a;f{IjFy|PuRFrTq#U%o1*T_%=Qo}VzRqMTx3~}H5r~==cGBq{z6M|fH@(ucmx+?F(RDc9CnMn zXwAt#ufZE- z>FUDX=j$oXMgwa{q_0>XkT7}T)3gLL*iOQ7%@_M^3pCEh(x$u&;40@K zDDlV8&O+NBf%}g^0=OYtcO7?9V&#o2l>4A6FBdws%JTm0#Out=%kS>wT3S^KJ-W5* z4{Xai5+y4h_O{H)7H<1WlBwm$j@oib!`5qTgIJb4(;7lae{o-15VN5c0jm>DyTML* zmy|u~0d`21^sX2B;>B?jFIl;@85$QoD|)ylLQ>Bx(p9F@yI2!BDJ*%BHIr}Um)hFR z@dZ&JAGbpLDgBd*$eFrDV!yGZhiSSY)yj!EQoza?pcd zJA1)LxWYHbyEiNhvlg~eu>_3%nnn5Vb3pMOtF8!6>x_rrfasqfMD9gO-Tgi50@xsJ zSgl{gWe2o1BRIf$cNnlqu3VL$dVjS>xNA<`*+GT~p76^P<=^Ah-t<}F?^PbyZU1<{ zKR?#cofT5SROC;V}4Oy|#9rKaHROwN-w?<3n)Ih25$Q zc8D9HPK+VUA8T)hdG-pumE8#hyw+udzRjljODqQY?JIG1yX)E`AYdT&;tt*{=d9qT zF_7tjn{OB;Aak!f5iOJF&wuhlipxXem?_dRi7sHFm)v4I`8FHRe%4pKf9VjQH#l7T zw5oJJ$3D5(ti`NOu&Vl#i_jjVHN@)oji(eDfej;<^w*n@Ss1m(xN#_+ps7EHxU@td z1l1%2-O{`I;8kc;I~|tY0xW~gt%WWa8h(}KBuV5Vsn974-u?5Rl=YT@%)o36zpM0J z>Shc6ofFeE?qpnnJ!zL7LtN6=V6$VH(gc)uCWf{{I#WPlbW<4_>(`ZtGr1xPH!%QTM#^;<~(S{V<&|}LXq^jmjP!?`-n5doJysr$DcwGW`4VI4K zE(h}-JmniCvf@*@L}o(PkITmflr8sYo{O~IcBT#ETJ$gv=!;QpIE(;a zuV8S_44WJ)p6@2zcy%Hp=UNFUkp&z&2v=vB=8<^^FlJ#-d?7?^WAaUlyKX(i&vixW z%gfwlhvY@^d`mG;>2J5THgF*Ns35gVWuP(OMWpv?E9;}^g6G+h@5VKI`(Mv|XqVcb zeHSNDCCE@vUpFb__et+LSgF6wKECw<8)q(uJvj%4$;7vhp&D=s+3(}2i`u*jg z*0X{P`Zoue`8X56@nrT10k`piD_+W;FYZp0y0+(qPVaU;u>4I2RuRjJieJs#%lYWiE>@f@WWt5zkQi#<{D%*=8NxToefrT zERPUtOrFxv&3K~5K+G4#uqQXu$Pzg73V?414(9wPb6E>xF&BcXS@2lIc7b7FAH_69 zbh?g(?c!gA!)p|}43LV2dMWX+fvp8dcIC;VFUjIh&K0v58vF-m+RA?A<``|@Gkt6Z zSa|y@`5A4!K4;*aqohL&@hI;J{QyLBX3Nj*apQs~R<6Uw3?0Y1&!oIrbQ*Gz0u{G% zYkXS1ba1rj7{jkC(5Y!u?}SO%m7aWhk;J@hU5rbiJGkh{XS#0$ublIQbLG{DL%nvf zfo#`f^`LIvXv%}FAHi(dTJocZM?T5Z*<5mcwWM)a&_xM zA#l{d+CB1q_%JcMSGcOI+1yQJSqX-bh1T0e5z>ttGdLZb+D-pCL?K+(!^mfNiXr~@o)t~{VN?s^8J?c(usZn;wSE8@Wa5nsfspnvYh*7{2u9 z^n)|g*{L@=FTVzO73Mj*x55$ez_C1g`0boofL?mR@ER7Qjnpd5(wWLkBdZBkjBlz~ z1IQj(d70Y}8<@`{Y@qZFs?`anNu~j3qt5Fxo1nhO)INn6EtOj(R-$AXQ3UO}!%DEA zoZo}`xZ55{EvWKG=7h7W1Dr1SwD%<)8eu&vW{x9gda9>oh|;`})HHI$)zK|cdv$Ep z4(gWQJgg6-QT(Xhq?A=?w(p8VY7A+hO zT<%sZce6ZL9Xrr_K5)Om#Qpu&<3>BjD&5Y~-I8@Et&BbdEK#k+4HW5c^v|1!XDM7i{7_Bw{Ch^P1T&q9&J(4cdN#kOU?7ZUId69p z=*NV+dnR(6Lr=?n$$j;`;Tb2hYWz-Wn`=Rt8daR%#(cX!a9fEfp$>z*FoZ4P>I*T% zju!{Y^c_AP9)exlD93Z4Bky;(X$mMEL!H^Kb=TG8YIpBCk3z zcLL6aqB^A7ciEfAjebY+Ht=Xbibc4MdVv*CM#q@Ma-EQ_xKWqxPMfv0wK8YUHv8nl z7KNNo?JP%&+3*ERP8?|>=~HmN$pk@jCOW34&CHRxy@XymRSjGT-X7NZ0(7o5_eD&9!?#YrdY?j8+xGF;yDz&*1LY} zbz}NUX!pgPR+q9_U98cF&ms0>5uMpRCBv`mYtEt@r{|Np-J*oTf&0Uq*p~mjdj20_ d0KK%f$yg-*V$<16>;IY`HMYVQ9d(LaJ5Hd3DFSzTEfDGxwc8&&+&;9`1eb zojdc)Ip6b}^Zc1-e*DHS?)=q-{P&9}{}tuhk1kyJ-zY!2@YfgqBEN|5|K{&6oR<9a z<-ZpfF1-Aof4=zfKmW^rZoVjf`OBRxU%Ys6L16<7U;qOczyJm?fB_6(00S7n00uCC z0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n z1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q z7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJ zU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm? zfB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n z00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO z0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD z3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAq zFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOc zzyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fPpnJ z@Ux%&?6oM@^L0(yJ@hMEMO3TrUr_fbW;iKfUyFiw25=rN@EuTNmT0d!ch5?`Yk&?rp#SM|`Y{5B}!w#WV2e)(3_9_u^D9 zUtnVKOz`mqK3+$hpSEkyZuf5IfBF8QcJMm55dZwV76vx$;O8ZIU~GGNEp~C9GyntZ zU?6nuN{Rl(HXmSO9Zc{uKd*{`N4MT8(ZJJuQ6G^$A`D<)K@5bhy;i7y_g8gYSdfqT zO-_e_0}MR6^{<5*=)MrTDF4C0q8QlZfX~`AFt)qvI&$DTA}$sc7g%2p>!EEo+w?EK z{}m?I!vtUR^{N>7;r(yB^8jD|Eyt1LU;qP4WT4=_kjN9Sp0<~lc>c~wTw`Fh41})T zD`*4%WK}t_cvx*b;Cx-}|IokJ+w?ECc^4P!;)1{VdkqYPwq0t|zxe*)8f@Vl#XJVq z#X#s^$z15qaIr2f_?y4iz(Aq?eZB@;I7cy$fpsxZ*#7+uF4n~bfAjYm7zq6*T6u*{lB4q)__?93(k?|t%!lpwUV)qd>-5t`Jem`0~lBo1G%Z8oq^2zqTDIfzSHgYw4LW}2lW@r7+4nrn>KIBT<7gI@c#`b z>*9pJ`Fm*$g!bhcfB)Sn?~8HaQ_YnB89&3oEE!m9{5IzuuUA9!KJKb}xqbZh!P2e+ z&PQ&uCI+^2;B@|4^LN@{-}~mX-Pg0W-~GJn-@C_Y{@&eB^ZD*;Zns_H`-@TXnU>kk z{oOIT*Zd~;wY_iee`ss=V2@fEh}g~h8a~)6nFHnD4>zy*ck@|(-n`#^ZQDM--~LU$ z-~PMp`|WMds^9KDoAb)ge;p;~vHU*DcE8=Z-iQ6J*6LgJqB|Hk%s|BNjXw2YW&8Rm zz7F%nKI~I71N86cT+llAJADc@bFOZ5cpn4w?tE)4QM7lpceQsH z#z4fi_V51rFyDo3?$N#aui^46K020xh;Q>>Ug_V%jpkiG)}DSR7BMg%1|r^b{&U^~ z@lKRqZoU3|^Y`{=xlKOb>}1b&&Gz})yzg`StVgroeBab7+ooBclJB!VxsU&d@<#mb zdY*rjOPHMxvwX!@eKHX7|ATwpcK^;}HJ@!CxA|=Mb*Sz4?YB90Q?HW0x3}4T-|WMy z_`(1NFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJ zU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm? zfPtYHIBOlevpzqo9;MswZnyjQ?*7mEzV!3b?RJm5`*&aa+1;vX+vFP0`I~&-)V0}1+vjI( z*Bra~ee?GRJLi|j&hO6J&&RR7b)*;ed>ooIz9x-n^N86uBc?syw+9=9Ew7B}JI7jf zZ1V5${*9RR{G%SUFRvl=Z+Kp50vq?qK*a1d`CmWzFZ~mnea5DJjlk2RTmMA==$}{{ zA=dPbR`>jP?caX1Py3gCxQ5J+fzZF}^1psGQ2Td&{L`#;`%M1VkM_y`)*VN5be{gF zfAml6&NFuT?fiZ#X#ai}+q@g)ByyblQF0z|zP^+1w?6;*=JWfT&)$jG_wuuN&AH0C zef}=D`}yXx=I_(j&Gxxn&M|JAli2L<^my^x)A}{9o8vV5&*SCy`J1MmO+A{=xA&Lz zZMHkD|K|4x>lE9V|EG_?x;}n7c|a%I$A5pQUG~@8wvTQ- z3tc=@1L@xZ&gddttdN0-*|z&XTJ^6tec9M&#`<@)Z(G7@9eF2B;{o(9sAsqf42AkO)>sETm8e>9>(Y)J*gxw@v?Q z9se-?OCRNWGh$$-`5*n85o5<(m;FXQHwFVW>R*g+)H?sKt^Ip>44*j$ZNNZ34Aj{E z4gG7I|5xq(Z(&d4zj9M;;JGkR(fDs_$Ekj_>tD6=UtE{_xh}IKJC4CX=uO-GAEVEI zDQN#rrGIVhU*jKhx$di{95omS{hQ-^_2u33&DH^M+a421q!|F1L`u>O^t zp_CQd&4QHz{Tsdg8+EGn{txY6aXpK;mLHbohn2Q}Yt=vPU;0P?mc&5&`0wcJUxg;O z-T$HgZ%GU~7n(W|1EDo-F$CU zsI>jtcK>g!`Jd;1EGRar$x+yJuxn0j?cc)uZ>sgLn*UX+f2aCQ zBWMH$X2C$E`Zw40|Ezx??q?DAa?O{yX6Rqr`Ug|Y|GO0RI*Bom`%!+md3`6}$L9~? z_21)l{B`!se-YdCeNhaAj^w>&pPx~Fmzp#6wPF&j+sFB%TOWiyezV6`|C66ZJ+1$| z&u%_jlx9q=2aZ2}KWW;$8Xcx5^aKMKzyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD z3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAq zFn|FJU;qOczyJm?fPon^5NkT+^MAjK^81QQK6j($`eogoTmNsGb;+y;$L>cn(Ej|( zL(ie~-PUtDL;pPgZN|C4(J|zlXPW~@%)TDE3mxmh24PFj|DXl4)q*wZf5dFt^FL@~ zp*E)eMH&COBs7QSVBjbQB3`rqkH+<2gVet@UPGO;{p}bS8bbf*z+81; zwe>ds(Od3I|LEUpb!4XP?}*tqwSW6*|A#G&|IRcH=+-)~T@kbT|FnOP>N}(q=T z`91XSQk0vK1HKXEC-MHxD7QD|W`4JM|AWuZ+Ww5sGsk>mYhTSio7ZOFt$&}f|3me^ zy*YMsj6An9w?AY5`P$m zkqorwf5t!L2J6fX_@$u{h>q4D4s%(XBrk|JAlxWZOo}?~i$Qd1aSJxBfu? z=pX&Vz$zKg{(W^Va9v~z46KWRm(NLY{|D~Z#XW!XcQVjE|Hb&PSP?52SSAC;KbGlN z@yf3lXlLNS+6Or>0#|5%5gm%yrXz-r$N&_7J|&6NFNYAy^I z|G?^8SXED~_RTy- zzZ|cgu~zvtYpF~+FM8V-1F2(Cu0?q_%KK5ii1JO8yqBV+d==Y0j*`E95an85b+aFw zV*mqvGY}eeG0N>IpGPUtxMQ~YB=&tL%B8;RZ+~I}0~qMSK8_4Q+5GzLO*QunfrdLI4i^S4j4PF=LywyyOUz(5xULSwE($$q&$wX4s4 zr4Gsm zIW=P7=opZ*%`;~^uirv9vX5^rI@eZDxgZUsffy)aAapP1n6zoi+`hki-fM#2uQM0m z_jUL^G%x2Z=bYmqwe5NAKj#Q$yZU5P@_mk7beSW4OdUVM@;X@NXMXO&Kxj{DU*G!k zVeIo}luq-NH+9Lr#~V@l*5jPF<9U|aLPc$%E-_@=d1`Lx!Idb-%<(RgJ13L&)?H>$^Ps=Gy|a(IX2N%Fa8w2>Ai2SuXD}1 zMfvuK^ZKN(I@pic#X#K*ggzY8W}L;n6mf3Zrq8-|)%Le>TQ|4-!$0R`AavpS5!x`j zxx;aeIS$=b1K&Kaef?gHVxUe2LJzW^tcxaOTXME@<+AP_&o^yjJj8g2c`*xQAY!}g z7(u6b%Qas2;+(H`)W8Qdo`*WsnN#q~Jp2+Gko{s^a=+_K@ok)U*Eav`b$=;7#oPBBm?0}=OK?r&S{IB3|R%eeP!`#r^B zopH!7)A%LgzI2}RlcoD8Z1G8yl05L~(rw}Vrin*(AJ6U)>(>h7JvCwR{a$g7UB-kL z(+4W%#)~<&uE*99@1^<9{k8ZlY?AlymE?er*J2arSx?OJML)iX81FLQZ#DDY!Y*CL z!dGJ#ao11Wv11)}j5sfy_p!SB9>O*^qLk!-+Q18(3rnNw(5NB(5b^y{L5x2evJN%x zJ8bh!fqmYu`5e@3`Ekt0$N9J*wln`(?0lCtZsOeUme{CmKfXVXPj+Lsp%{p`E`5IG zYUjCyjdK0ek~Xll^0k586FegZBCbygV*AUX^mi`%4I4cxu+w{UIUn_uQ(@r6g^1}~ ztF$e*xx02-g^k`Wu+#Ik+sXOU)wwVb@mxCZW%2W!+k6(bDry6_?Z@}@0Rwd~5HVeH zkHc!meRnwxdp(cRmMgFRTCr<4f7cQ3{P06RL@bxAckqPWUfM0}^=X0rRr}l%e*7W- z?6GcpL@bxg?bWBh8P5uPyATwYfwC`zw{+ZA5O8-jc3w`CfU-xyN zfA}XE2<>}Ppnq5K@{*UZRmn3lKVdKNg@O7RhEj$$XBdeEHIsVXvnJ*9-H7HrET>)UN?+_EE(0YX$KfCgR6Z zTjh4_g%=FWgMkwLi)~ha4@lUc=s5wnp9lB+#81gU#C1uVZuN88!cOl+XCd=dZM!bdy+HfYM%IeZSK{8c88HwsTePlwY`5BR%{cdxbq`Yi+$%UE z_T_2w${Xe0cFXZoIO0|Mrgf{WeNl8#upzeJ%En zb1j)4o;LA}JpF#gJ!Z^6#PEYCCHnV#Mf&$mp-mpF#U{?P|J;L3r?+Xu`NhImPmNss zJ^pcyx$alV^&q!dUB9T9ojzvypkE(E9KY2e<`+BHBWzGQ=8@WGy{j3wduT|%8Zvi# zcF@0X=YFpH>L2HybDf`cu)}KSh3~VU&*;gV8Hl*Q(INJ~ob$Qv);-QUwePDA=fC>< zqIYfRZ~8ZP1|t4T=0i7qW1r9ce4F~mc|Yl(edarB_ZstEAOoQRrSm=-4Sc`Rkh#9b zIltdQ`|`Z4^S40u=gO~o_nUV|d_V4}2YHX!Ec?Qu-X-_9HCmsqp7BfjWBd!HuWt(}cHx6*aL zcF%7%`d+&a)Nk4Pu>}8~Lj$w@TwR_Nb;`W9%Q(lj{^|2uaGPfd@#-APpQPqY?U$%S&TV-+%68qlyuUs5IXHg*Y_lnwmM{>yQF?#yS(=jT$B(Xqam>7z z<6)Gu>Q(aj+a)%#jab6Kav2B>={iojPg`=H$<-)>wv9K(D0ybbzB+Dywz@UH#PD)s zm~YSL+t8JFqipNLdETd<-i~taF@@YmlpNDIwr_9Wd7R+oe7vw9`z?)u(3qQ1_UXlW zKFfP1jB8PH4Eo}x%dye**LHH%@{byKOl8s9?iqRAPj7D@QVs{FxNM|x~6NAbCsiDU>XKOYjVCy4LX=PDcy6uALM#Z zU#8KQx!66lC&x*yM>+4kXouRgyWi#9z#DV1k$Q?D3@n#{)WF8S@jk~(a@_dKD7(6K z?B8E+_Gz6Kd7eBE1G8WtG%It%)WfS$a;=#=QBoT-f6FoD)V0*fPow1h!}(o4tMf*b zY+vVG?C-U;(O9p`y_WJV-!72>I)>{da_yXOjR6c`00S7n00uCC0SsUO0~o*n1~7mD z3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD4D`W3+=G|v z)L0YR{qwW9f4&dq?SpnE1EG8QOs8i3nRny8brt9!9mK#Y7zn+~HD?>fwX)*uZba5C)dTKxjg) zKbq^2ei-FRly9P>R-~5Xnx*-iwfCajjB>G7|3}?&J=NWuZ{Oc1wVs1|Ei1P8vp#=@ zM&w$}jppsshqljhE$8bs`8Mj4>qocMd;9x)HPv5T>WdRTS)NZqBXYg@Z5=qz`)^}k zRp?;UBXiWQ=aTts^=*1_xV$*z({X(oah~G>$7n=}rhGW1j^weU9INY>usAM@?9JX| zG7#F3bKpvJ>^$3KE;#8NlQ@3rU{{TQI;JliOYCD{JO)A!_RWPmkIuFIcJlF&IOiP8 zX{+b<_jfTl9+Pa%)!@vq(j{&*X$Z>rVhi$C>sxBGFU zGS++LSU;p@Mk&py-a7U;ef}=$TRI2mU>@9Oo$PCvIAGWH*)`%jbH9?jFUMy)<$U{i zihX2zxa4^8^XdH&buG;SwSg<}R}IXl!}M`m>Vt^y(%kRpyl=NIam>7jxI_c1(3Gg_ zlY;s_-aSu$&nFJ}YJI+nn9kgtpuqH|vW# zKCi>)5!ZJMH0X;V{1wM7Z3o{N;`m+n8THM%iEVm)?*4(U^|E~(vBVGa^Fze*rv)+H zTf29ckvMkAJmcrPznkLk!n$UjNCWi)x*w!+1~N{gwB<8{i;b86XQhp2S`CjS1Y&XA{;j?ARztUEQiwnRPK#>zhtBg=>peq6R6BbIaR=EveO$jxWUVpGG-!&G>3en>p67F~YvfwQt06+j{RG zj_LoXPxa#o!4e@A`V`q#3)lZ}J4*emO% z|F80SUvyQ=H2!syqGDQw}GG-U1!L_D8F zIh6lB8~YriKBf1><#vP4%h^8nJXVyeQ4ZNFzcc?&{^#D0888sB+BW|sBw+mOT-2*A zFHM~peQm%vX32cX(d#vZj~sLSxM1`CY#y zR-zHD)5KXIHAJ$CQM1pUQ_{N_7ad5D3C>ykdeNyapzZYNPnG;q+hv7!#8T0H5! zDTn;*J34@Y{R|Xp%+;~&7xgOXpKSDTu(>c%kCHiwS&vcL;$!>4@%G0JyDY;l5x1q! zCZD1mTw1q>L+}{3DeCu&?YlIQFwV z*C-`pzIp7M#~#P;>WvM)S%+^TeoN-IWt``D@u+R#INtpzdF+zX+kBlkUdcS{rcR?? z7sTZ{;*y`o^K-=eH-#FLF+bW`q;ag$@rOo>Zk&gk&GAac#hc?jIM4C?c09(}nyt@b zAmYAs4bqJJQDZ)icRfm@Hzlv{$M&6bviMEuy(di_G9T`IoU?r3bMc9R=@^Juz80m4 z?XzAdiTS8kX&ZgJ-mQItsb5i2U%Rw-n`7kf=%0Ci);w4U0};<{bA3nc|J%MEM%})O z(r8bY*IeuMVU&AO^88XuGe>+9rOSS{w;inyVA}@XPnRFC{W@&F(TD9=Z{AO`_FltX z)T>Jyy{Yq1uNRwod0j_b@bh~799pw451hQM7xn7eN7uLhpmDror-c2WuK09{p@k<=k-47Wgqy)00zcnAhhd7l+>_N-ODlE)XwZv)XvqvQ$_#I zm@(s6%hTx8vM9NRRgPm{i*heY&g;qhHuAIlj^5EbdWV6mrR{}#MGTuDWy^q(k-XSsd6Z% zb>~p5=|IS7QRFyoavXl|>HgfO&*%I3{rCI+9*^zu*mb=Q*Xw$nuIF{_l7pR<*k*;z zAP`8*`Uu()1OgufzTAz%z)V}>Q#1$!b@O+24Rf_UhV&%{Y5QP_r*YcUAQC_aflSS) zBp=^ET$svfoS%O%3dXCdgQ@sqQLvK+wmP;XbKDvKBT=C^rzksT->5)eV=T<OC?3-eK-1`&eENGb}pt``aX7EHroD(fs^fhd@(t%Hg=F%+j_plzV713R!;#WWO) zM>?V{e-{QuDA<{>FcK0DkBErSjzDM=L;c{o#>U2Q9X+_7o)*BNMUD&(^Py@5lT`&O ze&|5s$iAWeq%ePCu!=yZ&uJnh3=2p1eihU;qU z!vD&Tqx%18O)&X)cL9!r3n&1)&fnO>{PF(-yMXd}9sH>{f-Bk|a4H#y1`3AI)Ao9b&!uA z?xa69?989q{v;g31^Wpo|I)Nh5m-l{2-4w1us^ULy+5_N{z(JW>FB`!vXa|>ru`8O z>~|FWnPF68fvu2-Ro%6e`geS8IBLBU9&L@dP@hh29gVEzv( znTQXI@Cn5o@&nQe1v`Yt`vU=tQ~?Uy-!B*!ssfa$j<){ag(A-20EPdvJK=xb&A+TO zh5wuVKQ{lDUINJdm;-tg(CpxUbUR@1N58}c15Gj%=!RENZ7M*=jrRvK;omX<1loIp za-(%0`uMgcvxH0hGxQ5s-A((l4%rfJ-Ec^5+*@Zz?5p0Ng>M|Ixq&SpNUIsfYAuL% zY6ND}Z)xIe33oGQhHS55ITIPn&-$Y|BYor-Qnva21+a}H$37+|CagRmOHcxT0 z<7F($5+CH}Z#w#ExCVWtS2)c*dvLWZwGyB2;G$-lr+{~%9;2Q%2sElz?RmKScI6a< zbVprwTP=C^ZcDNF9?#YA&P2&>%;aG8Lzfozv6fG} zpGaTXnDz5Cg0u1E&)<9w#?V1EVJ+8wT6__+x~nC*;PQUgm)J`itRIJ6dJbzhaHG64 zkXQehwz@V^kUjtXd3)eX?%DE*dGWlSgr1b3IHj)eNxA0xTskEdnKSXqwn^{ELR{ zZ4=?0=j?=qyg<_38wY5~d!-WmizTE8(mQ+fu1(p&;8GjRRR;7X)EYhBLlhLjVrXH4 z4%J(i!*=J2y&!=kRR=!jwDC*FSdtIMPUZ%76n$D=b}Nw4Tqgm(j-Vppbkyc*S zmQMdyxqU*OU{7&RP}naSygOmuxDOV`}=>uzRE=T_`c(w)d&vG|jYN`t1?KOdM@Okv21=@zSF!Qltd z_=r$Rm*Rr08b+#O9&cO^P=d%5Jak;fCzvjkz~3*c37o>#zv%R4e_%BHO#;ly5ObT%LRroxxt89UGTKx1wMR5@Hm&aP z{%!0npK?+U%V11`jJd=6uc|c^BNeFQG=@EHXku{VjLu&;Y@NZD^%_iw;=@b8_Fc}c zHqhkfK_0Ilgxu1?Z;sz0;+2Hi{Qd;H=G}-m>l5c%LbjG%0OGauns(nTQd510W9X>O z$YWQ^Gapu~$SJ2nAScT|WD=mCOxUi9FKu6d8h8{} zQITB3Iz=nCtdD{(b=9@?D0aKm9}%!_usPK+})uK%Mh>%9ZAJ=R2K2P*Z5SSi*Fjlkn#>R3BhlPl1=3FjY zF)Y%n5H_I3Vq6$B1NS-kD%yg8rg{ub*ch|H==3q-Gljcv*utn3``@yAMf=k0)y z&iC6D(vul+UcS3* z=rG)Fo!qz!=Cwoed~n-;L@WC0p5iuTm*}>6GRJ$%*E)mK$gm4awWJp=l!R>NA8!3(2Bu#=9K$iv7htsxz|cSWiY`}C2``j65BkQ zLU{&VAgqN%;#VIH%{yIjqq)N+LsX{ru&&UW47Ux&ay7V**!&oCdHn{>gJNnhFHo8| z+c5pBPZ0!$DE3Fvb1p*jV3N~{%mI_U5ltaa;j~nScOa6!`#v-eXHlPV(6M(PHI)x% zqJAYBD4}lxHmY8xH-UH{JD;evwAs8l_ccv~@)=~}?$)QPFI=tyO^M6Pt8EWD-wG*y z&AzV>2sJ?3ioeBuso6*k_~2$aUc~}ZqS#jC-Io&3_e?rfdJ2pgl&l@Eh!4!?^jAq& z7Ou6Ht%*-zG51z|C+diz<0AZ_jZYqdS9K7wRtu@Ar)4tf^b;&^P}5cJ*U1ex`0##kg~U73Bg)DR^`vPJJ| zzr8nZ1L5foc*KS&C2re0wYI0g2>>9lBTQ6TWgU#17qq~iC3?-e!K zC^8tz@1sfCo;gtW*Xeh&-3^&-7ZEdgsRM}?=omTbiiADm4Ldt^;LNW;ElaMCPt4jC^L1@(Y}O8#m@Jc--QnWD^>lT0 z)w#L5yE{c_8#JLD~+>R3u*jPYT;HOstUIVBca(v=6?|H9C3IO@>(}0sa<3&=oDohMkV)8bh;QdcwO6)#{eX z%iWGz0)(|sF6Nizbmu@wcstIy8)J-M@viQ?qJR;QHsiH9?C3yyy$4Hm%WBXpwQffz z;G{2>-Np`E9OSvHbz{~(Ips;pU_>qIUAEL7e|w5$c5Nr;;j&_Txhuy~QkOm2mHHC^ z9&Rf>U3)IOY#z5gCJWOBKkP0549Rtm%K95aFW({nIVk`z8jCGaU@gH!QKmK1`cxP$5v0wf2g0jen`}fHh~3;H$lb)%8p*+MLMkQRO|lL zH%H)?o6)qFKv87@Ry_t?^aY0tmQjmyizpE2EWCjFuSy{F#4cDEC^#}m)&IIN73$~Z!@lbxj zZP@Ak+zL@koAT@&0BCyIu#}+WQ+=YEi@kAMJWoYP7`%iK^4WYfoN}+1G|=SlcOh5$ zBa1Mz1FPlEg00MroMWKkJKB}7keUo2As%A42OI_F!{tkIFq7$$rEa}GyDiWJ@wDSQ z&l7_CjcUIG8P>wCQePIW){-!2V(dE9wG?~jd&L7me$~~frFvv+*

4ve;JF%0Ag4VJ#Ib zXzO>gXt|))?E}VDpbm7sF{_K=7G+xMB00T_IWuRMIlgO{a#nKT{Edt6ok>7bUuu|E zU;~GJ`sO2K1+S=7vEF;(78A4ZYzajP5{aSpo&nXOy_Bo_kb7E zH`ot9bX8TfJdxfhPu7gp0}woXmrVP){c4FbGfo?t-s=dMrB#j zo4}~GBq6J+#`_;1gT4pC23)y>PvjKV3hNRh((A(^eK$b(m(`FLqH?`ftvNjq#SBJ= z;3#jh`8-Qs@|G~YGP?PCa@mGGwn-YxPc+R?3iBWX2lO~}myVVV_7nt-FAuOaznTHf zJH3*f{gYA2h-T8j3@e|p_%-MJ8Kf&s!5z(pnqh~!IDCXX84&Ysu50lcCp0Jqt@7n?~F#t9W~ z;ni%<56*`Fcw(~MYX7s#@Efh!qFkiz^1JamBeTKx?pkdrYOUF~JD;vm^|vSPqc^rl zKTxBjK=Q1+T3I^A95ap{vWUu0Ix1lY^~XF5dI!V zSIsa0NlWzsPLMuUzk$->RBY^ql>cT;@f*Hu`Vp{)~&QRXFntsQq}K6#9R|kADl8 zi-FR?t6d?%4ZT$BM=lQkKoM>_mr=MKEoZum`ib`tBq#=KRC zP^=8OVtet-C6iQfm4Bq$KZmKI2%ul1hGe2zL49w-uIai9@fUoOx@p^GhW(;!g+F`= zwdT)#k~VrUA|b_{1A=jab%J#p@atM}*ZPH~yshUj&w-1u9lm>TztAw4=azQ=S;2@- zKuW{~rw+o_G%z0%{6H26+8%wSBX3GU?I%3Ix#0ak4v7r~mZr82WT23llUh~Y~L7E!ivvI0aEdY8s6zWyH?UtnOn2O`V`nS zj&(?=@gvB7$_TSuDUw$d?e~J+$nv6yyjyUijXsBi%(U)yS52xYn29>1mjhJ-nrb-r zu5gU=%k&eFnybd$F6P`e1rt$+bHr@`C;>3f(RS3&BJvG-9;rGqnHwUuu>rJwSSHii zg;o%-{(z%aS&SL7D$9M_=>`Pj$?T!v;`Jw)TbPUIemqd!;*LNO``a@P`}%>8PCY)y z2>kK%)9w#MS}Z@M*_)Hj+TSE$<%?K6d!wlVD?$}a*(>zFViR1C&wk5_spVSOU zfaYmOtCq~r7~Szn*VgeU^CsZ)dmtiQ?vyK#OjVPn0Ed!i|;(ixoxL2Hp!JF+_1x|oD9-uX8;N~`| znwVAtEcc%3l&=ox4h()UzlD2*TgED9NwanWQfi_PnNVPleLzM@lO#yrfh1{7<*5F% k^8WY#X?U1Fy#}uKbhEiJwp9-JI|gKJVTUd{j5+sz0RN=NW&i*H literal 0 HcmV?d00001 diff --git a/distributions/JELOS/splash/splash-640.bmp b/distributions/JELOS/splash/splash-640.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d07de723032b5e85604b3a397e3bfff30e6579b6 GIT binary patch literal 1228938 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 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?0 z00Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# VzyJdbFu(u<3^2d|14}gU{{X_jI3@r9 literal 0 HcmV?d00001 diff --git a/distributions/JELOS/splash/splash-640.png b/distributions/JELOS/splash/splash-640.png new file mode 100644 index 0000000000000000000000000000000000000000..a62158e8344090c4dc29ef081145f07c20683ba0 GIT binary patch literal 10157 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 + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/licenses/GPL.txt b/licenses/GPL.txt new file mode 100644 index 000000000..5b6e7c66c --- /dev/null +++ b/licenses/GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/licenses/GPL2.txt b/licenses/GPL2.txt new file mode 100644 index 000000000..5b6e7c66c --- /dev/null +++ b/licenses/GPL2.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/licenses/GPL3.txt b/licenses/GPL3.txt new file mode 100644 index 000000000..443254047 --- /dev/null +++ b/licenses/GPL3.txt @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/licenses/ISC.txt b/licenses/ISC.txt new file mode 100644 index 000000000..4b33f862f --- /dev/null +++ b/licenses/ISC.txt @@ -0,0 +1,13 @@ +ISC License + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/licenses/Info-ZIP.txt b/licenses/Info-ZIP.txt new file mode 100644 index 000000000..bcfe47e97 --- /dev/null +++ b/licenses/Info-ZIP.txt @@ -0,0 +1,60 @@ +This is version 2007-Mar-4 of the Info-ZIP license. +The definitive version of this document should be available at +ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and +a copy at http://www.info-zip.org/pub/infozip/license.html. + + +Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + +For the purposes of this copyright and license, "Info-ZIP" is defined as +the following set of individuals: + + Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, + Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth, + Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, + David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, + Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, + Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, + Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren, + Rich Wales, Mike White. + +This software is provided "as is," without warranty of any kind, express +or implied. In no event shall Info-ZIP or its contributors be held liable +for any direct, indirect, incidental, special or consequential damages +arising out of the use of or inability to use this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the above disclaimer and the following restrictions: + + 1. Redistributions of source code (in whole or in part) must retain + the above copyright notice, definition, disclaimer, and this list + of conditions. + + 2. Redistributions in binary form (compiled executables and libraries) + must reproduce the above copyright notice, definition, disclaimer, + and this list of conditions in documentation and/or other materials + provided with the distribution. The sole exception to this condition + is redistribution of a standard UnZipSFX binary (including SFXWiz) as + part of a self-extracting archive; that is permitted without inclusion + of this license, as long as the normal SFX banner has not been removed + from the binary or disabled. + + 3. Altered versions--including, but not limited to, ports to new operating + systems, existing ports with new graphical interfaces, versions with + modified or added functionality, and dynamic, shared, or static library + versions not from Info-ZIP--must be plainly marked as such and must not + be misrepresented as being the original source or, if binaries, + compiled from the original source. Such altered versions also must not + be misrepresented as being Info-ZIP releases--including, but not + limited to, labeling of the altered versions with the names "Info-ZIP" + (or any variation thereof, including, but not limited to, different + capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the + explicit permission of Info-ZIP. Such altered versions are further + prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP + e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP + will provide support for the altered versions. + + 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," + "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its + own source and binary releases. diff --git a/licenses/LGPL2.txt b/licenses/LGPL2.txt new file mode 100644 index 000000000..9e31bbf0b --- /dev/null +++ b/licenses/LGPL2.txt @@ -0,0 +1,483 @@ + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/licenses/LGPL2_1.txt b/licenses/LGPL2_1.txt new file mode 100644 index 000000000..c4792dd27 --- /dev/null +++ b/licenses/LGPL2_1.txt @@ -0,0 +1,515 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper +mail. + +You should also get your employer (if you work as a programmer) or +your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James +Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/licenses/LGPL3.txt b/licenses/LGPL3.txt new file mode 100644 index 000000000..fc8a5de7e --- /dev/null +++ b/licenses/LGPL3.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/licenses/LibPNG2.txt b/licenses/LibPNG2.txt new file mode 100644 index 000000000..e0c5b531c --- /dev/null +++ b/licenses/LibPNG2.txt @@ -0,0 +1,134 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= + +PNG Reference Library License version 2 +--------------------------------------- + + * Copyright (c) 1995-2019 The PNG Reference Library Authors. + * Copyright (c) 2018-2019 Cosmin Truta. + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * Copyright (c) 1996-1997 Andreas Dilger. + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +The software is supplied "as is", without warranty of any kind, +express or implied, including, without limitation, the warranties +of merchantability, fitness for a particular purpose, title, and +non-infringement. In no event shall the Copyright owners, or +anyone distributing the software, be liable for any damages or +other liability, whether in contract, tort or otherwise, arising +from, out of, or in connection with the software, or the use or +other dealings in the software, even if advised of the possibility +of such damage. + +Permission is hereby granted to use, copy, modify, and distribute +this software, or portions hereof, for any purpose, without fee, +subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the product + documentation would be appreciated, but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + + +PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) +----------------------------------------------------------------------- + +libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are +derived from libpng-1.0.6, and are distributed according to the same +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of + the library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is + with the user. + +Some files in the "contrib" directory and some configure-generated +files that are distributed with libpng have other copyright owners, and +are released under other open source licenses. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +libpng-0.96, and are distributed according to the same disclaimer and +license as libpng-0.96, with the following individuals added to the +list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +Some files in the "scripts" directory have other copyright owners, +but are released under this license. + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing +Authors and Group 42, Inc. disclaim all warranties, expressed or +implied, including, without limitation, the warranties of +merchantability and of fitness for any purpose. The Contributing +Authors and Group 42, Inc. assume no liability for direct, indirect, +incidental, special, exemplary, or consequential damages, which may +result from the use of the PNG Reference Library, even if advised of +the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + + 1. The origin of this source code must not be misrepresented. + + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, +without fee, and encourage the use of this source code as a component +to supporting the PNG file format in commercial products. If you use +this source code in a product, acknowledgment is not required but would +be appreciated. diff --git a/licenses/MIT.txt b/licenses/MIT.txt new file mode 100644 index 000000000..b937e7862 --- /dev/null +++ b/licenses/MIT.txt @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) + +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. diff --git a/licenses/MIT_Modified.txt b/licenses/MIT_Modified.txt new file mode 100644 index 000000000..b937e7862 --- /dev/null +++ b/licenses/MIT_Modified.txt @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) + +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. diff --git a/licenses/MPL1_1.txt b/licenses/MPL1_1.txt new file mode 100644 index 000000000..7714141d1 --- /dev/null +++ b/licenses/MPL1_1.txt @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/licenses/NVIDIA.txt b/licenses/NVIDIA.txt new file mode 100644 index 000000000..11bcb7668 --- /dev/null +++ b/licenses/NVIDIA.txt @@ -0,0 +1,127 @@ + License For Customer Use of NVIDIA Software + + +IMPORTANT NOTICE -- READ CAREFULLY: This License For Customer Use of +NVIDIA Software ("LICENSE") is the agreement which governs use of +the software of NVIDIA Corporation and its subsidiaries ("NVIDIA") +downloadable herefrom, including computer software and associated +printed materials ("SOFTWARE"). By downloading, installing, copying, +or otherwise using the SOFTWARE, you agree to be bound by the terms +of this LICENSE. If you do not agree to the terms of this LICENSE, +do not download the SOFTWARE. + +RECITALS + +Use of NVIDIA's products requires three elements: the SOFTWARE, the +hardware on a graphics controller board, and a personal computer. The +SOFTWARE is protected by copyright laws and international copyright +treaties, as well as other intellectual property laws and treaties. +The SOFTWARE is not sold, and instead is only licensed for use, +strictly in accordance with this document. The hardware is protected +by various patents, and is sold, but this agreement does not cover +that sale, since it may not necessarily be sold as a package with +the SOFTWARE. This agreement sets forth the terms and conditions +of the SOFTWARE LICENSE only. + +1. DEFINITIONS + +1.1 Customer. Customer means the entity or individual that +downloads the SOFTWARE. + +2. GRANT OF LICENSE + +2.1 Rights and Limitations of Grant. NVIDIA hereby grants Customer +the following non-exclusive, non-transferable right to use the +SOFTWARE, with the following limitations: + +2.1.1 Rights. Customer may install and use one copy of the SOFTWARE +on a single computer, and except for making one back-up copy of +the Software, may not otherwise copy the SOFTWARE. This LICENSE +of SOFTWARE may not be shared or used concurrently on different +computers. + +2.1.2 Linux/FreeBSD Exception. Notwithstanding the foregoing terms +of Section 2.1.1, SOFTWARE designed exclusively for use on the Linux or +FreeBSD operating systems, or other operating systems derived from the +source code to these operating systems, may be copied and redistributed, +provided that the binary files thereof are not modified in any way +(except for unzipping of compressed files). + +2.1.3 Limitations. + +No Reverse Engineering. Customer may not reverse engineer, +decompile, or disassemble the SOFTWARE, nor attempt in any other +manner to obtain the source code. + +No Separation of Components. The SOFTWARE is licensed as a +single product. Its component parts may not be separated for use +on more than one computer, nor otherwise used separately from the +other parts. + +No Rental. Customer may not rent or lease the SOFTWARE to someone +else. + +3. TERMINATION + +This LICENSE will automatically terminate if Customer fails to +comply with any of the terms and conditions hereof. In such event, +Customer must destroy all copies of the SOFTWARE and all of its +component parts. + +Defensive Suspension. If Customer commences or participates in any legal +proceeding against NVIDIA, then NVIDIA may, in its sole discretion, +suspend or terminate all license grants and any other rights provided +under this LICENSE during the pendency of such legal proceedings. + +4. COPYRIGHT + +All title and copyrights in and to the SOFTWARE (including but +not limited to all images, photographs, animations, video, audio, +music, text, and other information incorporated into the SOFTWARE), +the accompanying printed materials, and any copies of the SOFTWARE, +are owned by NVIDIA, or its suppliers. The SOFTWARE is protected +by copyright laws and international treaty provisions. Accordingly, +Customer is required to treat the SOFTWARE like any other copyrighted +material, except as otherwise allowed pursuant to this LICENSE +and that it may make one copy of the SOFTWARE solely for backup or +archive purposes. + +5. APPLICABLE LAW + +This agreement shall be deemed to have been made in, and shall be +construed pursuant to, the laws of the State of California. + +6. DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY + +6.1 No Warranties. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA AND ITS SUPPLIERS +DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. + +6.2 No Liability for Consequential Damages. TO THE MAXIMUM +EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL NVIDIA OR +ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, +DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS +OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT +OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. MISCELLANEOUS + +The United Nations Convention on Contracts for the International +Sale of Goods is specifically disclaimed. If any provision of this +LICENSE is inconsistent with, or cannot be fully enforced under, +the law, such provision will be construed as limited to the extent +necessary to be consistent with and fully enforceable under the law. +This agreement is the final, complete and exclusive agreement between +the parties relating to the subject matter hereof, and supersedes +all prior or contemporaneous understandings and agreements relating +to such subject matter, whether oral or written. Customer agrees +that it will not ship, transfer or export the SOFTWARE into any +country, or use the SOFTWARE in any manner, prohibited by the +United States Bureau of Export Administration or any export laws, +restrictions or regulations. This LICENSE may only be modified in +writing signed by an authorized officer of NVIDIA. + diff --git a/licenses/OFL1_1.txt b/licenses/OFL1_1.txt new file mode 100644 index 000000000..aba73e8a4 --- /dev/null +++ b/licenses/OFL1_1.txt @@ -0,0 +1,102 @@ +Digitized data copyright (c) 2010 Google Corporation + with Reserved Font Arimo, Tinos and Cousine. +Copyright (c) 2012 Red Hat, Inc. + with Reserved Font Name Liberation. + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + +PREAMBLE The goals of the Open Font License (OFL) are to stimulate +worldwide development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to provide +a free and open framework in which fonts may be shared and improved in +partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. +The fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + + + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. +This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components +as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting ? in part or in whole ? +any of the components of the Original Version, by changing formats or +by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer +or other person who contributed to the Font Software. + + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components,in + Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under + this license does not apply to any document created using the Font + Software. + + + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + + + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER +DEALINGS IN THE FONT SOFTWARE. + diff --git a/licenses/Public_Domain.txt b/licenses/Public_Domain.txt new file mode 100644 index 000000000..171ffd34f --- /dev/null +++ b/licenses/Public_Domain.txt @@ -0,0 +1 @@ +This software is in the public domain. diff --git a/licenses/Radeon_rlc.txt b/licenses/Radeon_rlc.txt new file mode 100644 index 000000000..4ece3404c --- /dev/null +++ b/licenses/Radeon_rlc.txt @@ -0,0 +1,51 @@ +Copyright (C) 2009, 2010 Advanced Micro Devices, Inc. All rights reserved. + +REDISTRIBUTION: Permission is hereby granted, free of any license fees, +to any person obtaining a copy of this microcode (the "Software"), to +install, reproduce, copy and distribute copies, in binary form only, of +the Software and to permit persons to whom the Software is provided to +do the same, provided that the following conditions are met: + +No reverse engineering, decompilation, or disassembly of this Software +is permitted. + +Redistributions must reproduce the above copyright notice, this +permission notice, and the following disclaimers and notices in the +Software documentation and/or other materials provided with the +Software. + +DISCLAIMER: THE USE OF THE SOFTWARE IS AT YOUR SOLE RISK. THE SOFTWARE +IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND AND COPYRIGHT +HOLDER AND ITS LICENSORS EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS AND +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +COPYRIGHT HOLDER AND ITS LICENSORS DO NOT WARRANT THAT THE SOFTWARE WILL +MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF THE SOFTWARE WILL BE +UNINTERRUPTED OR ERROR-FREE. THE ENTIRE RISK ASSOCIATED WITH THE USE OF +THE SOFTWARE IS ASSUMED BY YOU. FURTHERMORE, COPYRIGHT HOLDER AND ITS +LICENSORS DO NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE +OR THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +ACCURACY, RELIABILITY, CURRENTNESS, OR OTHERWISE. + +DISCLAIMER: UNDER NO CIRCUMSTANCES INCLUDING NEGLIGENCE, SHALL COPYRIGHT +HOLDER AND ITS LICENSORS OR ITS DIRECTORS, OFFICERS, EMPLOYEES OR AGENTS +("AUTHORIZED REPRESENTATIVES") BE LIABLE FOR ANY INCIDENTAL, INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES (INCLUDING DAMAGES FOR LOSS OF BUSINESS +PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, AND THE +LIKE) ARISING OUT OF THE USE, MISUSE OR INABILITY TO USE THE SOFTWARE, +BREACH OR DEFAULT, INCLUDING THOSE ARISING FROM INFRINGEMENT OR ALLEGED +INFRINGEMENT OF ANY PATENT, TRADEMARK, COPYRIGHT OR OTHER INTELLECTUAL +PROPERTY RIGHT EVEN IF COPYRIGHT HOLDER AND ITS AUTHORIZED +REPRESENTATIVES HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN +NO EVENT SHALL COPYRIGHT HOLDER OR ITS AUTHORIZED REPRESENTATIVES TOTAL +LIABILITY FOR ALL DAMAGES, LOSSES, AND CAUSES OF ACTION (WHETHER IN +CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE) EXCEED THE AMOUNT OF +US$10. + +Notice: The Software is subject to United States export laws and +regulations. You agree to comply with all domestic and international +export laws and regulations that apply to the Software, including but +not limited to the Export Administration Regulations administered by the +U.S. Department of Commerce and International Traffic in Arm Regulations +administered by the U.S. Department of State. These laws include +restrictions on destinations, end users and end use. diff --git a/metadata/RG351P/packages.cfg b/metadata/RG351P/packages.cfg new file mode 100644 index 000000000..7a8125f0a --- /dev/null +++ b/metadata/RG351P/packages.cfg @@ -0,0 +1,11 @@ +cavestory|https://github.com/351ELEC/packages/releases/download/1.0/cavestory.zip|39d890ed0b387b67c019fa3fa812f177cba239c3089b898c772758c3a31633f1 +drastic|https://github.com/351ELEC/packages/releases/download/1.0/drastic.zip|341328e3a09d5ce118f3123f56d37a37048020af259a451047bd0a9fb5cb1971 +blockattack|https://github.com/Cebion/packages/releases/download/1.1/blockattack.zip|5d1e5e702181d596c6024fd83109015b172fa6634be3313dd6b3eaccf213a08d +iortcw|https://github.com/Cebion/packages/releases/download/1.2/iortcw.zip|e2a057fd2d9c18ed66f840124586e20be597e4ff9a16af9438f2bca3e817acf4 +uqm|https://github.com/Cebion/packages/releases/download/1.3/uqm.zip|a428498d6b25e62a87e47ea1b61d0da5385946111c7d7e370d60baab62150ebb +supertux|https://github.com/xargonwan/packages-351elec/releases/download/1.0.0/supertux-installer.zip|b7100761cd4308852ada8eb9a5047d04a756da7f3d24abd629690c651b7d9018 +cdogs-sdl|https://github.com/Cebion/packages/releases/download/1.4/cdogs-sdl.zip|4bb23b56fcef060db98eb2e7e4bc560da23eff4735df15a56659d9cd3f305b11 +openomf|https://github.com/Cebion/packages/releases/download/1.5/openomf.zip|f165f670c260cccf5f0b649db689f1f0f8b248ae501ecc12ad1f30fdf7d5d90a +tyrian|https://github.com/351ELEC/packages/releases/download/1.0/tyrian.zip|383bafdd443ec25defcdb8bd7ba0b4a6774cea5e8899508eed0ea864f8f10c59 +f2bgl|https://github.com/Cebion/packages/releases/download/1.6/f2bgl.zip|06d653714f36a458679a360a4a236e91ae2e2048a2b0b71c7f19d531bf5eee61 +smw|https://github.com/Cebion/packages/releases/download/1.7/smw.zip|ebec986b4da1b774c823b0a0271e9003e2ebf52f8f39740a7f803089efafedd3 diff --git a/metadata/RG351P/packages/blockattack.jpg b/metadata/RG351P/packages/blockattack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..687926063dcd6a9d1c4ef7ffa01036db9b924b12 GIT binary patch literal 36399 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

    {o7L}A}9<gD*;Q2K8!}zWMfXEx=;_0V{_VY&j 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 BnJfSR literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/cavestory.jpg b/metadata/RG351P/packages/cavestory.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7f9c8d261f18c0e5c3764497712be4574754abec GIT binary patch literal 33462 zcmeFZ2UrwK(=a+qmK+5X$w82?k=;ckEm@L8N#e4B%o3JhKro>qS+WW$Swti!5hJL8 zNS34`3KB&LDhS+JFrD|D_j}L%?)TsSzt24bJ5ya%U0vN>9j3ac*I%rUa1-@HJ;(rH zY6>U-0KfvULjZstgdhMByg`10={8^*Efd1@9Zv`H@P3EEh!BDAFvtbj1~6{O0e~FH z_Mh+#$j;y5!T?YLAPN2|An*;CAB20)cmNFF<4%K;q(QxCf2`jk06>oW$5Wd~aV3dc zxKpToTD!_=T~H7G_LhE;<@)!-OVEWi*C0L-)} z6pnyh`H@FZ|0{Gq(zvmAU@GF0i!@uW`4)Q|=P`dxsB z1vCvJJwy_qkP+{6d4?yS`7@3$^wy?56{*?#;=;(hC zxd8|Rgr1Ipj**#(g^`{e0TOxW86!KzGclqzRFHu2GJqQROY$+o zk0= z`T)RAzmX;npb5-dCmNZR5)+MNdfY!NJD;ORYisxfMUTtkm5mwo&n{lb@@e-qlsI12PabxA zqy}r*dG1KEH+KG0TA2tTnQvt1qu=4i@jFnBf`cJt>%g++SH|{5jr4G{#;%GZJCuuu zTBIv;Up-wa$=k}@d-KxE;C5_I0**h%Qzagjc`JwIU ztRlCPKk8fZUI)Cm=B`x_Ad=6`Sri|0`FNn{>Z;SEnA<|2*D+yYjUYh0us{u&E#9ti zW4QE{+pV|GUy~}Y2#O6SE)ph-s|KG>mi5&&rw*`P+Itx?JTwvTUd=~UQ$7WG#LMqx z=$I|}Xc!|%t0}b(arO5BwH>%p z`A_!BhX~7e_Z*cx7~Xc6ybeSkJ%hwH>`ckzx}mv{82-&apz%}AIxzTZ`5bOauE$$B z?s=eE%ATq_t;V0rs%Ku99Orz|w7c%@v0HD6)VThY{mrZOJn3dbW~bMIjN$sQf~@eG zZ(AQ8g*)oId>L(Bj6J=g7Www@%aTI!i@_>s!TH)23FpZM+%DBmQzIEH#iypZrTo0k zH#|+Ojyr$Kf4g!x++U<@$rTT|!aTpIm`J_wLTtTbel2Y_W2kh+tVp>@yqcuU5j;;< z?F*Z6zGKiG8|hwIGhLdRQe!>t@aFlKCF~oG*mvW1?=b}TQ1>9FN~|AMHILV>YR7rQ zV*SW{W;4r(6?wPjr0&wkQ7_T9y)EpK(OU#MKL-XJ7PM(@E$6A}eXCKumAT6%*6Z;H zm-3-1HLfoWQ#-u2wk8B&L@!5X+a4^d-vTLl*}EK$dsP|o>dknuP2bvJ;Kwk*5w%i# zl~>s+jGtbnE*easdu|ln zd^jm2e&^PpqF-QtnO;_ATk&9}?XxLO`{mfZYbEc-T#_FgyY2EhlRm!lfCaR8%#cPGZG35sB`$nq564m%x9O0gafKY6UZ;|f*f`epjbSyC-Vw=bx2nX=W%WhTL`qx`F> zlfmBQ{$9VjcbJCV@~h$Omg|6depl74rs_dQbZuX+#AJrd)1R`jy(?u&*4?ZK~J+WH4{Nef49|5}>fb2c@-=$rE*bb02^q;t$|=7dR( zyJDTFxP_$;14XNW@52x|(YT1_@?KTS%TKG@%iT1452S|l#zy*GjvhL^RDoSA?^fHd z{h7<{gTPp$vsy8Bd~4p_YLUin?8pF!JLm0? z757Xknf2RRD1~R@f{H~u$80}G7>vyp$9k4f_O@Jm;5>uck5VkXNjUXU@rc7aH23U% zxou@uRIVF4a97;=E}r^?+fmmV@VTmJ&rL#Dukd8eu^FLT zs(BT)BJ5T@kESeheS6mu7WwKWq0QWw_|na|x#jZ1p7NLoFU^K)rOBoOrFq%XmxGeJ-@Rxn zhI&yBqE4I3dYHvN3_i>*604~0|8+zSrNT9Z?OPDdj!7ImY*TVMXM32o<2|{drWBvx zw(CpGeVip79L_2lb+cZgJA(CM!&0KAC7zw=n+eHlAM3p!+FXIn;d#jddy7XUmkkU% zKCGNk3W?^an9Snz+;>&tV3_oyizAo-r&7cFy01QruDOh$12h`L_BS^@spgED4|Ia$ z)?%7OUWaS6PbS|B5-m^7N}N6`RDV7$S37V&8q=TcHXq_`HMK+f^#P8<9UdANbZhUT zDf1cO@@~`RpPfGo1Pd#p`Eo9)zjzlF&kJPM^s#R}UF(j?-3ip5IZ^ZB- ze7&oFk*#E8!BeaY;WTi)todzN;q1WkyXhWmb+we#lG3O|H7- zxsYl#ZQy|eOH8WuyKXVXhfubERL0phG9BRIb68w$Mla#l0Yi-sONEI1hDb+mu`?_C z4mVm)`qoXa1790bPvXuU8JPQEbkh9Fu_rh$0%1PICfwe;a^~g@_=+h0hSwA6%r^I8 zNmA7`K{WK~=+$#IPvy=`2k#L>KD+uT2Q_F;U=hvlRrz+cbseahSqC~a^DRynoB5$GLqb$wnZ zPgOkr==4&~zWrI?#gkpiPXiflTh-l%%ziM-_pyDn4%llQe_pQj>E^3d@kkRVhZr`^ z2WwKT0e2rrb2=S)=x-3qJC{0(R(nutA2sgeIK`Bu#j7prSnv6$NDS6Cs11+lBWpS--NpLkgJb%J>_vdHr=3NWb%NJMc zdH0@OVqGd*`|w6=y<6@}?lGTm>$>5~drq{DHH-^HO7upNBX|3Ih4s#SdrKL3HJZH+ zD7;^}z7D)hHu&a1e06S-Yf9F3cU#Ew!Q#Tvl!mmG7auk2#%|))0TJ_?jbFVeL+#&A z7>8L+R)u_NelnSv+N-|JeIl>=Lumi*#(NcqLmU?x3(Ah=;Hl9Xg^T4y3(INiz%54t zv|mFAu%!h{B5R%JJpL1*jPMbf=rt{rsZJWeY2~tytu=? z!eisU6=lyBtpkUx)`9bPuB*jaF2C#9xm5MJ&qr1~a;^UT1aiFY2<2R>Kif%{}aymu1&oU2AN_12b*+v z;*iq@O>Kkr4!m=NKiYdV0I>N5c=%GygQ$K%R4_<$KmZnjR4Z2s#e0Lp$d^hY`3CvW z2sD`X#CZqM!dx41tvo_$96BCUS{xdAQzj|E4DUm-*4u9lqBaxTj9?K!p^&Xe)F3}| zS5E>+WCtvO0DuDikpXeQ3LpVgAPDfIi2_*tesY7M4KX_2RNwC!vAYI&cvC%mH$;N; zEgRf8Q~SM}rLmhPf=&s%{mL=#Z#g#iqk2$$13|hVjT7fb_5G0vFq5tUKLeI-fu=tL zxBy?=uYfQ0SHQ&8JMbsP%#9lSGoa_=t@|?omg6tcIs`Ab?**}0N`R$-4i3}?bO`}~ zB~e_QNC|S)qP(UBH!gz!-#_7Wy#LIn6F{`K@uliZS$fmz_UEPJO%(qtyk(#_bpvk^ z>aAt@lbtn~M4(avbn#R?Ee9J)TDVyR{;&!fOk)P0G_?T}5_wb1za(o7dYt|$Su29~ zCf*`|pk+^!uyJt{0w{iV?j*2sK@0Wpb^B3#oHT+ZsFMzbN~QRCQ+(aNM`8a#p{ej2 zp5q7J(!-xCENni1byAIAoc)=ot? zIEDWhrk~#kZ`rtmH^_#Sg8n($#rnOGfanbk7B{elfC`xmQoO-C=tBc9$al=u^o*Yv z_y*nqy#L@qZD44Y{~fa-^9vXTXf12~FE9G{H1c1P*8iW-Hp+q~n$}SDj+Ti+i``&an5I^GnqJq%x3_l3p6{H1y zgS=^dC#_hRTq!}m#K3>)69`loNZS|!XbtJ7wSvfhv35Y`SF50@0$BbsdRmw%(A$GR z3bge$p*35`AJSpmpn+&!@W;FnFw*@kEoQd>N|4_lP)w8n4>ymWJ+ht^O}hC84wS)x z528{GNWP>1Je9PejrAeF9|H>OCNm8KvI0gvZsOqMe|7%pg95z&Ff45p{vR=>fo^{s zx|s0ZRBOE3AGkOPByVqPQYh6Z(9qh{%x~{DB(>L5Dh^4ZZ?X09VlEBn~>o z-9eZN{sK23KafN4KX8ZxIPgy#fCEqf24HD|H{ZQCeOt@`3z!i2zdo`}+MP=EQ&Um# z4OGU{_5~^vC_XBocs~`GGE@an*9`T;6TC=NaaR)P-Pt4gp}tX4+=IAB(hg+`HTA=h z+&v5r2av1|n^_YMdl9fiNlguL^-#4?A3q-w6)zs@IH+5|EsbM zq&aC+EJ=Zspa23%FPP*@mHHLklJqMVf0@`Hql4@}BNGWf6ZQjrTpPJ35>!auBp)!1 zK(JzAKlSwcu?h5Nls_c)le}RKKePku_OIE0m<^2)EG;!%3L%J=rjhQC`X^Ed9z?aD zV%1163>*oEl9aFn5=se;M8cJ@P&7#iM!;h6C^(cr#1MZ-Gx80j;(ZAunlwSGZ4x^O*7aUwyDObPJ8gSF}5gLfmTc>0mtB*lMa!Gz?7Cmb@e zu*T_nxRC-uK0S;+429E2!1Zx37)BeW4M*#!qP2B#C{?5`N=N(m*c)CsQwou^M-uTn z-Ux>SSF^|--XI|mTnQ34(!;63u&Sy`aAnv=j?{1gB+!`(uE&5Zv<E>&>qY{*K@~}r|8`ce1Ok$XL8FwQL?T>?j6@QYFbIOGk}6ac4#i;b1SlN+L(xBH z1*~JZ8Up(NN>&IIUz#KOSIzk01He^XDk&gvk0d#O;v@d6ZHQAT;&?wl(EX36RjEp_ zFY)`x^0UqS`!XYv0z7^*fZvn(se}0cWP<%7P^uM=~{$p0)t|(VH5$r;+s^Cb9#v&0)cmfHngeDSHNhnn;9D#xV zS6SKk4&eU~d;1R-Ml-@+Ciy>MZ~sFH{>MuCdn4Mvx3~W#m83$O5N-C_D*xJ{e;?{M z8?HXBF9@W9(-F15>b(E11=8Y!Q-%L9dBDO5Xjcr%Rf*(^K`0TiNLM8cmVgAu11vc9 zqe*y->&8$*leW1!`G0fpr*-W=J1sTZ5}yhF5ZLE^@9}l;Zom5eUwj)pv`sI2B>gA> z)Za(-4H8YxchYZT$6v;$4axr|{s!qk#Sc6bNG19F8wuZuG#MN9yO|x8UyA%8!@tl! z=1KMPO;jndWE*Vfn9!RV;sbkI6TG#Urh)z{X6YlD+A zgwCI1U@$0coW3d!g#>4A2yL{EjxI(=8-~iA@p?hb+pk?oHh!n`sWy%uV4Q<{f3jF7&sIG4gpwj z3WdNTvEcL>Pf#MjkqA6S6_12t$$wWCf<(X|Nvc>S6bgz|BB~-WO5jutrG!9`NJKC% zsu(Qs@5%y88!RkP3>r@+E4f0EXeA7sj8%f6iLO`zf{0c{|3%6FbsmvqaG)b&NJ^@3 z1W^eF11F4lBpIVbAmLH2csP_yM*Z#bLZMViu0%BWrlATW(AFi zxssHK2qX%8p~8YQV;Bs9K!P9Zfxo{ki{uJ*C4&=EC>o1ZLV)j3N>~&WoGQSOXc81d zB%u+1yX>*5t^^VsMgZUJzzP6oxHOdrFeQ{KN)>}~B_ZJ`*T1V5o`59a;c&7N2}Q&x zA&8)T;o-EhCzJ86t}p}%gZ$fi5y&KPivL9{NvglM$G`5j|Eho9;QYfPK9-KAt` zAuj$4|F<9>f?ojmIRnH3BWUvP*1cbXmSlTj@01z7Zg_FJlu6LdS zfU5T2^0Sp@FTX9}d5{Rov;zHk{YQqMoc|v9Ej?vgdOufJ#C12fUyIYMngDL64hj$t z1Xn>x;!6K&#Q*Jxzp3?`9*Ur+iWEQs{VL+Npp}6iyMWd0OZ1@m(ZxM{|F8!1n}q*n zwBIDqz)iab0lu6yfZs(K;BMy!=x16120k``-YFBLKz`Pn$rf91VHyDJ#Kt%69)v;q z#{CaBx;QXM7wECEr60gqT8k5c0)jVL7-$bh@QW8NfFBSBL;)#aC!ho_TBCv8fEJ(! z7z5^jHDC`M00`jHw-5MrSO{yaT3yIbaD`0lySshHyamAi@wahzw*G1P;MKG$48q6Nn|m9&!-k2JwXiL5@OB zLe4`HAsLXXkU~f)q!w}y@&wWW>4%I!CLo_6%XIW~>~#EeJLqKTROm2t+H`yAtm&NT z-01x24%3~Yi=|7WyGD0|u8Qs+T?<_g-D|ojx<&Bd8#el_^b+(+^cZ>^y*a%DJ()g$ z{uq4}eG2_G`kVB1^v(2L^snis>Ax~CG4L^nGbl0aW-w&1VIVO0GaO@xX2@VDV5nkv z$k4?w!Z63M#>l}a!nli3jnRm4KcgFC2xBB;3S%B)CF3K;9>#Z!OH52mTbbmT&`gF* z_Dr5kN0_3SE;E%d-DT=v8f98!W@Z*<-o?C!*_;{AOl6K_PG`Qs+{oO?{Eqnx3mc0V z3!Fut#ev0_bA6RdADVSm4{W1 zbq}jGt0(Jm)-=|etdCfSSm)W;*d*DoZ2QZ^gVh>`E zWzT27%ihmE&%wbV%b~^Lz(M7R^J;j^N`+#?pkDgD8564H~JIR;B_lWNuKNG(kzY)JD|9Spm{%8Di0=xo90b7Ak zfr|nS0?NEaTrE7jjbWR@wtd?|wq{@XC!x6u1IcZC&y0Bo&Gzo?d+CklE=t<$zPU#u0W@NQgBze zsL;NPZkOsVk6o8{btp0_VikQAuPOE^u`6jS1uGRPjVNzbHc>vIT&+B-BCX<}lAzM8 zvIa##y`eeKK^QO07z>5Pb>VhvCOqV4^XPv5Z(9Y&iBd_N$tz8da@K?Za-R-Cnz|?|!c? zr%qDOQ6JqSxd*@J>Ympc;u;4vu4ug0l+eU$UekP|C8b5w%F`Oxme=;wzM(y<1Jw!8 zsnq$5Q^SSf?&{L(8t6vpKGWmXv(d}Yd#Nv}@1|d*KWBh4IAU>%HoagvWF}+gYgTOzm>Zd2Fdw#%v+%d5 z-^aAiV&BDmW0o+>qn6E9d{!=2*R7VUb*$s82W@uR1lioT<+63MEwue?r)!sJ_jTm_S@_|>}wpD9c&%)92On*9Fra2IiZ{)oqC<+oI{X%_geS1^DgmW@j2*I>&xrw<@=B#N(rTO`0etG^n2~E=AZ08 z7qB-VFAx&w99To;2PadlK|6y^2aN=41YZpP5@H)t9?BEy8`^qE;n2B5%5K9CJN(KU^yORQS6HgNTCTtjE2Mx1E5VNIbD{((Yv4sU4>x zPK};6I9(LU85t1ScV_pQtg{SfJ+1P26z0@w`~KxaOwP&8sC_ zOU~Z{ZUx<%EInA-Tei3CemSQ6W`#_}rAofas47U+p{luR_v+U*_B9=~#FR<@zqDxax7t7=EL*F48Quj^3nxYMcGd9O>i ztEtbMfFMj;l8=9@me4j~ z9#9S)zzAUk4}D{01KC0OAjrcEfQPKH@M%l(Z{4yFFCYk>^(G~haMiLG!>ToRZ$vsN z+3f{Z=Y%dwRxTuU=VM`BVB?%NI)*JwTUfr!;b8zIco|{Zd`$Z!=kUk*x&6Vz;_ktv zn8iCr5CU7ZKI#M{26jm!PrSidSre0FEM4yts5#wlNi0H}=dMA(*c;b^Gekw8xxhjMXIaB~HM@ELQ_lEQY&wZxw5+ zcQe)qZtcFLoA|6&%cyu~tTrOLYOXAF{+MH8G#x4m|Dl{Kob9=BD}H*8I>zM*`Zcl4zQl-|<%&f_{+ zT=qd}L6Ni1&KzsEmYm6q=Ftm$+IhVS(hS7Jiyow-M<}rBaQj4?Nebj3Zj}lU*{6El zr~wM&!qs=hB%3b)N!+8+*72WeUt+$Nyi4wH*`}0f$N(PG7@;N3&9VuEgBHO8p#!ZP zh=`TSQA&|{T;`FLOU>TBTr$71d{Zd>+y1Znyx@z+!!2SnHK7phw@jiJMjf6;r0MG$ zX_z|SQN3jQW$}rJ=#Jz7NJgM`TAH&Ne>=ml9wLtW!z)?Au}a4yL0D7JxQ(FD*4-m z0Uf+nc?SpOibopEXqLqvvTl= z2huRa9f5gdyI@)2t4z+w6?ThSN=+Fhg#{9*{WSqfQBB42bj63Y(XXCJSFr?JBhD%mo%+N2mbD6_fNwFwP;C!@J$Qpve)F@}TsYSD0$k(FmRuSS?WZ+9!{wan$| zYf<8zdUt{4sBn3t4dLm(t?RLd z%Z*T;H~YUtD>8htu1xH|tH*n7e)R^v^hxFb-YesMoziZXM5C|JZE-24hkA?6d_rCJ zD&yXSsS1m$vj;Bv)3=)OG2}FHkkSvBZB0#T5PEpRx?m{rM%F&KjOTQ(A73xSAVVPK z!-d+LZ-u+UopYzI-5gDLi`O>NwkUh_*5UL$$+XKjH?x6#`~fGTsGS|wPOjF(Fq7BQ zZx;1Sl}fiK5^%ZBnh!5cUg~b~Epk57N}pzlG%7!AsG5|!D_lD9EN^#?+*5MDZj!W_ zd2n!=IJM6sarDvYiNayWr`3paxdqR~^R4BN&iKmIT)jJQT+ux)Ymz0eL~PEN$a9o` z!LaM3&FDRWZX5upiTNw8zi1k zV_kZz?R?AojtbS9s}jZ$2{@Cvv$=*=DJH0F)*FRkq@9ClDJ{}@xpyd5il3^V2?s@B zjFTP>S5J!=zP#-fdDVKi$F9>idraFc)9zhtk(F^e?sRQfy2`7XBk*kRZrhlC*cIm& zhMMVw_ILe!Xpk^03w z;jZ$hj_`P`T$*wVPm=o=6 zRA5W(@i$nW*m8QEp3L2>NxeLy!&-8^vd9{K&9}RRAm$d)>OF9ZaH>$}Z5~m;;4UVK zITkzhn8B4-M)kn3>BsJCj4c{hgPWOR*@uYb4ub9HcVi!`lm-J!7`m4+OL56dhMr$LbK78!?~dPu6rr zF5Na=df!_}aoJYA??RhSRy7WJVY`5U>Yg$tIQiHN+(p6pw%lVM_uF5toMO&uiKlGXZI$E4Bf<5fAr zob%~#tp>X?FzyStRTVBd2Xmjf^XU4~nzeW}xj>PJ0mABL@xgItWfXQR?7pQTE^i$_ z#wqub@TTv1I}_&xWBU)sp?NH;B-3p|?c_j~ecL}?a89@29d&N)Xl|OU&!OE1GPLU>bMN%my`*>#n}wAH9j$vgbgzSeJ=q_a_9CaY z<I=N!k<6t`{10L7pD+zSr%m--{fTlrcl(aP zn)~*yWbbvrd!?P=bclXv_D-uv<#6_g0-va*QQwP5)i|+fG^Jzp8hE5>)o`VmWY5(O z!DWeIMYZjngXK-GxLJJmS!)BzHDW5-%4J}Fm;KFc)boh@pib)V&B{NHr+_H>&(P-@D9to zjJhkf>2@E~{Xe8UV{AQ4NT#ZtP6uD=1nmY)P2YKD%n1mO!k*T&yv~z9;gKA!Irf08 zeml$tx$GY}SZ=c2vvR_?fKgZ`gMD(yp02)lTT#{x0$Q5BWi-!426kwu%i-}#g&-57 z#0&A5QA^Kj5y`G?4!l^NvjhDP9`BEQRv{)}B<51hY>Enam}tJ!fKy(dEyV=E5GWG1 zzq@}t8J4og1(LTrA~>q`NYcY=Lwea(s+HGcb1jdfx-$<6LRJ$}Y6jG(a*x<0o-cm`gCi)IYxH>q{+f`Z%r1eOY3QVpXXpSuuyt%3MBor-G1( zVN9(vU1Lu`%c@H(dtuEm6H_g9wekHon0xSW)6A(`Ol?xgU;&b-ac45amw<=<(DS+(ZBlDo@fwb5P^iy2LZL8piBclI4I;yzPrIhPihEg>Ej zuVuj^-QAUr86*yu6u%p&>!^6baU;y&RONo%y&m&JMf1(^A-b>VPIFy1=xRrN?!J^m`8=tR!UGmgvAE`6!N$h9J zGOt^ZQbc#3e=n7B;&_ghX<(tSSkm%DJ8K7A?bh{MD9fYRHE(d%H(<|`^z`YfjE%Dc zn?e>s*_cDUTQ;d6@|o!eU$SK}lI2;VA}MM2&d2#ystm-O-rJ=WF}cK*RfqFN(h(DS zQsx$kwWV?iOYBzc+bVXpBtuy5MsczBsrkKuk$eWZ2d6*t?7glZiQI@w&ru&+P z0fuElrpOajR#Uq^4mK;RxT*;1kI1Z=6 zJpaZ|y1F>3Sw5xiR~pZ75;379yv(T__PF{ixUB&f#jy5~_j(2()cl!y= zPWi<7g{15#8|lwLpVQ)rN7g?_ryWnBs;eUnuZ`(jbMzFlXcb&x*4)MZg}q5sdE&U@ z2SU;*M|WvbXhq4TBz9EF^>{<1jclz5#}wgGTUEu)x>wdd1+ea1dry|DEIDIf=|t-> zW`3>F=2x(hGRo7VJ9YCYAe(XB%Xrky{8+|I$Gz^?WaV?aV9^|wPpk^+J7XS5#nlWb zK2+1ncNnW>^+d_F4w-VPyUg}Qu+^t>zUIBleKvh->j`d=iF9=hx)3H=U+a?ROmGhK z^Uq)JP_#xFew3^bI}kej;ccYBaK@69NJPgz6rIf?H==O#;}=)o?CLZD=^ZG`o!V?# z+KX{yDdoE;K%jU}4!ucXx{&ssoG5$GoMM3su)@6-w+i0ye{sFP*7^Eeah?(W3dE)( z`6PVK|J}2S(KB)WJ)$#29x|D2TfNZ@$tK}SteWsS2|anIeYw%1$nN~Udu9+gr%;K7 zYlC)V@tp`vqQU$76>c`>XGJwpN6j=JR4+8@OWzs}PR?w*xX;e>X6}k~muV>L_+`w& zgxgBtg_P{V^Y)*&cc9M7Ik5Bxu@X^R<>Evfi*DF%k5+Jv(q~+_a_}CtTY#ZF@T#Ii za=Ylv5uUyA3OG@mWLQNBd(nA3L29j4k@3C-{P9V9fo{%3Hap7+DJW-X?UDWnCi8k> z`7LHd;Mi>vyleE^xbV};FB6Mz8c4b7;pX}6Ct{->X37{mIiqC2oItOVQe)3^B0kje z%C|3{T5#O8*c2|msP)#`EWBtlGWG7eE!L}_iLAqRfHQXygn*5B9@}LGn`@b z<%%|r-_3)(frcH+JTv-W`iRxti$T}){14A4=yvoAk4D-{br*Lh+bk-2=H+EtLWF7r zFMk;N7_S9!cof5O({0!zEt@q!iqH7+%Ft!$T?O^~3k4nnrey^!XSNcSw6XXzAC{KQ z7gvIgxr8i<(Ob9&G++Eke~bmQx-=X=_G;v-f8J4eyWoz>x^{-Dz^TlR>`eK~)61RB zY|mUj<+K*C>GLxxrO`tSTaUn|O1j=0^IomVqn4D!<*N~T=B%IZ6ghPCw)!#L$O#Kx zY^FwLrqEy`?~Uo)9iz3|2X~z_X(d1(_(h@&;TCtrWgZ!JYNH6pZLr+HTdW1wSad`l zPBEhC!I!<15awCc5fak~(v*R0+fdz*q%-Az;W~u3Fg7PFTf1Q7ys<%~mQ9h#duG<| z(2sYELSv79S#^1IYUf_gqwOe>B4aCM{p2gm^oDP+-x}?nII)VEcYRucUC&ZIpdO}S zQreUz(6lsMk+?SeJ~nl)xov~)&G<*!YN#<&OjLISDXXF0b8Ld+=|pX9vef?8OH$Oc zdu((P4ZCYIGP((K>wwpcaMjxEhgx*QBTDe&64}a{vdRnA9WF)^@zBEs-QW>-x4Dq-yW%IHnFsIOYWSa=$LLU2(b4PRZ5DE=|CQSrYN-%i+0t z-w|^4eIu#(^B1Kr^CUs?B()hmxzf60Oh;qZ9(a~Uwfj2mk~JKOk&N4S9Cty)oxjx8 zI=Rz1X8&`7`)u3wPQF{-X!8#@X9X@4dr=cu5|S!%8V5Uc8p$_yonPypnH?IWjMvqA zRUPR-K-sU!=(2n)umo}t&-8`SFJA0EF4iBdFZ^ zCqkDBnIBKeAP*`m0B=KIpCbV$G*h)Rop$PJ&*iIlCsy80Wzw}~6IOm#2FQrQ9~LO^ zR}s5eyZC&!o-z%igX}4L;&?GQ<0>I#$gEwMW%>Pxk@)!aij=94NOHNeG2L^hv$sy7 zm&wJ5mNY4~ySX$;DJx>0C9JjdyE`8b}ZF`j z;MTcRa5ZqrwX)?w&jP{7q(BdNd;d%tzvQL)CDwtMNS3Pl!7jBCs~TU25<#9(FOnX2eg((CY>fM?8+Rie#-YcIWW8o*v4p@1%FszwDY; zZp>ST=eJ5;O30nfWhr*JGvKxkyilI_rZId|xxTUXfV`4qRdqy*_xr01#^hjo_vk<# zedNg-?oC+_V`6;=KI}}F3aSeoPn;}$cwo6y;R=`9Go;OlvIbO#nfO4k=vaN_03mh1 zv#~Yb!|MXlUJ637(g_Y-g7ul7KAF~-%jPEx2ko^m?`KQ6^2YGBUs-Ei(K`X;r}6l= z1_fdicB=lXloWBhlRPH1eW$}J9?qNk+6uM>j;6m3^%oOsi*lQ2nat<1vVv19soCy}VT5;fYpXn}h_G5e> zT+UvUNph4Kr|uujJ709D*R}kS)Gqz#w-2tG<&&Q4*<}XjnI5sLc^rQC0UfeI-+p`H zXS}-rU2~@KG?UGvOIfD{11a12QwGK^_}?zCPT3uqVbu{MJSr=FKJRI_205MsDJAH9 z`DK;=y&-NKpPHU@pgu$CnX|&#uE`_?v!k4-HW8KU$u|={-Y^D^e+p$cWSvy>N~1Ry z6~55ktU_i}Z}s%Ldo(lMj(f1#dFM`e{<(HdzLrS&d`(X3msP~Ob761p+mH4d3}1Ot z5s8$E&~&FWIR3_T%Ly;GWWUNzs%M^kyu+nt`mAb}I1<%SbJ6uwp+)lt4C~zZWlmMj zp}`w(s|QDC>c;{V^l*yMoifDkg&u1K_c~AQ7Inuq-{rh+voLhmK3tcrPC+-|Dco5h zp7Ewvwrlpi&Q}A*Vt!sDb@-Tl8ULf!L8e8wa1r=z_)0~`5S1La7;l1yQ}eVuI~sOa zpRnfjxIKNbf=%Z1;-#w2vVFt}^X&!_vCcBdr+g=)HSVDR%e1nFTSGIF)5WtM>wuf? zXZFwga@bgQ?KVs(5z)-Wv~42A2nV80|3jgE}AZndg)QX7pOwX-gYV0(eUd0lmGoF(claDPGW*fLB1F;R zwqz(fX_*fwZ(=BYdYo(_@We9IPk+P8V=1BF7V8dX<47gFndO=2iI za{`f5%F_+YOOnx#kEl}G-8I)&cjNQR?i3?@?CkR=G8KthtJu_n$Gn{~kFDXkeY1l9nD7*W*FpU%;7u6{)Np`mX*sBBlG^tut3sL ziH6!kJ9_QKO%3hoESTU#`F&#|XB21M?%a<2rmherUF9IbQE-bxI?71c&QL>9e}8S` zAlfC652hrhtETL!6|I=SKzGW5-og+0+3cW&?Le*nvsAi9m6oWr#jG#kt4+d=b(8t4 zgMBVbaXb?b*dNsGe0U&xdMM{`O}oa8|Nkn^D9jl@Pv zJMIUE6V4=m>x5c3-)=Q(4)EUd;LE-G*-jT6FV6qSp6U4)Nj|0~(F+D<7(~FLL>{=dXKsgINgYp(VexUDQ{1VeDH^No zAuFMG-SYkBxp^KRG0sD$O!1$;?&+StZ%za6$c{09&M}VeLHhUr&IB=m400a4umR8Xaimo8fVD$- z{!3H;0L=p42{NTn(1TU61b^d6S4wHs8ij<+`+gfI1^qnxy}}T+?+3h~)f&QShPIYn zZ6~TVZT8%?q3u~|dD(li(w7OiB$+w<9m{5GA`1yhn_{R^h>7?LM)#-Ne12XJ@wtYs zERYcMCy;j|K8Q1mBW4z4PKlO_T}LEWxaAN?!Xg;};!JhD!dGeEejKA!*HIMK5t4Sv zLpVUA7}5LNdTkmglL1-4nC1ZOL_?V1IJ7}GaUp4`)@-***2&UgJlee&-)}}Fja}Qh zm+8VxxeF~J+&7|NL=W&7HdyS+y33>SdBC z7@(n1D1nC}03*ytEhOT;pUw+rf(u#fpT)#RBO>`cvxS4Dmn z36i`zMqnuVewsNE6M=*S9Au-+1E}-B@*Y4T?f(ELAF?_B0ISm(>(j5_(}B(h1Iv~@ z;p8LJ91cSq{@@S}eMcZ1`@c^<2bVI3E@7OTB_3aBltemo;IlNlWxB0q6dbb)6>36G zw>;gfn|AGFV_MF@IggSobJ8X0s*o$#p#(s{KFxn&w%MmGwk7X-fxF4O9Nd+beMYg@ zcWm0WdnqXHLQKt@q(DUiD5q`{_eYq3)@*DLY%vuZ10}2ruIVPKws;7`=nnk2LI-3dLEshj1QZd4C0e+3}VN(wl}8Yr)Qqinmv<)a-1f$nv8p8(?ZK z9(*wOokfb8X0>z*T&@~V%r@A{qeOq4lmnwrSUscsvjva#%HvR{h5eH@SA(asiB z&XNTTWdOt;!}jBgyneZ?U*PsK)v5MWS<5Eox5-vwE=xwdMzbwqjz%rQ@8MWXf-5;l zgvy8z#lYu0T(rb~mfIUzZl7j~yZIh;aST#Rm%j-v4`^yOJwXAj=o2ZKYUVUp!L=u!W%)MD*vx5ZO7<+~L z7fG0*>4tV~*G+kg;G0L54QkT2bGFOG-Y?Xa)aLTBw^xdSwu(DQSYV4@B!_nF#wZaY zo485>VGAeIZ*%z{;w4X1`3WgGtWD&*{a+QXd~vnH*CI`P`Oc}l+p~?A7tCeIN9mcwtmjJeCs!{Y4>f7FRp3Ti&e6VD>8N5H>Fvc*OGA* zl0Zh~YM~S%OWlqyTR%lOm#6F--2nRb#D({K%iKXq%C;!Ga3+)$v{{*(g(TuoQ8z{J zFs3IcU=Cp&ndA1z2Npe1x+>y0Vn_m57l8$#4rNbLhqwlQe!wT7V{&Q?n2GMsVUrlh#BI;U5$ zMGinjaZk2h_FkZq)ke5PwXwR1F5izN{49KuF0D{?>oc8jj7kOu>SU!g0^2Vh8Vgi`|aiI*xmO z&%35ObHioPIg(Yf&D^4)1Ur*mvdK9?Qjci!Npy-}e^A&`rQ4p z0+N+V#1l-Uomx?M8%ca;>%5IYRziu0m=LR&`7nWTbEhC7NNHI+0Q8z_Yjx+8FdCpm8HH0MWv5=RUcB7@GmvsH%{w77( z0;<1IJGAb9BHo{`$l%yBYiAf^N`4ztw$HE(N=)lWpX(|ZAWcZgc08jh}p*R^O6dl^lv zwX)06BR4-44telBnBhwSfn7)~u zE?~e8Kn=>_a@q_hb~&W&mPs9ajJ)I|goq+YhPO_yS z8}8yuS4C;C`w3bNhPo=pl>_IR_Oz<)f$M-ZFriJk_gB z%3bf3y+O8|60v2gLnpNBRH^tR?djH1w669$;=NFA?J@{tf^^R%q?l4QuZ@VvTI+Kz zc9)JD6Le5^Yh>UYi<8$wB|7$_M{e<*QUz3_BjW*_8)xoayhWjtk1B!+DslA`H#}n8QZh~UNj9QcZLRC1Hoi^_@)fmy^R{WieS!l0=V^$d2S>W}~rj_}5F#57aFv|h6k zLZG8&aV+vx!FWPKDfH( zN5~Okf{7eTVw>5HCu_3o%B*dg7GA$A=@k?osTnmM<|06ip9)8C&DgMbpd_&ey(5Si zy)nae>gk#Oyt&9t1rjByle6|XNT>#IWpGPd)goK8RpXaZW-?|$MT>$COc)G+eg!+& zA(Dv0NdZTY_XbSR2a&$qaG;X8VNkxBUhyEMOjBf>@F35g1U}!#vm5jgflhN@L~c4v72X(jmPwlhP3>41IgMd|BCAg4g8Lqhm(KZp-B|R(8W?nbp;e zV?7I5V>2A$O}q;jh}mYbi4|lUq~yyHAQKp(sE8c5M&6jYej_J-nUOMyK@Locph7C14ROy8i$t9^=vgh;|soZcr0|k8pR1RRbHD zhpu{$4qLFCEK}2zzYiiT{ZVY8PDMM2m^lIuc}gW5^T6@w#K+ETnsm`5C8wdG+p&da z;>hhK7$*63+>%LU9WiX#CCmiuAd~;JT%0=tua*|T1K7%aU5M)Cv)^w9KhzIzRoD0jh+rY^!OSCN7K}6rg zsG?2GlCdt^q`Ng+iCl=86%sZ;N0tYt0sjDktmPho`?7x4Ktq{amnFdCJvbA5muSEj z*h1t-IS>pv$nxd-xX;NpjOY3R)4QgABRxHxc-b1_q4X=0`hi&!xX9S0Hf3dJn*wWJ zM_Q|~u<#X^>BabowjRZ^Z0@}2>oHP6sTNgLy(EYwF~;X>+P~fV@?*+~i!~xDsTEY% zI=gB#kE}{Z%^FdALj^3JBW!lZkbKa76u_Hi$^v2UEO7TY*}g%O=l9q_TFL6u?qZxA&!Jua;lgnG&jJ=l0IQhI> z90U#N@o*LW57G51b8= z$e5`&)*Iyn%3~M|b9N=6$WbxO84>$xJanz(jGL-gFIqSB z)i?5K70Ms-;{7-P5PwIQ(o|V>qCp*_yW7zDGC~Fc-n$_qrN~;qZ)}gxZ zvJxMPIaO4gq`Yz2iy>G}awrLRe|S&KzZ|F(YZ?4q+go0v<3YuPWvP@ZU3MpI-mI0a za%OGXEfZC-SfCq4k;5fJx&k%2O;rR{RO^_)J}nRg!XQHFIYB7^M<7y(@8>v_y#pd6 z_KyVcyUc2jk2hT}v~;%FUQRB*tJj8D?`zPl5vkOg$Uq&_(PG~0OT9pk;5%LzS^Ar~XB{%((n+fQ|#xvXvI zdh>{zG%S2XTt>vK$hJIkDSAwuq_RZqDL{qum-wGkRDbdIiK;9b{{Zsph~lM*8>i;i z;|81fn*`tDNSEZMUWr4}0)F#7-ND=YelCCPoR{_ckK#o4)ybQI8EjXSGSQ zWf^I5_KAJhcKX~;;-`y?TH^rP#==TIIM0F1$|iDDNMD0Fj;JB#hmC3=3LFtpYNpUZ zRT2XTCUsFHQ-UI)$$>FJLxD$-7*JXyl#&gDgI2|{BioAXv%DBDUE@y z?e2Ay#?EmZ(ZUp+jP=z_W8EP}+eA%RJAoqzfJ03vFA+rqm5oJ9#0&0PIKj2mje< CC+q?M literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/cdogs-sdl.jpg b/metadata/RG351P/packages/cdogs-sdl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa39c7047644dacaa749bc2858345ed097b29b8b GIT binary patch literal 23233 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/drastic.jpg b/metadata/RG351P/packages/drastic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a152fd163dca4ec1052c6756afa6a652017ee6d5 GIT binary patch literal 27778 zcmeIb2V4`&*D$;Zy>|qq7XdMlgd`*s>Am-&fFTJ*LNSCQ3RqE5=|x0E1QZoPQ9x`c zRY63Mq7+d;P*4z*Uh-{%?f&n5o_oLNd*AQ({(kRWvb$%_IdkUB%$eEQGqVHj7402w zib-^!9{||c09yb6ULfLqQ(F?=Tn z7KR)ED1>bK370^We~XI%KnZ{xc;1E}8L%)2cOMM|n7_yU1WHl>^`ifAuIvW@CH^0G z17fHzNya`Plo}cy5E>?9WF&)xBXBaxZh;}h(5P?~00~DTwBSfBI93LM(?TG%kT_5* zz?=dAZ1g)Ese!ogBafi|7ob1WC0=0q1=Aye2P=f>yY8&N=MO^pl|M+#@A-p5e#n3v zg#MJx1IA_?=HL}f6=2+HuV|kEZbqJbjBEf1Z4%&RgaG1xIv=eMI1F&Jv$J!sb8~QT z3vh9A35f7b^35f}CGmh`K^}v5#Av|1MJiI*oyuAFvyu7@^^b4=>dK7_w zB7pV?5MT#QgUAGt1E2yBCIJX-0L&yCtsbHWYRLj&9H7GVg9(5@nORub*f}`4Apc2( z08pkMM1BCm3}J#YLs{5Z*;$ylH9(>O6SJ%!g2liAFC@470FqTWHUFleyn=}1V_yvv zHMG zt*D}*>;0^&Ut~horOL+c(K$^sH~*-k*_W%DddB7j04NmHmYJaw8!HQ%p@J+zkQvlq zx110Q@<6IEU4zGt?O!w$eBV(HrWrYj5W-Q@imY@6*fyhUJ3u80HV{o*FjUgePZj=a z4U~SVKWf#~mb0e5>U~u_N&|H6PE9$`fMC9rG@q|6rE9a&b1!JXQ^hI&RT@yMH-D7|n9WF! z#*YzcKuwh1=rz5`?KRJ6z_T<^vkDr}UlpH219D0bvoA|E`lk#&hZH5;Nqtvc+TYdZ zw6pTeXQqIPQ*mzyVZ6x=OwatKFE5xaY}Vr$v3<2Ja*yq`_Q{WrD`U=ISJyTgVvo|^ z(REI#fja0(14dG5fJEDq_sz&B?fuc$?pGRNcU0Z2;v3pm0{2JMvmZZ}%`@ObEZ^s7 zBd1iAXc?vFMtiZPq9gvjj?Y5(nv2V?N_zct#%j4}XiwgIW{?$zF|X(MPPhuS&8&KYukgo zMTMHto^HP7L;i2tR?^a%!s=@GZa^!7wTyXqBffvrwz>Ebuy}HP-1R1T^7iV@Sh!D$ zfGjW?U@!=MpvSc&s<~nlKg+X2X{BfB5e?W`8y*!{{d{M@`AO~USQEdJn5&y@A}S6i zaReDrt#dXa3Cvzc)hFCmGW3RX7A2}hdSZ9cfV874;d=5ta-}nQt+7@IrjzI076jY^ zKBZAJv(dEnEt!~yxgHUI(%TQ6*;kwRa_Qd7YvYo}$kEA*mvXm;5*ABB7hC)&0>_cB zc)XQZaU(741T@Y(EN@_~Y5~?hTO)p*^;3{$6#9;6+uVbv@oiiAmXo92baiV;CH9JY z1ryA8g7mpGu0>2{c92Opp76=&e%0#->M?}y%R!#Eus4M+X{>2wUIr$A^{S={ z-;-L(iO}}(I>k%a|Kgxx5p*}tbl!9a;;Vm%pWcFV{M31_l8E8X)4f~DI`WhH4Ul8n zU!&qCyRsfIl~Kv$Pn%Bc3TP&9UAcKt@(xccIk~WBRb(vFV;m(d5}tKdapV4XrMY)% zgdU#}kDh7kAKqxqE1mr<+N1ECqIO;=tz*llZI^vx+(k*)z2(w8Yu9uO*7Az)%vC%O z3o@>*XHC|);GKTtWWTlL?%W1zo;*ReJ2W7$#q8WUeY5%GcN=mSq@=daG)Fc_>eZx! zb~j{uzh`2zUGLq|?M?01YqM5VH`%S~PPBgt&)t5uaWdQh7J8h?v`jg=X78zr2bI}E zgdIIl3EQ#fdH0Kl$G?f&?nhW`>xrAFY1Qk``hG9Odnhb>Etk>&6xg|K{|Q-o#ISXK z%Ja$ZtowGef86eoBv^eH=1Q4@Y9aRWOHPg=5 zpK8Qs_dJOC%6t9jvR=vip#$7}>Lu}VZ5^5`1AQAVmugImO0`UD9WqT~J;8T+Rncb& zt(Td{Yq|P)?$2S)!{UN_OjwgN+o||A&_KfUzJ#tCUYsgJ-#5Cuj|TMA%yK?Bv+tqjW}?75 z_2nM6)VgUYXG_FmaZ}UQ7AYDq{IHD%XvdYt_m8iQ#g91BfOCUxdXo|H;Waa=4SHim z@$+mnfQ1Hhs>HWh(tt^}H7*)Z>?|QsvsgD5{{c1?KP0_yUT?T*ZFR0@v2QkfZOm<6 zn+C{buY6vrrUBvCme0|ERBu(Vfq>^7=>^TTe5!IpKA-`|;)eog zK(h4md@tCvLc7|Q&-wIEtt9$1Pjke6M$&u16~Oq&mU{9Gs)Tu5HqoV+ki1G$0dmko#)m!}hQ>)#xZ*J0n07kW(gS0dndcQ-zjh}L#X&b`HD#yN&Kjtu7 zx3)U2`zHI075EIw3;t0?79PvbrQfV5jK*JF9Q^7PA1}SSOzRx2Y4F|#cEO(J)tP;< z(LEkVylz(XRQX?STamu{esBq_Q6CzxB}Q*meRbU1Zq{v65pmY9>grfc(Thgh=jM{S zBL^|)(xbs%gZZ;|V0sVpX+Wq4SVI;z+{vY};YG0_d$-+w>*T82S+zl%Gt0)dFuOX( zc`A0TfChjDknjIdd`bG!ZMBbiu5tNJ@!dK>9-X0W%&|U2Z{9Y)c`?>MyttNk+YLvB!6L&S{PP3T5m(~2m4(p1+_CiGdId6SpN&8d3>70=hALOx&h*&b77*Shpz z)_;@eTwk0hEb~3w`esvmZ;$z!QJPcls$*4|*R1LJqS<(9KD}$BB=5;$VH7jO97fyu4@y;XWa@e#WRox|2jk}}j= zmRi!=Z^6Qk+*z0kXGS%IL^dv0p{cJV3FCQP6I;g#6Sn?t5iUBKtUV7KUyZQ`MdI$o zWlt$wRvmX+s2`u71&*7Il zwGvd8#?m{%r-T##tmX)&aV;Y5UMXMb>@^F!8?z_$8hK(ZN2wvXFJT{B^$&b=wxr9?hq!UmwtemRO(79=UlZzyAJkSLlbyfr!>`@m5o1p&x}J za<>)DhFp%f2b;%h?D^`zZz_BHw&Sn+-@K=nUhP<~=d@(!{ZZGktR!nz$zg9_z|-B~ zL07&JLvCAX#_RN|uJu|{AC|0!S4~KFOO&4Ij0q9CvAd!2#U_t_UhSs*n$FmYd&?rO zx8Q5H`eys`BUZexA3E;-aRKA!`#Px!-CBNOtg3$*w%WbQbAoGJ-TmV^?TJY5$PlA| z#`2Pc@*Zo!c_#N4ag?%I)vMGMZuJtE(H*@$IWN@;#I$1PaHZVWZ){6Xb80C}vrwUR z&44#W6@@elOACcG$21FtjNcJXwAZxHq6xp==rq*e0M^jLhME302mpK%5Kn+^fgx182x?da z6%5i}QUUvLs*`VMD4D@w5ke)ALL!3c1UgK=8<8pWFdrkXQ(!cm!!VFak3%P~%Op{3 z@xdf#6L)72wVv2|1ba$osGk#w8WCpayNdu4xdD5C0)&Epet-<%1dsqK5CMeIMFE^) zKe@pWLyRGr8uDEuZr_MNGBq%SArho>Fu09uJgnABLz^xF3Ii{{axC~;j_tyzfuSMc zAbkU!(};Qj@~|{7@XpN3^RRYggF>j@B(32Dd@wYADrJC35aHB zFw4N21L}T$AcYKG*F7bW@0k3YGe0p%kQV}Yg4Z8BXa! z=;Xg7(f+^C7-c~hP4B4q7$JIx1po?+>)%`${BQ=7;JQQQ_bY=+&nG>nblcp_z_2qg z-&;LYA50iLzt@r!9b)*R)_aMK^dOT7cv&widJv#{{1_)Y*c*|6V6fE40G*@S!|EFv5kd_Ak6wX5MSwKAaRKzE^wVC! z@PF7lVEC(D&{Y8(f0;c!%og$=39S3;9DjEDRcm76eZ=M!>@Ox3t*&DWMTz ze?YN@QUd)0fA+~HPIT#Z3>+wf2OmKVH6w+PD0nJ~p^fvNupf^U&UI!w24n>+g8gN{ z+yCzTGeuCye|Ru43jdE7n{fX>KD=1*WU4dX{|{We1QMC-Op2yjgqu6tSpVoA*?*w_ zz|0X4N{KNb2m1dgDZcg0oBu$AIcFo1{O}Qs?wTW#M4|o#yXz11AKAHl{f$D&p_JbW zS72Sfq1jIY7zMBm4WXAc2Q@SdeC&sle(w)C$zaF%CoH!wqoe&3o(rtvfd6D?v_55e zLf~^9G-tgp40yez(f!%$CcNHC=^Ox$9C)EO4!UuGCuA!CM1bub^bCuEp5A{w!T)-K z|Mdi4{nr!xuP69lPw>B<;D0^A|9XP|^#uRx3I5j;{C|@tnDJI63%(x#fERdzOOZhL zD_{V=E`;c#2&>z%Ob zaI88)1BSq8q2O9bq|En24orr~rBp8#z36wyF-&lq&5%h^hP<7=%P1my!9A;zlQ}ADwR&X#q zUkvVWs!1dm`M)dMaQX|qx+5t(G=f4PnM9I8sPey}JCc6o;x7~XV|0-HXJjJbXTo8i zKZKEcB0-%*CIy3Ogo71}_^D^uk7Z>)qx>PUpJawL{Ll`p+rMW2VK#I|u(Y&{LkSV| zG%bvO)ITwl5J=SeDOL*u_rv*-P-qyQh}M812`CZ_>xY5EH2g4l6cK^az+p9iNV5nD zr{Y5hB)T+EzFHtCiG(4-@dy+GM({--VQ@bb0fr@EP%uq2o`@$BPzVB?@FV`Z;|fpy zT`Lqq1CGOJYQV8ZI1Lk1I0kKsL?f{%j44*b)EH?ZCqpD?`Grz~@nCHR2IKun>bt^7 z{&F(EvS3Z}#}oEg*gG2;2l|u3K|T|#DFSU|s(~~$LLjgP2m_?1Ax6`{*a(e58KVsi zevi%Y;Mjx`NxE_xzvC^8jKH}Mzd$lb2nXj4WGqaKFbEt514F7I7&+21qL4tx8|b|U zS?EguVQ{bnu+9jq7Ptx!j__RP0%ZsK?fEm;_l1H#xWGn91m^+%j*pQh=!*iU3x2d* z`yVFs=aq@{rnPPf=7HhhOv9e?`#VGqlwmX#Ej)ofVFTtBA4ww0eMbiVRgL42 zL|;umI1GT>G;lmq}0ssFcD}>Mxy3_Jk&4l48;2a>8LNgUtWR1pn6FG~s9h3X8+Q@CYms z2FKBRC_KRrrs;>*08Nd6#o@vB_E-Q?c#s7!c+uv9i-3Wh~$xt(-({Og^_%*8ZaUbhDi=28k}`JL$J)$6v+|-xE$H1^*Wkz7zjWhKY@fwSlvp<9{LLC;6Ys zk@*`zGK|*7u$c7%Qva2;KNR6F^p6pl0XVv&j}!i?fVchKP)&!CBsuVBm2A^Q8=IOM zn3@`54KYTBnuaJ%O(VFmsevKV037CN82&j17K=78GQ}97QQ%lm!$8x}&=_lIfIyjQ z!VwrFEaJ~Gj8O;!6F9;YiNK=K2t!SrfdL$Af;2^&fJvJm;D3%`f`)6FYGTnSI6}h! z2RDY}3{haJD4d}o7#)NBix^nAAr@<-X<&dc1@$(-qKr%o4bVn7Q#29*M*E8xrYH>! zV?$E|q%i_(Vq}CvV$cRyV-yC9Mi`(_rhkrMiiD$0HBI1#h8P^y$iNg~fYvZEHZ?TR zgc}*4QJ6o+Sbw4W&jCHs4~|8`H8f$GIB-y=fdij0I88hOMnIx8@K|tAkHq=?Q&}1$ z0v1KW;9zJp90em{P*@l^_(Q`qG)N>Om=_EdNBpOw8JlYqJg!}oS|8aSt z(HN31QIh~eVGw@w;jAVMPXI?77!n49Cukxy@Wj8cy1&*7O~4`i5GYV3JP8GZBfy~w z9tRFpkQz8&A_3(K$7^E$X?bD5PmDl|M#6A#UlNR{0luQ)2sm)8jX-Edkd_kjt!8OnX1Qskx66W{z_}AU`U-i!n z&fk0{V7JRafsPnD_|pTl?T4r4-}}EM@NWtHTLS-t0`s`x0huFC+5{|BoO6LKp>HP7kpMxiyI3Y!C<^ z24Qj(HH?n`0>Z++L39|(Oou6;f*>qLhyB-KaD^ktvkvRiVPbFyxbhK7*Ex(BOr*p0 zAbcz`g1%&y$r^+cA_GZLAlwPU3gn33KoF*{=N1ko;lX9R%=ERC3RDsy0EFQn%uR82 z1lQv;>wp^>aQpuT`~C(~K_>&q3mAol?P09ulu;(AfZGG$urlVPC^Cskh1r7>dw2>F zoOTNi!-wnvmuNEbOpgT!{%OvEfnLA-x5VH0{yUIfx9jw;4vad3h(7y;`xWySF7zU} z${Soe&y?~D=bHlnRYw3otoIjA;Q}~=dKdsI+kVTBDBWIun-mNr5!C1f`t$f(hM%1O zHSk+{YV`De&ezBouP^?Up<6WpT+ACmkqHOqRY@|i|1{$Nam3%$`c03mpzn)BA%T7s z8CTHCz>h7!>JA|W(mnGsfgyjGRr*cB|1jEb66oN%U4wv7;Tj<9qXzJ|2?I=@p8?E5 zTmaLK^B@KCv)-&ZT*0Ys0C1BYTeo`<2I-9JA1=^jFbE9~WGpBLj2xY12oaRXbrxp& zjRpMTf)5Y|!~rQl9#95g;54`8aMP^oJA!Zq7 z7_&CBIkO8hfq6G`9P>%$Gt9-zmCW_bFPYyle_>u@;bD>=z2*|XTMvOi?+U>{>&=HTa0tfn58! zPIKMhdcyUNYmr-!dkeP__YUp|?j-KZ+>f|lbARRG;n~ci&*RBM2%ajSU+=Z4%z3 zy@{|XaZ~xGUJ0ng770g*y%Gfy&m?9gr6kQH!z6Pg>m)x(iAw29?UKrndMNc#T1a}E zbf9#GbdB`5jEIbZ3|Z#1Ouft(SqWKl*$CNu+2^v$a!PV8atGzgJptDO^+NRpd~_Dh4QKD>f<4Z&upuw)yDhs?8si#FQ+QVwA2a^(*rz>nZP6 zzNp-(!m5H*2~s(y@?r~g3wleymfS6Es!&yoYM|;l)%L9{TX9=MwqD%Y1LKAnz#?JS zVDHpK)vVPHs#U2?sw=2_s;8sKEbiz3~}+e z`?y6dj22a^Tx&`jrX8exRr`aEk`76yP-j?IP8YA6ulshJ%(k7|E^K?NC##3oyQnv$ zFRxG3zob8ApklDgpu}L(5N=2@tT3E6(lUxQdSuLGY-XHj{MM*G#hPM$*9K~1X_Ic# zZ>wkWFaM=h);VwFy~6KMg~7qpvk2vgBN6W+w?*bgE=0LT z-HH~74vBuYXUm@Bd&Xi+V~X}N?sZ%#K`3;7y<;^c>Ybns ziM*u?ffruoo8?zt+&Dmbl)_5$%S6jg+yHJw+!(*P^JaIsRe9|#?5)zuGf}wz;YW(^B~i{j8!D-CFS+ z^SrW6v+d3c+>5*II_(cT^g15DG=ACGY0=rzW!u%>?b7|KXGhQ5SHxEzUXx!>_eSVpzv-Y!Z z=7Q&z=Mxvi7m63Li%m;zOJmDXD{L#LS5;Q;u34@1(}KY-947%;#)>k4s1J?>z^$zK znV?MT%iidN1MpyMG4=bGhJOP?e;rIekKf|ZH&lZDB>Yo=R{L{{DR57w^)06AA<}e} z>AOpW$Mum3}Ekj{qLGE81T8yQ!{2MTqXZ zIvQ;gi>qoDB^go=ZkF#Jr2#Jsl%Bk6)joH8KLA~_y2Mn$A30XI`}N%w)n^**g<5?D z_03-AFU*xmsd>ay&XUIa`dbo4HYP;A*D%2!hvlVm-PG5vYwtsieI4ubRPvq!%f#GMRwtFXEqW(JODkhw4VYzilh?>&<& z*=m+FTF?~kFkD?c-QOQQxeM#$S*=v8z9^Xt8$9AXU{inIg-5E%&hqE)@nyy9Y$x}G zDysy0*O}&mTViFngnr$hyLS0S+vCx--ZLlQmuEsJ-b|Ay!Yp? z^UD6&^5D-<8lXR&+x+%&T6IyC-P?=Wd!3TrWDHkjVn4sP)sA#d8pxEdaxuR|O>Guc zCU0}_$U+2+P_4WD#pZmN&^d@tLI-~Q_ID;wjHka5F1@gN-Rrl9P4JnO)CRE&^DOQe z*l#m6MW$m<&v1Heo4?&Ouwqmk#cA=fOYq1+`QT*b*S$u8JcXE)UIS;_GqU>r54XSZ zo#_(H{@OXxoUK;0+Y7iM3EY&H-g>mDMRt1W$-bCd(o!W&O(zVd$DcX&#$C#2o74H` z)mAB|X3}Y;`&f%5EaYfd68JLX+CLin;1Pt9fAAXu>iAtwcdsoJgyMkZ;obu+;M)R+vSAJkMD|Nq659b zfKoyhM>{n#pu7sVTkjZhmTv_nG!xJgleA}p>fWwfsXu-xmWwSgt!TR)BLW3}Z$`^m zrTJ8*&cOI)0v5mx*&cjD*K#d+u&u-dzvF+^bOw|`okKcuKr|zdM ztnZ&2(g4Y4jRTLx%FbO7xgwEsL5cG6$vHK)RL>no4vC&d4tL$rl12Mx^emr9nO||> zx_n=`d3Fotg#Wf_!fjVOj|tRGxs0@08@cqf>~s33CG}5Btz}E?y6iLeT^?J~+7@3>82hOG zQ52i$lPC_;1N|^@*?zP*TUe+2(cQxCUPW~;SzL5R6Xpk0c5sBK4;86XM-zDnNw5pi zZxi9s1K`=0h`993UMHwQENEk@pV=wpTYS5-`Df3;yuzh<=oPy#$*O-WWK%+GKezM& zzUm~Ih1jZ;p>0ho;6_gLHb~#I5SVq4MJPIy2ve**wⅅC%Sd9$h$ed=L;N$@NWA+%V#m1Xkj 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

    39q>^wIX~YbS&^H1JCFlaL``5GwC!s`Zj=77m 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Art-Book.jpg b/metadata/RG351P/themes/Art-Book.jpg new file mode 100755 index 0000000000000000000000000000000000000000..cebae3ee438de52def069b91483ec365b7a23029 GIT binary patch literal 27575 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/CRAZYBOY.jpg b/metadata/RG351P/themes/CRAZYBOY.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fe7b2bd80d4e67e31cace701c0d81f775c82a3e GIT binary patch literal 47107 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 szNhkk$NYV$JA8dN_3x+e5iLX{ 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Chicuelo.jpg b/metadata/RG351P/themes/Chicuelo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d85ba00432bff92f14e8f8e33ef2b5f86cf8bb9 GIT binary patch literal 51947 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Comic-Book.jpg b/metadata/RG351P/themes/Comic-Book.jpg new file mode 100644 index 0000000000000000000000000000000000000000..56f463d56a35a6a771dfe3c2cee15c4738f01a93 GIT binary patch literal 74213 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/CosmicRise.jpg b/metadata/RG351P/themes/CosmicRise.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c20d0e9ad754f7ad11a78381208f4fc480bd859e GIT binary patch literal 64501 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Crystal.jpg b/metadata/RG351P/themes/Crystal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3034de098975efedad5cfd76e949c1bdd23bbc15 GIT binary patch literal 50722 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 bFIKG(W@}&zlj0XXB0anY8RNM6diK8nC1JP+ literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/EpicCody.jpg b/metadata/RG351P/themes/EpicCody.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c25410361debfe5521c07d7fc9000ed232fa70e4 GIT binary patch literal 51298 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 B+y?*v literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Fundamental.jpg b/metadata/RG351P/themes/Fundamental.jpg new file mode 100644 index 0000000000000000000000000000000000000000..162af0f6a3b46592e0fc50ea65a49794817bdc35 GIT binary patch literal 42466 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/GBZ.jpg b/metadata/RG351P/themes/GBZ.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a338915b7bb741b23e696d5caa11d6078e730caa GIT binary patch literal 28205 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

    5IF*(_bE>zDwbV3zmE!BL5<-arxZN_wc5^s4& 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Horizontal.jpg b/metadata/RG351P/themes/Horizontal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f65a53b2fd6ce0f10f7b9271c41c004ba05cab59 GIT binary patch literal 50138 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 Kb<4!xss9100BZCA literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Minimal.jpg b/metadata/RG351P/themes/Minimal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aef4e19cd5f5bb2f7f3e392b7ff66f2a7467d6b0 GIT binary patch literal 38943 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


    A^_~*Zwp-D1=U?!bfg&X`%l&?xh<}W*4*vo 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Pixel.jpg b/metadata/RG351P/themes/Pixel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df498e616cb1b61e1fbf1b96bf82c78ee6bf9136 GIT binary patch literal 56340 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

    rh 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 R-dul$n{#EM6OaBa{tw{sX3qcs literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Roleta.jpg b/metadata/RG351P/themes/Roleta.jpg new file mode 100644 index 0000000000000000000000000000000000000000..994128fc8dcc3ab955676f196931a680a4266b1a GIT binary patch literal 69130 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/SpinMaster.jpg b/metadata/RG351P/themes/SpinMaster.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92eaeb0c71f18889ecafa2b87133c3bf0f56c146 GIT binary patch literal 60005 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

    Gkwj2GT+PX@Nqx9ac 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

    sHli}ltd>C=}ZUhg%14fT?Ex=L8hg=c-JzDY#Q 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Switch.jpg b/metadata/RG351P/themes/Switch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..154e977c778c0d768a870f5fed999147ddbfa766 GIT binary patch literal 31188 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 m9?5X4-IKK1c75K2y%B1iCl^fQ}Bp3jn|= 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

      {o7L}A}9<gD*;Q2K8!}zWMfXEx=;_0V{_VY&j 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 BnJfSR literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/cavestory.jpg b/metadata/RG351V/packages/cavestory.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7f9c8d261f18c0e5c3764497712be4574754abec GIT binary patch literal 33462 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 CC+q?M literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/cdogs-sdl.jpg b/metadata/RG351V/packages/cdogs-sdl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa39c7047644dacaa749bc2858345ed097b29b8b GIT binary patch literal 23233 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/drastic.jpg b/metadata/RG351V/packages/drastic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a152fd163dca4ec1052c6756afa6a652017ee6d5 GIT binary patch literal 27778 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ⅅC%Sd9$h$ed=L;N$@NWA+%V#m1Xkj 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

      Tk;k#BZOITw+~u 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 z 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 IgU7G`**BE2YybcN literal 0 HcmV?d00001 diff --git a/metadata/RG351V/themes/Epic-Cody.jpg b/metadata/RG351V/themes/Epic-Cody.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5381b02d4a3d3467ac547a5053276a7e3e8ff704 GIT binary patch literal 94203 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�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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/themes/EpicBlancheNoir-V.jpg b/metadata/RG351V/themes/EpicBlancheNoir-V.jpg new file mode 100644 index 0000000000000000000000000000000000000000..09f1d31cc25dd2c9eb152a52f84f3dd2d33ed957 GIT binary patch literal 63413 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%0AMS|Wd2;74!am|{q;Ox{r4sdB6XG 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 YjqF!K_sN-4nYXL2j!>uy>EG}F7kOl5i~s-t literal 0 HcmV?d00001 diff --git a/metadata/RG351V/themes/Handheld-Simple.jpg b/metadata/RG351V/themes/Handheld-Simple.jpg new file mode 100644 index 0000000000000000000000000000000000000000..beefa19e8767a0edce60c91270dd43a3e28c63b8 GIT binary patch literal 55697 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/themes/Kiwi.jpg b/metadata/RG351V/themes/Kiwi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0154731e0e10a0129756ffb9197c5d68c2d628ea GIT binary patch literal 88467 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 G|K9)>*-Op< literal 0 HcmV?d00001 diff --git a/metadata/RG351V/themes/Minimal.jpg b/metadata/RG351V/themes/Minimal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94c366ba3f09f9bc3d5f9445a1c641aa51e31b1e GIT binary patch literal 62943 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 literal 0 HcmV?d00001 diff --git a/packages/audio/alsa-lib/config/modprobe.d/disable-spdif-for-hd-audio.conf b/packages/audio/alsa-lib/config/modprobe.d/disable-spdif-for-hd-audio.conf new file mode 100644 index 000000000..245345d41 --- /dev/null +++ b/packages/audio/alsa-lib/config/modprobe.d/disable-spdif-for-hd-audio.conf @@ -0,0 +1,16 @@ +# INTEL HBR WORKAROUND FOR DTS-MA & Dolby TrueHD PLAYBACK + +# Uncomment the following lines to disable any S/PDIF out to deliver +# bitstreamed audio on Intel builds. This is a rough workaround for +# users that have both S/PDIF and HDMI audio outputs on their motherboard +# or motherboard+discrete graphics combo. + +# EVEN IF YOU ARE NOT USING THE S/PDIF OUTPUT +# but still have one, you will need to uncomment the lines below ! + +# after uncommenting these lines, you must reboot for these settings to take effect + +# blacklist snd_hda_codec_realtek +# blacklist snd_hda_codec_sigmatel +# blacklist snd_hda_codec_cirrus + diff --git a/packages/audio/alsa-lib/modprobe.d/alsa-base.conf b/packages/audio/alsa-lib/modprobe.d/alsa-base.conf new file mode 100644 index 000000000..7bc10a12a --- /dev/null +++ b/packages/audio/alsa-lib/modprobe.d/alsa-base.conf @@ -0,0 +1,26 @@ +############################# +# ALSA drivers load options # +############################# + +# Prevent abnormal drivers from grabbing index 0 +options snd-bt87x index=-2 +options cx88-alsa index=-2 +options saa7134-alsa index=-2 +options snd-atiixp-modem index=-2 +options snd-intel8x0m index=-2 +options snd-via82xx-modem index=-2 +options snd-usb-audio index=-2 +options snd-usb-usx2y index=-2 +options snd-usb-caiaq index=-2 +options snd-cmipci mpu_port=0x330 fm_port=0x388 + +# RG552 shouldn't grab index 0 +options dw_hdmi_i2s_audio index=1 + +# Some Toshiba laptops might require this +# options snd-hda-intel model=toshiba +options snd-hda-intel model=auto + +# fix some Audio Problems with HDMI on ION based Hardware +# see: http://xbmc.org/forum/showthread.php?t=69479 +alias snd-card-0 snd-hda-codec-nvhdmi diff --git a/packages/audio/alsa-lib/modprobe.d/intel-audio.conf b/packages/audio/alsa-lib/modprobe.d/intel-audio.conf new file mode 100644 index 000000000..d3198ed20 --- /dev/null +++ b/packages/audio/alsa-lib/modprobe.d/intel-audio.conf @@ -0,0 +1,2 @@ +# use legacy hda-intel driver even if a DSP is present +options snd_intel_dspcfg dsp_driver=1 diff --git a/packages/audio/alsa-lib/package.mk b/packages/audio/alsa-lib/package.mk new file mode 100644 index 000000000..27f2645f3 --- /dev/null +++ b/packages/audio/alsa-lib/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="alsa-lib" +PKG_VERSION="1.2.6.1" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="ftp://ftp.alsa-project.org/pub/lib/alsa-lib-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="ALSA (Advanced Linux Sound Architecture) is the next generation Linux Sound API." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +if build_with_debug; then + PKG_ALSA_DEBUG=--with-debug +else + PKG_ALSA_DEBUG=--without-debug +fi + +PKG_CONFIGURE_OPTS_TARGET="${PKG_ALSA_DEBUG} \ + --disable-dependency-tracking \ + --with-plugindir=/usr/lib/alsa \ + --disable-python" + +post_configure_target() { + sed -i 's/.*PKGLIBDIR.*/#define PKGLIBDIR ""/' include/config.h +} + +post_makeinstall_target() { + #rm -rf ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/config + cp -PR ${PKG_DIR}/config/modprobe.d ${INSTALL}/usr/config +} + +post_install() { + add_group audio 63 +} diff --git a/packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch b/packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch new file mode 100644 index 000000000..efe2f1ae7 --- /dev/null +++ b/packages/audio/alsa-lib/patches/alsa-lib-asound.conf_configdir.patch @@ -0,0 +1,14 @@ +diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf +index a04173a0..1f13fd84 100644 +--- a/src/conf/alsa.conf ++++ b/src/conf/alsa.conf +@@ -11,7 +11,8 @@ + "/usr/etc/alsa/conf.d" + "/etc/alsa/conf.d" + "/etc/asound.conf|||/usr/etc/asound.conf" +- "~/.asoundrc" ++ "/run/asound.conf" ++ "/storage/.config/asound.conf" + { + @func concat + strings [ diff --git a/packages/audio/alsa-ucm-conf/package.mk b/packages/audio/alsa-ucm-conf/package.mk new file mode 100644 index 000000000..ccb053443 --- /dev/null +++ b/packages/audio/alsa-ucm-conf/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="alsa-ucm-conf" +PKG_VERSION="0b2aa9d22f8897cbe68f1aa2ffe437ad3194ec4b" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="https://github.com/alsa-project/alsa-ucm-conf.git" +GET_HANDLER_SUPPORT="git" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="ALSA Use Case Manager configuration" +PKG_TOOLCHAIN="manual" + +make_target() { + echo +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/alsa + cp -PR $PKG_BUILD/* $INSTALL/usr/share/alsa +} diff --git a/packages/audio/alsa-utils/package.mk b/packages/audio/alsa-utils/package.mk new file mode 100644 index 000000000..34014c056 --- /dev/null +++ b/packages/audio/alsa-utils/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="alsa-utils" +PKG_VERSION="1.2.6" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="ftp://ftp.alsa-project.org/pub/utils/alsa-utils-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib ncurses systemd" +PKG_LONGDESC="This package includes the utilities for ALSA, like alsamixer, aplay, arecord, alsactl, iecset and speaker-test." + +PKG_CONFIGURE_OPTS_TARGET="--disable-alsaconf \ + --disable-alsaloop \ + --enable-alsatest \ + --disable-bat \ + --disable-dependency-tracking \ + --disable-nls \ + --disable-rst2man \ + --disable-xmlto" + +post_makeinstall_target() { + rm -rf $INSTALL/lib $INSTALL/var + rm -rf $INSTALL/usr/share/alsa/speaker-test + rm -rf $INSTALL/usr/share/sounds + rm -rf $INSTALL/usr/lib/systemd/system + +# remove default udev rule to restore mixer configs, we install our own. +# so we avoid resetting our soundconfig + rm -rf $INSTALL/usr/lib/udev/rules.d/90-alsa-restore.rules + +# for i in aconnect alsamixer amidi aplaymidi arecord arecordmidi aseqdump aseqnet iecset; do +# rm -rf $INSTALL/usr/bin/$i +# done + + mkdir -p $INSTALL/usr/lib/udev + cp $PKG_DIR/scripts/soundconfig $INSTALL/usr/lib/udev +} diff --git a/packages/audio/alsa-utils/scripts/soundconfig b/packages/audio/alsa-utils/scripts/soundconfig new file mode 100755 index 000000000..ec097fc92 --- /dev/null +++ b/packages/audio/alsa-utils/scripts/soundconfig @@ -0,0 +1,161 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +# setup alsa (especially the mixer config) + +mixer() { + parm=${4:-on} + amixer -c "$1" sset "$2" "$3" $parm >/dev/null 2>&1 + amixer -c "$1" sset "$2" $parm >/dev/null 2>&1 +} + +( +. /etc/profile + +progress "Setting up sound card" + +if [ -f $HOME/.config/sound.conf ]; then + + alsactl restore -f $HOME/.config/sound.conf + +else + +# get card num + card=`echo $1 | sed 's/[^0-9]*//g'` + +# set common mixer params + mixer $card Master 0db + mixer $card Front 100% + mixer $card PCM 0db + mixer $card Synth 100% + +# mute CD, since using digital audio instead + mixer $card CD 0% mute + +# Only unmute Line and Aux if they are possibly used. +# mixer $card Line 100% +# mixer $card Aux 100% + +# mute mic + mixer $card Mic 0% mute + +# ESS 1969 chipset has 2 PCM channels + mixer $card PCM,1 100% + +# Trident/YMFPCI/emu10k1 + mixer $card Wave 100% + mixer $card Music 100% + mixer $card AC97 100% + mixer $card Surround 90% + mixer $card 'Surround Digital' 90% + mixer $card 'Wave Surround' 90% + mixer $card 'Duplicate Front' 90% + mixer $card 'Sigmatel 4-Speaker Stereo' 90% + +# CS4237B chipset: + mixer $card 'Master Digital' 100% + +# DRC + mixer $card 'Dynamic Range Compression' 90% + +# Envy24 chips with analog outs + mixer $card DAC 100% + mixer $card DAC,0 100% + mixer $card DAC,1 100% + +# some notebooks use headphone instead of master + mixer $card Headphone 100% + mixer $card Speaker 100% + mixer $card 'Internal Speaker' 0% mute + mixer $card Playback 100% + mixer $card Headphone 100% + mixer $card Speaker 100% + mixer $card Center 100% + mixer $card LFE 100% + mixer $card Center/LFE 100% + +# Intel P4P800-MX (Ubuntu bug #5813) + mixer $card 'Master Playback Switch' on + +# set digital output mixer params + mixer $card 'IEC958' 100% on + mixer $card 'IEC958 Output' 100% + mixer $card 'IEC958 Coaxial' 100% + mixer $card 'IEC958 LiveDrive' 100% + mixer $card 'IEC958 Optical Raw' 100% + mixer $card 'SPDIF Out' 100% + mixer $card 'SPDIF Front' 100% + mixer $card 'SPDIF Rear' 100% + mixer $card 'SPDIF Center/LFE' 100% + mixer $card 'Master Digital' 100% + + mixer $card 'Analog Front' 100% + mixer $card 'Analog Rear' 100% + mixer $card 'Analog Center/LFE' 100% + +# ASRock ION 330 (and perhaps others) has 2 IEC958 channels + mixer $card IEC958,0 on + mixer $card IEC958,1 on + +# some ION2 has much more IEC958 channels ... + mixer $card IEC958,2 on + mixer $card IEC958,3 on + +# ASRock ION 330 has Master Front set to 0 + mixer $card 'Master Front' 100% + +# Shuttle XS35GT needs this too + mixer $card 'Master',0 100% on + +# and this for various Fusion devices like Zotac ZBOX + mixer $card 'Front',0 100% on + +# NVidia CK804 sound devices + mixer $card 'IEC958 Playback AC97-SPSA' 100% + +# Allwinner H3 Analog + mixer $card 'Line Out' 0db on + +# Allwinner A20 Analog + mixer $card 'Power Amplifier' 0db + mixer $card 'Power Amplifier DAC' on + mixer $card 'Power Amplifier Mute' on + +# Allwinner A64 Analog + mixer $card Headphone 0db on + mixer $card 'AIF1 Slot 0 Digital DAC' on + +# Amlogic G12A/G12B/SM1 HDMI + case $(dtname) in + azw,gsking-x|khadas,vim3*) #TDM_A + mixer $card 'FRDDR_A SINK 1 SEL' 'OUT 0' + mixer $card 'FRDDR_A SRC 1 EN' on + mixer $card 'TDMOUT_A SRC SEL' 'IN 0' + mixer $card 'TOHDMITX' on + mixer $card 'TOHDMITX I2S SRC' 'I2S A' + ;; + *) #TDM_B + mixer $card 'FRDDR_A SINK 1 SEL' 'OUT 1' + mixer $card 'FRDDR_A SRC 1 EN' on + mixer $card 'TDMOUT_B SRC SEL' 'IN 0' + mixer $card 'TOHDMITX' on + mixer $card 'TOHDMITX I2S SRC' 'I2S B' + ;; + esac + +# Amlogic G12A/G12B/SM1 S/PDIF + mixer $card 'FRDDR_B SINK 1 SEL' 'OUT 3' + mixer $card 'FRDDR_B SRC 1 EN' on + mixer $card 'SPDIFOUT SRC SEL' 'IN 1' + mixer $card 'SPDIFOUT Playback' on + +# Amlogic GX HDMI and S/PDIF + mixer $card 'AIU HDMI CTRL SRC' 'I2S' + mixer $card 'AIU SPDIF SRC SEL' 'SPDIF' +fi + +exit 0 +)& diff --git a/packages/audio/alsa-utils/udev.d/90-alsa-restore.rules b/packages/audio/alsa-utils/udev.d/90-alsa-restore.rules new file mode 100644 index 000000000..3fa0a600b --- /dev/null +++ b/packages/audio/alsa-utils/udev.d/90-alsa-restore.rules @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# When a sound device is detected, restore the volume settings + KERNEL=="controlC[0-9]*", NAME="snd/%k", ACTION=="add", RUN+="soundconfig %k" diff --git a/packages/audio/espeak/package.mk b/packages/audio/espeak/package.mk new file mode 100644 index 000000000..8fbccc15c --- /dev/null +++ b/packages/audio/espeak/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="espeak" +PKG_VERSION="1.48.04-source" +PKG_SHA256="bf9a17673adffcc28ff7ea18764f06136547e97bbd9edf2ec612f09b207f0659" +PKG_LICENSE="GPL" +PKG_SITE="http://espeak.sourceforge.net/" +PKG_URL="http://sourceforge.net/projects/espeak/files/espeak/espeak-1.48/$PKG_NAME-$PKG_VERSION.zip" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Text to Speech engine for English, with support for other languages" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + cp src/portaudio19.h src/portaudio.h +} + +make_target() { + make -C src \ + CXXFLAGS="$CXXFLAGS" \ + LDFLAGS="$LDFLAGS" \ + AUDIO="" +} + +makeinstall_target() { + make -C src \ + CXXFLAGS="$CXXFLAGS" \ + LDFLAGS="$LDFLAGS" \ + AUDIO="" \ + DESTDIR=$INSTALL install +} diff --git a/packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch b/packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch new file mode 100644 index 000000000..446493fb4 --- /dev/null +++ b/packages/audio/espeak/patches/espeak-1.47-ftbs-ld-libm.patch @@ -0,0 +1,23 @@ +diff --git a/src/Makefile b/src/Makefile +index f04b4c4..b8d4b19 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -83,15 +83,15 @@ libespeak_SOURCES = speak_lib.cpp compiledict.cpp dictionary.cpp intonation.cpp + + SRCS1=$(speak_SOURCES) + OBJS1=$(patsubst %.cpp,%.o,$(SRCS1)) +-LIBS1=-lstdc++ $(LIB_AUDIO) -lpthread $(EXTRA_LIBS) ++LIBS1=-lstdc++ -lm $(LIB_AUDIO) -lpthread $(EXTRA_LIBS) + + SRCS2=$(libespeak_SOURCES) + OBJS2=$(patsubst %.cpp,x_%.o,$(SRCS2)) +-LIBS2=-lstdc++ $(LIB_AUDIO) -lpthread ++LIBS2=-lstdc++ -lm $(LIB_AUDIO) -lpthread + + SRCS3 = espeak.cpp + OBJS3=$(patsubst %.cpp,%.o,$(SRCS3)) +-LIBS3=-lstdc++ -L . -lespeak ++LIBS3=-lstdc++ -lm -L . -lespeak + + CXXFLAGS=-O2 + diff --git a/packages/audio/espeak/patches/espeak-1.47-wav-close.patch b/packages/audio/espeak/patches/espeak-1.47-wav-close.patch new file mode 100644 index 000000000..d0550d945 --- /dev/null +++ b/packages/audio/espeak/patches/espeak-1.47-wav-close.patch @@ -0,0 +1,23 @@ +diff --git a/src/espeak.cpp b/src/espeak.cpp +index 00f93c1..4ad42e8 100644 +--- a/src/espeak.cpp ++++ b/src/espeak.cpp +@@ -281,10 +281,7 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) + if(quiet) return(0); // -q quiet mode + + if(wav == NULL) +- { +- CloseWavFile(); + return(0); +- } + + while(events->type != 0) + { +@@ -805,5 +802,7 @@ int main (int argc, char **argv) + + if(f_phonemes_out != stdout) + fclose(f_phonemes_out); // needed for WinCE ++ CloseWavFile(); ++ espeak_Terminate(); + return(0); + } diff --git a/packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch b/packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch new file mode 100644 index 000000000..6e59c7892 --- /dev/null +++ b/packages/audio/espeak/patches/espeak-1.48-gcc-6-fix.patch @@ -0,0 +1,12 @@ +diff --git a/src/tr_languages.cpp b/src/tr_languages.cpp +--- a/src/tr_languages.cpp ++++ b/src/tr_languages.cpp +@@ -198,7 +198,7 @@ static const unsigned short chars_ignore_zwnj_hyphen[] = { + 0x200d, 1, // zero width joiner + 0, 0 }; + +-const char string_ordinal[] = {0xc2,0xba,0}; // masculine ordinal character, UTF-8 ++const char string_ordinal[] = {'\xc2','\xba',0}; // masculine ordinal character, UTF-8 + + + static Translator* NewTranslator(void) diff --git a/packages/audio/flac/package.mk b/packages/audio/flac/package.mk new file mode 100644 index 000000000..6e03c45dc --- /dev/null +++ b/packages/audio/flac/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="flac" +PKG_VERSION="1.3.2" +PKG_SHA256="91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f" +PKG_LICENSE="GPLv2" +PKG_SITE="https://xiph.org/flac/" +PKG_URL="http://downloads.xiph.org/releases/flac/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libogg" +PKG_LONGDESC="An Free Lossless Audio Codec." +PKG_TOOLCHAIN="autotools" +# flac-1.3.1 dont build with LTO support +PKG_BUILD_FLAGS="+pic" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-shared \ + --disable-static \ + --disable-rpath \ + --disable-altivec \ + --disable-doxygen-docs \ + --disable-thorough-tests \ + --disable-cpplibs \ + --disable-xmms-plugin \ + --disable-oggtest \ + --with-ogg=$SYSROOT_PREFIX/usr \ + --with-gnu-ld" + +if target_has_feature sse; then + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --enable-sse" +else + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-sse" +fi + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/audio/fluidsynth/package.mk b/packages/audio/fluidsynth/package.mk new file mode 100644 index 000000000..628c93493 --- /dev/null +++ b/packages/audio/fluidsynth/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fluidsynth" +PKG_VERSION="1.1.6" +PKG_SHA256="d28b47dfbf7f8e426902ae7fa2981d821fbf84f41da9e1b85be933d2d748f601" +PKG_LICENSE="GPL" +PKG_SITE="http://fluidsynth.org/" +PKG_URL="$SOURCEFORGE_SRC/project/fluidsynth/fluidsynth-$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain glib" +PKG_LONGDESC="FluidSynth renders midi music files as raw audio data, for playing or conversion." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=0 \ + -DLIB_SUFFIX= \ + -Denable-readline=0 \ + -Denable-pulseaudio=0 \ + -Denable-libsndfile=0" diff --git a/packages/audio/lame/package.mk b/packages/audio/lame/package.mk new file mode 100644 index 000000000..04554d3e0 --- /dev/null +++ b/packages/audio/lame/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="lame" +PKG_VERSION="3.99.5" +PKG_SHA256="24346b4158e4af3bd9f2e194bb23eb473c75fb7377011523353196b19b9a23ff" +PKG_LICENSE="LGPL" +PKG_SITE="http://lame.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/lame/lame/3.99/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A high quality MPEG Audio Layer III (MP3) encoder." +PKG_BUILD_FLAGS="-parallel +pic" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-nasm \ + --disable-rpath \ + --disable-cpml \ + --disable-gtktest \ + --disable-efence \ + --disable-analyzer-hooks \ + --enable-decoder \ + --disable-frontend \ + --disable-mp3x \ + --disable-mp3rtp \ + --disable-dynamic-frontends \ + --enable-expopt=no \ + --enable-debug=no \ + --with-gnu-ld \ + --with-fileio=lame \ + GTK_CONFIG=no" diff --git a/packages/audio/lame/patches/lame-3.99.5-am_path_gtk.patch b/packages/audio/lame/patches/lame-3.99.5-am_path_gtk.patch new file mode 100644 index 000000000..e49b7deda --- /dev/null +++ b/packages/audio/lame/patches/lame-3.99.5-am_path_gtk.patch @@ -0,0 +1,233 @@ +diff -Naur lame-3.98.4/configure.in lame-3.98.4.patch/configure.in +--- lame-3.98.4/configure.in 2010-03-22 21:40:17.000000000 +0100 ++++ lame-3.98.4.patch/configure.in 2011-03-25 12:11:44.982662225 +0100 +@@ -21,6 +21,8 @@ + AC_INIT([lame],[3.98.4],[lame-dev@lists.sf.net]) + AC_CONFIG_SRCDIR([libmp3lame/lame.c]) + ++AC_CONFIG_MACRO_DIR([m4]) ++ + dnl check system + AC_CANONICAL_HOST + +@@ -385,7 +387,7 @@ + + dnl configure use of features + +-AM_PATH_GTK(1.2.0, HAVE_GTK="yes", HAVE_GTK="no") ++AM_PATH_GTK_2_0(1.2.0, HAVE_GTK="yes", HAVE_GTK="no") + + dnl ElectricFence malloc debugging + AC_MSG_CHECKING(use of ElectricFence malloc debugging) +diff -Naur lame-3.98.4/m4/gtk-2.0.m4 lame-3.98.4.patch/m4/gtk-2.0.m4 +--- lame-3.98.4/m4/gtk-2.0.m4 1970-01-01 01:00:00.000000000 +0100 ++++ lame-3.98.4.patch/m4/gtk-2.0.m4 2010-12-22 03:34:53.000000000 +0100 +@@ -0,0 +1,196 @@ ++# Configure paths for GTK+ ++# Owen Taylor 1997-2001 ++ ++dnl AM_PATH_GTK_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) ++dnl Test for GTK+, and define GTK_CFLAGS and GTK_LIBS, if gthread is specified in MODULES, ++dnl pass to pkg-config ++dnl ++AC_DEFUN([AM_PATH_GTK_2_0], ++[dnl ++dnl Get the cflags and libraries from pkg-config ++dnl ++AC_ARG_ENABLE(gtktest, [ --disable-gtktest do not try to compile and run a test GTK+ program], ++ , enable_gtktest=yes) ++ ++ pkg_config_args=gtk+-2.0 ++ for module in . $4 ++ do ++ case "$module" in ++ gthread) ++ pkg_config_args="$pkg_config_args gthread-2.0" ++ ;; ++ esac ++ done ++ ++ no_gtk="" ++ ++ AC_PATH_PROG(PKG_CONFIG, pkg-config, no) ++ ++ if test x$PKG_CONFIG != xno ; then ++ if pkg-config --atleast-pkgconfig-version 0.7 ; then ++ : ++ else ++ echo "*** pkg-config too old; version 0.7 or better required." ++ no_gtk=yes ++ PKG_CONFIG=no ++ fi ++ else ++ no_gtk=yes ++ fi ++ ++ min_gtk_version=ifelse([$1], ,2.0.0,$1) ++ AC_MSG_CHECKING(for GTK+ - version >= $min_gtk_version) ++ ++ if test x$PKG_CONFIG != xno ; then ++ ## don't try to run the test against uninstalled libtool libs ++ if $PKG_CONFIG --uninstalled $pkg_config_args; then ++ echo "Will use uninstalled version of GTK+ found in PKG_CONFIG_PATH" ++ enable_gtktest=no ++ fi ++ ++ if $PKG_CONFIG --atleast-version $min_gtk_version $pkg_config_args; then ++ : ++ else ++ no_gtk=yes ++ fi ++ fi ++ ++ if test x"$no_gtk" = x ; then ++ GTK_CFLAGS=`$PKG_CONFIG $pkg_config_args --cflags` ++ GTK_LIBS=`$PKG_CONFIG $pkg_config_args --libs` ++ gtk_config_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ ++ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` ++ gtk_config_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ ++ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` ++ gtk_config_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ ++ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` ++ if test "x$enable_gtktest" = "xyes" ; then ++ ac_save_CFLAGS="$CFLAGS" ++ ac_save_LIBS="$LIBS" ++ CFLAGS="$CFLAGS $GTK_CFLAGS" ++ LIBS="$GTK_LIBS $LIBS" ++dnl ++dnl Now check if the installed GTK+ is sufficiently new. (Also sanity ++dnl checks the results of pkg-config to some extent) ++dnl ++ rm -f conf.gtktest ++ AC_TRY_RUN([ ++#include ++#include ++#include ++ ++int ++main () ++{ ++ int major, minor, micro; ++ char *tmp_version; ++ ++ fclose (fopen ("conf.gtktest", "w")); ++ ++ /* HP/UX 9 (%@#!) writes to sscanf strings */ ++ tmp_version = g_strdup("$min_gtk_version"); ++ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { ++ printf("%s, bad version string\n", "$min_gtk_version"); ++ exit(1); ++ } ++ ++ if ((gtk_major_version != $gtk_config_major_version) || ++ (gtk_minor_version != $gtk_config_minor_version) || ++ (gtk_micro_version != $gtk_config_micro_version)) ++ { ++ printf("\n*** 'pkg-config --modversion gtk+-2.0' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", ++ $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, ++ gtk_major_version, gtk_minor_version, gtk_micro_version); ++ printf ("*** was found! If pkg-config was correct, then it is best\n"); ++ printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); ++ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); ++ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); ++ printf("*** required on your system.\n"); ++ printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); ++ printf("*** to point to the correct configuration files\n"); ++ } ++ else if ((gtk_major_version != GTK_MAJOR_VERSION) || ++ (gtk_minor_version != GTK_MINOR_VERSION) || ++ (gtk_micro_version != GTK_MICRO_VERSION)) ++ { ++ printf("*** GTK+ header files (version %d.%d.%d) do not match\n", ++ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); ++ printf("*** library (version %d.%d.%d)\n", ++ gtk_major_version, gtk_minor_version, gtk_micro_version); ++ } ++ else ++ { ++ if ((gtk_major_version > major) || ++ ((gtk_major_version == major) && (gtk_minor_version > minor)) || ++ ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) ++ { ++ return 0; ++ } ++ else ++ { ++ printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", ++ gtk_major_version, gtk_minor_version, gtk_micro_version); ++ printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", ++ major, minor, micro); ++ printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); ++ printf("***\n"); ++ printf("*** If you have already installed a sufficiently new version, this error\n"); ++ printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); ++ printf("*** being found. The easiest way to fix this is to remove the old version\n"); ++ printf("*** of GTK+, but you can also set the PKG_CONFIG environment to point to the\n"); ++ printf("*** correct copy of pkg-config. (In this case, you will have to\n"); ++ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); ++ printf("*** so that the correct libraries are found at run-time))\n"); ++ } ++ } ++ return 1; ++} ++],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) ++ CFLAGS="$ac_save_CFLAGS" ++ LIBS="$ac_save_LIBS" ++ fi ++ fi ++ if test "x$no_gtk" = x ; then ++ AC_MSG_RESULT(yes (version $gtk_config_major_version.$gtk_config_minor_version.$gtk_config_micro_version)) ++ ifelse([$2], , :, [$2]) ++ else ++ AC_MSG_RESULT(no) ++ if test "$PKG_CONFIG" = "no" ; then ++ echo "*** A new enough version of pkg-config was not found." ++ echo "*** See http://pkgconfig.sourceforge.net" ++ else ++ if test -f conf.gtktest ; then ++ : ++ else ++ echo "*** Could not run GTK+ test program, checking why..." ++ ac_save_CFLAGS="$CFLAGS" ++ ac_save_LIBS="$LIBS" ++ CFLAGS="$CFLAGS $GTK_CFLAGS" ++ LIBS="$LIBS $GTK_LIBS" ++ AC_TRY_LINK([ ++#include ++#include ++], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], ++ [ echo "*** The test program compiled, but did not run. This usually means" ++ echo "*** that the run-time linker is not finding GTK+ or finding the wrong" ++ echo "*** version of GTK+. If it is not finding GTK+, you'll need to set your" ++ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" ++ echo "*** to the installed location Also, make sure you have run ldconfig if that" ++ echo "*** is required on your system" ++ echo "***" ++ echo "*** If you have an old version installed, it is best to remove it, although" ++ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], ++ [ echo "*** The test program failed to compile or link. See the file config.log for the" ++ echo "*** exact error that occured. This usually means GTK+ is incorrectly installed."]) ++ CFLAGS="$ac_save_CFLAGS" ++ LIBS="$ac_save_LIBS" ++ fi ++ fi ++ GTK_CFLAGS="" ++ GTK_LIBS="" ++ ifelse([$3], , :, [$3]) ++ fi ++ AC_SUBST(GTK_CFLAGS) ++ AC_SUBST(GTK_LIBS) ++ rm -f conf.gtktest ++]) +diff -Naur lame-3.98.4/Makefile.am lame-3.98.4.patch/Makefile.am +--- lame-3.98.4/Makefile.am 2010-02-26 23:33:06.000000000 +0100 ++++ lame-3.98.4.patch/Makefile.am 2011-03-25 12:15:37.951078720 +0100 +@@ -2,6 +2,8 @@ + + include $(top_srcdir)/Makefile.am.global + ++ACLOCAL_AMFLAGS = -I m4 ++ + .PHONY: test + + SUBDIRS = mpglib libmp3lame frontend Dll debian doc include misc dshow ACM \ diff --git a/packages/audio/lame/patches/lame-3.99.5-automake.patch b/packages/audio/lame/patches/lame-3.99.5-automake.patch new file mode 100644 index 000000000..4645a58c1 --- /dev/null +++ b/packages/audio/lame/patches/lame-3.99.5-automake.patch @@ -0,0 +1,46 @@ +diff -Naur lame-3.99.5/configure.in lame-3.99.5.patch/configure.in +--- lame-3.99.5/configure.in 2012-02-28 19:50:27.000000000 +0100 ++++ lame-3.99.5.patch/configure.in 2012-06-13 18:26:00.741781534 +0200 +@@ -77,9 +77,6 @@ + AC_MSG_RESULT(${GCC_version}) + fi + +-dnl more automake stuff +-AM_C_PROTOTYPES +- + AC_CHECK_HEADER(dmalloc.h) + if test "${ac_cv_header_dmalloc_h}" = "yes"; then + AM_WITH_DMALLOC +diff -Naur lame-3.99.5/doc/html/Makefile.am lame-3.99.5.patch/doc/html/Makefile.am +--- lame-3.99.5/doc/html/Makefile.am 2010-09-30 22:58:40.000000000 +0200 ++++ lame-3.99.5.patch/doc/html/Makefile.am 2012-06-13 18:28:01.586276747 +0200 +@@ -1,6 +1,6 @@ + ## $Id: Makefile.am,v 1.7 2010/09/30 20:58:40 jaz001 Exp $ + +-AUTOMAKE_OPTIONS = foreign ansi2knr ++AUTOMAKE_OPTIONS = foreign + + docdir = $(datadir)/doc + pkgdocdir = $(docdir)/$(PACKAGE) +diff -Naur lame-3.99.5/doc/man/Makefile.am lame-3.99.5.patch/doc/man/Makefile.am +--- lame-3.99.5/doc/man/Makefile.am 2000-10-22 13:39:44.000000000 +0200 ++++ lame-3.99.5.patch/doc/man/Makefile.am 2012-06-13 18:27:52.160085394 +0200 +@@ -1,6 +1,6 @@ + ## $Id: Makefile.am,v 1.1 2000/10/22 11:39:44 aleidinger Exp $ + +-AUTOMAKE_OPTIONS = foreign ansi2knr ++AUTOMAKE_OPTIONS = foreign + + man_MANS = lame.1 + EXTRA_DIST = ${man_MANS} +diff -Naur lame-3.99.5/libmp3lame/i386/Makefile.am lame-3.99.5.patch/libmp3lame/i386/Makefile.am +--- lame-3.99.5/libmp3lame/i386/Makefile.am 2011-04-04 11:42:34.000000000 +0200 ++++ lame-3.99.5.patch/libmp3lame/i386/Makefile.am 2012-06-13 18:27:23.761463827 +0200 +@@ -1,7 +1,5 @@ + ## $Id: Makefile.am,v 1.26 2011/04/04 09:42:34 aleidinger Exp $ + +-AUTOMAKE_OPTIONS = foreign $(top_srcdir)/ansi2knr +- + DEFS = @DEFS@ @CONFIG_DEFS@ + + ECHO ?= echo diff --git a/packages/audio/libcdio/package.mk b/packages/audio/libcdio/package.mk new file mode 100644 index 000000000..f63727933 --- /dev/null +++ b/packages/audio/libcdio/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libcdio" +PKG_VERSION="0.94" +PKG_SHA256="96e2c903f866ae96f9f5b9048fa32db0921464a2286f5b586c0f02699710025a" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/libcdio/" +PKG_URL="http://ftpmirror.gnu.org/libcdio/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A CD-ROM reading and control library." +PKG_BUILD_FLAGS="+pic" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-cxx \ + --disable-cpp-progs \ + --disable-shared \ + --enable-static \ + --enable-joliet \ + --disable-rpath \ + --enable-rock \ + --disable-cddb \ + --disable-vcd-info \ + --without-cd-drive \ + --without-cd-info \ + --without-cdda-player \ + --without-cd-read \ + --without-iso-info \ + --without-iso-read \ + --without-libiconv-prefix \ + --with-gnu-ld" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/audio/libmodplug/package.mk b/packages/audio/libmodplug/package.mk new file mode 100644 index 000000000..5a73c2972 --- /dev/null +++ b/packages/audio/libmodplug/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmodplug" +PKG_VERSION="0.8.9.0" +PKG_SHA256="457ca5a6c179656d66c01505c0d95fafaead4329b9dbaa0f997d00a3508ad9de" +PKG_LICENSE="GPL" +PKG_SITE="http://modplug-xmms.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/modplug-xmms/libmodplug/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libmodplug renders mod music files as raw audio data, for playing or conversion." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --enable-shared" diff --git a/packages/audio/libogg/package.mk b/packages/audio/libogg/package.mk new file mode 100644 index 000000000..16944ae31 --- /dev/null +++ b/packages/audio/libogg/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libogg" +PKG_VERSION="1.3.5" +PKG_LICENSE="BSD" +PKG_SITE="https://www.xiph.org/ogg/" +PKG_URL="http://downloads.xiph.org/releases/ogg/libogg-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Libogg contains necessary functionality to create, decode, and work with Ogg bitstreams." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DINSTALL_DOCS=OFF" \ No newline at end of file diff --git a/packages/audio/libopenmpt/package.mk b/packages/audio/libopenmpt/package.mk new file mode 100644 index 000000000..ad458e64f --- /dev/null +++ b/packages/audio/libopenmpt/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libopenmpt" +PKG_VERSION="0.4.5" +PKG_SHA256="0b4cc0cc8fbbdabc6263a900ff3560dae7be43be011b6f2bc9913f7a0ed3a521" +PKG_LICENSE="BSD" +PKG_SITE="http://lib.openmpt.org/libopenmpt/" +PKG_URL="http://lib.openmpt.org/files/libopenmpt/src/${PKG_NAME}-${PKG_VERSION}+release.autotools.tar.gz" +PKG_DEPENDS_TARGET="toolchain libogg libvorbis zlib" +PKG_LONGDESC="libopenmpt renders mod music files as raw audio data, for playing or conversion." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --without-mpg123 \ + --with-vorbis \ + --with-vorbisfile \ + --without-pulseaudio \ + --without-portaudio \ + --without-portaudiocpp \ + --without-sdl \ + --without-sdl2 \ + --without-sndfile \ + --without-flac" diff --git a/packages/audio/libsamplerate/package.mk b/packages/audio/libsamplerate/package.mk new file mode 100644 index 000000000..e96b53d8b --- /dev/null +++ b/packages/audio/libsamplerate/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libsamplerate" +PKG_VERSION="0.2.2" +PKG_SHA256="3258da280511d24b49d6b08615bbe824d0cacc9842b0e4caf11c52cf2b043893" +PKG_LICENSE="GPL" +PKG_SITE="http://www.mega-nerd.com/SRC/" +PKG_URL="https://github.com/libsndfile/libsamplerate/releases/download/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libsndfile" +PKG_LONGDESC="A Sample Rate Converter for audio." +PKG_BUILD_FLAGS="+pic" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --datadir=/usr/share \ + --disable-fftw \ + --enable-sndfile" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/audio/libsndfile/package.mk b/packages/audio/libsndfile/package.mk new file mode 100644 index 000000000..1bdb2b4f9 --- /dev/null +++ b/packages/audio/libsndfile/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libsndfile" +PKG_VERSION="1.0.31" +PKG_SHA256="a8cfb1c09ea6e90eff4ca87322d4168cdbe5035cb48717b40bf77e751cc02163" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.mega-nerd.com/libsndfile/" +PKG_URL="https://github.com/libsndfile/libsndfile/releases/download/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="A library for accessing various audio file formats." +PKG_SHORTDESC="A library for accessing various audio file formats." +PKG_TOOLCHAIN="configure" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-silent-rules \ + --disable-sqlite \ + --enable-alsa \ + --disable-experimental \ + --disable-test-coverage \ + --enable-largefile \ + --with-gnu-ld" + +make_target() { + make +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/audio/libvorbis/package.mk b/packages/audio/libvorbis/package.mk new file mode 100644 index 000000000..b2db41b71 --- /dev/null +++ b/packages/audio/libvorbis/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libvorbis" +PKG_VERSION="1.3.7" +#PKG_SHA256="" +PKG_LICENSE="BSD" +PKG_SITE="http://www.vorbis.com/" +PKG_URL="http://downloads.xiph.org/releases/vorbis/libvorbis-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libogg" +PKG_LONGDESC="Lossless audio compression tools using the ogg-vorbis algorithms." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --enable-shared \ + --with-ogg=$SYSROOT_PREFIX/usr \ + --disable-docs \ + --disable-examples \ + --disable-oggtest" diff --git a/packages/audio/openal-soft/package.mk b/packages/audio/openal-soft/package.mk new file mode 100644 index 000000000..d99a1b163 --- /dev/null +++ b/packages/audio/openal-soft/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="openal-soft" +PKG_VERSION="1.20.1" +PKG_SHA256="c32d10473457a8b545aab50070fe84be2b5b041e1f2099012777ee6be0057c13" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openal.org/" +PKG_URL="https://github.com/kcat/openal-soft/archive/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib openal-soft:host" +PKG_LONGDESC="OpenAL the Open Audio Library" + +configure_package() { + PKG_CMAKE_OPTS_HOST="-DALSOFT_BACKEND_OSS=off \ + -DALSOFT_BACKEND_WAVE=off \ + -DALSOFT_BACKEND_PULSEAUDIO=on \ + -DALSOFT_EXAMPLES=off \ + -DALSOFT_TESTS=off \ + -DALSOFT_UTILS=off" + + PKG_CMAKE_OPTS_TARGET="-DALSOFT_NATIVE_TOOLS_PATH=$PKG_BUILD/.$HOST_NAME/native-tools \ + -DALSOFT_BACKEND_OSS=off \ + -DALSOFT_BACKEND_WAVE=off \ + -DALSOFT_BACKEND_PULSEAUDIO=on \ + -DALSOFT_EXAMPLES=off \ + -DALSOFT_TESTS=off \ + -DALSOFT_UTILS=off" +} + +post_makeinstall_target() { + mkdir -p $INSTALL/etc/openal + sed s/^#drivers.*/drivers=alsa/ $INSTALL/usr/share/openal/alsoftrc.sample > $INSTALL/etc/openal/alsoft.conf + rm -rf $INSTALL/usr/share/openal +} diff --git a/packages/audio/pulseaudio/config/pulse-daemon.conf.d/README b/packages/audio/pulseaudio/config/pulse-daemon.conf.d/README new file mode 100644 index 000000000..350761ed5 --- /dev/null +++ b/packages/audio/pulseaudio/config/pulse-daemon.conf.d/README @@ -0,0 +1,5 @@ +Files have to have the .conf file name extension, but otherwise the file names can be +chosen freely. The files under pulse-daemon.conf.d are processed in alphabetical order. +In case the same option is set in multiple files, the last file to set an option +overrides earlier files. The main daemon.conf file is processed first, so +options set in files under pulse-daemon.conf.d override the main file. diff --git a/packages/audio/pulseaudio/config/pulseaudio-system.conf b/packages/audio/pulseaudio/config/pulseaudio-system.conf new file mode 100644 index 000000000..c92fc5301 --- /dev/null +++ b/packages/audio/pulseaudio/config/pulseaudio-system.conf @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + diff --git a/packages/audio/pulseaudio/config/system.pa b/packages/audio/pulseaudio/config/system.pa new file mode 100644 index 000000000..937a2f133 --- /dev/null +++ b/packages/audio/pulseaudio/config/system.pa @@ -0,0 +1,68 @@ +#!/usr/bin/pulseaudio -nF +# +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# PulseAudio 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 Lesser General Public License +# along with PulseAudio; if not, see . + +# This startup script is used only if PulseAudio is started in system +# mode. + +### Load several protocols +.ifexists module-esound-protocol-unix.so +load-module module-esound-protocol-unix +.endif +load-module module-native-protocol-unix + +### Automatically restore the volume of streams and devices +load-module module-stream-restore +load-module module-device-restore + +### Automatically restore the default sink/source when changed by the user +### during runtime +### NOTE: This should be loaded as early as possible so that subsequent modules +### that look up the default sink/source get the right value +load-module module-default-device-restore + +### Automatically move streams to the default sink if the sink they are +### connected to dies, similar for sources +load-module module-rescue-streams + +### Make sure we always have a sink around, even if it is a null sink. +load-module module-always-sink + +### Automatically suspend sinks/sources that become idle for too long +load-module module-suspend-on-idle + +### Enable positioned event sounds +load-module module-position-event-sounds + +### Automatically load modules for dbus +.ifexists module-dbus-protocol.so + load-module module-dbus-protocol +.endif + +### Automatically load modules for bluetooth +.ifexists module-bluetooth-policy.so + load-module module-bluetooth-policy +.endif + +.ifexists module-bluetooth-discover.so + load-module module-bluetooth-discover +.endif + +.ifexists module-zeroconf-publish.so + load-module module-zeroconf-publish +.endif + +load-module module-switch-on-connect diff --git a/packages/audio/pulseaudio/package.mk b/packages/audio/pulseaudio/package.mk new file mode 100644 index 000000000..f61d99e94 --- /dev/null +++ b/packages/audio/pulseaudio/package.mk @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pulseaudio" +PKG_VERSION="14.2" +PKG_SHA256="75d3f7742c1ae449049a4c88900e454b8b350ecaa8c544f3488a2562a9ff66f1" +PKG_LICENSE="GPL" +PKG_SITE="http://pulseaudio.org/" +PKG_URL="http://www.freedesktop.org/software/pulseaudio/releases/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain alsa-lib dbus libcap libsndfile libtool openssl soxr speexdsp systemd glib:host glib" +PKG_LONGDESC="PulseAudio is a sound system for POSIX OSes, meaning that it is a proxy for your sound applications." +PKG_TOOLCHAIN="meson" + +if [ "${BLUETOOTH_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" sbc" + PKG_PULSEAUDIO_BLUETOOTH="-Dbluez5=true" +else + PKG_PULSEAUDIO_BLUETOOTH="-Dbluez5=false" +fi + +if [ "${AVAHI_DAEMON}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" avahi" + PKG_PULSEAUDIO_AVAHI="-Davahi=enabled" +else + PKG_PULSEAUDIO_AVAHI="-Davahi=disabled" +fi + +PKG_MESON_OPTS_TARGET="-Dgcov=false \ + -Dman=false \ + -Dtests=false \ + -Dsystem_user=root \ + -Dsystem_group=root \ + -Daccess_group=root \ + -Ddatabase=simple \ + -Dlegacy-database-entry-format=false \ + -Drunning-from-build-tree=false \ + -Datomic-arm-linux-helpers=true \ + -Datomic-arm-memory-barrier=false \ + -Dmodlibexecdir=/usr/lib/pulse \ + -Dudevrulesdir=/usr/lib/udev/rules.d \ + -Dalsa=enabled \ + -Dasyncns=disabled \ + ${PKG_PULSEAUDIO_AVAHI} \ + ${PKG_PULSEAUDIO_BLUETOOTH} \ + -Dbluez5-native-headset=false \ + -Dbluez5-ofono-headset=false \ + -Ddbus=enabled \ + -Dfftw=disabled \ + -Dglib=enabled \ + -Dgsettings=disabled \ + -Dgtk=disabled \ + -Dhal-compat=false \ + -Dipv6=true \ + -Djack=disabled \ + -Dlirc=disabled \ + -Dopenssl=enabled \ + -Dorc=disabled \ + -Dsamplerate=disabled \ + -Dsoxr=enabled \ + -Dspeex=enabled \ + -Dsystemd=enabled \ + -Dudev=enabled \ + -Dx11=disabled \ + -Dadrian-aec=true \ + -Dwebrtc-aec=disabled" + +pre_configure_target() { + sed -e 's|; remixing-use-all-sink-channels = yes|; remixing-use-all-sink-channels = no|' \ + -i ${PKG_BUILD}/src/daemon/daemon.conf.in + sed -e 's|; default-fragments = 4|; default-fragments = 5|' \ + -i ${PKG_BUILD}/src/daemon/daemon.conf.in +} + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/include + safe_remove ${INSTALL}/usr/lib/cmake + safe_remove ${INSTALL}/usr/lib/pkgconfig + safe_remove ${INSTALL}/usr/lib/systemd + safe_remove ${INSTALL}/usr/share/vala + safe_remove ${INSTALL}/usr/share/zsh + safe_remove ${INSTALL}/usr/share/bash-completion + + cp ${PKG_DIR}/config/system.pa ${INSTALL}/etc/pulse/ + cp ${PKG_DIR}/config/pulseaudio-system.conf ${INSTALL}/etc/dbus-1/system.d/ + + mkdir -p ${INSTALL}/usr/config + cp -PR ${PKG_DIR}/config/pulse-daemon.conf.d ${INSTALL}/usr/config + + ln -sf /storage/.config/pulse-daemon.conf.d ${INSTALL}/etc/pulse/daemon.conf.d +} + +post_install() { + enable_service pulseaudio.service +} diff --git a/packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch b/packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch new file mode 100644 index 000000000..8bea8d95f --- /dev/null +++ b/packages/audio/pulseaudio/patches/pulseaudio-100.01-never-append-dirty-to-server-module-version.patch @@ -0,0 +1,24 @@ +From c9d7dcaa87f9ada49d75483a7c604dba27a0d71a Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 7 Jan 2014 13:22:48 +0200 +Subject: [PATCH] never append -dirty to server/module version + +--- + git-version-gen | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/git-version-gen b/git-version-gen +index 9d65b80..fcf11fd 100755 +--- a/git-version-gen ++++ b/git-version-gen +@@ -152,6 +152,7 @@ v=`echo "$v" |sed 's/^v//'` + git status > /dev/null 2>&1 + + dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty= ++dirty= + case "$dirty" in + '') ;; + *) # Append the suffix only if there isn't one already. +-- +1.7.2.5 + diff --git a/packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch b/packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch new file mode 100644 index 000000000..df9275089 --- /dev/null +++ b/packages/audio/pulseaudio/patches/pulseaudio-100.02-check_uid.patch @@ -0,0 +1,13 @@ +--- pulseaudio-4.0.orig/src/pulsecore/core-util.c 2014-01-12 23:31:26.281525000 -0800 ++++ pulseaudio-4.0/src/pulsecore/core-util.c 2014-01-12 23:32:32.977118803 -0800 +@@ -1447,10 +1447,6 @@ + if (stat(p, &st) < 0) + return -errno; + +-#ifdef HAVE_GETUID +- if (st.st_uid != getuid() && st.st_uid != 0) +- return -EACCES; +-#endif + + return 0; + } diff --git a/packages/audio/pulseaudio/profile.d/99-pulseaudio.conf b/packages/audio/pulseaudio/profile.d/99-pulseaudio.conf new file mode 100644 index 000000000..7e7b95357 --- /dev/null +++ b/packages/audio/pulseaudio/profile.d/99-pulseaudio.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib/pulseaudio" diff --git a/packages/audio/pulseaudio/system.d/pulseaudio.service b/packages/audio/pulseaudio/system.d/pulseaudio.service new file mode 100644 index 000000000..f052e019d --- /dev/null +++ b/packages/audio/pulseaudio/system.d/pulseaudio.service @@ -0,0 +1,12 @@ +[Unit] +Description=PulseAudio Sound Service +After=syslog.target local-fs.target + +[Service] +Type=dbus +BusName=org.pulseaudio.Server +ExecStart=/usr/bin/pulseaudio --system --disallow-exit --exit-idle-time=-1 --disable-shm +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/packages/audio/rpi-cirrus-config/config/rpi-cirrus-config.sh.sample b/packages/audio/rpi-cirrus-config/config/rpi-cirrus-config.sh.sample new file mode 100644 index 000000000..76fdb71bd --- /dev/null +++ b/packages/audio/rpi-cirrus-config/config/rpi-cirrus-config.sh.sample @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Sample user config script to setup Cirrus Logic Audio Card + +# load helper functions and definitions +. /usr/lib/alsa/rpi-cirrus-functions.sh + +# enable output to S/PDIF, line out and headset out +playback_to_spdif +playback_to_lineout +playback_to_headset + +# disable noise gate - this can cut off the first few ms of playback +mixer 'Noise Gate Switch' off + +# Uncomment this line to enable output to speakers +# playback_to_speakers + +# example: mix line in and headset in into line out using a high-pass filter +# - line in gain is set to +8dB +# - headset in gain is set to +20dB +# - line in and headset in are mixed together in the filter, each using +# a gain of -3dB (volume 29). line in uses input 1, headset in input 2 +# - first input of line out is connected to audio signal from RPi/Kodi, +# using a -3dB gain +# - second input of line out is connected to output of the filter +# +# mixer "${line_out} Digital Switch" off # mute output +# setup_line_in 8 +# setup_headset_in 20 +# setup_filter "High-Pass" "240,3" +# set_mixer $filter_signals $line_in_signals 29 1 +# set_mixer $filter_signals $headset_in_signals 29 2 +# set_mixer $line_out_signals $rpi_out_signals 29 1 +# set_mixer $line_out_signals $filter_signals 29 2 +# mixer "${line_out} Digital Switch" on # unmute output diff --git a/packages/audio/rpi-cirrus-config/modprobe.d/rpi-cirrus.conf b/packages/audio/rpi-cirrus-config/modprobe.d/rpi-cirrus.conf new file mode 100644 index 000000000..2b3237d29 --- /dev/null +++ b/packages/audio/rpi-cirrus-config/modprobe.d/rpi-cirrus.conf @@ -0,0 +1 @@ +softdep arizona-spi pre: arizona-ldo1 diff --git a/packages/audio/rpi-cirrus-config/package.mk b/packages/audio/rpi-cirrus-config/package.mk new file mode 100644 index 000000000..d775489fd --- /dev/null +++ b/packages/audio/rpi-cirrus-config/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rpi-cirrus-config" +PKG_VERSION="0.0.2" +PKG_SHA256="cc11c47f1f2b6d5e72dcdea828ba57e0dcaf74161f675a4a9f395054f5d82d31" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/HiassofT/rpi-cirrus-config" +PKG_URL="https://github.com/HiassofT/rpi-cirrus-config/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="alsa-utils" +PKG_LONGDESC="Config scripts for the Wolfson/Cirrus Logic audio card" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/udev + install -m 0755 $PKG_DIR/scripts/rpi-cirrus-config $INSTALL/usr/lib/udev/rpi-cirrus-config + + mkdir -p $INSTALL/usr/share/alsa/cards + cp alsa/RPiCirrus.conf $INSTALL/usr/share/alsa/cards + + mkdir -p $INSTALL/usr/lib/alsa + cp mixer-scripts/rpi-cirrus-functions.sh $INSTALL/usr/lib/alsa + + mkdir -p $INSTALL/usr/config + cp -PR $PKG_DIR/config/* $INSTALL/usr/config +} diff --git a/packages/audio/rpi-cirrus-config/scripts/rpi-cirrus-config b/packages/audio/rpi-cirrus-config/scripts/rpi-cirrus-config new file mode 100755 index 000000000..d8bda0b07 --- /dev/null +++ b/packages/audio/rpi-cirrus-config/scripts/rpi-cirrus-config @@ -0,0 +1,24 @@ +#!/bin/sh + +# setup default mixer settings for Cirrus Logic Audio Card + +. /etc/profile + +if [ -f $HOME/.config/sound.conf ] ; then + alsactl restore -f $HOME/.config/sound.conf +else + if [ -r $HOME/.config/rpi-cirrus-config.sh ] ; then + progress "Setting up Cirrus Logic Audio Card with user config" + sh $HOME/.config/rpi-cirrus-config.sh + else + progress "Setting up Cirrus Logic Audio Card" + + # load helper functions and definitions + . /usr/lib/alsa/rpi-cirrus-functions.sh + + playback_to_spdif + playback_to_lineout + playback_to_headset + mixer 'Noise Gate Switch' off + fi +fi diff --git a/packages/audio/rpi-cirrus-config/udev.d/90-alsa-restore.rules b/packages/audio/rpi-cirrus-config/udev.d/90-alsa-restore.rules new file mode 100644 index 000000000..283dc4c8b --- /dev/null +++ b/packages/audio/rpi-cirrus-config/udev.d/90-alsa-restore.rules @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +# When a sound device is detected, restore the volume settings +SUBSYSTEM=="sound", KERNEL=="controlC*", NAME="snd/%k", ACTION=="add", GOTO="alsa_restore_go" +GOTO="alsa_restore_end" + +LABEL="alsa_restore_go" + +# Separate config-script for RPi-Cirrus card +DRIVERS=="snd-rpi-cirrus", RUN+="rpi-cirrus-config", GOTO="alsa_restore_end" + +# Default config-script for all other cards +RUN+="soundconfig %k" + +LABEL="alsa_restore_end" + diff --git a/packages/audio/sbc/package.mk b/packages/audio/sbc/package.mk new file mode 100644 index 000000000..0735e4938 --- /dev/null +++ b/packages/audio/sbc/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sbc" +PKG_VERSION="1.4" +PKG_SHA256="050058cfc5a2709d324868ddbb82f9b796ba6c4f5e00cb6a715b3841ee13dfe9" +PKG_LICENSE="GPL" +PKG_SITE="http://www.bluez.org/" +PKG_URL="http://www.kernel.org/pub/linux/bluetooth/sbc-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="standalone SBC library" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-tools \ + --disable-tester" diff --git a/packages/audio/sidplay-libs/package.mk b/packages/audio/sidplay-libs/package.mk new file mode 100644 index 000000000..f958ed1c8 --- /dev/null +++ b/packages/audio/sidplay-libs/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="sidplay-libs" +PKG_VERSION="2.1.1" +PKG_SHA256="e9a24ada48215a46d2c232a70c5601bc9505e997f120e8f2ba3713e09e28d1f9" +PKG_LICENSE="GPL" +PKG_SITE="http://sidplay2.sourceforge.net/" +PKG_URL="http://mirrors.xbmc.org/build-deps/sources/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="sidplay-libs" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared --enable-static" + +pre_configure_target() { + # fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME + + export CXXFLAGS="$CXXFLAGS -Wno-narrowing" +} diff --git a/packages/audio/sidplay-libs/patches/sidplay-libs-01-m4-tests.patch b/packages/audio/sidplay-libs/patches/sidplay-libs-01-m4-tests.patch new file mode 100644 index 000000000..88592b0b7 --- /dev/null +++ b/packages/audio/sidplay-libs/patches/sidplay-libs-01-m4-tests.patch @@ -0,0 +1,26 @@ +--- sidplay-libs-2.1.1/libsidplay/unix/my_macros.m4.orig 2004-06-14 22:08:04.000000000 +0200 ++++ sidplay-libs-2.1.1/libsidplay/unix/my_macros.m4 2013-11-18 01:23:32.195297135 +0100 +@@ -80,8 +80,8 @@ + AC_CACHE_VAL(test_cv_have_ios_binary, + [ + AC_TRY_COMPILE( +- [#include ], +- [ifstream myTest(ios::in|ios::binary);], ++ [#include ], ++ [std::ifstream myTest(std::ios::in|std::ios::binary);], + [test_cv_have_ios_binary=yes], + [test_cv_have_ios_binary=no] + ) +@@ -105,9 +105,9 @@ + AC_CACHE_VAL(test_cv_have_ios_openmode, + [ + AC_TRY_COMPILE( +- [#include +- #include ], +- [ios::openmode myTest = ios::in;], ++ [#include ++ #include ], ++ [std::ios_base::openmode myTest = std::ios::in;], + [test_cv_have_ios_openmode=yes], + [test_cv_have_ios_openmode=no] + ) diff --git a/packages/audio/sidplay-libs/patches/sidplay-libs-02-inherited.patch b/packages/audio/sidplay-libs/patches/sidplay-libs-02-inherited.patch new file mode 100644 index 000000000..0e86eedf8 --- /dev/null +++ b/packages/audio/sidplay-libs/patches/sidplay-libs-02-inherited.patch @@ -0,0 +1,26 @@ +--- sidplay-libs-2.1.1/libsidplay/include/sidplay/SmartPtr.h.old 2013-11-18 00:40:16.679173012 +0100 ++++ sidplay-libs-2.1.1/libsidplay/include/sidplay/SmartPtr.h 2013-11-18 00:41:22.451176157 +0100 +@@ -211,16 +211,16 @@ + { + if ( bufferLen >= 1 ) + { +- pBufCurrent = ( bufBegin = buffer ); +- bufEnd = bufBegin + bufferLen; +- bufLen = bufferLen; +- status = true; ++ this->pBufCurrent = ( this->bufBegin = buffer ); ++ this->bufEnd = this->bufBegin + bufferLen; ++ this->bufLen = bufferLen; ++ this->status = true; + } + else + { +- pBufCurrent = bufBegin = bufEnd = 0; +- bufLen = 0; +- status = false; ++ this->pBufCurrent = this->bufBegin = this->bufEnd = 0; ++ this->bufLen = 0; ++ this->status = false; + } + } + }; diff --git a/packages/audio/sidplay-libs/patches/sidplay-libs-03-operator.patch b/packages/audio/sidplay-libs/patches/sidplay-libs-03-operator.patch new file mode 100644 index 000000000..88af8ccd3 --- /dev/null +++ b/packages/audio/sidplay-libs/patches/sidplay-libs-03-operator.patch @@ -0,0 +1,11 @@ +--- sidplay-libs-2.1.1/libsidutils/include/sidplay/utils/SidUsage.h.orig 2013-11-18 00:58:06.111224154 +0100 ++++ sidplay-libs-2.1.1/libsidutils/include/sidplay/utils/SidUsage.h 2013-11-18 00:58:28.219225212 +0100 +@@ -33,7 +33,7 @@ + uint_least16_t length; // usage scan length + + // Copy common parts of basic usage to extended usage. +- sid2_usage_t &sid2_usage_t::operator= (const sid_usage_t &usage) ++ sid2_usage_t &operator= (const sid_usage_t &usage) + { + *((sid_usage_t *) this) = usage; + return *this; diff --git a/packages/audio/sidplay-libs/patches/sidplay-libs-04-includes.patch b/packages/audio/sidplay-libs/patches/sidplay-libs-04-includes.patch new file mode 100644 index 000000000..ef9cf0601 --- /dev/null +++ b/packages/audio/sidplay-libs/patches/sidplay-libs-04-includes.patch @@ -0,0 +1,30 @@ +--- sidplay-libs-2.1.1/builders/hardsid-builder/src/hardsid-builder.cpp.orig 2004-06-14 22:07:57.000000000 +0200 ++++ sidplay-libs-2.1.1/builders/hardsid-builder/src/hardsid-builder.cpp 2013-11-18 01:01:50.399234880 +0100 +@@ -55,6 +55,7 @@ + + #include "hardsid.h" + #include "hardsid-emu.h" ++#include + + + #ifdef HAVE_MSWINDOWS +--- sidplay-libs-2.1.1/builders/resid-builder/src/resid.cpp.orig 2013-11-18 01:00:07.827229975 +0100 ++++ sidplay-libs-2.1.1/builders/resid-builder/src/resid.cpp 2013-11-18 01:00:21.563230632 +0100 +@@ -24,6 +24,7 @@ + + #include "resid.h" + #include "resid-emu.h" ++#include + + + char ReSID::m_credit[]; +--- sidplay-libs-2.1.1/builders/resid-builder/src/resid-builder.cpp.orig 2013-11-18 01:00:39.727231501 +0100 ++++ sidplay-libs-2.1.1/builders/resid-builder/src/resid-builder.cpp 2013-11-18 01:00:57.415232346 +0100 +@@ -45,6 +45,7 @@ + + #include "resid.h" + #include "resid-emu.h" ++#include + + // Error String(s) + const char *ReSIDBuilder::ERR_FILTER_DEFINITION = "RESID ERROR: Filter definition is not valid (see docs)."; diff --git a/packages/audio/soxr/package.mk b/packages/audio/soxr/package.mk new file mode 100644 index 000000000..29d9ab454 --- /dev/null +++ b/packages/audio/soxr/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="soxr" +PKG_VERSION="0.1.3" +PKG_SHA256="b111c15fdc8c029989330ff559184198c161100a59312f5dc19ddeb9b5a15889" +PKG_LICENSE="LGPL" +PKG_SITE="https://sourceforge.net/projects/soxr/" +PKG_URL="$SOURCEFORGE_SRC/soxr/soxr-$PKG_VERSION-Source.tar.xz" +PKG_DEPENDS_TARGET="toolchain cmake:host" +PKG_LONGDESC="The SoX Resampler library performs one-dimensional sample-rate conversion. It may be used to resample PCM-encoded audio." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_EXAMPLES=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTS=OFF \ + -DWITH_OPENMP=OFF \ + -DWITH_AVFFT=OFF" + +if [ "$TARGET_ARCH" = "arm" ]; then + if target_has_feature neon; then + PKG_CMAKE_OPTS_TARGET+=" -DWITH_CR32=OFF" + else + PKG_CMAKE_OPTS_TARGET+=" -DWITH_CR32S=OFF" + fi +fi + diff --git a/packages/audio/soxr/patches/0001-Add-Libs.private-for-static-linking.patch b/packages/audio/soxr/patches/0001-Add-Libs.private-for-static-linking.patch new file mode 100644 index 000000000..be96c6e64 --- /dev/null +++ b/packages/audio/soxr/patches/0001-Add-Libs.private-for-static-linking.patch @@ -0,0 +1,43 @@ +From 7d2d1039f303b6322ecb72eebae39b699fd28d19 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Krause?= +Date: Fri, 22 Feb 2019 01:31:11 +0100 +Subject: [PATCH] Add Libs.private in soxr.pc.in for static linking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If libsoxr is build statically against libavutil other applications +needs to know that they must link with `-lavutil` when building in a +static context. + +Signed-off-by: Jörg Krause +--- + CMakeLists.txt | 1 + + src/soxr.pc.in | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ee48f6c..714bd4d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -139,6 +139,7 @@ if (WITH_AVFFT OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND SIMD32_FOUND AND WI + if (AVUTIL_FOUND) + include_directories (${AVUTIL_INCLUDE_DIRS}) + set (LIBS ${LIBS} ${AVUTIL_LIBRARIES}) ++ set (PKGCONF_LIBS_PRIV ${PKGCONF_LIBS_PRIV} -lavutil) + endif () + endif () + +diff --git a/src/soxr.pc.in b/src/soxr.pc.in +index 69d225b..6c530a6 100644 +--- a/src/soxr.pc.in ++++ b/src/soxr.pc.in +@@ -2,4 +2,5 @@ Name: ${PROJECT_NAME} + Description: ${DESCRIPTION_SUMMARY} + Version: ${PROJECT_VERSION} + Libs: -L${LIB_INSTALL_DIR} -l${PROJECT_NAME} ++Libs.private: ${PKGCONF_LIBS_PRIV} + Cflags: -I${INCLUDE_INSTALL_DIR} +-- +2.20.1 + diff --git a/packages/audio/speex/package.mk b/packages/audio/speex/package.mk new file mode 100644 index 000000000..c82149536 --- /dev/null +++ b/packages/audio/speex/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="speex" +PKG_VERSION="1.2.0" +PKG_SHA256="eaae8af0ac742dc7d542c9439ac72f1f385ce838392dc849cae4536af9210094" +PKG_LICENSE="BSD" +PKG_SITE="https://speex.org" +PKG_URL="http://downloads.us.xiph.org/releases/speex/speex-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="An Open Source Software patent-free audio compression format designed for speech." diff --git a/packages/audio/speexdsp/package.mk b/packages/audio/speexdsp/package.mk new file mode 100644 index 000000000..18accd9a2 --- /dev/null +++ b/packages/audio/speexdsp/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="speexdsp" +PKG_VERSION="1.2.0" +PKG_SHA256="682042fc6f9bee6294ec453f470dadc26c6ff29b9c9e9ad2ffc1f4312fd64771" +PKG_LICENSE="BSD" +PKG_SITE="https://speex.org" +PKG_URL="http://downloads.us.xiph.org/releases/speex/speexdsp-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Speex audio processing library" diff --git a/packages/audio/taglib/package.mk b/packages/audio/taglib/package.mk new file mode 100644 index 000000000..3f695bcad --- /dev/null +++ b/packages/audio/taglib/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="taglib" +PKG_VERSION="1.11.1" +PKG_SHA256="b6d1a5a610aae6ff39d93de5efd0fdc787aa9e9dc1e7026fa4c961b26563526b" +PKG_LICENSE="LGPL" +PKG_SITE="http://taglib.github.com/" +PKG_URL="http://taglib.github.io/releases/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain cmake:host zlib" +PKG_LONGDESC="TagLib is a library for reading and editing the meta-data of several popular audio formats." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=OFF \ + -DWITH_MP4=ON \ + -DWITH_ASF=ON" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin + # pkgconf hack + sed -e "s:\(['=\" ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/bin/taglib-config + sed -e "s:\([':\" ]\)-I/usr:\\1-I$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/lib/pkgconfig/taglib.pc + sed -e "s:\([':\" ]\)-L/usr:\\1-L$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/lib/pkgconfig/taglib.pc + sed -e "s:\([':\" ]\)-I/usr:\\1-I$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/lib/pkgconfig/taglib_c.pc + sed -e "s:\([':\" ]\)-L/usr:\\1-L$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/lib/pkgconfig/taglib_c.pc +} diff --git a/packages/audio/taglib/patches/taglib-01-efficient_lookup_for_an_ID3v2_tag_in_MPEG_files_with_garbage.patch b/packages/audio/taglib/patches/taglib-01-efficient_lookup_for_an_ID3v2_tag_in_MPEG_files_with_garbage.patch new file mode 100644 index 000000000..b31cf6a08 --- /dev/null +++ b/packages/audio/taglib/patches/taglib-01-efficient_lookup_for_an_ID3v2_tag_in_MPEG_files_with_garbage.patch @@ -0,0 +1,72 @@ +From d2e0e5522308ce4c905c205c7bf5972ea71cd6e5 Mon Sep 17 00:00:00 2001 +From: Tsuda Kageyu +Date: Fri, 20 Jan 2017 21:14:38 +0900 +Subject: [PATCH] Efficient lookup for an ID3v2 tag in MPEG files with garbage. + +This looks for an ID3v2 tag until reaching the first valid MPEG frame in O(n) time. +--- + taglib/mpeg/mpegfile.cpp | 45 +++++++++++++++++++++++++++++---------------- + 1 file changed, 29 insertions(+), 16 deletions(-) + +diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp +index af7253f..c634eeb 100644 +--- a/taglib/mpeg/mpegfile.cpp ++++ b/taglib/mpeg/mpegfile.cpp +@@ -488,28 +488,41 @@ long MPEG::File::findID3v2() + const ByteVector headerID = ID3v2::Header::fileIdentifier(); + + seek(0); ++ if(readBlock(headerID.size()) == headerID) ++ return 0; + +- const ByteVector data = readBlock(headerID.size()); +- if(data.size() < headerID.size()) ++ Header firstHeader(this, 0, true); ++ if(firstHeader.isValid()) + return -1; + +- if(data == headerID) +- return 0; ++ // Look for an ID3v2 tag until reaching the first valid MPEG frame. + +- if(firstSyncByte(data[0]) && secondSynchByte(data[1])) +- return -1; ++ char frameSyncBytes[2] = {}; ++ char tagHeaderBytes[4] = {}; ++ long position = 0; + +- // Look for the entire file, if neither an MEPG frame or ID3v2 tag was found +- // at the beginning of the file. +- // We don't care about the inefficiency of the code, since this is a seldom case. ++ while(true) { ++ seek(position); ++ const ByteVector buffer = readBlock(bufferSize()); ++ if(buffer.isEmpty()) ++ return -1; + +- const long tagOffset = find(headerID); +- if(tagOffset < 0) +- return -1; ++ for(unsigned int i = 0; i < buffer.size(); ++i) { ++ frameSyncBytes[0] = frameSyncBytes[1]; ++ frameSyncBytes[1] = buffer[i]; ++ if(firstSyncByte(frameSyncBytes[0]) && secondSynchByte(frameSyncBytes[1])) { ++ Header header(this, position + i - 1, true); ++ if(header.isValid()) ++ return -1; ++ } + +- const long frameOffset = firstFrameOffset(); +- if(frameOffset < tagOffset) +- return -1; ++ tagHeaderBytes[0] = tagHeaderBytes[1]; ++ tagHeaderBytes[1] = tagHeaderBytes[2]; ++ tagHeaderBytes[2] = buffer[i]; ++ if(headerID == tagHeaderBytes) ++ return position + i - 2; ++ } + +- return tagOffset; ++ position += bufferSize(); ++ } + } diff --git a/packages/compat/lib32/package.mk b/packages/compat/lib32/package.mk new file mode 100644 index 000000000..fd06e20d4 --- /dev/null +++ b/packages/compat/lib32/package.mk @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="lib32" +PKG_VERSION="${OS_VERSION}" +PKG_ARCH="aarch64" +PKG_LICENSE="GPLv2" +PKG_DEPENDS_TARGET="toolchain retroarch SDL2 libsndfile libmodplug" +PKG_SHORTDESC="ARM 32bit bundle for aarch64" +PKG_PRIORITY="optional" +PKG_TOOLCHAIN="manual" +MALIVERSION="1.9.0" + +makeinstall_target() { + cd ${PKG_BUILD} + LIBROOT="${PKG_BUILD}/../../build.${DISTRO}-${DEVICE}.arm/image/system/" + if [ "${ARCH}" = "aarch64" ]; then + mkdir -p ${INSTALL}/usr/lib32 + LIBS="ld-2 \ + ld-linux-armhf \ + libarmmem-v7l \ + librt \ + libass \ + libasound \ + libopenal \ + libpulse \ + libfreetype \ + libpthread \ + libudev.so \ + libusb-1.0 \ + libSDL2 \ + libmodplug \ + libsndfile \ + libavcodec \ + libavformat \ + libavutil \ + libswscale \ + libswresample \ + libstdc++ \ + libm \ + libgcc_s \ + libc \ + libfontconfig \ + libexpat \ + libbz2 \ + libz \ + libpulsecommon-12 \ + libdbus-1 \ + libdav1d \ + libspeex \ + libssl \ + libcrypt \ + libsystemd \ + libncurses \ + libdl \ + libdrm \ + librga \ + libpng \ + libgo2 \ + libevdev \ + librockchip_mpp \ + libxkbcommon \ + libresolv \ + libnss_dns \ + libpthread \ + libGLES \ + libgnutls \ + libgbm \ + libidn2 \ + libnettle \ + libhogweed \ + libgmp \ + libuuid.so \ + libMaliOpenCL \ + libEG" + + for lib in ${LIBS} + do + find ${LIBROOT}/usr/lib -name ${lib}* -exec cp -vP \{} ${INSTALL}/usr/lib32 \; + done + cp -f ${LIBROOT}/usr/lib/${MALIDRIVER}.so ${INSTALL}/usr/lib32 + ln -sf ${MALIDRIVER}.so ${INSTALL}/usr/lib32/libmali.so.${MALIVERSION} + ln -sf libmali.so.${MALIVERSION} ${INSTALL}/usr/lib32/libmali.so.1 + ln -sf libmali.so.1 ${INSTALL}/usr/lib32/libmali.so + chmod -f +x ${INSTALL}/usr/lib32/* || : + fi + mkdir -p ${INSTALL}/usr/lib + ln -s /usr/lib32/ld-linux-armhf.so.3 ${INSTALL}/usr/lib/ld-linux-armhf.so.3 +} diff --git a/packages/compress/bzip2/package.mk b/packages/compress/bzip2/package.mk new file mode 100644 index 000000000..ac9ac5d3f --- /dev/null +++ b/packages/compress/bzip2/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bzip2" +PKG_VERSION="1.0.8" +PKG_SHA256="ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269" +PKG_LICENSE="GPL" +PKG_SITE="https://sourceware.org/bzip2/" +PKG_URL="https://sourceware.org/pub/bzip2/bzip2-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A high-quality bzip2 data compressor." +PKG_BUILD_FLAGS="+pic +pic:host" + +pre_build_host() { + mkdir -p ${PKG_BUILD}/.${HOST_NAME} + cp -r ${PKG_BUILD}/* ${PKG_BUILD}/.${HOST_NAME} +} + +make_host() { + cd ${PKG_BUILD}/.${HOST_NAME} + make -f Makefile-libbz2_so CC=${HOST_CC} CFLAGS="${CFLAGS}" +} + +makeinstall_host() { + make install PREFIX=${TOOLCHAIN} +} + +pre_build_target() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -r ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} + +pre_make_target() { + cd ${PKG_BUILD}/.${TARGET_NAME} + sed -e "s,ln -s (lib.*),ln -snf \$${1}; ln -snf libbz2.so.${PKG_VERSION} libbz2.so,g" -i Makefile-libbz2_so +} + +make_target() { + make -f Makefile-libbz2_so CC=${CC} CFLAGS="${CFLAGS}" +} + +post_make_target() { + ln -snf libbz2.so.1.0 libbz2.so +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/include + cp bzlib.h ${SYSROOT_PREFIX}/usr/include + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp -P libbz2.so* ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${INSTALL}/usr/lib + cp -P libbz2.so* ${INSTALL}/usr/lib +} diff --git a/packages/compress/bzip2/patches/bzip2-1.0.8-cflags.patch b/packages/compress/bzip2/patches/bzip2-1.0.8-cflags.patch new file mode 100644 index 000000000..b46d56c66 --- /dev/null +++ b/packages/compress/bzip2/patches/bzip2-1.0.8-cflags.patch @@ -0,0 +1,11 @@ +--- bzip2-1.0.8/Makefile-libbz2_so.orig 2019-07-28 09:43:16.597589341 +0200 ++++ bzip2-1.0.8/Makefile-libbz2_so 2019-07-28 09:53:41.142160730 +0200 +@@ -35,7 +35,7 @@ + bzlib.o + + all: $(OBJS) +- $(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.8 $(OBJS) ++ $(CC) $(CFLAGS) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.8 $(OBJS) + $(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.8 + rm -f libbz2.so.1.0 + ln -s libbz2.so.1.0.8 libbz2.so.1.0 diff --git a/packages/compress/cpio/package.mk b/packages/compress/cpio/package.mk new file mode 100644 index 000000000..bbe40b516 --- /dev/null +++ b/packages/compress/cpio/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="cpio" +PKG_VERSION="2.12" +PKG_SHA256="08a35e92deb3c85d269a0059a27d4140a9667a6369459299d08c17f713a92e73" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/cpio/" +PKG_URL="http://ftpmirror.gnu.org/cpio/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_LONGDESC="A program to manage archives of files." diff --git a/packages/compress/cpio/patches/0001-Minor-fix.patch b/packages/compress/cpio/patches/0001-Minor-fix.patch new file mode 100644 index 000000000..429df7d5f --- /dev/null +++ b/packages/compress/cpio/patches/0001-Minor-fix.patch @@ -0,0 +1,30 @@ +From 641d3f489cf6238bb916368d4ba0d9325a235afb Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Mon, 20 Jan 2020 07:45:39 +0200 +Subject: Minor fix * src/global.c: Remove superfluous declaration of + program_name + +[Retrieved from: +https://git.savannah.gnu.org/cgit/cpio.git/commit/?id=641d3f489cf6238bb916368d4ba0d9325a235afb] +Signed-off-by: Fabrice Fontaine +--- + src/global.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/global.c b/src/global.c +index fb3abe9..acf92bc 100644 +--- a/src/global.c ++++ b/src/global.c +@@ -184,9 +184,6 @@ unsigned int warn_option = 0; + /* Extract to standard output? */ + bool to_stdout_option = false; + +-/* The name this program was run with. */ +-char *program_name; +- + /* A pointer to either lstat or stat, depending on whether + dereferencing of symlinks is done for input files. */ + int (*xstat) (); +-- +cgit v1.2.1 + diff --git a/packages/compress/gzip/package.mk b/packages/compress/gzip/package.mk new file mode 100644 index 000000000..94a9c5817 --- /dev/null +++ b/packages/compress/gzip/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="gzip" +PKG_VERSION="1.10" +PKG_SHA256="8425ccac99872d544d4310305f915f5ea81e04d0f437ef1a230dc9d1c819d7c0" +PKG_LICENSE="GPL" +PKG_SITE="https://ftp.gnu.org/gnu/gzip" +PKG_URL="https://ftp.gnu.org/gnu/gzip/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="gcc:host" +PKG_LONGDESC="GNU Gzip is a popular data compression program originally written by Jean-loup Gailly for the GNU project." + diff --git a/packages/compress/libarchive/package.mk b/packages/compress/libarchive/package.mk new file mode 100644 index 000000000..31e05445f --- /dev/null +++ b/packages/compress/libarchive/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libarchive" +PKG_VERSION="3.5.1" +PKG_SHA256="0e17d3a8d0b206018693b27f08029b598f6ef03600c2b5d10c94ce58692e299b" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libarchive.org" +PKG_URL="https://www.libarchive.org/downloads/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_SHORTDESC="A multi-format archive and compression library." + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_POSITION_INDEPENDENT_CODE=1 \ + -DENABLE_EXPAT=0 \ + -DENABLE_ICONV=0 \ + -DENABLE_LIBXML2=0 \ + -DENABLE_LZO=1 \ + -DENABLE_TEST=0 \ + -DENABLE_COVERAGE=0 \ + -DENABLE_WERROR=0" + +post_makeinstall_target() { + rm -rf ${INSTALL} + + # delete the shared library as we only want static + rm ${SYSROOT_PREFIX}/usr/lib/libarchive.so* +} diff --git a/packages/compress/libzip/package.mk b/packages/compress/libzip/package.mk new file mode 100644 index 000000000..587fbaacd --- /dev/null +++ b/packages/compress/libzip/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libzip" +PKG_VERSION="0.11.2" +PKG_SHA256="7cfbbc2c540e154b933b6e9ec781e2671086bd8114eb744ae1a1ade34d2bb6bb" +PKG_LICENSE="GPL" +PKG_SITE="http://www.nih.at/libzip/" +PKG_URL="http://www.nih.at/libzip/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="A C library for reading, creating, and modifying zip archives." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared --enable-static" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin + rm -rf $INSTALL/usr/lib +} diff --git a/packages/compress/lz4/package.mk b/packages/compress/lz4/package.mk new file mode 100644 index 000000000..bcc4b79aa --- /dev/null +++ b/packages/compress/lz4/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lz4" +PKG_VERSION="1.9.3" +PKG_SHA256="030644df4611007ff7dc962d981f390361e6c97a34e5cbc393ddfbe019ffe2c1" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lz4/lz4" +PKG_URL="https://github.com/lz4/lz4/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="lz4 data compressor/decompressor" +PKG_TOOLCHAIN="cmake" + +configure_package() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/build/cmake/CMakeLists.txt" + + PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=0" +} + +post_makeinstall_target() { + rm -rf ${INSTALL} +} diff --git a/packages/compress/lzo/package.mk b/packages/compress/lzo/package.mk new file mode 100644 index 000000000..dc0ed3bb7 --- /dev/null +++ b/packages/compress/lzo/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="lzo" +PKG_VERSION="2.10" +PKG_SHA256="c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072" +PKG_LICENSE="GPL" +PKG_SITE="http://www.oberhumer.com/opensource/lzo" +PKG_URL="http://www.oberhumer.com/opensource/lzo/download/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A data compression library which is suitable for data de-/compression." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_HOST="-DENABLE_SHARED=OFF -DENABLE_STATIC=ON" +PKG_CMAKE_OPTS_TARGET="-DENABLE_SHARED=OFF -DENABLE_STATIC=ON" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/libexec +} diff --git a/packages/compress/minizip/package.mk b/packages/compress/minizip/package.mk new file mode 100644 index 000000000..e9e6a4c30 --- /dev/null +++ b/packages/compress/minizip/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="minizip" +PKG_VERSION="2.8.8" +PKG_SHA256="a551063636ae4f989baefc6a20870f5b28246052a372a2ce124ebf3f66018db0" +PKG_LICENSE="zlib" +PKG_SITE="https://github.com/nmoinvaz/minizip" +PKG_URL="https://github.com/nmoinvaz/minizip/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="zlib" +PKG_LONGDESC="Minizip zlib contribution fork with latest bug fixes" + +PKG_CMAKE_OPTS_TARGET="-DUSE_AES=OFF \ + -DBUILD_TEST=ON" + +makeinstall_target() { + cp -v miniunz_exec $SYSROOT_PREFIX/usr/bin/miniunz + cp -v minizip_exec $SYSROOT_PREFIX/usr/bin/minizip +} diff --git a/packages/compress/p7zip/package.mk b/packages/compress/p7zip/package.mk new file mode 100644 index 000000000..aaff58002 --- /dev/null +++ b/packages/compress/p7zip/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="p7zip" +PKG_VERSION="16.02" +PKG_SHA256="5eb20ac0e2944f6cb9c2d51dd6c4518941c185347d4089ea89087ffdd6e2341f" +PKG_LICENSE="GPL" +PKG_SITE="http://p7zip.sourceforge.net/" +PKG_URL="http://downloads.sourceforge.net/project/p7zip/p7zip/${PKG_VERSION}/p7zip_${PKG_VERSION}_src_all.tar.bz2" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="p7zip is a port of 7za.exe for POSIX systems like Unix." +PKG_TOOLCHAIN="manual" + +make_host() { + make CXX=$CXX CC=$CC 7za +} + +make_target() { + make CXX=$CXX CC=$CC 7z 7za 7zr +} + +makeinstall_host() { + mkdir -p $TOOLCHAIN/bin + cp bin/7za $TOOLCHAIN/bin +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp bin/7z bin/7za bin/7zr bin/7z.so $INSTALL/usr/bin +} diff --git a/packages/compress/p7zip/patches/0004-Fix-build-with-gcc-10.patch b/packages/compress/p7zip/patches/0004-Fix-build-with-gcc-10.patch new file mode 100644 index 000000000..b01833db2 --- /dev/null +++ b/packages/compress/p7zip/patches/0004-Fix-build-with-gcc-10.patch @@ -0,0 +1,32 @@ +From 78b760eae21d7b340c69e8abab8ca706e1e00adc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= +Date: Mon, 4 May 2020 09:19:46 +0200 +Subject: [PATCH] Fix build with gcc 10. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add cast to code that mixes HRESULT (aka long) and DWORD (aka unsigned +int) which causes an narrowing error with gcc 10. + +Signed-off-by: Stefan Sørensen +--- + CPP/Windows/ErrorMsg.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp +index 99684ae..ab48352 100644 +--- a/CPP/Windows/ErrorMsg.cpp ++++ b/CPP/Windows/ErrorMsg.cpp +@@ -13,7 +13,7 @@ UString MyFormatMessage(DWORD errorCode) + const char * txt = 0; + AString msg; + +- switch(errorCode) { ++ switch((HRESULT)errorCode) { + case ERROR_NO_MORE_FILES : txt = "No more files"; break ; + case E_NOTIMPL : txt = "E_NOTIMPL"; break ; + case E_NOINTERFACE : txt = "E_NOINTERFACE"; break ; +-- +2.26.2 + diff --git a/packages/compress/pigz/package.mk b/packages/compress/pigz/package.mk new file mode 100644 index 000000000..005a8861a --- /dev/null +++ b/packages/compress/pigz/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pigz" +PKG_VERSION="2.6" +PKG_SHA256="577673676cd5c7219f94b236075451220bae3e1ca451cf849947a2998fbf5820" +PKG_LICENSE="Other" +PKG_SITE="https://zlib.net/pigz/" +PKG_URL="https://github.com/madler/pigz/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="make:host zlib:host" +PKG_LONGDESC="a parallel implementation of the gzip file compressor" +PKG_TOOLCHAIN="manual" + +make_host() { + make CPPFLAGS="${CPPFLAGS} -I${TOOLCHAIN}/include" \ + LDFLAGS="${LDFLAGS}" \ + CXX="${CXX}" \ + CC="${CC}" \ + pigz +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp pigz ${TOOLCHAIN}/bin +} \ No newline at end of file diff --git a/packages/compress/unzip/package.mk b/packages/compress/unzip/package.mk new file mode 100644 index 000000000..0ddca31ed --- /dev/null +++ b/packages/compress/unzip/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="unzip" +PKG_VERSION="60" +PKG_SHA256="036d96991646d0449ed0aa952e4fbe21b476ce994abc276e49d30e686708bd37" +PKG_LICENSE="OSS" +PKG_SITE="http://www.info-zip.org/pub/infozip/" +PKG_URL="http://ftp.uk.i-scream.org/sites/www.ibiblio.org/gentoo/distfiles/$PKG_NAME$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="UnZip is an extraction utility for archives compressed in .zip format." +PKG_TOOLCHAIN="manual" + +make_target() { + make CC=$CC RANLIB=$RANLIB AR=$AR STRIP=$STRIP \ + -f unix/Makefile generic LOCAL_UNZIP="$CFLAGS" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp unzip $INSTALL/usr/bin + $STRIP $INSTALL/usr/bin/unzip +} diff --git a/packages/compress/xz/package.mk b/packages/compress/xz/package.mk new file mode 100644 index 000000000..41b48c1ac --- /dev/null +++ b/packages/compress/xz/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xz" +PKG_VERSION="5.2.5" +PKG_SHA256="5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df" +PKG_LICENSE="GPL" +PKG_SITE="http://tukaani.org/xz/" +PKG_URL="http://tukaani.org/xz/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A free general-purpose data compression software with high compression ratio." +PKG_BUILD_FLAGS="+pic +pic:host" + +# never build shared or k0p happens when building +# on fedora due to host selinux/liblzma +PKG_CONFIGURE_OPTS_HOST="--disable-shared --enable-static \ + --disable-lzmadec \ + --disable-lzmainfo \ + --enable-lzma-links \ + --disable-scripts \ + --disable-nls" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared --enable-static" + +post_makeinstall_target() { + rm -rf ${INSTALL} +} diff --git a/packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch b/packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch new file mode 100644 index 000000000..0d8888070 --- /dev/null +++ b/packages/compress/xz/patches/xz-01-init-uninitialized-variables.patch @@ -0,0 +1,27 @@ +From 5cd389f1fe1fe095cdf555194df875ee3ab445cf Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sun, 26 Nov 2017 22:21:15 +0000 +Subject: [PATCH] uninitialized variables build error + +--- + src/liblzma/lzma/lzma_encoder.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/liblzma/lzma/lzma_encoder.c b/src/liblzma/lzma/lzma_encoder.c +index ba9ce69..08e8c87 100644 +--- a/src/liblzma/lzma/lzma_encoder.c ++++ b/src/liblzma/lzma/lzma_encoder.c +@@ -359,8 +359,8 @@ lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf, + // - UINT32_MAX: not a match but a literal + // Value ranges for len: + // - [MATCH_LEN_MIN, MATCH_LEN_MAX] +- uint32_t len; +- uint32_t back; ++ uint32_t len = 0; ++ uint32_t back = 0; + + if (coder->fast_mode) + lzma_lzma_optimum_fast(coder, mf, &back, &len); +-- +2.14.1 + diff --git a/packages/compress/zip/package.mk b/packages/compress/zip/package.mk new file mode 100644 index 000000000..7f2204afd --- /dev/null +++ b/packages/compress/zip/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="zip" +PKG_VERSION="3.0" +PKG_SHA256="f0e8bb1f9b7eb0b01285495a2699df3a4b766784c1765a8f1aeedf63c0806369" +PKG_LICENSE="Info-ZIP" +PKG_SITE="http://www.info-zip.org/pub/infozip/" +PKG_URL="${SOURCEFORGE_SRC}/infozip/Zip%203.x%20%28latest%29/3.0/${PKG_NAME}${PKG_VERSION/./}.tar.gz" +PKG_DEPENDS_TARGET="toolchain bzip2" +PKG_LONGDESC="A compression and file packaging utility." +PKG_TOOLCHAIN="manual" + +make_target() { + make CC=${CC} CPP=${CPP} RANLIB=${RANLIB} AR=${AR} STRIP=${STRIP} LOCAL_ZIP="${CFLAGS}" \ + -f unix/Makefile generic +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp zip ${INSTALL}/usr/bin + ${STRIP} ${INSTALL}/usr/bin/zip +} diff --git a/packages/compress/zlib/package.mk b/packages/compress/zlib/package.mk new file mode 100644 index 000000000..f39e64dee --- /dev/null +++ b/packages/compress/zlib/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="zlib" +PKG_VERSION="1.2.11" +PKG_SHA256="4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066" +PKG_LICENSE="OSS" +PKG_SITE="http://www.zlib.net" +PKG_URL="http://zlib.net/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="cmake:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A general purpose (ZIP) data compression library." +PKG_TOOLCHAIN="cmake-make" diff --git a/packages/compress/zstd/package.mk b/packages/compress/zstd/package.mk new file mode 100644 index 000000000..a39841934 --- /dev/null +++ b/packages/compress/zstd/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="zstd" +PKG_VERSION="1.5.0" +PKG_SHA256="5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94" +PKG_LICENSE="BSD/GPLv2" +PKG_SITE="http://www.zstd.net" +PKG_URL="https://github.com/facebook/zstd/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host ninja:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A fast real-time compression algorithm." +PKG_TOOLCHAIN="meson" + +configure_package() { + PKG_MESON_SCRIPT="${PKG_BUILD}/build/meson/meson.build" +} + +PKG_MESON_OPTS_HOST="-Dlegacy_level=0 \ + -Dbin_programs=false \ + -Dzlib=disabled \ + -Dlzma=disabled \ + -Dlz4=disabled" \ No newline at end of file diff --git a/packages/databases/mariadb-connector-c/package.mk b/packages/databases/mariadb-connector-c/package.mk new file mode 100644 index 000000000..2f0c31bd3 --- /dev/null +++ b/packages/databases/mariadb-connector-c/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mariadb-connector-c" +PKG_VERSION="3.1.1" +PKG_SHA256="63a0ecfa3c87ba0361aef3b2c849abe280f7371030e84f41ce0dc4466db85637" +PKG_LICENSE="LGPL" +PKG_SITE="https://mariadb.org/" +PKG_URL="https://github.com/MariaDB/mariadb-connector-c/archive/v$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_LONGDESC="mariadb-connector: library to conntect to mariadb/mysql database server" +PKG_BUILD_FLAGS="-gold" + +PKG_CMAKE_OPTS_TARGET="-DWITH_EXTERNAL_ZLIB=ON + -DAUTH_CLEARTEXT=STATIC + -DAUTH_DIALOG=STATIC + -DAUTH_OLDPASSWORD=STATIC + -DREMOTEIO=OFF + " + +post_makeinstall_target() { + # drop all unneeded + rm -rf $INSTALL/usr +} diff --git a/packages/databases/mysql/package.mk b/packages/databases/mysql/package.mk new file mode 100644 index 000000000..8ebc1fa81 --- /dev/null +++ b/packages/databases/mysql/package.mk @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mysql" +PKG_VERSION="5.7.20" +PKG_SHA256="5397549bb7c238f396c123db2df4cad2191b11adf8986de7fe63bff8e2786487" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.mysql.com" +PKG_URL="http://ftp.gwdg.de/pub/misc/$PKG_NAME/Downloads/MySQL-5.7/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="toolchain zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib ncurses openssl boost mysql:host" +PKG_LONGDESC="A SQL database server." + +PKG_CMAKE_OPTS_HOST="-DCMAKE_BUILD_TYPE=Release \ + -DSTACK_DIRECTION=-1 \ + -DHAVE_LLVM_LIBCPP_EXITCODE=0 \ + -DHAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE_EXITCODE=0 \ + -DWITHOUT_SERVER=OFF \ + -DWITH_EMBEDDED_SERVER=OFF \ + -DWITH_INNOBASE_STORAGE_ENGINE=OFF \ + -DWITH_PARTITION_STORAGE_ENGINE=OFF \ + -DWITH_PERFSCHEMA_STORAGE_ENGINE=OFF \ + -DWITH_EXTRA_CHARSETS=none \ + -DWITH_EDITLINE=bundled \ + -DWITH_LIBEVENT=bundled \ + -DDOWNLOAD_BOOST=0 \ + -DLOCAL_BOOST_DIR=$(get_build_dir boost) \ + -DWITH_UNIT_TESTS=OFF \ + -DWITH_ZLIB=bundled" + +PKG_CMAKE_OPTS_TARGET="-DINSTALL_INCLUDEDIR=include/mysql \ + -DCMAKE_BUILD_TYPE=Release \ + -DFEATURE_SET=classic \ + -DDISABLE_SHARED=ON \ + -DENABLE_DTRACE=OFF \ + -DWITH_EMBEDDED_SERVER=OFF \ + -DWITH_INNOBASE_STORAGE_ENGINE=OFF \ + -DWITH_PARTITION_STORAGE_ENGINE=OFF \ + -DWITH_PERFSCHEMA_STORAGE_ENGINE=OFF \ + -DWITH_EXTRA_CHARSETS=all \ + -DWITH_UNIT_TESTS=OFF \ + -DWITHOUT_SERVER=ON \ + -DWITH_EDITLINE=bundled \ + -DWITH_LIBEVENT=bundled \ + -DWITH_ZLIB=system \ + -DWITH_SSL=$SYSROOT_PREFIX/usr \ + -DDOWNLOAD_BOOST=0 \ + -DLOCAL_BOOST_DIR=$(get_build_dir boost) \ + -DSTACK_DIRECTION=1 \ + -DHAVE_LLVM_LIBCPP=1" + +post_unpack() { + sed -i 's|GET_TARGET_PROPERTY(LIBMYSQL_OS_OUTPUT_NAME libmysql OUTPUT_NAME)|SET(LIBMYSQL_OS_OUTPUT_NAME "mysqlclient")|' $PKG_BUILD/scripts/CMakeLists.txt + sed -i "s|COMMAND comp_err|COMMAND $TOOLCHAIN/bin/comp_err|" $PKG_BUILD/extra/CMakeLists.txt + sed -i "s|COMMAND comp_sql|COMMAND $TOOLCHAIN/bin/comp_sql|" $PKG_BUILD/scripts/CMakeLists.txt + sed -i "s|COMMAND gen_lex_hash|COMMAND $TOOLCHAIN/bin/gen_lex_hash|" $PKG_BUILD/sql/CMakeLists.txt + + sed -i '/^IF(NOT BOOST_MINOR_VERSION.*$/,/^ENDIF()$/d' $PKG_BUILD/cmake/boost.cmake +} + +make_host() { + ninja comp_err + ninja gen_lex_hash + ninja comp_sql +} + +post_make_host() { + # needed so the binary isn't built for target + cp scripts/comp_sql ../scripts/comp_sql +} + +makeinstall_host() { + cp -P extra/comp_err $TOOLCHAIN/bin + cp -P sql/gen_lex_hash $TOOLCHAIN/bin + cp -P scripts/comp_sql $TOOLCHAIN/bin +} + +post_makeinstall_target() { + sed -i "s|pkgincludedir=.*|pkgincludedir=\'$SYSROOT_PREFIX/usr/include/mysql\'|" scripts/mysql_config + sed -i "s|pkglibdir=.*|pkglibdir=\'$SYSROOT_PREFIX/usr/lib/mysql\'|" scripts/mysql_config + cp scripts/mysql_config $SYSROOT_PREFIX/usr/bin + cp scripts/mysql_config $TOOLCHAIN/bin/mysql_config + + rm -rf $INSTALL +} diff --git a/packages/databases/mysql/patches/mysql-0002-revert-floating-point-optimizations.patch b/packages/databases/mysql/patches/mysql-0002-revert-floating-point-optimizations.patch new file mode 100644 index 000000000..4c5aef58e --- /dev/null +++ b/packages/databases/mysql/patches/mysql-0002-revert-floating-point-optimizations.patch @@ -0,0 +1,38 @@ +diff -Naur a/cmake/build_configurations/compiler_options.cmake b/cmake/build_configurations/compiler_options.cmake +--- a/cmake/build_configurations/compiler_options.cmake 2016-12-19 09:18:07.169866414 +0000 ++++ b/cmake/build_configurations/compiler_options.cmake 2016-12-19 09:19:26.290338156 +0000 +@@ -15,8 +15,6 @@ + + INCLUDE(CheckCCompilerFlag) + INCLUDE(CheckCXXCompilerFlag) +-INCLUDE(cmake/compiler_bugs.cmake) +-INCLUDE(cmake/floating_point.cmake) + + IF(SIZEOF_VOIDP EQUAL 4) + SET(32BIT 1) +@@ -35,10 +33,6 @@ + IF(WITH_VALGRIND) + SET(COMMON_C_FLAGS "-fno-inline ${COMMON_C_FLAGS}") + ENDIF() +- # Disable expensive-optimization if shift-or-optimization bug effective +- IF(HAVE_C_SHIFT_OR_OPTIMIZATION_BUG) +- SET(C_NO_EXPENSIVE_OPTIMIZATIONS TRUE) +- ENDIF() + # Disable floating point expression contractions to avoid result differences + IF(HAVE_C_FLOATING_POINT_FUSED_MADD) + IF(HAVE_C_FP_CONTRACT_FLAG) +@@ -69,14 +63,6 @@ + IF(HAVE_CXX_SHIFT_OR_OPTIMIZATION_BUG) + SET(CXX_NO_EXPENSIVE_OPTIMIZATIONS TRUE) + ENDIF() +- # Disable floating point expression contractions to avoid result differences +- IF(HAVE_CXX_FLOATING_POINT_FUSED_MADD) +- IF(HAVE_CXX_FP_CONTRACT_FLAG) +- SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -ffp-contract=off") +- ELSE() +- SET(CXX_NO_EXPENSIVE_OPTIMIZATIONS TRUE) +- ENDIF() +- ENDIF() + IF(CXX_NO_EXPENSIVE_OPTIMIZATIONS) + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -fno-expensive-optimizations") + ENDIF() diff --git a/packages/databases/mysql/patches/mysql-0003-compile-comp_err-even-when-crosscompiling.patch b/packages/databases/mysql/patches/mysql-0003-compile-comp_err-even-when-crosscompiling.patch new file mode 100644 index 000000000..350f3b813 --- /dev/null +++ b/packages/databases/mysql/patches/mysql-0003-compile-comp_err-even-when-crosscompiling.patch @@ -0,0 +1,18 @@ +diff -Naur a/extra/CMakeLists.txt b/extra/CMakeLists.txt +--- a/extra/CMakeLists.txt 2016-09-21 23:16:59.458308368 -0700 ++++ b/extra/CMakeLists.txt 2016-09-21 23:17:34.187663318 -0700 +@@ -28,11 +28,9 @@ + # Default install component for the files is Server here + SET(MYSQL_INSTALL_COMPONENT Server) + +-IF(NOT CMAKE_CROSSCOMPILING) +- ADD_EXECUTABLE(comp_err comp_err.c) +- TARGET_LINK_LIBRARIES(comp_err mysys mysys_ssl) +- SET_TARGET_PROPERTIES(comp_err PROPERTIES LINKER_LANGUAGE CXX) +-ENDIF() ++ADD_EXECUTABLE(comp_err comp_err.c) ++TARGET_LINK_LIBRARIES(comp_err mysys mysys_ssl) ++SET_TARGET_PROPERTIES(comp_err PROPERTIES LINKER_LANGUAGE CXX) + + IF (BUILD_BUNDLED_LZ4) + ADD_CONVENIENCE_LIBRARY(lz4_lib diff --git a/packages/databases/mysql/patches/mysql-0004-compile-comp_sql-even-when-crosscompiling.patch b/packages/databases/mysql/patches/mysql-0004-compile-comp_sql-even-when-crosscompiling.patch new file mode 100644 index 000000000..e42f7b8f0 --- /dev/null +++ b/packages/databases/mysql/patches/mysql-0004-compile-comp_sql-even-when-crosscompiling.patch @@ -0,0 +1,17 @@ +diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt +index 1d0480b..425abb8 100644 +--- a/scripts/CMakeLists.txt ++++ b/scripts/CMakeLists.txt +@@ -14,10 +14,8 @@ + # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + # Build comp_sql - used for embedding SQL in C or C++ programs +-IF(NOT CMAKE_CROSSCOMPILING) +- ADD_EXECUTABLE(comp_sql comp_sql.c) +- TARGET_LINK_LIBRARIES(comp_sql) +-ENDIF() ++ADD_EXECUTABLE(comp_sql comp_sql.c) ++TARGET_LINK_LIBRARIES(comp_sql) + + # Add compiler information, for easier debugging of output from mysql_config. + SET(COMPILER_ID_AND_VERSION diff --git a/packages/databases/mysql/patches/mysql-0005-pchar-fix-in-client-authtentification.patch b/packages/databases/mysql/patches/mysql-0005-pchar-fix-in-client-authtentification.patch new file mode 100644 index 000000000..bbde74e71 --- /dev/null +++ b/packages/databases/mysql/patches/mysql-0005-pchar-fix-in-client-authtentification.patch @@ -0,0 +1,11 @@ +--- a/sql-common/client_authentication.cc 2017-05-06 16:38:34.349486565 +0200 ++++ b/sql-common/client_authentication.cc 2017-05-06 16:41:32.286431336 +0200 +@@ -84,7 +84,7 @@ + + if (mysql->options.extension != NULL && + mysql->options.extension->server_public_key_path != NULL && +- mysql->options.extension->server_public_key_path != '\0') ++ *(mysql->options.extension->server_public_key_path) != '\0') + { + pub_key_file= fopen(mysql->options.extension->server_public_key_path, + "r"); diff --git a/packages/databases/sqlite/package.mk b/packages/databases/sqlite/package.mk new file mode 100644 index 000000000..832ffd135 --- /dev/null +++ b/packages/databases/sqlite/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="sqlite" +PKG_VERSION="autoconf-3280000" +PKG_SHA256="d61b5286f062adfce5125eaf544d495300656908e61fca143517afcc0a89b7c3" +PKG_LICENSE="PublicDomain" +PKG_SITE="https://www.sqlite.org/" +PKG_URL="https://www.sqlite.org/2019/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="An Embeddable SQL Database Engine." +# libsqlite3.a(sqlite3.o): requires dynamic R_X86_64_PC32 reloc against 'sqlite3_stricmp' which may overflow at runtime +PKG_BUILD_FLAGS="+pic +pic:host -parallel" + +PKG_CONFIGURE_OPTS_TARGET="--disable-static \ + --enable-shared \ + --disable-readline \ + --enable-threadsafe \ + --enable-dynamic-extensions \ + --with-gnu-ld" + +pre_configure_target() { +# sqlite fails to compile with fast-math link time optimization. + CFLAGS=`echo $CFLAGS | sed -e "s|-Ofast|-O3|g"` + CFLAGS=`echo $CFLAGS | sed -e "s|-ffast-math||g"` + +# This option adds additional logic to the ANALYZE command and to the query planner +# that can help SQLite to chose a better query plan under certain situations. The +# ANALYZE command is enhanced to collect histogram data from each index and store +# that data in the sqlite_stat3 table. The query planner will then use the histogram +# data to help it make better index choices. + CFLAGS="$CFLAGS -DSQLITE_ENABLE_STAT3" + +# When this C-preprocessor macro is defined, SQLite includes some additional APIs +# that provide convenient access to meta-data about tables and queries. The APIs that +# are enabled by this option are: +# - sqlite3_column_database_name() +# - sqlite3_column_database_name16() +# - sqlite3_column_table_name() +# - sqlite3_column_table_name16() +# - sqlite3_column_origin_name() +# - sqlite3_column_origin_name16() +# - sqlite3_table_column_metadata() + CFLAGS="$CFLAGS -DSQLITE_ENABLE_COLUMN_METADATA=1" + +# This macro sets the default limit on the amount of memory that will be used for +# memory-mapped I/O for each open database file. If the N is zero, then memory +# mapped I/O is disabled by default. This compile-time limit and the +# SQLITE_MAX_MMAP_SIZE can be modified at start-time using the +# sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) call, or at run-time using the +# mmap_size pragma. + CFLAGS="$CFLAGS -DSQLITE_TEMP_STORE=3 -DSQLITE_DEFAULT_MMAP_SIZE=268435456" +} diff --git a/packages/databases/sqlite/patches/sqlite-01_map_populate.patch b/packages/databases/sqlite/patches/sqlite-01_map_populate.patch new file mode 100644 index 000000000..3797ae342 --- /dev/null +++ b/packages/databases/sqlite/patches/sqlite-01_map_populate.patch @@ -0,0 +1,22 @@ +diff --git a/sqlite3.c b/sqlite3.c +index d0057a6..63b80c7 100644 +--- a/sqlite3.c ++++ b/sqlite3.c +@@ -28278,7 +28278,7 @@ static void unixRemapfile( + pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); + zErr = "mremap"; + #else +- pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); ++ pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED | MAP_POPULATE, h, nReuse); + if( pNew!=MAP_FAILED ){ + if( pNew!=pReq ){ + osMunmap(pNew, nNew - nReuse); +@@ -28297,7 +28297,7 @@ static void unixRemapfile( + + /* If pNew is still NULL, try to create an entirely new mapping. */ + if( pNew==0 ){ +- pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0); ++ pNew = osMmap(0, nNew, flags, MAP_SHARED | MAP_POPULATE, h, 0); + } + + if( pNew==MAP_FAILED ){ diff --git a/packages/debug/apitrace/package.mk b/packages/debug/apitrace/package.mk new file mode 100644 index 000000000..19e5b080d --- /dev/null +++ b/packages/debug/apitrace/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="apitrace" +PKG_VERSION="2a83ddd4f67014e2aacf99c6b203fd3f6b13c4f3" +PKG_SHA256="1bd282e4784725258f99fd8a1147502ceb7db3d7315a4e7a37d8d14ed33d5881" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/apitrace/apitrace" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A set of tools to trace, replay, and inspect OpenGL calls" +GET_HANDLER_SUPPORT="git" + +PKG_CMAKE_OPTS_TARGET="-DENABLE_GUI=false -DENABLE_X11=false" diff --git a/packages/debug/apitrace/patches/001-no-x11.patch b/packages/debug/apitrace/patches/001-no-x11.patch new file mode 100644 index 000000000..1aa46c51a --- /dev/null +++ b/packages/debug/apitrace/patches/001-no-x11.patch @@ -0,0 +1,40 @@ +diff -rupN apitrace.orig/dispatch/glimports.hpp apitrace.new/dispatch/glimports.hpp +--- apitrace.orig/dispatch/glimports.hpp 2021-01-08 19:52:31.768258806 -0500 ++++ apitrace.new/dispatch/glimports.hpp 2021-01-08 19:55:45.511116819 -0500 +@@ -37,7 +37,7 @@ + # include + #elif defined(__APPLE__) + #elif defined(HAVE_X11) +-# include ++//# include + #endif /* !_WIN32 */ + + +diff -rupN apitrace.orig/thirdparty/khronos/EGL/eglplatform.h apitrace.new/thirdparty/khronos/EGL/eglplatform.h +--- apitrace.orig/thirdparty/khronos/EGL/eglplatform.h 2021-01-08 19:52:31.792259353 -0500 ++++ apitrace.new/thirdparty/khronos/EGL/eglplatform.h 2021-01-08 19:58:22.843613539 -0500 +@@ -125,8 +125,8 @@ typedef khronos_uintptr_t EGLNativeWindo + #elif defined(__unix__) || defined(USE_X11) + + /* X11 (tentative) */ +-#include +-#include ++//#include ++//#include + + typedef Display *EGLNativeDisplayType; + typedef Pixmap EGLNativePixmapType; +diff -rupN apitrace.orig/thirdparty/khronos/GL/glx.h apitrace.new/thirdparty/khronos/GL/glx.h +--- apitrace.orig/thirdparty/khronos/GL/glx.h 2021-01-08 19:52:31.796259444 -0500 ++++ apitrace.new/thirdparty/khronos/GL/glx.h 2021-01-08 19:53:57.757888475 -0500 +@@ -35,8 +35,8 @@ + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +-#include +-#include ++//#include ++//#include + #include + + #ifdef __cplusplus diff --git a/packages/debug/edid-decode/package.mk b/packages/debug/edid-decode/package.mk new file mode 100644 index 000000000..854ba767b --- /dev/null +++ b/packages/debug/edid-decode/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="edid-decode" +PKG_VERSION="15df4aebf06da579241c58949493b866139d0e2b" +PKG_SHA256="58743c8ba768134ef1421e1ce9f4edf0eafdae29377fe5b8f4cb285f16dc142e" +PKG_LICENSE="None" +PKG_SITE="https://git.linuxtv.org/edid-decode.git/" +PKG_URL="https://git.linuxtv.org/edid-decode.git/snapshot/$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Decode EDID data in human-readable format" + +make_target() { + echo "$CC $CFLAGS -Wall $LDFLAGS -lm -o edid-decode edid-decode.c" + $CC $CFLAGS -Wall $LDFLAGS -lm -o edid-decode edid-decode.c +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp edid-decode $INSTALL/usr/bin +} diff --git a/packages/debug/gdb/package.mk b/packages/debug/gdb/package.mk new file mode 100644 index 000000000..065367918 --- /dev/null +++ b/packages/debug/gdb/package.mk @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gdb" +PKG_VERSION="11.1" +PKG_SHA256="cccfcc407b20d343fb320d4a9a2110776dd3165118ffd41f4b1b162340333f94" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/gdb/" +PKG_URL="http://ftpmirror.gnu.org/gdb/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib ncurses expat" +PKG_LONGDESC="GNU Project debugger, allows you to see what is going on inside another program while it executes." +# gdb could fail on runtime if build with LTO support + +PKG_CONFIGURE_OPTS_TARGET="bash_cv_have_mbstate_t=set \ + --disable-shared \ + --enable-static \ + --with-auto-load-safe-path=/ \ + --with-python=no \ + --with-guile=no \ + --with-mpfr=no \ + --with-intel-pt=no \ + --with-babeltrace=no \ + --with-expat=yes \ + --disable-source-highlight \ + --disable-nls \ + --disable-sim \ + --without-x \ + --disable-tui \ + --disable-libada \ + --without-lzma \ + --disable-libquadmath \ + --disable-libquadmath-support \ + --enable-libada \ + --enable-libssp \ + --disable-werror" + +pre_configure_target() { + CC_FOR_BUILD="$HOST_CC" + CFLAGS_FOR_BUILD="$HOST_CFLAGS" +} + +makeinstall_target() { + make DESTDIR=$INSTALL install +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/share/gdb/python +} diff --git a/packages/debug/gdb/patches/gdb-001-notex.patch b/packages/debug/gdb/patches/gdb-001-notex.patch new file mode 100644 index 000000000..0a9804e54 --- /dev/null +++ b/packages/debug/gdb/patches/gdb-001-notex.patch @@ -0,0 +1,12 @@ +--- gdb-7.11.1/missing.orig 2017-01-30 19:01:55.652407184 +0900 ++++ gdb-7.11.1/missing 2017-01-30 19:02:53.703405905 +0900 +@@ -83,6 +83,9 @@ + # If it succeeded, we are done. + test $st -eq 0 && exit 0 + ++# No need for tex monster ++test $1 = makeinfo && exit 0 ++ + # Also exit now if we it failed (or wasn't found), and '--version' was + # passed; such an option is passed most likely to detect whether the + # program is present and works. diff --git a/packages/debug/libunwind/package.mk b/packages/debug/libunwind/package.mk new file mode 100644 index 000000000..9f2f7a8de --- /dev/null +++ b/packages/debug/libunwind/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libunwind" +PKG_VERSION="1.6.2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.nongnu.org/libunwind/" +PKG_URL="http://download.savannah.nongnu.org/releases/libunwind/libunwind-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="gcc:host" +PKG_LONGDESC="library to determine the call-chain of a program" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared" + +makeinstall_target() { + make DESTDIR=$SYSROOT_PREFIX install +} diff --git a/packages/debug/libva-utils/package.mk b/packages/debug/libva-utils/package.mk new file mode 100644 index 000000000..747966a24 --- /dev/null +++ b/packages/debug/libva-utils/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libva-utils" +PKG_VERSION="2.4.1" +PKG_SHA256="4ab6faa6592ffe2d4817450f5453f3974b47441650e8f49e1a12497ce2a794ac" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/01org/libva-utils" +PKG_URL="https://github.com/intel/libva-utils/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Libva-utils is a collection of tests for VA-API (VIdeo Acceleration API)" +PKG_TOOLCHAIN="autotools" + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="toolchain libva libdrm libX11" + DISPLAYSERVER_LIBVA="--enable-x11" +else + PKG_DEPENDS_TARGET="toolchain libva libdrm" + DISPLAYSERVER_LIBVA="--disable-x11" +fi + +PKG_CONFIGURE_OPTS_TARGET="--disable-silent-rules \ + --enable-drm \ + $DISPLAYSERVER_LIBVA \ + --disable-wayland \ + --disable-tests" diff --git a/packages/debug/memtester/package.mk b/packages/debug/memtester/package.mk new file mode 100644 index 000000000..41604a741 --- /dev/null +++ b/packages/debug/memtester/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="memtester" +PKG_VERSION="4.5.0" +PKG_SHA256="8ed52b0d06d4aeb61954994146e2a5b2d20448a8f3ce3ee995120e6dbde2ae37" +PKG_LICENSE="GPL" +PKG_SITE="http://pyropus.ca/software/memtester/" +PKG_URL="http://pyropus.ca/software/memtester/old-versions/memtester-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A userspace utility for testing the memory subsystem for faults." +PKG_TOOLCHAIN="manual" + +make_target() { + make memtester +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp memtester $INSTALL/usr/bin +} diff --git a/packages/debug/memtester/patches/memtester-001-cross-compile.patch b/packages/debug/memtester/patches/memtester-001-cross-compile.patch new file mode 100644 index 000000000..3ff6decfc --- /dev/null +++ b/packages/debug/memtester/patches/memtester-001-cross-compile.patch @@ -0,0 +1,34 @@ +Author: Helmut Grohne +Description: make the build system honor $CC to facilitate cross builds + +Index: memtester-4.3.0/conf-cc +=================================================================== +--- memtester-4.3.0.orig/conf-cc 2012-06-09 23:45:22.000000000 +0200 ++++ memtester-4.3.0/conf-cc 2015-09-12 20:36:27.000000000 +0200 +@@ -1,3 +1,3 @@ +-cc -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c ++$CC -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c + + This will be used to compile .c files. +Index: memtester-4.3.0/conf-ld +=================================================================== +--- memtester-4.3.0.orig/conf-ld 2012-06-09 23:45:22.000000000 +0200 ++++ memtester-4.3.0/conf-ld 2015-09-12 20:36:33.000000000 +0200 +@@ -1,3 +1,3 @@ +-cc -s ++$CC -s + + This will be used to link .o files into an executable. +Index: memtester-4.3.0/Makefile +=================================================================== +--- memtester-4.3.0.orig/Makefile 2015-09-12 20:01:06.000000000 +0200 ++++ memtester-4.3.0/Makefile 2015-09-12 20:50:40.000000000 +0200 +@@ -10,8 +10,6 @@ + # You don't need to edit these; change the contents of the conf-cc and conf-ld + # files if you need to change the compile/link commands. See the README for + # more information. +-CC = $(shell head -n 1 conf-cc) +-LD = $(shell head -n 1 conf-ld) + + SOURCES = memtester.c tests.c + OBJECTS = $(SOURCES:.c=.o) diff --git a/packages/debug/valgrind/package.mk b/packages/debug/valgrind/package.mk new file mode 100644 index 000000000..1eb734259 --- /dev/null +++ b/packages/debug/valgrind/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="valgrind" +PKG_VERSION="3.15.0" +PKG_SHA256="417c7a9da8f60dd05698b3a7bc6002e4ef996f14c13f0ff96679a16873e78ab1" +PKG_LICENSE="GPL" +PKG_SITE="http://valgrind.org/" +PKG_URL="ftp://sourceware.org/pub/valgrind/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A tool to help find memory-management problems in programs" + +if [ "$TARGET_ARCH" = "arm" ]; then + PKG_CONFIGURE_OPTS_TARGET="--enable-only32bit" +elif [ "$TARGET_ARCH" = "aarch64" -o "$TARGET_ARCH" = "x86_64" ]; then + PKG_CONFIGURE_OPTS_TARGET="--enable-only64bit" +fi diff --git a/packages/debug/valgrind/patches/valgrind-0001-enable-armv8.patch b/packages/debug/valgrind/patches/valgrind-0001-enable-armv8.patch new file mode 100644 index 000000000..5e690a195 --- /dev/null +++ b/packages/debug/valgrind/patches/valgrind-0001-enable-armv8.patch @@ -0,0 +1,12 @@ +diff -Naur a/configure b/configure +--- a/configure 2017-06-15 06:41:35.000000000 -0700 ++++ b/configure 2018-06-26 14:51:02.264580174 -0700 +@@ -5627,7 +5627,7 @@ + ARCH_MAX="s390x" + ;; + +- armv7*) ++ armv7*|armv8*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (${host_cpu})" >&5 + $as_echo "ok (${host_cpu})" >&6; } + ARCH_MAX="arm" diff --git a/packages/debug/valgrind/patches/valgrind-0002-no-mpi1.patch b/packages/debug/valgrind/patches/valgrind-0002-no-mpi1.patch new file mode 100644 index 000000000..084ba67b3 --- /dev/null +++ b/packages/debug/valgrind/patches/valgrind-0002-no-mpi1.patch @@ -0,0 +1,67 @@ +From a3262243ca01f7cfe3ae86b168d5b3a7e5d1cbc0 Mon Sep 17 00:00:00 2001 +From: Balint Reczey +Date: Thu, 28 Nov 2019 19:31:12 +0100 +Subject: [PATCH] Drop MPI 1 support + +Signed-off-by: Balint Reczey +--- + mpi/libmpiwrap.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/mpi/libmpiwrap.c b/mpi/libmpiwrap.c +index 488bb13fd..a740ea562 100644 +--- a/mpi/libmpiwrap.c ++++ b/mpi/libmpiwrap.c +@@ -278,8 +278,6 @@ static void showTy ( FILE* f, MPI_Datatype ty ) + else if (ty == MPI_LONG_INT) fprintf(f,"LONG_INT"); + else if (ty == MPI_SHORT_INT) fprintf(f,"SHORT_INT"); + else if (ty == MPI_2INT) fprintf(f,"2INT"); +- else if (ty == MPI_UB) fprintf(f,"UB"); +- else if (ty == MPI_LB) fprintf(f,"LB"); + # if defined(MPI_WCHAR) + else if (ty == MPI_WCHAR) fprintf(f,"WCHAR"); + # endif +@@ -350,20 +348,11 @@ static void showCombiner ( FILE* f, int combiner ) + # endif + case MPI_COMBINER_CONTIGUOUS: fprintf(f, "CONTIGUOUS"); break; + case MPI_COMBINER_VECTOR: fprintf(f, "VECTOR"); break; +-#if defined(MPI_COMBINER_HVECTOR_INTEGER) +- case MPI_COMBINER_HVECTOR_INTEGER: fprintf(f, "HVECTOR_INTEGER"); break; +-# endif + case MPI_COMBINER_HVECTOR: fprintf(f, "HVECTOR"); break; + case MPI_COMBINER_INDEXED: fprintf(f, "INDEXED"); break; +-#if defined(MPI_COMBINER_HINDEXED_INTEGER) +- case MPI_COMBINER_HINDEXED_INTEGER: fprintf(f, "HINDEXED_INTEGER"); break; +-# endif + case MPI_COMBINER_HINDEXED: fprintf(f, "HINDEXED"); break; + #if defined(MPI_COMBINER_INDEXED_BLOCK) + case MPI_COMBINER_INDEXED_BLOCK: fprintf(f, "INDEXED_BLOCK"); break; +-# endif +-#if defined(MPI_COMBINER_STRUCT_INTEGER) +- case MPI_COMBINER_STRUCT_INTEGER: fprintf(f, "STRUCT_INTEGER"); break; + # endif + case MPI_COMBINER_STRUCT: fprintf(f, "STRUCT"); break; + #if defined(MPI_COMBINER_SUBARRAY) +@@ -458,8 +447,9 @@ Bool isMSI ( MPI_Status* status ) + static long extentOfTy ( MPI_Datatype ty ) + { + int r; ++ MPI_Aint lb; + MPI_Aint n; +- r = PMPI_Type_extent(ty, &n); ++ r = MPI_Type_get_extent(ty, &lb, &n); + assert(r == MPI_SUCCESS); + return (long)n; + } +@@ -733,8 +723,6 @@ void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty ) + f(base + offsetof(Ty,loc), sizeof(int)); + return; + } +- if (ty == MPI_LB || ty == MPI_UB) +- return; /* have zero size, so nothing needs to be done */ + goto unhandled; + /*NOTREACHED*/ + } +-- +2.17.1 + diff --git a/packages/debug/vdpauinfo/package.mk b/packages/debug/vdpauinfo/package.mk new file mode 100644 index 000000000..b8725e216 --- /dev/null +++ b/packages/debug/vdpauinfo/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="vdpauinfo" +PKG_VERSION="1.0" +PKG_SHA256="4054960b7ae618c351ff1ce3e7831b5cbda964ae1fbf9969b7146404d3044bc4" +PKG_LICENSE="GPL" +PKG_SITE="http://freedesktop.org/wiki/Software/VDPAU" +PKG_URL="http://people.freedesktop.org/~aplattner/vdpau/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libvdpau" +PKG_LONGDESC="A tool to show vdpau infos." diff --git a/packages/devel/android-headers/package.mk b/packages/devel/android-headers/package.mk new file mode 100644 index 000000000..0db28e4d2 --- /dev/null +++ b/packages/devel/android-headers/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="android-headers" +PKG_VERSION="25" +PKG_SHA256="1e0ecdf56c33aaa523109254e2c475878d8cfc5795ebd4bb5ecbaf80926f4fe9" +PKG_LICENSE="Apache" +PKG_SITE="https://android.googlesource.com/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Android Platform Headers from AOSP releases." +PKG_TOOLCHAIN="manual" diff --git a/packages/devel/apache-ant/package.mk b/packages/devel/apache-ant/package.mk new file mode 100644 index 000000000..72085763f --- /dev/null +++ b/packages/devel/apache-ant/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Peter Vicman (peter.vicman@gmail.com) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="apache-ant" +PKG_VERSION="1.10.7" +PKG_SHA256="c8d68b396d9e44b49668bafe0c82f8c89497915254b5395d73d6f6e41d7a0e25" +PKG_LICENSE="Apache License 2.0" +PKG_SITE="https://ant.apache.org/" +PKG_URL="https://archive.apache.org/dist/ant/source/${PKG_NAME}-${PKG_VERSION}-src.tar.xz" +PKG_DEPENDS_HOST="jdk-x86_64-zulu:host" +PKG_LONGDESC="Apache Ant is a Java library and command-line tool that help building software." +PKG_TOOLCHAIN="manual" + +make_host() { + ( + export JAVA_HOME=$(get_build_dir jdk-x86_64-zulu) + + ./bootstrap.sh + ./bootstrap/bin/ant -f fetch.xml -Ddest=optional + ./build.sh -Ddist.dir=${PKG_BUILD}/binary dist + ) +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp binary/bin/ant ${TOOLCHAIN}/bin + cp -r binary/lib ${TOOLCHAIN} +} diff --git a/packages/devel/arm-mem/package.mk b/packages/devel/arm-mem/package.mk new file mode 100644 index 000000000..5836689ad --- /dev/null +++ b/packages/devel/arm-mem/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="arm-mem" +PKG_VERSION="b48ea154fd74410022d8189003cd69fad8f3d02c" # Apr 30, 2019 +PKG_SHA256="93240defef3abba7d42a7420e55ae4f8b90cc99ef16044fdfb8b5820a17e766d" +PKG_ARCH="arm" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/bavison/arm-mem" +PKG_URL="https://github.com/bavison/arm-mem/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_INIT="toolchain arm-mem" +PKG_LONGDESC="arm-mem is a ARM-accelerated versions of selected functions from string.h" +PKG_BUILD_FLAGS="+pic" + +if target_has_feature neon; then + PKG_LIB_ARM_MEM="libarmmem-v7l.so" +else + PKG_LIB_ARM_MEM="libarmmem-v6l.so" +fi + +PKG_MAKE_OPTS_TARGET="${PKG_LIB_ARM_MEM}" + +pre_make_target() { + export CROSS_COMPILE=${TARGET_PREFIX} +} + +make_init() { + : # reuse make_target() +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib + cp -P ${PKG_LIB_ARM_MEM} ${INSTALL}/usr/lib + + mkdir -p ${INSTALL}/etc + echo "/usr/lib/${PKG_LIB_ARM_MEM}" >> ${INSTALL}/etc/ld.so.preload +} + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/lib + cp -P ${PKG_LIB_ARM_MEM} ${INSTALL}/usr/lib + + mkdir -p ${INSTALL}/etc + echo "/usr/lib/${PKG_LIB_ARM_MEM}" >> ${INSTALL}/etc/ld.so.preload +} diff --git a/packages/devel/attr/package.mk b/packages/devel/attr/package.mk new file mode 100644 index 000000000..12a624ee9 --- /dev/null +++ b/packages/devel/attr/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv) +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="attr" +PKG_VERSION="2.4.48" +PKG_SHA256="5ead72b358ec709ed00bbf7a9eaef1654baad937c001c044fe8b74c57f5324e7" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.nongnu.org/projects/attr" +PKG_URL="http://download.savannah.nongnu.org/releases/attr/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Extended Attributes Of Filesystem Objects." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="OPTIMIZER= \ + CONFIG_SHELL=/bin/bash \ + INSTALL_USER=root INSTALL_GROUP=root \ + --disable-shared --enable-static" + +if build_with_debug; then + PKG_CONFIGURE_OPTS_TARGET+=" DEBUG=-DDEBUG" +else + PKG_CONFIGURE_OPTS_TARGET+=" DEBUG=-DNDEBUG" +fi + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/ + cp .libs/libattr.a ${SYSROOT_PREFIX}/usr/lib/ + + mkdir -p ${SYSROOT_PREFIX}/usr/include/attr + cp include/*.h ${SYSROOT_PREFIX}/usr/include/attr +} diff --git a/packages/devel/autoconf-archive/package.mk b/packages/devel/autoconf-archive/package.mk new file mode 100644 index 000000000..cfd912670 --- /dev/null +++ b/packages/devel/autoconf-archive/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="autoconf-archive" +PKG_VERSION="2019.01.06" +PKG_SHA256="17195c833098da79de5778ee90948f4c5d90ed1a0cf8391b4ab348e2ec511e3f" +PKG_LICENSE="GPL" +PKG_SITE="https://www.gnu.org/software/autoconf-archive/" +PKG_URL="http://ftpmirror.gnu.org/autoconf-archive/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="autoconf-archive is an package of m4 macros" + +PKG_CONFIGURE_OPTS_HOST="--target=${TARGET_NAME} --prefix=${TOOLCHAIN}" + +makeinstall_host() { +# make install + make prefix=${SYSROOT_PREFIX}/usr install + +# remove problematic m4 file + rm -rf ${SYSROOT_PREFIX}/usr/share/aclocal/ax_prog_cc_for_build.m4 +} diff --git a/packages/devel/autoconf/package.mk b/packages/devel/autoconf/package.mk new file mode 100644 index 000000000..18172507a --- /dev/null +++ b/packages/devel/autoconf/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="autoconf" +PKG_VERSION="2.69" +PKG_SHA256="64ebcec9f8ac5b2487125a86a7760d2591ac9e1d3dbd59489633f9de62a57684" +PKG_LICENSE="GPL" +PKG_SITE="http://sources.redhat.com/autoconf/" +PKG_URL="http://ftpmirror.gnu.org/autoconf/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host m4:host gettext:host" +PKG_LONGDESC="A GNU tool for automatically configuring source code." + +PKG_CONFIGURE_OPTS_HOST="EMACS=no \ + ac_cv_path_M4=${TOOLCHAIN}/bin/m4 \ + ac_cv_prog_gnu_m4_gnu=no \ + --target=${TARGET_NAME}" + +post_makeinstall_host() { + make prefix=${SYSROOT_PREFIX}/usr install +} diff --git a/packages/devel/autoconf/patches/autoconf-0100-backport-runstatedir.patch b/packages/devel/autoconf/patches/autoconf-0100-backport-runstatedir.patch new file mode 100644 index 000000000..37a03843a --- /dev/null +++ b/packages/devel/autoconf/patches/autoconf-0100-backport-runstatedir.patch @@ -0,0 +1,59 @@ +From 8e269b13bc042bc2504d5860e0d453b4aac32909 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 24 Jun 2018 13:45:26 +0200 +Subject: [PATCH] backport AC_INIT: add --runstatedir option to configure + +Backport of a197431414088a417b407b9b20583b2e8f7363bd. +Changes to NEWS and doc/autoconf.tex have been dropped. +--- + lib/autoconf/general.m4 | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4 +index adfae1db..1437c0ca 100644 +--- a/lib/autoconf/general.m4 ++++ b/lib/autoconf/general.m4 +@@ -586,6 +586,7 @@ AC_SUBST([datadir], ['${datarootdir}'])dnl + AC_SUBST([sysconfdir], ['${prefix}/etc'])dnl + AC_SUBST([sharedstatedir], ['${prefix}/com'])dnl + AC_SUBST([localstatedir], ['${prefix}/var'])dnl ++AC_SUBST([runstatedir], ['${localstatedir}/run'])dnl + AC_SUBST([includedir], ['${prefix}/include'])dnl + AC_SUBST([oldincludedir], ['/usr/include'])dnl + AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME], +@@ -812,6 +813,15 @@ do + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + ++ -runstatedir | --runstatedir | --runstatedi | --runstated \ ++ | --runstate | --runstat | --runsta | --runst | --runs \ ++ | --run | --ru | --r) ++ ac_prev=runstatedir ;; ++ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ ++ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ ++ | --run=* | --ru=* | --r=*) ++ runstatedir=$ac_optarg ;; ++ + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ +@@ -921,7 +931,7 @@ fi + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ +- libdir localedir mandir ++ libdir localedir mandir runstatedir + do + eval ac_val=\$$ac_var + # Remove trailing slashes. +@@ -1058,6 +1068,7 @@ Fine tuning of the installation directories: + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] ++ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] +-- +2.11.0 + diff --git a/packages/devel/autoconf/patches/autoconf-0200-performance.patch b/packages/devel/autoconf/patches/autoconf-0200-performance.patch new file mode 100644 index 000000000..1842fe92b --- /dev/null +++ b/packages/devel/autoconf/patches/autoconf-0200-performance.patch @@ -0,0 +1,60 @@ +The check for solaris 'print' causes significant problems on a linux machine +with dash as /bin/sh since it triggers the execution of "print" which on some +linux systems is a perl script which is part of mailcap. Worse, this perl +script calls "which file" and if successful ignores the path file was found +in and just runs "file" without a path. Each exection causes PATH to be searched. + +Simply assuming the shell's printf function works cuts out all the fork overhead +and when parallel tasks are running, this overhead appears to be significant. + +RP +2015/11/28 +Upstream-Status: Inappropriate + +Index: autoconf-2.69/lib/m4sugar/m4sh.m4 +=================================================================== +--- autoconf-2.69.orig/lib/m4sugar/m4sh.m4 ++++ autoconf-2.69/lib/m4sugar/m4sh.m4 +@@ -1045,40 +1045,8 @@ m4_defun([_AS_ECHO_PREPARE], + [[as_nl=' + ' + export as_nl +-# Printing a long string crashes Solaris 7 /usr/bin/printf. +-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +-# Prefer a ksh shell builtin over an external printf program on Solaris, +-# but without wasting forks for bash or zsh. +-if test -z "$BASH_VERSION$ZSH_VERSION" \ +- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then +- as_echo='print -r --' +- as_echo_n='print -rn --' +-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then +- as_echo='printf %s\n' +- as_echo_n='printf %s' +-else +- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then +- as_echo_body='eval /usr/ucb/echo -n "$][1$as_nl"' +- as_echo_n='/usr/ucb/echo -n' +- else +- as_echo_body='eval expr "X$][1" : "X\\(.*\\)"' +- as_echo_n_body='eval +- arg=$][1; +- case $arg in @%:@( +- *"$as_nl"*) +- expr "X$arg" : "X\\(.*\\)$as_nl"; +- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; +- esac; +- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" +- ' +- export as_echo_n_body +- as_echo_n='sh -c $as_echo_n_body as_echo' +- fi +- export as_echo_body +- as_echo='sh -c $as_echo_body as_echo' +-fi ++as_echo='printf %s\n' ++as_echo_n='printf %s' + ]])# _AS_ECHO_PREPARE + + diff --git a/packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch b/packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch new file mode 100644 index 000000000..d1bd3a2a3 --- /dev/null +++ b/packages/devel/autoconf/patches/autoconf-autoreconf-exclude.patch @@ -0,0 +1,139 @@ +Upstream-Status: Pending + +Index: autoconf-2.63/bin/autoreconf.in +=================================================================== +--- autoconf-2.63.orig/bin/autoreconf.in 2008-12-31 17:39:01.000000000 +0000 ++++ autoconf-2.63/bin/autoreconf.in 2008-12-31 17:43:38.000000000 +0000 +@@ -76,6 +76,7 @@ + -i, --install copy missing auxiliary files + --no-recursive don't rebuild sub-packages + -s, --symlink with -i, install symbolic links instead of copies ++ -x, --exclude=STEPS steps we should not run + -m, --make when applicable, re-run ./configure && make + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [syntax] + +@@ -136,6 +137,13 @@ + # Recurse into subpackages + my $recursive = 1; + ++# Steps to exclude ++my @exclude; ++my @ex; ++ ++my $uses_gettext; ++my $configure_ac; ++ + ## ---------- ## + ## Routines. ## + ## ---------- ## +@@ -153,6 +161,7 @@ + 'B|prepend-include=s' => \@prepend_include, + 'i|install' => \$install, + 's|symlink' => \$symlink, ++ 'x|exclude=s' => \@exclude, + 'm|make' => \$run_make, + 'recursive!' => \$recursive); + +@@ -162,6 +171,8 @@ + parse_WARNINGS; + parse_warnings '--warnings', @warning; + ++ @exclude = map { split /,/ } @exclude; ++ + # Even if the user specified a configure.ac, trim to get the + # directory, and look for configure.ac again. Because (i) the code + # is simpler, and (ii) we are still able to diagnose simultaneous +@@ -255,6 +266,11 @@ + { + my ($aclocal, $flags) = @_; + ++ @ex = grep (/^aclocal$/, @exclude); ++ if ($#ex != -1) { ++ return; ++ } ++ + # aclocal 1.8+ does all this for free. It can be recognized by its + # --force support. + if ($aclocal_supports_force) +@@ -368,7 +384,10 @@ + } + else + { +- xsystem_hint ("autopoint is needed because this package uses Gettext", "$autopoint"); ++ @ex = grep (/^autopoint$/, @exclude); ++ if ($#ex == -1) { ++ xsystem_hint ("autopoint is needed because this package uses Gettext", "$autopoint"); ++ } + } + + +@@ -532,16 +551,17 @@ + { + $libtoolize .= " --ltdl"; + } +- xsystem_hint ("libtoolize is needed because this package uses Libtool", $libtoolize); +- $rerun_aclocal = 1; ++ @ex = grep (/^libtoolize$/, @exclude); ++ if ($#ex == -1) { ++ xsystem_hint ("libtoolize is needed because this package uses Libtool", $libtoolize); ++ $rerun_aclocal = 1; ++ } + } + else + { + verb "$configure_ac: not running libtoolize: --install not given"; + } + +- +- + # ------------------- # + # Rerunning aclocal. # + # ------------------- # +@@ -572,7 +592,10 @@ + # latter runs the former, and (ii) autoconf is stricter than + # autoheader. So all in all, autoconf should give better error + # messages. +- xsystem ($autoconf); ++ @ex = grep (/^autoconf$/, @exclude); ++ if ($#ex == -1) { ++ xsystem ("$autoconf"); ++ } + + + # -------------------- # +@@ -593,7 +616,10 @@ + } + else + { +- xsystem ($autoheader); ++ @ex = grep (/^autoheader$/, @exclude); ++ if ($#ex == -1) { ++ xsystem ("$autoheader"); ++ } + } + + +@@ -610,7 +636,10 @@ + # We should always run automake, and let it decide whether it shall + # update the file or not. In fact, the effect of `$force' is already + # included in `$automake' via `--no-force'. +- xsystem ($automake); ++ @ex = grep (/^automake$/, @exclude); ++ if ($#ex == -1) { ++ xsystem ("$automake"); ++ } + } + + +@@ -634,7 +663,10 @@ + } + else + { +- xsystem ("$make"); ++ @ex = grep (/^make$/, @exclude); ++ if ($#ex == -1) { ++ xsystem ("$make"); ++ } + } + } + } diff --git a/packages/devel/automake/package.mk b/packages/devel/automake/package.mk new file mode 100644 index 000000000..de321db9a --- /dev/null +++ b/packages/devel/automake/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="automake" +PKG_VERSION="1.16.5" +PKG_SHA256="f01d58cd6d9d77fbdca9eb4bbd5ead1988228fdb73d6f7a201f5f8d6b118b469" +PKG_LICENSE="GPL" +PKG_SITE="http://sources.redhat.com/automake/" +PKG_URL="http://ftpmirror.gnu.org/automake/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host autoconf:host" +PKG_LONGDESC="A GNU tool for automatically creating Makefiles." + +PKG_CONFIGURE_OPTS_HOST="--target=${TARGET_NAME} --disable-silent-rules" + +post_makeinstall_host() { + make prefix=${SYSROOT_PREFIX}/usr install +} diff --git a/packages/devel/automake/patches/automake-01-fix-help2man.patch b/packages/devel/automake/patches/automake-01-fix-help2man.patch new file mode 100644 index 000000000..7d5fa126d --- /dev/null +++ b/packages/devel/automake/patches/automake-01-fix-help2man.patch @@ -0,0 +1,25 @@ +From fc19cd1da6161ec5602e692488dfc8e670797afe Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 15 Aug 2014 22:10:03 +0300 +Subject: [PATCH] meh help2man + +--- + Makefile.in | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 5a336df..2d2029b 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -701,7 +701,7 @@ update_mans = \ + update_mans = \ + $(AM_V_GEN): \ + && $(MKDIR_P) doc \ +- && ./pre-inst-env $(PERL) $(srcdir)/doc/help2man --output=$@ ++ && ./pre-inst-env $(PERL) $(srcdir)/doc/help2man --output=$@ --no-discard-stderr + + checklinkx = $(top_srcdir)/contrib/checklinkx + # that 4-second sleep seems to be what gnu.org likes. +-- +1.7.2.5 + diff --git a/packages/devel/binutils/package.mk b/packages/devel/binutils/package.mk new file mode 100644 index 000000000..b73031540 --- /dev/null +++ b/packages/devel/binutils/package.mk @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="binutils" +PKG_VERSION="2.35.1" +PKG_SHA256="3ced91db9bf01182b7e420eab68039f2083aed0a214c0424e257eae3ddee8607" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/binutils/" +PKG_URL="http://ftp.gnu.org/gnu/binutils/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host bison:host flex:host linux:host" +PKG_DEPENDS_TARGET="toolchain zlib binutils:host" +PKG_LONGDESC="A GNU collection of binary utilities." + +PKG_CONFIGURE_OPTS_HOST="--target=${TARGET_NAME} \ + --with-sysroot=${SYSROOT_PREFIX} \ + --with-lib-path=${SYSROOT_PREFIX}/lib:${SYSROOT_PREFIX}/usr/lib \ + --without-ppl \ + --without-cloog \ + --disable-werror \ + --disable-multilib \ + --disable-libada \ + --disable-libssp \ + --enable-version-specific-runtime-libs \ + --enable-plugins \ + --enable-gold \ + --enable-ld=default \ + --enable-lto \ + --disable-nls" + +PKG_CONFIGURE_OPTS_TARGET="--target=${TARGET_NAME} \ + --with-sysroot=${SYSROOT_PREFIX} \ + --with-lib-path=${SYSROOT_PREFIX}/lib:${SYSROOT_PREFIX}/usr/lib \ + --with-system-zlib \ + --without-ppl \ + --without-cloog \ + --enable-static \ + --disable-shared \ + --disable-werror \ + --disable-multilib \ + --disable-libada \ + --disable-libssp \ + --disable-plugins \ + --disable-gold \ + --disable-ld \ + --disable-lto \ + --disable-nls" + +pre_configure_host() { + unset CPPFLAGS + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +make_host() { + make configure-host + make +} + +makeinstall_host() { + cp -v ../include/libiberty.h ${SYSROOT_PREFIX}/usr/include + make install +} + +make_target() { + make configure-host + make -C libiberty + make -C bfd + make -C opcodes + make -C binutils strings +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp libiberty/libiberty.a ${SYSROOT_PREFIX}/usr/lib + make DESTDIR="${SYSROOT_PREFIX}" -C bfd install + make DESTDIR="${SYSROOT_PREFIX}" -C opcodes install + + mkdir -p ${INSTALL}/usr/bin + cp binutils/strings ${INSTALL}/usr/bin +} diff --git a/packages/devel/binutils/patches/binutils-01-warn-for-uses-of-system-directories-when-link.patch b/packages/devel/binutils/patches/binutils-01-warn-for-uses-of-system-directories-when-link.patch new file mode 100644 index 000000000..91c501eec --- /dev/null +++ b/packages/devel/binutils/patches/binutils-01-warn-for-uses-of-system-directories-when-link.patch @@ -0,0 +1,32 @@ +simplified patch based on +http://git.yoctoproject.org/cgit.cgi/poky/plain/meta/recipes-devtools/binutils/binutils/0009-warn-for-uses-of-system-directories-when-cross-linki.patch +just detect and skip system directories if used by mistake + +linker output in case of using /usr/lib path: +/data/LibreELEC.tv/build.LibreELEC-Generic.x86_64-8.0-devel/toolchain/lib/gcc/x86_64-libreelec-linux-gnu/6.2.0/../../../../x86_64-libreelec-linux-gnu/bin/ld: warning: library search path "/usr/lib" is unsafe for cross-compilation, ignore it + +From 7ab8e318659eb5d9adc758c78d084a95560b93fd Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Fri, 15 Jan 2016 06:31:09 +0000 +Subject: [PATCH 09/13] warn for uses of system directories when cross linking + +--- a/ld/ldfile.c 2015-11-13 09:27:42.000000000 +0100 ++++ b/ld/ldfile.c 2016-11-15 19:09:31.658371254 +0100 +@@ -102,6 +102,17 @@ ldfile_add_library_path (const char *nam + if (!cmdline && config.only_cmd_line_lib_dirs) + return; + ++ /* skip those directories when linking */ ++ if ((!strncmp (name, "/lib", 4)) || ++ (!strncmp (name, "/usr/lib", 8)) || ++ (!strncmp (name, "/usr/local/lib", 14)) || ++ (!strncmp (name, "/usr/X11R6/lib", 14))) ++ { ++ einfo (_("%P: warning: library search path \"%s\" is unsafe for " ++ "cross-compilation, ignore it\n"), name); ++ return; ++ } ++ + new_dirs = (search_dirs_type *) xmalloc (sizeof (search_dirs_type)); + new_dirs->next = NULL; + new_dirs->cmdline = cmdline; diff --git a/packages/devel/binutils/patches/nodocs.patch b/packages/devel/binutils/patches/nodocs.patch new file mode 100644 index 000000000..ac880bc06 --- /dev/null +++ b/packages/devel/binutils/patches/nodocs.patch @@ -0,0 +1,12 @@ +diff -ur a/binutils/Makefile.in b/binutils/Makefile.in +--- a/binutils/Makefile.in 2020-02-01 12:50:05.000000000 +0100 ++++ b/binutils/Makefile.in 2020-02-20 00:45:18.792253182 +0100 +@@ -560,7 +560,7 @@ + zlibinc = @zlibinc@ + AUTOMAKE_OPTIONS = dejagnu no-dist foreign subdir-objects + ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd +-SUBDIRS = doc po ++SUBDIRS = + tooldir = $(exec_prefix)/$(target_alias) + + # Automake 1.10+ disables lex and yacc output file regeneration if diff --git a/packages/devel/bison/package.mk b/packages/devel/bison/package.mk new file mode 100644 index 000000000..00bce3137 --- /dev/null +++ b/packages/devel/bison/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bison" +PKG_VERSION="3.8.2" +PKG_SHA256="9bba0214ccf7f1079c5d59210045227bcf619519840ebfa80cd3849cff5a5bf2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/bison/" +PKG_URL="http://ftpmirror.gnu.org/bison/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host m4:host" +PKG_LONGDESC="A general-purpose parser generator." +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_HOST="--disable-rpath --with-gnu-ld" + +post_configure_host() { +# The configure system causes Bison to be built without support for +# internationalization of error messages if a bison program is not already in +# ${PATH}. The following addition will correct this: + echo '#define YYENABLE_NLS 1' >> lib/config.h +} diff --git a/packages/devel/boost/package.mk b/packages/devel/boost/package.mk new file mode 100644 index 000000000..ddbdc1555 --- /dev/null +++ b/packages/devel/boost/package.mk @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="boost" +PKG_VERSION="1.76.0" +PKG_SHA256="f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41" +PKG_LICENSE="OSS" +PKG_SITE="http://www.boost.org/" +PKG_URL="https://boostorg.jfrog.io/artifactory/main/release/${PKG_VERSION}/source/${PKG_NAME}_${PKG_VERSION//./_}.tar.bz2" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain boost:host Python3 zlib bzip2" +PKG_LONGDESC="boost: Peer-reviewed STL style libraries for C++" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +make_host() { + cd tools/build/src/engine + sh build.sh +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp bjam ${TOOLCHAIN}/bin +} + +pre_configure_target() { + export CFLAGS="${CFLAGS} -I${TOOLCHAIN}/include/${PKG_PYTHON_VERSION}" + export CXXFLAGS="${CXXFLAGS} -I${TOOLCHAIN}/include/${PKG_PYTHON_VERSION}" +} + +configure_target() { + sh bootstrap.sh --prefix=/usr \ + --with-bjam=${TOOLCHAIN}/bin/bjam \ + --with-python=${TOOLCHAIN}/bin/python \ + --with-python-root=${SYSROOT_PREFIX}/usr + + echo "using gcc : $(${CC} -v 2>&1 | tail -n 1 |awk '{print $3}') : ${CC} : \"${CFLAGS}\" \"${LDFLAGS}\" ;" \ + > tools/build/src/user-config.jam + echo "using python : ${PKG_PYTHON_VERSION/#python} : ${TOOLCHAIN} : ${SYSROOT_PREFIX}/usr/include : ${SYSROOT_PREFIX}/usr/lib ;" \ + >> tools/build/src/user-config.jam +} + +makeinstall_target() { + ${TOOLCHAIN}/bin/bjam -d2 --ignore-site-config \ + --layout=system \ + --prefix=${SYSROOT_PREFIX}/usr \ + --toolset=gcc link=static \ + --with-chrono \ + --with-date_time \ + --with-filesystem \ + --with-iostreams \ + --with-python \ + --with-random \ + --with-regex -sICU_PATH="${SYSROOT_PREFIX}/usr" \ + --with-serialization \ + --with-system \ + --with-thread \ + install +} diff --git a/packages/devel/ccache/package.mk b/packages/devel/ccache/package.mk new file mode 100644 index 000000000..7ed5c185e --- /dev/null +++ b/packages/devel/ccache/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ccache" +PKG_VERSION="3.7.12" +PKG_SHA256="a02f4e8360dc6618bc494ca35b0ae21cea080f804a4898eab1ad3fcd108eb400" +PKG_LICENSE="GPL" +PKG_SITE="https://ccache.dev/download.html" +PKG_URL="https://github.com/ccache/ccache/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="make:host" +PKG_LONGDESC="A compiler cache to speed up re-compilation of C/C++ code by caching." + +PKG_CONFIGURE_OPTS_HOST="--with-bundled-zlib" + +pre_configure_host() { + export CC=${LOCAL_CC} + export CXX=${LOCAL_CXX} +} + +post_makeinstall_host() { +# setup ccache + if [ -z "${CCACHE_DISABLE}" ]; then + ${TOOLCHAIN}/bin/ccache --max-size=${CCACHE_CACHE_SIZE} + fi + + cat > ${TOOLCHAIN}/bin/host-gcc < ${TOOLCHAIN}/bin/host-g++ <= 0x10100000L /* 1.1.0+ has no free compression methods */ ++#undef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS /* undef */ ++#endif ++ + #if (OPENSSL_VERSION_NUMBER < 0x0090808fL) + /* not present in older OpenSSL */ + #define OPENSSL_load_builtin_modules(x) diff --git a/packages/devel/configtools/package.mk b/packages/devel/configtools/package.mk new file mode 100644 index 000000000..6f4a009eb --- /dev/null +++ b/packages/devel/configtools/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="configtools" +PKG_VERSION="c8ddc8472f8efcadafc1ef53ca1d863415fddd5f" # 2020-12-22 +PKG_SHA256="6389d62e4e55554c764c2c0deb5b42767f34d7f274728c28355fedbaa337165b" +PKG_LICENSE="GPL" +PKG_SITE="http://git.savannah.gnu.org/cgit/config.git" +PKG_URL="http://git.savannah.gnu.org/cgit/config.git/snapshot/config-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="configtools" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/configtools + cp config.* ${TOOLCHAIN}/configtools +} diff --git a/packages/devel/crossguid/package.mk b/packages/devel/crossguid/package.mk new file mode 100644 index 000000000..cb08fe613 --- /dev/null +++ b/packages/devel/crossguid/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="crossguid" +PKG_VERSION="8f399e8bd4252be9952f3dfa8199924cc8487ca4" +PKG_SHA256="022c9f02cc36e865cd8fd0111a597ff2bd91988deeb348dbe2aba64aed1abd99" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/graeme-hill/crossguid" +PKG_URL="https://github.com/graeme-hill/crossguid/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain util-linux" +PKG_LONGDESC="minimal, cross platform, C++ GUID library" +PKG_TOOLCHAIN="manual" + +make_target() { + ${CXX} -c guid.cpp -o guid.o ${CXXFLAGS} -std=c++11 -DGUID_LIBUUID + ${AR} rvs libcrossguid.a guid.o +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/ + cp libcrossguid.a ${SYSROOT_PREFIX}/usr/lib/ + mkdir -p ${SYSROOT_PREFIX}/usr/include/ + cp guid.h ${SYSROOT_PREFIX}/usr/include +} diff --git a/packages/devel/dbus-glib/package.mk b/packages/devel/dbus-glib/package.mk new file mode 100644 index 000000000..205973e03 --- /dev/null +++ b/packages/devel/dbus-glib/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dbus-glib" +PKG_VERSION="0.110" +PKG_SHA256="7ce4760cf66c69148f6bd6c92feaabb8812dee30846b24cd0f7395c436d7e825" +PKG_LICENSE="GPL" +PKG_SITE="https://freedesktop.org/wiki/Software/dbus" +PKG_URL="https://dbus.freedesktop.org/releases/dbus-glib/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain dbus glib expat" +PKG_LONGDESC="A message bus, used for sending messages between applications." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic +lto" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_have_abstract_sockets=yes \ + ac_cv_func_posix_getpwnam_r=yes \ + have_abstract_sockets=yes \ + --enable-static \ + --disable-shared \ + --disable-tests \ + --disable-bash-completion \ + --enable-asserts=no" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin/dbus-binding-tool +} diff --git a/packages/devel/dbus-glib/patches/dbus-glib-01-dont-build-tools-examples.patch b/packages/devel/dbus-glib/patches/dbus-glib-01-dont-build-tools-examples.patch new file mode 100644 index 000000000..cfe18739d --- /dev/null +++ b/packages/devel/dbus-glib/patches/dbus-glib-01-dont-build-tools-examples.patch @@ -0,0 +1,38 @@ +From a45f914870e923741f3123799bd9e126b5da4aa0 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Wed, 20 Aug 2014 22:43:28 +0300 +Subject: [PATCH] dont build tools / examples + +--- + Makefile.am | 4 ++-- + dbus/Makefile.am | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index dd76c7e..78cb56f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,8 +1,8 @@ + ACLOCAL_AMFLAGS = -I m4 + GLIB_PC=dbus-glib-1.pc + +-SUBDIRS = dbus-gmain dbus tools test doc +-DIST_SUBDIRS = dbus-gmain dbus tools test doc m4 ++SUBDIRS = dbus-gmain dbus test doc ++DIST_SUBDIRS = dbus-gmain dbus test doc m4 + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = $(GLIB_PC) +diff --git a/dbus/Makefile.am b/dbus/Makefile.am +index 6d885f9..8bc102d 100644 +--- a/dbus/Makefile.am ++++ b/dbus/Makefile.am +@@ -1,4 +1,4 @@ +-SUBDIRS = . examples ++SUBDIRS = . + + INCLUDES = \ + -I$(top_srcdir) \ +-- +1.7.2.5 + diff --git a/packages/devel/elfutils/package.mk b/packages/devel/elfutils/package.mk new file mode 100644 index 000000000..0ceb31b61 --- /dev/null +++ b/packages/devel/elfutils/package.mk @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="elfutils" +PKG_VERSION="0.182" +PKG_SHA256="ecc406914edf335f0b7fc084ebe6c460c4d6d5175bfdd6688c1c78d9146b8858" +PKG_LICENSE="GPL" +PKG_SITE="https://sourceware.org/elfutils/" +PKG_URL="https://sourceware.org/elfutils/ftp/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="make:host zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib elfutils:host" +PKG_LONGDESC="A collection of utilities to handle ELF objects." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +if [ "${OS_VERSION}" = "devel" ]; then + PKG_PROGRAMS="--enable-programs --program-prefix=" + PKG_PROGRAMS_LIST="readelf" +else + PKG_PROGRAMS="--disable-programs" + PKG_PROGRAMS_LIST= +fi + +PKG_CONFIGURE_OPTS_HOST="utrace_cv_cc_biarch=false \ + --disable-programs \ + --disable-nls \ + --disable-debuginfod \ + --disable-libdebuginfod \ + --with-zlib \ + --without-bzlib \ + --without-lzma" + +PKG_CONFIGURE_OPTS_TARGET="utrace_cv_cc_biarch=false \ + ${PKG_PROGRAMS} \ + --disable-nls \ + --disable-debuginfod \ + --disable-libdebuginfod \ + --with-zlib \ + --without-bzlib \ + --without-lzma" + +post_makeinstall_target() { + # don't install progs into sysroot + rm -fr ${SYSROOT_PREFIX}/usr/bin + + if [ -n "${PKG_PROGRAMS_LIST}" ]; then + for PKG_TEMP in $(find ${INSTALL}/usr/bin -type f); do + listcontains "${PKG_PROGRAMS_LIST}" ${PKG_TEMP#${INSTALL}/usr/bin/} || rm ${PKG_TEMP} + done + fi +} diff --git a/packages/devel/elfutils/patches/elfutils-001-make-executables-optional.patch b/packages/devel/elfutils/patches/elfutils-001-make-executables-optional.patch new file mode 100644 index 000000000..f1ca865b8 --- /dev/null +++ b/packages/devel/elfutils/patches/elfutils-001-make-executables-optional.patch @@ -0,0 +1,46 @@ +From be854357189b6a3bd7e846b4e7914877f0deaf9f Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sat, 25 Jan 2020 21:28:52 +0000 +Subject: [PATCH] make executables optional + +--- + Makefile.am | 6 +++++- + configure.ac | 5 +++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index bd8926b..1733937 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -27,7 +27,11 @@ + pkginclude_HEADERS = version.h + + SUBDIRS = config m4 lib libelf libcpu backends libebl libdwelf libdwfl libdw \ +- libasm debuginfod src po doc tests ++ libasm debuginfod po doc tests ++ ++if BUILD_PROGRAMS ++ SUBDIRS += src ++endif + + EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \ + COPYING COPYING-GPLV2 COPYING-LGPLV3 +diff --git a/configure.ac b/configure.ac +index 5a2dc37..a1e856a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -87,6 +87,11 @@ AS_IF([test "$use_locks" = yes], + + AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.]) + ++AC_ARG_ENABLE([programs], ++AS_HELP_STRING([--enable-programs], [Build and install programs when enabled (default: disabled)]), ++ [build_programs=$enableval], [build_programs=no]) ++AM_CONDITIONAL(BUILD_PROGRAMS, test "$build_programs" = yes) ++ + AC_PROG_CC + AC_PROG_RANLIB + AC_PROG_YACC +-- +2.7.4 + diff --git a/packages/devel/fakeroot/package.mk b/packages/devel/fakeroot/package.mk new file mode 100644 index 000000000..fe858206d --- /dev/null +++ b/packages/devel/fakeroot/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fakeroot" +PKG_VERSION="1.25.3" +PKG_SHA256="8e903683357f7f5bcc31b879fd743391ad47691d4be33d24a76be3b6c21e956c" +PKG_LICENSE="GPL3" +PKG_SITE="https://tracker.debian.org/pkg/fakeroot" +PKG_URL="http://ftp.debian.org/debian/pool/main/f/fakeroot/${PKG_NAME}_${PKG_VERSION}.orig.tar.gz" +PKG_DEPENDS_HOST="ccache:host libcap:host autoconf:host libtool:host" +PKG_LONGDESC="fakeroot provides a fake root environment by means of LD_PRELOAD and SYSV IPC (or TCP) trickery." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_HOST="--with-gnu-ld" + +pre_configure_host() { + cd ${PKG_BUILD} + ./bootstrap +} diff --git a/packages/devel/fakeroot/patches/fakeroot-001-disable-docs-tests.patch b/packages/devel/fakeroot/patches/fakeroot-001-disable-docs-tests.patch new file mode 100644 index 000000000..94936d6ea --- /dev/null +++ b/packages/devel/fakeroot/patches/fakeroot-001-disable-docs-tests.patch @@ -0,0 +1,23 @@ +--- fakeroot-1.25.3/configure.ac 2020-10-08 17:13:18.000000000 +0000 ++++ fakeroot-1.25.3/configure.ac 2021-01-10 03:57:50.295218481 +0000 +@@ -597,9 +597,7 @@ + AC_CONFIG_FILES([ + Makefile + scripts/Makefile +- doc/Makefile +- doc/de/Makefile doc/es/Makefile doc/fr/Makefile doc/nl/Makefile doc/pt/Makefile doc/sv/Makefile +- test/Makefile test/defs]) ++ ]) + AC_OUTPUT + + dnl Local variables: +--- fakeroot-1.25.3/Makefile.am 2020-10-08 17:13:18.000000000 +0000 ++++ fakeroot-1.25.3/Makefile.am 2021-01-10 04:02:06.703081728 +0000 +@@ -1,6 +1,6 @@ + AUTOMAKE_OPTIONS=foreign + ACLOCAL_AMFLAGS = -I build-aux +-SUBDIRS=doc scripts test ++SUBDIRS=scripts + + noinst_LTLIBRARIES = libcommunicate.la libmacosx.la + libcommunicate_la_SOURCES = communicate.c diff --git a/packages/devel/flatbuffers/package.mk b/packages/devel/flatbuffers/package.mk new file mode 100644 index 000000000..8679e7483 --- /dev/null +++ b/packages/devel/flatbuffers/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flatbuffers" +PKG_VERSION="1.12.0" +PKG_SHA256="62f2223fb9181d1d6338451375628975775f7522185266cd5296571ac152bc45" +PKG_LICENSE="Apache-2.0" +PKG_SITE="https://github.com/google/flatbuffers" +PKG_URL="https://github.com/google/flatbuffers/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="An efficient cross platform serialization library for games and other memory constrained apps." + +PKG_CMAKE_OPTS_HOST="-DFLATBUFFERS_CODE_COVERAGE=OFF \ + -DFLATBUFFERS_BUILD_TESTS=OFF \ + -DFLATBUFFERS_INSTALL=ON \ + -DFLATBUFFERS_BUILD_FLATLIB=OFF \ + -DFLATBUFFERS_BUILD_FLATC=ON \ + -DFLATBUFFERS_BUILD_FLATHASH=OFF \ + -DFLATBUFFERS_BUILD_GRPCTEST=OFF \ + -DFLATBUFFERS_BUILD_SHAREDLIB=OFF" + +PKG_CMAKE_OPTS_TARGET="-DFLATBUFFERS_CODE_COVERAGE=OFF \ + -DFLATBUFFERS_BUILD_TESTS=OFF \ + -DFLATBUFFERS_INSTALL=ON \ + -DFLATBUFFERS_BUILD_FLATLIB=OFF \ + -DFLATBUFFERS_BUILD_FLATC=OFF \ + -DFLATBUFFERS_BUILD_FLATHASH=OFF \ + -DFLATBUFFERS_BUILD_GRPCTEST=OFF \ + -DFLATBUFFERS_BUILD_SHAREDLIB=OFF" + +pre_configure_host() { + export CXXFLAGS="${CXXFLAGS} -std=c++11" +} + +post_makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -PR ${PKG_BUILD}/.${HOST_NAME}/flatc ${TOOLCHAIN}/bin +} diff --git a/packages/devel/flex/package.mk b/packages/devel/flex/package.mk new file mode 100644 index 000000000..7a35ff90e --- /dev/null +++ b/packages/devel/flex/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flex" +PKG_VERSION="2.6.4" +PKG_SHA256="e87aae032bf07c26f85ac0ed3250998c37621d95f8bd748b31f15b33c45ee995" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/westes/flex" +PKG_URL="https://github.com/westes/flex/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host m4:host autotools:host bison:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A tool for generating programs that perform pattern-matching on text." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_HOST="--enable-static --disable-shared --disable-rpath --with-gnu-ld" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_realloc_0_nonnull=yes \ + ac_cv_func_malloc_0_nonnull=yes" + +post_makeinstall_host() { + cat > ${TOOLCHAIN}/bin/lex << "EOF" +#!/bin/sh +exec flex "$@" +EOF + + chmod -v 755 ${TOOLCHAIN}/bin/lex +} diff --git a/packages/devel/flex/patches/c5a26b17a2b091c560f6c4e6703e55f496bf74fa.patch b/packages/devel/flex/patches/c5a26b17a2b091c560f6c4e6703e55f496bf74fa.patch new file mode 100644 index 000000000..22592df34 --- /dev/null +++ b/packages/devel/flex/patches/c5a26b17a2b091c560f6c4e6703e55f496bf74fa.patch @@ -0,0 +1,28 @@ +From c5a26b17a2b091c560f6c4e6703e55f496bf74fa Mon Sep 17 00:00:00 2001 +From: Explorer09 +Date: Mon, 4 Sep 2017 10:47:33 +0800 +Subject: [PATCH] AC_USE_SYSTEM_EXTENSIONS in configure.ac + +This would define _GNU_SOURCE in config.h, enabling the reallocarray() +prototype in glibc 2.26+. + +Fixes #241. +--- + configure.ac | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/configure.ac b/configure.ac +index c6f12d64..3c977a4e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -25,8 +25,10 @@ + # autoconf requirements and initialization + + AC_INIT([the fast lexical analyser generator],[2.6.4],[flex-help@lists.sourceforge.net],[flex]) ++AC_PREREQ([2.60]) + AC_CONFIG_SRCDIR([src/scan.l]) + AC_CONFIG_AUX_DIR([build-aux]) ++AC_USE_SYSTEM_EXTENSIONS + LT_INIT + AM_INIT_AUTOMAKE([1.15 -Wno-portability foreign std-options dist-lzip parallel-tests subdir-objects]) + AC_CONFIG_HEADER([src/config.h]) diff --git a/packages/devel/flex/patches/flex-002-nocrap.patch b/packages/devel/flex/patches/flex-002-nocrap.patch new file mode 100644 index 000000000..e88034540 --- /dev/null +++ b/packages/devel/flex/patches/flex-002-nocrap.patch @@ -0,0 +1,13 @@ +--- a/Makefile.am 2020-01-08 12:57:40.940081434 +0100 ++++ b/Makefile.am 2020-01-08 12:57:59.603818146 +0100 +@@ -50,10 +50,6 @@ + SUBDIRS = \ + lib \ + src \ +- doc \ +- examples \ +- po \ +- tests \ + tools + + # Create the ChangeLog, but only if we're inside a git working directory diff --git a/packages/devel/fribidi/package.mk b/packages/devel/fribidi/package.mk new file mode 100644 index 000000000..9b86b4531 --- /dev/null +++ b/packages/devel/fribidi/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fribidi" +PKG_VERSION="1.0.10" +PKG_SHA256="7f1c687c7831499bcacae5e8675945a39bacbad16ecaa945e9454a32df653c01" +PKG_LICENSE="LGPL" +PKG_SITE="http://fribidi.freedesktop.org/" +PKG_URL="https://github.com/fribidi/fribidi/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A bidirectional algorithm library." +PKG_TOOLCHAIN="meson" +PKG_BUILD_FLAGS="+pic" + +PKG_MESON_OPTS_TARGET="-Ddeprecated=false \ + -Ddocs=false \ + -Ddefault_library=static" + +post_makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/bin + cp -f ${PKG_DIR}/scripts/fribidi-config ${SYSROOT_PREFIX}/usr/bin + chmod +x ${SYSROOT_PREFIX}/usr/bin/fribidi-config + + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/devel/fribidi/scripts/fribidi-config b/packages/devel/fribidi/scripts/fribidi-config new file mode 100644 index 000000000..120b3925d --- /dev/null +++ b/packages/devel/fribidi/scripts/fribidi-config @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +while test $# -gt 0; do + case $1 in + --libs) + echo "-lfribidi" + ;; + esac + shift +done diff --git a/packages/devel/gettext/package.mk b/packages/devel/gettext/package.mk new file mode 100644 index 000000000..f98b53ad8 --- /dev/null +++ b/packages/devel/gettext/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gettext" +PKG_VERSION="0.21" +PKG_SHA256="d20fcbb537e02dcf1383197ba05bd0734ef7bf5db06bdb241eb69b7d16b73192" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/s/gettext/" +PKG_URL="http://ftp.gnu.org/pub/gnu/gettext/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A program internationalization library and tools." + +PKG_CONFIGURE_OPTS_HOST="--disable-static --enable-shared \ + --disable-rpath \ + --with-gnu-ld \ + --disable-java \ + --disable-curses \ + --with-included-libxml \ + --disable-native-java \ + --disable-csharp \ + --without-emacs" diff --git a/packages/devel/gettext/patches/gettext-0.18.2-non_interactive.patch b/packages/devel/gettext/patches/gettext-0.18.2-non_interactive.patch new file mode 100644 index 000000000..86ca2db57 --- /dev/null +++ b/packages/devel/gettext/patches/gettext-0.18.2-non_interactive.patch @@ -0,0 +1,18 @@ +diff -Naur gettext-0.18.1.1-old/gettext-tools/misc/gettextize.in gettext-0.18.1.1-new/gettext-tools/misc/gettextize.in +--- gettext-0.18.1.1-old/gettext-tools/misc/gettextize.in 2010-06-06 05:49:57.000000000 -0700 ++++ gettext-0.18.1.1-new/gettext-tools/misc/gettextize.in 2010-08-18 06:52:51.000000000 -0700 +@@ -1272,10 +1272,10 @@ + 5) count="five paragraphs";; + *) count="$count paragraphs";; + esac +- echo "Press Return to acknowledge the previous $count." +- # Read from /dev/tty, not stdin, so that gettextize cannot be abused by +- # non-interactive tools. +- read dummy < /dev/tty ++# echo "Press Return to acknowledge the previous $count." ++# # Read from /dev/tty, not stdin, so that gettextize cannot be abused by ++# # non-interactive tools. ++# read dummy < /dev/tty + fi + + exit 0 diff --git a/packages/devel/gettext/patches/gettext-dont_build_docs_and_examples.patch b/packages/devel/gettext/patches/gettext-dont_build_docs_and_examples.patch new file mode 100644 index 000000000..a34330a02 --- /dev/null +++ b/packages/devel/gettext/patches/gettext-dont_build_docs_and_examples.patch @@ -0,0 +1,24 @@ +diff -Naur gettext-0.19.7/gettext-tools/Makefile.am gettext-0.19.7.patch/gettext-tools/Makefile.am +--- gettext-0.19.7/gettext-tools/Makefile.am 2015-12-08 13:50:04.000000000 +0100 ++++ gettext-0.19.7.patch/gettext-tools/Makefile.am 2016-01-01 20:49:07.476011819 +0100 +@@ -19,7 +19,7 @@ + AUTOMAKE_OPTIONS = 1.5 gnu no-dependencies + ACLOCAL_AMFLAGS = -I m4 -I ../gettext-runtime/m4 -I ../m4 -I gnulib-m4 -I libgrep/gnulib-m4 -I libgettextpo/gnulib-m4 + +-SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests examples doc ++SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests + + EXTRA_DIST = misc/DISCLAIM + MOSTLYCLEANFILES = core *.stackdump +diff -Naur gettext-0.19.7/gettext-tools/Makefile.in gettext-0.19.7.patch/gettext-tools/Makefile.in +--- gettext-0.19.7/gettext-tools/Makefile.in 2015-12-28 00:09:39.000000000 +0100 ++++ gettext-0.19.7.patch/gettext-tools/Makefile.in 2016-01-01 20:49:29.444038357 +0100 +@@ -1865,7 +1865,7 @@ + top_srcdir = @top_srcdir@ + AUTOMAKE_OPTIONS = 1.5 gnu no-dependencies + ACLOCAL_AMFLAGS = -I m4 -I ../gettext-runtime/m4 -I ../m4 -I gnulib-m4 -I libgrep/gnulib-m4 -I libgettextpo/gnulib-m4 +-SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests examples doc ++SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests + + # Allow users to use "gnulib-tool --update". + diff --git a/packages/devel/glib/package.mk b/packages/devel/glib/package.mk new file mode 100644 index 000000000..1d361db7f --- /dev/null +++ b/packages/devel/glib/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glib" +PKG_VER_MAJOR="2.70" +PKG_VERSION="${PKG_VER_MAJOR}.1" +PKG_SHA256="f9b7bce7f51753a1f43853bbcaca8bf09e15e994268e29cfd7a76f65636263c0" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.gtk.org/" +PKG_URL="https://download.gnome.org/sources/glib/${PKG_VER_MAJOR}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="libffi:host pcre:host Python3:host meson:host ninja:host" +PKG_DEPENDS_TARGET="toolchain pcre zlib libffi Python3:host util-linux" +PKG_LONGDESC="A library which includes support routines for C such as lists, trees, hashes, memory allocation." +PKG_TOOLCHAIN="meson" + +PKG_MESON_OPTS_HOST="-Ddefault_library=static \ + -Dinstalled_tests=false \ + -Dlibmount=disabled \ + -Dtests=false" + +PKG_MESON_OPTS_TARGET="-Ddefault_library=shared \ + -Dinstalled_tests=false \ + -Dselinux=disabled \ + -Dfam=false \ + -Dxattr=true \ + -Dgtk_doc=false \ + -Dman=false \ + -Ddtrace=false \ + -Dsystemtap=false \ + -Dbsymbolic_functions=true \ + -Dforce_posix_threads=true \ + -Dtests=false" + +PKG_MESON_PROPERTIES_TARGET=" +have_c99_vsnprintf=false +have_c99_snprintf=false +growing_stack=false +va_val_copy=false" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/lib/gdbus-2.0 + rm -rf ${INSTALL}/usr/lib/glib-2.0 + rm -rf ${INSTALL}/usr/lib/installed-tests + rm -rf ${INSTALL}/usr/share +} diff --git a/packages/devel/glibc/config/gai.conf b/packages/devel/glibc/config/gai.conf new file mode 100644 index 000000000..4616ed005 --- /dev/null +++ b/packages/devel/glibc/config/gai.conf @@ -0,0 +1,65 @@ +# Configuration for getaddrinfo(3). +# +# So far only configuration for the destination address sorting is needed. +# RFC 3484 governs the sorting. But the RFC also says that system +# administrators should be able to overwrite the defaults. This can be +# achieved here. +# +# All lines have an initial identifier specifying the option followed by +# up to two values. Information specified in this file replaces the +# default information. Complete absence of data of one kind causes the +# appropriate default information to be used. The supported commands include: +# +# reload +# If set to yes, each getaddrinfo(3) call will check whether this file +# changed and if necessary reload. This option should not really be +# used. There are possible runtime problems. The default is no. +# +# label +# Add another rule to the RFC 3484 label table. See section 2.1 in +# RFC 3484. The default is: +# +#label ::1/128 0 +#label ::/0 1 +#label 2002::/16 2 +#label ::/96 3 +#label ::ffff:0:0/96 4 +#label fec0::/10 5 +#label fc00::/7 6 +#label 2001:0::/32 7 +# +# This default differs from the tables given in RFC 3484 by handling +# (now obsolete) site-local IPv6 addresses and Unique Local Addresses. +# The reason for this difference is that these addresses are never +# NATed while IPv4 site-local addresses most probably are. Given +# the precedence of IPv6 over IPv4 (see below) on machines having only +# site-local IPv4 and IPv6 addresses a lookup for a global address would +# see the IPv6 be preferred. The result is a long delay because the +# site-local IPv6 addresses cannot be used while the IPv4 address is +# (at least for the foreseeable future) NATed. We also treat Teredo +# tunnels special. +# +# precedence +# Add another rule to the RFC 3484 precedence table. See section 2.1 +# and 10.3 in RFC 3484. The default is: +# +#precedence ::1/128 50 +#precedence ::/0 40 +#precedence 2002::/16 30 +#precedence ::/96 20 +#precedence ::ffff:0:0/96 10 +# +# For sites which prefer IPv4 connections change the last line to +# +#precedence ::ffff:0:0/96 100 + +# +# scopev4 +# Add another rule to the RFC 6724 scope table for IPv4 addresses. +# By default the scope IDs described in section 3.2 in RFC 6724 are +# used. Changing these defaults should hardly ever be necessary. +# The defaults are equivalent to: +# +#scopev4 ::ffff:169.254.0.0/112 2 +#scopev4 ::ffff:127.0.0.0/104 2 +#scopev4 ::ffff:0.0.0.0/96 14 diff --git a/packages/devel/glibc/config/host.conf b/packages/devel/glibc/config/host.conf new file mode 100644 index 000000000..d1a59f73a --- /dev/null +++ b/packages/devel/glibc/config/host.conf @@ -0,0 +1 @@ +multi on diff --git a/packages/devel/glibc/config/nsswitch-init.conf b/packages/devel/glibc/config/nsswitch-init.conf new file mode 100644 index 000000000..eba159e8f --- /dev/null +++ b/packages/devel/glibc/config/nsswitch-init.conf @@ -0,0 +1,3 @@ +# This is just enough to get DNS resolution working in the initramfs + +hosts: dns diff --git a/packages/devel/glibc/config/nsswitch-target.conf b/packages/devel/glibc/config/nsswitch-target.conf new file mode 100644 index 000000000..4391cdd21 --- /dev/null +++ b/packages/devel/glibc/config/nsswitch-target.conf @@ -0,0 +1,19 @@ +# /etc/nsswitch.conf +# +# Example configuration of GNU Name Service Switch functionality. +# + +passwd: files +group: files +shadow: files +gshadow: files + +hosts: files dns +networks: files dns + +protocols: files +services: files +ethers: files +rpc: files + +netgroup: files diff --git a/packages/devel/glibc/package.mk b/packages/devel/glibc/package.mk new file mode 100644 index 000000000..27579d350 --- /dev/null +++ b/packages/devel/glibc/package.mk @@ -0,0 +1,170 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glibc" +PKG_VERSION="2.34" +PKG_SHA256="44d26a1fe20b8853a48f470ead01e4279e869ac149b195dda4e44a195d981ab2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/libc/" +PKG_URL="http://ftp.gnu.org/pub/gnu/glibc/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="ccache:host autotools:host linux:host gcc:bootstrap pigz:host Python3:host" +PKG_DEPENDS_INIT="glibc" +PKG_LONGDESC="The Glibc package contains the main C library." +PKG_BUILD_FLAGS="-gold" + +PKG_CONFIGURE_OPTS_TARGET="BASH_SHELL=/bin/sh \ + ac_cv_path_PERL=no \ + ac_cv_prog_MAKEINFO= \ + --libexecdir=/usr/lib/glibc \ + --cache-file=config.cache \ + --disable-profile \ + --disable-sanity-checks \ + --enable-add-ons \ + --enable-bind-now \ + --with-elf \ + --with-tls \ + --with-__thread \ + --with-binutils=${BUILD}/toolchain/bin \ + --with-headers=${SYSROOT_PREFIX}/usr/include \ + --enable-kernel=4.4.0 \ + --without-cvs \ + --without-gd \ + --disable-build-nscd \ + --disable-nscd \ + --enable-lock-elision \ + --disable-timezone-tools" + +if build_with_debug; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-debug" +else + PKG_CONFIGURE_OPTS_TARGET+=" --disable-debug" +fi + +post_unpack() { + find "${PKG_BUILD}" -type f -name '*.py' -exec sed -e '1s,^#![[:space:]]*/usr/bin/python.*,#!/usr/bin/env python3,' -i {} \; +} + +pre_build_target() { + cd ${PKG_BUILD} + aclocal --force --verbose + autoconf --force --verbose + cd - +} + +pre_configure_target() { +# Filter out some problematic *FLAGS + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-ffast-math||g") + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-Ofast|-O2|g") + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|-O.|-O2|g") + + if [ -n "${PROJECT_CFLAGS}" ]; then + export CFLAGS=$(echo ${CFLAGS} | sed -e "s|${PROJECT_CFLAGS}||g") + fi + + export LDFLAGS=$(echo ${LDFLAGS} | sed -e "s|-ffast-math||g") + export LDFLAGS=$(echo ${LDFLAGS} | sed -e "s|-Ofast|-O2|g") + export LDFLAGS=$(echo ${LDFLAGS} | sed -e "s|-O.|-O2|g") + + export LDFLAGS=$(echo ${LDFLAGS} | sed -e "s|-Wl,--as-needed||") + + unset LD_LIBRARY_PATH + + # set some CFLAGS we need + export CFLAGS="${CFLAGS} -g -fno-stack-protector" + + export BUILD_CC=${HOST_CC} + export OBJDUMP_FOR_HOST=objdump + + cat >config.cache <configparms < +Date: Tue Oct 1 12:09:07 2013 +0300 + + fix dns with broken routers + + ref: https://fedoraproject.org/wiki/Networking/NameResolution/ADDRCONFIG + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 7bb3ded..2085ee5 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -830,6 +830,38 @@ gaih_inet (const char *name, const struct gaih_service *service, + } + } + ++ /* AI_ADDRCONFIG determines whether or not we should suppress any ++ * hostname lookups. If the local host has only IPv4 interfaces, ++ * then suppress lookups for IPv6 addresses, and vice versa; if ++ * the local host has only IPv6 interfaces, suppress any lookups ++ * for IPv4 addresses.. ++ * ++ * Link-local IPv6 addresses and loopback addresses of either ++ * family are ignored when determining whether or not the host has ++ * an interface of the given address family, cf. __check_pf(). ++ * ++ * This logic is only applied for AF_UNSPEC. If the caller ++ * explicitly requested an address family, give him what he asked ++ * for. ++ * ++ * If we didn't find any interfaces of either address family, ++ * we ignore AI_ADDRCONFIG and return all available resutlts. */ ++ int suppress_af = 0; ++ if (req->ai_family == AF_UNSPEC) ++ { ++ struct in6addrinfo *in6ai = NULL; ++ size_t in6ailen = 0; ++ bool seen_ipv4 = false; ++ bool seen_ipv6 = false; ++ __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen); ++ __free_in6ai (in6ai); ++ ++ if(seen_ipv4 && !seen_ipv6) ++ suppress_af = AF_INET6; ++ else if(seen_ipv6 && !seen_ipv4) ++ suppress_af = AF_INET; ++ } ++ + while (!no_more) + { + no_data = 0; +@@ -837,7 +869,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + + /* gethostbyname4_r sends out parallel A and AAAA queries and + is thus only suitable for PF_UNSPEC. */ +- if (req->ai_family == PF_UNSPEC) ++ if (req->ai_family == PF_UNSPEC && !suppress_af) + fct4 = __nss_lookup_function (nip, "gethostbyname4_r"); + + if (fct4 != NULL) +@@ -942,20 +974,22 @@ gaih_inet (const char *name, const struct gaih_service *service, + + if (fct != NULL) + { +- if (req->ai_family == AF_INET6 +- || req->ai_family == AF_UNSPEC) ++ if ((req->ai_family == AF_INET6 ++ || req->ai_family == AF_UNSPEC) ++ && suppress_af != AF_INET6) + { + gethosts (AF_INET6, struct in6_addr); + no_inet6_data = no_data; + inet6_status = status; + } +- if (req->ai_family == AF_INET +- || req->ai_family == AF_UNSPEC +- || (req->ai_family == AF_INET6 +- && (req->ai_flags & AI_V4MAPPED) +- /* Avoid generating the mapped addresses if we +- know we are not going to need them. */ +- && ((req->ai_flags & AI_ALL) || !got_ipv6))) ++ if ((req->ai_family == AF_INET ++ || req->ai_family == AF_UNSPEC ++ || (req->ai_family == AF_INET6 ++ && (req->ai_flags & AI_V4MAPPED) ++ /* Avoid generating the mapped addresses if we ++ know we are not going to need them. */ ++ && ((req->ai_flags & AI_ALL) || !got_ipv6))) ++ && suppress_af != AF_INET) + { + gethosts (AF_INET, struct in_addr); + +diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c +index 34c2146..be7de0d 100644 +--- a/sysdeps/unix/sysv/linux/check_pf.c ++++ b/sysdeps/unix/sysv/linux/check_pf.c +@@ -234,7 +234,8 @@ make_request (int fd, pid_t pid) + } + else + { +- if (!IN6_IS_ADDR_LOOPBACK (address)) ++ if (!IN6_IS_ADDR_LOOPBACK (address) && ++ !IN6_IS_ADDR_LINKLOCAL (address)) + seen_ipv6 = true; + } + } diff --git a/packages/devel/gmp/package.mk b/packages/devel/gmp/package.mk new file mode 100644 index 000000000..0f2e70de5 --- /dev/null +++ b/packages/devel/gmp/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gmp" +PKG_VERSION="6.2.1" +PKG_SHA256="fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2" +PKG_LICENSE="LGPLv3+" +PKG_SITE="http://gmplib.org/" +PKG_URL="https://gmplib.org/download/gmp/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host m4:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating point numbers." +PKG_BUILD_FLAGS="+pic:host" + +PKG_CONFIGURE_OPTS_HOST="--enable-cxx --enable-static --disable-shared" + +pre_configure_host() { + export CPPFLAGS="${CPPFLAGS} -fexceptions" +} diff --git a/packages/devel/gnulib/package.mk b/packages/devel/gnulib/package.mk new file mode 100644 index 000000000..39db806fc --- /dev/null +++ b/packages/devel/gnulib/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gnulib" +# Match version with GNULIB_REVISION in grub bootstrap.conf +PKG_VERSION="d271f868a8df9bbec29049d01e056481b7a1a263" +PKG_SHA256="4e23415ae2977ffca15e07419ceff3e9334d0369eafc9e7ae2578f8dd9a4839c" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.gnu.org/git/?group=gnulib" +PKG_URL="http://git.savannah.gnu.org/cgit/gnulib.git/snapshot/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_LONGDESC="GNU portability library" +PKG_TOOLCHAIN="manual" diff --git a/packages/devel/heimdal/package.mk b/packages/devel/heimdal/package.mk new file mode 100644 index 000000000..bff71ff3e --- /dev/null +++ b/packages/devel/heimdal/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="heimdal" +PKG_VERSION="7.7.0" +PKG_SHA256="f7d414d0914abb0e151a276b4de22cf4977fd6c28bd9ecdd990407b1138a945c" +PKG_LICENSE="BSD-3c" +PKG_SITE="http://www.h5l.org/" +PKG_URL="https://github.com/heimdal/heimdal/archive/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host Python3:host ncurses:host" +PKG_LONGDESC="Kerberos 5, PKIX, CMS, GSS-API, SPNEGO, NTLM, Digest-MD5 and, SASL implementation." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_HOST="ac_cv_prog_COMPILE_ET=no \ + --enable-static --disable-shared \ + --without-openldap \ + --without-capng \ + --without-sqlite3 \ + --without-libintl \ + --without-openssl \ + --without-berkeley-db \ + --without-readline \ + --without-libedit \ + --without-hesiod \ + --without-x \ + --disable-otp \ + --disable-heimdal-documentation" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -PR lib/asn1/asn1_compile ${TOOLCHAIN}/bin/heimdal_asn1_compile + cp -PR lib/com_err/compile_et ${TOOLCHAIN}/bin/heimdal_compile_et +} diff --git a/packages/devel/heimdal/patches/0001-upstream-check-libtinfo-for-tgetent.patch b/packages/devel/heimdal/patches/0001-upstream-check-libtinfo-for-tgetent.patch new file mode 100644 index 000000000..df80a4a8e --- /dev/null +++ b/packages/devel/heimdal/patches/0001-upstream-check-libtinfo-for-tgetent.patch @@ -0,0 +1,52 @@ +From 872222db35384f343a8a566a56a28c4eb73d38ed Mon Sep 17 00:00:00 2001 +From: Damir Franusic +Date: Sun, 9 Dec 2018 19:50:47 +0100 +Subject: [PATCH] AC_FIND_FUNC_NO_LIBS should check libtinfo for tgetent + +--- + configure.ac | 2 +- + lib/libedit/config.h.in | 3 +++ + lib/libedit/configure.ac | 3 ++- + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index f1e8d7b15e..f98a3c555e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -456,7 +456,7 @@ AC_FIND_FUNC_NO_LIBS(openpty, util,[ + #endif + ],[0,0,0,0,0]) + +-AC_FIND_FUNC_NO_LIBS(tgetent, termcap ncurses curses,[ ++AC_FIND_FUNC_NO_LIBS(tgetent, termcap ncurses curses tinfo,[ + #ifdef HAVE_TERMCAP_H + #include + #endif +diff --git a/lib/libedit/config.h.in b/lib/libedit/config.h.in +index ba283cc39f..059e5abc6a 100644 +--- a/lib/libedit/config.h.in ++++ b/lib/libedit/config.h.in +@@ -42,6 +42,9 @@ + /* Define to 1 if you have the `ncurses' library (-lncurses). */ + #undef HAVE_LIBNCURSES + ++/* Define to 1 if you have the `tinfo' library (-ltinfo). */ ++#undef HAVE_LIBTINFO ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_LIMITS_H + +diff --git a/lib/libedit/configure.ac b/lib/libedit/configure.ac +index 90c8ca57d7..89a9376b06 100644 +--- a/lib/libedit/configure.ac ++++ b/lib/libedit/configure.ac +@@ -36,7 +36,8 @@ EL_MANTYPE + + AC_CHECK_LIB(curses, tgetent,, + [AC_CHECK_LIB(ncurses, tgetent,, +- [AC_MSG_ERROR([libcurses or libncurses are required!])] )] ) ++ [AC_CHECK_LIB(tinfo, tgetent,, ++ [AC_MSG_ERROR([libcurses or libncurses are required!])] )] )] ) + + + # Checks for header files. diff --git a/packages/devel/heimdal/patches/0002-upstream-fix-configure-err-msg.patch b/packages/devel/heimdal/patches/0002-upstream-fix-configure-err-msg.patch new file mode 100644 index 000000000..64b203f06 --- /dev/null +++ b/packages/devel/heimdal/patches/0002-upstream-fix-configure-err-msg.patch @@ -0,0 +1,24 @@ +From 5e7bc8d8811fa401fa14adb9787504c0b460c7df Mon Sep 17 00:00:00 2001 +From: Earl Chew +Date: Wed, 20 May 2020 09:46:28 -0700 +Subject: [PATCH] [libedit/configure.ac] Refactor tgetent message to reflect + libraries searched + +Signed-off-by: Earl Chew +--- + lib/libedit/configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/libedit/configure.ac b/lib/libedit/configure.ac +index 89a9376b06..b94bafc6b9 100644 +--- a/lib/libedit/configure.ac ++++ b/lib/libedit/configure.ac +@@ -37,7 +37,7 @@ EL_MANTYPE + AC_CHECK_LIB(curses, tgetent,, + [AC_CHECK_LIB(ncurses, tgetent,, + [AC_CHECK_LIB(tinfo, tgetent,, +- [AC_MSG_ERROR([libcurses or libncurses are required!])] )] )] ) ++ [AC_MSG_ERROR([libcurses, libncurses, or tinfo are required!])] )] )] ) + + + # Checks for header files. diff --git a/packages/devel/heimdal/patches/22352b90e78e2d162b98b5ef6c84672c397be40a.patch b/packages/devel/heimdal/patches/22352b90e78e2d162b98b5ef6c84672c397be40a.patch new file mode 100644 index 000000000..0dcc31026 --- /dev/null +++ b/packages/devel/heimdal/patches/22352b90e78e2d162b98b5ef6c84672c397be40a.patch @@ -0,0 +1,29 @@ +From 22352b90e78e2d162b98b5ef6c84672c397be40a Mon Sep 17 00:00:00 2001 +From: Lars Wendler +Date: Wed, 17 Mar 2021 17:49:18 +0100 +Subject: [PATCH] autoconf-2.70 fix + +autoconf-2.70 and newer are more strict with quoting etc. and thus generate +a broken configure file: + + configure: 20855: Syntax error: ")" unexpected (expecting "fi") + +Gentoo-bug: https://bugs.gentoo.org/776241 +Signed-off-by: Lars Wendler +--- + cf/check-var.m4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cf/check-var.m4 b/cf/check-var.m4 +index 2fd7bca6f0..71d6f70ca8 100644 +--- a/cf/check-var.m4 ++++ b/cf/check-var.m4 +@@ -20,7 +20,7 @@ AC_MSG_RESULT($ac_foo) + if test "$ac_foo" = yes; then + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]$1), 1, + [Define if you have the `]$1[' variable.]) +- m4_ifval([$2], AC_CHECK_DECLS([$1],[],[],[$2])) ++ m4_ifval([$2], [AC_CHECK_DECLS([$1],[],[],[$2])]) + fi + ]) + diff --git a/packages/devel/heimdal/patches/c4cff6859d183a40fb35a76e2bc1ce084b3a6d67.patch b/packages/devel/heimdal/patches/c4cff6859d183a40fb35a76e2bc1ce084b3a6d67.patch new file mode 100644 index 000000000..826c7fb51 --- /dev/null +++ b/packages/devel/heimdal/patches/c4cff6859d183a40fb35a76e2bc1ce084b3a6d67.patch @@ -0,0 +1,22 @@ +From c4cff6859d183a40fb35a76e2bc1ce084b3a6d67 Mon Sep 17 00:00:00 2001 +From: Luke Howard +Date: Mon, 24 Dec 2018 02:21:32 +0000 +Subject: [PATCH] hx509: fix dependency, hxtool requires ASN.1 headers + +--- + lib/hx509/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/hx509/Makefile.am b/lib/hx509/Makefile.am +index c7ef53182d..b21d85202c 100644 +--- a/lib/hx509/Makefile.am ++++ b/lib/hx509/Makefile.am +@@ -164,7 +164,7 @@ hxtool-commands.c hxtool-commands.h: hxtool-commands.in $(SLC) + dist_hxtool_SOURCES = hxtool.c + nodist_hxtool_SOURCES = hxtool-commands.c hxtool-commands.h + +-$(hxtool_OBJECTS): hxtool-commands.h hx509_err.h ++$(hxtool_OBJECTS): hxtool-commands.h $(nodist_include_HEADERS) + + hxtool_LDADD = \ + libhx509.la \ diff --git a/packages/devel/heimdal/patches/cc6a3f337bac0411d0bb1c924fd857603a258d2f.patch b/packages/devel/heimdal/patches/cc6a3f337bac0411d0bb1c924fd857603a258d2f.patch new file mode 100644 index 000000000..15a6161fe --- /dev/null +++ b/packages/devel/heimdal/patches/cc6a3f337bac0411d0bb1c924fd857603a258d2f.patch @@ -0,0 +1,22 @@ +From cc6a3f337bac0411d0bb1c924fd857603a258d2f Mon Sep 17 00:00:00 2001 +From: Nicolas Williams +Date: Tue, 17 Mar 2020 19:46:37 -0500 +Subject: [PATCH] hcrypto: Fix Makefile build race + +--- + lib/hcrypto/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/hcrypto/Makefile.am b/lib/hcrypto/Makefile.am +index 195117d174..3c6ee3ca84 100644 +--- a/lib/hcrypto/Makefile.am ++++ b/lib/hcrypto/Makefile.am +@@ -298,7 +298,7 @@ ltmsources = \ + libtommath/bn_mp_to_unsigned_bin_n.c + + +-$(libhcrypto_la_OBJECTS): hcrypto-link ++$(libhcrypto_la_OBJECTS) $(test_rand_OBJECTS): hcrypto-link + + libhcrypto_la_CPPFLAGS = -DBUILD_HCRYPTO_LIB $(AM_CPPFLAGS) + diff --git a/packages/devel/heimdal/patches/yyerror-match-posix-standard.patch b/packages/devel/heimdal/patches/yyerror-match-posix-standard.patch new file mode 100644 index 000000000..07b84c355 --- /dev/null +++ b/packages/devel/heimdal/patches/yyerror-match-posix-standard.patch @@ -0,0 +1,83 @@ +From 79b8337d54b2d85f73eff2d033ca592447ac5fce Mon Sep 17 00:00:00 2001 +From: heitbaum +Date: Fri, 10 Sep 2021 00:28:16 +1000 +Subject: [PATCH] yyerror: update to POSIX standard + +To comply with the latest POSIX standard, in Yacc compatibility mode +(options `-y`/`--yacc`) Bison now generates prototypes for yyerror and +yylex. In some situations, this is breaking compatibility: if the user +has already declared these functions but with some differences (e.g., to +declare them as static, or to use specific attributes), the generated +parser will fail to compile. To disable these prototypes, #define yyerror +(to `yyerror`), and likewise for yylex. + +refer: https://git.savannah.gnu.org/cgit/bison.git/tree/NEWS + +GNU Bison 3.8 +--- + lib/asn1/asn1parse.y | 1 + + lib/com_err/parse.y | 5 +++-- + lib/sl/slc-lex.l | 2 +- + lib/sl/slc.h | 3 ++- + 4 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/lib/asn1/asn1parse.y b/lib/asn1/asn1parse.y +index 9d8b76f582..91b163a28b 100644 +--- a/lib/asn1/asn1parse.y ++++ b/lib/asn1/asn1parse.y +@@ -65,6 +65,7 @@ static void validate_object_set(IOSObjectSet *); + static struct constraint_spec *new_constraint_spec(enum ctype); + static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype); + void yyerror (const char *); ++#define yyerror yyerror + static struct objid *new_objid(const char *label, int value); + static void add_oid_to_tail(struct objid *, struct objid *); + static void fix_labels(Symbol *s); +diff --git a/lib/com_err/parse.y b/lib/com_err/parse.y +index 0c2e5084b5..bcb9b05204 100644 +--- a/lib/com_err/parse.y ++++ b/lib/com_err/parse.y +@@ -35,7 +35,8 @@ + #include "compile_et.h" + #include "lex.h" + +-void yyerror (char *s); ++void yyerror (const char *s); ++#define yyerror yyerror + static long name2number(const char *str); + + extern char *yytext; +@@ -168,7 +169,7 @@ name2number(const char *str) + } + + void +-yyerror (char *s) ++yyerror (const char *s) + { + _lex_error_message ("%s\n", s); + } +diff --git a/lib/sl/slc-lex.l b/lib/sl/slc-lex.l +index 50965bccd7..3a37302336 100644 +--- a/lib/sl/slc-lex.l ++++ b/lib/sl/slc-lex.l +@@ -78,7 +78,7 @@ error_message (const char *format, ...) + } + + void +-yyerror (char *s) ++yyerror (const char *s) + { + error_message("%s\n", s); + } +diff --git a/lib/sl/slc.h b/lib/sl/slc.h +index 6e45ed2f15..e4dc2cba6b 100644 +--- a/lib/sl/slc.h ++++ b/lib/sl/slc.h +@@ -51,5 +51,6 @@ extern char *filename; + extern int error_flag; + void error_message (const char *format, ...); + int yylex(void); +-void yyerror (char *s); ++void yyerror (const char *s); ++#define yyerror yyerror + extern unsigned lineno; diff --git a/packages/devel/intltool/package.mk b/packages/devel/intltool/package.mk new file mode 100644 index 000000000..4fb8320d1 --- /dev/null +++ b/packages/devel/intltool/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="intltool" +PKG_VERSION="0.51.0" +PKG_SHA256="67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnome.org" +PKG_URL="http://launchpad.net/intltool/trunk/${PKG_VERSION}/+download/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="Tools to translate strings from various source files (.xml.in, .glade, .desktop.in, .server.in, .oaf.in)." + +post_makeinstall_host() { + mkdir -p ${SYSROOT_PREFIX}/usr/share/aclocal + cp ../intltool.m4 ${SYSROOT_PREFIX}/usr/share/aclocal +} diff --git a/packages/devel/intltool/patches/intltool-0001-fix-regex-expressions.patch b/packages/devel/intltool/patches/intltool-0001-fix-regex-expressions.patch new file mode 100644 index 000000000..dcf910542 --- /dev/null +++ b/packages/devel/intltool/patches/intltool-0001-fix-regex-expressions.patch @@ -0,0 +1,45 @@ +=== modified file 'intltool-update.in' +--- a/intltool-update.in 2014-05-14 02:15:53 +0000 ++++ b/intltool-update.in 2016-01-19 15:59:38 +0000 +@@ -1062,7 +1062,7 @@ + } + } + +- if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/) ++ if ($str =~ /^(.*)\$\{?([A-Z_]+)}?(.*)$/) + { + my $rest = $3; + my $untouched = $1; +@@ -1190,10 +1190,10 @@ + $name =~ s/\(+$//g; + $version =~ s/\(+$//g; + +- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); +- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); +- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); +- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); ++ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/); ++ $varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/); ++ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/); ++ $varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/); + } + + if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)[,]?([^,\)]+)?/m) +@@ -1219,11 +1219,11 @@ + $version =~ s/\(+$//g; + $bugurl =~ s/\(+$//g if (defined $bugurl); + +- $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/); +- $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/); +- $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/); +- $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/); +- $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\${?\w+}?/); ++ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/); ++ $varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/); ++ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/); ++ $varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/); ++ $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\$\{?\w+}?/); + } + + # \s makes this not work, why? + diff --git a/packages/devel/libaio/package.mk b/packages/devel/libaio/package.mk new file mode 100644 index 000000000..f503cca14 --- /dev/null +++ b/packages/devel/libaio/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libaio" +PKG_VERSION="0.3.112" +PKG_SHA256="f69e5800425f4ea957426693ac09f9896bb993db5490fa021644454adcc72a32" +PKG_LICENSE="GPL" +PKG_SITE="http://lse.sourceforge.net/io/aio.html" +PKG_URL="http://http.debian.net/debian/pool/main/liba/libaio/${PKG_NAME}_${PKG_VERSION}.orig.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Kernel Asynchronous I/O (AIO) Support for Linux." + +make_target() { + make -C src +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp -PR src/libaio.a ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/include + cp -PR src/libaio.h ${SYSROOT_PREFIX}/usr/include +} diff --git a/packages/devel/libcap/package.mk b/packages/devel/libcap/package.mk new file mode 100644 index 000000000..fccd8ac04 --- /dev/null +++ b/packages/devel/libcap/package.mk @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv) +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libcap" +PKG_VERSION="2.46" +PKG_SHA256="4ed3d11413fa6c9667e49f819808fbb581cd8864b839f87d7c2a02c70f21d8b4" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library for getting and setting POSIX.1e capabilities." + +post_unpack() { + mkdir -p ${PKG_BUILD}/.${HOST_NAME} + cp -r ${PKG_BUILD}/* ${PKG_BUILD}/.${HOST_NAME} + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} + cp -r ${PKG_BUILD}/* ${PKG_BUILD}/.${TARGET_NAME} +} + +make_host() { + cd ${PKG_BUILD}/.${HOST_NAME} + make CC=${CC} \ + AR=${AR} \ + RANLIB=${RANLIB} \ + CFLAGS="${HOST_CFLAGS}" \ + BUILD_CFLAGS="${HOST_CFLAGS} -I${PKG_BUILD}/libcap/include" \ + PAM_CAP=no \ + lib=/lib \ + BUILD_GPERF=no \ + -C libcap libcap.pc libcap.a +} + +make_target() { + cd ${PKG_BUILD}/.${TARGET_NAME} + make CC=${CC} \ + AR=${AR} \ + RANLIB=${RANLIB} \ + CFLAGS="${TARGET_CFLAGS}" \ + BUILD_CC=${HOST_CC} \ + BUILD_CFLAGS="${HOST_CFLAGS} -I${PKG_BUILD}/libcap/include" \ + PAM_CAP=no \ + lib=/lib \ + BUILD_GPERF=no \ + -C libcap libcap.pc libcap.a +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/lib + cp libcap/libcap.a ${TOOLCHAIN}/lib + + mkdir -p ${TOOLCHAIN}/lib/pkgconfig + cp libcap/libcap.pc ${TOOLCHAIN}/lib/pkgconfig + + mkdir -p ${TOOLCHAIN}/include/sys + cp libcap/include/sys/capability.h ${TOOLCHAIN}/include/sys +} + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp libcap/libcap.a ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp libcap/libcap.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig + + mkdir -p ${SYSROOT_PREFIX}/usr/include/sys + cp libcap/include/sys/capability.h ${SYSROOT_PREFIX}/usr/include/sys +} diff --git a/packages/devel/libcec-4.0.5/package.mk b/packages/devel/libcec-4.0.5/package.mk new file mode 100644 index 000000000..445983bd0 --- /dev/null +++ b/packages/devel/libcec-4.0.5/package.mk @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="libcec-4.0.5" +PKG_VERSION="libcec-4.0.5" +PKG_SHA256="e4d749430ebcf3a35ec3a3f6675afcc5755afc1e5801c12121e54d80eb187743" +PKG_LICENSE="GPL" +PKG_SITE="http://libcec.pulse-eight.com/" +PKG_URL="https://github.com/Pulse-Eight/libcec/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd p8-platform swig:host" +PKG_LONGDESC="libCEC is an open-source dual licensed library designed for communicating with the Pulse-Eight USB - CEC Adaptor." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=1 \ + -DCMAKE_INSTALL_LIBDIR:STRING=lib \ + -DCMAKE_INSTALL_LIBDIR_NOARCH:STRING=lib \ + -DSKIP_PYTHON_WRAPPER=1 \ + -DHAVE_IMX_API=0 \ + -DHAVE_GIT_BIN=0" + +if [ "$PROJECT" = "RPi" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET bcm2835-driver" +fi + +if [ "$KODIPLAYER_DRIVER" = "libamcodec" ]; then + if [ "$TARGET_KERNEL_ARCH" = "arm64" ]; then + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AOCEC_API=1" + else + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AMLOGIC_API=1" + fi +else + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AOCEC_API=0 -DHAVE_AMLOGIC_API=0" +fi + +# libX11 and xrandr to read the sink's EDID, used to determine the PC's HDMI physical address +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libX11 libXrandr" +fi + +if [ "$CEC_FRAMEWORK_SUPPORT" = "yes" ]; then + PKG_PATCH_DIRS="cec-framework" + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_LINUX_API=1" +fi + +pre_configure_target() { + if [ "$PROJECT" = "RPi" ]; then + # detecting RPi support fails without -lvchiq_arm + export LDFLAGS="$LDFLAGS -lvchiq_arm" + fi +} + +post_makeinstall_target() { + # Remove the Python3 demo - useless for us + rm -f $INSTALL/usr/bin/pyCecClient + + PYTHON_DIR=$INSTALL/usr/lib/$PKG_PYTHON_VERSION + if [ -d $PYTHON_DIR/dist-packages ]; then + mv $PYTHON_DIR/dist-packages $PYTHON_DIR/site-packages + fi +} diff --git a/packages/devel/libcec-4.0.5/patches/cec-framework/libcec-0001-PR380.patch b/packages/devel/libcec-4.0.5/patches/cec-framework/libcec-0001-PR380.patch new file mode 100644 index 000000000..49af7eadf --- /dev/null +++ b/packages/devel/libcec-4.0.5/patches/cec-framework/libcec-0001-PR380.patch @@ -0,0 +1,887 @@ +From 467cc79fd289403e7d4f6e4e817b906c0c0027dd Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 6 Sep 2017 17:37:05 +0200 +Subject: [PATCH] Add Linux CEC Adapter + +--- + docs/README.linux.md | 6 + + include/cectypes.h | 11 + + src/libcec/CECTypeUtils.h | 2 + + src/libcec/CMakeLists.txt | 2 + + src/libcec/adapter/AdapterFactory.cpp | 26 +- + .../Linux/LinuxCECAdapterCommunication.cpp | 438 ++++++++++++++++++ + .../Linux/LinuxCECAdapterCommunication.h | 95 ++++ + .../Linux/LinuxCECAdapterDetection.cpp | 50 ++ + .../adapter/Linux/LinuxCECAdapterDetection.h | 51 ++ + src/libcec/cmake/CheckPlatformSupport.cmake | 12 + + src/libcec/cmake/DisplayPlatformSupport.cmake | 6 + + src/libcec/env.h.in | 3 + + 12 files changed, 700 insertions(+), 2 deletions(-) + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.h + +diff --git a/docs/README.linux.md b/docs/README.linux.md +index c59fb80..e8053cc 100644 +--- a/docs/README.linux.md ++++ b/docs/README.linux.md +@@ -51,5 +51,11 @@ Pass the argument `-DHAVE_TDA995X_API=1` to the cmake command in the compilation + cmake -DHAVE_TDA995X_API=1 .. + ``` + ++### Linux CEC Framework (v4.10+) ++Pass the argument `-DHAVE_LINUX_API=1` to the cmake command in the compilation instructions: ++``` ++cmake -DHAVE_LINUX_API=1 .. ++``` ++ + ### Debian / Ubuntu .deb packaging + See [docs/README.debian.md](README.debian.md). +\ No newline at end of file +diff --git a/include/cectypes.h b/include/cectypes.h +index 9c91842..2c32e4d 100644 +--- a/include/cectypes.h ++++ b/include/cectypes.h +@@ -281,6 +281,16 @@ namespace CEC { + */ + #define CEC_MAX_DATA_PACKET_SIZE (16 * 4) + ++/*! ++ * the path to use for the Linux CEC device ++ */ ++#define CEC_LINUX_PATH "/dev/cec0" ++ ++/*! ++ * the name of the virtual COM port to use for the Linux' CEC wire ++ */ ++#define CEC_LINUX_VIRTUAL_COM "Linux" ++ + /*! + * the path to use for the AOCEC HDMI CEC device + */ +@@ -861,6 +871,7 @@ typedef enum cec_adapter_type + ADAPTERTYPE_RPI = 0x100, + ADAPTERTYPE_TDA995x = 0x200, + ADAPTERTYPE_EXYNOS = 0x300, ++ ADAPTERTYPE_LINUX = 0x400, + ADAPTERTYPE_AOCEC = 0x500 + } cec_adapter_type; + +diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h +index 25c1c6e..15f9543 100644 +--- a/src/libcec/CECTypeUtils.h ++++ b/src/libcec/CECTypeUtils.h +@@ -766,6 +766,8 @@ namespace CEC + return "Raspberry Pi"; + case ADAPTERTYPE_TDA995x: + return "TDA995x"; ++ case ADAPTERTYPE_LINUX: ++ return "Linux"; + default: + return "unknown"; + } +diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt +index 6baee69..74fe5f3 100644 +--- a/src/libcec/CMakeLists.txt ++++ b/src/libcec/CMakeLists.txt +@@ -89,6 +89,8 @@ set(CEC_HEADERS devices/CECRecordingDevice.h + adapter/Exynos/ExynosCEC.h + adapter/Exynos/ExynosCECAdapterDetection.h + adapter/Exynos/ExynosCECAdapterCommunication.h ++ adapter/Linux/LinuxCECAdapterDetection.h ++ adapter/Linux/LinuxCECAdapterCommunication.h + adapter/AOCEC/AOCEC.h + adapter/AOCEC/AOCECAdapterDetection.h + adapter/AOCEC/AOCECAdapterCommunication.h +diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp +index 91195ea..323c272 100644 +--- a/src/libcec/adapter/AdapterFactory.cpp ++++ b/src/libcec/adapter/AdapterFactory.cpp +@@ -58,6 +58,11 @@ + #include "Exynos/ExynosCECAdapterCommunication.h" + #endif + ++#if defined(HAVE_LINUX_API) ++#include "Linux/LinuxCECAdapterDetection.h" ++#include "Linux/LinuxCECAdapterCommunication.h" ++#endif ++ + #if defined(HAVE_AOCEC_API) + #include "AOCEC/AOCECAdapterDetection.h" + #include "AOCEC/AOCECAdapterCommunication.h" +@@ -131,6 +136,18 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + } + #endif + ++#if defined(HAVE_LINUX_API) ++ if (iAdaptersFound < iBufSize && CLinuxCECAdapterDetection::FindAdapter()) ++ { ++ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_LINUX_PATH); ++ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_LINUX_VIRTUAL_COM); ++ deviceList[iAdaptersFound].iVendorId = 0; ++ deviceList[iAdaptersFound].iProductId = 0; ++ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_LINUX; ++ iAdaptersFound++; ++ } ++#endif ++ + #if defined(HAVE_AOCEC_API) + if (iAdaptersFound < iBufSize && CAOCECAdapterDetection::FindAdapter()) + { +@@ -144,7 +161,7 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + #endif + + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) + #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" + #endif + +@@ -163,6 +180,11 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CExynosCECAdapterCommunication(m_lib->m_cec); + #endif + ++#if defined(HAVE_LINUX_API) ++ if (!strcmp(strPort, CEC_LINUX_VIRTUAL_COM)) ++ return new CLinuxCECAdapterCommunication(m_lib->m_cec); ++#endif ++ + #if defined(HAVE_AOCEC_API) + if (!strcmp(strPort, CEC_AOCEC_VIRTUAL_COM)) + return new CAOCECAdapterCommunication(m_lib->m_cec); +@@ -177,7 +199,7 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); + #endif + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_AOCEC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) + return NULL; + #endif + } +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp +new file mode 100644 +index 0000000..6a28835 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp +@@ -0,0 +1,438 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017-2019 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include ++#include ++ ++#if defined(HAVE_LINUX_API) ++#include "LinuxCECAdapterCommunication.h" ++#include "CECTypeUtils.h" ++#include "LibCEC.h" ++#include "p8-platform/util/buffer.h" ++#include ++ ++using namespace CEC; ++using namespace P8PLATFORM; ++ ++#define LIB_CEC m_callback->GetLib() ++ ++// Required capabilities ++#define CEC_LINUX_CAPABILITIES (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH) ++ ++CLinuxCECAdapterCommunication::CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback) ++ : IAdapterCommunication(callback) ++{ ++ m_fd = INVALID_SOCKET_VALUE; ++} ++ ++CLinuxCECAdapterCommunication::~CLinuxCECAdapterCommunication(void) ++{ ++ Close(); ++} ++ ++bool CLinuxCECAdapterCommunication::Open(uint32_t UNUSED(iTimeoutMs), bool UNUSED(bSkipChecks), bool bStartListening) ++{ ++ if (IsOpen()) ++ Close(); ++ ++ if ((m_fd = open(CEC_LINUX_PATH, O_RDWR)) >= 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - m_fd=%d bStartListening=%d", m_fd, bStartListening); ++ ++ // Ensure the CEC device supports required capabilities ++ struct cec_caps caps = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_CAPS, &caps) || (caps.capabilities & CEC_LINUX_CAPABILITIES) != CEC_LINUX_CAPABILITIES) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_CAPS failed - capabilities=%02x errno=%d", caps.capabilities, errno); ++ Close(); ++ return false; ++ } ++ ++ if (!bStartListening) ++ { ++ Close(); ++ return true; ++ } ++ ++ // This is an exclusive follower, in addition put the CEC device into passthrough mode ++ uint32_t mode = CEC_MODE_INITIATOR | CEC_MODE_EXCL_FOLLOWER_PASSTHRU; ++ if (ioctl(m_fd, CEC_S_MODE, &mode)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_S_MODE failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ uint16_t addr; ++ if (ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR - addr=%04x", addr); ++ ++ if (addr == CEC_PHYS_ADDR_INVALID) ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "CLinuxCECAdapterCommunication::Open - physical address is invalid"); ++ ++ // Clear existing logical addresses and set the CEC device to the unconfigured state ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ // Set logical address to unregistered, without any logical address configured no messages is transmitted or received ++ log_addrs = {}; ++ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; ++ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; ++ log_addrs.num_log_addrs = 1; ++ log_addrs.flags = CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK; ++ log_addrs.log_addr[0] = CEC_LOG_ADDR_UNREGISTERED; ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ if (CreateThread()) ++ return true; ++ ++ Close(); ++ } ++ ++ return false; ++} ++ ++void CLinuxCECAdapterCommunication::Close(void) ++{ ++ StopThread(0); ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Close - m_fd=%d", m_fd); ++ ++ close(m_fd); ++ m_fd = INVALID_SOCKET_VALUE; ++} ++ ++bool CLinuxCECAdapterCommunication::IsOpen(void) ++{ ++ return m_fd != INVALID_SOCKET_VALUE; ++} ++ ++cec_adapter_message_state CLinuxCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) ++{ ++ if (IsOpen()) ++ { ++ struct cec_msg msg; ++ cec_msg_init(&msg, data.initiator, data.destination); ++ ++ if (data.opcode_set) ++ { ++ msg.msg[msg.len++] = data.opcode; ++ ++ if (data.parameters.size) ++ { ++ memcpy(&msg.msg[msg.len], data.parameters.data, data.parameters.size); ++ msg.len += data.parameters.size; ++ } ++ } ++ ++ if (ioctl(m_fd, CEC_TRANSMIT, &msg)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT failed - tx_status=%02x errno=%d", msg.tx_status, errno); ++ return ADAPTER_MESSAGE_STATE_ERROR; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT - tx_status=%02x len=%d addr=%02x opcode=%02x", msg.tx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); ++ ++ // The CEC driver will make re-transmission attempts ++ bRetry = false; ++ ++ if (msg.tx_status & CEC_TX_STATUS_OK) ++ return ADAPTER_MESSAGE_STATE_SENT_ACKED; ++ ++ if (msg.tx_status & CEC_TX_STATUS_NACK) ++ return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; ++ ++ return ADAPTER_MESSAGE_STATE_ERROR; ++ } ++ ++ return ADAPTER_MESSAGE_STATE_UNKNOWN; ++} ++ ++bool CLinuxCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) ++{ ++ if (IsOpen()) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ // TODO: Claiming a logical address will only work when CEC device has a valid physical address ++ ++ // Clear existing logical addresses and set the CEC device to the unconfigured state ++ if (log_addrs.num_log_addrs) ++ { ++ log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ } ++ ++ if (!addresses.IsEmpty()) ++ { ++ // NOTE: This can only be configured when num_log_addrs > 0 ++ // and gets reset when num_log_addrs = 0 ++ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; ++ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; ++ ++ // TODO: Support more then the primary logical address ++ log_addrs.num_log_addrs = 1; ++ log_addrs.log_addr[0] = addresses.primary; ++ ++ switch (addresses.primary) ++ { ++ case CECDEVICE_AUDIOSYSTEM: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM; ++ break; ++ case CECDEVICE_PLAYBACKDEVICE1: ++ case CECDEVICE_PLAYBACKDEVICE2: ++ case CECDEVICE_PLAYBACKDEVICE3: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_PLAYBACK; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK; ++ break; ++ case CECDEVICE_RECORDINGDEVICE1: ++ case CECDEVICE_RECORDINGDEVICE2: ++ case CECDEVICE_RECORDINGDEVICE3: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_RECORD; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD; ++ break; ++ case CECDEVICE_TUNER1: ++ case CECDEVICE_TUNER2: ++ case CECDEVICE_TUNER3: ++ case CECDEVICE_TUNER4: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TUNER; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER; ++ break; ++ case CECDEVICE_TV: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TV; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV; ++ break; ++ default: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; ++ break; ++ } ++ } ++ else ++ log_addrs.num_log_addrs = 0; ++ ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ if (log_addrs.num_log_addrs && !log_addrs.log_addr_mask) ++ return false; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++cec_logical_addresses CLinuxCECAdapterCommunication::GetLogicalAddresses(void) const ++{ ++ cec_logical_addresses addresses; ++ addresses.Clear(); ++ ++ if (m_fd != INVALID_SOCKET_VALUE) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ return addresses; ++ } ++ ++ for (int i = 0; i < log_addrs.num_log_addrs; i++) ++ addresses.Set(cec_logical_address(log_addrs.log_addr[i])); ++ } ++ ++ return addresses; ++} ++ ++uint16_t CLinuxCECAdapterCommunication::GetPhysicalAddress(void) ++{ ++ if (IsOpen()) ++ { ++ uint16_t addr; ++ if (!ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) ++ return addr; ++ ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetPhysicalAddress - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); ++ } ++ ++ return CEC_INVALID_PHYSICAL_ADDRESS; ++} ++ ++cec_vendor_id CLinuxCECAdapterCommunication::GetVendorId(void) ++{ ++ if (IsOpen()) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (!ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ return cec_vendor_id(log_addrs.vendor_id); ++ ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetVendorId - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ } ++ ++ return CEC_VENDOR_UNKNOWN; ++} ++ ++void *CLinuxCECAdapterCommunication::Process(void) ++{ ++ CTimeout phys_addr_timeout; ++ bool phys_addr_changed = false; ++ uint16_t phys_addr = CEC_INVALID_PHYSICAL_ADDRESS; ++ fd_set rd_fds; ++ fd_set ex_fds; ++ ++ while (!IsStopped()) ++ { ++ struct timeval timeval = {}; ++ timeval.tv_sec = 1; ++ ++ FD_ZERO(&rd_fds); ++ FD_ZERO(&ex_fds); ++ FD_SET(m_fd, &rd_fds); ++ FD_SET(m_fd, &ex_fds); ++ ++ if (select(m_fd + 1, &rd_fds, NULL, &ex_fds, &timeval) < 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - select failed - errno=%d", errno); ++ break; ++ } ++ ++ if (FD_ISSET(m_fd, &ex_fds)) ++ { ++ struct cec_event ev = {}; ++ if (ioctl(m_fd, CEC_DQEVENT, &ev)) ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_DQEVENT failed - errno=%d", errno); ++ else if (ev.event == CEC_EVENT_STATE_CHANGE) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - CEC_DQEVENT - CEC_EVENT_STATE_CHANGE - log_addr_mask=%04x phys_addr=%04x", ev.state_change.log_addr_mask, ev.state_change.phys_addr); ++ ++ // TODO: handle ev.state_change.log_addr_mask change ++ ++ phys_addr = ev.state_change.phys_addr; ++ phys_addr_changed = true; ++ ++ if (ev.state_change.phys_addr == CEC_PHYS_ADDR_INVALID) ++ { ++ // Debounce change to invalid physical address with 2 seconds because ++ // EDID refresh and other events may cause short periods of invalid physical address ++ phys_addr_timeout.Init(2000); ++ } ++ else ++ { ++ // Debounce change to valid physical address with 500 ms when no logical address have been claimed ++ phys_addr_timeout.Init(ev.state_change.log_addr_mask ? 0 : 500); ++ } ++ } ++ } ++ ++ if (phys_addr_changed && !phys_addr_timeout.TimeLeft() && !IsStopped()) ++ { ++ phys_addr_changed = false; ++ m_callback->HandlePhysicalAddressChanged(phys_addr); ++ } ++ ++ if (FD_ISSET(m_fd, &rd_fds)) ++ { ++ struct cec_msg msg = {}; ++ if (ioctl(m_fd, CEC_RECEIVE, &msg)) ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE failed - rx_status=%02x errno=%d", msg.rx_status, errno); ++ else if (msg.len > 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE - rx_status=%02x len=%d addr=%02x opcode=%02x", msg.rx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); ++ ++ cec_command cmd; ++ cmd.PushArray(msg.len, msg.msg); ++ ++ if (!IsStopped()) ++ m_callback->OnCommandReceived(cmd); ++ } ++ } ++ ++ if (!IsStopped()) ++ Sleep(5); ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - stopped - m_fd=%d", m_fd); ++ return 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h +new file mode 100644 +index 0000000..f4fac87 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h +@@ -0,0 +1,95 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017-2018 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_LINUX_API) ++#include "p8-platform/threads/threads.h" ++#include "../AdapterCommunication.h" ++ ++namespace CEC ++{ ++ class CLinuxCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread ++ { ++ public: ++ /*! ++ * @brief Create a new Linux CEC communication handler. ++ * @param callback The callback to use for incoming CEC commands. ++ */ ++ CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback); ++ virtual ~CLinuxCECAdapterCommunication(void); ++ ++ /** @name IAdapterCommunication implementation */ ++ ///{ ++ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true) override; ++ void Close(void) override; ++ bool IsOpen(void) override; ++ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply) override; ++ ++ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) override { return true; } ++ bool StartBootloader(void) override { return false; } ++ bool SetLogicalAddresses(const cec_logical_addresses &addresses) override; ++ cec_logical_addresses GetLogicalAddresses(void) const override; ++ bool PingAdapter(void) override { return true; } ++ uint16_t GetFirmwareVersion(void) override { return 0; } ++ uint32_t GetFirmwareBuildDate(void) override { return 0; } ++ bool IsRunningLatestFirmware(void) override { return true; } ++ bool SetControlledMode(bool UNUSED(controlled)) override { return true; } ++ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) override { return false; } ++ bool SetAutoMode(bool UNUSED(automode)) override { return false; } ++ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) override { return false; } ++ std::string GetPortName(void) override { return std::string("LINUX"); } ++ uint16_t GetPhysicalAddress(void) override; ++ cec_vendor_id GetVendorId(void) override; ++ bool SupportsSourceLogicalAddress(const cec_logical_address address) override { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } ++ cec_adapter_type GetAdapterType(void) override { return ADAPTERTYPE_LINUX; } ++ uint16_t GetAdapterVendorId(void) const override { return 1; } ++ uint16_t GetAdapterProductId(void) const override { return 1; } ++ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) override {} ++ ///} ++ ++ /** @name P8PLATFORM::CThread implementation */ ++ ///{ ++ void *Process(void) override; ++ ///} ++ ++ private: ++ int m_fd; ++ }; ++}; ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp +new file mode 100644 +index 0000000..7b72238 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp +@@ -0,0 +1,50 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include ++ ++#if defined(HAVE_LINUX_API) ++#include "LinuxCECAdapterDetection.h" ++ ++using namespace CEC; ++ ++bool CLinuxCECAdapterDetection::FindAdapter(void) ++{ ++ return access(CEC_LINUX_PATH, 0) == 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h +new file mode 100644 +index 0000000..f5ea2c4 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h +@@ -0,0 +1,51 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_LINUX_API) ++ ++namespace CEC ++{ ++ class CLinuxCECAdapterDetection ++ { ++ public: ++ static bool FindAdapter(void); ++ }; ++}; ++ ++#endif +diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake +index 2d7102f..dacca0f 100644 +--- a/src/libcec/cmake/CheckPlatformSupport.cmake ++++ b/src/libcec/cmake/CheckPlatformSupport.cmake +@@ -9,6 +9,7 @@ + # HAVE_RPI_API ON if Raspberry Pi is supported + # HAVE_TDA995X_API ON if TDA995X is supported + # HAVE_EXYNOS_API ON if Exynos is supported ++# HAVE_LINUX_API ON if Linux is supported + # HAVE_AOCEC_API ON if AOCEC is supported + # HAVE_P8_USB ON if Pulse-Eight devices are supported + # HAVE_P8_USB_DETECT ON if Pulse-Eight devices can be auto-detected +@@ -30,6 +31,7 @@ SET(HAVE_LIBUDEV OFF CACHE BOOL "udev not supported") + SET(HAVE_RPI_API OFF CACHE BOOL "raspberry pi not supported") + SET(HAVE_TDA995X_API OFF CACHE BOOL "tda995x not supported") + SET(HAVE_EXYNOS_API OFF CACHE BOOL "exynos not supported") ++SET(HAVE_LINUX_API OFF CACHE BOOL "linux not supported") + SET(HAVE_AOCEC_API OFF CACHE BOOL "aocec not supported") + # Pulse-Eight devices are always supported + set(HAVE_P8_USB ON CACHE BOOL "p8 usb-cec supported" FORCE) +@@ -139,6 +141,16 @@ else() + list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_EXYNOS}) + endif() + ++ # Linux ++ if (${HAVE_LINUX_API}) ++ set(LIB_INFO "${LIB_INFO}, Linux") ++ SET(HAVE_LINUX_API ON CACHE BOOL "linux supported" FORCE) ++ set(CEC_SOURCES_ADAPTER_LINUX adapter/Linux/LinuxCECAdapterDetection.cpp ++ adapter/Linux/LinuxCECAdapterCommunication.cpp) ++ source_group("Source Files\\adapter\\Linux" FILES ${CEC_SOURCES_ADAPTER_LINUX}) ++ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_LINUX}) ++ endif() ++ + # AOCEC + if (${HAVE_AOCEC_API}) + set(LIB_INFO "${LIB_INFO}, AOCEC") +diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake +index 83a778a..f47b1f7 100644 +--- a/src/libcec/cmake/DisplayPlatformSupport.cmake ++++ b/src/libcec/cmake/DisplayPlatformSupport.cmake +@@ -44,6 +44,12 @@ else() + message(STATUS "DRM support: no") + endif() + ++if (HAVE_LINUX_API) ++ message(STATUS "Linux support: yes") ++else() ++ message(STATUS "Linux support: no") ++endif() ++ + if (HAVE_AOCEC_API) + message(STATUS "AOCEC support: yes") + else() +diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in +index 456a2e7..71895a8 100644 +--- a/src/libcec/env.h.in ++++ b/src/libcec/env.h.in +@@ -76,6 +76,9 @@ + /* Define to 1 for Exynos support */ + #cmakedefine HAVE_EXYNOS_API @HAVE_EXYNOS_API@ + ++/* Define to 1 for Linux support */ ++#cmakedefine HAVE_LINUX_API @HAVE_LINUX_API@ ++ + /* Define to 1 for AOCEC support */ + #cmakedefine HAVE_AOCEC_API @HAVE_AOCEC_API@ + diff --git a/packages/devel/libcec-4.0.7/package.mk b/packages/devel/libcec-4.0.7/package.mk new file mode 100644 index 000000000..5faf396a5 --- /dev/null +++ b/packages/devel/libcec-4.0.7/package.mk @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="libcec-4.0.7" +PKG_VERSION="libcec-4.0.7" +PKG_SHA256="bcd92c376993a5721d346edcc09eb17289451f9156b1d1d113c9663c2046315a" +PKG_LICENSE="GPL" +PKG_SITE="http://libcec.pulse-eight.com/" +PKG_URL="https://github.com/Pulse-Eight/libcec/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd p8-platform swig:host" +PKG_LONGDESC="libCEC is an open-source dual licensed library designed for communicating with the Pulse-Eight USB - CEC Adaptor." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=1 \ + -DCMAKE_INSTALL_LIBDIR:STRING=lib \ + -DCMAKE_INSTALL_LIBDIR_NOARCH:STRING=lib \ + -DSKIP_PYTHON_WRAPPER=1 \ + -DHAVE_IMX_API=0 \ + -DHAVE_GIT_BIN=0" + +if [ "$PROJECT" = "RPi" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET bcm2835-driver" +fi + +if [ "$KODIPLAYER_DRIVER" = "libamcodec" ]; then + if [ "$TARGET_KERNEL_ARCH" = "arm64" ]; then + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AOCEC_API=1" + else + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AMLOGIC_API=1" + fi +else + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_AOCEC_API=0 -DHAVE_AMLOGIC_API=0" +fi + +# libX11 and xrandr to read the sink's EDID, used to determine the PC's HDMI physical address +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libX11 libXrandr" +fi + +if [ "$CEC_FRAMEWORK_SUPPORT" = "yes" ]; then + PKG_PATCH_DIRS="cec-framework" + PKG_CMAKE_OPTS_TARGET="$PKG_CMAKE_OPTS_TARGET -DHAVE_LINUX_API=1" +fi + +pre_configure_target() { + if [ "$PROJECT" = "RPi" ]; then + # detecting RPi support fails without -lvchiq_arm + export LDFLAGS="$LDFLAGS -lvchiq_arm" + fi +} + +post_makeinstall_target() { + # Remove the Python3 demo - useless for us + rm -f $INSTALL/usr/bin/pyCecClient + + PYTHON_DIR=$INSTALL/usr/lib/$PKG_PYTHON_VERSION + if [ -d $PYTHON_DIR/dist-packages ]; then + mv $PYTHON_DIR/dist-packages $PYTHON_DIR/site-packages + fi +} diff --git a/packages/devel/libcec-4.0.7/patches/cec-framework/libcec-0001-PR380.patch b/packages/devel/libcec-4.0.7/patches/cec-framework/libcec-0001-PR380.patch new file mode 100644 index 000000000..49af7eadf --- /dev/null +++ b/packages/devel/libcec-4.0.7/patches/cec-framework/libcec-0001-PR380.patch @@ -0,0 +1,887 @@ +From 467cc79fd289403e7d4f6e4e817b906c0c0027dd Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 6 Sep 2017 17:37:05 +0200 +Subject: [PATCH] Add Linux CEC Adapter + +--- + docs/README.linux.md | 6 + + include/cectypes.h | 11 + + src/libcec/CECTypeUtils.h | 2 + + src/libcec/CMakeLists.txt | 2 + + src/libcec/adapter/AdapterFactory.cpp | 26 +- + .../Linux/LinuxCECAdapterCommunication.cpp | 438 ++++++++++++++++++ + .../Linux/LinuxCECAdapterCommunication.h | 95 ++++ + .../Linux/LinuxCECAdapterDetection.cpp | 50 ++ + .../adapter/Linux/LinuxCECAdapterDetection.h | 51 ++ + src/libcec/cmake/CheckPlatformSupport.cmake | 12 + + src/libcec/cmake/DisplayPlatformSupport.cmake | 6 + + src/libcec/env.h.in | 3 + + 12 files changed, 700 insertions(+), 2 deletions(-) + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp + create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.h + +diff --git a/docs/README.linux.md b/docs/README.linux.md +index c59fb80..e8053cc 100644 +--- a/docs/README.linux.md ++++ b/docs/README.linux.md +@@ -51,5 +51,11 @@ Pass the argument `-DHAVE_TDA995X_API=1` to the cmake command in the compilation + cmake -DHAVE_TDA995X_API=1 .. + ``` + ++### Linux CEC Framework (v4.10+) ++Pass the argument `-DHAVE_LINUX_API=1` to the cmake command in the compilation instructions: ++``` ++cmake -DHAVE_LINUX_API=1 .. ++``` ++ + ### Debian / Ubuntu .deb packaging + See [docs/README.debian.md](README.debian.md). +\ No newline at end of file +diff --git a/include/cectypes.h b/include/cectypes.h +index 9c91842..2c32e4d 100644 +--- a/include/cectypes.h ++++ b/include/cectypes.h +@@ -281,6 +281,16 @@ namespace CEC { + */ + #define CEC_MAX_DATA_PACKET_SIZE (16 * 4) + ++/*! ++ * the path to use for the Linux CEC device ++ */ ++#define CEC_LINUX_PATH "/dev/cec0" ++ ++/*! ++ * the name of the virtual COM port to use for the Linux' CEC wire ++ */ ++#define CEC_LINUX_VIRTUAL_COM "Linux" ++ + /*! + * the path to use for the AOCEC HDMI CEC device + */ +@@ -861,6 +871,7 @@ typedef enum cec_adapter_type + ADAPTERTYPE_RPI = 0x100, + ADAPTERTYPE_TDA995x = 0x200, + ADAPTERTYPE_EXYNOS = 0x300, ++ ADAPTERTYPE_LINUX = 0x400, + ADAPTERTYPE_AOCEC = 0x500 + } cec_adapter_type; + +diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h +index 25c1c6e..15f9543 100644 +--- a/src/libcec/CECTypeUtils.h ++++ b/src/libcec/CECTypeUtils.h +@@ -766,6 +766,8 @@ namespace CEC + return "Raspberry Pi"; + case ADAPTERTYPE_TDA995x: + return "TDA995x"; ++ case ADAPTERTYPE_LINUX: ++ return "Linux"; + default: + return "unknown"; + } +diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt +index 6baee69..74fe5f3 100644 +--- a/src/libcec/CMakeLists.txt ++++ b/src/libcec/CMakeLists.txt +@@ -89,6 +89,8 @@ set(CEC_HEADERS devices/CECRecordingDevice.h + adapter/Exynos/ExynosCEC.h + adapter/Exynos/ExynosCECAdapterDetection.h + adapter/Exynos/ExynosCECAdapterCommunication.h ++ adapter/Linux/LinuxCECAdapterDetection.h ++ adapter/Linux/LinuxCECAdapterCommunication.h + adapter/AOCEC/AOCEC.h + adapter/AOCEC/AOCECAdapterDetection.h + adapter/AOCEC/AOCECAdapterCommunication.h +diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp +index 91195ea..323c272 100644 +--- a/src/libcec/adapter/AdapterFactory.cpp ++++ b/src/libcec/adapter/AdapterFactory.cpp +@@ -58,6 +58,11 @@ + #include "Exynos/ExynosCECAdapterCommunication.h" + #endif + ++#if defined(HAVE_LINUX_API) ++#include "Linux/LinuxCECAdapterDetection.h" ++#include "Linux/LinuxCECAdapterCommunication.h" ++#endif ++ + #if defined(HAVE_AOCEC_API) + #include "AOCEC/AOCECAdapterDetection.h" + #include "AOCEC/AOCECAdapterCommunication.h" +@@ -131,6 +136,18 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + } + #endif + ++#if defined(HAVE_LINUX_API) ++ if (iAdaptersFound < iBufSize && CLinuxCECAdapterDetection::FindAdapter()) ++ { ++ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_LINUX_PATH); ++ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_LINUX_VIRTUAL_COM); ++ deviceList[iAdaptersFound].iVendorId = 0; ++ deviceList[iAdaptersFound].iProductId = 0; ++ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_LINUX; ++ iAdaptersFound++; ++ } ++#endif ++ + #if defined(HAVE_AOCEC_API) + if (iAdaptersFound < iBufSize && CAOCECAdapterDetection::FindAdapter()) + { +@@ -144,7 +161,7 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + #endif + + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) + #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" + #endif + +@@ -163,6 +180,11 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CExynosCECAdapterCommunication(m_lib->m_cec); + #endif + ++#if defined(HAVE_LINUX_API) ++ if (!strcmp(strPort, CEC_LINUX_VIRTUAL_COM)) ++ return new CLinuxCECAdapterCommunication(m_lib->m_cec); ++#endif ++ + #if defined(HAVE_AOCEC_API) + if (!strcmp(strPort, CEC_AOCEC_VIRTUAL_COM)) + return new CAOCECAdapterCommunication(m_lib->m_cec); +@@ -177,7 +199,7 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); + #endif + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_AOCEC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) + return NULL; + #endif + } +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp +new file mode 100644 +index 0000000..6a28835 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp +@@ -0,0 +1,438 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017-2019 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include ++#include ++ ++#if defined(HAVE_LINUX_API) ++#include "LinuxCECAdapterCommunication.h" ++#include "CECTypeUtils.h" ++#include "LibCEC.h" ++#include "p8-platform/util/buffer.h" ++#include ++ ++using namespace CEC; ++using namespace P8PLATFORM; ++ ++#define LIB_CEC m_callback->GetLib() ++ ++// Required capabilities ++#define CEC_LINUX_CAPABILITIES (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH) ++ ++CLinuxCECAdapterCommunication::CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback) ++ : IAdapterCommunication(callback) ++{ ++ m_fd = INVALID_SOCKET_VALUE; ++} ++ ++CLinuxCECAdapterCommunication::~CLinuxCECAdapterCommunication(void) ++{ ++ Close(); ++} ++ ++bool CLinuxCECAdapterCommunication::Open(uint32_t UNUSED(iTimeoutMs), bool UNUSED(bSkipChecks), bool bStartListening) ++{ ++ if (IsOpen()) ++ Close(); ++ ++ if ((m_fd = open(CEC_LINUX_PATH, O_RDWR)) >= 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - m_fd=%d bStartListening=%d", m_fd, bStartListening); ++ ++ // Ensure the CEC device supports required capabilities ++ struct cec_caps caps = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_CAPS, &caps) || (caps.capabilities & CEC_LINUX_CAPABILITIES) != CEC_LINUX_CAPABILITIES) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_CAPS failed - capabilities=%02x errno=%d", caps.capabilities, errno); ++ Close(); ++ return false; ++ } ++ ++ if (!bStartListening) ++ { ++ Close(); ++ return true; ++ } ++ ++ // This is an exclusive follower, in addition put the CEC device into passthrough mode ++ uint32_t mode = CEC_MODE_INITIATOR | CEC_MODE_EXCL_FOLLOWER_PASSTHRU; ++ if (ioctl(m_fd, CEC_S_MODE, &mode)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_S_MODE failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ uint16_t addr; ++ if (ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR - addr=%04x", addr); ++ ++ if (addr == CEC_PHYS_ADDR_INVALID) ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "CLinuxCECAdapterCommunication::Open - physical address is invalid"); ++ ++ // Clear existing logical addresses and set the CEC device to the unconfigured state ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ // Set logical address to unregistered, without any logical address configured no messages is transmitted or received ++ log_addrs = {}; ++ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; ++ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; ++ log_addrs.num_log_addrs = 1; ++ log_addrs.flags = CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK; ++ log_addrs.log_addr[0] = CEC_LOG_ADDR_UNREGISTERED; ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ Close(); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ if (CreateThread()) ++ return true; ++ ++ Close(); ++ } ++ ++ return false; ++} ++ ++void CLinuxCECAdapterCommunication::Close(void) ++{ ++ StopThread(0); ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Close - m_fd=%d", m_fd); ++ ++ close(m_fd); ++ m_fd = INVALID_SOCKET_VALUE; ++} ++ ++bool CLinuxCECAdapterCommunication::IsOpen(void) ++{ ++ return m_fd != INVALID_SOCKET_VALUE; ++} ++ ++cec_adapter_message_state CLinuxCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) ++{ ++ if (IsOpen()) ++ { ++ struct cec_msg msg; ++ cec_msg_init(&msg, data.initiator, data.destination); ++ ++ if (data.opcode_set) ++ { ++ msg.msg[msg.len++] = data.opcode; ++ ++ if (data.parameters.size) ++ { ++ memcpy(&msg.msg[msg.len], data.parameters.data, data.parameters.size); ++ msg.len += data.parameters.size; ++ } ++ } ++ ++ if (ioctl(m_fd, CEC_TRANSMIT, &msg)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT failed - tx_status=%02x errno=%d", msg.tx_status, errno); ++ return ADAPTER_MESSAGE_STATE_ERROR; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT - tx_status=%02x len=%d addr=%02x opcode=%02x", msg.tx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); ++ ++ // The CEC driver will make re-transmission attempts ++ bRetry = false; ++ ++ if (msg.tx_status & CEC_TX_STATUS_OK) ++ return ADAPTER_MESSAGE_STATE_SENT_ACKED; ++ ++ if (msg.tx_status & CEC_TX_STATUS_NACK) ++ return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; ++ ++ return ADAPTER_MESSAGE_STATE_ERROR; ++ } ++ ++ return ADAPTER_MESSAGE_STATE_UNKNOWN; ++} ++ ++bool CLinuxCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) ++{ ++ if (IsOpen()) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ // TODO: Claiming a logical address will only work when CEC device has a valid physical address ++ ++ // Clear existing logical addresses and set the CEC device to the unconfigured state ++ if (log_addrs.num_log_addrs) ++ { ++ log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ } ++ ++ if (!addresses.IsEmpty()) ++ { ++ // NOTE: This can only be configured when num_log_addrs > 0 ++ // and gets reset when num_log_addrs = 0 ++ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; ++ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; ++ ++ // TODO: Support more then the primary logical address ++ log_addrs.num_log_addrs = 1; ++ log_addrs.log_addr[0] = addresses.primary; ++ ++ switch (addresses.primary) ++ { ++ case CECDEVICE_AUDIOSYSTEM: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM; ++ break; ++ case CECDEVICE_PLAYBACKDEVICE1: ++ case CECDEVICE_PLAYBACKDEVICE2: ++ case CECDEVICE_PLAYBACKDEVICE3: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_PLAYBACK; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK; ++ break; ++ case CECDEVICE_RECORDINGDEVICE1: ++ case CECDEVICE_RECORDINGDEVICE2: ++ case CECDEVICE_RECORDINGDEVICE3: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_RECORD; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD; ++ break; ++ case CECDEVICE_TUNER1: ++ case CECDEVICE_TUNER2: ++ case CECDEVICE_TUNER3: ++ case CECDEVICE_TUNER4: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TUNER; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER; ++ break; ++ case CECDEVICE_TV: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TV; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV; ++ break; ++ default: ++ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; ++ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; ++ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; ++ break; ++ } ++ } ++ else ++ log_addrs.num_log_addrs = 0; ++ ++ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); ++ return false; ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); ++ ++ if (log_addrs.num_log_addrs && !log_addrs.log_addr_mask) ++ return false; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++cec_logical_addresses CLinuxCECAdapterCommunication::GetLogicalAddresses(void) const ++{ ++ cec_logical_addresses addresses; ++ addresses.Clear(); ++ ++ if (m_fd != INVALID_SOCKET_VALUE) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ return addresses; ++ } ++ ++ for (int i = 0; i < log_addrs.num_log_addrs; i++) ++ addresses.Set(cec_logical_address(log_addrs.log_addr[i])); ++ } ++ ++ return addresses; ++} ++ ++uint16_t CLinuxCECAdapterCommunication::GetPhysicalAddress(void) ++{ ++ if (IsOpen()) ++ { ++ uint16_t addr; ++ if (!ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) ++ return addr; ++ ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetPhysicalAddress - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); ++ } ++ ++ return CEC_INVALID_PHYSICAL_ADDRESS; ++} ++ ++cec_vendor_id CLinuxCECAdapterCommunication::GetVendorId(void) ++{ ++ if (IsOpen()) ++ { ++ struct cec_log_addrs log_addrs = {}; ++ if (!ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) ++ return cec_vendor_id(log_addrs.vendor_id); ++ ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetVendorId - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); ++ } ++ ++ return CEC_VENDOR_UNKNOWN; ++} ++ ++void *CLinuxCECAdapterCommunication::Process(void) ++{ ++ CTimeout phys_addr_timeout; ++ bool phys_addr_changed = false; ++ uint16_t phys_addr = CEC_INVALID_PHYSICAL_ADDRESS; ++ fd_set rd_fds; ++ fd_set ex_fds; ++ ++ while (!IsStopped()) ++ { ++ struct timeval timeval = {}; ++ timeval.tv_sec = 1; ++ ++ FD_ZERO(&rd_fds); ++ FD_ZERO(&ex_fds); ++ FD_SET(m_fd, &rd_fds); ++ FD_SET(m_fd, &ex_fds); ++ ++ if (select(m_fd + 1, &rd_fds, NULL, &ex_fds, &timeval) < 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - select failed - errno=%d", errno); ++ break; ++ } ++ ++ if (FD_ISSET(m_fd, &ex_fds)) ++ { ++ struct cec_event ev = {}; ++ if (ioctl(m_fd, CEC_DQEVENT, &ev)) ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_DQEVENT failed - errno=%d", errno); ++ else if (ev.event == CEC_EVENT_STATE_CHANGE) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - CEC_DQEVENT - CEC_EVENT_STATE_CHANGE - log_addr_mask=%04x phys_addr=%04x", ev.state_change.log_addr_mask, ev.state_change.phys_addr); ++ ++ // TODO: handle ev.state_change.log_addr_mask change ++ ++ phys_addr = ev.state_change.phys_addr; ++ phys_addr_changed = true; ++ ++ if (ev.state_change.phys_addr == CEC_PHYS_ADDR_INVALID) ++ { ++ // Debounce change to invalid physical address with 2 seconds because ++ // EDID refresh and other events may cause short periods of invalid physical address ++ phys_addr_timeout.Init(2000); ++ } ++ else ++ { ++ // Debounce change to valid physical address with 500 ms when no logical address have been claimed ++ phys_addr_timeout.Init(ev.state_change.log_addr_mask ? 0 : 500); ++ } ++ } ++ } ++ ++ if (phys_addr_changed && !phys_addr_timeout.TimeLeft() && !IsStopped()) ++ { ++ phys_addr_changed = false; ++ m_callback->HandlePhysicalAddressChanged(phys_addr); ++ } ++ ++ if (FD_ISSET(m_fd, &rd_fds)) ++ { ++ struct cec_msg msg = {}; ++ if (ioctl(m_fd, CEC_RECEIVE, &msg)) ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE failed - rx_status=%02x errno=%d", msg.rx_status, errno); ++ else if (msg.len > 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE - rx_status=%02x len=%d addr=%02x opcode=%02x", msg.rx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); ++ ++ cec_command cmd; ++ cmd.PushArray(msg.len, msg.msg); ++ ++ if (!IsStopped()) ++ m_callback->OnCommandReceived(cmd); ++ } ++ } ++ ++ if (!IsStopped()) ++ Sleep(5); ++ } ++ ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - stopped - m_fd=%d", m_fd); ++ return 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h +new file mode 100644 +index 0000000..f4fac87 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h +@@ -0,0 +1,95 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017-2018 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_LINUX_API) ++#include "p8-platform/threads/threads.h" ++#include "../AdapterCommunication.h" ++ ++namespace CEC ++{ ++ class CLinuxCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread ++ { ++ public: ++ /*! ++ * @brief Create a new Linux CEC communication handler. ++ * @param callback The callback to use for incoming CEC commands. ++ */ ++ CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback); ++ virtual ~CLinuxCECAdapterCommunication(void); ++ ++ /** @name IAdapterCommunication implementation */ ++ ///{ ++ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true) override; ++ void Close(void) override; ++ bool IsOpen(void) override; ++ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply) override; ++ ++ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) override { return true; } ++ bool StartBootloader(void) override { return false; } ++ bool SetLogicalAddresses(const cec_logical_addresses &addresses) override; ++ cec_logical_addresses GetLogicalAddresses(void) const override; ++ bool PingAdapter(void) override { return true; } ++ uint16_t GetFirmwareVersion(void) override { return 0; } ++ uint32_t GetFirmwareBuildDate(void) override { return 0; } ++ bool IsRunningLatestFirmware(void) override { return true; } ++ bool SetControlledMode(bool UNUSED(controlled)) override { return true; } ++ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) override { return false; } ++ bool SetAutoMode(bool UNUSED(automode)) override { return false; } ++ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) override { return false; } ++ std::string GetPortName(void) override { return std::string("LINUX"); } ++ uint16_t GetPhysicalAddress(void) override; ++ cec_vendor_id GetVendorId(void) override; ++ bool SupportsSourceLogicalAddress(const cec_logical_address address) override { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } ++ cec_adapter_type GetAdapterType(void) override { return ADAPTERTYPE_LINUX; } ++ uint16_t GetAdapterVendorId(void) const override { return 1; } ++ uint16_t GetAdapterProductId(void) const override { return 1; } ++ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) override {} ++ ///} ++ ++ /** @name P8PLATFORM::CThread implementation */ ++ ///{ ++ void *Process(void) override; ++ ///} ++ ++ private: ++ int m_fd; ++ }; ++}; ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp +new file mode 100644 +index 0000000..7b72238 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp +@@ -0,0 +1,50 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include ++ ++#if defined(HAVE_LINUX_API) ++#include "LinuxCECAdapterDetection.h" ++ ++using namespace CEC; ++ ++bool CLinuxCECAdapterDetection::FindAdapter(void) ++{ ++ return access(CEC_LINUX_PATH, 0) == 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h +new file mode 100644 +index 0000000..f5ea2c4 +--- /dev/null ++++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h +@@ -0,0 +1,51 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman ++ * based heavily on: ++ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs ++ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_LINUX_API) ++ ++namespace CEC ++{ ++ class CLinuxCECAdapterDetection ++ { ++ public: ++ static bool FindAdapter(void); ++ }; ++}; ++ ++#endif +diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake +index 2d7102f..dacca0f 100644 +--- a/src/libcec/cmake/CheckPlatformSupport.cmake ++++ b/src/libcec/cmake/CheckPlatformSupport.cmake +@@ -9,6 +9,7 @@ + # HAVE_RPI_API ON if Raspberry Pi is supported + # HAVE_TDA995X_API ON if TDA995X is supported + # HAVE_EXYNOS_API ON if Exynos is supported ++# HAVE_LINUX_API ON if Linux is supported + # HAVE_AOCEC_API ON if AOCEC is supported + # HAVE_P8_USB ON if Pulse-Eight devices are supported + # HAVE_P8_USB_DETECT ON if Pulse-Eight devices can be auto-detected +@@ -30,6 +31,7 @@ SET(HAVE_LIBUDEV OFF CACHE BOOL "udev not supported") + SET(HAVE_RPI_API OFF CACHE BOOL "raspberry pi not supported") + SET(HAVE_TDA995X_API OFF CACHE BOOL "tda995x not supported") + SET(HAVE_EXYNOS_API OFF CACHE BOOL "exynos not supported") ++SET(HAVE_LINUX_API OFF CACHE BOOL "linux not supported") + SET(HAVE_AOCEC_API OFF CACHE BOOL "aocec not supported") + # Pulse-Eight devices are always supported + set(HAVE_P8_USB ON CACHE BOOL "p8 usb-cec supported" FORCE) +@@ -139,6 +141,16 @@ else() + list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_EXYNOS}) + endif() + ++ # Linux ++ if (${HAVE_LINUX_API}) ++ set(LIB_INFO "${LIB_INFO}, Linux") ++ SET(HAVE_LINUX_API ON CACHE BOOL "linux supported" FORCE) ++ set(CEC_SOURCES_ADAPTER_LINUX adapter/Linux/LinuxCECAdapterDetection.cpp ++ adapter/Linux/LinuxCECAdapterCommunication.cpp) ++ source_group("Source Files\\adapter\\Linux" FILES ${CEC_SOURCES_ADAPTER_LINUX}) ++ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_LINUX}) ++ endif() ++ + # AOCEC + if (${HAVE_AOCEC_API}) + set(LIB_INFO "${LIB_INFO}, AOCEC") +diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake +index 83a778a..f47b1f7 100644 +--- a/src/libcec/cmake/DisplayPlatformSupport.cmake ++++ b/src/libcec/cmake/DisplayPlatformSupport.cmake +@@ -44,6 +44,12 @@ else() + message(STATUS "DRM support: no") + endif() + ++if (HAVE_LINUX_API) ++ message(STATUS "Linux support: yes") ++else() ++ message(STATUS "Linux support: no") ++endif() ++ + if (HAVE_AOCEC_API) + message(STATUS "AOCEC support: yes") + else() +diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in +index 456a2e7..71895a8 100644 +--- a/src/libcec/env.h.in ++++ b/src/libcec/env.h.in +@@ -76,6 +76,9 @@ + /* Define to 1 for Exynos support */ + #cmakedefine HAVE_EXYNOS_API @HAVE_EXYNOS_API@ + ++/* Define to 1 for Linux support */ ++#cmakedefine HAVE_LINUX_API @HAVE_LINUX_API@ ++ + /* Define to 1 for AOCEC support */ + #cmakedefine HAVE_AOCEC_API @HAVE_AOCEC_API@ + diff --git a/packages/devel/libcec/package.mk b/packages/devel/libcec/package.mk new file mode 100644 index 000000000..5d079fe4a --- /dev/null +++ b/packages/devel/libcec/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libcec" +PKG_VERSION="4.0.7" +PKG_SHA256="bcd92c376993a5721d346edcc09eb17289451f9156b1d1d113c9663c2046315a" +PKG_LICENSE="GPL" +PKG_SITE="http://libcec.pulse-eight.com/" +PKG_URL="https://github.com/Pulse-Eight/libcec/archive/libcec-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd p8-platform swig:host" +PKG_LONGDESC="libCEC is an open-source dual licensed library designed for communicating with the Pulse-Eight USB - CEC Adaptor." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=1 \ + -DCMAKE_INSTALL_LIBDIR:STRING=lib \ + -DCMAKE_INSTALL_LIBDIR_NOARCH:STRING=lib \ + -DSKIP_PYTHON_WRAPPER=1 \ + -DHAVE_IMX_API=0 \ + -DHAVE_AOCEC_API=0 -DHAVE_AMLOGIC_API=0 \ + -DHAVE_GIT_BIN=0 \ + -DHAVE_RPI_LIB=0" + +# libX11 and xrandr to read the sink's EDID, used to determine the PC's HDMI physical address +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libX11 libXrandr" +fi + +if [ "${CEC_FRAMEWORK_SUPPORT}" = "yes" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DHAVE_LINUX_API=1" +else + PKG_CMAKE_OPTS_TARGET+=" -DHAVE_LINUX_API=0" +fi + +post_makeinstall_target() { + # Remove the Python3 demo - useless for us + rm -f ${INSTALL}/usr/bin/pyCecClient + + PYTHON_DIR=${INSTALL}/usr/lib/${PKG_PYTHON_VERSION} + if [ -d ${PYTHON_DIR}/dist-packages ]; then + mv ${PYTHON_DIR}/dist-packages ${PYTHON_DIR}/site-packages + fi +} diff --git a/packages/devel/libdaemon/package.mk b/packages/devel/libdaemon/package.mk new file mode 100644 index 000000000..076a34ee5 --- /dev/null +++ b/packages/devel/libdaemon/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libdaemon" +PKG_VERSION="0.14" +PKG_SHA256="fd23eb5f6f986dcc7e708307355ba3289abe03cc381fc47a80bca4a50aa6b834" +PKG_LICENSE="GPL" +PKG_SITE="http://0pointer.de/lennart/projects/libdaemon/" +PKG_URL="http://0pointer.de/lennart/projects/libdaemon/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A lightweight C library which eases the writing of UNIX daemons." + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_setpgrp_void=no \ + --enable-static \ + --disable-shared \ + --disable-lynx" diff --git a/packages/devel/libffi/package.mk b/packages/devel/libffi/package.mk new file mode 100644 index 000000000..aafb5f2ea --- /dev/null +++ b/packages/devel/libffi/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libffi" +PKG_VERSION="3.3" +PKG_SHA256="72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056" +PKG_LICENSE="GPL" +PKG_SITE="http://sourceware.org/${PKG_NAME}/" +PKG_URL="ftp://sourceware.org/pub/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host libtool:host pkg-config:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Foreign Function Interface Library." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-debug \ + --enable-static --disable-shared \ + --with-pic \ + --enable-structs \ + --enable-raw-api \ + --disable-purify-safety \ + --with-gnu-ld" diff --git a/packages/devel/libffi/patches/libffi-Fix-installation-location-of-libffi.patch b/packages/devel/libffi/patches/libffi-Fix-installation-location-of-libffi.patch new file mode 100644 index 000000000..56e08f736 --- /dev/null +++ b/packages/devel/libffi/patches/libffi-Fix-installation-location-of-libffi.patch @@ -0,0 +1,50 @@ +From 102c02de867bfe831b5366c89d66bcf170db962e Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Thu, 7 Feb 2013 22:26:56 +0100 +Subject: [PATCH] Fix installation location of libffi + +The libffi is currently declared as toolexeclib_LTLIBRARIES. In many +cases, toolexeclib libraries will be installed in /usr/lib, so it +doesn't make any difference. + +However, with multilib toolchains, they get installed in a +subdirectory of /usr/lib/. For example, with a Sourcery CodeBench +PowerPC toolchain, if the e500mc multilib variant is used, the libffi +library gets installed in /usr/lib/te500mc/. This is due to the +following code in the configure script: + + multi_os_directory=`$CC -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + +Once the library is installed in /usr/lib/te500mc/, nothing works +because this installation location is inconsistent with the +installation location declared in libffi.pc. + +So, instead of using this bizarre toolexeclib_LTLIBRARIES, simply use +the more standard lib_LTLIBRARIES, which ensures that the libffi +library is always installed in /usr/lib. + +Signed-off-by: Thomas Petazzoni +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 6f669ca..b60bcc1 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -93,7 +93,7 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS) + + MAKEOVERRIDES= + +-toolexeclib_LTLIBRARIES = libffi.la ++lib_LTLIBRARIES = libffi.la + noinst_LTLIBRARIES = libffi_convenience.la + + libffi_la_SOURCES = src/prep_cif.c src/types.c \ +-- +1.7.9.5 + diff --git a/packages/devel/libffi/patches/libffi-fix-pkgconf.patch b/packages/devel/libffi/patches/libffi-fix-pkgconf.patch new file mode 100644 index 000000000..9aa96a2fe --- /dev/null +++ b/packages/devel/libffi/patches/libffi-fix-pkgconf.patch @@ -0,0 +1,23 @@ +From a2d10693e352db0cdfc22550f23f8294564ce939 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 16 Aug 2014 12:26:53 +0300 +Subject: [PATCH] fix pkgconf + +--- + libffi.pc.in | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/libffi.pc.in b/libffi.pc.in +index 1477a66..1dd4ebd 100644 +--- a/libffi.pc.in ++++ b/libffi.pc.in +@@ -7,5 +7,5 @@ includedir=@includedir@/@PACKAGE_NAME@ + Name: @PACKAGE_NAME@ + Description: Library supporting Foreign Function Interfaces + Version: @PACKAGE_VERSION@ +-Libs: -L${toolexeclibdir} -lffi ++Libs: -L${libdir} -lffi + Cflags: -I${includedir} +-- +1.7.2.5 + diff --git a/packages/devel/libfmt/package.mk b/packages/devel/libfmt/package.mk new file mode 100644 index 000000000..c6e7d8722 --- /dev/null +++ b/packages/devel/libfmt/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libfmt" +PKG_VERSION="5.3.0" # newer version break easyrpg! +PKG_SHA256="defa24a9af4c622a7134076602070b45721a43c51598c8456ec6f2c4dbb51c89" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/fmtlib/fmt" +PKG_URL="https://github.com/fmtlib/fmt/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="fmt is an open-source formatting library for C++. It can be used as a safe alternative to printf or as a fast alternative to IOStreams." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DFMT_DOC=OFF -DFMT_INSTALL=ON -DFMT_TEST=OFF -DFMT_USE_CPP11=ON" \ No newline at end of file diff --git a/packages/devel/libfstrcmp/package.mk b/packages/devel/libfstrcmp/package.mk new file mode 100644 index 000000000..7347ce692 --- /dev/null +++ b/packages/devel/libfstrcmp/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libfstrcmp" +PKG_VERSION="0.7.D001" +PKG_SHA256="e4018e850f80700acee8da296e56e15b1eef711ab15157e542e7d7e1237c3476" +PKG_LICENSE="GPL" +PKG_SITE="http://fstrcmp.sourceforge.net/" +PKG_URL="https://downloads.sourceforge.net/project/fstrcmp/fstrcmp/$(get_pkg_version_maj_min)/fstrcmp-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The fstrcmp project provides a library that is used to make fuzzy comparisons of strings and byte arrays, including multi-byte character strings." + +pre_configure_target() { + cd "${PKG_BUILD}" +} + +make_target() { + make all-bin +} + +makeinstall_target() { + make DESTDIR="${SYSROOT_PREFIX}" install-include install-libdir +} diff --git a/packages/devel/libftdi1/package.mk b/packages/devel/libftdi1/package.mk new file mode 100644 index 000000000..52da3f1c8 --- /dev/null +++ b/packages/devel/libftdi1/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libftdi1" +PKG_VERSION="1.5" +PKG_SHA256="7c7091e9c86196148bd41177b4590dccb1510bfe6cea5bf7407ff194482eb049" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.intra2net.com/en/developer/libftdi/" +PKG_URL="http://www.intra2net.com/en/developer/libftdi/download/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libusb libconfuse" +PKG_LONGDESC="libFTDI is an open source library to talk to FTDI chips" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DSTATICLIBS=ON \ + -DDOCUMENTATION=FALSE \ + -DEXAMPLES=FALSE \ + -DFTDIPP=FALSE \ + -DPYTHON_BINDINGS=FALSE" + +makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/include/libftdi1 + cp ../src/ftdi.h ${SYSROOT_PREFIX}/usr/include/libftdi1 + + mkdir -p ${SYSROOT_PREFIX}/usr/lib + cp src/libftdi1.a ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp libftdi1.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig +} diff --git a/packages/devel/libirman/package.mk b/packages/devel/libirman/package.mk new file mode 100644 index 000000000..743306570 --- /dev/null +++ b/packages/devel/libirman/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libirman" +PKG_VERSION="0.5.2" +PKG_SHA256="43e58d7cd22b3a4c4dc8dcf8542a269ebcb4d8f6ceea0577b9fc882898f09a47" +PKG_LICENSE="GPL" +PKG_SITE="https://sourceforge.net/projects/libirman" +PKG_URL="http://downloads.sourceforge.net/project/libirman/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd lirc" +PKG_NEED_UNPACK="$(get_pkg_directory lirc)" +PKG_LONGDESC="libirman library for lircd" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic -parallel" + +PKG_CONFIGURE_OPTS_TARGET="--disable-swtest" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/devel/libirman/patches/libirman-0001-fix-poll-include.patch b/packages/devel/libirman/patches/libirman-0001-fix-poll-include.patch new file mode 100644 index 000000000..500572434 --- /dev/null +++ b/packages/devel/libirman/patches/libirman-0001-fix-poll-include.patch @@ -0,0 +1,35 @@ +diff -Naur a/config.h.in b/config.h.in +--- a/config.h.in 2016-05-18 18:19:56.000000000 +0200 ++++ b/config.h.in 2016-12-26 22:49:43.514203152 +0100 +@@ -21,6 +21,9 @@ + /* Define to 1 if you have the `mkfifo' function. */ + #undef HAVE_MKFIFO + ++/* defined if poll.h is available */ ++#undef HAVE_POLL_H ++ + /* Define to 1 if you have the `select' function. */ + #undef HAVE_SELECT + +@@ -48,6 +51,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_FILE_H + ++/* defined if sys/poll.h is available */ ++#undef HAVE_SYS_POLL_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_STAT_H + +diff -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2016-05-18 18:19:41.000000000 +0200 ++++ b/configure.ac 2016-12-26 22:48:40.190031280 +0100 +@@ -20,7 +20,7 @@ + + dnl Checks for header files. + AC_HEADER_STDC +-AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h termios.h memory.hi sys/file.h) ++AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h termios.h memory.hi sys/file.h poll.h sys/poll.h) + + dnl Checks for typedefs, structures, and compiler characteristics. + AC_TYPE_PID_T diff --git a/packages/devel/libplist/package.mk b/packages/devel/libplist/package.mk new file mode 100644 index 000000000..9d501fa8c --- /dev/null +++ b/packages/devel/libplist/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libplist" +PKG_VERSION="2.2.0" +PKG_SHA256="4a5517e5377ec421df84c586ba85bb4e1d26f11ad203d7d450a907c0156fbd9a" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libimobiledevice.org/" +PKG_URL="https://github.com/libimobiledevice/libplist/releases/download/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain glib" +PKG_LONGDESC="libplist is a library for manipulating Apple Binary and XML Property Lists" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--without-cython" + +pre_configure_target() { + # work around bashism in configure script + export CONFIG_SHELL="/bin/bash" +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/devel/libpthread-stubs/package.mk b/packages/devel/libpthread-stubs/package.mk new file mode 100644 index 000000000..d92d3d527 --- /dev/null +++ b/packages/devel/libpthread-stubs/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libpthread-stubs" +PKG_VERSION="0.4" +PKG_SHA256="50d5686b79019ccea08bcbd7b02fe5a40634abcfd4146b6e75c6420cc170e9d9" +PKG_LICENSE="OSS" +PKG_SITE="http://xcb.freedesktop.org/" +PKG_URL="http://xcb.freedesktop.org/dist/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library providing weak aliases for pthread functions." diff --git a/packages/devel/librga/package.mk b/packages/devel/librga/package.mk new file mode 100644 index 000000000..6b4678f43 --- /dev/null +++ b/packages/devel/librga/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="librga" +PKG_VERSION="1fc02d56d97041c86f01bc1284b7971c6098c5fb" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GNU" +PKG_DEPENDS_TARGET="toolchain libdrm" +PKG_SITE="https://github.com/rockchip-linux/linux-rga" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="The RGA driver userspace " +PKG_TOOLCHAIN="auto" diff --git a/packages/devel/libsodium/package.mk b/packages/devel/libsodium/package.mk new file mode 100644 index 000000000..cb9c3c1fc --- /dev/null +++ b/packages/devel/libsodium/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius +# Sodium License: https://libsodium.gitbook.io/doc/#license + +PKG_NAME="libsodium" +PKG_VERSION="d1580db1b34b7c73abb960e5f464a87ce8b7ed7d" +PKG_SHA256="75902b344f2a2279698266dc53fb48dfa394d2f507ae81c8f935264bbed49588" +PKG_LICENSE="ISC" +PKG_SITE="https://github.com/jedisct1/libsodium" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_GIT_CLONE_BRANCH="stable" +PKG_DEPENDS_HOST="toolchain" +PKG_LONGDESC="A modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more." +PKG_TOOLCHAIN="autotools" diff --git a/packages/devel/libtool/package.mk b/packages/devel/libtool/package.mk new file mode 100644 index 000000000..29a69cc68 --- /dev/null +++ b/packages/devel/libtool/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libtool" +PKG_VERSION="2.4.6" +PKG_SHA256="e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/libtool/" +PKG_URL="http://ftpmirror.gnu.org/libtool/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host intltool:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A generic library support script." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_HOST="--enable-static --disable-shared" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/share +} diff --git a/packages/devel/libtool/patches/libtool-01_dont_relink_against_host.patch b/packages/devel/libtool/patches/libtool-01_dont_relink_against_host.patch new file mode 100644 index 000000000..fd54ec6fc --- /dev/null +++ b/packages/devel/libtool/patches/libtool-01_dont_relink_against_host.patch @@ -0,0 +1,13 @@ +diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh +index 5eca4ae..23901ff 100644 +--- a/build-aux/ltmain.sh ++++ b/build-aux/ltmain.sh +@@ -8333,7 +8333,7 @@ func_mode_link () + fi + else + # We cannot seem to hardcode it, guess we'll fake it. +- add_dir=-L$libdir ++ #add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in diff --git a/packages/devel/libtool/patches/libtool-02-use_ld.patch b/packages/devel/libtool/patches/libtool-02-use_ld.patch new file mode 100644 index 000000000..e98c856e8 --- /dev/null +++ b/packages/devel/libtool/patches/libtool-02-use_ld.patch @@ -0,0 +1,13 @@ +diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh +index 23901ff..df26ab5 100644 +--- a/build-aux/ltmain.sh ++++ b/build-aux/ltmain.sh +@@ -7250,7 +7250,7 @@ func_mode_link () + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ +- -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) ++ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*|-fuse-ld=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" diff --git a/packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch b/packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch new file mode 100644 index 000000000..8e2defbb3 --- /dev/null +++ b/packages/devel/libtool/patches/libtool-03-remove-help2man-dependency.patch @@ -0,0 +1,26 @@ +diff -Naur a/Makefile.am b/Makefile.am +--- a/Makefile.am 2015-01-20 07:34:33.000000000 -0800 ++++ b/Makefile.am 2015-10-27 11:16:49.027497480 -0700 +@@ -406,22 +406,6 @@ + $(AM_V_GEN)$(MAKEINFO) -P '$(srcdir)/doc' --no-headers \ + $(MAKEINFOFLAGS) -o '$@' '$(notes_texi)' + +-dist_man1_MANS = $(libtool_1) $(libtoolize_1) +-MAINTAINERCLEANFILES += $(dist_man1_MANS) +-update_mans = \ +- PATH=".$(PATH_SEPARATOR)$$PATH"; export PATH; \ +- $(HELP2MAN) --output='$@' +- +-# It's wrong to make distributed files (e.g. $(libtool_1)) rely on +-# files created in the build tree, so instead we regenerate the +-# manual pages if the sources for the build-tree files we want to +-# run have changed. +-$(libtool_1): $(ltmain_sh) +- $(AM_V_GEN)$(update_mans) --help-option=--help-all libtool +-$(libtoolize_1): $(libtoolize_in) +- $(AM_V_GEN)$(update_mans) libtoolize +- +- + ## ------------- ## + ## Installation. ## + ## ------------- ## diff --git a/packages/devel/m4/package.mk b/packages/devel/m4/package.mk new file mode 100644 index 000000000..328a79a8c --- /dev/null +++ b/packages/devel/m4/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="m4" +PKG_VERSION="1.4.19" +PKG_SHA256="b306a91c0fd93bc4280cfc2e98cb7ab3981ff75a187bea3293811f452c89a8c8" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/m4/" +PKG_URL="http://ftpmirror.gnu.org/m4/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The m4 macro processor." + +PKG_CONFIGURE_OPTS_HOST="gl_cv_func_gettimeofday_clobber=no --target=${TARGET_NAME}" + +post_makeinstall_host() { + make prefix=${SYSROOT_PREFIX}/usr install +} diff --git a/packages/devel/make/package.mk b/packages/devel/make/package.mk new file mode 100644 index 000000000..18cee105f --- /dev/null +++ b/packages/devel/make/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="make" +PKG_VERSION="4.3" +PKG_SHA256="e05fdde47c5f7ca45cb697e973894ff4f5d79e13b750ed57d7b66d8defc78e19" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/make/" +PKG_URL="http://ftpmirror.gnu.org/make/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="Utility to maintain groups of programs." + +pre_configure_host() { + export CC=${LOCAL_CC} +} + +post_makeinstall_host() { + ln -sf make ${TOOLCHAIN}/bin/gmake +} diff --git a/packages/devel/make/patches/make-01-disable-inheritance-of-fds.patch b/packages/devel/make/patches/make-01-disable-inheritance-of-fds.patch new file mode 100644 index 000000000..db2c7f8cd --- /dev/null +++ b/packages/devel/make/patches/make-01-disable-inheritance-of-fds.patch @@ -0,0 +1,42 @@ +From d79fe162c009788888faaf0317253b6f0cac7092 Mon Sep 17 00:00:00 2001 +From: Kevin Buettner +Date: Thu, 23 Apr 2020 17:05:34 -0400 +Subject: [SV 58232] Disable inheritance of jobserver FDs for recursive make + +A parent make will invoke a sub-make with close-on-exec disabled for +the jobserver pipe FDs. Force close-on-exec to be to be enabled in +the sub-make so the pipe is not always passed to child jobs. + +I have a test case which, when invoked with a suitable -j switch, +will hang if the recipe inherits the jobserver pipe. This test case +was inspired by a real world case in which testing GDB on Fedora +would hang due to some poorly written test GDB cases having been +passed the jobserver file descriptors. + +* src/posixos.c (jobserver_parse_auth): Call fd_noinherit() for +jobserver pipe descriptors. + +Copyright-paperwork-exempt: yes +--- + src/posixos.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/posixos.c b/src/posixos.c +index 525f292..eab175a 100644 +--- a/src/posixos.c ++++ b/src/posixos.c +@@ -145,6 +145,11 @@ jobserver_parse_auth (const char *auth) + /* When using pselect() we want the read to be non-blocking. */ + set_blocking (job_fds[0], 0); + ++ /* By default we don't send the job pipe FDs to our children. ++ See jobserver_pre_child() and jobserver_post_child(). */ ++ fd_noinherit (job_fds[0]); ++ fd_noinherit (job_fds[1]); ++ + return 1; + } + +-- +cgit v1.2.1 + diff --git a/packages/devel/mpc/package.mk b/packages/devel/mpc/package.mk new file mode 100644 index 000000000..94ec78fc0 --- /dev/null +++ b/packages/devel/mpc/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mpc" +PKG_VERSION="1.2.1" +PKG_SHA256="17503d2c395dfcf106b622dc142683c1199431d095367c6aacba6eec30340459" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.multiprecision.org" +PKG_URL="http://ftpmirror.gnu.org/mpc/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host gmp:host mpfr:host" +PKG_LONGDESC="A C library for the arithmetic of complex numbers with arbitrarily high precision and correct rounding of the result." + +PKG_CONFIGURE_OPTS_HOST="--target=${TARGET_NAME} \ + --enable-static --disable-shared \ + --with-gmp=${TOOLCHAIN} \ + --with-mpfr=${TOOLCHAIN}" diff --git a/packages/devel/mpfr/package.mk b/packages/devel/mpfr/package.mk new file mode 100644 index 000000000..2747ba0fb --- /dev/null +++ b/packages/devel/mpfr/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mpfr" +PKG_VERSION="4.1.0" +PKG_SHA256="0c98a3f1732ff6ca4ea690552079da9c597872d30e96ec28414ee23c95558a7f" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.mpfr.org/" +PKG_URL="http://ftpmirror.gnu.org/mpfr/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host gmp:host" +PKG_LONGDESC="A C library for multiple-precision floating-point computations with exact rounding." + +PKG_CONFIGURE_OPTS_HOST="--target=${TARGET_NAME} \ + --enable-static --disable-shared \ + --prefix=${TOOLCHAIN} \ + --with-gmp-lib=${TOOLCHAIN}/lib \ + --with-gmp-include=${TOOLCHAIN}/include" diff --git a/packages/devel/ncurses/package.mk b/packages/devel/ncurses/package.mk new file mode 100644 index 000000000..04b4d59c7 --- /dev/null +++ b/packages/devel/ncurses/package.mk @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ncurses" +PKG_VERSION="6.1-20181215" +PKG_SHA256="08b07c3e792961f300829512c283d5fefc0b1c421a57b76922c3d13303ed677d" +PKG_LICENSE="MIT" +PKG_SITE="http://www.gnu.org/software/ncurses/" +PKG_URL="http://invisible-mirror.net/archives/ncurses/current/ncurses-${PKG_VERSION}.tgz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain zlib ncurses:host" +PKG_LONGDESC="A library is a free software emulation of curses in System V Release 4.0, and more." +# causes some segmentation fault's (dialog) when compiled with gcc's link time optimization. +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="auto" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -fcommon -fPIC" +} + +PKG_CONFIGURE_OPTS_TARGET=" + --without-ada \ + --without-cxx \ + --without-cxx-binding \ + --disable-db-install \ + --without-manpages \ + --without-progs \ + --without-tests \ + --with-shared \ + --with-normal \ + --without-debug \ + --without-profile \ + --with-termlib \ + --without-ticlib \ + --without-gpm \ + --without-dbmalloc \ + --without-dmalloc \ + --disable-rpath \ + --disable-database \ + --with-fallbacks=linux,screen,xterm,xterm-color,dumb,st-256color \ + --with-termpath=/storage/.config/termcap \ + --disable-big-core \ + --enable-termcap \ + --enable-getcap \ + --disable-getcap-cache \ + --enable-symlinks \ + --disable-bsdpad \ + --without-rcs-ids \ + --enable-ext-funcs \ + --disable-const \ + --enable-no-padding \ + --disable-sigwinch \ + --enable-pc-files \ + --with-pkg-config-libdir=/usr/lib/pkgconfig \ + --disable-tcap-names \ + --without-develop \ + --disable-hard-tabs \ + --disable-xmc-glitch \ + --disable-hashmap \ + --disable-safe-sprintf \ + --disable-scroll-hints \ + --disable-widec \ + --disable-echo \ + --disable-warnings \ + --disable-home-terminfo \ + --disable-assertions" + +post_makeinstall_target() { + #cp -rf ${INSTALL}/usr/lib/* ${TOOLCHAIN}/${TARGET_ARCH}-libreelec-linux-gnu${TARGET_ABI}/lib + cp misc/ncurses-config ${TOOLCHAIN}/bin + chmod +x ${TOOLCHAIN}/bin/ncurses-config + sed -e "s:\(['=\" ]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i ${TOOLCHAIN}/bin/ncurses-config + #rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch b/packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch new file mode 100644 index 000000000..030213be1 --- /dev/null +++ b/packages/devel/ncurses/patches/ncurses-001-terminfo-xterm.patch @@ -0,0 +1,16 @@ + +Remove recent xterm terminfo features to be compatible with other emulations + +--- a/misc/terminfo.src 2018-12-21 18:53:11.000000000 +0100 ++++ a/misc/terminfo.src 2018-12-22 22:56:47.000000000 +0100 +@@ -4335,8 +4335,8 @@ xterm-xfree86|xterm terminal emulator (X + xterm-new|modern xterm terminal emulator, + npc, + indn=\E[%p1%dS, kb2=\EOE, kcbt=\E[Z, kent=\EOM, +- rin=\E[%p1%dT, use=ansi+rep, use=ecma+strikeout, +- use=xterm+sm+1006, use=xterm+pcfkeys, use=xterm+tmux, ++ rin=\E[%p1%dT, use=ecma+strikeout, ++ use=xterm+sm+1005, use=xterm+pcfkeys, use=xterm+tmux, + use=xterm-basic, + + # This fragment is for people who cannot agree on what the backspace key diff --git a/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch b/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch new file mode 100644 index 000000000..218e3a7b3 --- /dev/null +++ b/packages/devel/ncurses/patches/ncurses-002-alloc-fallbacks.patch @@ -0,0 +1,24 @@ +Fix freeing not allocated fallback entries by allocating a copy. + +--- a/ncurses/tinfo/lib_setup.c 2018-11-24 23:13:16.000000000 +0100 ++++ b/ncurses/tinfo/lib_setup.c 2018-12-29 10:31:01.000000000 +0100 +@@ -756,6 +756,8 @@ TINFO_SETUP_TERM(TERMINAL **tp, + if (status != TGETENT_YES) { + const TERMTYPE2 *fallback = _nc_fallback2(tname); + ++ if (fallback) ++ fallback = _nc_copy_entry(fallback); + if (fallback) { + T(("found fallback entry")); + TerminalType(termp) = *fallback; +--- a/ncurses/tinfo/tinfo_driver.c 2018-11-24 23:17:03.000000000 +0100 ++++ b/ncurses/tinfo/tinfo_driver.c 2018-12-29 10:27:19.000000000 +0100 +@@ -172,6 +172,8 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * T + if (status != TGETENT_YES) { + const TERMTYPE2 *fallback = _nc_fallback2(tname); + ++ if (fallback) ++ fallback = _nc_copy_entry(fallback); + if (fallback) { + T(("found fallback entry")); + TerminalType(termp) = *fallback; diff --git a/packages/devel/parallel/package.mk b/packages/devel/parallel/package.mk new file mode 100644 index 000000000..24f99d8fb --- /dev/null +++ b/packages/devel/parallel/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="parallel" +PKG_VERSION="20190722" +PKG_SHA256="0ed0863184dbb396b4c030848e754b1ea76329c06ae9e43314bc0915eb6cbca7" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/parallel/" +PKG_URL="http://ftpmirror.gnu.org/parallel/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_HOST="" +PKG_LONGDESC="GNU parallel is a shell tool for executing jobs in parallel using one or more computers." diff --git a/packages/devel/pcre/package.mk b/packages/devel/pcre/package.mk new file mode 100644 index 000000000..87273ba41 --- /dev/null +++ b/packages/devel/pcre/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pcre" +PKG_VERSION="8.44" +PKG_SHA256="19108658b23b3ec5058edc9f66ac545ea19f9537234be1ec62b714c84399366d" +PKG_LICENSE="OSS" +PKG_SITE="http://www.pcre.org/" +PKG_URL="https://downloads.sourceforge.net/sourceforge/pcre/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A set of functions that implement regular expression pattern matching." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_HOST="--prefix=${TOOLCHAIN} \ + --enable-static \ + --enable-utf8 \ + --enable-unicode-properties \ + --with-gnu-ld" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --enable-utf8 \ + --enable-pcre16 \ + --enable-unicode-properties \ + --with-gnu-ld" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + sed -e "s:\(['= ]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i ${SYSROOT_PREFIX}/usr/bin/${PKG_NAME}-config +} diff --git a/packages/devel/pcre2/package.mk b/packages/devel/pcre2/package.mk new file mode 100644 index 000000000..5f1d6c2f2 --- /dev/null +++ b/packages/devel/pcre2/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="pcre2" +PKG_VERSION="10.33" +PKG_SHA256="35514dff0ccdf02b55bd2e9fa586a1b9d01f62332c3356e379eabb75f789d8aa" +PKG_LICENSE="BSD" +PKG_SITE="http://www.pcre.org/" +PKG_URL="https://ftp.pcre.org/pub/pcre/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A set of functions that implement regular expression pattern matching." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_HOST="--prefix=${TOOLCHAIN} \ + --enable-static \ + --enable-utf8 \ + --enable-unicode-properties \ + --with-gnu-ld" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --enable-utf8 \ + --enable-pcre2-16 \ + --enable-unicode-properties \ + --with-gnu-ld" + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/bin + sed -e "s:\(['= ]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i ${SYSROOT_PREFIX}/usr/bin/${PKG_NAME}-config +} diff --git a/packages/devel/pkg-config/package.mk b/packages/devel/pkg-config/package.mk new file mode 100644 index 000000000..2adaab576 --- /dev/null +++ b/packages/devel/pkg-config/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="pkg-config" +PKG_VERSION="0.29.2" +PKG_SHA256="6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freedesktop.org/software/pkgconfig/" +PKG_URL="http://pkg-config.freedesktop.org/releases/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host gettext:host" +PKG_LONGDESC="A system for managing library compile/link flags that works with automake and autoconf." + +PKG_CONFIGURE_OPTS_HOST="--disable-silent-rules \ + --with-internal-glib --disable-dtrace \ + --with-gnu-ld" + +post_makeinstall_host() { + mkdir -p ${SYSROOT_PREFIX}/usr/share/aclocal + cp pkg.m4 ${SYSROOT_PREFIX}/usr/share/aclocal +} diff --git a/packages/devel/pkg-config/patches/0001-Add-support-for-multiple-sysroots.patch b/packages/devel/pkg-config/patches/0001-Add-support-for-multiple-sysroots.patch new file mode 100644 index 000000000..61403a4c8 --- /dev/null +++ b/packages/devel/pkg-config/patches/0001-Add-support-for-multiple-sysroots.patch @@ -0,0 +1,256 @@ +From 64a39cd046040552729d32caef2a753b7f3dfc9c Mon Sep 17 00:00:00 2001 +From: Andre Heider +Date: Thu, 19 Dec 2019 17:42:01 +0100 +Subject: [PATCH] Add support for multiple sysroots + +Introduce PKG_CONFIG_SYSROOT_BASE, which can be set to a base directory +under which multiple install prefixes exist. + +Now it's possible to: +* configure and install libfoo with --prefix=/base/foo/usr +* configure and install libbar with --prefix=/base/bar/usr +* export PKG_CONFIG_SYSROOT_BASE=/base + +and pkg-config attempts to detect the sysroot directory for each .pc +file located under the base directory, and sets its sysroot accordingly. + +Example with libfoo.pc and libbar.pc both contain includedir=/usr/include + +$ PKG_CONFIG_PATH=/base/foo/usr/lib/pkg-config:/base/bar/usr/lib/pkgconfig \ + PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 \ + pkg-config --cflags libfoo libbar + +Will print "-I/base/foo/usr/include -I/base/bar/usr/include" +--- + main.c | 5 ++++ + parse.c | 2 ++ + pkg.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- + pkg.h | 2 ++ + 4 files changed, 84 insertions(+), 3 deletions(-) + +diff --git a/main.c b/main.c +index 9b27d9a..409d474 100644 +--- a/main.c ++++ b/main.c +@@ -35,6 +35,7 @@ + #undef STRICT + #endif + ++GString *pcsysrootbase = NULL; + char *pcsysrootdir = NULL; + char *pkg_config_pc_path = NULL; + +@@ -531,6 +532,8 @@ main (int argc, char **argv) + add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S); + } + ++ pcsysrootbase = g_string_new(getenv("PKG_CONFIG_SYSROOT_BASE")); ++ + pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR"); + if (pcsysrootdir) + { +@@ -834,5 +837,7 @@ main (int argc, char **argv) + if (need_newline) + printf ("\n"); + ++ g_string_free(pcsysrootbase, FALSE); ++ + return 0; + } +diff --git a/parse.c b/parse.c +index 6e9907c..bea87f3 100644 +--- a/parse.c ++++ b/parse.c +@@ -634,6 +634,7 @@ static void _do_parse_libs (Package *pkg, int argc, char **argv) + while (i < argc) + { + Flag *flag = g_new (Flag, 1); ++ flag->pkg = pkg; + char *tmp = trim_string (argv[i]); + char *arg = strdup_escape_shell(tmp); + char *p; +@@ -837,6 +838,7 @@ parse_cflags (Package *pkg, const char *str, const char *path) + while (i < argc) + { + Flag *flag = g_new (Flag, 1); ++ flag->pkg = pkg; + char *tmp = trim_string (argv[i]); + char *arg = strdup_escape_shell(tmp); + char *p = arg; +diff --git a/pkg.c b/pkg.c +index f29ecc7..ecae401 100644 +--- a/pkg.c ++++ b/pkg.c +@@ -408,6 +408,9 @@ flag_list_strip_duplicates (GList *list) + + if (cur->type == prev->type && g_strcmp0 (cur->arg, prev->arg) == 0) + { ++ if (cur->type & (CFLAGS_I | LIBS_L) && cur->pkg != prev->pkg) ++ continue; ++ + /* Remove the duplicate flag from the list and move to the last + * element to prepare for the next iteration. */ + GList *dup = tmp; +@@ -421,19 +424,75 @@ flag_list_strip_duplicates (GList *list) + return list; + } + ++static const struct _suffix { ++ const char * const suffix; ++ const size_t len; ++} suffixes[] = { ++ { ++ "/usr/local/lib/pkgconfig", ++ 24, ++ }, ++ { ++ "/usr/local/share/pkgconfig", ++ 26, ++ }, ++ { ++ "/usr/lib/pkgconfig", ++ 18, ++ }, ++ { ++ "/usr/share/pkgconfig", ++ 20, ++ }, ++ { ++ "/lib/pkgconfig", ++ 14, ++ }, ++ { ++ "/share/pkgconfig", ++ 16, ++ }, ++}; ++ ++static void ++get_sysroot(const Package *pkg, GString *dst) ++{ ++ if (pcsysrootbase->len && !strncmp(pkg->pcfiledir, pcsysrootbase->str, pcsysrootbase->len)) ++ { ++ size_t len = strlen(pkg->pcfiledir); ++ ++ for (int i = 0; i < sizeof(suffixes) / sizeof(*suffixes); i++) ++ { ++ const struct _suffix *x = &suffixes[i]; ++ ++ if (len > x->len && !strcmp(pkg->pcfiledir + len - x->len, x->suffix)) ++ { ++ g_string_assign(dst, pkg->pcfiledir); ++ g_string_truncate(dst, dst->len - x->len); ++ return; ++ } ++ } ++ } ++ ++ g_string_assign(dst, pcsysrootdir ? pcsysrootdir : ""); ++} ++ + static char * + flag_list_to_string (GList *list) + { + GList *tmp; + GString *str = g_string_new (""); ++ GString *sysroot = g_string_new (""); ++ GString *cmp = g_string_new(pcsysrootbase->len ? pcsysrootbase->str : pcsysrootdir); + char *retval; + + tmp = list; + while (tmp != NULL) { + Flag *flag = tmp->data; ++ get_sysroot(flag->pkg, sysroot); + char *tmpstr = flag->arg; + +- if (pcsysrootdir != NULL && flag->type & (CFLAGS_I | LIBS_L)) { ++ if (sysroot->len && flag->type & (CFLAGS_I | LIBS_L) && strncmp(tmpstr + 2, cmp->str, cmp->len)) { + /* Handle non-I Cflags like -isystem */ + if (flag->type & CFLAGS_I && strncmp (tmpstr, "-I", 2) != 0) { + char *space = strchr (tmpstr, ' '); +@@ -441,14 +500,17 @@ flag_list_to_string (GList *list) + /* Ensure this has a separate arg */ + g_assert (space != NULL && space[1] != '\0'); + g_string_append_len (str, tmpstr, space - tmpstr + 1); +- g_string_append (str, pcsysrootdir); ++ g_string_append (str, sysroot->str); + g_string_append (str, space + 1); + } else { + g_string_append_c (str, '-'); + g_string_append_c (str, tmpstr[1]); +- g_string_append (str, pcsysrootdir); ++ g_string_append (str, sysroot->str); + g_string_append (str, tmpstr+2); + } ++ } else if (sysroot->len && !strncmp(tmpstr, "/usr", 4) && strncmp(tmpstr, cmp->str, cmp->len)) { ++ g_string_append (str, sysroot->str); ++ g_string_append (str, tmpstr); + } else { + g_string_append (str, tmpstr); + } +@@ -458,6 +520,8 @@ flag_list_to_string (GList *list) + + retval = str->str; + g_string_free (str, FALSE); ++ g_string_free (cmp, FALSE); ++ g_string_free (sysroot, TRUE); + + return retval; + } +@@ -1046,6 +1110,8 @@ packages_get_var (GList *pkgs, + { + GList *tmp; + GString *str; ++ GString *sysroot = g_string_new (""); ++ GString *cmp = g_string_new(pcsysrootbase->len ? pcsysrootbase->str : pcsysrootdir); + + str = g_string_new (NULL); + +@@ -1055,11 +1121,14 @@ packages_get_var (GList *pkgs, + Package *pkg = tmp->data; + char *var; + ++ get_sysroot(pkg, sysroot); + var = parse_package_variable (pkg, varname); + if (var) + { + if (str->len > 0) + g_string_append_c (str, ' '); ++ if (sysroot->len && (!strcmp(varname, "includedir") || !strcmp(varname, "libdir")) && strncmp(var, sysroot->str, sysroot->len)) ++ g_string_append(str, sysroot->str); + g_string_append (str, var); + g_free (var); + } +@@ -1067,6 +1136,9 @@ packages_get_var (GList *pkgs, + tmp = g_list_next (tmp); + } + ++ g_string_free(cmp, FALSE); ++ g_string_free(sysroot, TRUE); ++ + return g_string_free (str, FALSE); + } + +diff --git a/pkg.h b/pkg.h +index c6732bd..58edf38 100644 +--- a/pkg.h ++++ b/pkg.h +@@ -53,6 +53,7 @@ struct Flag_ + { + FlagType type; + char *arg; ++ Package *pkg; + }; + + struct RequiredVersion_ +@@ -126,6 +127,7 @@ void disable_requires_private(void); + /* If TRUE, do not automatically prefer uninstalled versions */ + extern gboolean disable_uninstalled; + ++extern GString *pcsysrootbase; + extern char *pcsysrootdir; + + /* pkg-config default search path. On Windows the current pkg-config install +-- +2.24.0 + diff --git a/packages/devel/popt/package.mk b/packages/devel/popt/package.mk new file mode 100644 index 000000000..1c0f708ca --- /dev/null +++ b/packages/devel/popt/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="popt" +PKG_VERSION="1.18" +PKG_SHA256="5159bc03a20b28ce363aa96765f37df99ea4d8850b1ece17d1e6ad5c24fdc5d1" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/rpm-software-management/popt" +PKG_URL="http://ftp.rpm.org/popt/releases/popt-1.x/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The popt library exists essentially for parsing command-line options." + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} +} + +pre_configure_host() { + cd ${PKG_BUILD} + rm -rf .${HOST_NAME} +} diff --git a/packages/devel/rapidjson/package.mk b/packages/devel/rapidjson/package.mk new file mode 100644 index 000000000..bfaf3a9b7 --- /dev/null +++ b/packages/devel/rapidjson/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rapidjson" +PKG_VERSION="1.1.0" +PKG_SHA256="bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/miloyip/rapidjson" +PKG_URL="https://github.com/miloyip/rapidjson/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A fast JSON parser/generator for C++ with both SAX/DOM style API" + +PKG_CMAKE_OPTS_TARGET="-DRAPIDJSON_BUILD_DOC=OFF \ + -DRAPIDJSON_BUILD_EXAMPLES=OFF \ + -DRAPIDJSON_BUILD_TESTS=OFF \ + -DRAPIDJSON_BUILD_THIRDPARTY_GTEST=OFF \ + -DRAPIDJSON_BUILD_ASAN=OFF \ + -DRAPIDJSON_BUILD_UBSAN=OFF \ + -DRAPIDJSON_HAS_STDSTRING=ON" diff --git a/packages/devel/rapidjson/patches/rapidjson-0001-remove_custom_cxx_flags.patch b/packages/devel/rapidjson/patches/rapidjson-0001-remove_custom_cxx_flags.patch new file mode 100644 index 000000000..51434ff52 --- /dev/null +++ b/packages/devel/rapidjson/patches/rapidjson-0001-remove_custom_cxx_flags.patch @@ -0,0 +1,29 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ceda71b..efb259e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -50,7 +50,6 @@ if(CCACHE_FOUND) + endif(CCACHE_FOUND) + + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") + if (RAPIDJSON_BUILD_CXX11) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +@@ -73,7 +72,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + endif() + endif() + elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers") + if (RAPIDJSON_BUILD_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() +@@ -88,7 +86,6 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + endif() + endif() + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") +- add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") + endif() + + diff --git a/packages/devel/readline/package.mk b/packages/devel/readline/package.mk new file mode 100644 index 000000000..02734e965 --- /dev/null +++ b/packages/devel/readline/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="readline" +PKG_VERSION="8.0" +PKG_SHA256="e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" +PKG_LICENSE="MIT" +PKG_SITE="http://www.gnu.org/software/readline/" +PKG_URL="http://ftpmirror.gnu.org/readline/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="The GNU Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="bash_cv_wcwidth_broken=no \ + --disable-shared \ + --enable-static \ + --with-curses" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/share/readline +} diff --git a/packages/devel/slang/package.mk b/packages/devel/slang/package.mk new file mode 100644 index 000000000..362d032f5 --- /dev/null +++ b/packages/devel/slang/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="slang" +PKG_VERSION="2.3.2" +PKG_SHA256="fc9e3b0fc4f67c3c1f6d43c90c16a5c42d117b8e28457c5b46831b8b5d3ae31a" +PKG_LICENSE="GPL" +PKG_SITE="http://www.jedsoft.org/slang/" +PKG_URL="https://www.jedsoft.org/releases/slang/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library designed to allow a developer to create robust multi-platform software." +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_TARGET="--without-onig" + +pre_configure_target() { + # slang fails to build in subdirs + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} +} + +pre_configure_host() { + # slang fails to build in subdirs + cd ${PKG_BUILD} + rm -rf .${HOST_NAME} +} diff --git a/packages/devel/spdlog/package.mk b/packages/devel/spdlog/package.mk new file mode 100644 index 000000000..c09b02cc8 --- /dev/null +++ b/packages/devel/spdlog/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="spdlog" +PKG_VERSION="1.9.2" +PKG_SHA256="6fff9215f5cb81760be4cc16d033526d1080427d236e86d70bb02994f85e3d38" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/gabime/spdlog" +PKG_URL="https://github.com/gabime/spdlog/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain libfmt" +PKG_LONGDESC="Very fast, header only, C++ logging library." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_CXX_STANDARD=14 -DCMAKE_CXX_EXTENSIONS:BOOL=OFF -DSPDLOG_FMT_EXTERNAL=ON -DSPDLOG_BUILD_EXAMPLE=OFF -DSPDLOG_BUILD_TESTS=OFF" diff --git a/packages/devel/swig/package.mk b/packages/devel/swig/package.mk new file mode 100644 index 000000000..136eb0796 --- /dev/null +++ b/packages/devel/swig/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="swig" +PKG_VERSION="4.0.2" +PKG_SHA256="d53be9730d8d58a16bf0cbd1f8ac0c0c3e1090573168bfa151b01eb47fa906fc" +PKG_LICENSE="GPL" +PKG_SITE="http://www.swig.org" +PKG_URL="${SOURCEFORGE_SRC}/swig/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages." + +PKG_CONFIGURE_OPTS_HOST="--program-suffix=4.0 \ + --with-pcre-prefix=${TOOLCHAIN} \ + --with-boost=no \ + --without-pcre \ + --without-x \ + --without-tcl \ + --without-python \ + --without-python3 \ + --without-perl5 \ + --without-octave \ + --without-java \ + --without-gcj \ + --without-android \ + --without-guile \ + --without-mzscheme \ + --without-ruby \ + --without-php \ + --without-ocaml \ + --without-pike \ + --without-chicken \ + --without-csharp \ + --without-lua \ + --without-allegrocl \ + --without-clisp \ + --without-r \ + --without-go \ + --without-d" + +post_makeinstall_host() { + ln -sf swig4.0 ${TOOLCHAIN}/bin/swig +} diff --git a/packages/devel/yajl/package.mk b/packages/devel/yajl/package.mk new file mode 100644 index 000000000..3de3c00de --- /dev/null +++ b/packages/devel/yajl/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="yajl" +PKG_VERSION="2.1.0" +PKG_SHA256="020f55a2dfc979ad63dc99b629b3fea7e7e4b9f20d8b10b856cfcb8850f03c61" +PKG_LICENSE="ISC" +PKG_SITE="http://lloyd.github.com/yajl/" +PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small event-driven (SAX-style) JSON parser." + +post_makeinstall_target() { + mv ${SYSROOT_PREFIX}/usr/lib/libyajl_s.a ${SYSROOT_PREFIX}/usr/lib/libyajl.a + rm ${SYSROOT_PREFIX}/usr/lib/libyajl.so* + + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/lib +} diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00023.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00023.ini new file mode 100644 index 000000000..3bb22e244 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00023.ini @@ -0,0 +1,40 @@ +_S NPEG-00023 +_G GoW CoO [EUR-PSN] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00D166F 0x0001F690//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C166F +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C166F +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001A31C 0x0A200E01//Jump +_L 0x2001A320 0x34040000//FPS +_L 0x2001A324 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00D166F 0x0001F690//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C166F +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C166F +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001A31C 0x0A200E01//Jump +_L 0x2001A320 0x34040001//FPS +_L 0x2001A324 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x0001A31C +_L 0x2001A31C 0x8FBF0000 +_L 0x2001A320 0x03E00008 +_L 0x2001A324 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00044.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00044.ini new file mode 100644 index 000000000..eff298988 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPEG00044.ini @@ -0,0 +1,40 @@ +_S NPEG-00044 +_G GoW GoS [EUR-MULTI5-PSN] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00DE14D 0x000205DC//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE14D +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE14D +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040000//FPS +_L 0x2001B114 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00DE14D 0x000205DC//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE14D +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE14D +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040001//FPS +_L 0x2001B114 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x1001B10C +_L 0x2001B10C 0x8FBF0000 +_L 0x2001B110 0x03E00008 +_L 0x2001B114 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPUG80325.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPUG80325.ini new file mode 100644 index 000000000..d7b2640d0 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/NPUG80325.ini @@ -0,0 +1,40 @@ +_S NPUG-80325 +_G GoW CoO [USA-PSN] +_C1 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00D1671 0x0001F690//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C1671 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C1671 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001A31C 0x0A200E01//Jump +_L 0x2001A320 0x34040000//FPS +_L 0x2001A324 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00D1671 0x0001F690//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C1671 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C1671 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001A31C 0x0A200E01//Jump +_L 0x2001A320 0x34040001//FPS +_L 0x2001A324 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x0001A31C +_L 0x2001A31C 0x8FBF0000 +_L 0x2001A320 0x03E00008 +_L 0x2001A324 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00019.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00019.ini new file mode 100644 index 000000000..645546a3f --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00019.ini @@ -0,0 +1,10 @@ +_S UCES-00019 +_G Pursuit Force [EUR] +_C0 60 FPS v2 +_L 0x20188038 0x0A262017//FPS +_L 0x2016F308 0x3C043F00//GAMEPLAYSPEED +_L 0x2016F388 0x3C044270//MENUSPEED +_C0 30 FPS v2 [Default] +_L 0x20188038 0x10800008//FPS +_L 0x2016F308 0x3C043F80//GAMEPLAYSPEED +_L 0x2016F388 0x3C0441F0//MENUSPEED \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00842.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00842.ini new file mode 100644 index 000000000..e7617352c --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES00842.ini @@ -0,0 +1,40 @@ +_S UCES-00842 +_G GoW CoO [EUR] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00D0200 0x0001A378//Jump-0x10 +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C16F9 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C16F9 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0010 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0020 +_L 0x2001A388 0x0A200E01//Jump +_L 0x2001A38C 0x34040000//FPS +_L 0x2001A390 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00D0200 0x0001A378//Jump-0x10 +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C16F9 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C16F9 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0010 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0020 +_L 0x2001A388 0x0A200E01//Jump +_L 0x2001A38C 0x34040001//FPS +_L 0x2001A390 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x0001A388 +_L 0x2001A388 0x8FBF0010 +_L 0x2001A38C 0x03E00008 +_L 0x2001A390 0x27BD0020 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01184.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01184.ini new file mode 100644 index 000000000..031e0dfb8 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01184.ini @@ -0,0 +1,24 @@ +_S UCES-01184 +_G Resistance: Retribution [EUR] +_C0 60FPS v2 [No Vsync] +_L 0xE0030001 0x10003600 +_L 0xE0020003 0x0047F150 +_L 0x2047F158 0x34020001 +_L 0x20003600 0x00000001 +_C0 60FPS v2 [Default] +_L 0xE0030002 0x10003600 +_L 0xE0020003 0x0047F150 +_L 0x2047F158 0x0E31EDB7 +_L 0x20003600 0x00000002 +_C0 30FPS v2 +_L 0xE00A0003 0x10003600 +_L 0xE0090003 0x0047F150 +_L 0x2047F158 0x0E200D81//Jal +_L 0x20003600 0x00000003 +_L 0x20003604 0x03E0D821 +_L 0x20003608 0x0E3674AD//Vb +_L 0x2000360C 0x00000000 +_L 0x20003610 0x0E3674AD//Vb +_L 0x20003614 0x00000000 +_L 0x20003618 0x03600008 +_L 0x2000361C 0x34020001 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01401.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01401.ini new file mode 100644 index 000000000..390b942d3 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01401.ini @@ -0,0 +1,40 @@ +_S UCES-01401 +_G GoW GoS [EUR-MULTI5-UMD] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00DE13C 0x000205DC//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE13C +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE13C +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040000//FPS +_L 0x2001B114 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00DE13C 0x000205DC//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE13C +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE13C +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040001//FPS +_L 0x2001B114 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x1001B10C +_L 0x2001B10C 0x8FBF0000 +_L 0x2001B110 0x03E00008 +_L 0x2001B114 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01473.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01473.ini new file mode 100644 index 000000000..5dc49929e --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCES01473.ini @@ -0,0 +1,40 @@ +_S UCES-01473 +_G GoW GoS [EUR-MULTI3-UMD] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00DE173 0x000205DC//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE173 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE173 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040000//FPS +_L 0x2001B114 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00DE173 0x000205DC//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FE173 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FE173 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040001//FPS +_L 0x2001B114 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x1001B10C +_L 0x2001B10C 0x8FBF0000 +_L 0x2001B110 0x03E00008 +_L 0x2001B114 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98640.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98640.ini new file mode 100644 index 000000000..76c0eb4d9 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98640.ini @@ -0,0 +1,10 @@ +_S UCUS-98640 +_G Pursuit Force [USA] +_C0 60 FPS v2 +_L 0x201AC008 0x0A26B00B//FPS +_L 0x20193928 0x3C043F00//GAMEPLAYSPEED +_L 0x201939A8 0x3C044270//MENUSPEED +_C0 30 FPS v2 [Default] +_L 0x201AC008 0x10800008//FPS +_L 0x20193928 0x3C043F80//GAMEPLAYSPEED +_L 0x201939A8 0x3C0441F0//MENUSPEED \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98653.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98653.ini new file mode 100644 index 000000000..fa614adba --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98653.ini @@ -0,0 +1,40 @@ +_S UCUS-98653 +_G GoW CoO [USA] +_C0 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00D0200 0x0001A378//Jump-0x10 +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C16F9 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C16F9 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0010 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0020 +_L 0x2001A388 0x0A200E01//Jump +_L 0x2001A38C 0x34040000//FPS +_L 0x2001A390 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00D0200 0x0001A378//Jump-0x10 +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2C16F9 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2C16F9 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0010 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0020 +_L 0x2001A388 0x0A200E01//Jump +_L 0x2001A38C 0x34040001//FPS +_L 0x2001A390 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x0001A388 +_L 0x2001A388 0x8FBF0010 +_L 0x2001A38C 0x03E00008 +_L 0x2001A390 0x27BD0020 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98668.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98668.ini new file mode 100644 index 000000000..c70649b0c --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98668.ini @@ -0,0 +1,24 @@ +_S UCUS-98668 +_G Resistance: Retribution [USA] +_C0 60FPS v2 [No Vsync] +_L 0xE0030001 0x10003600 +_L 0xE0020003 0x0047F150 +_L 0x2047F158 0x34020001 +_L 0x20003600 0x00000001 +_C0 60FPS v2 [Default] +_L 0xE0030002 0x10003600 +_L 0xE0020003 0x0047F150 +_L 0x2047F158 0x0E31EDB7 +_L 0x20003600 0x00000002 +_C0 30FPS v2 +_L 0xE00A0003 0x10003600 +_L 0xE0090003 0x0047F150 +_L 0x2047F158 0x0E200D81//Jal +_L 0x20003600 0x00000003 +_L 0x20003604 0x03E0D821 +_L 0x20003608 0x0E3674AD//Vb +_L 0x2000360C 0x00000000 +_L 0x20003610 0x0E3674AD//Vb +_L 0x20003614 0x00000000 +_L 0x20003618 0x03600008 +_L 0x2000361C 0x34020001 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98737.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98737.ini new file mode 100644 index 000000000..41a9c3802 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/UCUS98737.ini @@ -0,0 +1,40 @@ +_S UCUS-98737 +_G GoW GoS [USA-UMD] +_C1 60 FPS [Fixed] +_L 0xE00E003C 0x10003800 +_L 0xE00DDC67 0x000205DC//vblank +_L 0x10003800 0x0000003C +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FDC67 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FDC67 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040000//FPS +_L 0x2001B114 0x00000000 +_C0 30 FPS [Fixed] +_L 0xE00E001E 0x10003800 +_L 0xE00DDC67 0x000205DC//vblank +_L 0x10003800 0x0000001E +_L 0x20003804 0x10800003 +_L 0x20003808 0x00000000 +_L 0x2000380C 0x0E2FDC67 +_L 0x20003810 0x00000000 +_L 0x20003814 0x0E2FDC67 +_L 0x20003818 0x00000000 +_L 0x2000381C 0x8FBF0000 +_L 0x20003820 0x03E00008 +_L 0x20003824 0x27BD0010 +_L 0x2001B10C 0x0A200E01//Jump +_L 0x2001B110 0x34040001//FPS +_L 0x2001B114 0x00000000 +_C0 Unlimited FPS [Default] +_L 0xE0040E01 0x1001B10C +_L 0x2001B10C 0x8FBF0000 +_L 0x2001B110 0x03E00008 +_L 0x2001B114 0x27BD0010 +_L 0x10003800 0x00000000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00033.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00033.ini new file mode 100644 index 000000000..f89c600b5 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00033.ini @@ -0,0 +1,10 @@ +_S ULES-00033 +_G Tony Hawk's Underground 2: Remix [EUR-ENG] +_C0 60 FPS +_L 0xE0021080 0x0005F61A +_L 0x2005F618 0x10000017 +_L 0x2000C190 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x0005F61A +_L 0x2005F618 0x10800017//Vblank +_L 0x2000C190 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00034.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00034.ini new file mode 100644 index 000000000..477246578 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00034.ini @@ -0,0 +1,10 @@ +ULES-00034 +_G Tony Hawk's Underground 2: Remix [EUR-FR] +_C0 60 FPS +_L 0xE0021080 0x0005F61A +_L 0x2005F618 0x10000017 +_L 0x2000C190 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x0005F61A +_L 0x2005F618 0x10800017//Vblank +_L 0x2000C190 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00035.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00035.ini new file mode 100644 index 000000000..66485ec7f --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00035.ini @@ -0,0 +1,10 @@ +_S ULES-00035 +_G Tony Hawk's Underground 2: Remix [EUR-GER] +_C0 60 FPS +_L 0xE0021080 0x0005F61A +_L 0x2005F618 0x10000017 +_L 0x2000C190 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x0005F61A +_L 0x2005F618 0x10800017//Vblank +_L 0x2000C190 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00125.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00125.ini new file mode 100644 index 000000000..2fc9333c8 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00125.ini @@ -0,0 +1,15 @@ +_S ULES-00125 +_G Burnout Legends [EUR-v2.00] +_C1 60 FPS v3 +_L 0xE0020003 0x000555D0//conditional +_L 0x200555D0 0x00000000//FPS,1 +_L 0x2024A7FC 0x3C043F00//Speed,EnableBeforeIngame +_L 0xE0010100 0x10441740//Condit,normalGame +_L 0x2000F380 0x14800003//FPS,2 +_L 0xE0010100 0x00441740//Condit,crashMode +_L 0x2000F380 0x16200003//FPS,2 +_C0 30 FPS v3 [Default] +_L 0xE0030000 0x000555D0//conditional +_L 0x200555D0 0x14A00003//FPS,1 +_L 0x2024A7FC 0x3C043F80//Speed,EnableBeforeIngame +_L 0x2000F380 0x14800003//FPS,2 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00483.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00483.ini new file mode 100644 index 000000000..e84e8b3cb --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00483.ini @@ -0,0 +1,7 @@ +_S ULES-00483 +_G The Warriors [EUR] +_C0 60 FPS +_L 0xE001FFF6 0x003B4D84 +_L 0x203B4D84 0x00000000 +_C0 30 FPS [Default] +_L 0x203B4D84 0x1440FFF6 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00625.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00625.ini new file mode 100644 index 000000000..f21d01022 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00625.ini @@ -0,0 +1,10 @@ +_S ULES-00625 +_G Tony Hawk's Project 8 [EUR-ENG] +_C0 60 FPS +_L 0xE0021080 0x00096E16 +_L 0x20096E14 0x10000017 +_L 0x20011C28 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x00096E16 +_L 0x20096E14 0x10800017//Vblank +_L 0x20011C28 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00626.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00626.ini new file mode 100644 index 000000000..1ddbb8278 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00626.ini @@ -0,0 +1,10 @@ +_S ULES-00626 +_G Tony Hawk's Project 8 [EUR-Multi5] +_C0 60 FPS +_L 0xE0021080 0x00096E16 +_L 0x20096E14 0x10000017 +_L 0x20011C28 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x00096E16 +_L 0x20096E14 0x10800017//Vblank +_L 0x20011C28 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00703.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00703.ini new file mode 100644 index 000000000..652c66050 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00703.ini @@ -0,0 +1,14 @@ +_S ULES-00703 +_G Burnout Dominator [EUR][MULTI5] +_C0 60 FPS v2 +_L 0xE004001A 0x0002574C +_L 0x2002574C 0x00000000//FPS +_L 0x201A0360 0x00000000//WritesSpeed1 +_L 0x204F08BC 0x3C888888//Speed1 +_L 0x2019AE98 0x3C043F00//Speed2,EnableBeforeIngameOnly +_C0 30 FPS v2 [Default] +_L 0xE0040000 0x0002574C +_L 0x2002574C 0x14A0001A//FPS +_L 0x201A0360 0x089A0360//WritesSpeed1 +_L 0x204F08BC 0x3D088888//Speed1 +_L 0x2019AE98 0x3C043F80//Speed2,EnableBeforeIngameOnly \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00968.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00968.ini new file mode 100644 index 000000000..e440020e9 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00968.ini @@ -0,0 +1,6 @@ +_S ULES-00968 +_G FlatOut - Head On [EUR] +_C0 60 FPS +_L 0x006FC1F0 0x00000000 +_C0 30 FPS [Default] +_L 0x006FC1F0 0x00000001 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00981.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00981.ini new file mode 100644 index 000000000..994966b1b --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00981.ini @@ -0,0 +1,30 @@ +_S ULES-00981 +_G Star Wars - The Force Unleashed [EUR-Multi3] +_C0 60FPS [Fixed] +_L 0xE0050002 0x004408B4 +_L 0x204408B4 0x00000000//value +_L 0x202B8B2C 0x00000000 +_L 0x203BB968 0x00000000 +_L 0x202B9130 0x00000000 +_L 0x203BC2F0 0x00000000 +_C0 30FPS [Fixed] +_L 0xE0050000 0x004408B4 +_L 0x204408B4 0x00000002//value +_L 0x202B8B2C 0x00000000 +_L 0x203BB968 0x00000000 +_L 0x202B9130 0x00000000 +_L 0x203BC2F0 0x00000000 +_C0 30/60FPS [Default] +_L 0xE0040000 0x002B8B2C +_L 0x202B8B2C 0xAC9308B4//30 +_L 0x203BB968 0xAC8608B4//30 +_L 0x202B9130 0xAC8008B4//60 +_L 0x203BC2F0 0xAC8008B4//60 +_S ULES-00981 +_G Star Wars - The Force Unleashed [EUR-Multi3] +_C0 Red overlay FIX +_L 0xE001ADAE 0x003E9712 +_L 0x203E9710 0xADA00000 +_C0 Red overlay NO-FIX [Default] +_L 0xE001ADA0 0x003E9712 +_L 0x203E9710 0xADAE0000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00982.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00982.ini new file mode 100644 index 000000000..3d0a33daa --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES00982.ini @@ -0,0 +1,30 @@ +_S ULES-00982 +_G Star Wars - The Force Unleashed [EUR-Multi2] +_C0 60FPS [Fixed] +_L 0xE0050002 0x00440A84 +_L 0x20440A84 0x00000000//value +_L 0x202B8B2C 0x00000000 +_L 0x203BB964 0x00000000 +_L 0x202B9130 0x00000000 +_L 0x203BC2EC 0x00000000 +_C0 30FPS [Fixed] +_L 0xE0050000 0x00440A84 +_L 0x20440A84 0x00000002//value +_L 0x202B8B2C 0x00000000 +_L 0x203BB964 0x00000000 +_L 0x202B9130 0x00000000 +_L 0x203BC2EC 0x00000000 +_C0 30/60FPS [Default] +_L 0xE0040000 0x002B8B2C +_L 0x202B8B2C 0xAC930A84//30 +_L 0x203BB964 0xAC860A84//30 +_L 0x202B9130 0xAC800A84//60 +_L 0x203BC2EC 0xAC800A84//60 +_S ULES-00982 +_G Star Wars - The Force Unleashed [EUR-Multi2] +_C0 Red overlay FIX +_L 0xE001ADAE 0x003E9882 +_L 0x203E9880 0xADA00000 +_C0 Red overlay NO-FIX [Default] +_L 0xE001ADA0 0x003E9882 +_L 0x203E9880 0xADAE0000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01214.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01214.ini new file mode 100644 index 000000000..350b78262 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01214.ini @@ -0,0 +1,11 @@ +_S ULES-01214 +_G Star Wars Battlefront - Elite Squadron [EUR] +_C0 60 FPS +_L 0x20456718 0x42700000 +_C0 45 FPS +_L 0x20456718 0x42340000 +_C0 40 FPS +_L 0x20456718 0x42200000 +_C0 30 FPS +_L 0x20456718 0x41F00000 +_C0 20 FPS [Default] \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01402.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01402.ini new file mode 100644 index 000000000..95d2f1c69 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01402.ini @@ -0,0 +1,8 @@ +_S ULES-01402 +_G Split/Second - Velocity [EUR] +_C0 60 FPS +_L 0x0018A790 0x00000001 +_C0 30 FPS [Default] +_L 0x0018A790 0x00000002 +_C0 20 FPS +_L 0x0018A790 0x00000003 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01406.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01406.ini new file mode 100644 index 000000000..3a93436da --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULES01406.ini @@ -0,0 +1,6 @@ +_S ULES-01406 +_G Toy Story 3 [EUR][MULTI2] +_C0 60 FPS +_L 0x202E7934 0x00000000 +_C0 30 FPS [Default] +_L 0x202E7934 0x1080FFFB \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS00125.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS00125.ini new file mode 100644 index 000000000..fb37e5b8b --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS00125.ini @@ -0,0 +1,15 @@ +_S ULUS-00125 / ULES-00125 +_G Burnout Legends [USA-v2.00] +_C1 60 FPS v3 +_L 0xE0020003 0x000555D0//conditional +_L 0x200555D0 0x00000000//FPS,1 +_L 0x2024A7FC 0x3C043F00//Speed,EnableBeforeIngame +_L 0xE0010100 0x10441740//Condit,normalGame +_L 0x2000F380 0x14800003//FPS,2 +_L 0xE0010100 0x00441740//Condit,crashMode +_L 0x2000F380 0x16200003//FPS,2 +_C0 30 FPS v3 [Default] +_L 0xE0030000 0x000555D0//conditional +_L 0x200555D0 0x14A00003//FPS,1 +_L 0x2024A7FC 0x3C043F80//Speed,EnableBeforeIngame +_L 0x2000F380 0x14800003//FPS,2 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10014.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10014.ini new file mode 100644 index 000000000..19434ecf3 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10014.ini @@ -0,0 +1,10 @@ +_S ULUS-10014 +_G Tony Hawk's Underground 2: Remix [USA] +_C1 60 FPS +_L 0xE0021080 0x0005F642 +_L 0x2005F640 0x10000017 +_L 0x2000C190 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x0005F642 +_L 0x2005F640 0x10800017//Vblank +_L 0x2000C190 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10189.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10189.ini new file mode 100644 index 000000000..56b2311dc --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10189.ini @@ -0,0 +1,9 @@ +_S ULUS-10189 +_G Snoopy vs the Red Baron [USA] +_C1 60 FPS +_L 0xE0010000 0x1023F394 +_L 0x204C6940 0x3F000000 +_L 0x0023F394 0x00000000 +_C0 30 FPS [Default] +_L 0x204C6940 0x3F800000 +_L 0x0023F394 0x00000001 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10197.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10197.ini new file mode 100644 index 000000000..2b62c5435 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10197.ini @@ -0,0 +1,10 @@ +_S ULUS-10197 +_G Tony Hawk's Project 8 [USA-UMDv1.0] +_C0 60 FPS +_L 0xE0021080 0x00097156 +_L 0x20097154 0x10000017 +_L 0x20011C28 0x00000000 +_C0 30 FPS [Default] +_L 0xE0021000 0x00097156 +_L 0x20097154 0x10800017//Vblank +_L 0x20011C28 0x1480FFEE//CtrlBuff \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10213.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10213.ini new file mode 100644 index 000000000..7d89a978d --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10213.ini @@ -0,0 +1,7 @@ +_S ULUS-10213 +_G The Warriors [USA] +_C1 60 FPS +_L 0xE001FFF6 0x003B517C +_L 0x203B517C 0x00000000 +_C0 30 FPS [Default] +_L 0x203B517C 0x1440FFF6 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10236.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10236.ini new file mode 100644 index 000000000..64da0ba1c --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10236.ini @@ -0,0 +1,14 @@ +_S ULUS-10236 +_G Burnout Dominator [USA] +_C0 60 FPS v2 +_L 0xE004001A 0x0002574C +_L 0x2002574C 0x00000000//FPS +_L 0x201A0358 0x00000000//WritesSpeed1 +_L 0x204F08BC 0x3C888888//Speed1 +_L 0x2019AE90 0x3C043F00//Speed2,EnableBeforeIngameOnly +_C0 30 FPS v2 [Default] +_L 0xE0040000 0x0002574C +_L 0x2002574C 0x14A0001A//FPS +_L 0x201A0358 0xE60C0034//WritesSpeed1 +_L 0x204F08BC 0x3D088888//Speed1 +_L 0x2019AE90 0x3C043F80//Speed2,EnableBeforeIngameOnly \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10328.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10328.ini new file mode 100644 index 000000000..794f4823d --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10328.ini @@ -0,0 +1,6 @@ +_S ULUS-10328 +_G FlatOut - Head On [USA] +_C0 60 FPS +_L 0x006FC0F0 0x00000000 +_C0 30 FPS [Default] +_L 0x006FC0F0 0x00000001 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10345.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10345.ini new file mode 100644 index 000000000..befe16bde --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10345.ini @@ -0,0 +1,30 @@ +_S ULUS-10345 +_G Star Wars - The Force Unleashed [USA] +_C0 60FPS [Fixed] +_L 0xE0050002 0x00440664 +_L 0x20440664 0x00000000//value +_L 0x202B8A14 0x00000000 +_L 0x203BB714 0x00000000 +_L 0x202B9018 0x00000000 +_L 0x203BC09C 0x00000000 +_C0 30FPS [Fixed] +_L 0xE0050000 0x00440664 +_L 0x20440664 0x00000002//value +_L 0x202B8A14 0x00000000 +_L 0x203BB714 0x00000000 +_L 0x202B9018 0x00000000 +_L 0x203BC09C 0x00000000 +_C0 30/60FPS [Default] +_L 0xE0040000 0x002B8A14 +_L 0x202B8A14 0xAC930664//30 +_L 0x203BB714 0xAC860664//30 +_L 0x202B9018 0xAC800664//60 +_L 0x203BC09C 0xAC800664//60 +_S ULUS-10345 +_G Star Wars - The Force Unleashed [USA] +_C0 Red overlay FIX +_L 0xE001ADAE 0x003E94BE +_L 0x203E94BC 0xADA00000 +_C0 Red overlay NO-FIX [Default] +_L 0xE001ADA0 0x003E94BE +_L 0x203E94BC 0xADAE0000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10390.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10390.ini new file mode 100644 index 000000000..ea9aa6c92 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10390.ini @@ -0,0 +1,12 @@ +_S ULUS-10390 +_G Star Wars Battlefront - Elite Squadron [USA] +_C0 60 FPS +_L 0x20456598 0x42700000 +_C0 45 FPS +_L 0x20456598 0x42340000 +_C0 40 FPS +_L 0x20456598 0x42200000 +_C0 30 FPS +_L 0x20456598 0x41F00000 +_C0 20 FPS [Default] +_L 0x20456598 0x41A00000 \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10507.ini b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10507.ini new file mode 100644 index 000000000..30770423e --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/config/PSP/Cheats/ULUS10507.ini @@ -0,0 +1,6 @@ +_S ULUS-10507 +_G Toy Story 3 [USA] +_C1 60 FPS +_L 0x202E77CC 0x00000000 +_C0 30 FPS [Default] +_L 0x202E77CC 0x1080FFFB \ No newline at end of file diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache b/packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/UCAS40015.glshadercache new file mode 100644 index 0000000000000000000000000000000000000000..af57dc95496182dbc76a4635b55f455497402bf1 GIT binary patch literal 1956 zcmY*aO>UDh5FLL7DWw86hzh70lz4;6jtle(RDjfzbYB7|$O+PKjlMOb^Ow4%gRab-(3C-LJS#e`9~PrT@BrpnTXB z>J#`h*phz{A7iu@x4Iriojq`6ejaBCf5UFo;{IE5zaFp_&*KO2r{uz!7p;AY zdgOj!*-1_O6c$hAPwzljJQR<_XYr%gM?J-B)m2#c-Ny&77pKUi6t5%y35!1+X3E04 z=O?`7zRoY6_89ej!i@*&1LBq5J@|)_IPP8VRqscAK|D`=w?{oPzu-mU;Enu=U$O^3 zF|vN*DWyIIfAao_#TxFDZ|W=R7svYE6TQ!%zbQU2`kHW_FV3U>q%^Xg5xU1m^^SL} z^Xq*mzUry-t55V8@2khiLHWu)<41x$KFTNhm+GOumHwh%$zFX@`s#byN8iQh@lm|& zJ5A4L@?HAs*NI&L{1L``?6LY`@+11TzEA2)%2$0dar7biSKrO-qF*I{0_!{H?~|&+ UdXIUZQ9odO-)dle|J1Ml1Et@NJ^%m! literal 0 HcmV?d00001 diff --git a/packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache b/packages/games/emulators/PPSSPPSDL/config/PSP/SYSTEM/CACHE/ULJM05600.glshadercache new file mode 100644 index 0000000000000000000000000000000000000000..411b76175da820f96301a07a692915e7eb705d22 GIT binary patch literal 172 zcmbPKs@}}Uz`!82Mj{+YF|a@}E0E>_2><~Tgklha(o#^G;R1-k$e_f~02W~clR)AE cgay+N6Nl-8sfU>d literal 0 HcmV?d00001 diff --git a/packages/games/emulators/PPSSPPSDL/package.mk b/packages/games/emulators/PPSSPPSDL/package.mk new file mode 100644 index 000000000..17a4f8c7f --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/package.mk @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="PPSSPPSDL" +PKG_VERSION="748eef05d0c64b7aa5be6714fa52fa84a5977f05" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/hrydgard/ppsspp" +PKG_URL="https://github.com/hrydgard/ppsspp.git" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} ffmpeg libzip SDL2 zlib zip" +PKG_SHORTDESC="PPSSPPDL" +PKG_LONGDESC="PPSSPP Standalone" +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="+lto" + +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_CMAKE_OPTS_TARGET+="-DUSE_SYSTEM_FFMPEG=OFF \ + -DUSE_WAYLAND_WSI=OFF \ + -DUSE_VULKAN_DISPLAY_KHR=OFF \ + -DUSING_FBDEV=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DUSING_EGL=OFF \ + -DUSING_GLES2=ON \ + -DVULKAN=OFF \ + -DARM_NO_VULKAN=ON \ + -DUSING_X11_VULKAN=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DANDROID=OFF \ + -DWIN32=OFF \ + -DAPPLE=OFF \ + -DCMAKE_CROSSCOMPILING=ON \ + -DUSING_QT_UI=OFF \ + -DUNITTEST=OFF \ + -DSIMULATOR=OFF \ + -DHEADLESS=OFF \ + -DUSE_DISCORD=OFF" + +pre_configure_target() { + sed -i "s|include_directories(/usr/include/drm)|include_directories(${SYSROOT_PREFIX}/usr/include/drm)|" $PKG_BUILD/CMakeLists.txt +} + +pre_make_target() { + export CPPFLAGS="${CPPFLAGS} -Wno-error" + export CFLAGS="${CFLAGS} -Wno-error" + + # fix cross compiling + find ${PKG_BUILD} -name flags.make -exec sed -i "s:isystem :I:g" \{} \; + find ${PKG_BUILD} -name build.ninja -exec sed -i "s:isystem :I:g" \{} \; +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/ppsspp.sh ${INSTALL}/usr/bin/ppsspp.sh + cp `find . -name "PPSSPPSDL" | xargs echo` ${INSTALL}/usr/bin/PPSSPPSDL + ln -sf /storage/.config/ppsspp/assets ${INSTALL}/usr/bin/assets + mkdir -p ${INSTALL}/usr/config/ppsspp/PSP/SYSTEM + cp -r `find . -name "assets" | xargs echo` ${INSTALL}/usr/config/ppsspp/ + cp -rf ${PKG_DIR}/config/* ${INSTALL}/usr/config/ppsspp/ + if [ "${DEVICE}" == "RG552" ] + then + cp ${PKG_DIR}/sources/RG552/* ${INSTALL}/usr/config/ppsspp/PSP/SYSTEM + elif [[ "${DEVICE}" =~ RG351 ]] + then + cp ${PKG_DIR}/sources/RG351/* ${INSTALL}/usr/config/ppsspp/PSP/SYSTEM + fi + rm ${INSTALL}/usr/config/ppsspp/assets/gamecontrollerdb.txt +} diff --git a/packages/games/emulators/PPSSPPSDL/patches/000-disable-mouse.patch b/packages/games/emulators/PPSSPPSDL/patches/000-disable-mouse.patch new file mode 100644 index 000000000..c6c8c88b3 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/patches/000-disable-mouse.patch @@ -0,0 +1,46 @@ +diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp +index 85b4982..4aae124 100644 +--- a/SDL/SDLMain.cpp ++++ b/SDL/SDLMain.cpp +@@ -533,9 +533,7 @@ int main(int argc, char *argv[]) { + printf("Init from thread error: '%s'\n", error_message.c_str()); + } + +-#ifdef MOBILE_DEVICE + SDL_ShowCursor(SDL_DISABLE); +-#endif + + if (!useEmuThread) { + NativeInitGraphics(graphicsContext); +@@ -608,14 +606,7 @@ int main(int argc, char *argv[]) { + } + + // Set variable here in case fullscreen was toggled by hotkey +- g_Config.bFullScreen = fullscreen; +- +- // Hide/Show cursor correctly toggling fullscreen +- if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { +- SDL_ShowCursor(SDL_DISABLE); +- } else if (lastUIState != UISTATE_INGAME || !fullscreen) { +- SDL_ShowCursor(SDL_ENABLE); +- } ++ g_Config.bFullScreen = fullscreen; + break; + } + +@@ -754,15 +745,6 @@ int main(int argc, char *argv[]) { + } + if (g_QuitRequested) + break; +-#if !defined(MOBILE_DEVICE) +- if (lastUIState != GetUIState()) { +- lastUIState = GetUIState(); +- if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) +- SDL_ShowCursor(SDL_DISABLE); +- if (lastUIState != UISTATE_INGAME || !g_Config.bFullScreen) +- SDL_ShowCursor(SDL_ENABLE); +- } +-#endif + + if (framecount % 60 == 0) { + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. diff --git a/packages/games/emulators/PPSSPPSDL/patches/006-fix-window-size.patch b/packages/games/emulators/PPSSPPSDL/patches/006-fix-window-size.patch new file mode 100644 index 000000000..dec4c2aff --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/patches/006-fix-window-size.patch @@ -0,0 +1,22 @@ +Binary files PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab.orig/.git/index and PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab/.git/index differ +diff -rupN PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab.orig/SDL/SDLMain.cpp PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab/SDL/SDLMain.cpp +--- PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab.orig/SDL/SDLMain.cpp 2020-11-23 11:24:47.893402871 -0500 ++++ PPSSPPSDL-087de849bdc74205dd00d8e6e11ba17a591213ab/SDL/SDLMain.cpp 2020-11-28 09:39:23.004618567 -0500 +@@ -581,13 +581,13 @@ int main(int argc, char *argv[]) { + #endif + + if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { +- pixel_xres = g_DesktopWidth; +- pixel_yres = g_DesktopHeight; ++ pixel_xres = 480; ++ pixel_yres = 320; + g_Config.bFullScreen = true; + } else { + // set a sensible default resolution (2x) +- pixel_xres = 480 * 2 * set_scale; +- pixel_yres = 272 * 2 * set_scale; ++ pixel_xres = 480; ++ pixel_yres = 320; + if (portrait) { + std::swap(pixel_xres, pixel_yres); + } diff --git a/packages/games/emulators/PPSSPPSDL/patches/008-exit-to-jelOS.patch b/packages/games/emulators/PPSSPPSDL/patches/008-exit-to-jelOS.patch new file mode 100644 index 000000000..c0ec52e62 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/patches/008-exit-to-jelOS.patch @@ -0,0 +1,55 @@ +MRFIXIT: Add the option to exit the emulator completely from the pause screen +Fewtarius: Update for 351ELEC +--- a/UI/PauseScreen.h ++++ b/UI/PauseScreen.h +@@ -40,6 +40,7 @@ + private: + UI::EventReturn OnGameSettings(UI::EventParams &e); + UI::EventReturn OnExitToMenu(UI::EventParams &e); ++ UI::EventReturn OnExitToBatocera(UI::EventParams &e); + UI::EventReturn OnReportFeedback(UI::EventParams &e); + + UI::EventReturn OnRewind(UI::EventParams &e); +--- a/UI/PauseScreen.cpp ++++ b/UI/PauseScreen.cpp +@@ -386,6 +386,8 @@ + rightColumnItems->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &GamePauseScreen::OnExitToMenu); + } else { + rightColumnItems->Add(new Choice(pa->T("Exit to menu")))->OnClick.Handle(this, &GamePauseScreen::OnExitToMenu); ++ rightColumnItems->Add(new Spacer(25.0)); ++ rightColumnItems->Add(new Choice(pa->T("Exit to JELOS")))->OnClick.Handle(this, &GamePauseScreen::OnExitToBatocera); + } + } + +@@ -437,6 +439,31 @@ + return UI::EVENT_DONE; + } + ++UI::EventReturn GamePauseScreen::OnExitToBatocera(UI::EventParams &e) { ++ if (g_Config.bPauseMenuExitsEmulator) { ++ System_SendMessage("finish", ""); ++ } else { ++ TriggerFinish(DR_OK); ++ } ++ ++ System_SendMessage("event", "exitprogram"); ++ ++ // Request the framework to exit cleanly. ++ System_SendMessage("finish", ""); ++ ++ // However, let's make sure the config was saved, since it may not have been. ++ g_Config.Save("MainScreen::OnExit"); ++ ++#ifdef __ANDROID__ ++#ifdef ANDROID_NDK_PROFILER ++ moncleanup(); ++#endif ++#endif ++ ++ UpdateUIState(UISTATE_EXIT); ++ return UI::EVENT_DONE; ++} ++ + UI::EventReturn GamePauseScreen::OnReportFeedback(UI::EventParams &e) { + screenManager()->push(new ReportScreen(gamePath_)); + return UI::EVENT_DONE; diff --git a/packages/games/emulators/PPSSPPSDL/patches/ppsspp-patch-005-build-flag.patch b/packages/games/emulators/PPSSPPSDL/patches/ppsspp-patch-005-build-flag.patch new file mode 100644 index 000000000..9adadf09c --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/patches/ppsspp-patch-005-build-flag.patch @@ -0,0 +1,18 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d43497e2c..11ac4fce8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -302,11 +302,11 @@ if(NOT MSVC) + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -D_DEBUG") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -Os -D_NDEBUG") +- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -D_NDEBUG") ++ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -fno-tree-slp-vectorize -D_NDEBUG") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O2 -g -D_NDEBUG") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -D_DEBUG") + set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -Os -D_NDEBUG") +- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 -D_NDEBUG") ++ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -fno-tree-slp-vectorize -D_NDEBUG") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O2 -g -D_NDEBUG") + + # Disable some warnings diff --git a/packages/games/emulators/PPSSPPSDL/ppsspp.sh b/packages/games/emulators/PPSSPPSDL/ppsspp.sh new file mode 100755 index 000000000..2bd06df2b --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/ppsspp.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present - Fewtarius + +. /etc/profile + +ARG=${1//[\\]/} +export SDL_AUDIODRIVER=alsa +${FAST_CORES} PPSSPPSDL "$ARG" diff --git a/packages/games/emulators/PPSSPPSDL/sources/RG351/controls.ini b/packages/games/emulators/PPSSPPSDL/sources/RG351/controls.ini new file mode 100644 index 000000000..3ec5b0b7e --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/sources/RG351/controls.ini @@ -0,0 +1,23 @@ +[ControlMapping] +Up = 1-19,10-19 +Down = 1-20,10-20 +Left = 1-21,10-21 +Right = 1-22,10-22 +Circle = 1-52,10-190,10-4004 +Cross = 1-54,10-189,10-4006 +Square = 1-29,10-191,10-4005 +Triangle = 1-47,10-188,10-4007 +Start = 1-62,10-197 +Select = 1-66,10-196 +L = 1-45,10-192 +R = 1-51,10-193 +An.Up = 1-37,10-4002 +An.Down = 1-39,10-4003 +An.Left = 1-38,10-4001 +An.Right = 1-40,10-4000 +Analog limiter = 1-60 +RapidFire = 1-59 +Unthrottle = 1-61 +SpeedToggle = 1-68 +Rewind = 1-67 +Pause = 1-111 diff --git a/packages/games/emulators/PPSSPPSDL/sources/RG351/ppsspp.ini b/packages/games/emulators/PPSSPPSDL/sources/RG351/ppsspp.ini new file mode 100644 index 000000000..1d4d699f5 --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/sources/RG351/ppsspp.ini @@ -0,0 +1,424 @@ +[General] +FirstRun = False +RunCount = 1 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = True +Language = en_US +ForceLagSync = False +DiscordPresence = False +NumWorkerThreads = 8 +AutoLoadSaveState = 0 +EnableCheats = True +CwCheatRefreshRate = 77 +ScreenshotsAsPNG = False +UseFFV1 = False +DumpFrames = False +DumpAudio = False +SaveLoadResetsAVdumping = False +StateSlot = 0 +EnableStateUndo = True +RewindFlipFrequency = 0 +GridView1 = True +GridView2 = True +GridView3 = False +ComboMode = 0 +ReportingHost = default +AutoSaveSymbolMap = False +CacheFullIsoInRam = False +RemoteISOPort = 0 +LastRemoteISOServer = +LastRemoteISOPort = 0 +RemoteISOManualConfig = False +RemoteShareOnStartup = False +RemoteISOSubdir = / +RemoteDebuggerOnStartup = False +InternalScreenRotation = 1 +PauseWhenMinimized = False +DumpDecryptedEboots = False +MemStickInserted = True +ForceLagSync2 = False +UISound = True +CwCheatScrollPosition = 0.000000 +DumpVideoOutput = False +ShowRegionOnGameIcon = False +ShowIDOnGameIcon = False +GameGridScale = 1.000000 +RightAnalogUp = 0 +RightAnalogDown = 0 +RightAnalogLeft = 0 +RightAnalogRight = 0 +RightAnalogPress = 0 +RightAnalogCustom = False +LoadPlugins = False +[CPU] +CPUCore = 1 +SeparateSASThread = True +SeparateIOThread = True +IOTimingMethod = 0 +FastMemoryAccess = True +FuncReplacements = True +HideSlowWarnings = False +HideStateWarnings = False +PreloadFunctions = False +CPUSpeed = 333 +JitDisableFlags = 0x00000000 +[Graphics] +EnableCardboard = False +CardboardScreenSize = 50 +CardboardXShift = 0 +CardboardYShift = 0 +ShowFPSCounter = 2 +GraphicsBackend = 0 (OPENGL) +FailedGraphicsBackends = +VulkanDevice = +RenderingMode = 0 +SoftwareRenderer = False +HardwareTransform = True +SoftwareSkinning = True +TextureFiltering = 1 +BufferFiltering = 1 +InternalResolution = 0 +AndroidHwScale = 1 +HighQualityDepth = 1 +FrameSkip = 0 +FrameSkipType = 1 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 60 +AnisotropyLevel = 0 +VertexDecCache = True +TextureBackoffCache = True +TextureSecondaryCache = False +FullScreen = True +FullScreenMulti = False +SmallDisplayZoomType = 2 +SmallDisplayOffsetX = 0.500000 +SmallDisplayOffsetY = 0.500000 +SmallDisplayZoomLevel = 1.000000 +ImmersiveMode = False +SustainedPerformanceMode = False +TrueColor = True +ReplaceTextures = True +SaveNewTextures = False +IgnoreTextureFilenames = True +TexScalingLevel = 1 +TexScalingType = 3 +TexDeposterize = False +VSyncInterval = True +DisableStencilTest = False +BloomHack = 2 +TimerHack = False +SplineBezierQuality = 0 +HardwareTessellation = False +PostShader = Off +MemBlockTransferGPU = True +DisableSlowFramebufEffects = True +FragmentTestCache = True +LogFrameDrops = False +EnableCardboardVR = False +DisabledGraphicsBackends = +CameraDevice = +UnthrottleMode = CONTINUOUS +IgnoreScreenInsets = True +TexHardwareScaling = False +TextureShader = Off +InflightFrames = 2 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AudioDevice = +AutoAudioDevice = False +[Control] +HapticFeedback = False +ShowTouchCross = True +ShowTouchCircle = True +ShowTouchSquare = True +ShowTouchTriangle = True +ComboKey0Mapping = 0 +ComboKey1Mapping = 0 +ComboKey2Mapping = 0 +ComboKey3Mapping = 0 +ComboKey4Mapping = 0 +ShowTouchPause = False +ShowTouchControls = False +DisableDpadDiagonals = False +GamepadOnlyFocused = False +TouchButtonStyle = 1 +TouchButtonOpacity = 65 +TouchButtonHideSeconds = 20 +AutoCenterTouchAnalog = False +ActionButtonSpacing2 = 1.000000 +ActionButtonCenterX = 0.937500 +ActionButtonCenterY = 0.900000 +ActionButtonScale = 1.150000 +DPadX = 0.074479 +DPadY = 0.760000 +DPadScale = 1.150000 +ShowTouchDpad = True +DPadSpacing = 1.000000 +StartKeyX = 0.559896 +StartKeyY = 0.942500 +StartKeyScale = 1.150000 +ShowTouchStart = True +SelectKeyX = 0.500000 +SelectKeyY = 0.942500 +SelectKeyScale = 1.150000 +ShowTouchSelect = True +UnthrottleKeyX = 0.440104 +UnthrottleKeyY = 0.942500 +UnthrottleKeyScale = 1.150000 +ShowTouchUnthrottle = True +LKeyX = 0.035937 +LKeyY = 0.635833 +LKeyScale = 1.150000 +ShowTouchLTrigger = True +RKeyX = 0.964063 +RKeyY = 0.635833 +RKeyScale = 1.150000 +ShowTouchRTrigger = True +AnalogStickX = 0.074479 +AnalogStickY = 0.923333 +AnalogStickScale = 1.150000 +ShowAnalogStick = True +fcombo0X = 0.571875 +fcombo0Y = 0.500000 +comboKeyScale0 = 1.150000 +ShowComboKey0 = False +fcombo1X = 0.631771 +fcombo1Y = 0.500000 +comboKeyScale1 = 1.150000 +ShowComboKey1 = False +fcombo2X = 0.691667 +fcombo2Y = 0.500000 +comboKeyScale2 = 1.150000 +ShowComboKey2 = False +fcombo3X = 0.571875 +fcombo3Y = 0.333333 +comboKeyScale3 = 1.150000 +ShowComboKey3 = False +fcombo4X = 0.631771 +fcombo4Y = 0.333333 +comboKeyScale4 = 1.150000 +ShowComboKey4 = False +Speed1KeyX = 0.440104 +Speed1KeyY = 0.885000 +Speed1KeyScale = 1.150000 +ShowSpeed1Key = False +Speed2KeyX = 0.500000 +Speed2KeyY = 0.885000 +Speed2KeyScale = 1.150000 +ShowSpeed2Key = False +XInputAnalogSensitivity = 1.000000 +AnalogLimiterDeadzone = 0.600000 +UseMouse = False +MapMouse = False +ConfineMap = False +MouseSensitivity = 0.100000 +MouseSmoothing = 0.900000 +ComboKey0Toggle = False +ComboKey1Toggle = False +ComboKey2Toggle = False +ComboKey3Toggle = False +ComboKey4Toggle = False +AnalogAutoRotSpeed = 15.000000 +TouchSnapToGrid = False +TouchSnapGridSize = 64 +RightAnalogStickX = 0.875000 +RightAnalogStickY = 0.856250 +RightAnalogStickScale = 1.150000 +ShowRightAnalogStick = False +RapidFireKeyX = 0.619792 +RapidFireKeyY = 0.784375 +RapidFireKeyScale = 1.150000 +ShowRapidFireKey = False +AnalogRotationCWKeyX = 0.500000 +AnalogRotationKeyCWY = 0.676562 +AnalogRotationKeyCWScale = 1.150000 +ShowAnalogRotationCWKey = False +AnalogRotationCCWKeyX = 0.380208 +AnalogRotationKeyCCWY = 0.676562 +AnalogRotationKeyCCWScale = 1.150000 +ShowAnalogRotationCCWKey = False +[Network] +EnableWlan = False +EnableAdhocServer = False +proAdhocServer = myneighborsushicat.com +PortOffset = 0 +MinTimeout = 1 +TCPNoDelay = False +EnableUPnP = False +UPnPUseOriginalPort = True +EnableNetworkChat = False +ChatButtonPosition = 0 +ChatScreenPosition = 0 +EnableQuickChat = True +QuickChat1 = Quick Chat 1 +QuickChat2 = Quick Chat 2 +QuickChat3 = Quick Chat 3 +QuickChat4 = Quick Chat 4 +QuickChat5 = Quick Chat 5 +ForcedFirstConnect = False +[SystemParam] +PSPModel = 0 +PSPFirmwareVersion = 660 +NickName = PPSSPP +proAdhocServer = black-seraph.com +MacAddress = 4e:7a:78:d9:49:32 +PortOffset = 0 +Language = 1 +TimeFormat = 1 +DateFormat = 1 +TimeZone = 0 +DayLightSavings = False +ButtonPreference = 1 +LockParentalLevel = 0 +WlanAdhocChannel = 0 +WlanPowerSave = False +EncryptSave = True +SavedataUpgradeVersion = True +ParamTimeFormat = 0 +ParamDateFormat = 0 +MemStickSize = 16 +[Debugger] +DisasmWindowX = -1 +DisasmWindowY = -1 +DisasmWindowW = -1 +DisasmWindowH = -1 +GEWindowX = -1 +GEWindowY = -1 +GEWindowW = -1 +GEWindowH = -1 +ConsoleWindowX = -1 +ConsoleWindowY = -1 +FontWidth = 8 +FontHeight = 12 +DisplayStatusBar = True +ShowBottomTabTitles = True +ShowDeveloperMenu = False +SkipDeadbeefFilling = False +FuncHashMap = False +DrawFrameGraph = False +[Upgrade] +UpgradeMessage = +UpgradeVersion = +DismissedVersion = +[Theme] +ItemStyleFg = 0xffffffff +ItemStyleBg = 0x55000000 +ItemFocusedStyleFg = 0xffffffff +ItemFocusedStyleBg = 0xffedc24c +ItemDownStyleFg = 0xffffffff +ItemDownStyleBg = 0xffbd9939 +ItemDisabledStyleFg = 0x80eeeeee +ItemDisabledStyleBg = 0x55e0d4af +ItemHighlightedStyleFg = 0xffffffff +ItemHighlightedStyleBg = 0x55bdbb39 +ButtonStyleFg = 0xffffffff +ButtonStyleBg = 0x55000000 +ButtonFocusedStyleFg = 0xffffffff +ButtonFocusedStyleBg = 0xffedc24c +ButtonDownStyleFg = 0xffffffff +ButtonDownStyleBg = 0xffbd9939 +ButtonDisabledStyleFg = 0x80eeeeee +ButtonDisabledStyleBg = 0x55e0d4af +ButtonHighlightedStyleFg = 0xffffffff +ButtonHighlightedStyleBg = 0x55bdbb39 +HeaderStyleFg = 0xffffffff +InfoStyleFg = 0xffffffff +InfoStyleBg = 0x00000000 +PopupTitleStyleFg = 0xffe3be59 +PopupStyleFg = 0xffffffff +PopupStyleBg = 0xff303030 +[Recent] +MaxRecent = 30 +FileName0 = /storage/roms/psp/Ultimate Ghosts n Goblins.cso +[Log] +SYSTEMEnabled = True +SYSTEMLevel = 4 +BOOTEnabled = True +BOOTLevel = 4 +COMMONEnabled = True +COMMONLevel = 4 +CPUEnabled = True +CPULevel = 4 +FILESYSEnabled = True +FILESYSLevel = 4 +G3DEnabled = True +G3DLevel = 4 +HLEEnabled = True +HLELevel = 4 +JITEnabled = True +JITLevel = 4 +LOADEREnabled = True +LOADERLevel = 4 +MEEnabled = True +MELevel = 4 +MEMMAPEnabled = True +MEMMAPLevel = 4 +SASMIXEnabled = True +SASMIXLevel = 4 +SAVESTATEEnabled = True +SAVESTATELevel = 4 +FRAMEBUFEnabled = True +FRAMEBUFLevel = 4 +SCEAUDIOEnabled = True +SCEAUDIOLevel = 4 +SCECTRLEnabled = True +SCECTRLLevel = 4 +SCEDISPEnabled = True +SCEDISPLevel = 4 +SCEFONTEnabled = True +SCEFONTLevel = 4 +SCEGEEnabled = True +SCEGELevel = 4 +SCEINTCEnabled = True +SCEINTCLevel = 4 +SCEIOEnabled = True +SCEIOLevel = 4 +SCEKERNELEnabled = True +SCEKERNELLevel = 4 +SCEMODULEEnabled = True +SCEMODULELevel = 4 +SCENETEnabled = True +SCENETLevel = 4 +SCERTCEnabled = True +SCERTCLevel = 4 +SCESASEnabled = True +SCESASLevel = 4 +SCEUTILEnabled = True +SCEUTILLevel = 4 +SCEMISCEnabled = True +SCEMISCLevel = 4 +AUDIOEnabled = True +AUDIOLevel = 2 +IOEnabled = True +IOLevel = 2 +[PostShaderSetting] +BloomSettingValue1 = 0.600000 +BloomSettingValue2 = 0.500000 +CartoonSettingValue1 = 0.500000 +ColorCorrectionSettingValue1 = 1.000000 +ColorCorrectionSettingValue2 = 1.000000 +ColorCorrectionSettingValue3 = 1.000000 +ColorCorrectionSettingValue4 = 1.000000 +ScanlinesSettingValue1 = 1.000000 +ScanlinesSettingValue2 = 0.500000 +SharpenSettingValue1 = 1.500000 +[PostShaderList] +PostShader1 = Off diff --git a/packages/games/emulators/PPSSPPSDL/sources/RG552/controls.ini b/packages/games/emulators/PPSSPPSDL/sources/RG552/controls.ini new file mode 100644 index 000000000..56447cebb --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/sources/RG552/controls.ini @@ -0,0 +1,18 @@ +[ControlMapping] +Up = 10-19 +Down = 10-20 +Left = 10-21 +Right = 10-22 +Circle = 10-189,10-4004 +Cross = 10-190,10-4006 +Square = 10-188,10-4005 +Triangle = 10-191,10-4007 +Start = 10-197 +Select = 10-196 +L = 10-193 +R = 10-192 +An.Up = 10-4003 +An.Down = 10-4002 +An.Left = 10-4001 +An.Right = 10-4000 +Pause = 10-107 diff --git a/packages/games/emulators/PPSSPPSDL/sources/RG552/ppsspp.ini b/packages/games/emulators/PPSSPPSDL/sources/RG552/ppsspp.ini new file mode 100755 index 000000000..bdb38298b --- /dev/null +++ b/packages/games/emulators/PPSSPPSDL/sources/RG552/ppsspp.ini @@ -0,0 +1,512 @@ +[General] +FirstRun = False +RunCount = 16 +Enable Logging = False +AutoRun = True +Browse = False +IgnoreBadMemAccess = False +CurrentDirectory = /storage/roms/psp +ShowDebuggerOnLoad = False +CheckForNewVersion = True +Language = en_US +ForceLagSync = False +DiscordPresence = False +NumWorkerThreads = 8 +AutoLoadSaveState = 0 +EnableCheats = True +CwCheatRefreshRate = 77 +ScreenshotsAsPNG = False +UseFFV1 = False +DumpFrames = False +DumpAudio = False +SaveLoadResetsAVdumping = False +StateSlot = 0 +EnableStateUndo = True +RewindFlipFrequency = 0 +GridView1 = True +GridView2 = True +GridView3 = False +ComboMode = 0 +ReportingHost = default +AutoSaveSymbolMap = False +CacheFullIsoInRam = False +RemoteISOPort = 0 +LastRemoteISOServer = +LastRemoteISOPort = 0 +RemoteISOManualConfig = False +RemoteShareOnStartup = False +RemoteISOSubdir = / +RemoteDebuggerOnStartup = False +InternalScreenRotation = 1 +PauseWhenMinimized = False +DumpDecryptedEboots = False +MemStickInserted = True +ForceLagSync2 = False +UISound = True +CwCheatScrollPosition = 0.000000 +DumpVideoOutput = False +ShowRegionOnGameIcon = False +ShowIDOnGameIcon = False +GameGridScale = 1.000000 +RightAnalogUp = 0 +RightAnalogDown = 0 +RightAnalogLeft = 0 +RightAnalogRight = 0 +RightAnalogPress = 0 +RightAnalogCustom = False +LoadPlugins = False +GameListScrollPosition = 0.000000 +StateLoadUndoGame = NA +StateUndoLastSaveGame = NA +StateUndoLastSaveSlot = -5 +ShowOnScreenMessage = True +RightAnalogDisableDiagonal = False +SwipeUp = 0 +SwipeDown = 0 +SwipeLeft = 0 +SwipeRight = 0 +SwipeSensitivity = 1.000000 +SwipeSmoothing = 0.300000 +DoubleTapGesture = 0 +GestureControlEnabled = False +BackgroundAnimation = 1 +EnablePlugins = True +[CPU] +CPUCore = 1 +SeparateSASThread = True +SeparateIOThread = True +IOTimingMethod = 0 +FastMemoryAccess = True +FuncReplacements = True +HideSlowWarnings = False +HideStateWarnings = False +PreloadFunctions = False +CPUSpeed = 0 +JitDisableFlags = 0x00000000 +FunctionReplacements = True +[Graphics] +EnableCardboard = False +CardboardScreenSize = 50 +CardboardXShift = 0 +CardboardYShift = 0 +ShowFPSCounter = 3 +GraphicsBackend = 0 (OPENGL) +FailedGraphicsBackends = +VulkanDevice = +RenderingMode = 0 +SoftwareRenderer = False +HardwareTransform = True +SoftwareSkinning = True +TextureFiltering = 1 +BufferFiltering = 1 +InternalResolution = 0 +AndroidHwScale = 1 +HighQualityDepth = 1 +FrameSkip = 1 +FrameSkipType = 0 +AutoFrameSkip = False +FrameRate = 0 +FrameRate2 = -1 +FrameSkipUnthrottle = True +ForceMaxEmulatedFPS = 60 +AnisotropyLevel = 0 +VertexDecCache = True +TextureBackoffCache = True +TextureSecondaryCache = False +FullScreen = True +FullScreenMulti = False +SmallDisplayZoomType = 2 +SmallDisplayOffsetX = 0.500000 +SmallDisplayOffsetY = 0.500000 +SmallDisplayZoomLevel = 1.000000 +ImmersiveMode = False +SustainedPerformanceMode = False +TrueColor = True +ReplaceTextures = True +SaveNewTextures = False +IgnoreTextureFilenames = True +TexScalingLevel = 1 +TexScalingType = 3 +TexDeposterize = False +VSyncInterval = True +DisableStencilTest = False +BloomHack = 2 +TimerHack = False +SplineBezierQuality = 0 +HardwareTessellation = False +PostShader = Off +MemBlockTransferGPU = True +DisableSlowFramebufEffects = True +FragmentTestCache = True +LogFrameDrops = False +EnableCardboardVR = False +DisabledGraphicsBackends = +CameraDevice = +UnthrottleMode = CONTINUOUS +IgnoreScreenInsets = True +TexHardwareScaling = False +TextureShader = Off +InflightFrames = 2 +RenderDuplicateFrames = True +ShaderChainRequires60FPS = False +ClearFramebuffersOnFirstUseHack = False +SoftwareRendererJit = True +UnthrottlingMode = CONTINUOUS +ReplaceTexturesAllowLate = True +[Sound] +Enable = True +AudioBackend = 0 +AudioLatency = 1 +ExtraAudioBuffering = False +SoundSpeedHack = False +AudioResampler = False +GlobalVolume = 10 +AltSpeedVolume = -1 +AudioDevice = es8316, ff890000.i2s-ES8316 HiFi ES8316 HiFi-0 +AutoAudioDevice = False +ReverbVolume = 10 +[Control] +HapticFeedback = False +ShowTouchCross = True +ShowTouchCircle = True +ShowTouchSquare = True +ShowTouchTriangle = True +ComboKey0Mapping = 0 +ComboKey1Mapping = 0 +ComboKey2Mapping = 0 +ComboKey3Mapping = 0 +ComboKey4Mapping = 0 +ShowTouchPause = False +ShowTouchControls = False +DisableDpadDiagonals = False +GamepadOnlyFocused = False +TouchButtonStyle = 1 +TouchButtonOpacity = 65 +TouchButtonHideSeconds = 20 +AutoCenterTouchAnalog = False +ActionButtonSpacing2 = 1.000000 +ActionButtonCenterX = 0.937500 +ActionButtonCenterY = 0.900000 +ActionButtonScale = 1.150000 +DPadX = 0.074479 +DPadY = 0.760000 +DPadScale = 1.150000 +ShowTouchDpad = True +DPadSpacing = 1.000000 +StartKeyX = 0.559896 +StartKeyY = 0.942500 +StartKeyScale = 1.150000 +ShowTouchStart = True +SelectKeyX = 0.500000 +SelectKeyY = 0.942500 +SelectKeyScale = 1.150000 +ShowTouchSelect = True +UnthrottleKeyX = 0.440104 +UnthrottleKeyY = 0.942500 +UnthrottleKeyScale = 1.150000 +ShowTouchUnthrottle = True +LKeyX = 0.035937 +LKeyY = 0.635833 +LKeyScale = 1.150000 +ShowTouchLTrigger = True +RKeyX = 0.964063 +RKeyY = 0.635833 +RKeyScale = 1.150000 +ShowTouchRTrigger = True +AnalogStickX = 0.074479 +AnalogStickY = 0.923333 +AnalogStickScale = 1.150000 +ShowAnalogStick = True +fcombo0X = 0.571875 +fcombo0Y = 0.500000 +comboKeyScale0 = 1.150000 +ShowComboKey0 = False +fcombo1X = 0.631771 +fcombo1Y = 0.500000 +comboKeyScale1 = 1.150000 +ShowComboKey1 = False +fcombo2X = 0.691667 +fcombo2Y = 0.500000 +comboKeyScale2 = 1.150000 +ShowComboKey2 = False +fcombo3X = 0.571875 +fcombo3Y = 0.333333 +comboKeyScale3 = 1.150000 +ShowComboKey3 = False +fcombo4X = 0.631771 +fcombo4Y = 0.333333 +comboKeyScale4 = 1.150000 +ShowComboKey4 = False +Speed1KeyX = 0.440104 +Speed1KeyY = 0.885000 +Speed1KeyScale = 1.150000 +ShowSpeed1Key = False +Speed2KeyX = 0.500000 +Speed2KeyY = 0.885000 +Speed2KeyScale = 1.150000 +ShowSpeed2Key = False +XInputAnalogSensitivity = 1.000000 +AnalogLimiterDeadzone = 0.600000 +UseMouse = False +MapMouse = False +ConfineMap = False +MouseSensitivity = 0.100000 +MouseSmoothing = 0.900000 +ComboKey0Toggle = False +ComboKey1Toggle = False +ComboKey2Toggle = False +ComboKey3Toggle = False +ComboKey4Toggle = False +AnalogAutoRotSpeed = 15.000000 +TouchSnapToGrid = False +TouchSnapGridSize = 64 +RightAnalogStickX = 0.875000 +RightAnalogStickY = 0.856250 +RightAnalogStickScale = 1.150000 +ShowRightAnalogStick = False +RapidFireKeyX = 0.619792 +RapidFireKeyY = 0.784375 +RapidFireKeyScale = 1.150000 +ShowRapidFireKey = False +AnalogRotationCWKeyX = 0.500000 +AnalogRotationKeyCWY = 0.676562 +AnalogRotationKeyCWScale = 1.150000 +ShowAnalogRotationCWKey = False +AnalogRotationCCWKeyX = 0.380208 +AnalogRotationKeyCCWY = 0.676562 +AnalogRotationKeyCCWScale = 1.150000 +ShowAnalogRotationCCWKey = False +Custom0Mapping = 0x0000000000000000 +Custom0Image = 0 +Custom0Shape = 0 +Custom0Toggle = False +Custom1Mapping = 0x0000000000000000 +Custom1Image = 1 +Custom1Shape = 0 +Custom1Toggle = False +Custom2Mapping = 0x0000000000000000 +Custom2Image = 2 +Custom2Shape = 0 +Custom2Toggle = False +Custom3Mapping = 0x0000000000000000 +Custom3Image = 3 +Custom3Shape = 0 +Custom3Toggle = False +Custom4Mapping = 0x0000000000000000 +Custom4Image = 4 +Custom4Shape = 0 +Custom4Toggle = False +Custom5Mapping = 0x0000000000000000 +Custom5Image = 0 +Custom5Shape = 1 +Custom5Toggle = False +Custom6Mapping = 0x0000000000000000 +Custom6Image = 1 +Custom6Shape = 1 +Custom6Toggle = False +Custom7Mapping = 0x0000000000000000 +Custom7Image = 2 +Custom7Shape = 1 +Custom7Toggle = False +Custom8Mapping = 0x0000000000000000 +Custom8Image = 3 +Custom8Shape = 1 +Custom8Toggle = False +Custom9Mapping = 0x0000000000000000 +Custom9Image = 4 +Custom9Shape = 1 +Custom9Toggle = False +fcombo5X = 0.428125 +fcombo5Y = 0.500000 +comboKeyScale5 = 1.150000 +ShowComboKey5 = False +fcombo6X = 0.368229 +fcombo6Y = 0.500000 +comboKeyScale6 = 1.150000 +ShowComboKey6 = False +fcombo7X = 0.308333 +fcombo7Y = 0.500000 +comboKeyScale7 = 1.150000 +ShowComboKey7 = False +fcombo8X = 0.428125 +fcombo8Y = 0.333333 +comboKeyScale8 = 1.150000 +ShowComboKey8 = False +fcombo9X = 0.368229 +fcombo9Y = 0.333333 +comboKeyScale9 = 1.150000 +ShowComboKey9 = False +AnalogDeadzone = 0.150000 +AnalogInverseDeadzone = 0.000000 +AnalogSensitivity = 1.100000 +AnalogIsCircular = False +LeftStickHeadScale = 1.000000 +RightStickHeadScale = 1.000000 +HideStickBackground = False +SystemControls = True +[Network] +EnableWlan = False +EnableAdhocServer = False +proAdhocServer = myneighborsushicat.com +PortOffset = 0 +MinTimeout = 1 +TCPNoDelay = False +EnableUPnP = False +UPnPUseOriginalPort = True +EnableNetworkChat = False +ChatButtonPosition = 0 +ChatScreenPosition = 0 +EnableQuickChat = True +QuickChat1 = Quick Chat 1 +QuickChat2 = Quick Chat 2 +QuickChat3 = Quick Chat 3 +QuickChat4 = Quick Chat 4 +QuickChat5 = Quick Chat 5 +ForcedFirstConnect = False +[SystemParam] +PSPModel = 0 +PSPFirmwareVersion = 660 +NickName = PPSSPP +proAdhocServer = black-seraph.com +MacAddress = 4e:7a:78:d9:49:32 +PortOffset = 0 +Language = 1 +TimeFormat = 1 +DateFormat = 1 +TimeZone = 0 +DayLightSavings = False +ButtonPreference = 1 +LockParentalLevel = 0 +WlanAdhocChannel = 0 +WlanPowerSave = False +EncryptSave = True +SavedataUpgradeVersion = True +ParamTimeFormat = 0 +ParamDateFormat = 0 +MemStickSize = 16 +[Debugger] +DisasmWindowX = -1 +DisasmWindowY = -1 +DisasmWindowW = -1 +DisasmWindowH = -1 +GEWindowX = -1 +GEWindowY = -1 +GEWindowW = -1 +GEWindowH = -1 +ConsoleWindowX = -1 +ConsoleWindowY = -1 +FontWidth = 8 +FontHeight = 12 +DisplayStatusBar = True +ShowBottomTabTitles = True +ShowDeveloperMenu = False +SkipDeadbeefFilling = False +FuncHashMap = False +DrawFrameGraph = False +MemInfoDetailed = False +[Upgrade] +UpgradeMessage = +UpgradeVersion = 1.12.0 +DismissedVersion = +[Theme] +ItemStyleFg = 0xffffffff +ItemStyleBg = 0x55000000 +ItemFocusedStyleFg = 0xffffffff +ItemFocusedStyleBg = 0xffedc24c +ItemDownStyleFg = 0xffffffff +ItemDownStyleBg = 0xffbd9939 +ItemDisabledStyleFg = 0x80eeeeee +ItemDisabledStyleBg = 0x55e0d4af +ItemHighlightedStyleFg = 0xffffffff +ItemHighlightedStyleBg = 0x55bdbb39 +ButtonStyleFg = 0xffffffff +ButtonStyleBg = 0x55000000 +ButtonFocusedStyleFg = 0xffffffff +ButtonFocusedStyleBg = 0xffedc24c +ButtonDownStyleFg = 0xffffffff +ButtonDownStyleBg = 0xffbd9939 +ButtonDisabledStyleFg = 0x80eeeeee +ButtonDisabledStyleBg = 0x55e0d4af +ButtonHighlightedStyleFg = 0xffffffff +ButtonHighlightedStyleBg = 0x55bdbb39 +HeaderStyleFg = 0xffffffff +InfoStyleFg = 0xffffffff +InfoStyleBg = 0x00000000 +PopupTitleStyleFg = 0xffe3be59 +PopupStyleFg = 0xffffffff +PopupStyleBg = 0xff303030 +[Recent] +MaxRecent = 30 +[Log] +SYSTEMEnabled = True +SYSTEMLevel = 4 +BOOTEnabled = True +BOOTLevel = 4 +COMMONEnabled = True +COMMONLevel = 4 +CPUEnabled = True +CPULevel = 4 +FILESYSEnabled = True +FILESYSLevel = 4 +G3DEnabled = True +G3DLevel = 4 +HLEEnabled = True +HLELevel = 4 +JITEnabled = True +JITLevel = 4 +LOADEREnabled = True +LOADERLevel = 4 +MEEnabled = True +MELevel = 4 +MEMMAPEnabled = True +MEMMAPLevel = 4 +SASMIXEnabled = True +SASMIXLevel = 4 +SAVESTATEEnabled = True +SAVESTATELevel = 4 +FRAMEBUFEnabled = True +FRAMEBUFLevel = 4 +SCEAUDIOEnabled = True +SCEAUDIOLevel = 4 +SCECTRLEnabled = True +SCECTRLLevel = 4 +SCEDISPEnabled = True +SCEDISPLevel = 4 +SCEFONTEnabled = True +SCEFONTLevel = 4 +SCEGEEnabled = True +SCEGELevel = 4 +SCEINTCEnabled = True +SCEINTCLevel = 4 +SCEIOEnabled = True +SCEIOLevel = 4 +SCEKERNELEnabled = True +SCEKERNELLevel = 4 +SCEMODULEEnabled = True +SCEMODULELevel = 4 +SCENETEnabled = True +SCENETLevel = 4 +SCERTCEnabled = True +SCERTCLevel = 4 +SCESASEnabled = True +SCESASLevel = 4 +SCEUTILEnabled = True +SCEUTILLevel = 4 +SCEMISCEnabled = True +SCEMISCLevel = 4 +AUDIOEnabled = True +AUDIOLevel = 2 +IOEnabled = True +IOLevel = 2 +[PostShaderSetting] +BloomSettingValue1 = 0.600000 +BloomSettingValue2 = 0.500000 +CRTSettingValue1 = 1.000000 +CartoonSettingValue1 = 0.500000 +ColorCorrectionSettingValue1 = 1.000000 +ColorCorrectionSettingValue2 = 1.000000 +ColorCorrectionSettingValue3 = 1.000000 +ColorCorrectionSettingValue4 = 1.000000 +ScanlinesSettingValue1 = 1.000000 +ScanlinesSettingValue2 = 0.500000 +SharpenSettingValue1 = 1.500000 diff --git a/packages/games/emulators/advancemame/bin/advmame.sh b/packages/games/emulators/advancemame/bin/advmame.sh new file mode 100644 index 000000000..aca7e1662 --- /dev/null +++ b/packages/games/emulators/advancemame/bin/advmame.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile + +CONFIG_DIR="/storage/.advance" + +if [ ! -d "$CONFIG_DIR" ]; then + mkdir -p $CONFIG_DIR + cp -rf /usr/share/advance/* $CONFIG_DIR/ +fi + +if [ ! -f "$CONFIG_DIR/advmame.rc" ]; then + cp -rf /usr/share/advance/advmame.rc $CONFIG_DIR/ +fi + +if [[ "$1" = *"roms/arcade"* ]]; then + sed -i "s|/roms/mame|/roms/arcade|g" $CONFIG_DIR/advmame.rc +else + sed -i "s|/roms/arcade|/roms/mame|g" $CONFIG_DIR/advmame.rc +fi + +sed -i '/device_video_modeline/d' $CONFIG_DIR/advmame.rc + +ARG=$(echo basename $1 | sed 's/\.[^.]*$//') +ARG="$(echo $1 | sed 's=.*/==;s/\.[^.]*$//')" + +SDL_AUDIODRIVER=alsa nice -n -19 /usr/bin/advmame $ARG -quiet diff --git a/packages/games/emulators/advancemame/config/RG351MP/advmame.rc b/packages/games/emulators/advancemame/config/RG351MP/advmame.rc new file mode 100644 index 000000000..aefd5d7c8 --- /dev/null +++ b/packages/games/emulators/advancemame/config/RG351MP/advmame.rc @@ -0,0 +1,58 @@ +dir_artwork /storage/roms/mame/artwork +dir_diff /storage/roms/mame/diff +dir_hi /storage/roms/mame/hi +dir_image /storage/roms/mame/image +dir_inp /storage/roms/mame/inp +dir_memcard /storage/roms/mame/memcard +dir_nvram /storage/roms/mame/nvram +dir_rom /storage/roms/mame +dir_sample /storage/roms/mame/samples +dir_snap /storage/roms/mame/snap +dir_sta /storage/roms/mame/nvram +device_video sdl +device_keyboard sdl +display_magnifysize 320 +display_resize none +display_resizeeffect none +misc_quiet yes +sound_mode mono +device_alsa_device sdl +device_color_bgr15 no +device_color_bgr8 no +record_sound no +record_video no +sound_latency 0.10 +sound_normalize no +display_vsync no +device_video_clock 10-180 / 30-80 / 50-70 +display_mode 320x224x32 +device_joystick raw +input_map[coin1] joystick_button[gosuper_gamepad,button13] +input_map[start1] joystick_button[gosuper_gamepad,button14] +input_map[ui_cancel] keyboard[0,backspace] or keyboard[1,backspace] or joystick_button[gosuper_gamepad,button16] +input_map[ui_configure] keyboard[1,tab] or keyboard[0,tab] or joystick_button[gosuper_gamepad,button15] +input_map[p1_button1] joystick_button[gosuper_gamepad,button2] +input_map[p1_button2] joystick_button[gosuper_gamepad,button1] +input_map[p1_button3] joystick_button[gosuper_gamepad,button3] +input_map[p1_button4] joystick_button[gosuper_gamepad,button4] +input_map[p1_button5] joystick_button[gosuper_gamepad,button6] +input_map[p1_button6] joystick_button[gosuper_gamepad,button5] +input_map[p1_button7] joystick_button[gosuper_gamepad,button8] +input_map[p1_button8] joystick_button[gosuper_gamepad,button7] +input_map[p1_up] joystick_button[gosuper_gamepad,button9] or joystick_digital[gosuper_gamepad,0,1,1] +input_map[ui_up] joystick_button[gosuper_gamepad,button9] or joystick_digital[gosuper_gamepad,0,1,1] +input_map[p1_down] joystick_button[gosuper_gamepad,button10] or joystick_digital[gosuper_gamepad,0,1,0] +input_map[ui_down] joystick_button[gosuper_gamepad,button10] or joystick_digital[gosuper_gamepad,0,1,0] +input_map[p1_right] joystick_button[gosuper_gamepad,button12] or joystick_digital[gosuper_gamepad,0,0,0] +input_map[ui_right] joystick_button[gosuper_gamepad,button12] or joystick_digital[gosuper_gamepad,0,0,0] +input_map[p1_left] joystick_button[gosuper_gamepad,button11] or joystick_digital[gosuper_gamepad,0,0,1] +input_map[ui_left] joystick_button[gosuper_gamepad,button11] or joystick_digital[gosuper_gamepad,0,0,1] +input_map[ui_select] keyboard[0,enter] or keyboard[1,enter] or joystick_button[gosuper_gamepad,button2] +input_map[p1_doubleright_up] joystick_digital[gosuper_gamepad,0,0,0] joystick_digital[gosuper_gamepad,0,1,1] +input_map[p1_doubleright_down] joystick_digital[gosuper_gamepad,0,1,0] joystick_digital[gosuper_gamepad,0,0,0] +input_map[p1_doubleright_left] joystick_digital[gosuper_gamepad,1,0,1] +input_map[p1_doubleright_right] joystick_digital[gosuper_gamepad,1,0,0] +input_map[p1_doubleleft_up] joystick_digital[gosuper_gamepad,0,1,1] joystick_digital[gosuper_gamepad,0,0,1] +input_map[p1_doubleleft_down] joystick_digital[gosuper_gamepad,0,0,1] joystick_digital[gosuper_gamepad,0,1,0] +input_map[p1_doubleleft_left] joystick_digital[gosuper_gamepad,1,0,1] +input_map[p1_doubleleft_right] joystick_digital[gosuper_gamepad,1,0,0] diff --git a/packages/games/emulators/advancemame/config/RG351P/advmame.rc b/packages/games/emulators/advancemame/config/RG351P/advmame.rc new file mode 100644 index 000000000..7d430c90e --- /dev/null +++ b/packages/games/emulators/advancemame/config/RG351P/advmame.rc @@ -0,0 +1,58 @@ +dir_artwork /storage/roms/mame/artwork +dir_diff /storage/roms/mame/diff +dir_hi /storage/roms/mame/hi +dir_image /storage/roms/mame/image +dir_inp /storage/roms/mame/inp +dir_memcard /storage/roms/mame/memcard +dir_nvram /storage/roms/mame/nvram +dir_rom /storage/roms/mame +dir_sample /storage/roms/mame/samples +dir_snap /storage/roms/mame/snap +dir_sta /storage/roms/mame/nvram +device_video sdl +device_keyboard sdl +display_magnifysize 320 +display_resize none +display_resizeeffect none +misc_quiet yes +sound_mode mono +device_alsa_device sdl +device_color_bgr15 no +device_color_bgr8 no +record_sound no +record_video no +sound_latency 0.10 +sound_normalize no +display_vsync no +device_video_clock 10-180 / 30-80 / 50-70 +display_mode 320x224x32 +device_joystick raw +input_map[coin1] joystick_button[opensimhardware_osh_pb_controller,button8] +input_map[start1] joystick_button[opensimhardware_osh_pb_controller,button7] +input_map[ui_cancel] keyboard[0,backspace] or keyboard[1,backspace] or joystick_button[opensimhardware_osh_pb_controller,button10] +input_map[ui_configure] keyboard[1,tab] or keyboard[0,tab] or joystick_button[opensimhardware_osh_pb_controller,button9] +input_map[p1_button1] joystick_button[opensimhardware_osh_pb_controller,button1] +input_map[p1_button2] joystick_button[opensimhardware_osh_pb_controller,button2] +input_map[p1_button3] joystick_button[opensimhardware_osh_pb_controller,button3] +input_map[p1_button4] joystick_button[opensimhardware_osh_pb_controller,button4] +input_map[p1_button5] joystick_button[opensimhardware_osh_pb_controller,button6] +input_map[p1_button6] joystick_button[opensimhardware_osh_pb_controller,button5] +input_map[p1_button7] joystick_button[opensimhardware_osh_pb_controller,button12] +input_map[p1_button8] joystick_button[opensimhardware_osh_pb_controller,button11] +input_map[p1_up] joystick_digital[opensimhardware_osh_pb_controller,3,1,1] or joystick_digital[opensimhardware_osh_pb_controller,0,1,0] +input_map[ui_up] joystick_digital[opensimhardware_osh_pb_controller,0,1,0] or joystick_digital[opensimhardware_osh_pb_controller,3,1,1] +input_map[p1_down] joystick_digital[opensimhardware_osh_pb_controller,0,1,1] or joystick_digital[opensimhardware_osh_pb_controller,3,1,0] +input_map[ui_down] joystick_digital[opensimhardware_osh_pb_controller,0,1,1] or joystick_digital[opensimhardware_osh_pb_controller,3,1,0] +input_map[p1_right] joystick_digital[opensimhardware_osh_pb_controller,0,0,1] or joystick_digital[opensimhardware_osh_pb_controller,3,0,0] +input_map[ui_right] joystick_digital[opensimhardware_osh_pb_controller,3,0,0] or joystick_digital[opensimhardware_osh_pb_controller,0,0,1] +input_map[p1_left] joystick_digital[opensimhardware_osh_pb_controller,0,0,0] or joystick_digital[opensimhardware_osh_pb_controller,3,0,1] +input_map[ui_left] joystick_digital[opensimhardware_osh_pb_controller,0,0,0] or joystick_digital[opensimhardware_osh_pb_controller,3,0,1] +input_map[ui_select] keyboard[0,enter] or keyboard[1,enter] or joystick_button[opensimhardware_osh_pb_controller,button1] +input_map[p1_doubleright_up] joystick_digital[opensimhardware_osh_pb_controller,1,1,1] joystick_digital[opensimhardware_osh_pb_controller,2,0,1] +input_map[p1_doubleright_down] joystick_digital[opensimhardware_osh_pb_controller,1,1,0] joystick_digital[opensimhardware_osh_pb_controller,2,0,0] +input_map[p1_doubleright_left] joystick_digital[opensimhardware_osh_pb_controller,1,0,1] +input_map[p1_doubleright_right] joystick_digital[opensimhardware_osh_pb_controller,1,0,0] +input_map[p1_doubleleft_up] joystick_digital[opensimhardware_osh_pb_controller,0,1,0] +input_map[p1_doubleleft_down] joystick_digital[opensimhardware_osh_pb_controller,0,1,1] +input_map[p1_doubleleft_left] joystick_digital[opensimhardware_osh_pb_controller,0,0,0] +input_map[p1_doubleleft_right] joystick_digital[opensimhardware_osh_pb_controller,0,0,1] diff --git a/packages/games/emulators/advancemame/package.mk b/packages/games/emulators/advancemame/package.mk new file mode 100644 index 000000000..21e8a3d64 --- /dev/null +++ b/packages/games/emulators/advancemame/package.mk @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="advancemame" +PKG_VERSION="384e646234d17b01f89a0e3b38cfdea770d1a1d2" +PKG_SHA256="a15293ee964b951ae2f37886796ee1a7b1d14361202985e8e5644a7af170a541" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/amadvance/advancemame" +PKG_URL="https://github.com/amadvance/advancemame/archive/$PKG_VERSION.tar.gz" +PKG_SOURCE_DIR="advancemame-$PKG_VERSION*" +PKG_DEPENDS_TARGET="toolchain freetype slang alsa" +PKG_SECTION="emuelec/mod" +PKG_SHORTDESC="A MAME and MESS port with an advanced video support for Arcade Monitors, TVs, and PC Monitors " +PKG_LONGDESC="A MAME and MESS port with an advanced video support for Arcade Monitors, TVs, and PC Monitors " +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + export CFLAGS="${CFLAGS} -fcommon" + sed -i "s|#include |#include <$SYSROOT_PREFIX/usr/include/slang.h>|" $PKG_BUILD/configure.ac +} + +pre_make_target() { + VERSION="${PKG_VERSION:0:7}" + echo $VERSION > $PKG_BUILD/.version +} + +make_target() { + cd $PKG_BUILD + ./autogen.sh + ./configure --prefix=/usr --datadir=/usr/share/ --datarootdir=/usr/share/ --host=armv8a-libreelec-linux --enable-fb --enable-freetype --with-freetype-prefix=$SYSROOT_PREFIX/usr/ --enable-slang + make mame +} + +makeinstall_target() { + : not +} + +post_make_target() { + mkdir -p $INSTALL/usr/share/advance + if [ "${DEVICE}" = "RG351MP" ]; then + cp -r $PKG_DIR/config/RG351MP/advmame.rc $INSTALL/usr/share/advance/advmame.rc + else + cp -r $PKG_DIR/config/RG351P/advmame.rc $INSTALL/usr/share/advance/advmame.rc + fi + mkdir -p $INSTALL/usr/bin + cp -r $PKG_DIR/bin/* $INSTALL/usr/bin + chmod +x $INSTALL/usr/bin/advmame.sh + cp -r $PKG_BUILD/obj/mame/linux/blend/advmame $INSTALL/usr/bin + cp -r $PKG_BUILD/support/category.ini $INSTALL/usr/share/advance + cp -r $PKG_BUILD/support/sysinfo.dat $INSTALL/usr/share/advance + cp -r $PKG_BUILD/support/history.dat $INSTALL/usr/share/advance + cp -r $PKG_BUILD/support/hiscore.dat $INSTALL/usr/share/advance + cp -r $PKG_BUILD/support/event.dat $INSTALL/usr/share/advance + CFLAGS=$OLDCFLAGS +} diff --git a/packages/games/emulators/advancemame/patches/advancemame-002-fix-vfb.patch b/packages/games/emulators/advancemame/patches/advancemame-002-fix-vfb.patch new file mode 100644 index 000000000..4d7b50db6 --- /dev/null +++ b/packages/games/emulators/advancemame/patches/advancemame-002-fix-vfb.patch @@ -0,0 +1,20 @@ +--- a/advance/linux/vfb.c 2018-03-10 10:38:17.000000000 -0600 ++++ b/advance/linux/vfb.c 2018-03-10 13:55:40.977788463 -0600 +@@ -859,6 +859,7 @@ + } + + /* set the preferred bit depth */ ++/* + switch (fb_state.varinfo.bits_per_pixel) { + case 16: + if ((fb_state.flags & VIDEO_DRIVER_FLAGS_MODE_BGR16) != 0) +@@ -873,6 +874,9 @@ + fb_state.flags |= VIDEO_DRIVER_FLAGS_DEFAULT_BGR32; + break; + } ++*/ ++/* force 16bit for EmuELEC */ ++ fb_state.flags |= VIDEO_DRIVER_FLAGS_DEFAULT_BGR16; + + log_std(("video:fb: size %ux%u\n", target_size_x(), target_size_y())); + log_std(("video:fb: aspect %ux%u\n", target_aspect_x(), target_aspect_y())); diff --git a/packages/games/emulators/advancemame/patches/advancemame-fix-slang.patch b/packages/games/emulators/advancemame/patches/advancemame-fix-slang.patch new file mode 100644 index 000000000..492757956 --- /dev/null +++ b/packages/games/emulators/advancemame/patches/advancemame-fix-slang.patch @@ -0,0 +1,108 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -717,40 +717,28 @@ + [ac_lib_slang=auto] + ) + if test $ac_lib_slang = auto; then +- PKG_CHECK_MODULES([SLANG], [slang], [ac_lib_slang=yes], [ac_lib_slang=no]) +- if test $ac_lib_slang = yes; then +- ac_save_CFLAGS="$CFLAGS" +- ac_save_LIBS="$LIBS" +- CFLAGS="SLANG_CFLAGS $CFLAGS" +- LIBS="$SLANG_LIBS $LIBS" +- AC_MSG_CHECKING([for linking slang]) +- AC_TRY_LINK([ +- #include +- ], [ +- if (SLang_init_tty(-1, 0, 0) < 0) { +- perror("SLang_init_tty"); +- return 1; +- } +- +- SLang_reset_tty(); +- return 0; +- ],[ac_lib_slang=yes],[ac_lib_slang=no]) +- AC_MSG_RESULT([$ac_lib_slang]) +- CFLAGS="$ac_save_CFLAGS" +- LIBS="$ac_save_LIBS" +- fi ++ AC_CHECK_LIB( ++ [slang], ++ [SLang_init_tty], ++ [ac_lib_slang=yes], ++ [ac_lib_slang=no], ++ [] ++ ) + elif test $ac_lib_slang = yes; then +- PKG_CHECK_MODULES([SLANG], [slang], [], AC_MSG_ERROR([the slang library is missing])) ++ AC_CHECK_LIB( ++ [slang], ++ [SLang_init_tty], ++ [], ++ [AC_MSG_ERROR([the sLang library is missing])], ++ [] ++ ) + fi + if test $ac_lib_slang = yes; then + AC_CHECK_HEADERS([slang.h slang/slang.h], [break]) + ac_lib_video="$ac_lib_video slang" + ac_lib_text_flag=yes + fi +-AC_SUBST([SLANGCFLAGS],[$SLANG_CFLAGS]) +-AC_SUBST([SLANGLIBS],[$SLANG_LIBS]) + AC_SUBST([CONF_LIB_SLANG],[$ac_lib_slang]) +- + + dnl Checks for ncurses + AC_ARG_ENABLE( +@@ -760,36 +748,27 @@ + [ac_lib_ncurses=auto] + ) + if test $ac_lib_ncurses = auto; then +- PKG_CHECK_MODULES([NCURSES], [ncurses], [ac_lib_ncurses=yes], [ac_lib_ncurses=no]) +- if test $ac_lib_ncurses = yes; then +- ac_save_CFLAGS="$CFLAGS" +- ac_save_LIBS="$LIBS" +- CFLAGS="$NCURSES_CFLAGS $CFLAGS" +- LIBS="$NCURSES_LIBS $LIBS" +- AC_MSG_CHECKING([for linking ncurses]) +- AC_TRY_LINK([ +- #include +- ], [ +- initscr(); +- noecho(); +- curs_set(FALSE); +- endwin(); +- ],[ac_lib_ncurses=yes],[ac_lib_ncurses=no]) +- AC_MSG_RESULT([$ac_lib_ncurses]) +- CFLAGS="$ac_save_CFLAGS" +- LIBS="$ac_save_LIBS" +- fi ++ AC_CHECK_LIB( ++ [ncurses], ++ [endwin], ++ [ac_lib_ncurses=yes], ++ [ac_lib_ncurses=no], ++ [] ++ ) + elif test $ac_lib_ncurses = yes; then +- PKG_CHECK_MODULES([NCURSES], [ncurses], [], AC_MSG_ERROR([the ncurses library is missing])) ++ AC_CHECK_LIB( ++ [ncurses], ++ [endwin], ++ [], ++ [AC_MSG_ERROR([the sLang library is missing])], ++ [] ++ ) + fi + if test $ac_lib_ncurses = yes; then + ac_lib_video="$ac_lib_video ncurses" + ac_lib_text_flag=yes + fi +-AC_SUBST([NCURSESCFLAGS],[$NCURSES_CFLAGS]) +-AC_SUBST([NCURSESLIBS],[$NCURSES_LIBS]) + AC_SUBST([CONF_LIB_NCURSES],[$ac_lib_ncurses]) +- + + dnl Checks for freetype + AC_ARG_ENABLE( diff --git a/packages/games/emulators/advancemame/patches/advancemame-return-0-on-terminate.patch b/packages/games/emulators/advancemame/patches/advancemame-return-0-on-terminate.patch new file mode 100644 index 000000000..7031e3e07 --- /dev/null +++ b/packages/games/emulators/advancemame/patches/advancemame-return-0-on-terminate.patch @@ -0,0 +1,11 @@ +--- a/advance/linux/target.c ++++ b/advance/linux/target.c +@@ -1099,7 +1099,7 @@ + exit(EXIT_FAILURE); + } else if (signum == SIGTERM) { + fprintf(stderr, "Terminated\n\r"); +- exit(EXIT_FAILURE); ++ exit(0); + } else if (signum == SIGALRM) { + fprintf(stderr, "Alarm\n\r"); + exit(EXIT_FAILURE); diff --git a/packages/games/emulators/amiberry/config/conf/AmigaA1200-default.uae b/packages/games/emulators/amiberry/config/conf/AmigaA1200-default.uae new file mode 100644 index 000000000..fa660dd61 --- /dev/null +++ b/packages/games/emulators/amiberry/config/conf/AmigaA1200-default.uae @@ -0,0 +1,174 @@ +config_description=UAE Amiga 1200/ Amiga CD32 default configuration +config_hardware=true +config_host=true +config_version=3.6.0 +rtg_nocustom=true +a1000ram=false +synchronize_clock=yes +sound_auto=yes +pandora.jump=-1 +pandora.autofire_button=3 +pandora.button2=1 +pandora.button1=2 +pandora.move_y=0 +pandora.move_x=0 +pandora.custom_r=0 +pandora.custom_l=0 +pandora.custom_y=0 +pandora.custom_x=0 +pandora.custom_b=0 +pandora.custom_a=0 +pandora.custom_right=0 +pandora.custom_left=0 +pandora.custom_down=0 +pandora.custom_up=0 +pandora.custom_dpad=0 +pandora.custom_controls=0 +pandora.tap_delay=10 +pandora.stylus_offset=0 +pandora.joy_port=0 +pandora.joy_conf=0 +pandora.cpu_speed=600 +pandora.hardfile_path=/storage/.config/amiberry/ +pandora.floppy_path=/storage/.config/amiberry/disks/ +pandora.rom_path=/storage/.config/amiberry/kickstarts/ +amiberry.rom_path=/storage/.config/amiberry/kickstarts/ +amiberry.floppy_path=/storage/.config/amiberry/disks/ +amiberry.hardfile_path=/storage/.config/amiberry/ +amiberry.cd_path=/storage/.config/amiberry/cd32/ +; +; *** Controller/Input Configuration +; +joyport0=mouse +joyport0_autofire=none +joyport0_friendlyname=Mouse +joyport0_name=MOUSE0 +; +joyport1=joy1 +joyport1_autofire=normal +joyport1_friendlyname=Logitech Gamepad F310 +joyport1_name=JOY1 +; +joyport2=joy0 +joyport2_autofire=normal +joyport2_friendlyname=Keyboard as Joystick [Default] +joyport2_name=JOY0 +; +; +; +input.joymouse_speed_analog=2 +input.joymouse_speed_digital=10 +input.joymouse_deadzone=33 +input.joystick_deadzone=33 +input.analog_joystick_multiplier=15 +input.analog_joystick_offset=-1 +input.mouse_speed=100 +input.autofire_speed=2496 +kbd_lang=us +; +; *** Host-Specific +; +amiberry.vertical_offset=0 +amiberry.hide_idle_led=0 +amiberry.gfx_correct_aspect=1 +amiberry.kbd_led_num=-1 +amiberry.kbd_led_scr=-1 +amiberry.scaling_method=-1 +amiberry.use_analogue_remap=false +amiberry.use_retroarch_quit=true +amiberry.use_retroarch_menu=true +amiberry.use_retroarch_reset=false +; +; *** Common / Paths +; +use_gui=no +kickstart_rom_file=$(FILE_PATH)/kick40068.A1200.rom +kickstart_ext_rom_file= +ide_mb_rom_file=:ENABLED +flash_file= +cart_file= +; +; *** Floppy Drives +; +;floppy0= +;floppy1= +;floppy2= +;floppy3= +nr_floppies=4 +floppy_speed=100 +; +; *** Hard Drives +; +; +; *** CD / CD32 +; +cd_speed=100 +; +; *** Display / Screen Setup +; +gfx_framerate=0 +gfx_width=640 +gfx_height=256 +gfx_refreshrate=50 +gfx_refreshrate_rtg=50 +gfx_lores=false +gfx_resolution=hires +gfx_linemode=none +gfx_fullscreen_amiga=false +gfx_fullscreen_picasso=false +ntsc=false +; +; *** CPU options +; +cpu_speed=real +cpu_type=68ec020 +cpu_model=68020 +cpu_compatible=false +cpu_24bit_addressing=true +fpu_strict=false +compfpu=true +cachesize=0 +finegrain_cpu_speed=1024 +; +; *** Memory +; +chipmem_size=4 +z3mapping=real +fastmem_size=0 +a3000mem_size=0 +mbresmem_size=0 +z3mem_size=0 +z3mem_start=0x40000000 +bogomem_size=0 +rtg_modes=0x502 +; +; *** Chipset +; +chipset=aga +chipset_refreshrate=50.000000 +collision_level=playfields +chipset_compatible=Generic +rtc=MSM6242B +immediate_blits=false +fast_copper=true +; +; *** Sound Options +; +sound_output=exact +sound_channels=stereo +sound_stereo_separation=7 +sound_stereo_mixing_delay=0 +sound_frequency=44100 +sound_interpol=none +sound_filter=off +sound_filter_type=standard +sound_volume_cd=20 +; +; *** Misc. Options +; +bsdsocket_emu=false + +gfx_center_vertical=smart +gfx_center_horizontal=smart +gfx_center_vertical=smart +gfx_center_horizontal=smart diff --git a/packages/games/emulators/amiberry/config/conf/AmigaA500-default.uae b/packages/games/emulators/amiberry/config/conf/AmigaA500-default.uae new file mode 100644 index 000000000..c855eca41 --- /dev/null +++ b/packages/games/emulators/amiberry/config/conf/AmigaA500-default.uae @@ -0,0 +1,173 @@ +config_description=UAE Amiga 500 default configuration +config_hardware=true +config_host=true +config_version=3.6.0 +rtg_nocustom=true +a1000ram=false +synchronize_clock=yes +sound_auto=yes +pandora.jump=-1 +pandora.autofire_button=3 +pandora.button2=1 +pandora.button1=2 +pandora.move_y=0 +pandora.move_x=0 +pandora.custom_r=0 +pandora.custom_l=0 +pandora.custom_y=0 +pandora.custom_x=0 +pandora.custom_b=0 +pandora.custom_a=0 +pandora.custom_right=0 +pandora.custom_left=0 +pandora.custom_down=0 +pandora.custom_up=0 +pandora.custom_dpad=0 +pandora.custom_controls=0 +pandora.tap_delay=10 +pandora.stylus_offset=0 +pandora.joy_port=0 +pandora.joy_conf=0 +pandora.cpu_speed=600 +pandora.hardfile_path=/storage/.config/amiberry/ +pandora.floppy_path=/storage/.config/amiberry/disks/ +pandora.rom_path=/storage/.config/amiberry/kickstarts/ +amiberry.rom_path=/storage/.config/amiberry/kickstarts/ +amiberry.floppy_path=/storage/.config/amiberry/disks/ +amiberry.hardfile_path=/storage/.config/amiberry/ +amiberry.cd_path=/storage/.config/amiberry/cd32/ +; +; *** Controller/Input Configuration +; +joyport0=mouse +joyport0_autofire=none +joyport0_friendlyname=Mouse +joyport0_name=MOUSE0 +; +joyport1=joy1 +joyport1_autofire=normal +joyport1_friendlyname=Logitech Gamepad F310 +joyport1_name=JOY1 +; +joyport2=joy0 +joyport2_autofire=normal +joyport2_friendlyname=Keyboard as Joystick [Default] +joyport2_name=JOY0 +; +; +; +input.joymouse_speed_analog=2 +input.joymouse_speed_digital=10 +input.joymouse_deadzone=33 +input.joystick_deadzone=33 +input.analog_joystick_multiplier=15 +input.analog_joystick_offset=-1 +input.mouse_speed=100 +input.autofire_speed=2496 +kbd_lang=us +; +; *** Host-Specific +; +amiberry.vertical_offset=0 +amiberry.hide_idle_led=0 +amiberry.gfx_correct_aspect=1 +amiberry.kbd_led_num=-1 +amiberry.kbd_led_scr=-1 +amiberry.scaling_method=-1 +amiberry.use_analogue_remap=false +amiberry.use_retroarch_quit=true +amiberry.use_retroarch_menu=true +amiberry.use_retroarch_reset=false +; +; *** Common / Paths +; +use_gui=no +kickstart_rom_file=$(FILE_PATH)/kick34005.A500.rom +kickstart_ext_rom_file= +ide_mb_rom_file=:ENABLED +flash_file= +cart_file= +; +; *** Floppy Drives +; +;floppy0= +;floppy1= +;floppy2= +;floppy3= +nr_floppies=4 +floppy_speed=100 +; +; *** Hard Drives +; +; +; *** CD / CD32 +; +cd_speed=100 +; +; *** Display / Screen Setup +; +gfx_framerate=0 +gfx_width=640 +gfx_height=256 +gfx_refreshrate=50 +gfx_refreshrate_rtg=50 +gfx_lores=false +gfx_resolution=hires +gfx_linemode=none +gfx_fullscreen_amiga=false +gfx_fullscreen_picasso=false +ntsc=false +; +; *** CPU options +; +cpu_speed=real +cpu_type=68000 +cpu_model=68000 +cpu_compatible=false +cpu_24bit_addressing=true +fpu_strict=false +compfpu=true +cachesize=8192 +; +; *** Memory +; +chipmem_size=2 +z3mapping=real +fastmem_size=0 +a3000mem_size=0 +mbresmem_size=0 +z3mem_size=0 +z3mem_start=0x40000000 +bogomem_size=0 +rtg_modes=0x502 +; +; *** Chipset +; +chipset=ecs +chipset_refreshrate=50.000000 +collision_level=playfields +chipset_compatible=Generic +rtc=MSM6242B +immediate_blits=false +fast_copper=true +; +; *** Sound Options +; +sound_output=exact +sound_channels=stereo +sound_stereo_separation=7 +sound_stereo_mixing_delay=0 +sound_frequency=44100 +sound_interpol=none +sound_filter=off +sound_filter_type=standard +sound_volume_cd=20 +; +; *** Misc. Options +; +bsdsocket_emu=false + +gfx_center_vertical=smart +gfx_center_horizontal=smart +gfx_center_vertical=smart +gfx_center_horizontal=smart diff --git a/packages/games/emulators/amiberry/config/conf/adfdir.conf b/packages/games/emulators/amiberry/config/conf/adfdir.conf new file mode 100644 index 000000000..9ae98c169 --- /dev/null +++ b/packages/games/emulators/amiberry/config/conf/adfdir.conf @@ -0,0 +1,35 @@ +path=/storage/roms/amiga/ +config_path=/storage/.config/amiberry/conf/ +controllers_path=/storage/.config/amiberry/controller/ +retroarch_config=/storage/.config/retroarch/retroarch.cfg +rom_path=/storage/.config/amiberry/kickstarts/ +ROMs=6 +ROMName=KS ROM v1.2 (A500,A1000,A2000) rev 33.180 (256k) [315093-01] +ROMPath=/storage/.config/amiberry/kickstarts/kick33180.A500.rom +ROMType=256 +ROMName=KS ROM v1.3 (A500,A1000,A2000) rev 34.5 (256k) [315093-02] +ROMPath=/storage/.config/amiberry/kickstarts/kick34005.A500.rom +ROMType=256 +ROMName=KS ROM v2.04 (A500+) rev 37.175 (512k) [390979-01] +ROMPath=/storage/.config/amiberry/kickstarts/kick37175.A500.rom +ROMType=256 +ROMName=KS ROM v3.0 (A1200) rev 39.106 (512k) [391523-01/391524-01] +ROMPath=/storage/.config/amiberry/kickstarts/kick39106.A1200.rom +ROMType=256 +ROMName=KS ROM v3.1 (A1200) rev 40.68 (512k) [391773-01/391774-01] +ROMPath=/storage/.config/amiberry/kickstarts/kick40068.A1200.rom +ROMType=256 +ROMName=KS ROM v3.1 (A4000) rev 40.68 (512k) +ROMPath=/storage/.config/amiberry/kickstarts/kick40068.A4000.rom +ROMType=256 +MRUDiskList=1 +Diskfile= +MRUCDList=0 +Quickstart=1 +read_config_descriptions=yes +swap_win_alt_keys=no +gui_joystick_control=yes +use_sdl2_render_thread=no +input_default_mouse_speed=100 +input_keyboard_as_joystick_stop_keypresses=no +default_open_gui_key=F12 diff --git a/packages/games/emulators/amiberry/package.mk b/packages/games/emulators/amiberry/package.mk new file mode 100644 index 000000000..bec78ec6f --- /dev/null +++ b/packages/games/emulators/amiberry/package.mk @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="amiberry" +PKG_VERSION="52eb8cd76667eb66aa94924af1d97259ab5f43ab" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/midwan/amiberry" +PKG_URL="https://github.com/midwan/amiberry.git" +PKG_DEPENDS_TARGET="toolchain linux glibc bzip2 zlib SDL2 SDL2_image SDL2_ttf capsimg freetype libxml2 flac libogg mpg123 libpng libmpeg2" +PKG_LONGDESC="Amiberry is an optimized Amiga emulator for ARM-based boards." +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" +PKG_GIT_CLONE_BRANCH="master" + +pre_configure_target() { + cd ${PKG_BUILD} + export SYSROOT_PREFIX=${SYSROOT_PREFIX} + + case ${PROJECT} in + Amlogic) + if [ $ARCH == "arm" ]; then + AMIBERRY_PLATFORM="AMLGX" + else + AMIBERRY_PLATFORM="pi64" + fi + ;; + Amlogic-ng) + if [ $ARCH == "arm" ]; then + AMIBERRY_PLATFORM="AMLG12B" + else + AMIBERRY_PLATFORM="n2" + fi + ;; + esac + +if [[ "$DEVICE" =~ RG351 ]]; then +if [ $ARCH == "arm" ]; then +AMIBERRY_PLATFORM="RK3326" +else +AMIBERRY_PLATFORM="pi64" +fi + +fi + +sed -i "s|AS = as|AS \?= as|" Makefile +PKG_MAKE_OPTS_TARGET+=" all PLATFORM=${AMIBERRY_PLATFORM} SDL_CONFIG=${SYSROOT_PREFIX}/usr/bin/sdl2-config" +} + +makeinstall_target() { + # Create directories + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/lib + mkdir -p ${INSTALL}/usr/config/amiberry + # mkdir -p ${INSTALL}/usr/config/amiberry/controller + + # Copy ressources + cp -ra ${PKG_DIR}/config/* ${INSTALL}/usr/config/amiberry/ + cp -a data ${INSTALL}/usr/config/amiberry/ + cp -a savestates ${INSTALL}/usr/config/amiberry/ + cp -a screenshots ${INSTALL}/usr/config/amiberry/ + cp -a whdboot ${INSTALL}/usr/config/amiberry/ + ln -s /storage/roms/bios ${INSTALL}/usr/config/amiberry/kickstarts + + # Create links to Retroarch controller files + # ln -s /usr/share/retroarch/autoconfig/udev/8Bitdo_Pro_SF30_BT_B.cfg "${INSTALL}/usr/config/amiberry/controller/8Bitdo SF30 Pro.cfg" + ln -s "/tmp/joypads" "${INSTALL}/usr/config/amiberry/controller" + + # Copy binary, scripts & link libcapsimg + cp -a amiberry* ${INSTALL}/usr/bin/amiberry + cp -a ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin + ln -sf /usr/lib/libcapsimage.so.5.1 ${INSTALL}/usr/config/amiberry/capsimg.so + + UAE="${INSTALL}/usr/config/amiberry/conf/*.uae" + for i in $UAE; do echo -e "gfx_center_vertical=smart\ngfx_center_horizontal=smart" >> $i; done + +} diff --git a/packages/games/emulators/amiberry/scripts/amiberry.start b/packages/games/emulators/amiberry/scripts/amiberry.start new file mode 100755 index 000000000..e153eebc4 --- /dev/null +++ b/packages/games/emulators/amiberry/scripts/amiberry.start @@ -0,0 +1,145 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +. /etc/profile + +# Set some common variables +AMIBERRY_DIR=/storage/.config/amiberry +AMIBERRY_CONFIG_DIR=$AMIBERRY_DIR/conf +AMIBERRY_TMP_DIR=/tmp/emulation/amiberry +AMIBERRY_TMP_CONFIG="$AMIBERRY_TMP_DIR"/.amiberry_conf.uae +AMIBERRY_LOG=/tmp/logs/amiberry.log +MAX_DRIVES=4 +i=0 + +echo "Amiberry Log" > "$AMIBERRY_LOG" + +find_gamepad() { +# Search for connected gamepads based s0 and extract the name to $GAMEPAD +for file in /tmp/joypads/*.cfg; do + EE_GAMEPAD=$(cat "$file" | grep input_device| cut -d'"' -f 2) + ES_EE_GAMEPAD=$(printf %q "$EE_GAMEPAD") +if cat /proc/bus/input/devices | grep -Ew -A 4 -B 1 "Name=\"${ES_EE_GAMEPAD}" | grep "js0" > /dev/null; then + sed -i "s|joyport1_friendlyname=.*|joyport1_friendlyname=${EE_GAMEPAD}|" "$AMIBERRY_TMP_CONFIG" + echo "Gamepad used $EE_GAMEPAD" >> "$AMIBERRY_LOG" + break; +fi +done +} + +# Set SDL audio driver to alsa +SDL_AUDIODRIVER=alsa + +# Which file should amiberry load? +echo "Trying to boot this game:" "$1" >> $AMIBERRY_LOG + +# Change working directory cause amiberry loads assets from there +cd $AMIBERRY_DIR + +# Create a clean working directory +if [ -d "$AMIBERRY_TMP_DIR" ]; then + echo "Clean up old working directory." >> $AMIBERRY_LOG + rm -rf "$AMIBERRY_TMP_DIR" +fi +mkdir -p "$AMIBERRY_TMP_DIR" + +# Check if the file is an Amiga 1200/CD32 game and set configuration options for an Amiga 1200 +AMIBERRY_SET_CONF() { + if [ `echo $1 | egrep 'AGA|CD32' | wc -l` -eq 1 -o `echo "$AMIBERRY_TMP_DIR"/* | egrep 'AGA|CD32' | wc -l` -eq 1 ]; then + echo "Loading Amiga 1200/CD32 config." >> $AMIBERRY_LOG + cp $AMIBERRY_CONFIG_DIR/AmigaA1200-default.uae "$AMIBERRY_TMP_CONFIG" + else + echo "Loading Amiga 500 config." >> $AMIBERRY_LOG + cp $AMIBERRY_CONFIG_DIR/AmigaA500-default.uae "$AMIBERRY_TMP_CONFIG" + fi + +find_gamepad +} + +# Check if we are loading a .zip file +if [ `echo $1 | grep -i .zip | wc -l` -eq 1 ]; then + + # Unpack the zip file + unzip -q -o "$1" -d "$AMIBERRY_TMP_DIR" + + if [ -f "$AMIBERRY_TMP_DIR"/*.*nfo ] && [ -f "$AMIBERRY_TMP_DIR"/*/*.*lave ]; then + + # WHDLoad file detected + echo "Loading a WHDLoad (.zip) file..." >> $AMIBERRY_LOG + + # Set default config + AMIBERRY_SET_CONF "$1" + + # Add amiberry.uae conf & start amiberry with WHDLoad + amiberry -f "$AMIBERRY_TMP_CONFIG" --autoload "$1" >> $AMIBERRY_LOG 2>&1 + + else + # .zip file detected + echo "Loading a .zip file..." >> $AMIBERRY_LOG + + # Set default config + AMIBERRY_SET_CONF "$1" + + # Assign files to floppy0-3 + for FILE in "$AMIBERRY_TMP_DIR"/* + do + ARGS="$ARGS\nfloppy$i="$FILE"" + i=$(($i+1)) + # This emulator supports 4 floppies max + if [ $i -eq $MAX_DRIVES ]; then + break; + fi + done + + # Add game files as floppies 0-3 to amiberry.uae & start amiberry + echo -e ";" >> "$AMIBERRY_TMP_CONFIG" + echo -e "; *** temporary added Floppy Drives" >> "$AMIBERRY_TMP_CONFIG" + echo -e ";" >> "$AMIBERRY_TMP_CONFIG" + echo -e $ARGS >> "$AMIBERRY_TMP_CONFIG" + echo -e "\nAssigned floppy drives:" $ARGS "\n" >> "$AMIBERRY_LOG" + amiberry -f "$AMIBERRY_TMP_CONFIG" >> $AMIBERRY_LOG 2>&1 + fi + +# Check for WHDload files (.lha) +elif [ `echo $1 | grep -i .lha | wc -l` -eq 1 ]; then + + #.lha file detected + echo "Loading a WHDLoad (.lha) file..." >> $AMIBERRY_LOG + + # Set default config + AMIBERRY_SET_CONF "$1" + + # Add amiberry.uae conf & start amiberry with WHDLoad + amiberry -f "$AMIBERRY_TMP_CONFIG" --autoload "$1" >> $AMIBERRY_LOG 2>&1 + +# Check for .uae config file +elif [ `echo $1 | grep -i .uae | wc -l` -eq 1 ]; then + + # .uae file detected + echo "Loading an .uae file..." >> $AMIBERRY_LOG + + # Load .uae config file + amiberry -f "$1" >> $AMIBERRY_LOG 2>&1 + +# All other files (.adf .adz .ipf) +else + + #.adf or .adz or .ipf file detected + echo "Loading a single .adf or .adz or .ipf file..." >> $AMIBERRY_LOG + + # Set default config + AMIBERRY_SET_CONF "$1" + + # Add game file as floppy0 to amiberry.uae & start amiberry + echo -e ";" >> "$AMIBERRY_TMP_CONFIG" + echo -e "; *** temporary added Floppy Drives" >> "$AMIBERRY_TMP_CONFIG" + echo -e ";" >> "$AMIBERRY_TMP_CONFIG" + echo -e "\nfloppy0=$1" >> "$AMIBERRY_TMP_CONFIG" + echo -e "\nAssigned floppy drive:\nfloppy0=$1\n" >> "$AMIBERRY_LOG" + amiberry -f "$AMIBERRY_TMP_CONFIG" >> $AMIBERRY_LOG 2>&1 +fi + +# Remove temporary dir +rm -rf "$AMIBERRY_TMP_DIR" diff --git a/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2-MT32.conf b/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2-MT32.conf new file mode 100644 index 000000000..6151374e2 --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2-MT32.conf @@ -0,0 +1,344 @@ +# This is the configuration file for DOSBox SDL2. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb, opengl, openglnb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen=true +# Note that VSYNC is be very demanding +vsync=false +fullresolution=0x0 +windowresolution=original +output=texture +# Place shaders in /storage/.config/dosbox/shaders +gl.shader=crt-easymode +texture.renderer=auto +autolock=true +sensitivity=100 +waitonerror=true +priority=highest,highest +# Input mapper file is looked for in the same directory as the specified conf +mapperfile=example.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language= +machine=svga_s3 +captures=capture +memsize=16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip=0 +aspect=true +scaler=none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core=auto +cputype=auto +cycles=auto +cycleup=10 +cycledown=20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound=false +rate=44100 +blocksize=1024 +prebuffer=20 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. +# or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401=intelligent +mididevice=mt32 +midiconfig= +# Place MT-32 roms here +mt32.romdir=/storage/roms/bios +mt32.reverse.stereo=false +mt32.verbose=false +mt32.thread=false +mt32.chunk=16 +mt32.prebuffer=32 +mt32.partials=32 +mt32.dac=0 +mt32.analog=2 +mt32.reverb.mode=auto +mt32.reverb.time=5 +mt32.reverb.level=3 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype=sb16 +sbbase=220 +irq=7 +dma=1 +hdma=5 +sbmixer=true +oplmode=auto +oplemu=default +oplrate=44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus=true +gusrate=44100 +gusbase=240 +gusirq=5 +gusdma=3 +# Place GUS files in /storage/roms/dos/ULTRASND +ultradir=C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker=true +pcrate=44100 +tandy=auto +tandyrate=44100 +disney=true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. + +joysticktype=fcs +timed=true +autofire=false +swap34=false +buttonwrap=false + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1=dummy +serial2=dummy +serial3=disabled +serial4=disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms=true +ems=true +umb=true +keyboardlayout=auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx=false + +[autoexec] +# Lines in this section will be run at startup. + +mount c /storage/roms/dos +c: +cd example +example.exe +#exit diff --git a/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2.conf b/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2.conf new file mode 100644 index 000000000..babafcb02 --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/config/dosbox-SDL2.conf @@ -0,0 +1,327 @@ +# This is the configuration file for DOSBox SDL2. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb, opengl, openglnb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen=true +# Note that VSYNC is be very demanding +vsync=false +fullresolution=0x0 +windowresolution=original +output=texture +# Place shaders in /storage/.config/dosbox/shaders +gl.shader=crt-easymode +texture.renderer=auto +autolock=true +sensitivity=100 +waitonerror=true +priority=highest,highest +# Input mapper file is looked for in the same directory as the specified conf +mapperfile=example.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language= +machine=svga_s3 +captures=capture +memsize=16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip=0 +aspect=true +scaler=none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core=auto +cputype=auto +cycles=auto +cycleup=10 +cycledown=20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound=false +rate=44100 +blocksize=1024 +prebuffer=20 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. +# or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401=intelligent +# FluidSynth Software Synthesizer +mididevice=fluidsynth +fluid.driver=pulseaudio +fluid.soundfont=/usr/share/soundfonts/GeneralUser.sf2 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype=sb16 +sbbase=220 +irq=7 +dma=1 +hdma=5 +sbmixer=true +oplmode=auto +oplemu=default +oplrate=44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus=true +gusrate=44100 +gusbase=240 +gusirq=5 +gusdma=3 +# Place GUS files in /storage/roms/dos/ULTRASND +ultradir=C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker=true +pcrate=44100 +tandy=auto +tandyrate=44100 +disney=true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. + +joysticktype=fcs +timed=true +autofire=false +swap34=false +buttonwrap=false + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1=dummy +serial2=dummy +serial3=disabled +serial4=disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms=true +ems=true +umb=true +keyboardlayout=auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx=false + +[autoexec] +# Lines in this section will be run at startup. diff --git a/packages/games/emulators/dosbox-sdl2/config/dosbox-SVN.conf b/packages/games/emulators/dosbox-sdl2/config/dosbox-SVN.conf new file mode 100644 index 000000000..bd7410faf --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/config/dosbox-SVN.conf @@ -0,0 +1,357 @@ +# This is the configuration file for DOSBox SVN. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface.On Windows 10 with display scaling (Scale and layout) set to a value above 100%, it is recommended +# to use a lower full/windowresolution, in order to avoid window size problems. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. The optional second parameter specifies vertical sensitivity (e.g. 100,-50). +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen = true +vsync = false +fullresolution = 0x0 +windowresolution = original +output = texturenb +gl.shader = +texture.renderer = auto +autolock = true +sensitivity = 100 +waitonerror = true +priority = higher,normal +mapperfile = mapper-sdl2-SVN.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language = +machine = svga_s3 +captures = capture +memsize = 16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down! +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# To fit a scaler in the resolution used at full screen may require a border or side bars, +# to fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip = 0 +aspect = true +scaler = none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core = auto +cputype = auto +cycles = auto +cycleup = 10 +cycledown = 20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound = false +rate = 44100 +blocksize = 1024 +prebuffer = 25 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, fluidsynth, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id or part of the name of the device you want to use (find the id/name with mixer/listmidi). +# Or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# fluid.driver: Driver to use with Fluidsynth, not needed under Windows. Available drivers depend on what Fluidsynth was compiled with +# Possible values: pulseaudio, alsa, oss, coreaudio, dsound, portaudio, sndman, jack, file, default. +# fluid.soundfont: Soundfont to use with Fluidsynth. One must be specified. +# fluid.samplerate: Sample rate to use with Fluidsynth. +# fluid.gain: Fluidsynth gain. +# fluid.polyphony: Fluidsynth polyphony. +# fluid.cores: Fluidsynth CPU cores to use, default. +# fluid.periods: Fluidsynth periods. +# fluid.periodsize: Fluidsynth period size. +# fluid.reverb: Fluidsynth use reverb. +# Possible values: no, yes. +# fluid.chorus: Fluidsynth use chorus. +# Possible values: no, yes. +# fluid.reverb,roomsize: Fluidsynth reverb room size. +# fluid.reverb.damping: Fluidsynth reverb damping. +# fluid.reverb.width: Fluidsynth reverb width. +# fluid.reverb.level: Fluidsynth reverb level. +# fluid.chorus.number: Fluidsynth chorus voices +# fluid.chorus.level: Fluidsynth chorus level. +# fluid.chorus.speed: Fluidsynth chorus speed. +# fluid.chorus.depth: Fluidsynth chorus depth. +# fluid.chorus.type: Fluidsynth chorus type. 0 is sine wave, 1 is triangle wave. +# Possible values: 0, 1. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401 = intelligent +# FluidSynth Software Synthesizer +mididevice = fluidsynth +fluid.driver = pulseaudio +fluid.soundfont = /usr/share/soundfonts/GeneralUser.sf2 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast, mame. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype = sb16 +sbbase = 220 +irq = 7 +dma = 1 +hdma = 5 +sbmixer = true +oplmode = auto +oplemu = default +oplrate = 44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus = false +gusrate = 44100 +gusbase = 240 +gusirq = 5 +gusdma = 3 +ultradir = C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker = true +pcrate = 44100 +tandy = auto +tandyrate = 44100 +disney = true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. Can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. +# circularinput: enable translation of circular input to square output. +# Try enabling this if your left analog stick can only move in a circle. +# deadzone: the percentage of motion to ignore. 100 turns the stick into a digital one. + +joysticktype = auto +timed = true +autofire = false +swap34 = false +buttonwrap = false +circularinput = false +deadzone = 10 + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1 = dummy +serial2 = dummy +serial3 = disabled +serial4 = disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms = true +ems = true +umb = true +keyboardlayout = auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx = false + +[autoexec] +# Lines in this section will be run at startup. +# You can put your MOUNT lines here. + + diff --git a/packages/games/emulators/dosbox-sdl2/config/games/_Scan DOSBox Games.sh b/packages/games/emulators/dosbox-sdl2/config/games/_Scan DOSBox Games.sh new file mode 100644 index 000000000..4c16cc5cf --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/config/games/_Scan DOSBox Games.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Sylvia van Os (https://github.com/TheLastProject) +# Copyright (C) 2020-present Fewtarius + +echo -e $(date -u)" - Script started.\n" >> /tmp/logs/dosbox_scan.log + +EE_DEVICE=$(cat /ee_arch) + +source /usr/bin/env.sh +source /etc/profile +rp_registerAllModules + +joy2keyStart +clear >/dev/console + +#rm "/storage/.config/dosbox/games/*.conf" + +function create_launcher() { + message_stream "\nAdding $2..." 0 + launcher_name="$1 ($2)" + cp /storage/.config/dosbox/dosbox-SDL2.conf "/storage/.config/dosbox/games/$launcher_name.conf" + cat <> "/storage/.config/dosbox/games/$launcher_name.conf" +mount c /storage/roms/pc/$(basename $data_dir) +c: +$2 +exit +EOF +} + +message_stream "Scanning for games...\n" 0 + +OIFS="$IFS" +IFS=$'\n' +for data_dir in $(find /storage/roms/pc/ -type d -name "*") +do + echo "Testing (dir) $data_dir" + if [ -d "$data_dir" ]; then + for executable in $(find "$data_dir" -iname "*.exe") + do + echo "Testing (exe) $executable" + executable_case="$(basename "$executable" | tr '[:lower:]' '[:upper:]')" + echo "Case $executable" + case "$executable_case" in + "SETUP.EXE" | "INSTALL.EXE" | "INSTALLER.EXE" | \ + "APOGEE.BAT" | "CATALOG.EXE" | "DEALERS.EXE" | \ + "SWCBBS.EXE" | "FILE0001.EXE" | "FILE0001.EXE" | \ + "HELPME.EXE" | "DOS4GW.EXE" | "NETARENA.EXE" | \ + "NETIPX.EXE" | "NETMODEM.EXE" | "NETTERM.EXE" | \ + "ORDER.EXE" | "DOSINST.EXE" | "PM2WINST.EXE" | \ + "README.EXE" | "MMD.EXE" | "PMDL.EXE" | "RAP-HELP.EXE" | \ + "XRFILE01.EXE" | "XRFILE02.EXE" | "XRFILE03.EXE" | \ + "XRFILE04.EXE" | "FADER.EXE" | "SETSOUND.EXE" | \ + "DRIVER.EXE" | "EMUSET.EXE" | "GRAVUTIL.EXE" | "GUSEMU.EXE" | \ + "INSTGRPS.EXE" | "LOADER.EXE" | "LOADBOS.EXE" | "MEGAEM.EXE" | \ + "MIDIFIER.EXE" | "PLAYFILE.EXE" | "PLAYMIDI.EXE" | \ + "ULTRAJOY.EXE" | "ULTRAMID.EXE" | "ULTRAMIX.EXE" | \ + "ULTRINIT.EXE" | "OMF21.EXE" | "LOADSBOS.EXE" ) + ;; + *) + create_launcher "$(basename "$data_dir")" "$(basename "$executable")" + ;; + esac + done + fi +done +message_stream "Restarting EmulationStation...\n" 0 +echo echo "Restarting EmulationStation..." >> /tmp/logs/dosbox_scan.log +systemctl restart emustation +clear >/dev/console diff --git a/packages/games/emulators/dosbox-sdl2/package.mk b/packages/games/emulators/dosbox-sdl2/package.mk new file mode 100644 index 000000000..d4294fdc3 --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="dosbox-sdl2" +PKG_VERSION="0dd982477bff268c10558004dd1671e183b1a10f" +PKG_SHA256="2737817cd45889b21a4cef1e5fbd0782ffb5972f29bd3eaf7c3b8cc99cd9bac0" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/moralrecordings/dosbox" +PKG_URL="https://github.com/moralrecordings/dosbox/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux glibc glib systemd dbus alsa-lib SDL2 SDL2_net SDL_sound libpng zlib libvorbis flac libogg fluidsynth-git munt" +PKG_LONGDESC="This is an enhanced fork of DOSBox. It is currently in sync with revision 4156." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+lto" + +pre_configure_target() { + +if [ $ARCH == "arm" ]; then + EE_ARCH="armv7l" +else + EE_ARCH=$ARCH +fi + + # Clean up build directory + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --enable-core-inline \ + --enable-dynrec \ + --enable-unaligned_memory \ + --with-sdl-prefix=${SYSROOT_PREFIX}/usr" + + PKG_CONFIGURE_OPTS_TARGET+=" --host=$EE_ARCH" + +} + +pre_make_target() { + # Define DOSBox version + sed -e "s/SVN/SDL2/" -i ${PKG_BUILD}/config.h +} + +post_makeinstall_target() { + # Create config directory & install config + mkdir -p ${INSTALL}/usr/config/dosbox + cp -a ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin/ + cp -a ${PKG_DIR}/config/* ${INSTALL}/usr/config/dosbox/ +} diff --git a/packages/games/emulators/dosbox-sdl2/patches/dosbox-sdl2.995.01-add-mt32emu-MIDI-device.patch b/packages/games/emulators/dosbox-sdl2/patches/dosbox-sdl2.995.01-add-mt32emu-MIDI-device.patch new file mode 100644 index 000000000..fe03835af --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/patches/dosbox-sdl2.995.01-add-mt32emu-MIDI-device.patch @@ -0,0 +1,530 @@ +diff --git b/configure.ac a/configure.ac +index f393457e41..b14d3e9ad3 100644 +--- b/configure.ac ++++ a/configure.ac +@@ -421,6 +421,16 @@ if test x$have_wordexp_h = xyes ; then + AC_DEFINE(C_WORDEXP,1) + fi + ++AH_TEMPLATE(C_MUNT,[define to 1 if you have munt lib]) ++AC_CHECK_LIB(mt32emu, main, have_mt32emu_lib=yes, have_mt32emu_lib=no, ) ++if test x$have_mt32emu_lib = xyes ; then ++ LIBS="$LIBS -lmt32emu" ++ AC_DEFINE(C_MUNT,1) ++ AC_MSG_RESULT(yes) ++else ++ AC_MSG_WARN([Can't find munt, Roland MIDI device emulation disabled.]) ++fi ++ + AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support]) + AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , ) + AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , ) +diff --git b/src/dosbox.cpp a/src/dosbox.cpp +index 485f6a7958..18688a8e00 100644 +--- b/src/dosbox.cpp ++++ a/src/dosbox.cpp +@@ -500,6 +500,9 @@ void DOSBOX_Init(void) { + "coremidi", + #ifdef C_FLUIDSYNTH + "fluidsynth", ++#endif ++#ifdef C_MUNT ++ "mt32", + #endif + "none", + 0 +@@ -587,6 +590,10 @@ void DOSBOX_Init(void) { + Pint->Set_help("Fluidsynth chorus type. 0 is sine wave, 1 is triangle wave."); + #endif + ++#ifdef C_MUNT ++#include "mt32options.h" ++#endif ++ + #if C_DEBUG + secprop=control->AddSection_prop("debug",&DEBUG_Init); + #endif +diff --git b/src/gui/Makefile.am a/src/gui/Makefile.am +index 3fed5e68ae..eb994d86b8 100644 +--- b/src/gui/Makefile.am ++++ a/src/gui/Makefile.am +@@ -7,5 +7,6 @@ libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp dosbox_logo.h \ + render_templates_sai.h render_templates_hq.h \ + render_templates_hq2x.h render_templates_hq3x.h \ + midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h \ +- midi_coremidi.h sdl_gui.cpp dosbox_splash.h ++ midi_coremidi.h midi_mt32.h midi_mt32.cpp sdl_gui.cpp \ ++ dosbox_splash.h + +diff --git b/src/gui/midi.cpp a/src/gui/midi.cpp +index 16cdae2cb5..bed8b7f6bd 100644 +--- b/src/gui/midi.cpp ++++ a/src/gui/midi.cpp +@@ -95,6 +95,11 @@ MidiHandler Midi_none; + + #endif + ++#ifdef C_MUNT ++#include "midi_mt32.h" ++static MidiHandler_mt32 &Midi_mt32 = MidiHandler_mt32::GetInstance(); ++#endif ++ + DB_Midi midi; + + void MIDI_RawOutByte(Bit8u data) { +diff --git b/src/gui/midi_mt32.cpp a/src/gui/midi_mt32.cpp +new file mode 100644 +index 0000000000..d7beafba0b +--- /dev/null ++++ a/src/gui/midi_mt32.cpp +@@ -0,0 +1,283 @@ ++#include "config.h" ++#ifdef C_MUNT ++ ++#include "SDL_thread.h" ++#include "SDL_endian.h" ++#include "control.h" ++ ++#ifndef DOSBOX_MIDI_H ++#include "midi.h" ++#endif ++ ++#ifdef C_WORDEXP ++#include ++#endif ++ ++#include "midi_mt32.h" ++ ++static const Bitu MILLIS_PER_SECOND = 1000; ++ ++MidiHandler_mt32 &MidiHandler_mt32::GetInstance() { ++ static MidiHandler_mt32 midiHandler_mt32; ++ return midiHandler_mt32; ++} ++ ++const char *MidiHandler_mt32::GetName(void) { ++ return "mt32"; ++} ++ ++bool MidiHandler_mt32::Open(const char *conf) { ++ Section_prop *section = static_cast(control->GetSection("midi")); ++ const char *romDir = section->Get_string("mt32.romdir"); ++ if (romDir == NULL) romDir = "./"; // Paranoid NULL-check, should never happen ++ size_t romDirLen = strlen(romDir); ++ bool addPathSeparator = false; ++ if (romDirLen < 1) { ++ romDir = "./"; ++ } else if (4080 < romDirLen) { ++ LOG_MSG("MT32: mt32.romdir is too long, using the current dir."); ++ romDir = "./"; ++ } else { ++ char lastChar = romDir[strlen(romDir) - 1]; ++ addPathSeparator = lastChar != '/' && lastChar != '\\'; ++ } ++ ++ char pathName[4096]; ++ MT32Emu::FileStream controlROMFile; ++ MT32Emu::FileStream pcmROMFile; ++ ++ makeROMPathName(pathName, romDir, "CM32L_CONTROL.ROM", addPathSeparator); ++ if (!controlROMFile.open(pathName)) { ++ makeROMPathName(pathName, romDir, "MT32_CONTROL.ROM", addPathSeparator); ++ if (!controlROMFile.open(pathName)) { ++ LOG_MSG("MT32: Control ROM file not found"); ++ return false; ++ } ++ } ++ makeROMPathName(pathName, romDir, "CM32L_PCM.ROM", addPathSeparator); ++ if (!pcmROMFile.open(pathName)) { ++ makeROMPathName(pathName, romDir, "MT32_PCM.ROM", addPathSeparator); ++ if (!pcmROMFile.open(pathName)) { ++ LOG_MSG("MT32: PCM ROM file not found"); ++ return false; ++ } ++ } ++ const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile); ++ const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile); ++ ++ MT32Emu::AnalogOutputMode analogOutputMode = (MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog"); ++ ++ synth = new MT32Emu::Synth(&reportHandler); ++ if (!synth->open(*controlROMImage, *pcmROMImage, section->Get_int("mt32.partials"), analogOutputMode)) { ++ delete synth; ++ synth = NULL; ++ LOG_MSG("MT32: Error initialising emulation"); ++ return false; ++ } ++ MT32Emu::ROMImage::freeROMImage(controlROMImage); ++ MT32Emu::ROMImage::freeROMImage(pcmROMImage); ++ ++ if (strcmp(section->Get_string("mt32.reverb.mode"), "auto") != 0) { ++ Bit8u reverbsysex[] = {0x10, 0x00, 0x01, 0x00, 0x05, 0x03}; ++ reverbsysex[3] = (Bit8u)atoi(section->Get_string("mt32.reverb.mode")); ++ reverbsysex[4] = (Bit8u)section->Get_int("mt32.reverb.time"); ++ reverbsysex[5] = (Bit8u)section->Get_int("mt32.reverb.level"); ++ synth->writeSysex(16, reverbsysex, 6); ++ synth->setReverbOverridden(true); ++ } ++ ++ synth->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac")); ++ ++ synth->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo")); ++ noise = section->Get_bool("mt32.verbose"); ++ renderInThread = section->Get_bool("mt32.thread"); ++ ++ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", synth->getPartialCount()); ++ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", synth->getStereoOutputSampleRate()); ++ chan = MIXER_AddChannel(mixerCallBack, synth->getStereoOutputSampleRate(), "MT32"); ++ if (renderInThread) { ++ stopProcessing = false; ++ playPos = 0; ++ sampleRateRatio = MT32Emu::SAMPLE_RATE / (double)synth->getStereoOutputSampleRate(); ++ int chunkSize = section->Get_int("mt32.chunk"); ++ minimumRenderFrames = (chunkSize * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND; ++ int latency = section->Get_int("mt32.prebuffer"); ++ if (latency <= chunkSize) { ++ latency = 2 * chunkSize; ++ LOG_MSG("MT32: chunk length must be less than prebuffer length, prebuffer length reset to %i ms.", latency); ++ } ++ framesPerAudioBuffer = (latency * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND; ++ audioBufferSize = framesPerAudioBuffer << 1; ++ audioBuffer = new Bit16s[audioBufferSize]; ++ synth->render(audioBuffer, framesPerAudioBuffer - 1); ++ renderPos = (framesPerAudioBuffer - 1) << 1; ++ playedBuffers = 1; ++ lock = SDL_CreateMutex(); ++ framesInBufferChanged = SDL_CreateCond(); ++ thread = SDL_CreateThread(processingThread, NULL, NULL); ++ } ++ chan->Enable(true); ++ ++ open = true; ++ return true; ++} ++ ++void MidiHandler_mt32::Close(void) { ++ if (!open) return; ++ chan->Enable(false); ++ if (renderInThread) { ++ stopProcessing = true; ++ SDL_LockMutex(lock); ++ SDL_CondSignal(framesInBufferChanged); ++ SDL_UnlockMutex(lock); ++ SDL_WaitThread(thread, NULL); ++ thread = NULL; ++ SDL_DestroyMutex(lock); ++ lock = NULL; ++ SDL_DestroyCond(framesInBufferChanged); ++ framesInBufferChanged = NULL; ++ delete[] audioBuffer; ++ audioBuffer = NULL; ++ } ++ MIXER_DelChannel(chan); ++ chan = NULL; ++ synth->close(); ++ delete synth; ++ synth = NULL; ++ open = false; ++} ++ ++void MidiHandler_mt32::PlayMsg(Bit8u *msg) { ++ if (renderInThread) { ++ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp()); ++ } else { ++ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg)); ++ } ++} ++ ++void MidiHandler_mt32::PlaySysex(Bit8u *sysex, Bitu len) { ++ if (renderInThread) { ++ synth->playSysex(sysex, len, getMidiEventTimestamp()); ++ } else { ++ synth->playSysex(sysex, len); ++ } ++} ++ ++void MidiHandler_mt32::mixerCallBack(Bitu len) { ++ MidiHandler_mt32::GetInstance().handleMixerCallBack(len); ++} ++ ++int MidiHandler_mt32::processingThread(void *) { ++ MidiHandler_mt32::GetInstance().renderingLoop(); ++ return 0; ++} ++ ++void MidiHandler_mt32::makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator) { ++ ++#ifdef C_WORDEXP ++ wordexp_t p; ++ wordexp(romDir, &p, 0); ++ strcpy(pathName, p.we_wordv[0]); ++ wordfree(&p); ++#else ++ strcpy(pathName, romDir); ++#endif ++ ++ if (addPathSeparator) { ++ strcat(pathName, "/"); ++ } ++ strcat(pathName, fileName); ++} ++ ++MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), synth(NULL), thread(NULL) { ++} ++ ++MidiHandler_mt32::~MidiHandler_mt32() { ++ Close(); ++} ++ ++void MidiHandler_mt32::handleMixerCallBack(Bitu len) { ++ if (renderInThread) { ++ while (renderPos == playPos) { ++ SDL_LockMutex(lock); ++ SDL_CondWait(framesInBufferChanged, lock); ++ SDL_UnlockMutex(lock); ++ if (stopProcessing) return; ++ } ++ Bitu renderPosSnap = renderPos; ++ Bitu playPosSnap = playPos; ++ Bitu samplesReady = (renderPosSnap < playPosSnap) ? audioBufferSize - playPosSnap : renderPosSnap - playPosSnap; ++ if (len > (samplesReady >> 1)) { ++ len = samplesReady >> 1; ++ } ++ chan->AddSamples_s16(len, audioBuffer + playPosSnap); ++ playPosSnap += (len << 1); ++ while (audioBufferSize <= playPosSnap) { ++ playPosSnap -= audioBufferSize; ++ playedBuffers++; ++ } ++ playPos = playPosSnap; ++ renderPosSnap = renderPos; ++ const Bitu samplesFree = (renderPosSnap < playPosSnap) ? playPosSnap - renderPosSnap : audioBufferSize + playPosSnap - renderPosSnap; ++ if (minimumRenderFrames <= (samplesFree >> 1)) { ++ SDL_LockMutex(lock); ++ SDL_CondSignal(framesInBufferChanged); ++ SDL_UnlockMutex(lock); ++ } ++ } else { ++ synth->render((Bit16s *)MixTemp, len); ++ chan->AddSamples_s16(len, (Bit16s *)MixTemp); ++ } ++} ++ ++void MidiHandler_mt32::renderingLoop() { ++ while (!stopProcessing) { ++ const Bitu renderPosSnap = renderPos; ++ const Bitu playPosSnap = playPos; ++ Bitu samplesToRender; ++ if (renderPosSnap < playPosSnap) { ++ samplesToRender = playPosSnap - renderPosSnap - 2; ++ } else { ++ samplesToRender = audioBufferSize - renderPosSnap; ++ if (playPosSnap == 0) samplesToRender -= 2; ++ } ++ Bitu framesToRender = samplesToRender >> 1; ++ if ((framesToRender == 0) || ((framesToRender < minimumRenderFrames) && (renderPosSnap < playPosSnap))) { ++ SDL_LockMutex(lock); ++ SDL_CondWait(framesInBufferChanged, lock); ++ SDL_UnlockMutex(lock); ++ } else { ++ synth->render(audioBuffer + renderPosSnap, framesToRender); ++ renderPos = (renderPosSnap + samplesToRender) % audioBufferSize; ++ if (renderPosSnap == playPos) { ++ SDL_LockMutex(lock); ++ SDL_CondSignal(framesInBufferChanged); ++ SDL_UnlockMutex(lock); ++ } ++ } ++ } ++} ++ ++void MidiHandler_mt32::MT32ReportHandler::onErrorControlROM() { ++ LOG_MSG("MT32: Couldn't open Control ROM file"); ++} ++ ++void MidiHandler_mt32::MT32ReportHandler::onErrorPCMROM() { ++ LOG_MSG("MT32: Couldn't open PCM ROM file"); ++} ++ ++void MidiHandler_mt32::MT32ReportHandler::showLCDMessage(const char *message) { ++ LOG_MSG("MT32: LCD-Message: %s", message); ++} ++ ++void MidiHandler_mt32::MT32ReportHandler::printDebug(const char *fmt, va_list list) { ++ MidiHandler_mt32 &midiHandler_mt32 = MidiHandler_mt32::GetInstance(); ++ if (midiHandler_mt32.noise) { ++ char s[1024]; ++ strcpy(s, "MT32: "); ++ vsnprintf(s + 6, 1017, fmt, list); ++ LOG_MSG(s); ++ } ++} ++ ++#endif // C_MUNT +diff --git b/src/gui/midi_mt32.h a/src/gui/midi_mt32.h +new file mode 100644 +index 0000000000..5ceabe7400 +--- /dev/null ++++ a/src/gui/midi_mt32.h +@@ -0,0 +1,57 @@ ++#ifndef DOSBOX_MIDI_MT32_H ++#define DOSBOX_MIDI_MT32_H ++ ++#include "mixer.h" ++#include ++ ++struct SDL_Thread; ++ ++class MidiHandler_mt32 : public MidiHandler { ++public: ++ static MidiHandler_mt32 &GetInstance(void); ++ ++ const char *GetName(void); ++ bool Open(const char *conf); ++ void Close(void); ++ void PlayMsg(Bit8u *msg); ++ void PlaySysex(Bit8u *sysex, Bitu len); ++ ++private: ++ MixerChannel *chan; ++ MT32Emu::Synth *synth; ++ SDL_Thread *thread; ++ SDL_mutex *lock; ++ SDL_cond *framesInBufferChanged; ++ Bit16s *audioBuffer; ++ Bitu audioBufferSize; ++ Bitu framesPerAudioBuffer; ++ Bitu minimumRenderFrames; ++ double sampleRateRatio; ++ volatile Bitu renderPos, playPos, playedBuffers; ++ volatile bool stopProcessing; ++ bool open, noise, renderInThread; ++ ++ class MT32ReportHandler : public MT32Emu::ReportHandler { ++ protected: ++ virtual void onErrorControlROM(); ++ virtual void onErrorPCMROM(); ++ virtual void showLCDMessage(const char *message); ++ virtual void printDebug(const char *fmt, va_list list); ++ } reportHandler; ++ ++ static void mixerCallBack(Bitu len); ++ static int processingThread(void *); ++ static void makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator); ++ ++ MidiHandler_mt32(); ++ ~MidiHandler_mt32(); ++ ++ Bit32u inline getMidiEventTimestamp() { ++ return Bit32u((playedBuffers * framesPerAudioBuffer + (playPos >> 1)) * sampleRateRatio); ++ } ++ ++ void handleMixerCallBack(Bitu len); ++ void renderingLoop(); ++}; ++ ++#endif /* DOSBOX_MIDI_MT32_H */ +diff --git b/src/mt32options.h a/src/mt32options.h +new file mode 100644 +index 0000000000..85082157a8 +--- /dev/null ++++ a/src/mt32options.h +@@ -0,0 +1,98 @@ ++Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,""); ++Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n" ++ " Accepted file names are as follows:\n" ++ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n" ++ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file."); ++ ++Pbool = secprop->Add_bool("mt32.reverse.stereo",Property::Changeable::WhenIdle,false); ++Pbool->Set_help("Reverse stereo channels for MT-32 output"); ++ ++Pbool = secprop->Add_bool("mt32.verbose",Property::Changeable::WhenIdle,false); ++Pbool->Set_help("MT-32 debug logging"); ++ ++Pbool = secprop->Add_bool("mt32.thread",Property::Changeable::WhenIdle,false); ++Pbool->Set_help("MT-32 rendering in separate thread"); ++ ++const char *mt32chunk[] = {"2", "3", "16", "99", "100",0}; ++Pint = secprop->Add_int("mt32.chunk",Property::Changeable::WhenIdle,16); ++Pint->Set_values(mt32chunk); ++Pint->SetMinMax(2,100); ++Pint->Set_help("Minimum milliseconds of data to render at once.\n" ++ "Increasing this value reduces rendering overhead which may improve performance but also increases audio lag.\n" ++ "Valid for rendering in separate thread only."); ++ ++const char *mt32prebuffer[] = {"3", "4", "32", "199", "200",0}; ++Pint = secprop->Add_int("mt32.prebuffer",Property::Changeable::WhenIdle,32); ++Pint->Set_values(mt32prebuffer); ++Pint->SetMinMax(3,200); ++Pint->Set_help("How many milliseconds of data to render ahead.\n" ++ "Increasing this value may help to avoid underruns but also increases audio lag.\n" ++ "Cannot be set less than or equal to mt32.chunk value.\n" ++ "Valid for rendering in separate thread only."); ++ ++const char *mt32partials[] = {"8", "9", "32", "255", "256",0}; ++Pint = secprop->Add_int("mt32.partials",Property::Changeable::WhenIdle,32); ++Pint->Set_values(mt32partials); ++Pint->SetMinMax(8,256); ++Pint->Set_help("The maximum number of partials playing simultaneously."); ++ ++const char *mt32DACModes[] = {"0", "1", "2", "3",0}; ++Pint = secprop->Add_int("mt32.dac",Property::Changeable::WhenIdle,0); ++Pint->Set_values(mt32DACModes); ++Pint->Set_help("MT-32 DAC input emulation mode\n" ++ "Nice = 0 - default\n" ++ "Produces samples at double the volume, without tricks.\n" ++ "Higher quality than the real devices\n\n" ++ ++ "Pure = 1\n" ++ "Produces samples that exactly match the bits output from the emulated LA32.\n" ++ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n" ++ "Much less likely to overdrive than any other mode.\n" ++ "Half the volume of any of the other modes.\n" ++ "Perfect for developers while debugging :)\n\n" ++ ++ "GENERATION1 = 2\n" ++ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n" ++ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n" ++ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n" ++ ++ "GENERATION2 = 3\n" ++ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n" ++ "Bit order at DAC (where each number represents the original LA32 output bit number):\n" ++ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14"); ++ ++const char *mt32analogModes[] = {"0", "1", "2", "3",0}; ++Pint = secprop->Add_int("mt32.analog",Property::Changeable::WhenIdle,2); ++Pint->Set_values(mt32analogModes); ++Pint->Set_help("MT-32 analogue output emulation mode\n" ++ "Digital = 0\n" ++ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n" ++ "Fastest mode.\n\n" ++ ++ "Coarse = 1\n" ++ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n" ++ "A bit better sounding but also a bit slower.\n\n" ++ ++ "Accurate = 2 - default\n" ++ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n" ++ "which is passed through the LPF circuit without significant attenuation.\n" ++ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n" ++ ++ "Oversampled = 3\n" ++ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n" ++ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer."); ++ ++const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0}; ++Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto"); ++Pstring->Set_values(mt32reverbModes); ++Pstring->Set_help("MT-32 reverb mode"); ++ ++const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0}; ++Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5); ++Pint->Set_values(mt32reverbTimes); ++Pint->Set_help("MT-32 reverb decaying time"); ++ ++const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0}; ++Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3); ++Pint->Set_values(mt32reverbLevels); ++Pint->Set_help("MT-32 reverb level"); diff --git a/packages/games/emulators/dosbox-sdl2/scripts/dosbox.start b/packages/games/emulators/dosbox-sdl2/scripts/dosbox.start new file mode 100755 index 000000000..d106d5ad1 --- /dev/null +++ b/packages/games/emulators/dosbox-sdl2/scripts/dosbox.start @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +# Source predefined functions and variables +. /etc/profile + +set_audio pulseaudio + +# Set common variables +RR_DOSBOX_HOME=/storage/.dosbox +RR_DOSBOX_HOME_CONFIG=/storage/.config/dosbox + +# Create symlink to config dir +if [ ! -L ${RR_DOSBOX_HOME} ]; then + if [ -d ${RR_DOSBOX_HOME} ]; then + cp -rf ${RR_DOSBOX_HOME} ${RR_DOSBOX_HOME_CONFIG} + rm -rf ${RR_DOSBOX_HOME} + fi + ln -sf ${RR_DOSBOX_HOME_CONFIG} ${RR_DOSBOX_HOME} +fi + +# Run the emulator +dosbox "$@" > /tmp/logs/dosbox.log 2>&1 + +set_audio default diff --git a/packages/games/emulators/dosbox-x/config/dosbox-SDL2-MT32.conf b/packages/games/emulators/dosbox-x/config/dosbox-SDL2-MT32.conf new file mode 100644 index 000000000..6151374e2 --- /dev/null +++ b/packages/games/emulators/dosbox-x/config/dosbox-SDL2-MT32.conf @@ -0,0 +1,344 @@ +# This is the configuration file for DOSBox SDL2. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb, opengl, openglnb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen=true +# Note that VSYNC is be very demanding +vsync=false +fullresolution=0x0 +windowresolution=original +output=texture +# Place shaders in /storage/.config/dosbox/shaders +gl.shader=crt-easymode +texture.renderer=auto +autolock=true +sensitivity=100 +waitonerror=true +priority=highest,highest +# Input mapper file is looked for in the same directory as the specified conf +mapperfile=example.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language= +machine=svga_s3 +captures=capture +memsize=16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip=0 +aspect=true +scaler=none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core=auto +cputype=auto +cycles=auto +cycleup=10 +cycledown=20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound=false +rate=44100 +blocksize=1024 +prebuffer=20 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. +# or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401=intelligent +mididevice=mt32 +midiconfig= +# Place MT-32 roms here +mt32.romdir=/storage/roms/bios +mt32.reverse.stereo=false +mt32.verbose=false +mt32.thread=false +mt32.chunk=16 +mt32.prebuffer=32 +mt32.partials=32 +mt32.dac=0 +mt32.analog=2 +mt32.reverb.mode=auto +mt32.reverb.time=5 +mt32.reverb.level=3 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype=sb16 +sbbase=220 +irq=7 +dma=1 +hdma=5 +sbmixer=true +oplmode=auto +oplemu=default +oplrate=44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus=true +gusrate=44100 +gusbase=240 +gusirq=5 +gusdma=3 +# Place GUS files in /storage/roms/dos/ULTRASND +ultradir=C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker=true +pcrate=44100 +tandy=auto +tandyrate=44100 +disney=true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. + +joysticktype=fcs +timed=true +autofire=false +swap34=false +buttonwrap=false + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1=dummy +serial2=dummy +serial3=disabled +serial4=disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms=true +ems=true +umb=true +keyboardlayout=auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx=false + +[autoexec] +# Lines in this section will be run at startup. + +mount c /storage/roms/dos +c: +cd example +example.exe +#exit diff --git a/packages/games/emulators/dosbox-x/config/dosbox-SDL2.conf b/packages/games/emulators/dosbox-x/config/dosbox-SDL2.conf new file mode 100644 index 000000000..630a89349 --- /dev/null +++ b/packages/games/emulators/dosbox-x/config/dosbox-SDL2.conf @@ -0,0 +1,335 @@ +# This is the configuration file for DOSBox SDL2. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb, opengl, openglnb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen=true +# Note that VSYNC is be very demanding +vsync=false +fullresolution=0x0 +windowresolution=original +output=texture +# Place shaders in /storage/.config/dosbox/shaders +gl.shader=crt-easymode +texture.renderer=auto +autolock=true +sensitivity=100 +waitonerror=true +priority=highest,highest +# Input mapper file is looked for in the same directory as the specified conf +mapperfile=example.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language= +machine=svga_s3 +captures=capture +memsize=16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip=0 +aspect=true +scaler=none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core=auto +cputype=auto +cycles=auto +cycleup=10 +cycledown=20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound=false +rate=44100 +blocksize=1024 +prebuffer=20 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. +# or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401=intelligent +# FluidSynth Software Synthesizer +mididevice=fluidsynth +fluid.driver=pulseaudio +fluid.soundfont=/usr/share/soundfonts/GeneralUser.sf2 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype=sb16 +sbbase=220 +irq=7 +dma=1 +hdma=5 +sbmixer=true +oplmode=auto +oplemu=default +oplrate=44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus=true +gusrate=44100 +gusbase=240 +gusirq=5 +gusdma=3 +# Place GUS files in /storage/roms/dos/ULTRASND +ultradir=C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker=true +pcrate=44100 +tandy=auto +tandyrate=44100 +disney=true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. + +joysticktype=fcs +timed=true +autofire=false +swap34=false +buttonwrap=false + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1=dummy +serial2=dummy +serial3=disabled +serial4=disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms=true +ems=true +umb=true +keyboardlayout=auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx=false + +[autoexec] +# Lines in this section will be run at startup. + +mount c /storage/roms/pc +c: +@echo off +echo ######################################################## +echo # DOSBox SDL2 default config # +echo ######################################################## +echo. diff --git a/packages/games/emulators/dosbox-x/config/dosbox-SVN.conf b/packages/games/emulators/dosbox-x/config/dosbox-SVN.conf new file mode 100644 index 000000000..bd7410faf --- /dev/null +++ b/packages/games/emulators/dosbox-x/config/dosbox-SVN.conf @@ -0,0 +1,357 @@ +# This is the configuration file for DOSBox SVN. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface.On Windows 10 with display scaling (Scale and layout) set to a value above 100%, it is recommended +# to use a lower full/windowresolution, in order to avoid window size problems. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. The optional second parameter specifies vertical sensitivity (e.g. 100,-50). +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen = true +vsync = false +fullresolution = 0x0 +windowresolution = original +output = texturenb +gl.shader = +texture.renderer = auto +autolock = true +sensitivity = 100 +waitonerror = true +priority = higher,normal +mapperfile = mapper-sdl2-SVN.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language = +machine = svga_s3 +captures = capture +memsize = 16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down! +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# To fit a scaler in the resolution used at full screen may require a border or side bars, +# to fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip = 0 +aspect = true +scaler = none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core = auto +cputype = auto +cycles = auto +cycleup = 10 +cycledown = 20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound = false +rate = 44100 +blocksize = 1024 +prebuffer = 25 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, fluidsynth, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id or part of the name of the device you want to use (find the id/name with mixer/listmidi). +# Or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# fluid.driver: Driver to use with Fluidsynth, not needed under Windows. Available drivers depend on what Fluidsynth was compiled with +# Possible values: pulseaudio, alsa, oss, coreaudio, dsound, portaudio, sndman, jack, file, default. +# fluid.soundfont: Soundfont to use with Fluidsynth. One must be specified. +# fluid.samplerate: Sample rate to use with Fluidsynth. +# fluid.gain: Fluidsynth gain. +# fluid.polyphony: Fluidsynth polyphony. +# fluid.cores: Fluidsynth CPU cores to use, default. +# fluid.periods: Fluidsynth periods. +# fluid.periodsize: Fluidsynth period size. +# fluid.reverb: Fluidsynth use reverb. +# Possible values: no, yes. +# fluid.chorus: Fluidsynth use chorus. +# Possible values: no, yes. +# fluid.reverb,roomsize: Fluidsynth reverb room size. +# fluid.reverb.damping: Fluidsynth reverb damping. +# fluid.reverb.width: Fluidsynth reverb width. +# fluid.reverb.level: Fluidsynth reverb level. +# fluid.chorus.number: Fluidsynth chorus voices +# fluid.chorus.level: Fluidsynth chorus level. +# fluid.chorus.speed: Fluidsynth chorus speed. +# fluid.chorus.depth: Fluidsynth chorus depth. +# fluid.chorus.type: Fluidsynth chorus type. 0 is sine wave, 1 is triangle wave. +# Possible values: 0, 1. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401 = intelligent +# FluidSynth Software Synthesizer +mididevice = fluidsynth +fluid.driver = pulseaudio +fluid.soundfont = /usr/share/soundfonts/GeneralUser.sf2 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast, mame. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype = sb16 +sbbase = 220 +irq = 7 +dma = 1 +hdma = 5 +sbmixer = true +oplmode = auto +oplemu = default +oplrate = 44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus = false +gusrate = 44100 +gusbase = 240 +gusirq = 5 +gusdma = 3 +ultradir = C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker = true +pcrate = 44100 +tandy = auto +tandyrate = 44100 +disney = true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. Can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. +# circularinput: enable translation of circular input to square output. +# Try enabling this if your left analog stick can only move in a circle. +# deadzone: the percentage of motion to ignore. 100 turns the stick into a digital one. + +joysticktype = auto +timed = true +autofire = false +swap34 = false +buttonwrap = false +circularinput = false +deadzone = 10 + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1 = dummy +serial2 = dummy +serial3 = disabled +serial4 = disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms = true +ems = true +umb = true +keyboardlayout = auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx = false + +[autoexec] +# Lines in this section will be run at startup. +# You can put your MOUNT lines here. + + diff --git a/packages/games/emulators/dosbox-x/config/dosbox.conf b/packages/games/emulators/dosbox-x/config/dosbox.conf new file mode 100644 index 000000000..630a89349 --- /dev/null +++ b/packages/games/emulators/dosbox-x/config/dosbox.conf @@ -0,0 +1,335 @@ +# This is the configuration file for DOSBox SDL2. (Please use the latest version of DOSBox) +# Lines starting with a # are comment lines and are ignored by DOSBox. +# They are used to (briefly) document the effect of each option. + +[sdl] +# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) +# vsync: Sync to Vblank IF supported by the output device and renderer (if relevant). +# It can reduce screen flickering, but it can also result in a slow DOSBox. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# output: What video system to use for output. +# Possible values: surface, texture, texturenb, opengl, openglnb. +# gl.shader: What set of GLSL shaders to use with an OpenGL output. Keep empty if this is not desired. +# Note that in case it is used, the respective shader files must be found in the "shaders" subdirectory +# relatively to where the default DOSBox configuration fiel is stored. For shader file naming convention, +# suppose that you have a pair of shader files ready: mysample.vert and mysample.frag. +# Then shader=mysample should be set. +# +# texture.renderer: Choose a renderer driver if output=texture or output=texturenb. Use output=auto for an automatic choice. +# Possible values: auto, opengl, software. +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# sensitivity: Mouse sensitivity. +# waitonerror: Wait before closing the console if dosbox has an error. +# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. + +fullscreen=true +# Note that VSYNC is be very demanding +vsync=false +fullresolution=0x0 +windowresolution=original +output=texture +# Place shaders in /storage/.config/dosbox/shaders +gl.shader=crt-easymode +texture.renderer=auto +autolock=true +sensitivity=100 +waitonerror=true +priority=highest,highest +# Input mapper file is looked for in the same directory as the specified conf +mapperfile=example.map + +[dosbox] +# language: Select another language file. +# machine: The type of machine DOSBox tries to emulate. +# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. +# captures: Directory where things like wave, midi, screenshot get captured. +# memsize: Amount of memory DOSBox has in megabytes. +# This value is best left at its default to avoid problems with some games, +# though few games might require a higher value. +# There is generally no speed advantage when raising this value. + +language= +machine=svga_s3 +captures=capture +memsize=16 + +[render] +# frameskip: How many frames DOSBox skips before drawing one. +# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. + +frameskip=0 +aspect=true +scaler=none + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and +# appropriate. +# Possible values: auto, dynamic, normal, simple. +# cputype: CPU Type used in emulation. auto is the fastest choice. +# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. +# cycles: Amount of instructions DOSBox tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed amount of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12) +# cycledown: Setting it lower than 100 will be a percentage. + +core=auto +cputype=auto +cycles=auto +cycleup=10 +cycledown=20 + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. + +nosound=false +rate=44100 +blocksize=1024 +prebuffer=20 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, none. +# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. +# or in the case of coreaudio, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.reverse.stereo: Reverse stereo channels for MT-32 output +# mt32.verbose: MT-32 debug logging +# mt32.thread: MT-32 rendering in separate thread +# mt32.chunk: Minimum milliseconds of data to render at once. +# Increasing this value reduces rendering overhead which may improve performance but also increases audio lag. +# Valid for rendering in separate thread only. +# Possible values: 2, 3, 16, 99, 100. +# mt32.prebuffer: How many milliseconds of data to render ahead. +# Increasing this value may help to avoid underruns but also increases audio lag. +# Cannot be set less than or equal to mt32.chunk value. +# Valid for rendering in separate thread only. +# Possible values: 3, 4, 32, 199, 200. +# mt32.partials: The maximum number of partials playing simultaneously. +# Possible values: 8, 9, 32, 255, 256. +# mt32.dac: MT-32 DAC input emulation mode +# Nice = 0 - default +# Produces samples at double the volume, without tricks. +# Higher quality than the real devices +# +# Pure = 1 +# Produces samples that exactly match the bits output from the emulated LA32. +# Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range) +# Much less likely to overdrive than any other mode. +# Half the volume of any of the other modes. +# Perfect for developers while debugging :) +# +# GENERATION1 = 2 +# Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia). +# Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX +# +# GENERATION2 = 3 +# Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG). +# Bit order at DAC (where each number represents the original LA32 output bit number): +# 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14 +# Possible values: 0, 1, 2, 3. +# mt32.analog: MT-32 analogue output emulation mode +# Digital = 0 +# Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance. +# Fastest mode. +# +# Coarse = 1 +# Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. +# A bit better sounding but also a bit slower. +# +# Accurate = 2 - default +# Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz, +# which is passed through the LPF circuit without significant attenuation. +# Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1. +# +# Oversampled = 3 +# Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz. +# Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer. +# Possible values: 0, 1, 2, 3. +# mt32.reverb.mode: MT-32 reverb mode +# Possible values: 0, 1, 2, 3, auto. +# mt32.reverb.time: MT-32 reverb decaying time +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. +# mt32.reverb.level: MT-32 reverb level +# Possible values: 0, 1, 2, 3, 4, 5, 6, 7. + +mpu401=intelligent +# FluidSynth Software Synthesizer +mididevice=fluidsynth +fluid.driver=pulseaudio +fluid.soundfont=/usr/share/soundfonts/GeneralUser.sf2 + +[sblaster] +# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. +# sbbase: The IO address of the soundblaster. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. +# irq: The IRQ number of the soundblaster. +# Possible values: 7, 5, 3, 9, 10, 11, 12. +# dma: The DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# hdma: The High DMA number of the soundblaster. +# Possible values: 1, 5, 0, 3, 6, 7. +# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none. +# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). +# Possible values: default, compat, fast. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. + +sbtype=sb16 +sbbase=220 +irq=7 +dma=1 +hdma=5 +sbmixer=true +oplmode=auto +oplemu=default +oplrate=44100 + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. + +gus=true +gusrate=44100 +gusbase=240 +gusirq=5 +gusdma=3 +# Place GUS files in /storage/roms/dos/ULTRASND +ultradir=C:\ULTRASND + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). + +pcspeaker=true +pcrate=44100 +tandy=auto +tandyrate=44100 +disney=true + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), none, +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# none disables joystick emulation. +# auto chooses emulation depending on real joystick(s). +# (Remember to reset dosbox's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. + +joysticktype=fcs +timed=true +autofire=false +swap34=false +buttonwrap=false + +[serial] +# serial1: set type of device connected to com port. +# Can be disabled, dummy, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket (all optional). +# Example: serial1=modem listenport:5000 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, directserial. + +serial1=dummy +serial2=dummy +serial3=disabled +serial4=disabled + +[dos] +# xms: Enable XMS support. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false. +# umb: Enable UMB support. +# keyboardlayout: Language code of the keyboard layout (or none). + +xms=true +ems=true +umb=true +keyboardlayout=auto + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. + +ipx=false + +[autoexec] +# Lines in this section will be run at startup. + +mount c /storage/roms/pc +c: +@echo off +echo ######################################################## +echo # DOSBox SDL2 default config # +echo ######################################################## +echo. diff --git a/packages/games/emulators/dosbox-x/package.mk b/packages/games/emulators/dosbox-x/package.mk new file mode 100644 index 000000000..e630bd708 --- /dev/null +++ b/packages/games/emulators/dosbox-x/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="dosbox-x" +PKG_VERSION="684836fab51b9b4fc9d6616de126fc9a5bf21d59" +PKG_SHA256="c5caa65b39621907c417dc50633320f8a407206e46a1527b2e37c10a7baafa52" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/joncampbell123/dosbox-x" +PKG_URL="$PKG_SITE/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux glibc glib systemd dbus alsa-lib SDL2 SDL2_net SDL_sound libpng zlib libvorbis flac libogg fluidsynth-git munt" +PKG_LONGDESC="DOSBox-X fork of the DOSBox project." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+lto" + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --enable-core-inline \ + --enable-dynrec \ + --enable-unaligned_memory \ + --disable-sdl \ + --enable-sdl2 \ + --enable-mt32 \ + --with-sdl2-prefix=${SYSROOT_PREFIX}/usr" +} + +pre_make_target() { + # Define DOSBox version + sed -e "s/SVN/SDL2/" -i ${PKG_BUILD}/config.h +} + +post_makeinstall_target() { + # Create config directory & install config + mkdir -p ${INSTALL}/usr/config/distribution/configs/dosbox/ + cp -a ${PKG_DIR}/scripts/* ${INSTALL}/usr/bin/ + cp -a ${PKG_DIR}/config/* ${INSTALL}/usr/config/distribution/configs/dosbox/ +} diff --git a/packages/games/emulators/dosbox-x/patches/000-arm_configure.patch b/packages/games/emulators/dosbox-x/patches/000-arm_configure.patch new file mode 100644 index 000000000..76735764b --- /dev/null +++ b/packages/games/emulators/dosbox-x/patches/000-arm_configure.patch @@ -0,0 +1,17 @@ +diff --git a/configure.ac b/configure.ac +index 407d553..e15473b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -249,6 +249,12 @@ dnl The target cpu checks for dynamic cores + AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has]) + AC_MSG_CHECKING(for target cpu type) + case "$host_cpu" in ++ arm) ++ AC_DEFINE(C_TARGETCPU,ARMV7LE) ++ AC_MSG_RESULT(ARMv7 Little Endian) ++ c_targetcpu="arm" ++ c_unalignedmemory=yes ++ ;; + x86_64 | amd64) + AC_DEFINE(C_TARGETCPU,X86_64) + AC_MSG_RESULT(x86-64 bit compatible) diff --git a/packages/games/emulators/dosbox-x/patches/001-sdl-config.patch b/packages/games/emulators/dosbox-x/patches/001-sdl-config.patch new file mode 100644 index 000000000..87fe0bd17 --- /dev/null +++ b/packages/games/emulators/dosbox-x/patches/001-sdl-config.patch @@ -0,0 +1,46 @@ +diff --git a/acinclude.m4 b/acinclude.m4 +index 9b85f7f..a2c7117 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -14,35 +14,13 @@ AC_ARG_ENABLE(sdl2, [ --enable-sdl2 Enable SDL 2.x], + + SDL2_CONFIG=no + if test x$enable_sdl2enable = xyes ; then +- if test x$sdl2_exec_prefix != x ; then +- sdl2_args="$sdl2_args --exec-prefix=$sdl2_exec_prefix" +- if test x${SDL2_CONFIG+set} != xset ; then +- SDL2_CONFIG=$sdl2_exec_prefix/bin/sdl2-config +- fi +- fi +- if test x$sdl2_prefix != x ; then +- sdl2_args="$sdl2_args --prefix=$sdl2_prefix" +- if test x${SDL2_CONFIG+set} != xset ; then +- SDL2_CONFIG=$sdl2_prefix/bin/sdl2-config +- fi +- fi +- +- if test -x vs2015/sdl2/linux-host/bin/sdl2-config ; then +- SDL2_CONFIG=vs2015/sdl2/linux-host/bin/sdl2-config +- PATH=vs2015/sdl2/linux-host/bin:$PATH +- fi +- ++ ++ SDL2_CONFIG=$sdl2_prefix/bin/sdl2-config + AC_PATH_PROG(SDL2_CONFIG, sdl2-config, no) +- min_sdl2_version=ifelse([$1], ,0.11.0,$1) +- AC_MSG_CHECKING(for SDL2 - version >= $min_sdl2_version) +- no_sdl2="" +- if test "$SDL2_CONFIG" = "no" ; then +- no_sdl2=yes +- else +- SDL2_CFLAGS=`$SDL2_CONFIG $sdl2conf_args --cflags` +- SDL2_LIBS=`$SDL2_CONFIG $sdl2conf_args --libs` +- AC_DEFINE(C_SDL2,1) +- fi ++ SDL2_CFLAGS=`$SDL2_CONFIG $sdl2conf_args --cflags` ++ SDL2_LIBS=`$SDL2_CONFIG $sdl2conf_args --libs` ++ AC_DEFINE(C_SDL2,1) ++ + fi + + AC_SUBST(SDL2_CFLAGS) diff --git a/packages/games/emulators/dosbox-x/patches/003-dosboxconf.patch b/packages/games/emulators/dosbox-x/patches/003-dosboxconf.patch new file mode 100644 index 000000000..00a77495b --- /dev/null +++ b/packages/games/emulators/dosbox-x/patches/003-dosboxconf.patch @@ -0,0 +1,49 @@ +diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp +index ec6ba7b..f689b3c 100644 +--- a/src/gui/sdlmain.cpp ++++ b/src/gui/sdlmain.cpp +@@ -947,7 +947,7 @@ + #elif defined(HAIKU) + #define DEFAULT_CONFIG_FILE "~/config/settings/dosbox-x/dosbox-x.conf" + #else /*linux freebsd*/ +-# define DEFAULT_CONFIG_FILE "/.dosboxrc" ++# define DEFAULT_CONFIG_FILE "/dosbox-x.conf" + #endif + + #if C_SET_PRIORITY +diff --git a/src/misc/cross.cpp b/src/misc/cross.cpp +index 05a5893..74daf41 100644 +--- a/src/misc/cross.cpp ++++ b/src/misc/cross.cpp +@@ -89,7 +89,7 @@ + #elif defined(RISCOS) + in = "//DosBox-X"; + #elif !defined(HX_DOS) +- in = "~/.config/dosbox-x"; ++ in = "/storage/.config/distribution/configs/dosbox-x"; + ResolveHomedir(in); + #endif + in += CROSS_FILESPLIT; +@@ -97,11 +97,11 @@ + + void Cross::GetPlatformConfigName(std::string& in) { + #ifdef WIN32 +-#define DEFAULT_CONFIG_FILE "dosbox-x-" VERSION ".conf" ++#define DEFAULT_CONFIG_FILE "dosbox-x.conf" + #elif defined(MACOSX) + #define DEFAULT_CONFIG_FILE "DOSBox-X " VERSION " Preferences" + #else /*linux freebsd*/ +-#define DEFAULT_CONFIG_FILE "dosbox-x-" VERSION ".conf" ++#define DEFAULT_CONFIG_FILE "dosbox-x.conf" + #endif + in = DEFAULT_CONFIG_FILE; + } +@@ -123,7 +123,7 @@ + in = "//DosBox-X"; + mkdir(in.c_str(),0700); + #elif !defined(HX_DOS) +- in = "~/.config/dosbox-x"; ++ in = "/storage/.config/distribution/configs/dosbox-x"; + ResolveHomedir(in); + mkdir(in.c_str(),0700); + #endif diff --git a/packages/games/emulators/dosbox-x/scripts/dosbox-x.start b/packages/games/emulators/dosbox-x/scripts/dosbox-x.start new file mode 100755 index 000000000..5eeac2421 --- /dev/null +++ b/packages/games/emulators/dosbox-x/scripts/dosbox-x.start @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +# Source predefined functions and variables +. /etc/profile + +set_audio pulseaudio + +# Set common variables +RR_DOSBOX_HOME=/storage/.dosbox +RR_DOSBOX_HOME_CONFIG=/storage/.config/distribution/configs/dosbox-x + +# Create symlink to config dir +if [ ! -L ${RR_DOSBOX_HOME} ]; then + if [ -d ${RR_DOSBOX_HOME} ]; then + cp -rf ${RR_DOSBOX_HOME} ${RR_DOSBOX_HOME_CONFIG} + rm -rf ${RR_DOSBOX_HOME} + fi + ln -sf ${RR_DOSBOX_HOME_CONFIG} ${RR_DOSBOX_HOME} +fi + +# Run the emulator +ARG="$(echo $1 | sed 's=.*/==;s/\.[^.]*$//')" + +dosbox-x -c "${ARG}" > /tmp/logs/dosbox-x.log 2>&1 + +set_audio default diff --git a/packages/games/emulators/ecwolf/config/ecwolf.cfg b/packages/games/emulators/ecwolf/config/ecwolf.cfg new file mode 100644 index 000000000..e3425ff28 --- /dev/null +++ b/packages/games/emulators/ecwolf/config/ecwolf.cfg @@ -0,0 +1,5 @@ +BaseDataPaths = ".;$PROGDIR;/storage/roms/ecwolf;/storage/roms/ecwolf/spear;/storage/roms/ecwolf/ark"; +FullScreenWidth = 640; +FullScreenHeight = 480; +WindowedScreenWidth = 640; +WindowedScreenHeight = 480; diff --git a/packages/games/emulators/ecwolf/ecwolf.sh b/packages/games/emulators/ecwolf/ecwolf.sh new file mode 100644 index 000000000..234b14f41 --- /dev/null +++ b/packages/games/emulators/ecwolf/ecwolf.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC/351ELEC) + +. /etc/profile +. /etc/os-release + +EE_DEVICE=${HW_DEVICE} +CONFIG_DIR="/storage/.config/distribution/ecwolf" +CONFIG_FILE="${CONFIG_DIR}/ecwolf.cfg" +SAVE_DIR="/storage/roms/gamedata/ecwolf" + +if [ ! -L "/storage/.config/ecwolf" ] +then + ln -sf "/storage/.config/distribution/ecwolf" "/storage/.config/ecwolf" +fi + +if [ ! -f "/storage/.config/distribution/ecwolf/ecwolf.cfg" ] +then + cp -rf /usr/config/distribution/ecwolf/ecwolf.cfg /storage/.config/distribution/ecwolf/ +fi + +mkdir -p ${SAVE_DIR} + +params=" --config ${CONFIG_FILE} --savedir ${SAVE_DIR}" + +if [[ "$EE_DEVICE" == RG351P ]]; then + params+=" --res 480 320" +fi +if [[ "$EE_DEVICE" == RG351V ]] || [[ "$EE_DEVICE" == RG351MP ]]; then + params+=" --res 640 480" +fi + +# data can be SD2 SD3 SOD WL6 or N3D and it's passed as the ROM +DATA=${1#*.} + +# If its a mod (extension .ecwolf) read the file and parse the data +if [ ${DATA} == "ecwolf" ]; then + dos2unix "${1}" + while IFS== read -r key value; do + if [ "$key" == "DATA" ]; then + params+=" --data $value" + fi + if [ "$key" == "PK3" ]; then + params+=" --file $value" + fi + if [ "$key" == "PK3_1" ]; then + params+=" --file $value" + fi + if [ "$key" == "PK3_2" ]; then + params+=" --file $value" + fi + if [ "$key" == "PK3_3" ]; then + params+=" --file $value" + fi + if [ "$key" == "PK3_4" ]; then + params+=" --file $value" + fi + done < "${1}" +else + params+=" --data ${DATA}" +fi + +cd "${CONFIG_DIR}" +/usr/bin/ecwolf ${params} > /tmp/logs/ecwolf.log 2>&1 diff --git a/packages/games/emulators/ecwolf/package.mk b/packages/games/emulators/ecwolf/package.mk new file mode 100644 index 000000000..7402a3232 --- /dev/null +++ b/packages/games/emulators/ecwolf/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="ecwolf" +PKG_VERSION="3ce6e4d064b54eec72386fe949ec7be20746c16c" +PKG_LICENSE="GPLv2" +PKG_SITE="https://bitbucket.org/ecwolf/ecwolf" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_mixer SDL2_net ecwolf:host" +PKG_LONGDESC="ECWolf is a port of the Wolfenstein 3D engine based of Wolf4SDL. It combines the original Wolfenstein 3D engine with the user experience of ZDoom to create the most user and mod author friendly Wolf3D source port." +PKG_TOOLCHAIN="cmake-make" +GET_HANDLER_SUPPORT="git" + +pre_patch() { + find $(echo "${PKG_BUILD}" | cut -f1 -d\ ) -type f -exec dos2unix -q {} \; +} + +pre_build_host() { +HOST_CMAKE_OPTS="" +} + +make_host() { + cmake . -DNO_GTK=ON + make +} + +makeinstall_host() { +: #no +} + +pre_configure_target() { +PKG_CMAKE_OPTS_TARGET=" -DNO_GTK=ON \ + -DFORCE_CROSSCOMPILE=ON \ + -DIMPORT_EXECUTABLES=$PKG_BUILD/.$HOST_NAME/ImportExecutables.cmake + -DCMAKE_BUILD_TYPE=Release" + + cd $PKG_BUILD/deps/gdtoa + $HOST_CC -o rithchk arithchk.c -Wall -Wextra + ./rithchk > $PKG_BUILD/deps/gdtoa/arith.h + + $HOST_CC -o qnan qnan.c -Wall -Wextra + ./qnan > $PKG_BUILD/deps/gdtoa/gd_qnan.h + cd $PKG_BUILD +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_BUILD/ecwolf $INSTALL/usr/bin/ + cp $PKG_DIR/ecwolf.sh $INSTALL/usr/bin/ + + mkdir -p $INSTALL/usr/config/distribution/ecwolf + cp $PKG_BUILD/ecwolf.pk3 $INSTALL/usr/config/distribution/ecwolf/ + cp $PKG_DIR/config/* $INSTALL/usr/config/distribution/ecwolf/ +} diff --git a/packages/games/emulators/ecwolf/patches/ecwolf-001-add-video-modes.patch b/packages/games/emulators/ecwolf/patches/ecwolf-001-add-video-modes.patch new file mode 100644 index 000000000..84e4dd747 --- /dev/null +++ b/packages/games/emulators/ecwolf/patches/ecwolf-001-add-video-modes.patch @@ -0,0 +1,12 @@ +diff --git a/src/sdlvideo.cpp b/src/sdlvideo.cpp +index 83e9c73..32a9ee5 100644 +--- a/src/sdlvideo.cpp ++++ b/src/sdlvideo.cpp +@@ -388,6 +388,7 @@ static MiniModeInfo WinModes[] = + { 400, 225 }, // 16:9 + { 400, 300 }, + { 480, 270 }, // 16:9 ++ { 480, 320 }, // 3:2 + { 480, 360 }, + { 512, 288 }, // 16:9 + { 512, 384 }, diff --git a/packages/games/emulators/ecwolf/patches/ecwolf-002-add-exit-menu.patch b/packages/games/emulators/ecwolf/patches/ecwolf-002-add-exit-menu.patch new file mode 100644 index 000000000..21239b037 --- /dev/null +++ b/packages/games/emulators/ecwolf/patches/ecwolf-002-add-exit-menu.patch @@ -0,0 +1,13 @@ +diff --git a/src/wl_play.cpp b/src/wl_play.cpp +index aa9e527..5c3fa72 100644 +--- a/src/wl_play.cpp ++++ b/src/wl_play.cpp +@@ -101,6 +101,8 @@ ControlScheme controlScheme[] = + { bt_zoom, "Zoom", -1, -1, -1, CS_AxisDigital, 0 }, + { bt_automap, "Automap", -1, -1, -1, CS_AxisDigital, 0 }, + { bt_showstatusbar, "Show Status", -1, sc_Tab, -1, CS_AxisDigital, 0 }, ++ { bt_pause, "Pause Game", -1, sc_Enter, -1, CS_AxisDigital, 0 }, ++ { bt_esc, "Escape Game", -1, sc_Escape, -1, CS_AxisDigital, 0 }, + + // End of List + { bt_nobutton, NULL, -1, -1, -1, CS_AxisDigital, 0 } diff --git a/packages/games/emulators/gzdoom/config/RG351MP/gzdoom.ini b/packages/games/emulators/gzdoom/config/RG351MP/gzdoom.ini new file mode 100644 index 000000000..7cf5c5cdc --- /dev/null +++ b/packages/games/emulators/gzdoom/config/RG351MP/gzdoom.ini @@ -0,0 +1,746 @@ +# This file was generated by GZDoom g4.8pre-28-gbc75dc056 on 2021-10-16 16:14:47 +# These are the directories to automatically search for IWADs. +# Each directory should be on a separate line, preceded by Path= +[IWADSearch.Directories] +Path=. +Path=$DOOMWADDIR +Path=/storage/.config/distribution/gzdoom +Path=/storage/roms/doom + +# These are the directories to search for wads added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for IWADSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/gzdoom +Path=/storage/roms/doom +Path=$DOOMWADDIR + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for IWADSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/gzdoom/soundfonts +Path=/storage/.config/distribution/gzdoom/fm_banks + +# Files to automatically execute when running the corresponding game. +# Each file should be on its own line, preceded by Path= + +[Doom.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +# WAD files to always load. These are loaded after the IWAD but before +# any files added with -file. Place each file on its own line, preceded +# by Path= +[Global.Autoload] + +# Wad files to automatically load depending on the game and IWAD you are +# playing. You may have have files that are loaded for all similar IWADs +# (the game) and files that are only loaded for particular IWADs. For example, +# any files listed under 'doom.Autoload' will be loaded for any version of Doom, +# but files listed under 'doom.doom2.Autoload' will only load when you are +# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under +# 'doom.doom2.commercial.Autoload' only when playing doom2.wad. + +[doom.Autoload] + +[doom.id.Autoload] + +[doom.id.doom2.Autoload] + +[doom.id.doom2.commercial.Autoload] + +[doom.id.doom2.commercial.french.Autoload] + +[doom.id.doom2.commercial.xbox.Autoload] + +[doom.id.doom2.unity.Autoload] + +[doom.id.doom2.bfg.Autoload] + +[doom.id.doom2.plutonia.Autoload] + +[doom.id.doom2.plutonia.unity.Autoload] + +[doom.id.doom2.tnt.Autoload] + +[doom.id.doom2.tnt.unity.Autoload] + +[doom.id.doom1.Autoload] + +[doom.id.doom1.registered.Autoload] + +[doom.id.doom1.ultimate.Autoload] + +[doom.id.doom1.ultimate.xbox.Autoload] + +[doom.id.wadsmoosh.Autoload] + +[doom.id.doom1.unity.Autoload] + +[doom.id.doom1.bfg.Autoload] + +[doom.freedoom.Autoload] + +[doom.freedoom.demo.Autoload] + +[doom.freedoom.phase1.Autoload] + +[doom.freedoom.phase2.Autoload] + +[doom.freedoom.freedm.Autoload] + +[heretic.Autoload] + +[heretic.heretic.Autoload] + +[heretic.shadow.Autoload] + +[blasphemer.Autoload] + +[hexen.Autoload] + +[hexen.deathkings.Autoload] + +[hexen.hexen.Autoload] + +[strife.Autoload] + +[strife.strife.Autoload] + +[strife.veteran.Autoload] + +[chex.Autoload] + +[chex.chex1.Autoload] + +[chex.chex3.Autoload] + +[urbanbrawl.Autoload] + +[hacx.Autoload] + +[hacx.hacx1.Autoload] + +[hacx.hacx2.Autoload] + +[harmony.Autoload] + +[square.Autoload] + +[square.squareware.Autoload] + +[square.square.Autoload] + +[delaweare.Autoload] + +[woolball.Autoload] + +[woolball.rotwb.Autoload] + +[LastRun] +Version=222 + +[GlobalSettings] +I_FriendlyWindowTitle=1 +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=false +autoloadlights=false +autoloadwidescreen=true +autosavecount=4 +autosavenum=1 +chase_dist=90 +chase_height=-8 +cl_capfps=false +cl_defaultconfiguration=0 +cl_noprediction=false +cl_oldfreelooklimit=false +cl_predict_lerpscale=0.05000000074505806 +cl_predict_lerpthreshold=2 +cl_predict_specials=true +cl_run=false +cl_waitforsave=true +con_4bitansi=false +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +con_printansi=true +defaultiwad= +demo_compress=true +developer=0 +disableautoload=false +disableautosave=0 +enablescriptscreenshot=false +fluid_chorus=false +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=0.5 +fluid_interp=1 +fluid_lib= +fluid_patchset=gzdoom +fluid_reverb=false +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=1 +fluid_voices=128 +freelook=true +gl_billboard_faces_camera=false +gl_billboard_mode=0 +gl_billboard_particles=true +gl_cachenodes=true +gl_cachetime=0.6000000238418579 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_distfog=70 +gl_dither_bpc=0 +gl_enhanced_nv_stealth=3 +gl_es=true +gl_finishbeforeswap=false +gl_fxaa=0 +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_particles=true +gl_light_shadowmap=false +gl_light_sprites=true +gl_lights=false +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_multisample=1 +gl_multithread=true +gl_no_skyclear=false +gl_particles_style=2 +gl_pipeline_depth=0 +gl_plane_reflection=true +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_sort_textures=false +gl_sprite_blend=false +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=6 +gl_texture_filter_anisotropic=2 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=15 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gl_usecolorblending=true +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +i_soundinbackground=false +inter_subtitles=false +invertmouse=false +invertmousex=false +language=auto +longsavemessages=true +lookstrafe=false +m_blockcontrollers=false +m_cleanscale=false +m_filter=false +m_forward=1 +m_pitch=1 +m_sensitivity_x=4 +m_sensitivity_y=2 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=2 +m_simpleoptions=false +m_use_mouse=2 +m_yaw=1 +map_point_coordinates=true +midi_config=gzdoom +midi_dmxgus=false +midi_voices=32 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mus_calcgain=true +mus_enabled=true +mus_gainoffset=0 +mus_usereplaygain=false +nointerscrollabort=false +nomonsterinterpolation=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=1 +opn_fullpan=true +opn_run_at_pcm_rate=false +os_isanyof=true +png_gamma=0 +png_level=5 +queryiwad=true +quicksavenum=-1 +quicksaverotation=false +quicksaverotationcount=4 +r_actorspriteshadow=1 +r_actorspriteshadowdist=1500 +r_blendmethod=false +r_dynlights=true +r_fakecontrast=1 +r_fullbrightignoresectorcolor=true +r_fuzzscale=true +r_line_distance_cull=0 +r_linearsky=false +r_magfilter=false +r_minfilter=true +r_mipmap=true +r_mirror_recursions=4 +r_models=true +r_multithreaded=1 +r_noaccel=false +r_quakeintensity=1 +r_sprite_distance_cull=0 +r_spriteadjust=2 +r_ticstability=true +save_dir= +save_formatted=false +saveloadconfirmation=true +savestatistics=0 +screenshot_dir= +screenshot_quiet=false +screenshot_type=png +show_messages=true +showendoom=0 +snd_aldevice=Default +snd_alresampler=Default +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=true +snd_enabled=true +snd_hrtf=-1 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_waterreverb=true +statfile=zdoomstat.txt +storesavepic=true +strictdecorate=false +telezoom=true +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=gzdoom +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_min_sustain_time=5000 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +turnspeedsprintfast=1280 +turnspeedsprintslow=320 +turnspeedwalkfast=640 +turnspeedwalkslow=320 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=true +vid_defheight=480 +vid_defwidth=640 +vid_fullscreen=true +vid_gamma=1 +vid_hdr=false +vid_maxfps=0 +vid_preferbackend=3 +vid_rendermode=4 +vid_saturation=1 +vid_scale_customheight=200 +vid_scale_custompixelaspect=1 +vid_scale_customwidth=320 +vid_scale_linear=false +vid_scalefactor=1 +vid_scalemode=0 +vid_sdl_render_driver= +vid_vsync=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_mode=0 +vr_screendist=0.800000011920929 +vr_swap_eyes=false +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +win_h=384 +win_maximized=false +win_w=512 +win_x=-1 +win_y=-1 +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[Doom.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Doom.ConsoleVariables] +addrocketexplosion=false +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_linealpha=1 +am_linethickness=1 +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=1 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showgrid=false +am_showitems=true +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=true +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +am_zoomdir=0 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_gfxlocalization=3 +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_pulsetext=false +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=2 +crosshairon=true +crosshairscale=0.5 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +dlg_vgafont=false +gl_aalines=false +gl_bandedswlight=false +gl_bloom=true +gl_bloom_amount=1.399999976158142 +gl_brightfog=false +gl_enhanced_nightvision=true +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=0 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=2 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=true +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=2 +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=true +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_oldscale=true +hud_scale=-1 +hud_scalefactor=1 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +inter_classic_scaling=true +log_vgafont=false +lookspring=true +m_quickexit=false +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=3 +underwater_fade_scalar=1 +vid_allowtrueultrawide=1 +vid_cursor=None +vid_nopalsubstitutions=false +wi_cleantextscale=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Doom.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Doom.ConfigOnlyVariables] + +[Doom.UnknownConsoleVariables] + +[Doom.ConsoleAliases] + +[Doom.Bindings] +Joy1=+use +Joy5=+speed +Joy6=+attack +Joy7=+crouch +Joy8=+jump +Joy11=weapprev +Joy12=weapnext +Joy13=togglemap +Joy14=menu_main +Joy16=centerview +Joy3=turn180 +Joy4=+reload + +[Doom.DoubleBindings] + +[Doom.AutomapBindings] +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 +Joy5=+am_zoomout +Joy6=+am_zoomin + +[Joy:JS:0] +Axis0deadzone=0.200001 +Axis0scale=0.8 +Axis1deadzone=0.200001 +Axis1scale=0.6 +Axis2deadzone=0.200001 +Axis2scale=0.6 +Axis2map=0 +Axis3deadzone=0.400001 +Axis3scale=0.2 +Axis3map=1 + diff --git a/packages/games/emulators/gzdoom/config/RG351P/gzdoom.ini b/packages/games/emulators/gzdoom/config/RG351P/gzdoom.ini new file mode 100644 index 000000000..7cf5c5cdc --- /dev/null +++ b/packages/games/emulators/gzdoom/config/RG351P/gzdoom.ini @@ -0,0 +1,746 @@ +# This file was generated by GZDoom g4.8pre-28-gbc75dc056 on 2021-10-16 16:14:47 +# These are the directories to automatically search for IWADs. +# Each directory should be on a separate line, preceded by Path= +[IWADSearch.Directories] +Path=. +Path=$DOOMWADDIR +Path=/storage/.config/distribution/gzdoom +Path=/storage/roms/doom + +# These are the directories to search for wads added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for IWADSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/gzdoom +Path=/storage/roms/doom +Path=$DOOMWADDIR + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for IWADSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/gzdoom/soundfonts +Path=/storage/.config/distribution/gzdoom/fm_banks + +# Files to automatically execute when running the corresponding game. +# Each file should be on its own line, preceded by Path= + +[Doom.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/distribution/gzdoom/autoexec.cfg + +# WAD files to always load. These are loaded after the IWAD but before +# any files added with -file. Place each file on its own line, preceded +# by Path= +[Global.Autoload] + +# Wad files to automatically load depending on the game and IWAD you are +# playing. You may have have files that are loaded for all similar IWADs +# (the game) and files that are only loaded for particular IWADs. For example, +# any files listed under 'doom.Autoload' will be loaded for any version of Doom, +# but files listed under 'doom.doom2.Autoload' will only load when you are +# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under +# 'doom.doom2.commercial.Autoload' only when playing doom2.wad. + +[doom.Autoload] + +[doom.id.Autoload] + +[doom.id.doom2.Autoload] + +[doom.id.doom2.commercial.Autoload] + +[doom.id.doom2.commercial.french.Autoload] + +[doom.id.doom2.commercial.xbox.Autoload] + +[doom.id.doom2.unity.Autoload] + +[doom.id.doom2.bfg.Autoload] + +[doom.id.doom2.plutonia.Autoload] + +[doom.id.doom2.plutonia.unity.Autoload] + +[doom.id.doom2.tnt.Autoload] + +[doom.id.doom2.tnt.unity.Autoload] + +[doom.id.doom1.Autoload] + +[doom.id.doom1.registered.Autoload] + +[doom.id.doom1.ultimate.Autoload] + +[doom.id.doom1.ultimate.xbox.Autoload] + +[doom.id.wadsmoosh.Autoload] + +[doom.id.doom1.unity.Autoload] + +[doom.id.doom1.bfg.Autoload] + +[doom.freedoom.Autoload] + +[doom.freedoom.demo.Autoload] + +[doom.freedoom.phase1.Autoload] + +[doom.freedoom.phase2.Autoload] + +[doom.freedoom.freedm.Autoload] + +[heretic.Autoload] + +[heretic.heretic.Autoload] + +[heretic.shadow.Autoload] + +[blasphemer.Autoload] + +[hexen.Autoload] + +[hexen.deathkings.Autoload] + +[hexen.hexen.Autoload] + +[strife.Autoload] + +[strife.strife.Autoload] + +[strife.veteran.Autoload] + +[chex.Autoload] + +[chex.chex1.Autoload] + +[chex.chex3.Autoload] + +[urbanbrawl.Autoload] + +[hacx.Autoload] + +[hacx.hacx1.Autoload] + +[hacx.hacx2.Autoload] + +[harmony.Autoload] + +[square.Autoload] + +[square.squareware.Autoload] + +[square.square.Autoload] + +[delaweare.Autoload] + +[woolball.Autoload] + +[woolball.rotwb.Autoload] + +[LastRun] +Version=222 + +[GlobalSettings] +I_FriendlyWindowTitle=1 +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=false +autoloadlights=false +autoloadwidescreen=true +autosavecount=4 +autosavenum=1 +chase_dist=90 +chase_height=-8 +cl_capfps=false +cl_defaultconfiguration=0 +cl_noprediction=false +cl_oldfreelooklimit=false +cl_predict_lerpscale=0.05000000074505806 +cl_predict_lerpthreshold=2 +cl_predict_specials=true +cl_run=false +cl_waitforsave=true +con_4bitansi=false +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +con_printansi=true +defaultiwad= +demo_compress=true +developer=0 +disableautoload=false +disableautosave=0 +enablescriptscreenshot=false +fluid_chorus=false +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=0.5 +fluid_interp=1 +fluid_lib= +fluid_patchset=gzdoom +fluid_reverb=false +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=1 +fluid_voices=128 +freelook=true +gl_billboard_faces_camera=false +gl_billboard_mode=0 +gl_billboard_particles=true +gl_cachenodes=true +gl_cachetime=0.6000000238418579 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_distfog=70 +gl_dither_bpc=0 +gl_enhanced_nv_stealth=3 +gl_es=true +gl_finishbeforeswap=false +gl_fxaa=0 +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_particles=true +gl_light_shadowmap=false +gl_light_sprites=true +gl_lights=false +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_multisample=1 +gl_multithread=true +gl_no_skyclear=false +gl_particles_style=2 +gl_pipeline_depth=0 +gl_plane_reflection=true +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_sort_textures=false +gl_sprite_blend=false +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=6 +gl_texture_filter_anisotropic=2 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=15 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gl_usecolorblending=true +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +i_soundinbackground=false +inter_subtitles=false +invertmouse=false +invertmousex=false +language=auto +longsavemessages=true +lookstrafe=false +m_blockcontrollers=false +m_cleanscale=false +m_filter=false +m_forward=1 +m_pitch=1 +m_sensitivity_x=4 +m_sensitivity_y=2 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=2 +m_simpleoptions=false +m_use_mouse=2 +m_yaw=1 +map_point_coordinates=true +midi_config=gzdoom +midi_dmxgus=false +midi_voices=32 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mus_calcgain=true +mus_enabled=true +mus_gainoffset=0 +mus_usereplaygain=false +nointerscrollabort=false +nomonsterinterpolation=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=1 +opn_fullpan=true +opn_run_at_pcm_rate=false +os_isanyof=true +png_gamma=0 +png_level=5 +queryiwad=true +quicksavenum=-1 +quicksaverotation=false +quicksaverotationcount=4 +r_actorspriteshadow=1 +r_actorspriteshadowdist=1500 +r_blendmethod=false +r_dynlights=true +r_fakecontrast=1 +r_fullbrightignoresectorcolor=true +r_fuzzscale=true +r_line_distance_cull=0 +r_linearsky=false +r_magfilter=false +r_minfilter=true +r_mipmap=true +r_mirror_recursions=4 +r_models=true +r_multithreaded=1 +r_noaccel=false +r_quakeintensity=1 +r_sprite_distance_cull=0 +r_spriteadjust=2 +r_ticstability=true +save_dir= +save_formatted=false +saveloadconfirmation=true +savestatistics=0 +screenshot_dir= +screenshot_quiet=false +screenshot_type=png +show_messages=true +showendoom=0 +snd_aldevice=Default +snd_alresampler=Default +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=true +snd_enabled=true +snd_hrtf=-1 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_waterreverb=true +statfile=zdoomstat.txt +storesavepic=true +strictdecorate=false +telezoom=true +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=gzdoom +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_min_sustain_time=5000 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +turnspeedsprintfast=1280 +turnspeedsprintslow=320 +turnspeedwalkfast=640 +turnspeedwalkslow=320 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=true +vid_defheight=480 +vid_defwidth=640 +vid_fullscreen=true +vid_gamma=1 +vid_hdr=false +vid_maxfps=0 +vid_preferbackend=3 +vid_rendermode=4 +vid_saturation=1 +vid_scale_customheight=200 +vid_scale_custompixelaspect=1 +vid_scale_customwidth=320 +vid_scale_linear=false +vid_scalefactor=1 +vid_scalemode=0 +vid_sdl_render_driver= +vid_vsync=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_mode=0 +vr_screendist=0.800000011920929 +vr_swap_eyes=false +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +win_h=384 +win_maximized=false +win_w=512 +win_x=-1 +win_y=-1 +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[Doom.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Doom.ConsoleVariables] +addrocketexplosion=false +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_linealpha=1 +am_linethickness=1 +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=1 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showgrid=false +am_showitems=true +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=true +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +am_zoomdir=0 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_gfxlocalization=3 +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_pulsetext=false +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=2 +crosshairon=true +crosshairscale=0.5 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +dlg_vgafont=false +gl_aalines=false +gl_bandedswlight=false +gl_bloom=true +gl_bloom_amount=1.399999976158142 +gl_brightfog=false +gl_enhanced_nightvision=true +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=0 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=2 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=true +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=2 +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=true +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_oldscale=true +hud_scale=-1 +hud_scalefactor=1 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +inter_classic_scaling=true +log_vgafont=false +lookspring=true +m_quickexit=false +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=3 +underwater_fade_scalar=1 +vid_allowtrueultrawide=1 +vid_cursor=None +vid_nopalsubstitutions=false +wi_cleantextscale=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Doom.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Doom.ConfigOnlyVariables] + +[Doom.UnknownConsoleVariables] + +[Doom.ConsoleAliases] + +[Doom.Bindings] +Joy1=+use +Joy5=+speed +Joy6=+attack +Joy7=+crouch +Joy8=+jump +Joy11=weapprev +Joy12=weapnext +Joy13=togglemap +Joy14=menu_main +Joy16=centerview +Joy3=turn180 +Joy4=+reload + +[Doom.DoubleBindings] + +[Doom.AutomapBindings] +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 +Joy5=+am_zoomout +Joy6=+am_zoomin + +[Joy:JS:0] +Axis0deadzone=0.200001 +Axis0scale=0.8 +Axis1deadzone=0.200001 +Axis1scale=0.6 +Axis2deadzone=0.200001 +Axis2scale=0.6 +Axis2map=0 +Axis3deadzone=0.400001 +Axis3scale=0.2 +Axis3map=1 + diff --git a/packages/games/emulators/gzdoom/gzdoom.sh b/packages/games/emulators/gzdoom/gzdoom.sh new file mode 100644 index 000000000..e5fabc649 --- /dev/null +++ b/packages/games/emulators/gzdoom/gzdoom.sh @@ -0,0 +1,54 @@ +#!/usr/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile +. /etc/os-release + +EE_DEVICE=${HW_DEVICE} +RUN_DIR="/storage/roms/doom" +CONFIG="/storage/.config/distribution/gzdoom/gzdoom.ini" +SAVE_DIR="/storage/roms/gamedata/gzdoom" + +if [ ! -L "/storage/.config/gzdoom" ] +then + ln -sf "/storage/.config/distribution/gzdoom" "/storage/.config/gzdoom" +fi + +if [ ! -f "/storage/.config/distribution/gzdoom/gzdoom.ini" ] +then + cp -rf /usr/config/distribution/gzdoom/gzdoom.ini /storage/.config/distribution/gzdoom/ +fi + +mkdir -p ${SAVE_DIR} + +params=" -config ${CONFIG} -savedir ${SAVE_DIR}" + +if [[ "$EE_DEVICE" == RG351P ]]; then + params+=" +gl_es 1 +vid_preferbackend 3 +cl_capfps 0 +vid_fps 1" +fi +if [[ "$EE_DEVICE" == RG351V ]] || [[ "$EE_DEVICE" == RG351MP ]]; then + params+=" +gl_es 1 +vid_preferbackend 3 +cl_capfps 0 +vid_fps 1" +fi + +# EXT can be wad, WAD, iwad, IWAD, pwad, PWAD or doom +EXT=${1#*.} + +# If its not a simple wad (extension .doom) read the file and parse the data +if [ ${EXT} == "doom" ]; then + dos2unix "${1}" + while IFS== read -r key value; do + if [ "$key" == "IWAD" ]; then + params+=" -iwad $value" + fi + if [ "$key" == "MOD" ]; then + params+=" -file $value" + fi + done < "${1}" +else + params+=" -iwad ${1}" +fi + +cd "${RUN_DIR}" +LD_PRELOAD=/usr/lib/libSDL2-2.0.so.0.14.0 /usr/bin/gzdoom ${params} >/tmp/logs/gzdoom.log 2>&1 diff --git a/packages/games/emulators/gzdoom/package.mk b/packages/games/emulators/gzdoom/package.mk new file mode 100644 index 000000000..90d5e05b7 --- /dev/null +++ b/packages/games/emulators/gzdoom/package.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="gzdoom" +PKG_VERSION="5e931f344a91e65d58d2374f3e98740974613272" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/dhwz/gzdoom" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_HOST="toolchain zmusic:host" +PKG_DEPENDS_TARGET="toolchain SDL2 gzdoom:host zmusic" +PKG_SHORTDESC="GZDoom is a modder-friendly OpenGL and Vulkan source port based on the DOOM engine" +PKG_LONGDESC="GZDoom is a modder-friendly OpenGL and Vulkan source port based on the DOOM engine" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="cmake-make" + +if [ ! "${DEVICE}" = "RG351MP" ] +then + PKG_PATCH_DIRS="RG351P" +fi + +pre_build_host() { + HOST_CMAKE_OPTS="" +} + +make_host() { + cmake . -DNO_GTK=ON + make +} + +makeinstall_host() { +: #no +} + +pre_configure_host(){ +PKG_CMAKE_OPTS_HOST=" -DZMUSIC_LIBRARIES=$(get_build_dir zmusic)/build_host/source/libzmusic.so \ + -DZMUSIC_INCLUDE_DIR=$(get_build_dir zmusic)/include" +} + +pre_configure_target() { +PKG_CMAKE_OPTS_TARGET=" -DNO_GTK=ON \ + -DFORCE_CROSSCOMPILE=ON \ + -DIMPORT_EXECUTABLES=$PKG_BUILD/.$HOST_NAME/ImportExecutables.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DHAVE_GLES2=ON \ + -DHAVE_VULKAN=OFF \ + -DZMUSIC_LIBRARIES=$(get_build_dir zmusic)/build_target/source/libzmusic.so -DZMUSIC_INCLUDE_DIR=$(get_build_dir zmusic)/include" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/gzdoom.sh $INSTALL/usr/bin/ + cp $PKG_BUILD/.$TARGET_NAME/gzdoom $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/config/distribution/gzdoom + if [ "${DEVICE}" = "RG351MP" ]; then + cp $PKG_DIR/config/RG351MP/* $INSTALL/usr/config/distribution/gzdoom + else + cp $PKG_DIR/config/RG351P/* $INSTALL/usr/config/distribution/gzdoom + fi + cp $PKG_BUILD/.$TARGET_NAME/*.pk3 $INSTALL/usr/config/distribution/gzdoom + cp -r $PKG_BUILD/.$TARGET_NAME/soundfonts $INSTALL/usr/config/distribution/gzdoom + cp -r $PKG_BUILD/.$TARGET_NAME/fm_banks $INSTALL/usr/config/distribution/gzdoom +} diff --git a/packages/games/emulators/gzdoom/patches/RG351P/0001_key_swap.patch b/packages/games/emulators/gzdoom/patches/RG351P/0001_key_swap.patch new file mode 100644 index 000000000..364580a78 --- /dev/null +++ b/packages/games/emulators/gzdoom/patches/RG351P/0001_key_swap.patch @@ -0,0 +1,19 @@ +diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp +index 05ae2073f..b8e6b8210 100644 +--- a/src/common/menu/menu.cpp ++++ b/src/common/menu/menu.cpp +@@ -694,12 +694,12 @@ bool M_Responder (event_t *ev) + { + case KEY_JOY2: + case KEY_PAD_A: +- mkey = MKEY_Enter; ++ mkey = MKEY_Back; + break; + + case KEY_JOY1: + case KEY_PAD_B: +- mkey = MKEY_Back; ++ mkey = MKEY_Enter; + break; + + case KEY_JOY4: diff --git a/packages/games/emulators/gzdoom/zmusic/package.mk b/packages/games/emulators/gzdoom/zmusic/package.mk new file mode 100644 index 000000000..4301b5ea8 --- /dev/null +++ b/packages/games/emulators/gzdoom/zmusic/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="zmusic" +PKG_VERSION="d8e6e28879ee97d00ce0eb9ad13ba462d85faf29" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/coelckers/ZMusic" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain zmusic:host" +PKG_SHORTDESC="GZDoom's music system as a standalone library" +PKG_LONGDESC="GZDoom's music system as a standalone library" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="cmake-make" + +pre_build_host() { + HOST_CMAKE_OPTS="" +} + +make_host() { + mkdir $PKG_BUILD/build_host + cd $PKG_BUILD/build_host + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . +} + +make_target() { + mkdir $PKG_BUILD/build_target + cd $PKG_BUILD/build_target + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . +} + +makeinstall_host() { +: #no +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib + cp -f $PKG_BUILD/build_target/source/libzmusic* $INSTALL/usr/lib/ +} diff --git a/packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg b/packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg new file mode 100644 index 000000000..f242a8e4a --- /dev/null +++ b/packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg @@ -0,0 +1,252 @@ +[Log] +sLogFileName = stderr +sTraceFileName = stderr +nTextLogLevel = 3 +nAlertDlgLogLevel = 1 +bConfirmQuit = FALSE +bNatFeats = FALSE +bConsoleWindow = FALSE + +[Debugger] +nNumberBase = 10 +nSymbolLines = -1 +nMemdumpLines = -1 +nDisasmLines = -1 +nExceptionDebugMask = 515 +nDisasmOptions = 15 +bDisasmUAE = FALSE +bSymbolsResident = FALSE +bMatchAllSymbols = FALSE + +[Screen] +nMonitorType = 1 +nFrameSkips = 5 +bFullScreen = TRUE +bKeepResolution = TRUE +bResizable = TRUE +bAllowOverscan = TRUE +nSpec512Threshold = 1 +nForceBpp = 0 +bAspectCorrect = TRUE +bUseExtVdiResolutions = FALSE +nVdiWidth = 640 +nVdiHeight = 480 +nVdiColors = 2 +bMouseWarp = TRUE +bShowStatusbar = FALSE +bShowDriveLed = FALSE +bCrop = FALSE +bForceMax = FALSE +nMaxWidth = 832 +nMaxHeight = 588 +bUseSdlRenderer = TRUE +nRenderScaleQuality = 0 +bUseVsync = TRUE + +[Joystick0] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick1] +nJoystickMode = 1 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick2] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick3] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick4] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick5] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Keyboard] +bDisableKeyRepeat = FALSE +nKeymapType = 0 +szMappingFileName = + +[KeyShortcutsWithMod] +kOptions = O +kFullScreen = F +kBorders = B +kMouseMode = M +kColdReset = C +kWarmReset = R +kScreenShot = G +kBossKey = I +kCursorEmu = J +kFastForward = X +kRecAnim = A +kRecSound = Y +kSound = S +kPause = +kDebugger = Pause +kQuit = Q +kLoadMem = L +kSaveMem = K +kInsertDiskA = D +kSwitchJoy0 = F1 +kSwitchJoy1 = F2 +kSwitchPadA = F3 +kSwitchPadB = F4 + +[KeyShortcutsWithoutMod] +kOptions = F12 +kFullScreen = F11 +kBorders = +kMouseMode = +kColdReset = +kWarmReset = +kScreenShot = +kBossKey = +kCursorEmu = +kFastForward = +kRecAnim = +kRecSound = +kSound = +kPause = Pause +kDebugger = +kQuit = +kLoadMem = +kSaveMem = +kInsertDiskA = +kSwitchJoy0 = +kSwitchJoy1 = +kSwitchPadA = +kSwitchPadB = + +[Sound] +bEnableMicrophone = TRUE +bEnableSound = TRUE +bEnableSoundSync = FALSE +nPlaybackFreq = 44100 +nSdlAudioBufferSize = 0 +szYMCaptureFileName = /storage/.hatari/hatari.wav +YmVolumeMixing = 2 + +[Memory] +nMemorySize = 1024 +nTTRamSize = 0 +bAutoSave = FALSE +szMemoryCaptureFileName = /storage/.config/hatari/hatari.sav +szAutoSaveFileName = /storage/.config/hatari/auto.sav + +[HardDisk] +nGemdosDrive = 0 +bBootFromHardDisk = FALSE +bUseHardDiskDirectory = FALSE +szHardDiskDirectory = /storage/.hatari +nGemdosCase = 0 +nWriteProtection = 0 +bFilenameConversion = FALSE +bGemdosHostTime = FALSE +bUseHardDiskImage = FALSE +szHardDiskImage = /storage/.hatari +bUseIdeMasterHardDiskImage = FALSE +bUseIdeSlaveHardDiskImage = FALSE +szIdeMasterHardDiskImage = /storage/.hatari +szIdeSlaveHardDiskImage = /storage/.hatari + +[ROM] +szTosImageFileName = /storage/roms/bios/tos.img +bPatchTos = TRUE +szCartridgeImageFileName = + +[RS232] +bEnableRS232 = FALSE +szOutFileName = /dev/modem +szInFileName = /dev/modem + +[Printer] +bEnablePrinting = FALSE +szPrintToFileName = /storage/.config/hatari/hatari.prn + +[Midi] +bEnableMidi = FALSE +sMidiInFileName = /dev/snd/midiC1D0 +sMidiOutFileName = /dev/snd/midiC1D0 +sMidiInPortName = Off +sMidiOutPortName = Off + +[System] +nCpuLevel = 0 +nCpuFreq = 8 +bCompatibleCpu = TRUE +nModelType = 0 +bBlitter = FALSE +nDSPType = 0 +bPatchTimerD = FALSE +bFastBoot = FALSE +bFastForward = FALSE +bAddressSpace24 = TRUE +bCycleExactCpu = TRUE +n_FPUType = 0 +bSoftFloatFPU = FALSE +bMMU = FALSE +VideoTiming = 3 + +[Video] +AviRecordVcodec = 2 +AviRecordFps = 0 +AviRecordFile = /storage/.hatari/hatari.avi + +[Floppy] +bAutoInsertDiskB = TRUE +FastFloppy = TRUE +EnableDriveA = TRUE +DriveA_NumberOfHeads = 2 +EnableDriveB = TRUE +DriveB_NumberOfHeads = 2 +nWriteProtection = 0 +szDiskImageDirectory = /storage/roms/atarist +szDiskAZipPath = +szDiskBZipPath = diff --git a/packages/games/emulators/hatarisa/package.mk b/packages/games/emulators/hatarisa/package.mk new file mode 100644 index 000000000..e5b810fdd --- /dev/null +++ b/packages/games/emulators/hatarisa/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="hatarisa" +PKG_VERSION="527b68f6b09c779f5eddd272aa2362c09fafc7cd" +PKG_SHA256="4f0aefbe8d9e8d49967eecdcee0f3738c07d2ec052e311073c8efb09df783735" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/hatari/hatari" +PKG_URL="https://github.com/hatari/hatari/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux glibc systemd alsa-lib SDL2 portaudio zlib capsimg libpng" +PKG_LONGDESC="Hatari is an Atari ST/STE/TT/Falcon emulator" + + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DCMAKE_SKIP_RPATH=ON \ + -DDATADIR="/usr/config/hatari" \ + -DBIN2DATADIR="../../storage/.config/hatari" \ + -DCAPSIMAGE_INCLUDE_DIR=$PKG_BUILD/src/include \ + -DCAPSIMAGE_LIBRARY=$PKG_BUILD/libcapsimage.so.5.1" + + # copy IPF Support Library include files + mkdir -p $PKG_BUILD/src/includes/caps/ + cp -R $(get_build_dir capsimg)/LibIPF/* $PKG_BUILD/src/includes/caps/ + cp -R $(get_build_dir capsimg)/Core/CommonTypes.h $PKG_BUILD/src/includes/caps/ + cp -R $(get_build_dir capsimg)/.install_pkg/usr/lib/libcapsimage.so.5.1 $PKG_BUILD/ + + # add library search path for loading libcapsimage library + LDFLAGS="$LDFLAGS -Wl,-rpath='$PKG_BUILD'" +} + +makeinstall_target() { + # create directories + mkdir -p $INSTALL/usr/bin + mkdir -p $INSTALL/usr/config/hatari + + # copy config files + touch $INSTALL/usr/config/hatari/hatari.nvram + cp -R $PKG_DIR/config/* $INSTALL/usr/config/hatari + + # copy binary & start script + cp src/hatari $INSTALL/usr/bin + cp -R $PKG_DIR/scripts/* $INSTALL/usr/bin/ +} diff --git a/packages/games/emulators/hatarisa/portaudio/package.mk b/packages/games/emulators/hatarisa/portaudio/package.mk new file mode 100644 index 000000000..3a1845cd5 --- /dev/null +++ b/packages/games/emulators/hatarisa/portaudio/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="portaudio" +PKG_VERSION="64d1bf913433d7a2835526b80a93487d5038cb8e" +PKG_SHA256="c33e48217a844cca3b66ab88571b90beefb8fcb6967177951d4dc283587bf834" +PKG_LICENSE="GPL" +PKG_SITE="https://portaudio.com" +PKG_URL="https://github.com/zhang-ray/portaudio/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib" +PKG_LONGDESC="PortAudio is a free, cross-platform, open-source, audio I/O library." diff --git a/packages/games/emulators/hatarisa/scripts/hatari.start b/packages/games/emulators/hatarisa/scripts/hatari.start new file mode 100755 index 000000000..bb78c8286 --- /dev/null +++ b/packages/games/emulators/hatarisa/scripts/hatari.start @@ -0,0 +1,76 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +. /etc/profile + +# Set some common variables +HATARI_DIR_HOME=/storage/.hatari +HATARI_DIR=/storage/.config/hatari +HATARI_CONFIG_DIR=$HATARI_DIR/conf +HATARI_TMP_DIR=/tmp/hatari +HATARI_TMP_CONFIG="$HATARI_TMP_DIR"/.hatari-temp.cfg +HATARI_LOG="/tmp/logs/hatari.log" +MAX_DRIVES=2 +i=0 + +export SDL_AUDIODRIVER=alsa + +# create symlink to hatari config dir +if [ ! -L $HATARI_DIR_HOME ]; then + rm -rf $HATARI_DIR_HOME + ln -s $HATARI_DIR $HATARI_DIR_HOME +fi + +# Which file should hatari load? +echo "Trying to boot this game:" "$1" >> $HATARI_LOG + +# Create a clean working directory +if [ -d "$HATARI_TMP_DIR" ]; then + echo "Clean up old working directory." >> $HATARI_LOG + rm -rf "$HATARI_TMP_DIR" +fi +mkdir -p "$HATARI_TMP_DIR" + +# copy default config file to tmp +cp $HATARI_CONFIG_DIR/Atari-ST-default.cfg "$HATARI_TMP_CONFIG" + +# Check if we are loading a .zip file +if [ `echo $1 | grep -i .zip | wc -l` -eq 1 ]; then + + #unpack the zip file + unzip -q -o "$1" -d "$HATARI_TMP_DIR" + + # Assign files to floppy 1 & 2 + for FILE in "$HATARI_TMP_DIR"/* + do + i=$(($i+1)) + case "$i" in + 1) + ARGS="\nszDiskAFileName = "$FILE"" + ;; + 2) + ARGS="$ARGS\nszDiskBFileName = "$FILE"" + ;; + esac + + # This emulator supports 2 floppies max + if [ $i -eq $MAX_DRIVES ]; then + break; + fi + done + + # Add game files as floppy 1 & 2 to .hatari-temp.cfg & start hatari + echo -e $ARGS >> "$HATARI_TMP_CONFIG" + echo -e "\nAssigned floppy drives:" $ARGS "\n" >> "$HATARI_LOG" + nice -n -19 hatari --configfile "$HATARI_TMP_CONFIG" >> $HATARI_LOG 2>&1 + +# Check for .cfg config file +elif [ `echo $1 | grep -i .cfg | wc -l` -eq 1 ]; then + nice -n -19 hatari --configfile "$1" >> $HATARI_LOG 2>&1 +# All other files +else + nice -n -19 hatari --configfile "$HATARI_TMP_CONFIG" --disk-a "$1" >> $HATARI_LOG 2>&1 +fi +# Remove temporary dir +rm -rf "$HATARI_TMP_DIR" diff --git a/packages/games/emulators/hypseus/config/hypinput.ini b/packages/games/emulators/hypseus/config/hypinput.ini new file mode 100644 index 000000000..9c5044024 --- /dev/null +++ b/packages/games/emulators/hypseus/config/hypinput.ini @@ -0,0 +1,31 @@ +# Sample hypinput.ini +# All key options listed +# Arcade layout by OzFalcon +# Hypseus uses SDL2 Keycodes +# Button3 Turns scoreboard on/off +# SWITCH = Key1 Key2 Joy + +[KEYBOARD] +KEY_UP = 1073741906 0 0 +KEY_DOWN = 1073741905 0 0 +KEY_LEFT = 1073741904 0 0 +KEY_RIGHT = 1073741903 0 0 +KEY_COIN1 = 53 54 0 +KEY_COIN2 = 54 53 0 +KEY_START1 = 49 0 0 +KEY_START2 = 50 0 0 +KEY_BUTTON1 = 1073742048 0 0 +KEY_BUTTON2 = 1073742050 0 0 +KEY_BUTTON3 = 32 0 0 +KEY_SKILL1 = 1073742049 0 0 +KEY_SKILL2 = 122 0 0 +KEY_SKILL3 = 120 0 0 +KEY_SERVICE = 57 0 0 +KEY_TEST = 1073741883 0 0 +KEY_RESET = 48 0 0 +KEY_SCREENSHOT = 1073741893 0 0 +KEY_QUIT = 27 0 0 +KEY_PAUSE = 112 0 0 +KEY_CONSOLE = 92 0 0 +KEY_TILT = 116 0 0 +END diff --git a/packages/games/emulators/hypseus/package.mk b/packages/games/emulators/hypseus/package.mk new file mode 100644 index 000000000..68632ffa5 --- /dev/null +++ b/packages/games/emulators/hypseus/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="hypseus" +PKG_VERSION="9ba6530805c9236655d023cfa3e31b3db2e09b39" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL3" +PKG_SITE="https://github.com/btolab/hypseus" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_ttf SDL2_image zlib libogg libvorbis libmpeg2" +PKG_LONGDESC="Hypseus is a fork of Daphne. A program that lets one play the original versions of many laserdisc arcade games on one's PC." +PKG_TOOLCHAIN="cmake" +GET_HANDLER_SUPPORT="git" + +PKG_CMAKE_OPTS_TARGET=" ./src" + +pre_configure_target() { + mkdir -p $INSTALL/usr/config/distribution/configs/hypseus + ln -fs /storage/roms/daphne/roms $INSTALL/usr/config/distribution/configs/hypseus/roms + ln -fs /storage/roms/daphne/sound $INSTALL/usr/config/distribution/configs/hypseus/sound + ln -fs /usr/share/daphne/fonts $INSTALL/usr/config/distribution/configs/hypseus/fonts + ln -fs /usr/share/daphne/pics $INSTALL/usr/config/distribution/configs/hypseus/pics + cp -a ${PKG_DIR}/config/* ${INSTALL}/usr/config/hypseus + cp $PKG_BUILD/doc/hypinput.ini $INSTALL/usr/config/distribution/configs/hypseus/ +} + +post_makeinstall_target() { + ln -fs /storage/.config/distribution/configs/hypseus/hypinput.ini $INSTALL/usr/share/daphne/hypinput.ini +} diff --git a/packages/games/emulators/hypseus/patches/hypseus-003-controller.patch b/packages/games/emulators/hypseus/patches/hypseus-003-controller.patch new file mode 100644 index 000000000..417a4b962 --- /dev/null +++ b/packages/games/emulators/hypseus/patches/hypseus-003-controller.patch @@ -0,0 +1,262 @@ +Improve joystick support: +- Support not only first joystick +- No more limit on button number +- Allow mapping of axis for joystick movement + +Signed-off-by: Laurent Merckx + +--- a/src/io/input.cpp 2017-11-02 17:41:39.000000000 +0100 ++++ b/src/io/input.cpp 2018-07-07 11:43:19.568545916 +0200 +@@ -54,7 +54,6 @@ using namespace std; + const int JOY_AXIS_MID = (int)(32768 * (0.75)); // how far they have to move the + // joystick before it 'grabs' + +-SDL_Joystick *G_joystick = NULL; // pointer to joystick object + bool g_use_joystick = true; // use a joystick by default + bool g_alt_pressed = false; // whether the ALT key is presssed (for ALT-Enter + // combo) +@@ -107,24 +106,46 @@ int g_key_defs[SWITCH_COUNT][2] = { + {SDLK_ESCAPE, SDLK_q}, // Quit DAPHNE + {SDLK_p, 0}, // pause game + {SDLK_BACKQUOTE, 0}, // toggle console (TODO) +- {SDLK_t, 0}, // Tilt/Slam switch ++ {SDLK_t, 0} // Tilt/Slam switch + }; + + //////////// + +-// added by Russ +-// global button mapping array. just hardcoded room for 10 buttons max +-int joystick_buttons_map[10] = { +- SWITCH_BUTTON1, // button 1 +- SWITCH_BUTTON2, // button 2 +- SWITCH_BUTTON3, // button 3 +- SWITCH_BUTTON1, // button 4 +- SWITCH_COIN1, // button 5 +- SWITCH_START1, // button 6 +- SWITCH_BUTTON1, // button 7 +- SWITCH_BUTTON1, // button 8 +- SWITCH_BUTTON1, // button 9 +- SWITCH_BUTTON1, // button 10 ++// default joystick buttons assignments, in case .ini file is missing ++// Two values defined: 1st=joystick index (0=1st joystick), 2nd=button index (0=not defined) ++// NOTE : These are in a specific order, corresponding to the enum in hypseus.h ++int g_joy_btn_defs[SWITCH_COUNT][2] = { ++ {0, 0}, // up ++ {0, 0}, // left ++ {0, 0}, // down ++ {0, 0}, // right ++ {0, 7}, // 1 player start ++ {0, 0}, // 2 player start ++ {0, 1}, // action button 1 ++ {0, 2}, // action button 2 ++ {0, 3}, // action button 3 ++ {0, 8}, // coin chute left ++ {0, 0}, // coin chute right ++ {0, 0}, // skill easy ++ {0, 0}, // skill medium ++ {0, 0}, // skill hard ++ {0, 0}, // service coin ++ {0, 0}, // test mode ++ {0, 0}, // reset cpu ++ {0, 0}, // take screenshot ++ {0, 12}, // Quit DAPHNE ++ {0, 11}, // pause game ++ {0, 0}, // toggle console (TODO) ++ {0, 0} // Tilt/Slam switch ++}; ++// default joystick axis assignments, in case .ini file is missing ++// Three values defined: 1st=joystick index (0=1st joystick), 2nd=axis index (0=not defined), 3rd=direction (-1/1, 0=not defined) ++// Only first four switch defined (SWITCH_UP to SWITCH_RIGHT) ++int g_joy_axs_defs[SWITCH_START1][3] = { ++ {0, 2, -1}, // up ++ {0, 1, -1}, // left ++ {0, 2, 1}, // down ++ {0, 1, 1} // right + }; + + // Mouse button to key mappings +@@ -143,8 +164,8 @@ void CFG_Keys() + { + struct mpo_io *io; + string cur_line = ""; +- string key_name = "", sval1 = "", sval2 = "", sval3 = "", eq_sign = ""; +- int val1 = 0, val2 = 0, val3 = 0; ++ string key_name = "", sval1 = "", sval2 = "", sval3 = "", sval4 = "", eq_sign = ""; ++ int val1 = 0, val2 = 0, val3 = 0, val4 = 0; + // bool done = false; + + // find where the hypinput ini file is (if the file doesn't exist, this +@@ -188,6 +209,10 @@ void CFG_Keys() + val1 = atoi(sval1.c_str()); + val2 = atoi(sval2.c_str()); + val3 = atoi(sval3.c_str()); ++ val4 = 0; ++ if (find_word(cur_line.c_str(), sval4, cur_line)) { ++ val4 = atoi(sval4.c_str()); ++ } + corrupt_file = false; // looks like we're + // good + +@@ -200,11 +225,22 @@ void CFG_Keys() + g_key_defs[i][0] = val1; + g_key_defs[i][1] = val2; + +- // if zero then no mapping +- // necessary, just use default, if +- // any +- if (val3 > 0) +- joystick_buttons_map[val3 - 1] = i; ++ // joystick buttons: ++ // if zero, use default ++ // if not: hundreds=joystick index, units=button index ++ if (val3 > 0) { ++ g_joy_btn_defs[i][0] = (val3 / 100); ++ g_joy_btn_defs[i][1] = (val3 % 100); ++ } ++ // joystick axis: ++ // if zero, use default ++ // if not: hundreds=joystick index, units=axis index, sign=direction ++ if (val4 != 0) { ++ g_joy_axs_defs[i][0] = abs(val4 / 100); ++ g_joy_axs_defs[i][1] = abs(val4 % 100); ++ g_joy_axs_defs[i][2] = (val4 == 0)?0:((val4 < 0)?-1:1); ++ } ++ + found_match = true; + break; + } +@@ -263,20 +299,17 @@ int SDL_input_init() + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0) { + // if joystick usage is enabled + if (g_use_joystick) { +- // if there is at least 1 joystick and we are authorized to use the +- // joystick for input +- if (SDL_NumJoysticks() > 0) { +- G_joystick = SDL_JoystickOpen(0); // FIXME: right now we +- // automatically choose the +- // first joystick +- if (G_joystick != NULL) { +- LOGD << "Joystick #0 was successfully opened"; ++ // open joysticks ++ for (int i=0; i < SDL_NumJoysticks(); i++) { ++ SDL_Joystick* joystick = SDL_JoystickOpen(i); ++ if (joystick != NULL) { ++ LOGD << "Joystick #" << i << " was successfully opened"; + } else { +- LOGW << "Error opening joystick!"; ++ LOGW << "Error opening joystick #" << i << "!"; + } +- } else { +- LOGI << "No joysticks detected"; + } ++ if (SDL_NumJoysticks() == 0) ++ LOGI << "No joysticks detected"; + } + // notify user that their attempt to disable the joystick is successful + else { +@@ -459,11 +492,10 @@ void process_event(SDL_Event *event) + case SDL_JOYBUTTONDOWN: + reset_idle(); // added by JFA for -idleexit + +- // added by Russ +- // loop through buttons and look for a press +- for (i = 0; i < (sizeof(joystick_buttons_map) / sizeof(int)); i++) { +- if (event->jbutton.button == i) { +- input_enable((Uint8)joystick_buttons_map[i]); ++ // loop through map and find corresponding action ++ for (i = 0; i < SWITCH_COUNT; i++) { ++ if (event->jbutton.which == g_joy_btn_defs[i][0] && event->jbutton.button == g_joy_btn_defs[i][1]-1) { ++ input_enable(i); + break; + } + } +@@ -472,10 +504,10 @@ void process_event(SDL_Event *event) + case SDL_JOYBUTTONUP: + reset_idle(); // added by JFA for -idleexit + +- // added by Russ +- for (i = 0; i < (sizeof(joystick_buttons_map) / sizeof(int)); i++) { +- if (event->jbutton.button == i) { +- input_disable((Uint8)joystick_buttons_map[i]); ++ // loop through map and find corresponding action ++ for (i = 0; i < SWITCH_COUNT; i++) { ++ if (event->jbutton.which == g_joy_btn_defs[i][0] && event->jbutton.button == g_joy_btn_defs[i][1]-1) { ++ input_disable(i); + break; + } + } +@@ -562,50 +594,37 @@ void process_keyup(SDL_Keycode key) + // processes movements of the joystick + void process_joystick_motion(SDL_Event *event) + { ++ static int x_axis_in_use = 0; ++ static int y_axis_in_use = 0; + +- static int x_axis_in_use = 0; // true if joystick is left or right +- static int y_axis_in_use = 0; // true if joystick is up or down +- +- // if they are moving along the verticle axis +- if (event->jaxis.axis == 1) { +- // if they're moving up +- if (event->jaxis.value < -JOY_AXIS_MID) { +- input_enable(SWITCH_UP); +- y_axis_in_use = 1; +- } +- // if they're moving down +- else if (event->jaxis.value > JOY_AXIS_MID) { +- input_enable(SWITCH_DOWN); ++ // loop through map and find corresponding action ++ int key = -1; ++ for (int i = 0; i < SWITCH_START1; i++) { ++ if (event->jaxis.which == g_joy_axs_defs[i][0] && event->jaxis.axis == g_joy_axs_defs[i][1]-1 && ((event->jaxis.value < 0)?-1:1) == g_joy_axs_defs[i][2]) { ++ key = i; ++ break; ++ } ++ } ++ if (key == -1) return; ++ ++ if (abs(event->jaxis.value) > JOY_AXIS_MID) { ++ input_enable(key); ++ if (key == SWITCH_UP || key == SWITCH_DOWN) + y_axis_in_use = 1; +- } +- +- // if they just barely stopped moving up or down +- else if (y_axis_in_use == 1) { ++ else ++ x_axis_in_use = 1; ++ } ++ else { ++ if ((key == SWITCH_UP || key == SWITCH_DOWN) && y_axis_in_use) { + input_disable(SWITCH_UP); + input_disable(SWITCH_DOWN); + y_axis_in_use = 0; +- } +- } // end verticle axis +- +- // horizontal axis +- else { +- // if they're moving right +- if (event->jaxis.value > JOY_AXIS_MID) { +- input_enable(SWITCH_RIGHT); +- x_axis_in_use = 1; +- } +- // if they're moving left +- else if (event->jaxis.value < -JOY_AXIS_MID) { +- input_enable(SWITCH_LEFT); +- x_axis_in_use = 1; +- } +- // if they just barely stopped moving right or left +- else if (x_axis_in_use == 1) { +- input_disable(SWITCH_RIGHT); ++ } else if ((key == SWITCH_LEFT || key == SWITCH_RIGHT) && x_axis_in_use) { + input_disable(SWITCH_LEFT); ++ input_disable(SWITCH_RIGHT); + x_axis_in_use = 0; + } +- } // end horizontal axis ++ } + } + + // processes movement of the joystick hat diff --git a/packages/games/emulators/hypseus/patches/hypseus-004-install_fix.patch b/packages/games/emulators/hypseus/patches/hypseus-004-install_fix.patch new file mode 100644 index 000000000..1a528e35a --- /dev/null +++ b/packages/games/emulators/hypseus/patches/hypseus-004-install_fix.patch @@ -0,0 +1,11 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 438451d..4e7a1db 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -129,3 +129,6 @@ set(CPACK_PACKAGE_VERSION_MINOR "${VER_MINOR}") + set(CPACK_PACKAGE_VERSION_PATCH "${VER_PATCH}") + + include(CPack) ++install(TARGETS hypseus DESTINATION bin) ++execute_process(COMMAND svn export https://github.com/mirror/daphne-emu/trunk/sound ../sound) ++install(DIRECTORY ../pics ../fonts ../sound DESTINATION /usr/share/daphne) diff --git a/packages/games/emulators/hypseus/patches/hypseus-005-external-mpeg2.patch b/packages/games/emulators/hypseus/patches/hypseus-005-external-mpeg2.patch new file mode 100644 index 000000000..2532e7909 --- /dev/null +++ b/packages/games/emulators/hypseus/patches/hypseus-005-external-mpeg2.patch @@ -0,0 +1,70 @@ +diff -rupN hypseus.orig/src/CMakeLists.txt hypseus.new/src/CMakeLists.txt +--- hypseus.orig/src/CMakeLists.txt 2021-02-09 18:13:21.665745426 -0500 ++++ hypseus.new/src/CMakeLists.txt 2021-02-09 19:45:52.277715721 -0500 +@@ -37,15 +37,16 @@ include(GNUInstallDirs) + include(GetGitRevisionDescription) + include(InstallRequiredSystemLibraries) + include(FindPkgConfig) +-include(ExternalProject) +-include(BuildLibMPEG2) ++#include(ExternalProject) ++#include(BuildLibMPEG2) + + use_cxx11( ) + + PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2) + PKG_SEARCH_MODULE(SDL2_TTF REQUIRED SDL2_ttf) + PKG_SEARCH_MODULE(SDL2_IMAGE REQUIRED SDL2_image) +-build_libmpeg2( ) ++PKG_SEARCH_MODULE(MPEG2 REQUIRED libmpeg2) ++#build_libmpeg2( ) + + message(STATUS "Target: ${CMAKE_SYSTEM_NAME} ${CMAKE_TARGET_ARCHITECTURES}") + +@@ -73,6 +74,7 @@ message(STATUS "Version: ${VER_TAG}") + include_directories( + ${PROJECT_BINARY_DIR} # config.h + ${SDL2_INCLUDE_DIRS} ++ ${MPEG2_INCLUDE_DIRS} + ) + + if( "${CMAKE_TARGET_ARCHITECTURES}" MATCHES "i386" ) +@@ -98,10 +100,10 @@ add_subdirectory(timer) + add_subdirectory(video) + add_subdirectory(vldp) + +-add_dependencies( vldp libmpeg2 ) +-add_dependencies( ldp-out vldp ) +-add_dependencies( game vldp ) +-add_dependencies( sound vldp ) ++#add_dependencies( vldp libmpeg2 ) ++#add_dependencies( ldp-out vldp ) ++#add_dependencies( game vldp ) ++#add_dependencies( sound vldp ) + + add_executable( hypseus hypseus.cpp globals.h ) + target_link_libraries( hypseus plog io timer sound video cpu game ${SDL2_LIBRARIES} ${SDL2_TTF_LIBRARIES}) +diff -rupN hypseus.orig/src/vldp/vldp.h hypseus.new/src/vldp/vldp.h +--- hypseus.orig/src/vldp/vldp.h 2021-02-09 18:13:21.665745426 -0500 ++++ hypseus.new/src/vldp/vldp.h 2021-02-09 19:44:56.957310374 -0500 +@@ -34,6 +34,8 @@ extern "C" { + // Ubuntu Linux complains with plain + #include // only used for threading + ++#include ++ + struct yuv_buf { + uint8_t *Y; // Y channel + uint8_t *U; // U channel +diff -rupN hypseus.orig/src/vldp/vldp_internal.cpp hypseus.new/src/vldp/vldp_internal.cpp +--- hypseus.orig/src/vldp/vldp_internal.cpp 2021-02-09 18:13:21.665745426 -0500 ++++ hypseus.new/src/vldp/vldp_internal.cpp 2021-02-09 19:44:56.957310374 -0500 +@@ -37,8 +37,6 @@ + + #include + +-#include +- + // NOTICE : these variables should only be used by the private thread + // !!!!!!!!!!!! + diff --git a/packages/games/emulators/lzdoom/config/RG351MP/lzdoom.ini b/packages/games/emulators/lzdoom/config/RG351MP/lzdoom.ini new file mode 100644 index 000000000..a3f343a0b --- /dev/null +++ b/packages/games/emulators/lzdoom/config/RG351MP/lzdoom.ini @@ -0,0 +1,2601 @@ +# This file was generated by LZDoom 3.88a-65-g7ebe6cc37-m on 2021-11-13 11:57:44 +# These are the directories to automatically search for IWADs. +# Each directory should be on a separate line, preceded by Path= +[IWADSearch.Directories] +Path=. +Path=$DOOMWADDIR +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom + +# These are the directories to search for wads added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for IWADSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom +Path=$DOOMWADDIR + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for IWADSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/lzdoom/soundfonts +Path=/storage/.config/distribution/lzdoom/fm_banks + +# Files to automatically execute when running the corresponding game. +# Each file should be on its own line, preceded by Path= + +[Doom.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +# WAD files to always load. These are loaded after the IWAD but before +# any files added with -file. Place each file on its own line, preceded +# by Path= +[Global.Autoload] + +# Wad files to automatically load depending on the game and IWAD you are +# playing. You may have have files that are loaded for all similar IWADs +# (the game) and files that are only loaded for particular IWADs. For example, +# any files listed under 'doom.Autoload' will be loaded for any version of Doom, +# but files listed under 'doom.doom2.Autoload' will only load when you are +# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under +# 'doom.doom2.commercial.Autoload' only when playing doom2.wad. + +[doom.Autoload] + +[doom.id.Autoload] + +[doom.id.doom2.Autoload] + +[doom.id.doom2.nerve.Autoload] + +[doom.id.doom2.commercial.Autoload] + +[doom.id.doom2.commercial.french.Autoload] + +[doom.id.doom2.commercial.xbox.Autoload] + +[doom.id.doom2.unity.Autoload] + +[doom.id.doom2.bfg.Autoload] + +[doom.id.doom1.Autoload] + +[doom.id.doom1.sigil.Autoload] + +[doom.id.doom2.plutonia.Autoload] + +[doom.id.doom2.plutonia.unity.Autoload] + +[doom.id.doom2.tnt.Autoload] + +[doom.id.doom2.tnt.unity.Autoload] + +[doom.id.doom1.registered.Autoload] + +[doom.id.doom1.ultimate.Autoload] + +[doom.id.doom1.ultimate.xbox.Autoload] + +[doom.id.wadsmoosh.Autoload] + +[doom.id.doom1.unity.Autoload] + +[doom.id.doom1.bfg.Autoload] + +[doom.freedoom.Autoload] + +[doom.freedoom.demo.Autoload] + +[doom.freedoom.phase1.Autoload] + +[doom.freedoom.phase2.Autoload] + +[doom.freedoom.freedm.Autoload] + +[heretic.Autoload] + +[heretic.heretic.Autoload] + +[heretic.shadow.Autoload] + +[blasphemer.Autoload] + +[hexen.Autoload] + +[hexen.deathkings.Autoload] + +[hexen.hexen.Autoload] + +[strife.Autoload] + +[strife.strife.Autoload] + +[strife.veteran.Autoload] + +[chex.Autoload] + +[chex.chex1.Autoload] + +[chex.chex3.Autoload] + +[urbanbrawl.Autoload] + +[hacx.Autoload] + +[hacx.hacx1.Autoload] + +[hacx.hacx2.Autoload] + +[harmony.Autoload] + +[square.Autoload] + +[square.squareware.Autoload] + +[square.square.Autoload] + +[delaweare.Autoload] + +[woolball.Autoload] + +[woolball.rotwb.Autoload] + +[doom.id.doom2.wadsmoosh.Autoload] + +[LastRun] +Version=222 + +[GlobalSettings] +Gamma=1.4999995231628418 +I_FriendlyWindowTitle=true +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=false +autoloadconpics=true +autoloadlights=false +autoloadwidescreen=true +autosavecount=4 +autosavenum=1 +bgamma=1 +chase_dist=90 +chase_height=-8 +chat_self=false +cl_capfps=false +cl_noprediction=false +cl_oldfreelooklimit=false +cl_predict_lerpscale=0.05000000074505806 +cl_predict_lerpthreshold=2 +cl_predict_specials=true +cl_run=false +cl_waitforsave=true +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +defaultiwad=DOOM Shareware +demo_compress=true +developer=0 +disableautoload=false +disableautosave=0 +enablescriptscreenshot=false +fluid_chorus=true +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=1 +fluid_interp=1 +fluid_lib= +fluid_patchset=lzdoom +fluid_reverb=true +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=4 +fluid_voices=128 +freelook=true +fullscreen=true +ggamma=1 +gl_billboard_faces_camera=false +gl_billboard_mode=0 +gl_billboard_particles=true +gl_cachenodes=true +gl_cachetime=0.6000000238418579 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_distfog=70 +gl_dither_bpc=0 +gl_enhanced_nv_stealth=3 +gl_es=false +gl_finishbeforeswap=false +gl_fxaa=0 +gl_legacy_mode=false +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_particles=true +gl_light_shadowmap=false +gl_light_sprites=true +gl_lights=true +gl_lights_additive=false +gl_lights_checkside=true +gl_line_distance_cull=0 +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_mirrors=true +gl_multisample=1 +gl_no_skyclear=false +gl_particles_style=2 +gl_plane_reflection=true +gl_render_precise=false +gl_renderbuffers=true +gl_riskymodernpath=false +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_sort_textures=false +gl_sprite_blend=false +gl_sprite_distance_cull=0 +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=0 +gl_texture_filter_anisotropic=8 +gl_texture_format=0 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=7 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gl_texture_useshaders=true +gl_usecolorblending=true +gl_usefb=false +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +i_soundinbackground=false +inter_subtitles=false +invertmouse=false +invertmousex=false +joy_background=true +k_modern=1 +language=auto +longsavemessages=true +lookstrafe=false +m_blockcontrollers=false +m_filter=false +m_forward=1 +m_noprescale=false +m_pitch=1 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=2 +m_use_mouse=2 +m_yaw=1 +map_point_coordinates=true +midi_config=lzdoom +midi_dmxgus=false +midi_voices=32 +min_sustain_time=5000 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mouse_sensitivity=1.5 +nointerscrollabort=false +nomonsterinterpolation=false +oldsaveorder=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=0 +opn_fullpan=true +opn_run_at_pcm_rate=false +pistolstart=false +png_gamma=0 +png_level=5 +queryiwad=true +quicksavenum=-1 +quicksaverotation=false +quicksaverotationcount=4 +r_actorspriteshadow=1 +r_actorspriteshadowdist=1500 +r_blendmethod=false +r_dynlights=false +r_fakecontrast=1 +r_fullbrightignoresectorcolor=true +r_fuzzscale=true +r_line_distance_cull=6000 +r_linearsky=false +r_magfilter=false +r_minfilter=false +r_mipmap=false +r_mirror_recursions=2 +r_models=true +r_models_carmack=false +r_multithreaded=1 +r_polyrenderer=false +r_quakeintensity=1 +r_sprite_distance_cull=3000 +r_ticstability=true +rgamma=1 +save_dir= +save_formatted=false +saveloadconfirmation=true +savestatistics=0 +screenshot_dir= +screenshot_quiet=false +screenshot_type=png +show_messages=true +showendoom=0 +snd_aldevice=Default +snd_alresampler=Default +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=false +snd_hrtf=0 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_waterreverb=true +statfile=zdoomstat.txt +storesavepic=true +strictdecorate=false +swtruecolor=true +telezoom=true +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=lzdoom +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +turnspeedsprintfast=1280 +turnspeedsprintslow=320 +turnspeedwalkfast=640 +turnspeedwalkslow=320 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=true +vid_defbits=24 +vid_defheight=240 +vid_defwidth=320 +vid_displaybits=32 +vid_forcesurface=false +vid_glswfb=false +vid_hdr=false +vid_hwaalines=true +vid_hwgamma=2 +vid_maxfps=200 +vid_refreshrate=0 +vid_renderer=0 +vid_saturation=1 +vid_scale_customheight=200 +vid_scale_customlinear=false +vid_scale_customstretched=false +vid_scale_customwidth=320 +vid_scalefactor=1 +vid_scalemode=1 +vid_vsync=false +vid_winscale=1 +vr_enable_quadbuffered=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_mode=0 +vr_screendist=0.800000011920929 +vr_swap_eyes=false +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[Doom.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Doom.ConsoleVariables] +addrocketexplosion=false +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=2 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_hideextreme=false +menu_screenratios=0 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Doom.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Doom.ConfigOnlyVariables] + +[Doom.UnknownConsoleVariables] + +[Doom.ConsoleAliases] + +[Doom.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy5=+speed +Joy6=+attack +Joy9=+forward +Joy10=+back +Joy11=+left +Joy12=+right +Joy14=menu_main +Joy15=toggle cl_run +Joy16=centerview + +[Doom.DoubleBindings] + +[Doom.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Joy:JS:0] +Sensitivity=1.2 +Axis0deadzone=0.500001 +Axis0scale=0.6 +Axis1deadzone=0.500001 +Axis1scale=0.6 +Axis2deadzone=0.500001 +Axis2scale=0.6 +Axis2map=0 +Axis3deadzone=0.500001 +Axis3scale=0.6 +Axis3map=1 + +[Strife.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Strife.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Strife.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Strife.ConfigOnlyVariables] + +[Strife.UnknownConsoleVariables] + +[Strife.ConsoleAliases] + +[Strife.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Strife.DoubleBindings] + +[Strife.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Hexen.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=2 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Hexen.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Hexen.ConfigOnlyVariables] + +[Hexen.UnknownConsoleVariables] + +[Hexen.ConsoleAliases] + +[Hexen.Bindings] +5=use ArtiInvulnerability2 +6=use ArtiPork +7=use ArtiTeleportOther +8=use ArtiTeleport +9=use ArtiBlastRadius +0=useflechette +T=messagemode +\=use ArtiHealth +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Hexen.DoubleBindings] + +[Hexen.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.Player.Mod] +b_flashlighthpos=0 +b_flashlightlowq=0 +b_flashlightmode=0 +b_flashlightvpos=18 +bd_bloodamount=2 +bd_disablebloodyscreen=0 +bd_enablesprint=0 +bd_lowgraphicsmode=0 +bd_morebloodmist=0 +bd_sbartype=1 +cl_step_delaymul=1 +cl_step_volmul=7 + +[Doom.LocalServerInfo.Mod] +bd_classicmonsters=0 +bd_disablecrueltybonus=0 +bd_disabledecorations=0 +bd_disabledemonspheres=0 +bd_disablefriendlymarines=0 +bd_disablemapenhancements=0 +bd_disablenewenemies=0 +bd_disablenewguns=0 +bd_disablescanner=0 +bd_disablewaterripples2=1 +bd_footstepsounds=1 +bd_infinitecasings=0 +bd_rocketbackblast=1 +bd_shootablerocketammo=0 +bd_voxeldec=1 +flashlight_color=ff ff ff +flashlight_inner=13 +flashlight_intensity=235 +flashlight_location=0 +flashlight_outer=18 +gmota_nomusic=0 +isrunningzandronum=1 +zdoombrutalblood=2 +zdoombrutaljanitor=0 + +[Doom.ConfigOnlyVariables.Mod] + +[Doom.GMOTAactionkeys.Bindings] + +[Doom.GMOTAactionkeys.DoubleBindings] + +[UrbanBrawl.AutoExec] +Path=/storage/.config/lzdoom/autoexec.cfg + +[UrbanBrawl.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[UrbanBrawl.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[UrbanBrawl.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[UrbanBrawl.ConfigOnlyVariables] + +[UrbanBrawl.UnknownConsoleVariables] + +[UrbanBrawl.ConsoleAliases] + +[UrbanBrawl.spdivk_keysection.Bindings] +Z=ad2_drop + +[UrbanBrawl.spdivk_keysection.DoubleBindings] + +[UrbanBrawl.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +-=sizedown +Equals=sizeup +Tab=togglemap +W=+forward +E=+jump +T=messagemode +LeftBracket=invprev +RightBracket=invnext +A=+moveleft +S=+back +D=+moveright +`=toggleconsole +Shift=+speed +\=+showscores +X=crouch +Space=+use +CapsLock=toggle cl_run +F1=menu_help +F2=menu_save +F3=menu_load +F4=menu_options +F5=menu_display +F6=quicksave +F7=menu_endgame +F8=togglemessages +F9=quickload +F10=menu_quit +F11=bumpgamma +F12=spynext +SysRq=screenshot +Pause=pause +Home=land +PgUp=+moveup +End=centerview +PgDn=+lookup +Ins=+movedown +Del=+lookdown +Mouse1=+attack +Mouse2=+altattack +Mouse3=invuse +MWheelUp=weapprev +MWheelDown=weapnext +MWheelRight=invnext +MWheelLeft=invprev +DPadUp=togglemap +DPadDown=invuse +DPadLeft=invprev +DPadRight=invnext +Pad_Start=pause +Pad_Back=menu_main +LThumb=crouch +LShoulder=weapprev +RShoulder=weapnext +LTrigger=+altattack +RTrigger=+attack +Pad_A=+use +Pad_Y=+jump + +[UrbanBrawl.DoubleBindings] + +[UrbanBrawl.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Chex.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Chex.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=true +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.3999999761581421 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Chex.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Chex.ConfigOnlyVariables] + +[Chex.UnknownConsoleVariables] + +[Chex.ConsoleAliases] + +[Chex.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Chex.DoubleBindings] + +[Chex.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player.Mod] +WoC_AutoPetLeash=true +WoC_Dam_fontclass=DamNumFontGameDefault +WoC_Dam_physics=0 +WoC_Dam_translation=DamDefault +WoC_Dam_usetypes=true +WoC_DamageIndicator=true +WoC_EnemyFloatingHealthBar=true +WoC_EnemyHealthBar=true +WoC_FloatingHealthBar=true +WoC_GoreLevel=0 +WoC_HPBars_FullBright=false +WoC_HPBars_Offset=0.10000000149011612 +WoC_HPBars_RenderStyle=true +WoC_HPBars_Scale=0.30000001192092896 +WoC_MajorPotion=0.6600000262260437 +WoC_MinorPotion=1 +WoC_MysticUrn=0.25 +WoC_NormalPotion=0.75 +WoC_PlayerDamageDisplay=true +WoC_RandomSkills=false +WoC_RandomStats=false +WoC_SupremePotion=0.5 + +[Hexen.LocalServerInfo.Mod] +WoC_AgilitySpeedMult=1 +WoC_Dam_enabled=true +WoC_Dam_shootable=false +WoC_Dam_spray=0 +WoC_Director=false +WoC_DisableAwards=false +WoC_DisableKillingSpree=false +WoC_ExpDeath=1 +WoC_ExpDeathAmount=33 +WoC_ExpMult=100 +WoC_GoldDeath=true +WoC_GoldDeathAmount=50 +WoC_HPBars_Enable=true +WoC_MaxJump=12 +WoC_MaxLevel=160 +WoC_MaxSpeed=200 +WoC_MinLevel=1 +WoC_ServerDisableHealthBar=false +WoC_SetMonstersOnce=true +WoC_SpeedMult=1 +WoC_WeaponStart=false + +[Hexen.ConfigOnlyVariables.Mod] + +[Hexen.WOCKeysection.Bindings] +Joy16=viewStats +Joy2=abil1 +Joy13=abil2 +Joy14=abil3 +Joy15=abil4 + +[Hexen.WOCKeysection.DoubleBindings] + +[Hexen.woc_weaponsection.Bindings] + +[Hexen.woc_weaponsection.DoubleBindings] + +[Hexen.woc_artifacts.Bindings] + +[Hexen.woc_artifacts.DoubleBindings] + +[Hexen.woc_flasks.Bindings] + +[Hexen.woc_flasks.DoubleBindings] + +[Heretic.Player] +autoaim=35 +classicflight=false +color=3f 60 40 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Heretic.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=1 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=2 +cl_rockettrails=3 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=true +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Heretic.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Heretic.ConfigOnlyVariables] + +[Heretic.UnknownConsoleVariables] + +[Heretic.ConsoleAliases] + +[Heretic.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +Backspace=use ArtiTomeOfPower +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Heretic.DoubleBindings] + +[Heretic.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.SteveFlashlightKeySection.Bindings] +F=toggleflashlight_bind + +[Doom.SteveFlashlightKeySection.DoubleBindings] + +[Doom.options.Bindings] +Y=rdrone +Z=tflare +T=pturret +Mouse3=isight +M=MusicPlay +B=MuteTracker +P=rain +K=death + +[Doom.options.DoubleBindings] + +[Doom.BrutalDoomActions.Bindings] +Q=kickem +R=reload +F=flashlightswitch +G=grenadetoss + +[Doom.BrutalDoomActions.DoubleBindings] + +[Doom.BrutalDoomInteractions.Bindings] +H=brutaltaunt +V=wave1 +N=wave2 +J=advtaunt +K=oneliner +X=dual +O=selectammodrop + +[Doom.BrutalDoomInteractions.DoubleBindings] + +[Doom.BrutalDoomAdvMoves.Bindings] + +[Doom.BrutalDoomAdvMoves.DoubleBindings] + +[Doom.CODBO_Active.Bindings] +B=knife +KP8=grenade +Joy1=invuse + +[Doom.CODBO_Active.DoubleBindings] + +[Doom.CODBO_Advanced.Bindings] +M=Scopeselection +P=WeaponLookselection + +[Doom.CODBO_Advanced.DoubleBindings] + +[Doom.CODBO_EQ.Bindings] +KP1=use Medicalkit_COD +KP2=use TacticalInsertion +KP3=use BeaconHand +KP4=use ClaymoreHand +KP5=use C4Hand + +[Doom.CODBO_EQ.DoubleBindings] + diff --git a/packages/games/emulators/lzdoom/config/RG351P/lzdoom.ini b/packages/games/emulators/lzdoom/config/RG351P/lzdoom.ini new file mode 100644 index 000000000..39c7cfb35 --- /dev/null +++ b/packages/games/emulators/lzdoom/config/RG351P/lzdoom.ini @@ -0,0 +1,2600 @@ +# This file was generated by LZDoom 3.87c-183-g96a09d4471-m on 2021-10-11 19:20:24 +# These are the directories to automatically search for IWADs. +# Each directory should be on a separate line, preceded by Path= +[IWADSearch.Directories] +Path=. +Path=$DOOMWADDIR +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom + +# These are the directories to search for wads added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for IWADSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom +Path=$DOOMWADDIR + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for IWADSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/lzdoom/soundfonts +Path=/storage/.config/distribution/lzdoom/fm_banks + +# Files to automatically execute when running the corresponding game. +# Each file should be on its own line, preceded by Path= + +[Doom.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +# WAD files to always load. These are loaded after the IWAD but before +# any files added with -file. Place each file on its own line, preceded +# by Path= +[Global.Autoload] + +# Wad files to automatically load depending on the game and IWAD you are +# playing. You may have have files that are loaded for all similar IWADs +# (the game) and files that are only loaded for particular IWADs. For example, +# any files listed under 'doom.Autoload' will be loaded for any version of Doom, +# but files listed under 'doom.doom2.Autoload' will only load when you are +# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under +# 'doom.doom2.commercial.Autoload' only when playing doom2.wad. + +[doom.Autoload] + +[doom.id.Autoload] + +[doom.id.doom2.Autoload] + +[doom.id.doom2.nerve.Autoload] + +[doom.id.doom2.commercial.Autoload] + +[doom.id.doom2.commercial.french.Autoload] + +[doom.id.doom2.commercial.xbox.Autoload] + +[doom.id.doom2.unity.Autoload] + +[doom.id.doom2.bfg.Autoload] + +[doom.id.doom1.Autoload] + +[doom.id.doom1.sigil.Autoload] + +[doom.id.doom2.plutonia.Autoload] + +[doom.id.doom2.plutonia.unity.Autoload] + +[doom.id.doom2.tnt.Autoload] + +[doom.id.doom2.tnt.unity.Autoload] + +[doom.id.doom1.registered.Autoload] + +[doom.id.doom1.ultimate.Autoload] + +[doom.id.doom1.ultimate.xbox.Autoload] + +[doom.id.wadsmoosh.Autoload] + +[doom.id.doom1.unity.Autoload] + +[doom.id.doom1.bfg.Autoload] + +[doom.freedoom.Autoload] + +[doom.freedoom.demo.Autoload] + +[doom.freedoom.phase1.Autoload] + +[doom.freedoom.phase2.Autoload] + +[doom.freedoom.freedm.Autoload] + +[heretic.Autoload] + +[heretic.heretic.Autoload] + +[heretic.shadow.Autoload] + +[blasphemer.Autoload] + +[hexen.Autoload] + +[hexen.deathkings.Autoload] + +[hexen.hexen.Autoload] + +[strife.Autoload] + +[strife.strife.Autoload] + +[strife.veteran.Autoload] + +[chex.Autoload] + +[chex.chex1.Autoload] + +[chex.chex3.Autoload] + +[urbanbrawl.Autoload] + +[hacx.Autoload] + +[hacx.hacx1.Autoload] + +[hacx.hacx2.Autoload] + +[harmony.Autoload] + +[square.Autoload] + +[square.squareware.Autoload] + +[square.square.Autoload] + +[delaweare.Autoload] + +[woolball.Autoload] + +[woolball.rotwb.Autoload] + +[doom.id.doom2.wadsmoosh.Autoload] + +[LastRun] +Version=222 + +[GlobalSettings] +Gamma=1.4999995231628418 +I_FriendlyWindowTitle=true +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=false +autoloadconpics=true +autoloadlights=false +autoloadwidescreen=true +autosavecount=4 +autosavenum=1 +bgamma=1 +chase_dist=90 +chase_height=-8 +chat_self=false +cl_capfps=false +cl_noprediction=false +cl_oldfreelooklimit=false +cl_predict_lerpscale=0.05000000074505806 +cl_predict_lerpthreshold=2 +cl_predict_specials=true +cl_run=false +cl_waitforsave=true +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +defaultiwad=DOOM Shareware +demo_compress=true +developer=0 +disableautoload=false +disableautosave=0 +enablescriptscreenshot=false +fluid_chorus=true +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=1 +fluid_interp=1 +fluid_lib= +fluid_patchset=lzdoom +fluid_reverb=true +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=4 +fluid_voices=128 +freelook=true +fullscreen=false +ggamma=1 +gl_billboard_faces_camera=false +gl_billboard_mode=0 +gl_billboard_particles=true +gl_cachenodes=true +gl_cachetime=0.6000000238418579 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_distfog=70 +gl_dither_bpc=0 +gl_enhanced_nv_stealth=3 +gl_es=false +gl_finishbeforeswap=false +gl_fxaa=0 +gl_legacy_mode=false +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_particles=true +gl_light_shadowmap=false +gl_light_sprites=true +gl_lights=true +gl_lights_additive=false +gl_lights_checkside=true +gl_line_distance_cull=8000 +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_mirrors=true +gl_multisample=1 +gl_no_skyclear=false +gl_particles_style=2 +gl_plane_reflection=true +gl_render_precise=false +gl_renderbuffers=true +gl_riskymodernpath=false +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_sort_textures=false +gl_sprite_blend=false +gl_sprite_distance_cull=4000 +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=0 +gl_texture_filter_anisotropic=8 +gl_texture_format=0 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=7 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gl_texture_useshaders=true +gl_usecolorblending=true +gl_usefb=false +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +i_soundinbackground=false +inter_subtitles=false +invertmouse=false +invertmousex=false +joy_background=true +k_modern=1 +language=auto +longsavemessages=true +lookstrafe=false +m_blockcontrollers=false +m_filter=false +m_forward=1 +m_noprescale=false +m_pitch=1 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=2 +m_use_mouse=2 +m_yaw=1 +map_point_coordinates=true +midi_config=lzdoom +midi_dmxgus=false +midi_voices=32 +min_sustain_time=5000 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mouse_sensitivity=1.5 +nointerscrollabort=false +nomonsterinterpolation=false +oldsaveorder=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=0 +opn_fullpan=true +opn_run_at_pcm_rate=false +png_gamma=0 +png_level=5 +queryiwad=true +quicksavenum=-1 +quicksaverotation=false +quicksaverotationcount=4 +r_actorspriteshadow=1 +r_actorspriteshadowdist=1500 +r_blendmethod=false +r_dynlights=false +r_fakecontrast=1 +r_fullbrightignoresectorcolor=true +r_fuzzscale=true +r_line_distance_cull=8000 +r_linearsky=false +r_magfilter=false +r_minfilter=true +r_mipmap=false +r_mirror_recursions=2 +r_models=true +r_models_carmack=false +r_multithreaded=1 +r_polyrenderer=false +r_quakeintensity=1 +r_sprite_distance_cull=4000 +r_ticstability=true +rgamma=1 +save_dir= +save_formatted=false +saveloadconfirmation=true +savestatistics=0 +screenshot_dir= +screenshot_quiet=false +screenshot_type=png +show_messages=true +showendoom=0 +snd_aldevice=Default +snd_alresampler=Default +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=false +snd_hrtf=0 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_waterreverb=true +statfile=zdoomstat.txt +storesavepic=true +strictdecorate=false +swtruecolor=true +telezoom=true +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=lzdoom +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +turnspeedsprintfast=1280 +turnspeedsprintslow=320 +turnspeedwalkfast=640 +turnspeedwalkslow=320 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=true +vid_defbits=24 +vid_defheight=640 +vid_defwidth=480 +vid_displaybits=32 +vid_forcesurface=false +vid_glswfb=false +vid_hdr=false +vid_hwaalines=true +vid_hwgamma=2 +vid_maxfps=200 +vid_refreshrate=0 +vid_renderer=0 +vid_saturation=1 +vid_scale_customheight=200 +vid_scale_customlinear=false +vid_scale_customstretched=false +vid_scale_customwidth=320 +vid_scalefactor=1 +vid_scalemode=0 +vid_vsync=false +vid_winscale=1 +vr_enable_quadbuffered=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_screendist=0.800000011920929 +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[Doom.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Doom.ConsoleVariables] +addrocketexplosion=false +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_hideextreme=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Doom.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Doom.ConfigOnlyVariables] + +[Doom.UnknownConsoleVariables] + +[Doom.ConsoleAliases] + +[Doom.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +`=toggleconsole +Joy1=+use +Joy2=invuse +Joy3=+jump +Joy5=+speed +Joy6=+attack +Joy7=weapprev +Joy8=menu_endgame +Joy9=toggle cl_run +Joy10=centerview +POV1Up=+forward +POV1Right=+right +POV1Down=+back +POV1Left=+left + +[Doom.DoubleBindings] + +[Doom.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Joy:JS:0] +Sensitivity=1.2 +Axis0deadzone=0.500001 +Axis0scale=-0.6 +Axis0map=0 +Axis1deadzone=0.500001 +Axis1scale=-0.6 +Axis2deadzone=0.500001 +Axis2scale=0.6 +Axis2map=3 +Axis3deadzone=0.500001 +Axis3scale=0.6 +Axis3map=1 + +[Strife.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Strife.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Strife.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Strife.ConfigOnlyVariables] + +[Strife.UnknownConsoleVariables] + +[Strife.ConsoleAliases] + +[Strife.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Strife.DoubleBindings] + +[Strife.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Hexen.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=2 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Hexen.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Hexen.ConfigOnlyVariables] + +[Hexen.UnknownConsoleVariables] + +[Hexen.ConsoleAliases] + +[Hexen.Bindings] +5=use ArtiInvulnerability2 +6=use ArtiPork +7=use ArtiTeleportOther +8=use ArtiTeleport +9=use ArtiBlastRadius +0=useflechette +T=messagemode +\=use ArtiHealth +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Hexen.DoubleBindings] + +[Hexen.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.Player.Mod] +b_flashlighthpos=0 +b_flashlightlowq=0 +b_flashlightmode=0 +b_flashlightvpos=18 +bd_bloodamount=2 +bd_disablebloodyscreen=0 +bd_enablesprint=0 +bd_lowgraphicsmode=0 +bd_morebloodmist=0 +bd_sbartype=1 +cl_step_delaymul=1 +cl_step_volmul=7 + +[Doom.LocalServerInfo.Mod] +bd_classicmonsters=0 +bd_disablecrueltybonus=0 +bd_disabledecorations=0 +bd_disabledemonspheres=0 +bd_disablefriendlymarines=0 +bd_disablemapenhancements=0 +bd_disablenewenemies=0 +bd_disablenewguns=0 +bd_disablescanner=0 +bd_disablewaterripples2=1 +bd_footstepsounds=1 +bd_infinitecasings=0 +bd_rocketbackblast=1 +bd_shootablerocketammo=0 +bd_voxeldec=1 +flashlight_color=ff ff ff +flashlight_inner=13 +flashlight_intensity=235 +flashlight_location=0 +flashlight_outer=18 +gmota_nomusic=0 +isrunningzandronum=1 +zdoombrutalblood=2 +zdoombrutaljanitor=0 + +[Doom.ConfigOnlyVariables.Mod] + +[Doom.GMOTAactionkeys.Bindings] + +[Doom.GMOTAactionkeys.DoubleBindings] + +[UrbanBrawl.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[UrbanBrawl.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[UrbanBrawl.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[UrbanBrawl.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[UrbanBrawl.ConfigOnlyVariables] + +[UrbanBrawl.UnknownConsoleVariables] + +[UrbanBrawl.ConsoleAliases] + +[UrbanBrawl.spdivk_keysection.Bindings] +Z=ad2_drop + +[UrbanBrawl.spdivk_keysection.DoubleBindings] + +[UrbanBrawl.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +-=sizedown +Equals=sizeup +Tab=togglemap +W=+forward +E=+jump +T=messagemode +LeftBracket=invprev +RightBracket=invnext +A=+moveleft +S=+back +D=+moveright +`=toggleconsole +Shift=+speed +\=+showscores +X=crouch +Space=+use +CapsLock=toggle cl_run +F1=menu_help +F2=menu_save +F3=menu_load +F4=menu_options +F5=menu_display +F6=quicksave +F7=menu_endgame +F8=togglemessages +F9=quickload +F10=menu_quit +F11=bumpgamma +F12=spynext +SysRq=screenshot +Pause=pause +Home=land +PgUp=+moveup +End=centerview +PgDn=+lookup +Ins=+movedown +Del=+lookdown +Mouse1=+attack +Mouse2=+altattack +Mouse3=invuse +MWheelUp=weapprev +MWheelDown=weapnext +MWheelRight=invnext +MWheelLeft=invprev +DPadUp=togglemap +DPadDown=invuse +DPadLeft=invprev +DPadRight=invnext +Pad_Start=pause +Pad_Back=menu_main +LThumb=crouch +LShoulder=weapprev +RShoulder=weapnext +LTrigger=+altattack +RTrigger=+attack +Pad_A=+use +Pad_Y=+jump + +[UrbanBrawl.DoubleBindings] + +[UrbanBrawl.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Chex.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Chex.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=true +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.3999999761581421 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Chex.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Chex.ConfigOnlyVariables] + +[Chex.UnknownConsoleVariables] + +[Chex.ConsoleAliases] + +[Chex.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Chex.DoubleBindings] + +[Chex.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player.Mod] +WoC_AutoPetLeash=true +WoC_Dam_fontclass=DamNumFontGameDefault +WoC_Dam_physics=0 +WoC_Dam_translation=DamDefault +WoC_Dam_usetypes=true +WoC_DamageIndicator=true +WoC_EnemyFloatingHealthBar=true +WoC_EnemyHealthBar=true +WoC_FloatingHealthBar=true +WoC_GoreLevel=0 +WoC_HPBars_FullBright=false +WoC_HPBars_Offset=0.10000000149011612 +WoC_HPBars_RenderStyle=true +WoC_HPBars_Scale=0.30000001192092896 +WoC_MajorPotion=0.6600000262260437 +WoC_MinorPotion=1 +WoC_MysticUrn=0.25 +WoC_NormalPotion=0.75 +WoC_PlayerDamageDisplay=true +WoC_RandomSkills=false +WoC_RandomStats=false +WoC_SupremePotion=0.5 + +[Hexen.LocalServerInfo.Mod] +WoC_AgilitySpeedMult=1 +WoC_Dam_enabled=true +WoC_Dam_shootable=false +WoC_Dam_spray=0 +WoC_Director=false +WoC_DisableAwards=false +WoC_DisableKillingSpree=false +WoC_ExpDeath=1 +WoC_ExpDeathAmount=33 +WoC_ExpMult=100 +WoC_GoldDeath=true +WoC_GoldDeathAmount=50 +WoC_HPBars_Enable=true +WoC_MaxJump=12 +WoC_MaxLevel=160 +WoC_MaxSpeed=200 +WoC_MinLevel=1 +WoC_ServerDisableHealthBar=false +WoC_SetMonstersOnce=true +WoC_SpeedMult=1 +WoC_WeaponStart=false + +[Hexen.ConfigOnlyVariables.Mod] + +[Hexen.WOCKeysection.Bindings] +Joy16=viewStats +Joy2=abil1 +Joy13=abil2 +Joy14=abil3 +Joy15=abil4 + +[Hexen.WOCKeysection.DoubleBindings] + +[Hexen.woc_weaponsection.Bindings] + +[Hexen.woc_weaponsection.DoubleBindings] + +[Hexen.woc_artifacts.Bindings] + +[Hexen.woc_artifacts.DoubleBindings] + +[Hexen.woc_flasks.Bindings] + +[Hexen.woc_flasks.DoubleBindings] + +[Heretic.Player] +autoaim=35 +classicflight=false +color=3f 60 40 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Heretic.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=1 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=2 +cl_rockettrails=3 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=true +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Heretic.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Heretic.ConfigOnlyVariables] + +[Heretic.UnknownConsoleVariables] + +[Heretic.ConsoleAliases] + +[Heretic.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +Backspace=use ArtiTomeOfPower +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Heretic.DoubleBindings] + +[Heretic.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.SteveFlashlightKeySection.Bindings] +F=toggleflashlight_bind + +[Doom.SteveFlashlightKeySection.DoubleBindings] + +[Doom.options.Bindings] +Y=rdrone +Z=tflare +T=pturret +Mouse3=isight +M=MusicPlay +B=MuteTracker +P=rain +K=death + +[Doom.options.DoubleBindings] + +[Doom.BrutalDoomActions.Bindings] +Q=kickem +R=reload +F=flashlightswitch +G=grenadetoss + +[Doom.BrutalDoomActions.DoubleBindings] + +[Doom.BrutalDoomInteractions.Bindings] +H=brutaltaunt +V=wave1 +N=wave2 +J=advtaunt +K=oneliner +X=dual +O=selectammodrop + +[Doom.BrutalDoomInteractions.DoubleBindings] + +[Doom.BrutalDoomAdvMoves.Bindings] + +[Doom.BrutalDoomAdvMoves.DoubleBindings] + +[Doom.CODBO_Active.Bindings] +B=knife +KP8=grenade +Joy1=invuse + +[Doom.CODBO_Active.DoubleBindings] + +[Doom.CODBO_Advanced.Bindings] +M=Scopeselection +P=WeaponLookselection + +[Doom.CODBO_Advanced.DoubleBindings] + +[Doom.CODBO_EQ.Bindings] +KP1=use Medicalkit_COD +KP2=use TacticalInsertion +KP3=use BeaconHand +KP4=use ClaymoreHand +KP5=use C4Hand + +[Doom.CODBO_EQ.DoubleBindings] + diff --git a/packages/games/emulators/lzdoom/config/lzdoom.ini b/packages/games/emulators/lzdoom/config/lzdoom.ini new file mode 100644 index 000000000..b6994bf77 --- /dev/null +++ b/packages/games/emulators/lzdoom/config/lzdoom.ini @@ -0,0 +1,2599 @@ +# This file was generated by LZDoom 3.87c-85-g3b0921fcb-m on 2021-05-24 17:30:07 +# These are the directories to automatically search for IWADs. +# Each directory should be on a separate line, preceded by Path= +[IWADSearch.Directories] +Path=. +Path=$DOOMWADDIR +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom + +# These are the directories to search for wads added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for IWADSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/lzdoom +Path=/storage/roms/doom +Path=$DOOMWADDIR + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for IWADSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/lzdoom/soundfonts +Path=/storage/.config/distribution/lzdoom/fm_banks + +# Files to automatically execute when running the corresponding game. +# Each file should be on its own line, preceded by Path= + +[Doom.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Heretic.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Hexen.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Strife.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +[Chex.AutoExec] +Path=/storage/.config/distribution/lzdoom/autoexec.cfg + +# WAD files to always load. These are loaded after the IWAD but before +# any files added with -file. Place each file on its own line, preceded +# by Path= +[Global.Autoload] + +# Wad files to automatically load depending on the game and IWAD you are +# playing. You may have have files that are loaded for all similar IWADs +# (the game) and files that are only loaded for particular IWADs. For example, +# any files listed under 'doom.Autoload' will be loaded for any version of Doom, +# but files listed under 'doom.doom2.Autoload' will only load when you are +# playing a Doom 2 based game (doom2.wad, tnt.wad or plutonia.wad), and files listed under +# 'doom.doom2.commercial.Autoload' only when playing doom2.wad. + +[doom.Autoload] + +[doom.id.Autoload] + +[doom.id.doom2.Autoload] + +[doom.id.doom2.nerve.Autoload] + +[doom.id.doom2.commercial.Autoload] + +[doom.id.doom2.commercial.french.Autoload] + +[doom.id.doom2.commercial.xbox.Autoload] + +[doom.id.doom2.unity.Autoload] + +[doom.id.doom2.bfg.Autoload] + +[doom.id.doom1.Autoload] + +[doom.id.doom1.sigil.Autoload] + +[doom.id.doom2.plutonia.Autoload] + +[doom.id.doom2.plutonia.unity.Autoload] + +[doom.id.doom2.tnt.Autoload] + +[doom.id.doom2.tnt.unity.Autoload] + +[doom.id.doom1.registered.Autoload] + +[doom.id.doom1.ultimate.Autoload] + +[doom.id.doom1.ultimate.xbox.Autoload] + +[doom.id.wadsmoosh.Autoload] + +[doom.id.doom1.unity.Autoload] + +[doom.id.doom1.bfg.Autoload] + +[doom.freedoom.Autoload] + +[doom.freedoom.demo.Autoload] + +[doom.freedoom.phase1.Autoload] + +[doom.freedoom.phase2.Autoload] + +[doom.freedoom.freedm.Autoload] + +[heretic.Autoload] + +[heretic.heretic.Autoload] + +[heretic.shadow.Autoload] + +[blasphemer.Autoload] + +[hexen.Autoload] + +[hexen.deathkings.Autoload] + +[hexen.hexen.Autoload] + +[strife.Autoload] + +[strife.strife.Autoload] + +[strife.veteran.Autoload] + +[chex.Autoload] + +[chex.chex1.Autoload] + +[chex.chex3.Autoload] + +[urbanbrawl.Autoload] + +[hacx.Autoload] + +[hacx.hacx1.Autoload] + +[hacx.hacx2.Autoload] + +[harmony.Autoload] + +[square.Autoload] + +[square.squareware.Autoload] + +[square.square.Autoload] + +[delaweare.Autoload] + +[woolball.Autoload] + +[woolball.rotwb.Autoload] + +[doom.id.doom2.wadsmoosh.Autoload] + +[LastRun] +Version=221 + +[GlobalSettings] +Gamma=1.4999995231628418 +I_FriendlyWindowTitle=true +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=false +autoloadconpics=true +autoloadlights=false +autoloadwidescreen=true +autosavecount=4 +autosavenum=1 +bgamma=1 +chase_dist=90 +chase_height=-8 +chat_self=false +cl_capfps=false +cl_noprediction=false +cl_oldfreelooklimit=false +cl_predict_lerpscale=0.05000000074505806 +cl_predict_lerpthreshold=2 +cl_predict_specials=true +cl_run=false +cl_waitforsave=true +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +defaultiwad=DOOM Shareware +demo_compress=true +developer=0 +disableautoload=false +disableautosave=0 +enablescriptscreenshot=false +fluid_chorus=true +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=1 +fluid_interp=1 +fluid_lib= +fluid_patchset=lzdoom +fluid_reverb=true +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=4 +fluid_voices=128 +freelook=true +fullscreen=false +ggamma=1 +gl_billboard_faces_camera=false +gl_billboard_mode=0 +gl_billboard_particles=true +gl_cachenodes=true +gl_cachetime=0.6000000238418579 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_distfog=70 +gl_dither_bpc=0 +gl_enhanced_nv_stealth=3 +gl_es=false +gl_finishbeforeswap=false +gl_fxaa=0 +gl_legacy_mode=false +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_particles=true +gl_light_shadowmap=false +gl_light_sprites=true +gl_lights=true +gl_lights_additive=false +gl_lights_checkside=true +gl_line_distance_cull=8000 +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_mirrors=true +gl_multisample=1 +gl_no_skyclear=false +gl_particles_style=2 +gl_plane_reflection=true +gl_render_precise=false +gl_renderbuffers=true +gl_riskymodernpath=false +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_sort_textures=false +gl_sprite_blend=false +gl_sprite_distance_cull=4000 +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=0 +gl_texture_filter_anisotropic=8 +gl_texture_format=0 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=7 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gl_texture_useshaders=true +gl_usecolorblending=true +gl_usefb=false +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +i_soundinbackground=false +inter_subtitles=false +invertmouse=false +invertmousex=false +joy_background=true +k_modern=1 +language=auto +longsavemessages=true +lookstrafe=false +m_blockcontrollers=false +m_filter=false +m_forward=1 +m_noprescale=false +m_pitch=1 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=2 +m_use_mouse=2 +m_yaw=1 +map_point_coordinates=true +midi_config=lzdoom +midi_dmxgus=false +midi_voices=32 +min_sustain_time=5000 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mouse_sensitivity=1.5 +nointerscrollabort=false +nomonsterinterpolation=false +oldsaveorder=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=0 +opn_fullpan=true +opn_run_at_pcm_rate=false +png_gamma=0 +png_level=5 +queryiwad=true +quicksavenum=-1 +quicksaverotation=false +quicksaverotationcount=4 +r_blendmethod=false +r_dynlights=false +r_fakecontrast=1 +r_fullbrightignoresectorcolor=true +r_fuzzscale=true +r_line_distance_cull=8000 +r_linearsky=false +r_magfilter=false +r_minfilter=true +r_mipmap=false +r_mirror_recursions=2 +r_models=true +r_models_carmack=false +r_multithreaded=1 +r_polyrenderer=false +r_quakeintensity=1 +r_sprite_distance_cull=4000 +r_ticstability=true +rgamma=1 +save_dir= +save_formatted=false +saveloadconfirmation=true +savestatistics=0 +screenshot_dir= +screenshot_quiet=false +screenshot_type=png +show_messages=true +showendoom=0 +snd_aldevice=Default +snd_alresampler=Default +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=false +snd_hrtf=0 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_waterreverb=true +statfile=zdoomstat.txt +storesavepic=true +strictdecorate=false +swtruecolor=true +telezoom=true +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=lzdoom +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +turnspeedsprintfast=1280 +turnspeedsprintslow=320 +turnspeedwalkfast=640 +turnspeedwalkslow=320 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=true +vid_defbits=24 +vid_defheight=640 +vid_defwidth=480 +vid_displaybits=32 +vid_forcesurface=false +vid_glswfb=false +vid_hdr=false +vid_hwaalines=true +vid_hwgamma=2 +vid_maxfps=200 +vid_refreshrate=0 +vid_renderer=0 +vid_saturation=1 +vid_scale_customheight=200 +vid_scale_customlinear=false +vid_scale_customstretched=false +vid_scale_customwidth=320 +vid_scalefactor=1 +vid_scalemode=0 +vid_vsync=false +vid_winscale=1 +vr_enable_quadbuffered=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_screendist=0.800000011920929 +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[Doom.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Doom.ConsoleVariables] +addrocketexplosion=false +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Doom.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Doom.ConfigOnlyVariables] + +[Doom.UnknownConsoleVariables] + +[Doom.ConsoleAliases] + +[Doom.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy5=+speed +Joy6=+attack +Joy7=weapprev +Joy8=menu_endgame +Joy9=toggle cl_run +Joy10=centerview +POV1Up=+forward +POV1Right=+right +POV1Down=+back +POV1Left=+left +Joy13=togglemap +Joy14=menu_main + +[Doom.DoubleBindings] + +[Doom.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Joy:JS:0] +Sensitivity=1.2 +Axis0deadzone=0.500001 +Axis0scale=-0.6 +Axis0map=0 +Axis1deadzone=0.500001 +Axis1scale=-0.6 +Axis2deadzone=0.500001 +Axis2scale=0.6 +Axis2map=3 +Axis3deadzone=0.500001 +Axis3scale=0.6 +Axis3map=1 + +[Strife.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Strife.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Strife.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Strife.ConfigOnlyVariables] + +[Strife.UnknownConsoleVariables] + +[Strife.ConsoleAliases] + +[Strife.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Strife.DoubleBindings] + +[Strife.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Hexen.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=2 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Hexen.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Hexen.ConfigOnlyVariables] + +[Hexen.UnknownConsoleVariables] + +[Hexen.ConsoleAliases] + +[Hexen.Bindings] +5=use ArtiInvulnerability2 +6=use ArtiPork +7=use ArtiTeleportOther +8=use ArtiTeleport +9=use ArtiBlastRadius +0=useflechette +T=messagemode +\=use ArtiHealth +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Hexen.DoubleBindings] + +[Hexen.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.Player.Mod] +b_flashlighthpos=0 +b_flashlightlowq=0 +b_flashlightmode=0 +b_flashlightvpos=18 +bd_bloodamount=2 +bd_disablebloodyscreen=0 +bd_enablesprint=0 +bd_lowgraphicsmode=0 +bd_morebloodmist=0 +bd_sbartype=1 +cl_step_delaymul=1 +cl_step_volmul=7 + +[Doom.LocalServerInfo.Mod] +bd_classicmonsters=0 +bd_disablecrueltybonus=0 +bd_disabledecorations=0 +bd_disabledemonspheres=0 +bd_disablefriendlymarines=0 +bd_disablemapenhancements=0 +bd_disablenewenemies=0 +bd_disablenewguns=0 +bd_disablescanner=0 +bd_disablewaterripples2=1 +bd_footstepsounds=1 +bd_infinitecasings=0 +bd_rocketbackblast=1 +bd_shootablerocketammo=0 +bd_voxeldec=1 +flashlight_color=ff ff ff +flashlight_inner=13 +flashlight_intensity=235 +flashlight_location=0 +flashlight_outer=18 +gmota_nomusic=0 +isrunningzandronum=1 +zdoombrutalblood=2 +zdoombrutaljanitor=0 + +[Doom.ConfigOnlyVariables.Mod] + +[Doom.GMOTAactionkeys.Bindings] + +[Doom.GMOTAactionkeys.DoubleBindings] + +[UrbanBrawl.AutoExec] +Path=/storage/.config/lzdoom/autoexec.cfg + +[UrbanBrawl.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[UrbanBrawl.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=8 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=10 +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[UrbanBrawl.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[UrbanBrawl.ConfigOnlyVariables] + +[UrbanBrawl.UnknownConsoleVariables] + +[UrbanBrawl.ConsoleAliases] + +[UrbanBrawl.spdivk_keysection.Bindings] +Z=ad2_drop + +[UrbanBrawl.spdivk_keysection.DoubleBindings] + +[UrbanBrawl.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +-=sizedown +Equals=sizeup +Tab=togglemap +W=+forward +E=+jump +T=messagemode +LeftBracket=invprev +RightBracket=invnext +A=+moveleft +S=+back +D=+moveright +`=toggleconsole +Shift=+speed +\=+showscores +X=crouch +Space=+use +CapsLock=toggle cl_run +F1=menu_help +F2=menu_save +F3=menu_load +F4=menu_options +F5=menu_display +F6=quicksave +F7=menu_endgame +F8=togglemessages +F9=quickload +F10=menu_quit +F11=bumpgamma +F12=spynext +SysRq=screenshot +Pause=pause +Home=land +PgUp=+moveup +End=centerview +PgDn=+lookup +Ins=+movedown +Del=+lookdown +Mouse1=+attack +Mouse2=+altattack +Mouse3=invuse +MWheelUp=weapprev +MWheelDown=weapnext +MWheelRight=invnext +MWheelLeft=invprev +DPadUp=togglemap +DPadDown=invuse +DPadLeft=invprev +DPadRight=invnext +Pad_Start=pause +Pad_Back=menu_main +LThumb=crouch +LShoulder=weapprev +RShoulder=weapnext +LTrigger=+altattack +RTrigger=+attack +Pad_A=+use +Pad_Y=+jump + +[UrbanBrawl.DoubleBindings] + +[UrbanBrawl.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Chex.Player] +autoaim=35 +classicflight=false +color=40 cf 00 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Chex.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=4c 38 20 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=88 70 58 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=2c 18 08 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=0 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=0 +cl_rockettrails=1 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=false +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=true +menu_screenratios=-1 +msg=0 +msg0color=6 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=5 +msgmidcolor2=4 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=false +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.3999999761581421 +snd_pitched=false +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=true +wi_showtotaltime=true +wipetype=1 + +[Chex.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Chex.ConfigOnlyVariables] + +[Chex.UnknownConsoleVariables] + +[Chex.ConsoleAliases] + +[Chex.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Chex.DoubleBindings] + +[Chex.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Hexen.Player.Mod] +WoC_AutoPetLeash=true +WoC_Dam_fontclass=DamNumFontGameDefault +WoC_Dam_physics=0 +WoC_Dam_translation=DamDefault +WoC_Dam_usetypes=true +WoC_DamageIndicator=true +WoC_EnemyFloatingHealthBar=true +WoC_EnemyHealthBar=true +WoC_FloatingHealthBar=true +WoC_GoreLevel=0 +WoC_HPBars_FullBright=false +WoC_HPBars_Offset=0.10000000149011612 +WoC_HPBars_RenderStyle=true +WoC_HPBars_Scale=0.30000001192092896 +WoC_MajorPotion=0.6600000262260437 +WoC_MinorPotion=1 +WoC_MysticUrn=0.25 +WoC_NormalPotion=0.75 +WoC_PlayerDamageDisplay=true +WoC_RandomSkills=false +WoC_RandomStats=false +WoC_SupremePotion=0.5 + +[Hexen.LocalServerInfo.Mod] +WoC_AgilitySpeedMult=1 +WoC_Dam_enabled=true +WoC_Dam_shootable=false +WoC_Dam_spray=0 +WoC_Director=false +WoC_DisableAwards=false +WoC_DisableKillingSpree=false +WoC_ExpDeath=1 +WoC_ExpDeathAmount=33 +WoC_ExpMult=100 +WoC_GoldDeath=true +WoC_GoldDeathAmount=50 +WoC_HPBars_Enable=true +WoC_MaxJump=12 +WoC_MaxLevel=160 +WoC_MaxSpeed=200 +WoC_MinLevel=1 +WoC_ServerDisableHealthBar=false +WoC_SetMonstersOnce=true +WoC_SpeedMult=1 +WoC_WeaponStart=false + +[Hexen.ConfigOnlyVariables.Mod] + +[Hexen.WOCKeysection.Bindings] +Joy16=viewStats +Joy2=abil1 +Joy13=abil2 +Joy14=abil3 +Joy15=abil4 + +[Hexen.WOCKeysection.DoubleBindings] + +[Hexen.woc_weaponsection.Bindings] + +[Hexen.woc_weaponsection.DoubleBindings] + +[Hexen.woc_artifacts.Bindings] + +[Hexen.woc_artifacts.DoubleBindings] + +[Hexen.woc_flasks.Bindings] + +[Hexen.woc_flasks.DoubleBindings] + +[Heretic.Player] +autoaim=35 +classicflight=false +color=3f 60 40 +colorset=0 +fov=90 +gender=male +movebob=0.25 +name=Player +neverswitchonpickup=false +playerclass=Fighter +skin=base +stillbob=0 +team=255 +wbobfire=0 +wbobspeed=1 +wi_noautostartmap=false + +[Heretic.ConsoleVariables] +addrocketexplosion=false +allcheats=false +am_backcolor=6c 54 40 +am_cdwallcolor=73 43 23 +am_colorset=0 +am_customcolors=true +am_drawmapback=1 +am_efwallcolor=66 55 55 +am_emptyspacemargin=0 +am_fdwallcolor=d0 b0 85 +am_followplayer=true +am_gridcolor=8b 5a 2b +am_interlevelcolor=ff 00 00 +am_intralevelcolor=00 00 ff +am_lockedcolor=00 78 00 +am_map_secrets=1 +am_markcolor=2 +am_markfont=AMMNUMx +am_notseencolor=6c 6c 6c +am_ovcdwallcolor=00 88 44 +am_ovefwallcolor=00 88 44 +am_overlay=0 +am_ovfdwallcolor=00 88 44 +am_ovinterlevelcolor=ff ff 00 +am_ovlockedcolor=00 88 44 +am_ovotherwallscolor=00 88 44 +am_ovportalcolor=00 40 22 +am_ovsecretsectorcolor=00 ff ff +am_ovsecretwallcolor=00 88 44 +am_ovspecialwallcolor=ff ff ff +am_ovtelecolor=ff ff 00 +am_ovthingcolor=e8 88 00 +am_ovthingcolor_citem=e8 88 00 +am_ovthingcolor_friend=e8 88 00 +am_ovthingcolor_item=e8 88 00 +am_ovthingcolor_monster=e8 88 00 +am_ovthingcolor_ncmonster=e8 88 00 +am_ovunexploredsecretcolor=00 ff ff +am_ovunseencolor=00 22 6e +am_ovwallcolor=00 ff 00 +am_ovyourcolor=fc e8 d8 +am_portalcolor=40 40 40 +am_portaloverlay=true +am_rotate=0 +am_secretsectorcolor=ff 00 ff +am_secretwallcolor=00 00 00 +am_showitems=false +am_showkeys=true +am_showkeys_always=false +am_showmaplabel=2 +am_showmonsters=true +am_showsecrets=true +am_showthingsprites=0 +am_showtime=true +am_showtotaltime=false +am_showtriggerlines=0 +am_specialwallcolor=ff ff ff +am_textured=false +am_thingcolor=fc fc fc +am_thingcolor_citem=fc fc fc +am_thingcolor_friend=fc fc fc +am_thingcolor_item=fc fc fc +am_thingcolor_monster=fc fc fc +am_thingcolor_ncmonster=fc fc fc +am_thingrenderstyles=true +am_tswallcolor=88 88 88 +am_unexploredsecretcolor=ff 00 ff +am_wallcolor=54 3b 17 +am_xhaircolor=80 80 80 +am_yourcolor=fc e8 d8 +blood_fade_scalar=1 +chat_substitution=false +chatmacro0=No +chatmacro1=I'm ready to kick butt! +chatmacro2=I'm OK. +chatmacro3=I'm not looking too good! +chatmacro4=Help! +chatmacro5=You suck! +chatmacro6=Next time, scumbag... +chatmacro7=Come here! +chatmacro8=I'll take care of it. +chatmacro9=Yes +cl_bbannounce=false +cl_bloodsplats=true +cl_bloodtype=1 +cl_custominvulmapcolor1=00 00 1a +cl_custominvulmapcolor2=a6 a6 7a +cl_customizeinvulmap=false +cl_doautoaim=false +cl_maxdecals=1024 +cl_missiledecals=true +cl_pufftype=2 +cl_rockettrails=3 +cl_showmultikills=true +cl_showsecretmessage=true +cl_showsprees=true +cl_spreaddecals=true +compatmode=0 +con_alpha=0.75 +con_centernotify=true +con_midtime=3 +con_notablist=false +con_notifytime=3 +con_scale=0 +con_scaletext=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairforce=false +crosshairgrow=false +crosshairhealth=1 +crosshairon=true +crosshairscale=1 +dehload=0 +dimamount=-1 +dimcolor=ff d7 00 +displaynametags=0 +dlg_musicvolume=1 +gl_aalines=false +gl_bandedswlight=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_bloom_kernel_size=7 +gl_brightfog=false +gl_enhanced_nightvision=false +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_fuzztype=6 +gl_interpolate_model_frames=true +gl_light_models=true +gl_lightadditivesurfaces=false +gl_lightmode=3 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_sclipfactor=1.7999999523162842 +gl_sclipthreshold=10 +gl_spriteclip=1 +gl_texture_usehires=true +gl_tonemap=0 +gl_weaponlight=8 +hud_althud=false +hud_althud_forceinternal=false +hud_althudscale=0 +hud_ammo_order=0 +hud_ammo_red=25 +hud_ammo_yellow=50 +hud_armor_green=100 +hud_armor_red=25 +hud_armor_yellow=50 +hud_aspectscale=false +hud_berserk_health=true +hud_health_green=100 +hud_health_red=25 +hud_health_yellow=50 +hud_scale=0 +hud_showammo=2 +hud_showangles=false +hud_showitems=false +hud_showlag=0 +hud_showmonsters=true +hud_showscore=false +hud_showsecrets=true +hud_showstats=false +hud_showtime=0 +hud_showweapons=true +hud_timecolor=5 +hudcolor_ltim=8 +hudcolor_statnames=6 +hudcolor_stats=3 +hudcolor_time=6 +hudcolor_titl=10 +hudcolor_ttim=5 +hudcolor_xyco=3 +lookspring=true +m_quickexit=false +menu_screenratios=-1 +msg=0 +msg0color=9 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=9 +msgmidcolor2=10 +nametagcolor=5 +nocheats=false +os_isanyof=true +paletteflash=0 +pickup_fade_scalar=1 +r_deathcamera=true +r_drawfuzz=1 +r_highlight_portals=false +r_maxparticles=4000 +r_portal_recursions=4 +r_rail_smartspiral=false +r_rail_spiralsparsity=1 +r_rail_trailsparsity=1 +r_shadercolormaps=true +r_skymode=2 +r_vanillatrans=0 +sb_cooperative_enable=true +sb_cooperative_headingcolor=6 +sb_cooperative_otherplayercolor=2 +sb_cooperative_yourplayercolor=3 +sb_deathmatch_enable=true +sb_deathmatch_headingcolor=6 +sb_deathmatch_otherplayercolor=2 +sb_deathmatch_yourplayercolor=3 +sb_teamdeathmatch_enable=true +sb_teamdeathmatch_headingcolor=6 +screenblocks=11 +setslotstrict=true +show_obituaries=true +snd_menuvolume=0.6000000238418579 +snd_pitched=true +st_oldouch=false +st_scale=-1 +transsouls=0.75 +uiscale=0 +underwater_fade_scalar=1 +vid_cursor=- +vid_nopalsubstitutions=false +wi_percents=false +wi_showtotaltime=true +wipetype=1 + +[Heretic.LocalServerInfo] +compatflags=0 +compatflags2=0 +forcewater=false +maxviewpitch=90 +sv_alwaystally=0 +sv_corpsequeuesize=64 +sv_disableautohealth=false +sv_dropstyle=0 +sv_portal_recursions=4 +sv_smartaim=0 + +[Heretic.ConfigOnlyVariables] + +[Heretic.UnknownConsoleVariables] + +[Heretic.ConsoleAliases] + +[Heretic.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 0 +Backspace=use ArtiTomeOfPower +T=messagemode +`=toggleconsole +Joy1=invuse +Joy2=+use +Joy3=+jump +Joy4=invnext +Joy5=+speed +Joy6=+attack +Joy7=menu_main +Joy8=togglemap +Joy9=toggle cl_run +Joy10=centerview +Joy11=weapprev +Joy12=weapnext +Joy14=showpop 3 +Joy15=showpop 2 +Joy16=showpop 1 +POV1Up=+forward +POV1Right=+moveright +POV1Down=+back +POV1Left=+moveleft + +[Heretic.DoubleBindings] + +[Heretic.AutomapBindings] +0=am_gobig +-=+am_zoomout +Equals=+am_zoomin +P=am_toggletexture +F=am_togglefollow +G=am_togglegrid +C=am_clearmarks +M=am_setmark +KP-=+am_zoomout +KP+=+am_zoomin +UpArrow=+am_panup +LeftArrow=+am_panleft +RightArrow=+am_panright +DownArrow=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[Doom.SteveFlashlightKeySection.Bindings] +F=toggleflashlight_bind + +[Doom.SteveFlashlightKeySection.DoubleBindings] + +[Doom.options.Bindings] +Y=rdrone +Z=tflare +T=pturret +Mouse3=isight +M=MusicPlay +B=MuteTracker +P=rain +K=death + +[Doom.options.DoubleBindings] + +[Doom.BrutalDoomActions.Bindings] +Q=kickem +R=reload +F=flashlightswitch +G=grenadetoss + +[Doom.BrutalDoomActions.DoubleBindings] + +[Doom.BrutalDoomInteractions.Bindings] +H=brutaltaunt +V=wave1 +N=wave2 +J=advtaunt +K=oneliner +X=dual +O=selectammodrop + +[Doom.BrutalDoomInteractions.DoubleBindings] + +[Doom.BrutalDoomAdvMoves.Bindings] + +[Doom.BrutalDoomAdvMoves.DoubleBindings] + +[Doom.CODBO_Active.Bindings] +B=knife +KP8=grenade +Joy1=invuse + +[Doom.CODBO_Active.DoubleBindings] + +[Doom.CODBO_Advanced.Bindings] +M=Scopeselection +P=WeaponLookselection + +[Doom.CODBO_Advanced.DoubleBindings] + +[Doom.CODBO_EQ.Bindings] +KP1=use Medicalkit_COD +KP2=use TacticalInsertion +KP3=use BeaconHand +KP4=use ClaymoreHand +KP5=use C4Hand + +[Doom.CODBO_EQ.DoubleBindings] + diff --git a/packages/games/emulators/lzdoom/lzdoom.sh b/packages/games/emulators/lzdoom/lzdoom.sh new file mode 100644 index 000000000..e39005a88 --- /dev/null +++ b/packages/games/emulators/lzdoom/lzdoom.sh @@ -0,0 +1,54 @@ +#!/usr/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC/351ELEC) + +. /etc/profile +. /etc/os-release + +EE_DEVICE=${HW_DEVICE} +RUN_DIR="/storage/roms/doom" +CONFIG="/storage/.config/distribution/lzdoom/lzdoom.ini" +SAVE_DIR="/storage/roms/gamedata/lzdoom" + +if [ ! -L "/storage/.config/lzdoom" ] +then + ln -sf "/storage/.config/distribution/lzdoom" "/storage/.config/lzdoom" +fi + +if [ ! -f "/storage/.config/distribution/lzdoom/lzdoom.ini" ] +then + cp -rf /usr/config/distribution/lzdoom/lzdoom.ini /storage/.config/distribution/lzdoom/ +fi + +mkdir -p ${SAVE_DIR} + +params=" -config ${CONFIG} -savedir ${SAVE_DIR}" + +if [[ "$EE_DEVICE" == RG351P ]]; then + params+=" -width 360 -height 240 +vid_fps 1 +cl_capfps 0 +vid_renderer 0 +vid_glswfb 0" +fi +if [[ "$EE_DEVICE" == RG351V ]] || [[ "$EE_DEVICE" == RG351MP ]]; then + params+=" -width 320 -height 240 +vid_fps 1 +cl_capfps 0 +vid_renderer 0 +vid_glswfb 0" +fi + +# EXT can be wad, WAD, iwad, IWAD, pwad, PWAD or doom +EXT=${1#*.} + +# If its not a simple wad (extension .doom) read the file and parse the data +if [ ${EXT} == "doom" ]; then + dos2unix "${1}" + while IFS== read -r key value; do + if [ "$key" == "IWAD" ]; then + params+=" -iwad $value" + fi + if [ "$key" == "MOD" ]; then + params+=" -file $value" + fi + done < "${1}" +else + params+=" -iwad ${1}" +fi + +cd "${RUN_DIR}" +LD_PRELOAD=/usr/lib/libSDL2-2.0.so.0.14.0 /usr/bin/lzdoom ${params} >/tmp/logs/lzdoom.log 2>&1 diff --git a/packages/games/emulators/lzdoom/package.mk b/packages/games/emulators/lzdoom/package.mk new file mode 100644 index 000000000..21493a287 --- /dev/null +++ b/packages/games/emulators/lzdoom/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lzdoom" +PKG_VERSION="9074cae040a581684f0e8cc6409517edb4986eb2" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/351ELEC/lzdoom" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 lzdoom:host" +PKG_SHORTDESC="LZDoom" +PKG_LONGDESC="ZDoom is a family of enhanced ports of the Doom engine for running on modern operating systems. It runs on Windows, Linux, and OS X, and adds new features not found in the games as originally published by id Software." +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="cmake-make" + +if [ "${DEVICE}" = "RG351MP" ] +then + PKG_PATCH_DIRS="RG351MP" +fi + +pre_build_host() { + HOST_CMAKE_OPTS="" +} + +make_host() { + cmake . -DNO_GTK=ON + make +} + +makeinstall_host() { +: #no +} + +pre_configure_target() { +PKG_CMAKE_OPTS_TARGET=" -DNO_GTK=ON \ + -DFORCE_CROSSCOMPILE=ON \ + -DIMPORT_EXECUTABLES=$PKG_BUILD/.$HOST_NAME/ImportExecutables.cmake \ + -DCMAKE_BUILD_TYPE=Release" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/lzdoom.sh $INSTALL/usr/bin/ + cp $PKG_BUILD/.$TARGET_NAME/lzdoom $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/config/distribution/lzdoom + if [ "${DEVICE}" = "RG351MP" ]; then + cp $PKG_DIR/config/RG351MP/* $INSTALL/usr/config/distribution/lzdoom + else + cp $PKG_DIR/config/RG351P/* $INSTALL/usr/config/distribution/lzdoom + fi + cp $PKG_BUILD/.$TARGET_NAME/*.pk3 $INSTALL/usr/config/distribution/lzdoom + cp -r $PKG_BUILD/.$TARGET_NAME/soundfonts $INSTALL/usr/config/distribution/lzdoom + cp -r $PKG_BUILD/.$TARGET_NAME/fm_banks $INSTALL/usr/config/distribution/lzdoom +} diff --git a/packages/games/emulators/lzdoom/patches/RG351MP/MP_key_swap.patch b/packages/games/emulators/lzdoom/patches/RG351MP/MP_key_swap.patch new file mode 100644 index 000000000..397462257 --- /dev/null +++ b/packages/games/emulators/lzdoom/patches/RG351MP/MP_key_swap.patch @@ -0,0 +1,19 @@ +diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp +index 97fe9c334b..d3d61bbb62 100644 +--- a/src/menu/menu.cpp ++++ b/src/menu/menu.cpp +@@ -668,12 +668,12 @@ bool M_Responder (event_t *ev) + { + case KEY_JOY2: + case KEY_PAD_A: +- mkey = MKEY_Back; ++ mkey = MKEY_Enter; + break; + + case KEY_JOY1: + case KEY_PAD_B: +- mkey = MKEY_Enter; ++ mkey = MKEY_Back; + break; + + case KEY_JOY3: diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-audio-sdl/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-audio-sdl/package.mk new file mode 100644 index 000000000..882d76b20 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-audio-sdl/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-audio-sdl" +PKG_VERSION="af6af5b1fd4fdb435c836be15371dd047f395c4d" +PKG_SHA256="265ccdd56736f9cb4144196ad6673d2728a8ebd1e7b9c4280a632c3a343be261" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-audio-sdl" +PKG_URL="https://github.com/mupen64plus/mupen64plus-audio-sdl/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-audio-sdl" +PKG_LONGDESC="Mupen64Plus Standalone Audio SDL" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-audio-sdl.so ${UPLUGINDIR} + #$STRIP ${UPLUGINDIR}/mupen64plus-audio-sdl.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-audio-sdl.so +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351MP.cfg b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351MP.cfg new file mode 100644 index 000000000..a6b780f10 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351MP.cfg @@ -0,0 +1,630 @@ +# Mupen64Plus Configuration File +# This file is automatically read and written by the Mupen64Plus Core library + +[64DD] + +# Filename of the 64DD IPL ROM +IPL-ROM = "" +# Filename of the disk to load into Disk Drive +Disk = "" + + +[Audio-SDL] + +# Mupen64Plus SDL Audio Plugin config parameter version number +Version = 1.000000 +# Frequency which is used if rom doesn't want to change it +DEFAULT_FREQUENCY = 33600 +# Swaps left and right channels +SWAP_CHANNELS = False +# Size of primary buffer in output samples. This is where audio is loaded after it's extracted from n64's memory. +PRIMARY_BUFFER_SIZE = 16384 +# Fullness level target for Primary audio buffer, in equivalent output samples. This value must be larger than the SECONDARY_BUFFER_SIZE. Decreasing this value will reduce audio latency but requires a faster PC to avoid choppiness. Increasing this will increase audio latency but reduce the chance of drop-outs. +PRIMARY_BUFFER_TARGET = 2048 +# Size of secondary buffer in output samples. This is SDL's hardware buffer. The SDL documentation states that this should be a power of two between 512 and 8192. +SECONDARY_BUFFER_SIZE = 1024 +# Audio resampling algorithm. src-sinc-best-quality, src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, src-linear, speex-fixed-{10-0}, trivial +RESAMPLE = "trivial" +# Volume control type: 1 = SDL (only affects Mupen64Plus output) 2 = OSS mixer (adjusts master PC volume) +VOLUME_CONTROL_TYPE = 1 +# Percentage change each time the volume is increased or decreased +VOLUME_ADJUST = 5 +# Default volume when a game is started. Only used if VOLUME_CONTROL_TYPE is 1 +VOLUME_DEFAULT = 100 +# Synchronize Video/Audio +AUDIO_SYNC = False + + +[Core] + +# Mupen64Plus Core config parameter set version number. Please don't change this version number. +Version = 1.010000 +# Draw on-screen display if True, otherwise don't draw OSD +OnScreenDisplay = True +# Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more +R4300Emulator = 2 +# Disable compiled jump commands in dynamic recompiler (should be set to False) +NoCompiledJump = False +# Disable 4MB expansion RAM pack. May be necessary for some games +DisableExtraMem = False +# Increment the save state slot after each save operation +AutoStateSlotIncrement = False +# Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support +EnableDebugger = False +# Save state slot (0-9) to use when saving/loading the emulator state +CurrentStateSlot = 0 +# Path to directory where screenshots are saved. If this is blank, the default value of ${UserDataPath}/screenshot will be used +ScreenshotPath = "/storage/roms/n64" +# Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of ${UserDataPath}/save will be used +SaveStatePath = "/storage/roms/n64" +# Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of ${UserDataPath}/save will be used +SaveSRAMPath = "/storage/roms/n64" +# Path to a directory to search when looking for shared data files +SharedDataPath = "/storage/roms/gamedata/mupen64plussa" +# Force number of cycles per emulated instruction +CountPerOp = 0 +# Randomize PI/SI Interrupt Timing +RandomizeInterrupt = True +# Duration of SI DMA (-1: use per game settings) +SiDmaDuration = -1 +# Gameboy Camera Video Capture backend +GbCameraVideoCaptureBackend1 = "" +# Disk Save Format (0: Full Disk Copy (*.ndr/*.d6r), 1: RAM Area Only (*.ram)) +SaveDiskFormat = 1 + + +[CoreEvents] + +# Mupen64Plus CoreEvents config parameter set version number. Please don't change this version number. +Version = 1.000000 +# SDL keysym for stopping the emulator +Kbd Mapping Stop = 27 +# SDL keysym for switching between fullscreen/windowed modes +Kbd Mapping Fullscreen = 0 +# SDL keysym for saving the emulator state +Kbd Mapping Save State = 286 +# SDL keysym for loading the emulator state +Kbd Mapping Load State = 288 +# SDL keysym for advancing the save state slot +Kbd Mapping Increment Slot = 0 +# SDL keysym for resetting the emulator +Kbd Mapping Reset = 290 +# SDL keysym for slowing down the emulator +Kbd Mapping Speed Down = 291 +# SDL keysym for speeding up the emulator +Kbd Mapping Speed Up = 292 +# SDL keysym for taking a screenshot +Kbd Mapping Screenshot = 293 +# SDL keysym for pausing the emulator +Kbd Mapping Pause = 112 +# SDL keysym for muting/unmuting the sound +Kbd Mapping Mute = 109 +# SDL keysym for increasing the volume +Kbd Mapping Increase Volume = 93 +# SDL keysym for decreasing the volume +Kbd Mapping Decrease Volume = 91 +# SDL keysym for temporarily going really fast +Kbd Mapping Fast Forward = 102 +# SDL keysym for advancing by one frame when paused +Kbd Mapping Frame Advance = 47 +# SDL keysym for pressing the game shark button +Kbd Mapping Gameshark = 103 +# Joystick event string for stopping the emulator +Joy Mapping Stop = "J0B12/B13" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B12/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B12/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "" +# Joystick event string for slowing down the emulator +Joy Mapping Speed Down = "" +# Joystick event string for speeding up the emulator +Joy Mapping Speed Up = "" +# Joystick event string for taking a screenshot +Joy Mapping Screenshot = "" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "J0B12/B1" +# Joystick event string for muting/unmuting the sound +Joy Mapping Mute = "" +# Joystick event string for increasing the volume +Joy Mapping Increase Volume = "" +# Joystick event string for decreasing the volume +Joy Mapping Decrease Volume = "" +# Joystick event string for fast-forward +Joy Mapping Fast Forward = "" +# Joystick event string for advancing by one frame when paused +Joy Mapping Frame Advance = "" +# Joystick event string for pressing the game shark button +Joy Mapping Gameshark = "" +# SDL keysym for save slot 0 +Kbd Mapping Slot 0 = 48 +# SDL keysym for save slot 1 +Kbd Mapping Slot 1 = 49 +# SDL keysym for save slot 2 +Kbd Mapping Slot 2 = 50 +# SDL keysym for save slot 3 +Kbd Mapping Slot 3 = 51 +# SDL keysym for save slot 4 +Kbd Mapping Slot 4 = 52 +# SDL keysym for save slot 5 +Kbd Mapping Slot 5 = 53 +# SDL keysym for save slot 6 +Kbd Mapping Slot 6 = 54 +# SDL keysym for save slot 7 +Kbd Mapping Slot 7 = 55 +# SDL keysym for save slot 8 +Kbd Mapping Slot 8 = 56 +# SDL keysym for save slot 9 +Kbd Mapping Slot 9 = 57 + + +[Input-SDL-Control1] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = 0 +# SDL joystick name (or Keyboard) +name = "GO-Super Gamepad" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = True +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "0,0" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "button(11)" +DPad L = "button(10)" +DPad D = "button(9)" +DPad U = "button(8)" +Start = "button(13)" +Z Trig = "button(15)" +B Button = "button(3)" +A Button = "button(0)" +C Button R = "button(7)" +C Button L = "button(2)" +C Button D = "button(1)" +C Button U = "button(6)" +R Trig = "button(5)" +L Trig = "button(4)" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "axis(0-,0+)" +Y Axis = "axis(1-,1+)" + + +[Input-SDL-Control2] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control3] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control4] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Rsp-HLE] + +# Mupen64Plus RSP HLE Plugin config parameter version number +Version = 1.000000 +# Path to a RSP plugin which will be used when encountering an unknown ucode.You can disable this by letting an empty string. +RspFallback = "" +# Send display lists to the graphics plugin +DisplayListToGraphicsPlugin = True +# Send audio lists to the audio plugin +AudioListToAudioPlugin = False + + +[Transferpak] + +# Filename of the GB ROM to load into transferpak 1 +GB-rom-1 = "" +# Filename of the GB RAM to load into transferpak 1 +GB-ram-1 = "" +# Filename of the GB ROM to load into transferpak 2 +GB-rom-2 = "" +# Filename of the GB RAM to load into transferpak 2 +GB-ram-2 = "" +# Filename of the GB ROM to load into transferpak 3 +GB-rom-3 = "" +# Filename of the GB RAM to load into transferpak 3 +GB-ram-3 = "" +# Filename of the GB ROM to load into transferpak 4 +GB-rom-4 = "" +# Filename of the GB RAM to load into transferpak 4 +GB-ram-4 = "" + + +[UI-Console] + +# Mupen64Plus UI-Console config parameter set version number. Please don't change this version number. +Version = 1.000000 +# Directory in which to search for plugins +PluginDir = "/usr/local/lib/mupen64plus" +# Filename of video plugin +VideoPlugin = "mupen64plus-video-rice" +# Filename of audio plugin +AudioPlugin = "mupen64plus-audio-sdl.so" +# Filename of input plugin +InputPlugin = "mupen64plus-input-sdl.so" +# Filename of RSP plugin +RspPlugin = "mupen64plus-rsp-hle.so" + + +[Video-General] + +# Width of output window or fullscreen width +ScreenWidth = 640 +# Height of output window or fullscreen height +ScreenHeight = 480 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = False +# If true, activate the SDL_GL_SWAP_CONTROL attribute +VerticalSync = True +# Rotate screen contents: 0=0 degree, 1=90 degree, 2 = 180 degree, 3=270 degree +Rotate = 0 + + +[Video-Glide64mk2] + +# Enable full-scene anti-aliasing by setting this to a value greater than 1 +wrpAntiAliasing = 0 +# Card ID +card_id = 0 +# If true, use polygon offset values specified below +force_polygon_offset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +polygon_offset_factor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +polygon_offset_units = 0.000000 +# Vertical sync +vsync = True +# TODO:ssformat +ssformat = False +# Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent +show_fps = 0 +# Clock enabled +clock = False +# Clock is 24-hour +clock_24_hr = True +# Wrapper resolution +wrpResolution = 0 +# Wrapper VRAM +wrpVRAM = 0 +# Wrapper FBO +wrpFBO = True +# Wrapper Anisotropic Filtering +wrpAnisotropic = True +# Texture Enhancement: Smooth/Sharpen Filters +ghq_fltr = 0 +# Texture Compression: 0 for S3TC, 1 for FXT1 +ghq_cmpr = 0 +# Texture Enhancement: More filters +ghq_enht = 0 +# Hi-res texture pack format (0 for none, 1 for Rice) +ghq_hirs = 1 +# Compress texture cache with S3TC or FXT1 +ghq_enht_cmpr = False +# Tile textures (saves memory but could cause issues) +ghq_enht_tile = 0 +# Force 16bpp textures (saves ram but lower quality) +ghq_enht_f16bpp = False +# Compress texture cache +ghq_enht_gz = True +# Don't enhance textures for backgrounds +ghq_enht_nobg = False +# Enable S3TC and FXT1 compression +ghq_hirs_cmpr = False +# Tile hi-res textures (saves memory but could cause issues) +ghq_hirs_tile = False +# Force 16bpp hi-res textures (saves ram but lower quality) +ghq_hirs_f16bpp = False +# Compress hi-res texture cache +ghq_hirs_gz = True +# Alternative CRC calculation -- emulates Rice bug +ghq_hirs_altcrc = True +# Save tex cache to disk +ghq_cache_save = True +# Texture Cache Size (MB) +ghq_cache_size = 128 +# Use full alpha channel -- could cause issues for some tex packs +ghq_hirs_let_texartists_fly = False +# Dump textures +ghq_hirs_dump = False +# Alternate texture size method: -1=Game default, 0=disable. 1=enable +alt_tex_size = -1 +# Use first SETTILESIZE only: -1=Game default, 0=disable. 1=enable +use_sts1_only = -1 +# Use spheric mapping only: -1=Game default, 0=disable. 1=enable +force_calc_sphere = -1 +# Force positive viewport: -1=Game default, 0=disable. 1=enable +correct_viewport = -1 +# Force texrect size to integral value: -1=Game default, 0=disable. 1=enable +increase_texrect_edge = -1 +# Reduce fillrect size by 1: -1=Game default, 0=disable. 1=enable +decrease_fillrect_edge = -1 +# Enable perspective texture correction emulation: -1=Game default, 0=disable. 1=enable +texture_correction = -1 +# Set special scale for PAL games: -1=Game default, 0=disable. 1=enable +pal230 = -1 +# 3DFX Dithered alpha emulation mode: -1=Game default, >=0=dithered alpha emulation mode +stipple_mode = -1 +# 3DFX Dithered alpha pattern: -1=Game default, >=0=pattern used for dithered alpha emulation +stipple_pattern = -1 +# Check microcode each frame: -1=Game default, 0=disable. 1=enable +force_microcheck = -1 +# Force 0xb5 command to be quad, not line 3D: -1=Game default, 0=disable. 1=enable +force_quad3d = -1 +# Enable near z clipping: -1=Game default, 0=disable. 1=enable +clip_zmin = -1 +# Enable far plane clipping: -1=Game default, 0=disable. 1=enable +clip_zmax = -1 +# Use fast CRC algorithm: -1=Game default, 0=disable. 1=enable +fast_crc = -1 +# Adjust screen aspect for wide screen mode: -1=Game default, 0=disable. 1=enable +adjust_aspect = -1 +# Force strict check in Depth buffer test: -1=Game default, 0=disable. 1=enable +zmode_compare_less = -1 +# Apply alpha dither regardless of alpha_dither_mode: -1=Game default, 0=disable. 1=enable +old_style_adither = -1 +# Scale vertex z value before writing to depth buffer: -1=Game default, 0=disable. 1=enable +n64_z_scale = -1 +# Fast texrect rendering with hwfbe: -1=Game default, 0=disable. 1=enable +optimize_texrect = -1 +# Do not copy auxiliary frame buffers: -1=Game default, 0=disable. 1=enable +ignore_aux_copy = -1 +# Clear auxiliary texture frame buffers: -1=Game default, 0=disable. 1=enable +hires_buf_clear = -1 +# Read alpha from framebuffer: -1=Game default, 0=disable. 1=enable +fb_read_alpha = -1 +# Handle unchanged fb: -1=Game default, 0=disable. 1=enable +useless_is_useless = -1 +# Set frambuffer CRC mode: -1=Game default, 0=disable CRC, 1=fast CRC, 2=safe CRC +fb_crc_mode = -1 +# Filtering mode: -1=Game default, 0=automatic, 1=force bilinear, 2=force point sampled +filtering = -1 +# Fog: -1=Game default, 0=disable. 1=enable +fog = -1 +# Buffer clear on every frame: -1=Game default, 0=disable. 1=enable +buff_clear = -1 +# Buffer swapping method: -1=Game default, 0=swap buffers when vertical interrupt has occurred, 1=swap buffers when set of conditions is satisfied. Prevents flicker on some games, 2=mix of first two methods +swapmode = -1 +# Aspect ratio: -1=Game default, 0=Force 4:3, 1=Force 16:9, 2=Stretch, 3=Original +aspect = -1 +# LOD calculation: -1=Game default, 0=disable. 1=fast, 2=precise +lodmode = -1 +# Smart framebuffer: -1=Game default, 0=disable. 1=enable +fb_smart = -1 +# Hardware frame buffer emulation: -1=Game default, 0=disable. 1=enable +fb_hires = -1 +# Read framebuffer every frame (may be slow use only for effects that need it e.g. Banjo Kazooie, DK64 transitions): -1=Game default, 0=disable. 1=enable +fb_read_always = -1 +# Render N64 frame buffer as texture: -1=Game default, 0=disable, 1=mode1, 2=mode2 +read_back_to_screen = -1 +# Show images written directly by CPU: -1=Game default, 0=disable. 1=enable +detect_cpu_write = -1 +# Get frame buffer info: -1=Game default, 0=disable. 1=enable +fb_get_info = -1 +# Enable software depth render: -1=Game default, 0=disable. 1=enable +fb_render = -1 +# If true, skip up to maxframeskip frames to maintain clock schedule; if false, skip exactly maxframeskip frames +autoframeskip = False +# If autoframeskip is true, skip up to this many frames to maintain clock schedule; if autoframeskip is false, skip exactly this many frames +maxframeskip = 0 + + +[Video-Rice] + +# Mupen64Plus Rice Video Plugin config parameter version number +Version = 1 +# Frame Buffer Emulation (0=ROM default, 1=disable) +FrameBufferSetting = 0 +# Frequency to write back the frame buffer (0=every frame, 1=every other frame, etc) +FrameBufferWriteBackControl = 0 +# Render-to-texture emulation (0=none, 1=ignore, 2=normal, 3=write back, 4=write back and reload) +RenderToTexture = 0 +# Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn) +ScreenUpdateSetting = 4 +# Force to use normal alpha blender +NormalAlphaBlender = False +# Use a faster algorithm to speed up texture loading and CRC computation +FastTextureLoading = False +# Use different texture coordinate clamping code +AccurateTextureMapping = True +# Force emulated frame buffers to be in N64 native resolution +InN64Resolution = False +# Try to reduce Video RAM usage (should never be used) +SaveVRAM = False +# Enable this option to have better render-to-texture quality +DoubleSizeForSmallTxtrBuf = False +# Force to use normal color combiner +DefaultCombinerDisable = False +# Enable game-specific settings from INI file +EnableHacks = True +# If enabled, graphics will be drawn in WinFrame mode instead of solid and texture mode +WinFrameMode = False +# N64 Texture Memory Full Emulation (may fix some games, may break others) +FullTMEMEmulation = False +# Enable vertex clipper for fog operations +OpenGLVertexClipper = False +# Enable/Disable SSE optimizations for capable CPUs +EnableSSE = True +# If this option is enabled, the plugin will skip every other frame +SkipFrame = False +# If enabled, texture enhancement will be done only for TxtRect ucode +TexRectOnly = False +# If enabled, texture enhancement will be done only for textures width+height<=128 +SmallTextureOnly = False +# Select hi-resolution textures based only on the CRC and ignore format+size information (Glide64 compatibility) +LoadHiResCRCOnly = True +# Enable hi-resolution texture file loading +LoadHiResTextures = False +# Enable texture dumping +DumpTexturesToFiles = False +# Display On-screen FPS +ShowFPS = False +# Use Mipmapping? 0=no, 1=nearest, 2=bilinear, 3=trilinear +Mipmapping = 2 +# Enable, Disable fog generation (0=Disable, 1=Enable) +FogMethod = 1 +# Force to use texture filtering or not (0=auto: n64 choose, 1=force no filtering, 2=force filtering) +ForceTextureFilter = 0 +# Primary texture enhancement filter (0=None, 1=2X, 2=2XSAI, 3=HQ2X, 4=LQ2X, 5=HQ4X, 6=Sharpen, 7=Sharpen More, 8=External, 9=Mirrored) +TextureEnhancement = 0 +# Secondary texture enhancement filter (0 = none, 1-4 = filtered) +TextureEnhancementControl = 0 +# Color bit depth to use for textures (0=default, 1=32 bits, 2=16 bits) +TextureQuality = 0 +# Z-buffer depth (only 16 or 32) +OpenGLDepthBufferSetting = 16 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Color bit depth for rendering window (0=32 bits, 1=16 bits) +ColorQuality = 1 +# OpenGL level to support (0=auto, 1=OGL_FRAGMENT_PROGRAM) +OpenGLRenderSetting = 0 +# Enable/Disable Anisotropic Filtering for Mipmapping (0=no filtering, 2-16=quality). This is uneffective if Mipmapping is 0. If the given value is to high to be supported by your graphic card, the value will be the highest value your graphic card can support. Better result with Trilinear filtering +AnisotropicFiltering = 0 +# If true, use polygon offset values specified below +ForcePolygonOffset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +PolygonOffsetFactor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +PolygonOffsetUnits = 0.000000 + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351P.cfg b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351P.cfg new file mode 100644 index 000000000..612a9cfb3 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351P.cfg @@ -0,0 +1,630 @@ +# Mupen64Plus Configuration File +# This file is automatically read and written by the Mupen64Plus Core library + +[64DD] + +# Filename of the 64DD IPL ROM +IPL-ROM = "" +# Filename of the disk to load into Disk Drive +Disk = "" + + +[Audio-SDL] + +# Mupen64Plus SDL Audio Plugin config parameter version number +Version = 1.000000 +# Frequency which is used if rom doesn't want to change it +DEFAULT_FREQUENCY = 33600 +# Swaps left and right channels +SWAP_CHANNELS = False +# Size of primary buffer in output samples. This is where audio is loaded after it's extracted from n64's memory. +PRIMARY_BUFFER_SIZE = 16384 +# Fullness level target for Primary audio buffer, in equivalent output samples. This value must be larger than the SECONDARY_BUFFER_SIZE. Decreasing this value will reduce audio latency but requires a faster PC to avoid choppiness. Increasing this will increase audio latency but reduce the chance of drop-outs. +PRIMARY_BUFFER_TARGET = 2048 +# Size of secondary buffer in output samples. This is SDL's hardware buffer. The SDL documentation states that this should be a power of two between 512 and 8192. +SECONDARY_BUFFER_SIZE = 1024 +# Audio resampling algorithm. src-sinc-best-quality, src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, src-linear, speex-fixed-{10-0}, trivial +RESAMPLE = "trivial" +# Volume control type: 1 = SDL (only affects Mupen64Plus output) 2 = OSS mixer (adjusts master PC volume) +VOLUME_CONTROL_TYPE = 1 +# Percentage change each time the volume is increased or decreased +VOLUME_ADJUST = 5 +# Default volume when a game is started. Only used if VOLUME_CONTROL_TYPE is 1 +VOLUME_DEFAULT = 100 +# Synchronize Video/Audio +AUDIO_SYNC = False + + +[Core] + +# Mupen64Plus Core config parameter set version number. Please don't change this version number. +Version = 1.010000 +# Draw on-screen display if True, otherwise don't draw OSD +OnScreenDisplay = True +# Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more +R4300Emulator = 2 +# Disable compiled jump commands in dynamic recompiler (should be set to False) +NoCompiledJump = False +# Disable 4MB expansion RAM pack. May be necessary for some games +DisableExtraMem = False +# Increment the save state slot after each save operation +AutoStateSlotIncrement = False +# Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support +EnableDebugger = False +# Save state slot (0-9) to use when saving/loading the emulator state +CurrentStateSlot = 0 +# Path to directory where screenshots are saved. If this is blank, the default value of ${UserDataPath}/screenshot will be used +ScreenshotPath = "/storage/roms/n64" +# Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of ${UserDataPath}/save will be used +SaveStatePath = "/storage/roms/n64" +# Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of ${UserDataPath}/save will be used +SaveSRAMPath = "/storage/roms/n64" +# Path to a directory to search when looking for shared data files +SharedDataPath = "/storage/roms/gamedata/mupen64plussa" +# Force number of cycles per emulated instruction +CountPerOp = 0 +# Randomize PI/SI Interrupt Timing +RandomizeInterrupt = True +# Duration of SI DMA (-1: use per game settings) +SiDmaDuration = -1 +# Gameboy Camera Video Capture backend +GbCameraVideoCaptureBackend1 = "" +# Disk Save Format (0: Full Disk Copy (*.ndr/*.d6r), 1: RAM Area Only (*.ram)) +SaveDiskFormat = 1 + + +[CoreEvents] + +# Mupen64Plus CoreEvents config parameter set version number. Please don't change this version number. +Version = 1.000000 +# SDL keysym for stopping the emulator +Kbd Mapping Stop = 27 +# SDL keysym for switching between fullscreen/windowed modes +Kbd Mapping Fullscreen = 0 +# SDL keysym for saving the emulator state +Kbd Mapping Save State = 286 +# SDL keysym for loading the emulator state +Kbd Mapping Load State = 288 +# SDL keysym for advancing the save state slot +Kbd Mapping Increment Slot = 0 +# SDL keysym for resetting the emulator +Kbd Mapping Reset = 290 +# SDL keysym for slowing down the emulator +Kbd Mapping Speed Down = 291 +# SDL keysym for speeding up the emulator +Kbd Mapping Speed Up = 292 +# SDL keysym for taking a screenshot +Kbd Mapping Screenshot = 293 +# SDL keysym for pausing the emulator +Kbd Mapping Pause = 112 +# SDL keysym for muting/unmuting the sound +Kbd Mapping Mute = 109 +# SDL keysym for increasing the volume +Kbd Mapping Increase Volume = 93 +# SDL keysym for decreasing the volume +Kbd Mapping Decrease Volume = 91 +# SDL keysym for temporarily going really fast +Kbd Mapping Fast Forward = 102 +# SDL keysym for advancing by one frame when paused +Kbd Mapping Frame Advance = 47 +# SDL keysym for pressing the game shark button +Kbd Mapping Gameshark = 103 +# Joystick event string for stopping the emulator +Joy Mapping Stop = "J0B7/B6" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B7/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B7/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "" +# Joystick event string for slowing down the emulator +Joy Mapping Speed Down = "" +# Joystick event string for speeding up the emulator +Joy Mapping Speed Up = "" +# Joystick event string for taking a screenshot +Joy Mapping Screenshot = "" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "J0B7/B0" +# Joystick event string for muting/unmuting the sound +Joy Mapping Mute = "" +# Joystick event string for increasing the volume +Joy Mapping Increase Volume = "" +# Joystick event string for decreasing the volume +Joy Mapping Decrease Volume = "" +# Joystick event string for fast-forward +Joy Mapping Fast Forward = "" +# Joystick event string for advancing by one frame when paused +Joy Mapping Frame Advance = "" +# Joystick event string for pressing the game shark button +Joy Mapping Gameshark = "" +# SDL keysym for save slot 0 +Kbd Mapping Slot 0 = 48 +# SDL keysym for save slot 1 +Kbd Mapping Slot 1 = 49 +# SDL keysym for save slot 2 +Kbd Mapping Slot 2 = 50 +# SDL keysym for save slot 3 +Kbd Mapping Slot 3 = 51 +# SDL keysym for save slot 4 +Kbd Mapping Slot 4 = 52 +# SDL keysym for save slot 5 +Kbd Mapping Slot 5 = 53 +# SDL keysym for save slot 6 +Kbd Mapping Slot 6 = 54 +# SDL keysym for save slot 7 +Kbd Mapping Slot 7 = 55 +# SDL keysym for save slot 8 +Kbd Mapping Slot 8 = 56 +# SDL keysym for save slot 9 +Kbd Mapping Slot 9 = 57 + + +[Input-SDL-Control1] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = 0 +# SDL joystick name (or Keyboard) +name = "OpenSimHardware OSH PB Controller" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = True +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "0,0" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "hat(0 Right)" +DPad L = "hat(0 Left)" +DPad D = "hat(0 Down)" +DPad U = "hat(0 Up)" +Start = "button(6)" +Z Trig = "button(9)" +B Button = "button(3)" +A Button = "button(1)" +C Button R = "button(11)" +C Button L = "button(2)" +C Button D = "button(0)" +C Button U = "button(10)" +R Trig = "button(5)" +L Trig = "button(4)" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "axis(0+,0-)" +Y Axis = "axis(1+,1-)" + + +[Input-SDL-Control2] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control3] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control4] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Rsp-HLE] + +# Mupen64Plus RSP HLE Plugin config parameter version number +Version = 1.000000 +# Path to a RSP plugin which will be used when encountering an unknown ucode.You can disable this by letting an empty string. +RspFallback = "" +# Send display lists to the graphics plugin +DisplayListToGraphicsPlugin = True +# Send audio lists to the audio plugin +AudioListToAudioPlugin = False + + +[Transferpak] + +# Filename of the GB ROM to load into transferpak 1 +GB-rom-1 = "" +# Filename of the GB RAM to load into transferpak 1 +GB-ram-1 = "" +# Filename of the GB ROM to load into transferpak 2 +GB-rom-2 = "" +# Filename of the GB RAM to load into transferpak 2 +GB-ram-2 = "" +# Filename of the GB ROM to load into transferpak 3 +GB-rom-3 = "" +# Filename of the GB RAM to load into transferpak 3 +GB-ram-3 = "" +# Filename of the GB ROM to load into transferpak 4 +GB-rom-4 = "" +# Filename of the GB RAM to load into transferpak 4 +GB-ram-4 = "" + + +[UI-Console] + +# Mupen64Plus UI-Console config parameter set version number. Please don't change this version number. +Version = 1.000000 +# Directory in which to search for plugins +PluginDir = "/usr/local/lib/mupen64plus" +# Filename of video plugin +VideoPlugin = "mupen64plus-video-rice" +# Filename of audio plugin +AudioPlugin = "mupen64plus-audio-sdl.so" +# Filename of input plugin +InputPlugin = "mupen64plus-input-sdl.so" +# Filename of RSP plugin +RspPlugin = "mupen64plus-rsp-hle.so" + + +[Video-General] + +# Width of output window or fullscreen width +ScreenWidth = 480 +# Height of output window or fullscreen height +ScreenHeight = 320 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = False +# If true, activate the SDL_GL_SWAP_CONTROL attribute +VerticalSync = True +# Rotate screen contents: 0=0 degree, 1=90 degree, 2 = 180 degree, 3=270 degree +Rotate = 0 + + +[Video-Glide64mk2] + +# Enable full-scene anti-aliasing by setting this to a value greater than 1 +wrpAntiAliasing = 0 +# Card ID +card_id = 0 +# If true, use polygon offset values specified below +force_polygon_offset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +polygon_offset_factor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +polygon_offset_units = 0.000000 +# Vertical sync +vsync = True +# TODO:ssformat +ssformat = False +# Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent +show_fps = 0 +# Clock enabled +clock = False +# Clock is 24-hour +clock_24_hr = True +# Wrapper resolution +wrpResolution = 0 +# Wrapper VRAM +wrpVRAM = 0 +# Wrapper FBO +wrpFBO = True +# Wrapper Anisotropic Filtering +wrpAnisotropic = True +# Texture Enhancement: Smooth/Sharpen Filters +ghq_fltr = 0 +# Texture Compression: 0 for S3TC, 1 for FXT1 +ghq_cmpr = 0 +# Texture Enhancement: More filters +ghq_enht = 0 +# Hi-res texture pack format (0 for none, 1 for Rice) +ghq_hirs = 1 +# Compress texture cache with S3TC or FXT1 +ghq_enht_cmpr = False +# Tile textures (saves memory but could cause issues) +ghq_enht_tile = 0 +# Force 16bpp textures (saves ram but lower quality) +ghq_enht_f16bpp = False +# Compress texture cache +ghq_enht_gz = True +# Don't enhance textures for backgrounds +ghq_enht_nobg = False +# Enable S3TC and FXT1 compression +ghq_hirs_cmpr = False +# Tile hi-res textures (saves memory but could cause issues) +ghq_hirs_tile = False +# Force 16bpp hi-res textures (saves ram but lower quality) +ghq_hirs_f16bpp = False +# Compress hi-res texture cache +ghq_hirs_gz = True +# Alternative CRC calculation -- emulates Rice bug +ghq_hirs_altcrc = True +# Save tex cache to disk +ghq_cache_save = True +# Texture Cache Size (MB) +ghq_cache_size = 128 +# Use full alpha channel -- could cause issues for some tex packs +ghq_hirs_let_texartists_fly = False +# Dump textures +ghq_hirs_dump = False +# Alternate texture size method: -1=Game default, 0=disable. 1=enable +alt_tex_size = -1 +# Use first SETTILESIZE only: -1=Game default, 0=disable. 1=enable +use_sts1_only = -1 +# Use spheric mapping only: -1=Game default, 0=disable. 1=enable +force_calc_sphere = -1 +# Force positive viewport: -1=Game default, 0=disable. 1=enable +correct_viewport = -1 +# Force texrect size to integral value: -1=Game default, 0=disable. 1=enable +increase_texrect_edge = -1 +# Reduce fillrect size by 1: -1=Game default, 0=disable. 1=enable +decrease_fillrect_edge = -1 +# Enable perspective texture correction emulation: -1=Game default, 0=disable. 1=enable +texture_correction = -1 +# Set special scale for PAL games: -1=Game default, 0=disable. 1=enable +pal230 = -1 +# 3DFX Dithered alpha emulation mode: -1=Game default, >=0=dithered alpha emulation mode +stipple_mode = -1 +# 3DFX Dithered alpha pattern: -1=Game default, >=0=pattern used for dithered alpha emulation +stipple_pattern = -1 +# Check microcode each frame: -1=Game default, 0=disable. 1=enable +force_microcheck = -1 +# Force 0xb5 command to be quad, not line 3D: -1=Game default, 0=disable. 1=enable +force_quad3d = -1 +# Enable near z clipping: -1=Game default, 0=disable. 1=enable +clip_zmin = -1 +# Enable far plane clipping: -1=Game default, 0=disable. 1=enable +clip_zmax = -1 +# Use fast CRC algorithm: -1=Game default, 0=disable. 1=enable +fast_crc = -1 +# Adjust screen aspect for wide screen mode: -1=Game default, 0=disable. 1=enable +adjust_aspect = -1 +# Force strict check in Depth buffer test: -1=Game default, 0=disable. 1=enable +zmode_compare_less = -1 +# Apply alpha dither regardless of alpha_dither_mode: -1=Game default, 0=disable. 1=enable +old_style_adither = -1 +# Scale vertex z value before writing to depth buffer: -1=Game default, 0=disable. 1=enable +n64_z_scale = -1 +# Fast texrect rendering with hwfbe: -1=Game default, 0=disable. 1=enable +optimize_texrect = -1 +# Do not copy auxiliary frame buffers: -1=Game default, 0=disable. 1=enable +ignore_aux_copy = -1 +# Clear auxiliary texture frame buffers: -1=Game default, 0=disable. 1=enable +hires_buf_clear = -1 +# Read alpha from framebuffer: -1=Game default, 0=disable. 1=enable +fb_read_alpha = -1 +# Handle unchanged fb: -1=Game default, 0=disable. 1=enable +useless_is_useless = -1 +# Set frambuffer CRC mode: -1=Game default, 0=disable CRC, 1=fast CRC, 2=safe CRC +fb_crc_mode = -1 +# Filtering mode: -1=Game default, 0=automatic, 1=force bilinear, 2=force point sampled +filtering = -1 +# Fog: -1=Game default, 0=disable. 1=enable +fog = -1 +# Buffer clear on every frame: -1=Game default, 0=disable. 1=enable +buff_clear = -1 +# Buffer swapping method: -1=Game default, 0=swap buffers when vertical interrupt has occurred, 1=swap buffers when set of conditions is satisfied. Prevents flicker on some games, 2=mix of first two methods +swapmode = -1 +# Aspect ratio: -1=Game default, 0=Force 4:3, 1=Force 16:9, 2=Stretch, 3=Original +aspect = -1 +# LOD calculation: -1=Game default, 0=disable. 1=fast, 2=precise +lodmode = -1 +# Smart framebuffer: -1=Game default, 0=disable. 1=enable +fb_smart = -1 +# Hardware frame buffer emulation: -1=Game default, 0=disable. 1=enable +fb_hires = -1 +# Read framebuffer every frame (may be slow use only for effects that need it e.g. Banjo Kazooie, DK64 transitions): -1=Game default, 0=disable. 1=enable +fb_read_always = -1 +# Render N64 frame buffer as texture: -1=Game default, 0=disable, 1=mode1, 2=mode2 +read_back_to_screen = -1 +# Show images written directly by CPU: -1=Game default, 0=disable. 1=enable +detect_cpu_write = -1 +# Get frame buffer info: -1=Game default, 0=disable. 1=enable +fb_get_info = -1 +# Enable software depth render: -1=Game default, 0=disable. 1=enable +fb_render = -1 +# If true, skip up to maxframeskip frames to maintain clock schedule; if false, skip exactly maxframeskip frames +autoframeskip = False +# If autoframeskip is true, skip up to this many frames to maintain clock schedule; if autoframeskip is false, skip exactly this many frames +maxframeskip = 0 + + +[Video-Rice] + +# Mupen64Plus Rice Video Plugin config parameter version number +Version = 1 +# Frame Buffer Emulation (0=ROM default, 1=disable) +FrameBufferSetting = 0 +# Frequency to write back the frame buffer (0=every frame, 1=every other frame, etc) +FrameBufferWriteBackControl = 0 +# Render-to-texture emulation (0=none, 1=ignore, 2=normal, 3=write back, 4=write back and reload) +RenderToTexture = 0 +# Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn) +ScreenUpdateSetting = 4 +# Force to use normal alpha blender +NormalAlphaBlender = False +# Use a faster algorithm to speed up texture loading and CRC computation +FastTextureLoading = False +# Use different texture coordinate clamping code +AccurateTextureMapping = True +# Force emulated frame buffers to be in N64 native resolution +InN64Resolution = False +# Try to reduce Video RAM usage (should never be used) +SaveVRAM = False +# Enable this option to have better render-to-texture quality +DoubleSizeForSmallTxtrBuf = False +# Force to use normal color combiner +DefaultCombinerDisable = False +# Enable game-specific settings from INI file +EnableHacks = True +# If enabled, graphics will be drawn in WinFrame mode instead of solid and texture mode +WinFrameMode = False +# N64 Texture Memory Full Emulation (may fix some games, may break others) +FullTMEMEmulation = False +# Enable vertex clipper for fog operations +OpenGLVertexClipper = False +# Enable/Disable SSE optimizations for capable CPUs +EnableSSE = True +# If this option is enabled, the plugin will skip every other frame +SkipFrame = False +# If enabled, texture enhancement will be done only for TxtRect ucode +TexRectOnly = False +# If enabled, texture enhancement will be done only for textures width+height<=128 +SmallTextureOnly = False +# Select hi-resolution textures based only on the CRC and ignore format+size information (Glide64 compatibility) +LoadHiResCRCOnly = True +# Enable hi-resolution texture file loading +LoadHiResTextures = False +# Enable texture dumping +DumpTexturesToFiles = False +# Display On-screen FPS +ShowFPS = False +# Use Mipmapping? 0=no, 1=nearest, 2=bilinear, 3=trilinear +Mipmapping = 2 +# Enable, Disable fog generation (0=Disable, 1=Enable) +FogMethod = 1 +# Force to use texture filtering or not (0=auto: n64 choose, 1=force no filtering, 2=force filtering) +ForceTextureFilter = 0 +# Primary texture enhancement filter (0=None, 1=2X, 2=2XSAI, 3=HQ2X, 4=LQ2X, 5=HQ4X, 6=Sharpen, 7=Sharpen More, 8=External, 9=Mirrored) +TextureEnhancement = 0 +# Secondary texture enhancement filter (0 = none, 1-4 = filtered) +TextureEnhancementControl = 0 +# Color bit depth to use for textures (0=default, 1=32 bits, 2=16 bits) +TextureQuality = 0 +# Z-buffer depth (only 16 or 32) +OpenGLDepthBufferSetting = 16 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Color bit depth for rendering window (0=32 bits, 1=16 bits) +ColorQuality = 1 +# OpenGL level to support (0=auto, 1=OGL_FRAGMENT_PROGRAM) +OpenGLRenderSetting = 0 +# Enable/Disable Anisotropic Filtering for Mipmapping (0=no filtering, 2-16=quality). This is uneffective if Mipmapping is 0. If the given value is to high to be supported by your graphic card, the value will be the highest value your graphic card can support. Better result with Trilinear filtering +AnisotropicFiltering = 0 +# If true, use polygon offset values specified below +ForcePolygonOffset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +PolygonOffsetFactor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +PolygonOffsetUnits = 0.000000 + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351V.cfg b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351V.cfg new file mode 100644 index 000000000..2d5060446 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-core/config/mupen64plus-RG351V.cfg @@ -0,0 +1,630 @@ +# Mupen64Plus Configuration File +# This file is automatically read and written by the Mupen64Plus Core library + +[64DD] + +# Filename of the 64DD IPL ROM +IPL-ROM = "" +# Filename of the disk to load into Disk Drive +Disk = "" + + +[Audio-SDL] + +# Mupen64Plus SDL Audio Plugin config parameter version number +Version = 1.000000 +# Frequency which is used if rom doesn't want to change it +DEFAULT_FREQUENCY = 33600 +# Swaps left and right channels +SWAP_CHANNELS = False +# Size of primary buffer in output samples. This is where audio is loaded after it's extracted from n64's memory. +PRIMARY_BUFFER_SIZE = 16384 +# Fullness level target for Primary audio buffer, in equivalent output samples. This value must be larger than the SECONDARY_BUFFER_SIZE. Decreasing this value will reduce audio latency but requires a faster PC to avoid choppiness. Increasing this will increase audio latency but reduce the chance of drop-outs. +PRIMARY_BUFFER_TARGET = 2048 +# Size of secondary buffer in output samples. This is SDL's hardware buffer. The SDL documentation states that this should be a power of two between 512 and 8192. +SECONDARY_BUFFER_SIZE = 1024 +# Audio resampling algorithm. src-sinc-best-quality, src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, src-linear, speex-fixed-{10-0}, trivial +RESAMPLE = "trivial" +# Volume control type: 1 = SDL (only affects Mupen64Plus output) 2 = OSS mixer (adjusts master PC volume) +VOLUME_CONTROL_TYPE = 1 +# Percentage change each time the volume is increased or decreased +VOLUME_ADJUST = 5 +# Default volume when a game is started. Only used if VOLUME_CONTROL_TYPE is 1 +VOLUME_DEFAULT = 100 +# Synchronize Video/Audio +AUDIO_SYNC = False + + +[Core] + +# Mupen64Plus Core config parameter set version number. Please don't change this version number. +Version = 1.010000 +# Draw on-screen display if True, otherwise don't draw OSD +OnScreenDisplay = True +# Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more +R4300Emulator = 2 +# Disable compiled jump commands in dynamic recompiler (should be set to False) +NoCompiledJump = False +# Disable 4MB expansion RAM pack. May be necessary for some games +DisableExtraMem = False +# Increment the save state slot after each save operation +AutoStateSlotIncrement = False +# Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support +EnableDebugger = False +# Save state slot (0-9) to use when saving/loading the emulator state +CurrentStateSlot = 0 +# Path to directory where screenshots are saved. If this is blank, the default value of ${UserDataPath}/screenshot will be used +ScreenshotPath = "/storage/roms/n64" +# Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of ${UserDataPath}/save will be used +SaveStatePath = "/storage/roms/n64" +# Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of ${UserDataPath}/save will be used +SaveSRAMPath = "/storage/roms/n64" +# Path to a directory to search when looking for shared data files +SharedDataPath = "/storage/roms/gamedata/mupen64plussa" +# Force number of cycles per emulated instruction +CountPerOp = 0 +# Randomize PI/SI Interrupt Timing +RandomizeInterrupt = True +# Duration of SI DMA (-1: use per game settings) +SiDmaDuration = -1 +# Gameboy Camera Video Capture backend +GbCameraVideoCaptureBackend1 = "" +# Disk Save Format (0: Full Disk Copy (*.ndr/*.d6r), 1: RAM Area Only (*.ram)) +SaveDiskFormat = 1 + + +[CoreEvents] + +# Mupen64Plus CoreEvents config parameter set version number. Please don't change this version number. +Version = 1.000000 +# SDL keysym for stopping the emulator +Kbd Mapping Stop = 27 +# SDL keysym for switching between fullscreen/windowed modes +Kbd Mapping Fullscreen = 0 +# SDL keysym for saving the emulator state +Kbd Mapping Save State = 286 +# SDL keysym for loading the emulator state +Kbd Mapping Load State = 288 +# SDL keysym for advancing the save state slot +Kbd Mapping Increment Slot = 0 +# SDL keysym for resetting the emulator +Kbd Mapping Reset = 290 +# SDL keysym for slowing down the emulator +Kbd Mapping Speed Down = 291 +# SDL keysym for speeding up the emulator +Kbd Mapping Speed Up = 292 +# SDL keysym for taking a screenshot +Kbd Mapping Screenshot = 293 +# SDL keysym for pausing the emulator +Kbd Mapping Pause = 112 +# SDL keysym for muting/unmuting the sound +Kbd Mapping Mute = 109 +# SDL keysym for increasing the volume +Kbd Mapping Increase Volume = 93 +# SDL keysym for decreasing the volume +Kbd Mapping Decrease Volume = 91 +# SDL keysym for temporarily going really fast +Kbd Mapping Fast Forward = 102 +# SDL keysym for advancing by one frame when paused +Kbd Mapping Frame Advance = 47 +# SDL keysym for pressing the game shark button +Kbd Mapping Gameshark = 103 +# Joystick event string for stopping the emulator +Joy Mapping Stop = "J0B7/B6" +# Joystick event string for switching between fullscreen/windowed modes +Joy Mapping Fullscreen = "" +# Joystick event string for saving the emulator state +Joy Mapping Save State = "J0B7/B5" +# Joystick event string for loading the emulator state +Joy Mapping Load State = "J0B7/B4" +# Joystick event string for advancing the save state slot +Joy Mapping Increment Slot = "" +# Joystick event string for resetting the emulator +Joy Mapping Reset = "" +# Joystick event string for slowing down the emulator +Joy Mapping Speed Down = "" +# Joystick event string for speeding up the emulator +Joy Mapping Speed Up = "" +# Joystick event string for taking a screenshot +Joy Mapping Screenshot = "" +# Joystick event string for pausing the emulator +Joy Mapping Pause = "J0B7/B0" +# Joystick event string for muting/unmuting the sound +Joy Mapping Mute = "" +# Joystick event string for increasing the volume +Joy Mapping Increase Volume = "" +# Joystick event string for decreasing the volume +Joy Mapping Decrease Volume = "" +# Joystick event string for fast-forward +Joy Mapping Fast Forward = "" +# Joystick event string for advancing by one frame when paused +Joy Mapping Frame Advance = "" +# Joystick event string for pressing the game shark button +Joy Mapping Gameshark = "" +# SDL keysym for save slot 0 +Kbd Mapping Slot 0 = 48 +# SDL keysym for save slot 1 +Kbd Mapping Slot 1 = 49 +# SDL keysym for save slot 2 +Kbd Mapping Slot 2 = 50 +# SDL keysym for save slot 3 +Kbd Mapping Slot 3 = 51 +# SDL keysym for save slot 4 +Kbd Mapping Slot 4 = 52 +# SDL keysym for save slot 5 +Kbd Mapping Slot 5 = 53 +# SDL keysym for save slot 6 +Kbd Mapping Slot 6 = 54 +# SDL keysym for save slot 7 +Kbd Mapping Slot 7 = 55 +# SDL keysym for save slot 8 +Kbd Mapping Slot 8 = 56 +# SDL keysym for save slot 9 +Kbd Mapping Slot 9 = 57 + + +[Input-SDL-Control1] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = 0 +# SDL joystick name (or Keyboard) +name = "OpenSimHardware OSH PB Controller" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = True +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "0,0" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "hat(0 Right)" +DPad L = "hat(0 Left)" +DPad D = "hat(0 Down)" +DPad U = "hat(0 Up)" +Start = "button(6)" +Z Trig = "button(9)" +B Button = "button(3)" +A Button = "button(1)" +C Button R = "button(11)" +C Button L = "button(2)" +C Button D = "button(0)" +C Button U = "button(10)" +R Trig = "button(5)" +L Trig = "button(4)" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "axis(0+,0-)" +Y Axis = "axis(1+,1-)" + + +[Input-SDL-Control2] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control3] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Input-SDL-Control4] + +# Mupen64Plus SDL Input Plugin config parameter version number. Please don't change this version number. +version = 2.000000 +# Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic +mode = 2 +# Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number +device = -1 +# SDL joystick name (or Keyboard) +name = "" +# Specifies whether this controller is 'plugged in' to the simulated N64 +plugged = False +# Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 4=Transfer pak, 5=Rumble pak +plugin = 2 +# If True, then mouse buttons may be used with this controller +mouse = False +# Scaling factor for mouse movements. For X, Y axes. +MouseSensitivity = "2.00,2.00" +# The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes. +AnalogDeadzone = "4096,4096" +# An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value +AnalogPeak = "32768,32768" +# Digital button configuration mappings +DPad R = "" +DPad L = "" +DPad D = "" +DPad U = "" +Start = "" +Z Trig = "" +B Button = "" +A Button = "" +C Button R = "" +C Button L = "" +C Button D = "" +C Button U = "" +R Trig = "" +L Trig = "" +Mempak switch = "" +Rumblepak switch = "" +# Analog axis configuration mappings +X Axis = "" +Y Axis = "" + + +[Rsp-HLE] + +# Mupen64Plus RSP HLE Plugin config parameter version number +Version = 1.000000 +# Path to a RSP plugin which will be used when encountering an unknown ucode.You can disable this by letting an empty string. +RspFallback = "" +# Send display lists to the graphics plugin +DisplayListToGraphicsPlugin = True +# Send audio lists to the audio plugin +AudioListToAudioPlugin = False + + +[Transferpak] + +# Filename of the GB ROM to load into transferpak 1 +GB-rom-1 = "" +# Filename of the GB RAM to load into transferpak 1 +GB-ram-1 = "" +# Filename of the GB ROM to load into transferpak 2 +GB-rom-2 = "" +# Filename of the GB RAM to load into transferpak 2 +GB-ram-2 = "" +# Filename of the GB ROM to load into transferpak 3 +GB-rom-3 = "" +# Filename of the GB RAM to load into transferpak 3 +GB-ram-3 = "" +# Filename of the GB ROM to load into transferpak 4 +GB-rom-4 = "" +# Filename of the GB RAM to load into transferpak 4 +GB-ram-4 = "" + + +[UI-Console] + +# Mupen64Plus UI-Console config parameter set version number. Please don't change this version number. +Version = 1.000000 +# Directory in which to search for plugins +PluginDir = "/usr/local/lib/mupen64plus" +# Filename of video plugin +VideoPlugin = "mupen64plus-video-rice" +# Filename of audio plugin +AudioPlugin = "mupen64plus-audio-sdl.so" +# Filename of input plugin +InputPlugin = "mupen64plus-input-sdl.so" +# Filename of RSP plugin +RspPlugin = "mupen64plus-rsp-hle.so" + + +[Video-General] + +# Width of output window or fullscreen width +ScreenWidth = 640 +# Height of output window or fullscreen height +ScreenHeight = 480 +# Use fullscreen mode if True, or windowed mode if False +Fullscreen = False +# If true, activate the SDL_GL_SWAP_CONTROL attribute +VerticalSync = True +# Rotate screen contents: 0=0 degree, 1=90 degree, 2 = 180 degree, 3=270 degree +Rotate = 0 + + +[Video-Glide64mk2] + +# Enable full-scene anti-aliasing by setting this to a value greater than 1 +wrpAntiAliasing = 0 +# Card ID +card_id = 0 +# If true, use polygon offset values specified below +force_polygon_offset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +polygon_offset_factor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +polygon_offset_units = 0.000000 +# Vertical sync +vsync = True +# TODO:ssformat +ssformat = False +# Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent +show_fps = 0 +# Clock enabled +clock = False +# Clock is 24-hour +clock_24_hr = True +# Wrapper resolution +wrpResolution = 0 +# Wrapper VRAM +wrpVRAM = 0 +# Wrapper FBO +wrpFBO = True +# Wrapper Anisotropic Filtering +wrpAnisotropic = True +# Texture Enhancement: Smooth/Sharpen Filters +ghq_fltr = 0 +# Texture Compression: 0 for S3TC, 1 for FXT1 +ghq_cmpr = 0 +# Texture Enhancement: More filters +ghq_enht = 0 +# Hi-res texture pack format (0 for none, 1 for Rice) +ghq_hirs = 1 +# Compress texture cache with S3TC or FXT1 +ghq_enht_cmpr = False +# Tile textures (saves memory but could cause issues) +ghq_enht_tile = 0 +# Force 16bpp textures (saves ram but lower quality) +ghq_enht_f16bpp = False +# Compress texture cache +ghq_enht_gz = True +# Don't enhance textures for backgrounds +ghq_enht_nobg = False +# Enable S3TC and FXT1 compression +ghq_hirs_cmpr = False +# Tile hi-res textures (saves memory but could cause issues) +ghq_hirs_tile = False +# Force 16bpp hi-res textures (saves ram but lower quality) +ghq_hirs_f16bpp = False +# Compress hi-res texture cache +ghq_hirs_gz = True +# Alternative CRC calculation -- emulates Rice bug +ghq_hirs_altcrc = True +# Save tex cache to disk +ghq_cache_save = True +# Texture Cache Size (MB) +ghq_cache_size = 128 +# Use full alpha channel -- could cause issues for some tex packs +ghq_hirs_let_texartists_fly = False +# Dump textures +ghq_hirs_dump = False +# Alternate texture size method: -1=Game default, 0=disable. 1=enable +alt_tex_size = -1 +# Use first SETTILESIZE only: -1=Game default, 0=disable. 1=enable +use_sts1_only = -1 +# Use spheric mapping only: -1=Game default, 0=disable. 1=enable +force_calc_sphere = -1 +# Force positive viewport: -1=Game default, 0=disable. 1=enable +correct_viewport = -1 +# Force texrect size to integral value: -1=Game default, 0=disable. 1=enable +increase_texrect_edge = -1 +# Reduce fillrect size by 1: -1=Game default, 0=disable. 1=enable +decrease_fillrect_edge = -1 +# Enable perspective texture correction emulation: -1=Game default, 0=disable. 1=enable +texture_correction = -1 +# Set special scale for PAL games: -1=Game default, 0=disable. 1=enable +pal230 = -1 +# 3DFX Dithered alpha emulation mode: -1=Game default, >=0=dithered alpha emulation mode +stipple_mode = -1 +# 3DFX Dithered alpha pattern: -1=Game default, >=0=pattern used for dithered alpha emulation +stipple_pattern = -1 +# Check microcode each frame: -1=Game default, 0=disable. 1=enable +force_microcheck = -1 +# Force 0xb5 command to be quad, not line 3D: -1=Game default, 0=disable. 1=enable +force_quad3d = -1 +# Enable near z clipping: -1=Game default, 0=disable. 1=enable +clip_zmin = -1 +# Enable far plane clipping: -1=Game default, 0=disable. 1=enable +clip_zmax = -1 +# Use fast CRC algorithm: -1=Game default, 0=disable. 1=enable +fast_crc = -1 +# Adjust screen aspect for wide screen mode: -1=Game default, 0=disable. 1=enable +adjust_aspect = -1 +# Force strict check in Depth buffer test: -1=Game default, 0=disable. 1=enable +zmode_compare_less = -1 +# Apply alpha dither regardless of alpha_dither_mode: -1=Game default, 0=disable. 1=enable +old_style_adither = -1 +# Scale vertex z value before writing to depth buffer: -1=Game default, 0=disable. 1=enable +n64_z_scale = -1 +# Fast texrect rendering with hwfbe: -1=Game default, 0=disable. 1=enable +optimize_texrect = -1 +# Do not copy auxiliary frame buffers: -1=Game default, 0=disable. 1=enable +ignore_aux_copy = -1 +# Clear auxiliary texture frame buffers: -1=Game default, 0=disable. 1=enable +hires_buf_clear = -1 +# Read alpha from framebuffer: -1=Game default, 0=disable. 1=enable +fb_read_alpha = -1 +# Handle unchanged fb: -1=Game default, 0=disable. 1=enable +useless_is_useless = -1 +# Set frambuffer CRC mode: -1=Game default, 0=disable CRC, 1=fast CRC, 2=safe CRC +fb_crc_mode = -1 +# Filtering mode: -1=Game default, 0=automatic, 1=force bilinear, 2=force point sampled +filtering = -1 +# Fog: -1=Game default, 0=disable. 1=enable +fog = -1 +# Buffer clear on every frame: -1=Game default, 0=disable. 1=enable +buff_clear = -1 +# Buffer swapping method: -1=Game default, 0=swap buffers when vertical interrupt has occurred, 1=swap buffers when set of conditions is satisfied. Prevents flicker on some games, 2=mix of first two methods +swapmode = -1 +# Aspect ratio: -1=Game default, 0=Force 4:3, 1=Force 16:9, 2=Stretch, 3=Original +aspect = -1 +# LOD calculation: -1=Game default, 0=disable. 1=fast, 2=precise +lodmode = -1 +# Smart framebuffer: -1=Game default, 0=disable. 1=enable +fb_smart = -1 +# Hardware frame buffer emulation: -1=Game default, 0=disable. 1=enable +fb_hires = -1 +# Read framebuffer every frame (may be slow use only for effects that need it e.g. Banjo Kazooie, DK64 transitions): -1=Game default, 0=disable. 1=enable +fb_read_always = -1 +# Render N64 frame buffer as texture: -1=Game default, 0=disable, 1=mode1, 2=mode2 +read_back_to_screen = -1 +# Show images written directly by CPU: -1=Game default, 0=disable. 1=enable +detect_cpu_write = -1 +# Get frame buffer info: -1=Game default, 0=disable. 1=enable +fb_get_info = -1 +# Enable software depth render: -1=Game default, 0=disable. 1=enable +fb_render = -1 +# If true, skip up to maxframeskip frames to maintain clock schedule; if false, skip exactly maxframeskip frames +autoframeskip = False +# If autoframeskip is true, skip up to this many frames to maintain clock schedule; if autoframeskip is false, skip exactly this many frames +maxframeskip = 0 + + +[Video-Rice] + +# Mupen64Plus Rice Video Plugin config parameter version number +Version = 1 +# Frame Buffer Emulation (0=ROM default, 1=disable) +FrameBufferSetting = 0 +# Frequency to write back the frame buffer (0=every frame, 1=every other frame, etc) +FrameBufferWriteBackControl = 0 +# Render-to-texture emulation (0=none, 1=ignore, 2=normal, 3=write back, 4=write back and reload) +RenderToTexture = 0 +# Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn) +ScreenUpdateSetting = 4 +# Force to use normal alpha blender +NormalAlphaBlender = False +# Use a faster algorithm to speed up texture loading and CRC computation +FastTextureLoading = False +# Use different texture coordinate clamping code +AccurateTextureMapping = True +# Force emulated frame buffers to be in N64 native resolution +InN64Resolution = False +# Try to reduce Video RAM usage (should never be used) +SaveVRAM = False +# Enable this option to have better render-to-texture quality +DoubleSizeForSmallTxtrBuf = False +# Force to use normal color combiner +DefaultCombinerDisable = False +# Enable game-specific settings from INI file +EnableHacks = True +# If enabled, graphics will be drawn in WinFrame mode instead of solid and texture mode +WinFrameMode = False +# N64 Texture Memory Full Emulation (may fix some games, may break others) +FullTMEMEmulation = False +# Enable vertex clipper for fog operations +OpenGLVertexClipper = False +# Enable/Disable SSE optimizations for capable CPUs +EnableSSE = True +# If this option is enabled, the plugin will skip every other frame +SkipFrame = False +# If enabled, texture enhancement will be done only for TxtRect ucode +TexRectOnly = False +# If enabled, texture enhancement will be done only for textures width+height<=128 +SmallTextureOnly = False +# Select hi-resolution textures based only on the CRC and ignore format+size information (Glide64 compatibility) +LoadHiResCRCOnly = True +# Enable hi-resolution texture file loading +LoadHiResTextures = False +# Enable texture dumping +DumpTexturesToFiles = False +# Display On-screen FPS +ShowFPS = False +# Use Mipmapping? 0=no, 1=nearest, 2=bilinear, 3=trilinear +Mipmapping = 2 +# Enable, Disable fog generation (0=Disable, 1=Enable) +FogMethod = 1 +# Force to use texture filtering or not (0=auto: n64 choose, 1=force no filtering, 2=force filtering) +ForceTextureFilter = 0 +# Primary texture enhancement filter (0=None, 1=2X, 2=2XSAI, 3=HQ2X, 4=LQ2X, 5=HQ4X, 6=Sharpen, 7=Sharpen More, 8=External, 9=Mirrored) +TextureEnhancement = 0 +# Secondary texture enhancement filter (0 = none, 1-4 = filtered) +TextureEnhancementControl = 0 +# Color bit depth to use for textures (0=default, 1=32 bits, 2=16 bits) +TextureQuality = 0 +# Z-buffer depth (only 16 or 32) +OpenGLDepthBufferSetting = 16 +# Enable/Disable MultiSampling (0=off, 2,4,8,16=quality) +MultiSampling = 0 +# Color bit depth for rendering window (0=32 bits, 1=16 bits) +ColorQuality = 1 +# OpenGL level to support (0=auto, 1=OGL_FRAGMENT_PROGRAM) +OpenGLRenderSetting = 0 +# Enable/Disable Anisotropic Filtering for Mipmapping (0=no filtering, 2-16=quality). This is uneffective if Mipmapping is 0. If the given value is to high to be supported by your graphic card, the value will be the highest value your graphic card can support. Better result with Trilinear filtering +AnisotropicFiltering = 0 +# If true, use polygon offset values specified below +ForcePolygonOffset = False +# Specifies a scale factor that is used to create a variable depth offset for each polygon +PolygonOffsetFactor = 0.000000 +# Is multiplied by an implementation-specific value to create a constant depth offset +PolygonOffsetUnits = 0.000000 + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-core/m64p.sh b/packages/games/emulators/mupen64plussa/mupen64plussa-core/m64p.sh new file mode 100755 index 000000000..ea71ad33e --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-core/m64p.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +if [[ ! -f "/storage/roms/gamedata/mupen64plussa/InputAutoCfg.ini" ]]; then + mkdir -p /storage/roms/gamedata/mupen64plussa + cp /usr/local/share/mupen64plus/InputAutoCfg.ini /storage/roms/gamedata/mupen64plussa/ +fi + +if [[ ! -f "/storage/.config/mupen64plussa/mupen64plus.cfg" ]]; then + mkdir -p /storage/.config/mupen64plussa + cp /usr/local/share/mupen64plus/mupen64plus.cfg /storage/.config/mupen64plussa/ +fi + +case $1 in + "m64p_gl64mk2") + /usr/local/bin/mupen64plus --configdir /storage/.config/mupen64plussa --gfx mupen64plus-video-glide64mk2 "$2" + ;; + "m64p_rice") + /usr/local/bin/mupen64plus --configdir /storage/.config/mupen64plussa --gfx mupen64plus-video-rice "$2" + ;; + *) + /usr/local/bin/mupen64plus --configdir /storage/.config/mupen64plussa --gfx mupen64plus-video-rice "$2" + ;; +esac diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-core/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-core/package.mk new file mode 100644 index 000000000..8decc8d50 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-core/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-core" +PKG_VERSION="6860d134afd16f40262fe335cfee04967265fbac" +PKG_SHA256="c71156b23e2edfd54a60e0c34b7ead1fec8d7fef8501bc4fe5e5e2cdd3b31fab" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-core" +PKG_URL="https://github.com/mupen64plus/mupen64plus-core/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} boost libpng SDL2 SDL2_net zlib freetype nasm:host" +PKG_SHORTDESC="mupen64plus" +PKG_LONGDESC="Mupen64Plus Standalone" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/local/lib + cp ${PKG_BUILD}/projects/unix/libmupen64plus.so.2.0.0 ${INSTALL}/usr/local/lib + chmod 644 ${INSTALL}/usr/local/lib/libmupen64plus.so.2.0.0 + cp ${PKG_BUILD}/projects/unix/libmupen64plus.so.2 ${INSTALL}/usr/local/lib + mkdir -p ${INSTALL}/usr/local/share/mupen64plus + cp ${PKG_BUILD}/data/* ${INSTALL}/usr/local/share/mupen64plus + chmod 0644 ${INSTALL}/usr/local/share/mupen64plus/* + mkdir -p ${INSTALL}/usr/local/include/mupen64plus + cp ${PKG_BUILD}/src/api/m64p_*.h ${INSTALL}/usr/local/include/mupen64plus + chmod 0644 ${INSTALL}/usr/local/include/mupen64plus/* + + if [ "${DEVICE}" = "RG351P" ]; then + cp ${PKG_DIR}/config/mupen64plus-RG351P.cfg ${INSTALL}/usr/local/share/mupen64plus/mupen64plus.cfg + elif [ "${DEVICE}" = "RG351V" ]; then + cp ${PKG_DIR}/config/mupen64plus-RG351V.cfg ${INSTALL}/usr/local/share/mupen64plus/mupen64plus.cfg + elif [ "${DEVICE}" = "RG351MP" ]; then + cp ${PKG_DIR}/config/mupen64plus-RG351MP.cfg ${INSTALL}/usr/local/share/mupen64plus/mupen64plus.cfg + fi + chmod 644 ${INSTALL}/usr/local/share/mupen64plus/mupen64plus.cfg + mkdir -p ${INSTALL}/usr/bin + cp ${PKG_DIR}/m64p.sh ${INSTALL}/usr/bin + chmod 755 ${INSTALL}/usr/bin/m64p.sh +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/config/InputAutoCfg.ini b/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/config/InputAutoCfg.ini new file mode 100644 index 000000000..29d8e5802 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/config/InputAutoCfg.ini @@ -0,0 +1,2151 @@ +; InputAutoCfg.ini for Mupen64Plus SDL Input plugin for RGB10 + +[Keyboard] +plugged = True +mouse = False +DPad R = key(100) +DPad L = key(97) +DPad D = key(115) +DPad U = key(119) +Start = key(13) +Z Trig = key(122) +B Button = key(306) +A Button = key(304) +C Button R = key(108) +C Button L = key(106) +C Button D = key(107) +C Button U = key(105) +R Trig = key(99) +L Trig = key(120) +Mempak switch = key(44) +Rumblepak switch = key(46) +X Axis = key(276,275) +Y Axis = key(273,274) + +[Austgame PS to USB convert cable] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(8) +Z Trig = button(4) +B Button = button(3) +A Button = button(2) +C Button R = button(1) +C Button L = button(0) +C Button D = button(5) +C Button U = axis(3-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[BDA Pro Ex] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(4+) +DPad L = axis(4-) +DPad D = axis(5+) +DPad U = axis(5-) +Start = button(9) +Z Trig = button(7) +B Button = button(2) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = key(44) +Rumblepak switch = key(46) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Boom Smart Joy Converter +[HID 6666:0667] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(13) +DPad L = button(15) +DPad D = button(14) +DPad U = button(12) +Start = button(11) +Z Trig = button(10) +B Button = button(4) +A Button = button(5) +C Button R = button(1) +C Button L = button(3) +C Button D = button(2) +C Button U = button(0) +R Trig = button(7) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Cyborg V.3 Rumble Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(4+) +DPad L = axis(4-) +DPad D = axis(5+) +DPad U = axis(5-) +Start = button(12) +Z Trig = button(7) +B Button = button(0) +A Button = button(1) +C Button R = button(8) axis(2+) +C Button L = button(3) axis(2-) +C Button D = button(2) axis(3+) +C Button U = button(9) axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[DragonRise Inc. Generic USB Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = key(275) axis(0+) +DPad L = key(276) axis(0-) +DPad D = key(274) axis(1+) +DPad U = key(273) axis(1-) +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(2) +C Button R = button(7) axis(3+) +C Button L = button(6) axis(3-) +C Button D = button(1) axis(4+) +C Button U = button(0) axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; FuSa is a homebrew program which allows a PSP to be used as a gamepad +[FuSa FuSa GamePad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = +DPad L = +DPad D = +DPad U = +Start = button(7) +Z Trig = button(4) +B Button = button(2) +A Button = button(0) +C Button R = hat(0 Right) +C Button L = hat(0 Left) +C Button D = hat(0 Down) +C Button U = hat(0 Up) +R Trig = button(5) +L Trig = button(3) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; "Super Joy Box 13" USB adaptor for a Gamecube controller +[GameCube to USB box 1] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = button(6) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3-) +C Button U = axis(3+) +R Trig = axis(5+) +L Trig = axis(4+) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Gasia Co.,Ltd PS(R) Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = key(275) axis(0+) hat(0 Right) +DPad L = key(276) axis(0-) hat(0 Left) +DPad D = key(274) axis(1+) hat(0 Down) +DPad U = key(273) axis(1-) hat(0 Up) +Start = button(9) +Z Trig = button(6) +B Button = button(3) +A Button = button(2) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(1) +Rumblepak switch = button(0) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; raphnet technologies USB converter (http://www.raphnet-tech.com/) +[GC/N64_USB] +[GC/N64 to USB, v2.9] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(13) +DPad L = button(12) +DPad D = button(11) +DPad U = button(10) +Start = button(3) +Z Trig = button(2) +B Button = button(1) +A Button = button(0) +C Button R = button(7) +C Button L = button(6) +C Button D = button(5) +C Button U = button(4) +R Trig = button(9) +L Trig = button(8) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; raphnet technologies USB converter, v3 series (http://www.raphnet-tech.com/) +[raphnet technologies GC/N64 to USB] +[raphnet technologies N64 to USB] +[raphnet technologies Dual N64 to USB] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(13) +DPad L = button(12) +DPad D = button(11) +DPad U = button(10) +Start = button(3) +Z Trig = button(2) +B Button = button(1) +A Button = button(0) +C Button R = button(9) +C Button L = button(8) +C Button D = button(7) +C Button U = button(6) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Retrolink N64 USB clone +[Generic USB Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(5+) +DPad L = axis(5-) +DPad D = axis(6+) +DPad U = axis(6-) +Start = button(9) +Z Trig = button(7) +B Button = button(8) +A Button = button(6) +C Button R = button(1) +C Button L = button(3) +C Button D = button(2) +C Button U = button(0) +R Trig = button(5) +L Trig = button(4) +Mempak switch = key(109) +Rumblepak switch = key(114) +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +; gioteck VX2PS3-21 RF Wireless Controller +[Goodbetterbest Ltd PC USB Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +Mempak switch = button(7) +Rumblepak switch = +C Button D = button(1) axis(3+) +C Button L = axis(2-) +Z Trig = button(6) +Start = button(9) +Y Axis = axis(1-,1+) +DPad U = hat(0 Up) +C Button U = button(0) axis(3-) +A Button = button(2) +DPad D = hat(0 Down) +X Axis = axis(0-,0+) +R Trig = button(5) +DPad R = hat(0 Right) +B Button = button(3) +DPad L = hat(0 Left) +C Button R = axis(2+) +L Trig = button(4) + +[GreenAsia Inc. USB Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(1) +B Button = button(3) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[GS gamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(2) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Guillemot Corporation DA Leader] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(12) +Z Trig = button(11) +B Button = button(1) +A Button = button(3) +C Button R = button(6) +C Button L = button(4) +C Button D = button(7) +C Button U = button(5) +R Trig = button(2) +L Trig = button(0) +Mempak switch = key(44) +Rumblepak switch = key(46) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[ipega media gamepad controller] +plugged = True +mouse = False +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(11) +Z Trig = button(6) +B Button = button(3) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = axis(4+) +L Trig = axis(5+) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[ipega gamepad controller] +plugged = True +mouse = False +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(2) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Jess Tech Dual Analog Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Win32: Colour Rumble Pad] +[Jess Tech Colour Rumble Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(4) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(7) +L Trig = button(5) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Jess Tech USB 4-Axis 12-Button Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(4) +Z Trig = button(5) +B Button = button(8) +A Button = button(9) +C Button R = button(1) +C Button L = button(3) +C Button D = button(2) +C Button U = button(0) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Jess Technology Co., Ltd. USB Game Controllers] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(0+) +DPad L = axis(0-) +DPad D = axis(1+) +DPad U = axis(1-) +Start = button(9) +Z Trig = button(3) +B Button = button(0) +A Button = button(2) +C Button R = axis(5+) +C Button L = axis(5-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = button(7) +Rumblepak switch = button(5) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; X-box controllers and compatible clones +[Logitech Chillstream Controller] +[Logic3 Controller] +[HORIPAD ONE] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(6) +Rumblepak switch = button(8) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Logitech Cordless Rumblepad 2] +[Logitech Cordless RumblePad 2] +[Logitech RumblePad 2 USB] +[Logitech Dual Action] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(4+) hat(0 Right) +DPad L = axis(4-) hat(0 Left) +DPad D = axis(5+) hat(0 Down) +DPad U = axis(5-) hat(0 Up) +Start = button(9) +Z Trig = button(6) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(8) +Rumblepak switch = button(7) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Logitech Gamepad F310] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = button(5) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = axis(5-) +L Trig = axis(2-) +Mempak switch = button(1) +Rumblepak switch = button(3) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Logitech Gamepad F710] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(0) +A Button = button(1) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(6) +Rumblepak switch = axis(5+) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Logitech Logitech(R) Precision(TM) Gamepad] +[Gravis GamePad Pro USB] +plugged = True +mouse = False +AnalogDeadzone = 100,100 +AnalogPeak = 32768,32768 +DPad R = axis(0+) +DPad L = axis(0-) +DPad D = axis(1+) +Dpad U = axis(1-) +Start = button(9) +Z Trig = button(6) +B Button = button(5) +A Button = button(4) +C Button R = button(2) +C Button L = button(0) +C Button D = button(1) +C Button U = button(3) +R Trig = button(7) +L Trig = button(8) +Mempack switch = +Rumblepak Switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Logitech WingMan Action Pad] +[Logitech Inc WingMan RumblePad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(13) +DPad L = button(15) +DPad D = button(14) +DPad U = button(12) +Start = button(8) +Z Trig = button(6) +B Button = button(3) +A Button = button(0) +C Button R = button(2) +C Button L = button(4) +C Button D = button(1) +C Button U = button(5) +R Trig = button(7) +L Trig = +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Mayflash GC Controller Adapter 4-Port] +; Mayflash Gamecube 4-Port Controller Adapter (for PC & Wii U USB) - With one Gamecube gamepad(s) connected +; this is a 4-port USB device. The ports from left to right are p1, p2, p3, p4. +; This is configured for Toki no Ocarina, therefore the L trig represents the Z trig and vice versa +plugged = True +mouse = False +AnalogDeadzone = 128,128 +AnalogPeak = 28000,28000 +DPad R = hat(4 Right) +DPad L = hat(4 Left) +DPad D = hat(4 Down) +DPad U = hat(4 Up) +Start = button(36) +; L Trig is mapped to Z +Z Trig = axis(12+) +B Button = button(8) +A Button = button(4) +C Button R = axis(20+) +C Button L = axis(20-) +C Button D = axis(8+) +C Button U = axis(8-) +R Trig = axis(16+) +L Trig = button(28) +Mempak switch = +Rumblepak switch = +Y Axis = axis(0-,0+) +X Axis = axis(4-,4+) + +[Mega World Thrustmaster dual analog 3.2] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(8) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = button(5) +Rumblepak switch = button(7) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Mega World USB Game Controllers] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[MP-8866 Dual USB Joypad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(8) +Z Trig = button(6) +B Button = button(3) +A Button = button(2) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(7) +L Trig = button(4) +Mempak switch = button(10) +Rumblepak switch = button(11) +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +; Nes30 Pro Controller +; NB - this maps Z trigger to button Y +; Select, L2 and R2 are unmapped +[Bluetooth Wireless Controller ] +[8Bitdo NES30 Pro] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(6+) +DPad L = axis(6-) +DPad D = axis(7+) +DPad U = axis(7-) +Start = button(11) +Z Trig = button(4) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Linux: Microsoft X-Box 360 pad] +[Linux: Xbox 360 Wireless Receiver (XBOX)] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+,24000) +C Button L = axis(3-,24000) button(3) +C Button D = axis(4+,24000) button(1) +C Button U = axis(4-,24000) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Multilaser PS2 Generic Controller JS030 +[Linux: Microntek USB Joystick] +[Win32: USB Network Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(6) +B Button = button(3) +A Button = button(2) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Microsoft X-Box 360 pad] +[Microsoft X-Box One pad] +[Win32: Controller (XBOX 360 For Windows)] +[Win32: XBOX 360 For Windows (Controller)] +[Win32: XBOX 360 For Windows] +[Xbox 360 Wireless Receiver] +[Linux: Xbox Gamepad (userspace driver)] +[Afterglow Gamepad for Xbox 360] +[Controller (Xbox One For Windows)] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(4+,24000) +C Button L = axis(4-,24000) +C Button D = axis(3+,24000) +C Button U = axis(3-,24000) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +# mappings for use with the TattieBogle driver under OSX, given in googlecode.com issue #630 +[OSX: Wireless 360 Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(3) +DPad L = button(2) +DPad D = button(0) +DPad U = button(1) +Start = button(4) +Z Trig = axis(5+) +B Button = button(13) +A Button = button(11) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(9) +L Trig = button(8) +Mempak switch = "" +Rumblepak switch = "" +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +# For Xbox One controllers in Bluetooth mode +[Xbox Wireless Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(11) +Z Trig = button(7) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = axis(4+) +L Trig = axis(5+) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +# from the Google Group, with the tattiebogle driver 0.15 beta 3 under El Capitan 10.11.1 +[OSX: Xbox 360 Wired Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(14) +DPad L = button(13) +DPad D = button(12) +DPad U = button(11) +Start = button(8) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = "" +Rumblepak switch = "" +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; ACRUX Gamepad (USB ID: 1a34:0802), a Xbox 360 controller clone aviable under +; various brands (e.g. techsolo TG-30) +[USB GAMEPAD 8116] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = axis(4-) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) button(3) +C Button D = axis(2+) button(1) +C Button U = axis(2-) +R Trig = button(5) axis(4+) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[XInput: Microsoft X-Box 360 pad] +[XInput: Controller (XBOX 360 For Windows)] +[XInput: XBOX 360 For Windows (Controller)] +[XInput: XBOX 360 For Windows] +[XInput: Xbox 360 Wireless Receiver] +[XInput: XInput Controller #] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) button(3) +C Button D = axis(4+) button(1) +C Button U = axis(4-) +R Trig = button(5) axis(5+) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +;Snakebyte PS3-style USB controller +[MY-POWER CO.,LTD. 2In1 USB Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(2) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[N64 controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(0) +B Button = button(2) +A Button = button(1) +C Button R = button(4) +C Button L = button(5) +C Button D = button(3) +C Button U = button(6) +R Trig = button(8) +L Trig = button(7) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Nintendo Wiimote Classic] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(23) +DPad L = button(22) +DPad D = button(21) +DPad U = button(20) +Start = button(17) +Z Trig = button(24) +B Button = button(14) +A Button = button(13) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(25) +L Trig = button(26) +Mempak switch = button(16) +Rumblepak switch = button(15) +X Axis = axis(4-,4+) +Y Axis = axis(5-,5+) + +[Nintendo Wii Remote Pro Controller] +plugged = True +mouse = False +AnalogDeadzone = 2000,2000 +AnalogPeak = 17000,17000 +DPad R = button(16) +DPad L = button(15) +DPad D = button(14) +DPad U = button(13) +Start = button(9) +Z Trig = button(6) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[OUYA Game Controller] +plugged = True +mouse = False +Mempak switch = +Rumblepak switch = +DPad U = button(8) +DPad D = button(9) +DPad L = button(10) +DPad R = button(11) +Start = button(7) +Z Trig = button(12) +A Button = button(0) +B Button = button(1) +C Button U = axis(4-) +C Button D = axis(4+) +C Button L = axis(3-) +C Button R = axis(3+) +L Trig = button(4) +R Trig = button(5) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[PC Game Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(8) +B Button = button(4) +A Button = button(5) +C Button R = button(1) +C Button L = button(3) +C Button D = button(2) +C Button U = button(0) +R Trig = button(7) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Nintendo Switch Pro Controller +[Pro Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(4+) +DPad L = axis(4-) +DPad D = axis(5+) +DPad U = axis(5-) +Start = button(9) +Z Trig = button(6) +B Button = button(0) +A Button = button(1) +C Button R = axis(2-) +C Button L = axis(2+) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(7) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Playfect PS3 controller (cheap clone of the Sony DualShock 3 controller) +[PS3/PC WirelessGamePad] +plugged = True +mouse = False +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(2) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; this is also the MayFlash / HuiJia adapter +[PS/SS/N64 Joypad to USB BOX] +plugged=True +mouse=False +AnalogDeadzone=1024,1024 +AnalogPeak=11000,11000 +DPad R=hat(0 right) +DPad L=hat(0 left) +DPad U=hat(0 up) +DPad D=hat(0 down) +Start=button(8) +Z Trig=button(9) +B Button=button(2) +A Button=button(1) +C Button R=axis(2-) +C Button L=axis(2+) +C Button U=axis(3-) +C Button D=axis(3+) +R Trig=button(7) +L Trig=button(5) +X Axis=axis(0-,0+) +Y Axis=axis(1-,1+) + +[Rock Candy Gamepad for PS3] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[PLAYSTATION(R)3 Controller] +[Sony PLAYSTATION(R)3 Controller] +[SHENGHIC 2009/0708ZXW-V1Inc. PLAYSTATION(R)3Conteroller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(5) +DPad L = button(7) +DPad D = button(6) +DPad U = button(4) +Start = button(3) +Z Trig = button(10) +B Button = button(15) +A Button = button(14) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(11) +L Trig = button(8) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Sony Computer Entertainment Wireless Controller] +[Sony Interactive Entertainment Wireless Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = axis(3+) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(5+) +C Button U = axis(5-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Sony DS4 connected via Bluetooth advertises itself as "Wireless Controller" +[Wireless Controller] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +; L2, change to 7 for R2 +Z Trig = button(6) +B Button = button(0) +A Button = button(1) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[SAITEK P880] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(10) +Z Trig = button(3) +B Button = button(0) +A Button = button(2) +C Button R = button(5) axis(3+) +C Button L = button(1) axis(3-) +C Button D = button(9) axis(2+) +C Button U = button(4) axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Saitek P990 Dual Analog Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(5) +Z Trig = button(4) +B Button = button(0) +A Button = button(1) +C Button R = button(8) axis(3+) +C Button L = button(3) axis(3-) +C Button D = button(2) axis(2+) +C Button U = button(9) axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = button(11) +Rumblepak switch = button(10) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Saitek P2900 Wireless Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(4+) +DPad L = axis(4-) +DPad D = axis(5+) +DPad U = axis(5-) +Start = button(6) +Z Trig = button(7) +B Button = button(0) +A Button = button(1) +C Button R = button(8) axis(3+) +C Button L = button(3) axis(3-) +C Button D = button(2) axis(2+) +C Button U = button(9) axis(2-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(11) +Rumblepak switch = axis(10+) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Saitek PLC Cyborg Force Rumble Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(8) +B Button = button(0) +A Button = button(2) +C Button R = button(5) axis(3+) +C Button L = button(1) axis(3-) +C Button D = button(3) axis(2+) +C Button U = button(4) axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = button(11) +Rumblepak switch = axis(10+) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[ShanWan USB WirelessGamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(0+) +DPad L = axis(0-) +DPad D = axis(1+) +DPad U = axis(1-) +Start = button(9) +Z Trig = button(8) +B Button = button(3) +A Button = button(2) +C Button R = button(7) +C Button L = button(6) +C Button D = button(1) +C Button U = button(0) +R Trig = button(5) +L Trig = button(4) +Mempak switch = key(109) +Rumblepak switch = key(114) +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +[SZMY-POWER CO.,LTD. GAMEPAD 3 TURBO] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(6) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = key(44) +Rumblepak switch = key(46) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Thrustmaster Dual Trigger 3-in-1] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(3) +B Button = button(0) +A Button = button(1) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(5+) +C Button U = axis(5-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = button(6) +Rumblepak switch = button(7) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[THRUSTMASTER Firestorm Dual Power 2] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(5) +Z Trig = button(8) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Thrustmaster T Mini Wireless] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat (0 Right) +DPad L = hat (0 Left) +DPad D = hat (0 Down) +DPad U = hat (0 Up) +Start = button(9) +Z Trig = button(5) +B Button = button(0) +A Button = button(1) +C Button R = Axis = axis(2+) +C Button L = Axis = axis(2-) +C Button D = Axis = axis(3+) +C Button U = Axis = axis(3-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Twin USB Joystick] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(4) +B Button = button(6) +A Button = button(7) +C Button R = button(1) +C Button L = button(3) +C Button D = button(2) +C Button U = button(0) +R Trig = button(5) +L Trig = button(11) +Mempak switch = +Rumblepak switch = +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +[Twin USB Vibration Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +;Twin USB PS-controller lookalike, branded "POWER PAD". +;The controller closest to the USB-plug is Player 1. +[Twin USB Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(4) +B Button = button(3) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +[Wii U GameCube Adapter Port 1] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(11) +DPad L = button(10) +DPad D = button(9) +DPad U = button(8) +Start = button(7) +Z Trig = button(4) +B Button = button(3) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[TigerGame XBOX+PS2+GC Game Controller Adapter] +[WiseGroup.,Ltd TigerGame XBOX+PS2+GC Game Controller Adapter] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(9) +DPad L = button(8) +DPad D = button(10) +DPad U = button(11) +Start = button(7) +Z Trig = button(6) +B Button = button(1) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = axis(4+) +L Trig = axis(5+) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Wish Technologies Adaptoid] +[Adaptoid] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = button(13) +DPad L = button(12) +DPad D = button(11) +DPad U = button(10) +Start = button(8) +Z Trig = button(9) +B Button = button(3) +A Button = button(0) +C Button R = button(2) +C Button L = button(4) +C Button D = button(1) +C Button U = button(5) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; X-box controllers and compatible clones +[Microsoft X-Box pad v1 (US)] +[Microsoft X-Box pad v2 (US)] +[Microsoft X-Box pad (Japan)] +[Microsoft Xbox Controller S] +[Thrustmaster, Inc. Controller] +[Logitech Xbox Cordless Controller] +[Logitech Compact Controller for Xbox] +[Mad Catz Controller (unverified)] +[InterAct 'PowerPad Pro' X-Box pad (Germany)] +[Mad Catz Control Pad] +[Mad Catz LumiCON] +[Mad Catz Control Pad Pro] +[Mad Catz MicroCON] +[Mad Catz Lynx Wireless Controller] +[Zeroplus Xbox Controller] +[Pelican Eclipse PL-2023] +[Zeroplus Xbox Controller] +[Radica Gamester Controller] +[Radica Games Jtech Controller] +[Logic3 Freebird wireless Controller] +[Eclipse wireless Controller] +[Edge wireless Controller] +[SmartJoy Frag Xpad/PS2 adaptor] +[Joytech Advanced Controller] +[BigBen XBMiniPad Controller] +[Joytech Wireless Advanced Controller] +[Chinese-made Xbox Controller] +[Generic X-Box pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(7) +Z Trig = axis(2+) +B Button = button(2) +A Button = button(0) +C Button R = axis(3+) +C Button L = axis(3-) button(3) +C Button D = axis(4+) button(1) +C Button U = axis(4-) +R Trig = button(5) axis(5+) +L Trig = button(4) +Mempak switch = button(9) +Rumblepak switch = button(10) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[OSX: USB GamePad] +; this is a 2-port USB device. The Right port is controller #1, the Left port is #2 +; this is the "MayFlash" adapter, aka HuiJia. The OSX driver seems to have a +; different button mapping +plugged = True +mouse = False +AnalogDeadzone = 2500,2500 +AnalogPeak = 20000,20000 +DPad R = button(13) +DPad L = button(15) +DPad D = button(14) +DPad U = button(12) +Start = button(9) +Z Trig = button(8) +B Button = button(2) +A Button = button(1) +C Button R = axis(1-) +C Button L = axis(1+) +C Button D = axis(0+) +C Button U = axis(0-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(2-,2+) +Y Axis = axis(3-,3+) +__NextController: +plugged = True +mouse = False +AnalogDeadzone = 2500,2500 +AnalogPeak = 20000,20000 +DPad R = button(29) +DPad L = button(31) +DPad D = button(30) +DPad U = button(28) +Start = button(25) +Z Trig = button(24) +B Button = button(18) +A Button = button(17) +C Button R = axis(5-) +C Button L = axis(5+) +C Button D = axis(4+) +C Button U = axis(4-) +R Trig = button(23) +L Trig = button(22) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(6-,6+) +Y Axis = axis(7-,7+) + +[Linux: HuiJia USB GamePad] +plugged = True +mouse = False +AnalogDeadzone = 100,100 +AnalogPeak = 20000,20000 +DPad R = button(13) +DPad L = button(15) +DPad D = button(14) +DPad U = button(12) +Start = button(8) +Z Trig = button(9) +B Button = button(2) +A Button = button(1) +C Button R = axis(3-) +C Button L = axis(3+) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; Mayflash N64 Controller Adapter (for PC USB) - With two N64 gamepads connected +; this is a 2-port USB device. The Right port is controller #1, the Left port is #2 +[Win32: USB GamePad] +plugged = True +mouse = False +AnalogDeadzone = 1024,1024 +AnalogPeak = 12288,12288 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(8) +Z Trig = button(9) +B Button = button(2) +A Button = button(1) +C Button R = axis(3-) +C Button L = axis(3+) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(7) +L Trig = button(6) +Mempak switch = key(109) +Rumblepak switch = key(114) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; MayFlash PC048 adapter +[PS/SS/N64 Joypad to USB BOX] +plugged = True +mouse = False +AnalogDeadzone = 1024,1024 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(8) +Z Trig = button(9) +B Button = button(2) +A Button = button(1) +C Button R = axis(2-) +C Button L = axis(2+) +C Button D = axis(3+) +C Button U = axis(3-) +R Trig = button(7) +L Trig = button(5) +Mempak switch = +Rumblepak switch = +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +; Asikgame - Super Dual Box (with two PS2 gamepads connected) +; this is a 2-port USB device. The Right port is controller #1, the Left port is #2 +[USB Human(2p) Interface Device] +plugged = True +mouse = False +DPad R= axis(2+) +DPad L= axis(2-) +DPad D= axis(5+) +DPad U= axis(5-) +Start= button(0) +Z Trig= button(1) +B Button= button(3) +A Button= button(2) +C Button R= hat(0 Right) +C Button L= hat(0 Left) +C Button D= hat(0 Down) +C Button U= hat(0 Up) +R Trig= button(5) +L Trig= button(4) +Mempak switch= button(9) +Rumblepak switch= button(8) +Y Axis= axis(1-,1+) +X Axis= axis(0-,0+) +__NextController: +plugged = True +mouse = False +DPad R= axis(6+) +DPad L= axis(6-) +DPad D= axis(7+) +DPad U= axis(7-) +Start= button(12) +Z Trig= button(13) +B Button= button(15) +A Button= button(14) +C Button R= hat(1 Right) +C Button L= hat(1 Left) +C Button D= hat(1 Down) +C Button U= hat(1 Up) +R Trig= button(17) +L Trig= button(16) +Mempak switch= button(21) +Rumblepak switch= button(20) +Y Axis= axis(4-,4+) +X Axis= axis(3-,3+) + +[Microsoft SideWinder Game Pad Pro USB version 1.0] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = key(275) +DPad L = key(276) +DPad D = key(274) +DPad U = key(273) +Start = button(8) +Z Trig = button(6) +B Button = button(0) +A Button = button(3) +C Button R = button(2) +C Button L = button(4) +C Button D = button(1) +C Button U = button(5) +R Trig = button(7) +L Trig = button(6) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[USB,2-axis 8-button gamepad] +[USB Gamepad ] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = axis(0+) +DPad L = axis(0-) +DPad D = axis(1+) +DPad U = axis(1-) +Start = button(7) +Z Trig = button(6) +B Button = button(1) +A Button = button(0) +C Button R = button(2) +C Button L = button(3) +C Button D = button(99) +C Button U = button(99) +R Trig = button(4) +L Trig = button(5) +Mempak switch = key(109) +Rumblepak switch = key(114) +Y Axis = axis(1-,1+) +X Axis = axis(0-,0+) + +; RetroUSB "USB N64 RetroPort" +[N64 ] +plugged = True +mouse = False +AnalogDeadzone = 2048,2048 +AnalogPeak = 18432,18432 +DPad R = button(0) +DPad L = button(1) +DPad D = button(2) +DPad U = button(3) +Start = button(4) +Z Trig = button(5) +B Button = button(6) +A Button = button(7) +C Button R = button(8) +C Button L = button(9) +C Button D = button(10) +C Button U = button(11) +R Trig = button(12) +L Trig = button(13) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[Jess Tech GGE909 PC Recoil Pad] +plugged = True +mouse = False +AnalogDeadzone = 4096,4096 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(9) +Z Trig = button(7) +B Button = button(0) +A Button = button(2) +C Button R = axis(3+) +C Button L = axis(3-) +C Button D = axis(2+) +C Button U = axis(2-) +R Trig = button(6) +L Trig = button(4) +Mempak switch = button(10) +Rumblepak switch = button(11) +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +[8BITDO NES30] +plugged = True +mouse = False +DPad R = key(3) +DPad L = key(2) +DPad D = key(5) +DPad U = key(0) +Start = key(22) +Z Trig = key(21) +B Button = key(12) +A Button = key(11) +C Button R = key(3) +C Button L = key(2) +C Button D = key(5) +C Button U = key(0) +R Trig = key(99) +L Trig = key(120) +Mempak switch = key(44) +Rumblepak switch = key(46) +X Axis = key(276,275) +Y Axis = key(273,274) + +; Xiaomi Bluetooth Controller +[å°ç±³è“牙手柄] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = axis(8+) +DPad L = axis(8-) +DPad D = axis(9+) +DPad U = axis(9-) +Start = button(11) +Z Trig = button(6) +B Button = button(3) +A Button = button(0) +C Button R = axis(2+) +C Button L = axis(2-) +C Button D = axis(5+) +C Button U = axis(5-) +R Trig = button(7) +L Trig = button(8) +Mempak switch = +Rumblepak switch = +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; ODROID Go Advance Gamepad +[odroidgo2_joypad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(11) +DPad L = button(10) +DPad D = button(9) +DPad U = button(8) +Start = button(17) +Z Trig = button(12) +B Button = button(3) +A Button = button(0) +C Button R = button(15) +C Button L = button(2) +C Button D = button(1) +C Button U = button(14) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) + +; RG351P Gamepad +[OpenSimHardware OSH PB Controller] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = hat(0 Right) +DPad L = hat(0 Left) +DPad D = hat(0 Down) +DPad U = hat(0 Up) +Start = button(6) +Z Trig = button(9) +B Button = button(3) +A Button = button(1) +C Button R = button(11) +C Button L = button(2) +C Button D = button(0) +C Button U = button(10) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0+,0-) +Y Axis = axis(1+,1-) + +; RG351MP Gamepad +[GO-Super Gamepad] +plugged = True +mouse = False +AnalogDeadzone = 0,0 +AnalogPeak = 32768,32768 +DPad R = button(11) +DPad L = button(10) +DPad D = button(9) +DPad U = button(8) +Start = button(13) +Z Trig = button(15) +B Button = button(3) +A Button = button(0) +C Button R = button(7) +C Button L = button(2) +C Button D = button(1) +C Button U = button(6) +R Trig = button(5) +L Trig = button(4) +Mempak switch = +Rumblepak switch = +# Analog axis configuration mappings +X Axis = axis(0-,0+) +Y Axis = axis(1-,1+) \ No newline at end of file diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/package.mk new file mode 100644 index 000000000..89b737440 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-input-sdl/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-input-sdl" +PKG_VERSION="5e20c6f87b73a07c92148cc4d11f9dfb3b0b0f15" +PKG_SHA256="113558329487f8fba6c6fe361a1ff5863d0e3088c26dde6f1a4eb6c599762917" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-input-sdl" +PKG_URL="https://github.com/mupen64plus/mupen64plus-input-sdl/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-input-sdl" +PKG_LONGDESC="Mupen64Plus Standalone Input SDL" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + USHAREDIR=${UPREFIX}/share/mupen64plus + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-input-sdl.so ${UPLUGINDIR} + #$STRIP ${UPLUGINDIR}/mupen64plus-input-sdl.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-input-sdl.so + mkdir -p ${USHAREDIR} + cp ${PKG_DIR}/config/InputAutoCfg.ini ${USHAREDIR} + chmod 644 ${USHAREDIR}/InputAutoCfg.ini +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-rsp-hle/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-rsp-hle/package.mk new file mode 100644 index 000000000..676cf7a71 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-rsp-hle/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-rsp-hle" +PKG_VERSION="4bac3aeb98aff2d89095c59ec105aad721a16167" +PKG_SHA256="eadefaacbd7e916ae578c8be9ead84d0a079ba1b0bb3f61b9b91f40de5448e37" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-rsp-hle" +PKG_URL="https://github.com/mupen64plus/mupen64plus-rsp-hle/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-rsp-hle" +PKG_LONGDESC="Mupen64Plus Standalone RSP HLE" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-rsp-hle.so ${UPLUGINDIR} + #$STRIP ${UPLUGINDIR}/mupen64plus-rsp-hle.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-rsp-hle.so +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-ui-console/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-ui-console/package.mk new file mode 100644 index 000000000..b790ea6af --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-ui-console/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-ui-console" +PKG_VERSION="32e27344214946f0dce3cd2b4fff152a3538bd8f" +PKG_SHA256="7d4a0a71545caec19d007f34038cffaee36b75d27de615cd4e175bb5ab2e227d" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-ui-console" +PKG_URL="https://github.com/mupen64plus/mupen64plus-ui-console/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-ui-console" +PKG_LONGDESC="Mupen64Plus Standalone Console" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + UBINDIR=${UPREFIX}/bin + UMANDIR=${UPREFIX}/share/man + UAPPSDIR=${UPREFIX}/share/applications + UICONSDIR=${UPREFIX}/share/icons/hicolor + mkdir -p ${UBINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus ${UBINDIR} + #$STRIP ${UBINDIR}/mupen64plus + chmod 0755 ${UBINDIR}/mupen64plus + mkdir -p ${UMANDIR}/man6 + cp ${PKG_BUILD}/doc/mupen64plus.6 ${UMANDIR}/man6 + chmod 0644 ${UMANDIR}/man6/mupen64plus.6 + mkdir -p ${UAPPSDIR} + cp ${PKG_BUILD}/data/mupen64plus.desktop ${UAPPSDIR} + chmod 0644 ${UAPPSDIR}/mupen64plus.desktop + mkdir -p ${UICONSDIR}/48x48/apps + cp ${PKG_BUILD}/data/icons/48x48/apps/mupen64plus.png ${UICONSDIR}/48x48/apps + chmod 0644 ${UICONSDIR}/48x48/apps/mupen64plus.png + mkdir -p ${UICONSDIR}/scalable/apps + cp ${PKG_BUILD}/data/icons/scalable/apps/mupen64plus.svg ${UICONSDIR}/scalable/apps + chmod 0644 ${UICONSDIR}/scalable/apps/mupen64plus.svg +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-video-glide64mk2/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-video-glide64mk2/package.mk new file mode 100644 index 000000000..c0c81a5b3 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-video-glide64mk2/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-video-glide64mk2" +PKG_VERSION="5ac60b38e2c9d9dea3c21fd341b03799841b0b5f" +PKG_SHA256="715a4d92f38672225ccf670edbec974816870d061e5ccdf4bc70a49cdccde8d2" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-video-glide64mk2" +PKG_URL="https://github.com/mupen64plus/mupen64plus-video-glide64mk2/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} boost libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-video-glide64mk2" +PKG_LONGDESC="Mupen64Plus Standalone Glide64 Video Driver" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + USHAREDIR=${UPREFIX}/share/mupen64plus + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-glide64mk2.so ${UPLUGINDIR} + #$STRIP ${UPLUGINDIR}/mupen64plus-video-glide64mk2.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-glide64mk2.so + mkdir -p ${USHAREDIR} + cp ${PKG_BUILD}/data/Glide64mk2.ini ${USHAREDIR} + chmod 0644 ${USHAREDIR}/Glide64mk2.ini +} + diff --git a/packages/games/emulators/mupen64plussa/mupen64plussa-video-rice/package.mk b/packages/games/emulators/mupen64plussa/mupen64plussa-video-rice/package.mk new file mode 100644 index 000000000..ae65b7059 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/mupen64plussa-video-rice/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mupen64plussa-video-rice" +PKG_VERSION="3da7d800989717111da5992a50a8ac410cac038f" +PKG_SHA256="4a7d1ac05a0dc82f071afdef747b4a7876140e580e2d6c8b5306865cfb069c43" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/mupen64plus/mupen64plus-video-rice" +PKG_URL="https://github.com/mupen64plus/mupen64plus-video-rice/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES} libpng SDL2 SDL2_net zlib freetype nasm:host mupen64plussa-core" +PKG_SHORTDESC="mupen64plus-video-rice" +PKG_LONGDESC="Mupen64Plus Standalone Rice Video Driver" +PKG_TOOLCHAIN="manual" + +PKG_MAKE_OPTS_TARGET+="USE_GLES=1" + +make_target() { + export HOST_CPU=aarch64 + export APIDIR=$(get_build_dir mupen64plussa-core)/.install_pkg/usr/local/include/mupen64plus + export USE_GLES=1 + export SDL_CFLAGS="-I$SYSROOT_PREFIX/usr/include/SDL2 -D_REENTRANT" + export SDL_LDLIBS="-lSDL2_net -lSDL2" + export CROSS_COMPILE="$TARGET_PREFIX" + export V=1 + export VC=0 + BINUTILS="$(get_build_dir binutils)/.aarch64-libreelec-linux-gnueabi" + make -C projects/unix clean + make -C projects/unix all ${PKG_MAKE_OPTS_TARGET} +} + +makeinstall_target() { + UPREFIX=${INSTALL}/usr/local + ULIBDIR=${UPREFIX}/lib + USHAREDIR=${UPREFIX}/share/mupen64plus + UPLUGINDIR=${ULIBDIR}/mupen64plus + mkdir -p ${UPLUGINDIR} + cp ${PKG_BUILD}/projects/unix/mupen64plus-video-rice.so ${UPLUGINDIR} + #$STRIP ${UPLUGINDIR}/mupen64plus-video-rice.so + chmod 0644 ${UPLUGINDIR}/mupen64plus-video-rice.so + mkdir -p ${USHAREDIR} + cp ${PKG_BUILD}/data/RiceVideoLinux.ini ${USHAREDIR} + chmod 0644 ${USHAREDIR}/RiceVideoLinux.ini +} + diff --git a/packages/games/emulators/mupen64plussa/package.mk b/packages/games/emulators/mupen64plussa/package.mk new file mode 100644 index 000000000..74378e129 --- /dev/null +++ b/packages/games/emulators/mupen64plussa/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mupen64plussa" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://mupen64plus.org/" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain mupen64plussa-core mupen64plussa-ui-console mupen64plussa-audio-sdl mupen64plussa-input-sdl mupen64plussa-rsp-hle mupen64plussa-video-rice mupen64plussa-video-glide64mk2" +PKG_SECTION="virtual" +PKG_LONGDESC="Meta package for installing the different Mupen64Plus standalone modules" diff --git a/packages/games/emulators/openbor/config/Saves/default.cfg b/packages/games/emulators/openbor/config/Saves/default.cfg new file mode 100755 index 0000000000000000000000000000000000000000..a5276276eb0588f80cb74046c46ede457ec22163 GIT binary patch literal 352 zcma*iSx!Ph5CzbO-~gClBFLclhYTY6_n1LL!a{TrE{a8ZioE`}l9OBAo$92Hc{xi} z(i~1%){xQv@XK9s7Uzn$n5uBWC0AT?LzNnJZn>w$15Mg==+fhnC;B`yV91CU#!Pr+ s${RD@`5Fz%nGa*&QE&u=k literal 0 HcmV?d00001 diff --git a/packages/games/emulators/openbor/config/master.cfg b/packages/games/emulators/openbor/config/master.cfg new file mode 100644 index 0000000000000000000000000000000000000000..abe3f75ca66aeaf1cb111003bc2493934f3deb69 GIT binary patch literal 320 zcmajaxotvG5CzbWK|(~%kl5FN4hV^m$N<+s5f0r3m>rs8Ukl+pnIHQ~M>F&ECYWA3 z8O8b3BpC7i?!z4N#gGAgQe-JnAWeoAT|&kmQS{4{2{Yy_Sh8ZxhAkmG^}vxmC(c~B oa^uc}Cm}f}6eyCXM41XzYSd}amappings\[SDID_START\] = SDL_CONTROLLER_BUTTON_START;|device->mappings\[SDID_START\] = SDL_CONTROLLER_BUTTON_BACK;|g" engine/sdl/control.c + #sed -i "s|device->mappings\[SDID_SCREENSHOT\] = SDL_CONTROLLER_BUTTON_BACK;|device->mappings\[SDID_SCREENSHOT\] = SDL_CONTROLLER_BUTTON_START;|g" engine/sdl/control.c + sed -i "s|-Werror||g" engine/Makefile +} + +pre_make_target() { + cd $PKG_BUILD/engine + ./version.sh +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp OpenBOR $INSTALL/usr/bin/OpenBOR + cp $PKG_DIR/scripts/*.sh $INSTALL/usr/bin + chmod +x $INSTALL/usr/bin/* + mkdir -p $INSTALL/usr/config/openbor + cp $PKG_DIR/config/master.cfg $INSTALL/usr/config/openbor/master.cfg +} diff --git a/packages/games/emulators/openbor/patches/openbor-02-addplatform.patch b/packages/games/emulators/openbor/patches/openbor-02-addplatform.patch new file mode 100644 index 000000000..50473bdfa --- /dev/null +++ b/packages/games/emulators/openbor/patches/openbor-02-addplatform.patch @@ -0,0 +1,75 @@ +From 5d057e7b6b350e2faa75c041d0081fb2963e980d Mon Sep 17 00:00:00 2001 +From: 5schatten +Date: Sat, 12 Oct 2019 19:24:14 +0200 +Subject: [PATCH] engine/Makefile: updated platform + +--- + engine/Makefile | 48 +++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 47 insertions(+), 1 deletion(-) + +diff --git a/engine/Makefile b/engine/Makefile +index 8b0f9a65..6e8198e0 100644 +--- a/engine/Makefile ++++ b/engine/Makefile +@@ -103,6 +103,52 @@ BUILD_DEBUG = 1 + endif + endif + ++ifdef BUILD_LINUX_x86_64 ++TARGET = $(VERSION_NAME).elf ++TARGET_FINAL = $(VERSION_NAME) ++TARGET_PLATFORM = LINUX ++BUILD_SDL = 1 ++BUILD_GFX = 1 ++BUILD_PTHREAD = 1 ++BUILD_SDL_IO = 1 ++BUILD_OPENGL = 1 ++BUILD_LOADGL = 1 ++BUILD_VORBIS = 1 ++BUILD_WEBM = 1 ++BUILDING = 1 ++YASM = nasm ++OBJTYPE = elf ++INCLUDES = $(SDKPATH)/usr/include \ ++ $(SDKPATH)/usr/include/SDL2 ++TARGET_ARCH = amd64 ++BUILD_AMD64 = 1 ++ARCHFLAGS = -m64 ++LIBRARIES = $(SDKPATH)/usr/lib ++CFLAGS += -DAMD64 ++# Workaround for GCC 9 ++CFLAGS += -Wno-error=format-overflow -Wno-error=stringop-truncation ++endif ++ ++ifdef BUILD_LINUX_aarch64 ++TARGET = $(VERSION_NAME).elf ++TARGET_FINAL = $(VERSION_NAME) ++TARGET_PLATFORM = LINUX ++BUILD_LINUX = 1 ++BUILD_SDL = 1 ++BUILD_GFX = 1 ++BUILD_PTHREAD = 1 ++BUILD_SDL_IO = 1 ++BUILD_VORBIS = 1 ++BUILD_WEBM = 1 ++BUILDING = 1 ++INCLUDES = $(SDKPATH)/usr/include \ ++ $(SDKPATH)/usr/include/SDL2 ++OBJTYPE = elf ++LIBRARIES = $(SDKPATH)/usr/lib ++# Workaround for GCC 9 ++CFLAGS += -Wno-error=format-overflow -Wno-error=stringop-truncation -Wno-error=implicit-function-declaration -Wno-error=unused-variable -Wno-error=unused-label ++endif ++ + ifdef BUILD_DARWIN + TARGET = $(VERSION_NAME).elf + TARGET_FINAL = $(VERSION_NAME) +@@ -195,7 +241,7 @@ ifdef BUILD_WIN + STRIP = $(WINDEV)/$(PREFIX)strip$(EXTENSION) $(TARGET) -o $(TARGET_FINAL) + endif + ifdef BUILD_LINUX +-STRIP = $(LNXDEV)/$(PREFIX)strip $(TARGET) -o $(TARGET_FINAL) ++STRIP = $(PREFIX)-strip $(TARGET) -o $(TARGET_FINAL) + endif + ifdef BUILD_DARWIN + STRIP = $(PREFIX)strip $(TARGET) -o $(TARGET_FINAL) diff --git a/packages/games/emulators/openbor/scripts/openbor.sh b/packages/games/emulators/openbor/scripts/openbor.sh new file mode 100755 index 000000000..3f1ec0547 --- /dev/null +++ b/packages/games/emulators/openbor/scripts/openbor.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +# OpenBOR only works with Pak files, if you have an extracted game you will need to create a pak first. + +pakname=$(basename "$1") +pakname="${pakname%.*}" + +CONFIGDIR="/storage/openbor" +PAKS="${CONFIGDIR}/Paks" +SAVES="${CONFIGDIR}/Saves" + +# Make sure the folders exists + mkdir -p "${CONFIGDIR}" + mkdir -p "${PAKS}" + mkdir -p "${SAVES}" + +# Check if master.cfg exists + if [ ! -f "${CONFIGDIR}/master.cfg" ]; then + cp -f "/usr/config/openbor/master.cfg" "${CONFIGDIR}/" + fi + +# Clear PAKS folder to avoid getting the launcher on next run + rm -rf ${PAKS}/* + +# make a symlink to the pak + ln -sf "$1" "${PAKS}" + +# only create symlink to master.cfg if its the first time running the pak + if [ ! -f "${SAVES}/${pakname}.cfg" ]; then + ln -sf "${CONFIGDIR}/master.cfg" "${SAVES}/${pakname}.cfg" + fi + +# We start the fake keyboard + gptokeyb openbor & + +# Run OpenBOR in the config folder + cd "${CONFIGDIR}" + LD_PRELOAD=/usr/lib/libSDL2-2.0.so.0.14.0 SDL_AUDIODRIVER=alsa OpenBOR + +# We stop the fake keyboard + killall gptokeyb & diff --git a/packages/games/emulators/raze/config/RG351MP/raze.ini b/packages/games/emulators/raze/config/RG351MP/raze.ini new file mode 100644 index 000000000..4d45568ec --- /dev/null +++ b/packages/games/emulators/raze/config/RG351MP/raze.ini @@ -0,0 +1,783 @@ +# This file was generated by Raze 1.2pre-392-g50715d3eb +# These are the directories to automatically search for game data. +# Each directory should be on a separate line, preceded by Path= +[GameSearch.Directories] +Path=. +Path=./* +Path=/storage/.config/distribution/raze +Path=/storage/roms/build + +# These are the directories to search for add-ons added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for GameSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/raze +Path=/storage/roms/build + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for GameSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/raze/soundfonts + +[LastRun] +Version=2 + +[GlobalSettings] +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=true +autoloadlights=true +autoloadwidescreen=true +autosavecount=4 +autosavenum=0 +cl_capfps=false +cl_defaultconfiguration=0 +cl_gender=0 +cl_savedir= +con_4bitansi=false +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +con_printansi=true +defaultiwad= +developer=0 +disableautoload=false +disableautosave=0 +duke_menufont=-1 +fluid_chorus=false +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=0.5 +fluid_interp=1 +fluid_lib= +fluid_patchset=raze +fluid_reverb=false +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=1 +fluid_voices=128 +gl_custompost=true +gl_customshader=false +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_dither_bpc=0 +gl_es=true +gl_finishbeforeswap=false +gl_fxaa=0 +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_shadowmap=false +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_multisample=1 +gl_no_skyclear=false +gl_pipeline_depth=0 +gl_plane_reflection=true +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=4 +gl_texture_filter_anisotropic=8 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=15 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +hud_showmapname=true +hud_stats=false +hw_animsmoothing=true +hw_hightile=true +hw_models=false +hw_parallaxskypanning=true +hw_shadeinterpolate=true +hw_shadescale=1 +hw_useindexedcolortextures=false +i_soundinbackground=false +in_mousemode=false +inter_subtitles=false +invertmouse=false +invertmousex=false +language=auto +m_blockcontrollers=false +m_cleanscale=false +m_filter=false +m_forward=0.6999999284744263 +m_pitch=0.7999999523162842 +m_sensitivity_x=3.5 +m_sensitivity_y=1.5 +m_show_backbutton=3 +m_showinputgrid=0 +m_side=0.6999999284744263 +m_use_mouse=1 +m_yaw=0.7999999523162842 +midi_config=raze +midi_dmxgus=false +midi_voices=32 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mus_calcgain=true +mus_enabled=true +mus_extendedlookup=false +mus_gainoffset=0 +mus_usereplaygain=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=0 +opn_fullpan=true +opn_run_at_pcm_rate=false +os_isanyof=true +png_gamma=0 +png_level=5 +queryiwad=true +quicksavecount=4 +quicksavenum=0 +r_ambientlight=1 +r_drawweapon=1 +r_fov=90 +r_mirror_recursions=4 +r_multithreaded=1 +r_precache=true +r_shadows=true +r_skipmats=false +r_spriteadjust=2 +r_ticstability=true +saveloadconfirmation=true +savestatistics=0 +secret_notify=false +showendoom=0 +silentmouseaimtoggle=false +snd_aldevice=Default +snd_alresampler=Default +snd_ambience=true +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=true +snd_enabled=true +snd_extendedlookup=false +snd_hrtf=-1 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_reverb=true +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_tryformats=true +snd_waterreverb=true +statfile=razestat.txt +strictdecorate=false +sw_darts=false +testnewrenderer=false +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=raze +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_min_sustain_time=5000 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=false +vid_defheight=480 +vid_defwidth=640 +vid_fullscreen=true +vid_gamma=1 +vid_hdr=false +vid_maxfps=200 +vid_preferbackend=3 +vid_saturation=1 +vid_scale_customheight=400 +vid_scale_custompixelaspect=1 +vid_scale_customwidth=640 +vid_scale_linear=false +vid_scalefactor=1 +vid_scalemode=0 +vid_sdl_render_driver= +vid_vsync=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_mode=0 +vr_screendist=0.800000011920929 +vr_swap_eyes=false +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +win_h=384 +win_maximized=false +win_w=512 +win_x=-1 +win_y=-1 +wt_commentary=false +wt_forcemidi=false +wt_forcevoc=false +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[.Player] +cl_autoaim=1 +cl_weaponswitch=3 +combatmacro0= +combatmacro1= +combatmacro2= +combatmacro3= +combatmacro4= +combatmacro5= +combatmacro6= +combatmacro7= +combatmacro8= +combatmacro9= +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[.VideoSettings] + +[.UnknownConsoleVariables] + +[.ConsoleAliases] + +[.Bindings] + +[.DoubleBindings] + +[.AutomapBindings] + +[Duke.AutoExec] +Path=/storage/.config/raze/autoexec.cfg + +[Duke.Player] +cl_autoaim=1 +cl_weaponswitch=3 +combatmacro0=An inspiration for birth control. +combatmacro1=You're gonna die for that! +combatmacro2=It hurts to be you. +combatmacro3=Lucky Son of a Bitch. +combatmacro4=Hmmm....Payback time. +combatmacro5=You bottom dwelling scum sucker. +combatmacro6=Damn, you're ugly. +combatmacro7=Ha ha ha...Wasted! +combatmacro8=You suck! +combatmacro9=AARRRGHHHHH!!! +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[Duke.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=2 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[Duke.VideoSettings] + +[Duke.UnknownConsoleVariables] + +[Duke.ConsoleAliases] + +[Duke.Bindings] +Y=show_weapon +K=coop_view +F4=openmenu SoundOptions +LThumb=crouch +LTrigger=+altattack +RTrigger=+attack +Joy1=+open +Joy3=turnaround +Joy5=+run +Joy6=+fire +Joy7=+crouch +Joy8=+jump +Joy11=weapprev +Joy12=weapnext +Joy13=togglemap +Joy14=menu_main +Joy15=toggle cl_autorun +Joy16=centerview + +[Duke.DoubleBindings] + +[Duke.AutomapBindings] +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 +Joy5=+shrink_screen +Joy6=+enlarge_Screen + +[ShadowWarrior.AutoExec] +Path=/storage/.config/raze/autoexec.cfg + +[ShadowWarrior.Player] +cl_autoaim=1 +cl_weaponswitch=1 +combatmacro0=Burn baby burn... +combatmacro1=You make another stupid move. +combatmacro2=Blocking with your head again? +combatmacro3=You not fight well with hands! +combatmacro4=You so stupid! +combatmacro5=Quit jerking off. Come fight me! +combatmacro6=What the matter you scaredy cat? +combatmacro7=Did I break your concentration? +combatmacro8=Hope you were paying attention. +combatmacro9=ITTAIIIUUU!!! +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[ShadowWarrior.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=2 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[ShadowWarrior.VideoSettings] + +[ShadowWarrior.UnknownConsoleVariables] + +[ShadowWarrior.ConsoleAliases] + +[ShadowWarrior.Bindings] +Y=show_weapon +I=toggle cl_crosshair +J=fly +K=coop_view +Shift=+Run +RShift=+Run +Alt=+Strafe +CapsLock=toggle cl_autorun +F4=openmenu SoundOptions +RAlt=+Strafe +LThumb=crouch +LTrigger=+altattack +RTrigger=+attack +Joy5=+run +Joy6=+fire +Joy7=+crouch +Joy8=+jump +Joy14=menu_main +Joy16=centerview +Joy1=+open +Joy3=turnaround +Joy11=weapprev +Joy12=weapnext +Joy13=togglemap + +[ShadowWarrior.DoubleBindings] + +[ShadowWarrior.AutomapBindings] +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 +Joy5=+shrink_screen +Joy6=+enlarge_Screen + +[Joy:JS:0] +Axis0deadzone=0.200001 +Axis1deadzone=0.200001 +Axis2deadzone=0.300001 +Axis2scale=0.7 +Axis2map=0 +Axis3deadzone=0.300001 +Axis3scale=0.6 +Axis3map=1 + diff --git a/packages/games/emulators/raze/config/RG351P/raze.ini b/packages/games/emulators/raze/config/RG351P/raze.ini new file mode 100644 index 000000000..071120dd6 --- /dev/null +++ b/packages/games/emulators/raze/config/RG351P/raze.ini @@ -0,0 +1,944 @@ +# This file was generated by Raze 1.2pre-168-gd2beee587 +# These are the directories to automatically search for game data. +# Each directory should be on a separate line, preceded by Path= +[GameSearch.Directories] +Path=. +Path=./* +Path=/storage/.config/distribution/raze +Path=/storage/roms/build + +# These are the directories to search for add-ons added with the -file +# command line parameter, if they cannot be found with the path +# as-is. Layout is the same as for GameSearch.Directories +[FileSearch.Directories] +Path=/storage/.config/distribution/raze +Path=/storage/roms/build + +# These are the directories to search for soundfonts that let listed in the menu. +# Layout is the same as for GameSearch.Directories +[SoundfontSearch.Directories] +Path=/storage/.config/distribution/raze/soundfonts + +[LastRun] +Version=2 + +[GlobalSettings] +adl_chips_count=6 +adl_emulator_id=0 +adl_fullpan=true +adl_run_at_pcm_rate=false +adl_volume_model=0 +autoloadbrightmaps=true +autoloadlights=true +autoloadwidescreen=true +autosavecount=4 +autosavenum=0 +cl_capfps=false +cl_defaultconfiguration=0 +cl_gender=0 +cl_savedir= +con_4bitansi=false +con_buffersize=-1 +con_ctrl_d= +con_notifylines=4 +con_printansi=true +defaultiwad= +developer=0 +disableautoload=false +disableautosave=0 +duke_menufont=-1 +fluid_chorus=false +fluid_chorus_depth=8 +fluid_chorus_level=1 +fluid_chorus_speed=0.30000001192092896 +fluid_chorus_type=0 +fluid_chorus_voices=3 +fluid_gain=0.5 +fluid_interp=1 +fluid_lib= +fluid_patchset=raze +fluid_reverb=false +fluid_reverb_damping=0.23000000417232513 +fluid_reverb_level=0.5699999928474426 +fluid_reverb_roomsize=0.6100000143051147 +fluid_reverb_width=0.7599999904632568 +fluid_samplerate=0 +fluid_threads=1 +fluid_voices=128 +gl_debug=false +gl_debug_breakpoint=false +gl_debug_level=0 +gl_dither_bpc=0 +gl_es=true +gl_finishbeforeswap=false +gl_fxaa=0 +gl_lens=false +gl_lens_chromatic=1.1200000047683716 +gl_lens_k=-0.11999999731779099 +gl_lens_kcube=0.10000000149011612 +gl_light_shadowmap=false +gl_mask_sprite_threshold=0.5 +gl_mask_threshold=0.5 +gl_mirror_envmap=true +gl_multisample=1 +gl_no_skyclear=false +gl_pipeline_depth=0 +gl_plane_reflection=true +gl_satformula=1 +gl_seamless=false +gl_shadowmap_filter=1 +gl_shadowmap_quality=512 +gl_ssao=0 +gl_ssao_portals=1 +gl_ssao_strength=0.699999988079071 +gl_texture_filter=4 +gl_texture_filter_anisotropic=8 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize_mt_height=4 +gl_texture_hqresize_mt_width=16 +gl_texture_hqresize_multithread=true +gl_texture_hqresize_targets=15 +gl_texture_hqresizemode=0 +gl_texture_hqresizemult=1 +gme_stereodepth=0 +gus_memsize=0 +gus_patchdir= +hud_showmapname=true +hud_stats=false +hw_animsmoothing=true +hw_hightile=true +hw_models=false +hw_parallaxskypanning=true +hw_shadeinterpolate=true +hw_shadescale=1 +hw_useindexedcolortextures=false +i_soundinbackground=false +in_mousemode=true +inter_subtitles=false +invertmouse=false +invertmousex=false +language=auto +m_blockcontrollers=false +m_cleanscale=false +m_filter=false +m_forward=1 +m_pitch=1 +m_sensitivity_x=4 +m_sensitivity_y=2 +m_show_backbutton=0 +m_showinputgrid=0 +m_side=1 +m_use_mouse=2 +m_yaw=1 +midi_config=raze +midi_dmxgus=false +midi_voices=32 +mod_autochip=false +mod_autochip_scan_threshold=12 +mod_autochip_size_force=100 +mod_autochip_size_scan=500 +mod_dumb_mastervolume=1 +mod_interp=2 +mod_samplerate=0 +mod_volramp=2 +mouse_capturemode=1 +mus_calcgain=true +mus_enabled=true +mus_extendedlookup=false +mus_gainoffset=0 +mus_usereplaygain=false +opl_core=0 +opl_fullpan=true +opl_numchips=2 +opn_chips_count=8 +opn_emulator_id=0 +opn_fullpan=true +opn_run_at_pcm_rate=false +os_isanyof=true +png_gamma=0 +png_level=5 +queryiwad=true +quicksavecount=4 +quicksavenum=0 +r_ambientlight=1 +r_drawweapon=1 +r_fov=90 +r_mirror_recursions=4 +r_multithreaded=1 +r_precache=true +r_shadows=true +r_spriteadjust=2 +r_ticstability=true +saveloadconfirmation=true +savestatistics=0 +secret_notify=false +showendoom=0 +silentmouseaimtoggle=false +snd_aldevice=Default +snd_alresampler=Default +snd_ambience=true +snd_backend=openal +snd_buffersize=0 +snd_channels=128 +snd_efx=true +snd_enabled=true +snd_extendedlookup=false +snd_hrtf=-1 +snd_mastervolume=1 +snd_mididevice=-5 +snd_midiprecache=false +snd_musicvolume=0.5 +snd_reverb=true +snd_samplerate=0 +snd_sfxvolume=1 +snd_streambuffersize=64 +snd_tryformats=true +snd_waterreverb=true +statfile=razestat.txt +strictdecorate=false +sw_darts=false +testnewrenderer=false +timidity_channel_pressure=false +timidity_chorus=0 +timidity_config=raze +timidity_drum_effect=false +timidity_drum_power=1 +timidity_key_adjust=0 +timidity_lpf_def=1 +timidity_min_sustain_time=5000 +timidity_modulation_envelope=true +timidity_modulation_wheel=true +timidity_overlap_voice_allow=true +timidity_pan_delay=false +timidity_portamento=true +timidity_reverb=0 +timidity_reverb_level=0 +timidity_surround_chorus=false +timidity_temper_control=true +timidity_tempo_adjust=1 +use_joystick=true +use_mouse=false +vid_activeinbackground=false +vid_adapter=0 +vid_aspect=0 +vid_brightness=0 +vid_contrast=1 +vid_cropaspect=false +vid_defheight=480 +vid_defwidth=640 +vid_fullscreen=true +vid_gamma=1 +vid_hdr=false +vid_maxfps=200 +vid_preferbackend=3 +vid_saturation=1 +vid_scale_customheight=400 +vid_scale_custompixelaspect=1 +vid_scale_customwidth=640 +vid_scale_linear=false +vid_scalefactor=1 +vid_scalemode=0 +vid_sdl_render_driver= +vid_vsync=false +vr_hunits_per_meter=41 +vr_ipd=0.06199999898672104 +vr_mode=0 +vr_screendist=0.800000011920929 +vr_swap_eyes=false +wildmidi_config= +wildmidi_enhanced_resampling=true +wildmidi_reverb=false +win_h=384 +win_maximized=false +win_w=512 +win_x=-1 +win_y=-1 +wt_commentary=false +wt_forcemidi=false +wt_forcevoc=false +xbrz_centerdirectionbias=4 +xbrz_colorformat=0 +xbrz_dominantdirectionthreshold=3.5999999046325684 +xbrz_equalcolortolerance=30 +xbrz_luminanceweight=1 +xbrz_steepdirectionthreshold=2.200000047683716 + +[GlobalSettings.Unknown] + +[.Player] +cl_autoaim=1 +cl_weaponswitch=3 +combatmacro0= +combatmacro1= +combatmacro2= +combatmacro3= +combatmacro4= +combatmacro5= +combatmacro6= +combatmacro7= +combatmacro8= +combatmacro9= +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[.VideoSettings] + +[.UnknownConsoleVariables] + +[.ConsoleAliases] + +[.Bindings] + +[.DoubleBindings] + +[.AutomapBindings] + +[Duke.AutoExec] +Path=/storage/.config/raze/autoexec.cfg + +[Duke.Player] +cl_autoaim=1 +cl_weaponswitch=3 +combatmacro0=An inspiration for birth control. +combatmacro1=You're gonna die for that! +combatmacro2=It hurts to be you. +combatmacro3=Lucky Son of a Bitch. +combatmacro4=Hmmm....Payback time. +combatmacro5=You bottom dwelling scum sucker. +combatmacro6=Damn, you're ugly. +combatmacro7=Ha ha ha...Wasted! +combatmacro8=You suck! +combatmacro9=AARRRGHHHHH!!! +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[Duke.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[Duke.VideoSettings] + +[Duke.UnknownConsoleVariables] + +[Duke.ConsoleAliases] + +[Duke.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 10 +-=sizedown +Equals=sizeup +Backspace=turnaround +Tab=togglemap +Q=+Quick_Kick +W=+Move_Forward +E=+Open +R=useitem 2 +T=messagemode +Y=show_weapon +LeftBracket=invprev +RightBracket=invnext +Enter=invuse +Ctrl=+Crouch +A=+Strafe_Left +S=+Move_Backward +D=+Strafe_Right +H=useitem 3 +J=useitem 4 +K=coop_view +'=weapnext +`=toggleconsole +Shift=+Run +C=+Toggle_Crouch +N=useitem 5 +M=useitem 1 +/=+Jump +RShift=+Run +Alt=+Strafe +Space=+Jump +CapsLock=toggle cl_autorun +F1=openhelpmenu +F2=opensavemenu +F3=openloadmenu +F4=openmenu SoundOptions +F5=openmenu OptionsMenu +F6=quicksave +F7=third_person_view +F8=togglemessages +F9=quickload +F10=menu_endgame +Scroll=HolsterWeapon +KP7=+Aim_Up +KP8=+Move_Forward +KP9=+Look_Up +KP-=sizedown +KP4=+Turn_Left +KP5=centerview +KP6=+Turn_Right +KP+=sizeup +KP1=+Aim_Down +KP2=+Move_Backward +KP3=+Look_Down +KP0=+Look_Left +F11=bumpgamma +F12=screenshot +KP-Enter=invuse +RCtrl=+Fire +RAlt=+Strafe +Pause=pause +Home=+Aim_Up +PgUp=+Look_Up +LeftArrow=+Turn_Left +RightArrow=+Turn_Right +End=+Aim_Down +PgDn=+Look_Down +Ins=+Look_Left +Del=+Look_Right +Mouse1=+Fire +Mouse2=useitem 4 +Mouse3=useitem 1 +MWheelUp=weapprev +MWheelDown=weapnext +DPadUp=togglemap +DPadDown=invuse +DPadLeft=invprev +DPadRight=invnext +Pad_Start=pause +Pad_Back=menu_main +LThumb=crouch +LShoulder=weapprev +RShoulder=weapnext +LTrigger=+altattack +RTrigger=+attack +Pad_A=+open +Pad_Y=+jump + +[Duke.DoubleBindings] + +[Duke.AutomapBindings] +-=+Shrink_Screen +Equals=+Enlarge_Screen +W=+am_panup +R=togglerotate +A=+am_panleft +S=+am_pandown +D=+am_panright +F=togglefollow +KP8=+am_panup +KP-=+Shrink_Screen +KP4=+am_panleft +KP6=+am_panright +KP+=+Enlarge_Screen +KP2=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + +[ShadowWarrior.AutoExec] +Path=/storage/.config/raze/autoexec.cfg + +[ShadowWarrior.Player] +cl_autoaim=1 +cl_weaponswitch=1 +combatmacro0=Burn baby burn... +combatmacro1=You make another stupid move. +combatmacro2=Blocking with your head again? +combatmacro3=You not fight well with hands! +combatmacro4=You so stupid! +combatmacro5=Quit jerking off. Come fight me! +combatmacro6=What the matter you scaredy cat? +combatmacro7=Did I break your concentration? +combatmacro8=Hope you were paying attention. +combatmacro9=ITTAIIIUUU!!! +playercolor=0 +playergender=0 +playername=Player +rtsname= + +[ShadowWarrior.ConsoleVariables] +adl_bank=14 +adl_custom_bank= +adl_use_custom_bank=false +adult_lockout=false +am_followplayer=true +am_linealpha=1 +am_linethickness=1 +am_nameontop=false +am_onesidedcolor=aa aa aa +am_ovonesidedcolor=aa aa aa +am_ovplayercolor=aa aa aa +am_ovtwosidedcolor=aa aa aa +am_playercolor=aa aa aa +am_rotate=true +am_showlabel=false +am_textfont=false +am_twosidedcolor=aa aa aa +chat_substitution=false +cl_automsg=false +cl_autorun=true +cl_autosave=true +cl_autosavedeletion=true +cl_bloodoldweapbalance=false +cl_bloodqavforcedinterp=false +cl_bloodqavinterp=true +cl_bloodvanillabobbing=true +cl_bloodvanillaenemies=false +cl_bloodvanillaexplosions=false +cl_bloodvanillarun=true +cl_bloodweapinterp=false +cl_crosshair=true +cl_exhumedoldturn=false +cl_hudinterpolation=true +cl_idplayers=true +cl_interpolate=true +cl_loadingscreens=true +cl_maxautosaves=8 +cl_nomeleeblur=false +cl_obituaries=true +cl_resumesavegame=true +cl_runmode=true +cl_showmagamt=false +cl_showweapon=1 +cl_slopetilting=false +cl_sointerpolation=true +cl_swsmoothsway=true +cl_syncinput=false +cl_viewbob=true +cl_viewhbob=true +cl_viewvbob=true +cl_weaponsway=true +classic_scaling_factor=1 +classic_scaling_pixelaspect=1.2000000476837158 +con_alpha=0.75 +con_centernotify=false +con_notablist=false +con_notify_advanced=false +con_notifyscale=1 +con_notifytime=3 +con_pulsetext=false +con_scale=0 +crosshair=0 +crosshaircolor=ff 00 00 +crosshairgrow=false +crosshairhealth=2 +crosshairscale=0.5 +gl_aalines=false +gl_bloom=false +gl_bloom_amount=1.399999976158142 +gl_exposure_base=0.3499999940395355 +gl_exposure_min=0.3499999940395355 +gl_exposure_scale=1.2999999523162842 +gl_exposure_speed=0.05000000074505806 +gl_fogmode=1 +gl_menu_blur=-1 +gl_paltonemap_powtable=2 +gl_paltonemap_reverselookup=true +gl_precache=false +gl_scale_viewport=true +gl_tonemap=0 +hud_bgstretch=false +hud_ctf_vanilla=false +hud_flashing=1 +hud_messages=true +hud_position=false +hud_powerupduration=true +hud_scalefactor=1 +hud_size=5 +hud_statscale=0.5 +hud_textfont=false +m_quickexit=false +menu_sounds=true +msg=0 +msg0color=11 +msg1color=5 +msg2color=2 +msg3color=3 +msg4color=3 +msgmidcolor=11 +msgmidcolor2=4 +mus_redbook=true +mus_restartonload=false +nocheats=false +opn_custom_bank= +opn_use_custom_bank=false +r_drawfuzz=1 +r_voxels=true +screenshot_dir= +screenshotname= +snd_menuvolume=0.6000000238418579 +snd_pitched=false +snd_speech=1 +transsouls=0.75 +ui_screenborder_classic_scaling=true +uiscale=0 +usermapfolder= +vid_allowtrueultrawide=1 + +[ShadowWarrior.VideoSettings] + +[ShadowWarrior.UnknownConsoleVariables] + +[ShadowWarrior.ConsoleAliases] + +[ShadowWarrior.Bindings] +1=slot 1 +2=slot 2 +3=slot 3 +4=slot 4 +5=slot 5 +6=slot 6 +7=slot 7 +8=slot 8 +9=slot 9 +0=slot 10 +-=sizedown +Equals=sizeup +Backspace=turnaround +Tab=togglemap +W=+Move_Forward +E=+Open +T=messagemode +Y=show_weapon +I=toggle cl_crosshair +LeftBracket=invprev +RightBracket=invnext +Enter=invuse +Ctrl=+Crouch +A=+Strafe_Left +S=+Move_Backward +D=+Strafe_Right +F=useitem 6 +G=useitem 5 +J=fly +K=coop_view +'=weapnext +`=toggleconsole +Shift=+Run +C=useitem 7 +B=useitem 3 +N=useitem 4 +M=useitem 1 +/=+Jump +RShift=+Run +Alt=+Strafe +Space=+Jump +CapsLock=toggle cl_autorun +F1=openhelpmenu +F2=opensavemenu +F3=openloadmenu +F4=openmenu SoundOptions +F5=openmenu OptionsMenu +F6=quicksave +F7=third_person_view +F8=togglemessages +F9=quickload +F10=menu_endgame +Scroll=HolsterWeapon +KP7=+Aim_Up +KP8=+Move_Forward +KP9=+Look_Up +KP-=sizedown +KP4=+Turn_Left +KP5=centerview +KP6=+Turn_Right +KP+=sizeup +KP1=+Aim_Down +KP2=+Move_Backward +KP3=+Look_Down +KP0=+Look_Left +F11=bumpgamma +F12=screenshot +KP-Enter=invuse +RCtrl=+Fire +RAlt=+Strafe +Pause=pause +Home=+Aim_Up +PgUp=+Look_Up +LeftArrow=+Turn_Left +RightArrow=+Turn_Right +End=+Aim_Down +PgDn=+Look_Down +Ins=+Look_Left +Del=+Look_Right +Mouse1=+Fire +Mouse2=useitem 1 +MWheelUp=weapprev +MWheelDown=weapnext +DPadUp=togglemap +DPadDown=invuse +DPadLeft=invprev +DPadRight=invnext +Pad_Start=pause +Pad_Back=menu_main +LThumb=crouch +LShoulder=weapprev +RShoulder=weapnext +LTrigger=+altattack +RTrigger=+attack +Pad_A=+open +Pad_Y=+jump + +[ShadowWarrior.DoubleBindings] + +[ShadowWarrior.AutomapBindings] +-=+Shrink_Screen +Equals=+Enlarge_Screen +W=+am_panup +R=togglerotate +A=+am_panleft +S=+am_pandown +D=+am_panright +F=togglefollow +KP8=+am_panup +KP-=+Shrink_Screen +KP4=+am_panleft +KP6=+am_panright +KP+=+Enlarge_Screen +KP2=+am_pandown +MWheelUp=am_zoom 1.2 +MWheelDown=am_zoom -1.2 + diff --git a/packages/games/emulators/raze/libvpx/package.mk b/packages/games/emulators/raze/libvpx/package.mk new file mode 100644 index 000000000..12b35e2a3 --- /dev/null +++ b/packages/games/emulators/raze/libvpx/package.mk @@ -0,0 +1,39 @@ +PKG_NAME="libvpx" +PKG_VERSION="1.11.0" +PKG_LICENSE="BSD" +PKG_SITE="https://www.webmproject.org" +PKG_URL="https://github.com/webmproject/libvpx/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="WebM VP8/VP9 Codec" + +configure_target() { + + case $ARCH in + aarch64) + PKG_TARGET_NAME_LIBVPX="arm64-linux-gcc" + ;; + arm) + PKG_TARGET_NAME_LIBVPX="armv7-linux-gcc" + ;; + x86_64) + PKG_TARGET_NAME_LIBVPX="x86_64-linux-gcc" + ;; + esac + + $PKG_CONFIGURE_SCRIPT --prefix=/usr \ + --extra-cflags="$CFLAGS" \ + --as=nasm \ + --target=$PKG_TARGET_NAME_LIBVPX \ + --disable-docs \ + --disable-examples \ + --disable-shared \ + --disable-tools \ + --disable-unit-tests \ + --disable-vp8-decoder \ + --disable-vp9-decoder \ + --enable-ccache \ + --enable-pic \ + --enable-static \ + --enable-vp8 \ + --enable-vp9 +} diff --git a/packages/games/emulators/raze/package.mk b/packages/games/emulators/raze/package.mk new file mode 100644 index 000000000..0da1ee62f --- /dev/null +++ b/packages/games/emulators/raze/package.mk @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="raze" +PKG_VERSION="47001e6bab0229561109ff74fa65802863509fab" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/dhwz/Raze" +PKG_URL="${PKG_SITE}.git" +PKG_DEPENDS_TARGET="toolchain SDL2 raze:host zmusic libvpx" +PKG_SHORTDESC="Raze is a fork of Build engine games backed by GZDoom tech and combines Duke Nukem 3D, Blood, Redneck Rampage, Shadow Warrior and Exhumed/Powerslave in a single package." +PKG_LONGDESC="Raze is a fork of Build engine games backed by GZDoom tech and combines Duke Nukem 3D, Blood, Redneck Rampage, Shadow Warrior and Exhumed/Powerslave in a single package." +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="cmake-make" + +if [ ! "${DEVICE}" = "RG351MP" ] +then + PKG_PATCH_DIRS="RG351P" +fi + +pre_build_host() { + HOST_CMAKE_OPTS="" +} + +make_host() { + cmake . -DNO_GTK=ON + make +} + +makeinstall_host() { +: #no +} + +pre_configure_host(){ +PKG_CMAKE_OPTS_HOST=" -DZMUSIC_LIBRARIES=$(get_build_dir zmusic)/build_host/source/libzmusic.so \ + -DZMUSIC_INCLUDE_DIR=$(get_build_dir zmusic)/include" +} + +pre_configure_target() { +PKG_CMAKE_OPTS_TARGET=" -DNO_GTK=ON \ + -DFORCE_CROSSCOMPILE=ON \ + -DIMPORT_EXECUTABLES=$PKG_BUILD/.$HOST_NAME/ImportExecutables.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DHAVE_GLES2=ON \ + -DHAVE_VULKAN=OFF \ + -DZMUSIC_LIBRARIES=$(get_build_dir zmusic)/build_target/source/libzmusic.so -DZMUSIC_INCLUDE_DIR=$(get_build_dir zmusic)/include" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/raze.sh $INSTALL/usr/bin/ + cp $PKG_BUILD/.$TARGET_NAME/raze $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/config/distribution/raze + if [ "${DEVICE}" = "RG351MP" ]; then + cp $PKG_DIR/config/RG351MP/* $INSTALL/usr/config/distribution/raze + else + cp $PKG_DIR/config/RG351P/* $INSTALL/usr/config/distribution/raze + fi + cp $PKG_BUILD/.$TARGET_NAME/*.pk3 $INSTALL/usr/config/distribution/raze + cp -r $PKG_BUILD/.$TARGET_NAME/soundfonts $INSTALL/usr/config/distribution/raze +} diff --git a/packages/games/emulators/raze/patches/RG351P/0001_key_swap.patch b/packages/games/emulators/raze/patches/RG351P/0001_key_swap.patch new file mode 100644 index 000000000..2f6b3a82b --- /dev/null +++ b/packages/games/emulators/raze/patches/RG351P/0001_key_swap.patch @@ -0,0 +1,19 @@ +diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp +index 05ae2073f..b8e6b8210 100644 +--- a/source/common/menu/menu.cpp ++++ b/source/common/menu/menu.cpp +@@ -694,12 +694,12 @@ bool M_Responder (event_t *ev) + { + case KEY_JOY2: + case KEY_PAD_A: +- mkey = MKEY_Enter; ++ mkey = MKEY_Back; + break; + + case KEY_JOY1: + case KEY_PAD_B: +- mkey = MKEY_Back; ++ mkey = MKEY_Enter; + break; + + case KEY_JOY4: diff --git a/packages/games/emulators/raze/raze.sh b/packages/games/emulators/raze/raze.sh new file mode 100644 index 000000000..cb52aa967 --- /dev/null +++ b/packages/games/emulators/raze/raze.sh @@ -0,0 +1,46 @@ +#!/usr/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile +. /etc/os-release + +EE_DEVICE=${HW_DEVICE} +RUN_DIR="/storage/roms/build" +CONFIG="/storage/.config/distribution/raze/raze.ini" +SAVE_DIR="/storage/roms/gamedata/raze" + +if [ ! -L "/storage/.config/raze" ] +then + ln -sf "/storage/.config/distribution/raze" "/storage/.config/raze" +fi + +if [ ! -f "/storage/.config/distribution/raze/raze.ini" ] +then + cp -rf /usr/config/distribution/raze/raze.ini /storage/.config/distribution/raze/ +fi + +mkdir -p ${SAVE_DIR} + +params=" -config ${CONFIG} -savedir ${SAVE_DIR}" +params+=" +gl_es 1 +vid_preferbackend 3 +cl_capfps 0 +cl_nomeleeblur 1 +vid_fps 1" + +EXT=${1#*.} + +if [ ${EXT} == "build" ]; then + dos2unix "${1}" + while IFS== read -r key value; do + if [ "$key" == "PATH" ]; then + RUN_DIR+="/$value" + fi + if [ "$key" == "GRP" ]; then + params+=" -gamegrp $value" + fi + done < "${1}" +fi + +if [[ ! "RUN_DIR" == "/storage/roms/build" ]]; then + cd "${RUN_DIR}" + LD_PRELOAD=/usr/lib/libSDL2-2.0.so.0.14.0 /usr/bin/raze ${params} >/tmp/logs/raze.log 2>&1 +fi diff --git a/packages/games/emulators/retroarch/modprobe.d/usbhid.conf b/packages/games/emulators/retroarch/modprobe.d/usbhid.conf new file mode 100644 index 000000000..a93b4222f --- /dev/null +++ b/packages/games/emulators/retroarch/modprobe.d/usbhid.conf @@ -0,0 +1,51 @@ +# Juyao +options usbhid quirks=0x0314:0x0326:0x040 +options usbhid quirks=0x0314:0x0328:0x040 + +# 4NES4SNES +options usbhid quirks=0x1781:0x0A9D:0x040 + +# Retrolink SNES +options usbhid quirks=0x1292:0x5346:0x040 +options usbhid quirks=0x1292:0x5366:0x040 + +# Retrobit Atari to USB Driver +options usbhid quirks=0x1292:0x4154:0x040 + +# Retrobit Genesis to PC USB Adapter +options usbhid quirks=0x1292:0x4745:0x040 + +# Retrode +options usbhid quirks=0x0403:0x97c1:0x040 + +# HuiJia USB GamePad Mayflash Sega Saturn +options usbhid quirks=0x0e8f:0x3010:0x040 + +# HuiJia USB GamePad Mayflash NES SNES +options usbhid quirks=0x0079:0x1804:0x040 + +# Mayflash Dreamcast +options usbhid quirks=0x0xe8f:0x3013:0x040 + +# Xin-Mo 2players 20pins +options usbhid quirks=0x16c0:0x75e1:0x040 + +# Xinmo 18 pins USB THT 2P arcade controller THT 2P arcade controller +options usbhid quirks=0x16c0:0x05e1:0x040 + +# USB PS2 Adapter GreenAsia Electronics +options usbhid quirks=0xe8f:0x1013:0x040 + +# HuiJia USB GamePad Mayflash N64 - need test +options usbhid quirks=0xe8f:0x3013:0x040 + +# XCSOURCE 2 Encoder USB - Twin USB Gamepad +options usbhid quirks=0x810:0xe001:0x040 + +# 3H Dual Arcade 2Players +options usbhid quirks=0x16c0:0x05e0:0x040 + +#ShanWan Twin USB Joystick +options usbhid quirks=0x2563:0x555:0x040 + + diff --git a/packages/games/emulators/retroarch/package.mk b/packages/games/emulators/retroarch/package.mk new file mode 100644 index 000000000..1e63736c2 --- /dev/null +++ b/packages/games/emulators/retroarch/package.mk @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="retroarch" +PKG_VERSION="e2848ad0d52314b5d0aabfa0c4f7339fe4998cb2" +PKG_SITE="https://github.com/libretro/RetroArch" +PKG_URL="$PKG_SITE.git" +PKG_LICENSE="GPLv3" +PKG_DEPENDS_TARGET="toolchain SDL2 alsa-lib openssl freetype zlib retroarch-assets core-info ffmpeg libass joyutils empty ${OPENGLES} samba avahi nss-mdns openal-soft libogg libvorbisidec libvpx libpng libdrm librga pulseaudio miniupnpc" +PKG_LONGDESC="Reference frontend for the libretro API." +GET_HANDLER_SUPPORT="git" + +PKG_PATCH_DIRS+="$DEVICE" + +pre_configure_target() { + TARGET_CONFIGURE_OPTS="" + PKG_CONFIGURE_OPTS_TARGET="--disable-qt \ + --enable-alsa \ + --enable-udev \ + --disable-opengl1 \ + --disable-opengl \ + --disable-vulkan \ + --disable-vulkan_display \ + --enable-egl \ + --enable-opengles \ + --disable-wayland \ + --disable-x11 \ + --enable-zlib \ + --enable-freetype \ + --disable-discord \ + --disable-vg \ + --disable-sdl \ + --enable-sdl2 \ + --disable-ffmpeg \ + --enable-opengles3 \ + --enable-opengles3_2 \ + --enable-kms \ + --disable-mali_fbdev \ + --enable-odroidgo2" + + if [ $ARCH == "arm" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-neon" + fi + + cd $PKG_BUILD +} + +make_target() { + make HAVE_UPDATE_ASSETS=1 HAVE_LIBRETRODB=1 HAVE_BLUETOOTH=1 HAVE_NETWORKING=1 HAVE_LAKKA=1 HAVE_ZARCH=1 HAVE_QT=0 HAVE_LANGEXTRA=1 + [ $? -eq 0 ] && echo "(retroarch ok)" || { echo "(retroarch failed)" ; exit 1 ; } + make -C gfx/video_filters compiler=$CC extra_flags="$CFLAGS" + [ $? -eq 0 ] && echo "(video filters ok)" || { echo "(video filters failed)" ; exit 1 ; } + make -C libretro-common/audio/dsp_filters compiler=$CC extra_flags="$CFLAGS" + [ $? -eq 0 ] && echo "(audio filters ok)" || { echo "(audio filters failed)" ; exit 1 ; } +} + +makeinstall_target() { + if [ "${ARCH}" == "aarch64" ]; then + mkdir -p $INSTALL/usr/bin + cp $PKG_BUILD/retroarch $INSTALL/usr/bin + cp -vP $PKG_BUILD/../../build.${DISTRO}-${DEVICE}.arm/retroarch-*/.install_pkg/usr/bin/retroarch ${INSTALL}/usr/bin/retroarch32 + + mkdir -p $INSTALL/usr/share/retroarch/filters + cp -rvP $PKG_BUILD/../../build.${DISTRO}-${DEVICE}.arm/retroarch-*/.install_pkg/usr/share/retroarch/filters/* ${INSTALL}/usr/share/retroarch/filters + + mkdir -p $INSTALL/etc + cp $PKG_BUILD/retroarch.cfg $INSTALL/etc + + mkdir -p $INSTALL/usr/share/retroarch/filters/64bit/video + cp $PKG_BUILD/gfx/video_filters/*.so $INSTALL/usr/share/retroarch/filters/64bit/video + cp $PKG_BUILD/gfx/video_filters/*.filt $INSTALL/usr/share/retroarch/filters/64bit/video + + mkdir -p $INSTALL/usr/share/retroarch/filters/64bit/audio + cp $PKG_BUILD/libretro-common/audio/dsp_filters/*.so $INSTALL/usr/share/retroarch/filters/64bit/audio + cp $PKG_BUILD/libretro-common/audio/dsp_filters/*.dsp $INSTALL/usr/share/retroarch/filters/64bit/audio + + # General configuration + mkdir -p $INSTALL/usr/config/retroarch/ + cp -rf $PKG_DIR/sources/* $INSTALL/usr/config/retroarch/ + else + mkdir -p $INSTALL/usr/bin + cp $PKG_BUILD/retroarch $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/share/retroarch/filters/32bit/video + cp $PKG_BUILD/gfx/video_filters/*.so $INSTALL/usr/share/retroarch/filters/32bit/video + cp $PKG_BUILD/gfx/video_filters/*.filt $INSTALL/usr/share/retroarch/filters/32bit/video + + mkdir -p $INSTALL/usr/share/retroarch/filters/32bit/audio + cp $PKG_BUILD/libretro-common/audio/dsp_filters/*.so $INSTALL/usr/share/retroarch/filters/32bit/audio + cp $PKG_BUILD/libretro-common/audio/dsp_filters/*.dsp $INSTALL/usr/share/retroarch/filters/32bit/audio + fi +} + +post_install() { + enable_service retroarch.service + enable_service tmp-cores.mount + enable_service tmp-joypads.mount + enable_service tmp-database.mount + enable_service tmp-assets.mount + enable_service tmp-shaders.mount + enable_service tmp-overlays.mount +} diff --git a/packages/games/emulators/retroarch/patches/0001-Increase-glui-size.patch b/packages/games/emulators/retroarch/patches/0001-Increase-glui-size.patch new file mode 100644 index 000000000..7ed2281b9 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/0001-Increase-glui-size.patch @@ -0,0 +1,22 @@ +diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c +index 4b2e7d8fb0..2e01a355aa 100644 +--- a/menu/drivers/materialui.c ++++ b/menu/drivers/materialui.c +@@ -3539,7 +3539,7 @@ static void materialui_render(void *data, + /* Check whether screen dimensions, menu scale + * factor or layout optimisation settings have changed */ + scale_factor = gfx_display_get_dpi_scale(p_disp, settings, +- width, height, false, false); ++ width, height, false, false) * 2.000f; + + if ((scale_factor != mui->last_scale_factor) || + (width != mui->last_width) || +@@ -7947,7 +7947,7 @@ static void *materialui_init(void **userdata, bool video_is_threaded) + mui->last_height = height; + mui->last_scale_factor = gfx_display_get_dpi_scale( + p_disp, settings, width, height, +- false, false); ++ false, false) * 2.000f; + mui->dip_base_unit_size = mui->last_scale_factor + * MUI_DIP_BASE_UNIT_SIZE; + diff --git a/packages/games/emulators/retroarch/patches/0001-Increase-ozone-size.patch b/packages/games/emulators/retroarch/patches/0001-Increase-ozone-size.patch new file mode 100644 index 000000000..ba1b4a9f4 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/0001-Increase-ozone-size.patch @@ -0,0 +1,22 @@ +diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c +index cab4491028..97a614ff63 100644 +--- a/menu/drivers/ozone.c ++++ b/menu/drivers/ozone.c +@@ -6837,7 +6837,7 @@ static void *ozone_init(void **userdata, bool video_is_threaded) + ozone->last_width = width; + ozone->last_height = height; + ozone->last_scale_factor = gfx_display_get_dpi_scale(p_disp, +- settings, width, height, false, false); ++ settings, width, height, false, false) * 2.000f; + + file_list_initialize(&ozone->selection_buf_old); + +@@ -7902,7 +7902,7 @@ static void ozone_render(void *data, + /* Check whether screen dimensions or menu scale + * factor have changed */ + scale_factor = gfx_display_get_dpi_scale(p_disp, settings, +- width, height, false, false); ++ width, height, false, false) * 2.000f; + + if ((scale_factor != ozone->last_scale_factor) || + (width != ozone->last_width) || diff --git a/packages/games/emulators/retroarch/patches/0001-Increase-ozone-widget_size.patch b/packages/games/emulators/retroarch/patches/0001-Increase-ozone-widget_size.patch new file mode 100644 index 000000000..3dd774b0b --- /dev/null +++ b/packages/games/emulators/retroarch/patches/0001-Increase-ozone-widget_size.patch @@ -0,0 +1,14 @@ +diff --git a/gfx/gfx_widgets.c b/gfx/gfx_widgets.c +index 29e956763e..3caec1f48d 100644 +--- a/gfx/gfx_widgets.c ++++ b/gfx/gfx_widgets.c +@@ -931,6 +931,9 @@ void gfx_widgets_iterate( + p_disp, + settings, width, height, fullscreen, true); + ++ if (p_disp->menu_driver_id == MENU_DRIVER_ID_OZONE) ++ scale_factor = scale_factor * 1.500f; ++ + /* Check whether screen dimensions or menu scale + * factor have changed */ + if ((scale_factor != p_dispwidget->last_scale_factor) || diff --git a/packages/games/emulators/retroarch/patches/0001-video_thread_wrapper-implement-RETRO_ENVIRONMENT_GET.patch b/packages/games/emulators/retroarch/patches/0001-video_thread_wrapper-implement-RETRO_ENVIRONMENT_GET.patch new file mode 100644 index 000000000..a9f05234c --- /dev/null +++ b/packages/games/emulators/retroarch/patches/0001-video_thread_wrapper-implement-RETRO_ENVIRONMENT_GET.patch @@ -0,0 +1,55 @@ +From cfc19b7e5ccaabd0ae5cf74a470badc04a97fab0 Mon Sep 17 00:00:00 2001 +From: valadaa48 +Date: Sun, 13 Dec 2020 15:24:02 -0500 +Subject: [PATCH] video_thread_wrapper: implement + RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER: + +--- + gfx/video_thread_wrapper.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c +index d663eed6e1..b743e5e95b 100644 +--- a/gfx/video_thread_wrapper.c ++++ b/gfx/video_thread_wrapper.c +@@ -596,7 +596,7 @@ static bool video_thread_frame(void *data, const void *frame_, + * still working on last frame. */ + if (!thr->frame.updated) + { +- if (src) ++ if (src && src != dst) + { + unsigned h; + for (h = 0; h < height; h++, src += pitch, dst += copy_stride) +@@ -1189,6 +1189,20 @@ static uint32_t thread_get_flags(void *data) + return thr->poke->get_flags(thr->driver_data); + } + ++static bool thread_get_current_software_framebuffer(void *data, ++ struct retro_framebuffer *framebuffer) ++{ ++ thread_video_t *thr = (thread_video_t*)data; ++ if (!thr) ++ return false; ++ ++ framebuffer->data = (uint8_t*)thr->frame.buffer; ++ framebuffer->pitch = thr->frame.pitch; ++ framebuffer->format = thr->info.rgb32 ? RETRO_PIXEL_FORMAT_XRGB8888 : RETRO_PIXEL_FORMAT_RGB565; ++ ++ return true; ++} ++ + static const video_poke_interface_t thread_poke = { + thread_get_flags, + thread_load_texture, +@@ -1211,7 +1225,7 @@ static const video_poke_interface_t thread_poke = { + thread_grab_mouse_toggle, + + thread_get_current_shader, +- NULL, /* get_current_software_framebuffer */ ++ thread_get_current_software_framebuffer, + NULL, /* get_hw_render_interface */ + thread_set_hdr_max_nits, + thread_set_hdr_paper_white_nits, + + diff --git a/packages/games/emulators/retroarch/patches/008-drm-resolution.patch b/packages/games/emulators/retroarch/patches/008-drm-resolution.patch new file mode 100644 index 000000000..369b26729 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/008-drm-resolution.patch @@ -0,0 +1,27 @@ +diff --git a/gfx/common/drm_common.c b/gfx/common/drm_common.c +index a1bede5..8bc674a 100644 +--- a/gfx/common/drm_common.c ++++ b/gfx/common/drm_common.c +@@ -156,6 +156,22 @@ bool drm_get_encoder(int fd) + g_drm_connector->modes[i].vrefresh); + } + ++ // batocera - set resolution ++ FILE* fdDrmMode; ++ int drmMode; ++ if((fdDrmMode = fopen("/var/run/drmMode", "r")) != NULL) { ++ if(fscanf(fdDrmMode, "%i", &drmMode) == 1) { ++ if(drmMode>=0 && drmModecount_modes) { ++ drmModeCrtc *pcrtc = drmModeGetCrtc(fd, g_drm_encoder->crtc_id); ++ if(pcrtc != NULL) { ++ drmModeSetCrtc(fd, pcrtc->crtc_id, pcrtc->buffer_id, 0, 0, &g_drm_connector->connector_id, 1, &g_drm_connector->modes[drmMode]); ++ } ++ } ++ } ++ fclose(fdDrmMode); ++ } ++ // ++ + return true; + } + diff --git a/packages/games/emulators/retroarch/patches/010-disable-drm-resolution-adaptation.patch b/packages/games/emulators/retroarch/patches/010-disable-drm-resolution-adaptation.patch new file mode 100644 index 000000000..2df44e2ed --- /dev/null +++ b/packages/games/emulators/retroarch/patches/010-disable-drm-resolution-adaptation.patch @@ -0,0 +1,70 @@ +diff --git a/gfx/drivers_context/drm_ctx.c b/gfx/drivers_context/drm_ctx.c +index 182d0b4..66d063c 100644 +--- a/gfx/drivers_context/drm_ctx.c ++++ b/gfx/drivers_context/drm_ctx.c +@@ -701,6 +701,8 @@ static bool gfx_ctx_drm_set_video_mode(void *data, + settings_t *settings = config_get_ptr(); + unsigned black_frame_insertion = settings->uints.video_black_frame_insertion; + float video_refresh_rate = settings->floats.video_refresh_rate; ++ FILE* fdDrmMode; ++ int drmMode; + + if (!drm) + return false; +@@ -715,46 +717,16 @@ static bool gfx_ctx_drm_set_video_mode(void *data, + /* Find desired video mode, and use that. + * If not fullscreen, we get desired windowed size, + * which is not appropriate. */ +- if ((width == 0 && height == 0) || !fullscreen) +- g_drm_mode = &g_drm_connector->modes[0]; +- else +- { +- /* check if custom hdmi timings were asked */ +- if(gfx_ctx_crt_switch_mode.vdisplay > 0) +- { +- RARCH_LOG("[DRM]: custom mode requested: %s\n", gfx_ctx_crt_switch_mode.name); +- g_drm_mode = &gfx_ctx_crt_switch_mode; +- } +- else +- { +- /* Try to match refresh_rate as closely as possible. +- * +- * Lower resolutions tend to have multiple supported +- * refresh rates as well. +- */ +- float minimum_fps_diff = 0.0f; +- float mode_vrefresh = 0.0f; +- drmModeModeInfo *mode; +- +- /* Find best match. */ +- for (i = 0; i < g_drm_connector->count_modes; i++) { +- float diff; +- mode = &g_drm_connector->modes[i]; +- +- if (width != mode->hdisplay || +- height != mode->vdisplay) +- continue; +- +- mode_vrefresh = drm_calc_refresh_rate(mode); +- +- diff = fabsf(refresh_mod * mode_vrefresh - video_refresh_rate); +- +- if (!g_drm_mode || diff < minimum_fps_diff) { +- g_drm_mode = mode; +- minimum_fps_diff = diff; +- } +- } +- } ++ //if ((width == 0 && height == 0) || !fullscreen) ++ g_drm_mode = &g_drm_connector->modes[0]; ++ // batocera - set resolution ++ if((fdDrmMode = fopen("/var/run/drmMode", "r")) != NULL) { ++ if(fscanf(fdDrmMode, "%i", &drmMode) == 1) { ++ if(drmMode>=0 && drmModecount_modes) { ++ g_drm_mode = &g_drm_connector->modes[drmMode]; ++ } ++ } ++ fclose(fdDrmMode); + } + + if (!g_drm_mode) diff --git a/packages/games/emulators/retroarch/patches/RG351V/0001-remove_rotation.patch b/packages/games/emulators/retroarch/patches/RG351V/0001-remove_rotation.patch new file mode 100644 index 000000000..65d2aa950 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/RG351V/0001-remove_rotation.patch @@ -0,0 +1,23 @@ +diff --git a/deps/libgo2/src/display.c b/deps/libgo2/src/display.c +index b91cf0624b..da433890e5 100644 +--- a/deps/libgo2/src/display.c ++++ b/deps/libgo2/src/display.c +@@ -597,15 +597,15 @@ void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidt + break; + + case GO2_ROTATION_DEGREES_90: +- src.rotation = HAL_TRANSFORM_ROT_90; ++ src.rotation = 0; + break; + + case GO2_ROTATION_DEGREES_180: +- src.rotation = HAL_TRANSFORM_ROT_180; ++ src.rotation = 0; + break; + + case GO2_ROTATION_DEGREES_270: +- src.rotation = HAL_TRANSFORM_ROT_270; ++ src.rotation = 0; + break; + + default: diff --git a/packages/games/emulators/retroarch/patches/retroarch-01-xkb-fix.patch b/packages/games/emulators/retroarch/patches/retroarch-01-xkb-fix.patch new file mode 100644 index 000000000..630547b0e --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-01-xkb-fix.patch @@ -0,0 +1,30 @@ +diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c +index bcdacb60a6..d2f00114bd 100644 +--- a/input/drivers/udev_input.c ++++ b/input/drivers/udev_input.c +@@ -76,14 +76,14 @@ + #include "../../retroarch.h" + #include "../../verbosity.h" + +-#if defined(HAVE_XKBCOMMON) && defined(HAVE_KMS) ++#if defined(HAVE_XKBCOMMON) + #define UDEV_XKB_HANDLING + #endif + + /* Force UDEV_XKB_HANDLING for Lakka */ + #ifdef HAVE_LAKKA + #ifndef UDEV_XKB_HANDLING +-#define UDEV_XKB_HANDLING ++#undef UDEV_XKB_HANDLING + #endif + #endif + +@@ -1402,7 +1402,7 @@ + /* Force xkb_handling on Lakka */ + udev->xkb_handling = true; + #else +- udev->xkb_handling = string_is_equal(ctx_ident.ident, "kms"); ++ udev->xkb_handling = true; //string_is_equal(ctx_ident.ident, "kms"); + #endif /* HAVE_LAKKA */ + #endif + diff --git a/packages/games/emulators/retroarch/patches/retroarch-02_disable_search.patch b/packages/games/emulators/retroarch/patches/retroarch-02_disable_search.patch new file mode 100644 index 000000000..f6b5fde0a --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-02_disable_search.patch @@ -0,0 +1,13 @@ +diff --git a/menu/menu_driver.c b/menu/menu_driver.c +index 87166738e6..1c27a89e15 100644 +--- a/menu/menu_driver.c ++++ b/menu/menu_driver.c +@@ -7901,7 +7901,7 @@ int generic_menu_entry_action( + entry->label, entry->type, i, entry->entry_idx); + break; + case MENU_ACTION_SEARCH: +- menu_input_dialog_start_search(); ++ //menu_input_dialog_start_search(); + break; + case MENU_ACTION_SCAN: + if (cbs && cbs->action_scan) diff --git a/packages/games/emulators/retroarch/patches/retroarch-04-enablecontent.patch b/packages/games/emulators/retroarch/patches/retroarch-04-enablecontent.patch new file mode 100644 index 000000000..f51e3b5f7 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-04-enablecontent.patch @@ -0,0 +1,26 @@ +diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c +index cc14b36a23..61b47b5be0 100644 +--- a/menu/menu_displaylist.c ++++ b/menu/menu_displaylist.c +@@ -11520,7 +11520,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + case DISPLAYLIST_OPTIONS: + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); + { +-#ifdef HAVE_LAKKA ++#ifndef HAVE_LAKKA + if (menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_LAKKA), + msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_LAKKA), +diff --git a/menu/menu_setting.c b/menu/menu_setting.c +index b6fd84cab3..2038cb5b55 100644 +--- a/menu/menu_setting.c ++++ b/menu/menu_setting.c +@@ -8699,7 +8699,7 @@ static bool setting_append_list( + #endif + #if !defined(IOS) + /* Apple rejects iOS apps that let you forcibly quit them. */ +-#ifdef HAVE_LAKKA ++#ifndef HAVE_LAKKA + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_QUIT_RETROARCH, diff --git a/packages/games/emulators/retroarch/patches/retroarch-05-disable_updater_entries.patch b/packages/games/emulators/retroarch/patches/retroarch-05-disable_updater_entries.patch new file mode 100644 index 000000000..9760574e6 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-05-disable_updater_entries.patch @@ -0,0 +1,149 @@ +diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c +index 57eeca4327..d39fd1fd64 100644 +--- a/menu/menu_displaylist.c ++++ b/menu/menu_displaylist.c +@@ -12021,29 +12021,29 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + } + #endif + #endif +- if (settings->bools.menu_show_legacy_thumbnail_updater) +- { +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST), +- msg_hash_to_str(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST), +- MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, +- MENU_SETTING_ACTION, 0, 0)) +- count++; +- } +- +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST), +- msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST), +- MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST, +- MENU_SETTING_ACTION, 0, 0)) +- count++; +- +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT), +- msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS), +- MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS, +- MENU_SETTING_ACTION, 0, 0)) +- count++; ++ //if (settings->bools.menu_show_legacy_thumbnail_updater) ++ //{ ++ // if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST), ++ // msg_hash_to_str(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST), ++ // MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; ++ //} ++ ++ //if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST), ++ // msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST), ++ // MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; ++ ++ //if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT), ++ // msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS), ++ // MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; + + #ifdef HAVE_COMPRESSION + if (settings->bools.menu_show_core_updater) +@@ -12057,20 +12057,20 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + } + + #ifdef HAVE_UPDATE_ASSETS +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS), +- msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_ASSETS), +- MENU_ENUM_LABEL_UPDATE_ASSETS, +- MENU_SETTING_ACTION, 0, 0)) +- count++; ++ //if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS), ++ // msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_ASSETS), ++ // MENU_ENUM_LABEL_UPDATE_ASSETS, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; + #endif + #if !defined(_3DS) +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES), +- msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES), +- MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES, +- MENU_SETTING_ACTION, 0, 0)) +- count++; ++ //if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES), ++ // msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES), ++ // MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; + + if (menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_CHEATS), +@@ -12090,12 +12090,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + #endif + #endif + #if !defined(_3DS) +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_OVERLAYS), +- msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_OVERLAYS), +- MENU_ENUM_LABEL_UPDATE_OVERLAYS, +- MENU_SETTING_ACTION, 0, 0)) +- count++; ++ //if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_OVERLAYS), ++ // msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_OVERLAYS), ++ // MENU_ENUM_LABEL_UPDATE_OVERLAYS, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; + + #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) + if (video_shader_is_supported(RARCH_SHADER_CG)) +@@ -12108,15 +12108,15 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + count++; + } + +- if (video_shader_is_supported(RARCH_SHADER_GLSL)) +- { +- if (menu_entries_append_enum(info->list, +- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_GLSL_SHADERS), +- msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS), +- MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS, +- MENU_SETTING_ACTION, 0, 0)) +- count++; +- } ++ //if (video_shader_is_supported(RARCH_SHADER_GLSL)) ++ //{ ++ // if (menu_entries_append_enum(info->list, ++ // msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_GLSL_SHADERS), ++ // msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS), ++ // MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS, ++ // MENU_SETTING_ACTION, 0, 0)) ++ // count++; ++ //} + + if (video_shader_is_supported(RARCH_SHADER_SLANG)) + { +@@ -12133,10 +12133,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, + #endif + + #ifdef HAVE_NETWORKING +- if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, +- MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, +- PARSE_ONLY_BOOL, false) != -1) +- count++; ++ //if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, ++ // MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, ++ // PARSE_ONLY_BOOL, false) != -1) ++ // count++; + #endif + } + diff --git a/packages/games/emulators/retroarch/patches/retroarch-10-Exit_menu.patch b/packages/games/emulators/retroarch/patches/retroarch-10-Exit_menu.patch new file mode 100644 index 000000000..e37ab682c --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-10-Exit_menu.patch @@ -0,0 +1,68 @@ +--- ./retroarch.c 2017-07-26 23:59:01.195225618 -0500 ++++ ./retroarch.c 2017-08-14 01:58:07.722644341 -0500 +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -3962,9 +3963,30 @@ + } + break; + case CMD_EVENT_QUIT: +- if (!retroarch_main_quit()) ++ { ++ /* Exit Back to Kodi if the option exists on the cfg file*/ ++ settings_t *settings = config_get_ptr(); ++ if(settings->bools.emuelec_exit_to_kodi) ++ { ++ remove("/var/lock/start.retro"); ++ system("touch /var/lock/start.kodi"); ++ system("systemctl start kodi.service"); ++ system("systemctl stop retroarch.service"); ++ } ++ else ++ { ++ /* Exit back to ES - TODO: Check if start.retro file exists, if it does, then exit with the following code */ ++ if( access( "/var/lock/start.retro", F_OK ) != -1 ) { remove("/var/lock/start.retro"); ++ system("touch /var/lock/start.games"); ++ system("systemctl restart emustation.service"); ++ system("systemctl stop retroarch.service"); ++ } } ++ /* if it doesn't exist then just exit */ ++ ++ if (!retroarch_main_quit()) + return false; + break; ++ } + case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE: + #ifdef HAVE_CHEEVOS + rcheevos_toggle_hardcore_mode(); + +--- ./configuration.h 2017-08-14 02:20:37.546187576 -0500 ++++ ./configuration.h 2017-08-14 02:20:46.390236188 -0500 +@@ -47,6 +47,9 @@ + { + bool placeholder; + ++ /* emuelec */ ++ bool emuelec_exit_to_kodi; ++ bool video_oga_vertical_enable; + /* Video */ + bool video_fullscreen; + bool video_windowed_fullscreen; +--- ./configuration.c 2017-08-18 06:30:31.000000000 -0500 ++++ ./configuration.c 2017-08-23 01:24:28.009570267 -0500 +@@ -1329,6 +1329,10 @@ + { + struct config_bool_setting *tmp = (struct config_bool_setting*)calloc(1, (*size + 1) * sizeof(struct config_bool_setting)); + unsigned count = 0; ++ /* emuelec */ ++ SETTING_BOOL("emuelec_exit_to_kodi", &settings->bools.emuelec_exit_to_kodi, true, false, false); ++ SETTING_BOOL("video_oga_vertical_enable", &settings->bools.video_oga_vertical_enable, true, false, false); ++ /* emuelec */ + + SETTING_BOOL("accessibility_enable", &settings->bools.accessibility_enable, true, DEFAULT_ACCESSIBILITY_ENABLE, false); + SETTING_BOOL("driver_switch_enable", &settings->bools.driver_switch_enable, true, DEFAULT_DRIVER_SWITCH_ENABLE, false); diff --git a/packages/games/emulators/retroarch/patches/retroarch-12-input_sort_devices.patch b/packages/games/emulators/retroarch/patches/retroarch-12-input_sort_devices.patch new file mode 100644 index 000000000..dfe28a461 --- /dev/null +++ b/packages/games/emulators/retroarch/patches/retroarch-12-input_sort_devices.patch @@ -0,0 +1,50 @@ +diff --git a/input/drivers_joypad/udev_joypad.c b/input/drivers_joypad/udev_joypad.c +index e60a8b2..03ba777 100644 +--- a/input/drivers_joypad/udev_joypad.c ++++ b/input/drivers_joypad/udev_joypad.c +@@ -538,6 +538,14 @@ + } + } + ++/* Used for sorting devnodes to appear in the correct order */ ++static int sort_devnodes(const void *a, const void *b) ++{ ++ const struct joypad_udev_entry *aa = (const struct joypad_udev_entry*)a; ++ const struct joypad_udev_entry *bb = (const struct joypad_udev_entry*)b; ++ return strcmp(aa->devnode, bb->devnode); ++} ++ + static void *udev_joypad_init(void *data) + { + unsigned i; +@@ -570,9 +578,29 @@ + udev_enumerate_scan_devices(enumerate); + devs = udev_enumerate_get_list_entry(enumerate); + +- udev_list_entry_foreach(item, devs) ++ for (item = devs; item; item = udev_list_entry_get_next(item)) + { + const char *name = udev_list_entry_get_name(item); ++ struct udev_device *dev = udev_device_new_from_syspath(udev_joypad_fd, name); ++ const char *devnode = udev_device_get_devnode(dev); ++ ++ if (devnode != NULL) { ++ sorted[sorted_count].devnode = devnode; ++ sorted[sorted_count].item = item; ++ sorted_count++; ++ } else { ++ udev_device_unref(dev); ++ } ++ } ++ ++ /* Sort the udev entries by devnode name so that they are ++ * created in the proper order */ ++ qsort(sorted, sorted_count, ++ sizeof(struct joypad_udev_entry), sort_devnodes); ++ ++ for (i = 0; i < sorted_count; i++) ++ { ++ const char *name = udev_list_entry_get_name(sorted[i].item); + struct udev_device *dev = udev_device_new_from_syspath(udev_joypad_fd, name); + const char *devnode = udev_device_get_devnode(dev); + diff --git a/packages/games/emulators/retroarch/scripts/retroarch-config b/packages/games/emulators/retroarch/scripts/retroarch-config new file mode 100755 index 000000000..f68676fd1 --- /dev/null +++ b/packages/games/emulators/retroarch/scripts/retroarch-config @@ -0,0 +1,6 @@ +#!/bin/sh + +for i in 5 4 3 2 1 0; do [ -e /dev/snd/pcmC${i}D0p ] && export ALSA_CARD=$i; done + +echo "ALSA_CARD=\"$ALSA_CARD\"" > /run/libreelec/retroarch.conf +echo "LD_LIBRARY_PATH=\"/usr/lib:/tmp/cores\"" >> /run/libreelec/retroarch.conf diff --git a/packages/games/emulators/retroarch/sources/retroarch-core-options.cfg b/packages/games/emulators/retroarch/sources/retroarch-core-options.cfg new file mode 100644 index 000000000..def1535c1 --- /dev/null +++ b/packages/games/emulators/retroarch/sources/retroarch-core-options.cfg @@ -0,0 +1,83 @@ +pcsx_rearmed_analog_axis_modifier = "circle" +pcsx_rearmed_async_cd = "sync" +pcsx_rearmed_bios = "auto" +pcsx_rearmed_display_internal_fps = "disabled" +pcsx_rearmed_dithering = "enabled" +pcsx_rearmed_drc = "enabled" +pcsx_rearmed_duping_enable = "enabled" +pcsx_rearmed_frameskip = "0" +pcsx_rearmed_gteregsunneeded = "disabled" +pcsx_rearmed_gunconadjustratiox = "1" +pcsx_rearmed_gunconadjustratioy = "1" +pcsx_rearmed_gunconadjustx = "0" +pcsx_rearmed_gunconadjusty = "0" +pcsx_rearmed_idiablofix = "disabled" +pcsx_rearmed_input_sensitivity = "1.00" +pcsx_rearmed_inuyasha_fix = "disabled" +pcsx_rearmed_memcard2 = "disabled" +pcsx_rearmed_multitap1 = "auto" +pcsx_rearmed_multitap2 = "auto" +pcsx_rearmed_negcon_deadzone = "0" +pcsx_rearmed_negcon_response = "linear" +pcsx_rearmed_neon_enhancement_enable = "disabled" +pcsx_rearmed_neon_enhancement_no_main = "disabled" +pcsx_rearmed_neon_interlace_enable = "disabled" +pcsx_rearmed_nocdaudio = "enabled" +pcsx_rearmed_nogteflags = "disabled" +pcsx_rearmed_nosmccheck = "disabled" +pcsx_rearmed_noxadecoding = "enabled" +pcsx_rearmed_pad1type = "standard" +pcsx_rearmed_pad2type = "standard" +pcsx_rearmed_pad3type = "none" +pcsx_rearmed_pad4type = "none" +pcsx_rearmed_pad5type = "none" +pcsx_rearmed_pad6type = "none" +pcsx_rearmed_pad7type = "none" +pcsx_rearmed_pad8type = "none" +pcsx_rearmed_pe2_fix = "disabled" +pcsx_rearmed_psxclock = "57" +pcsx_rearmed_region = "auto" +pcsx_rearmed_show_bios_bootlogo = "disabled" +pcsx_rearmed_show_other_input_settings = "disabled" +pcsx_rearmed_spu_interpolation = "simple" +pcsx_rearmed_spu_reverb = "enabled" +pcsx_rearmed_spuirq = "disabled" +pcsx_rearmed_vibration = "enabled" +gambatte_gb_colorization = "disabled" +gambatte_gb_internal_palette = "" +mame2003-plus_analog = "digital" +mame2003-plus_art_resolution = "1" +mame2003-plus_brightness = "1.0" +mame2003-plus_cheat_input_ports = "disabled" +mame2003-plus_core_save_subfolder = "enabled" +mame2003-plus_core_sys_subfolder = "enabled" +mame2003-plus_dcs_speedhack = "enabled" +mame2003-plus_deadzone = "20" +mame2003-plus_digital_joy_centering = "enabled" +mame2003-plus_display_artwork = "enabled" +mame2003-plus_display_setup = "disabled" +mame2003-plus_four_way_emulation = "disabled" +mame2003-plus_frameskip = "0" +mame2003-plus_gamma = "1.0" +mame2003-plus_input_interface = "retropad" +mame2003-plus_machine_timing = "enabled" +mame2003-plus_mame_remapping = "enabled" +mame2003-plus_mouse_device = "mouse" +mame2003-plus_sample_rate = "48000" +mame2003-plus_skip_disclaimer = "disabled" +mame2003-plus_skip_warnings = "disabled" +flycast_internal_resolution = "640x480" +flycast_alpha_sorting = "per-strip (fast, least accurate)" +flycast_enable_dsp = "disabled" +flycast_threaded_rendering = "enabled" +flycast_anisotropic_filtering = "off" +flycast_synchronous_rendering = "enabled" +flycast_enable_rtt = "disabled" +flycast_enable_rttb = "disabled" +flycast_delay_frame_swapping = "disabled" +flycast_div_matching = "auto" +flycast_texupscale = "off" +opera_swi_hle = "enabled" +opera_dsp_threaded = "enabled" +opera_madam_matrix_engine = "software" +puae_deadzone = "25" \ No newline at end of file diff --git a/packages/games/emulators/retroarch/sources/retroarch.cfg b/packages/games/emulators/retroarch/sources/retroarch.cfg new file mode 100644 index 000000000..bdd58302d --- /dev/null +++ b/packages/games/emulators/retroarch/sources/retroarch.cfg @@ -0,0 +1,2743 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_enable = "true" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +ai_service_url = "http://localhost:4404/" +all_users_control_menu = "true" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +aspect_ratio_index = "22" +assets_directory = "/tmp/assets" +audio_block_frames = "0" +audio_device = "" +audio_driver = "alsathread" +audio_dsp_plugin = "" +audio_enable = "true" +audio_enable_menu = "false" +audio_enable_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_fastforward_mute = "false" +audio_filter_dir = "~/.config/retroarch/filters/audio" +audio_latency = "64" +audio_max_timing_skew = "0.049999" +audio_mixer_mute_enable = "false" +audio_mixer_volume = "0.000000" +audio_mute_enable = "false" +audio_out_rate = "48000" +audio_rate_control = "true" +audio_rate_control_delta = "0.004999" +audio_resampler = "sinc" +audio_resampler_quality = "2" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +autosave_interval = "10" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "true" +builtin_mediaplayer_enable = "true" +bundle_assets_dst_path = "" +bundle_assets_dst_path_subdir = "" +bundle_assets_extract_enable = "false" +bundle_assets_extract_last_version = "0" +bundle_assets_extract_version_current = "0" +bundle_assets_src_path = "" +cache_directory = "/tmp/cache" +camera_allow = "false" +camera_device = "" +camera_driver = "null" +cheat_database_path = "/tmp/database/cht" +check_firmware_before_loading = "false" +cheevos_auto_screenshot = "false" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "true" +cheevos_enable = "false" +cheevos_hardcore_mode_enable = "false" +cheevos_leaderboards_enable = "" +cheevos_password = "" +cheevos_richpresence_enable = "true" +cheevos_start_active = "false" +cheevos_test_unofficial = "false" +cheevos_token = "" +cheevos_unlock_sound_enable = "false" +cheevos_username = "" +cheevos_verbose_enable = "false" +config_save_on_exit = "true" +content_database_path = "/tmp/database/rdb" +content_favorites_directory = "default" +content_favorites_path = "~/.config/retroarch/content_favorites.lpl" +content_favorites_size = "200" +content_history_dir = "" +content_history_directory = "default" +content_history_path = "~/.config/retroarch/content_history.lpl" +content_history_size = "200" +content_image_history_directory = "default" +content_image_history_path = "~/.config/retroarch/content_image_history.lpl" +content_music_history_directory = "default" +content_music_history_path = "~/.config/retroarch/content_music_history.lpl" +content_runtime_log = "true" +content_runtime_log_aggregate = "false" +content_show_add = "true" +content_show_add_entry = "2" +content_show_explore = "true" +content_show_favorites = "true" +content_show_history = "true" +content_show_images = "false" +content_show_music = "false" +content_show_netplay = "true" +content_show_playlists = "true" +content_show_settings = "true" +content_show_settings_password = "" +content_show_video = "false" +content_video_directory = "default" +content_video_history_path = "~/.config/retroarch/content_video_history.lpl" +core_assets_directory = "~/roms/downloads" +core_info_cache_enable = "true" +core_option_category_enable = "true" +core_options_path = "" +core_set_supports_no_game_enable = "true" +core_updater_auto_backup = "false" +core_updater_auto_backup_history_size = "1" +core_updater_auto_extract_archive = "true" +core_updater_buildbot_assets_url = "http://buildbot.libretro.com/assets/" +core_updater_buildbot_cores_url = "" +core_updater_buildbot_url = "http://buildbot.libretro.com/nightly/linux/armhf/latest/" +core_updater_show_experimental_cores = "false" +cpu_main_gov = "performance" +cpu_max_freq = "-1" +cpu_menu_gov = "ondemand" +cpu_min_freq = "1" +cpu_scaling_mode = "0" +crt_switch_center_adjust = "0" +crt_switch_hires_menu = "false" +crt_switch_porch_adjust = "0" +crt_switch_resolution = "0" +crt_switch_resolution_super = "2560" +crt_switch_resolution_use_custom_refresh_rate = "false" +crt_switch_timings = "" +crt_video_refresh_rate = "60.000000" +current_resolution_id = "0" +cursor_directory = "~/.config/retroarch/database/cursors" +custom_viewport_height = "1152" +custom_viewport_width = "1536" +custom_viewport_x = "192" +custom_viewport_y = "0" +desktop_menu_enable = "true" +discord_allow = "false" +discord_app_id = "475456035851599874" +driver_switch_enable = "true" +dynamic_wallpapers_directory = "default" +emuelec_exit_to_kodi = "false" +enable_device_vibration = "true" +facebook_stream_key = "" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +fps_show = "false" +fps_update_interval = "256" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +framecount_show = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.500000" +input_audio_mute = "f9" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute_mbtn = "nul" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_autodetect_enable = "true" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus = "t" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "u" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_close_content = "nul" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle = "f5" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle_mbtn = "nul" +input_device_p1 = "0" +input_device_p10 = "0" +input_device_p11 = "0" +input_device_p12 = "0" +input_device_p13 = "0" +input_device_p14 = "0" +input_device_p15 = "0" +input_device_p16 = "0" +input_device_p2 = "0" +input_device_p3 = "0" +input_device_p4 = "0" +input_device_p5 = "0" +input_device_p6 = "0" +input_device_p7 = "0" +input_device_p8 = "0" +input_device_p9 = "0" +input_disk_eject_toggle = "nul" +input_disk_eject_toggle_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_next = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_prev = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_driver = "udev" +input_duty_cycle = "3" +input_enable_hotkey = "nul" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "nul" +input_enable_hotkey_mbtn = "nul" +input_exit_emulator = "escape" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "nul" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "f3" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "k" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p1 = "1" +input_libretro_device_p10 = "1" +input_libretro_device_p11 = "1" +input_libretro_device_p12 = "1" +input_libretro_device_p13 = "1" +input_libretro_device_p14 = "1" +input_libretro_device_p15 = "1" +input_libretro_device_p16 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_libretro_device_p6 = "1" +input_libretro_device_p7 = "1" +input_libretro_device_p8 = "1" +input_libretro_device_p9 = "1" +input_load_state = "f4" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "f1" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "2" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_toggle = "f12" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle_mbtn = "nul" +input_overlay = "" +input_overlay_aspect_adjust_landscape = "0.000000" +input_overlay_aspect_adjust_portrait = "0.000000" +input_overlay_auto_rotate = "false" +input_overlay_auto_scale = "false" +input_overlay_enable = "true" +input_overlay_enable_autopreferred = "true" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next = "nul" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_opacity = "0.700000" +input_overlay_scale_landscape = "1.000000" +input_overlay_scale_portrait = "1.000000" +input_overlay_show_inputs = "2" +input_overlay_show_inputs_port = "0" +input_overlay_show_mouse_cursor = "true" +input_overlay_x_offset_landscape = "0.000000" +input_overlay_x_offset_portrait = "0.000000" +input_overlay_x_separation_landscape = "0.000000" +input_overlay_x_separation_portrait = "0.000000" +input_overlay_y_offset_landscape = "0.000000" +input_overlay_y_offset_portrait = "0.000000" +input_overlay_y_separation_landscape = "0.000000" +input_overlay_y_separation_portrait = "0.000000" +input_pause_toggle = "p" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle = "nul" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/remappings" +input_reset = "h" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "r" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "100" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "f2" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "f8" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot_mbtn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next = "m" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "n" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "subtract" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "add" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +joypad_autoconfig_dir = "/tmp/joypads" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_directory = "/tmp/cores" +libretro_info_path = "/tmp/cores" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "false" +log_to_file_timestamp = "false" +log_verbosity = "true" +materialui_auto_rotate_nav_bar = "true" +materialui_dual_thumbnail_list_view_enable = "true" +materialui_icons_enable = "true" +materialui_landscape_layout_optimization = "1" +materialui_menu_color_theme = "9" +materialui_menu_transition_animation = "0" +materialui_playlist_icons_enable = "true" +materialui_show_nav_bar = "true" +materialui_thumbnail_background_enable = "true" +materialui_thumbnail_view_landscape = "2" +materialui_thumbnail_view_portrait = "1" +memory_show = "false" +memory_update_interval = "256" +menu_battery_level_enable = "true" +menu_core_enable = "true" +menu_driver = "xmb" +menu_dynamic_wallpaper_enable = "false" +menu_enable_widgets = "true" +menu_font_color_blue = "255" +menu_font_color_green = "255" +menu_font_color_red = "255" +menu_footer_opacity = "1.000000" +menu_framebuffer_opacity = "0.899999" +menu_header_opacity = "1.000000" +menu_horizontal_animation = "true" +menu_insert_disk_resume = "true" +menu_left_thumbnails = "0" +menu_linear_filter = "false" +menu_mouse_enable = "false" +menu_navigation_browser_filter_supported_extensions_enable = "true" +menu_navigation_wraparound_enable = "true" +menu_pause_libretro = "true" +menu_pointer_enable = "false" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "0.750000" +menu_screensaver_animation = "0" +menu_screensaver_animation_speed = "1.000000" +menu_screensaver_timeout = "0" +menu_scroll_delay = "256" +menu_scroll_fast = "false" +menu_shader_pipeline = "2" +menu_show_advanced_settings = "true" +menu_show_configurations = "true" +menu_show_core_updater = "false" +menu_show_dump_disc = "true" +menu_show_help = "true" +menu_show_information = "true" +menu_show_latency = "true" +menu_show_legacy_thumbnail_updater = "false" +menu_show_load_content = "true" +menu_show_load_content_animation = "false" +menu_show_load_core = "true" +menu_show_load_disc = "true" +menu_show_online_updater = "true" +menu_show_overlays = "true" +menu_show_quit_retroarch = "true" +menu_show_reboot = "false" +menu_show_restart_retroarch = "true" +menu_show_rewind = "true" +menu_show_shutdown = "false" +menu_show_sublabels = "true" +menu_show_video_layout = "true" +menu_swap_ok_cancel_buttons = "false" +menu_throttle_framerate = "true" +menu_thumbnail_upscale_threshold = "0" +menu_thumbnails = "3" +menu_ticker_smooth = "true" +menu_ticker_speed = "2.000000" +menu_ticker_type = "1" +menu_timedate_date_separator = "0" +menu_timedate_enable = "true" +menu_timedate_style = "11" +menu_unified_controls = "false" +menu_use_preferred_system_color_theme = "false" +menu_wallpaper = "" +menu_wallpaper_opacity = "1.000000" +menu_widget_scale_auto = "false" +menu_widget_scale_factor = "1.000000" +menu_widget_scale_factor_windowed = "1.000000" +menu_xmb_animation_horizontal_highlight = "0" +menu_xmb_animation_move_up_down = "0" +menu_xmb_animation_opening_main_menu = "0" +menu_xmb_thumbnail_scale_factor = "100" +midi_driver = "alsa" +midi_input = "Off" +midi_output = "Off" +midi_volume = "100" +netplay_allow_slaves = "true" +netplay_check_frames = "600" +netplay_input_latency_frames_min = "0" +netplay_input_latency_frames_range = "0" +netplay_ip_address = "" +netplay_ip_port = "55435" +netplay_max_connections = "3" +netplay_mitm_server = "nyc" +netplay_nat_traversal = "true" +netplay_nickname = "" +netplay_password = "" +netplay_public_announce = "true" +netplay_request_device_p1 = "false" +netplay_request_device_p10 = "false" +netplay_request_device_p11 = "false" +netplay_request_device_p12 = "false" +netplay_request_device_p13 = "false" +netplay_request_device_p14 = "false" +netplay_request_device_p15 = "false" +netplay_request_device_p16 = "false" +netplay_request_device_p2 = "false" +netplay_request_device_p3 = "false" +netplay_request_device_p4 = "false" +netplay_request_device_p5 = "false" +netplay_request_device_p6 = "false" +netplay_request_device_p7 = "false" +netplay_request_device_p8 = "false" +netplay_request_device_p9 = "false" +netplay_require_slaves = "false" +netplay_share_analog = "1" +netplay_share_digital = "1" +netplay_spectate_password = "" +netplay_start_as_spectator = "false" +netplay_stateless_mode = "false" +netplay_use_mitm_server = "false" +network_cmd_enable = "false" +network_cmd_port = "55355" +network_on_demand_thumbnails = "false" +network_remote_base_port = "55400" +network_remote_enable = "false" +network_remote_enable_user_p1 = "false" +network_remote_enable_user_p10 = "false" +network_remote_enable_user_p11 = "false" +network_remote_enable_user_p12 = "false" +network_remote_enable_user_p13 = "false" +network_remote_enable_user_p14 = "false" +network_remote_enable_user_p15 = "false" +network_remote_enable_user_p16 = "false" +network_remote_enable_user_p2 = "false" +network_remote_enable_user_p3 = "false" +network_remote_enable_user_p4 = "false" +network_remote_enable_user_p5 = "false" +network_remote_enable_user_p6 = "false" +network_remote_enable_user_p7 = "false" +network_remote_enable_user_p8 = "false" +network_remote_enable_user_p9 = "false" +notification_show_autoconfig = "false" +notification_show_cheats_applied = "true" +notification_show_config_override_load = "false" +notification_show_fast_forward = "true" +notification_show_netplay_extra = "false" +notification_show_patch_applied = "true" +notification_show_refresh_rate = "true" +notification_show_remap_load = "false" +notification_show_screenshot = "false" +notification_show_screenshot_duration = "2" +notification_show_screenshot_flash = "1" +notification_show_set_initial_disk = "true" +overlay_directory = "/tmp/overlays" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_cores = "/tmp/cores/stella_libretro.so;/tmp/cores/atari800_libretro.so;/tmp/cores/prosystem_libretro.so;/tmp/cores/virtualjaguar_libretro.so;/tmp/cores/handy_libretro.so;/tmp/cores/hatari_libretro.so;/tmp/cores/beetle_wswan_libretro.so;/tmp/cores/beetle_wswan_libretro.so;/tmp/cores/nxengine_libretro.so;/tmp/cores/chailove_libretro.so;/tmp/cores/bluemsx_libretro.so;/tmp/cores/vice_x64_libretro.so;/tmp/cores/vice_x64_libretro.so;/tmp/cores/vice_x64_libretro.so;/tmp/cores/puae_libretro.so;/tmp/cores/vice_xplus4_libretro.so;/tmp/cores/vice_xvic_libretro.so;/tmp/cores/dinothawr_libretro.so;/tmp/cores/prboom_libretro.so;/tmp/cores/dosbox_libretro.so;/tmp/cores/fbneo_libretro.so;/tmp/cores/reminiscence_libretro.so;/tmp/cores/vecx_libretro.so;/tmp/cores/lutro_libretro.so;/tmp/cores/o2em_libretro.so;/tmp/cores/mame2003_plus_libretro.so;/tmp/cores/mame2010_libretro.so;/tmp/cores/freeintv_libretro.so;/tmp/cores/bluemsx_libretro.so;/tmp/cores/bluemsx_libretro.so;/tmp/cores/beetle_supergrafx_libretro.so;/tmp/cores/beetle_pce_fast_libretro.so;/tmp/cores/nestopia_libretro.so;/tmp/cores/mgba_libretro.so;/tmp/cores/mgba_libretro.so;/tmp/cores/gambatte_libretro.so;/tmp/cores/gambatte_libretro.so;/tmp/cores/dolphin_libretro.so;/tmp/cores/citra_libretro.so;/tmp/cores/parallel_n64_libretro.so;/tmp/cores/desmume_libretro.so;/tmp/cores/desmume_libretro.so;/tmp/cores/desmume_libretro.so;/tmp/cores/desmume_libretro.so;/tmp/cores/desmume_libretro.so;/tmp/cores/nestopia_libretro.so;/tmp/cores/snes9x2010_libretro.so;/tmp/cores/snes9x2010_libretro.so;/tmp/cores/beetle_vb_libretro.so;/tmp/cores/dolphin_libretro.so;/tmp/cores/pokemini_libretro.so;/tmp/cores/tyrquake_libretro.so;/tmp/cores/scummvm_libretro.so;/tmp/cores/picodrive_libretro.so;/tmp/cores/flycast_libretro.so;/tmp/cores/genesis_plus_gx_libretro.so;/tmp/cores/genesis_plus_gx_libretro.so;/tmp/cores/genesis_plus_gx_libretro.so;/tmp/cores/picodrive_libretro.so;/tmp/cores/genesis_plus_gx_libretro.so;/tmp/cores/yabause_libretro.so;/tmp/cores/fuse_libretro.so;/tmp/cores/beetle_ngp_libretro.so;/tmp/cores/beetle_ngp_libretro.so;/tmp/cores/play_libretro.so;/tmp/cores/ppsspp_libretro.so;/tmp/cores/pcsx_rearmed_libretro.so;/tmp/cores/theodore_libretro.so;/tmp/cores/tic80_libretro.so;/tmp/cores/4do_libretro.so" +playlist_directory = "~/playlists" +playlist_entry_remove = "false" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "false" +playlist_fuzzy_archive_match = "false" +playlist_names = "Atari - 2600.lpl;Atari - 5200.lpl;Atari - 7800.lpl;Atari - Jaguar.lpl;Atari - Lynx.lpl;Atari - ST.lpl;Bandai - WonderSwan Color.lpl;Bandai - WonderSwan.lpl;Cave Story.lpl;ChaiLove.lpl;Coleco - ColecoVision.lpl;Commodore - 64 (PP).lpl;Commodore - 64 (Tapes).lpl;Commodore - 64.lpl;Commodore - Amiga.lpl;Commodore - Plus-4.lpl;Commodore - VIC20.lpl;Dinothawr.lpl;DOOM.lpl;DOS.lpl;FBNeo - Arcade Games.lpl;Flashback.lpl;GCE - Vectrex.lpl;Lutro.lpl;Magnavox - Odyssey2.lpl;MAME 2003-Plus.lpl;MAME 2010.lpl;Mattel - Intellivision.lpl;Microsoft - MSX2.lpl;Microsoft - MSX.lpl;NEC - PC Engine SuperGrafx.lpl;NEC - PC Engine - TurboGrafx 16.lpl;Nintendo - Famicom Disk System.lpl;Nintendo - Game Boy Advance (e-Cards).lpl;Nintendo - Game Boy Advance.lpl;Nintendo - Game Boy Color.lpl;Nintendo - Game Boy.lpl;Nintendo - GameCube.lpl;Nintendo - Nintendo 3DS.lpl;Nintendo - Nintendo 64.lpl;Nintendo - Nintendo DS.lpl;Nintendo - Nintendo DS Decrypted.lpl;Nintendo - Nintendo DS (Download Play) (BETA).lpl;Nintendo - Nintendo DSi Decrypted.lpl;Nintendo - Nintendo DSi (DLC).lpl;Nintendo - Nintendo Entertainment System.lpl;Nintendo - Satellaview.lpl;Nintendo - Super Nintendo Entertainment System.lpl;Nintendo - Virtual Boy.lpl;Nintendo - Wii.lpl;Nintendo - Pokemon Mini (PokeMini).lpl;Quake.lpl;ScummVM.lpl;Sega - 32X.lpl;Sega - Dreamcast.lpl;Sega - Game Gear.lpl;Sega - Master System - Mark III.lpl;Sega - Mega Drive - Genesis.lpl;Sega - PICO.lpl;Sega - SG-1000.lpl;Sega - Saturn.lpl;Sinclair - ZX Spectrum +3.lpl;SNK - Neo Geo Pocket Color.lpl;SNK - Neo Geo Pocket.lpl;Sony - PlayStation 2.lpl;Sony - PlayStation Portable.lpl;Sony - PlayStation.lpl;Thomson - MOTO.lpl;TIC-80.lpl;The 3DO Company - 3DO.lpl" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_inline_core_name = "0" +playlist_show_sublabels = "true" +playlist_sort_alphabetical = "true" +playlist_sublabel_last_played_style = "0" +playlist_sublabel_runtime_type = "0" +playlist_use_old_format = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_cheats = "true" +quick_menu_show_close_content = "true" +quick_menu_show_controls = "true" +quick_menu_show_core_options_flush = "false" +quick_menu_show_download_thumbnails = "true" +quick_menu_show_information = "true" +quick_menu_show_options = "true" +quick_menu_show_recording = "true" +quick_menu_show_reset_core_association = "true" +quick_menu_show_restart_content = "true" +quick_menu_show_resume_content = "true" +quick_menu_show_save_content_dir_overrides = "true" +quick_menu_show_save_core_overrides = "false" +quick_menu_show_save_game_overrides = "false" +quick_menu_show_save_load_state = "true" +quick_menu_show_set_core_association = "true" +quick_menu_show_shaders = "true" +quick_menu_show_start_recording = "true" +quick_menu_show_start_streaming = "true" +quick_menu_show_streaming = "true" +quick_menu_show_take_screenshot = "true" +quick_menu_show_undo_save_load_state = "false" +quit_on_close_content = "0" +quit_press_twice = "true" +record_driver = "null" +recording_config_directory = "" +recording_output_directory = "~/roms/screenshots" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +rewind_enable = "false" +rewind_granularity = "1" +rgui_aspect_ratio = "0" +rgui_aspect_ratio_lock = "0" +rgui_background_filler_thickness_enable = "true" +rgui_border_filler_enable = "true" +rgui_border_filler_thickness_enable = "true" +rgui_browser_directory = "~/roms" +rgui_config_directory = "~/.config/retroarch/config" +rgui_extended_ascii = "false" +rgui_inline_thumbnails = "false" +rgui_internal_upscale_level = "0" +rgui_menu_color_theme = "4" +rgui_menu_theme_preset = "" +rgui_particle_effect = "0" +rgui_particle_effect_screensaver = "true" +rgui_particle_effect_speed = "1.000000" +rgui_show_start_screen = "false" +rgui_swap_thumbnails = "false" +rgui_switch_icons = "true" +rgui_thumbnail_delay = "0" +rgui_thumbnail_downscaler = "0" +run_ahead_enabled = "false" +run_ahead_frames = "1" +run_ahead_hide_warnings = "false" +run_ahead_secondary_instance = "true" +runtime_log_directory = "default" +save_file_compression = "false" +savefile_directory = "~/.config/retroarch/saves" +savefiles_in_content_dir = "true" +savestate_auto_index = "false" +savestate_auto_load = "false" +savestate_auto_save = "false" +savestate_directory = "~/.config/retroarch/states" +savestate_file_compression = "true" +savestate_max_keep = "0" +savestate_thumbnail_enable = "true" +savestates_in_content_dir = "false" +scan_without_core_match = "false" +screen_brightness = "100" +screen_orientation = "0" +screenshot_directory = "~/roms/screenshots" +screenshots_in_content_dir = "false" +settings_show_accessibility = "true" +settings_show_achievements = "true" +settings_show_ai_service = "true" +settings_show_audio = "true" +settings_show_configuration = "true" +settings_show_core = "true" +settings_show_directory = "true" +settings_show_drivers = "true" +settings_show_file_browser = "true" +settings_show_frame_throttle = "true" +settings_show_input = "true" +settings_show_latency = "true" +settings_show_logging = "true" +settings_show_network = "true" +settings_show_onscreen_display = "true" +settings_show_playlists = "true" +settings_show_power_management = "true" +settings_show_recording = "true" +settings_show_saving = "true" +settings_show_user = "true" +settings_show_user_interface = "true" +settings_show_video = "true" +show_hidden_files = "false" +slowmotion_ratio = "3.000000" +soft_filter_enable = "false" +soft_filter_index = "0" +sort_savefiles_by_content_enable = "false" +sort_savefiles_enable = "false" +sort_savestates_by_content_enable = "false" +sort_savestates_enable = "false" +sort_screenshots_by_content_enable = "false" +state_slot = "0" +statistics_show = "false" +stdin_cmd_enable = "false" +streaming_mode = "0" +suspend_screensaver_enable = "true" +sustained_performance_mode = "false" +system_directory = "~/roms/bios" +systemfiles_in_content_dir = "false" +threaded_data_runloop_enable = "true" +thumbnails_directory = "~/thumbnails" +twitch_stream_key = "" +ui_companion_enable = "false" +ui_companion_start_on_boot = "true" +ui_companion_toggle = "false" +ui_menubar_enable = "true" +use_last_start_directory = "false" +user_language = "0" +vibrate_on_keypress = "true" +video_adaptive_vsync = "false" +video_allow_rotate = "true" +video_aspect_ratio = "-1.000000" +video_aspect_ratio_auto = "true" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_ctx_scaling = "false" +video_disable_composition = "false" +video_driver = "gl" +video_filter = "" +video_filter_dir = "~/.config/retroarch/filters/video" +video_font_enable = "true" +video_font_path = "/usr/share/retroarch-assets/xmb/monochrome/font.ttf" +video_font_size = "32.000000" +video_force_aspect = "true" +video_force_srgb_disable = "false" +video_frame_delay = "0" +video_frame_delay_auto = "false" +video_fullscreen = "true" +video_fullscreen_x = "0" +video_fullscreen_y = "0" +video_gpu_record = "false" +video_gpu_screenshot = "false" +video_hard_sync = "false" +video_hard_sync_frames = "0" +video_hdr_display_contrast = "5.000000" +video_hdr_enable = "false" +video_hdr_expand_gamut = "true" +video_hdr_max_nits = "1000.000000" +video_hdr_paper_white_nits = "200.000000" +video_layout_directory = "~/.config/retroarch/layouts" +video_layout_enable = "true" +video_layout_path = "" +video_layout_selected_view = "0" +video_max_swapchain_images = "3" +video_message_color = "ffff00" +video_message_pos_x = "0.049999" +video_message_pos_y = "0.049999" +video_monitor_index = "0" +video_msg_bgcolor_blue = "0" +video_msg_bgcolor_enable = "false" +video_msg_bgcolor_green = "0" +video_msg_bgcolor_opacity = "1.000000" +video_msg_bgcolor_red = "0" +video_notch_write_over_enable = "false" +video_oga_vertical_enable = "false" +video_post_filter_record = "false" +video_record_config = "" +video_record_quality = "4" +video_record_scale_factor = "1" +video_record_threads = "2" +video_refresh_rate = "60.000000" +video_rotation = "0" +video_scale = "3.000000" +video_scale_integer = "false" +video_scale_integer_overscale = "false" +video_shader_delay = "0" +video_shader_dir = "/tmp/shaders" +video_shader_enable = "false" +video_shader_preset_save_reference_enable = "true" +video_shader_remember_last_dir = "false" +video_shader_watch_files = "false" +video_shared_context = "false" +video_smooth = "false" +video_stream_config = "" +video_stream_port = "56400" +video_stream_quality = "10" +video_stream_scale_factor = "1" +video_stream_url = "" +video_swap_interval = "1" +video_threaded = "true" +video_vsync = "true" +video_window_auto_height_max = "1080" +video_window_auto_width_max = "1920" +video_window_custom_size_enable = "false" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +vrr_runloop_enable = "true" +wifi_driver = "null" +wifi_enabled = "true" +xmb_alpha_factor = "75" +xmb_font = "/usr/share/retroarch-assets/xmb/monochrome/font.ttf" +xmb_layout = "2" +xmb_menu_color_theme = "4" +xmb_shadows_enable = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" diff --git a/packages/games/emulators/retroarch/sources/retroarch32bit-append.cfg b/packages/games/emulators/retroarch/sources/retroarch32bit-append.cfg new file mode 100644 index 000000000..be5d55d5b --- /dev/null +++ b/packages/games/emulators/retroarch/sources/retroarch32bit-append.cfg @@ -0,0 +1,2 @@ +audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/32bit/video" \ No newline at end of file diff --git a/packages/games/emulators/retroarch/sources/retroarch64bit-append.cfg b/packages/games/emulators/retroarch/sources/retroarch64bit-append.cfg new file mode 100644 index 000000000..a2277a382 --- /dev/null +++ b/packages/games/emulators/retroarch/sources/retroarch64bit-append.cfg @@ -0,0 +1,2 @@ +audio_filter_dir = "/usr/share/retroarch/filters/64bit/audio" +video_filter_dir = "/usr/share/retroarch/filters/64bit/video" \ No newline at end of file diff --git a/packages/games/emulators/retroarch/system.d/retroarch.service b/packages/games/emulators/retroarch/system.d/retroarch.service new file mode 100644 index 000000000..3712274e4 --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/retroarch.service @@ -0,0 +1,19 @@ +[Unit] +Description=RetroArch emulator frontend +ConditionPathExists=/var/lock/start.retro + +[Service] +Environment=DISPLAY=:0.0 +Environment=SDL_MOUSE_RELATIVE=0 +Environment=FB_MULTI_BUFFER=2 +Environment=HOME=/storage +ExecStartPre=/usr/bin/emustation-config retroarch +ExecStart=/usr/bin/retroarch +KillMode=process +TimeoutStopSec=3 +Restart=on-failure +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-assets.mount b/packages/games/emulators/retroarch/system.d/tmp-assets.mount new file mode 100644 index 000000000..ed984ed0f --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-assets.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Assets directory +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/assets +Type=overlay +Options=lowerdir=/usr/share/retroarch-assets,upperdir=/storage/assets,workdir=/storage/.tmp/assets-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-cores.mount b/packages/games/emulators/retroarch/system.d/tmp-cores.mount new file mode 100644 index 000000000..bff71017c --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-cores.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Cores directory +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/cores +Type=overlay +Options=lowerdir=/usr/lib/libretro,upperdir=/storage/cores,workdir=/storage/.tmp/cores-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-database.mount b/packages/games/emulators/retroarch/system.d/tmp-database.mount new file mode 100644 index 000000000..98452fd57 --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-database.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Database directory +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/database +Type=overlay +Options=lowerdir=/usr/share/libretro-database,upperdir=/storage/database,workdir=/storage/.tmp/database-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-joypads.mount b/packages/games/emulators/retroarch/system.d/tmp-joypads.mount new file mode 100644 index 000000000..b828ebd3d --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-joypads.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Joypad configs directory +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/joypads +Type=overlay +Options=lowerdir=/etc/retroarch-joypad-autoconfig,upperdir=/storage/joypads,workdir=/storage/.tmp/joypads-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-overlays.mount b/packages/games/emulators/retroarch/system.d/tmp-overlays.mount new file mode 100644 index 000000000..e9d270623 --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-overlays.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Overlays directory +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/overlays +Type=overlay +Options=lowerdir=/usr/share/retroarch-overlays,upperdir=/storage/overlays,workdir=/storage/.tmp/overlays-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/system.d/tmp-shaders.mount b/packages/games/emulators/retroarch/system.d/tmp-shaders.mount new file mode 100644 index 000000000..ddd80238b --- /dev/null +++ b/packages/games/emulators/retroarch/system.d/tmp-shaders.mount @@ -0,0 +1,13 @@ +[Unit] +Description=Shaders directory RetroArch +After=systemd-tmpfiles-setup.service +DefaultDependencies=no + +[Mount] +What=none +Where=/tmp/shaders +Type=overlay +Options=lowerdir=/usr/share/common-shaders,upperdir=/storage/shaders,workdir=/storage/.tmp/shaders-workdir + +[Install] +WantedBy=jelos.target diff --git a/packages/games/emulators/retroarch/tmpfiles.d/retroarch-userdirs.conf b/packages/games/emulators/retroarch/tmpfiles.d/retroarch-userdirs.conf new file mode 100644 index 000000000..1a40a9ea2 --- /dev/null +++ b/packages/games/emulators/retroarch/tmpfiles.d/retroarch-userdirs.conf @@ -0,0 +1,32 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 2 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +d /storage/assets 0777 root root - - +d /storage/cores 0777 root root - - +d /storage/database 0777 root root - - +d /storage/joypads 0777 root root - - +d /storage/overlays 0777 root root - - +d /storage/remappings 0777 root root - - +d /storage/shaders 0777 root root - - + +d /storage/.tmp/cores-workdir 0777 root root - - +d /storage/.tmp/joypads-workdir 0777 root root - - +d /storage/.tmp/database-workdir 0777 root root - - +d /storage/.tmp/assets-workdir 0777 root root - - +d /storage/.tmp/overlays-workdir 0777 root root - - +d /storage/.tmp/shaders-workdir 0777 root root - - diff --git a/packages/games/emulators/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules b/packages/games/emulators/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules new file mode 100644 index 000000000..45594b13d --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-8bitdo-bluetooth-controllers.rules @@ -0,0 +1,43 @@ +# Add the ID_INPUT_JOYSTICK attribute to the device so SDL picks up on it + +# 8Bitdo FC30 1P GamePad Bluetooth mode(START) mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo FC30 GamePad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo FC30 2P GamePad Bluetooth mode(START) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo FC30 II", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo FC30 2P GamePad Bluetooth mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo FC30 II Joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo SFC30 GamePad Bluetooth mode(START) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo SFC30 GamePad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo SFC30 GamePad Bluetooth mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo SFC30 GamePad Joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo NES30 GamePad Bluetooth mode(START) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo NES30 GamePad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo NES30 GamePad Bluetooth mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo NES30 GamePad Joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo SNES30 GamePad Bluetooth mode(START) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo SNES30 GamePad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo SNES30 GamePad Bluetooth mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo SNES30 GamePad Joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo FC30 Pro GamePad Bluetooth mode(POWER) mode(POWER+R1) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo FC30 Pro", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo NES30 Pro GamePad Bluetooth mode(POWER) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo NES30 Pro", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo NES30 Pro GamePad Bluetooth mode(POWER+R1) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo NES30 Pro Joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo FC30 Arcade Joystick Bluetooth mode(HOME) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo Joy", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# 8Bitdo Zero GamePad Bluetooth mode(START) mode(START+R) +SUBSYSTEM=="input", ATTRS{name}=="8Bitdo Zero GamePad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-ION-iCade-bluetooth.rules b/packages/games/emulators/retroarch/udev.d/99-ION-iCade-bluetooth.rules new file mode 100644 index 000000000..a25b646dc --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-ION-iCade-bluetooth.rules @@ -0,0 +1 @@ +SUBSYSTEM=="input", ATTRS{name}=="ION iCade", KERNEL=="event*", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-bluetooth-power-on.rules b/packages/games/emulators/retroarch/udev.d/99-bluetooth-power-on.rules new file mode 100644 index 000000000..8800f3b24 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-bluetooth-power-on.rules @@ -0,0 +1 @@ +ACTION=="add", KERNEL=="hci0", RUN+="/usr/bin/hciconfig hci0 up" diff --git a/packages/games/emulators/retroarch/udev.d/99-evdev.rules b/packages/games/emulators/retroarch/udev.d/99-evdev.rules new file mode 100644 index 000000000..3d972f20d --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-evdev.rules @@ -0,0 +1,2 @@ +# Needed for permissions set correctly for /dev/input/event* for keyboard input +SUBSYSTEM=="input", ATTRS{name}=="input/%k", KERNEL=="event*", MODE="0666", ENV{ID_INPUT_KEYBOARD}="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-gen-game-s3-controller.rules b/packages/games/emulators/retroarch/udev.d/99-gen-game-s3-controller.rules new file mode 100644 index 000000000..66b6a0ac6 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-gen-game-s3-controller.rules @@ -0,0 +1 @@ +SUBSYSTEM=="input", ATTRS{name}=="GEN GAME S3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1", ENV{ID_INPUT_MOUSE}="", ENV{ID_INPUT_KEYBOARD}="" diff --git a/packages/games/emulators/retroarch/udev.d/99-juyao-dual-arcade.rules b/packages/games/emulators/retroarch/udev.d/99-juyao-dual-arcade.rules new file mode 100644 index 000000000..979d585d3 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-juyao-dual-arcade.rules @@ -0,0 +1,2 @@ +# Needed for device Juyao dual arcade (Bus 002 Device 007: ID 0314:0328) +ATTRS{product}=="JUYAO Dual Arcade",ACTION=="add",ENV{ID_INPUT_TABLET}="0",ENV{ID_INPUT_JOYSTICK}:="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-nintendo-wii-remote.rules b/packages/games/emulators/retroarch/udev.d/99-nintendo-wii-remote.rules new file mode 100644 index 000000000..f07b27200 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-nintendo-wii-remote.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="input", ATTRS{name}=="Nintendo Wii Remote", MODE="666", ENV{ID_INPUT_JOYSTICK}="1" +SUBSYSTEM=="input", ATTRS{name}=="Nintendo Wii Remote Classic Controller", MODE="666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-ninteno-wii-remote.rules b/packages/games/emulators/retroarch/udev.d/99-ninteno-wii-remote.rules new file mode 100644 index 000000000..f07b27200 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-ninteno-wii-remote.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="input", ATTRS{name}=="Nintendo Wii Remote", MODE="666", ENV{ID_INPUT_JOYSTICK}="1" +SUBSYSTEM=="input", ATTRS{name}=="Nintendo Wii Remote Classic Controller", MODE="666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/packages/games/emulators/retroarch/udev.d/99-nv-shield-controller.rules b/packages/games/emulators/retroarch/udev.d/99-nv-shield-controller.rules new file mode 100644 index 000000000..f5b679f7b --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-nv-shield-controller.rules @@ -0,0 +1 @@ +SUBSYSTEM=="input", ATTRS{idVendor}=="0955", ATTRS{idProduct}=="7210", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1", ENV{ID_INPUT_MOUSE}="" diff --git a/packages/games/emulators/retroarch/udev.d/99-ouya-controller.rules b/packages/games/emulators/retroarch/udev.d/99-ouya-controller.rules new file mode 100644 index 000000000..55a0949d9 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-ouya-controller.rules @@ -0,0 +1 @@ +SUBSYSTEM=="input", ATTRS{name}=="OUYA Game Controller", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1", ENV{ID_INPUT_MOUSE}="" diff --git a/packages/games/emulators/retroarch/udev.d/99-terios-t3.rules b/packages/games/emulators/retroarch/udev.d/99-terios-t3.rules new file mode 100644 index 000000000..32d169289 --- /dev/null +++ b/packages/games/emulators/retroarch/udev.d/99-terios-t3.rules @@ -0,0 +1,2 @@ +# Needed for device Terios T3 (1949:0402) +SUBSYSTEM=="input", ATTRS{name}=="Gamepad", KERNEL=="event*", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/packages/games/emulators/scummvmsa/bin/scummvm.start b/packages/games/emulators/scummvmsa/bin/scummvm.start new file mode 100644 index 000000000..5d6656afc --- /dev/null +++ b/packages/games/emulators/scummvmsa/bin/scummvm.start @@ -0,0 +1,64 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +# Source predefined functions and variables +. /etc/profile + +CONFIG_DIR="/storage/.config/scummvm" +ROMSPATH="/storage/roms" +BIOSPATH="${ROMSPATH}/bios" +GAME=$2 +RATMPCONF="/storage/.config/retroarch/retroarch.cfg" + +if [ ! -d "${CONFIG_DIR}/games" ] +then + mkdir -p "${CONFIG_DIR}/games" +fi + +create_svm(){ + /usr/bin/scummvm --list-targets | tail -n +4 | cut -d " " -f 1 | \ + while read line + do + id=($line); + filename=$(grep -A7 "\[$id\]" ${CONFIG_DIR}/scummvm.ini | \ + awk 'BEGIN {FS="="}; /description/ {printf $2}' | \ + sed -e 's# (.*)# ('${id}')#g' -e "s#'##g" -e "s#: # - #g" \ + ) + + SVMPATH="$(grep -A7 "\[$id\]" ${CONFIG_DIR}/scummvm.ini | awk 'BEGIN {FS="="}; /path/ {print $2}')" + echo '--path="'${SVMPATH}'" '${id} >"${CONFIG_DIR}/games/${filename}.scummvm" + done +} + +if [ ! -d "$CONFIG_DIR" ]; then + mkdir -p $CONFIG_DIR + cp -rf /usr/config/scummvm/* $CONFIG_DIR/ +fi + +case $1 in + "sa") + set_audio "fluidsynth" + GAME=$(cat "${GAME}") + eval /usr/bin/scummvm --fullscreen --joystick=0 ${GAME} + set_audio "pulseaudio" + ;; + + "libretro") + GAME=$(cat "${GAME}" | awk 'BEGIN {FS="\""}; {print $2}') + cd "${GAME}" + /usr/bin/retroarch -L /tmp/cores/scummvm_libretro.so --config ${RATMPCONF} . + ;; + + "add") + /usr/bin/scummvm --add --path="${ROMSPATH}/scummvm" --recursive + mkdir -p ${BIOSPATH} + cp $CONFIG_DIR/scummvm.ini ${BIOSPATH}/scummvm.ini + ;; + + "create") + create_svm + ;; + +esac diff --git a/packages/games/emulators/scummvmsa/config/games/_Scan ScummVM Games.sh b/packages/games/emulators/scummvmsa/config/games/_Scan ScummVM Games.sh new file mode 100644 index 000000000..2be753726 --- /dev/null +++ b/packages/games/emulators/scummvmsa/config/games/_Scan ScummVM Games.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +EE_DEVICE=$(cat /ee_arch) + +source /usr/bin/env.sh +. /etc/profile + +rp_registerAllModules + +joy2keyStart +ear >/dev/console +message_stream "Scanning for games...\n" 0 +bash /usr/bin/scummvm.start add +message_stream "Adding games...\n" 0 +bash /usr/bin/scummvm.start create +message_stream "Restarting EmulationStation...\n" 0 +systemctl restart emustation +clear >/dev/console diff --git a/packages/games/emulators/scummvmsa/config/scummvm.ini b/packages/games/emulators/scummvmsa/config/scummvm.ini new file mode 100644 index 000000000..a4a10416a --- /dev/null +++ b/packages/games/emulators/scummvmsa/config/scummvm.ini @@ -0,0 +1,20 @@ +[scummvm] +gui_browser_show_hidden=true +browser_lastpath=/storage/roms/scummvm +gm_device=fluidsynth +fullscreen=true +soundfont=/storage/.config/fluidsynth/soundfonts/GeneralUser.sf2 +fluidsynth_chorus_speed=30 +fluidsynth_chorus_depth=80 +fluidsynth_reverb_roomsize=20 +fluidsynth_reverb_activate=true +fluidsynth_reverb_damping=0 +fluidsynth_reverb_width=1 +fluidsynth_misc_interpolation=4th +fluidsynth_chorus_waveform=sine +fluidsynth_reverb_level=90 +fluidsynth_chorus_nr=3 +fluidsynth_chorus_level=100 +fluidsynth_chorus_activate=true +music_driver=auto +gfx_mode=opengl diff --git a/packages/games/emulators/scummvmsa/package.mk b/packages/games/emulators/scummvmsa/package.mk new file mode 100644 index 000000000..34a991372 --- /dev/null +++ b/packages/games/emulators/scummvmsa/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="scummvmsa" +PKG_VERSION="6d8672bec9400414a49d2005e6b10ea17be9def2" +PKG_SHA256="d8093d863fad50622e7fd6c3d6bcd5433268bd9cef5001c3b6222d5345e363cc" +PKG_REV="1" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/scummvm/scummvm" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_net freetype fluidsynth-git" +PKG_SHORTDESC="Script Creation Utility for Maniac Mansion Virtual Machine" +PKG_LONGDESC="ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files." + +pre_configure_target() { + sed -i "s|sdl-config|sdl2-config|g" $PKG_BUILD/configure + TARGET_CONFIGURE_OPTS="--host=${TARGET_NAME} --backend=sdl --with-sdl-prefix=${SYSROOT_PREFIX}/usr/bin --disable-debug --enable-release --enable-vkeybd --opengl-mode=gles2" +} + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/config/scummvm/ + cp -rf $PKG_DIR/config/* $INSTALL/usr/config/scummvm/ + + mv $INSTALL/usr/local/bin $INSTALL/usr/ + cp -rf $PKG_DIR/bin/* $INSTALL/usr/bin + chmod 755 $INSTALL/usr/bin/* + + for i in appdata applications doc icons man; do + rm -rf "$INSTALL/usr/local/share/$i" + done + + for i in residualvm.zip scummmodern.zip scummclassic.zip; do + rm -rf "$INSTALL/usr/local/share/scummvm/$i" + done + + if [[ "$DEVICE" == RG351P ]]; then + mkdir -p $INSTALL/usr/local/share/scummvm/ + cp -rf $PKG_DIR/scummremastered.zip $INSTALL/usr/local/share/scummvm/ + fi +} + diff --git a/packages/games/emulators/scummvmsa/scummremastered.zip b/packages/games/emulators/scummvmsa/scummremastered.zip new file mode 100644 index 0000000000000000000000000000000000000000..2d2df0ed664100273f364e2fc5e561d72032cf16 GIT binary patch literal 92994 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 rf2;7lFwP{}LM7Ah! +Date: Tue, 26 Jan 2021 14:10:15 -0500 +Subject: [PATCH] Change keyboard mapping from French to US + +--- + libretro.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libretro.c b/libretro.c +index ef4b250..b18e01e 100644 +--- a/libretro.c ++++ b/libretro.c +@@ -125,7 +125,7 @@ void retro_init(void) + + // Get map layout + +- gb.keyboardLayout = 1; // French ++ gb.keyboardLayout = 0; // English + + for (i = 0; i < RETROK_LAST; i++) { + KeySymToCPCKey[i] = CPC_NIL; diff --git a/packages/games/libretro/daphne/package.mk b/packages/games/libretro/daphne/package.mk new file mode 100644 index 000000000..8a1500743 --- /dev/null +++ b/packages/games/libretro/daphne/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="daphne" +PKG_VERSION="0a7e6f0fda1348144369ce0a889876df60263e8f" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/libretro/daphne" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SHORTDESC="This is a Daphne core" +PKG_TOOLCHAIN="make" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp daphne_libretro.so $INSTALL/usr/lib/libretro/ +} + diff --git a/packages/games/libretro/dinothawr/package.mk b/packages/games/libretro/dinothawr/package.mk new file mode 100644 index 000000000..60450e9a6 --- /dev/null +++ b/packages/games/libretro/dinothawr/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="dinothawr" +PKG_VERSION="2e789028a8738ecfbde4da6dc164c41502a94955" +PKG_SHA256="29afdd8f0d6f901f3eb55ac9a0172e488fca7179f4490aec2e5a8a31cc57227f" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/Dinothawr" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Dinothawr is a block pushing puzzle game on slippery surfaces" +PKG_LONGDESC="Dinothawr is a block pushing puzzle game on slippery surfaces. Our hero is a dinosaur whose friends are trapped in ice. Through puzzles it is your task to free the dinos from their ice prison." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_BUILD_FLAGS="-gold" + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="HAVE_NEON=1" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp dinothawr_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/dosbox-pure/package.mk b/packages/games/libretro/dosbox-pure/package.mk new file mode 100644 index 000000000..5b5849877 --- /dev/null +++ b/packages/games/libretro/dosbox-pure/package.mk @@ -0,0 +1,45 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="dosbox-pure" +PKG_VERSION="01f2f5f6f3b5c2c2c58fbd4be7c271542aa84155" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/schellingb/dosbox-pure" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A port of DOSBox to libretro" +PKG_LONGDESC="A port of DOSBox to libretro" +GET_HANDLER_SUPPORT="git" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="make" + +make_target() { + make platform=emuelec-hh +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp dosbox_pure_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/dosbox-pure/patches/dosbox-pure-add-emuelec-platform.patch b/packages/games/libretro/dosbox-pure/patches/dosbox-pure-add-emuelec-platform.patch new file mode 100644 index 000000000..331d635fb --- /dev/null +++ b/packages/games/libretro/dosbox-pure/patches/dosbox-pure-add-emuelec-platform.patch @@ -0,0 +1,33 @@ +--- a/Makefile ++++ b/Makefile +@@ -88,6 +88,30 @@ + LDFLAGS += $(CPUFLAGS) -lpthread -shared + #LDFLAGS += -static-libstdc++ -static-libgcc #adds 1MB to output + ++ifneq (,$(findstring emuelec,$(platform))) ++OUTNAME := dosbox_pure_libretro.so ++BUILD := RELEASE ++BUILDDIR := release ++CFLAGS := -DNDEBUG -O3 -fno-ident ++LDFLAGS += -O3 -fno-ident ++ ++CPUFLAGS := -mtune=cortex-a53 -mcpu=cortex-a53 -march=armv8-a+crc+fp+simd ++ ++ ifneq (,$(findstring emuelec-hh,$(platform))) ++ CPUFLAGS := -mtune=cortex-a35 -mcpu=cortex-a35 -march=armv8-a+crc+fp+simd ++ endif ++ ifneq (,$(findstring emuelec-ng,$(platform))) ++ CPUFLAGS := -mtune=cortex-a72.cortex-a53 -mcpu=cortex-a72.cortex-a53 -march=armv8-a+crc+fp+simd ++ endif ++ ++CFLAGS += $(CPUFLAGS) -fpic -fomit-frame-pointer -fno-exceptions -fno-non-call-exceptions -Wno-psabi -Wno-format ++LDFLAGS += $(CPUFLAGS) -lpthread -Wl,--gc-sections -shared ++CXX = $(CC) ++endif ++ ++CFLAGS += -pthread -D__LIBRETRO__ -Iinclude ++$(info Building $(platform) with $(CPUFLAGS)) ++ + .PHONY: all clean + all: $(OUTNAME) + diff --git a/packages/games/libretro/dosbox-svn/package.mk b/packages/games/libretro/dosbox-svn/package.mk new file mode 100644 index 000000000..fa8b76a58 --- /dev/null +++ b/packages/games/libretro/dosbox-svn/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="dosbox-svn" +PKG_VERSION="ba9e1819d6ce59d9a08bf6dbb80515bcc0eebe09" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/dosbox-svn" +PKG_URL="$PKG_SITE.git" +PKG_GIT_CLONE_BRANCH="libretro" +PKG_DEPENDS_TARGET="toolchain SDL SDL_net retroarch" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Upstream port of DOSBox to libretro" +PKG_LONGDESC="Upstream port of DOSBox to libretro" +GET_HANDLER_SUPPORT="git" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_BUILD_FLAGS="-lto" +PKG_TOOLCHAIN="make" + +make_target() { + make -C libretro target=arm64 WITH_EMBEDDED_SDL=0 +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/libretro/dosbox_svn_libretro.so $INSTALL/usr/lib/libretro +} diff --git a/packages/games/libretro/dosbox-svn/patches/dosbox-svn-use-sdl-config.patch b/packages/games/libretro/dosbox-svn/patches/dosbox-svn-use-sdl-config.patch new file mode 100644 index 000000000..bfc259624 --- /dev/null +++ b/packages/games/libretro/dosbox-svn/patches/dosbox-svn-use-sdl-config.patch @@ -0,0 +1,13 @@ +--- a/libretro/Makefile.libretro 2018-08-15 16:42:50.000000000 +0200 ++++ b/libretro/Makefile.libretro 2018-08-16 16:22:53.958591362 +0200 +@@ -268,8 +268,8 @@ + + OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o) + OBJECT_DEPS = $(OBJECTS:.o=.d) +-CXXFLAGS += -D__LIBRETRO__ -MMD $(fpic) $(INCFLAGS) $(COMMONFLAGS) +-CFLAGS += -D__LIBRETRO__ -MMD $(fpic) $(INCFLAGS) $(COMMONFLAGS) ++CXXFLAGS += -D__LIBRETRO__ -MMD $(fpic) $(INCFLAGS) $(COMMONFLAGS) `sdl-config --cflags` ++CFLAGS += -D__LIBRETRO__ -MMD $(fpic) $(INCFLAGS) $(COMMONFLAGS) `sdl-config --cflags` + LDFLAGS += -lm $(fpic) + + .PHONY: all diff --git a/packages/games/libretro/dosbox/package.mk b/packages/games/libretro/dosbox/package.mk new file mode 100644 index 000000000..fa2eefefa --- /dev/null +++ b/packages/games/libretro/dosbox/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="dosbox" +PKG_VERSION="665d16d4edaeb8b1d6170c4bcf3747d20b03d032" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/dosbox-libretro" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="libretro wrapper for the DOSBox emulator" +PKG_LONGDESC="An open source DOS emulator for BeOS, Linux, Mac OS X, OS/2, and Windows. Primarily focuses on running DOS Games." +PKG_BUILD_FLAGS="-lto" +GET_HANDLER_SUPPORT="git" + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp dosbox_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/duckstation/package.mk b/packages/games/libretro/duckstation/package.mk new file mode 100644 index 000000000..7056e2960 --- /dev/null +++ b/packages/games/libretro/duckstation/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Maintenance 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="duckstation" +PKG_VERSION="1.0" +PKG_ARCH="aarch64" +PKG_URL="https://www.duckstation.org/libretro/duckstation_libretro_linux_aarch64.zip" +PKG_SECTION="libretro" +PKG_SHORTDESC="DuckStation - PlayStation 1, aka. PSX Emulator" +PKG_TOOLCHAIN="manual" + +pre_unpack() { + unzip sources/duckstation/duckstation-1.0.zip -d $PKG_BUILD +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro/ + cp $PKG_BUILD/duckstation_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/easyrpg/easyrpg.sh b/packages/games/libretro/easyrpg/easyrpg.sh new file mode 100644 index 000000000..edf7aad5b --- /dev/null +++ b/packages/games/libretro/easyrpg/easyrpg.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile + +clear > /dev/console + +DEST="/storage/roms/bios/rtp" + +SHASUMS="ddd519b50a22a2a95beeb831d29f7d7d92ae6263f953491163b446b808b66863 rpg2003_rtp_installer.zip#ec82b92da65ca6fdb2d3df25dfbcd7f2bb716e4fe63a079e8e5e396e91fa5e29 rpg2000_rtp_installer.exe" + +install_bios() { + BIOS="$1" + BIOSPATH="$2" + if [ -d "${INSTALLPATH}/${BIOSPATH}" ] + then + rm -rf "${INSTALLPATH}/${BIOSPATH}" + fi + mkdir -p "${INSTALLPATH}/${BIOSPATH}" + cd "${INSTALLPATH}/${BIOSPATH}" + curl -Lo "${BIOS}" "${PKG_URL}/${BIOS}" + BINSUM=$(sha256sum "${BIOS}" | awk '{print $1}') + SHASUM=$(echo $SHASUMS | tr '#' '\n' | awk '/'${BIOS}'/ {print $1}') + if [ ! "${SHASUM}" == "${BINSUM}" ] + then + echo "Checksum mismatch, please update the package." >/dev/console + exit 1 + fi + if [[ "${BIOS}" =~ .zip$ ]] + then + /usr/bin/7z x "${BIOS}" + rm "${BIOS}" + BIOS="$(echo ${BIOS} | sed "s#.zip#.exe#")" + fi + /usr/bin/7z x "${BIOS}" >/dev/console + rm "${BIOS}" + cd ${SOURCEPATH} +} + +INSTALLPATH="/storage/roms/bios" +SOURCEPATH="$(pwd)" +PKG_NAME="rpgmaker" +PKG_VERSION="1.0.0" +PKG_URL="https://dl.degica.com/rpgmakerweb/run-time-packages" + +# Check if the easyrpg runtime files are already available +[ "$(ls -A ${DEST})" ] && JDKINSTALLED="yes" || JDKINSTALLED="no" + +if [ ${JDKINSTALLED} == "no" ]; then + mkdir -p ${DEST} + echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1 + if [ $? -ne 0 ]; then + text_viewer -e -w -t "No Internet!" -m "You need to be connected to the internet to download the easyrpg runtime files."; + exit 1 + fi + echo "Downloading easyrpg runtime files please be patient..." > /dev/console + + install_bios rpg2000_rtp_installer.exe rtp/2000 + install_bios rpg2003_rtp_installer.zip rtp/2003 + + echo "Done! loading core!" > /dev/console +fi + +clear > /dev/console < /dev/null 2>&1 +exit 0 diff --git a/packages/games/libretro/easyrpg/liblcf/package.mk b/packages/games/libretro/easyrpg/liblcf/package.mk new file mode 100644 index 000000000..28e2307ab --- /dev/null +++ b/packages/games/libretro/easyrpg/liblcf/package.mk @@ -0,0 +1,37 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 2 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="liblcf" +PKG_VERSION="01b73de93cf80185fcdf3ffd4737dfdb9111a85e" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/EasyRPG/liblcf" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain expat icu" +PKG_SHORTDESC="Library to handle RPG Maker 2000/2003 and EasyRPG projects" +GET_HANDLER_SUPPORT="git" + +PKG_USE_CMAKE="yes" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_BUILD_TYPE=Release" + +pre_make_target() { + find $PKG_BUILD -name flags.make -exec sed -i "s:isystem :I:g" \{} \; + find $PKG_BUILD -name build.ninja -exec sed -i "s:isystem :I:g" \{} \; +} diff --git a/packages/games/libretro/easyrpg/liblcf/patches/liblcf-02-add-icu-compile-defs.patch b/packages/games/libretro/easyrpg/liblcf/patches/liblcf-02-add-icu-compile-defs.patch new file mode 100644 index 000000000..54c945d33 --- /dev/null +++ b/packages/games/libretro/easyrpg/liblcf/patches/liblcf-02-add-icu-compile-defs.patch @@ -0,0 +1,12 @@ +--- a/CMakeLists.txt 2020-12-20 15:19:33.535997406 +0100 ++++ b/CMakeLists.txt 2020-12-20 15:21:56.337546477 +0100 +@@ -259,6 +259,9 @@ + else() + find_package(ICU COMPONENTS i18n uc data REQUIRED) + target_link_libraries(lcf ICU::i18n ICU::uc ICU::data) ++ INCLUDE(FindPkgConfig) ++ pkg_get_variable(ICUDEFS icu-i18n DEFS) ++ target_compile_definitions(lcf PRIVATE LCF_SUPPORT_ICU=1 ${ICUDEFS}) + list(APPEND LIBLCF_DEPS "icu-i18n") + endif() + diff --git a/packages/games/libretro/easyrpg/libspeexdsp/package.mk b/packages/games/libretro/easyrpg/libspeexdsp/package.mk new file mode 100644 index 000000000..9c89c84b7 --- /dev/null +++ b/packages/games/libretro/easyrpg/libspeexdsp/package.mk @@ -0,0 +1,38 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="libspeexdsp" +PKG_VERSION="095fd36e189554bbcbfd9884630a53d7792409dc" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="https://github.com/xiph/speexdsp" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SHORTDESC="Speex audio processing library" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="configure" + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +pre_configure_target() { + ./autogen.sh +} diff --git a/packages/games/libretro/easyrpg/libxmp-lite/package.mk b/packages/games/libretro/easyrpg/libxmp-lite/package.mk new file mode 100644 index 000000000..9544b3835 --- /dev/null +++ b/packages/games/libretro/easyrpg/libxmp-lite/package.mk @@ -0,0 +1,40 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="libxmp-lite" +PKG_VERSION="4.5.0" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="http://sourceforge.net/projects/xmp" +PKG_URL="$PKG_SITE/files/libxmp/$PKG_VERSION/libxmp-lite-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SHORTDESC="Libxmp is a library that renders module files to PCM data." + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + cd $PKG_BUILD +} + + diff --git a/packages/games/libretro/easyrpg/libxmp-lite/sources/CMakeLists.txt b/packages/games/libretro/easyrpg/libxmp-lite/sources/CMakeLists.txt new file mode 100644 index 000000000..01033a207 --- /dev/null +++ b/packages/games/libretro/easyrpg/libxmp-lite/sources/CMakeLists.txt @@ -0,0 +1,65 @@ +cmake_minimum_required(VERSION 3.7) + +project(xmp-lite VERSION 4.5.0 LANGUAGES C) + +add_library(xmp-lite + include/libxmp-lite/xmp.h + src/virtual.c + src/format.c + src/period.c + src/player.c + src/read_event.c + src/dataio.c + src/lfo.c + src/scan.c + src/control.c + src/filter.c + src/effects.c + src/mixer.c + src/mix_all.c + src/load_helpers.c + src/load.c + src/hio.c + src/smix.c + src/memio.c + src/md5.c + src/misc.c + src/loaders/common.c + src/loaders/itsex.c + src/loaders/sample.c + src/loaders/xm_load.c + src/loaders/mod_load.c + src/loaders/s3m_load.c + src/loaders/it_load.c) + +target_include_directories(xmp-lite PUBLIC + $ + $) + +target_compile_definitions(xmp-lite PRIVATE + LIBXMP_CORE_PLAYER=1 + LIBXMP_NO_DEPACKERS=1) + +# pkg-config +set(PACKAGE_TARNAME ${PROJECT_NAME}) +set(prefix "${CMAKE_INSTALL_PREFIX}") +set(exec_prefix "\${prefix}") +set(libdir "\${exec_prefix}/lib") +set(includedir "\${prefix}/include") +configure_file(lib${PROJECT_NAME}.pc.in libxmp.pc @ONLY) + +# install +install( + TARGETS xmp-lite + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) + +install( + FILES include/libxmp-lite/xmp.h + DESTINATION include/libxmp-lite) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/libxmp.pc + DESTINATION lib/pkgconfig +) diff --git a/packages/games/libretro/easyrpg/package.mk b/packages/games/libretro/easyrpg/package.mk new file mode 100644 index 000000000..a64bf432f --- /dev/null +++ b/packages/games/libretro/easyrpg/package.mk @@ -0,0 +1,54 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="easyrpg" +PKG_VERSION="69aaeb2d8bf17eee565ac3e46a98809a9ebe4df0" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/easyrpg/player" +PKG_URL="$PKG_SITE.git" +PKG_GIT_CLONE_BRANCH="0-7-0-stable" +PKG_DEPENDS_TARGET="toolchain zlib libfmt liblcf pixman libspeexdsp mpg123 libsndfile libvorbis opusfile wildmidi libxmp-lite fluidsynth-git harfbuzz libpng" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="An unofficial libretro port of the EasyRPG/Player." +PKG_LONGDESC="An unofficial libretro port of the EasyRPG/Player." +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="+pic" + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +PKG_CMAKE_OPTS_TARGET="-DPLAYER_TARGET_PLATFORM=libretro \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release" + +pre_make_target() { + find $PKG_BUILD -name flags.make -exec sed -i "s:isystem :I:g" \{} \; + find $PKG_BUILD -name build.ninja -exec sed -i "s:isystem :I:g" \{} \; +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/.$TARGET_NAME/easyrpg_libretro.so $INSTALL/usr/lib/libretro/ + + mkdir -p $INSTALL/usr/bin + cp ${PKG_DIR}/easyrpg.sh $INSTALL/usr/bin +} diff --git a/packages/games/libretro/easyrpg/wildmidi/package.mk b/packages/games/libretro/easyrpg/wildmidi/package.mk new file mode 100644 index 000000000..a77242603 --- /dev/null +++ b/packages/games/libretro/easyrpg/wildmidi/package.mk @@ -0,0 +1,35 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="wildmidi" +PKG_VERSION="405ca73" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="https://github.com/Mindwerks/wildmidi" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SHORTDESC="WildMIDI is a simple software midi player which has a core softsynth library that can be used with other applications." + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="WANT_PLAYER=OFF -DWANT_ALSA=ON" diff --git a/packages/games/libretro/easyrpg/wildmidi/sources/CMakeLists.txt b/packages/games/libretro/easyrpg/wildmidi/sources/CMakeLists.txt new file mode 100644 index 000000000..7d35f304b --- /dev/null +++ b/packages/games/libretro/easyrpg/wildmidi/sources/CMakeLists.txt @@ -0,0 +1,303 @@ +# ########## Project setup ########## +PROJECT(wildmidi C) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11) + +# WildMIDI Version +SET(VERSION_MAJOR 0) +SET(VERSION_MINOR 4) +SET(VERSION_RELEASE 3) +SET(WILDMIDI_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}") + +# Lib Versions +SET(SOVERSION 2) +SET(VERSION 2.1.0) + +# Find Macros +SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +INCLUDE(CMakeDependentOption) +INCLUDE(CheckCCompilerFlag) +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckIncludeFile) +INCLUDE(TestBigEndian) + +# Set a default build type if none was specified +IF (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") + MESSAGE(STATUS "Setting build type to 'Debug' as none was specified.") + SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +ENDIF () +SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}") +MESSAGE(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") + +# Set our options +OPTION(BUILD_SHARED_LIBS "Build a dynamic wildmidi library" ON) +OPTION(WANT_PLAYER "Build WildMIDI player in addition to the libraries" ON) +OPTION(WANT_STATIC "Build static library in addition to dynamic library" OFF) +CMAKE_DEPENDENT_OPTION(WANT_PLAYERSTATIC "Build a statically linked WildMIDI player" ON "WANT_STATIC;WANT_PLAYER" OFF) +OPTION(WANT_ALSA "Include ALSA (Advanced Linux Sound Architecture) support" OFF) +OPTION(WANT_OSS "Include OSS (Open Sound System) support" OFF) +OPTION(WANT_OPENAL "Include OpenAL (Cross Platform) support" OFF) +OPTION(WANT_DEVTEST "Build WildMIDI DevTest file to check files" OFF) +OPTION(WANT_OSX_DEPLOYMENT "OSX Deployment" OFF) +IF (WIN32 AND MSVC) + OPTION(WANT_MP_BUILD "Build with Multiple Processes (/MP)" OFF) +ENDIF () +IF (UNIX AND NOT APPLE AND NOT RISCOS) + SET(WILDMIDI_CFG "/etc/wildmidi/wildmidi.cfg" CACHE STRING "default config location") +ELSE () + SET(WILDMIDI_CFG "wildmidi.cfg" CACHE STRING "default config location") +ENDIF () + +IF ((NOT BUILD_SHARED_LIBS) AND (NOT WANT_STATIC)) + MESSAGE(FATAL_ERROR "Neither dynamic nor static library build is selected.") +ENDIF () + + +# Platform specific defines +IF (UNIX) + # allow 'large' files in 32 bit builds + ADD_DEFINITIONS( + -D_LARGEFILE_SOURCE + -D_FILE_OFFSET_BITS=64 + -D_LARGE_FILES + ) +ENDIF (UNIX) + +# Usage of RPATH for macOS is enabled by default; this just suppresses the CMP0042 warning +# when building libwildmidi_dynamic. +IF (POLICY CMP0042) + CMAKE_POLICY(SET CMP0042 NEW) +ENDIF () + +IF (OPENBSD) # Set RPATH for OpenBSD so WildMIDI can find libWildMidi.so + # use, i.e. don't skip the full RPATH for the build tree + SET(CMAKE_SKIP_BUILD_RPATH FALSE) + + # when building, don't use the install RPATH already + # (but later on when installing) + SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + + # add the automatically determined parts of the RPATH + # which point to directories outside the build tree to the install RPATH + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + # the RPATH to be used when installing, but only if it's not a system directory + LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) + IF ("${isSystemDir}" STREQUAL "-1") + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + ENDIF () +ENDIF (OPENBSD) + +IF (WIN32) + ADD_DEFINITIONS( + -DNOMINMAX + -DWIN32_LEAN_AND_MEAN + -D_CRT_SECURE_NO_WARNINGS + ) +ENDIF (WIN32) + +# Compiler specific settings +IF (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang")) + ADD_DEFINITIONS( + -Wall -W + -fno-common + ) + + IF (NOT WIN32 AND NOT CYGWIN) + SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -Werror") + CHECK_C_SOURCE_COMPILES("int foo(void) __attribute__((visibility(\"default\"))); + int main(void) {return 0;}" HAVE_VISIBILITY_DEFAULT) + IF (HAVE_VISIBILITY_DEFAULT) + CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) + ENDIF () + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") + ENDIF () + + IF (CMAKE_BUILD_TYPE STREQUAL "Debug") + ADD_DEFINITIONS(-ggdb3 -O0) + ELSEIF (CMAKE_BUILD_TYPE STREQUAL "Release") + ADD_DEFINITIONS(-O3) + ENDIF (CMAKE_BUILD_TYPE STREQUAL "Debug") +ENDIF () + +IF (CMAKE_C_COMPILER_ID MATCHES "SunPro") + SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -xldscope=hidden") + # __SUNPRO_C >= 0x590 + # CHECK_C_SOURCE_COMPILES("int foo(void) __attribute__((visibility(\"default\"))); + # int main(void) {return 0;}" HAVE_VISIBILITY_DEFAULT) + # __SUNPRO_C >= 0x550 + CHECK_C_SOURCE_COMPILES("__global int foo(void); + int main(void) {return 0;}" HAVE_LDSCOPE_GLOBAL) + IF (HAVE_LDSCOPE_GLOBAL)# OR HAVE_VISIBILITY_DEFAULT + SET(HAVE_LDSCOPE_HIDDEN 1) + ENDIF () + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") +ENDIF () + +CHECK_C_SOURCE_COMPILES("int main(void) {__builtin_expect(0,0); return 0;}" HAVE___BUILTIN_EXPECT) + +CHECK_C_SOURCE_COMPILES("static inline int static_foo() {return 0;} + int main(void) {return 0;}" HAVE_C_INLINE) +CHECK_C_SOURCE_COMPILES("static __inline__ int static_foo() {return 0;} + int main(void) {return 0;}" HAVE_C___INLINE__) +CHECK_C_SOURCE_COMPILES("static __inline int static_foo() {return 0;} + int main(void) {return 0;}" HAVE_C___INLINE) + +# we must not have any unresolved symbols: +if (APPLE) + SET(EXTRA_LDFLAGS "-Wl,-undefined,error") +ELSE() + SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -Wl,--no-undefined") + CHECK_C_COMPILER_FLAG("" HAVE_NO_UNDEFINED) + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") + IF (HAVE_NO_UNDEFINED) + SET(EXTRA_LDFLAGS "-Wl,--no-undefined -lm") + ELSE() + SET(EXTRA_LDFLAGS "") + ENDIF() +ENDIF() + +CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) +CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H) + +TEST_BIG_ENDIAN(WORDS_BIGENDIAN) + +SET(AUDIODRV_ALSA) +SET(AUDIODRV_OSS) +SET(AUDIODRV_OPENAL) + +# UNIX-like environments +IF (UNIX AND NOT APPLE) + + # Go looking for available sound packages for WildMIDI player + IF (WANT_PLAYER) + FIND_PACKAGE(ALSA) + FIND_PACKAGE(OpenAL) + FIND_PACKAGE(OSS) + + # Set preferred output + IF (WANT_ALSA) + IF (NOT ALSA_FOUND) + MESSAGE(FATAL_ERROR "ALSA required but not found.") + ENDIF () + SET(AUDIODRV_ALSA 1) + SET(AUDIO_LIBRARY ${ALSA_LIBRARY}) + + ELSEIF (WANT_OSS) + IF (NOT OSS_FOUND) + MESSAGE(FATAL_ERROR "OSS required but not found.") + ENDIF () + # no special header paths + SET(AUDIODRV_OSS 1) + SET(AUDIO_LIBRARY ${OSS_LIBRARY}) + + ELSEIF (WANT_OPENAL) + IF (NOT OPENAL_FOUND) + MESSAGE(FATAL_ERROR "OpenAL required but not found.") + ENDIF () + SET(AUDIODRV_OPENAL 1) + SET(AUDIO_LIBRARY ${OPENAL_LIBRARY}) + + ELSE () # Try to auto-detect + + IF (ALSA_FOUND) + SET(AUDIO_LIBRARY ${ALSA_LIBRARY}) + SET(AUDIODRV_ALSA 1) + + ELSEIF (OSS_FOUND) + # no special header paths + SET(AUDIO_LIBRARY ${OSS_LIBRARY}) + SET(AUDIODRV_OSS 1) + + ELSEIF (OPENAL_FOUND) + SET(AUDIO_LIBRARY ${OPENAL_LIBRARY}) + SET(AUDIODRV_OPENAL 1) + + ELSE () + MESSAGE(WARNING "Could not find an audio sub-system!") + SET(AUDIO_LIBRARY "") + ENDIF () + + ENDIF () + ENDIF () + + # find our math lib + FIND_LIBRARY(M_LIBRARY m) + MESSAGE(STATUS "M_LIBRARY: ${M_LIBRARY}") + IF (NOT M_LIBRARY) + SET(M_LIBRARY "") + ENDIF () + + ## Debian and non debian Linux building + IF (DPKG_PROGRAM) + ## Debian specific + ELSE () + ## Non debian specific + ENDIF () +ENDIF (UNIX AND NOT APPLE) + +IF (APPLE AND WANT_PLAYER) + FIND_PACKAGE(OpenAL) + + IF (WANT_OPENAL) + IF (NOT OPENAL_FOUND) + MESSAGE(FATAL_ERROR "OpenAL required but not found.") + ENDIF () + SET(AUDIO_LIBRARY ${OPENAL_LIBRARY}) + + ELSE () + IF (OPENAL_FOUND) + SET(AUDIO_LIBRARY ${OPENAL_LIBRARY}) + SET(AUDIODRV_OPENAL 1) + + ELSE () + MESSAGE(WARNING "Could not find an audio sub-system!") + SET(AUDIO_LIBRARY "") + ENDIF () + + ENDIF () +ENDIF () + +IF (WIN32) + IF (WANT_PLAYER) + LINK_LIBRARIES(winmm) + ENDIF () +ENDIF (WIN32) + +# ######### General setup ########## +INCLUDE_DIRECTORIES(BEFORE "${CMAKE_SOURCE_DIR}/include") +FILE(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") +INCLUDE_DIRECTORIES(BEFORE "${CMAKE_BINARY_DIR}/include") +IF (NOT HAVE_STDINT_H) # AND NOT HAVE_INTTYPES_H + INCLUDE_DIRECTORIES(BEFORE "${CMAKE_SOURCE_DIR}/include/stdint") +ENDIF () + +IF (AMIGA OR AROS) + SET(WILDMIDI_AMIGA 1) +ENDIF () + +IF (APPLE) + SET(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app") + SET(APP_BUNDLE_DIR "${wildmidi_BINARY_DIR}/${APP_BUNDLE_NAME}") + IF (WANT_OSX_DEPLOYMENT) + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + ENDIF () +ENDIF (APPLE) + +IF (APPLE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS") +ELSE (APPLE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${wildmidi_BINARY_DIR}") +ENDIF (APPLE) + +# Setup up our config file +CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/include/config.h.cmake" "${CMAKE_BINARY_DIR}/include/config.h") + +ADD_SUBDIRECTORY(src) diff --git a/packages/games/libretro/fbalpha2012/package.mk b/packages/games/libretro/fbalpha2012/package.mk new file mode 100644 index 000000000..d303b7768 --- /dev/null +++ b/packages/games/libretro/fbalpha2012/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="fbalpha2012" +PKG_VERSION="23f98fc7cf4f2f216149c263cf5913d2e28be8d4" +PKG_SHA256="74a222c998c8a2ea40b992515329a894d1770933f4a557bfb37d2de28bb316ca" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/fbalpha2012" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Final Burn Alpha 2012 to Libretro" +PKG_TOOLCHAIN="make" + +make_target() { + cd svn-current/trunk + make -f makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp fbalpha2012_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/fbalpha2019/fbalpha2019_libretro.info b/packages/games/libretro/fbalpha2019/fbalpha2019_libretro.info new file mode 100644 index 000000000..5a605e484 --- /dev/null +++ b/packages/games/libretro/fbalpha2019/fbalpha2019_libretro.info @@ -0,0 +1,20 @@ +# Software Information +display_name = "Arcade (FB Alpha 2019)" +authors = "Team FB Alpha" +supported_extensions = "iso|zip|7z" +corename = "FB Alpha 2019" +license = "Non-commercial" +permissions = "" +display_version = "v0.2.97.44" +categories = "Emulator" + +# Hardware Information +manufacturer = "Various" +systemname = "Arcade (various)" +systemid = "fb_alpha" + +# Libretro Features +supports_no_game = "false" +notes = "(!) The BIOS files must be inside the ROM directory." + +description = "Based on a snapshot of the Final Burn Alpha codebase from circa 2019, 'FB Alpha 2019' is compatible with FB Alpha v0.2.97.44 ROM sets. Most users should use up-to-date FBNeo instead and should only fall back to this core if their device is not capable of running that core." diff --git a/packages/games/libretro/fbalpha2019/package.mk b/packages/games/libretro/fbalpha2019/package.mk new file mode 100644 index 000000000..bd3ebc66f --- /dev/null +++ b/packages/games/libretro/fbalpha2019/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="fbalpha2019" +PKG_VERSION="0a25932ac981108a5eb5ef401056ac78ea57e3ce" +PKG_SHA256="bab484e956367cf9ebb7caed081c3c1b51ac378e0c0cae1adaeb295433a2e4a0" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/fbalpha" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Final Burn Alpha to Libretro (v0.2.97.44)." +PKG_LONGDESC="Currently, FB Alpha supports games on Capcom CPS-1 and CPS-2 hardware, SNK Neo-Geo hardware, Toaplan hardware, Cave hardware, and various games on miscellaneous hardware." +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_DIR/fbalpha2019_libretro.info $INSTALL/usr/lib/libretro/ + cp fbalpha_libretro.so $INSTALL/usr/lib/libretro/fbalpha2019_libretro.so +} diff --git a/packages/games/libretro/fbneo/package.mk b/packages/games/libretro/fbneo/package.mk new file mode 100644 index 000000000..1bade8b38 --- /dev/null +++ b/packages/games/libretro/fbneo/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Maintenance 2020 351ELEC team (https://github.com/fewtarius/351ELEC) + +PKG_NAME="fbneo" +PKG_VERSION="3c8a46e5f63277fd4f512bc3ac3712d513c98325" +PKG_SHA256="29df6bb00669423b21db5e1ac497b13773983a3362c856a26b704e10f9e23623" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/FBNeo" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Final Burn Neo to Libretro (v0.2.97.38)." +PKG_LONGDESC="Currently, FB neo supports games on Capcom CPS-1 and CPS-2 hardware, SNK Neo-Geo hardware, Toaplan hardware, Cave hardware, and various games on miscellaneous hardware. " +PKG_TOOLCHAIN="make" + + +pre_configure_target() { +sed -i "s|LDFLAGS += -static-libgcc -static-libstdc++|LDFLAGS += -static-libgcc|" ./src/burner/libretro/Makefile + +PKG_MAKE_OPTS_TARGET=" -C ./src/burner/libretro USE_CYCLONE=0 profile=performance" + +if [[ "$TARGET_FPU" =~ "neon" ]]; then + PKG_MAKE_OPTS_TARGET+=" HAVE_NEON=1" +fi + +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/src/burner/libretro/fbneo_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/fceumm/package.mk b/packages/games/libretro/fceumm/package.mk new file mode 100644 index 000000000..e0f2fa010 --- /dev/null +++ b/packages/games/libretro/fceumm/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="fceumm" +PKG_VERSION="a918869c18c9f30b84e04260b78b675b8a3c7be1" +PKG_SHA256="9be07e6b925510d9d75d50d54f601772f8d12bd0012e1eb59c16ceca1a456dac" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-fceumm" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of FCEUmm / FCEUX to Libretro." +PKG_LONGDESC="FCEUX is a Nintendo Entertainment System (NES), Famicom, and Famicom Disk System (FDS) emulator." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp fceumm_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/flycast/package.mk b/packages/games/libretro/flycast/package.mk new file mode 100644 index 000000000..28b589955 --- /dev/null +++ b/packages/games/libretro/flycast/package.mk @@ -0,0 +1,82 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="flycast" +PKG_VERSION="ae670ea28fdbb9f08149cb598312a71a0970ca67" +PKG_SHA256="661b9871d100aa910ec3440377b7ef905df9a4f6f5ee01ec7e3a364524436c6f" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/flycast" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain $OPENGLES" +PKG_LONGDESC="Flycast is a multiplatform Sega Dreamcast emulator " +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-gold" + +pre_configure_target() { +sed -i 's/define CORE_OPTION_NAME "reicast"/define CORE_OPTION_NAME "flycast"/g' core/libretro/libretro_core_option_defines.h +# Flycast defaults to -O3 but then CHD v5 do not seem to work on EmuELEC so we change it to -O2 to fix the issue +#PKG_MAKE_OPTS_TARGET="ARCH=arm HAVE_OPENMP=1 GIT_VERSION=${PKG_VERSION:0:7} FORCE_GLES=1 SET_OPTIM=-O2 HAVE_LTCG=0" +PKG_MAKE_OPTS_TARGET="ARCH=arm HAVE_OPENMP=1 GIT_VERSION=${PKG_VERSION:0:7} FORCE_GLES=1 HAVE_LTCG=0" + +if [ "${ARCH}" == "aarch64" ]; then +PKG_MAKE_OPTS_TARGET+=" WITH_DYNAREC=arm64" +fi +} + +pre_make_target() { + export BUILD_SYSROOT=$SYSROOT_PREFIX + + if [ "$OPENGLES_SUPPORT" = "yes" ]; then + PKG_MAKE_OPTS_TARGET+=" FORCE_GLES=1 LDFLAGS=-lrt" + fi + +if [ "${ARCH}" == "aarch64" ]; then + case $PROJECT in + Amlogic-ng) + PKG_MAKE_OPTS_TARGET+=" platform=odroid-n2" + ;; + Amlogic) + PKG_MAKE_OPTS_TARGET+=" platform=arm64" + ;; + esac +else + case $PROJECT in + Amlogic-ng) + PKG_MAKE_OPTS_TARGET+=" platform=AMLG12B" + ;; + Amlogic) + PKG_MAKE_OPTS_TARGET+=" platform=AMLGX" + ;; + esac +fi + + if [[ "$DEVICE" =~ RG351 ]] || [[ "$DEVICE" =~ RG552 ]]; then + if [ "$ARCH" == "arm" ]; then + PKG_MAKE_OPTS_TARGET+=" platform=classic_armv8_a35" + else + PKG_MAKE_OPTS_TARGET+=" platform=arm64" + fi + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp flycast_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/fmsx/package.mk b/packages/games/libretro/fmsx/package.mk new file mode 100644 index 000000000..b8c76afb4 --- /dev/null +++ b/packages/games/libretro/fmsx/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="fmsx" +PKG_VERSION="f5d21539b480e2fea8523860f2df429bf7855461" +PKG_SHA256="02e7e9053a39e2e822390ea37a425866ba04f8fa5681ec47524a943705b6979c" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/fmsx-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of fMSX 4.9 to the libretro API." +PKG_LONGDESC="Port of fMSX 4.9 to the libretro API." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp fmsx_libretro.so $INSTALL/usr/lib/libretro/ +} \ No newline at end of file diff --git a/packages/games/libretro/freechaf/package.mk b/packages/games/libretro/freechaf/package.mk new file mode 100644 index 000000000..b3a7fe17b --- /dev/null +++ b/packages/games/libretro/freechaf/package.mk @@ -0,0 +1,23 @@ +PKG_NAME="freechaf" +PKG_VERSION="7275a3e067ed3fd701e0bbcfbcfec8f528587735" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/FreeChaF" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="FreeChaF is a libretro emulation core for the Fairchild ChannelF / Video Entertainment System designed to be compatible with joypads from the SNES era forward." +PKG_LONGDESC="FreeChaF is a libretro emulation core for the Fairchild ChannelF / Video Entertainment System designed to be compatible with joypads from the SNES era forward." +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +make_target() { + make +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp freechaf_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/freeintv/package.mk b/packages/games/libretro/freeintv/package.mk new file mode 100644 index 000000000..79145b213 --- /dev/null +++ b/packages/games/libretro/freeintv/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="freeintv" +PKG_VERSION="0058a09492c5c17a4fa59ebb3601ce66844b3b25" +PKG_SHA256="7cc050bd8673cfd5be8ac5dc3320f7b1e662d348f85480bf3ee33343d8e2791d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/FreeIntv" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="FreeIntv is a libretro emulation core for the Mattel Intellivision." +PKG_LONGDESC="FreeIntv is a libretro emulation core for the Mattel Intellivision." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp freeintv_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/freej2me/freej2me.sh b/packages/games/libretro/freej2me/freej2me.sh new file mode 100644 index 000000000..6f2bf8b4b --- /dev/null +++ b/packages/games/libretro/freej2me/freej2me.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +. /etc/profile + +clear > /dev/console + +if [ ! -f "/storage/roms/bios/freej2me-lr.jar" ]; then + cp /usr/config/distribution/freej2me/freej2me-lr.jar /storage/roms/bios +fi + +JDKDEST="/storage/jdk" +JDKNAME="zulu11.48.21-ca-jdk11.0.11" + +mkdir -p ${JDKDEST} + +# Check if the jdk does not already exists +[ "$(ls -A ${JDKDEST})" ] && JDKINSTALLED="yes" || JDKINSTALLED="no" + +if [ ${JDKINSTALLED} == "no" ]; then + echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1 + if [ $? -ne 0 ]; then + text_viewer -e -w -t "No Internet!" -m "You need to be connected to the internet to download the JDK."; + exit 1 + fi + echo "Downloading JDK please be patient..." > /dev/console + cd ${JDKDEST}/.. + wget "https://cdn.azul.com/zulu-embedded/bin/${JDKNAME}-linux_aarch64.tar.gz" > /dev/console 2>&1 + echo "Inflating JDK please be patient..." > /dev/console + tar xvfz ${JDKNAME}-linux_aarch64.tar.gz ${JDKNAME}-linux_aarch64/lib > /dev/console 2>&1 + tar xvfz ${JDKNAME}-linux_aarch64.tar.gz ${JDKNAME}-linux_aarch64/bin > /dev/console 2>&1 + tar xvfz ${JDKNAME}-linux_aarch64.tar.gz ${JDKNAME}-linux_aarch64/conf > /dev/console 2>&1 + rm ${JDKNAME}-linux_aarch64/lib/*.zip + mv ${JDKNAME}-linux_aarch64/* jdk + rm -rf ${JDKNAME}-linux_aarch64* + + for del in jmods include demo legal man DISCLAIMER LICENSE readme.txt release Welcome.html; do + rm -rf ${JDKDEST}/${del} + done + echo "JDK done! loading core!" > /dev/console + cp -rf /usr/config/distribution/freej2me/freej2me-lr.jar /storage/roms/bios +fi + +clear > /dev/console < /dev/null 2>&1 +exit 0 diff --git a/packages/games/libretro/freej2me/package.mk b/packages/games/libretro/freej2me/package.mk new file mode 100644 index 000000000..6e1ad4747 --- /dev/null +++ b/packages/games/libretro/freej2me/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="freej2me" +PKG_VERSION="560859c84d26f27cfa264555d1c856aeb630c13a" +PKG_SHA256="d343da4dc4db31d40fd97cbe584f9f92c3992e12189a909ca8e65c753df443aa" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="https://github.com/hex007/freej2me" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain apache-ant:host" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A free J2ME emulator with libretro, awt and sdl2 frontends." +PKG_LONGDESC="A free J2ME emulator with libretro, awt and sdl2 frontends." +PKG_TOOLCHAIN="make" + +pre_configure_target() { + ${TOOLCHAIN}/bin/ant +} + +make_target() { + make -C ${PKG_BUILD}/src/libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp ${PKG_BUILD}/src/libretro/freej2me_libretro.so $INSTALL/usr/lib/libretro/ + + mkdir -p $INSTALL/usr/config/distribution/freej2me + cp ${PKG_BUILD}/build/freej2me-lr.jar $INSTALL/usr/config/distribution/freej2me + + mkdir -p $INSTALL/usr/bin + cp ${PKG_DIR}/freej2me.sh $INSTALL/usr/bin +} diff --git a/packages/games/libretro/fuse-libretro/package.mk b/packages/games/libretro/fuse-libretro/package.mk new file mode 100644 index 000000000..25a2440e9 --- /dev/null +++ b/packages/games/libretro/fuse-libretro/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="fuse-libretro" +PKG_VERSION="23f7db522e1b9ad22a142e828d7c3631eb653142" +PKG_SHA256="bff4fed04eaf320025382f99c3ec45baae10300affe824584589682a06807c60" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/fuse-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A port of the Fuse Unix Spectrum Emulator to libretro " +PKG_LONGDESC="A port of the Fuse Unix Spectrum Emulator to libretro " + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp fuse_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/gambatte/package.mk b/packages/games/libretro/gambatte/package.mk new file mode 100644 index 000000000..ecf6466fd --- /dev/null +++ b/packages/games/libretro/gambatte/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="gambatte" +PKG_VERSION="c842d49b1daab6e45f3a1802ee7516b100827599" +PKG_SHA256="d9cb39d5e4738546babc457fe9f98e4463ac1577cd4d130026cd4ff0ad675ff0" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/gambatte-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="libretro implementation of libgambatte" +PKG_LONGDESC="Gambatte is an open-source Game Boy Color emulator written for fun and made available in the hope that it will be useful." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_PATCH_DIRS+="${DEVICE}" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp gambatte_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/gambatte/patches/RG351MP b/packages/games/libretro/gambatte/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/gambatte/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/gambatte/patches/RG351P/disable_palette_switching.patch b/packages/games/libretro/gambatte/patches/RG351P/disable_palette_switching.patch new file mode 100644 index 000000000..0563f79f8 --- /dev/null +++ b/packages/games/libretro/gambatte/patches/RG351P/disable_palette_switching.patch @@ -0,0 +1,31 @@ +diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp +index e8a2b10..9b618f5 100644 +--- a/libgambatte/libretro/libretro.cpp ++++ b/libgambatte/libretro/libretro.cpp +@@ -1120,8 +1120,7 @@ static void update_input_state(void) + bool turbo_b = false; + bool palette_prev = false; + bool palette_next = false; +- bool palette_switch_enabled = (libretro_supports_set_variable && +- internal_palette_active); ++ bool palette_switch_enabled = false; + + if (libretro_supports_bitmasks) + { +@@ -2229,14 +2228,14 @@ bool retro_load_game(const struct retro_game_info *info) + if (libretro_supports_ff_override) + { + if (libretro_supports_set_variable) +- environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_ff_ps); ++ environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_ff); + else + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_ff); + } + else + { + if (libretro_supports_set_variable) +- environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_ps); ++ environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + else + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + } diff --git a/packages/games/libretro/gambatte/patches/RG351P/rumble.patch b/packages/games/libretro/gambatte/patches/RG351P/rumble.patch new file mode 100644 index 000000000..63c4657d8 --- /dev/null +++ b/packages/games/libretro/gambatte/patches/RG351P/rumble.patch @@ -0,0 +1,35 @@ +diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp +index b0f1ee1..d68c5ee 100644 +--- a/libgambatte/libretro/libretro.cpp ++++ b/libgambatte/libretro/libretro.cpp +@@ -594,8 +594,15 @@ static void apply_rumble(void) + if (strength == rumble_strength_last) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, strength); +- rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength); ++ if (rumble_level == 0){ ++ return; ++ } ++ ++ uint pwm_duty_cycle = 1000000 - static_cast((static_cast(strength) / 65535.0) * 1000000.0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", pwm_duty_cycle); ++ fclose(fp); + + rumble_strength_last = strength; + } +@@ -610,8 +617,10 @@ static void deactivate_rumble(void) + (rumble_strength_last == 0)) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, 0); +- rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, 0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", 1000000); ++ fclose(fp); + + rumble_strength_last = 0; + } diff --git a/packages/games/libretro/gambatte/patches/RG351V b/packages/games/libretro/gambatte/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/gambatte/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/gearboy/package.mk b/packages/games/libretro/gearboy/package.mk new file mode 100644 index 000000000..0e0bdbc0c --- /dev/null +++ b/packages/games/libretro/gearboy/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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. +# +################################################################################ + +PKG_NAME="gearboy" +PKG_VERSION="cd9c5f76145ee7063fd1708d51f98a6d2d373b9d" +PKG_SHA256="7030a9647f11ab0667e9074b1006d143b416ce22803e586b2beea3ee0347a787" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/drhelius/Gearboy" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Game Boy / Gameboy Color emulator for iOS, Mac, Raspberry Pi, Windows and Linux" +PKG_LONGDESC="Game Boy / Gameboy Color emulator for iOS, Mac, Raspberry Pi, Windows and Linux" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -C platforms/libretro/ +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp platforms/libretro/gearboy_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/gearcoleco/package.mk b/packages/games/libretro/gearcoleco/package.mk new file mode 100644 index 000000000..b3e2b0975 --- /dev/null +++ b/packages/games/libretro/gearcoleco/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# +# Copyright (C) 2021 351ELEC team (https://github.com/351ELEC/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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. +# +################################################################################ + +PKG_NAME="gearcoleco" +PKG_VERSION="223b96c6f92fe2ece238df8a463334e2dfadaa7d" +PKG_SHA256="36684b0d60e9f9edd203931e4ce8c31f6e95da75e074619ead55a73cc063337e" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/drhelius/Gearcoleco" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Gearcoleco is a very accurate cross-platform ColecoVision emulator written in C++ that runs on Windows, macOS, Linux, BSD, Raspberry Pi and RetroArch." +PKG_LONGDESC="Gearcoleco is a very accurate cross-platform ColecoVision emulator written in C++ that runs on Windows, macOS, Linux, BSD, Raspberry Pi and RetroArch." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -C platforms/libretro/ +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp platforms/libretro/gearcoleco_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/gearsystem/package.mk b/packages/games/libretro/gearsystem/package.mk new file mode 100644 index 000000000..58dc85f86 --- /dev/null +++ b/packages/games/libretro/gearsystem/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="gearsystem" +PKG_VERSION="ae1beb2f2ec33a3fac996b75f82951a005c58107" +PKG_SHA256="" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/drhelius/Gearsystem" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Gearsystem is a Sega Master System / Game Gear / SG-1000 emulator written in C++" +PKG_LONGDESC="Gearsystem is a Sega Master System / Game Gear / SG-1000 emulator written in C++" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +make_target() { + make -C platforms/libretro/ +} + + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp platforms/libretro/gearsystem_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/genesis-plus-gx-wide/package.mk b/packages/games/libretro/genesis-plus-gx-wide/package.mk new file mode 100644 index 000000000..aed568176 --- /dev/null +++ b/packages/games/libretro/genesis-plus-gx-wide/package.mk @@ -0,0 +1,50 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="genesis-plus-gx-wide" +PKG_VERSION="fa71a1640f6a01025a045b616007c2fe4effd384" +PKG_SHA256="4ed8aba9c9a93ac4026ac94a9d5d8193b2f7c9ee526e91c28d235303e4b44cf7" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/Genesis-Plus-GX-Wide" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="An enhanced port of Genesis Plus for Gamecube/Wii" +PKG_LONGDESC="Genesis Plus GX is an open-source & portable Sega Mega Drive / Genesis emulator, now also emulating SG-1000, Master System, Game Gear and Sega/Mega CD hardware." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DALIGN_LONG" + fi + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp genesis_plus_gx_wide_libretro.so $INSTALL/usr/lib/libretro/genesis_plus_gx_wide_libretro.so +} diff --git a/packages/games/libretro/genesis-plus-gx/package.mk b/packages/games/libretro/genesis-plus-gx/package.mk new file mode 100644 index 000000000..d085c0dd5 --- /dev/null +++ b/packages/games/libretro/genesis-plus-gx/package.mk @@ -0,0 +1,50 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="genesis-plus-gx" +PKG_VERSION="c1c605e862c4a277e880b510c68ebde630487948" +PKG_SHA256="8231d4c6cf0b504aa1362d1e1ad0b5a7ffeb5abc9f2fc8a9e21225ae70acb7fa" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/Genesis-Plus-GX" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="An enhanced port of Genesis Plus for Gamecube/Wii" +PKG_LONGDESC="Genesis Plus GX is an open-source & portable Sega Mega Drive / Genesis emulator, now also emulating SG-1000, Master System, Game Gear and Sega/Mega CD hardware." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DALIGN_LONG" + fi + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp genesis_plus_gx_libretro.so $INSTALL/usr/lib/libretro/genesis_plus_gx_libretro.so +} diff --git a/packages/games/libretro/glsl-shaders/package.mk b/packages/games/libretro/glsl-shaders/package.mk new file mode 100644 index 000000000..536c97542 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/package.mk @@ -0,0 +1,53 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="glsl-shaders" +PKG_VERSION="5efcd63b706081646fcd41be57c9916e2007748d" +PKG_SHA256="f19691c1e3f2693ea1fba9ce9c6450bd150bce3e2d02c3a0c9ae6ae7b556e4fb" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/glsl-shaders" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Common GSLS shaders for RetroArch" +PKG_LONGDESC="Common GSLS shaders for RetroArch" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +configure_target() { + cd $PKG_BUILD +} + +makeinstall_target() { + make install INSTALLDIR="$INSTALL/usr/share/common-shaders" + cp -r $PKG_DIR/shaders/* $INSTALL/usr/share/common-shaders +} + +post_makeinstall_target() { + cp $PKG_DIR/removeshaders.sh . + chmod 755 removeshaders.sh + /bin/sh removeshaders.sh $INSTALL +} diff --git a/packages/games/libretro/glsl-shaders/removeshaders.sh b/packages/games/libretro/glsl-shaders/removeshaders.sh new file mode 100644 index 000000000..22016a156 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/removeshaders.sh @@ -0,0 +1,122 @@ +#! /bin/sh + +# Fail to load + +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_3dfx.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_shader_cmyk_halftone.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_strong_extra.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_variant.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant_bayer.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant_deposterize.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant_gendither.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant_natural_colors.glslp +rm -f $1/usr/share/common-shaders/cel/presets/MMJ_Cel_Shader_vhs_variant_ntsc.glslp +rm -f $1/usr/share/common-shaders/cel/advcartoon.glslp +rm -f $1/usr/share/common-shaders/cel/MMJ_Cel_Shader_MP.glslp +rm -f $1/usr/share/common-shaders/crt/crt-caligari.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-fake-bloom.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-ntsc-256px-composite.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-ntsc-256px-svideo.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-ntsc-320px-composite.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-ntsc-320px-svideo.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale-pal-r57shell.glslp +rm -f $1/usr/share/common-shaders/crt/crt-royale.glslp +rm -f $1/usr/share/common-shaders/crt/crt-torridgristle.glslp +rm -f $1/usr/share/common-shaders/crt/mame_hlsl.glslp +rm -f $1/usr/share/common-shaders/crt/tvout-tweaks-linearized-multipass.glslp +rm -f $1/usr/share/common-shaders/crt/yee64.glslp +rm -f $1/usr/share/common-shaders/crt/yeetron.glslp +rm -f $1/usr/share/common-shaders/cubic/cubic.glslp +rm -f $1/usr/share/common-shaders/deblur/simoneT-3d-2d-mixed.glslp +rm -f $1/usr/share/common-shaders/denoisers/crt-fast-bilateral-super-xbr.glslp +rm -f $1/usr/share/common-shaders/denoisers/fast-bilateral-super-2xbr-3d-3p.glslp +rm -f $1/usr/share/common-shaders/denoisers/fast-bilateral-super-xbr-natural-vision.glslp +rm -f $1/usr/share/common-shaders/dithering/bayer-matrix-dithering.glslp +rm -f $1/usr/share/common-shaders/gpu/powervr2.glslp +rm -f $1/usr/share/common-shaders/interpolation/controlled_sharpness.glslp +rm -f $1/usr/share/common-shaders/nes_raw_palette/cgwg-famicom-geom.glslp +rm -f $1/usr/share/common-shaders/nes_raw_palette/pal-r57shell-raw.glslp +rm -f $1/usr/share/common-shaders/ntsc/ntsc-320px-gauss-scanline.glslp +rm -f $1/usr/share/common-shaders/ntsc/ntsc-320px-*.glslp +rm -f $1/usr/share/common-shaders/ntsc/ntsc-adaptive.glslp +rm -f $1/usr/share/common-shaders/pal/pal-r57shell.glslp +rm -f $1/usr/share/common-shaders/pal/pal.glslp +rm -f $1/usr/share/common-shaders/presets/tvout/gtu-famicom-240p.glslp +rm -f $1/usr/share/common-shaders/presets/tvout/tvout+*.glslp +rm -f $1/usr/share/common-shaders/presets/tvout/tvout-jinc-sharpen.glslp +rm -f $1/usr/share/common-shaders/presets/tvout/tvout-pixelsharp.glslp +rm -f $1/usr/share/common-shaders/presets/tvout/tvout.glslp +rm -f $1/usr/share/common-shaders/presets/tvout+interlacing/gtu-famicom-240p+interlacing.glslp +rm -f $1/usr/share/common-shaders/presets/tvout+interlacing/tvout+*.glslp +rm -f $1/usr/share/common-shaders/presets/tvout+interlacing/tvout-jinc-sharpen+interlacing.glslp +rm -f $1/usr/share/common-shaders/presets/crt-guest-dr-venom-ntsc-* +rm -f $1/usr/share/common-shaders/presets/crt-hyllian-*.glslp +rm -f $1/usr/share/common-shaders/presets/crt-royale-*.glslp +rm -f $1/usr/share/common-shaders/presets/scalefx+rAA*.glslp +rm -f $1/usr/share/common-shaders/procedural/*.glslp +rm -f $1/usr/share/common-shaders/reshade/bloom.glslp +rm -f $1/usr/share/common-shaders/scalefx/scalefx+rAA.glslp +rm -f $1/usr/share/common-shaders/scale3x/scale3x.glslp +rm -f $1/usr/share/common-shaders/sharpen/adaptive-sharpen-multipass.glslp +rm -f $1/usr/share/common-shaders/sharpen/super-xbr-super-res.glslp +rm -f $1/usr/share/common-shaders/vhs/mudlord-pal-vhs.glslp +rm -f $1/usr/share/common-shaders/xbr/super-4xbr-*.glslp +rm -f $1/usr/share/common-shaders/xbr/super-8xbr-*.glslp +rm -f $1/usr/share/common-shaders/xbr/xbr-lvl2*.glslp + +# Loads without display + +rm -f $1/usr/share/common-shaders/crt/crt-easymode-halation.glslp +rm -f $1/usr/share/common-shaders/crt/crt-guest-dr-venom.glslp +rm -f $1/usr/share/common-shaders/crt/crtglow_gauss.glslp +rm -f $1/usr/share/common-shaders/crt/crtglow_gauss_ntsc_3phase.glslp +rm -f $1/usr/share/common-shaders/crt/crtglow_lanczos.glslp +rm -f $1/usr/share/common-shaders/presets/crt-guest-dr-venom-kurozumi.glslp +rm -f $1/usr/share/common-shaders/presets/xsoft+scalefx-level2aa+sharpsmoother.glslp +rm -f $1/usr/share/common-shaders/rpi/gameboy.glslp +rm -f $1/usr/share/common-shaders/rpi/gameboy2.glslp + +# Nearly freezing + +rm -f $1/usr/share/common-shaders/anti-aliasing/aa-shader-4.0-level2.glslp +rm -f $1/usr/share/common-shaders/anti-aliasing/aa-shader-4.0.glslp +rm -f $1/usr/share/common-shaders/crt/crt-lottes.glslp +rm -f $1/usr/share/common-shaders/crt/crt-mattias.glslp +rm -f $1/usr/share/common-shaders/crt/metacrt.glslp +rm -f $1/usr/share/common-shaders/denoisers/fast-bilateral-super-xbr-4p.glslp +rm -f $1/usr/share/common-shaders/denoisers/fast-bilateral-super-xbr-6p.glslp +rm -f $1/usr/share/common-shaders/nnedi3/*.glslp +rm -f $1/usr/share/common-shaders/ntsc/ntsc-xot.glslp +rm -f $1/usr/share/common-shaders/omniscale/*.glslp +rm -f $1/usr/share/common-shaders/presets/c64-monitor.glslp +rm -f $1/usr/share/common-shaders/sharpen/adaptive-sharpen.glslp +rm -f $1/usr/share/common-shaders/xbr/super-xbr-6p-*.glslp +rm -f $1/usr/share/common-shaders/xbrz/4x*.glslp +rm -f $1/usr/share/common-shaders/xbrz/5x*.glslp +rm -f $1/usr/share/common-shaders/xbrz/6x*.glslp + +# Slightly rough + +#rm -f $1/usr/share/common-shaders/crt/crt-yo6-KV-M1420B-sharp.glslp +#rm -f $1/usr/share/common-shaders/crt/crt-yo6-KV-M1420B.glslp +#rm -f $1/usr/share/common-shaders/deblur/sedi.glslp +#rm -f $1/usr/share/common-shaders/denoisers/fast-bilateral-super-xbr.glslp +#rm -f $1/usr/share/common-shaders/denoisers/slow-bilateral.glslp +#rm -f $1/usr/share/common-shaders/nedi/fast-bilateral-nedi.glslp +#rm -f $1/usr/share/common-shaders/nedi/nedi.glslp +#rm -f $1/usr/share/common-shaders/nes_raw_palette/gtu-famicom.glslp +#rm -f $1/usr/share/common-shaders/ntsc/artifact-colors.glslp +#rm -f $1/usr/share/common-shaders/presets/scalefx-aa.glslp +#rm -f $1/usr/share/common-shaders/presets/xsoft+scalefx+hybrid+level2aa.glslp +#rm -f $1/usr/share/common-shaders/presets/xsoft+scalefx-level2aa.glslp +#rm -f $1/usr/share/common-shaders/rpi/nedi.glslp +#rm -f $1/usr/share/common-shaders/xbr/xbr-hybrid.glslp + +# Broken display + +#rm -f $1/usr/share/common-shaders/film/technicolor.glslp +#rm -f $1/usr/share/common-shaders/handheld/ds-hybrid-sabr.glslp +#rm -f $1/usr/share/common-shaders/kurg/kurg-ROPi-scanlines-3x.glslp +#rm -f $1/usr/share/common-shaders/presets/crt-faker/crt-faker-glow-2.glslp diff --git a/packages/games/libretro/glsl-shaders/shaders/_redraw.glslp b/packages/games/libretro/glsl-shaders/shaders/_redraw.glslp new file mode 100644 index 000000000..8f83119cb --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/_redraw.glslp @@ -0,0 +1,11 @@ +shaders = 2 +shader0 = rpi/shaders/xbr/2xbr-v3.8d.glsl +shader1 = rpi/shaders/aa/reverse-aa.glsl + +filter_linear0 = false +filter_linear1 = false +scale_type0 = source +scale_type1 = source +scale0 = 2.0 +scale1 = 2.0 + diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/crt-nes-mini.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/crt-nes-mini.glslp new file mode 100644 index 000000000..0c41c03be --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/crt-nes-mini.glslp @@ -0,0 +1,3 @@ +shaders = 1 + +shader0 = shaders/crt-nes-mini.glsl diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi-vertical.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi-vertical.glslp new file mode 100644 index 000000000..e64c1b47b --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi-vertical.glslp @@ -0,0 +1,8 @@ +shaders = "1" +shader0 = "shaders/crt-pi-vertical.glsl" +filter_linear0 = "true" +wrap_mode0 = "clamp_to_border" +mipmap_input0 = "false" +alias0 = "" +float_framebuffer0 = "false" +srgb_framebuffer0 = "false" diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi.glslp new file mode 100644 index 000000000..587e11026 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/crt-pi.glslp @@ -0,0 +1,8 @@ +shaders = "1" +shader0 = "shaders/crt-pi.glsl" +filter_linear0 = "true" +wrap_mode0 = "clamp_to_border" +mipmap_input0 = "false" +alias0 = "" +float_framebuffer0 = "false" +srgb_framebuffer0 = "false" diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/fakelottes.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/fakelottes.glslp new file mode 100644 index 000000000..9e2cf6dbc --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/fakelottes.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/fakelottes.glsl +filter_linear0 = true \ No newline at end of file diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/scanline.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/scanline.glslp new file mode 100644 index 000000000..51d07c027 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/scanline.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/scanlines.glsl +filter_linear0 = true \ No newline at end of file diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-nes-mini.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-nes-mini.glsl new file mode 100644 index 000000000..ed3488e1a --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-nes-mini.glsl @@ -0,0 +1,106 @@ +// Parameter lines go here: +#pragma parameter SCANTHICK "Scanline Thickness" 2.0 2.0 4.0 2.0 +#pragma parameter INTENSITY "Scanline Intensity" 0.15 0.0 1.0 0.01 +#pragma parameter BRIGHTBOOST "Luminance Boost" 0.15 0.0 1.0 0.01 + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +vec4 _oPosition1; +uniform mat4 MVPMatrix; +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; + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy * 1.00001; +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +// compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy + +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutputSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float SCANTHICK; +uniform COMPAT_PRECISION float INTENSITY; +uniform COMPAT_PRECISION float BRIGHTBOOST; +#else +#define SCANTHICK 2.0 +#define INTENSITY 0.15 +#define BRIGHTBOOST 0.15 +#endif + +void main() +{ + vec3 texel = COMPAT_TEXTURE(Texture, TEX0.xy).rgb; + vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; + vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; + float selectY = mod(TEX0.y * SCANTHICK * TextureSize.y, 2.0); + float selectHigh = step(1.0, selectY); + float selectLow = 1.0 - selectHigh; + vec3 pixelColor = (selectLow * pixelLow) + (selectHigh * pixelHigh); + + FragColor = vec4(pixelColor, 1.0); +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi-vertical.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi-vertical.glsl new file mode 100644 index 000000000..bdcf3afdd --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi-vertical.glsl @@ -0,0 +1,242 @@ +/* + crt-pi-vertical - A Raspberry Pi friendly CRT shader. + + For use with portrait mode games on landscape mode screens (or landscape mode games on portrait mode sreens). + + Copyright (C) 2015-2016 davej + + This program 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 2 of the License, or (at your option) + any later version. + + +Notes: + +This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA. + +SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely. + +GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA. + +CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot. + +By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER. + +BLOOM_FACTOR controls the increase in width for bright scanlines. + +MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen. + +*/ + +#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01 +#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01 +#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01 +#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1 +#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01 +#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01 +#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01 +#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01 + +// Haven't put these as parameters as it would slow the code down. +#define SCANLINES +#define MULTISAMPLE +#define GAMMA +//#define FAKE_GAMMA +//#define CURVATURE +//#define SHARPER +// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish) +#define MASK_TYPE 1 + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +precision mediump float; +#else +#define COMPAT_PRECISION +#endif + +#ifdef PARAMETER_UNIFORM +uniform COMPAT_PRECISION float CURVATURE_X; +uniform COMPAT_PRECISION float CURVATURE_Y; +uniform COMPAT_PRECISION float MASK_BRIGHTNESS; +uniform COMPAT_PRECISION float SCANLINE_WEIGHT; +uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS; +uniform COMPAT_PRECISION float BLOOM_FACTOR; +uniform COMPAT_PRECISION float INPUT_GAMMA; +uniform COMPAT_PRECISION float OUTPUT_GAMMA; +#else +#define CURVATURE_X 0.10 +#define CURVATURE_Y 0.25 +#define MASK_BRIGHTNESS 0.70 +#define SCANLINE_WEIGHT 6.0 +#define SCANLINE_GAP_BRIGHTNESS 0.12 +#define BLOOM_FACTOR 1.5 +#define INPUT_GAMMA 2.4 +#define OUTPUT_GAMMA 2.2 +#endif + +/* COMPATIBILITY + - GLSL compilers +*/ + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + + +uniform vec2 TextureSize; +#if defined(CURVATURE) +varying COMPAT_PRECISION vec2 screenScale; +#endif +varying COMPAT_PRECISION vec2 TEX0; +varying COMPAT_PRECISION float filterWidth; + +#if defined(VERTEX) +uniform mat4 MVPMatrix; +attribute vec4 VertexCoord; +attribute vec2 TexCoord; +uniform vec2 InputSize; +uniform vec2 OutputSize; + +void main() +{ +#if defined(CURVATURE) + screenScale = TextureSize / InputSize; +#endif + filterWidth = (InputSize.y / OutputSize.y) / 3.0; + TEX0 = TexCoord; + gl_Position = MVPMatrix * VertexCoord; +} +#elif defined(FRAGMENT) + +uniform sampler2D Texture; + +#if defined(CURVATURE) +vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y); +// Barrel distortion shrinks the display area a bit, this will allow us to counteract that. +vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION); + +vec2 Distort(vec2 coord) +{ + coord *= screenScale; + coord -= vec2(0.5); + float rsq = coord.x * coord.x + coord.y * coord.y; + coord += coord * (CURVATURE_DISTORTION * rsq); + coord *= barrelScale; + if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5) + coord = vec2(-1.0); // If out of bounds, return an invalid value. + else + { + coord += vec2(0.5); + coord /= screenScale; + } + + return coord; +} +#endif + +float CalcScanLineWeight(float dist) +{ + return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS); +} + +float CalcScanLine(float dy) +{ + float scanLineWeight = CalcScanLineWeight(dy); +#if defined(MULTISAMPLE) + scanLineWeight += CalcScanLineWeight(dy-filterWidth); + scanLineWeight += CalcScanLineWeight(dy+filterWidth); + scanLineWeight *= 0.3333333; +#endif + return scanLineWeight; +} + +void main() +{ +#if defined(CURVATURE) + vec2 texcoord = Distort(TEX0); + if (texcoord.x < 0.0) + gl_FragColor = vec4(0.0); + else +#else + vec2 texcoord = TEX0; +#endif + { + vec2 texcoordInPixels = texcoord * TextureSize; +#if defined(SHARPER) + vec2 tempCoord = floor(texcoordInPixels) + 0.5; + vec2 coord = tempCoord / TextureSize; + vec2 deltas = texcoordInPixels - tempCoord; + float scanLineWeight = CalcScanLine(deltas.y); + vec2 signs = sign(deltas); + deltas.x *= 2.0; + deltas = deltas * deltas; + deltas.y = deltas.y * deltas.y; + deltas.x *= 0.5; + deltas.y *= 8.0; + deltas /= TextureSize; + deltas *= signs; + vec2 tc = coord + deltas; +#else + float tempY = floor(texcoordInPixels.y) + 0.5; + float yCoord = tempY / TextureSize.y; + float dy = texcoordInPixels.y - tempY; + float scanLineWeight = CalcScanLine(dy); + float signY = sign(dy); + dy = dy * dy; + dy = dy * dy; + dy *= 8.0; + dy /= TextureSize.y; + dy *= signY; + vec2 tc = vec2(texcoord.x, yCoord + dy); +#endif + + vec3 colour = texture2D(Texture, tc).rgb; + +#if defined(SCANLINES) +#if defined(GAMMA) +#if defined(FAKE_GAMMA) + colour = colour * colour; +#else + colour = pow(colour, vec3(INPUT_GAMMA)); +#endif +#endif + scanLineWeight *= BLOOM_FACTOR; + colour *= scanLineWeight; + +#if defined(GAMMA) +#if defined(FAKE_GAMMA) + colour = sqrt(colour); +#else + colour = pow(colour, vec3(1.0/OUTPUT_GAMMA)); +#endif +#endif +#endif +#if MASK_TYPE == 0 + gl_FragColor = vec4(colour, 1.0); +#else +#if MASK_TYPE == 1 + float whichMask = fract(gl_FragCoord.y * 0.5); + vec3 mask; + if (whichMask < 0.5) + mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS); + else + mask = vec3(1.0, MASK_BRIGHTNESS, 1.0); +#elif MASK_TYPE == 2 + float whichMask = fract(gl_FragCoord.y * 0.3333333); + vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS); + if (whichMask < 0.3333333) + mask.x = 1.0; + else if (whichMask < 0.6666666) + mask.y = 1.0; + else + mask.z = 1.0; +#endif + + gl_FragColor = vec4(colour * mask, 1.0); +#endif + } +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi.glsl new file mode 100644 index 000000000..c1cc0ad23 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/crt-pi.glsl @@ -0,0 +1,234 @@ +/* + crt-pi - A Raspberry Pi friendly CRT shader. + + Copyright (C) 2015-2016 davej + + This program 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 2 of the License, or (at your option) + any later version. + + +Notes: + +This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA. + +SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely. + +GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA. + +CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot. + +By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER. + +BLOOM_FACTOR controls the increase in width for bright scanlines. + +MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen. + +*/ + +#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01 +#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01 +#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01 +#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1 +#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01 +#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01 +#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01 +#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01 + +// Haven't put these as parameters as it would slow the code down. +#define SCANLINES +#define MULTISAMPLE +#define GAMMA +//#define FAKE_GAMMA +//#define CURVATURE +//#define SHARPER +// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish) +#define MASK_TYPE 1 + + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +precision mediump float; +#else +#define COMPAT_PRECISION +#endif + +#ifdef PARAMETER_UNIFORM +uniform COMPAT_PRECISION float CURVATURE_X; +uniform COMPAT_PRECISION float CURVATURE_Y; +uniform COMPAT_PRECISION float MASK_BRIGHTNESS; +uniform COMPAT_PRECISION float SCANLINE_WEIGHT; +uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS; +uniform COMPAT_PRECISION float BLOOM_FACTOR; +uniform COMPAT_PRECISION float INPUT_GAMMA; +uniform COMPAT_PRECISION float OUTPUT_GAMMA; +#else +#define CURVATURE_X 0.10 +#define CURVATURE_Y 0.25 +#define MASK_BRIGHTNESS 0.70 +#define SCANLINE_WEIGHT 6.0 +#define SCANLINE_GAP_BRIGHTNESS 0.12 +#define BLOOM_FACTOR 1.5 +#define INPUT_GAMMA 2.4 +#define OUTPUT_GAMMA 2.2 +#endif + +/* COMPATIBILITY + - GLSL compilers +*/ + +uniform vec2 TextureSize; +#if defined(CURVATURE) +varying vec2 screenScale; +#endif +varying vec2 TEX0; +varying float filterWidth; + +#if defined(VERTEX) +uniform mat4 MVPMatrix; +attribute vec4 VertexCoord; +attribute vec2 TexCoord; +uniform vec2 InputSize; +uniform vec2 OutputSize; + +void main() +{ +#if defined(CURVATURE) + screenScale = TextureSize / InputSize; +#endif + filterWidth = (InputSize.y / OutputSize.y) / 3.0; + TEX0 = TexCoord; + gl_Position = MVPMatrix * VertexCoord; +} +#elif defined(FRAGMENT) + +uniform sampler2D Texture; + +#if defined(CURVATURE) +vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y); +// Barrel distortion shrinks the display area a bit, this will allow us to counteract that. +vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION); + +vec2 Distort(vec2 coord) +{ + coord *= screenScale; + coord -= vec2(0.5); + float rsq = coord.x * coord.x + coord.y * coord.y; + coord += coord * (CURVATURE_DISTORTION * rsq); + coord *= barrelScale; + if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5) + coord = vec2(-1.0); // If out of bounds, return an invalid value. + else + { + coord += vec2(0.5); + coord /= screenScale; + } + + return coord; +} +#endif + +float CalcScanLineWeight(float dist) +{ + return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS); +} + +float CalcScanLine(float dy) +{ + float scanLineWeight = CalcScanLineWeight(dy); +#if defined(MULTISAMPLE) + scanLineWeight += CalcScanLineWeight(dy-filterWidth); + scanLineWeight += CalcScanLineWeight(dy+filterWidth); + scanLineWeight *= 0.3333333; +#endif + return scanLineWeight; +} + +void main() +{ +#if defined(CURVATURE) + vec2 texcoord = Distort(TEX0); + if (texcoord.x < 0.0) + gl_FragColor = vec4(0.0); + else +#else + vec2 texcoord = TEX0; +#endif + { + vec2 texcoordInPixels = texcoord * TextureSize; +#if defined(SHARPER) + vec2 tempCoord = floor(texcoordInPixels) + 0.5; + vec2 coord = tempCoord / TextureSize; + vec2 deltas = texcoordInPixels - tempCoord; + float scanLineWeight = CalcScanLine(deltas.y); + vec2 signs = sign(deltas); + deltas.x *= 2.0; + deltas = deltas * deltas; + deltas.y = deltas.y * deltas.y; + deltas.x *= 0.5; + deltas.y *= 8.0; + deltas /= TextureSize; + deltas *= signs; + vec2 tc = coord + deltas; +#else + float tempY = floor(texcoordInPixels.y) + 0.5; + float yCoord = tempY / TextureSize.y; + float dy = texcoordInPixels.y - tempY; + float scanLineWeight = CalcScanLine(dy); + float signY = sign(dy); + dy = dy * dy; + dy = dy * dy; + dy *= 8.0; + dy /= TextureSize.y; + dy *= signY; + vec2 tc = vec2(texcoord.x, yCoord + dy); +#endif + + vec3 colour = texture2D(Texture, tc).rgb; + +#if defined(SCANLINES) +#if defined(GAMMA) +#if defined(FAKE_GAMMA) + colour = colour * colour; +#else + colour = pow(colour, vec3(INPUT_GAMMA)); +#endif +#endif + scanLineWeight *= BLOOM_FACTOR; + colour *= scanLineWeight; + +#if defined(GAMMA) +#if defined(FAKE_GAMMA) + colour = sqrt(colour); +#else + colour = pow(colour, vec3(1.0/OUTPUT_GAMMA)); +#endif +#endif +#endif +#if MASK_TYPE == 0 + gl_FragColor = vec4(colour, 1.0); +#else +#if MASK_TYPE == 1 + float whichMask = fract(gl_FragCoord.x * 0.5); + vec3 mask; + if (whichMask < 0.5) + mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS); + else + mask = vec3(1.0, MASK_BRIGHTNESS, 1.0); +#elif MASK_TYPE == 2 + float whichMask = fract(gl_FragCoord.x * 0.3333333); + vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS); + if (whichMask < 0.3333333) + mask.x = 1.0; + else if (whichMask < 0.6666666) + mask.y = 1.0; + else + mask.z = 1.0; +#endif + + gl_FragColor = vec4(colour * mask, 1.0); +#endif + } +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/fakelottes.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/fakelottes.glsl new file mode 100644 index 000000000..86d68c496 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/fakelottes.glsl @@ -0,0 +1,280 @@ +// Simple scanlines with curvature and mask effects lifted from crt-lottes +// by hunterk + +//////////////////////////////////////////////////////////////////// +//////////////////////////// SETTINGS //////////////////////////// +///// comment these lines to disable effects and gain speed ////// +//////////////////////////////////////////////////////////////////// + +//#define MASK // fancy, expensive phosphor mask effect +#define CURVATURE // applies barrel distortion to the screen +#define SCANLINES // applies horizontal scanline effect +//#define ROTATE_SCANLINES // for TATE games; also disables the mask effects, which look bad with it +//#define EXTRA_MASKS // disable these if you need extra registers freed up + +//////////////////////////////////////////////////////////////////// +////////////////////////// END SETTINGS ////////////////////////// +//////////////////////////////////////////////////////////////////// + +/////////////////////// Runtime Parameters /////////////////////// +#pragma parameter shadowMask "shadowMask" 1.0 0.0 4.0 1.0 +#pragma parameter SCANLINE_SINE_COMP_B "Scanline Intensity" 0.40 0.0 1.0 0.05 +#pragma parameter warpX "warpX" 0.031 0.0 0.125 0.01 +#pragma parameter warpY "warpY" 0.041 0.0 0.125 0.01 +#pragma parameter maskDark "maskDark" 0.5 0.0 2.0 0.1 +#pragma parameter maskLight "maskLight" 1.5 0.0 2.0 0.1 +#pragma parameter crt_gamma "CRT Gamma" 2.5 1.0 4.0 0.05 +#pragma parameter monitor_gamma "Monitor Gamma" 2.2 1.0 4.0 0.05 +#pragma parameter SCANLINE_SINE_COMP_A "Scanline Sine Comp A" 0.0 0.0 0.10 0.01 +#pragma parameter SCANLINE_BASE_BRIGHTNESS "Scanline Base Brightness" 0.95 0.0 1.0 0.01 + +// prevent stupid behavior +#if defined ROTATE_SCANLINES && !defined SCANLINES + #define SCANLINES +#endif + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +vec4 _oPosition1; +uniform mat4 MVPMatrix; +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; + +// compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +uniform COMPAT_PRECISION float WHATEVER; +#else +#define WHATEVER 0.0 +#endif + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + TEX0.xy = TexCoord.xy; +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +// 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) + +#ifdef PARAMETER_UNIFORM +uniform COMPAT_PRECISION float SCANLINE_BASE_BRIGHTNESS; +uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_A; +uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_B; +uniform COMPAT_PRECISION float warpX; +uniform COMPAT_PRECISION float warpY; +uniform COMPAT_PRECISION float maskDark; +uniform COMPAT_PRECISION float maskLight; +uniform COMPAT_PRECISION float shadowMask; +uniform COMPAT_PRECISION float crt_gamma; +uniform COMPAT_PRECISION float monitor_gamma; +#else +#define SCANLINE_BASE_BRIGHTNESS 0.95 +#define SCANLINE_SINE_COMP_A 0.0 +#define SCANLINE_SINE_COMP_B 0.40 +#define warpX 0.031 +#define warpY 0.041 +#define maskDark 0.5 +#define maskLight 1.5 +#define shadowMask 1.0 +#define crt_gamma 2.5 +#define monitor_gamma 2.2 +#endif + +vec4 scanline(vec2 coord, vec4 frame) +{ +#if defined SCANLINES + vec2 omega = vec2(3.1415 * OutputSize.x, 2.0 * 3.1415 * TextureSize.y); + vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B); + vec3 res = frame.xyz; + #ifdef ROTATE_SCANLINES + sine_comp = sine_comp.yx; + omega = omega.yx; + #endif + vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(coord * omega), vec2(1.0, 1.0))); + + return vec4(scanline.x, scanline.y, scanline.z, 1.0); +#else + return frame; +#endif +} + +#ifdef CURVATURE +// Distortion of scanlines, and end of screen alpha. +vec2 Warp(vec2 pos) +{ + pos = pos*2.0-1.0; + pos *= vec2(1.0 + (pos.y*pos.y)*warpX, 1.0 + (pos.x*pos.x)*warpY); + + return pos*0.5 + 0.5; +} +#endif + +#if defined MASK && !defined ROTATE_SCANLINES + // Shadow mask. + vec4 Mask(vec2 pos) + { + vec3 mask = vec3(maskDark, maskDark, maskDark); + + // Very compressed TV style shadow mask. + if (shadowMask == 1.0) + { + float line = maskLight; + float odd = 0.0; + + if (fract(pos.x*0.166666666) < 0.5) odd = 1.0; + if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark; + + pos.x = fract(pos.x*0.333333333); + + if (pos.x < 0.333) mask.r = maskLight; + else if (pos.x < 0.666) mask.g = maskLight; + else mask.b = maskLight; + mask*=line; + } + + // Aperture-grille. + else if (shadowMask == 2.0) + { + pos.x = fract(pos.x*0.333333333); + + if (pos.x < 0.333) mask.r = maskLight; + else if (pos.x < 0.666) mask.g = maskLight; + else mask.b = maskLight; + } + #ifdef EXTRA_MASKS + // These can cause moire with curvature and scanlines + // so they're an easy target for freeing up registers + + // Stretched VGA style shadow mask (same as prior shaders). + else if (shadowMask == 3.0) + { + pos.x += pos.y*3.0; + pos.x = fract(pos.x*0.166666666); + + if (pos.x < 0.333) mask.r = maskLight; + else if (pos.x < 0.666) mask.g = maskLight; + else mask.b = maskLight; + } + + // VGA style shadow mask. + else if (shadowMask == 4.0) + { + pos.xy = floor(pos.xy*vec2(1.0, 0.5)); + pos.x += pos.y*3.0; + pos.x = fract(pos.x*0.166666666); + + if (pos.x < 0.333) mask.r = maskLight; + else if (pos.x < 0.666) mask.g = maskLight; + else mask.b = maskLight; + } + #endif + + else mask = vec3(1.,1.,1.); + + return vec4(mask, 1.0); + } +#endif + +void main() +{ +#ifdef CURVATURE + vec2 pos = Warp(TEX0.xy*(TextureSize.xy/InputSize.xy))*(InputSize.xy/TextureSize.xy); +#else + vec2 pos = TEX0.xy; +#endif + +#if defined MASK && !defined ROTATE_SCANLINES + // mask effects look bad unless applied in linear gamma space + vec4 in_gamma = vec4(monitor_gamma, monitor_gamma, monitor_gamma, 1.0); + vec4 out_gamma = vec4(1.0 / crt_gamma, 1.0 / crt_gamma, 1.0 / crt_gamma, 1.0); + vec4 res = pow(COMPAT_TEXTURE(Source, pos), in_gamma); +#else + vec4 res = COMPAT_TEXTURE(Source, pos); +#endif + +#if defined MASK && !defined ROTATE_SCANLINES + // apply the mask; looks bad with vert scanlines so make them mutually exclusive + res *= Mask(gl_FragCoord.xy * 1.0001); +#endif + +#if defined CURVATURE && defined GL_ES + // hacky clamp fix for GLES + vec2 bordertest = (pos); + if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999) + res = res; + else + res = vec4(0.,0.,0.,0.); +#endif + +#if defined MASK && !defined ROTATE_SCANLINES + // re-apply the gamma curve for the mask path + FragColor = pow(scanline(pos, res), out_gamma); +#else + FragColor = scanline(pos, res); +#endif +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/scanlines.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/scanlines.glsl new file mode 100644 index 000000000..7c8423b29 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/scanlines.glsl @@ -0,0 +1,106 @@ +// Parameter lines go here: +#pragma parameter SCANLINE_BASE_BRIGHTNESS "Scanline Base Brightness" 0.95 0.0 1.0 0.01 +#pragma parameter SCANLINE_SINE_COMP_A "Scanline Sine Comp A" 0.0 0.0 0.10 0.01 +#pragma parameter SCANLINE_SINE_COMP_B "Scanline Sine Comp B" 0.15 0.0 1.0 0.05 + +#define pi 3.141592654 + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec2 omega; + +vec4 _oPosition1; +uniform mat4 MVPMatrix; +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; + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + omega = vec2(pi * OutputSize.x, 2.0 * pi * TextureSize.y); +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec2 omega; + +// compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy + +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutputSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float SCANLINE_BASE_BRIGHTNESS; +uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_A; +uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_B; +#else +#define SCANLINE_BASE_BRIGHTNESS 0.95 +#define SCANLINE_SINE_COMP_A 0.0 +#define SCANLINE_SINE_COMP_B 0.15 +#endif + +void main() +{ + vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B); + vec3 res = COMPAT_TEXTURE(Source, vTexCoord).xyz; + vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(vTexCoord * omega), vec2(1.0, 1.0))); + FragColor = vec4(scanline.x, scanline.y, scanline.z, 1.0); +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/shaders/zfast_crt.glsl b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/zfast_crt.glsl new file mode 100644 index 000000000..ed982689f --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/shaders/zfast_crt.glsl @@ -0,0 +1,199 @@ +/* + zfast_crt_standard - A simple, fast CRT shader. + + Copyright (C) 2017 Greg Hogan (SoltanGris42) + + This program 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 2 of the License, or (at your option) + any later version. + + +Notes: This shader does scaling with a weighted linear filter for adjustable + sharpness on the x and y axes based on the algorithm by Inigo Quilez here: + http://http://www.iquilezles.org/www/articles/texture/texture.htm + but modified to be somewhat sharper. Then a scanline effect that varies + based on pixel brighness is applied along with a monochrome aperture mask. + This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s + resolutions (1920x1080 or 1600x1200). +*/ + +//For testing compilation +//#define FRAGMENT +//#define VERTEX + +//This can't be an option without slowing the shader down +//Comment this out for a coarser 3 pixel mask...which is currently broken +//on SNES Classic Edition due to Mali 400 gpu precision +#define FINEMASK +//Some drivers don't return black with texture coordinates out of bounds +//SNES Classic is too slow to black these areas out when using fullscreen +//overlays. But you can uncomment the below to black them out if necessary +//#define BLACK_OUT_BORDER + +// Parameter lines go here: +#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05 +#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5 +#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0 +#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05 +#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05 +#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05 + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING float maskFade; +COMPAT_VARYING vec2 invDims; + +vec4 _oPosition1; +uniform mat4 MVPMatrix; +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; + +// compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float BLURSCALEX; +//uniform COMPAT_PRECISION float BLURSCALEY; +uniform COMPAT_PRECISION float LOWLUMSCAN; +uniform COMPAT_PRECISION float HILUMSCAN; +uniform COMPAT_PRECISION float BRIGHTBOOST; +uniform COMPAT_PRECISION float MASK_DARK; +uniform COMPAT_PRECISION float MASK_FADE; +#else +#define BLURSCALEX 0.45 +//#define BLURSCALEY 0.20 +#define LOWLUMSCAN 5.0 +#define HILUMSCAN 10.0 +#define BRIGHTBOOST 1.25 +#define MASK_DARK 0.25 +#define MASK_FADE 0.8 +#endif + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + + TEX0.xy = (TexCoord.xy); + maskFade = 0.3333*MASK_FADE; + invDims = 1.0/TextureSize.xy; +} + +#elif defined(FRAGMENT) + +#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 + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + +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; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING float maskFade; +COMPAT_VARYING vec2 invDims; + +// compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float BLURSCALEX; +//uniform COMPAT_PRECISION float BLURSCALEY; +uniform COMPAT_PRECISION float LOWLUMSCAN; +uniform COMPAT_PRECISION float HILUMSCAN; +uniform COMPAT_PRECISION float BRIGHTBOOST; +uniform COMPAT_PRECISION float MASK_DARK; +uniform COMPAT_PRECISION float MASK_FADE; +#else +#define BLURSCALEX 0.45 +//#define BLURSCALEY 0.20 +#define LOWLUMSCAN 5.0 +#define HILUMSCAN 10.0 +#define BRIGHTBOOST 1.25 +#define MASK_DARK 0.25 +#define MASK_FADE 0.8 +#endif + +void main() +{ + + //This is just like "Quilez Scaling" but sharper + COMPAT_PRECISION vec2 p = vTexCoord * TextureSize; + COMPAT_PRECISION vec2 i = floor(p) + 0.50; + COMPAT_PRECISION vec2 f = p - i; + p = (i + 4.0*f*f*f)*invDims; + p.x = mix( p.x , vTexCoord.x, BLURSCALEX); + COMPAT_PRECISION float Y = f.y*f.y; + COMPAT_PRECISION float YY = Y*Y; + +#if defined(FINEMASK) + COMPAT_PRECISION float whichmask = fract( gl_FragCoord.x*-0.4999); + COMPAT_PRECISION float mask = 1.0 + float(whichmask < 0.5) * -MASK_DARK; +#else + COMPAT_PRECISION float whichmask = fract(gl_FragCoord.x * -0.3333); + COMPAT_PRECISION float mask = 1.0 + float(whichmask <= 0.33333) * -MASK_DARK; +#endif + COMPAT_PRECISION vec3 colour = COMPAT_TEXTURE(Source, p).rgb; + + COMPAT_PRECISION float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY)); + COMPAT_PRECISION float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y); + +#if defined(BLACK_OUT_BORDER) + colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing? +#endif + + FragColor.rgb = colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,vec3(maskFade))); + +} +#endif \ No newline at end of file diff --git a/packages/games/libretro/glsl-shaders/shaders/crt/zfast-crt.glslp b/packages/games/libretro/glsl-shaders/shaders/crt/zfast-crt.glslp new file mode 100644 index 000000000..3f35952ec --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/crt/zfast-crt.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/zfast_crt.glsl +filter_linear0 = true \ No newline at end of file diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glsl b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glsl new file mode 100644 index 000000000..88d5fed1d --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glsl @@ -0,0 +1,47 @@ +#if defined(VERTEX) + + +attribute vec4 VertexCoord; +attribute vec4 TexCoord; +varying vec4 TEX0; +uniform mat4 MVPMatrix; + +void main() { + gl_Position = VertexCoord.x*MVPMatrix[0] + VertexCoord.y*MVPMatrix[1] + VertexCoord.z*MVPMatrix[2] + VertexCoord.w*MVPMatrix[3]; + TEX0.xy = TexCoord.xy; +} + + +#elif defined(FRAGMENT) + + +precision mediump float; + +uniform sampler2D Texture; +varying vec4 TEX0; +uniform vec2 TextureSize; + +void main() { + + vec3 col; + float x = TEX0.x * TextureSize.x; + float y = floor(gl_FragCoord.y / 3.0) + 0.5; + float ymod = mod(gl_FragCoord.y, 3.0); + vec2 f0 = vec2(x, y); + vec2 uv0 = f0 / TextureSize.xy; + vec3 t0 = texture2D(Texture, uv0).xyz; + if (ymod > 2.0) { + vec2 f1 = vec2(x, y + 1.0); + vec2 uv1 = f1 / TextureSize.xy; + vec3 t1 = texture2D(Texture, uv1).xyz; + col = (t0 + t1) / 2.0 * 0.6; + } else { + col = t0; + } + + gl_FragColor = vec4( col, 1.0 ); + +} + + +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glslp b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glslp new file mode 100644 index 000000000..0f43f5df9 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x.glslp @@ -0,0 +1,9 @@ +shaders = 1 +shader0 = kurg-ROPi-scanlines-3x.glsl + +filter_linear0 = true + +scale_type_x0 = "viewport" +scale_x0 = "1.000000" +scale_type_y0 = "viewport" +scale_y0 = "1.000000" diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glsl b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glsl new file mode 100644 index 000000000..8701e8ebe --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glsl @@ -0,0 +1,45 @@ +#if defined(VERTEX) + + +attribute vec4 VertexCoord; +attribute vec4 TexCoord; +varying vec4 TEX0; +uniform mat4 MVPMatrix; + +void main() { + gl_Position = MVPMatrix * VertexCoord; + TEX0.xy = TexCoord.xy; +} + + +#elif defined(FRAGMENT) + + +precision mediump float; + +uniform sampler2D Texture; +varying vec4 TEX0; +uniform vec2 TextureSize; +uniform vec2 InputSize; + +void main() { + vec3 col; + if (InputSize.y > 220.0 && InputSize.y < 242.0) { + float x = TEX0.x; + float y = TEX0.y + (0.25 / TextureSize.y); + col = texture2D(Texture, vec2(x, y)).xyz; + float texel_y = TEX0.y * TextureSize.y * 3.0; + float ymod = mod(texel_y, 3.0); + if (ymod >= 1.5) { + col = col * 0.6; + } + } else { + col = texture2D(Texture, TEX0.xy).xyz; + } + + gl_FragColor = vec4( col, 1.0 ); + +} + + +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glslp b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glslp new file mode 100644 index 000000000..38d8dfcc2 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg-ROPi-scanlines-3x_v2.glslp @@ -0,0 +1,9 @@ +shaders = 1 +shader0 = kurg-ROPi-scanlines-3x_v2.glsl + +filter_linear0 = true + +scale_type_x0 = "viewport" +scale_x0 = "1.000000" +scale_type_y0 = "viewport" +scale_y0 = "1.000000" diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source.glsl b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source.glsl new file mode 100644 index 000000000..1fd68a0ec --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source.glsl @@ -0,0 +1,111 @@ +#if defined(VERTEX) + +#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_VARYING float _frame_rotation; + +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; + +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_VARYING vec4 COL0; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +void main() { + gl_Position = VertexCoord.x*MVPMatrix[0] + VertexCoord.y*MVPMatrix[1] + VertexCoord.z*MVPMatrix[2] + VertexCoord.w*MVPMatrix[3]; + TEX0.xy = TexCoord.xy; +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING float _frame_rotation; + +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; + +float _TMP2; +float _TMP1; +uniform sampler2D Texture; +input_dummy _IN1; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +void main() { + vec4 _res; + + _res = COMPAT_TEXTURE(Texture, TEX0.xy); + + _TMP1 = TEX0.y*TextureSize.y; + _TMP2 = fract(_TMP1); + if (_TMP2 < 0.5) { + FragColor = _res; + } else { + //FragColor = vec4(0.0, 0.0, 0.0, 0.0); + FragColor = _res * 0.5; + //FragColor = _res * 0.8; + } + + +} + + +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source_nearest.glslp b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source_nearest.glslp new file mode 100644 index 000000000..19858162e --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/kurg/kurg_scanlines_source_nearest.glslp @@ -0,0 +1,11 @@ +shaders = 1 +shader0 = kurg_scanlines_source.glsl + +filter_linear0 = false +#filter_linear0 = true + +scale_type_x0 = "source" +scale_x0 = "1.000000" +scale_type_y0 = "source" +scale_y0 = "3.000000" + diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/aa-shader-4.o.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/aa-shader-4.o.glsl new file mode 100644 index 000000000..34d9de95f --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/aa-shader-4.o.glsl @@ -0,0 +1,518 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec2 _texCoord11; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord11; +}; +out_vertex _ret_0; +vec4 _r0007; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _texCoord; + _r0007 = VertexCoord.x*MVPMatrix[0]; + _r0007 = _r0007 + VertexCoord.y*MVPMatrix[1]; + _r0007 = _r0007 + VertexCoord.z*MVPMatrix[2]; + _r0007 = _r0007 + VertexCoord.w*MVPMatrix[3]; + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _ret_0._position1 = _r0007; + _ret_0._color1 = COLOR; + _ret_0._texCoord11 = _texCoord; + gl_Position = _r0007; + COL0 = COLOR; + TEX0.xy = _texCoord; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord11; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord1; +}; +vec4 _ret_0; +float _TMP16; +vec3 _TMP15; +float _TMP14; +vec3 _TMP13; +float _TMP12; +vec3 _TMP11; +float _TMP10; +vec3 _TMP9; +float _TMP8; +vec3 _TMP7; +float _TMP6; +vec3 _TMP5; +float _TMP4; +vec3 _TMP3; +float _TMP2; +vec3 _TMP1; +float _TMP24; +vec3 _TMP23; +float _TMP22; +vec3 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec2 _TMP0; +vec2 _texcoord0037; +float _m10037; +float _m20037; +vec2 _c0039; +vec2 _c0041; +vec2 _c0043; +vec2 _c0045; +vec3 _a0047; +vec3 _a0051; +vec2 _texcoord0055; +float _m10055; +float _m20055; +vec2 _c0057; +vec2 _c0059; +vec2 _c0061; +vec2 _c0063; +vec3 _a0065; +vec3 _a0069; +vec2 _texcoord0073; +float _m10073; +float _m20073; +vec2 _c0075; +vec2 _c0077; +vec2 _c0079; +vec2 _c0081; +vec3 _a0083; +vec3 _a0087; +vec2 _texcoord0091; +float _m10091; +float _m20091; +vec2 _c0093; +vec2 _c0095; +vec2 _c0097; +vec2 _c0099; +vec3 _a0101; +vec3 _a0105; +float _m10109; +float _m20109; +vec2 _c0111; +vec2 _c0113; +vec2 _c0115; +vec2 _c0117; +vec3 _a0119; +vec3 _a0123; +vec2 _texcoord0127; +float _m10127; +float _m20127; +vec2 _c0129; +vec2 _c0131; +vec2 _c0133; +vec2 _c0135; +vec3 _a0137; +vec3 _a0141; +vec2 _texcoord0145; +float _m10145; +float _m20145; +vec2 _c0147; +vec2 _c0149; +vec2 _c0151; +vec2 _c0153; +vec3 _a0155; +vec3 _a0159; +vec2 _texcoord0163; +float _m10163; +float _m20163; +vec2 _c0165; +vec2 _c0167; +vec2 _c0169; +vec2 _c0171; +vec3 _a0173; +vec3 _a0177; +vec2 _texcoord0181; +float _m10181; +float _m20181; +vec2 _c0183; +vec2 _c0185; +vec2 _c0187; +vec2 _c0189; +vec3 _a0191; +vec3 _a0195; +vec3 _a0199; +vec3 _a0203; +vec3 _a0207; +vec3 _a0211; +vec3 _a0215; +vec3 _a0219; +vec3 _a0223; +vec3 _a0227; +COMPAT_VARYING vec4 TEX0; +sampler2D _TMP230; +uniform sampler2D Texture; +sampler2D _TMP232; +sampler2D _TMP233; +sampler2D _TMP234; +sampler2D _TMP235; +sampler2D _TMP236; +sampler2D _TMP237; +sampler2D _TMP238; +sampler2D _TMP239; +sampler2D _TMP240; +sampler2D _TMP241; +sampler2D _TMP242; +sampler2D _TMP243; +sampler2D _TMP244; +sampler2D _TMP245; +sampler2D _TMP246; +sampler2D _TMP247; +sampler2D _TMP248; +sampler2D _TMP249; +sampler2D _TMP250; +sampler2D _TMP251; +sampler2D _TMP252; +sampler2D _TMP253; +sampler2D _TMP254; +sampler2D _TMP255; +sampler2D _TMP256; +sampler2D _TMP257; +sampler2D _TMP258; +sampler2D _TMP259; +sampler2D _TMP260; +sampler2D _TMP261; +sampler2D _TMP262; +sampler2D _TMP263; +sampler2D _TMP264; +sampler2D _TMP265; +sampler2D _TMP266; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _OGL2Pos; + vec2 _fp; + vec2 _pC4; + vec3 _C0; + vec3 _C1; + vec3 _C2; + vec3 _C3; + vec3 _C4; + vec3 _C5; + vec3 _C6; + vec3 _C7; + vec3 _C8; + vec3 _ul; + vec3 _ur; + vec3 _dl; + vec3 _dr; + float _m11; + float _m21; + vec3 _c11; + _OGL2Pos = TEX0.xy*vec2( 1.28000000E+03, 1.12000000E+03); + _fp = fract(_OGL2Pos); + _TMP0 = floor(_OGL2Pos); + _pC4 = _TMP0*vec2( 7.81250012E-04, 8.92857148E-04); + _texcoord0037 = _pC4 - vec2( 7.81250012E-04, 8.92857148E-04); + _TMP230 = sampler2D(sampler(Texture)); + _c0039 = _texcoord0037 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP230, _c0039); + _TMP232 = sampler2D(sampler(Texture)); + _c0041 = _texcoord0037 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP232, _c0041); + _TMP233 = sampler2D(sampler(Texture)); + _c0043 = _texcoord0037 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP233, _c0043); + _TMP234 = sampler2D(sampler(Texture)); + _c0045 = _texcoord0037 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP234, _c0045); + _a0047 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0047); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10037 = _TMP22 + 1.00000005E-03; + _a0051 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0051); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20037 = _TMP24 + 1.00000005E-03; + _C0 = (5.00000000E-01*(_m20037*(_TMP17.xyz + _TMP19.xyz) + _m10037*(_TMP20.xyz + _TMP18.xyz)))/(_m10037 + _m20037); + _texcoord0055 = _pC4 - vec2( 0.00000000E+00, 8.92857148E-04); + _TMP235 = sampler2D(sampler(Texture)); + _c0057 = _texcoord0055 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP235, _c0057); + _TMP236 = sampler2D(sampler(Texture)); + _c0059 = _texcoord0055 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP236, _c0059); + _TMP237 = sampler2D(sampler(Texture)); + _c0061 = _texcoord0055 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP237, _c0061); + _TMP238 = sampler2D(sampler(Texture)); + _c0063 = _texcoord0055 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP238, _c0063); + _a0065 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0065); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10055 = _TMP22 + 1.00000005E-03; + _a0069 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0069); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20055 = _TMP24 + 1.00000005E-03; + _C1 = (5.00000000E-01*(_m20055*(_TMP17.xyz + _TMP19.xyz) + _m10055*(_TMP20.xyz + _TMP18.xyz)))/(_m10055 + _m20055); + _texcoord0073 = _pC4 - vec2( -7.81250012E-04, 8.92857148E-04); + _TMP239 = sampler2D(sampler(Texture)); + _c0075 = _texcoord0073 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP239, _c0075); + _TMP240 = sampler2D(sampler(Texture)); + _c0077 = _texcoord0073 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP240, _c0077); + _TMP241 = sampler2D(sampler(Texture)); + _c0079 = _texcoord0073 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP241, _c0079); + _TMP242 = sampler2D(sampler(Texture)); + _c0081 = _texcoord0073 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP242, _c0081); + _a0083 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0083); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10073 = _TMP22 + 1.00000005E-03; + _a0087 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0087); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20073 = _TMP24 + 1.00000005E-03; + _C2 = (5.00000000E-01*(_m20073*(_TMP17.xyz + _TMP19.xyz) + _m10073*(_TMP20.xyz + _TMP18.xyz)))/(_m10073 + _m20073); + _texcoord0091 = _pC4 - vec2( 7.81250012E-04, 0.00000000E+00); + _TMP243 = sampler2D(sampler(Texture)); + _c0093 = _texcoord0091 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP243, _c0093); + _TMP244 = sampler2D(sampler(Texture)); + _c0095 = _texcoord0091 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP244, _c0095); + _TMP245 = sampler2D(sampler(Texture)); + _c0097 = _texcoord0091 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP245, _c0097); + _TMP246 = sampler2D(sampler(Texture)); + _c0099 = _texcoord0091 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP246, _c0099); + _a0101 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0101); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10091 = _TMP22 + 1.00000005E-03; + _a0105 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0105); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20091 = _TMP24 + 1.00000005E-03; + _C3 = (5.00000000E-01*(_m20091*(_TMP17.xyz + _TMP19.xyz) + _m10091*(_TMP20.xyz + _TMP18.xyz)))/(_m10091 + _m20091); + _TMP247 = sampler2D(sampler(Texture)); + _c0111 = _pC4 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP247, _c0111); + _TMP248 = sampler2D(sampler(Texture)); + _c0113 = _pC4 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP248, _c0113); + _TMP249 = sampler2D(sampler(Texture)); + _c0115 = _pC4 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP249, _c0115); + _TMP250 = sampler2D(sampler(Texture)); + _c0117 = _pC4 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP250, _c0117); + _a0119 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0119); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10109 = _TMP22 + 1.00000005E-03; + _a0123 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0123); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20109 = _TMP24 + 1.00000005E-03; + _C4 = (5.00000000E-01*(_m20109*(_TMP17.xyz + _TMP19.xyz) + _m10109*(_TMP20.xyz + _TMP18.xyz)))/(_m10109 + _m20109); + _texcoord0127 = _pC4 + vec2( 7.81250012E-04, 0.00000000E+00); + _TMP251 = sampler2D(sampler(Texture)); + _c0129 = _texcoord0127 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP251, _c0129); + _TMP252 = sampler2D(sampler(Texture)); + _c0131 = _texcoord0127 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP252, _c0131); + _TMP253 = sampler2D(sampler(Texture)); + _c0133 = _texcoord0127 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP253, _c0133); + _TMP254 = sampler2D(sampler(Texture)); + _c0135 = _texcoord0127 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP254, _c0135); + _a0137 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0137); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10127 = _TMP22 + 1.00000005E-03; + _a0141 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0141); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20127 = _TMP24 + 1.00000005E-03; + _C5 = (5.00000000E-01*(_m20127*(_TMP17.xyz + _TMP19.xyz) + _m10127*(_TMP20.xyz + _TMP18.xyz)))/(_m10127 + _m20127); + _texcoord0145 = _pC4 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP255 = sampler2D(sampler(Texture)); + _c0147 = _texcoord0145 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP255, _c0147); + _TMP256 = sampler2D(sampler(Texture)); + _c0149 = _texcoord0145 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP256, _c0149); + _TMP257 = sampler2D(sampler(Texture)); + _c0151 = _texcoord0145 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP257, _c0151); + _TMP258 = sampler2D(sampler(Texture)); + _c0153 = _texcoord0145 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP258, _c0153); + _a0155 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0155); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10145 = _TMP22 + 1.00000005E-03; + _a0159 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0159); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20145 = _TMP24 + 1.00000005E-03; + _C6 = (5.00000000E-01*(_m20145*(_TMP17.xyz + _TMP19.xyz) + _m10145*(_TMP20.xyz + _TMP18.xyz)))/(_m10145 + _m20145); + _texcoord0163 = _pC4 + vec2( 0.00000000E+00, 8.92857148E-04); + _TMP259 = sampler2D(sampler(Texture)); + _c0165 = _texcoord0163 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP259, _c0165); + _TMP260 = sampler2D(sampler(Texture)); + _c0167 = _texcoord0163 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP260, _c0167); + _TMP261 = sampler2D(sampler(Texture)); + _c0169 = _texcoord0163 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP261, _c0169); + _TMP262 = sampler2D(sampler(Texture)); + _c0171 = _texcoord0163 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP262, _c0171); + _a0173 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0173); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10163 = _TMP22 + 1.00000005E-03; + _a0177 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0177); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20163 = _TMP24 + 1.00000005E-03; + _C7 = (5.00000000E-01*(_m20163*(_TMP17.xyz + _TMP19.xyz) + _m10163*(_TMP20.xyz + _TMP18.xyz)))/(_m10163 + _m20163); + _texcoord0181 = _pC4 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP263 = sampler2D(sampler(Texture)); + _c0183 = _texcoord0181 + vec2( -7.81250012E-04, -8.92857148E-04); + _TMP17 = COMPAT_TEXTURE(_TMP263, _c0183); + _TMP264 = sampler2D(sampler(Texture)); + _c0185 = _texcoord0181 + vec2( 7.81250012E-04, -8.92857148E-04); + _TMP18 = COMPAT_TEXTURE(_TMP264, _c0185); + _TMP265 = sampler2D(sampler(Texture)); + _c0187 = _texcoord0181 + vec2( 7.81250012E-04, 8.92857148E-04); + _TMP19 = COMPAT_TEXTURE(_TMP265, _c0187); + _TMP266 = sampler2D(sampler(Texture)); + _c0189 = _texcoord0181 + vec2( -7.81250012E-04, 8.92857148E-04); + _TMP20 = COMPAT_TEXTURE(_TMP266, _c0189); + _a0191 = _TMP17.xyz - _TMP19.xyz; + _TMP21 = abs(_a0191); + _TMP22 = dot(_TMP21, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m10181 = _TMP22 + 1.00000005E-03; + _a0195 = _TMP20.xyz - _TMP18.xyz; + _TMP23 = abs(_a0195); + _TMP24 = dot(_TMP23, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m20181 = _TMP24 + 1.00000005E-03; + _C8 = (5.00000000E-01*(_m20181*(_TMP17.xyz + _TMP19.xyz) + _m10181*(_TMP20.xyz + _TMP18.xyz)))/(_m10181 + _m20181); + _a0199 = _C0 - _C4; + _TMP1 = abs(_a0199); + _TMP2 = dot(_TMP1, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m11 = _TMP2 + 1.00000005E-03; + _a0203 = _C1 - _C3; + _TMP3 = abs(_a0203); + _TMP4 = dot(_TMP3, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m21 = _TMP4 + 1.00000005E-03; + _ul = (_m21*(_C0 + _C4) + _m11*(_C1 + _C3))/(_m11 + _m21); + _a0207 = _C1 - _C5; + _TMP5 = abs(_a0207); + _TMP6 = dot(_TMP5, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m11 = _TMP6 + 1.00000005E-03; + _a0211 = _C2 - _C4; + _TMP7 = abs(_a0211); + _TMP8 = dot(_TMP7, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m21 = _TMP8 + 1.00000005E-03; + _ur = (_m21*(_C1 + _C5) + _m11*(_C2 + _C4))/(_m11 + _m21); + _a0215 = _C3 - _C7; + _TMP9 = abs(_a0215); + _TMP10 = dot(_TMP9, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m11 = _TMP10 + 1.00000005E-03; + _a0219 = _C6 - _C4; + _TMP11 = abs(_a0219); + _TMP12 = dot(_TMP11, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m21 = _TMP12 + 1.00000005E-03; + _dl = (_m21*(_C3 + _C7) + _m11*(_C6 + _C4))/(_m11 + _m21); + _a0223 = _C4 - _C8; + _TMP13 = abs(_a0223); + _TMP14 = dot(_TMP13, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m11 = _TMP14 + 1.00000005E-03; + _a0227 = _C5 - _C7; + _TMP15 = abs(_a0227); + _TMP16 = dot(_TMP15, vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00)); + _m21 = _TMP16 + 1.00000005E-03; + _dr = (_m21*(_C4 + _C8) + _m11*(_C5 + _C7))/(_m11 + _m21); + _c11 = 5.00000000E-01*((_dr*_fp.x + _dl*(1.00000000E+00 - _fp.x))*_fp.y + (_ur*_fp.x + _ul*(1.00000000E+00 - _fp.x))*(1.00000000E+00 - _fp.y)); + _ret_0 = vec4(_c11.x, _c11.y, _c11.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/advanced-aa.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/advanced-aa.glsl new file mode 100644 index 000000000..377a86e9b --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/advanced-aa.glsl @@ -0,0 +1,293 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t41; +COMPAT_VARYING vec4 _t31; +COMPAT_VARYING vec4 _t21; +COMPAT_VARYING vec4 _t11; +COMPAT_VARYING vec2 _CT; +COMPAT_VARYING vec4 _position2; +COMPAT_VARYING vec4 _color2; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; +}; +struct output_dummy { + vec4 _color2; +}; +struct VERTEX_INPUT { + vec4 _position2; + vec2 _CT; + vec4 _t11; + vec4 _t21; + vec4 _t31; + vec4 _t41; +}; +VERTEX_OUTPUT _ret_0; +float _TMP2; +float _TMP1; +input_dummy _IN1; +vec4 _r0009; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + VERTEX_OUTPUT _OUT; + vec2 _ps; + float _dx; + float _dy; + vec2 _texCoord; + _r0009 = VertexCoord.x*MVPMatrix[0]; + _r0009 = _r0009 + VertexCoord.y*MVPMatrix[1]; + _r0009 = _r0009 + VertexCoord.z*MVPMatrix[2]; + _r0009 = _r0009 + VertexCoord.w*MVPMatrix[3]; + if (TextureSize.x == 0.00000000E+00) { + _TMP1 = TextureSize.x; + } else { + _TMP1 = TextureSize.x; + } + if (TextureSize.y == 0.00000000E+00) { + _TMP2 = TextureSize.y; + } else { + _TMP2 = TextureSize.y; + } + _ps = vec2(1.00000000E+00/_TMP1, 1.00000000E+00/_TMP2); + _dx = _ps.x*5.00000000E-01; + _dy = _ps.y*5.00000000E-01; + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = _texCoord + vec2(-_dx, 0.00000000E+00); + _OUT._t2.xy = _texCoord + vec2(_dx, 0.00000000E+00); + _OUT._t3.xy = _texCoord + vec2(0.00000000E+00, -_dy); + _OUT._t4.xy = _texCoord + vec2(0.00000000E+00, _dy); + _OUT._t1.zw = _texCoord + vec2(-_dx, -_dy); + _OUT._t2.zw = _texCoord + vec2(-_dx, _dy); + _OUT._t3.zw = _texCoord + vec2(_dx, -_dy); + _OUT._t4.zw = _texCoord + vec2(_dx, _dy); + _ret_0._position1 = _r0009; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + gl_Position = _r0009; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t21; +COMPAT_VARYING vec4 _t11; +COMPAT_VARYING vec2 _CT; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _t41; +COMPAT_VARYING vec4 _t31; +COMPAT_VARYING vec4 _t22; +COMPAT_VARYING vec4 _t12; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _color; + vec2 _texCoord; + vec4 _t12; + vec4 _t22; + vec4 _t31; + vec4 _t41; +}; +struct output_dummy { + vec4 _color1; +}; +struct VERTEX_INPUT { + vec2 _CT; + vec4 _t11; + vec4 _t21; + vec4 _t3; + vec4 _t4; +}; +float _TMP20; +vec3 _TMP19; +float _TMP18; +vec3 _TMP17; +float _TMP16; +vec3 _TMP15; +float _TMP14; +vec3 _TMP13; +float _TMP12; +vec3 _TMP11; +float _TMP10; +vec3 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +vec3 _a0045; +vec3 _a0049; +vec3 _a0053; +vec3 _a0057; +vec3 _a0061; +vec3 _a0065; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +uniform vec3 _dt; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + output_dummy _OUT; + float _d1; + float _d2; + float _hl; + float _vl; + float _k1; + float _k2; + vec3 _t1; + vec3 _t2; + vec3 _TMP25; + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX3.xy); + _TMP2 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX1.xy); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.xy); + _TMP6 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX4.xy); + _TMP8 = COMPAT_TEXTURE(Texture, TEX4.zw); + _a0045 = _TMP0.xyz - _TMP8.xyz; + _TMP9 = abs(_a0045); + _TMP10 = dot(_TMP9, _dt); + _d1 = _TMP10 + 9.99999975E-05; + _a0049 = _TMP2.xyz - _TMP6.xyz; + _TMP11 = abs(_a0049); + _TMP12 = dot(_TMP11, _dt); + _d2 = _TMP12 + 9.99999975E-05; + _a0053 = _TMP3.xyz - _TMP5.xyz; + _TMP13 = abs(_a0053); + _TMP14 = dot(_TMP13, _dt); + _hl = _TMP14 + 9.99999975E-05; + _a0057 = _TMP1.xyz - _TMP7.xyz; + _TMP15 = abs(_a0057); + _TMP16 = dot(_TMP15, _dt); + _vl = _TMP16 + 9.99999975E-05; + _k1 = 5.00000000E-01*(_hl + _vl); + _k2 = 5.00000000E-01*(_d1 + _d2); + _t1 = (_hl*(_TMP1.xyz + _TMP7.xyz) + _vl*(_TMP3.xyz + _TMP5.xyz) + _k1*_TMP4.xyz)/(2.50000000E+00*(_hl + _vl)); + _t2 = (_d1*(_TMP2.xyz + _TMP6.xyz) + _d2*(_TMP0.xyz + _TMP8.xyz) + _k2*_TMP4.xyz)/(2.50000000E+00*(_d1 + _d2)); + _a0061 = _t1 - _TMP4.xyz; + _TMP17 = abs(_a0061); + _TMP18 = dot(_TMP17, _dt); + _k1 = _TMP18 + 9.99999975E-05; + _a0065 = _t2 - _TMP4.xyz; + _TMP19 = abs(_a0065); + _TMP20 = dot(_TMP19, _dt); + _k2 = _TMP20 + 9.99999975E-05; + _TMP25 = (_k1*_t2 + _k2*_t1)/(_k1 + _k2); + _OUT._color1 = vec4(_TMP25.x, _TMP25.y, _TMP25.z, 1.00000000E+00); + FragColor = _OUT._color1; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fx-aa.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fx-aa.glsl new file mode 100644 index 000000000..24339604a --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fx-aa.glsl @@ -0,0 +1,220 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _color; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _vpos1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _position1; + vec4 _vpos1; + vec2 _texCoord1; +}; +struct output_dummy { + vec4 _color; +}; +VERTEX_OUTPUT _ret_0; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ret_0._position1 = _r0006; + _ret_0._vpos1 = _r0006; + _ret_0._texCoord1 = TexCoord.xy; + gl_Position = _r0006; + TEX1 = _r0006; + TEX0.xy = TexCoord.xy; + return; + TEX1 = _ret_0._vpos1; + TEX0.xy = _ret_0._texCoord1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _color; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _vpos; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _vpos; + vec2 _texCoord; +}; +struct output_dummy { + vec4 _color; +}; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec2 _TMP15; +vec2 _TMP14; +float _TMP13; +float _TMP12; +float _TMP11; +float _TMP10; +float _TMP9; +float _TMP8; +float _TMP7; +float _TMP6; +float _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _c0026; +vec2 _c0028; +vec2 _c0030; +vec2 _c0032; +float _a0062; +vec2 _b0070; +vec2 _c0074; +vec2 _c0076; +vec2 _c0078; +vec2 _c0080; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + output_dummy _OUT; + vec2 _inverse_resolution; + float _lumaNW; + float _lumaNE; + float _lumaSW; + float _lumaSE; + float _lumaM; + float _lumaMin; + float _lumaMax; + vec2 _dir; + float _dirReduce; + float _rcpDirMin; + vec3 _rgbA; + vec3 _rgbB; + float _lumaB; + _inverse_resolution = 1.00000000E+00/InputSize.xy; + _c0026 = (TEX0.xy + vec2( -1.00000000E+00, -1.00000000E+00))*_inverse_resolution; + _TMP0 = COMPAT_TEXTURE(Texture, _c0026); + _c0028 = (TEX0.xy + vec2( 1.00000000E+00, -1.00000000E+00))*_inverse_resolution; + _TMP1 = COMPAT_TEXTURE(Texture, _c0028); + _c0030 = (TEX0.xy + vec2( -1.00000000E+00, 1.00000000E+00))*_inverse_resolution; + _TMP2 = COMPAT_TEXTURE(Texture, _c0030); + _c0032 = (TEX0.xy + vec2( 1.00000000E+00, 1.00000000E+00))*_inverse_resolution; + _TMP3 = COMPAT_TEXTURE(Texture, _c0032); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _lumaNW = dot(_TMP0.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaNE = dot(_TMP1.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaSW = dot(_TMP2.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaSE = dot(_TMP3.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaM = dot(_TMP4.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _TMP5 = min(_lumaNW, _lumaNE); + _TMP6 = min(_lumaSW, _lumaSE); + _TMP7 = min(_TMP5, _TMP6); + _lumaMin = min(_lumaM, _TMP7); + _TMP8 = max(_lumaNW, _lumaNE); + _TMP9 = max(_lumaSW, _lumaSE); + _TMP10 = max(_TMP8, _TMP9); + _lumaMax = max(_lumaM, _TMP10); + _dir.x = -((_lumaNW + _lumaNE) - (_lumaSW + _lumaSE)); + _dir.y = (_lumaNW + _lumaSW) - (_lumaNE + _lumaSE); + _a0062 = (_lumaNW + _lumaNE + _lumaSW + _lumaSE)*3.12500000E-02; + _dirReduce = max(_a0062, 3.90625000E-03); + _TMP11 = abs(_dir.x); + _TMP12 = abs(_dir.y); + _TMP13 = min(_TMP11, _TMP12); + _rcpDirMin = 1.00000000E+00/(_TMP13 + _dirReduce); + _b0070 = _dir*_rcpDirMin; + _TMP14 = max(vec2( -8.00000000E+00, -8.00000000E+00), _b0070); + _TMP15 = min(vec2( 8.00000000E+00, 8.00000000E+00), _TMP14); + _dir = _TMP15*_inverse_resolution; + _c0074 = TEX0.xy + _dir*-1.66666657E-01; + _TMP16 = COMPAT_TEXTURE(Texture, _c0074); + _c0076 = TEX0.xy + _dir*1.66666687E-01; + _TMP17 = COMPAT_TEXTURE(Texture, _c0076); + _rgbA = 5.00000000E-01*(_TMP16.xyz + _TMP17.xyz); + _c0078 = TEX0.xy*_inverse_resolution + _dir*-5.00000000E-01; + _TMP18 = COMPAT_TEXTURE(Texture, _c0078); + _c0080 = TEX0.xy + _dir*5.00000000E-01; + _TMP19 = COMPAT_TEXTURE(Texture, _c0080); + _rgbB = _rgbA*5.00000000E-01 + 2.50000000E-01*(_TMP18.xyz + _TMP19.xyz); + _lumaB = dot(_rgbB, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + if (_lumaB < _lumaMin || _lumaB > _lumaMax) { + _OUT._color = vec4(_rgbA.x, _rgbA.y, _rgbA.z, 1.00000000E+00); + } else { + _OUT._color = vec4(_rgbB.x, _rgbB.y, _rgbB.z, 1.00000000E+00); + } + FragColor = _OUT._color; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fxaa-edge-detect.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fxaa-edge-detect.glsl new file mode 100644 index 000000000..669f6a204 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/fxaa-edge-detect.glsl @@ -0,0 +1,180 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec2 _M; +COMPAT_VARYING vec2 _DR; +COMPAT_VARYING vec2 _DL; +COMPAT_VARYING vec2 _UR; +COMPAT_VARYING vec2 _UL; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _vpos1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _position1; + vec4 _vpos1; + vec2 _texCoord1; +}; +struct output_dummy { + vec4 _color; +}; +struct deltas { + vec2 _UL; + vec2 _UR; + vec2 _DL; + vec2 _DR; + vec2 _M; +}; +VERTEX_OUTPUT _ret_0; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ret_0._position1 = _r0006; + _ret_0._vpos1 = _r0006; + _ret_0._texCoord1 = TexCoord.xy; + gl_Position = _r0006; + TEX1 = _r0006; + TEX0.xy = TexCoord.xy; + return; + TEX1 = _ret_0._vpos1; + TEX0.xy = _ret_0._texCoord1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec2 _M; +COMPAT_VARYING vec2 _DR; +COMPAT_VARYING vec2 _DL; +COMPAT_VARYING vec2 _UR; +COMPAT_VARYING vec2 _UL; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _vpos; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct VERTEX_OUTPUT { + vec4 _vpos; + vec2 _texCoord; +}; +struct output_dummy { + vec4 _color; +}; +struct deltas { + vec2 _UL; + vec2 _UR; + vec2 _DL; + vec2 _DR; + vec2 _M; +}; +float _TMP12; +float _TMP11; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + output_dummy _OUT; + vec2 _ps; + float _lumaUL; + float _lumaUR; + float _lumaDL; + float _lumaDR; + vec2 _dir; + deltas _TMP16; + _ps = vec2(9.99899983E-01/TextureSize.x, 9.99899983E-01/TextureSize.y); + _TMP16._UL = TEX0.xy + vec2(-_ps.x, -_ps.y); + _TMP16._UR = TEX0.xy + vec2(_ps.x, -_ps.y); + _TMP16._DL = TEX0.xy + vec2(-_ps.x, _ps.y); + _TMP16._DR = TEX0.xy + vec2(_ps.x, _ps.y); + _TMP0 = COMPAT_TEXTURE(Texture, _TMP16._UL); + _TMP1 = COMPAT_TEXTURE(Texture, _TMP16._UR); + _TMP2 = COMPAT_TEXTURE(Texture, _TMP16._DL); + _TMP3 = COMPAT_TEXTURE(Texture, _TMP16._DR); + _lumaUL = dot(_TMP0.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaUR = dot(_TMP1.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaDL = dot(_TMP2.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _lumaDR = dot(_TMP3.xyz, vec3( 2.98999995E-01, 5.87000012E-01, 1.14000000E-01)); + _dir.x = -((_lumaUL + _lumaUR) - (_lumaDR + _lumaDL)); + _dir.y = (_lumaUR + _lumaDR) - (_lumaUL + _lumaDL); + _TMP11 = abs(_dir.x); + _TMP12 = abs(_dir.y); + _OUT._color = vec4(_TMP11 + _TMP12, _TMP11 + _TMP12, _TMP11 + _TMP12, _TMP11 + _TMP12); + FragColor = _OUT._color; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/reverse-aa.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/reverse-aa.glsl new file mode 100644 index 000000000..b032f0372 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/aa/reverse-aa.glsl @@ -0,0 +1,267 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0006; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t21; +COMPAT_VARYING vec4 _t11; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t11; + vec4 _t21; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP14; +vec3 _TMP13; +vec3 _TMP12; +vec3 _TMP11; +vec3 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec2 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0023; +vec3 _TMP190043[4]; +vec3 _m0043; +vec3 _t0043; +vec3 _TMP52; +vec3 _a0053; +vec3 _TMP190059[4]; +vec3 _m0059; +vec3 _t0059; +vec3 _TMP68; +vec3 _a0069; +vec3 _x0075; +vec3 _TMP76; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + _x0023 = TEX0.xy*TextureSize; + _TMP0 = fract(_x0023); + _fp = 2.00000000E+00*_TMP0 - 1.00000000E+00; + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP9 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP190043[0] = _TMP2.xyz - _TMP1.xyz; + _TMP190043[1] = _TMP4.xyz - _TMP2.xyz; + _TMP190043[2] = _TMP6.xyz - _TMP4.xyz; + _TMP190043[3] = _TMP7.xyz - _TMP6.xyz; + _m0043 = vec3(_TMP4.x < 5.00000000E-01 ? _TMP4.x : (1.00000000E+00 - _TMP4.xyz).x, _TMP4.y < 5.00000000E-01 ? _TMP4.y : (1.00000000E+00 - _TMP4.xyz).y, _TMP4.z < 5.00000000E-01 ? _TMP4.z : (1.00000000E+00 - _TMP4.xyz).z); + _TMP10 = abs(_TMP190043[1]); + _TMP11 = abs(_TMP190043[2]); + _TMP12 = min(_TMP10, _TMP11); + _TMP13 = min(_m0043, _TMP12); + _m0043 = 2.00000000E+00*_TMP13; + _t0043 = (7.00000000E+00*(_TMP190043[1] + _TMP190043[2]) - 3.00000000E+00*(_TMP190043[0] + _TMP190043[3]))/1.60000000E+01; + _a0053 = -_m0043; + _TMP14 = min(_m0043, _t0043); + _TMP52 = max(_a0053, _TMP14); + _TMP190059[0] = _TMP3.xyz - _TMP8.xyz; + _TMP190059[1] = _TMP4.xyz - _TMP3.xyz; + _TMP190059[2] = _TMP5.xyz - _TMP4.xyz; + _TMP190059[3] = _TMP9.xyz - _TMP5.xyz; + _m0059 = vec3(_TMP4.x < 5.00000000E-01 ? _TMP4.x : (1.00000000E+00 - _TMP4.xyz).x, _TMP4.y < 5.00000000E-01 ? _TMP4.y : (1.00000000E+00 - _TMP4.xyz).y, _TMP4.z < 5.00000000E-01 ? _TMP4.z : (1.00000000E+00 - _TMP4.xyz).z); + _TMP10 = abs(_TMP190059[1]); + _TMP11 = abs(_TMP190059[2]); + _TMP12 = min(_TMP10, _TMP11); + _TMP13 = min(_m0059, _TMP12); + _m0059 = 2.00000000E+00*_TMP13; + _t0059 = (7.00000000E+00*(_TMP190059[1] + _TMP190059[2]) - 3.00000000E+00*(_TMP190059[0] + _TMP190059[3]))/1.60000000E+01; + _a0069 = -_m0059; + _TMP14 = min(_m0059, _t0059); + _TMP68 = max(_a0069, _TMP14); + _x0075 = _TMP4.xyz + _fp.y*_TMP52 + _fp.x*_TMP68; + _TMP14 = min(vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0075); + _TMP76 = max(vec3( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP14); + _ret_0 = vec4(_TMP76.x, _TMP76.y, _TMP76.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v2.2.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v2.2.glsl new file mode 100644 index 000000000..4f667dbcf --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v2.2.glsl @@ -0,0 +1,467 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color1; +struct output_dummy { + vec4 _color1; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +vec4 _oPosition1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec4 _oColor; + vec2 _otexCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _oPosition1 = _r0006; + _oColor = COLOR; + _otexCoord = TexCoord.xy; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color1; +struct output_dummy { + vec4 _color1; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +vec3 _TMP28; +vec3 _TMP30; +vec3 _TMP29; +vec4 _TMP24; +vec4 _TMP23; +vec4 _TMP22; +vec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _c0038; +vec2 _c0040; +vec2 _c0042; +vec2 _c0044; +vec2 _c0048; +vec2 _c0050; +vec2 _c0052; +vec2 _c0054; +vec2 _c0056; +vec2 _c0058; +vec2 _c0060; +vec2 _c0062; +vec2 _c0064; +vec2 _c0066; +vec2 _c0068; +vec2 _c0070; +vec2 _c0072; +vec2 _c0074; +vec2 _c0076; +vec2 _c0078; +vec2 _c0080; +vec2 _c0082; +vec2 _c0084; +vec2 _c0086; +float _TMP87; +float _TMP91; +float _TMP95; +float _TMP99; +float _TMP103; +float _TMP107; +float _TMP111; +float _TMP115; +float _TMP119; +float _TMP123; +float _TMP127; +float _TMP131; +float _TMP135; +float _TMP139; +float _TMP143; +float _TMP147; +float _TMP151; +float _TMP155; +float _TMP159; +float _TMP163; +float _TMP167; +float _TMP171; +float _TMP175; +float _TMP179; +float _TMP183; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _ps; + vec2 _dx; + vec2 _dy; + vec2 _pixcoord; + vec2 _fp; + vec2 _d11; + vec3 _E[4]; + output_dummy _OUT; + _ps = vec2(9.99899983E-01/TextureSize.x, 9.99899983E-01/TextureSize.y); + _dx = vec2(_ps.x, 0.00000000E+00); + _dy = vec2(0.00000000E+00, _ps.y); + _pixcoord = TEX0.xy/_ps; + _fp = fract(_pixcoord); + _d11 = TEX0.xy - _fp*_ps; + _c0038 = (_d11 - _dx) - _dy; + _TMP0 = COMPAT_TEXTURE(Texture, _c0038); + _c0040 = _d11 - _dy; + _TMP1 = COMPAT_TEXTURE(Texture, _c0040); + _c0042 = (_d11 + _dx) - _dy; + _TMP2 = COMPAT_TEXTURE(Texture, _c0042); + _c0044 = _d11 - _dx; + _TMP3 = COMPAT_TEXTURE(Texture, _c0044); + _TMP4 = COMPAT_TEXTURE(Texture, _d11); + _c0048 = _d11 + _dx; + _TMP5 = COMPAT_TEXTURE(Texture, _c0048); + _c0050 = (_d11 - _dx) + _dy; + _TMP6 = COMPAT_TEXTURE(Texture, _c0050); + _c0052 = _d11 + _dy; + _TMP7 = COMPAT_TEXTURE(Texture, _c0052); + _c0054 = _d11 + _dx + _dy; + _TMP8 = COMPAT_TEXTURE(Texture, _c0054); + _c0056 = (((_d11 - _dx) - _dx) - _dy) - _dy; + _TMP9 = COMPAT_TEXTURE(Texture, _c0056); + _c0058 = ((_d11 + _dx + _dx) - _dy) - _dy; + _TMP10 = COMPAT_TEXTURE(Texture, _c0058); + _c0060 = ((_d11 - _dx) - _dx) + _dy + _dy; + _TMP11 = COMPAT_TEXTURE(Texture, _c0060); + _c0062 = _d11 + _dx + _dx + _dy + _dy; + _TMP12 = COMPAT_TEXTURE(Texture, _c0062); + _c0064 = ((_d11 - _dx) - _dy) - _dy; + _TMP13 = COMPAT_TEXTURE(Texture, _c0064); + _c0066 = (_d11 - _dy) - _dy; + _TMP14 = COMPAT_TEXTURE(Texture, _c0066); + _c0068 = ((_d11 + _dx) - _dy) - _dy; + _TMP15 = COMPAT_TEXTURE(Texture, _c0068); + _c0070 = ((_d11 - _dx) - _dx) - _dy; + _TMP16 = COMPAT_TEXTURE(Texture, _c0070); + _c0072 = (_d11 - _dx) - _dx; + _TMP17 = COMPAT_TEXTURE(Texture, _c0072); + _c0074 = ((_d11 - _dx) - _dx) + _dy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0074); + _c0076 = (_d11 + _dx + _dx) - _dy; + _TMP19 = COMPAT_TEXTURE(Texture, _c0076); + _c0078 = _d11 + _dx + _dx; + _TMP20 = COMPAT_TEXTURE(Texture, _c0078); + _c0080 = _d11 + _dx + _dx + _dy; + _TMP21 = COMPAT_TEXTURE(Texture, _c0080); + _c0082 = (_d11 - _dx) + _dy + _dy; + _TMP22 = COMPAT_TEXTURE(Texture, _c0082); + _c0084 = _d11 + _dy + _dy; + _TMP23 = COMPAT_TEXTURE(Texture, _c0084); + _c0086 = _d11 + _dx + _dy + _dy; + _TMP24 = COMPAT_TEXTURE(Texture, _c0086); + _E[3] = _TMP4.xyz; + _E[2] = _TMP4.xyz; + _E[1] = _TMP4.xyz; + _E[0] = _TMP4.xyz; + _TMP87 = dot(_TMP0.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP91 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP95 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP99 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP103 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP107 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP111 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP115 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP119 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP123 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP127 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP131 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP135 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP139 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP143 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP147 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP151 = dot(_TMP16.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP155 = dot(_TMP17.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP159 = dot(_TMP18.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP163 = dot(_TMP19.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP167 = dot(_TMP20.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP171 = dot(_TMP21.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP175 = dot(_TMP22.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP179 = dot(_TMP23.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP183 = dot(_TMP24.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP103 != _TMP115 && _TMP115 == _TMP107 && (_TMP103 != _TMP119 && (_TMP103 != _TMP91 || _TMP103 != _TMP99 || _TMP91 == _TMP147 && _TMP99 == _TMP159 || _TMP107 != _TMP91 && _TMP107 != _TMP95 || _TMP115 != _TMP99 && _TMP115 != _TMP111) || _TMP103 == _TMP111 && (_TMP119 == _TMP115 || _TMP103 == _TMP99 || _TMP115 != _TMP99) || _TMP103 == _TMP95 && (_TMP119 == _TMP115 || _TMP103 == _TMP91 || _TMP107 != _TMP91))) { + if (_TMP103 == _TMP95 && _TMP103 == _TMP99 && _TMP115 == _TMP111) { + if (_TMP99 == _TMP155 && _TMP111 == _TMP159) { + _E[3] = _TMP4.xyz + 8.33299994E-01*(_TMP7.xyz - _TMP4.xyz); + _E[2] = _TMP4.xyz + 5.00000000E-01*(_TMP7.xyz - _TMP4.xyz); + } else { + _E[3] = _TMP4.xyz + 7.50000000E-01*(_TMP7.xyz - _TMP4.xyz); + _E[2] = (_TMP4.xyz + _TMP7.xyz) - _E[3]; + } + } else { + if (_TMP103 == _TMP111 && _TMP103 == _TMP91 && _TMP107 == _TMP95) { + if (_TMP91 == _TMP143 && _TMP95 == _TMP147) { + _E[3] = _TMP4.xyz + 8.33299994E-01*(_TMP5.xyz - _TMP4.xyz); + _E[1] = (_TMP4.xyz + _TMP5.xyz)*5.00000000E-01; + } else { + _E[3] = _TMP4.xyz + 7.50000000E-01*(_TMP5.xyz - _TMP4.xyz); + _E[1] = (_TMP4.xyz + _TMP5.xyz) - _E[3]; + } + } else { + _E[3] = (_TMP4.xyz + _TMP5.xyz)*5.00000000E-01; + } + } + } else { + if (_TMP107 != _TMP119 && _TMP119 == _TMP167 && (_TMP107 != _TMP171 || _TMP119 != _TMP135) && _TMP107 == _TMP163 && _TMP107 == _TMP103 && _TMP119 == _TMP115 && _TMP103 == _TMP99 && _TMP115 == _TMP111) { + _E[3] = _TMP4.xyz + 1.66700006E-01*(_TMP7.xyz - _TMP4.xyz); + } else { + if (_TMP115 != _TMP119 && _TMP119 == _TMP179 && (_TMP115 != _TMP183 || _TMP119 != _TMP135) && _TMP115 == _TMP175 && _TMP115 == _TMP103 && _TMP119 == _TMP107 && _TMP103 == _TMP91 && _TMP107 == _TMP95) { + _E[3] = _TMP4.xyz + 1.66700006E-01*(_TMP5.xyz - _TMP4.xyz); + } else { + if (_TMP103 != _TMP115 && _TMP103 != _TMP107 && _TMP107 != _TMP119 && _TMP103 == _TMP95 && (_TMP115 == _TMP119 && _TMP107 != _TMP91 || _TMP103 != _TMP119 && _TMP107 == _TMP163)) { + _E[3] = (_TMP4.xyz + _TMP5.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP115 && _TMP103 != _TMP107 && _TMP115 != _TMP119 && _TMP103 == _TMP111 && (_TMP107 == _TMP119 && _TMP115 != _TMP99 || _TMP103 != _TMP119 && _TMP115 == _TMP175)) { + _E[3] = (_TMP4.xyz + _TMP7.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP115 && _TMP103 != _TMP119 && _TMP103 != _TMP107 && _TMP111 == _TMP103 && _TMP103 == _TMP95) { + _E[3] = (_TMP5.xyz + _TMP7.xyz)*5.00000000E-01; + } + } + } + } + } + } + if (_TMP103 != _TMP107 && _TMP107 == _TMP91 && (_TMP103 != _TMP95 && (_TMP103 != _TMP99 || _TMP103 != _TMP115 || _TMP99 == _TMP151 && _TMP115 == _TMP183 || _TMP91 != _TMP99 && _TMP91 != _TMP87 || _TMP107 != _TMP115 && _TMP107 != _TMP119) || _TMP103 == _TMP119 && (_TMP95 == _TMP107 || _TMP103 == _TMP115 || _TMP107 != _TMP115) || _TMP103 == _TMP87 && (_TMP95 == _TMP107 || _TMP103 == _TMP99 || _TMP91 != _TMP99))) { + if (_TMP103 == _TMP87 && _TMP103 == _TMP115 && _TMP107 == _TMP119) { + if (_TMP115 == _TMP179 && _TMP119 == _TMP183) { + _E[1] = _E[1] + 8.33299994E-01*(_TMP5.xyz - _E[1]); + _E[3] = _E[3] + 5.00000000E-01*(_TMP5.xyz - _E[3]); + } else { + _E[1] = _E[1] + 7.50000000E-01*(_TMP5.xyz - _E[1]); + _E[3] = (_E[3] + _TMP5.xyz) - _E[1]; + } + } else { + if (_TMP103 == _TMP119 && _TMP103 == _TMP99 && _TMP91 == _TMP87) { + if (_TMP99 == _TMP155 && _TMP87 == _TMP151) { + _E[1] = _E[1] + 8.33299994E-01*(_TMP1.xyz - _E[1]); + _E[0] = (_TMP4.xyz + _TMP1.xyz)*5.00000000E-01; + } else { + _E[1] = _E[1] + 7.50000000E-01*(_TMP1.xyz - _E[1]); + _E[0] = (_TMP4.xyz + _TMP1.xyz) - _E[1]; + } + } else { + _E[1] = (_E[1] + _TMP1.xyz)*5.00000000E-01; + } + } + } else { + if (_TMP91 != _TMP95 && _TMP95 == _TMP143 && (_TMP91 != _TMP147 || _TMP95 != _TMP127) && _TMP91 == _TMP139 && _TMP91 == _TMP103 && _TMP95 == _TMP107 && _TMP103 == _TMP115 && _TMP107 == _TMP119) { + _E[1] = _E[1] + 1.66700006E-01*(_TMP5.xyz - _E[1]); + } else { + if (_TMP107 != _TMP95 && _TMP95 == _TMP167 && (_TMP107 != _TMP163 || _TMP95 != _TMP127) && _TMP107 == _TMP171 && _TMP107 == _TMP103 && _TMP95 == _TMP91 && _TMP103 == _TMP99 && _TMP91 == _TMP87) { + _E[1] = _E[1] + 1.66700006E-01*(_TMP1.xyz - _E[1]); + } else { + if (_TMP103 != _TMP107 && _TMP103 != _TMP91 && _TMP91 != _TMP95 && _TMP103 == _TMP87 && (_TMP107 == _TMP95 && _TMP91 != _TMP99 || _TMP103 != _TMP95 && _TMP91 == _TMP139)) { + _E[1] = (_E[1] + _TMP1.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP107 && _TMP103 != _TMP91 && _TMP107 != _TMP95 && _TMP103 == _TMP119 && (_TMP91 == _TMP95 && _TMP107 != _TMP115 || _TMP103 != _TMP95 && _TMP107 == _TMP171)) { + _E[1] = (_E[1] + _TMP5.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP107 && _TMP103 != _TMP95 && _TMP103 != _TMP91 && _TMP119 == _TMP103 && _TMP103 == _TMP87) { + _E[1] = (_TMP1.xyz + _TMP5.xyz)*5.00000000E-01; + } + } + } + } + } + } + if (_TMP103 != _TMP91 && _TMP91 == _TMP99 && (_TMP103 != _TMP87 && (_TMP103 != _TMP115 || _TMP103 != _TMP107 || _TMP115 == _TMP175 && _TMP107 == _TMP163 || _TMP99 != _TMP115 && _TMP99 != _TMP111 || _TMP91 != _TMP107 && _TMP91 != _TMP95) || _TMP103 == _TMP95 && (_TMP87 == _TMP91 || _TMP103 == _TMP107 || _TMP91 != _TMP107) || _TMP103 == _TMP111 && (_TMP87 == _TMP91 || _TMP103 == _TMP115 || _TMP99 != _TMP115))) { + if (_TMP103 == _TMP111 && _TMP103 == _TMP107 && _TMP91 == _TMP95) { + if (_TMP107 == _TMP167 && _TMP95 == _TMP163) { + _E[0] = _E[0] + 8.33299994E-01*(_TMP1.xyz - _E[0]); + _E[1] = _E[1] + 5.00000000E-01*(_TMP1.xyz - _E[1]); + } else { + _E[0] = _E[0] + 7.50000000E-01*(_TMP1.xyz - _E[0]); + _E[1] = (_E[1] + _TMP1.xyz) - _E[0]; + } + } else { + if (_TMP103 == _TMP95 && _TMP103 == _TMP115 && _TMP99 == _TMP111) { + if (_TMP115 == _TMP179 && _TMP111 == _TMP175) { + _E[0] = _E[0] + 8.33299994E-01*(_TMP3.xyz - _E[0]); + _E[2] = (_E[2] + _TMP3.xyz)*5.00000000E-01; + } else { + _E[0] = _E[0] + 7.50000000E-01*(_TMP3.xyz - _E[0]); + _E[2] = (_E[2] + _TMP3.xyz) - _E[0]; + } + } else { + _E[0] = (_E[0] + _TMP3.xyz)*5.00000000E-01; + } + } + } else { + if (_TMP99 != _TMP87 && _TMP87 == _TMP155 && (_TMP99 != _TMP151 || _TMP87 != _TMP123) && _TMP99 == _TMP159 && _TMP99 == _TMP103 && _TMP87 == _TMP91 && _TMP103 == _TMP107 && _TMP91 == _TMP95) { + _E[0] = _E[0] + 1.66700006E-01*(_TMP1.xyz - _E[0]); + } else { + if (_TMP91 != _TMP87 && _TMP87 == _TMP143 && (_TMP91 != _TMP139 || _TMP87 != _TMP123) && _TMP91 == _TMP147 && _TMP91 == _TMP103 && _TMP87 == _TMP99 && _TMP103 == _TMP115 && _TMP99 == _TMP111) { + _E[0] = _E[0] + 1.66700006E-01*(_TMP3.xyz - _E[0]); + } else { + if (_TMP103 != _TMP91 && _TMP103 != _TMP99 && _TMP99 != _TMP87 && _TMP103 == _TMP111 && (_TMP91 == _TMP87 && _TMP99 != _TMP115 || _TMP103 != _TMP87 && _TMP99 == _TMP159)) { + _E[0] = (_E[0] + _TMP3.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP91 && _TMP103 != _TMP99 && _TMP91 != _TMP87 && _TMP103 == _TMP95 && (_TMP99 == _TMP87 && _TMP91 != _TMP107 || _TMP103 != _TMP87 && _TMP91 == _TMP147)) { + _E[0] = (_E[0] + _TMP1.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP91 && _TMP103 != _TMP87 && _TMP103 != _TMP99 && _TMP95 == _TMP103 && _TMP103 == _TMP111) { + _E[0] = (_TMP3.xyz + _TMP1.xyz)*5.00000000E-01; + } + } + } + } + } + } + if (_TMP103 != _TMP99 && _TMP99 == _TMP115 && (_TMP103 != _TMP111 && (_TMP103 != _TMP107 || _TMP103 != _TMP91 || _TMP107 == _TMP171 && _TMP91 == _TMP139 || _TMP115 != _TMP107 && _TMP115 != _TMP119 || _TMP99 != _TMP91 && _TMP99 != _TMP87) || _TMP103 == _TMP87 && (_TMP111 == _TMP99 || _TMP103 == _TMP91 || _TMP99 != _TMP91) || _TMP103 == _TMP119 && (_TMP111 == _TMP99 || _TMP103 == _TMP107 || _TMP115 != _TMP107))) { + if (_TMP103 == _TMP119 && _TMP103 == _TMP91 && _TMP99 == _TMP87) { + if (_TMP91 == _TMP143 && _TMP87 == _TMP139) { + _E[2] = _E[2] + 8.33299994E-01*(_TMP3.xyz - _E[2]); + _E[0] = _E[0] + 5.00000000E-01*(_TMP3.xyz - _E[0]); + } else { + _E[2] = _E[2] + 7.50000000E-01*(_TMP3.xyz - _E[2]); + _E[0] = (_E[0] + _TMP3.xyz) - _E[2]; + } + } else { + if (_TMP103 == _TMP87 && _TMP103 == _TMP107 && _TMP115 == _TMP119) { + if (_TMP107 == _TMP167 && _TMP119 == _TMP171) { + _E[2] = _E[2] + 8.33299994E-01*(_TMP7.xyz - _E[2]); + _E[3] = (_E[3] + _TMP7.xyz)*5.00000000E-01; + } else { + _E[2] = _E[2] + 7.50000000E-01*(_TMP7.xyz - _E[2]); + _E[3] = (_E[3] + _TMP7.xyz) - _E[2]; + } + } else { + _E[2] = (_E[2] + _TMP7.xyz)*5.00000000E-01; + } + } + } else { + if (_TMP115 != _TMP111 && _TMP111 == _TMP179 && (_TMP115 != _TMP175 || _TMP111 != _TMP131) && _TMP115 == _TMP183 && _TMP115 == _TMP103 && _TMP111 == _TMP99 && _TMP103 == _TMP91 && _TMP99 == _TMP87) { + _E[2] = _E[2] + 1.66700006E-01*(_TMP3.xyz - _E[2]); + } else { + if (_TMP99 != _TMP111 && _TMP111 == _TMP155 && (_TMP99 != _TMP159 || _TMP111 != _TMP131) && _TMP99 == _TMP151 && _TMP99 == _TMP103 && _TMP111 == _TMP115 && _TMP103 == _TMP107 && _TMP115 == _TMP119) { + _E[2] = _E[2] + 1.66700006E-01*(_TMP7.xyz - _E[2]); + } else { + if (_TMP103 != _TMP99 && _TMP103 != _TMP115 && _TMP115 != _TMP111 && _TMP103 == _TMP119 && (_TMP99 == _TMP111 && _TMP115 != _TMP107 || _TMP103 != _TMP111 && _TMP115 == _TMP183)) { + _E[2] = (_E[2] + _TMP7.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP99 && _TMP103 != _TMP115 && _TMP99 != _TMP111 && _TMP103 == _TMP87 && (_TMP115 == _TMP111 && _TMP99 != _TMP91 || _TMP103 != _TMP111 && _TMP99 == _TMP151)) { + _E[2] = (_E[2] + _TMP3.xyz)*5.00000000E-01; + } else { + if (_TMP103 != _TMP99 && _TMP103 != _TMP111 && _TMP103 != _TMP115 && _TMP87 == _TMP103 && _TMP103 == _TMP119) { + _E[2] = (_TMP7.xyz + _TMP3.xyz)*5.00000000E-01; + } + } + } + } + } + } + if (_fp.x < 5.00000000E-01) { + if (_fp.y < 5.00000000E-01) { + _TMP29 = _E[0]; + } else { + _TMP29 = _E[2]; + } + _TMP28 = _TMP29; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP30 = _E[1]; + } else { + _TMP30 = _E[3]; + } + _TMP28 = _TMP30; + } + _OUT._color1 = vec4(_TMP28.x, _TMP28.y, _TMP28.z, 1.00000000E+00); + FragColor = _OUT._color1; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.5a.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.5a.glsl new file mode 100644 index 000000000..2616c8d16 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.5a.glsl @@ -0,0 +1,687 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(_ps.x, 0.00000000E+00); + _OUT._t1.zw = vec2(0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP33; +vec3 _TMP35; +vec3 _TMP34; +vec3 _TMP32; +vec3 _TMP31; +vec3 _TMP30; +vec3 _TMP29; +vec4 _TMP22; +vec4 _TMP21; +vec3 _TMP43; +vec3 _TMP41; +vec3 _TMP39; +vec3 _TMP37; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0081; +vec2 _c0083; +vec2 _c0085; +vec2 _c0087; +vec2 _c0089; +vec2 _c0093; +vec2 _c0095; +vec2 _c0097; +vec2 _c0099; +vec2 _c0101; +vec2 _c0103; +vec2 _c0105; +vec2 _c0107; +vec2 _c0109; +vec2 _c0111; +vec2 _c0113; +vec2 _c0115; +vec2 _c0117; +vec2 _c0119; +vec2 _c0121; +vec2 _c0123; +vec3 _r0169; +vec3 _r0179; +vec3 _r0189; +vec3 _r0199; +vec3 _r0211; +vec3 _r0221; +vec3 _r0231; +vec3 _r0241; +vec3 _r0253; +vec3 _r0263; +vec3 _r0273; +vec3 _r0283; +vec3 _r0295; +vec3 _r0305; +vec3 _r0315; +vec3 _r0325; +vec3 _r0337; +vec3 _r0347; +vec3 _r0357; +vec3 _r0367; +vec3 _r0379; +vec3 _r0389; +vec3 _r0399; +vec3 _r0409; +vec3 _r0421; +vec3 _r0431; +vec3 _r0441; +vec3 _r0451; +vec3 _r0463; +vec3 _r0473; +vec3 _r0483; +vec3 _r0493; +vec3 _r0715; +vec3 _r0725; +vec3 _r0735; +vec3 _r0745; +vec3 _r0799; +vec3 _r0809; +vec3 _r0819; +vec3 _r0829; +vec3 _r0925; +vec3 _r0935; +vec3 _r0945; +vec3 _r0955; +vec3 _r0967; +vec3 _r0977; +vec3 _r0987; +vec3 _r0997; +vec4 _TMP1008; +vec4 _a1011; +vec4 _TMP1012; +vec4 _a1015; +vec4 _TMP1016; +vec4 _a1019; +vec4 _TMP1020; +vec4 _a1023; +vec4 _TMP1024; +vec4 _a1027; +vec4 _TMP1030; +vec4 _a1033; +vec4 _TMP1034; +vec4 _a1037; +vec4 _TMP1038; +vec4 _a1041; +vec4 _TMP1042; +vec4 _a1045; +vec4 _TMP1046; +vec4 _a1049; +vec4 _TMP1050; +vec4 _a1053; +vec4 _TMP1054; +vec4 _a1057; +vec4 _TMP1058; +vec4 _a1061; +vec4 _TMP1062; +vec4 _a1065; +vec4 _TMP1066; +vec4 _a1069; +vec4 _TMP1070; +vec4 _a1073; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + vec2 _fp; + vec4 _b2; + vec4 _c2; + vec4 _d2; + vec4 _e1; + vec4 _f1; + vec4 _g1; + vec4 _h1; + vec4 _i; + vec4 _i4; + vec4 _i5; + vec4 _h5; + vec4 _f4; + vec3 _E0; + vec3 _E1; + vec3 _E2; + vec3 _E3; + _x0081 = TEX0.xy*TextureSize; + _fp = fract(_x0081); + _c0083 = (TEX0.xy - TEX1.xy) - TEX1.zw; + _TMP0 = COMPAT_TEXTURE(Texture, _c0083); + _c0085 = TEX0.xy - TEX1.zw; + _TMP1 = COMPAT_TEXTURE(Texture, _c0085); + _c0087 = (TEX0.xy + TEX1.xy) - TEX1.zw; + _TMP2 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = TEX0.xy - TEX1.xy; + _TMP3 = COMPAT_TEXTURE(Texture, _c0089); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0093 = TEX0.xy + TEX1.xy; + _TMP5 = COMPAT_TEXTURE(Texture, _c0093); + _c0095 = (TEX0.xy - TEX1.xy) + TEX1.zw; + _TMP6 = COMPAT_TEXTURE(Texture, _c0095); + _c0097 = TEX0.xy + TEX1.zw; + _TMP7 = COMPAT_TEXTURE(Texture, _c0097); + _c0099 = TEX0.xy + TEX1.xy + TEX1.zw; + _TMP8 = COMPAT_TEXTURE(Texture, _c0099); + _c0101 = (TEX0.xy - TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP9 = COMPAT_TEXTURE(Texture, _c0101); + _c0103 = (TEX0.xy + TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP10 = COMPAT_TEXTURE(Texture, _c0103); + _c0105 = (TEX0.xy - 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP11 = COMPAT_TEXTURE(Texture, _c0105); + _c0107 = (TEX0.xy - 2.00000000E+00*TEX1.xy) + TEX1.zw; + _TMP12 = COMPAT_TEXTURE(Texture, _c0107); + _c0109 = (TEX0.xy + 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP13 = COMPAT_TEXTURE(Texture, _c0109); + _c0111 = TEX0.xy + 2.00000000E+00*TEX1.xy + TEX1.zw; + _TMP14 = COMPAT_TEXTURE(Texture, _c0111); + _c0113 = (TEX0.xy - TEX1.xy) + 2.00000000E+00*TEX1.zw; + _TMP15 = COMPAT_TEXTURE(Texture, _c0113); + _c0115 = TEX0.xy + TEX1.xy + 2.00000000E+00*TEX1.zw; + _TMP16 = COMPAT_TEXTURE(Texture, _c0115); + _c0117 = TEX0.xy - 2.00000000E+00*TEX1.zw; + _TMP17 = COMPAT_TEXTURE(Texture, _c0117); + _c0119 = TEX0.xy - 2.00000000E+00*TEX1.xy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0119); + _c0121 = TEX0.xy + 2.00000000E+00*TEX1.zw; + _TMP19 = COMPAT_TEXTURE(Texture, _c0121); + _c0123 = TEX0.xy + 2.00000000E+00*TEX1.xy; + _TMP20 = COMPAT_TEXTURE(Texture, _c0123); + _r0169.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0169.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0169.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP37 = abs(_r0169); + _r0179.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0179.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0179.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP39 = abs(_r0179); + _r0189.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0189.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0189.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP41 = abs(_r0189); + _r0199.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0199.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0199.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP43 = abs(_r0199); + _b2 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0211.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0211.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0211.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP37 = abs(_r0211); + _r0221.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0221.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0221.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP39 = abs(_r0221); + _r0231.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0231.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0231.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP41 = abs(_r0231); + _r0241.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0241.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0241.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP43 = abs(_r0241); + _c2 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0253.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0253.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0253.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP37 = abs(_r0253); + _r0263.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0263.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0263.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP39 = abs(_r0263); + _r0273.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0273.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0273.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP41 = abs(_r0273); + _r0283.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0283.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0283.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP43 = abs(_r0283); + _d2 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0295.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0295.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0295.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP37 = abs(_r0295); + _r0305.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0305.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0305.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP39 = abs(_r0305); + _r0315.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0315.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0315.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP41 = abs(_r0315); + _r0325.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0325.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0325.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP43 = abs(_r0325); + _e1 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0337.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0337.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0337.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP37 = abs(_r0337); + _r0347.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0347.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0347.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP39 = abs(_r0347); + _r0357.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0357.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0357.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP41 = abs(_r0357); + _r0367.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0367.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0367.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP43 = abs(_r0367); + _f1 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0379.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0379.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0379.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP37 = abs(_r0379); + _r0389.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0389.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0389.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP39 = abs(_r0389); + _r0399.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0399.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0399.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP41 = abs(_r0399); + _r0409.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0409.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0409.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP43 = abs(_r0409); + _g1 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0421.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0421.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0421.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP37 = abs(_r0421); + _r0431.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0431.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0431.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP39 = abs(_r0431); + _r0441.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0441.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0441.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP41 = abs(_r0441); + _r0451.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0451.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0451.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP43 = abs(_r0451); + _h1 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0463.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0463.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0463.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP37 = abs(_r0463); + _r0473.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0473.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0473.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP39 = abs(_r0473); + _r0483.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0483.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0483.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP41 = abs(_r0483); + _r0493.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0493.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0493.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP43 = abs(_r0493); + _i = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0715.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP14.xyz); + _r0715.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP14.xyz); + _r0715.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP14.xyz); + _TMP37 = abs(_r0715); + _r0725.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP10.xyz); + _r0725.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP10.xyz); + _r0725.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP10.xyz); + _TMP39 = abs(_r0725); + _r0735.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP11.xyz); + _r0735.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP11.xyz); + _r0735.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP11.xyz); + _TMP41 = abs(_r0735); + _r0745.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0745.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP15.xyz); + _r0745.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP15.xyz); + _TMP43 = abs(_r0745); + _i4 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0799.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP16.xyz); + _r0799.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP16.xyz); + _r0799.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP16.xyz); + _TMP37 = abs(_r0799); + _r0809.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP13.xyz); + _r0809.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP13.xyz); + _r0809.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP13.xyz); + _TMP39 = abs(_r0809); + _r0819.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP9.xyz); + _r0819.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP9.xyz); + _r0819.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP9.xyz); + _TMP41 = abs(_r0819); + _r0829.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0829.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP12.xyz); + _r0829.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP12.xyz); + _TMP43 = abs(_r0829); + _i5 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0925.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0925.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r0925.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP37 = abs(_r0925); + _r0935.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0935.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0935.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP39 = abs(_r0935); + _r0945.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0945.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0945.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP41 = abs(_r0945); + _r0955.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0955.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0955.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP43 = abs(_r0955); + _h5 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _r0967.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0967.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0967.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP37 = abs(_r0967); + _r0977.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0977.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0977.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP39 = abs(_r0977); + _r0987.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0987.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0987.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP41 = abs(_r0987); + _r0997.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0997.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r0997.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP43 = abs(_r0997); + _f4 = vec4(_TMP37.x, _TMP39.x, _TMP41.x, _TMP43.x); + _interp_restriction_lv1 = bvec4(_e1.x != _f1.x && _e1.x != _h1.x, _e1.y != _f1.y && _e1.y != _h1.y, _e1.z != _f1.z && _e1.z != _h1.z, _e1.w != _f1.w && _e1.w != _h1.w); + _interp_restriction_lv2_left = bvec4(_e1.x != _g1.x && _d2.x != _g1.x, _e1.y != _g1.y && _d2.y != _g1.y, _e1.z != _g1.z && _d2.z != _g1.z, _e1.w != _g1.w && _d2.w != _g1.w); + _interp_restriction_lv2_up = bvec4(_e1.x != _c2.x && _b2.x != _c2.x, _e1.y != _c2.y && _b2.y != _c2.y, _e1.z != _c2.z && _b2.z != _c2.z, _e1.w != _c2.w && _b2.w != _c2.w); + _a1011 = _e1 - _c2; + _TMP1008 = abs(_a1011); + _a1015 = _e1 - _g1; + _TMP1012 = abs(_a1015); + _a1019 = _i - _h5; + _TMP1016 = abs(_a1019); + _a1023 = _i - _f4; + _TMP1020 = abs(_a1023); + _a1027 = _h1 - _f1; + _TMP1024 = abs(_a1027); + _TMP21 = _TMP1008 + _TMP1012 + _TMP1016 + _TMP1020 + 4.00000000E+00*_TMP1024; + _a1033 = _h1 - _d2; + _TMP1030 = abs(_a1033); + _a1037 = _h1 - _i5; + _TMP1034 = abs(_a1037); + _a1041 = _f1 - _i4; + _TMP1038 = abs(_a1041); + _a1045 = _f1 - _b2; + _TMP1042 = abs(_a1045); + _a1049 = _e1 - _i; + _TMP1046 = abs(_a1049); + _TMP22 = _TMP1030 + _TMP1034 + _TMP1038 + _TMP1042 + 4.00000000E+00*_TMP1046; + _edr = bvec4(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z, _TMP21.w < _TMP22.w && _interp_restriction_lv1.w); + _a1053 = _f1 - _g1; + _TMP1050 = abs(_a1053); + _a1057 = _h1 - _c2; + _TMP1054 = abs(_a1057); + _edr_left = bvec4((2.00000000E+00*_TMP1050).x <= _TMP1054.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP1050).y <= _TMP1054.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP1050).z <= _TMP1054.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP1050).w <= _TMP1054.w && _interp_restriction_lv2_left.w); + _a1061 = _f1 - _g1; + _TMP1058 = abs(_a1061); + _a1065 = _h1 - _c2; + _TMP1062 = abs(_a1065); + _edr_up = bvec4(_TMP1058.x >= (2.00000000E+00*_TMP1062).x && _interp_restriction_lv2_up.x, _TMP1058.y >= (2.00000000E+00*_TMP1062).y && _interp_restriction_lv2_up.y, _TMP1058.z >= (2.00000000E+00*_TMP1062).z && _interp_restriction_lv2_up.z, _TMP1058.w >= (2.00000000E+00*_TMP1062).w && _interp_restriction_lv2_up.w); + _E0 = _TMP4.xyz; + _E1 = _TMP4.xyz; + _E2 = _TMP4.xyz; + _E3 = _TMP4.xyz; + _a1069 = _e1 - _f1; + _TMP1066 = abs(_a1069); + _a1073 = _e1 - _h1; + _TMP1070 = abs(_a1073); + _px = bvec4(_TMP1066.x <= _TMP1070.x, _TMP1066.y <= _TMP1070.y, _TMP1066.z <= _TMP1070.z, _TMP1066.w <= _TMP1070.w); + if (_px.x) { + _TMP29 = _TMP5.xyz; + } else { + _TMP29 = _TMP7.xyz; + } + if (_px.y) { + _TMP30 = _TMP1.xyz; + } else { + _TMP30 = _TMP5.xyz; + } + if (_px.z) { + _TMP31 = _TMP3.xyz; + } else { + _TMP31 = _TMP1.xyz; + } + if (_px.w) { + _TMP32 = _TMP7.xyz; + } else { + _TMP32 = _TMP3.xyz; + } + if (_edr.x) { + if (_edr_left.x && _edr_up.x) { + _E3 = _TMP4.xyz + 8.33333015E-01*(_TMP29 - _TMP4.xyz); + _E2 = _TMP4.xyz + 2.50000000E-01*(_TMP29 - _TMP4.xyz); + _E1 = _TMP4.xyz + 2.50000000E-01*(_TMP29 - _TMP4.xyz); + } else { + if (_edr_left.x) { + _E3 = _TMP4.xyz + 7.50000000E-01*(_TMP29 - _TMP4.xyz); + _E2 = _TMP4.xyz + 2.50000000E-01*(_TMP29 - _TMP4.xyz); + } else { + if (_edr_up.x) { + _E3 = _TMP4.xyz + 7.50000000E-01*(_TMP29 - _TMP4.xyz); + _E1 = _TMP4.xyz + 2.50000000E-01*(_TMP29 - _TMP4.xyz); + } else { + _E3 = _TMP4.xyz + 5.00000000E-01*(_TMP29 - _TMP4.xyz); + } + } + } + } + if (_edr.y) { + if (_edr_left.y && _edr_up.y) { + _E1 = _E1 + 8.33333015E-01*(_TMP30 - _E1); + _E3 = _E3 + 2.50000000E-01*(_TMP30 - _E3); + _E0 = _TMP4.xyz + 2.50000000E-01*(_TMP30 - _TMP4.xyz); + } else { + if (_edr_left.y) { + _E1 = _E1 + 7.50000000E-01*(_TMP30 - _E1); + _E3 = _E3 + 2.50000000E-01*(_TMP30 - _E3); + } else { + if (_edr_up.y) { + _E1 = _E1 + 7.50000000E-01*(_TMP30 - _E1); + _E0 = _TMP4.xyz + 2.50000000E-01*(_TMP30 - _TMP4.xyz); + } else { + _E1 = _E1 + 5.00000000E-01*(_TMP30 - _E1); + } + } + } + } + if (_edr.z) { + if (_edr_left.z && _edr_up.z) { + _E0 = _E0 + 8.33333015E-01*(_TMP31 - _E0); + _E1 = _E1 + 2.50000000E-01*(_TMP31 - _E1); + _E2 = _E2 + 2.50000000E-01*(_TMP31 - _E2); + } else { + if (_edr_left.z) { + _E0 = _E0 + 7.50000000E-01*(_TMP31 - _E0); + _E1 = _E1 + 2.50000000E-01*(_TMP31 - _E1); + } else { + if (_edr_up.z) { + _E0 = _E0 + 7.50000000E-01*(_TMP31 - _E0); + _E2 = _E2 + 2.50000000E-01*(_TMP31 - _E2); + } else { + _E0 = _E0 + 5.00000000E-01*(_TMP31 - _E0); + } + } + } + } + if (_edr.w) { + if (_edr_left.w && _edr_up.w) { + _E2 = _E2 + 8.33333015E-01*(_TMP32 - _E2); + _E0 = _E0 + 2.50000000E-01*(_TMP32 - _E0); + _E3 = _E3 + 2.50000000E-01*(_TMP32 - _E3); + } else { + if (_edr_left.w) { + _E2 = _E2 + 7.50000000E-01*(_TMP32 - _E2); + _E0 = _E0 + 2.50000000E-01*(_TMP32 - _E0); + } else { + if (_edr_up.w) { + _E2 = _E2 + 7.50000000E-01*(_TMP32 - _E2); + _E3 = _E3 + 2.50000000E-01*(_TMP32 - _E3); + } else { + _E2 = _E2 + 5.00000000E-01*(_TMP32 - _E2); + } + } + } + } + if (_fp.x < 5.00000000E-01) { + if (_fp.y < 5.00000000E-01) { + _TMP34 = _E0; + } else { + _TMP34 = _E2; + } + _TMP33 = _TMP34; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP35 = _E1; + } else { + _TMP35 = _E3; + } + _TMP33 = _TMP35; + } + _ret_0 = vec4(_TMP33.x, _TMP33.y, _TMP33.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.7c.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.7c.glsl new file mode 100644 index 000000000..27b38f0af --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.7c.glsl @@ -0,0 +1,538 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP43; +vec3 _TMP42; +vec3 _TMP41; +vec3 _TMP40; +vec4 _TMP33; +vec4 _TMP32; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0063; +vec4 _r0107; +vec4 _r0117; +vec4 _r0127; +vec4 _r0137; +vec4 _r0147; +vec4 _r0157; +vec4 _TMP168; +vec4 _a0171; +vec4 _TMP174; +vec4 _a0177; +vec4 _TMP180; +vec4 _a0183; +vec4 _TMP186; +vec4 _a0189; +vec4 _TMP192; +vec4 _a0195; +vec4 _TMP198; +vec4 _a0201; +vec4 _TMP204; +vec4 _a0207; +vec4 _TMP210; +vec4 _a0213; +vec4 _TMP216; +vec4 _a0219; +vec4 _TMP222; +vec4 _a0225; +vec4 _TMP228; +vec4 _a0231; +vec4 _TMP234; +vec4 _a0237; +vec4 _TMP238; +vec4 _a0241; +vec4 _TMP242; +vec4 _a0245; +vec4 _TMP246; +vec4 _a0249; +vec4 _TMP250; +vec4 _a0253; +vec4 _TMP256; +vec4 _a0259; +vec4 _TMP260; +vec4 _a0263; +vec4 _TMP264; +vec4 _a0267; +vec4 _TMP268; +vec4 _a0271; +vec4 _TMP272; +vec4 _a0275; +vec4 _TMP276; +vec4 _a0279; +vec4 _TMP280; +vec4 _a0283; +vec4 _TMP284; +vec4 _a0287; +vec4 _TMP288; +vec4 _a0291; +vec4 _TMP292; +vec4 _a0295; +vec4 _TMP296; +vec4 _a0299; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + vec2 _fp; + vec3 _res; + _x0063 = TEX0.xy*TextureSize; + _fp = fract(_x0063); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0107.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0107.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0107.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0107.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0117.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0117.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0117.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0117.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0127.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0127.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0127.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0127.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0137.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0137.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0137.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0137.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0147.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0147.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0147.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0147.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0157.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0157.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0157.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0157.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _a0171 = _r0107.wxyz - _r0107; + _TMP168 = abs(_a0171); + _TMP21 = bvec4(_TMP168.x < 1.50000000E+01, _TMP168.y < 1.50000000E+01, _TMP168.z < 1.50000000E+01, _TMP168.w < 1.50000000E+01); + _a0177 = _r0107.wxyz - _r0117; + _TMP174 = abs(_a0177); + _TMP22 = bvec4(_TMP174.x < 1.50000000E+01, _TMP174.y < 1.50000000E+01, _TMP174.z < 1.50000000E+01, _TMP174.w < 1.50000000E+01); + _a0183 = _r0107.zwxy - _r0107.yzwx; + _TMP180 = abs(_a0183); + _TMP23 = bvec4(_TMP180.x < 1.50000000E+01, _TMP180.y < 1.50000000E+01, _TMP180.z < 1.50000000E+01, _TMP180.w < 1.50000000E+01); + _a0189 = _r0107.zwxy - _r0117.zwxy; + _TMP186 = abs(_a0189); + _TMP24 = bvec4(_TMP186.x < 1.50000000E+01, _TMP186.y < 1.50000000E+01, _TMP186.z < 1.50000000E+01, _TMP186.w < 1.50000000E+01); + _a0195 = _r0127 - _r0117.wxyz; + _TMP192 = abs(_a0195); + _TMP25 = bvec4(_TMP192.x < 1.50000000E+01, _TMP192.y < 1.50000000E+01, _TMP192.z < 1.50000000E+01, _TMP192.w < 1.50000000E+01); + _a0201 = _r0107.wxyz - _r0157.yzwx; + _TMP198 = abs(_a0201); + _TMP26 = bvec4(_TMP198.x < 1.50000000E+01, _TMP198.y < 1.50000000E+01, _TMP198.z < 1.50000000E+01, _TMP198.w < 1.50000000E+01); + _a0207 = _r0107.wxyz - _r0137; + _TMP204 = abs(_a0207); + _TMP27 = bvec4(_TMP204.x < 1.50000000E+01, _TMP204.y < 1.50000000E+01, _TMP204.z < 1.50000000E+01, _TMP204.w < 1.50000000E+01); + _a0213 = _r0107.zwxy - _r0157; + _TMP210 = abs(_a0213); + _TMP28 = bvec4(_TMP210.x < 1.50000000E+01, _TMP210.y < 1.50000000E+01, _TMP210.z < 1.50000000E+01, _TMP210.w < 1.50000000E+01); + _a0219 = _r0107.zwxy - _r0147; + _TMP216 = abs(_a0219); + _TMP29 = bvec4(_TMP216.x < 1.50000000E+01, _TMP216.y < 1.50000000E+01, _TMP216.z < 1.50000000E+01, _TMP216.w < 1.50000000E+01); + _a0225 = _r0127 - _r0117.zwxy; + _TMP222 = abs(_a0225); + _TMP30 = bvec4(_TMP222.x < 1.50000000E+01, _TMP222.y < 1.50000000E+01, _TMP222.z < 1.50000000E+01, _TMP222.w < 1.50000000E+01); + _a0231 = _r0127 - _r0117; + _TMP228 = abs(_a0231); + _TMP31 = bvec4(_TMP228.x < 1.50000000E+01, _TMP228.y < 1.50000000E+01, _TMP228.z < 1.50000000E+01, _TMP228.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0127.x != _r0107.w && _r0127.x != _r0107.z && (!_TMP21.x && !_TMP22.x || !_TMP23.x && !_TMP24.x || _TMP25.x && (!_TMP26.x && !_TMP27.x || !_TMP28.x && !_TMP29.x) || _TMP30.x || _TMP31.x), _r0127.y != _r0107.x && _r0127.y != _r0107.w && (!_TMP21.y && !_TMP22.y || !_TMP23.y && !_TMP24.y || _TMP25.y && (!_TMP26.y && !_TMP27.y || !_TMP28.y && !_TMP29.y) || _TMP30.y || _TMP31.y), _r0127.z != _r0107.y && _r0127.z != _r0107.x && (!_TMP21.z && !_TMP22.z || !_TMP23.z && !_TMP24.z || _TMP25.z && (!_TMP26.z && !_TMP27.z || !_TMP28.z && !_TMP29.z) || _TMP30.z || _TMP31.z), _r0127.w != _r0107.z && _r0127.w != _r0107.y && (!_TMP21.w && !_TMP22.w || !_TMP23.w && !_TMP24.w || _TMP25.w && (!_TMP26.w && !_TMP27.w || !_TMP28.w && !_TMP29.w) || _TMP30.w || _TMP31.w)); + _interp_restriction_lv2_left = bvec4(_r0127.x != _r0117.z && _r0107.y != _r0117.z, _r0127.y != _r0117.w && _r0107.z != _r0117.w, _r0127.z != _r0117.x && _r0107.w != _r0117.x, _r0127.w != _r0117.y && _r0107.x != _r0117.y); + _interp_restriction_lv2_up = bvec4(_r0127.x != _r0117.x && _r0107.x != _r0117.x, _r0127.y != _r0117.y && _r0107.y != _r0117.y, _r0127.z != _r0117.z && _r0107.z != _r0117.z, _r0127.w != _r0117.w && _r0107.w != _r0117.w); + _a0237 = _r0127 - _r0117; + _TMP234 = abs(_a0237); + _a0241 = _r0127 - _r0117.zwxy; + _TMP238 = abs(_a0241); + _a0245 = _r0117.wxyz - _r0157; + _TMP242 = abs(_a0245); + _a0249 = _r0117.wxyz - _r0157.yzwx; + _TMP246 = abs(_a0249); + _a0253 = _r0107.zwxy - _r0107.wxyz; + _TMP250 = abs(_a0253); + _TMP32 = _TMP234 + _TMP238 + _TMP242 + _TMP246 + 4.00000000E+00*_TMP250; + _a0259 = _r0107.zwxy - _r0107.yzwx; + _TMP256 = abs(_a0259); + _a0263 = _r0107.zwxy - _r0147; + _TMP260 = abs(_a0263); + _a0267 = _r0107.wxyz - _r0137; + _TMP264 = abs(_a0267); + _a0271 = _r0107.wxyz - _r0107; + _TMP268 = abs(_a0271); + _a0275 = _r0127 - _r0117.wxyz; + _TMP272 = abs(_a0275); + _TMP33 = _TMP256 + _TMP260 + _TMP264 + _TMP268 + 4.00000000E+00*_TMP272; + _edr = bvec4(_TMP32.x < _TMP33.x && _interp_restriction_lv1.x, _TMP32.y < _TMP33.y && _interp_restriction_lv1.y, _TMP32.z < _TMP33.z && _interp_restriction_lv1.z, _TMP32.w < _TMP33.w && _interp_restriction_lv1.w); + _a0279 = _r0107.wxyz - _r0117.zwxy; + _TMP276 = abs(_a0279); + _a0283 = _r0107.zwxy - _r0117; + _TMP280 = abs(_a0283); + _edr_left = bvec4((2.00000000E+00*_TMP276).x <= _TMP280.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP276).y <= _TMP280.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP276).z <= _TMP280.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP276).w <= _TMP280.w && _interp_restriction_lv2_left.w); + _a0287 = _r0107.wxyz - _r0117.zwxy; + _TMP284 = abs(_a0287); + _a0291 = _r0107.zwxy - _r0117; + _TMP288 = abs(_a0291); + _edr_up = bvec4(_TMP284.x >= (2.00000000E+00*_TMP288).x && _interp_restriction_lv2_up.x, _TMP284.y >= (2.00000000E+00*_TMP288).y && _interp_restriction_lv2_up.y, _TMP284.z >= (2.00000000E+00*_TMP288).z && _interp_restriction_lv2_up.z, _TMP284.w >= (2.00000000E+00*_TMP288).w && _interp_restriction_lv2_up.w); + _a0295 = _r0127 - _r0107.wxyz; + _TMP292 = abs(_a0295); + _a0299 = _r0127 - _r0107.zwxy; + _TMP296 = abs(_a0299); + _px = bvec4(_TMP292.x <= _TMP296.x, _TMP292.y <= _TMP296.y, _TMP292.z <= _TMP296.z, _TMP292.w <= _TMP296.w); + if (_px.x) { + _TMP40 = _TMP8.xyz; + } else { + _TMP40 = _TMP10.xyz; + } + if (_px.y) { + _TMP41 = _TMP4.xyz; + } else { + _TMP41 = _TMP8.xyz; + } + if (_px.z) { + _TMP42 = _TMP6.xyz; + } else { + _TMP42 = _TMP4.xyz; + } + if (_px.w) { + _TMP43 = _TMP10.xyz; + } else { + _TMP43 = _TMP6.xyz; + } + _res = _TMP7.xyz; + if (_fp.x >= 5.00000000E-01) { + if (_fp.y >= 5.00000000E-01) { + if (_edr.x && _edr_left.x && _edr_up.x) { + _res = _TMP7.xyz + 8.33333015E-01*(_TMP40 - _TMP7.xyz); + } else { + if (_edr.x && (_edr_left.x || _edr_up.x)) { + _res = _TMP7.xyz + 7.50000000E-01*(_TMP40 - _TMP7.xyz); + } else { + if (_edr.y && _edr_left.y && _edr.w && _edr_up.w) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP43 - _TMP7.xyz); + } else { + if (_edr.y && _edr_left.y) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP41 - _TMP7.xyz); + } else { + if (_edr.w && _edr_up.w) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP43 - _TMP7.xyz); + } else { + if (_edr.x) { + _res = _TMP7.xyz + 5.00000000E-01*(_TMP40 - _TMP7.xyz); + } + } + } + } + } + } + } else { + if (_edr.y && _edr_left.y && _edr_up.y) { + _res = _TMP7.xyz + 8.33333015E-01*(_TMP41 - _TMP7.xyz); + } else { + if (_edr.y && (_edr_left.y || _edr_up.y)) { + _res = _TMP7.xyz + 7.50000000E-01*(_TMP41 - _TMP7.xyz); + } else { + if (_edr.z && _edr_left.z && _edr.x && _edr_up.x) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP40 - _TMP7.xyz); + } else { + if (_edr.z && _edr_left.z) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP42 - _TMP7.xyz); + } else { + if (_edr.x && _edr_up.x) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP40 - _TMP7.xyz); + } else { + if (_edr.y) { + _res = _TMP7.xyz + 5.00000000E-01*(_TMP41 - _TMP7.xyz); + } + } + } + } + } + } + } + } else { + if (_fp.y >= 5.00000000E-01) { + if (_edr.w && _edr_left.w && _edr_up.w) { + _res = _TMP7.xyz + 8.33333015E-01*(_TMP43 - _TMP7.xyz); + } else { + if (_edr.w && (_edr_left.w || _edr_up.w)) { + _res = _TMP7.xyz + 7.50000000E-01*(_TMP43 - _TMP7.xyz); + } else { + if (_edr.x && _edr_left.x && _edr.z && _edr_up.z) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP42 - _TMP7.xyz); + } else { + if (_edr.x && _edr_left.x) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP40 - _TMP7.xyz); + } else { + if (_edr.z && _edr_up.z) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP42 - _TMP7.xyz); + } else { + if (_edr.w) { + _res = _TMP7.xyz + 5.00000000E-01*(_TMP43 - _TMP7.xyz); + } + } + } + } + } + } + } else { + if (_edr.z && _edr_left.z && _edr_up.z) { + _res = _TMP7.xyz + 8.33333015E-01*(_TMP42 - _TMP7.xyz); + } else { + if (_edr.z && (_edr_left.z || _edr_up.z)) { + _res = _TMP7.xyz + 7.50000000E-01*(_TMP42 - _TMP7.xyz); + } else { + if (_edr.w && _edr_left.w && _edr.y && _edr_up.y) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP41 - _TMP7.xyz); + } else { + if (_edr.w && _edr_left.w) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP43 - _TMP7.xyz); + } else { + if (_edr.y && _edr_up.y) { + _res = _TMP7.xyz + 2.50000000E-01*(_TMP41 - _TMP7.xyz); + } else { + if (_edr.z) { + _res = _TMP7.xyz + 5.00000000E-01*(_TMP42 - _TMP7.xyz); + } + } + } + } + } + } + } + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.8d.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.8d.glsl new file mode 100644 index 000000000..878bb6351 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr-v3.8d.glsl @@ -0,0 +1,479 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP46; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec3 _TMP45; +vec3 _TMP43; +vec3 _TMP41; +vec3 _TMP39; +vec4 _TMP38; +vec4 _TMP31; +vec4 _TMP30; +vec4 _TMP53; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0068; +vec4 _r0112; +vec4 _r0122; +vec4 _r0132; +vec4 _r0142; +vec4 _r0152; +vec4 _r0162; +vec4 _TMP173; +vec4 _a0176; +vec4 _TMP179; +vec4 _a0182; +vec4 _TMP185; +vec4 _a0188; +vec4 _TMP191; +vec4 _a0194; +vec4 _TMP197; +vec4 _a0200; +vec4 _TMP203; +vec4 _a0206; +vec4 _TMP209; +vec4 _a0212; +vec4 _TMP215; +vec4 _a0218; +vec4 _TMP221; +vec4 _a0224; +vec4 _x0226; +vec4 _TMP227; +vec4 _x0234; +vec4 _TMP235; +vec4 _x0242; +vec4 _TMP243; +vec4 _TMP251; +vec4 _a0254; +vec4 _TMP255; +vec4 _a0258; +vec4 _TMP259; +vec4 _a0262; +vec4 _TMP263; +vec4 _a0266; +vec4 _TMP267; +vec4 _a0270; +vec4 _TMP273; +vec4 _a0276; +vec4 _TMP277; +vec4 _a0280; +vec4 _TMP281; +vec4 _a0284; +vec4 _TMP285; +vec4 _a0288; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec4 _TMP301; +vec4 _a0304; +vec4 _TMP305; +vec4 _a0308; +vec4 _TMP309; +vec4 _a0312; +vec4 _TMP313; +vec4 _a0316; +float _t0322; +float _t0326; +float _t0330; +float _t0334; +vec4 _r0338; +vec4 _TMP347; +vec4 _a0350; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec2 _fp; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _maximo; + vec3 _res; + float _mx; + _x0068 = TEX0.xy*TextureSize; + _fp = fract(_x0068); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0112.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _a0176 = _r0112.wxyz - _r0112; + _TMP173 = abs(_a0176); + _TMP21 = bvec4(_TMP173.x < 1.50000000E+01, _TMP173.y < 1.50000000E+01, _TMP173.z < 1.50000000E+01, _TMP173.w < 1.50000000E+01); + _a0182 = _r0112.zwxy - _r0112.yzwx; + _TMP179 = abs(_a0182); + _TMP22 = bvec4(_TMP179.x < 1.50000000E+01, _TMP179.y < 1.50000000E+01, _TMP179.z < 1.50000000E+01, _TMP179.w < 1.50000000E+01); + _a0188 = _r0132 - _r0122.wxyz; + _TMP185 = abs(_a0188); + _TMP23 = bvec4(_TMP185.x < 1.50000000E+01, _TMP185.y < 1.50000000E+01, _TMP185.z < 1.50000000E+01, _TMP185.w < 1.50000000E+01); + _a0194 = _r0112.wxyz - _r0142; + _TMP191 = abs(_a0194); + _TMP24 = bvec4(_TMP191.x < 1.50000000E+01, _TMP191.y < 1.50000000E+01, _TMP191.z < 1.50000000E+01, _TMP191.w < 1.50000000E+01); + _a0200 = _r0112.zwxy - _r0152; + _TMP197 = abs(_a0200); + _TMP25 = bvec4(_TMP197.x < 1.50000000E+01, _TMP197.y < 1.50000000E+01, _TMP197.z < 1.50000000E+01, _TMP197.w < 1.50000000E+01); + _a0206 = _r0132 - _r0122.zwxy; + _TMP203 = abs(_a0206); + _TMP26 = bvec4(_TMP203.x < 1.50000000E+01, _TMP203.y < 1.50000000E+01, _TMP203.z < 1.50000000E+01, _TMP203.w < 1.50000000E+01); + _a0212 = _r0132 - _r0122; + _TMP209 = abs(_a0212); + _TMP27 = bvec4(_TMP209.x < 1.50000000E+01, _TMP209.y < 1.50000000E+01, _TMP209.z < 1.50000000E+01, _TMP209.w < 1.50000000E+01); + _a0218 = _r0112 - _r0142.yzwx; + _TMP215 = abs(_a0218); + _TMP28 = bvec4(_TMP215.x < 1.50000000E+01, _TMP215.y < 1.50000000E+01, _TMP215.z < 1.50000000E+01, _TMP215.w < 1.50000000E+01); + _a0224 = _r0112.yzwx - _r0152.wxyz; + _TMP221 = abs(_a0224); + _TMP29 = bvec4(_TMP221.x < 1.50000000E+01, _TMP221.y < 1.50000000E+01, _TMP221.z < 1.50000000E+01, _TMP221.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0132.x != _r0112.w && _r0132.x != _r0112.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0112.w != _r0162.y && _r0112.w != _r0122.w || _r0112.z != _r0162.x && _r0112.z != _r0122.w || _r0112.z != _r0122.z || _r0112.w != _r0122.x || _TMP28.x && _TMP29.x), _r0132.y != _r0112.x && _r0132.y != _r0112.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0112.x != _r0162.z && _r0112.x != _r0122.x || _r0112.w != _r0162.y && _r0112.w != _r0122.x || _r0112.w != _r0122.w || _r0112.x != _r0122.y || _TMP28.y && _TMP29.y), _r0132.z != _r0112.y && _r0132.z != _r0112.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0112.y != _r0162.w && _r0112.y != _r0122.y || _r0112.x != _r0162.z && _r0112.x != _r0122.y || _r0112.x != _r0122.x || _r0112.y != _r0122.z || _TMP28.z && _TMP29.z), _r0132.w != _r0112.z && _r0132.w != _r0112.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0112.z != _r0162.x && _r0112.z != _r0122.z || _r0112.y != _r0162.w && _r0112.y != _r0122.z || _r0112.y != _r0122.y || _r0112.z != _r0122.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0132.x != _r0122.z && _r0112.y != _r0122.z, _r0132.y != _r0122.w && _r0112.z != _r0122.w, _r0132.z != _r0122.x && _r0112.w != _r0122.x, _r0132.w != _r0122.y && _r0112.x != _r0122.y); + _interp_restriction_lv2_up = bvec4(_r0132.x != _r0122.x && _r0112.x != _r0122.x, _r0132.y != _r0122.y && _r0112.y != _r0122.y, _r0132.z != _r0122.z && _r0112.z != _r0122.z, _r0132.w != _r0122.w && _r0112.w != _r0122.w); + _x0226 = (_fx + vec4( 5.00000000E-01, 5.00000000E-01, 5.00000000E-01, 5.00000000E-01)) - vec4( 1.50000000E+00, 5.00000000E-01, -5.00000000E-01, 5.00000000E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0226); + _TMP227 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0234 = ((_fx_left + vec4( 2.50000000E-01, 5.00000000E-01, 2.50000000E-01, 5.00000000E-01)) - vec4( 1.00000000E+00, 1.00000000E+00, -5.00000000E-01, 0.00000000E+00))/vec4( 5.00000000E-01, 1.00000000E+00, 5.00000000E-01, 1.00000000E+00); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0234); + _TMP235 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0242 = ((_fx_up + vec4( 5.00000000E-01, 2.50000000E-01, 5.00000000E-01, 2.50000000E-01)) - vec4( 2.00000000E+00, 0.00000000E+00, -1.00000000E+00, 5.00000000E-01))/vec4( 1.00000000E+00, 5.00000000E-01, 1.00000000E+00, 5.00000000E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0242); + _TMP243 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _a0254 = _r0132 - _r0122; + _TMP251 = abs(_a0254); + _a0258 = _r0132 - _r0122.zwxy; + _TMP255 = abs(_a0258); + _a0262 = _r0122.wxyz - _r0162; + _TMP259 = abs(_a0262); + _a0266 = _r0122.wxyz - _r0162.yzwx; + _TMP263 = abs(_a0266); + _a0270 = _r0112.zwxy - _r0112.wxyz; + _TMP267 = abs(_a0270); + _TMP30 = _TMP251 + _TMP255 + _TMP259 + _TMP263 + 4.00000000E+00*_TMP267; + _a0276 = _r0112.zwxy - _r0112.yzwx; + _TMP273 = abs(_a0276); + _a0280 = _r0112.zwxy - _r0152; + _TMP277 = abs(_a0280); + _a0284 = _r0112.wxyz - _r0142; + _TMP281 = abs(_a0284); + _a0288 = _r0112.wxyz - _r0112; + _TMP285 = abs(_a0288); + _a0292 = _r0132 - _r0122.wxyz; + _TMP289 = abs(_a0292); + _TMP31 = _TMP273 + _TMP277 + _TMP281 + _TMP285 + 4.00000000E+00*_TMP289; + _edr = bvec4(_TMP30.x < _TMP31.x && _interp_restriction_lv1.x, _TMP30.y < _TMP31.y && _interp_restriction_lv1.y, _TMP30.z < _TMP31.z && _interp_restriction_lv1.z, _TMP30.w < _TMP31.w && _interp_restriction_lv1.w); + _a0296 = _r0112.wxyz - _r0122.zwxy; + _TMP293 = abs(_a0296); + _a0300 = _r0112.zwxy - _r0122; + _TMP297 = abs(_a0300); + _edr_left = bvec4((2.00000000E+00*_TMP293).x <= _TMP297.x && _interp_restriction_lv2_left.x && _edr.x, (2.00000000E+00*_TMP293).y <= _TMP297.y && _interp_restriction_lv2_left.y && _edr.y, (2.00000000E+00*_TMP293).z <= _TMP297.z && _interp_restriction_lv2_left.z && _edr.z, (2.00000000E+00*_TMP293).w <= _TMP297.w && _interp_restriction_lv2_left.w && _edr.w); + _a0304 = _r0112.wxyz - _r0122.zwxy; + _TMP301 = abs(_a0304); + _a0308 = _r0112.zwxy - _r0122; + _TMP305 = abs(_a0308); + _edr_up = bvec4(_TMP301.x >= (2.00000000E+00*_TMP305).x && _interp_restriction_lv2_up.x && _edr.x, _TMP301.y >= (2.00000000E+00*_TMP305).y && _interp_restriction_lv2_up.y && _edr.y, _TMP301.z >= (2.00000000E+00*_TMP305).z && _interp_restriction_lv2_up.z && _edr.z, _TMP301.w >= (2.00000000E+00*_TMP305).w && _interp_restriction_lv2_up.w && _edr.w); + _fx45 = vec4(float(_edr.x), float(_edr.y), float(_edr.z), float(_edr.w))*_TMP227; + _fx30 = vec4(float(_edr_left.x), float(_edr_left.y), float(_edr_left.z), float(_edr_left.w))*_TMP235; + _fx60 = vec4(float(_edr_up.x), float(_edr_up.y), float(_edr_up.z), float(_edr_up.w))*_TMP243; + _a0312 = _r0132 - _r0112.wxyz; + _TMP309 = abs(_a0312); + _a0316 = _r0132 - _r0112.zwxy; + _TMP313 = abs(_a0316); + _px = bvec4(_TMP309.x <= _TMP313.x, _TMP309.y <= _TMP313.y, _TMP309.z <= _TMP313.z, _TMP309.w <= _TMP313.w); + _TMP38 = max(_fx30, _fx60); + _maximo = max(_TMP38, _fx45); + _t0322 = float(_px.x); + _TMP39 = _TMP10.xyz + _t0322*(_TMP8.xyz - _TMP10.xyz); + _TMP40 = _TMP7.xyz + _maximo.x*(_TMP39 - _TMP7.xyz); + _t0326 = float(_px.y); + _TMP41 = _TMP8.xyz + _t0326*(_TMP4.xyz - _TMP8.xyz); + _TMP42 = _TMP7.xyz + _maximo.y*(_TMP41 - _TMP7.xyz); + _t0330 = float(_px.z); + _TMP43 = _TMP4.xyz + _t0330*(_TMP6.xyz - _TMP4.xyz); + _TMP44 = _TMP7.xyz + _maximo.z*(_TMP43 - _TMP7.xyz); + _t0334 = float(_px.w); + _TMP45 = _TMP6.xyz + _t0334*(_TMP10.xyz - _TMP6.xyz); + _TMP46 = _TMP7.xyz + _maximo.w*(_TMP45 - _TMP7.xyz); + _r0338.x = dot(_TMP40, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.y = dot(_TMP42, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.z = dot(_TMP44, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.w = dot(_TMP46, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _a0350 = _r0338 - _r0132; + _TMP347 = abs(_a0350); + _res = _TMP40; + _mx = _TMP347.x; + if (_TMP347.y > _TMP347.x) { + _res = _TMP42; + _mx = _TMP347.y; + } + if (_TMP347.z > _mx) { + _res = _TMP44; + _mx = _TMP347.z; + } + if (_TMP347.w > _mx) { + _res = _TMP46; + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr.glsl new file mode 100644 index 000000000..281f4c45a --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/2xbr.glsl @@ -0,0 +1,202 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +float _TMP7; +float _TMP6; +float _TMP5; +float _TMP4; +float _TMP3; +float _TMP2; +float _TMP1; +float _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0021; +vec2 _c0039; +vec2 _c0041; +vec2 _c0043; +vec2 _c0047; +vec2 _c0049; +vec2 _c0051; +vec2 _c0053; +float _TMP54; +float _TMP58; +float _TMP62; +float _TMP66; +float _TMP70; +float _TMP74; +float _TMP78; +float _TMP82; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec3 _res; + vec2 _fp; + vec2 _g1; + vec2 _g2; + _x0021 = TEX0.xy*TextureSize; + _fp = fract(_x0021); + _TMP0 = float((_fp.x >= 5.00000000E-01)); + _TMP1 = float((_fp.y >= 5.00000000E-01)); + _TMP2 = float((_fp.x >= 5.00000000E-01)); + _TMP3 = float((_fp.y >= 5.00000000E-01)); + _g1 = TEX1.xy*((_TMP0 + _TMP1) - 1.00000000E+00) + TEX1.zw*(_TMP2 - _TMP3); + _TMP4 = float((_fp.y >= 5.00000000E-01)); + _TMP5 = float((_fp.x >= 5.00000000E-01)); + _TMP6 = float((_fp.x >= 5.00000000E-01)); + _TMP7 = float((_fp.y >= 5.00000000E-01)); + _g2 = TEX1.xy*(_TMP4 - _TMP5) + TEX1.zw*((_TMP6 + _TMP7) - 1.00000000E+00); + _c0039 = TEX0.xy + _g1; + _TMP8 = COMPAT_TEXTURE(Texture, _c0039); + _c0041 = (TEX0.xy + _g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0041); + _c0043 = TEX0.xy + _g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0043); + _TMP11 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0047 = TEX0.xy - _g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0047); + _c0049 = (TEX0.xy - _g1) + _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0049); + _c0051 = TEX0.xy - _g1; + _TMP14 = COMPAT_TEXTURE(Texture, _c0051); + _c0053 = (TEX0.xy - _g1) - _g2; + _TMP15 = COMPAT_TEXTURE(Texture, _c0053); + _TMP54 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP58 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP62 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP66 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP70 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP74 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP78 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP82 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _res = _TMP11.xyz; + if (_TMP78 == _TMP70 && _TMP78 != _TMP66 && (_TMP66 == _TMP74 && (_TMP78 == _TMP82 || _TMP66 == _TMP62) || _TMP66 == _TMP58 && (_TMP78 == _TMP82 || _TMP66 == _TMP54))) { + _res = _TMP11.xyz + 5.00000000E-01*(_TMP12.xyz - _TMP11.xyz); + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v2.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v2.glsl new file mode 100644 index 000000000..1ae35a0b8 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v2.glsl @@ -0,0 +1,379 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color1; +struct output_dummy { + vec4 _color1; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +vec4 _oPosition1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec4 _oColor; + vec2 _otexCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _oPosition1 = _r0006; + _oColor = COLOR; + _otexCoord = TexCoord.xy; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color1; +struct output_dummy { + vec4 _color1; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +vec3 _TMP27; +vec3 _TMP28; +vec3 _TMP25; +vec3 _TMP26; +vec3 _TMP23; +vec3 _TMP24; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _c0036; +vec2 _c0038; +vec2 _c0040; +vec2 _c0042; +vec2 _c0046; +vec2 _c0048; +vec2 _c0050; +vec2 _c0052; +vec2 _c0054; +vec2 _c0056; +vec2 _c0058; +vec2 _c0060; +vec2 _c0062; +vec2 _c0064; +vec2 _c0066; +vec2 _c0068; +float _TMP69; +float _TMP73; +float _TMP77; +float _TMP81; +float _TMP85; +float _TMP89; +float _TMP93; +float _TMP97; +float _TMP101; +float _TMP105; +float _TMP109; +float _TMP113; +float _TMP117; +float _TMP121; +float _TMP125; +float _TMP129; +float _TMP133; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _ps; + vec2 _dx; + vec2 _dy; + vec2 _pixcoord; + vec2 _fp; + vec2 _d11; + vec3 _E[9]; + vec3 _res; + output_dummy _OUT; + _ps = vec2(9.99899983E-01/TextureSize.x, 9.99899983E-01/TextureSize.y); + _dx = vec2(_ps.x, 0.00000000E+00); + _dy = vec2(0.00000000E+00, _ps.y); + _pixcoord = TEX0.xy/_ps; + _fp = fract(_pixcoord); + _d11 = TEX0.xy - _fp*_ps; + _c0036 = (_d11 - _dx) - _dy; + _TMP0 = COMPAT_TEXTURE(Texture, _c0036); + _c0038 = _d11 - _dy; + _TMP1 = COMPAT_TEXTURE(Texture, _c0038); + _c0040 = (_d11 + _dx) - _dy; + _TMP2 = COMPAT_TEXTURE(Texture, _c0040); + _c0042 = _d11 - _dx; + _TMP3 = COMPAT_TEXTURE(Texture, _c0042); + _TMP4 = COMPAT_TEXTURE(Texture, _d11); + _c0046 = _d11 + _dx; + _TMP5 = COMPAT_TEXTURE(Texture, _c0046); + _c0048 = (_d11 - _dx) + _dy; + _TMP6 = COMPAT_TEXTURE(Texture, _c0048); + _c0050 = _d11 + _dy; + _TMP7 = COMPAT_TEXTURE(Texture, _c0050); + _c0052 = _d11 + _dx + _dy; + _TMP8 = COMPAT_TEXTURE(Texture, _c0052); + _c0054 = ((_d11 - _dx) - _dy) - _dy; + _TMP9 = COMPAT_TEXTURE(Texture, _c0054); + _c0056 = ((_d11 + _dx) - _dy) - _dy; + _TMP10 = COMPAT_TEXTURE(Texture, _c0056); + _c0058 = ((_d11 - _dx) - _dx) - _dy; + _TMP11 = COMPAT_TEXTURE(Texture, _c0058); + _c0060 = ((_d11 - _dx) - _dx) + _dy; + _TMP12 = COMPAT_TEXTURE(Texture, _c0060); + _c0062 = (_d11 + _dx + _dx) - _dy; + _TMP13 = COMPAT_TEXTURE(Texture, _c0062); + _c0064 = _d11 + _dx + _dx + _dy; + _TMP14 = COMPAT_TEXTURE(Texture, _c0064); + _c0066 = (_d11 - _dx) + _dy + _dy; + _TMP15 = COMPAT_TEXTURE(Texture, _c0066); + _c0068 = _d11 + _dx + _dy + _dy; + _TMP16 = COMPAT_TEXTURE(Texture, _c0068); + _E[2] = _TMP4.xyz; + _E[1] = _TMP4.xyz; + _E[0] = _TMP4.xyz; + _E[5] = _TMP4.xyz; + _E[3] = _TMP4.xyz; + _E[8] = _TMP4.xyz; + _E[7] = _TMP4.xyz; + _E[6] = _TMP4.xyz; + _TMP69 = dot(_TMP0.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP73 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP77 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP81 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP85 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP89 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP93 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP97 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP101 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP105 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP109 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP113 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP117 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP121 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP125 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP129 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP133 = dot(_TMP16.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP85 != _TMP97 && _TMP97 == _TMP89 && (_TMP85 != _TMP101 && (_TMP85 != _TMP73 || _TMP85 != _TMP81 || _TMP73 == _TMP109 && _TMP81 == _TMP117 || _TMP89 != _TMP73 && _TMP89 != _TMP77 || _TMP97 != _TMP81 && _TMP97 != _TMP93) || _TMP85 == _TMP93 && (_TMP101 == _TMP97 || _TMP85 == _TMP81 || _TMP97 != _TMP81) || _TMP85 == _TMP77 && (_TMP101 == _TMP97 || _TMP85 == _TMP73 || _TMP89 != _TMP73))) { + if (_TMP85 == _TMP77 && _TMP85 == _TMP81 && _TMP97 == _TMP93) { + _E[5] = (3.00000000E+00*_TMP4.xyz + _TMP5.xyz)*2.50000000E-01; + _E[6] = _E[5]; + _E[7] = (_TMP4.xyz + _TMP5.xyz) - _E[5]; + _E[8] = _TMP7.xyz; + } else { + if (_TMP85 == _TMP93 && _TMP85 == _TMP73 && _TMP89 == _TMP77) { + _E[7] = (3.00000000E+00*_TMP4.xyz + _TMP7.xyz)*2.50000000E-01; + _E[2] = _E[7]; + _E[5] = (_TMP4.xyz + _TMP7.xyz) - _E[7]; + _E[8] = _TMP5.xyz; + } else { + _E[8] = _TMP4.xyz + 8.75000000E-01*(_TMP5.xyz - _TMP4.xyz); + _E[5] = (_TMP4.xyz + _TMP5.xyz) - _E[8]; + _E[7] = _E[5]; + } + } + } else { + if (_TMP85 != _TMP97 && _TMP93 == _TMP85 && _TMP85 == _TMP77 && _TMP85 != _TMP101 && _TMP85 != _TMP89) { + _E[8] = _TMP4.xyz + 8.75000000E-01*(_TMP5.xyz - _TMP4.xyz); + _E[5] = _TMP4.xyz + 1.25000000E-01*(_TMP5.xyz - _TMP4.xyz); + _E[7] = _TMP4.xyz + 1.25000000E-01*(_TMP7.xyz - _TMP4.xyz); + } + } + if (_TMP85 != _TMP89 && _TMP89 == _TMP73 && (_TMP85 != _TMP77 && (_TMP85 != _TMP81 || _TMP85 != _TMP97 || _TMP81 == _TMP113 && _TMP97 == _TMP133 || _TMP73 != _TMP81 && _TMP73 != _TMP69 || _TMP89 != _TMP97 && _TMP89 != _TMP101) || _TMP85 == _TMP101 && (_TMP77 == _TMP89 || _TMP85 == _TMP97 || _TMP89 != _TMP97) || _TMP85 == _TMP69 && (_TMP77 == _TMP89 || _TMP85 == _TMP81 || _TMP73 != _TMP81))) { + if (_TMP85 == _TMP69 && _TMP85 == _TMP97 && _TMP89 == _TMP101) { + _E[1] = (3.00000000E+00*_TMP4.xyz + _TMP1.xyz)*2.50000000E-01; + _E[8] = _E[1]; + _E[5] = (_E[5] + _TMP1.xyz) - _E[1]; + _E[2] = _TMP5.xyz; + } else { + if (_TMP85 == _TMP101 && _TMP85 == _TMP81 && _TMP73 == _TMP69) { + _E[5] = (3.00000000E+00*_E[5] + _TMP5.xyz)*2.50000000E-01; + _E[0] = _E[5]; + _E[1] = (_TMP4.xyz + _TMP5.xyz) - _E[5]; + _E[2] = _TMP1.xyz; + } else { + _E[2] = _E[2] + 8.75000000E-01*(_TMP1.xyz - _E[2]); + _E[1] = (_TMP4.xyz + _TMP1.xyz) - _E[2]; + _E[5] = _E[1]; + } + } + } else { + if (_TMP85 != _TMP89 && _TMP101 == _TMP85 && _TMP85 == _TMP69 && _TMP85 != _TMP77 && _TMP85 != _TMP73) { + _E[2] = _E[2] + 8.75000000E-01*(_TMP1.xyz - _E[2]); + _E[1] = _TMP4.xyz + 1.25000000E-01*(_TMP1.xyz - _TMP4.xyz); + _E[5] = _E[5] + 1.25000000E-01*(_TMP5.xyz - _E[5]); + } + } + if (_TMP85 != _TMP73 && _TMP73 == _TMP81 && (_TMP85 != _TMP69 && (_TMP85 != _TMP97 || _TMP85 != _TMP89 || _TMP97 == _TMP129 && _TMP89 == _TMP121 || _TMP81 != _TMP97 && _TMP81 != _TMP93 || _TMP73 != _TMP89 && _TMP73 != _TMP77) || _TMP85 == _TMP77 && (_TMP69 == _TMP73 || _TMP85 == _TMP89 || _TMP73 != _TMP89) || _TMP85 == _TMP93 && (_TMP69 == _TMP73 || _TMP85 == _TMP97 || _TMP81 != _TMP97))) { + if (_TMP85 == _TMP93 && _TMP85 == _TMP89 && _TMP73 == _TMP77) { + _E[3] = (3.00000000E+00*_TMP4.xyz + _TMP3.xyz)*2.50000000E-01; + _E[2] = _E[3]; + _E[1] = (_E[1] + _TMP3.xyz) - _E[3]; + _E[0] = _TMP1.xyz; + } else { + if (_TMP85 == _TMP77 && _TMP85 == _TMP97 && _TMP81 == _TMP93) { + _E[1] = (3.00000000E+00*_E[1] + _TMP1.xyz)*2.50000000E-01; + _E[6] = _E[1]; + _E[3] = (_TMP4.xyz + _TMP1.xyz) - _E[1]; + _E[0] = _TMP3.xyz; + } else { + _E[0] = _E[0] + 8.75000000E-01*(_TMP3.xyz - _E[0]); + _E[3] = (_TMP4.xyz + _TMP3.xyz) - _E[0]; + _E[1] = _E[3]; + } + } + } else { + if (_TMP85 != _TMP73 && _TMP77 == _TMP85 && _TMP85 == _TMP93 && _TMP85 != _TMP69 && _TMP85 != _TMP81) { + _E[0] = _E[0] + 8.75000000E-01*(_TMP3.xyz - _E[0]); + _E[3] = _TMP4.xyz + 1.25000000E-01*(_TMP3.xyz - _TMP4.xyz); + _E[1] = _E[1] + 1.25000000E-01*(_TMP1.xyz - _E[1]); + } + } + if (_TMP85 != _TMP81 && _TMP81 == _TMP97 && (_TMP85 != _TMP93 && (_TMP85 != _TMP89 || _TMP85 != _TMP73 || _TMP89 == _TMP125 && _TMP73 == _TMP105 || _TMP97 != _TMP89 && _TMP97 != _TMP101 || _TMP81 != _TMP73 && _TMP81 != _TMP69) || _TMP85 == _TMP69 && (_TMP93 == _TMP81 || _TMP85 == _TMP73 || _TMP81 != _TMP73) || _TMP85 == _TMP101 && (_TMP93 == _TMP81 || _TMP85 == _TMP89 || _TMP97 != _TMP89))) { + if (_TMP85 == _TMP101 && _TMP85 == _TMP73 && _TMP81 == _TMP69) { + _E[7] = (3.00000000E+00*_E[7] + _TMP7.xyz)*2.50000000E-01; + _E[0] = _E[7]; + _E[3] = (_E[3] + _TMP7.xyz) - _E[7]; + _E[6] = _TMP3.xyz; + } else { + if (_TMP85 == _TMP69 && _TMP85 == _TMP89 && _TMP97 == _TMP101) { + _E[3] = (3.00000000E+00*_E[3] + _TMP3.xyz)*2.50000000E-01; + _E[8] = _E[3]; + _E[7] = (_E[7] + _TMP3.xyz) - _E[3]; + _E[6] = _TMP7.xyz; + } else { + _E[6] = _E[6] + 8.75000000E-01*(_TMP7.xyz - _E[6]); + _E[7] = (_E[7] + _TMP7.xyz) - _E[6]; + _E[3] = _E[7]; + } + } + } else { + if (_TMP85 != _TMP81 && _TMP69 == _TMP85 && _TMP85 == _TMP101 && _TMP85 != _TMP93 && _TMP85 != _TMP97) { + _E[6] = _E[6] + 8.75000000E-01*(_TMP7.xyz - _E[6]); + _E[7] = _E[7] + 1.25000000E-01*(_TMP7.xyz - _E[7]); + _E[3] = _E[3] + 1.25000000E-01*(_TMP3.xyz - _E[3]); + } + } + if (_fp.x < 3.33333343E-01) { + if (_fp.y < 3.33333343E-01) { + _TMP23 = _E[0]; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP24 = _E[3]; + } else { + _TMP24 = _E[6]; + } + _TMP23 = _TMP24; + } + _res = _TMP23; + } else { + if (_fp.x < 6.66666687E-01) { + if (_fp.y < 3.33333343E-01) { + _TMP25 = _E[1]; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP26 = _TMP4.xyz; + } else { + _TMP26 = _E[7]; + } + _TMP25 = _TMP26; + } + _res = _TMP25; + } else { + if (_fp.y < 3.33333343E-01) { + _TMP27 = _E[2]; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP28 = _E[5]; + } else { + _TMP28 = _E[8]; + } + _TMP27 = _TMP28; + } + _res = _TMP27; + } + } + _OUT._color1 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _OUT._color1; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v3.8d.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v3.8d.glsl new file mode 100644 index 000000000..eb09a06f5 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr-v3.8d.glsl @@ -0,0 +1,479 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP46; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec3 _TMP45; +vec3 _TMP43; +vec3 _TMP41; +vec3 _TMP39; +vec4 _TMP38; +vec4 _TMP31; +vec4 _TMP30; +vec4 _TMP53; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0068; +vec4 _r0112; +vec4 _r0122; +vec4 _r0132; +vec4 _r0142; +vec4 _r0152; +vec4 _r0162; +vec4 _TMP173; +vec4 _a0176; +vec4 _TMP179; +vec4 _a0182; +vec4 _TMP185; +vec4 _a0188; +vec4 _TMP191; +vec4 _a0194; +vec4 _TMP197; +vec4 _a0200; +vec4 _TMP203; +vec4 _a0206; +vec4 _TMP209; +vec4 _a0212; +vec4 _TMP215; +vec4 _a0218; +vec4 _TMP221; +vec4 _a0224; +vec4 _x0226; +vec4 _TMP227; +vec4 _x0234; +vec4 _TMP235; +vec4 _x0242; +vec4 _TMP243; +vec4 _TMP251; +vec4 _a0254; +vec4 _TMP255; +vec4 _a0258; +vec4 _TMP259; +vec4 _a0262; +vec4 _TMP263; +vec4 _a0266; +vec4 _TMP267; +vec4 _a0270; +vec4 _TMP273; +vec4 _a0276; +vec4 _TMP277; +vec4 _a0280; +vec4 _TMP281; +vec4 _a0284; +vec4 _TMP285; +vec4 _a0288; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec4 _TMP301; +vec4 _a0304; +vec4 _TMP305; +vec4 _a0308; +vec4 _TMP309; +vec4 _a0312; +vec4 _TMP313; +vec4 _a0316; +float _t0322; +float _t0326; +float _t0330; +float _t0334; +vec4 _r0338; +vec4 _TMP347; +vec4 _a0350; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec2 _fp; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _maximo; + vec3 _res; + float _mx; + _x0068 = TEX0.xy*TextureSize; + _fp = fract(_x0068); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0112.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _a0176 = _r0112.wxyz - _r0112; + _TMP173 = abs(_a0176); + _TMP21 = bvec4(_TMP173.x < 1.50000000E+01, _TMP173.y < 1.50000000E+01, _TMP173.z < 1.50000000E+01, _TMP173.w < 1.50000000E+01); + _a0182 = _r0112.zwxy - _r0112.yzwx; + _TMP179 = abs(_a0182); + _TMP22 = bvec4(_TMP179.x < 1.50000000E+01, _TMP179.y < 1.50000000E+01, _TMP179.z < 1.50000000E+01, _TMP179.w < 1.50000000E+01); + _a0188 = _r0132 - _r0122.wxyz; + _TMP185 = abs(_a0188); + _TMP23 = bvec4(_TMP185.x < 1.50000000E+01, _TMP185.y < 1.50000000E+01, _TMP185.z < 1.50000000E+01, _TMP185.w < 1.50000000E+01); + _a0194 = _r0112.wxyz - _r0142; + _TMP191 = abs(_a0194); + _TMP24 = bvec4(_TMP191.x < 1.50000000E+01, _TMP191.y < 1.50000000E+01, _TMP191.z < 1.50000000E+01, _TMP191.w < 1.50000000E+01); + _a0200 = _r0112.zwxy - _r0152; + _TMP197 = abs(_a0200); + _TMP25 = bvec4(_TMP197.x < 1.50000000E+01, _TMP197.y < 1.50000000E+01, _TMP197.z < 1.50000000E+01, _TMP197.w < 1.50000000E+01); + _a0206 = _r0132 - _r0122.zwxy; + _TMP203 = abs(_a0206); + _TMP26 = bvec4(_TMP203.x < 1.50000000E+01, _TMP203.y < 1.50000000E+01, _TMP203.z < 1.50000000E+01, _TMP203.w < 1.50000000E+01); + _a0212 = _r0132 - _r0122; + _TMP209 = abs(_a0212); + _TMP27 = bvec4(_TMP209.x < 1.50000000E+01, _TMP209.y < 1.50000000E+01, _TMP209.z < 1.50000000E+01, _TMP209.w < 1.50000000E+01); + _a0218 = _r0112 - _r0142.yzwx; + _TMP215 = abs(_a0218); + _TMP28 = bvec4(_TMP215.x < 1.50000000E+01, _TMP215.y < 1.50000000E+01, _TMP215.z < 1.50000000E+01, _TMP215.w < 1.50000000E+01); + _a0224 = _r0112.yzwx - _r0152.wxyz; + _TMP221 = abs(_a0224); + _TMP29 = bvec4(_TMP221.x < 1.50000000E+01, _TMP221.y < 1.50000000E+01, _TMP221.z < 1.50000000E+01, _TMP221.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0132.x != _r0112.w && _r0132.x != _r0112.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0112.w != _r0162.y && _r0112.w != _r0122.w || _r0112.z != _r0162.x && _r0112.z != _r0122.w || _r0112.z != _r0122.z || _r0112.w != _r0122.x || _TMP28.x && _TMP29.x), _r0132.y != _r0112.x && _r0132.y != _r0112.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0112.x != _r0162.z && _r0112.x != _r0122.x || _r0112.w != _r0162.y && _r0112.w != _r0122.x || _r0112.w != _r0122.w || _r0112.x != _r0122.y || _TMP28.y && _TMP29.y), _r0132.z != _r0112.y && _r0132.z != _r0112.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0112.y != _r0162.w && _r0112.y != _r0122.y || _r0112.x != _r0162.z && _r0112.x != _r0122.y || _r0112.x != _r0122.x || _r0112.y != _r0122.z || _TMP28.z && _TMP29.z), _r0132.w != _r0112.z && _r0132.w != _r0112.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0112.z != _r0162.x && _r0112.z != _r0122.z || _r0112.y != _r0162.w && _r0112.y != _r0122.z || _r0112.y != _r0122.y || _r0112.z != _r0122.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0132.x != _r0122.z && _r0112.y != _r0122.z, _r0132.y != _r0122.w && _r0112.z != _r0122.w, _r0132.z != _r0122.x && _r0112.w != _r0122.x, _r0132.w != _r0122.y && _r0112.x != _r0122.y); + _interp_restriction_lv2_up = bvec4(_r0132.x != _r0122.x && _r0112.x != _r0122.x, _r0132.y != _r0122.y && _r0112.y != _r0122.y, _r0132.z != _r0122.z && _r0112.z != _r0122.z, _r0132.w != _r0122.w && _r0112.w != _r0122.w); + _x0226 = ((_fx + vec4( 3.33333343E-01, 3.33333343E-01, 3.33333343E-01, 3.33333343E-01)) - vec4( 1.50000000E+00, 5.00000000E-01, -5.00000000E-01, 5.00000000E-01))/vec4( 6.66666687E-01, 6.66666687E-01, 6.66666687E-01, 6.66666687E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0226); + _TMP227 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0234 = ((_fx_left + vec4( 1.66666672E-01, 3.33333343E-01, 1.66666672E-01, 3.33333343E-01)) - vec4( 1.00000000E+00, 1.00000000E+00, -5.00000000E-01, 0.00000000E+00))/vec4( 3.33333343E-01, 6.66666687E-01, 3.33333343E-01, 6.66666687E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0234); + _TMP235 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0242 = ((_fx_up + vec4( 3.33333343E-01, 1.66666672E-01, 3.33333343E-01, 1.66666672E-01)) - vec4( 2.00000000E+00, 0.00000000E+00, -1.00000000E+00, 5.00000000E-01))/vec4( 6.66666687E-01, 3.33333343E-01, 6.66666687E-01, 3.33333343E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0242); + _TMP243 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _a0254 = _r0132 - _r0122; + _TMP251 = abs(_a0254); + _a0258 = _r0132 - _r0122.zwxy; + _TMP255 = abs(_a0258); + _a0262 = _r0122.wxyz - _r0162; + _TMP259 = abs(_a0262); + _a0266 = _r0122.wxyz - _r0162.yzwx; + _TMP263 = abs(_a0266); + _a0270 = _r0112.zwxy - _r0112.wxyz; + _TMP267 = abs(_a0270); + _TMP30 = _TMP251 + _TMP255 + _TMP259 + _TMP263 + 4.00000000E+00*_TMP267; + _a0276 = _r0112.zwxy - _r0112.yzwx; + _TMP273 = abs(_a0276); + _a0280 = _r0112.zwxy - _r0152; + _TMP277 = abs(_a0280); + _a0284 = _r0112.wxyz - _r0142; + _TMP281 = abs(_a0284); + _a0288 = _r0112.wxyz - _r0112; + _TMP285 = abs(_a0288); + _a0292 = _r0132 - _r0122.wxyz; + _TMP289 = abs(_a0292); + _TMP31 = _TMP273 + _TMP277 + _TMP281 + _TMP285 + 4.00000000E+00*_TMP289; + _edr = bvec4(_TMP30.x < _TMP31.x && _interp_restriction_lv1.x, _TMP30.y < _TMP31.y && _interp_restriction_lv1.y, _TMP30.z < _TMP31.z && _interp_restriction_lv1.z, _TMP30.w < _TMP31.w && _interp_restriction_lv1.w); + _a0296 = _r0112.wxyz - _r0122.zwxy; + _TMP293 = abs(_a0296); + _a0300 = _r0112.zwxy - _r0122; + _TMP297 = abs(_a0300); + _edr_left = bvec4((2.00000000E+00*_TMP293).x <= _TMP297.x && _interp_restriction_lv2_left.x && _edr.x, (2.00000000E+00*_TMP293).y <= _TMP297.y && _interp_restriction_lv2_left.y && _edr.y, (2.00000000E+00*_TMP293).z <= _TMP297.z && _interp_restriction_lv2_left.z && _edr.z, (2.00000000E+00*_TMP293).w <= _TMP297.w && _interp_restriction_lv2_left.w && _edr.w); + _a0304 = _r0112.wxyz - _r0122.zwxy; + _TMP301 = abs(_a0304); + _a0308 = _r0112.zwxy - _r0122; + _TMP305 = abs(_a0308); + _edr_up = bvec4(_TMP301.x >= (2.00000000E+00*_TMP305).x && _interp_restriction_lv2_up.x && _edr.x, _TMP301.y >= (2.00000000E+00*_TMP305).y && _interp_restriction_lv2_up.y && _edr.y, _TMP301.z >= (2.00000000E+00*_TMP305).z && _interp_restriction_lv2_up.z && _edr.z, _TMP301.w >= (2.00000000E+00*_TMP305).w && _interp_restriction_lv2_up.w && _edr.w); + _fx45 = vec4(float(_edr.x), float(_edr.y), float(_edr.z), float(_edr.w))*_TMP227; + _fx30 = vec4(float(_edr_left.x), float(_edr_left.y), float(_edr_left.z), float(_edr_left.w))*_TMP235; + _fx60 = vec4(float(_edr_up.x), float(_edr_up.y), float(_edr_up.z), float(_edr_up.w))*_TMP243; + _a0312 = _r0132 - _r0112.wxyz; + _TMP309 = abs(_a0312); + _a0316 = _r0132 - _r0112.zwxy; + _TMP313 = abs(_a0316); + _px = bvec4(_TMP309.x <= _TMP313.x, _TMP309.y <= _TMP313.y, _TMP309.z <= _TMP313.z, _TMP309.w <= _TMP313.w); + _TMP38 = max(_fx30, _fx60); + _maximo = max(_TMP38, _fx45); + _t0322 = float(_px.x); + _TMP39 = _TMP10.xyz + _t0322*(_TMP8.xyz - _TMP10.xyz); + _TMP40 = _TMP7.xyz + _maximo.x*(_TMP39 - _TMP7.xyz); + _t0326 = float(_px.y); + _TMP41 = _TMP8.xyz + _t0326*(_TMP4.xyz - _TMP8.xyz); + _TMP42 = _TMP7.xyz + _maximo.y*(_TMP41 - _TMP7.xyz); + _t0330 = float(_px.z); + _TMP43 = _TMP4.xyz + _t0330*(_TMP6.xyz - _TMP4.xyz); + _TMP44 = _TMP7.xyz + _maximo.z*(_TMP43 - _TMP7.xyz); + _t0334 = float(_px.w); + _TMP45 = _TMP6.xyz + _t0334*(_TMP10.xyz - _TMP6.xyz); + _TMP46 = _TMP7.xyz + _maximo.w*(_TMP45 - _TMP7.xyz); + _r0338.x = dot(_TMP40, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.y = dot(_TMP42, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.z = dot(_TMP44, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.w = dot(_TMP46, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _a0350 = _r0338 - _r0132; + _TMP347 = abs(_a0350); + _res = _TMP40; + _mx = _TMP347.x; + if (_TMP347.y > _TMP347.x) { + _res = _TMP42; + _mx = _TMP347.y; + } + if (_TMP347.z > _mx) { + _res = _TMP44; + _mx = _TMP347.z; + } + if (_TMP347.w > _mx) { + _res = _TMP46; + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr.glsl new file mode 100644 index 000000000..f4bad69b8 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/3xbr.glsl @@ -0,0 +1,253 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP16; +vec3 _TMP19; +vec3 _TMP22; +vec3 _TMP23; +vec3 _TMP20; +vec3 _TMP21; +vec3 _TMP17; +vec3 _TMP18; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +float _TMP7; +float _TMP6; +float _TMP5; +float _TMP4; +float _TMP3; +float _TMP2; +float _TMP1; +float _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0029; +vec2 _c0047; +vec2 _c0049; +vec2 _c0051; +vec2 _c0055; +vec2 _c0057; +vec2 _c0059; +vec2 _c0061; +float _TMP62; +float _TMP66; +float _TMP70; +float _TMP74; +float _TMP78; +float _TMP82; +float _TMP86; +float _TMP90; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _g1; + vec2 _g2; + vec3 _E5; + vec3 _E8; + _x0029 = TEX0.xy*TextureSize; + _fp = fract(_x0029); + _TMP0 = float((_fp.x >= 5.00000000E-01)); + _TMP1 = float((_fp.y >= 5.00000000E-01)); + _TMP2 = float((_fp.x >= 5.00000000E-01)); + _TMP3 = float((_fp.y >= 5.00000000E-01)); + _g1 = TEX1.xy*((_TMP0 + _TMP1) - 1.00000000E+00) + TEX1.zw*(_TMP2 - _TMP3); + _TMP4 = float((_fp.y >= 5.00000000E-01)); + _TMP5 = float((_fp.x >= 5.00000000E-01)); + _TMP6 = float((_fp.x >= 5.00000000E-01)); + _TMP7 = float((_fp.y >= 5.00000000E-01)); + _g2 = TEX1.xy*(_TMP4 - _TMP5) + TEX1.zw*((_TMP6 + _TMP7) - 1.00000000E+00); + _c0047 = TEX0.xy + _g1; + _TMP8 = COMPAT_TEXTURE(Texture, _c0047); + _c0049 = (TEX0.xy + _g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0049); + _c0051 = TEX0.xy + _g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0051); + _TMP11 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0055 = TEX0.xy - _g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0055); + _c0057 = (TEX0.xy - _g1) + _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0057); + _c0059 = TEX0.xy - _g1; + _TMP14 = COMPAT_TEXTURE(Texture, _c0059); + _c0061 = (TEX0.xy - _g1) - _g2; + _TMP15 = COMPAT_TEXTURE(Texture, _c0061); + _E5 = _TMP11.xyz; + _E8 = _TMP11.xyz; + _TMP62 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP66 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP70 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP74 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP78 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP82 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP86 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP90 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP86 == _TMP78 && _TMP86 != _TMP74 && (_TMP74 == _TMP82 && (_TMP86 == _TMP90 || _TMP74 == _TMP70) || _TMP74 == _TMP66 && (_TMP86 == _TMP90 || _TMP74 == _TMP62))) { + _E8 = _TMP11.xyz + 8.75000000E-01*(_TMP12.xyz - _TMP11.xyz); + _E5 = _TMP11.xyz + 1.25000000E-01*(_TMP12.xyz - _TMP11.xyz); + } + if (_fp.x < 3.33333343E-01) { + if (_fp.y < 3.33333343E-01) { + _TMP17 = _E8; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP18 = _E5; + } else { + _TMP18 = _E8; + } + _TMP17 = _TMP18; + } + _TMP16 = _TMP17; + } else { + if (_fp.x < 6.66666687E-01) { + if (_fp.y < 3.33333343E-01) { + _TMP20 = _E5; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP21 = _TMP11.xyz; + } else { + _TMP21 = _E5; + } + _TMP20 = _TMP21; + } + _TMP19 = _TMP20; + } else { + if (_fp.y < 3.33333343E-01) { + _TMP22 = _E8; + } else { + if (_fp.y < 6.66666687E-01) { + _TMP23 = _E5; + } else { + _TMP23 = _E8; + } + _TMP22 = _TMP23; + } + _TMP19 = _TMP22; + } + _TMP16 = _TMP19; + } + _ret_0 = vec4(_TMP16.x, _TMP16.y, _TMP16.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v1.1.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v1.1.glsl new file mode 100644 index 000000000..a69eb402e --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v1.1.glsl @@ -0,0 +1,328 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP25; +vec3 _TMP33; +vec3 _TMP37; +vec3 _TMP38; +vec3 _TMP39; +vec3 _TMP34; +vec3 _TMP35; +vec3 _TMP36; +vec3 _TMP26; +vec3 _TMP30; +vec3 _TMP31; +vec3 _TMP32; +vec3 _TMP27; +vec3 _TMP28; +vec3 _TMP29; +vec4 _TMP23; +vec4 _TMP21; +vec4 _TMP20; +vec4 _TMP18; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +float _TMP7; +float _TMP6; +float _TMP5; +float _TMP4; +float _TMP3; +float _TMP2; +float _TMP1; +float _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0045; +vec2 _c0065; +vec2 _c0067; +vec2 _c0069; +vec2 _c0073; +vec2 _c0075; +vec2 _c0077; +vec2 _c0079; +vec2 _c0083; +vec2 _c0087; +vec2 _c0089; +vec2 _c0093; +float _TMP100; +float _TMP104; +float _TMP108; +float _TMP112; +float _TMP116; +float _TMP120; +float _TMP124; +float _TMP128; +float _TMP136; +float _TMP144; +float _TMP148; +float _TMP156; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _g1; + vec2 _g2; + vec3 _E11; + vec3 _E14; + vec3 _E15; + _x0045 = TEX0.xy*TextureSize; + _fp = fract(_x0045); + _TMP0 = float((_fp.x >= 5.00000000E-01)); + _TMP1 = float((_fp.y >= 5.00000000E-01)); + _TMP2 = float((_fp.x >= 5.00000000E-01)); + _TMP3 = float((_fp.y >= 5.00000000E-01)); + _g1 = TEX1.xy*((_TMP0 + _TMP1) - 1.00000000E+00) + TEX1.zw*(_TMP2 - _TMP3); + _TMP4 = float((_fp.y >= 5.00000000E-01)); + _TMP5 = float((_fp.x >= 5.00000000E-01)); + _TMP6 = float((_fp.x >= 5.00000000E-01)); + _TMP7 = float((_fp.y >= 5.00000000E-01)); + _g2 = TEX1.xy*(_TMP4 - _TMP5) + TEX1.zw*((_TMP6 + _TMP7) - 1.00000000E+00); + _c0065 = TEX0.xy + _g1; + _TMP9 = COMPAT_TEXTURE(Texture, _c0065); + _c0067 = (TEX0.xy + _g1) - _g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0067); + _c0069 = TEX0.xy + _g2; + _TMP11 = COMPAT_TEXTURE(Texture, _c0069); + _TMP12 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0073 = TEX0.xy - _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0073); + _c0075 = (TEX0.xy - _g1) + _g2; + _TMP14 = COMPAT_TEXTURE(Texture, _c0075); + _c0077 = TEX0.xy - _g1; + _TMP15 = COMPAT_TEXTURE(Texture, _c0077); + _c0079 = (TEX0.xy - _g1) - _g2; + _TMP16 = COMPAT_TEXTURE(Texture, _c0079); + _c0083 = (TEX0.xy + 2.00000000E+00*_g1) - _g2; + _TMP18 = COMPAT_TEXTURE(Texture, _c0083); + _c0087 = (TEX0.xy - _g1) + 2.00000000E+00*_g2; + _TMP20 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP21 = COMPAT_TEXTURE(Texture, _c0089); + _c0093 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP23 = COMPAT_TEXTURE(Texture, _c0093); + _E11 = _TMP12.xyz; + _E14 = _TMP12.xyz; + _E15 = _TMP12.xyz; + _TMP100 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP104 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP108 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP112 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP116 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP120 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP124 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP128 = dot(_TMP16.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP136 = dot(_TMP18.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP144 = dot(_TMP20.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP148 = dot(_TMP21.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP156 = dot(_TMP23.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP112 != _TMP124 && (_TMP124 == _TMP116 && (_TMP112 != _TMP128 && (_TMP112 != _TMP100 || _TMP112 != _TMP108 || _TMP100 == _TMP136 && _TMP108 == _TMP144 || _TMP116 != _TMP100 && _TMP116 != _TMP104 || _TMP124 != _TMP108 && _TMP124 != _TMP120) || _TMP112 == _TMP120 && (_TMP128 == _TMP124 || _TMP112 == _TMP108 || _TMP124 != _TMP108) || _TMP112 == _TMP104 && (_TMP128 == _TMP124 || _TMP112 == _TMP100 || _TMP116 != _TMP100)) || _TMP112 != _TMP116 && _TMP112 == _TMP104 && (_TMP116 != _TMP128 && (_TMP124 == _TMP128 && _TMP116 != _TMP100 || _TMP112 != _TMP128 && _TMP116 == _TMP148) || _TMP112 != _TMP128 && _TMP112 == _TMP120))) { + _E11 = (_TMP12.xyz + _TMP13.xyz)*5.00000000E-01; + _E14 = (_TMP12.xyz + _TMP15.xyz)*5.00000000E-01; + _E15 = _TMP13.xyz; + } else { + if (_TMP112 != _TMP124 && _TMP112 != _TMP116 && _TMP124 != _TMP128 && _TMP112 == _TMP120 && (_TMP116 == _TMP128 && _TMP124 != _TMP108 || _TMP112 != _TMP128 && _TMP124 == _TMP156)) { + _E11 = (_TMP12.xyz + _TMP15.xyz)*5.00000000E-01; + _E14 = _E11; + _E15 = _TMP15.xyz; + } + } + if (_fp.x < 5.00000000E-01) { + if (_fp.x < 2.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP27 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP28 = _E11; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP29 = _E14; + } else { + _TMP29 = _E15; + } + _TMP28 = _TMP29; + } + _TMP27 = _TMP28; + } + _TMP26 = _TMP27; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP30 = _E14; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP31 = _TMP12.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP32 = _TMP12.xyz; + } else { + _TMP32 = _E11; + } + _TMP31 = _TMP32; + } + _TMP30 = _TMP31; + } + _TMP26 = _TMP30; + } + _TMP25 = _TMP26; + } else { + if (_fp.x < 7.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP34 = _E11; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP35 = _TMP12.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP36 = _TMP12.xyz; + } else { + _TMP36 = _E14; + } + _TMP35 = _TMP36; + } + _TMP34 = _TMP35; + } + _TMP33 = _TMP34; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP37 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP38 = _E14; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP39 = _E11; + } else { + _TMP39 = _E15; + } + _TMP38 = _TMP39; + } + _TMP37 = _TMP38; + } + _TMP33 = _TMP37; + } + _TMP25 = _TMP33; + } + _ret_0 = vec4(_TMP25.x, _TMP25.y, _TMP25.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.5-plus-crt.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.5-plus-crt.glsl new file mode 100644 index 000000000..1ca851abf --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.5-plus-crt.glsl @@ -0,0 +1,705 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0008; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP55; +vec3 _TMP71; +float _TMP70; +float _TMP69; +float _TMP68; +vec4 _TMP54; +vec3 _TMP39; +vec3 _TMP47; +vec3 _TMP51; +vec3 _TMP52; +vec3 _TMP53; +vec3 _TMP48; +vec3 _TMP49; +vec3 _TMP50; +vec3 _TMP40; +vec3 _TMP44; +vec3 _TMP45; +vec3 _TMP46; +vec3 _TMP41; +vec3 _TMP42; +vec3 _TMP43; +vec3 _TMP34; +vec3 _TMP33; +vec3 _TMP32; +vec3 _TMP22; +vec3 _TMP21; +vec3 _TMP62; +vec3 _TMP60; +vec3 _TMP58; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0103; +vec2 _c0107; +vec2 _c0109; +vec2 _c0111; +vec2 _c0113; +vec2 _c0117; +vec2 _c0119; +vec2 _c0121; +vec2 _c0123; +vec2 _c0125; +vec2 _c0127; +vec2 _c0129; +vec2 _c0131; +vec2 _c0133; +vec2 _c0135; +vec2 _c0137; +vec2 _c0139; +vec2 _c0141; +vec2 _c0143; +vec3 _r0183; +vec3 _r0193; +vec3 _r0203; +vec3 _r0215; +vec3 _r0225; +vec3 _r0235; +vec3 _r0247; +vec3 _r0257; +vec3 _r0267; +vec3 _r0279; +vec3 _r0289; +vec3 _r0299; +vec3 _r0311; +vec3 _r0321; +vec3 _r0331; +vec3 _r0343; +vec3 _r0353; +vec3 _r0363; +vec3 _r0375; +vec3 _r0385; +vec3 _r0395; +vec3 _r0407; +vec3 _r0417; +vec3 _r0427; +vec3 _r0599; +vec3 _r0609; +vec3 _r0619; +vec3 _r0663; +vec3 _r0673; +vec3 _r0683; +vec3 _r0759; +vec3 _r0769; +vec3 _r0779; +vec3 _r0791; +vec3 _r0801; +vec3 _r0811; +vec3 _TMP822; +vec3 _a0825; +vec3 _TMP826; +vec3 _a0829; +vec3 _TMP830; +vec3 _a0833; +vec3 _TMP834; +vec3 _a0837; +vec3 _TMP838; +vec3 _a0841; +vec3 _TMP844; +vec3 _a0847; +vec3 _TMP848; +vec3 _a0851; +vec3 _TMP852; +vec3 _a0855; +vec3 _TMP856; +vec3 _a0859; +vec3 _TMP860; +vec3 _a0863; +vec3 _TMP864; +vec3 _a0867; +vec3 _TMP868; +vec3 _a0871; +vec3 _TMP872; +vec3 _a0875; +vec3 _TMP876; +vec3 _a0879; +vec3 _TMP880; +vec3 _a0883; +vec3 _TMP884; +vec3 _a0887; +vec2 _c0927; +vec3 _TMP944; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec3 _edr; + bvec3 _edr_left; + bvec3 _edr_up; + bvec3 _px; + bvec3 _interp_restriction_lv1; + bvec3 _interp_restriction_lv2_left; + bvec3 _interp_restriction_lv2_up; + vec3 _E11; + vec3 _E14; + vec3 _E15; + vec2 _fp; + vec2 _st; + vec2 _g1; + vec2 _g2; + vec3 _b2; + vec3 _c2; + vec3 _d1; + vec3 _e1; + vec3 _f1; + vec3 _g3; + vec3 _h1; + vec3 _i; + vec3 _i4; + vec3 _i5; + vec3 _h5; + vec3 _f4; + vec3 _color; + float _dy; + float _v_weight_00; + vec2 _coords10; + vec3 _colorNB; + float _v_weight_10; + _x0103 = TEX0.xy*TextureSize; + _fp = fract(_x0103); + _st = vec2(float((_fp.x >= 5.00000000E-01)), float((_fp.y >= 5.00000000E-01))); + _g1 = TEX1.xy*((_st.x + _st.y) - 1.00000000E+00) + TEX1.zw*(_st.x - _st.y); + _g2 = TEX1.xy*(_st.y - _st.x) + TEX1.zw*((_st.x + _st.y) - 1.00000000E+00); + _c0107 = TEX0.xy + _g1 + _g2; + _TMP0 = COMPAT_TEXTURE(Texture, _c0107); + _c0109 = TEX0.xy + _g1; + _TMP1 = COMPAT_TEXTURE(Texture, _c0109); + _c0111 = (TEX0.xy + _g1) - _g2; + _TMP2 = COMPAT_TEXTURE(Texture, _c0111); + _c0113 = TEX0.xy + _g2; + _TMP3 = COMPAT_TEXTURE(Texture, _c0113); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0117 = TEX0.xy - _g2; + _TMP5 = COMPAT_TEXTURE(Texture, _c0117); + _c0119 = (TEX0.xy - _g1) + _g2; + _TMP6 = COMPAT_TEXTURE(Texture, _c0119); + _c0121 = TEX0.xy - _g1; + _TMP7 = COMPAT_TEXTURE(Texture, _c0121); + _c0123 = (TEX0.xy - _g1) - _g2; + _TMP8 = COMPAT_TEXTURE(Texture, _c0123); + _c0125 = (TEX0.xy + 2.00000000E+00*_g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0125); + _c0127 = (TEX0.xy - _g1) + 2.00000000E+00*_g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0127); + _c0129 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP11 = COMPAT_TEXTURE(Texture, _c0129); + _c0131 = TEX0.xy - 2.00000000E+00*_g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0131); + _c0133 = (TEX0.xy - _g1) - 2.00000000E+00*_g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0133); + _c0135 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP14 = COMPAT_TEXTURE(Texture, _c0135); + _c0137 = TEX0.xy - 2.00000000E+00*_g1; + _TMP15 = COMPAT_TEXTURE(Texture, _c0137); + _c0139 = (TEX0.xy - 2.00000000E+00*_g1) - _g2; + _TMP16 = COMPAT_TEXTURE(Texture, _c0139); + _c0141 = TEX0.xy + 2.00000000E+00*_g1; + _TMP17 = COMPAT_TEXTURE(Texture, _c0141); + _c0143 = TEX0.xy + 2.00000000E+00*_g2; + _TMP18 = COMPAT_TEXTURE(Texture, _c0143); + _r0183.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0183.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0183.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP58 = abs(_r0183); + _r0193.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0193.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0193.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP60 = abs(_r0193); + _r0203.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0203.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0203.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP62 = abs(_r0203); + _b2 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0215.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0215.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0215.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP58 = abs(_r0215); + _r0225.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0225.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0225.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP60 = abs(_r0225); + _r0235.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0235.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0235.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP62 = abs(_r0235); + _c2 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0247.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0247.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0247.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP58 = abs(_r0247); + _r0257.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0257.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0257.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP60 = abs(_r0257); + _r0267.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0267.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0267.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP62 = abs(_r0267); + _d1 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0279.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0279.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0279.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP58 = abs(_r0279); + _r0289.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0289.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0289.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP60 = abs(_r0289); + _r0299.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0299.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0299.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP62 = abs(_r0299); + _e1 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0311.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0311.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0311.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP58 = abs(_r0311); + _r0321.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0321.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0321.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP60 = abs(_r0321); + _r0331.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0331.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0331.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP62 = abs(_r0331); + _f1 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0343.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0343.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0343.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP58 = abs(_r0343); + _r0353.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0353.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0353.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP60 = abs(_r0353); + _r0363.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0363.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0363.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP62 = abs(_r0363); + _g3 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0375.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0375.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0375.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP58 = abs(_r0375); + _r0385.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0385.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0385.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP60 = abs(_r0385); + _r0395.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0395.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0395.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP62 = abs(_r0395); + _h1 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0407.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0407.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0407.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP58 = abs(_r0407); + _r0417.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0417.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0417.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP60 = abs(_r0417); + _r0427.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0427.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0427.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP62 = abs(_r0427); + _i = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0599.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP13.xyz); + _r0599.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP13.xyz); + _r0599.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP13.xyz); + _TMP58 = abs(_r0599); + _r0609.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP9.xyz); + _r0609.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP9.xyz); + _r0609.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP9.xyz); + _TMP60 = abs(_r0609); + _r0619.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP14.xyz); + _r0619.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP14.xyz); + _r0619.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP14.xyz); + _TMP62 = abs(_r0619); + _i4 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0663.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP16.xyz); + _r0663.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP16.xyz); + _r0663.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP16.xyz); + _TMP58 = abs(_r0663); + _r0673.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP11.xyz); + _r0673.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP11.xyz); + _r0673.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP11.xyz); + _TMP60 = abs(_r0673); + _r0683.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP10.xyz); + _r0683.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP10.xyz); + _r0683.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP10.xyz); + _TMP62 = abs(_r0683); + _i5 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0759.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0759.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP15.xyz); + _r0759.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP15.xyz); + _TMP58 = abs(_r0759); + _r0769.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0769.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP12.xyz); + _r0769.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP12.xyz); + _TMP60 = abs(_r0769); + _r0779.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0779.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0779.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP62 = abs(_r0779); + _h5 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _r0791.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0791.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP12.xyz); + _r0791.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP12.xyz); + _TMP58 = abs(_r0791); + _r0801.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0801.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0801.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP60 = abs(_r0801); + _r0811.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0811.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP15.xyz); + _r0811.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP15.xyz); + _TMP62 = abs(_r0811); + _f4 = vec3(_TMP58.x, _TMP60.x, _TMP62.x); + _interp_restriction_lv1 = bvec3(_e1.x != _f1.x && _e1.x != _h1.x, _e1.y != _f1.y && _e1.y != _h1.y, _e1.z != _f1.z && _e1.z != _h1.z); + _interp_restriction_lv2_left = bvec3(_e1.x != _g3.x && _d1.x != _g3.x, _e1.y != _g3.y && _d1.y != _g3.y, _e1.z != _g3.z && _d1.z != _g3.z); + _interp_restriction_lv2_up = bvec3(_e1.x != _c2.x && _b2.x != _c2.x, _e1.y != _c2.y && _b2.y != _c2.y, _e1.z != _c2.z && _b2.z != _c2.z); + _a0825 = _e1 - _c2; + _TMP822 = abs(_a0825); + _a0829 = _e1 - _g3; + _TMP826 = abs(_a0829); + _a0833 = _i - _h5; + _TMP830 = abs(_a0833); + _a0837 = _i - _f4; + _TMP834 = abs(_a0837); + _a0841 = _h1 - _f1; + _TMP838 = abs(_a0841); + _TMP21 = _TMP822 + _TMP826 + _TMP830 + _TMP834 + 4.00000000E+00*_TMP838; + _a0847 = _h1 - _d1; + _TMP844 = abs(_a0847); + _a0851 = _h1 - _i5; + _TMP848 = abs(_a0851); + _a0855 = _f1 - _i4; + _TMP852 = abs(_a0855); + _a0859 = _f1 - _b2; + _TMP856 = abs(_a0859); + _a0863 = _e1 - _i; + _TMP860 = abs(_a0863); + _TMP22 = _TMP844 + _TMP848 + _TMP852 + _TMP856 + 4.00000000E+00*_TMP860; + _edr = bvec3(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z); + _a0867 = _f1 - _g3; + _TMP864 = abs(_a0867); + _a0871 = _h1 - _c2; + _TMP868 = abs(_a0871); + _edr_left = bvec3((2.00000000E+00*_TMP864).x <= _TMP868.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP864).y <= _TMP868.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP864).z <= _TMP868.z && _interp_restriction_lv2_left.z); + _a0875 = _f1 - _g3; + _TMP872 = abs(_a0875); + _a0879 = _h1 - _c2; + _TMP876 = abs(_a0879); + _edr_up = bvec3(_TMP872.x >= (2.00000000E+00*_TMP876).x && _interp_restriction_lv2_up.x, _TMP872.y >= (2.00000000E+00*_TMP876).y && _interp_restriction_lv2_up.y, _TMP872.z >= (2.00000000E+00*_TMP876).z && _interp_restriction_lv2_up.z); + _a0883 = _e1 - _f1; + _TMP880 = abs(_a0883); + _a0887 = _e1 - _h1; + _TMP884 = abs(_a0887); + _px = bvec3(_TMP880.x <= _TMP884.x, _TMP880.y <= _TMP884.y, _TMP880.z <= _TMP884.z); + _E15 = _TMP4.xyz; + _E14 = _TMP4.xyz; + _E11 = _TMP4.xyz; + if (_px.x) { + _TMP32 = _TMP5.xyz; + } else { + _TMP32 = _TMP7.xyz; + } + if (_px.y) { + _TMP33 = _TMP1.xyz; + } else { + _TMP33 = _TMP5.xyz; + } + if (_px.z) { + _TMP34 = _TMP7.xyz; + } else { + _TMP34 = _TMP3.xyz; + } + if (_edr.x && _edr_left.x && _edr_up.x) { + _E15 = _TMP32; + _E14 = _TMP32; + _E11 = _TMP32; + } else { + if (_edr.x && _edr_left.x) { + _E11 = _TMP4.xyz + 7.50000000E-01*(_TMP32 - _TMP4.xyz); + _E15 = _TMP32; + _E14 = _TMP32; + } else { + if (_edr.x && _edr_up.x) { + _E14 = _TMP4.xyz + 7.50000000E-01*(_TMP32 - _TMP4.xyz); + _E15 = _TMP32; + _E11 = _TMP32; + } else { + if (_edr.y && _edr_left.y && _edr.z && _edr_up.z) { + _E11 = _TMP4.xyz + 7.50000000E-01*(_TMP33 - _TMP4.xyz); + _E14 = _TMP4.xyz + 7.50000000E-01*(_TMP34 - _TMP4.xyz); + _E15 = _TMP4.xyz + 2.50000000E-01*(_TMP33 - _TMP4.xyz); + _E15 = _E15 + 2.50000000E-01*(_TMP34 - _E15); + } else { + if (_edr.y && _edr_left.y) { + _E11 = _TMP4.xyz + 7.50000000E-01*(_TMP33 - _TMP4.xyz); + _E15 = _TMP4.xyz + 2.50000000E-01*(_TMP33 - _TMP4.xyz); + } else { + if (_edr.z && _edr_up.z) { + _E14 = _TMP4.xyz + 7.50000000E-01*(_TMP34 - _TMP4.xyz); + _E15 = _TMP4.xyz + 2.50000000E-01*(_TMP34 - _TMP4.xyz); + } else { + if (_edr.x) { + _E11 = _TMP4.xyz + 5.00000000E-01*(_TMP32 - _TMP4.xyz); + _E14 = _TMP4.xyz + 5.00000000E-01*(_TMP32 - _TMP4.xyz); + _E15 = _TMP32; + } + } + } + } + } + } + } + if (_fp.x < 5.00000000E-01) { + if (_fp.x < 2.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP41 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP42 = _E11; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP43 = _E14; + } else { + _TMP43 = _E15; + } + _TMP42 = _TMP43; + } + _TMP41 = _TMP42; + } + _TMP40 = _TMP41; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP44 = _E14; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP45 = _TMP4.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP46 = _TMP4.xyz; + } else { + _TMP46 = _E11; + } + _TMP45 = _TMP46; + } + _TMP44 = _TMP45; + } + _TMP40 = _TMP44; + } + _TMP39 = _TMP40; + } else { + if (_fp.x < 7.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP48 = _E11; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP49 = _TMP4.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP50 = _TMP4.xyz; + } else { + _TMP50 = _E14; + } + _TMP49 = _TMP50; + } + _TMP48 = _TMP49; + } + _TMP47 = _TMP48; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP51 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP52 = _E14; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP53 = _E11; + } else { + _TMP53 = _E15; + } + _TMP52 = _TMP53; + } + _TMP51 = _TMP52; + } + _TMP47 = _TMP51; + } + _TMP39 = _TMP47; + } + _TMP68 = pow(_TMP39.x, 2.40000010E+00); + _TMP69 = pow(_TMP39.y, 2.40000010E+00); + _TMP70 = pow(_TMP39.z, 2.40000010E+00); + _color = vec3(_TMP68, _TMP69, _TMP70); + _dy = _fp.y - 5.00000000E-01; + _v_weight_00 = _dy/5.00000000E-01; + if (_v_weight_00 > 1.00000000E+00) { + _v_weight_00 = 1.00000000E+00; + } + _v_weight_00 = 1.00000000E+00 - _v_weight_00*_v_weight_00; + _v_weight_00 = _v_weight_00*_v_weight_00; + _color = _color*vec3(_v_weight_00, _v_weight_00, _v_weight_00); + if (_dy > 0.00000000E+00) { + _coords10 = -TEX1.xy; + _dy = 1.00000000E+00 - _dy; + } else { + _coords10 = TEX1.xy; + _dy = 1.00000000E+00 + _dy; + } + _c0927 = TEX0.xy + _coords10; + _TMP54 = COMPAT_TEXTURE(Texture, _c0927); + _TMP68 = pow(_TMP54.x, 2.40000010E+00); + _TMP69 = pow(_TMP54.y, 2.40000010E+00); + _TMP70 = pow(_TMP54.z, 2.40000010E+00); + _colorNB = vec3(_TMP68, _TMP69, _TMP70); + _v_weight_10 = _dy/5.00000000E-01; + if (_v_weight_10 > 1.00000000E+00) { + _v_weight_10 = 1.00000000E+00; + } + _v_weight_10 = 1.00000000E+00 - _v_weight_10*_v_weight_10; + _v_weight_10 = _v_weight_10*_v_weight_10; + _color = _color + _colorNB*vec3(_v_weight_10, _v_weight_10, _v_weight_10); + _color = _color*vec3( 1.45000005E+00, 1.45000005E+00, 1.45000005E+00); + _TMP68 = pow(_color.x, 4.54545438E-01); + _TMP69 = pow(_color.y, 4.54545438E-01); + _TMP70 = pow(_color.z, 4.54545438E-01); + _TMP55 = vec3(_TMP68, _TMP69, _TMP70); + _TMP71 = min(vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _TMP55); + _TMP944 = max(vec3( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP71); + _ret_0 = vec4(_TMP944.x, _TMP944.y, _TMP944.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.9c.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.9c.glsl new file mode 100644 index 000000000..501ca7688 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v3.9c.glsl @@ -0,0 +1,582 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP52; +vec3 _TMP63; +float _TMP62; +float _TMP61; +float _TMP60; +float _TMP51; +float _TMP50; +float _TMP49; +vec3 _TMP48; +vec3 _TMP47; +vec3 _TMP46; +vec3 _TMP45; +vec3 _TMP44; +vec3 _TMP43; +vec3 _TMP42; +vec3 _TMP41; +vec3 _TMP40; +vec3 _TMP39; +vec4 _TMP38; +vec4 _TMP31; +vec4 _TMP30; +vec4 _TMP64; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0078; +vec4 _r0122; +vec4 _r0132; +vec4 _r0142; +vec4 _r0152; +vec4 _r0162; +vec4 _r0172; +vec4 _TMP183; +vec4 _a0186; +vec4 _TMP189; +vec4 _a0192; +vec4 _TMP195; +vec4 _a0198; +vec4 _TMP201; +vec4 _a0204; +vec4 _TMP207; +vec4 _a0210; +vec4 _TMP213; +vec4 _a0216; +vec4 _TMP219; +vec4 _a0222; +vec4 _TMP225; +vec4 _a0228; +vec4 _TMP231; +vec4 _a0234; +vec4 _x0238; +vec4 _TMP239; +vec4 _x0248; +vec4 _TMP249; +vec4 _x0258; +vec4 _TMP259; +vec4 _TMP267; +vec4 _a0270; +vec4 _TMP271; +vec4 _a0274; +vec4 _TMP275; +vec4 _a0278; +vec4 _TMP279; +vec4 _a0282; +vec4 _TMP283; +vec4 _a0286; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec4 _TMP301; +vec4 _a0304; +vec4 _TMP305; +vec4 _a0308; +vec4 _TMP309; +vec4 _a0312; +vec4 _TMP313; +vec4 _a0316; +vec4 _TMP317; +vec4 _a0320; +vec4 _TMP321; +vec4 _a0324; +vec4 _TMP325; +vec4 _a0328; +vec4 _TMP329; +vec4 _a0332; +vec3 _df0366; +vec3 _a0368; +vec3 _df0370; +vec3 _a0372; +vec3 _TMP385; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _nc30; + bvec4 _nc60; + bvec4 _nc45; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec3 _res1; + vec3 _res2; + vec3 _pix1; + vec3 _pix2; + float _blend1; + float _blend2; + vec2 _fp; + vec3 _E; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _final45; + vec4 _final30; + vec4 _final60; + vec4 _maximo; + vec3 _res; + _x0078 = TEX0.xy*TextureSize; + _fp = fract(_x0078); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0122.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0172.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _a0186 = _r0122.wxyz - _r0122; + _TMP183 = abs(_a0186); + _TMP21 = bvec4(_TMP183.x < 1.00000000E+01, _TMP183.y < 1.00000000E+01, _TMP183.z < 1.00000000E+01, _TMP183.w < 1.00000000E+01); + _a0192 = _r0122.zwxy - _r0122.yzwx; + _TMP189 = abs(_a0192); + _TMP22 = bvec4(_TMP189.x < 1.00000000E+01, _TMP189.y < 1.00000000E+01, _TMP189.z < 1.00000000E+01, _TMP189.w < 1.00000000E+01); + _a0198 = _r0142 - _r0132.wxyz; + _TMP195 = abs(_a0198); + _TMP23 = bvec4(_TMP195.x < 1.00000000E+01, _TMP195.y < 1.00000000E+01, _TMP195.z < 1.00000000E+01, _TMP195.w < 1.00000000E+01); + _a0204 = _r0122.wxyz - _r0152; + _TMP201 = abs(_a0204); + _TMP24 = bvec4(_TMP201.x < 1.00000000E+01, _TMP201.y < 1.00000000E+01, _TMP201.z < 1.00000000E+01, _TMP201.w < 1.00000000E+01); + _a0210 = _r0122.zwxy - _r0162; + _TMP207 = abs(_a0210); + _TMP25 = bvec4(_TMP207.x < 1.00000000E+01, _TMP207.y < 1.00000000E+01, _TMP207.z < 1.00000000E+01, _TMP207.w < 1.00000000E+01); + _a0216 = _r0142 - _r0132.zwxy; + _TMP213 = abs(_a0216); + _TMP26 = bvec4(_TMP213.x < 1.00000000E+01, _TMP213.y < 1.00000000E+01, _TMP213.z < 1.00000000E+01, _TMP213.w < 1.00000000E+01); + _a0222 = _r0142 - _r0132; + _TMP219 = abs(_a0222); + _TMP27 = bvec4(_TMP219.x < 1.00000000E+01, _TMP219.y < 1.00000000E+01, _TMP219.z < 1.00000000E+01, _TMP219.w < 1.00000000E+01); + _a0228 = _r0122 - _r0152.yzwx; + _TMP225 = abs(_a0228); + _TMP28 = bvec4(_TMP225.x < 1.00000000E+01, _TMP225.y < 1.00000000E+01, _TMP225.z < 1.00000000E+01, _TMP225.w < 1.00000000E+01); + _a0234 = _r0122.yzwx - _r0162.wxyz; + _TMP231 = abs(_a0234); + _TMP29 = bvec4(_TMP231.x < 1.00000000E+01, _TMP231.y < 1.00000000E+01, _TMP231.z < 1.00000000E+01, _TMP231.w < 1.00000000E+01); + _interp_restriction_lv1 = bvec4(_r0142.x != _r0122.w && _r0142.x != _r0122.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0122.w != _r0172.y && _r0122.w != _r0132.w || _r0122.z != _r0172.x && _r0122.z != _r0132.w || _r0122.z != _r0132.z || _r0122.w != _r0132.x || _TMP28.x && _TMP29.x), _r0142.y != _r0122.x && _r0142.y != _r0122.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0122.x != _r0172.z && _r0122.x != _r0132.x || _r0122.w != _r0172.y && _r0122.w != _r0132.x || _r0122.w != _r0132.w || _r0122.x != _r0132.y || _TMP28.y && _TMP29.y), _r0142.z != _r0122.y && _r0142.z != _r0122.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0122.y != _r0172.w && _r0122.y != _r0132.y || _r0122.x != _r0172.z && _r0122.x != _r0132.y || _r0122.x != _r0132.x || _r0122.y != _r0132.z || _TMP28.z && _TMP29.z), _r0142.w != _r0122.z && _r0142.w != _r0122.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0122.z != _r0172.x && _r0122.z != _r0132.z || _r0122.y != _r0172.w && _r0122.y != _r0132.z || _r0122.y != _r0132.y || _r0122.z != _r0132.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0142.x != _r0132.z && _r0122.y != _r0132.z, _r0142.y != _r0132.w && _r0122.z != _r0132.w, _r0142.z != _r0132.x && _r0122.w != _r0132.x, _r0142.w != _r0132.y && _r0122.x != _r0132.y); + _interp_restriction_lv2_up = bvec4(_r0142.x != _r0132.x && _r0122.x != _r0132.x, _r0142.y != _r0132.y && _r0122.y != _r0132.y, _r0142.z != _r0132.z && _r0122.z != _r0132.z, _r0142.w != _r0132.w && _r0122.w != _r0132.w); + _x0238 = (_fx - vec4( 1.10000002E+00, 9.99999940E-02, -8.99999976E-01, 9.99999940E-02))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 7.99999952E-01); + _TMP64 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0238); + _TMP239 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP64); + _fx45 = _TMP239*_TMP239*(3.00000000E+00 - 2.00000000E+00*_TMP239); + _x0248 = (_fx_left - vec4( 6.00000024E-01, 6.00000024E-01, -8.99999976E-01, -4.00000006E-01))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 8.00000012E-01); + _TMP64 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0248); + _TMP249 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP64); + _fx30 = _TMP249*_TMP249*(3.00000000E+00 - 2.00000000E+00*_TMP249); + _x0258 = (_fx_up - vec4( 1.60000002E+00, -4.00000006E-01, -1.39999998E+00, 9.99999940E-02))/vec4( 8.00000072E-01, 8.00000012E-01, 7.99999952E-01, 7.99999952E-01); + _TMP64 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0258); + _TMP259 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP64); + _fx60 = _TMP259*_TMP259*(3.00000000E+00 - 2.00000000E+00*_TMP259); + _a0270 = _r0142 - _r0132; + _TMP267 = abs(_a0270); + _a0274 = _r0142 - _r0132.zwxy; + _TMP271 = abs(_a0274); + _a0278 = _r0132.wxyz - _r0172; + _TMP275 = abs(_a0278); + _a0282 = _r0132.wxyz - _r0172.yzwx; + _TMP279 = abs(_a0282); + _a0286 = _r0122.zwxy - _r0122.wxyz; + _TMP283 = abs(_a0286); + _TMP30 = _TMP267 + _TMP271 + _TMP275 + _TMP279 + 4.00000000E+00*_TMP283; + _a0292 = _r0122.zwxy - _r0122.yzwx; + _TMP289 = abs(_a0292); + _a0296 = _r0122.zwxy - _r0162; + _TMP293 = abs(_a0296); + _a0300 = _r0122.wxyz - _r0152; + _TMP297 = abs(_a0300); + _a0304 = _r0122.wxyz - _r0122; + _TMP301 = abs(_a0304); + _a0308 = _r0142 - _r0132.wxyz; + _TMP305 = abs(_a0308); + _TMP31 = _TMP289 + _TMP293 + _TMP297 + _TMP301 + 4.00000000E+00*_TMP305; + _edr = bvec4(_TMP30.x < _TMP31.x && _interp_restriction_lv1.x, _TMP30.y < _TMP31.y && _interp_restriction_lv1.y, _TMP30.z < _TMP31.z && _interp_restriction_lv1.z, _TMP30.w < _TMP31.w && _interp_restriction_lv1.w); + _a0312 = _r0122.wxyz - _r0132.zwxy; + _TMP309 = abs(_a0312); + _a0316 = _r0122.zwxy - _r0132; + _TMP313 = abs(_a0316); + _edr_left = bvec4((2.00000000E+00*_TMP309).x <= _TMP313.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP309).y <= _TMP313.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP309).z <= _TMP313.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP309).w <= _TMP313.w && _interp_restriction_lv2_left.w); + _a0320 = _r0122.wxyz - _r0132.zwxy; + _TMP317 = abs(_a0320); + _a0324 = _r0122.zwxy - _r0132; + _TMP321 = abs(_a0324); + _edr_up = bvec4(_TMP317.x >= (2.00000000E+00*_TMP321).x && _interp_restriction_lv2_up.x, _TMP317.y >= (2.00000000E+00*_TMP321).y && _interp_restriction_lv2_up.y, _TMP317.z >= (2.00000000E+00*_TMP321).z && _interp_restriction_lv2_up.z, _TMP317.w >= (2.00000000E+00*_TMP321).w && _interp_restriction_lv2_up.w); + _nc45 = bvec4(_edr.x && bool(_fx45.x), _edr.y && bool(_fx45.y), _edr.z && bool(_fx45.z), _edr.w && bool(_fx45.w)); + _nc30 = bvec4(_edr.x && _edr_left.x && bool(_fx30.x), _edr.y && _edr_left.y && bool(_fx30.y), _edr.z && _edr_left.z && bool(_fx30.z), _edr.w && _edr_left.w && bool(_fx30.w)); + _nc60 = bvec4(_edr.x && _edr_up.x && bool(_fx60.x), _edr.y && _edr_up.y && bool(_fx60.y), _edr.z && _edr_up.z && bool(_fx60.z), _edr.w && _edr_up.w && bool(_fx60.w)); + _a0328 = _r0142 - _r0122.wxyz; + _TMP325 = abs(_a0328); + _a0332 = _r0142 - _r0122.zwxy; + _TMP329 = abs(_a0332); + _px = bvec4(_TMP325.x <= _TMP329.x, _TMP325.y <= _TMP329.y, _TMP325.z <= _TMP329.z, _TMP325.w <= _TMP329.w); + _nc = bvec4(_nc30.x || _nc60.x || _nc45.x, _nc30.y || _nc60.y || _nc45.y, _nc30.z || _nc60.z || _nc45.z, _nc30.w || _nc60.w || _nc45.w); + _final45 = vec4(float(_nc45.x), float(_nc45.y), float(_nc45.z), float(_nc45.w))*_fx45; + _final30 = vec4(float(_nc30.x), float(_nc30.y), float(_nc30.z), float(_nc30.w))*_fx30; + _final60 = vec4(float(_nc60.x), float(_nc60.y), float(_nc60.z), float(_nc60.w))*_fx60; + _TMP38 = max(_final30, _final60); + _maximo = max(_TMP38, _final45); + if (_nc.x) { + if (_px.x) { + _TMP39 = _TMP8.xyz; + } else { + _TMP39 = _TMP10.xyz; + } + _pix1 = _TMP39; + _blend1 = _maximo.x; + } else { + if (_nc.y) { + if (_px.y) { + _TMP40 = _TMP4.xyz; + } else { + _TMP40 = _TMP8.xyz; + } + _pix1 = _TMP40; + _blend1 = _maximo.y; + } else { + if (_nc.z) { + if (_px.z) { + _TMP41 = _TMP6.xyz; + } else { + _TMP41 = _TMP4.xyz; + } + _pix1 = _TMP41; + _blend1 = _maximo.z; + } else { + if (_nc.w) { + if (_px.w) { + _TMP42 = _TMP10.xyz; + } else { + _TMP42 = _TMP6.xyz; + } + _pix1 = _TMP42; + _blend1 = _maximo.w; + } + } + } + } + if (_nc.w) { + if (_px.w) { + _TMP43 = _TMP10.xyz; + } else { + _TMP43 = _TMP6.xyz; + } + _pix2 = _TMP43; + _blend2 = _maximo.w; + } else { + if (_nc.z) { + if (_px.z) { + _TMP44 = _TMP6.xyz; + } else { + _TMP44 = _TMP4.xyz; + } + _pix2 = _TMP44; + _blend2 = _maximo.z; + } else { + if (_nc.y) { + if (_px.y) { + _TMP45 = _TMP4.xyz; + } else { + _TMP45 = _TMP8.xyz; + } + _pix2 = _TMP45; + _blend2 = _maximo.y; + } else { + if (_nc.x) { + if (_px.x) { + _TMP46 = _TMP8.xyz; + } else { + _TMP46 = _TMP10.xyz; + } + _pix2 = _TMP46; + _blend2 = _maximo.x; + } + } + } + } + _TMP60 = pow(_TMP7.x, 2.40000010E+00); + _TMP61 = pow(_TMP7.y, 2.40000010E+00); + _TMP62 = pow(_TMP7.z, 2.40000010E+00); + _E = vec3(_TMP60, _TMP61, _TMP62); + _TMP60 = pow(_pix1.x, 2.40000010E+00); + _TMP61 = pow(_pix1.y, 2.40000010E+00); + _TMP62 = pow(_pix1.z, 2.40000010E+00); + _TMP47 = vec3(_TMP60, _TMP61, _TMP62); + _res1 = _E + _blend1*(_TMP47 - _E); + _TMP60 = pow(_pix2.x, 2.40000010E+00); + _TMP61 = pow(_pix2.y, 2.40000010E+00); + _TMP62 = pow(_pix2.z, 2.40000010E+00); + _TMP48 = vec3(_TMP60, _TMP61, _TMP62); + _res2 = _E + _blend2*(_TMP48 - _E); + _a0368 = _E - _res1; + _df0366 = abs(_a0368); + _TMP49 = _df0366.x + _df0366.y + _df0366.z; + _a0372 = _E - _res2; + _df0370 = abs(_a0372); + _TMP50 = _df0370.x + _df0370.y + _df0370.z; + _TMP51 = float((_TMP50 >= _TMP49)); + _res = _res1 + _TMP51*(_res2 - _res1); + _TMP60 = pow(_res.x, 4.54545438E-01); + _TMP61 = pow(_res.y, 4.54545438E-01); + _TMP62 = pow(_res.z, 4.54545438E-01); + _TMP52 = vec3(_TMP60, _TMP61, _TMP62); + _TMP63 = min(vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _TMP52); + _TMP385 = max(vec3( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _ret_0 = vec4(_TMP385.x, _TMP385.y, _TMP385.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v4.0.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v4.0.glsl new file mode 100644 index 000000000..d1a9382ee --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr-v4.0.glsl @@ -0,0 +1,613 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +float _TMP55; +float _TMP54; +float _TMP53; +vec3 _TMP52; +vec3 _TMP51; +vec3 _TMP50; +vec3 _TMP49; +vec3 _TMP48; +vec3 _TMP47; +vec3 _TMP46; +vec3 _TMP45; +vec4 _TMP44; +vec4 _TMP43; +vec4 _TMP42; +vec4 _TMP35; +vec4 _TMP34; +vec4 _TMP63; +bvec4 _TMP33; +bvec4 _TMP32; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0077; +vec4 _r0121; +vec4 _r0131; +vec4 _r0141; +vec4 _r0151; +vec4 _r0161; +vec4 _r0171; +vec4 _TMP182; +vec4 _a0185; +vec4 _TMP188; +vec4 _a0191; +vec4 _TMP194; +vec4 _a0197; +vec4 _TMP200; +vec4 _a0203; +vec4 _TMP206; +vec4 _a0209; +vec4 _TMP212; +vec4 _a0215; +vec4 _TMP218; +vec4 _a0221; +vec4 _TMP224; +vec4 _a0227; +vec4 _TMP230; +vec4 _a0233; +vec4 _TMP236; +vec4 _a0239; +vec4 _TMP242; +vec4 _a0245; +vec4 _TMP248; +vec4 _a0251; +vec4 _TMP254; +vec4 _a0257; +vec4 _x0261; +vec4 _TMP262; +vec4 _x0271; +vec4 _TMP272; +vec4 _x0281; +vec4 _TMP282; +vec4 _x0291; +vec4 _TMP292; +vec4 _x0301; +vec4 _TMP302; +vec4 _TMP310; +vec4 _a0313; +vec4 _TMP314; +vec4 _a0317; +vec4 _TMP318; +vec4 _a0321; +vec4 _TMP322; +vec4 _a0325; +vec4 _TMP326; +vec4 _a0329; +vec4 _TMP332; +vec4 _a0335; +vec4 _TMP336; +vec4 _a0339; +vec4 _TMP340; +vec4 _a0343; +vec4 _TMP344; +vec4 _a0347; +vec4 _TMP348; +vec4 _a0351; +vec4 _TMP352; +vec4 _a0355; +vec4 _TMP356; +vec4 _a0359; +vec4 _TMP360; +vec4 _a0363; +vec4 _TMP364; +vec4 _a0367; +vec4 _TMP368; +vec4 _a0371; +vec4 _TMP372; +vec4 _a0375; +vec3 _df0389; +vec3 _a0391; +vec3 _df0393; +vec3 _a0395; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _interp_restriction_lv3_left; + bvec4 _interp_restriction_lv3_up; + bvec4 _nc; + bvec4 _nc30; + bvec4 _nc60; + bvec4 _nc45; + bvec4 _nc15; + bvec4 _nc75; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec4 _fx3_left; + vec4 _fx3_up; + vec3 _res1; + vec3 _res2; + vec3 _pix1; + vec3 _pix2; + float _blend1; + float _blend2; + vec2 _fp; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _fx15; + vec4 _fx75; + vec4 _final45; + vec4 _final30; + vec4 _final60; + vec4 _final15; + vec4 _final75; + vec4 _maximo; + vec3 _res; + _x0077 = TEX0.xy*TextureSize; + _fp = fract(_x0077); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0121.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0121.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0121.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0121.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0131.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0131.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0131.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0131.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0141.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0141.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0141.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0141.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0151.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0151.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0151.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0151.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0161.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0161.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0161.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0161.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0171.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0171.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0171.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0171.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _fx3_left = vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x; + _fx3_up = vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x; + _a0185 = _r0121.wxyz - _r0121; + _TMP182 = abs(_a0185); + _TMP21 = bvec4(_TMP182.x < 1.00000000E+01, _TMP182.y < 1.00000000E+01, _TMP182.z < 1.00000000E+01, _TMP182.w < 1.00000000E+01); + _a0191 = _r0121.zwxy - _r0121.yzwx; + _TMP188 = abs(_a0191); + _TMP22 = bvec4(_TMP188.x < 1.00000000E+01, _TMP188.y < 1.00000000E+01, _TMP188.z < 1.00000000E+01, _TMP188.w < 1.00000000E+01); + _a0197 = _r0141 - _r0131.wxyz; + _TMP194 = abs(_a0197); + _TMP23 = bvec4(_TMP194.x < 1.00000000E+01, _TMP194.y < 1.00000000E+01, _TMP194.z < 1.00000000E+01, _TMP194.w < 1.00000000E+01); + _a0203 = _r0121.wxyz - _r0151; + _TMP200 = abs(_a0203); + _TMP24 = bvec4(_TMP200.x < 1.00000000E+01, _TMP200.y < 1.00000000E+01, _TMP200.z < 1.00000000E+01, _TMP200.w < 1.00000000E+01); + _a0209 = _r0121.zwxy - _r0161; + _TMP206 = abs(_a0209); + _TMP25 = bvec4(_TMP206.x < 1.00000000E+01, _TMP206.y < 1.00000000E+01, _TMP206.z < 1.00000000E+01, _TMP206.w < 1.00000000E+01); + _a0215 = _r0141 - _r0131.zwxy; + _TMP212 = abs(_a0215); + _TMP26 = bvec4(_TMP212.x < 1.00000000E+01, _TMP212.y < 1.00000000E+01, _TMP212.z < 1.00000000E+01, _TMP212.w < 1.00000000E+01); + _a0221 = _r0141 - _r0131; + _TMP218 = abs(_a0221); + _TMP27 = bvec4(_TMP218.x < 1.00000000E+01, _TMP218.y < 1.00000000E+01, _TMP218.z < 1.00000000E+01, _TMP218.w < 1.00000000E+01); + _a0227 = _r0121 - _r0151.yzwx; + _TMP224 = abs(_a0227); + _TMP28 = bvec4(_TMP224.x < 1.00000000E+01, _TMP224.y < 1.00000000E+01, _TMP224.z < 1.00000000E+01, _TMP224.w < 1.00000000E+01); + _a0233 = _r0121.yzwx - _r0161.wxyz; + _TMP230 = abs(_a0233); + _TMP29 = bvec4(_TMP230.x < 1.00000000E+01, _TMP230.y < 1.00000000E+01, _TMP230.z < 1.00000000E+01, _TMP230.w < 1.00000000E+01); + _interp_restriction_lv1 = bvec4(_r0141.x != _r0121.w && _r0141.x != _r0121.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0121.w != _r0171.y && _r0121.w != _r0131.w || _r0121.z != _r0171.x && _r0121.z != _r0131.w || _r0121.z != _r0131.z || _r0121.w != _r0131.x || _TMP28.x && _TMP29.x), _r0141.y != _r0121.x && _r0141.y != _r0121.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0121.x != _r0171.z && _r0121.x != _r0131.x || _r0121.w != _r0171.y && _r0121.w != _r0131.x || _r0121.w != _r0131.w || _r0121.x != _r0131.y || _TMP28.y && _TMP29.y), _r0141.z != _r0121.y && _r0141.z != _r0121.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0121.y != _r0171.w && _r0121.y != _r0131.y || _r0121.x != _r0171.z && _r0121.x != _r0131.y || _r0121.x != _r0131.x || _r0121.y != _r0131.z || _TMP28.z && _TMP29.z), _r0141.w != _r0121.z && _r0141.w != _r0121.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0121.z != _r0171.x && _r0121.z != _r0131.z || _r0121.y != _r0171.w && _r0121.y != _r0131.z || _r0121.y != _r0131.y || _r0121.z != _r0131.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0141.x != _r0131.z && _r0121.y != _r0131.z, _r0141.y != _r0131.w && _r0121.z != _r0131.w, _r0141.z != _r0131.x && _r0121.w != _r0131.x, _r0141.w != _r0131.y && _r0121.x != _r0131.y); + _interp_restriction_lv2_up = bvec4(_r0141.x != _r0131.x && _r0121.x != _r0131.x, _r0141.y != _r0131.y && _r0121.y != _r0131.y, _r0141.z != _r0131.z && _r0121.z != _r0131.z, _r0141.w != _r0131.w && _r0121.w != _r0131.w); + _a0239 = _r0131.zwxy - _r0161.wxyz; + _TMP236 = abs(_a0239); + _TMP30 = bvec4(_TMP236.x < 2.00000000E+00, _TMP236.y < 2.00000000E+00, _TMP236.z < 2.00000000E+00, _TMP236.w < 2.00000000E+00); + _a0245 = _r0171.wxyz - _r0161.wxyz; + _TMP242 = abs(_a0245); + _TMP31 = bvec4(_TMP242.x < 2.00000000E+00, _TMP242.y < 2.00000000E+00, _TMP242.z < 2.00000000E+00, _TMP242.w < 2.00000000E+00); + _interp_restriction_lv3_left = bvec4(_TMP30.x && !_TMP31.x, _TMP30.y && !_TMP31.y, _TMP30.z && !_TMP31.z, _TMP30.w && !_TMP31.w); + _a0251 = _r0131 - _r0151.yzwx; + _TMP248 = abs(_a0251); + _TMP32 = bvec4(_TMP248.x < 2.00000000E+00, _TMP248.y < 2.00000000E+00, _TMP248.z < 2.00000000E+00, _TMP248.w < 2.00000000E+00); + _a0257 = _r0171.zwxy - _r0151.yzwx; + _TMP254 = abs(_a0257); + _TMP33 = bvec4(_TMP254.x < 2.00000000E+00, _TMP254.y < 2.00000000E+00, _TMP254.z < 2.00000000E+00, _TMP254.w < 2.00000000E+00); + _interp_restriction_lv3_up = bvec4(_TMP32.x && !_TMP33.x, _TMP32.y && !_TMP33.y, _TMP32.z && !_TMP33.z, _TMP32.w && !_TMP33.w); + _x0261 = (_fx - vec4( 1.10000002E+00, 9.99999940E-02, -8.99999976E-01, 9.99999940E-02))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 7.99999952E-01); + _TMP63 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0261); + _TMP262 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _fx45 = _TMP262*_TMP262*(3.00000000E+00 - 2.00000000E+00*_TMP262); + _x0271 = (_fx_left - vec4( 6.00000024E-01, 6.00000024E-01, -8.99999976E-01, -4.00000006E-01))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 8.00000012E-01); + _TMP63 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0271); + _TMP272 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _fx30 = _TMP272*_TMP272*(3.00000000E+00 - 2.00000000E+00*_TMP272); + _x0281 = (_fx_up - vec4( 1.60000002E+00, -4.00000006E-01, -1.39999998E+00, 9.99999940E-02))/vec4( 8.00000072E-01, 8.00000012E-01, 7.99999952E-01, 7.99999952E-01); + _TMP63 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0281); + _TMP282 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _fx60 = _TMP282*_TMP282*(3.00000000E+00 - 2.00000000E+00*_TMP282); + _x0291 = (_fx3_left - vec4( 4.59999990E+00, 2.59999990E+00, -3.40000010E+00, -1.39999998E+00))/vec4( 8.00000191E-01, 8.00000191E-01, 8.00000191E-01, 7.99999952E-01); + _TMP63 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0291); + _TMP292 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _fx15 = _TMP292*_TMP292*(3.00000000E+00 - 2.00000000E+00*_TMP292); + _x0301 = (_fx3_up - vec4( 4.59999990E+00, -1.39999998E+00, -3.40000010E+00, 2.59999990E+00))/vec4( 8.00000191E-01, 7.99999952E-01, 8.00000191E-01, 8.00000191E-01); + _TMP63 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0301); + _TMP302 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP63); + _fx75 = _TMP302*_TMP302*(3.00000000E+00 - 2.00000000E+00*_TMP302); + _a0313 = _r0141 - _r0131; + _TMP310 = abs(_a0313); + _a0317 = _r0141 - _r0131.zwxy; + _TMP314 = abs(_a0317); + _a0321 = _r0131.wxyz - _r0171; + _TMP318 = abs(_a0321); + _a0325 = _r0131.wxyz - _r0171.yzwx; + _TMP322 = abs(_a0325); + _a0329 = _r0121.zwxy - _r0121.wxyz; + _TMP326 = abs(_a0329); + _TMP34 = _TMP310 + _TMP314 + _TMP318 + _TMP322 + 4.00000000E+00*_TMP326; + _a0335 = _r0121.zwxy - _r0121.yzwx; + _TMP332 = abs(_a0335); + _a0339 = _r0121.zwxy - _r0161; + _TMP336 = abs(_a0339); + _a0343 = _r0121.wxyz - _r0151; + _TMP340 = abs(_a0343); + _a0347 = _r0121.wxyz - _r0121; + _TMP344 = abs(_a0347); + _a0351 = _r0141 - _r0131.wxyz; + _TMP348 = abs(_a0351); + _TMP35 = _TMP332 + _TMP336 + _TMP340 + _TMP344 + 4.00000000E+00*_TMP348; + _edr = bvec4(_TMP34.x < _TMP35.x && _interp_restriction_lv1.x, _TMP34.y < _TMP35.y && _interp_restriction_lv1.y, _TMP34.z < _TMP35.z && _interp_restriction_lv1.z, _TMP34.w < _TMP35.w && _interp_restriction_lv1.w); + _a0355 = _r0121.wxyz - _r0131.zwxy; + _TMP352 = abs(_a0355); + _a0359 = _r0121.zwxy - _r0131; + _TMP356 = abs(_a0359); + _edr_left = bvec4((2.00000000E+00*_TMP352).x <= _TMP356.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP352).y <= _TMP356.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP352).z <= _TMP356.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP352).w <= _TMP356.w && _interp_restriction_lv2_left.w); + _a0363 = _r0121.wxyz - _r0131.zwxy; + _TMP360 = abs(_a0363); + _a0367 = _r0121.zwxy - _r0131; + _TMP364 = abs(_a0367); + _edr_up = bvec4(_TMP360.x >= (2.00000000E+00*_TMP364).x && _interp_restriction_lv2_up.x, _TMP360.y >= (2.00000000E+00*_TMP364).y && _interp_restriction_lv2_up.y, _TMP360.z >= (2.00000000E+00*_TMP364).z && _interp_restriction_lv2_up.z, _TMP360.w >= (2.00000000E+00*_TMP364).w && _interp_restriction_lv2_up.w); + _nc45 = bvec4(_edr.x && bool(_fx45.x), _edr.y && bool(_fx45.y), _edr.z && bool(_fx45.z), _edr.w && bool(_fx45.w)); + _nc30 = bvec4(_edr.x && _edr_left.x && bool(_fx30.x), _edr.y && _edr_left.y && bool(_fx30.y), _edr.z && _edr_left.z && bool(_fx30.z), _edr.w && _edr_left.w && bool(_fx30.w)); + _nc60 = bvec4(_edr.x && _edr_up.x && bool(_fx60.x), _edr.y && _edr_up.y && bool(_fx60.y), _edr.z && _edr_up.z && bool(_fx60.z), _edr.w && _edr_up.w && bool(_fx60.w)); + _nc15 = bvec4(_edr.x && _edr_left.x && _interp_restriction_lv3_left.x && bool(_fx15.x), _edr.y && _edr_left.y && _interp_restriction_lv3_left.y && bool(_fx15.y), _edr.z && _edr_left.z && _interp_restriction_lv3_left.z && bool(_fx15.z), _edr.w && _edr_left.w && _interp_restriction_lv3_left.w && bool(_fx15.w)); + _nc75 = bvec4(_edr.x && _edr_up.x && _interp_restriction_lv3_up.x && bool(_fx75.x), _edr.y && _edr_up.y && _interp_restriction_lv3_up.y && bool(_fx75.y), _edr.z && _edr_up.z && _interp_restriction_lv3_up.z && bool(_fx75.z), _edr.w && _edr_up.w && _interp_restriction_lv3_up.w && bool(_fx75.w)); + _a0371 = _r0141 - _r0121.wxyz; + _TMP368 = abs(_a0371); + _a0375 = _r0141 - _r0121.zwxy; + _TMP372 = abs(_a0375); + _px = bvec4(_TMP368.x <= _TMP372.x, _TMP368.y <= _TMP372.y, _TMP368.z <= _TMP372.z, _TMP368.w <= _TMP372.w); + _nc = bvec4(_nc75.x || _nc15.x || _nc30.x || _nc60.x || _nc45.x, _nc75.y || _nc15.y || _nc30.y || _nc60.y || _nc45.y, _nc75.z || _nc15.z || _nc30.z || _nc60.z || _nc45.z, _nc75.w || _nc15.w || _nc30.w || _nc60.w || _nc45.w); + _final45 = vec4(float(_nc45.x), float(_nc45.y), float(_nc45.z), float(_nc45.w))*_fx45; + _final30 = vec4(float(_nc30.x), float(_nc30.y), float(_nc30.z), float(_nc30.w))*_fx30; + _final60 = vec4(float(_nc60.x), float(_nc60.y), float(_nc60.z), float(_nc60.w))*_fx60; + _final15 = vec4(float(_nc15.x), float(_nc15.y), float(_nc15.z), float(_nc15.w))*_fx15; + _final75 = vec4(float(_nc75.x), float(_nc75.y), float(_nc75.z), float(_nc75.w))*_fx75; + _TMP42 = max(_final15, _final75); + _TMP43 = max(_final30, _final60); + _TMP44 = max(_TMP42, _TMP43); + _maximo = max(_TMP44, _final45); + if (_nc.x) { + if (_px.x) { + _TMP45 = _TMP8.xyz; + } else { + _TMP45 = _TMP10.xyz; + } + _pix1 = _TMP45; + _blend1 = _maximo.x; + } else { + if (_nc.y) { + if (_px.y) { + _TMP46 = _TMP4.xyz; + } else { + _TMP46 = _TMP8.xyz; + } + _pix1 = _TMP46; + _blend1 = _maximo.y; + } else { + if (_nc.z) { + if (_px.z) { + _TMP47 = _TMP6.xyz; + } else { + _TMP47 = _TMP4.xyz; + } + _pix1 = _TMP47; + _blend1 = _maximo.z; + } else { + if (_nc.w) { + if (_px.w) { + _TMP48 = _TMP10.xyz; + } else { + _TMP48 = _TMP6.xyz; + } + _pix1 = _TMP48; + _blend1 = _maximo.w; + } + } + } + } + if (_nc.w) { + if (_px.w) { + _TMP49 = _TMP10.xyz; + } else { + _TMP49 = _TMP6.xyz; + } + _pix2 = _TMP49; + _blend2 = _maximo.w; + } else { + if (_nc.z) { + if (_px.z) { + _TMP50 = _TMP6.xyz; + } else { + _TMP50 = _TMP4.xyz; + } + _pix2 = _TMP50; + _blend2 = _maximo.z; + } else { + if (_nc.y) { + if (_px.y) { + _TMP51 = _TMP4.xyz; + } else { + _TMP51 = _TMP8.xyz; + } + _pix2 = _TMP51; + _blend2 = _maximo.y; + } else { + if (_nc.x) { + if (_px.x) { + _TMP52 = _TMP8.xyz; + } else { + _TMP52 = _TMP10.xyz; + } + _pix2 = _TMP52; + _blend2 = _maximo.x; + } + } + } + } + _res1 = _TMP7.xyz + _blend1*(_pix1 - _TMP7.xyz); + _res2 = _TMP7.xyz + _blend2*(_pix2 - _TMP7.xyz); + _a0391 = _TMP7.xyz - _res1; + _df0389 = abs(_a0391); + _TMP53 = _df0389.x + _df0389.y + _df0389.z; + _a0395 = _TMP7.xyz - _res2; + _df0393 = abs(_a0395); + _TMP54 = _df0393.x + _df0393.y + _df0393.z; + _TMP55 = float((_TMP54 >= _TMP53)); + _res = _res1 + _TMP55*(_res2 - _res1); + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr.glsl new file mode 100644 index 000000000..4413d0e0e --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/4xbr.glsl @@ -0,0 +1,295 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP16; +vec3 _TMP24; +vec3 _TMP28; +vec3 _TMP29; +vec3 _TMP30; +vec3 _TMP25; +vec3 _TMP26; +vec3 _TMP27; +vec3 _TMP17; +vec3 _TMP21; +vec3 _TMP22; +vec3 _TMP23; +vec3 _TMP18; +vec3 _TMP19; +vec3 _TMP20; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +float _TMP7; +float _TMP6; +float _TMP5; +float _TMP4; +float _TMP3; +float _TMP2; +float _TMP1; +float _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0036; +vec2 _c0054; +vec2 _c0056; +vec2 _c0058; +vec2 _c0062; +vec2 _c0064; +vec2 _c0066; +vec2 _c0068; +float _TMP69; +float _TMP73; +float _TMP77; +float _TMP81; +float _TMP85; +float _TMP89; +float _TMP93; +float _TMP97; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _g1; + vec2 _g2; + vec3 _E11; + vec3 _E15; + _x0036 = TEX0.xy*TextureSize; + _fp = fract(_x0036); + _TMP0 = float((_fp.x >= 5.00000000E-01)); + _TMP1 = float((_fp.y >= 5.00000000E-01)); + _TMP2 = float((_fp.x >= 5.00000000E-01)); + _TMP3 = float((_fp.y >= 5.00000000E-01)); + _g1 = TEX1.xy*((_TMP0 + _TMP1) - 1.00000000E+00) + TEX1.zw*(_TMP2 - _TMP3); + _TMP4 = float((_fp.y >= 5.00000000E-01)); + _TMP5 = float((_fp.x >= 5.00000000E-01)); + _TMP6 = float((_fp.x >= 5.00000000E-01)); + _TMP7 = float((_fp.y >= 5.00000000E-01)); + _g2 = TEX1.xy*(_TMP4 - _TMP5) + TEX1.zw*((_TMP6 + _TMP7) - 1.00000000E+00); + _c0054 = TEX0.xy + _g1; + _TMP8 = COMPAT_TEXTURE(Texture, _c0054); + _c0056 = (TEX0.xy + _g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0056); + _c0058 = TEX0.xy + _g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0058); + _TMP11 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0062 = TEX0.xy - _g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0062); + _c0064 = (TEX0.xy - _g1) + _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0064); + _c0066 = TEX0.xy - _g1; + _TMP14 = COMPAT_TEXTURE(Texture, _c0066); + _c0068 = (TEX0.xy - _g1) - _g2; + _TMP15 = COMPAT_TEXTURE(Texture, _c0068); + _E11 = _TMP11.xyz; + _E15 = _TMP11.xyz; + _TMP69 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP73 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP77 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP81 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP85 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP89 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP93 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP97 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP93 == _TMP85 && _TMP93 != _TMP81 && (_TMP81 == _TMP89 && (_TMP93 == _TMP97 || _TMP81 == _TMP77) || _TMP81 == _TMP73 && (_TMP93 == _TMP97 || _TMP81 == _TMP69))) { + _E11 = _TMP11.xyz*5.00000000E-01 + _TMP12.xyz*5.00000000E-01; + _E15 = _TMP12.xyz; + } + if (_fp.x < 5.00000000E-01) { + if (_fp.x < 2.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP18 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP19 = _E11; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP20 = _E11; + } else { + _TMP20 = _E15; + } + _TMP19 = _TMP20; + } + _TMP18 = _TMP19; + } + _TMP17 = _TMP18; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP21 = _E11; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP22 = _TMP11.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP23 = _TMP11.xyz; + } else { + _TMP23 = _E11; + } + _TMP22 = _TMP23; + } + _TMP21 = _TMP22; + } + _TMP17 = _TMP21; + } + _TMP16 = _TMP17; + } else { + if (_fp.x < 7.50000000E-01) { + if (_fp.y < 2.50000000E-01) { + _TMP25 = _E11; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP26 = _TMP11.xyz; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP27 = _TMP11.xyz; + } else { + _TMP27 = _E11; + } + _TMP26 = _TMP27; + } + _TMP25 = _TMP26; + } + _TMP24 = _TMP25; + } else { + if (_fp.y < 2.50000000E-01) { + _TMP28 = _E15; + } else { + if (_fp.y < 5.00000000E-01) { + _TMP29 = _E11; + } else { + if (_fp.y < 7.50000000E-01) { + _TMP30 = _E11; + } else { + _TMP30 = _E15; + } + _TMP29 = _TMP30; + } + _TMP28 = _TMP29; + } + _TMP24 = _TMP28; + } + _TMP16 = _TMP24; + } + _ret_0 = vec4(_TMP16.x, _TMP16.y, _TMP16.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v1.1.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v1.1.glsl new file mode 100644 index 000000000..25517c035 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v1.1.glsl @@ -0,0 +1,241 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP10; +vec3 _TMP11; +vec3 _TMP12; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0018; +vec2 _c0022; +vec2 _c0024; +vec2 _c0026; +vec2 _c0030; +vec2 _c0032; +vec2 _c0034; +vec2 _c0036; +vec2 _c0038; +vec2 _c0040; +float _TMP41; +float _TMP45; +float _TMP49; +float _TMP53; +float _TMP57; +float _TMP61; +float _TMP65; +float _TMP69; +float _TMP73; +float _TMP77; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _st; + vec2 _g1; + vec2 _g2; + float _AO; + float _BO; + float _CO; + vec3 _res; + bool _fx_1; + bool _condition_11; + bool _condition_21; + bool _condition_31; + _x0018 = TEX0.xy*TextureSize; + _fp = fract(_x0018); + _st = vec2(float((_fp.x >= 5.00000000E-01)), float((_fp.y >= 5.00000000E-01))); + _g1 = TEX1.xy*((_st.x + _st.y) - 1.00000000E+00) + TEX1.zw*(_st.x - _st.y); + _g2 = TEX1.xy*(_st.y - _st.x) + TEX1.zw*((_st.x + _st.y) - 1.00000000E+00); + _AO = 2.00000000E+00*_st.y - 1.00000000E+00; + _BO = 2.00000000E+00*_st.x - 1.00000000E+00; + _CO = (_st.x + _st.y) - 5.00000000E-01; + _c0022 = TEX0.xy + _g1; + _TMP0 = COMPAT_TEXTURE(Texture, _c0022); + _c0024 = (TEX0.xy + _g1) - _g2; + _TMP1 = COMPAT_TEXTURE(Texture, _c0024); + _c0026 = TEX0.xy + _g2; + _TMP2 = COMPAT_TEXTURE(Texture, _c0026); + _TMP3 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0030 = TEX0.xy - _g2; + _TMP4 = COMPAT_TEXTURE(Texture, _c0030); + _c0032 = (TEX0.xy - _g1) + _g2; + _TMP5 = COMPAT_TEXTURE(Texture, _c0032); + _c0034 = TEX0.xy - _g1; + _TMP6 = COMPAT_TEXTURE(Texture, _c0034); + _c0036 = (TEX0.xy - _g1) - _g2; + _TMP7 = COMPAT_TEXTURE(Texture, _c0036); + _c0038 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP8 = COMPAT_TEXTURE(Texture, _c0038); + _c0040 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0040); + _TMP41 = dot(_TMP0.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP45 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP49 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP53 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP57 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP61 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP65 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP69 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP73 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP77 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _res = _TMP3.xyz; + _fx_1 = _AO*_fp.y + _BO*_fp.x > _CO; + if (_fx_1) { + _condition_11 = _TMP53 != _TMP65 && (_TMP65 == _TMP57 && (_TMP53 != _TMP69 && (_TMP53 != _TMP41 || _TMP53 != _TMP49 || _TMP57 != _TMP41 && _TMP57 != _TMP45 || _TMP65 != _TMP49 && _TMP65 != _TMP61) || _TMP53 == _TMP61 && (_TMP69 == _TMP65 || _TMP53 == _TMP49 || _TMP65 != _TMP49) || _TMP53 == _TMP45 && (_TMP69 == _TMP65 || _TMP53 == _TMP41 || _TMP57 != _TMP41)) || _TMP53 != _TMP57 && _TMP65 != _TMP69 && _TMP53 == _TMP61 && (_TMP57 == _TMP69 && _TMP65 != _TMP49 || _TMP53 != _TMP69 && _TMP65 == _TMP77)); + _condition_21 = _TMP53 != _TMP65 && _TMP53 != _TMP57 && _TMP57 != _TMP69 && _TMP53 == _TMP45 && (_TMP65 == _TMP69 && _TMP57 != _TMP41 || _TMP53 != _TMP69 && _TMP57 == _TMP73); + _condition_31 = _TMP53 != _TMP65 && _TMP61 == _TMP53 && _TMP53 == _TMP45 && _TMP53 != _TMP69 && _TMP53 != _TMP57; + if (_condition_11) { + _TMP10 = _TMP6.xyz; + } else { + if (_condition_21) { + _TMP11 = _TMP4.xyz; + } else { + if (_condition_31) { + _TMP12 = (_TMP4.xyz + _TMP6.xyz)*5.00000000E-01; + } else { + _TMP12 = _TMP3.xyz; + } + _TMP11 = _TMP12; + } + _TMP10 = _TMP11; + } + _res = _TMP10; + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.1.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.1.glsl new file mode 100644 index 000000000..d4db681da --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.1.glsl @@ -0,0 +1,265 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec4 _TMP13; +vec4 _TMP11; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0020; +vec2 _c0024; +vec2 _c0026; +vec2 _c0028; +vec2 _c0030; +vec2 _c0034; +vec2 _c0036; +vec2 _c0038; +vec2 _c0040; +vec2 _c0046; +vec2 _c0050; +float _TMP53; +float _TMP57; +float _TMP61; +float _TMP65; +float _TMP69; +float _TMP73; +float _TMP77; +float _TMP81; +float _TMP85; +float _TMP97; +float _TMP105; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _st; + vec2 _g1; + vec2 _g2; + float _AO; + float _BO; + float _CO; + float _AX; + float _BX; + float _CX; + float _AY; + float _BY; + float _CY; + vec3 _res; + bool _fx_1; + bool _fx_2; + bool _fx_3; + bool _condition_1; + bool _condition_1a; + bool _condition_1b; + bool _condition_2; + bool _condition_3; + bool _condition_4; + bool _condition_7; + bool _condition_8; + bool _condition_7a; + bool _condition_8a; + _x0020 = TEX0.xy*TextureSize; + _fp = fract(_x0020); + _st = vec2(float((_fp.x >= 5.00000000E-01)), float((_fp.y >= 5.00000000E-01))); + _g1 = TEX1.xy*((_st.x + _st.y) - 1.00000000E+00) + TEX1.zw*(_st.x - _st.y); + _g2 = TEX1.xy*(_st.y - _st.x) + TEX1.zw*((_st.x + _st.y) - 1.00000000E+00); + _AO = 2.00000000E+00*_st.y - 1.00000000E+00; + _BO = 2.00000000E+00*_st.x - 1.00000000E+00; + _CO = (_st.x + _st.y) - 5.00000000E-01; + _AX = (5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 1.00000000E+00; + _BX = (1.50000000E+00*_st.x - 5.00000000E-01*_st.y) - 5.00000000E-01; + _CX = (_st.x + 5.00000000E-01*_st.y) - 5.00000000E-01; + _AY = (-5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 5.00000000E-01; + _BY = (1.50000000E+00*_st.x + 5.00000000E-01*_st.y) - 1.00000000E+00; + _CY = (5.00000000E-01*_st.x + _st.y) - 5.00000000E-01; + _c0024 = TEX0.xy + _g1 + _g2; + _TMP0 = COMPAT_TEXTURE(Texture, _c0024); + _c0026 = TEX0.xy + _g1; + _TMP1 = COMPAT_TEXTURE(Texture, _c0026); + _c0028 = (TEX0.xy + _g1) - _g2; + _TMP2 = COMPAT_TEXTURE(Texture, _c0028); + _c0030 = TEX0.xy + _g2; + _TMP3 = COMPAT_TEXTURE(Texture, _c0030); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0034 = TEX0.xy - _g2; + _TMP5 = COMPAT_TEXTURE(Texture, _c0034); + _c0036 = (TEX0.xy - _g1) + _g2; + _TMP6 = COMPAT_TEXTURE(Texture, _c0036); + _c0038 = TEX0.xy - _g1; + _TMP7 = COMPAT_TEXTURE(Texture, _c0038); + _c0040 = (TEX0.xy - _g1) - _g2; + _TMP8 = COMPAT_TEXTURE(Texture, _c0040); + _c0046 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP11 = COMPAT_TEXTURE(Texture, _c0046); + _c0050 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0050); + _TMP53 = dot(_TMP0.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP57 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP61 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP65 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP69 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP73 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP77 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP81 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP85 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP97 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP105 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _res = _TMP4.xyz; + _fx_1 = _AO*_fp.y + _BO*_fp.x > _CO; + _fx_2 = _AX*_fp.y + _BX*_fp.x > _CX; + _fx_3 = _AY*_fp.y + _BY*_fp.x > _CY; + _condition_1a = _TMP69 == _TMP61 && _TMP69 == _TMP65 && _TMP81 == _TMP77; + _condition_1b = _TMP69 == _TMP77 && _TMP69 == _TMP57 && _TMP73 == _TMP61; + _condition_1 = _TMP69 != _TMP81 && _TMP81 == _TMP73 && (_TMP69 != _TMP85 && (_TMP69 != _TMP57 || _TMP69 != _TMP65 || _TMP73 != _TMP57 && _TMP73 != _TMP61 || _TMP81 != _TMP65 && _TMP81 != _TMP77) || _TMP69 == _TMP77 && (_TMP85 == _TMP81 || _TMP69 == _TMP65 || _TMP81 != _TMP65) || _TMP69 == _TMP61 && (_TMP85 == _TMP81 || _TMP69 == _TMP57 || _TMP73 != _TMP57)); + _condition_2 = _TMP69 != _TMP81 && _TMP69 != _TMP73 && _TMP73 != _TMP85 && _TMP69 == _TMP61 && (_TMP81 == _TMP85 && _TMP73 != _TMP57 || _TMP69 != _TMP85 && _TMP73 == _TMP97); + _condition_3 = _TMP69 != _TMP81 && _TMP69 != _TMP73 && _TMP81 != _TMP85 && _TMP69 == _TMP77 && (_TMP73 == _TMP85 && _TMP81 != _TMP65 || _TMP69 != _TMP85 && _TMP81 == _TMP105); + _condition_4 = _TMP69 != _TMP81 && _TMP77 == _TMP69 && _TMP69 == _TMP61 && _TMP69 != _TMP85 && _TMP69 != _TMP73; + _condition_7 = _TMP69 != _TMP73 && _TMP73 == _TMP57 && (_TMP69 != _TMP61 && (_TMP69 != _TMP65 || _TMP69 != _TMP81 || _TMP57 != _TMP65 && _TMP57 != _TMP53 || _TMP73 != _TMP81 && _TMP73 != _TMP85) || _TMP69 == _TMP85 && (_TMP61 == _TMP73 || _TMP69 == _TMP81 || _TMP73 != _TMP81)); + _condition_8 = _TMP69 != _TMP65 && _TMP65 == _TMP81 && (_TMP69 != _TMP77 && (_TMP69 != _TMP73 || _TMP69 != _TMP57 || _TMP81 != _TMP73 && _TMP81 != _TMP85 || _TMP65 != _TMP57 && _TMP65 != _TMP53) || _TMP69 == _TMP85 && (_TMP77 == _TMP65 || _TMP69 == _TMP73 || _TMP81 != _TMP73)); + _condition_7a = _TMP69 == _TMP53 && _TMP69 == _TMP81 && _TMP73 == _TMP85; + _condition_8a = _TMP69 == _TMP53 && _TMP69 == _TMP73 && _TMP81 == _TMP85; + if (_condition_1 && (_fx_1 || _condition_1a && _fx_2 || _condition_1b && _fx_3) || _condition_8 && _condition_8a && _BY*_fp.y + _AY*(1.00000000E+00 - _fp.x) > _CY || _fx_1 && _condition_3) { + _res = _TMP7.xyz; + } else { + if (_condition_7 && _condition_7a && _BX*(1.00000000E+00 - _fp.y) + _AX*_fp.x > _CX || _fx_1 && _condition_2) { + _res = _TMP5.xyz; + } else { + if (_fx_1 && _condition_4) { + _res = (_TMP5.xyz + _TMP7.xyz)*5.00000000E-01; + } + } + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.glsl new file mode 100644 index 000000000..f6534f1e8 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v2.glsl @@ -0,0 +1,229 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = TexCoord.xy + vec2(-_ps.x, 0.00000000E+00); + _OUT._t2.xy = TexCoord.xy + vec2(_ps.x, 0.00000000E+00); + _OUT._t3.xy = TexCoord.xy + vec2(0.00000000E+00, -_ps.y); + _OUT._t4.xy = TexCoord.xy + vec2(0.00000000E+00, _ps.y); + _OUT._t1.zw = TexCoord.xy + vec2(-_ps.x, -_ps.y); + _OUT._t2.zw = TexCoord.xy + vec2(-_ps.x, _ps.y); + _OUT._t3.zw = TexCoord.xy + vec2(_ps.x, -_ps.y); + _OUT._t4.zw = TexCoord.xy + vec2(_ps.x, _ps.y); + _ret_0._position1 = _r0006; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + gl_Position = _r0006; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; +}; +vec4 _ret_0; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0014; +float _TMP33; +float _TMP37; +float _TMP41; +float _TMP45; +float _TMP49; +float _TMP53; +float _TMP57; +float _TMP61; +float _TMP65; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec3 _res; + _x0014 = TEX0.xy*TextureSize; + _fp = fract(_x0014); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX3.xy); + _TMP2 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX1.xy); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.xy); + _TMP6 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX4.xy); + _TMP8 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP33 = dot(_TMP0.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP37 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP41 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP45 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP49 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP53 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP57 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP61 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP65 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _res = _TMP4.xyz; + if (_TMP49 != _TMP61 && _TMP61 == _TMP53 && (_TMP49 != _TMP65 && (_TMP49 != _TMP37 || _TMP49 != _TMP45 || _TMP53 != _TMP37 && _TMP53 != _TMP41 || _TMP61 != _TMP45 && _TMP61 != _TMP57) || _TMP49 == _TMP57 && (_TMP65 == _TMP61 || _TMP49 == _TMP45 || _TMP61 != _TMP45) || _TMP49 == _TMP41 && (_TMP65 == _TMP61 || _TMP49 == _TMP37 || _TMP53 != _TMP37))) { + if (_fp.y + _fp.x > 1.50000000E+00 || _TMP49 == _TMP41 && _TMP49 == _TMP45 && _TMP61 == _TMP57 && _fp.y + 5.00000000E-01*_fp.x > 1.00000000E+00 || _TMP49 == _TMP57 && _TMP49 == _TMP37 && _TMP53 == _TMP41 && _fp.y + 2.00000000E+00*_fp.x > 2.00000000E+00) { + _res = _TMP7.xyz; + } + } + if (_TMP49 != _TMP53 && _TMP53 == _TMP37 && (_TMP49 != _TMP41 && (_TMP49 != _TMP45 || _TMP49 != _TMP61 || _TMP37 != _TMP45 && _TMP37 != _TMP33 || _TMP53 != _TMP61 && _TMP53 != _TMP65) || _TMP49 == _TMP65 && (_TMP41 == _TMP53 || _TMP49 == _TMP61 || _TMP53 != _TMP61) || _TMP49 == _TMP33 && (_TMP41 == _TMP53 || _TMP49 == _TMP45 || _TMP37 != _TMP45))) { + if (-_fp.y + _fp.x > 5.00000000E-01 || _TMP49 == _TMP33 && _TMP49 == _TMP61 && _TMP53 == _TMP65 && -_fp.y + 2.00000000E+00*_fp.x > 1.00000000E+00 || _TMP49 == _TMP65 && _TMP49 == _TMP45 && _TMP37 == _TMP33 && -_fp.y + 5.00000000E-01*_fp.x > 0.00000000E+00) { + _res = _TMP5.xyz; + } + } + if (_TMP49 != _TMP37 && _TMP37 == _TMP45 && (_TMP49 != _TMP33 && (_TMP49 != _TMP61 || _TMP49 != _TMP53 || _TMP45 != _TMP61 && _TMP45 != _TMP57 || _TMP37 != _TMP53 && _TMP37 != _TMP41) || _TMP49 == _TMP41 && (_TMP33 == _TMP37 || _TMP49 == _TMP53 || _TMP37 != _TMP53) || _TMP49 == _TMP57 && (_TMP33 == _TMP37 || _TMP49 == _TMP61 || _TMP45 != _TMP61))) { + if (-_fp.y + -_fp.x > -5.00000000E-01 || _TMP49 == _TMP57 && _TMP49 == _TMP53 && _TMP37 == _TMP41 && -_fp.y + -5.00000000E-01*_fp.x > -5.00000000E-01 || _TMP49 == _TMP41 && _TMP49 == _TMP61 && _TMP45 == _TMP57 && -_fp.y + -2.00000000E+00*_fp.x > -1.00000000E+00) { + _res = _TMP1.xyz; + } + } + if (_TMP49 != _TMP45 && _TMP45 == _TMP61 && (_TMP49 != _TMP57 && (_TMP49 != _TMP53 || _TMP49 != _TMP37 || _TMP61 != _TMP53 && _TMP61 != _TMP65 || _TMP45 != _TMP37 && _TMP45 != _TMP33) || _TMP49 == _TMP33 && (_TMP57 == _TMP45 || _TMP49 == _TMP37 || _TMP45 != _TMP37) || _TMP49 == _TMP65 && (_TMP57 == _TMP45 || _TMP49 == _TMP53 || _TMP61 != _TMP53))) { + if (_fp.y + -_fp.x > 5.00000000E-01 || _TMP49 == _TMP65 && _TMP49 == _TMP37 && _TMP45 == _TMP33 && _fp.y + -2.00000000E+00*_fp.x > 0.00000000E+00 || _TMP49 == _TMP33 && _TMP49 == _TMP53 && _TMP61 == _TMP65 && _fp.y + -5.00000000E-01*_fp.x > 5.00000000E-01) { + _res = _TMP3.xyz; + } + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.2.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.2.glsl new file mode 100644 index 000000000..0218b500e --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.2.glsl @@ -0,0 +1,629 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP66; +vec3 _TMP67; +vec3 _TMP68; +vec3 _TMP55; +float _TMP56; +vec3 _TMP70; +vec3 _TMP52; +float _TMP53; +vec3 _TMP49; +float _TMP50; +float _TMP47; +float _TMP46; +float _TMP45; +float _TMP44; +float _TMP43; +float _TMP42; +float _TMP41; +float _TMP40; +float _TMP39; +float _TMP37; +float _TMP36; +float _TMP35; +float _TMP34; +float _TMP33; +float _TMP32; +float _TMP31; +float _TMP30; +float _TMP29; +float _TMP27; +float _TMP26; +float _TMP25; +float _TMP24; +float _TMP23; +float _TMP22; +float _TMP21; +float _TMP20; +float _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0081; +vec2 _c0085; +vec2 _c0087; +vec2 _c0089; +vec2 _c0091; +vec2 _c0095; +vec2 _c0097; +vec2 _c0099; +vec2 _c0101; +vec2 _c0103; +vec2 _c0105; +vec2 _c0107; +vec2 _c0109; +vec2 _c0111; +vec2 _c0113; +vec2 _c0115; +vec2 _c0117; +vec2 _c0119; +vec2 _c0121; +float _TMP126; +float _TMP130; +float _TMP134; +float _TMP138; +float _TMP142; +float _TMP146; +float _TMP150; +float _TMP154; +vec3 _r0201; +vec3 _v0201; +vec3 _r0213; +vec3 _v0213; +vec3 _r0225; +vec3 _v0225; +vec3 _r0237; +vec3 _v0237; +vec3 _r0249; +vec3 _v0249; +vec3 _r0261; +vec3 _v0261; +vec3 _r0273; +vec3 _v0273; +vec3 _r0285; +vec3 _v0285; +vec3 _r0297; +vec3 _v0297; +vec3 _r0309; +vec3 _v0309; +vec3 _r0321; +vec3 _v0321; +vec3 _r0333; +vec3 _v0333; +vec3 _r0345; +vec3 _v0345; +vec3 _r0357; +vec3 _v0357; +vec3 _r0369; +vec3 _v0369; +vec3 _r0381; +vec3 _v0381; +vec3 _r0393; +vec3 _v0393; +vec3 _r0405; +vec3 _v0405; +vec3 _r0417; +vec3 _v0417; +vec3 _r0429; +vec3 _v0429; +vec3 _r0441; +vec3 _v0441; +vec3 _r0453; +vec3 _v0453; +vec3 _r0465; +vec3 _v0465; +vec3 _r0477; +vec3 _v0477; +vec3 _r0489; +vec3 _v0489; +vec3 _r0501; +vec3 _v0501; +vec3 _r0513; +vec3 _v0513; +vec3 _r0525; +vec3 _v0525; +vec3 _r0537; +vec3 _v0537; +vec3 _r0549; +vec3 _v0549; +vec3 _r0561; +vec3 _v0561; +vec3 _r0573; +vec3 _v0573; +vec3 _r0585; +vec3 _v0585; +vec3 _r0597; +vec3 _v0597; +vec3 _r0609; +vec3 _v0609; +vec3 _r0621; +vec3 _v0621; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _st; + vec2 _g1; + vec2 _g2; + float _AO; + float _BO; + float _CO; + float _AX; + float _BX; + float _CX; + float _AY; + float _BY; + float _CY; + bool _ex; + bool _e_i; + bool _kei; + bool _mei; + bool _ex_ck; + bool _ex_em; + bool _fx_1; + bool _fx_2; + bool _fx_3; + bool _fx_4; + bool _fx_5; + bool _r1; + bool _r2; + bool _r3; + _x0081 = TEX0.xy*TextureSize; + _fp = fract(_x0081); + _st = vec2(float((_fp.x >= 5.00000000E-01)), float((_fp.y >= 5.00000000E-01))); + _g1 = TEX1.xy*((_st.x + _st.y) - 1.00000000E+00) + TEX1.zw*(_st.x - _st.y); + _g2 = TEX1.xy*(_st.y - _st.x) + TEX1.zw*((_st.x + _st.y) - 1.00000000E+00); + _AO = 2.00000000E+00*_st.y - 1.00000000E+00; + _BO = 2.00000000E+00*_st.x - 1.00000000E+00; + _CO = (_st.x + _st.y) - 5.00000000E-01; + _AX = (5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 1.00000000E+00; + _BX = (1.50000000E+00*_st.x - 5.00000000E-01*_st.y) - 5.00000000E-01; + _CX = (_st.x + 5.00000000E-01*_st.y) - 5.00000000E-01; + _AY = (-5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 5.00000000E-01; + _BY = (1.50000000E+00*_st.x + 5.00000000E-01*_st.y) - 1.00000000E+00; + _CY = (5.00000000E-01*_st.x + _st.y) - 5.00000000E-01; + _c0085 = TEX0.xy + _g1 + _g2; + _TMP0 = COMPAT_TEXTURE(Texture, _c0085); + _c0087 = TEX0.xy + _g1; + _TMP1 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = (TEX0.xy + _g1) - _g2; + _TMP2 = COMPAT_TEXTURE(Texture, _c0089); + _c0091 = TEX0.xy + _g2; + _TMP3 = COMPAT_TEXTURE(Texture, _c0091); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0095 = TEX0.xy - _g2; + _TMP5 = COMPAT_TEXTURE(Texture, _c0095); + _c0097 = (TEX0.xy - _g1) + _g2; + _TMP6 = COMPAT_TEXTURE(Texture, _c0097); + _c0099 = TEX0.xy - _g1; + _TMP7 = COMPAT_TEXTURE(Texture, _c0099); + _c0101 = (TEX0.xy - _g1) - _g2; + _TMP8 = COMPAT_TEXTURE(Texture, _c0101); + _c0103 = (TEX0.xy + 2.00000000E+00*_g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0103); + _c0105 = (TEX0.xy - _g1) + 2.00000000E+00*_g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0105); + _c0107 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP11 = COMPAT_TEXTURE(Texture, _c0107); + _c0109 = TEX0.xy - 2.00000000E+00*_g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0109); + _c0111 = (TEX0.xy - _g1) - 2.00000000E+00*_g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0111); + _c0113 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP14 = COMPAT_TEXTURE(Texture, _c0113); + _c0115 = TEX0.xy - 2.00000000E+00*_g1; + _TMP15 = COMPAT_TEXTURE(Texture, _c0115); + _c0117 = (TEX0.xy - 2.00000000E+00*_g1) - _g2; + _TMP16 = COMPAT_TEXTURE(Texture, _c0117); + _c0119 = TEX0.xy + 2.00000000E+00*_g1; + _TMP17 = COMPAT_TEXTURE(Texture, _c0119); + _c0121 = TEX0.xy + 2.00000000E+00*_g2; + _TMP18 = COMPAT_TEXTURE(Texture, _c0121); + _TMP126 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP130 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP134 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP138 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP142 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP146 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP150 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP154 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _fx_1 = _AO*_fp.y + _BO*_fp.x > _CO; + _fx_2 = _AX*_fp.y + _BX*_fp.x > _CX; + _fx_3 = _AY*_fp.y + _BY*_fp.x > _CY; + _fx_4 = _BY*_fp.y + _AY*(1.00000000E+00 - _fp.x) > _CY; + _fx_5 = _BX*(1.00000000E+00 - _fp.y) + _AX*_fp.x > _CX; + _v0201 = _TMP4.xyz - _TMP2.xyz; + _r0201.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0201); + _r0201.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0201); + _r0201.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0201); + _TMP70 = abs(_r0201); + _TMP19 = _TMP70.x; + _v0213 = _TMP4.xyz - _TMP6.xyz; + _r0213.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0213); + _r0213.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0213); + _r0213.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0213); + _TMP70 = abs(_r0213); + _TMP20 = _TMP70.x; + _v0225 = _TMP8.xyz - _TMP15.xyz; + _r0225.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0225); + _r0225.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0225); + _r0225.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0225); + _TMP70 = abs(_r0225); + _TMP21 = _TMP70.x; + _v0237 = _TMP8.xyz - _TMP12.xyz; + _r0237.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0237); + _r0237.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0237); + _r0237.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0237); + _TMP70 = abs(_r0237); + _TMP22 = _TMP70.x; + _v0249 = _TMP7.xyz - _TMP5.xyz; + _r0249.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0249); + _r0249.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0249); + _r0249.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0249); + _TMP70 = abs(_r0249); + _TMP23 = _TMP70.x; + _v0261 = _TMP7.xyz - _TMP3.xyz; + _r0261.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0261); + _r0261.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0261); + _r0261.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0261); + _TMP70 = abs(_r0261); + _TMP24 = _TMP70.x; + _v0273 = _TMP7.xyz - _TMP16.xyz; + _r0273.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0273); + _r0273.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0273); + _r0273.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0273); + _TMP70 = abs(_r0273); + _TMP25 = _TMP70.x; + _v0285 = _TMP5.xyz - _TMP13.xyz; + _r0285.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0285); + _r0285.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0285); + _r0285.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0285); + _TMP70 = abs(_r0285); + _TMP26 = _TMP70.x; + _v0297 = _TMP5.xyz - _TMP1.xyz; + _r0297.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0297); + _r0297.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0297); + _r0297.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0297); + _TMP70 = abs(_r0297); + _TMP27 = _TMP70.x; + _v0309 = _TMP4.xyz - _TMP8.xyz; + _r0309.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0309); + _r0309.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0309); + _r0309.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0309); + _TMP70 = abs(_r0309); + _e_i = _TMP19 + _TMP20 + _TMP21 + _TMP22 + 4.00000000E+00*_TMP23 < _TMP24 + _TMP25 + _TMP26 + _TMP27 + 4.00000000E+00*_TMP70.x; + _v0321 = _TMP4.xyz - _TMP0.xyz; + _r0321.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0321); + _r0321.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0321); + _r0321.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0321); + _TMP70 = abs(_r0321); + _TMP29 = _TMP70.x; + _v0333 = _TMP4.xyz - _TMP8.xyz; + _r0333.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0333); + _r0333.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0333); + _r0333.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0333); + _TMP70 = abs(_r0333); + _TMP30 = _TMP70.x; + _v0345 = _TMP2.xyz - _TMP12.xyz; + _r0345.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0345); + _r0345.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0345); + _r0345.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0345); + _TMP70 = abs(_r0345); + _TMP31 = _TMP70.x; + _v0357 = _TMP2.xyz - _TMP17.xyz; + _r0357.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0357); + _r0357.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0357); + _r0357.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0357); + _TMP70 = abs(_r0357); + _TMP32 = _TMP70.x; + _v0369 = _TMP5.xyz - _TMP1.xyz; + _r0369.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0369); + _r0369.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0369); + _r0369.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0369); + _TMP70 = abs(_r0369); + _TMP33 = _TMP70.x; + _v0381 = _TMP5.xyz - _TMP7.xyz; + _r0381.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0381); + _r0381.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0381); + _r0381.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0381); + _TMP70 = abs(_r0381); + _TMP34 = _TMP70.x; + _v0393 = _TMP5.xyz - _TMP11.xyz; + _r0393.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0393); + _r0393.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0393); + _r0393.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0393); + _TMP70 = abs(_r0393); + _TMP35 = _TMP70.x; + _v0405 = _TMP1.xyz - _TMP9.xyz; + _r0405.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0405); + _r0405.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0405); + _r0405.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0405); + _TMP70 = abs(_r0405); + _TMP36 = _TMP70.x; + _v0417 = _TMP1.xyz - _TMP3.xyz; + _r0417.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0417); + _r0417.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0417); + _r0417.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0417); + _TMP70 = abs(_r0417); + _TMP37 = _TMP70.x; + _v0429 = _TMP4.xyz - _TMP2.xyz; + _r0429.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0429); + _r0429.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0429); + _r0429.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0429); + _TMP70 = abs(_r0429); + _kei = _TMP29 + _TMP30 + _TMP31 + _TMP32 + 4.00000000E+00*_TMP33 < _TMP34 + _TMP35 + _TMP36 + _TMP37 + 4.00000000E+00*_TMP70.x; + _v0441 = _TMP4.xyz - _TMP8.xyz; + _r0441.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0441); + _r0441.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0441); + _r0441.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0441); + _TMP70 = abs(_r0441); + _TMP39 = _TMP70.x; + _v0453 = _TMP4.xyz - _TMP0.xyz; + _r0453.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0453); + _r0453.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0453); + _r0453.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0453); + _TMP70 = abs(_r0453); + _TMP40 = _TMP70.x; + _v0465 = _TMP6.xyz - _TMP18.xyz; + _r0465.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0465); + _r0465.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0465); + _r0465.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0465); + _TMP70 = abs(_r0465); + _TMP41 = _TMP70.x; + _v0477 = _TMP6.xyz - _TMP15.xyz; + _r0477.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0477); + _r0477.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0477); + _r0477.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0477); + _TMP70 = abs(_r0477); + _TMP42 = _TMP70.x; + _v0489 = _TMP3.xyz - _TMP7.xyz; + _r0489.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0489); + _r0489.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0489); + _r0489.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0489); + _TMP70 = abs(_r0489); + _TMP43 = _TMP70.x; + _v0501 = _TMP3.xyz - _TMP1.xyz; + _r0501.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0501); + _r0501.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0501); + _r0501.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0501); + _TMP70 = abs(_r0501); + _TMP44 = _TMP70.x; + _v0513 = _TMP3.xyz - _TMP10.xyz; + _r0513.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0513); + _r0513.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0513); + _r0513.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0513); + _TMP70 = abs(_r0513); + _TMP45 = _TMP70.x; + _v0525 = _TMP7.xyz - _TMP14.xyz; + _r0525.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0525); + _r0525.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0525); + _r0525.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0525); + _TMP70 = abs(_r0525); + _TMP46 = _TMP70.x; + _v0537 = _TMP7.xyz - _TMP5.xyz; + _r0537.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0537); + _r0537.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0537); + _r0537.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0537); + _TMP70 = abs(_r0537); + _TMP47 = _TMP70.x; + _v0549 = _TMP4.xyz - _TMP6.xyz; + _r0549.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0549); + _r0549.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0549); + _r0549.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0549); + _TMP70 = abs(_r0549); + _mei = _TMP39 + _TMP40 + _TMP41 + _TMP42 + 4.00000000E+00*_TMP43 < _TMP44 + _TMP45 + _TMP46 + _TMP47 + 4.00000000E+00*_TMP70.x; + _v0561 = _TMP4.xyz - _TMP5.xyz; + _r0561.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0561); + _r0561.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0561); + _r0561.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0561); + _TMP70 = abs(_r0561); + _TMP50 = _TMP70.x; + _v0573 = _TMP4.xyz - _TMP7.xyz; + _r0573.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0573); + _r0573.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0573); + _r0573.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0573); + _TMP70 = abs(_r0573); + if (_TMP50 <= _TMP70.x) { + _TMP49 = _TMP5.xyz; + } else { + _TMP49 = _TMP7.xyz; + } + _v0585 = _TMP4.xyz - _TMP1.xyz; + _r0585.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0585); + _r0585.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0585); + _r0585.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0585); + _TMP70 = abs(_r0585); + _TMP53 = _TMP70.x; + _v0597 = _TMP4.xyz - _TMP5.xyz; + _r0597.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0597); + _r0597.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0597); + _r0597.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0597); + _TMP70 = abs(_r0597); + if (_TMP53 <= _TMP70.x) { + _TMP52 = _TMP1.xyz; + } else { + _TMP52 = _TMP5.xyz; + } + _v0609 = _TMP4.xyz - _TMP7.xyz; + _r0609.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0609); + _r0609.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0609); + _r0609.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0609); + _TMP70 = abs(_r0609); + _TMP56 = _TMP70.x; + _v0621 = _TMP4.xyz - _TMP3.xyz; + _r0621.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0621); + _r0621.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0621); + _r0621.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0621); + _TMP70 = abs(_r0621); + if (_TMP56 <= _TMP70.x) { + _TMP55 = _TMP7.xyz; + } else { + _TMP55 = _TMP3.xyz; + } + _ex = _TMP138 != _TMP142 && _TMP138 != _TMP150; + _ex_ck = _TMP138 != _TMP126 && _TMP138 != _TMP142; + _ex_em = _TMP138 != _TMP150 && _TMP138 != _TMP134; + _r1 = _e_i && _ex && (_fx_1 || _TMP142 == _TMP146 && _fx_2 || _TMP150 == _TMP130 && _fx_3); + _r2 = _ex_ck && _kei && _TMP126 == _TMP154 && _fx_5; + _r3 = _ex_em && _mei && _TMP134 == _TMP154 && _fx_4; + if (_r1) { + _TMP66 = _TMP49; + } else { + if (_r2) { + _TMP67 = _TMP52; + } else { + if (_r3) { + _TMP68 = _TMP55; + } else { + _TMP68 = _TMP4.xyz; + } + _TMP67 = _TMP68; + } + _TMP66 = _TMP67; + } + _ret_0 = vec4(_TMP66.x, _TMP66.y, _TMP66.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.3.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.3.glsl new file mode 100644 index 000000000..5136110b0 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.3.glsl @@ -0,0 +1,689 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP58; +vec3 _TMP59; +vec3 _TMP60; +vec3 _TMP55; +float _TMP56; +vec3 _TMP62; +vec3 _TMP52; +float _TMP53; +vec3 _TMP49; +float _TMP50; +float _TMP47; +float _TMP46; +float _TMP45; +float _TMP44; +float _TMP43; +float _TMP42; +float _TMP41; +float _TMP40; +float _TMP39; +float _TMP37; +float _TMP36; +float _TMP35; +float _TMP34; +float _TMP33; +float _TMP32; +float _TMP31; +float _TMP30; +float _TMP29; +float _TMP27; +float _TMP26; +float _TMP25; +float _TMP24; +float _TMP23; +float _TMP22; +float _TMP21; +float _TMP20; +float _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0071; +vec2 _c0075; +vec2 _c0077; +vec2 _c0079; +vec2 _c0081; +vec2 _c0085; +vec2 _c0087; +vec2 _c0089; +vec2 _c0091; +vec2 _c0093; +vec2 _c0095; +vec2 _c0097; +vec2 _c0099; +vec2 _c0101; +vec2 _c0103; +vec2 _c0105; +vec2 _c0107; +vec2 _c0109; +vec2 _c0111; +float _TMP116; +float _TMP120; +float _TMP124; +float _TMP128; +float _TMP132; +float _TMP136; +float _TMP140; +float _TMP144; +vec3 _r0191; +vec3 _v0191; +vec3 _r0203; +vec3 _v0203; +vec3 _r0215; +vec3 _v0215; +vec3 _r0227; +vec3 _v0227; +vec3 _r0239; +vec3 _v0239; +vec3 _r0251; +vec3 _v0251; +vec3 _r0263; +vec3 _v0263; +vec3 _r0275; +vec3 _v0275; +vec3 _r0287; +vec3 _v0287; +vec3 _r0299; +vec3 _v0299; +vec3 _r0311; +vec3 _v0311; +vec3 _r0323; +vec3 _v0323; +vec3 _r0335; +vec3 _v0335; +vec3 _r0347; +vec3 _v0347; +vec3 _r0359; +vec3 _v0359; +vec3 _r0371; +vec3 _v0371; +vec3 _r0383; +vec3 _v0383; +vec3 _r0395; +vec3 _v0395; +vec3 _r0407; +vec3 _v0407; +vec3 _r0419; +vec3 _v0419; +vec3 _r0431; +vec3 _v0431; +vec3 _r0443; +vec3 _v0443; +vec3 _r0455; +vec3 _v0455; +vec3 _r0467; +vec3 _v0467; +vec3 _r0479; +vec3 _v0479; +vec3 _r0491; +vec3 _v0491; +vec3 _r0503; +vec3 _v0503; +vec3 _r0515; +vec3 _v0515; +vec3 _r0527; +vec3 _v0527; +vec3 _r0539; +vec3 _v0539; +vec3 _r0551; +vec3 _v0551; +vec3 _r0563; +vec3 _v0563; +vec3 _r0575; +vec3 _v0575; +vec3 _r0587; +vec3 _v0587; +vec3 _r0599; +vec3 _v0599; +vec3 _r0611; +vec3 _v0611; +vec3 _r0623; +vec3 _v0623; +vec3 _r0635; +vec3 _v0635; +vec3 _r0647; +vec3 _v0647; +vec3 _r0659; +vec3 _v0659; +vec3 _r0671; +vec3 _v0671; +vec3 _r0683; +vec3 _v0683; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _st; + vec2 _g1; + vec2 _g2; + float _AO; + float _BO; + float _CO; + float _AX; + float _BX; + float _CX; + float _AY; + float _BY; + float _CY; + bool _ex; + bool _e_i; + bool _kei; + bool _mei; + bool _ex_ck; + bool _ex_em; + bool _ex2; + bool _ex3; + bool _exkm; + bool _fx_1; + bool _fx_2; + bool _fx_3; + bool _fx_4; + bool _fx_5; + float _ke; + float _ki; + float _kek; + float _kem; + float _kik; + float _kim; + bool _r1; + bool _r2; + bool _r3; + _x0071 = TEX0.xy*TextureSize; + _fp = fract(_x0071); + _st = vec2(float((_fp.x >= 5.00000000E-01)), float((_fp.y >= 5.00000000E-01))); + _g1 = TEX1.xy*((_st.x + _st.y) - 1.00000000E+00) + TEX1.zw*(_st.x - _st.y); + _g2 = TEX1.xy*(_st.y - _st.x) + TEX1.zw*((_st.x + _st.y) - 1.00000000E+00); + _AO = 2.00000000E+00*_st.y - 1.00000000E+00; + _BO = 2.00000000E+00*_st.x - 1.00000000E+00; + _CO = (_st.x + _st.y) - 5.00000000E-01; + _AX = (5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 1.00000000E+00; + _BX = (1.50000000E+00*_st.x - 5.00000000E-01*_st.y) - 5.00000000E-01; + _CX = (_st.x + 5.00000000E-01*_st.y) - 5.00000000E-01; + _AY = (-5.00000000E-01*_st.x + 1.50000000E+00*_st.y) - 5.00000000E-01; + _BY = (1.50000000E+00*_st.x + 5.00000000E-01*_st.y) - 1.00000000E+00; + _CY = (5.00000000E-01*_st.x + _st.y) - 5.00000000E-01; + _c0075 = TEX0.xy + _g1 + _g2; + _TMP0 = COMPAT_TEXTURE(Texture, _c0075); + _c0077 = TEX0.xy + _g1; + _TMP1 = COMPAT_TEXTURE(Texture, _c0077); + _c0079 = (TEX0.xy + _g1) - _g2; + _TMP2 = COMPAT_TEXTURE(Texture, _c0079); + _c0081 = TEX0.xy + _g2; + _TMP3 = COMPAT_TEXTURE(Texture, _c0081); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0085 = TEX0.xy - _g2; + _TMP5 = COMPAT_TEXTURE(Texture, _c0085); + _c0087 = (TEX0.xy - _g1) + _g2; + _TMP6 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = TEX0.xy - _g1; + _TMP7 = COMPAT_TEXTURE(Texture, _c0089); + _c0091 = (TEX0.xy - _g1) - _g2; + _TMP8 = COMPAT_TEXTURE(Texture, _c0091); + _c0093 = (TEX0.xy + 2.00000000E+00*_g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0093); + _c0095 = (TEX0.xy - _g1) + 2.00000000E+00*_g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0095); + _c0097 = (TEX0.xy + _g1) - 2.00000000E+00*_g2; + _TMP11 = COMPAT_TEXTURE(Texture, _c0097); + _c0099 = TEX0.xy - 2.00000000E+00*_g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0099); + _c0101 = (TEX0.xy - _g1) - 2.00000000E+00*_g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0101); + _c0103 = (TEX0.xy - 2.00000000E+00*_g1) + _g2; + _TMP14 = COMPAT_TEXTURE(Texture, _c0103); + _c0105 = TEX0.xy - 2.00000000E+00*_g1; + _TMP15 = COMPAT_TEXTURE(Texture, _c0105); + _c0107 = (TEX0.xy - 2.00000000E+00*_g1) - _g2; + _TMP16 = COMPAT_TEXTURE(Texture, _c0107); + _c0109 = TEX0.xy + 2.00000000E+00*_g1; + _TMP17 = COMPAT_TEXTURE(Texture, _c0109); + _c0111 = TEX0.xy + 2.00000000E+00*_g2; + _TMP18 = COMPAT_TEXTURE(Texture, _c0111); + _TMP116 = dot(_TMP1.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP120 = dot(_TMP2.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP124 = dot(_TMP3.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP128 = dot(_TMP4.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP132 = dot(_TMP5.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP136 = dot(_TMP6.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP140 = dot(_TMP7.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP144 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _fx_1 = _AO*_fp.y + _BO*_fp.x > _CO; + _fx_2 = _AX*_fp.y + _BX*_fp.x > _CX; + _fx_3 = _AY*_fp.y + _BY*_fp.x > _CY; + _fx_4 = _BY*_fp.y + _AY*(1.00000000E+00 - _fp.x) > _CY; + _fx_5 = _BX*(1.00000000E+00 - _fp.y) + _AX*_fp.x > _CX; + _v0191 = _TMP4.xyz - _TMP2.xyz; + _r0191.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0191); + _r0191.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0191); + _r0191.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0191); + _TMP62 = abs(_r0191); + _TMP19 = _TMP62.x; + _v0203 = _TMP4.xyz - _TMP6.xyz; + _r0203.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0203); + _r0203.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0203); + _r0203.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0203); + _TMP62 = abs(_r0203); + _TMP20 = _TMP62.x; + _v0215 = _TMP8.xyz - _TMP15.xyz; + _r0215.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0215); + _r0215.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0215); + _r0215.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0215); + _TMP62 = abs(_r0215); + _TMP21 = _TMP62.x; + _v0227 = _TMP8.xyz - _TMP12.xyz; + _r0227.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0227); + _r0227.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0227); + _r0227.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0227); + _TMP62 = abs(_r0227); + _TMP22 = _TMP62.x; + _v0239 = _TMP7.xyz - _TMP5.xyz; + _r0239.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0239); + _r0239.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0239); + _r0239.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0239); + _TMP62 = abs(_r0239); + _TMP23 = _TMP62.x; + _v0251 = _TMP7.xyz - _TMP3.xyz; + _r0251.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0251); + _r0251.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0251); + _r0251.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0251); + _TMP62 = abs(_r0251); + _TMP24 = _TMP62.x; + _v0263 = _TMP7.xyz - _TMP16.xyz; + _r0263.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0263); + _r0263.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0263); + _r0263.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0263); + _TMP62 = abs(_r0263); + _TMP25 = _TMP62.x; + _v0275 = _TMP5.xyz - _TMP13.xyz; + _r0275.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0275); + _r0275.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0275); + _r0275.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0275); + _TMP62 = abs(_r0275); + _TMP26 = _TMP62.x; + _v0287 = _TMP5.xyz - _TMP1.xyz; + _r0287.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0287); + _r0287.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0287); + _r0287.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0287); + _TMP62 = abs(_r0287); + _TMP27 = _TMP62.x; + _v0299 = _TMP4.xyz - _TMP8.xyz; + _r0299.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0299); + _r0299.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0299); + _r0299.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0299); + _TMP62 = abs(_r0299); + _e_i = _TMP19 + _TMP20 + _TMP21 + _TMP22 + 4.00000000E+00*_TMP23 < _TMP24 + _TMP25 + _TMP26 + _TMP27 + 4.00000000E+00*_TMP62.x; + _v0311 = _TMP4.xyz - _TMP0.xyz; + _r0311.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0311); + _r0311.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0311); + _r0311.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0311); + _TMP62 = abs(_r0311); + _TMP29 = _TMP62.x; + _v0323 = _TMP4.xyz - _TMP8.xyz; + _r0323.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0323); + _r0323.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0323); + _r0323.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0323); + _TMP62 = abs(_r0323); + _TMP30 = _TMP62.x; + _v0335 = _TMP2.xyz - _TMP12.xyz; + _r0335.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0335); + _r0335.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0335); + _r0335.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0335); + _TMP62 = abs(_r0335); + _TMP31 = _TMP62.x; + _v0347 = _TMP2.xyz - _TMP17.xyz; + _r0347.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0347); + _r0347.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0347); + _r0347.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0347); + _TMP62 = abs(_r0347); + _TMP32 = _TMP62.x; + _v0359 = _TMP5.xyz - _TMP1.xyz; + _r0359.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0359); + _r0359.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0359); + _r0359.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0359); + _TMP62 = abs(_r0359); + _TMP33 = _TMP62.x; + _v0371 = _TMP5.xyz - _TMP7.xyz; + _r0371.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0371); + _r0371.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0371); + _r0371.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0371); + _TMP62 = abs(_r0371); + _TMP34 = _TMP62.x; + _v0383 = _TMP5.xyz - _TMP11.xyz; + _r0383.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0383); + _r0383.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0383); + _r0383.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0383); + _TMP62 = abs(_r0383); + _TMP35 = _TMP62.x; + _v0395 = _TMP1.xyz - _TMP9.xyz; + _r0395.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0395); + _r0395.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0395); + _r0395.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0395); + _TMP62 = abs(_r0395); + _TMP36 = _TMP62.x; + _v0407 = _TMP1.xyz - _TMP3.xyz; + _r0407.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0407); + _r0407.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0407); + _r0407.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0407); + _TMP62 = abs(_r0407); + _TMP37 = _TMP62.x; + _v0419 = _TMP4.xyz - _TMP2.xyz; + _r0419.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0419); + _r0419.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0419); + _r0419.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0419); + _TMP62 = abs(_r0419); + _kei = _TMP29 + _TMP30 + _TMP31 + _TMP32 + 4.00000000E+00*_TMP33 < _TMP34 + _TMP35 + _TMP36 + _TMP37 + 4.00000000E+00*_TMP62.x; + _v0431 = _TMP4.xyz - _TMP8.xyz; + _r0431.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0431); + _r0431.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0431); + _r0431.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0431); + _TMP62 = abs(_r0431); + _TMP39 = _TMP62.x; + _v0443 = _TMP4.xyz - _TMP0.xyz; + _r0443.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0443); + _r0443.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0443); + _r0443.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0443); + _TMP62 = abs(_r0443); + _TMP40 = _TMP62.x; + _v0455 = _TMP6.xyz - _TMP18.xyz; + _r0455.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0455); + _r0455.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0455); + _r0455.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0455); + _TMP62 = abs(_r0455); + _TMP41 = _TMP62.x; + _v0467 = _TMP6.xyz - _TMP15.xyz; + _r0467.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0467); + _r0467.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0467); + _r0467.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0467); + _TMP62 = abs(_r0467); + _TMP42 = _TMP62.x; + _v0479 = _TMP3.xyz - _TMP7.xyz; + _r0479.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0479); + _r0479.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0479); + _r0479.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0479); + _TMP62 = abs(_r0479); + _TMP43 = _TMP62.x; + _v0491 = _TMP3.xyz - _TMP1.xyz; + _r0491.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0491); + _r0491.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0491); + _r0491.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0491); + _TMP62 = abs(_r0491); + _TMP44 = _TMP62.x; + _v0503 = _TMP3.xyz - _TMP10.xyz; + _r0503.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0503); + _r0503.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0503); + _r0503.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0503); + _TMP62 = abs(_r0503); + _TMP45 = _TMP62.x; + _v0515 = _TMP7.xyz - _TMP14.xyz; + _r0515.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0515); + _r0515.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0515); + _r0515.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0515); + _TMP62 = abs(_r0515); + _TMP46 = _TMP62.x; + _v0527 = _TMP7.xyz - _TMP5.xyz; + _r0527.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0527); + _r0527.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0527); + _r0527.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0527); + _TMP62 = abs(_r0527); + _TMP47 = _TMP62.x; + _v0539 = _TMP4.xyz - _TMP6.xyz; + _r0539.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0539); + _r0539.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0539); + _r0539.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0539); + _TMP62 = abs(_r0539); + _mei = _TMP39 + _TMP40 + _TMP41 + _TMP42 + 4.00000000E+00*_TMP43 < _TMP44 + _TMP45 + _TMP46 + _TMP47 + 4.00000000E+00*_TMP62.x; + _v0551 = _TMP5.xyz - _TMP6.xyz; + _r0551.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0551); + _r0551.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0551); + _r0551.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0551); + _TMP62 = abs(_r0551); + _ke = _TMP62.x; + _v0563 = _TMP1.xyz - _TMP8.xyz; + _r0563.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0563); + _r0563.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0563); + _r0563.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0563); + _TMP62 = abs(_r0563); + _kek = _TMP62.x; + _v0575 = _TMP3.xyz - _TMP8.xyz; + _r0575.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0575); + _r0575.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0575); + _r0575.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0575); + _TMP62 = abs(_r0575); + _kem = _TMP62.x; + _v0587 = _TMP7.xyz - _TMP2.xyz; + _r0587.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0587); + _r0587.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0587); + _r0587.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0587); + _TMP62 = abs(_r0587); + _ki = _TMP62.x; + _v0599 = _TMP5.xyz - _TMP0.xyz; + _r0599.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0599); + _r0599.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0599); + _r0599.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0599); + _TMP62 = abs(_r0599); + _kik = _TMP62.x; + _v0611 = _TMP7.xyz - _TMP0.xyz; + _r0611.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0611); + _r0611.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0611); + _r0611.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0611); + _TMP62 = abs(_r0611); + _kim = _TMP62.x; + _ex2 = _TMP128 != _TMP136; + _exkm = _TMP128 != _TMP144; + _ex3 = _TMP128 != _TMP120; + _v0623 = _TMP4.xyz - _TMP5.xyz; + _r0623.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0623); + _r0623.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0623); + _r0623.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0623); + _TMP62 = abs(_r0623); + _TMP50 = _TMP62.x; + _v0635 = _TMP4.xyz - _TMP7.xyz; + _r0635.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0635); + _r0635.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0635); + _r0635.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0635); + _TMP62 = abs(_r0635); + if (_TMP50 <= _TMP62.x) { + _TMP49 = _TMP5.xyz; + } else { + _TMP49 = _TMP7.xyz; + } + _v0647 = _TMP4.xyz - _TMP1.xyz; + _r0647.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0647); + _r0647.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0647); + _r0647.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0647); + _TMP62 = abs(_r0647); + _TMP53 = _TMP62.x; + _v0659 = _TMP4.xyz - _TMP5.xyz; + _r0659.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0659); + _r0659.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0659); + _r0659.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0659); + _TMP62 = abs(_r0659); + if (_TMP53 <= _TMP62.x) { + _TMP52 = _TMP1.xyz; + } else { + _TMP52 = _TMP5.xyz; + } + _v0671 = _TMP4.xyz - _TMP7.xyz; + _r0671.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0671); + _r0671.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0671); + _r0671.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0671); + _TMP62 = abs(_r0671); + _TMP56 = _TMP62.x; + _v0683 = _TMP4.xyz - _TMP3.xyz; + _r0683.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _v0683); + _r0683.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _v0683); + _r0683.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _v0683); + _TMP62 = abs(_r0683); + if (_TMP56 <= _TMP62.x) { + _TMP55 = _TMP7.xyz; + } else { + _TMP55 = _TMP3.xyz; + } + _ex = _TMP128 != _TMP132 || _TMP128 != _TMP140; + _ex_ck = _TMP128 != _TMP116 || _TMP128 != _TMP132; + _ex_em = _TMP128 != _TMP140 || _TMP128 != _TMP124; + _r1 = _e_i && _ex && (_fx_1 || 2.50000000E+00*_ke <= _ki && _ex2 && _fx_2 || _ke >= 2.50000000E+00*_ki && _ex3 && _fx_3); + _r2 = 2.50000000E+00*_kek <= _kik && _exkm && _fx_5 && _kei && _ex_ck; + _r3 = 2.50000000E+00*_kem <= _kim && _exkm && _fx_4 && _mei && _ex_em; + if (_r1) { + _TMP58 = _TMP49; + } else { + if (_r2) { + _TMP59 = _TMP52; + } else { + if (_r3) { + _TMP60 = _TMP55; + } else { + _TMP60 = _TMP4.xyz; + } + _TMP59 = _TMP60; + } + _TMP58 = _TMP59; + } + _ret_0 = vec4(_TMP58.x, _TMP58.y, _TMP58.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5-plus-crt.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5-plus-crt.glsl new file mode 100644 index 000000000..fcaef8c8a --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5-plus-crt.glsl @@ -0,0 +1,675 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(_ps.x, 0.00000000E+00); + _OUT._t1.zw = vec2(0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color1; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP37; +vec3 _TMP55; +float _TMP54; +float _TMP53; +float _TMP52; +vec3 _TMP29; +vec3 _TMP31; +vec3 _TMP33; +vec3 _TMP35; +vec3 _TMP36; +vec3 _TMP34; +vec3 _TMP32; +vec3 _TMP30; +vec4 _TMP22; +vec4 _TMP21; +vec3 _TMP46; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0088; +vec2 _c0090; +vec2 _c0092; +vec2 _c0094; +vec2 _c0096; +vec2 _c0100; +vec2 _c0102; +vec2 _c0104; +vec2 _c0106; +vec2 _c0108; +vec2 _c0110; +vec2 _c0112; +vec2 _c0114; +vec2 _c0116; +vec2 _c0118; +vec2 _c0120; +vec2 _c0122; +vec2 _c0124; +vec2 _c0126; +vec2 _c0128; +vec2 _c0130; +vec3 _r0176; +vec3 _r0186; +vec3 _r0196; +vec3 _r0206; +vec3 _r0218; +vec3 _r0228; +vec3 _r0238; +vec3 _r0248; +vec3 _r0260; +vec3 _r0270; +vec3 _r0280; +vec3 _r0290; +vec3 _r0302; +vec3 _r0312; +vec3 _r0322; +vec3 _r0332; +vec3 _r0344; +vec3 _r0354; +vec3 _r0364; +vec3 _r0374; +vec3 _r0386; +vec3 _r0396; +vec3 _r0406; +vec3 _r0416; +vec3 _r0428; +vec3 _r0438; +vec3 _r0448; +vec3 _r0458; +vec3 _r0470; +vec3 _r0480; +vec3 _r0490; +vec3 _r0500; +vec3 _r0722; +vec3 _r0732; +vec3 _r0742; +vec3 _r0752; +vec3 _r0806; +vec3 _r0816; +vec3 _r0826; +vec3 _r0836; +vec3 _r0932; +vec3 _r0942; +vec3 _r0952; +vec3 _r0962; +vec3 _r0974; +vec3 _r0984; +vec3 _r0994; +vec3 _r1004; +vec4 _TMP1015; +vec4 _a1018; +vec4 _TMP1019; +vec4 _a1022; +vec4 _TMP1023; +vec4 _a1026; +vec4 _TMP1027; +vec4 _a1030; +vec4 _TMP1031; +vec4 _a1034; +vec4 _TMP1037; +vec4 _a1040; +vec4 _TMP1041; +vec4 _a1044; +vec4 _TMP1045; +vec4 _a1048; +vec4 _TMP1049; +vec4 _a1052; +vec4 _TMP1053; +vec4 _a1056; +vec4 _TMP1057; +vec4 _a1060; +vec4 _TMP1061; +vec4 _a1064; +vec4 _TMP1065; +vec4 _a1068; +vec4 _TMP1069; +vec4 _a1072; +vec4 _TMP1073; +vec4 _a1076; +vec4 _TMP1077; +vec4 _a1080; +vec3 _TMP1105; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + vec2 _fp; + vec4 _b2; + vec4 _c2; + vec4 _d2; + vec4 _e1; + vec4 _f1; + vec4 _g1; + vec4 _h1; + vec4 _i; + vec4 _i4; + vec4 _i5; + vec4 _h5; + vec4 _f4; + vec3 _color; + float _ddy; + float _v_weight_00; + vec3 _coords10; + vec3 _colorNB; + float _v_weight_10; + _x0088 = TEX0.xy*TextureSize; + _fp = fract(_x0088); + _c0090 = (TEX0.xy - TEX1.xy) - TEX1.zw; + _TMP0 = COMPAT_TEXTURE(Texture, _c0090); + _c0092 = TEX0.xy - TEX1.zw; + _TMP1 = COMPAT_TEXTURE(Texture, _c0092); + _c0094 = (TEX0.xy + TEX1.xy) - TEX1.zw; + _TMP2 = COMPAT_TEXTURE(Texture, _c0094); + _c0096 = TEX0.xy - TEX1.xy; + _TMP3 = COMPAT_TEXTURE(Texture, _c0096); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0100 = TEX0.xy + TEX1.xy; + _TMP5 = COMPAT_TEXTURE(Texture, _c0100); + _c0102 = (TEX0.xy - TEX1.xy) + TEX1.zw; + _TMP6 = COMPAT_TEXTURE(Texture, _c0102); + _c0104 = TEX0.xy + TEX1.zw; + _TMP7 = COMPAT_TEXTURE(Texture, _c0104); + _c0106 = TEX0.xy + TEX1.xy + TEX1.zw; + _TMP8 = COMPAT_TEXTURE(Texture, _c0106); + _c0108 = (TEX0.xy - TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP9 = COMPAT_TEXTURE(Texture, _c0108); + _c0110 = (TEX0.xy + TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP10 = COMPAT_TEXTURE(Texture, _c0110); + _c0112 = (TEX0.xy - 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP11 = COMPAT_TEXTURE(Texture, _c0112); + _c0114 = (TEX0.xy - 2.00000000E+00*TEX1.xy) + TEX1.zw; + _TMP12 = COMPAT_TEXTURE(Texture, _c0114); + _c0116 = (TEX0.xy + 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP13 = COMPAT_TEXTURE(Texture, _c0116); + _c0118 = TEX0.xy + 2.00000000E+00*TEX1.xy + TEX1.zw; + _TMP14 = COMPAT_TEXTURE(Texture, _c0118); + _c0120 = (TEX0.xy - TEX1.xy) + 2.00000000E+00*TEX1.zw; + _TMP15 = COMPAT_TEXTURE(Texture, _c0120); + _c0122 = TEX0.xy + TEX1.xy + 2.00000000E+00*TEX1.zw; + _TMP16 = COMPAT_TEXTURE(Texture, _c0122); + _c0124 = TEX0.xy - 2.00000000E+00*TEX1.zw; + _TMP17 = COMPAT_TEXTURE(Texture, _c0124); + _c0126 = TEX0.xy - 2.00000000E+00*TEX1.xy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0126); + _c0128 = TEX0.xy + 2.00000000E+00*TEX1.zw; + _TMP19 = COMPAT_TEXTURE(Texture, _c0128); + _c0130 = TEX0.xy + 2.00000000E+00*TEX1.xy; + _TMP20 = COMPAT_TEXTURE(Texture, _c0130); + _r0176.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0176.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0176.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP40 = abs(_r0176); + _r0186.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0186.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0186.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP42 = abs(_r0186); + _r0196.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0196.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0196.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP44 = abs(_r0196); + _r0206.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0206.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0206.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP46 = abs(_r0206); + _b2 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0218.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0218.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0218.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP40 = abs(_r0218); + _r0228.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0228.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0228.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP42 = abs(_r0228); + _r0238.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0238.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0238.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP44 = abs(_r0238); + _r0248.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0248.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0248.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP46 = abs(_r0248); + _c2 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0260.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0260.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0260.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP40 = abs(_r0260); + _r0270.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0270.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0270.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP42 = abs(_r0270); + _r0280.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0280.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0280.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP44 = abs(_r0280); + _r0290.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0290.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0290.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP46 = abs(_r0290); + _d2 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0302.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0302.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0302.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP40 = abs(_r0302); + _r0312.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0312.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0312.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP42 = abs(_r0312); + _r0322.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0322.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0322.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP44 = abs(_r0322); + _r0332.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0332.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0332.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP46 = abs(_r0332); + _e1 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0344.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0344.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0344.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP40 = abs(_r0344); + _r0354.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0354.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0354.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP42 = abs(_r0354); + _r0364.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0364.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0364.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP44 = abs(_r0364); + _r0374.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0374.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0374.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP46 = abs(_r0374); + _f1 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0386.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0386.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0386.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP40 = abs(_r0386); + _r0396.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0396.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0396.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP42 = abs(_r0396); + _r0406.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0406.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0406.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP44 = abs(_r0406); + _r0416.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0416.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0416.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP46 = abs(_r0416); + _g1 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0428.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0428.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0428.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP40 = abs(_r0428); + _r0438.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0438.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0438.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP42 = abs(_r0438); + _r0448.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0448.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0448.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP44 = abs(_r0448); + _r0458.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0458.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0458.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP46 = abs(_r0458); + _h1 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0470.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0470.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0470.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP40 = abs(_r0470); + _r0480.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0480.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0480.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP42 = abs(_r0480); + _r0490.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0490.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0490.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP44 = abs(_r0490); + _r0500.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0500.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0500.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP46 = abs(_r0500); + _i = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0722.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP14.xyz); + _r0722.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP14.xyz); + _r0722.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP14.xyz); + _TMP40 = abs(_r0722); + _r0732.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP10.xyz); + _r0732.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP10.xyz); + _r0732.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP10.xyz); + _TMP42 = abs(_r0732); + _r0742.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP11.xyz); + _r0742.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP11.xyz); + _r0742.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP11.xyz); + _TMP44 = abs(_r0742); + _r0752.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0752.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP15.xyz); + _r0752.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP15.xyz); + _TMP46 = abs(_r0752); + _i4 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0806.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP16.xyz); + _r0806.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP16.xyz); + _r0806.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP16.xyz); + _TMP40 = abs(_r0806); + _r0816.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP13.xyz); + _r0816.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP13.xyz); + _r0816.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP13.xyz); + _TMP42 = abs(_r0816); + _r0826.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP9.xyz); + _r0826.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP9.xyz); + _r0826.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP9.xyz); + _TMP44 = abs(_r0826); + _r0836.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0836.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP12.xyz); + _r0836.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP12.xyz); + _TMP46 = abs(_r0836); + _i5 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0932.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0932.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r0932.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP40 = abs(_r0932); + _r0942.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0942.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0942.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP42 = abs(_r0942); + _r0952.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0952.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0952.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP44 = abs(_r0952); + _r0962.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0962.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0962.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP46 = abs(_r0962); + _h5 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _r0974.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0974.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0974.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP40 = abs(_r0974); + _r0984.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0984.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0984.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP42 = abs(_r0984); + _r0994.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0994.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0994.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP44 = abs(_r0994); + _r1004.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r1004.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r1004.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP46 = abs(_r1004); + _f4 = vec4(_TMP40.x, _TMP42.x, _TMP44.x, _TMP46.x); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _interp_restriction_lv1 = bvec4(_e1.x != _f1.x && _e1.x != _h1.x, _e1.y != _f1.y && _e1.y != _h1.y, _e1.z != _f1.z && _e1.z != _h1.z, _e1.w != _f1.w && _e1.w != _h1.w); + _interp_restriction_lv2_left = bvec4(_e1.x != _g1.x && _d2.x != _g1.x, _e1.y != _g1.y && _d2.y != _g1.y, _e1.z != _g1.z && _d2.z != _g1.z, _e1.w != _g1.w && _d2.w != _g1.w); + _interp_restriction_lv2_up = bvec4(_e1.x != _c2.x && _b2.x != _c2.x, _e1.y != _c2.y && _b2.y != _c2.y, _e1.z != _c2.z && _b2.z != _c2.z, _e1.w != _c2.w && _b2.w != _c2.w); + _a1018 = _e1 - _c2; + _TMP1015 = abs(_a1018); + _a1022 = _e1 - _g1; + _TMP1019 = abs(_a1022); + _a1026 = _i - _h5; + _TMP1023 = abs(_a1026); + _a1030 = _i - _f4; + _TMP1027 = abs(_a1030); + _a1034 = _h1 - _f1; + _TMP1031 = abs(_a1034); + _TMP21 = _TMP1015 + _TMP1019 + _TMP1023 + _TMP1027 + 4.00000000E+00*_TMP1031; + _a1040 = _h1 - _d2; + _TMP1037 = abs(_a1040); + _a1044 = _h1 - _i5; + _TMP1041 = abs(_a1044); + _a1048 = _f1 - _i4; + _TMP1045 = abs(_a1048); + _a1052 = _f1 - _b2; + _TMP1049 = abs(_a1052); + _a1056 = _e1 - _i; + _TMP1053 = abs(_a1056); + _TMP22 = _TMP1037 + _TMP1041 + _TMP1045 + _TMP1049 + 4.00000000E+00*_TMP1053; + _edr = bvec4(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z, _TMP21.w < _TMP22.w && _interp_restriction_lv1.w); + _a1060 = _f1 - _g1; + _TMP1057 = abs(_a1060); + _a1064 = _h1 - _c2; + _TMP1061 = abs(_a1064); + _edr_left = bvec4((2.00000000E+00*_TMP1057).x <= _TMP1061.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP1057).y <= _TMP1061.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP1057).z <= _TMP1061.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP1057).w <= _TMP1061.w && _interp_restriction_lv2_left.w); + _a1068 = _f1 - _g1; + _TMP1065 = abs(_a1068); + _a1072 = _h1 - _c2; + _TMP1069 = abs(_a1072); + _edr_up = bvec4(_TMP1065.x >= (2.00000000E+00*_TMP1069).x && _interp_restriction_lv2_up.x, _TMP1065.y >= (2.00000000E+00*_TMP1069).y && _interp_restriction_lv2_up.y, _TMP1065.z >= (2.00000000E+00*_TMP1069).z && _interp_restriction_lv2_up.z, _TMP1065.w >= (2.00000000E+00*_TMP1069).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && _fx_left.x || _edr_up.x && _fx_up.x), _edr.y && (_fx.y || _edr_left.y && _fx_left.y || _edr_up.y && _fx_up.y), _edr.z && (_fx.z || _edr_left.z && _fx_left.z || _edr_up.z && _fx_up.z), _edr.w && (_fx.w || _edr_left.w && _fx_left.w || _edr_up.w && _fx_up.w)); + _a1076 = _e1 - _f1; + _TMP1073 = abs(_a1076); + _a1080 = _e1 - _h1; + _TMP1077 = abs(_a1080); + _px = bvec4(_TMP1073.x <= _TMP1077.x, _TMP1073.y <= _TMP1077.y, _TMP1073.z <= _TMP1077.z, _TMP1073.w <= _TMP1077.w); + if (_nc.x) { + if (_px.x) { + _TMP30 = _TMP5.xyz; + } else { + _TMP30 = _TMP7.xyz; + } + _TMP29 = _TMP30; + } else { + if (_nc.y) { + if (_px.y) { + _TMP32 = _TMP1.xyz; + } else { + _TMP32 = _TMP5.xyz; + } + _TMP31 = _TMP32; + } else { + if (_nc.z) { + if (_px.z) { + _TMP34 = _TMP3.xyz; + } else { + _TMP34 = _TMP1.xyz; + } + _TMP33 = _TMP34; + } else { + if (_nc.w) { + if (_px.w) { + _TMP36 = _TMP7.xyz; + } else { + _TMP36 = _TMP3.xyz; + } + _TMP35 = _TMP36; + } else { + _TMP35 = _TMP4.xyz; + } + _TMP33 = _TMP35; + } + _TMP31 = _TMP33; + } + _TMP29 = _TMP31; + } + _TMP52 = pow(_TMP29.x, 2.40000010E+00); + _TMP53 = pow(_TMP29.y, 2.40000010E+00); + _TMP54 = pow(_TMP29.z, 2.40000010E+00); + _color = vec3(_TMP52, _TMP53, _TMP54); + _ddy = _fp.y - 5.00000000E-01; + _v_weight_00 = _ddy/5.00000000E-01; + if (_v_weight_00 > 1.00000000E+00) { + _v_weight_00 = 1.00000000E+00; + } + _v_weight_00 = 1.00000000E+00 - _v_weight_00*_v_weight_00; + _v_weight_00 = _v_weight_00*_v_weight_00; + _color = _color*vec3(_v_weight_00, _v_weight_00, _v_weight_00); + if (_ddy > 0.00000000E+00) { + _coords10 = _TMP7.xyz; + _ddy = 1.00000000E+00 - _ddy; + } else { + _coords10 = _TMP1.xyz; + _ddy = 1.00000000E+00 + _ddy; + } + _TMP52 = pow(_coords10.x, 2.40000010E+00); + _TMP53 = pow(_coords10.y, 2.40000010E+00); + _TMP54 = pow(_coords10.z, 2.40000010E+00); + _colorNB = vec3(_TMP52, _TMP53, _TMP54); + _v_weight_10 = _ddy/5.00000000E-01; + if (_v_weight_10 > 1.00000000E+00) { + _v_weight_10 = 1.00000000E+00; + } + _v_weight_10 = 1.00000000E+00 - _v_weight_10*_v_weight_10; + _v_weight_10 = _v_weight_10*_v_weight_10; + _color = _color + _colorNB*vec3(_v_weight_10, _v_weight_10, _v_weight_10); + _color = _color*vec3( 1.45000005E+00, 1.45000005E+00, 1.45000005E+00); + _TMP52 = pow(_color.x, 4.54545438E-01); + _TMP53 = pow(_color.y, 4.54545438E-01); + _TMP54 = pow(_color.z, 4.54545438E-01); + _TMP37 = vec3(_TMP52, _TMP53, _TMP54); + _TMP55 = min(vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _TMP37); + _TMP1105 = max(vec3( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP55); + _ret_0 = vec4(_TMP1105.x, _TMP1105.y, _TMP1105.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5.glsl new file mode 100644 index 000000000..9ce3b6b78 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5.glsl @@ -0,0 +1,626 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0007; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0007 = VertexCoord.x*MVPMatrix[0]; + _r0007 = _r0007 + VertexCoord.y*MVPMatrix[1]; + _r0007 = _r0007 + VertexCoord.z*MVPMatrix[2]; + _r0007 = _r0007 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(_ps.x, 0.00000000E+00); + _OUT._t1.zw = vec2(0.00000000E+00, _ps.y); + _ret_0._position1 = _r0007; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0007; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP29; +vec3 _TMP31; +vec3 _TMP33; +vec3 _TMP35; +vec3 _TMP36; +vec3 _TMP34; +vec3 _TMP32; +vec3 _TMP30; +vec4 _TMP22; +vec4 _TMP21; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec3 _TMP38; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0081; +vec2 _c0083; +vec2 _c0085; +vec2 _c0087; +vec2 _c0089; +vec2 _c0093; +vec2 _c0095; +vec2 _c0097; +vec2 _c0099; +vec2 _c0101; +vec2 _c0103; +vec2 _c0105; +vec2 _c0107; +vec2 _c0109; +vec2 _c0111; +vec2 _c0113; +vec2 _c0115; +vec2 _c0117; +vec2 _c0119; +vec2 _c0121; +vec2 _c0123; +vec3 _r0169; +vec3 _r0179; +vec3 _r0189; +vec3 _r0199; +vec3 _r0211; +vec3 _r0221; +vec3 _r0231; +vec3 _r0241; +vec3 _r0253; +vec3 _r0263; +vec3 _r0273; +vec3 _r0283; +vec3 _r0295; +vec3 _r0305; +vec3 _r0315; +vec3 _r0325; +vec3 _r0337; +vec3 _r0347; +vec3 _r0357; +vec3 _r0367; +vec3 _r0379; +vec3 _r0389; +vec3 _r0399; +vec3 _r0409; +vec3 _r0421; +vec3 _r0431; +vec3 _r0441; +vec3 _r0451; +vec3 _r0463; +vec3 _r0473; +vec3 _r0483; +vec3 _r0493; +vec3 _r0715; +vec3 _r0725; +vec3 _r0735; +vec3 _r0745; +vec3 _r0799; +vec3 _r0809; +vec3 _r0819; +vec3 _r0829; +vec3 _r0925; +vec3 _r0935; +vec3 _r0945; +vec3 _r0955; +vec3 _r0967; +vec3 _r0977; +vec3 _r0987; +vec3 _r0997; +vec4 _TMP1008; +vec4 _a1011; +vec4 _TMP1012; +vec4 _a1015; +vec4 _TMP1016; +vec4 _a1019; +vec4 _TMP1020; +vec4 _a1023; +vec4 _TMP1024; +vec4 _a1027; +vec4 _TMP1030; +vec4 _a1033; +vec4 _TMP1034; +vec4 _a1037; +vec4 _TMP1038; +vec4 _a1041; +vec4 _TMP1042; +vec4 _a1045; +vec4 _TMP1046; +vec4 _a1049; +vec4 _TMP1050; +vec4 _a1053; +vec4 _TMP1054; +vec4 _a1057; +vec4 _TMP1058; +vec4 _a1061; +vec4 _TMP1062; +vec4 _a1065; +vec4 _TMP1066; +vec4 _a1069; +vec4 _TMP1070; +vec4 _a1073; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + vec2 _fp; + vec4 _b2; + vec4 _c2; + vec4 _d2; + vec4 _e1; + vec4 _f1; + vec4 _g1; + vec4 _h1; + vec4 _i; + vec4 _i4; + vec4 _i5; + vec4 _h5; + vec4 _f4; + _x0081 = TEX0.xy*TextureSize; + _fp = fract(_x0081); + _c0083 = (TEX0.xy - TEX1.xy) - TEX1.zw; + _TMP0 = COMPAT_TEXTURE(Texture, _c0083); + _c0085 = TEX0.xy - TEX1.zw; + _TMP1 = COMPAT_TEXTURE(Texture, _c0085); + _c0087 = (TEX0.xy + TEX1.xy) - TEX1.zw; + _TMP2 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = TEX0.xy - TEX1.xy; + _TMP3 = COMPAT_TEXTURE(Texture, _c0089); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0093 = TEX0.xy + TEX1.xy; + _TMP5 = COMPAT_TEXTURE(Texture, _c0093); + _c0095 = (TEX0.xy - TEX1.xy) + TEX1.zw; + _TMP6 = COMPAT_TEXTURE(Texture, _c0095); + _c0097 = TEX0.xy + TEX1.zw; + _TMP7 = COMPAT_TEXTURE(Texture, _c0097); + _c0099 = TEX0.xy + TEX1.xy + TEX1.zw; + _TMP8 = COMPAT_TEXTURE(Texture, _c0099); + _c0101 = (TEX0.xy - TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP9 = COMPAT_TEXTURE(Texture, _c0101); + _c0103 = (TEX0.xy + TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP10 = COMPAT_TEXTURE(Texture, _c0103); + _c0105 = (TEX0.xy - 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP11 = COMPAT_TEXTURE(Texture, _c0105); + _c0107 = (TEX0.xy - 2.00000000E+00*TEX1.xy) + TEX1.zw; + _TMP12 = COMPAT_TEXTURE(Texture, _c0107); + _c0109 = (TEX0.xy + 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP13 = COMPAT_TEXTURE(Texture, _c0109); + _c0111 = TEX0.xy + 2.00000000E+00*TEX1.xy + TEX1.zw; + _TMP14 = COMPAT_TEXTURE(Texture, _c0111); + _c0113 = (TEX0.xy - TEX1.xy) + 2.00000000E+00*TEX1.zw; + _TMP15 = COMPAT_TEXTURE(Texture, _c0113); + _c0115 = TEX0.xy + TEX1.xy + 2.00000000E+00*TEX1.zw; + _TMP16 = COMPAT_TEXTURE(Texture, _c0115); + _c0117 = TEX0.xy - 2.00000000E+00*TEX1.zw; + _TMP17 = COMPAT_TEXTURE(Texture, _c0117); + _c0119 = TEX0.xy - 2.00000000E+00*TEX1.xy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0119); + _c0121 = TEX0.xy + 2.00000000E+00*TEX1.zw; + _TMP19 = COMPAT_TEXTURE(Texture, _c0121); + _c0123 = TEX0.xy + 2.00000000E+00*TEX1.xy; + _TMP20 = COMPAT_TEXTURE(Texture, _c0123); + _r0169.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0169.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP1.xyz); + _r0169.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP1.xyz); + _TMP38 = abs(_r0169); + _r0179.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0179.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP3.xyz); + _r0179.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP3.xyz); + _TMP40 = abs(_r0179); + _r0189.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0189.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP7.xyz); + _r0189.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP7.xyz); + _TMP42 = abs(_r0189); + _r0199.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0199.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP5.xyz); + _r0199.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP5.xyz); + _TMP44 = abs(_r0199); + _b2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0211.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0211.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP2.xyz); + _r0211.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP2.xyz); + _TMP38 = abs(_r0211); + _r0221.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0221.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP0.xyz); + _r0221.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP0.xyz); + _TMP40 = abs(_r0221); + _r0231.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0231.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP6.xyz); + _r0231.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP6.xyz); + _TMP42 = abs(_r0231); + _r0241.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0241.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP8.xyz); + _r0241.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP8.xyz); + _TMP44 = abs(_r0241); + _c2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0253.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0253.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP3.xyz); + _r0253.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP3.xyz); + _TMP38 = abs(_r0253); + _r0263.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0263.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP7.xyz); + _r0263.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP7.xyz); + _TMP40 = abs(_r0263); + _r0273.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0273.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP5.xyz); + _r0273.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP5.xyz); + _TMP42 = abs(_r0273); + _r0283.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0283.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP1.xyz); + _r0283.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP1.xyz); + _TMP44 = abs(_r0283); + _d2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0295.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0295.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP4.xyz); + _r0295.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP4.xyz); + _TMP38 = abs(_r0295); + _r0305.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0305.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP4.xyz); + _r0305.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP4.xyz); + _TMP40 = abs(_r0305); + _r0315.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0315.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP4.xyz); + _r0315.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP4.xyz); + _TMP42 = abs(_r0315); + _r0325.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0325.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP4.xyz); + _r0325.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP4.xyz); + _TMP44 = abs(_r0325); + _e1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0337.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0337.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP5.xyz); + _r0337.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP5.xyz); + _TMP38 = abs(_r0337); + _r0347.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0347.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP1.xyz); + _r0347.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP1.xyz); + _TMP40 = abs(_r0347); + _r0357.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0357.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP3.xyz); + _r0357.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP3.xyz); + _TMP42 = abs(_r0357); + _r0367.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0367.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP7.xyz); + _r0367.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP7.xyz); + _TMP44 = abs(_r0367); + _f1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0379.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0379.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP6.xyz); + _r0379.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP6.xyz); + _TMP38 = abs(_r0379); + _r0389.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0389.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP8.xyz); + _r0389.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP8.xyz); + _TMP40 = abs(_r0389); + _r0399.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0399.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP2.xyz); + _r0399.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP2.xyz); + _TMP42 = abs(_r0399); + _r0409.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0409.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP0.xyz); + _r0409.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP0.xyz); + _TMP44 = abs(_r0409); + _g1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0421.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0421.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP7.xyz); + _r0421.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP7.xyz); + _TMP38 = abs(_r0421); + _r0431.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0431.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP5.xyz); + _r0431.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP5.xyz); + _TMP40 = abs(_r0431); + _r0441.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0441.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP1.xyz); + _r0441.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP1.xyz); + _TMP42 = abs(_r0441); + _r0451.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0451.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP3.xyz); + _r0451.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP3.xyz); + _TMP44 = abs(_r0451); + _h1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0463.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0463.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP8.xyz); + _r0463.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP8.xyz); + _TMP38 = abs(_r0463); + _r0473.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0473.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP2.xyz); + _r0473.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP2.xyz); + _TMP40 = abs(_r0473); + _r0483.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0483.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP0.xyz); + _r0483.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP0.xyz); + _TMP42 = abs(_r0483); + _r0493.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0493.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP6.xyz); + _r0493.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP6.xyz); + _TMP44 = abs(_r0493); + _i = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0715.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP14.xyz); + _r0715.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP14.xyz); + _r0715.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP14.xyz); + _TMP38 = abs(_r0715); + _r0725.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP10.xyz); + _r0725.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP10.xyz); + _r0725.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP10.xyz); + _TMP40 = abs(_r0725); + _r0735.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP11.xyz); + _r0735.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP11.xyz); + _r0735.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP11.xyz); + _TMP42 = abs(_r0735); + _r0745.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0745.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP15.xyz); + _r0745.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP15.xyz); + _TMP44 = abs(_r0745); + _i4 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0799.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP16.xyz); + _r0799.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP16.xyz); + _r0799.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP16.xyz); + _TMP38 = abs(_r0799); + _r0809.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP13.xyz); + _r0809.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP13.xyz); + _r0809.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP13.xyz); + _TMP40 = abs(_r0809); + _r0819.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP9.xyz); + _r0819.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP9.xyz); + _r0819.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP9.xyz); + _TMP42 = abs(_r0819); + _r0829.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0829.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP12.xyz); + _r0829.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP12.xyz); + _TMP44 = abs(_r0829); + _i5 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0925.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0925.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP19.xyz); + _r0925.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP19.xyz); + _TMP38 = abs(_r0925); + _r0935.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0935.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP20.xyz); + _r0935.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP20.xyz); + _TMP40 = abs(_r0935); + _r0945.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0945.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP17.xyz); + _r0945.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP17.xyz); + _TMP42 = abs(_r0945); + _r0955.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0955.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP18.xyz); + _r0955.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP18.xyz); + _TMP44 = abs(_r0955); + _h5 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0967.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0967.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP20.xyz); + _r0967.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP20.xyz); + _TMP38 = abs(_r0967); + _r0977.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0977.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP17.xyz); + _r0977.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP17.xyz); + _TMP40 = abs(_r0977); + _r0987.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0987.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP18.xyz); + _r0987.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP18.xyz); + _TMP42 = abs(_r0987); + _r0997.x = dot(vec3( 1.43520002E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0997.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.50000000E+00), _TMP19.xyz); + _r0997.z = dot(vec3( 3.00000000E+00, -2.51399994E+00, -4.86000001E-01), _TMP19.xyz); + _TMP44 = abs(_r0997); + _f4 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _interp_restriction_lv1 = bvec4(_e1.x != _f1.x && _e1.x != _h1.x, _e1.y != _f1.y && _e1.y != _h1.y, _e1.z != _f1.z && _e1.z != _h1.z, _e1.w != _f1.w && _e1.w != _h1.w); + _interp_restriction_lv2_left = bvec4(_e1.x != _g1.x && _d2.x != _g1.x, _e1.y != _g1.y && _d2.y != _g1.y, _e1.z != _g1.z && _d2.z != _g1.z, _e1.w != _g1.w && _d2.w != _g1.w); + _interp_restriction_lv2_up = bvec4(_e1.x != _c2.x && _b2.x != _c2.x, _e1.y != _c2.y && _b2.y != _c2.y, _e1.z != _c2.z && _b2.z != _c2.z, _e1.w != _c2.w && _b2.w != _c2.w); + _a1011 = _e1 - _c2; + _TMP1008 = abs(_a1011); + _a1015 = _e1 - _g1; + _TMP1012 = abs(_a1015); + _a1019 = _i - _h5; + _TMP1016 = abs(_a1019); + _a1023 = _i - _f4; + _TMP1020 = abs(_a1023); + _a1027 = _h1 - _f1; + _TMP1024 = abs(_a1027); + _TMP21 = _TMP1008 + _TMP1012 + _TMP1016 + _TMP1020 + 4.00000000E+00*_TMP1024; + _a1033 = _h1 - _d2; + _TMP1030 = abs(_a1033); + _a1037 = _h1 - _i5; + _TMP1034 = abs(_a1037); + _a1041 = _f1 - _i4; + _TMP1038 = abs(_a1041); + _a1045 = _f1 - _b2; + _TMP1042 = abs(_a1045); + _a1049 = _e1 - _i; + _TMP1046 = abs(_a1049); + _TMP22 = _TMP1030 + _TMP1034 + _TMP1038 + _TMP1042 + 4.00000000E+00*_TMP1046; + _edr = bvec4(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z, _TMP21.w < _TMP22.w && _interp_restriction_lv1.w); + _a1053 = _f1 - _g1; + _TMP1050 = abs(_a1053); + _a1057 = _h1 - _c2; + _TMP1054 = abs(_a1057); + _edr_left = bvec4((2.00000000E+00*_TMP1050).x <= _TMP1054.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP1050).y <= _TMP1054.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP1050).z <= _TMP1054.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP1050).w <= _TMP1054.w && _interp_restriction_lv2_left.w); + _a1061 = _f1 - _g1; + _TMP1058 = abs(_a1061); + _a1065 = _h1 - _c2; + _TMP1062 = abs(_a1065); + _edr_up = bvec4(_TMP1058.x >= (2.00000000E+00*_TMP1062).x && _interp_restriction_lv2_up.x, _TMP1058.y >= (2.00000000E+00*_TMP1062).y && _interp_restriction_lv2_up.y, _TMP1058.z >= (2.00000000E+00*_TMP1062).z && _interp_restriction_lv2_up.z, _TMP1058.w >= (2.00000000E+00*_TMP1062).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && _fx_left.x || _edr_up.x && _fx_up.x), _edr.y && (_fx.y || _edr_left.y && _fx_left.y || _edr_up.y && _fx_up.y), _edr.z && (_fx.z || _edr_left.z && _fx_left.z || _edr_up.z && _fx_up.z), _edr.w && (_fx.w || _edr_left.w && _fx_left.w || _edr_up.w && _fx_up.w)); + _a1069 = _e1 - _f1; + _TMP1066 = abs(_a1069); + _a1073 = _e1 - _h1; + _TMP1070 = abs(_a1073); + _px = bvec4(_TMP1066.x <= _TMP1070.x, _TMP1066.y <= _TMP1070.y, _TMP1066.z <= _TMP1070.z, _TMP1066.w <= _TMP1070.w); + if (_nc.x) { + if (_px.x) { + _TMP30 = _TMP5.xyz; + } else { + _TMP30 = _TMP7.xyz; + } + _TMP29 = _TMP30; + } else { + if (_nc.y) { + if (_px.y) { + _TMP32 = _TMP1.xyz; + } else { + _TMP32 = _TMP5.xyz; + } + _TMP31 = _TMP32; + } else { + if (_nc.z) { + if (_px.z) { + _TMP34 = _TMP3.xyz; + } else { + _TMP34 = _TMP1.xyz; + } + _TMP33 = _TMP34; + } else { + if (_nc.w) { + if (_px.w) { + _TMP36 = _TMP7.xyz; + } else { + _TMP36 = _TMP3.xyz; + } + _TMP35 = _TMP36; + } else { + _TMP35 = _TMP4.xyz; + } + _TMP33 = _TMP35; + } + _TMP31 = _TMP33; + } + _TMP29 = _TMP31; + } + _ret_0 = vec4(_TMP29.x, _TMP29.y, _TMP29.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5a.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5a.glsl new file mode 100644 index 000000000..34acf7445 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.5a.glsl @@ -0,0 +1,626 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(_ps.x, 0.00000000E+00); + _OUT._t1.zw = vec2(0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP29; +vec3 _TMP31; +vec3 _TMP33; +vec3 _TMP35; +vec3 _TMP36; +vec3 _TMP34; +vec3 _TMP32; +vec3 _TMP30; +vec4 _TMP22; +vec4 _TMP21; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec3 _TMP38; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0082; +vec2 _c0084; +vec2 _c0086; +vec2 _c0088; +vec2 _c0090; +vec2 _c0094; +vec2 _c0096; +vec2 _c0098; +vec2 _c0100; +vec2 _c0102; +vec2 _c0104; +vec2 _c0106; +vec2 _c0108; +vec2 _c0110; +vec2 _c0112; +vec2 _c0114; +vec2 _c0116; +vec2 _c0118; +vec2 _c0120; +vec2 _c0122; +vec2 _c0124; +vec3 _r0170; +vec3 _r0180; +vec3 _r0190; +vec3 _r0200; +vec3 _r0212; +vec3 _r0222; +vec3 _r0232; +vec3 _r0242; +vec3 _r0254; +vec3 _r0264; +vec3 _r0274; +vec3 _r0284; +vec3 _r0296; +vec3 _r0306; +vec3 _r0316; +vec3 _r0326; +vec3 _r0338; +vec3 _r0348; +vec3 _r0358; +vec3 _r0368; +vec3 _r0380; +vec3 _r0390; +vec3 _r0400; +vec3 _r0410; +vec3 _r0422; +vec3 _r0432; +vec3 _r0442; +vec3 _r0452; +vec3 _r0464; +vec3 _r0474; +vec3 _r0484; +vec3 _r0494; +vec3 _r0716; +vec3 _r0726; +vec3 _r0736; +vec3 _r0746; +vec3 _r0800; +vec3 _r0810; +vec3 _r0820; +vec3 _r0830; +vec3 _r0926; +vec3 _r0936; +vec3 _r0946; +vec3 _r0956; +vec3 _r0968; +vec3 _r0978; +vec3 _r0988; +vec3 _r0998; +vec4 _TMP1009; +vec4 _a1012; +vec4 _TMP1013; +vec4 _a1016; +vec4 _TMP1017; +vec4 _a1020; +vec4 _TMP1021; +vec4 _a1024; +vec4 _TMP1025; +vec4 _a1028; +vec4 _TMP1031; +vec4 _a1034; +vec4 _TMP1035; +vec4 _a1038; +vec4 _TMP1039; +vec4 _a1042; +vec4 _TMP1043; +vec4 _a1046; +vec4 _TMP1047; +vec4 _a1050; +vec4 _TMP1051; +vec4 _a1054; +vec4 _TMP1055; +vec4 _a1058; +vec4 _TMP1059; +vec4 _a1062; +vec4 _TMP1063; +vec4 _a1066; +vec4 _TMP1067; +vec4 _a1070; +vec4 _TMP1071; +vec4 _a1074; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + vec2 _fp; + vec4 _b2; + vec4 _c2; + vec4 _d2; + vec4 _e1; + vec4 _f1; + vec4 _g1; + vec4 _h1; + vec4 _i; + vec4 _i4; + vec4 _i5; + vec4 _h5; + vec4 _f4; + _x0082 = TEX0.xy*TextureSize; + _fp = fract(_x0082); + _c0084 = (TEX0.xy - TEX1.xy) - TEX1.zw; + _TMP0 = COMPAT_TEXTURE(Texture, _c0084); + _c0086 = TEX0.xy - TEX1.zw; + _TMP1 = COMPAT_TEXTURE(Texture, _c0086); + _c0088 = (TEX0.xy + TEX1.xy) - TEX1.zw; + _TMP2 = COMPAT_TEXTURE(Texture, _c0088); + _c0090 = TEX0.xy - TEX1.xy; + _TMP3 = COMPAT_TEXTURE(Texture, _c0090); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0094 = TEX0.xy + TEX1.xy; + _TMP5 = COMPAT_TEXTURE(Texture, _c0094); + _c0096 = (TEX0.xy - TEX1.xy) + TEX1.zw; + _TMP6 = COMPAT_TEXTURE(Texture, _c0096); + _c0098 = TEX0.xy + TEX1.zw; + _TMP7 = COMPAT_TEXTURE(Texture, _c0098); + _c0100 = TEX0.xy + TEX1.xy + TEX1.zw; + _TMP8 = COMPAT_TEXTURE(Texture, _c0100); + _c0102 = (TEX0.xy - TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP9 = COMPAT_TEXTURE(Texture, _c0102); + _c0104 = (TEX0.xy + TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP10 = COMPAT_TEXTURE(Texture, _c0104); + _c0106 = (TEX0.xy - 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP11 = COMPAT_TEXTURE(Texture, _c0106); + _c0108 = (TEX0.xy - 2.00000000E+00*TEX1.xy) + TEX1.zw; + _TMP12 = COMPAT_TEXTURE(Texture, _c0108); + _c0110 = (TEX0.xy + 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP13 = COMPAT_TEXTURE(Texture, _c0110); + _c0112 = TEX0.xy + 2.00000000E+00*TEX1.xy + TEX1.zw; + _TMP14 = COMPAT_TEXTURE(Texture, _c0112); + _c0114 = (TEX0.xy - TEX1.xy) + 2.00000000E+00*TEX1.zw; + _TMP15 = COMPAT_TEXTURE(Texture, _c0114); + _c0116 = TEX0.xy + TEX1.xy + 2.00000000E+00*TEX1.zw; + _TMP16 = COMPAT_TEXTURE(Texture, _c0116); + _c0118 = TEX0.xy - 2.00000000E+00*TEX1.zw; + _TMP17 = COMPAT_TEXTURE(Texture, _c0118); + _c0120 = TEX0.xy - 2.00000000E+00*TEX1.xy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0120); + _c0122 = TEX0.xy + 2.00000000E+00*TEX1.zw; + _TMP19 = COMPAT_TEXTURE(Texture, _c0122); + _c0124 = TEX0.xy + 2.00000000E+00*TEX1.xy; + _TMP20 = COMPAT_TEXTURE(Texture, _c0124); + _r0170.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0170.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0170.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP38 = abs(_r0170); + _r0180.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0180.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0180.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP40 = abs(_r0180); + _r0190.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0190.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0190.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP42 = abs(_r0190); + _r0200.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0200.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0200.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP44 = abs(_r0200); + _b2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0212.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0212.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0212.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP38 = abs(_r0212); + _r0222.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0222.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0222.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP40 = abs(_r0222); + _r0232.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0232.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0232.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP42 = abs(_r0232); + _r0242.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0242.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0242.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP44 = abs(_r0242); + _c2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0254.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0254.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0254.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP38 = abs(_r0254); + _r0264.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0264.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0264.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP40 = abs(_r0264); + _r0274.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0274.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0274.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP42 = abs(_r0274); + _r0284.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0284.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0284.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP44 = abs(_r0284); + _d2 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0296.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0296.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0296.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP38 = abs(_r0296); + _r0306.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0306.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0306.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP40 = abs(_r0306); + _r0316.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0316.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0316.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP42 = abs(_r0316); + _r0326.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP4.xyz); + _r0326.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP4.xyz); + _r0326.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP4.xyz); + _TMP44 = abs(_r0326); + _e1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0338.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0338.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0338.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP38 = abs(_r0338); + _r0348.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0348.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0348.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP40 = abs(_r0348); + _r0358.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0358.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0358.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP42 = abs(_r0358); + _r0368.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0368.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0368.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP44 = abs(_r0368); + _f1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0380.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0380.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0380.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP38 = abs(_r0380); + _r0390.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0390.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0390.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP40 = abs(_r0390); + _r0400.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0400.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0400.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP42 = abs(_r0400); + _r0410.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0410.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0410.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP44 = abs(_r0410); + _g1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0422.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP7.xyz); + _r0422.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP7.xyz); + _r0422.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP7.xyz); + _TMP38 = abs(_r0422); + _r0432.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP5.xyz); + _r0432.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP5.xyz); + _r0432.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP5.xyz); + _TMP40 = abs(_r0432); + _r0442.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP1.xyz); + _r0442.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP1.xyz); + _r0442.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP1.xyz); + _TMP42 = abs(_r0442); + _r0452.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP3.xyz); + _r0452.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP3.xyz); + _r0452.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP3.xyz); + _TMP44 = abs(_r0452); + _h1 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0464.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP8.xyz); + _r0464.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP8.xyz); + _r0464.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP8.xyz); + _TMP38 = abs(_r0464); + _r0474.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP2.xyz); + _r0474.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP2.xyz); + _r0474.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP2.xyz); + _TMP40 = abs(_r0474); + _r0484.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP0.xyz); + _r0484.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP0.xyz); + _r0484.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP0.xyz); + _TMP42 = abs(_r0484); + _r0494.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP6.xyz); + _r0494.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP6.xyz); + _r0494.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP6.xyz); + _TMP44 = abs(_r0494); + _i = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0716.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP14.xyz); + _r0716.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP14.xyz); + _r0716.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP14.xyz); + _TMP38 = abs(_r0716); + _r0726.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP10.xyz); + _r0726.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP10.xyz); + _r0726.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP10.xyz); + _TMP40 = abs(_r0726); + _r0736.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP11.xyz); + _r0736.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP11.xyz); + _r0736.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP11.xyz); + _TMP42 = abs(_r0736); + _r0746.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP15.xyz); + _r0746.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP15.xyz); + _r0746.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP15.xyz); + _TMP44 = abs(_r0746); + _i4 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0800.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP16.xyz); + _r0800.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP16.xyz); + _r0800.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP16.xyz); + _TMP38 = abs(_r0800); + _r0810.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP13.xyz); + _r0810.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP13.xyz); + _r0810.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP13.xyz); + _TMP40 = abs(_r0810); + _r0820.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP9.xyz); + _r0820.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP9.xyz); + _r0820.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP9.xyz); + _TMP42 = abs(_r0820); + _r0830.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP12.xyz); + _r0830.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP12.xyz); + _r0830.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP12.xyz); + _TMP44 = abs(_r0830); + _i5 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0926.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0926.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r0926.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP38 = abs(_r0926); + _r0936.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0936.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0936.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP40 = abs(_r0936); + _r0946.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0946.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0946.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP42 = abs(_r0946); + _r0956.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0956.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0956.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP44 = abs(_r0956); + _h5 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _r0968.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP20.xyz); + _r0968.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP20.xyz); + _r0968.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP20.xyz); + _TMP38 = abs(_r0968); + _r0978.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP17.xyz); + _r0978.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP17.xyz); + _r0978.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP17.xyz); + _TMP40 = abs(_r0978); + _r0988.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP18.xyz); + _r0988.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP18.xyz); + _r0988.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP18.xyz); + _TMP42 = abs(_r0988); + _r0998.x = dot(vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00), _TMP19.xyz); + _r0998.y = dot(vec3( -1.18299997E+00, -2.31699991E+00, 3.49300003E+00), _TMP19.xyz); + _r0998.z = dot(vec3( 2.99399996E+00, -2.50800014E+00, -4.87800002E-01), _TMP19.xyz); + _TMP44 = abs(_r0998); + _f4 = vec4(_TMP38.x, _TMP40.x, _TMP42.x, _TMP44.x); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _interp_restriction_lv1 = bvec4(_e1.x != _f1.x && _e1.x != _h1.x, _e1.y != _f1.y && _e1.y != _h1.y, _e1.z != _f1.z && _e1.z != _h1.z, _e1.w != _f1.w && _e1.w != _h1.w); + _interp_restriction_lv2_left = bvec4(_e1.x != _g1.x && _d2.x != _g1.x, _e1.y != _g1.y && _d2.y != _g1.y, _e1.z != _g1.z && _d2.z != _g1.z, _e1.w != _g1.w && _d2.w != _g1.w); + _interp_restriction_lv2_up = bvec4(_e1.x != _c2.x && _b2.x != _c2.x, _e1.y != _c2.y && _b2.y != _c2.y, _e1.z != _c2.z && _b2.z != _c2.z, _e1.w != _c2.w && _b2.w != _c2.w); + _a1012 = _e1 - _c2; + _TMP1009 = abs(_a1012); + _a1016 = _e1 - _g1; + _TMP1013 = abs(_a1016); + _a1020 = _i - _h5; + _TMP1017 = abs(_a1020); + _a1024 = _i - _f4; + _TMP1021 = abs(_a1024); + _a1028 = _h1 - _f1; + _TMP1025 = abs(_a1028); + _TMP21 = _TMP1009 + _TMP1013 + _TMP1017 + _TMP1021 + 4.00000000E+00*_TMP1025; + _a1034 = _h1 - _d2; + _TMP1031 = abs(_a1034); + _a1038 = _h1 - _i5; + _TMP1035 = abs(_a1038); + _a1042 = _f1 - _i4; + _TMP1039 = abs(_a1042); + _a1046 = _f1 - _b2; + _TMP1043 = abs(_a1046); + _a1050 = _e1 - _i; + _TMP1047 = abs(_a1050); + _TMP22 = _TMP1031 + _TMP1035 + _TMP1039 + _TMP1043 + 4.00000000E+00*_TMP1047; + _edr = bvec4(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z, _TMP21.w < _TMP22.w && _interp_restriction_lv1.w); + _a1054 = _f1 - _g1; + _TMP1051 = abs(_a1054); + _a1058 = _h1 - _c2; + _TMP1055 = abs(_a1058); + _edr_left = bvec4((2.00000000E+00*_TMP1051).x <= _TMP1055.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP1051).y <= _TMP1055.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP1051).z <= _TMP1055.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP1051).w <= _TMP1055.w && _interp_restriction_lv2_left.w); + _a1062 = _f1 - _g1; + _TMP1059 = abs(_a1062); + _a1066 = _h1 - _c2; + _TMP1063 = abs(_a1066); + _edr_up = bvec4(_TMP1059.x >= (2.00000000E+00*_TMP1063).x && _interp_restriction_lv2_up.x, _TMP1059.y >= (2.00000000E+00*_TMP1063).y && _interp_restriction_lv2_up.y, _TMP1059.z >= (2.00000000E+00*_TMP1063).z && _interp_restriction_lv2_up.z, _TMP1059.w >= (2.00000000E+00*_TMP1063).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && _fx_left.x || _edr_up.x && _fx_up.x), _edr.y && (_fx.y || _edr_left.y && _fx_left.y || _edr_up.y && _fx_up.y), _edr.z && (_fx.z || _edr_left.z && _fx_left.z || _edr_up.z && _fx_up.z), _edr.w && (_fx.w || _edr_left.w && _fx_left.w || _edr_up.w && _fx_up.w)); + _a1070 = _e1 - _f1; + _TMP1067 = abs(_a1070); + _a1074 = _e1 - _h1; + _TMP1071 = abs(_a1074); + _px = bvec4(_TMP1067.x <= _TMP1071.x, _TMP1067.y <= _TMP1071.y, _TMP1067.z <= _TMP1071.z, _TMP1067.w <= _TMP1071.w); + if (_nc.x) { + if (_px.x) { + _TMP30 = _TMP5.xyz; + } else { + _TMP30 = _TMP7.xyz; + } + _TMP29 = _TMP30; + } else { + if (_nc.y) { + if (_px.y) { + _TMP32 = _TMP1.xyz; + } else { + _TMP32 = _TMP5.xyz; + } + _TMP31 = _TMP32; + } else { + if (_nc.z) { + if (_px.z) { + _TMP34 = _TMP3.xyz; + } else { + _TMP34 = _TMP1.xyz; + } + _TMP33 = _TMP34; + } else { + if (_nc.w) { + if (_px.w) { + _TMP36 = _TMP7.xyz; + } else { + _TMP36 = _TMP3.xyz; + } + _TMP35 = _TMP36; + } else { + _TMP35 = _TMP4.xyz; + } + _TMP33 = _TMP35; + } + _TMP31 = _TMP33; + } + _TMP29 = _TMP31; + } + _ret_0 = vec4(_TMP29.x, _TMP29.y, _TMP29.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.6c.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.6c.glsl new file mode 100644 index 000000000..9dcad92f6 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.6c.glsl @@ -0,0 +1,388 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord1; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord1; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _OUT._t1.xy = vec2(_ps.x, 0.00000000E+00); + _OUT._t1.zw = vec2(0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord1 = TexCoord.xy; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + TEX1 = _OUT._t1; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord1; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP29; +vec3 _TMP31; +vec3 _TMP33; +vec3 _TMP35; +vec3 _TMP36; +vec3 _TMP34; +vec3 _TMP32; +vec3 _TMP30; +vec4 _TMP22; +vec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0055; +vec2 _c0057; +vec2 _c0059; +vec2 _c0061; +vec2 _c0063; +vec2 _c0067; +vec2 _c0069; +vec2 _c0071; +vec2 _c0073; +vec2 _c0075; +vec2 _c0077; +vec2 _c0079; +vec2 _c0081; +vec2 _c0083; +vec2 _c0085; +vec2 _c0087; +vec2 _c0089; +vec2 _c0091; +vec2 _c0093; +vec2 _c0095; +vec2 _c0097; +vec4 _r0099; +vec4 _r0109; +vec4 _r0119; +vec4 _r0129; +vec4 _r0139; +vec4 _r0149; +vec4 _TMP160; +vec4 _a0163; +vec4 _TMP164; +vec4 _a0167; +vec4 _TMP168; +vec4 _a0171; +vec4 _TMP172; +vec4 _a0175; +vec4 _TMP176; +vec4 _a0179; +vec4 _TMP182; +vec4 _a0185; +vec4 _TMP186; +vec4 _a0189; +vec4 _TMP190; +vec4 _a0193; +vec4 _TMP194; +vec4 _a0197; +vec4 _TMP198; +vec4 _a0201; +vec4 _TMP202; +vec4 _a0205; +vec4 _TMP206; +vec4 _a0209; +vec4 _TMP210; +vec4 _a0213; +vec4 _TMP214; +vec4 _a0217; +vec4 _TMP218; +vec4 _a0221; +vec4 _TMP222; +vec4 _a0225; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + vec2 _fp; + _x0055 = TEX0.xy*TextureSize; + _fp = fract(_x0055); + _c0057 = (TEX0.xy - TEX1.xy) - TEX1.zw; + _TMP0 = COMPAT_TEXTURE(Texture, _c0057); + _c0059 = TEX0.xy - TEX1.zw; + _TMP1 = COMPAT_TEXTURE(Texture, _c0059); + _c0061 = (TEX0.xy + TEX1.xy) - TEX1.zw; + _TMP2 = COMPAT_TEXTURE(Texture, _c0061); + _c0063 = TEX0.xy - TEX1.xy; + _TMP3 = COMPAT_TEXTURE(Texture, _c0063); + _TMP4 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0067 = TEX0.xy + TEX1.xy; + _TMP5 = COMPAT_TEXTURE(Texture, _c0067); + _c0069 = (TEX0.xy - TEX1.xy) + TEX1.zw; + _TMP6 = COMPAT_TEXTURE(Texture, _c0069); + _c0071 = TEX0.xy + TEX1.zw; + _TMP7 = COMPAT_TEXTURE(Texture, _c0071); + _c0073 = TEX0.xy + TEX1.xy + TEX1.zw; + _TMP8 = COMPAT_TEXTURE(Texture, _c0073); + _c0075 = (TEX0.xy - TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP9 = COMPAT_TEXTURE(Texture, _c0075); + _c0077 = (TEX0.xy + TEX1.xy) - 2.00000000E+00*TEX1.zw; + _TMP10 = COMPAT_TEXTURE(Texture, _c0077); + _c0079 = (TEX0.xy - 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP11 = COMPAT_TEXTURE(Texture, _c0079); + _c0081 = (TEX0.xy - 2.00000000E+00*TEX1.xy) + TEX1.zw; + _TMP12 = COMPAT_TEXTURE(Texture, _c0081); + _c0083 = (TEX0.xy + 2.00000000E+00*TEX1.xy) - TEX1.zw; + _TMP13 = COMPAT_TEXTURE(Texture, _c0083); + _c0085 = TEX0.xy + 2.00000000E+00*TEX1.xy + TEX1.zw; + _TMP14 = COMPAT_TEXTURE(Texture, _c0085); + _c0087 = (TEX0.xy - TEX1.xy) + 2.00000000E+00*TEX1.zw; + _TMP15 = COMPAT_TEXTURE(Texture, _c0087); + _c0089 = TEX0.xy + TEX1.xy + 2.00000000E+00*TEX1.zw; + _TMP16 = COMPAT_TEXTURE(Texture, _c0089); + _c0091 = TEX0.xy - 2.00000000E+00*TEX1.zw; + _TMP17 = COMPAT_TEXTURE(Texture, _c0091); + _c0093 = TEX0.xy - 2.00000000E+00*TEX1.xy; + _TMP18 = COMPAT_TEXTURE(Texture, _c0093); + _c0095 = TEX0.xy + 2.00000000E+00*TEX1.zw; + _TMP19 = COMPAT_TEXTURE(Texture, _c0095); + _c0097 = TEX0.xy + 2.00000000E+00*TEX1.xy; + _TMP20 = COMPAT_TEXTURE(Texture, _c0097); + _r0099.x = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0099.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0099.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0099.w = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0109.x = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0109.y = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0109.z = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0109.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0119.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0119.y = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0119.z = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0119.w = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0129.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0129.y = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0129.z = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0129.w = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0139.x = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0139.y = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0139.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0139.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0149.x = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0149.y = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0149.z = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0149.w = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _interp_restriction_lv1 = bvec4(_r0119.x != _r0099.w && _r0119.x != _r0099.z && (_r0099.w != _r0099.x && _r0099.w != _r0109.x || _r0099.z != _r0099.y && _r0099.z != _r0109.z || _r0119.x == _r0109.w && (_r0099.w != _r0149.y && _r0099.w != _r0129.x || _r0099.z != _r0149.x && _r0099.z != _r0139.x) || _r0119.x == _r0109.z || _r0119.x == _r0109.x), _r0119.y != _r0099.x && _r0119.y != _r0099.w && (_r0099.x != _r0099.y && _r0099.x != _r0109.y || _r0099.w != _r0099.z && _r0099.w != _r0109.w || _r0119.y == _r0109.x && (_r0099.x != _r0149.z && _r0099.x != _r0129.y || _r0099.w != _r0149.y && _r0099.w != _r0139.y) || _r0119.y == _r0109.w || _r0119.y == _r0109.y), _r0119.z != _r0099.y && _r0119.z != _r0099.x && (_r0099.y != _r0099.z && _r0099.y != _r0109.z || _r0099.x != _r0099.w && _r0099.x != _r0109.x || _r0119.z == _r0109.y && (_r0099.y != _r0149.w && _r0099.y != _r0129.z || _r0099.x != _r0149.z && _r0099.x != _r0139.z) || _r0119.z == _r0109.x || _r0119.z == _r0109.z), _r0119.w != _r0099.z && _r0119.w != _r0099.y && (_r0099.z != _r0099.w && _r0099.z != _r0109.w || _r0099.y != _r0099.x && _r0099.y != _r0109.y || _r0119.w == _r0109.z && (_r0099.z != _r0149.x && _r0099.z != _r0129.w || _r0099.y != _r0149.w && _r0099.y != _r0139.w) || _r0119.w == _r0109.y || _r0119.w == _r0109.w)); + _interp_restriction_lv2_left = bvec4(_r0119.x != _r0109.z && _r0099.y != _r0109.z, _r0119.y != _r0109.w && _r0099.z != _r0109.w, _r0119.z != _r0109.x && _r0099.w != _r0109.x, _r0119.w != _r0109.y && _r0099.x != _r0109.y); + _interp_restriction_lv2_up = bvec4(_r0119.x != _r0109.x && _r0099.x != _r0109.x, _r0119.y != _r0109.y && _r0099.y != _r0109.y, _r0119.z != _r0109.z && _r0099.z != _r0109.z, _r0119.w != _r0109.w && _r0099.w != _r0109.w); + _a0163 = _r0119 - _r0109; + _TMP160 = abs(_a0163); + _a0167 = _r0119 - _r0109.zwxy; + _TMP164 = abs(_a0167); + _a0171 = _r0109.wxyz - _r0149; + _TMP168 = abs(_a0171); + _a0175 = _r0109.wxyz - _r0149.yzwx; + _TMP172 = abs(_a0175); + _a0179 = _r0099.zwxy - _r0099.wxyz; + _TMP176 = abs(_a0179); + _TMP21 = _TMP160 + _TMP164 + _TMP168 + _TMP172 + 4.00000000E+00*_TMP176; + _a0185 = _r0099.zwxy - _r0099.yzwx; + _TMP182 = abs(_a0185); + _a0189 = _r0099.zwxy - _r0139; + _TMP186 = abs(_a0189); + _a0193 = _r0099.wxyz - _r0129; + _TMP190 = abs(_a0193); + _a0197 = _r0099.wxyz - _r0099; + _TMP194 = abs(_a0197); + _a0201 = _r0119 - _r0109.wxyz; + _TMP198 = abs(_a0201); + _TMP22 = _TMP182 + _TMP186 + _TMP190 + _TMP194 + 4.00000000E+00*_TMP198; + _edr = bvec4(_TMP21.x < _TMP22.x && _interp_restriction_lv1.x, _TMP21.y < _TMP22.y && _interp_restriction_lv1.y, _TMP21.z < _TMP22.z && _interp_restriction_lv1.z, _TMP21.w < _TMP22.w && _interp_restriction_lv1.w); + _a0205 = _r0099.wxyz - _r0109.zwxy; + _TMP202 = abs(_a0205); + _a0209 = _r0099.zwxy - _r0109; + _TMP206 = abs(_a0209); + _edr_left = bvec4((2.00000000E+00*_TMP202).x <= _TMP206.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP202).y <= _TMP206.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP202).z <= _TMP206.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP202).w <= _TMP206.w && _interp_restriction_lv2_left.w); + _a0213 = _r0099.wxyz - _r0109.zwxy; + _TMP210 = abs(_a0213); + _a0217 = _r0099.zwxy - _r0109; + _TMP214 = abs(_a0217); + _edr_up = bvec4(_TMP210.x >= (2.00000000E+00*_TMP214).x && _interp_restriction_lv2_up.x, _TMP210.y >= (2.00000000E+00*_TMP214).y && _interp_restriction_lv2_up.y, _TMP210.z >= (2.00000000E+00*_TMP214).z && _interp_restriction_lv2_up.z, _TMP210.w >= (2.00000000E+00*_TMP214).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && _fx_left.x || _edr_up.x && _fx_up.x), _edr.y && (_fx.y || _edr_left.y && _fx_left.y || _edr_up.y && _fx_up.y), _edr.z && (_fx.z || _edr_left.z && _fx_left.z || _edr_up.z && _fx_up.z), _edr.w && (_fx.w || _edr_left.w && _fx_left.w || _edr_up.w && _fx_up.w)); + _a0221 = _r0119 - _r0099.wxyz; + _TMP218 = abs(_a0221); + _a0225 = _r0119 - _r0099.zwxy; + _TMP222 = abs(_a0225); + _px = bvec4(_TMP218.x <= _TMP222.x, _TMP218.y <= _TMP222.y, _TMP218.z <= _TMP222.z, _TMP218.w <= _TMP222.w); + if (_nc.x) { + if (_px.x) { + _TMP30 = _TMP5.xyz; + } else { + _TMP30 = _TMP7.xyz; + } + _TMP29 = _TMP30; + } else { + if (_nc.y) { + if (_px.y) { + _TMP32 = _TMP1.xyz; + } else { + _TMP32 = _TMP5.xyz; + } + _TMP31 = _TMP32; + } else { + if (_nc.z) { + if (_px.z) { + _TMP34 = _TMP3.xyz; + } else { + _TMP34 = _TMP1.xyz; + } + _TMP33 = _TMP34; + } else { + if (_nc.w) { + if (_px.w) { + _TMP36 = _TMP7.xyz; + } else { + _TMP36 = _TMP3.xyz; + } + _TMP35 = _TMP36; + } else { + _TMP35 = _TMP4.xyz; + } + _TMP33 = _TMP35; + } + _TMP31 = _TMP33; + } + _TMP29 = _TMP31; + } + _ret_0 = vec4(_TMP29.x, _TMP29.y, _TMP29.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.7d.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.7d.glsl new file mode 100644 index 000000000..92a4ef62b --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.7d.glsl @@ -0,0 +1,519 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +float _TMP56; +float _TMP55; +float _TMP54; +vec3 _TMP46; +vec3 _TMP48; +vec3 _TMP50; +vec3 _TMP52; +vec3 _TMP53; +vec3 _TMP51; +vec3 _TMP49; +vec3 _TMP47; +vec3 _TMP38; +vec3 _TMP40; +vec3 _TMP42; +vec3 _TMP44; +vec3 _TMP45; +vec3 _TMP43; +vec3 _TMP41; +vec3 _TMP39; +vec4 _TMP31; +vec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0076; +vec4 _r0120; +vec4 _r0130; +vec4 _r0140; +vec4 _r0150; +vec4 _r0160; +vec4 _r0170; +vec4 _TMP181; +vec4 _a0184; +vec4 _TMP187; +vec4 _a0190; +vec4 _TMP193; +vec4 _a0196; +vec4 _TMP199; +vec4 _a0202; +vec4 _TMP205; +vec4 _a0208; +vec4 _TMP211; +vec4 _a0214; +vec4 _TMP217; +vec4 _a0220; +vec4 _TMP223; +vec4 _a0226; +vec4 _TMP229; +vec4 _a0232; +vec4 _TMP235; +vec4 _a0238; +vec4 _TMP239; +vec4 _a0242; +vec4 _TMP243; +vec4 _a0246; +vec4 _TMP247; +vec4 _a0250; +vec4 _TMP251; +vec4 _a0254; +vec4 _TMP257; +vec4 _a0260; +vec4 _TMP261; +vec4 _a0264; +vec4 _TMP265; +vec4 _a0268; +vec4 _TMP269; +vec4 _a0272; +vec4 _TMP273; +vec4 _a0276; +vec4 _TMP277; +vec4 _a0280; +vec4 _TMP281; +vec4 _a0284; +vec4 _TMP285; +vec4 _a0288; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec3 _df0302; +vec3 _a0304; +vec3 _df0306; +vec3 _a0308; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + vec2 _fp; + vec3 _res; + _x0076 = TEX0.xy*TextureSize; + _fp = fract(_x0076); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0120.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0120.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0120.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0120.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0130.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0130.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0130.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0130.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0140.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0140.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0140.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0140.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0150.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0150.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0150.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0150.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0160.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0160.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0160.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0160.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0170.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0170.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0170.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0170.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _a0184 = _r0120.wxyz - _r0120; + _TMP181 = abs(_a0184); + _TMP21 = bvec4(_TMP181.x < 1.00000000E+01, _TMP181.y < 1.00000000E+01, _TMP181.z < 1.00000000E+01, _TMP181.w < 1.00000000E+01); + _a0190 = _r0120.zwxy - _r0120.yzwx; + _TMP187 = abs(_a0190); + _TMP22 = bvec4(_TMP187.x < 1.00000000E+01, _TMP187.y < 1.00000000E+01, _TMP187.z < 1.00000000E+01, _TMP187.w < 1.00000000E+01); + _a0196 = _r0140 - _r0130.wxyz; + _TMP193 = abs(_a0196); + _TMP23 = bvec4(_TMP193.x < 1.00000000E+01, _TMP193.y < 1.00000000E+01, _TMP193.z < 1.00000000E+01, _TMP193.w < 1.00000000E+01); + _a0202 = _r0120.wxyz - _r0150; + _TMP199 = abs(_a0202); + _TMP24 = bvec4(_TMP199.x < 1.00000000E+01, _TMP199.y < 1.00000000E+01, _TMP199.z < 1.00000000E+01, _TMP199.w < 1.00000000E+01); + _a0208 = _r0120.zwxy - _r0160; + _TMP205 = abs(_a0208); + _TMP25 = bvec4(_TMP205.x < 1.00000000E+01, _TMP205.y < 1.00000000E+01, _TMP205.z < 1.00000000E+01, _TMP205.w < 1.00000000E+01); + _a0214 = _r0140 - _r0130.zwxy; + _TMP211 = abs(_a0214); + _TMP26 = bvec4(_TMP211.x < 1.00000000E+01, _TMP211.y < 1.00000000E+01, _TMP211.z < 1.00000000E+01, _TMP211.w < 1.00000000E+01); + _a0220 = _r0140 - _r0130; + _TMP217 = abs(_a0220); + _TMP27 = bvec4(_TMP217.x < 1.00000000E+01, _TMP217.y < 1.00000000E+01, _TMP217.z < 1.00000000E+01, _TMP217.w < 1.00000000E+01); + _a0226 = _r0120 - _r0150.yzwx; + _TMP223 = abs(_a0226); + _TMP28 = bvec4(_TMP223.x < 1.00000000E+01, _TMP223.y < 1.00000000E+01, _TMP223.z < 1.00000000E+01, _TMP223.w < 1.00000000E+01); + _a0232 = _r0120.yzwx - _r0160.wxyz; + _TMP229 = abs(_a0232); + _TMP29 = bvec4(_TMP229.x < 1.00000000E+01, _TMP229.y < 1.00000000E+01, _TMP229.z < 1.00000000E+01, _TMP229.w < 1.00000000E+01); + _interp_restriction_lv1 = bvec4(_r0140.x != _r0120.w && _r0140.x != _r0120.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0120.w != _r0170.y && _r0120.w != _r0130.w || _r0120.z != _r0170.x && _r0120.z != _r0130.w || _r0120.z != _r0130.z || _r0120.w != _r0130.x || _TMP28.x && _TMP29.x), _r0140.y != _r0120.x && _r0140.y != _r0120.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0120.x != _r0170.z && _r0120.x != _r0130.x || _r0120.w != _r0170.y && _r0120.w != _r0130.x || _r0120.w != _r0130.w || _r0120.x != _r0130.y || _TMP28.y && _TMP29.y), _r0140.z != _r0120.y && _r0140.z != _r0120.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0120.y != _r0170.w && _r0120.y != _r0130.y || _r0120.x != _r0170.z && _r0120.x != _r0130.y || _r0120.x != _r0130.x || _r0120.y != _r0130.z || _TMP28.z && _TMP29.z), _r0140.w != _r0120.z && _r0140.w != _r0120.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0120.z != _r0170.x && _r0120.z != _r0130.z || _r0120.y != _r0170.w && _r0120.y != _r0130.z || _r0120.y != _r0130.y || _r0120.z != _r0130.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0140.x != _r0130.z && _r0120.y != _r0130.z, _r0140.y != _r0130.w && _r0120.z != _r0130.w, _r0140.z != _r0130.x && _r0120.w != _r0130.x, _r0140.w != _r0130.y && _r0120.x != _r0130.y); + _interp_restriction_lv2_up = bvec4(_r0140.x != _r0130.x && _r0120.x != _r0130.x, _r0140.y != _r0130.y && _r0120.y != _r0130.y, _r0140.z != _r0130.z && _r0120.z != _r0130.z, _r0140.w != _r0130.w && _r0120.w != _r0130.w); + _a0238 = _r0140 - _r0130; + _TMP235 = abs(_a0238); + _a0242 = _r0140 - _r0130.zwxy; + _TMP239 = abs(_a0242); + _a0246 = _r0130.wxyz - _r0170; + _TMP243 = abs(_a0246); + _a0250 = _r0130.wxyz - _r0170.yzwx; + _TMP247 = abs(_a0250); + _a0254 = _r0120.zwxy - _r0120.wxyz; + _TMP251 = abs(_a0254); + _TMP30 = _TMP235 + _TMP239 + _TMP243 + _TMP247 + 4.00000000E+00*_TMP251; + _a0260 = _r0120.zwxy - _r0120.yzwx; + _TMP257 = abs(_a0260); + _a0264 = _r0120.zwxy - _r0160; + _TMP261 = abs(_a0264); + _a0268 = _r0120.wxyz - _r0150; + _TMP265 = abs(_a0268); + _a0272 = _r0120.wxyz - _r0120; + _TMP269 = abs(_a0272); + _a0276 = _r0140 - _r0130.wxyz; + _TMP273 = abs(_a0276); + _TMP31 = _TMP257 + _TMP261 + _TMP265 + _TMP269 + 4.00000000E+00*_TMP273; + _edr = bvec4(_TMP30.x < _TMP31.x && _interp_restriction_lv1.x, _TMP30.y < _TMP31.y && _interp_restriction_lv1.y, _TMP30.z < _TMP31.z && _interp_restriction_lv1.z, _TMP30.w < _TMP31.w && _interp_restriction_lv1.w); + _a0280 = _r0120.wxyz - _r0130.zwxy; + _TMP277 = abs(_a0280); + _a0284 = _r0120.zwxy - _r0130; + _TMP281 = abs(_a0284); + _edr_left = bvec4((2.00000000E+00*_TMP277).x <= _TMP281.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP277).y <= _TMP281.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP277).z <= _TMP281.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP277).w <= _TMP281.w && _interp_restriction_lv2_left.w); + _a0288 = _r0120.wxyz - _r0130.zwxy; + _TMP285 = abs(_a0288); + _a0292 = _r0120.zwxy - _r0130; + _TMP289 = abs(_a0292); + _edr_up = bvec4(_TMP285.x >= (2.00000000E+00*_TMP289).x && _interp_restriction_lv2_up.x, _TMP285.y >= (2.00000000E+00*_TMP289).y && _interp_restriction_lv2_up.y, _TMP285.z >= (2.00000000E+00*_TMP289).z && _interp_restriction_lv2_up.z, _TMP285.w >= (2.00000000E+00*_TMP289).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && _fx_left.x || _edr_up.x && _fx_up.x), _edr.y && (_fx.y || _edr_left.y && _fx_left.y || _edr_up.y && _fx_up.y), _edr.z && (_fx.z || _edr_left.z && _fx_left.z || _edr_up.z && _fx_up.z), _edr.w && (_fx.w || _edr_left.w && _fx_left.w || _edr_up.w && _fx_up.w)); + _a0296 = _r0140 - _r0120.wxyz; + _TMP293 = abs(_a0296); + _a0300 = _r0140 - _r0120.zwxy; + _TMP297 = abs(_a0300); + _px = bvec4(_TMP293.x <= _TMP297.x, _TMP293.y <= _TMP297.y, _TMP293.z <= _TMP297.z, _TMP293.w <= _TMP297.w); + if (_nc.x) { + if (_px.x) { + _TMP39 = _TMP8.xyz; + } else { + _TMP39 = _TMP10.xyz; + } + _TMP38 = _TMP39; + } else { + if (_nc.y) { + if (_px.y) { + _TMP41 = _TMP4.xyz; + } else { + _TMP41 = _TMP8.xyz; + } + _TMP40 = _TMP41; + } else { + if (_nc.z) { + if (_px.z) { + _TMP43 = _TMP6.xyz; + } else { + _TMP43 = _TMP4.xyz; + } + _TMP42 = _TMP43; + } else { + if (_nc.w) { + if (_px.w) { + _TMP45 = _TMP10.xyz; + } else { + _TMP45 = _TMP6.xyz; + } + _TMP44 = _TMP45; + } else { + _TMP44 = _TMP7.xyz; + } + _TMP42 = _TMP44; + } + _TMP40 = _TMP42; + } + _TMP38 = _TMP40; + } + if (_nc.w) { + if (_px.w) { + _TMP47 = _TMP10.xyz; + } else { + _TMP47 = _TMP6.xyz; + } + _TMP46 = _TMP47; + } else { + if (_nc.z) { + if (_px.z) { + _TMP49 = _TMP6.xyz; + } else { + _TMP49 = _TMP4.xyz; + } + _TMP48 = _TMP49; + } else { + if (_nc.y) { + if (_px.y) { + _TMP51 = _TMP4.xyz; + } else { + _TMP51 = _TMP8.xyz; + } + _TMP50 = _TMP51; + } else { + if (_nc.x) { + if (_px.x) { + _TMP53 = _TMP8.xyz; + } else { + _TMP53 = _TMP10.xyz; + } + _TMP52 = _TMP53; + } else { + _TMP52 = _TMP7.xyz; + } + _TMP50 = _TMP52; + } + _TMP48 = _TMP50; + } + _TMP46 = _TMP48; + } + _a0304 = _TMP7.xyz - _TMP38; + _df0302 = abs(_a0304); + _TMP54 = _df0302.x + _df0302.y + _df0302.z; + _a0308 = _TMP7.xyz - _TMP46; + _df0306 = abs(_a0308); + _TMP55 = _df0306.x + _df0306.y + _df0306.z; + _TMP56 = float((_TMP55 >= _TMP54)); + _res = _TMP38 + _TMP56*(_TMP46 - _TMP38); + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.8d.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.8d.glsl new file mode 100644 index 000000000..293e0dee2 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v3.8d.glsl @@ -0,0 +1,479 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP46; +vec3 _TMP44; +vec3 _TMP42; +vec3 _TMP40; +vec3 _TMP45; +vec3 _TMP43; +vec3 _TMP41; +vec3 _TMP39; +vec4 _TMP38; +vec4 _TMP31; +vec4 _TMP30; +vec4 _TMP53; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0068; +vec4 _r0112; +vec4 _r0122; +vec4 _r0132; +vec4 _r0142; +vec4 _r0152; +vec4 _r0162; +vec4 _TMP173; +vec4 _a0176; +vec4 _TMP179; +vec4 _a0182; +vec4 _TMP185; +vec4 _a0188; +vec4 _TMP191; +vec4 _a0194; +vec4 _TMP197; +vec4 _a0200; +vec4 _TMP203; +vec4 _a0206; +vec4 _TMP209; +vec4 _a0212; +vec4 _TMP215; +vec4 _a0218; +vec4 _TMP221; +vec4 _a0224; +vec4 _x0226; +vec4 _TMP227; +vec4 _x0234; +vec4 _TMP235; +vec4 _x0242; +vec4 _TMP243; +vec4 _TMP251; +vec4 _a0254; +vec4 _TMP255; +vec4 _a0258; +vec4 _TMP259; +vec4 _a0262; +vec4 _TMP263; +vec4 _a0266; +vec4 _TMP267; +vec4 _a0270; +vec4 _TMP273; +vec4 _a0276; +vec4 _TMP277; +vec4 _a0280; +vec4 _TMP281; +vec4 _a0284; +vec4 _TMP285; +vec4 _a0288; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec4 _TMP301; +vec4 _a0304; +vec4 _TMP305; +vec4 _a0308; +vec4 _TMP309; +vec4 _a0312; +vec4 _TMP313; +vec4 _a0316; +float _t0322; +float _t0326; +float _t0330; +float _t0334; +vec4 _r0338; +vec4 _TMP347; +vec4 _a0350; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec2 _fp; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _maximo; + vec3 _res; + float _mx; + _x0068 = TEX0.xy*TextureSize; + _fp = fract(_x0068); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0112.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0112.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0122.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0132.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0142.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0152.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0162.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _a0176 = _r0112.wxyz - _r0112; + _TMP173 = abs(_a0176); + _TMP21 = bvec4(_TMP173.x < 1.50000000E+01, _TMP173.y < 1.50000000E+01, _TMP173.z < 1.50000000E+01, _TMP173.w < 1.50000000E+01); + _a0182 = _r0112.zwxy - _r0112.yzwx; + _TMP179 = abs(_a0182); + _TMP22 = bvec4(_TMP179.x < 1.50000000E+01, _TMP179.y < 1.50000000E+01, _TMP179.z < 1.50000000E+01, _TMP179.w < 1.50000000E+01); + _a0188 = _r0132 - _r0122.wxyz; + _TMP185 = abs(_a0188); + _TMP23 = bvec4(_TMP185.x < 1.50000000E+01, _TMP185.y < 1.50000000E+01, _TMP185.z < 1.50000000E+01, _TMP185.w < 1.50000000E+01); + _a0194 = _r0112.wxyz - _r0142; + _TMP191 = abs(_a0194); + _TMP24 = bvec4(_TMP191.x < 1.50000000E+01, _TMP191.y < 1.50000000E+01, _TMP191.z < 1.50000000E+01, _TMP191.w < 1.50000000E+01); + _a0200 = _r0112.zwxy - _r0152; + _TMP197 = abs(_a0200); + _TMP25 = bvec4(_TMP197.x < 1.50000000E+01, _TMP197.y < 1.50000000E+01, _TMP197.z < 1.50000000E+01, _TMP197.w < 1.50000000E+01); + _a0206 = _r0132 - _r0122.zwxy; + _TMP203 = abs(_a0206); + _TMP26 = bvec4(_TMP203.x < 1.50000000E+01, _TMP203.y < 1.50000000E+01, _TMP203.z < 1.50000000E+01, _TMP203.w < 1.50000000E+01); + _a0212 = _r0132 - _r0122; + _TMP209 = abs(_a0212); + _TMP27 = bvec4(_TMP209.x < 1.50000000E+01, _TMP209.y < 1.50000000E+01, _TMP209.z < 1.50000000E+01, _TMP209.w < 1.50000000E+01); + _a0218 = _r0112 - _r0142.yzwx; + _TMP215 = abs(_a0218); + _TMP28 = bvec4(_TMP215.x < 1.50000000E+01, _TMP215.y < 1.50000000E+01, _TMP215.z < 1.50000000E+01, _TMP215.w < 1.50000000E+01); + _a0224 = _r0112.yzwx - _r0152.wxyz; + _TMP221 = abs(_a0224); + _TMP29 = bvec4(_TMP221.x < 1.50000000E+01, _TMP221.y < 1.50000000E+01, _TMP221.z < 1.50000000E+01, _TMP221.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0132.x != _r0112.w && _r0132.x != _r0112.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0112.w != _r0162.y && _r0112.w != _r0122.w || _r0112.z != _r0162.x && _r0112.z != _r0122.w || _r0112.z != _r0122.z || _r0112.w != _r0122.x || _TMP28.x && _TMP29.x), _r0132.y != _r0112.x && _r0132.y != _r0112.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0112.x != _r0162.z && _r0112.x != _r0122.x || _r0112.w != _r0162.y && _r0112.w != _r0122.x || _r0112.w != _r0122.w || _r0112.x != _r0122.y || _TMP28.y && _TMP29.y), _r0132.z != _r0112.y && _r0132.z != _r0112.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0112.y != _r0162.w && _r0112.y != _r0122.y || _r0112.x != _r0162.z && _r0112.x != _r0122.y || _r0112.x != _r0122.x || _r0112.y != _r0122.z || _TMP28.z && _TMP29.z), _r0132.w != _r0112.z && _r0132.w != _r0112.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0112.z != _r0162.x && _r0112.z != _r0122.z || _r0112.y != _r0162.w && _r0112.y != _r0122.z || _r0112.y != _r0122.y || _r0112.z != _r0122.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0132.x != _r0122.z && _r0112.y != _r0122.z, _r0132.y != _r0122.w && _r0112.z != _r0122.w, _r0132.z != _r0122.x && _r0112.w != _r0122.x, _r0132.w != _r0122.y && _r0112.x != _r0122.y); + _interp_restriction_lv2_up = bvec4(_r0132.x != _r0122.x && _r0112.x != _r0122.x, _r0132.y != _r0122.y && _r0112.y != _r0122.y, _r0132.z != _r0122.z && _r0112.z != _r0122.z, _r0132.w != _r0122.w && _r0112.w != _r0122.w); + _x0226 = ((_fx + vec4( 2.00000003E-01, 2.00000003E-01, 2.00000003E-01, 2.00000003E-01)) - vec4( 1.50000000E+00, 5.00000000E-01, -5.00000000E-01, 5.00000000E-01))/vec4( 4.00000006E-01, 4.00000006E-01, 4.00000006E-01, 4.00000006E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0226); + _TMP227 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0234 = ((_fx_left + vec4( 1.00000001E-01, 2.00000003E-01, 1.00000001E-01, 2.00000003E-01)) - vec4( 1.00000000E+00, 1.00000000E+00, -5.00000000E-01, 0.00000000E+00))/vec4( 2.00000003E-01, 4.00000006E-01, 2.00000003E-01, 4.00000006E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0234); + _TMP235 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _x0242 = ((_fx_up + vec4( 2.00000003E-01, 1.00000001E-01, 2.00000003E-01, 1.00000001E-01)) - vec4( 2.00000000E+00, 0.00000000E+00, -1.00000000E+00, 5.00000000E-01))/vec4( 4.00000006E-01, 2.00000003E-01, 4.00000006E-01, 2.00000003E-01); + _TMP53 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0242); + _TMP243 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP53); + _a0254 = _r0132 - _r0122; + _TMP251 = abs(_a0254); + _a0258 = _r0132 - _r0122.zwxy; + _TMP255 = abs(_a0258); + _a0262 = _r0122.wxyz - _r0162; + _TMP259 = abs(_a0262); + _a0266 = _r0122.wxyz - _r0162.yzwx; + _TMP263 = abs(_a0266); + _a0270 = _r0112.zwxy - _r0112.wxyz; + _TMP267 = abs(_a0270); + _TMP30 = _TMP251 + _TMP255 + _TMP259 + _TMP263 + 4.00000000E+00*_TMP267; + _a0276 = _r0112.zwxy - _r0112.yzwx; + _TMP273 = abs(_a0276); + _a0280 = _r0112.zwxy - _r0152; + _TMP277 = abs(_a0280); + _a0284 = _r0112.wxyz - _r0142; + _TMP281 = abs(_a0284); + _a0288 = _r0112.wxyz - _r0112; + _TMP285 = abs(_a0288); + _a0292 = _r0132 - _r0122.wxyz; + _TMP289 = abs(_a0292); + _TMP31 = _TMP273 + _TMP277 + _TMP281 + _TMP285 + 4.00000000E+00*_TMP289; + _edr = bvec4(_TMP30.x < _TMP31.x && _interp_restriction_lv1.x, _TMP30.y < _TMP31.y && _interp_restriction_lv1.y, _TMP30.z < _TMP31.z && _interp_restriction_lv1.z, _TMP30.w < _TMP31.w && _interp_restriction_lv1.w); + _a0296 = _r0112.wxyz - _r0122.zwxy; + _TMP293 = abs(_a0296); + _a0300 = _r0112.zwxy - _r0122; + _TMP297 = abs(_a0300); + _edr_left = bvec4((2.00000000E+00*_TMP293).x <= _TMP297.x && _interp_restriction_lv2_left.x && _edr.x, (2.00000000E+00*_TMP293).y <= _TMP297.y && _interp_restriction_lv2_left.y && _edr.y, (2.00000000E+00*_TMP293).z <= _TMP297.z && _interp_restriction_lv2_left.z && _edr.z, (2.00000000E+00*_TMP293).w <= _TMP297.w && _interp_restriction_lv2_left.w && _edr.w); + _a0304 = _r0112.wxyz - _r0122.zwxy; + _TMP301 = abs(_a0304); + _a0308 = _r0112.zwxy - _r0122; + _TMP305 = abs(_a0308); + _edr_up = bvec4(_TMP301.x >= (2.00000000E+00*_TMP305).x && _interp_restriction_lv2_up.x && _edr.x, _TMP301.y >= (2.00000000E+00*_TMP305).y && _interp_restriction_lv2_up.y && _edr.y, _TMP301.z >= (2.00000000E+00*_TMP305).z && _interp_restriction_lv2_up.z && _edr.z, _TMP301.w >= (2.00000000E+00*_TMP305).w && _interp_restriction_lv2_up.w && _edr.w); + _fx45 = vec4(float(_edr.x), float(_edr.y), float(_edr.z), float(_edr.w))*_TMP227; + _fx30 = vec4(float(_edr_left.x), float(_edr_left.y), float(_edr_left.z), float(_edr_left.w))*_TMP235; + _fx60 = vec4(float(_edr_up.x), float(_edr_up.y), float(_edr_up.z), float(_edr_up.w))*_TMP243; + _a0312 = _r0132 - _r0112.wxyz; + _TMP309 = abs(_a0312); + _a0316 = _r0132 - _r0112.zwxy; + _TMP313 = abs(_a0316); + _px = bvec4(_TMP309.x <= _TMP313.x, _TMP309.y <= _TMP313.y, _TMP309.z <= _TMP313.z, _TMP309.w <= _TMP313.w); + _TMP38 = max(_fx30, _fx60); + _maximo = max(_TMP38, _fx45); + _t0322 = float(_px.x); + _TMP39 = _TMP10.xyz + _t0322*(_TMP8.xyz - _TMP10.xyz); + _TMP40 = _TMP7.xyz + _maximo.x*(_TMP39 - _TMP7.xyz); + _t0326 = float(_px.y); + _TMP41 = _TMP8.xyz + _t0326*(_TMP4.xyz - _TMP8.xyz); + _TMP42 = _TMP7.xyz + _maximo.y*(_TMP41 - _TMP7.xyz); + _t0330 = float(_px.z); + _TMP43 = _TMP4.xyz + _t0330*(_TMP6.xyz - _TMP4.xyz); + _TMP44 = _TMP7.xyz + _maximo.z*(_TMP43 - _TMP7.xyz); + _t0334 = float(_px.w); + _TMP45 = _TMP6.xyz + _t0334*(_TMP10.xyz - _TMP6.xyz); + _TMP46 = _TMP7.xyz + _maximo.w*(_TMP45 - _TMP7.xyz); + _r0338.x = dot(_TMP40, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.y = dot(_TMP42, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.z = dot(_TMP44, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0338.w = dot(_TMP46, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _a0350 = _r0338 - _r0132; + _TMP347 = abs(_a0350); + _res = _TMP40; + _mx = _TMP347.x; + if (_TMP347.y > _TMP347.x) { + _res = _TMP42; + _mx = _TMP347.y; + } + if (_TMP347.z > _mx) { + _res = _TMP44; + _mx = _TMP347.z; + } + if (_TMP347.w > _mx) { + _res = _TMP46; + } + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v4.0-noblend.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v4.0-noblend.glsl new file mode 100644 index 000000000..410aa5988 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr-v4.0-noblend.glsl @@ -0,0 +1,551 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +float _TMP60; +float _TMP59; +float _TMP58; +vec3 _TMP50; +vec3 _TMP52; +vec3 _TMP54; +vec3 _TMP56; +vec3 _TMP57; +vec3 _TMP55; +vec3 _TMP53; +vec3 _TMP51; +vec3 _TMP42; +vec3 _TMP44; +vec3 _TMP46; +vec3 _TMP48; +vec3 _TMP49; +vec3 _TMP47; +vec3 _TMP45; +vec3 _TMP43; +vec4 _TMP35; +vec4 _TMP34; +bvec4 _TMP33; +bvec4 _TMP32; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0081; +vec4 _r0125; +vec4 _r0135; +vec4 _r0145; +vec4 _r0155; +vec4 _r0165; +vec4 _r0175; +vec4 _TMP186; +vec4 _a0189; +vec4 _TMP192; +vec4 _a0195; +vec4 _TMP198; +vec4 _a0201; +vec4 _TMP204; +vec4 _a0207; +vec4 _TMP210; +vec4 _a0213; +vec4 _TMP216; +vec4 _a0219; +vec4 _TMP222; +vec4 _a0225; +vec4 _TMP228; +vec4 _a0231; +vec4 _TMP234; +vec4 _a0237; +vec4 _TMP240; +vec4 _a0243; +vec4 _TMP246; +vec4 _a0249; +vec4 _TMP252; +vec4 _a0255; +vec4 _TMP258; +vec4 _a0261; +vec4 _TMP264; +vec4 _a0267; +vec4 _TMP268; +vec4 _a0271; +vec4 _TMP272; +vec4 _a0275; +vec4 _TMP276; +vec4 _a0279; +vec4 _TMP280; +vec4 _a0283; +vec4 _TMP286; +vec4 _a0289; +vec4 _TMP290; +vec4 _a0293; +vec4 _TMP294; +vec4 _a0297; +vec4 _TMP298; +vec4 _a0301; +vec4 _TMP302; +vec4 _a0305; +vec4 _TMP306; +vec4 _a0309; +vec4 _TMP310; +vec4 _a0313; +vec4 _TMP314; +vec4 _a0317; +vec4 _TMP318; +vec4 _a0321; +vec4 _TMP322; +vec4 _a0325; +vec4 _TMP326; +vec4 _a0329; +vec3 _df0331; +vec3 _a0333; +vec3 _df0335; +vec3 _a0337; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _interp_restriction_lv3_left; + bvec4 _interp_restriction_lv3_up; + bvec4 _nc; + bvec4 _fx; + bvec4 _fx_left; + bvec4 _fx_up; + bvec4 _fx3_left; + bvec4 _fx3_up; + vec2 _fp; + vec3 _res; + _x0081 = TEX0.xy*TextureSize; + _fp = fract(_x0081); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0125.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0125.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0125.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0125.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0135.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0135.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0135.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0135.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0145.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0145.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0145.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0145.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0155.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0155.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0155.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0155.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0165.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0165.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0165.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0165.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0175.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0175.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0175.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0175.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.50000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 5.00000000E-01); + _fx_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -5.00000000E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 0.00000000E+00); + _fx_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 0.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.00000000E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 5.00000000E-01); + _fx3_left = bvec4((vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x).x > 5.00000000E+00, (vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x).y > 3.00000000E+00, (vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x).z > -3.00000000E+00, (vec4( 6.00000000E+00, -2.00000000E+00, -6.00000000E+00, 2.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 6.00000000E+00, -2.00000000E+00, -6.00000000E+00)*_fp.x).w > -1.00000000E+00); + _fx3_up = bvec4((vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x).x > 5.00000000E+00, (vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x).y > -1.00000000E+00, (vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x).z > -3.00000000E+00, (vec4( 2.00000000E+00, -6.00000000E+00, -2.00000000E+00, 6.00000000E+00)*_fp.y + vec4( 6.00000000E+00, 2.00000000E+00, -6.00000000E+00, -2.00000000E+00)*_fp.x).w > 3.00000000E+00); + _a0189 = _r0125.wxyz - _r0125; + _TMP186 = abs(_a0189); + _TMP21 = bvec4(_TMP186.x < 1.00000000E+01, _TMP186.y < 1.00000000E+01, _TMP186.z < 1.00000000E+01, _TMP186.w < 1.00000000E+01); + _a0195 = _r0125.zwxy - _r0125.yzwx; + _TMP192 = abs(_a0195); + _TMP22 = bvec4(_TMP192.x < 1.00000000E+01, _TMP192.y < 1.00000000E+01, _TMP192.z < 1.00000000E+01, _TMP192.w < 1.00000000E+01); + _a0201 = _r0145 - _r0135.wxyz; + _TMP198 = abs(_a0201); + _TMP23 = bvec4(_TMP198.x < 1.00000000E+01, _TMP198.y < 1.00000000E+01, _TMP198.z < 1.00000000E+01, _TMP198.w < 1.00000000E+01); + _a0207 = _r0125.wxyz - _r0155; + _TMP204 = abs(_a0207); + _TMP24 = bvec4(_TMP204.x < 1.00000000E+01, _TMP204.y < 1.00000000E+01, _TMP204.z < 1.00000000E+01, _TMP204.w < 1.00000000E+01); + _a0213 = _r0125.zwxy - _r0165; + _TMP210 = abs(_a0213); + _TMP25 = bvec4(_TMP210.x < 1.00000000E+01, _TMP210.y < 1.00000000E+01, _TMP210.z < 1.00000000E+01, _TMP210.w < 1.00000000E+01); + _a0219 = _r0145 - _r0135.zwxy; + _TMP216 = abs(_a0219); + _TMP26 = bvec4(_TMP216.x < 1.00000000E+01, _TMP216.y < 1.00000000E+01, _TMP216.z < 1.00000000E+01, _TMP216.w < 1.00000000E+01); + _a0225 = _r0145 - _r0135; + _TMP222 = abs(_a0225); + _TMP27 = bvec4(_TMP222.x < 1.00000000E+01, _TMP222.y < 1.00000000E+01, _TMP222.z < 1.00000000E+01, _TMP222.w < 1.00000000E+01); + _a0231 = _r0125 - _r0155.yzwx; + _TMP228 = abs(_a0231); + _TMP28 = bvec4(_TMP228.x < 1.00000000E+01, _TMP228.y < 1.00000000E+01, _TMP228.z < 1.00000000E+01, _TMP228.w < 1.00000000E+01); + _a0237 = _r0125.yzwx - _r0165.wxyz; + _TMP234 = abs(_a0237); + _TMP29 = bvec4(_TMP234.x < 1.00000000E+01, _TMP234.y < 1.00000000E+01, _TMP234.z < 1.00000000E+01, _TMP234.w < 1.00000000E+01); + _interp_restriction_lv1 = bvec4(_r0145.x != _r0125.w && _r0145.x != _r0125.z && (!_TMP21.x && !_TMP22.x || _TMP23.x && !_TMP24.x && !_TMP25.x || _TMP26.x || _TMP27.x) && (_r0125.w != _r0175.y && _r0125.w != _r0135.w || _r0125.z != _r0175.x && _r0125.z != _r0135.w || _r0125.z != _r0135.z || _r0125.w != _r0135.x || _TMP28.x && _TMP29.x), _r0145.y != _r0125.x && _r0145.y != _r0125.w && (!_TMP21.y && !_TMP22.y || _TMP23.y && !_TMP24.y && !_TMP25.y || _TMP26.y || _TMP27.y) && (_r0125.x != _r0175.z && _r0125.x != _r0135.x || _r0125.w != _r0175.y && _r0125.w != _r0135.x || _r0125.w != _r0135.w || _r0125.x != _r0135.y || _TMP28.y && _TMP29.y), _r0145.z != _r0125.y && _r0145.z != _r0125.x && (!_TMP21.z && !_TMP22.z || _TMP23.z && !_TMP24.z && !_TMP25.z || _TMP26.z || _TMP27.z) && (_r0125.y != _r0175.w && _r0125.y != _r0135.y || _r0125.x != _r0175.z && _r0125.x != _r0135.y || _r0125.x != _r0135.x || _r0125.y != _r0135.z || _TMP28.z && _TMP29.z), _r0145.w != _r0125.z && _r0145.w != _r0125.y && (!_TMP21.w && !_TMP22.w || _TMP23.w && !_TMP24.w && !_TMP25.w || _TMP26.w || _TMP27.w) && (_r0125.z != _r0175.x && _r0125.z != _r0135.z || _r0125.y != _r0175.w && _r0125.y != _r0135.z || _r0125.y != _r0135.y || _r0125.z != _r0135.w || _TMP28.w && _TMP29.w)); + _interp_restriction_lv2_left = bvec4(_r0145.x != _r0135.z && _r0125.y != _r0135.z, _r0145.y != _r0135.w && _r0125.z != _r0135.w, _r0145.z != _r0135.x && _r0125.w != _r0135.x, _r0145.w != _r0135.y && _r0125.x != _r0135.y); + _interp_restriction_lv2_up = bvec4(_r0145.x != _r0135.x && _r0125.x != _r0135.x, _r0145.y != _r0135.y && _r0125.y != _r0135.y, _r0145.z != _r0135.z && _r0125.z != _r0135.z, _r0145.w != _r0135.w && _r0125.w != _r0135.w); + _a0243 = _r0135.zwxy - _r0165.wxyz; + _TMP240 = abs(_a0243); + _TMP30 = bvec4(_TMP240.x < 2.00000000E+00, _TMP240.y < 2.00000000E+00, _TMP240.z < 2.00000000E+00, _TMP240.w < 2.00000000E+00); + _a0249 = _r0175.wxyz - _r0165.wxyz; + _TMP246 = abs(_a0249); + _TMP31 = bvec4(_TMP246.x < 2.00000000E+00, _TMP246.y < 2.00000000E+00, _TMP246.z < 2.00000000E+00, _TMP246.w < 2.00000000E+00); + _interp_restriction_lv3_left = bvec4(_TMP30.x && !_TMP31.x, _TMP30.y && !_TMP31.y, _TMP30.z && !_TMP31.z, _TMP30.w && !_TMP31.w); + _a0255 = _r0135 - _r0155.yzwx; + _TMP252 = abs(_a0255); + _TMP32 = bvec4(_TMP252.x < 2.00000000E+00, _TMP252.y < 2.00000000E+00, _TMP252.z < 2.00000000E+00, _TMP252.w < 2.00000000E+00); + _a0261 = _r0175.zwxy - _r0155.yzwx; + _TMP258 = abs(_a0261); + _TMP33 = bvec4(_TMP258.x < 2.00000000E+00, _TMP258.y < 2.00000000E+00, _TMP258.z < 2.00000000E+00, _TMP258.w < 2.00000000E+00); + _interp_restriction_lv3_up = bvec4(_TMP32.x && !_TMP33.x, _TMP32.y && !_TMP33.y, _TMP32.z && !_TMP33.z, _TMP32.w && !_TMP33.w); + _a0267 = _r0145 - _r0135; + _TMP264 = abs(_a0267); + _a0271 = _r0145 - _r0135.zwxy; + _TMP268 = abs(_a0271); + _a0275 = _r0135.wxyz - _r0175; + _TMP272 = abs(_a0275); + _a0279 = _r0135.wxyz - _r0175.yzwx; + _TMP276 = abs(_a0279); + _a0283 = _r0125.zwxy - _r0125.wxyz; + _TMP280 = abs(_a0283); + _TMP34 = _TMP264 + _TMP268 + _TMP272 + _TMP276 + 4.00000000E+00*_TMP280; + _a0289 = _r0125.zwxy - _r0125.yzwx; + _TMP286 = abs(_a0289); + _a0293 = _r0125.zwxy - _r0165; + _TMP290 = abs(_a0293); + _a0297 = _r0125.wxyz - _r0155; + _TMP294 = abs(_a0297); + _a0301 = _r0125.wxyz - _r0125; + _TMP298 = abs(_a0301); + _a0305 = _r0145 - _r0135.wxyz; + _TMP302 = abs(_a0305); + _TMP35 = _TMP286 + _TMP290 + _TMP294 + _TMP298 + 4.00000000E+00*_TMP302; + _edr = bvec4(_TMP34.x < _TMP35.x && _interp_restriction_lv1.x, _TMP34.y < _TMP35.y && _interp_restriction_lv1.y, _TMP34.z < _TMP35.z && _interp_restriction_lv1.z, _TMP34.w < _TMP35.w && _interp_restriction_lv1.w); + _a0309 = _r0125.wxyz - _r0135.zwxy; + _TMP306 = abs(_a0309); + _a0313 = _r0125.zwxy - _r0135; + _TMP310 = abs(_a0313); + _edr_left = bvec4((2.00000000E+00*_TMP306).x <= _TMP310.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP306).y <= _TMP310.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP306).z <= _TMP310.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP306).w <= _TMP310.w && _interp_restriction_lv2_left.w); + _a0317 = _r0125.wxyz - _r0135.zwxy; + _TMP314 = abs(_a0317); + _a0321 = _r0125.zwxy - _r0135; + _TMP318 = abs(_a0321); + _edr_up = bvec4(_TMP314.x >= (2.00000000E+00*_TMP318).x && _interp_restriction_lv2_up.x, _TMP314.y >= (2.00000000E+00*_TMP318).y && _interp_restriction_lv2_up.y, _TMP314.z >= (2.00000000E+00*_TMP318).z && _interp_restriction_lv2_up.z, _TMP314.w >= (2.00000000E+00*_TMP318).w && _interp_restriction_lv2_up.w); + _nc = bvec4(_edr.x && (_fx.x || _edr_left.x && (_fx_left.x || _interp_restriction_lv3_left.x && _fx3_left.x) || _edr_up.x && (_fx_up.x || _interp_restriction_lv3_up.x && _fx3_up.x)), _edr.y && (_fx.y || _edr_left.y && (_fx_left.y || _interp_restriction_lv3_left.y && _fx3_left.y) || _edr_up.y && (_fx_up.y || _interp_restriction_lv3_up.y && _fx3_up.y)), _edr.z && (_fx.z || _edr_left.z && (_fx_left.z || _interp_restriction_lv3_left.z && _fx3_left.z) || _edr_up.z && (_fx_up.z || _interp_restriction_lv3_up.z && _fx3_up.z)), _edr.w && (_fx.w || _edr_left.w && (_fx_left.w || _interp_restriction_lv3_left.w && _fx3_left.w) || _edr_up.w && (_fx_up.w || _interp_restriction_lv3_up.w && _fx3_up.w))); + _a0325 = _r0145 - _r0125.wxyz; + _TMP322 = abs(_a0325); + _a0329 = _r0145 - _r0125.zwxy; + _TMP326 = abs(_a0329); + _px = bvec4(_TMP322.x <= _TMP326.x, _TMP322.y <= _TMP326.y, _TMP322.z <= _TMP326.z, _TMP322.w <= _TMP326.w); + if (_nc.x) { + if (_px.x) { + _TMP43 = _TMP8.xyz; + } else { + _TMP43 = _TMP10.xyz; + } + _TMP42 = _TMP43; + } else { + if (_nc.y) { + if (_px.y) { + _TMP45 = _TMP4.xyz; + } else { + _TMP45 = _TMP8.xyz; + } + _TMP44 = _TMP45; + } else { + if (_nc.z) { + if (_px.z) { + _TMP47 = _TMP6.xyz; + } else { + _TMP47 = _TMP4.xyz; + } + _TMP46 = _TMP47; + } else { + if (_nc.w) { + if (_px.w) { + _TMP49 = _TMP10.xyz; + } else { + _TMP49 = _TMP6.xyz; + } + _TMP48 = _TMP49; + } else { + _TMP48 = _TMP7.xyz; + } + _TMP46 = _TMP48; + } + _TMP44 = _TMP46; + } + _TMP42 = _TMP44; + } + if (_nc.w) { + if (_px.w) { + _TMP51 = _TMP10.xyz; + } else { + _TMP51 = _TMP6.xyz; + } + _TMP50 = _TMP51; + } else { + if (_nc.z) { + if (_px.z) { + _TMP53 = _TMP6.xyz; + } else { + _TMP53 = _TMP4.xyz; + } + _TMP52 = _TMP53; + } else { + if (_nc.y) { + if (_px.y) { + _TMP55 = _TMP4.xyz; + } else { + _TMP55 = _TMP8.xyz; + } + _TMP54 = _TMP55; + } else { + if (_nc.x) { + if (_px.x) { + _TMP57 = _TMP8.xyz; + } else { + _TMP57 = _TMP10.xyz; + } + _TMP56 = _TMP57; + } else { + _TMP56 = _TMP7.xyz; + } + _TMP54 = _TMP56; + } + _TMP52 = _TMP54; + } + _TMP50 = _TMP52; + } + _a0333 = _TMP7.xyz - _TMP42; + _df0331 = abs(_a0333); + _TMP58 = _df0331.x + _df0331.y + _df0331.z; + _a0337 = _TMP7.xyz - _TMP50; + _df0335 = abs(_a0337); + _TMP59 = _df0335.x + _df0335.y + _df0335.z; + _TMP60 = float((_TMP59 >= _TMP58)); + _res = _TMP42 + _TMP60*(_TMP50 - _TMP42); + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr.glsl new file mode 100644 index 000000000..5f0fcfa15 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/5xbr.glsl @@ -0,0 +1,352 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _position1; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec4 _position1; + vec2 _texCoord2; + vec4 _t1; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0006; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0006 = VertexCoord.x*MVPMatrix[0]; + _r0006 = _r0006 + VertexCoord.y*MVPMatrix[1]; + _r0006 = _r0006 + VertexCoord.z*MVPMatrix[2]; + _r0006 = _r0006 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1.xy = vec2(0.00000000E+00, -_ps.y); + _OUT._t1.zw = vec2(-_ps.x, 0.00000000E+00); + _ret_0._position1 = _r0006; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + gl_Position = _r0006; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + return; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING float _frame_rotation; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +struct out_vertex { + vec2 _texCoord; + vec4 _t1; +}; +vec4 _ret_0; +vec3 _TMP16; +vec3 _TMP26; +vec3 _TMP36; +vec3 _TMP37; +vec3 _TMP38; +vec3 _TMP39; +vec3 _TMP27; +vec3 _TMP32; +vec3 _TMP33; +vec3 _TMP34; +vec3 _TMP35; +vec3 _TMP28; +vec3 _TMP29; +vec3 _TMP30; +vec3 _TMP31; +vec3 _TMP17; +vec3 _TMP22; +vec3 _TMP23; +vec3 _TMP24; +vec3 _TMP25; +vec3 _TMP18; +vec3 _TMP19; +vec3 _TMP20; +vec3 _TMP21; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +float _TMP7; +float _TMP6; +float _TMP5; +float _TMP4; +float _TMP3; +float _TMP2; +float _TMP1; +float _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0045; +vec2 _c0063; +vec2 _c0065; +vec2 _c0067; +vec2 _c0071; +vec2 _c0073; +vec2 _c0075; +vec2 _c0077; +float _TMP78; +float _TMP82; +float _TMP86; +float _TMP90; +float _TMP94; +float _TMP98; +float _TMP102; +float _TMP106; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec2 _fp; + vec2 _g1; + vec2 _g2; + vec3 _E14; + vec3 _E19; + vec3 _E24; + _x0045 = TEX0.xy*TextureSize; + _fp = fract(_x0045); + _TMP0 = float((_fp.x >= 5.00000000E-01)); + _TMP1 = float((_fp.y >= 5.00000000E-01)); + _TMP2 = float((_fp.x >= 5.00000000E-01)); + _TMP3 = float((_fp.y >= 5.00000000E-01)); + _g1 = TEX1.xy*((_TMP0 + _TMP1) - 1.00000000E+00) + TEX1.zw*(_TMP2 - _TMP3); + _TMP4 = float((_fp.y >= 5.00000000E-01)); + _TMP5 = float((_fp.x >= 5.00000000E-01)); + _TMP6 = float((_fp.x >= 5.00000000E-01)); + _TMP7 = float((_fp.y >= 5.00000000E-01)); + _g2 = TEX1.xy*(_TMP4 - _TMP5) + TEX1.zw*((_TMP6 + _TMP7) - 1.00000000E+00); + _c0063 = TEX0.xy + _g1; + _TMP8 = COMPAT_TEXTURE(Texture, _c0063); + _c0065 = (TEX0.xy + _g1) - _g2; + _TMP9 = COMPAT_TEXTURE(Texture, _c0065); + _c0067 = TEX0.xy + _g2; + _TMP10 = COMPAT_TEXTURE(Texture, _c0067); + _TMP11 = COMPAT_TEXTURE(Texture, TEX0.xy); + _c0071 = TEX0.xy - _g2; + _TMP12 = COMPAT_TEXTURE(Texture, _c0071); + _c0073 = (TEX0.xy - _g1) + _g2; + _TMP13 = COMPAT_TEXTURE(Texture, _c0073); + _c0075 = TEX0.xy - _g1; + _TMP14 = COMPAT_TEXTURE(Texture, _c0075); + _c0077 = (TEX0.xy - _g1) - _g2; + _TMP15 = COMPAT_TEXTURE(Texture, _c0077); + _E14 = _TMP11.xyz; + _E19 = _TMP11.xyz; + _E24 = _TMP11.xyz; + _TMP78 = dot(_TMP8.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP82 = dot(_TMP9.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP86 = dot(_TMP10.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP90 = dot(_TMP11.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP94 = dot(_TMP12.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP98 = dot(_TMP13.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP102 = dot(_TMP14.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + _TMP106 = dot(_TMP15.xyz, vec3( 6.55360000E+04, 2.55000000E+02, 1.00000000E+00)); + if (_TMP102 == _TMP94 && _TMP102 != _TMP90 && (_TMP90 == _TMP98 && (_TMP102 == _TMP106 || _TMP90 == _TMP86) || _TMP90 == _TMP82 && (_TMP102 == _TMP106 || _TMP90 == _TMP78))) { + _E24 = _TMP12.xyz; + _E19 = _TMP11.xyz + 8.75000000E-01*(_TMP12.xyz - _TMP11.xyz); + _E14 = _TMP11.xyz + 1.25000000E-01*(_TMP12.xyz - _TMP11.xyz); + } + if (_fp.x < 4.00000006E-01) { + if (_fp.x < 2.00000003E-01) { + if (_fp.y < 2.00000003E-01) { + _TMP18 = _E24; + } else { + if (_fp.y < 4.00000006E-01) { + _TMP19 = _E19; + } else { + if (_fp.y < 6.00000024E-01) { + _TMP20 = _E14; + } else { + if (_fp.y < 8.00000012E-01) { + _TMP21 = _E19; + } else { + _TMP21 = _E24; + } + _TMP20 = _TMP21; + } + _TMP19 = _TMP20; + } + _TMP18 = _TMP19; + } + _TMP17 = _TMP18; + } else { + if (_fp.y < 2.00000003E-01) { + _TMP22 = _E19; + } else { + if (_fp.y < 4.00000006E-01) { + _TMP23 = _E14; + } else { + if (_fp.y < 6.00000024E-01) { + _TMP24 = _TMP11.xyz; + } else { + if (_fp.y < 8.00000012E-01) { + _TMP25 = _E14; + } else { + _TMP25 = _E19; + } + _TMP24 = _TMP25; + } + _TMP23 = _TMP24; + } + _TMP22 = _TMP23; + } + _TMP17 = _TMP22; + } + _TMP16 = _TMP17; + } else { + if (_fp.x < 8.00000012E-01) { + if (_fp.x < 6.00000024E-01) { + if (_fp.y < 2.00000003E-01) { + _TMP28 = _E14; + } else { + if (_fp.y < 4.00000006E-01) { + _TMP29 = _TMP11.xyz; + } else { + if (_fp.y < 6.00000024E-01) { + _TMP30 = _TMP11.xyz; + } else { + if (_fp.y < 8.00000012E-01) { + _TMP31 = _TMP11.xyz; + } else { + _TMP31 = _E14; + } + _TMP30 = _TMP31; + } + _TMP29 = _TMP30; + } + _TMP28 = _TMP29; + } + _TMP27 = _TMP28; + } else { + if (_fp.y < 2.00000003E-01) { + _TMP32 = _E19; + } else { + if (_fp.y < 4.00000006E-01) { + _TMP33 = _E14; + } else { + if (_fp.y < 6.00000024E-01) { + _TMP34 = _TMP11.xyz; + } else { + if (_fp.y < 8.00000012E-01) { + _TMP35 = _E14; + } else { + _TMP35 = _E19; + } + _TMP34 = _TMP35; + } + _TMP33 = _TMP34; + } + _TMP32 = _TMP33; + } + _TMP27 = _TMP32; + } + _TMP26 = _TMP27; + } else { + if (_fp.y < 2.00000003E-01) { + _TMP36 = _E24; + } else { + if (_fp.y < 4.00000006E-01) { + _TMP37 = _E19; + } else { + if (_fp.y < 6.00000024E-01) { + _TMP38 = _E14; + } else { + if (_fp.y < 8.00000012E-01) { + _TMP39 = _E19; + } else { + _TMP39 = _E24; + } + _TMP38 = _TMP39; + } + _TMP37 = _TMP38; + } + _TMP36 = _TMP37; + } + _TMP26 = _TMP36; + } + _TMP16 = _TMP26; + } + _ret_0 = vec4(_TMP16.x, _TMP16.y, _TMP16.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-dilation.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-dilation.glsl new file mode 100644 index 000000000..73a64f74a --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-dilation.glsl @@ -0,0 +1,543 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +float _TMP59; +float _TMP58; +float _TMP57; +vec3 _TMP49; +vec3 _TMP51; +vec3 _TMP53; +vec3 _TMP55; +vec3 _TMP56; +vec3 _TMP54; +vec3 _TMP52; +vec3 _TMP50; +vec3 _TMP41; +vec3 _TMP43; +vec3 _TMP45; +vec3 _TMP47; +vec3 _TMP48; +vec3 _TMP46; +vec3 _TMP44; +vec3 _TMP42; +vec4 _TMP40; +vec4 _TMP33; +vec4 _TMP32; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0079; +vec4 _r0123; +vec4 _r0133; +vec4 _r0143; +vec4 _r0153; +vec4 _r0163; +vec4 _r0173; +vec4 _TMP184; +vec4 _a0187; +vec4 _TMP190; +vec4 _a0193; +vec4 _TMP196; +vec4 _a0199; +vec4 _TMP202; +vec4 _a0205; +vec4 _TMP208; +vec4 _a0211; +vec4 _TMP214; +vec4 _a0217; +vec4 _TMP220; +vec4 _a0223; +vec4 _TMP226; +vec4 _a0229; +vec4 _TMP232; +vec4 _a0235; +vec4 _TMP238; +vec4 _a0241; +vec4 _TMP244; +vec4 _a0247; +vec4 _TMP250; +vec4 _a0253; +vec4 _TMP254; +vec4 _a0257; +vec4 _TMP258; +vec4 _a0261; +vec4 _TMP262; +vec4 _a0265; +vec4 _TMP266; +vec4 _a0269; +vec4 _TMP272; +vec4 _a0275; +vec4 _TMP276; +vec4 _a0279; +vec4 _TMP280; +vec4 _a0283; +vec4 _TMP284; +vec4 _a0287; +vec4 _TMP288; +vec4 _a0291; +vec4 _TMP292; +vec4 _a0295; +vec4 _TMP296; +vec4 _a0299; +vec4 _TMP300; +vec4 _a0303; +vec4 _TMP304; +vec4 _a0307; +vec4 _TMP308; +vec4 _a0311; +vec4 _TMP312; +vec4 _a0315; +vec4 _t0317; +vec3 _df0319; +vec3 _a0321; +vec3 _df0323; +vec3 _a0325; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _fxd; + bvec4 _fxd_left; + bvec4 _fxd_up; + bvec4 _fxe; + bvec4 _fxe_left; + bvec4 _fxe_up; + vec2 _fp; + bvec4 _dilation; + vec3 _res; + _x0079 = TEX0.xy*TextureSize; + _fp = fract(_x0079); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0123.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0123.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0123.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0123.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0133.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0133.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0133.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0133.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0143.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0143.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0143.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0143.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0153.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0153.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0153.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0153.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0163.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0163.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0163.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0163.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0173.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0173.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0173.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0173.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fxd = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.29999995E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 3.00000012E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -6.99999988E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 3.00000012E-01); + _fxd_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 8.99999976E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 8.00000012E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -6.00000024E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > -2.00000003E-01); + _fxd_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 1.79999995E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > -1.00000001E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -1.20000005E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 4.00000006E-01); + _fxe = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).x > 1.70000005E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).y > 6.99999988E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).z > -3.00000012E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x).w > 6.99999988E-01); + _fxe_left = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).x > 1.10000002E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).y > 1.20000005E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).z > -4.00000006E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x).w > 2.00000003E-01); + _fxe_up = bvec4((vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).x > 2.20000005E+00, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).y > 1.00000001E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).z > -8.00000012E-01, (vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x).w > 6.00000024E-01); + _a0187 = _r0123.wxyz - _r0123; + _TMP184 = abs(_a0187); + _TMP21 = bvec4(_TMP184.x < 1.50000000E+01, _TMP184.y < 1.50000000E+01, _TMP184.z < 1.50000000E+01, _TMP184.w < 1.50000000E+01); + _a0193 = _r0123.wxyz - _r0133; + _TMP190 = abs(_a0193); + _TMP22 = bvec4(_TMP190.x < 1.50000000E+01, _TMP190.y < 1.50000000E+01, _TMP190.z < 1.50000000E+01, _TMP190.w < 1.50000000E+01); + _a0199 = _r0123.zwxy - _r0123.yzwx; + _TMP196 = abs(_a0199); + _TMP23 = bvec4(_TMP196.x < 1.50000000E+01, _TMP196.y < 1.50000000E+01, _TMP196.z < 1.50000000E+01, _TMP196.w < 1.50000000E+01); + _a0205 = _r0123.zwxy - _r0133.zwxy; + _TMP202 = abs(_a0205); + _TMP24 = bvec4(_TMP202.x < 1.50000000E+01, _TMP202.y < 1.50000000E+01, _TMP202.z < 1.50000000E+01, _TMP202.w < 1.50000000E+01); + _a0211 = _r0143 - _r0133.wxyz; + _TMP208 = abs(_a0211); + _TMP25 = bvec4(_TMP208.x < 1.50000000E+01, _TMP208.y < 1.50000000E+01, _TMP208.z < 1.50000000E+01, _TMP208.w < 1.50000000E+01); + _a0217 = _r0123.wxyz - _r0173.yzwx; + _TMP214 = abs(_a0217); + _TMP26 = bvec4(_TMP214.x < 1.50000000E+01, _TMP214.y < 1.50000000E+01, _TMP214.z < 1.50000000E+01, _TMP214.w < 1.50000000E+01); + _a0223 = _r0123.wxyz - _r0153; + _TMP220 = abs(_a0223); + _TMP27 = bvec4(_TMP220.x < 1.50000000E+01, _TMP220.y < 1.50000000E+01, _TMP220.z < 1.50000000E+01, _TMP220.w < 1.50000000E+01); + _a0229 = _r0123.zwxy - _r0173; + _TMP226 = abs(_a0229); + _TMP28 = bvec4(_TMP226.x < 1.50000000E+01, _TMP226.y < 1.50000000E+01, _TMP226.z < 1.50000000E+01, _TMP226.w < 1.50000000E+01); + _a0235 = _r0123.zwxy - _r0163; + _TMP232 = abs(_a0235); + _TMP29 = bvec4(_TMP232.x < 1.50000000E+01, _TMP232.y < 1.50000000E+01, _TMP232.z < 1.50000000E+01, _TMP232.w < 1.50000000E+01); + _a0241 = _r0143 - _r0133.zwxy; + _TMP238 = abs(_a0241); + _TMP30 = bvec4(_TMP238.x < 1.50000000E+01, _TMP238.y < 1.50000000E+01, _TMP238.z < 1.50000000E+01, _TMP238.w < 1.50000000E+01); + _a0247 = _r0143 - _r0133; + _TMP244 = abs(_a0247); + _TMP31 = bvec4(_TMP244.x < 1.50000000E+01, _TMP244.y < 1.50000000E+01, _TMP244.z < 1.50000000E+01, _TMP244.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0143.x != _r0123.w && _r0143.x != _r0123.z && (!_TMP21.x && !_TMP22.x || !_TMP23.x && !_TMP24.x || _TMP25.x && (!_TMP26.x && !_TMP27.x || !_TMP28.x && !_TMP29.x) || _TMP30.x || _TMP31.x), _r0143.y != _r0123.x && _r0143.y != _r0123.w && (!_TMP21.y && !_TMP22.y || !_TMP23.y && !_TMP24.y || _TMP25.y && (!_TMP26.y && !_TMP27.y || !_TMP28.y && !_TMP29.y) || _TMP30.y || _TMP31.y), _r0143.z != _r0123.y && _r0143.z != _r0123.x && (!_TMP21.z && !_TMP22.z || !_TMP23.z && !_TMP24.z || _TMP25.z && (!_TMP26.z && !_TMP27.z || !_TMP28.z && !_TMP29.z) || _TMP30.z || _TMP31.z), _r0143.w != _r0123.z && _r0143.w != _r0123.y && (!_TMP21.w && !_TMP22.w || !_TMP23.w && !_TMP24.w || _TMP25.w && (!_TMP26.w && !_TMP27.w || !_TMP28.w && !_TMP29.w) || _TMP30.w || _TMP31.w)); + _interp_restriction_lv2_left = bvec4(_r0143.x != _r0133.z && _r0123.y != _r0133.z, _r0143.y != _r0133.w && _r0123.z != _r0133.w, _r0143.z != _r0133.x && _r0123.w != _r0133.x, _r0143.w != _r0133.y && _r0123.x != _r0133.y); + _interp_restriction_lv2_up = bvec4(_r0143.x != _r0133.x && _r0123.x != _r0133.x, _r0143.y != _r0133.y && _r0123.y != _r0133.y, _r0143.z != _r0133.z && _r0123.z != _r0133.z, _r0143.w != _r0133.w && _r0123.w != _r0133.w); + _a0253 = _r0143 - _r0133; + _TMP250 = abs(_a0253); + _a0257 = _r0143 - _r0133.zwxy; + _TMP254 = abs(_a0257); + _a0261 = _r0133.wxyz - _r0173; + _TMP258 = abs(_a0261); + _a0265 = _r0133.wxyz - _r0173.yzwx; + _TMP262 = abs(_a0265); + _a0269 = _r0123.zwxy - _r0123.wxyz; + _TMP266 = abs(_a0269); + _TMP32 = _TMP250 + _TMP254 + _TMP258 + _TMP262 + 4.00000000E+00*_TMP266; + _a0275 = _r0123.zwxy - _r0123.yzwx; + _TMP272 = abs(_a0275); + _a0279 = _r0123.zwxy - _r0163; + _TMP276 = abs(_a0279); + _a0283 = _r0123.wxyz - _r0153; + _TMP280 = abs(_a0283); + _a0287 = _r0123.wxyz - _r0123; + _TMP284 = abs(_a0287); + _a0291 = _r0143 - _r0133.wxyz; + _TMP288 = abs(_a0291); + _TMP33 = _TMP272 + _TMP276 + _TMP280 + _TMP284 + 4.00000000E+00*_TMP288; + _edr = bvec4(_TMP32.x < _TMP33.x && _interp_restriction_lv1.x, _TMP32.y < _TMP33.y && _interp_restriction_lv1.y, _TMP32.z < _TMP33.z && _interp_restriction_lv1.z, _TMP32.w < _TMP33.w && _interp_restriction_lv1.w); + _a0295 = _r0123.wxyz - _r0133.zwxy; + _TMP292 = abs(_a0295); + _a0299 = _r0123.zwxy - _r0133; + _TMP296 = abs(_a0299); + _edr_left = bvec4((2.00000000E+00*_TMP292).x <= _TMP296.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP292).y <= _TMP296.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP292).z <= _TMP296.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP292).w <= _TMP296.w && _interp_restriction_lv2_left.w); + _a0303 = _r0123.wxyz - _r0133.zwxy; + _TMP300 = abs(_a0303); + _a0307 = _r0123.zwxy - _r0133; + _TMP304 = abs(_a0307); + _edr_up = bvec4(_TMP300.x >= (2.00000000E+00*_TMP304).x && _interp_restriction_lv2_up.x, _TMP300.y >= (2.00000000E+00*_TMP304).y && _interp_restriction_lv2_up.y, _TMP300.z >= (2.00000000E+00*_TMP304).z && _interp_restriction_lv2_up.z, _TMP300.w >= (2.00000000E+00*_TMP304).w && _interp_restriction_lv2_up.w); + _a0311 = _r0143 - _r0123.wxyz; + _TMP308 = abs(_a0311); + _a0315 = _r0143 - _r0123.zwxy; + _TMP312 = abs(_a0315); + _px = bvec4(_TMP308.x <= _TMP312.x, _TMP308.y <= _TMP312.y, _TMP308.z <= _TMP312.z, _TMP308.w <= _TMP312.w); + _t0317 = vec4(float(_px.x), float(_px.y), float(_px.z), float(_px.w)); + _TMP40 = _r0123.zwxy + _t0317*(_r0123.wxyz - _r0123.zwxy); + _dilation = bvec4(_TMP40.x > _r0143.x, _TMP40.y > _r0143.y, _TMP40.z > _r0143.z, _TMP40.w > _r0143.w); + _nc = bvec4(_dilation.x && _edr.x && (_fxd.x || _edr_left.x && _fxd_left.x || _edr_up.x && _fxd_up.x) || !_dilation.x && _edr.x && (_fxe.x || _edr_left.x && _fxe_left.x || _edr_up.x && _fxe_up.x), _dilation.y && _edr.y && (_fxd.y || _edr_left.y && _fxd_left.y || _edr_up.y && _fxd_up.y) || !_dilation.y && _edr.y && (_fxe.y || _edr_left.y && _fxe_left.y || _edr_up.y && _fxe_up.y), _dilation.z && _edr.z && (_fxd.z || _edr_left.z && _fxd_left.z || _edr_up.z && _fxd_up.z) || !_dilation.z && _edr.z && (_fxe.z || _edr_left.z && _fxe_left.z || _edr_up.z && _fxe_up.z), _dilation.w && _edr.w && (_fxd.w || _edr_left.w && _fxd_left.w || _edr_up.w && _fxd_up.w) || !_dilation.w && _edr.w && (_fxe.w || _edr_left.w && _fxe_left.w || _edr_up.w && _fxe_up.w)); + if (_nc.x) { + if (_px.x) { + _TMP42 = _TMP8.xyz; + } else { + _TMP42 = _TMP10.xyz; + } + _TMP41 = _TMP42; + } else { + if (_nc.y) { + if (_px.y) { + _TMP44 = _TMP4.xyz; + } else { + _TMP44 = _TMP8.xyz; + } + _TMP43 = _TMP44; + } else { + if (_nc.z) { + if (_px.z) { + _TMP46 = _TMP6.xyz; + } else { + _TMP46 = _TMP4.xyz; + } + _TMP45 = _TMP46; + } else { + if (_nc.w) { + if (_px.w) { + _TMP48 = _TMP10.xyz; + } else { + _TMP48 = _TMP6.xyz; + } + _TMP47 = _TMP48; + } else { + _TMP47 = _TMP7.xyz; + } + _TMP45 = _TMP47; + } + _TMP43 = _TMP45; + } + _TMP41 = _TMP43; + } + if (_nc.w) { + if (_px.w) { + _TMP50 = _TMP10.xyz; + } else { + _TMP50 = _TMP6.xyz; + } + _TMP49 = _TMP50; + } else { + if (_nc.z) { + if (_px.z) { + _TMP52 = _TMP6.xyz; + } else { + _TMP52 = _TMP4.xyz; + } + _TMP51 = _TMP52; + } else { + if (_nc.y) { + if (_px.y) { + _TMP54 = _TMP4.xyz; + } else { + _TMP54 = _TMP8.xyz; + } + _TMP53 = _TMP54; + } else { + if (_nc.x) { + if (_px.x) { + _TMP56 = _TMP8.xyz; + } else { + _TMP56 = _TMP10.xyz; + } + _TMP55 = _TMP56; + } else { + _TMP55 = _TMP7.xyz; + } + _TMP53 = _TMP55; + } + _TMP51 = _TMP53; + } + _TMP49 = _TMP51; + } + _a0321 = _TMP7.xyz - _TMP41; + _df0319 = abs(_a0321); + _TMP57 = _df0319.x + _df0319.y + _df0319.z; + _a0325 = _TMP7.xyz - _TMP49; + _df0323 = abs(_a0325); + _TMP58 = _df0323.x + _df0323.y + _df0323.z; + _TMP59 = float((_TMP58 >= _TMP57)); + _res = _TMP41 + _TMP59*(_TMP49 - _TMP41); + _ret_0 = vec4(_res.x, _res.y, _res.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-v3.8c-gamma.glsl b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-v3.8c-gamma.glsl new file mode 100644 index 000000000..01c9d1a55 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/rpi/shaders/xbr/xbr-v3.8c-gamma.glsl @@ -0,0 +1,594 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord2; +COMPAT_VARYING vec4 _color1; +COMPAT_VARYING vec4 _position1; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _position1; + vec4 _color1; + vec2 _texCoord2; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +out_vertex _ret_0; +input_dummy _IN1; +vec4 _r0008; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + out_vertex _OUT; + vec2 _ps; + vec2 _texCoord; + _r0008 = VertexCoord.x*MVPMatrix[0]; + _r0008 = _r0008 + VertexCoord.y*MVPMatrix[1]; + _r0008 = _r0008 + VertexCoord.z*MVPMatrix[2]; + _r0008 = _r0008 + VertexCoord.w*MVPMatrix[3]; + _ps = vec2(1.00000000E+00/TextureSize.x, 1.00000000E+00/TextureSize.y); + _texCoord = TexCoord.xy + vec2( 1.00000001E-07, 1.00000001E-07); + _OUT._t1 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -2.00000000E+00*_ps.y); + _OUT._t2 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, -_ps.y); + _OUT._t3 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 0.00000000E+00); + _OUT._t4 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, _ps.y); + _OUT._t5 = _texCoord.xxxy + vec4(-_ps.x, 0.00000000E+00, _ps.x, 2.00000000E+00*_ps.y); + _OUT._t6 = _texCoord.xyyy + vec4(-2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _OUT._t7 = _texCoord.xyyy + vec4(2.00000000E+00*_ps.x, -_ps.y, 0.00000000E+00, _ps.y); + _ret_0._position1 = _r0008; + _ret_0._color1 = COLOR; + _ret_0._texCoord2 = _texCoord; + _ret_0._t1 = _OUT._t1; + _ret_0._t2 = _OUT._t2; + _ret_0._t3 = _OUT._t3; + _ret_0._t4 = _OUT._t4; + _ret_0._t5 = _OUT._t5; + _ret_0._t6 = _OUT._t6; + _ret_0._t7 = _OUT._t7; + gl_Position = _r0008; + COL0 = COLOR; + TEX0.xy = _texCoord; + TEX1 = _OUT._t1; + TEX2 = _OUT._t2; + TEX3 = _OUT._t3; + TEX4 = _OUT._t4; + TEX5 = _OUT._t5; + TEX6 = _OUT._t6; + TEX7 = _OUT._t7; + return; + COL0 = _ret_0._color1; + TEX0.xy = _ret_0._texCoord2; + TEX1 = _ret_0._t1; + TEX2 = _ret_0._t2; + TEX3 = _ret_0._t3; + TEX4 = _ret_0._t4; + TEX5 = _ret_0._t5; + TEX6 = _ret_0._t6; + TEX7 = _ret_0._t7; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING vec4 _t7; +COMPAT_VARYING vec4 _t6; +COMPAT_VARYING vec4 _t5; +COMPAT_VARYING vec4 _t4; +COMPAT_VARYING vec4 _t3; +COMPAT_VARYING vec4 _t2; +COMPAT_VARYING vec4 _t1; +COMPAT_VARYING vec2 _texCoord; +COMPAT_VARYING vec4 _color; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; +}; +struct out_vertex { + vec4 _color; + vec2 _texCoord; + vec4 _t1; + vec4 _t2; + vec4 _t3; + vec4 _t4; + vec4 _t5; + vec4 _t6; + vec4 _t7; +}; +vec4 _ret_0; +vec3 _TMP54; +vec3 _TMP65; +float _TMP64; +float _TMP63; +float _TMP62; +float _TMP53; +float _TMP52; +float _TMP51; +vec3 _TMP50; +vec3 _TMP49; +vec3 _TMP48; +vec3 _TMP47; +vec3 _TMP46; +vec3 _TMP45; +vec3 _TMP44; +vec3 _TMP43; +vec3 _TMP42; +vec3 _TMP41; +vec4 _TMP40; +vec4 _TMP33; +vec4 _TMP32; +vec4 _TMP66; +bvec4 _TMP31; +bvec4 _TMP30; +bvec4 _TMP29; +bvec4 _TMP28; +bvec4 _TMP27; +bvec4 _TMP26; +bvec4 _TMP25; +bvec4 _TMP24; +bvec4 _TMP23; +bvec4 _TMP22; +bvec4 _TMP21; +vec4 _TMP20; +vec4 _TMP19; +vec4 _TMP18; +vec4 _TMP17; +vec4 _TMP16; +vec4 _TMP15; +vec4 _TMP14; +vec4 _TMP13; +vec4 _TMP12; +vec4 _TMP11; +vec4 _TMP10; +vec4 _TMP9; +vec4 _TMP8; +vec4 _TMP7; +vec4 _TMP6; +vec4 _TMP5; +vec4 _TMP4; +vec4 _TMP3; +vec4 _TMP2; +vec4 _TMP1; +vec4 _TMP0; +uniform sampler2D Texture; +input_dummy _IN1; +vec2 _x0080; +vec4 _r0124; +vec4 _r0134; +vec4 _r0144; +vec4 _r0154; +vec4 _r0164; +vec4 _r0174; +vec4 _TMP185; +vec4 _a0188; +vec4 _TMP191; +vec4 _a0194; +vec4 _TMP197; +vec4 _a0200; +vec4 _TMP203; +vec4 _a0206; +vec4 _TMP209; +vec4 _a0212; +vec4 _TMP215; +vec4 _a0218; +vec4 _TMP221; +vec4 _a0224; +vec4 _TMP227; +vec4 _a0230; +vec4 _TMP233; +vec4 _a0236; +vec4 _TMP239; +vec4 _a0242; +vec4 _TMP245; +vec4 _a0248; +vec4 _x0252; +vec4 _TMP253; +vec4 _x0262; +vec4 _TMP263; +vec4 _x0272; +vec4 _TMP273; +vec4 _TMP281; +vec4 _a0284; +vec4 _TMP285; +vec4 _a0288; +vec4 _TMP289; +vec4 _a0292; +vec4 _TMP293; +vec4 _a0296; +vec4 _TMP297; +vec4 _a0300; +vec4 _TMP303; +vec4 _a0306; +vec4 _TMP307; +vec4 _a0310; +vec4 _TMP311; +vec4 _a0314; +vec4 _TMP315; +vec4 _a0318; +vec4 _TMP319; +vec4 _a0322; +vec4 _TMP323; +vec4 _a0326; +vec4 _TMP327; +vec4 _a0330; +vec4 _TMP331; +vec4 _a0334; +vec4 _TMP335; +vec4 _a0338; +vec4 _TMP339; +vec4 _a0342; +vec4 _TMP343; +vec4 _a0346; +vec3 _df0380; +vec3 _a0382; +vec3 _df0384; +vec3 _a0386; +vec3 _TMP399; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 TEX1; +COMPAT_VARYING vec4 TEX2; +COMPAT_VARYING vec4 TEX3; +COMPAT_VARYING vec4 TEX4; +COMPAT_VARYING vec4 TEX5; +COMPAT_VARYING vec4 TEX6; +COMPAT_VARYING vec4 TEX7; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + bvec4 _edr; + bvec4 _edr_left; + bvec4 _edr_up; + bvec4 _px; + bvec4 _interp_restriction_lv1; + bvec4 _interp_restriction_lv2_left; + bvec4 _interp_restriction_lv2_up; + bvec4 _nc; + bvec4 _nc30; + bvec4 _nc60; + bvec4 _nc45; + vec4 _fx; + vec4 _fx_left; + vec4 _fx_up; + vec3 _res1; + vec3 _res2; + vec3 _pix1; + vec3 _pix2; + float _blend1; + float _blend2; + vec2 _fp; + vec3 _E; + vec4 _fx45; + vec4 _fx30; + vec4 _fx60; + vec4 _final45; + vec4 _final30; + vec4 _final60; + vec4 _maximo; + vec3 _res; + _x0080 = TEX0.xy*TextureSize; + _fp = fract(_x0080); + _TMP0 = COMPAT_TEXTURE(Texture, TEX1.xw); + _TMP1 = COMPAT_TEXTURE(Texture, TEX1.yw); + _TMP2 = COMPAT_TEXTURE(Texture, TEX1.zw); + _TMP3 = COMPAT_TEXTURE(Texture, TEX2.xw); + _TMP4 = COMPAT_TEXTURE(Texture, TEX2.yw); + _TMP5 = COMPAT_TEXTURE(Texture, TEX2.zw); + _TMP6 = COMPAT_TEXTURE(Texture, TEX3.xw); + _TMP7 = COMPAT_TEXTURE(Texture, TEX3.yw); + _TMP8 = COMPAT_TEXTURE(Texture, TEX3.zw); + _TMP9 = COMPAT_TEXTURE(Texture, TEX4.xw); + _TMP10 = COMPAT_TEXTURE(Texture, TEX4.yw); + _TMP11 = COMPAT_TEXTURE(Texture, TEX4.zw); + _TMP12 = COMPAT_TEXTURE(Texture, TEX5.xw); + _TMP13 = COMPAT_TEXTURE(Texture, TEX5.yw); + _TMP14 = COMPAT_TEXTURE(Texture, TEX5.zw); + _TMP15 = COMPAT_TEXTURE(Texture, TEX6.xy); + _TMP16 = COMPAT_TEXTURE(Texture, TEX6.xz); + _TMP17 = COMPAT_TEXTURE(Texture, TEX6.xw); + _TMP18 = COMPAT_TEXTURE(Texture, TEX7.xy); + _TMP19 = COMPAT_TEXTURE(Texture, TEX7.xz); + _TMP20 = COMPAT_TEXTURE(Texture, TEX7.xw); + _r0124.x = dot(_TMP4.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0124.y = dot(_TMP6.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0124.z = dot(_TMP10.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0124.w = dot(_TMP8.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0134.x = dot(_TMP5.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0134.y = dot(_TMP3.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0134.z = dot(_TMP9.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0134.w = dot(_TMP11.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0144.x = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0144.y = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0144.z = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0144.w = dot(_TMP7.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0154.x = dot(_TMP20.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0154.y = dot(_TMP2.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0154.z = dot(_TMP15.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0154.w = dot(_TMP12.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0164.x = dot(_TMP14.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0164.y = dot(_TMP18.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0164.z = dot(_TMP0.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0164.w = dot(_TMP17.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0174.x = dot(_TMP13.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0174.y = dot(_TMP19.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0174.z = dot(_TMP1.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _r0174.w = dot(_TMP16.xyz, vec3( 1.43519993E+01, 2.81760006E+01, 5.47200012E+00)); + _fx = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 1.00000000E+00, 1.00000000E+00, -1.00000000E+00, -1.00000000E+00)*_fp.x; + _fx_left = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 5.00000000E-01, 2.00000000E+00, -5.00000000E-01, -2.00000000E+00)*_fp.x; + _fx_up = vec4( 1.00000000E+00, -1.00000000E+00, -1.00000000E+00, 1.00000000E+00)*_fp.y + vec4( 2.00000000E+00, 5.00000000E-01, -2.00000000E+00, -5.00000000E-01)*_fp.x; + _a0188 = _r0124.wxyz - _r0124; + _TMP185 = abs(_a0188); + _TMP21 = bvec4(_TMP185.x < 1.50000000E+01, _TMP185.y < 1.50000000E+01, _TMP185.z < 1.50000000E+01, _TMP185.w < 1.50000000E+01); + _a0194 = _r0124.wxyz - _r0134; + _TMP191 = abs(_a0194); + _TMP22 = bvec4(_TMP191.x < 1.50000000E+01, _TMP191.y < 1.50000000E+01, _TMP191.z < 1.50000000E+01, _TMP191.w < 1.50000000E+01); + _a0200 = _r0124.zwxy - _r0124.yzwx; + _TMP197 = abs(_a0200); + _TMP23 = bvec4(_TMP197.x < 1.50000000E+01, _TMP197.y < 1.50000000E+01, _TMP197.z < 1.50000000E+01, _TMP197.w < 1.50000000E+01); + _a0206 = _r0124.zwxy - _r0134.zwxy; + _TMP203 = abs(_a0206); + _TMP24 = bvec4(_TMP203.x < 1.50000000E+01, _TMP203.y < 1.50000000E+01, _TMP203.z < 1.50000000E+01, _TMP203.w < 1.50000000E+01); + _a0212 = _r0144 - _r0134.wxyz; + _TMP209 = abs(_a0212); + _TMP25 = bvec4(_TMP209.x < 1.50000000E+01, _TMP209.y < 1.50000000E+01, _TMP209.z < 1.50000000E+01, _TMP209.w < 1.50000000E+01); + _a0218 = _r0124.wxyz - _r0174.yzwx; + _TMP215 = abs(_a0218); + _TMP26 = bvec4(_TMP215.x < 1.50000000E+01, _TMP215.y < 1.50000000E+01, _TMP215.z < 1.50000000E+01, _TMP215.w < 1.50000000E+01); + _a0224 = _r0124.wxyz - _r0154; + _TMP221 = abs(_a0224); + _TMP27 = bvec4(_TMP221.x < 1.50000000E+01, _TMP221.y < 1.50000000E+01, _TMP221.z < 1.50000000E+01, _TMP221.w < 1.50000000E+01); + _a0230 = _r0124.zwxy - _r0174; + _TMP227 = abs(_a0230); + _TMP28 = bvec4(_TMP227.x < 1.50000000E+01, _TMP227.y < 1.50000000E+01, _TMP227.z < 1.50000000E+01, _TMP227.w < 1.50000000E+01); + _a0236 = _r0124.zwxy - _r0164; + _TMP233 = abs(_a0236); + _TMP29 = bvec4(_TMP233.x < 1.50000000E+01, _TMP233.y < 1.50000000E+01, _TMP233.z < 1.50000000E+01, _TMP233.w < 1.50000000E+01); + _a0242 = _r0144 - _r0134.zwxy; + _TMP239 = abs(_a0242); + _TMP30 = bvec4(_TMP239.x < 1.50000000E+01, _TMP239.y < 1.50000000E+01, _TMP239.z < 1.50000000E+01, _TMP239.w < 1.50000000E+01); + _a0248 = _r0144 - _r0134; + _TMP245 = abs(_a0248); + _TMP31 = bvec4(_TMP245.x < 1.50000000E+01, _TMP245.y < 1.50000000E+01, _TMP245.z < 1.50000000E+01, _TMP245.w < 1.50000000E+01); + _interp_restriction_lv1 = bvec4(_r0144.x != _r0124.w && _r0144.x != _r0124.z && (!_TMP21.x && !_TMP22.x || !_TMP23.x && !_TMP24.x || _TMP25.x && (!_TMP26.x && !_TMP27.x || !_TMP28.x && !_TMP29.x) || _TMP30.x || _TMP31.x), _r0144.y != _r0124.x && _r0144.y != _r0124.w && (!_TMP21.y && !_TMP22.y || !_TMP23.y && !_TMP24.y || _TMP25.y && (!_TMP26.y && !_TMP27.y || !_TMP28.y && !_TMP29.y) || _TMP30.y || _TMP31.y), _r0144.z != _r0124.y && _r0144.z != _r0124.x && (!_TMP21.z && !_TMP22.z || !_TMP23.z && !_TMP24.z || _TMP25.z && (!_TMP26.z && !_TMP27.z || !_TMP28.z && !_TMP29.z) || _TMP30.z || _TMP31.z), _r0144.w != _r0124.z && _r0144.w != _r0124.y && (!_TMP21.w && !_TMP22.w || !_TMP23.w && !_TMP24.w || _TMP25.w && (!_TMP26.w && !_TMP27.w || !_TMP28.w && !_TMP29.w) || _TMP30.w || _TMP31.w)); + _interp_restriction_lv2_left = bvec4(_r0144.x != _r0134.z && _r0124.y != _r0134.z, _r0144.y != _r0134.w && _r0124.z != _r0134.w, _r0144.z != _r0134.x && _r0124.w != _r0134.x, _r0144.w != _r0134.y && _r0124.x != _r0134.y); + _interp_restriction_lv2_up = bvec4(_r0144.x != _r0134.x && _r0124.x != _r0134.x, _r0144.y != _r0134.y && _r0124.y != _r0134.y, _r0144.z != _r0134.z && _r0124.z != _r0134.z, _r0144.w != _r0134.w && _r0124.w != _r0134.w); + _x0252 = (_fx - vec4( 1.10000002E+00, 9.99999940E-02, -8.99999976E-01, 9.99999940E-02))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 7.99999952E-01); + _TMP66 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0252); + _TMP253 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP66); + _fx45 = _TMP253*_TMP253*(3.00000000E+00 - 2.00000000E+00*_TMP253); + _x0262 = (_fx_left - vec4( 6.00000024E-01, 6.00000024E-01, -8.99999976E-01, -4.00000006E-01))/vec4( 7.99999952E-01, 7.99999952E-01, 7.99999952E-01, 8.00000012E-01); + _TMP66 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0262); + _TMP263 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP66); + _fx30 = _TMP263*_TMP263*(3.00000000E+00 - 2.00000000E+00*_TMP263); + _x0272 = (_fx_up - vec4( 1.60000002E+00, -4.00000006E-01, -1.39999998E+00, 9.99999940E-02))/vec4( 8.00000072E-01, 8.00000012E-01, 7.99999952E-01, 7.99999952E-01); + _TMP66 = min(vec4( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _x0272); + _TMP273 = max(vec4( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP66); + _fx60 = _TMP273*_TMP273*(3.00000000E+00 - 2.00000000E+00*_TMP273); + _a0284 = _r0144 - _r0134; + _TMP281 = abs(_a0284); + _a0288 = _r0144 - _r0134.zwxy; + _TMP285 = abs(_a0288); + _a0292 = _r0134.wxyz - _r0174; + _TMP289 = abs(_a0292); + _a0296 = _r0134.wxyz - _r0174.yzwx; + _TMP293 = abs(_a0296); + _a0300 = _r0124.zwxy - _r0124.wxyz; + _TMP297 = abs(_a0300); + _TMP32 = _TMP281 + _TMP285 + _TMP289 + _TMP293 + 4.00000000E+00*_TMP297; + _a0306 = _r0124.zwxy - _r0124.yzwx; + _TMP303 = abs(_a0306); + _a0310 = _r0124.zwxy - _r0164; + _TMP307 = abs(_a0310); + _a0314 = _r0124.wxyz - _r0154; + _TMP311 = abs(_a0314); + _a0318 = _r0124.wxyz - _r0124; + _TMP315 = abs(_a0318); + _a0322 = _r0144 - _r0134.wxyz; + _TMP319 = abs(_a0322); + _TMP33 = _TMP303 + _TMP307 + _TMP311 + _TMP315 + 4.00000000E+00*_TMP319; + _edr = bvec4(_TMP32.x < _TMP33.x && _interp_restriction_lv1.x, _TMP32.y < _TMP33.y && _interp_restriction_lv1.y, _TMP32.z < _TMP33.z && _interp_restriction_lv1.z, _TMP32.w < _TMP33.w && _interp_restriction_lv1.w); + _a0326 = _r0124.wxyz - _r0134.zwxy; + _TMP323 = abs(_a0326); + _a0330 = _r0124.zwxy - _r0134; + _TMP327 = abs(_a0330); + _edr_left = bvec4((2.00000000E+00*_TMP323).x <= _TMP327.x && _interp_restriction_lv2_left.x, (2.00000000E+00*_TMP323).y <= _TMP327.y && _interp_restriction_lv2_left.y, (2.00000000E+00*_TMP323).z <= _TMP327.z && _interp_restriction_lv2_left.z, (2.00000000E+00*_TMP323).w <= _TMP327.w && _interp_restriction_lv2_left.w); + _a0334 = _r0124.wxyz - _r0134.zwxy; + _TMP331 = abs(_a0334); + _a0338 = _r0124.zwxy - _r0134; + _TMP335 = abs(_a0338); + _edr_up = bvec4(_TMP331.x >= (2.00000000E+00*_TMP335).x && _interp_restriction_lv2_up.x, _TMP331.y >= (2.00000000E+00*_TMP335).y && _interp_restriction_lv2_up.y, _TMP331.z >= (2.00000000E+00*_TMP335).z && _interp_restriction_lv2_up.z, _TMP331.w >= (2.00000000E+00*_TMP335).w && _interp_restriction_lv2_up.w); + _nc45 = bvec4(_edr.x && bool(_fx45.x), _edr.y && bool(_fx45.y), _edr.z && bool(_fx45.z), _edr.w && bool(_fx45.w)); + _nc30 = bvec4(_edr.x && _edr_left.x && bool(_fx30.x), _edr.y && _edr_left.y && bool(_fx30.y), _edr.z && _edr_left.z && bool(_fx30.z), _edr.w && _edr_left.w && bool(_fx30.w)); + _nc60 = bvec4(_edr.x && _edr_up.x && bool(_fx60.x), _edr.y && _edr_up.y && bool(_fx60.y), _edr.z && _edr_up.z && bool(_fx60.z), _edr.w && _edr_up.w && bool(_fx60.w)); + _a0342 = _r0144 - _r0124.wxyz; + _TMP339 = abs(_a0342); + _a0346 = _r0144 - _r0124.zwxy; + _TMP343 = abs(_a0346); + _px = bvec4(_TMP339.x <= _TMP343.x, _TMP339.y <= _TMP343.y, _TMP339.z <= _TMP343.z, _TMP339.w <= _TMP343.w); + _nc = bvec4(_nc30.x || _nc60.x || _nc45.x, _nc30.y || _nc60.y || _nc45.y, _nc30.z || _nc60.z || _nc45.z, _nc30.w || _nc60.w || _nc45.w); + _final45 = vec4(float(_nc45.x), float(_nc45.y), float(_nc45.z), float(_nc45.w))*_fx45; + _final30 = vec4(float(_nc30.x), float(_nc30.y), float(_nc30.z), float(_nc30.w))*_fx30; + _final60 = vec4(float(_nc60.x), float(_nc60.y), float(_nc60.z), float(_nc60.w))*_fx60; + _TMP40 = max(_final30, _final60); + _maximo = max(_TMP40, _final45); + if (_nc.x) { + if (_px.x) { + _TMP41 = _TMP8.xyz; + } else { + _TMP41 = _TMP10.xyz; + } + _pix1 = _TMP41; + _blend1 = _maximo.x; + } else { + if (_nc.y) { + if (_px.y) { + _TMP42 = _TMP4.xyz; + } else { + _TMP42 = _TMP8.xyz; + } + _pix1 = _TMP42; + _blend1 = _maximo.y; + } else { + if (_nc.z) { + if (_px.z) { + _TMP43 = _TMP6.xyz; + } else { + _TMP43 = _TMP4.xyz; + } + _pix1 = _TMP43; + _blend1 = _maximo.z; + } else { + if (_nc.w) { + if (_px.w) { + _TMP44 = _TMP10.xyz; + } else { + _TMP44 = _TMP6.xyz; + } + _pix1 = _TMP44; + _blend1 = _maximo.w; + } + } + } + } + if (_nc.w) { + if (_px.w) { + _TMP45 = _TMP10.xyz; + } else { + _TMP45 = _TMP6.xyz; + } + _pix2 = _TMP45; + _blend2 = _maximo.w; + } else { + if (_nc.z) { + if (_px.z) { + _TMP46 = _TMP6.xyz; + } else { + _TMP46 = _TMP4.xyz; + } + _pix2 = _TMP46; + _blend2 = _maximo.z; + } else { + if (_nc.y) { + if (_px.y) { + _TMP47 = _TMP4.xyz; + } else { + _TMP47 = _TMP8.xyz; + } + _pix2 = _TMP47; + _blend2 = _maximo.y; + } else { + if (_nc.x) { + if (_px.x) { + _TMP48 = _TMP8.xyz; + } else { + _TMP48 = _TMP10.xyz; + } + _pix2 = _TMP48; + _blend2 = _maximo.x; + } + } + } + } + _TMP62 = pow(_TMP7.x, 2.40000010E+00); + _TMP63 = pow(_TMP7.y, 2.40000010E+00); + _TMP64 = pow(_TMP7.z, 2.40000010E+00); + _E = vec3(_TMP62, _TMP63, _TMP64); + _TMP62 = pow(_pix1.x, 2.40000010E+00); + _TMP63 = pow(_pix1.y, 2.40000010E+00); + _TMP64 = pow(_pix1.z, 2.40000010E+00); + _TMP49 = vec3(_TMP62, _TMP63, _TMP64); + _res1 = _E + _blend1*(_TMP49 - _E); + _TMP62 = pow(_pix2.x, 2.40000010E+00); + _TMP63 = pow(_pix2.y, 2.40000010E+00); + _TMP64 = pow(_pix2.z, 2.40000010E+00); + _TMP50 = vec3(_TMP62, _TMP63, _TMP64); + _res2 = _E + _blend2*(_TMP50 - _E); + _a0382 = _E - _res1; + _df0380 = abs(_a0382); + _TMP51 = _df0380.x + _df0380.y + _df0380.z; + _a0386 = _E - _res2; + _df0384 = abs(_a0386); + _TMP52 = _df0384.x + _df0384.y + _df0384.z; + _TMP53 = float((_TMP52 >= _TMP51)); + _res = _res1 + _TMP53*(_res2 - _res1); + _TMP62 = pow(_res.x, 4.54545438E-01); + _TMP63 = pow(_res.y, 4.54545438E-01); + _TMP64 = pow(_res.z, 4.54545438E-01); + _TMP54 = vec3(_TMP62, _TMP63, _TMP64); + _TMP65 = min(vec3( 1.00000000E+00, 1.00000000E+00, 1.00000000E+00), _TMP54); + _TMP399 = max(vec3( 0.00000000E+00, 0.00000000E+00, 0.00000000E+00), _TMP65); + _ret_0 = vec4(_TMP399.x, _TMP399.y, _TMP399.z, 1.00000000E+00); + FragColor = _ret_0; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-scanlines.glsl b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-scanlines.glsl new file mode 100644 index 000000000..535202f1b --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-scanlines.glsl @@ -0,0 +1,150 @@ +/* + Author: rsn8887 (based on TheMaister) + License: Public domain + + This is an integer prescale filter that should be combined + with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve + a smooth scaling result with minimum blur. This is good for pixelgraphics + that are scaled by non-integer factors. + + The prescale factor and texel coordinates are precalculated + in the vertex shader for speed. +*/ + +// Parameter lines go here: +#pragma parameter SCANLINE_BASE_BRIGHTNESS "Scanline Base Brightness" 0.60 0.0 1.0 0.01 +#pragma parameter SCANLINE_HORIZONTAL_MODULATION "Scanline Horizontal Modulation" 0.0 0.0 2.00 0.01 +#pragma parameter SCANLINE_VERTICAL_MODULATION "Scanline Vertical Modulation" 0.75 0.0 2.0 0.01 + +#define pi 3.141592654 + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec2 omega; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform 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) + +COMPAT_VARYING vec2 precalc_texel; +COMPAT_VARYING vec2 precalc_scale; + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + omega = vec2(pi * OutputSize.x, 2.0 * pi * TextureSize.y); + + precalc_texel = vTexCoord * SourceSize.xy; + precalc_scale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec2 omega; + +// fragment compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float SCANLINE_BASE_BRIGHTNESS; +uniform COMPAT_PRECISION float SCANLINE_HORIZONTAL_MODULATION; +uniform COMPAT_PRECISION float SCANLINE_VERTICAL_MODULATION; +#else +#define SCANLINE_BASE_BRIGHTNESS 0.60 +#define SCANLINE_HORIZONTAL_MODULATION 0.0 +#define SCANLINE_VERTICAL_MODULATION 0.75 +#endif + +COMPAT_VARYING vec2 precalc_texel; +COMPAT_VARYING vec2 precalc_scale; + +void main() +{ + vec2 texel = precalc_texel; + vec2 scale = precalc_scale; + + vec2 texel_floored = floor(texel); + vec2 s = fract(texel); + vec2 region_range = 0.5 - 0.5 / scale; + + // Figure out where in the texel to sample to get correct pre-scaled bilinear. + // Uses the hardware bilinear interpolator to avoid having to sample 4 times manually. + + vec2 center_dist = s - 0.5; + vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; + + vec2 mod_texel = texel_floored + f; + + vec3 res = texture(Source, mod_texel / SourceSize.xy).xyz; + + // thick scanlines (thickness pre-calculated in vertex shader based on source resolution) + vec2 sine_comp = vec2(SCANLINE_HORIZONTAL_MODULATION, SCANLINE_VERTICAL_MODULATION); + + vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(vTexCoord * omega), vec2(1.0, 1.0))); + FragColor = vec4(scanline.rgb, 1.0); +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-simple.glsl b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-simple.glsl new file mode 100644 index 000000000..71277a641 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/sharp-bilinear-simple.glsl @@ -0,0 +1,123 @@ +/* + Author: rsn8887 (based on TheMaister) + License: Public domain + + This is an integer prescale filter that should be combined + with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve + a smooth scaling result with minimum blur. This is good for pixelgraphics + that are scaled by non-integer factors. + + The prescale factor and texel coordinates are precalculated + in the vertex shader for speed. +*/ + +#if defined(VERTEX) + +#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 vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform 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) + +COMPAT_VARYING vec2 precalc_texel; +COMPAT_VARYING vec2 precalc_scale; + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + + precalc_texel = vTexCoord * SourceSize.xy; + precalc_scale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +// fragment compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +COMPAT_VARYING vec2 precalc_texel; +COMPAT_VARYING vec2 precalc_scale; + +void main() +{ + vec2 texel = precalc_texel; + vec2 scale = precalc_scale; + + vec2 texel_floored = floor(texel); + vec2 s = fract(texel); + vec2 region_range = 0.5 - 0.5 / scale; + + // Figure out where in the texel to sample to get correct pre-scaled bilinear. + // Uses the hardware bilinear interpolator to avoid having to sample 4 times manually. + + vec2 center_dist = s - 0.5; + vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; + + vec2 mod_texel = texel_floored + f; + + FragColor = vec4(texture(Source, mod_texel / SourceSize.xy).rgb, 1.0); +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/stock.glsl b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/stock.glsl new file mode 100644 index 000000000..9e636f39c --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/shaders/stock.glsl @@ -0,0 +1,111 @@ +// GLSL shader autogenerated by cg2glsl.py. +#if defined(VERTEX) + +#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_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color1; +struct output_dummy { + vec4 _color1; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +vec4 _oPosition1; +vec4 _r0005; +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + vec4 _oColor; + vec2 _otexCoord; + _r0005 = VertexCoord.x*MVPMatrix[0]; + _r0005 = _r0005 + VertexCoord.y*MVPMatrix[1]; + _r0005 = _r0005 + VertexCoord.z*MVPMatrix[2]; + _r0005 = _r0005 + VertexCoord.w*MVPMatrix[3]; + _oPosition1 = _r0005; + _oColor = COLOR; + _otexCoord = TexCoord.xy; + gl_Position = _r0005; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; +} +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#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 +COMPAT_VARYING float _frame_rotation; +COMPAT_VARYING vec4 _color; +struct output_dummy { + vec4 _color; +}; +struct input_dummy { + vec2 _video_size; + vec2 _texture_size; + vec2 _output_dummy_size; + float _frame_count; + float _frame_direction; + float _frame_rotation; +}; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +void main() +{ + output_dummy _OUT; + _OUT._color = COMPAT_TEXTURE(Texture, TEX0.xy); + FragColor = _OUT._color; + return; +} +#endif diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-2x-prescale.glslp b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-2x-prescale.glslp new file mode 100644 index 000000000..54a3b7187 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-2x-prescale.glslp @@ -0,0 +1,7 @@ +shaders = 2 +shader0 = shaders/stock.glsl +filter_linear0 = false +scale_type0 = source +scale0 = 2.0 +shader1 = shaders/stock.glsl +filter_linear1 = true \ No newline at end of file diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-scanlines.glslp b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-scanlines.glslp new file mode 100644 index 000000000..a71347b69 --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-scanlines.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/sharp-bilinear-scanlines.glsl +filter_linear0 = true diff --git a/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-simple.glslp b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-simple.glslp new file mode 100644 index 000000000..37be32e1b --- /dev/null +++ b/packages/games/libretro/glsl-shaders/shaders/sharp/sharp-bilinear-simple.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/sharp-bilinear-simple.glsl +filter_linear0 = true \ No newline at end of file diff --git a/packages/games/libretro/gme/package.mk b/packages/games/libretro/gme/package.mk new file mode 100644 index 000000000..426b37e35 --- /dev/null +++ b/packages/games/libretro/gme/package.mk @@ -0,0 +1,44 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="gme" +PKG_VERSION="42bff0eed05ce165c98b119bfd576d29982618e7" +PKG_SHA256="582c023966669f956417efed7357da90cd27627135d2433208ecdad8ad257f5e" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/libretro-gme" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of blargg's Game_Music_Emu library." +PKG_LONGDESC="Port of blargg's Game_Music_Emu library." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp gme_libretro.so $INSTALL/usr/lib/libretro/ +} + diff --git a/packages/games/libretro/gpsp/package.mk b/packages/games/libretro/gpsp/package.mk new file mode 100644 index 000000000..27e9c490e --- /dev/null +++ b/packages/games/libretro/gpsp/package.mk @@ -0,0 +1,51 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="gpsp" +PKG_VERSION="c39f5391f0ebb7aa6e166cd5fdc496c31bde0ef9" +PKG_SHA256="a1702e357c274b621477201b21a18772634c1175e6cafb141d03b4512e67c32a" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/gpsp" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="gpSP for libretro." +PKG_LONGDESC="gameplaySP is a Gameboy Advance emulator for Playstation Portable" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + make CC=$CC platform=unix + else + make CC=$CC + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp gpsp_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/gw-libretro/package.mk b/packages/games/libretro/gw-libretro/package.mk new file mode 100644 index 000000000..f724e2645 --- /dev/null +++ b/packages/games/libretro/gw-libretro/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="gw-libretro" +PKG_VERSION="0f1ccca156388880bf4507ad44741f80945dfc6f" +PKG_SHA256="bca59f2f7f1384e9a20db1d7dcfbe23ef288785d94dc3aabf7ab8a80d25e51cd" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/gw-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A libretro core for Game & Watch simulators " +PKG_LONGDESC="A libretro core for Game & Watch simulators " + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp gw_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/handy/package.mk b/packages/games/libretro/handy/package.mk new file mode 100644 index 000000000..1b898a3d7 --- /dev/null +++ b/packages/games/libretro/handy/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="handy" +PKG_VERSION="e7b4e32d5f32d6e96630072072844a7dd16a02d9" +PKG_SHA256="03916eff68a77cdb353d203f330177d4427e2ca461d598a4aa4941fdf84de979" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Zlib" +PKG_SITE="https://github.com/libretro/libretro-handy" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="K. Wilkins' Atari Lynx emulator Handy for libretro" +PKG_LONGDESC="Handy is an Atari Lynx Emulator for Windows 95/98/NT/2000. Handy was the original name of the Lynx project that was started at Epyx and then finished by Atari." +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +if [ ${ARCH} = "aarch64" ]; then + PKG_MAKE_OPTS_TARGET=" platform=emuelec" +else + PKG_MAKE_OPTS_TARGET=" platform=classic_armv8_a35" +fi + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp handy_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/handy/patches/aarch64/handy-01-add-emuelec.patch b/packages/games/libretro/handy/patches/aarch64/handy-01-add-emuelec.patch new file mode 100644 index 000000000..7cb85cb80 --- /dev/null +++ b/packages/games/libretro/handy/patches/aarch64/handy-01-add-emuelec.patch @@ -0,0 +1,23 @@ +--- a/Makefile ++++ b/Makefile +@@ -245,7 +245,7 @@ + + # (armv8 a35, hard point, neon based) ### + # Playstation Classic +-else ifeq ($(platform), classic_armv8_a35) ++else ifeq ($(platform), emuelec) + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC + SHARED := -shared -Wl,-version-script=$(LIBRETRO_DIR)/link.T -Wl,-no-undefined +@@ -256,9 +256,9 @@ + -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ + -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ + -fmerge-all-constants -fno-math-errno \ +- -marm -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ -mtune=cortex-a72 #-mfpu=neon-fp-armv8 -mfloat-abi=hard + HAVE_NEON = 1 +- ARCH = arm ++ ARCH = aarch64 + ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1) + CFLAGS += -march=armv8-a + else diff --git a/packages/games/libretro/hatari/config/conf/Atari-ST-default.cfg b/packages/games/libretro/hatari/config/conf/Atari-ST-default.cfg new file mode 100644 index 000000000..f242a8e4a --- /dev/null +++ b/packages/games/libretro/hatari/config/conf/Atari-ST-default.cfg @@ -0,0 +1,252 @@ +[Log] +sLogFileName = stderr +sTraceFileName = stderr +nTextLogLevel = 3 +nAlertDlgLogLevel = 1 +bConfirmQuit = FALSE +bNatFeats = FALSE +bConsoleWindow = FALSE + +[Debugger] +nNumberBase = 10 +nSymbolLines = -1 +nMemdumpLines = -1 +nDisasmLines = -1 +nExceptionDebugMask = 515 +nDisasmOptions = 15 +bDisasmUAE = FALSE +bSymbolsResident = FALSE +bMatchAllSymbols = FALSE + +[Screen] +nMonitorType = 1 +nFrameSkips = 5 +bFullScreen = TRUE +bKeepResolution = TRUE +bResizable = TRUE +bAllowOverscan = TRUE +nSpec512Threshold = 1 +nForceBpp = 0 +bAspectCorrect = TRUE +bUseExtVdiResolutions = FALSE +nVdiWidth = 640 +nVdiHeight = 480 +nVdiColors = 2 +bMouseWarp = TRUE +bShowStatusbar = FALSE +bShowDriveLed = FALSE +bCrop = FALSE +bForceMax = FALSE +nMaxWidth = 832 +nMaxHeight = 588 +bUseSdlRenderer = TRUE +nRenderScaleQuality = 0 +bUseVsync = TRUE + +[Joystick0] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick1] +nJoystickMode = 1 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick2] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick3] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick4] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Joystick5] +nJoystickMode = 0 +bEnableAutoFire = FALSE +bEnableJumpOnFire2 = FALSE +nJoyId = 0 +kUp = Up +kDown = Down +kLeft = Left +kRight = Right +kFire = Right Ctrl + +[Keyboard] +bDisableKeyRepeat = FALSE +nKeymapType = 0 +szMappingFileName = + +[KeyShortcutsWithMod] +kOptions = O +kFullScreen = F +kBorders = B +kMouseMode = M +kColdReset = C +kWarmReset = R +kScreenShot = G +kBossKey = I +kCursorEmu = J +kFastForward = X +kRecAnim = A +kRecSound = Y +kSound = S +kPause = +kDebugger = Pause +kQuit = Q +kLoadMem = L +kSaveMem = K +kInsertDiskA = D +kSwitchJoy0 = F1 +kSwitchJoy1 = F2 +kSwitchPadA = F3 +kSwitchPadB = F4 + +[KeyShortcutsWithoutMod] +kOptions = F12 +kFullScreen = F11 +kBorders = +kMouseMode = +kColdReset = +kWarmReset = +kScreenShot = +kBossKey = +kCursorEmu = +kFastForward = +kRecAnim = +kRecSound = +kSound = +kPause = Pause +kDebugger = +kQuit = +kLoadMem = +kSaveMem = +kInsertDiskA = +kSwitchJoy0 = +kSwitchJoy1 = +kSwitchPadA = +kSwitchPadB = + +[Sound] +bEnableMicrophone = TRUE +bEnableSound = TRUE +bEnableSoundSync = FALSE +nPlaybackFreq = 44100 +nSdlAudioBufferSize = 0 +szYMCaptureFileName = /storage/.hatari/hatari.wav +YmVolumeMixing = 2 + +[Memory] +nMemorySize = 1024 +nTTRamSize = 0 +bAutoSave = FALSE +szMemoryCaptureFileName = /storage/.config/hatari/hatari.sav +szAutoSaveFileName = /storage/.config/hatari/auto.sav + +[HardDisk] +nGemdosDrive = 0 +bBootFromHardDisk = FALSE +bUseHardDiskDirectory = FALSE +szHardDiskDirectory = /storage/.hatari +nGemdosCase = 0 +nWriteProtection = 0 +bFilenameConversion = FALSE +bGemdosHostTime = FALSE +bUseHardDiskImage = FALSE +szHardDiskImage = /storage/.hatari +bUseIdeMasterHardDiskImage = FALSE +bUseIdeSlaveHardDiskImage = FALSE +szIdeMasterHardDiskImage = /storage/.hatari +szIdeSlaveHardDiskImage = /storage/.hatari + +[ROM] +szTosImageFileName = /storage/roms/bios/tos.img +bPatchTos = TRUE +szCartridgeImageFileName = + +[RS232] +bEnableRS232 = FALSE +szOutFileName = /dev/modem +szInFileName = /dev/modem + +[Printer] +bEnablePrinting = FALSE +szPrintToFileName = /storage/.config/hatari/hatari.prn + +[Midi] +bEnableMidi = FALSE +sMidiInFileName = /dev/snd/midiC1D0 +sMidiOutFileName = /dev/snd/midiC1D0 +sMidiInPortName = Off +sMidiOutPortName = Off + +[System] +nCpuLevel = 0 +nCpuFreq = 8 +bCompatibleCpu = TRUE +nModelType = 0 +bBlitter = FALSE +nDSPType = 0 +bPatchTimerD = FALSE +bFastBoot = FALSE +bFastForward = FALSE +bAddressSpace24 = TRUE +bCycleExactCpu = TRUE +n_FPUType = 0 +bSoftFloatFPU = FALSE +bMMU = FALSE +VideoTiming = 3 + +[Video] +AviRecordVcodec = 2 +AviRecordFps = 0 +AviRecordFile = /storage/.hatari/hatari.avi + +[Floppy] +bAutoInsertDiskB = TRUE +FastFloppy = TRUE +EnableDriveA = TRUE +DriveA_NumberOfHeads = 2 +EnableDriveB = TRUE +DriveB_NumberOfHeads = 2 +nWriteProtection = 0 +szDiskImageDirectory = /storage/roms/atarist +szDiskAZipPath = +szDiskBZipPath = diff --git a/packages/games/libretro/hatari/config/hatari.nvram b/packages/games/libretro/hatari/config/hatari.nvram new file mode 100644 index 000000000..e69de29bb diff --git a/packages/games/libretro/hatari/package.mk b/packages/games/libretro/hatari/package.mk new file mode 100644 index 000000000..7c4c1d912 --- /dev/null +++ b/packages/games/libretro/hatari/package.mk @@ -0,0 +1,59 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="hatari" +PKG_VERSION="cea06eebf695b078fadc0e78bb0f2b2baaca799f" +PKG_SHA256="41a044a0a5625052a4a477dca47897aafccd23d835dc20b43e41b37a38e64628" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/hatari" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain capsimg" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="New rebasing of Hatari based on Mercurial upstream. Tries to be a shallow fork for easy upstreaming later on." +PKG_LONGDESC="New rebasing of Hatari based on Mercurial upstream. Tries to be a shallow fork for easy upstreaming later on." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_USE_CMAKE="no" + +configure_target() { + : +} + +make_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DNO_ASM -DARM -D__arm__ -DARM_ASM -DNOSSE -DARM_HARDFP" + fi + CFLAGS="$CFLAGS -I$(get_build_dir capsimg)/Core -I$(get_build_dir capsimg)/.install_pkg/usr/local/include -L$(get_build_dir capsimg)/.install_pkg/usr/lib -lcapsimage -DHAVE_CAPSIMAGE=1 -DCAPSIMAGE_VERSION=5" + LDFLAGS="$LDFLAGS -I$(get_build_dir capsimg)/LibIPF -DHAVE_CAPSIMAGE=1" + make -C .. -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + mkdir -p $INSTALL/usr/config/distribution/configs/hatari + cp ../hatari_libretro.so $INSTALL/usr/lib/libretro/ + cp -rf ${PKG_DIR}/config/* $INSTALL/usr/config/distribution/configs/hatari/ +} diff --git a/packages/games/libretro/hatari/patches/findcapsimage.patch b/packages/games/libretro/hatari/patches/findcapsimage.patch new file mode 100644 index 000000000..b7de702a5 --- /dev/null +++ b/packages/games/libretro/hatari/patches/findcapsimage.patch @@ -0,0 +1,48 @@ +diff --git a/cmake/FindCapsImage.cmake b/cmake/FindCapsImage.cmake +index 982e5285..94ada2fe 100644 +--- a/cmake/FindCapsImage.cmake ++++ b/cmake/FindCapsImage.cmake +@@ -6,7 +6,7 @@ ENDIF (CAPSIMAGE_INCLUDE_DIR) + + + # Choose the library version to use : 4 or 5 +-SET(CAPSIMAGE_VERSION 4) ++SET(CAPSIMAGE_VERSION 5) + + + if(CAPSIMAGE_VERSION STREQUAL 4) +diff --git a/src/floppy_ipf.c b/src/floppy_ipf.c +index c615b755..8e52b712 100644 +--- a/src/floppy_ipf.c ++++ b/src/floppy_ipf.c +@@ -24,10 +24,16 @@ const char floppy_ipf_fileid[] = "Hatari floppy_ipf.c : " __DATE__ " " __TIME__; + #include "screen.h" + #include "video.h" + #include "cycles.h" ++#include + + #ifdef HAVE_CAPSIMAGE ++#ifndef __cdecl ++#define __cdecl /* CAPS headers need this, but do not define it on their own */ ++#endif + #if CAPSIMAGE_VERSION == 5 + #include ++#define CapsLong SDWORD ++#define CapsULong UDWORD + #else + #include + #define CAPS_LIB_RELEASE 4 +diff --git a/src/uae-cpu/newcpu.c b/src/uae-cpu/newcpu.c +index e752e83d..91cf41cf 100644 +--- a/src/uae-cpu/newcpu.c ++++ b/src/uae-cpu/newcpu.c +@@ -162,6 +162,9 @@ const char NewCpu_fileid[] = "Hatari newcpu.c : " __DATE__ " " __TIME__; + #include "68kDisass.h" + + #ifdef HAVE_CAPSIMAGE ++#ifndef __cdecl ++#define __cdecl /* CAPS headers need this, but do not define it on their own */ ++#endif + #if CAPSIMAGE_VERSION == 5 + #include + #endif diff --git a/packages/games/libretro/libretro-database/package.mk b/packages/games/libretro/libretro-database/package.mk new file mode 100644 index 000000000..8f437719f --- /dev/null +++ b/packages/games/libretro/libretro-database/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="libretro-database" +PKG_VERSION="ef0b6d96f0607266206193b806ab43b65658fe8c" +PKG_SHA256="de79366edf317670d013d6b75e04a369f5db644986dfa75d718581bc8831eb7b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-database" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Repository containing cheatcode files, content data files, etc." +PKG_LONGDESC="Repository containing cheatcode files, content data files, etc." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +configure_target() { + cd $PKG_BUILD +} + +makeinstall_target() { + make install INSTALLDIR="$INSTALL/usr/share/libretro-database" +} diff --git a/packages/games/libretro/mame/package.mk b/packages/games/libretro/mame/package.mk new file mode 100644 index 000000000..4325b9738 --- /dev/null +++ b/packages/games/libretro/mame/package.mk @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019 Trond Haugland (trondah@gmail.com) + +PKG_NAME="mame" +PKG_VERSION="031ac783585e7d5156a6f87a9ba20d88caf94ad6" +PKG_SHA256="bb91e074f96bcbbfef4f1da852f12fda5f9e3f83dc480f8901b088e93e06fdaa" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/mame" +PKG_URL="https://github.com/libretro/mame/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib flac sqlite expat" +PKG_SECTION="libretro" +PKG_SHORTDESC="MAME - Multiple Arcade Machine Emulator" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + + +PKG_MAKE_OPTS_TARGET="REGENIE=1 \ + VERBOSE=1 \ + NOWERROR=1 \ + OPENMP=1 \ + CROSS_BUILD=1 \ + TOOLS=0 \ + RETRO=1 \ + PTR64=0 \ + NOASM=0 \ + PYTHON_EXECUTABLE=python3 \ + CONFIG=libretro \ + LIBRETRO_OS=unix \ + LIBRETRO_CPU= \ + PLATFORM=arm64 \ + ARCH= \ + TARGET=mame \ + SUBTARGET=mame \ + OSD=retro \ + USE_SYSTEM_LIB_EXPAT=1 \ + USE_SYSTEM_LIB_ZLIB=1 \ + USE_SYSTEM_LIB_FLAC=1 \ + USE_SYSTEM_LIB_SQLITE3=1" + +pre_configure_target() { + sed -i "s/-static-libstdc++//g" scripts/genie.lua +} + +make_target() { + unset ARCH + unset DISTRO + unset PROJECT + export ARCHOPTS="-D__aarch64__ -DASMJIT_BUILD_X86" + make $PKG_MAKE_OPTS_TARGET OVERRIDE_CC=$CC OVERRIDE_CXX=$CXX OVERRIDE_LD=$LD AR=$AR $MAKEFLAGS +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp *.so $INSTALL/usr/lib/libretro/mame_libretro.so + mkdir -p $INSTALL/usr/config/retroarch/savefiles/mame/hi + cp plugins/hiscore/hiscore.dat $INSTALL/usr/config/retroarch/savefiles/mame/hi +} diff --git a/packages/games/libretro/mame/patches/mame-crosscompile.patch b/packages/games/libretro/mame/patches/mame-crosscompile.patch new file mode 100644 index 000000000..49f1ff376 --- /dev/null +++ b/packages/games/libretro/mame/patches/mame-crosscompile.patch @@ -0,0 +1,54 @@ +--- a/3rdparty/genie/build/gmake.linux/genie.make 2018-08-11 00:17:44.000000000 +0200 ++++ b/3rdparty/genie/build/gmake.linux/genie.make 2019-04-03 11:57:27.671223016 +0200 +@@ -28,8 +28,8 @@ + RM = $(SILENT) del /F "$(subst /,\\,$(1))" 2> nul || exit 0 + endif + +-CC = gcc +-CXX = g++ ++CC = $(HOST_CC) ++CXX = $(HOST_CXX) + AR = ar + + ifndef RESCOMP +@@ -50,12 +50,12 @@ + INCLUDES += -I"../../src/host/lua-5.3.0/src" + ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP -MP $(DEFINES) $(INCLUDES) + ALL_ASMFLAGS += $(ASMFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough +- ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough +- ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough +- ALL_OBJCFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough +- ALL_OBJCPPFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough ++ ALL_CFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough ++ ALL_CXXFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough ++ ALL_OBJCFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough ++ ALL_OBJCPPFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os $(MPARAM) -Wno-implicit-fallthrough + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) +- ALL_LDFLAGS += $(LDFLAGS) -L"." -s -rdynamic ++ ALL_LDFLAGS += -L"." -s -rdynamic + LIBDEPS += + LDDEPS += + LDRESP = +--- a/3rdparty/genie/src/host/scripts.c 2019-05-21 22:41:14.207745861 +0200 ++++ b/3rdparty/genie/src/host/scripts.c 2019-05-21 22:42:43.159893481 +0200 +@@ -147,7 +147,7 @@ + + /* tools/gcc.lua */ + "premake.gcc = { }\npremake.gcc.cc = \"gcc\"\npremake.gcc.cxx = \"g++\"\npremake.gcc.ar = \"ar\"\npremake.gcc.rc = \"windres\"\npremake.gcc.llvm = false\nlocal cflags =\n{\nEnableSSE = \"-msse\",\nEnableSSE2 = \"-msse2\",\nEnableAVX = \"-mavx\",\nEnableAVX2 = \"-mavx2\",\nPedanticWarnings = \"-Wall -Wextra -pedantic\",\nExtraWarnings = \"-Wall -Wextra\",\nFatalWarnings = \"-Werror\",\nFloatFast = \"-ffast-math\",\nFloatStrict = \"-ffloat-store\",\nNoFramePointer = \"-fomit-frame-pointer\",\nOptimize = \"-O2\",\nOptimizeSize = \"-Os\",\nOptimizeSpeed = \"-O3\",\nSymbols = \"-g\",\n}\nlocal cxxflags =\n{\nCpp11 = \"-std=c++11\",\nCpp14 = \"-std=c++14\",\nCpp17 = \"-std=c++17\",\nCppLatest = \"-std=c++2a\",\nNoExceptions = \"-fno-exceptions\",\nNoRTTI = \"-fno-rtti\",\nUnsignedChar = \"-funsigned-char\",\n}\nlocal objcflags =\n{\nObjcARC = \"-fobjc-arc\",\n}\npremake.gcc.platforms =\n{\nNative = {\n" +- "cppflags = \"-MMD -MP\",\n},\nx32 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m32\",\n},\nx64 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m64\",\n},\nUniversal = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch x86_64 -arch ppc -arch ppc64\",\n},\nUniversal32 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch ppc\",\n},\nUniversal64 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch x86_64 -arch ppc64\",\n},\nPS3 = {\ncc = \"ppu-lv2-g++\",\ncxx = \"ppu-lv2-g++\",\nar = \"ppu-lv2-ar\",\ncppflags = \"-MMD -MP\",\n},\nWiiDev = {\ncppflags = \"-MMD -MP -I$(LIBOGC_INC) $(MACHDEP)\",\nldflags= \"-L$(LIBOGC_LIB) $(MACHDEP)\",\ncfgsettings = [[\n ifeq ($(strip $(DEVKITPPC)),)\n $(error \"DEVKITPPC environment variable is not set\")'\n endif\n include $(DEVKITPPC)/wii_rules']],\n},\nOrbis = {\ncc = \"orbis-clang\",\ncxx = \"orbis-clang++\",\nar = \"orbis-ar\",\ncppflag" ++ "cppflags = \"-MMD -MP\",\n},\nx32 = {\ncppflags = \"-MMD -MP\"\n},\nx64 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m64\",\n},\nUniversal = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch x86_64 -arch ppc -arch ppc64\",\n},\nUniversal32 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch ppc\",\n},\nUniversal64 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch x86_64 -arch ppc64\",\n},\nPS3 = {\ncc = \"ppu-lv2-g++\",\ncxx = \"ppu-lv2-g++\",\nar = \"ppu-lv2-ar\",\ncppflags = \"-MMD -MP\",\n},\nWiiDev = {\ncppflags = \"-MMD -MP -I$(LIBOGC_INC) $(MACHDEP)\",\nldflags= \"-L$(LIBOGC_LIB) $(MACHDEP)\",\ncfgsettings = [[\n ifeq ($(strip $(DEVKITPPC)),)\n $(error \"DEVKITPPC environment variable is not set\")'\n endif\n include $(DEVKITPPC)/wii_rules']],\n},\nOrbis = {\ncc = \"orbis-clang\",\ncxx = \"orbis-clang++\",\nar = \"orbis-ar\",\ncppflag" + "s = \"-MMD -MP\",\n},\nEmscripten = {\ncc = \"$(EMSCRIPTEN)/emcc\",\ncxx = \"$(EMSCRIPTEN)/em++\",\nar = \"$(EMSCRIPTEN)/emar\",\ncppflags = \"-MMD -MP\",\n}\n}\nlocal platforms = premake.gcc.platforms\nfunction premake.gcc.getcppflags(cfg)\nlocal flags = { }\ntable.insert(flags, platforms[cfg.platform].cppflags)\nif flags[1]:startswith(\"-MMD\") then\ntable.insert(flags, \"-MP\")\nend\nreturn flags\nend\nfunction premake.gcc.getcflags(cfg)\nlocal result = table.translate(cfg.flags, cflags)\ntable.insert(result, platforms[cfg.platform].flags)\nif cfg.system ~= \"windows\" and cfg.kind == \"SharedLib\" then\ntable.insert(result, \"-fPIC\")\nend\nreturn result\nend\nfunction premake.gcc.getcxxflags(cfg)\nlocal result = table.translate(cfg.flags, cxxflags)\nreturn result\nend\nfunction premake.gcc.getobjcflags(cfg)\nreturn table.translate(cfg.flags, objcflags)\nend\nfunction premake.gcc.getldflags(cfg)\nlocal result = { }\nif not cfg.flags.Symbols then\nif cfg.system == \"macosx\" then" + "\nelse\ntable.insert(result, \"-s\")\nend\nend\nif cfg.kind == \"Bundle\" then\ntable.insert(result, \"-bundle\")\nend\nif cfg.kind == \"SharedLib\" then\nif cfg.system == \"macosx\" then\ntable.insert(result, \"-dynamiclib\")\nelse\ntable.insert(result, \"-shared\")\nend\nif cfg.system == \"windows\" and not cfg.flags.NoImportLib then\ntable.insert(result, '-Wl,--out-implib=\"' .. cfg.linktarget.fullpath .. '\"')\nend\nend\nif cfg.kind == \"WindowedApp\" and cfg.system == \"windows\" then\ntable.insert(result, \"-mwindows\")\nend\nlocal platform = platforms[cfg.platform]\ntable.insert(result, platform.flags)\ntable.insert(result, platform.ldflags)\nreturn result\nend\nfunction premake.gcc.getlibdirflags(cfg)\nlocal result = { }\nfor _, value in ipairs(premake.getlinks(cfg, \"all\", \"directory\")) do\ntable.insert(result, '-L\\\"' .. value .. '\\\"')\nend\nreturn result\nend\nfunction premake.gcc.islibfile(p)\nif path.getextension(p) == \".a\" then\nreturn true\nend\nreturn false\nend\nfunction premake.gcc.ge" + "tlibfiles(cfg)\nlocal result = {}\nfor _, value in ipairs(premake.getlinks(cfg, \"system\", \"fullpath\")) do\nif premake.gcc.islibfile(value) then\ntable.insert(result, _MAKE.esc(value))\nend\nend\nreturn result\nend\nfunction premake.gcc.getlinkflags(cfg)\nlocal result = {}\nfor _, value in ipairs(premake.getlinks(cfg, \"system\", \"fullpath\")) do\nif premake.gcc.islibfile(value) then\nvalue = path.rebase(value, cfg.project.location, cfg.location)\ntable.insert(result, _MAKE.esc(value))\nelseif path.getextension(value) == \".framework\" then\ntable.insert(result, '-framework ' .. _MAKE.esc(path.getbasename(value)))\nelse\ntable.insert(result, '-l' .. _MAKE.esc(path.getname(value)))\nend\nend\nreturn result\nend\nfunction premake.gcc.wholearchive(lib)\nif premake.gcc.llvm then\nreturn {\"-force_load\", lib}\nelse\nreturn {\"-Wl,--whole-archive\", lib, \"-Wl,--no-whole-archive\"}\nend\nend\nfunction premake.gcc.getarchiveflags(prj, cfg, ndx)\nlocal result = {}\nif cfg.platform:startswith(\"Universal\") then\n" +--- a/scripts/toolchain.lua 2019-04-30 15:47:21.000000000 +0200 ++++ b/scripts/toolchain.lua 2019-05-21 22:51:48.116148725 +0200 +@@ -698,9 +698,6 @@ + + configuration { "linux-gcc", "x32" } + objdir (_buildDir .. "linux_gcc" .. "/obj") +- buildoptions { +- "-m32", +- } + + configuration { "linux-gcc", "x32", "Release" } + targetdir (_buildDir .. "linux_gcc" .. "/bin/x32/Release") diff --git a/packages/games/libretro/mame/patches/mame-remove-bgfx.patch b/packages/games/libretro/mame/patches/mame-remove-bgfx.patch new file mode 100644 index 000000000..d8c570413 --- /dev/null +++ b/packages/games/libretro/mame/patches/mame-remove-bgfx.patch @@ -0,0 +1,80 @@ +diff --git a/Makefile.libretro b/Makefile.libretro +index 31c414be..8de62064 100644 +--- a/Makefile.libretro ++++ b/Makefile.libretro +@@ -55,6 +55,8 @@ VERBOSE ?= 1 + # scripts/toolchain.lua) + # PTR64 = 1 + ++USE_BGFX ?= 0 ++ + ########################################################################### + # + # LIBRETRO PLATFORM GUESSING +diff --git a/scripts/genie.lua b/scripts/genie.lua +index 4655b3f4..495308a8 100644 +--- a/scripts/genie.lua ++++ b/scripts/genie.lua +@@ -387,8 +387,22 @@ newoption { + description = "Arguments for running debug build.", + } + ++newoption { ++ trigger = "USE_BGFX", ++ description = "Use bgfx.", ++ allowed = { ++ { "0", "Disabled" }, ++ { "1", "Enabled" }, ++ } ++} ++ + dofile ("extlib.lua") + ++if not _OPTIONS["USE_BGFX"] then ++ _OPTIONS["USE_BGFX"] = "0" ++end ++ ++ + if _OPTIONS["SHLIB"]=="1" then + LIBTYPE = "SharedLib" + else +diff --git a/scripts/src/3rdparty.lua b/scripts/src/3rdparty.lua +index 664898d1..d720578d 100644 +--- a/scripts/src/3rdparty.lua ++++ b/scripts/src/3rdparty.lua +@@ -1249,7 +1249,7 @@ + -------------------------------------------------- + -- BGFX library objects + -------------------------------------------------- +- ++if not _OPTIONS["use_bgfx"]=="0" then + project "bgfx" + uuid "d3e7e119-35cf-4f4f-aba0-d3bdcd1b879a" + kind "StaticLib" +@@ -1433,7 +1433,7 @@ + "-x objective-c++", + } + end +- ++end + + -------------------------------------------------- + -- PortAudio library objects +diff --git a/scripts/src/main.lua b/scripts/src/main.lua +index 0b47e662..b19eb646 100644 +--- a/scripts/src/main.lua 2019-05-22 00:15:58.983419982 +0200 ++++ b/scripts/src/main.lua 2019-05-22 00:17:39.675345144 +0200 +@@ -380,8 +380,12 @@ + ext_lib("portmidi"), + } + end ++ if _OPTIONS["USE_BGFX"]~="0" then ++ links { ++ "bgfx", ++ } ++ end + links { +- "bgfx", + "bimg", + "bx", + "ocore_" .. _OPTIONS["osd"], diff --git a/packages/games/libretro/mame2000/package.mk b/packages/games/libretro/mame2000/package.mk new file mode 100644 index 000000000..eb5816d2d --- /dev/null +++ b/packages/games/libretro/mame2000/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mame2000" +PKG_VERSION="4793742b457945afb74053c8a895e6ff0b36b033" +PKG_SHA256="2d59e1083535c8a32f30afdfff9202b394c35d2c52123050730d7b6f3f339866" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2000-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="MAME - Multiple Arcade Machine Emulator" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make WANT_LIBCO=0 +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2000_libretro.so $INSTALL/usr/lib/libretro/ +} \ No newline at end of file diff --git a/packages/games/libretro/mame2003-midway/package.mk b/packages/games/libretro/mame2003-midway/package.mk new file mode 100644 index 000000000..c9edbebb6 --- /dev/null +++ b/packages/games/libretro/mame2003-midway/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mame2003-midway" +PKG_VERSION="2204233a66a78ebbb0ef1e86bb9d36e4405a2a92" +PKG_SHA256="8ed1addf56c9ed1999bac813e132c630f67096c9eaf4ab16495030c3e9045d43" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2003_midway" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="MAME - Multiple Arcade Machine Emulator" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_BUILD_FLAGS="-lto" + +make_target() { + make ARCH="" CC="$CC" NATIVE_CC="$CC" LD="$CC" -j 1 +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2003_midway_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mame2003-plus/package.mk b/packages/games/libretro/mame2003-plus/package.mk new file mode 100644 index 000000000..c2085df52 --- /dev/null +++ b/packages/games/libretro/mame2003-plus/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mame2003-plus" +PKG_VERSION="94640788aa9ff233118eeeeea5d6dced61566f82" +PKG_SHA256="ac3e73f81c1b5f40e4b8cae678de45a6a03707034600092ea78d9486c632b42d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2003-plus-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="MAME - Multiple Arcade Machine Emulator" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make ARCH="" CC="$CC" NATIVE_CC="$CC" LD="$CC" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2003_plus_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mame2003-xtreme/package.mk b/packages/games/libretro/mame2003-xtreme/package.mk new file mode 100644 index 000000000..e15952956 --- /dev/null +++ b/packages/games/libretro/mame2003-xtreme/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mame2003-xtreme" +PKG_VERSION="47deb07f49224ec5b0bbc56392b639d728183629" +PKG_SHA256="185b7e857e836b3987737ff9077d0709444491a0f138cfbbe1f50a6ad5d719b7" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/KMFDManic/mame2003-xtreme" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Updated 2018 version of MAME (0.78) for libretro, with added game support, and optimized for performance and speed on the Mini Classics. " +PKG_TOOLCHAIN="make" + +pre_configure_target() { + cd ${PKG_BUILD} + export SYSROOT_PREFIX=${SYSROOT_PREFIX} + + case ${PROJECT} in + Amlogic-ng) + PKG_MAKE_OPTS_TARGET+=" platform=AMLG12B" + ;; + Amlogic) + PKG_MAKE_OPTS_TARGET+=" platform=AMLGX" + ;; + esac + PKG_MAKE_OPTS_TARGET+=" ARCH=\"\" CC=\"$CC\" NATIVE_CC=\"$CC\" LD=\"$CC\"" + + # PKG_MAKE_OPTS_TARGET=" platform=rpi2 ARCH=\"\" CC=\"$CC\" NATIVE_CC=\"$CC\" LD=\"$CC\"" + + } + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2003_libretro.so $INSTALL/usr/lib/libretro/km_mame2003_xtreme_libretro.so + cp km_mame2003_xtreme_libretro.info $INSTALL/usr/lib/libretro/km_mame2003_xtreme_libretro.info + +} diff --git a/packages/games/libretro/mame2003-xtreme/sources/km_mame2003_xtreme_libretro.info b/packages/games/libretro/mame2003-xtreme/sources/km_mame2003_xtreme_libretro.info new file mode 100644 index 000000000..84494a69e --- /dev/null +++ b/packages/games/libretro/mame2003-xtreme/sources/km_mame2003_xtreme_libretro.info @@ -0,0 +1,14 @@ +display_name = "Arcade (km_MAME 2003 Xtreme)" +authors = "MAMEdev" +supported_extensions = "zip" +corename = "MAME 2003 Xtreme (0.78)" +manufacturer = "Various" +categories = "Emulator" +systemname = "Arcade (various)" +systemid = "mame" +database = "MAME 2003" +license = "MAME" +permissions = "" +display_version = "0.78" +supports_no_game = "false" +notes = "(!) The BIOS files must be inside the ROM directory.|" diff --git a/packages/games/libretro/mame2003/package.mk b/packages/games/libretro/mame2003/package.mk new file mode 100644 index 000000000..481e8e6c8 --- /dev/null +++ b/packages/games/libretro/mame2003/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mame2003" +PKG_VERSION="c079e586e5ef54e084622863816f4f0439fdb870" +PKG_SHA256="a23579c5df4cadcf57740a4d64e10eff0e26805e304261902a4d891fd2a2662a" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2003-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="MAME - Multiple Arcade Machine Emulator" +PKG_LONGDESC="MAME - Multiple Arcade Machine Emulator" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make ARCH="" CC="$CC" NATIVE_CC="$CC" LD="$CC" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2003_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mame2010/package.mk b/packages/games/libretro/mame2010/package.mk new file mode 100644 index 000000000..0d9fec5c7 --- /dev/null +++ b/packages/games/libretro/mame2010/package.mk @@ -0,0 +1,55 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mame2010" +PKG_VERSION="932e6f2c4f13b67b29ab33428a4037dee9a236a8" +PKG_SHA256="af60ec225fc4470e7bbc4a2e35cc7d4e1498aed4fe35b8f238fd5ba0dd9ead26" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/mame2010-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Late 2010 version of MAME (0.139) for libretro. Compatible with MAME 0.139 romsets." +PKG_LONGDESC="Late 2010 version of MAME (0.139) for libretro. Compatible with MAME 0.139 romsets." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + make CC="$CC" LD="$CC" PLATCFLAGS="$CFLAGS" PTR64=0 ARM_ENABLED=1 LCPU=arm + elif [ "$ARCH" == "i386" ]; then + make CC="$CC" LD="$CC" PLATCFLAGS="$CFLAGS" PTR64=0 ARM_ENABLED=0 LCPU=x86 + elif [ "$ARCH" == "x86_64" ]; then + make CC="$CC" LD="$CC" PLATCFLAGS="$CFLAGS" PTR64=1 ARM_ENABLED=0 LCPU=x86_64 + elif [ "$ARCH" == "aarch64" ]; then + make CC="$CC" LD="$CC" PLATCFLAGS="$CFLAGS" PTR64=1 ARM_ENABLED=1 LCPU=arm64 + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mame2010_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mame2015/package.mk b/packages/games/libretro/mame2015/package.mk new file mode 100644 index 000000000..923df374f --- /dev/null +++ b/packages/games/libretro/mame2015/package.mk @@ -0,0 +1,57 @@ +################################################################################ +# This file is part of LibreELEC - http://www.libreelec.tv +# Copyright (C) 2016 Team LibreELEC +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# LibreELEC 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 2 of the License, or +# (at your option) any later version. +# +# LibreELEC 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 LibreELEC. If not, see . +################################################################################ + +PKG_NAME="mame2015" +PKG_VERSION="ef41361dc9c88172617f7bbf6cd0ead4516a3c3f" +PKG_SHA256="13f7e1dac06a67f21d38e688f93470810d1d120bfc157ab6c5dbbe8f0cad95a3" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/mame2015-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="libretro" +PKG_SHORTDESC="Late 2014/Early 2015 version of MAME (0.160-ish) for libretro. Compatible with MAME 0.160 romsets." +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +pre_make_target() { + export REALCC=$CC + export CC=$CXX + export LD=$CXX +} + +pre_configure_target() { + if [[ "${DEVICE}" =~ RG351 ]]; then + PKG_MAKE_OPTS_TARGET=" platform=armv8-neon-hardfloat-cortex-a35" + sed -i 's/CCOMFLAGS += -mstructure-size-boundary=32//g' Makefile + sed -i 's/-DSDLMAME_NO64BITIO//g' Makefile + sed -i 's/LDFLAGS += -Wl,--fix-cortex-a8 -Wl,--no-as-needed//g' Makefile + else + PKG_MAKE_OPTS_TARGET=" platform=armv8-neon-hardfloat-cortex-a53" + sed -i 's/CCOMFLAGS += -mstructure-size-boundary=32//g' Makefile + sed -i 's/LDFLAGS += -Wl,--fix-cortex-a8 -Wl,--no-as-needed//g' Makefile + fi +} + +makeinstall_target() { + aarch64-linux-gnu-strip -s *.so + mkdir -p $INSTALL/usr/lib/libretro + cp mame*_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mame2016/package.mk b/packages/games/libretro/mame2016/package.mk new file mode 100644 index 000000000..656fdb653 --- /dev/null +++ b/packages/games/libretro/mame2016/package.mk @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019 Trond Haugland (trondah@gmail.com) + +PKG_NAME="mame2016" +PKG_VERSION="d53c379892b0bd91b4a52fc2de491e1199f03e32" +PKG_SHA256="bafcac133ff37fb3adeafd9960427e3314e682caf22d455395855d64553d46fe" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/mame2016-libretro" +PKG_URL="https://github.com/libretro/mame2016-libretro/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="escalade" +PKG_SHORTDESC="MAME (0.174-ish) for libretro" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +PTR64="0" +NOASM="0" + +if [ "$ARCH" == "arm" ]; then + NOASM="1" +elif [ "$ARCH" == "x86_64" ]; then + PTR64="1" +fi + +PKG_MAKE_OPTS_TARGET="REGENIE=1 \ + VERBOSE=1 \ + NOWERROR=1 \ + OPENMP=1 \ + CROSS_BUILD=1 \ + TOOLS=1 \ + RETRO=1 \ + PTR64=$PTR64 \ + NOASM=$NOASM \ + PYTHON_EXECUTABLE=python2 \ + CONFIG=libretro \ + LIBRETRO_OS=unix \ + LIBRETRO_CPU=$ARCH \ + PLATFORM=$ARCH \ + ARCH= \ + TARGET=mame \ + SUBTARGET=arcade \ + OSD=retro \ + USE_SYSTEM_LIB_EXPAT=1 \ + USE_SYSTEM_LIB_ZLIB=1 \ + USE_SYSTEM_LIB_FLAC=1 \ + USE_SYSTEM_LIB_SQLITE3=1" + +make_target() { + unset DISTRO + make $PKG_MAKE_OPTS_TARGET OVERRIDE_CC=$CC OVERRIDE_CXX=$CXX OVERRIDE_LD=$LD AR=$AR $MAKEFLAGS +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + mkdir -p $INSTALL/usr/lib/libretro + cp *.so $INSTALL/usr/lib/libretro/mame2016_libretro.so + mkdir -p $INSTALL/usr/config/retroarch/savefiles/mame2016/hi + cp metadata/hiscore.dat $INSTALL/usr/config/retroarch/savefiles/mame2016/hi +} + diff --git a/packages/games/libretro/mame2016/patches/mame2016-libretro-crosscompile.patch b/packages/games/libretro/mame2016/patches/mame2016-libretro-crosscompile.patch new file mode 100644 index 000000000..7875180e3 --- /dev/null +++ b/packages/games/libretro/mame2016/patches/mame2016-libretro-crosscompile.patch @@ -0,0 +1,52 @@ +--- a/3rdparty/genie/build/gmake.linux/genie.make 2018-08-11 00:17:44.000000000 +0200 ++++ b/3rdparty/genie/build/gmake.linux/genie.make 2019-04-03 11:57:27.671223016 +0200 +@@ -28,8 +28,8 @@ + RM = $(SILENT) del /F "$(subst /,\\,$(1))" 2> nul || exit 0 + endif + +-CC = gcc +-CXX = g++ ++CC = $(HOST_CC) ++CXX = $(HOST_CXX) + AR = ar + + ifndef RESCOMP +@@ -47,11 +47,11 @@ + DEFINES += -DNDEBUG -DLUA_COMPAT_MODULE -DLUA_USE_POSIX -DLUA_USE_DLOPEN + INCLUDES += -I../../src/host/lua-5.3.0/src + ALL_CPPFLAGS += $(CPPFLAGS) -MMD -MP -MP $(DEFINES) $(INCLUDES) +- ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os +- ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os +- ALL_OBJCFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os ++ ALL_CFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os ++ ALL_CXXFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os ++ ALL_OBJCFLAGS += $(ALL_CPPFLAGS) $(ARCH) -Wall -Wextra -Os + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) +- ALL_LDFLAGS += $(LDFLAGS) -L. -s -rdynamic ++ ALL_LDFLAGS += -L. -s -rdynamic + LDDEPS += + LIBS += $(LDDEPS) -ldl -lm + EXTERNAL_LIBS += +--- a/scripts/toolchain.lua 2019-04-03 12:13:08.556919475 +0200 ++++ b/scripts/toolchain.lua 2019-04-03 12:13:43.323043587 +0200 +@@ -675,9 +675,6 @@ + + configuration { "linux-gcc", "x32" } + objdir (_buildDir .. "linux_gcc" .. "/obj") +- buildoptions { +- "-m32", +- } + + configuration { "linux-gcc", "x32", "Release" } + targetdir (_buildDir .. "linux_gcc" .. "/bin/x32/Release") +--- a/3rdparty/genie/src/host/scripts.c 2019-04-03 12:30:33.272654617 +0200 ++++ b/3rdparty/genie/src/host/scripts.c 2019-04-03 12:30:12.892921812 +0200 +@@ -131,7 +131,7 @@ + "gs(cfg)\nlocal result = table.translate(cfg.flags, flags)\nreturn result\nend\nfunction premake.dotnet.getkind(cfg)\nif (cfg.kind == \"ConsoleApp\") then\nreturn \"Exe\"\nelseif (cfg.kind == \"WindowedApp\") then\nreturn \"WinExe\"\nelseif (cfg.kind == \"SharedLib\") then\nreturn \"Library\"\nend\nend", + + /* tools/gcc.lua */ +- "premake.gcc = { }\npremake.gcc.cc = \"gcc\"\npremake.gcc.cxx = \"g++\"\npremake.gcc.ar = \"ar\"\npremake.gcc.llvm = false\nlocal cflags =\n{\nEnableSSE = \"-msse\",\nEnableSSE2 = \"-msse2\",\nEnableAVX = \"-mavx\",\nEnableAVX2 = \"-mavx2\",\nExtraWarnings = \"-Wall -Wextra\",\nFatalWarnings = \"-Werror\",\nFloatFast = \"-ffast-math\",\nFloatStrict = \"-ffloat-store\",\nNoFramePointer = \"-fomit-frame-pointer\",\nOptimize = \"-O2\",\nOptimizeSize = \"-Os\",\nOptimizeSpeed = \"-O3\",\nSymbols = \"-g\",\n}\nlocal cxxflags =\n{\nNoExceptions = \"-fno-exceptions\",\nNoRTTI = \"-fno-rtti\",\nUnsignedChar = \"-funsigned-char\",\n}\npremake.gcc.platforms =\n{\nNative = {\ncppflags = \"-MMD -MP\",\n},\nx32 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m32\",\n},\nx64 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m64\",\n},\nUniversal = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch x86_64 -arch ppc -arch ppc64\",\n}," ++ "premake.gcc = { }\npremake.gcc.cc = \"gcc\"\npremake.gcc.cxx = \"g++\"\npremake.gcc.ar = \"ar\"\npremake.gcc.llvm = false\nlocal cflags =\n{\nEnableSSE = \"-msse\",\nEnableSSE2 = \"-msse2\",\nEnableAVX = \"-mavx\",\nEnableAVX2 = \"-mavx2\",\nExtraWarnings = \"-Wall -Wextra\",\nFatalWarnings = \"-Werror\",\nFloatFast = \"-ffast-math\",\nFloatStrict = \"-ffloat-store\",\nNoFramePointer = \"-fomit-frame-pointer\",\nOptimize = \"-O2\",\nOptimizeSize = \"-Os\",\nOptimizeSpeed = \"-O3\",\nSymbols = \"-g\",\n}\nlocal cxxflags =\n{\nNoExceptions = \"-fno-exceptions\",\nNoRTTI = \"-fno-rtti\",\nUnsignedChar = \"-funsigned-char\",\n}\npremake.gcc.platforms =\n{\nNative = {\ncppflags = \"-MMD -MP\",\n},\nx32 = {\ncppflags = \"-MMD -MP\",\n},\nx64 = {\ncppflags = \"-MMD -MP\",\nflags = \"-m64\",\n},\nUniversal = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch x86_64 -arch ppc -arch ppc64\",\n}," + "\nUniversal32 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch i386 -arch ppc\",\n},\nUniversal64 = {\nar = \"libtool\",\ncppflags = \"-MMD -MP\",\nflags = \"-arch x86_64 -arch ppc64\",\n},\nPS3 = {\ncc = \"ppu-lv2-g++\",\ncxx = \"ppu-lv2-g++\",\nar = \"ppu-lv2-ar\",\ncppflags = \"-MMD -MP\",\n},\nWiiDev = {\ncppflags = \"-MMD -MP -I$(LIBOGC_INC) $(MACHDEP)\",\nldflags= \"-L$(LIBOGC_LIB) $(MACHDEP)\",\ncfgsettings = [[\n ifeq ($(strip $(DEVKITPPC)),)\n $(error \"DEVKITPPC environment variable is not set\")'\n endif\n include $(DEVKITPPC)/wii_rules']],\n},\nOrbis = {\ncc = \"orbis-clang\",\ncxx = \"orbis-clang++\",\nar = \"orbis-ar\",\ncppflags = \"-MMD -MP\",\n}\n}\nlocal platforms = premake.gcc.platforms\nfunction premake.gcc.getcppflags(cfg)\nlocal flags = { }\ntable.insert(flags, platforms[cfg.platform].cppflags)\nif flags[1]:startswith(\"-MMD\") then\ntable.insert(flags, \"-MP\")\nend\nreturn flags\nend\nfunction " + "premake.gcc.getcflags(cfg)\nlocal result = table.translate(cfg.flags, cflags)\ntable.insert(result, platforms[cfg.platform].flags)\nif cfg.system ~= \"windows\" and cfg.kind == \"SharedLib\" then\ntable.insert(result, \"-fPIC\")\nend\nreturn result\nend\nfunction premake.gcc.getcxxflags(cfg)\nlocal result = table.translate(cfg.flags, cxxflags)\nreturn result\nend\nfunction premake.gcc.getldflags(cfg)\nlocal result = { }\nif not cfg.flags.Symbols then\nif cfg.system == \"macosx\" then\nelse\ntable.insert(result, \"-s\")\nend\nend\nif cfg.kind == \"SharedLib\" then\nif cfg.system == \"macosx\" then\ntable.insert(result, \"-dynamiclib\")\nelse\ntable.insert(result, \"-shared\")\nend\nif cfg.system == \"windows\" and not cfg.flags.NoImportLib then\ntable.insert(result, '-Wl,--out-implib=\"' .. cfg.linktarget.fullpath .. '\"')\nend\nend\nif cfg.kind == \"WindowedApp\" and cfg.system == \"windows\" then\ntable.insert(result, \"-mwindows\")\nend\nlocal platform = platforms[cfg.platform]\ntable.insert(result, platform" + ".flags)\ntable.insert(result, platform.ldflags)\nreturn result\nend\nfunction premake.gcc.getlibdirflags(cfg)\nlocal result = { }\nfor _, value in ipairs(premake.getlinks(cfg, \"all\", \"directory\")) do\ntable.insert(result, '-L' .. _MAKE.esc(value))\nend\nreturn result\nend\nfunction premake.gcc.islibfile(p)\nif path.getextension(p) == \".a\" then\nreturn true\nend\nreturn false\nend\nfunction premake.gcc.getlibfiles(cfg)\nlocal result = {}\nfor _, value in ipairs(premake.getlinks(cfg, \"system\", \"fullpath\")) do\nif premake.gcc.islibfile(value) then\ntable.insert(result, _MAKE.esc(value))\nend\nend\nreturn result\nend\nfunction premake.gcc.getlinkflags(cfg)\nlocal result = {}\nfor _, value in ipairs(premake.getlinks(cfg, \"system\", \"fullpath\")) do\nif premake.gcc.islibfile(value) then\ntable.insert(result, _MAKE.esc(value))\nelseif path.getextension(value) == \".framework\" then\ntable.insert(result, '-framework ' .. _MAKE.esc(path.getbasename(value)))\nelse\ntable.insert(result, '-l' .. _MAKE.esc(path" diff --git a/packages/games/libretro/meowpc98/package.mk b/packages/games/libretro/meowpc98/package.mk new file mode 100644 index 000000000..b4d162f86 --- /dev/null +++ b/packages/games/libretro/meowpc98/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="meowpc98" +PKG_VERSION="cd389b3490d5048873c40edd949a1b0631e0606d" +PKG_SHA256="6689487085533e6db9f95151ad202a7a04f0b6ddfcc9db87b32cbb34ed4ef4c0" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Unknown" +PKG_SITE="https://github.com/libretro/libretro-meowPC98" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Neko Project 2 (PC98 emulator) port for libretro/RetroArch" +PKG_LONGDESC="Neko Project 2 (PC98 emulator) port for libretro/RetroArch" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -C libretro -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp libretro/nekop2_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mgba/package.mk b/packages/games/libretro/mgba/package.mk new file mode 100644 index 000000000..bc33eb465 --- /dev/null +++ b/packages/games/libretro/mgba/package.mk @@ -0,0 +1,53 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mgba" +PKG_VERSION="033e067285745909722df930deaeead80ea2d54a" +PKG_SHA256="792f835cf2c10279350047e43ffd1550f78a7dfcf886880c35ce15e5ea34e998" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MPLv2.0" +PKG_SITE="https://github.com/libretro/mgba" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="mGBA Game Boy Advance Emulator" +PKG_LONGDESC="mGBA is a new emulator for running Game Boy Advance games. It aims to be faster and more accurate than many existing Game Boy Advance emulators, as well as adding features that other emulators lack." +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_USE_CMAKE="no" + +make_target() { + cd $PKG_BUILD + if [[ "$ARCH" =~ "arm" ]]; then + make -f Makefile.libretro platform=unix-armv HAVE_NEON=1 + else + make -f Makefile.libretro platform=goadvance + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mgba_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mgba/patches/RG351MP b/packages/games/libretro/mgba/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/mgba/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/mgba/patches/RG351P/libretro-mgba-0001-rumble.patch b/packages/games/libretro/mgba/patches/RG351P/libretro-mgba-0001-rumble.patch new file mode 100644 index 000000000..acb8b11c8 --- /dev/null +++ b/packages/games/libretro/mgba/patches/RG351P/libretro-mgba-0001-rumble.patch @@ -0,0 +1,27 @@ +diff -rupN mgba-417eb53ec10c8de41335b13e69f8f28eb90c91c4.orig/src/platform/libretro/libretro.c mgba-417eb53ec10c8de41335b13e69f8f28eb90c91c4/src/platform/libretro/libretro.c + --- mgba-417eb53ec10c8de41335b13e69f8f28eb90c91c4.orig/src/platform/libretro/libretro.c 2020-12-01 18:59:59.638698704 -0500 + +++ mgba-417eb53ec10c8de41335b13e69f8f28eb90c91c4/src/platform/libretro/libretro.c 2020-12-01 19:08:02.608690046 -0500 + @@ -1503,12 +1503,19 @@ void retro_run(void) { + */ + + if (rumbleCallback) { + + FILE *fp; + if (rumbleUp) { + - rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + - rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + + //rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + + //rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + + fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); + + fprintf(fp, "10"); + + fclose(fp); + } else { + - rumbleCallback(0, RETRO_RUMBLE_STRONG, 0); + - rumbleCallback(0, RETRO_RUMBLE_WEAK, 0); + + //rumbleCallback(0, RETRO_RUMBLE_STRONG, 0); + + //rumbleCallback(0, RETRO_RUMBLE_WEAK, 0); + + fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); + + fprintf(fp, "1000000"); + + fclose(fp); + } + rumbleUp = 0; + rumbleDown = 0; diff --git a/packages/games/libretro/mgba/patches/RG351V b/packages/games/libretro/mgba/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/mgba/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/mrboom/package.mk b/packages/games/libretro/mrboom/package.mk new file mode 100644 index 000000000..f72013ca3 --- /dev/null +++ b/packages/games/libretro/mrboom/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mrboom" +PKG_VERSION="9b51b0faa49ab4f5008a3fff4d67681a920c344f" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/mrboom-libretro" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Mr.Boom is a 8 players Bomberman clone for RetroArch/Libretro" +PKG_LONGDESC="Mr.Boom is a 8 players Bomberman clone for RetroArch/Libretro" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_configure_target() { +if [ "$ARCH" == "arm" ]; then +PKG_MAKE_OPTS_TARGET="platform=classic_armv7_a7" +#else +#PKG_MAKE_OPTS_TARGET="platform=classic_armv7_a7" +fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mrboom_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mupen64plus-nx/package.mk b/packages/games/libretro/mupen64plus-nx/package.mk new file mode 100755 index 000000000..7e86e2a1a --- /dev/null +++ b/packages/games/libretro/mupen64plus-nx/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="mupen64plus-nx" +PKG_VERSION="018ee72b4fe247b38ed161033ad12a19bb936f00" +PKG_SHA256="1dd5d92adc5db29e03ee493cbfea4406de9a4b9c0e90106dd7e1bf8ed1e1d208" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/mupen64plus-libretro-nx" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain nasm:host $OPENGLES" +PKG_SECTION="libretro" +PKG_SHORTDESC="mupen64plus NX" +PKG_LONGDESC="mupen64plus NX" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" + +pre_configure_target() { + sed -e "s|^GIT_VERSION ?.*$|GIT_VERSION := \" ${PKG_VERSION:0:7}\"|" -i Makefile + +if [ $ARCH == "arm" ]; then + sed -i "s|cortex-a53|cortex-a35|g" Makefile + PKG_MAKE_OPTS_TARGET+=" platform=odroidgoa" +else + PKG_MAKE_OPTS_TARGET+=" platform=amlogic64" +fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mupen64plus_next_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mupen64plus-nx/patches/mupen64plus-nx-01-add-amlogic64.patch b/packages/games/libretro/mupen64plus-nx/patches/mupen64plus-nx-01-add-amlogic64.patch new file mode 100644 index 000000000..aa0f186cf --- /dev/null +++ b/packages/games/libretro/mupen64plus-nx/patches/mupen64plus-nx-01-add-amlogic64.patch @@ -0,0 +1,19 @@ +--- a/Makefile ++++ b/Makefile +@@ -248,9 +248,13 @@ + LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined -ldl + GLES = 1 + GL_LIB := -lGLESv2 +- CPUFLAGS += -marm -mfloat-abi=hard -mfpu=neon +- HAVE_NEON = 1 +- WITH_DYNAREC=arm ++ ifneq (,$(findstring amlogic64,$(platform))) ++ WITH_DYNAREC=aarch64 ++ else ++ CPUFLAGS += -marm -mfloat-abi=hard -mfpu=neon ++ HAVE_NEON = 1 ++ WITH_DYNAREC=arm ++ endif + COREFLAGS += -DUSE_GENERIC_GLESV2 -DOS_LINUX + CPUFLAGS += -march=armv8-a -mcpu=cortex-a53 -mtune=cortex-a53 + diff --git a/packages/games/libretro/mupen64plus/package.mk b/packages/games/libretro/mupen64plus/package.mk new file mode 100644 index 000000000..8a2698447 --- /dev/null +++ b/packages/games/libretro/mupen64plus/package.mk @@ -0,0 +1,78 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="mupen64plus" +PKG_VERSION="ab8134ac90a567581df6de4fc427dd67bfad1b17" +PKG_SHA256="98e197cdcac64c0e08eda91a6d63b637c3f151066bede25766e62bc1a59552a0" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/mupen64plus-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain nasm:host $OPENGLES" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="mupen64plus + RSP-HLE + GLideN64 + libretro" +PKG_LONGDESC="mupen64plus + RSP-HLE + GLideN64 + libretro" +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" +PKG_PATCH_DIRS+="${DEVICE}" + +pre_make_target() { + export CFLAGS="${CFLAGS} -fcommon" +} + +pre_configure_target() { + + case $PROJECT in + Amlogic-ng) + if [ $ARCH == "arm" ]; then + PKG_MAKE_OPTS_TARGET="platform=odroid board=c2" + else + PKG_MAKE_OPTS_TARGET="platform=odroid64 board=n2 HAVE_NEON=0" + fi + ;; + Amlogic) + if [ $ARCH == "arm" ]; then + PKG_MAKE_OPTS_TARGET="platform=odroid BOARD=c2" + else + PKG_MAKE_OPTS_TARGET="platform=odroid64 BOARD=c2 HAVE_NEON=0" + fi + ;; + esac + + if [[ "$DEVICE" =~ RG351 ]] || [[ "$DEVICE" =~ RG552 ]]; then + if [[ "$ARCH" == "arm" ]]; then + CFLAGS="$CFLAGS -DLINUX -DEGL_API_FB" + CPPFLAGS="$CPPFLAGS -DLINUX -DEGL_API_FB" + PKG_MAKE_OPTS_TARGET=" platform=unix GLES=1 FORCE_GLES=1 HAVE_NEON=1 WITH_DYNAREC=arm" + else + CFLAGS="$CFLAGS -DLINUX -DEGL_API_FB" + CPPFLAGS="$CPPFLAGS -DLINUX -DEGL_API_FB" + PKG_MAKE_OPTS_TARGET=" platform=unix GLES=1 FORCE_GLES=1 HAVE_NEON=0 WITH_DYNAREC=aarch64" + fi + fi + +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp mupen64plus_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/mupen64plus/patches/RG351MP b/packages/games/libretro/mupen64plus/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/mupen64plus/patches/RG351P/mupen64plus-fix-rumble.patch b/packages/games/libretro/mupen64plus/patches/RG351P/mupen64plus-fix-rumble.patch new file mode 100644 index 000000000..10494f5e9 --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/RG351P/mupen64plus-fix-rumble.patch @@ -0,0 +1,25 @@ +diff -rupN mupen64plus-libretro-ab8134ac90a567581df6de4fc427dd67bfad1b17.orig/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c mupen64plus-libretro-ab8134ac90a567581df6de4fc427dd67bfad1b17/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c +--- mupen64plus-libretro-ab8134ac90a567581df6de4fc427dd67bfad1b17.orig/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c 2020-11-19 14:38:34.233991783 -0500 ++++ mupen64plus-libretro-ab8134ac90a567581df6de4fc427dd67bfad1b17/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c 2020-12-02 04:49:12.778279430 -0500 +@@ -252,13 +252,21 @@ EXPORT void CALL inputControllerCommand( + + if ((dwAddress == PAK_IO_RUMBLE) && (rumble.set_rumble_state)) + { ++ FILE *fp; ++ + if (*Data) + { ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "10"); ++ fclose(fp); + rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0xFFFF); + rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0xFFFF); + } + else + { ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "1000000"); ++ fclose(fp); + rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0); + rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0); + } diff --git a/packages/games/libretro/mupen64plus/patches/RG351V b/packages/games/libretro/mupen64plus/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/mupen64plus/patches/mupen64plus-fixdouble.patch b/packages/games/libretro/mupen64plus/patches/mupen64plus-fixdouble.patch new file mode 100644 index 000000000..64070b5d2 --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/mupen64plus-fixdouble.patch @@ -0,0 +1,12 @@ +diff --git a/libretro-common/include/glsym/rglgen_headers.h b/libretro-common/include/glsym/rglgen_headers.h +index 766efb63..3de538d6 100644 +--- a/libretro-common/include/glsym/rglgen_headers.h ++++ b/libretro-common/include/glsym/rglgen_headers.h +@@ -53,6 +53,7 @@ + #include + #elif defined(HAVE_OPENGLES2) + #include ++#define GL_NV_path_rendering + #include + #elif defined(HAVE_OPENGLES1) + #include diff --git a/packages/games/libretro/mupen64plus/patches/mupen64plus-inc-string.patch b/packages/games/libretro/mupen64plus/patches/mupen64plus-inc-string.patch new file mode 100644 index 000000000..5c85488ab --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/mupen64plus-inc-string.patch @@ -0,0 +1,11 @@ +diff -rupN mupen64plus-libretro.orig/GLideN64/src/ShaderUtils.h mupen64plus-libretro.new/GLideN64/src/ShaderUtils.h +--- mupen64plus-libretro.orig/GLideN64/src/ShaderUtils.h 2021-01-27 17:21:42.177358627 -0500 ++++ mupen64plus-libretro.new/GLideN64/src/ShaderUtils.h 2021-01-27 17:22:02.081763415 -0500 +@@ -1,6 +1,7 @@ + #ifndef SHADER_UTILS_H + #define SHADER_UTILS_H + ++#include + #include "OpenGL.h" + #include "Combiner.h" + diff --git a/packages/games/libretro/mupen64plus/patches/mupen64plus-sx05re-neonfix.patch b/packages/games/libretro/mupen64plus/patches/mupen64plus-sx05re-neonfix.patch new file mode 100644 index 000000000..6a994c192 --- /dev/null +++ b/packages/games/libretro/mupen64plus/patches/mupen64plus-sx05re-neonfix.patch @@ -0,0 +1,11 @@ +--- a/Makefile 2018-12-15 12:01:25.246556521 -0600 ++++ b/Makefile 2018-12-15 12:01:37.110536416 -0600 +@@ -92,6 +92,8 @@ + else + GL_LIB := -lGL + endif ++ HAVE_NEON = 1 ++ WITH_DYNAREC=arm + + COREFLAGS += -DOS_LINUX + ASFLAGS = -f elf -d ELF_TYPE diff --git a/packages/games/libretro/neocd_libretro/package.mk b/packages/games/libretro/neocd_libretro/package.mk new file mode 100644 index 000000000..a7e450ba8 --- /dev/null +++ b/packages/games/libretro/neocd_libretro/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="neocd_libretro" +PKG_VERSION="83d10f3be10fff2f28aa56fc674c687528cb7f5c" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="LGPLv3.0" +PKG_SITE="https://github.com/libretro/neocd_libretro" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain flac libogg libvorbis" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Neo Geo CD emulator for libretro " +PKG_LONGDESC="NeoCD-Libretro is a complete rewrite of NeoCD from scratch in modern C++11. It is designed with accuracy and portability in mind rather than being all about speed like the the older versions. The goal is also to document all I know about the platform in the source code so other emulator authors can make their own implementations." +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +GET_HANDLER_SUPPORT="git" + +make_target() { +cd $PKG_BUILD +CFLAGS=$CFLAGS CXXFLAGS="$CXXFLAGS" CXX="$CXX" CC="$CC" LD="$LD" RANLIB="$RANLIB" AR="$AR" make +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/neocd_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/nestopia/package.mk b/packages/games/libretro/nestopia/package.mk new file mode 100644 index 000000000..a14ee45e5 --- /dev/null +++ b/packages/games/libretro/nestopia/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="nestopia" +PKG_VERSION="ea6f1c0631bb62bf15ab96493127dd9cfaf74d1c" +PKG_SHA256="d8c84a8fdf24cf80875b67b47d844690ea78c6b7c25e9b3cf2394c0dae20289b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/nestopia" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Libretro implementation of NEStopia. (Nintendo Entertainment System)" +PKG_LONGDESC="This project is a fork of the original Nestopia source code, plus the Linux port. The purpose of the project is to enhance the original, and ensure it continues to work on modern operating systems." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_USE_CMAKE="no" + +make_target() { + cd $PKG_BUILD + make -C libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp libretro/nestopia_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/np2kai/package.mk b/packages/games/libretro/np2kai/package.mk new file mode 100644 index 000000000..95a0479b4 --- /dev/null +++ b/packages/games/libretro/np2kai/package.mk @@ -0,0 +1,44 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="np2kai" +PKG_VERSION="910ab3f636af8d159c85464029f3e59b1a835374" +PKG_SHA256="7fc2f52d7297b3707b3cc7868fae06d08a32a48d782ade8ab293bd0f7cd399d5" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/AZO234/NP2kai" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Neko Project II kai" +PKG_TOOLCHAIN="make" + +make_target() { + VERSION="${PKG_VERSION:0:7}" + cd $PKG_BUILD/sdl + make NP2KAI_VERSION=$VERSION NP2KAI_HASH=$VERSION +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/sdl/np2kai_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/nxengine/package.mk b/packages/games/libretro/nxengine/package.mk new file mode 100644 index 000000000..4c4ba0fa2 --- /dev/null +++ b/packages/games/libretro/nxengine/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="nxengine" +PKG_VERSION="4e2ea9ffe86bb7a0605677636b68431d470b4572" +PKG_SHA256="ca6a4533c117e708b0370e00a1e650bc60e5be3177ed0a7b2717379903c9bf6b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/nxengine-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of NxEngine to libretro - Cave Story game engine clone" +PKG_LONGDESC="A complete open-source clone/rewrite of the masterpiece jump-and-run platformer Doukutsu Monogatari (also known as Cave Story)." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +pre_configure_target() { + sed -i -e "s/CC = gcc//" Makefile +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp nxengine_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/o2em/package.mk b/packages/games/libretro/o2em/package.mk new file mode 100644 index 000000000..93c98ab3b --- /dev/null +++ b/packages/games/libretro/o2em/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="o2em" +PKG_VERSION="c039e83f2589cb9d21b9aa5dc211954234ab8c97" +PKG_SHA256="63f8ab5feed119f092ba102a66cfe32f5e5c5279928e3a71f01df503c5390d4a" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Artistic License" +PKG_SITE="https://github.com/libretro/libretro-o2em" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of O2EM to the libretro API, an Odyssey 2 / VideoPac emulator." +PKG_LONGDESC="Port of O2EM to the libretro API, an Odyssey 2 / VideoPac emulator." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp o2em_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/opera/package.mk b/packages/games/libretro/opera/package.mk new file mode 100644 index 000000000..0be475878 --- /dev/null +++ b/packages/games/libretro/opera/package.mk @@ -0,0 +1,44 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="opera" +PKG_VERSION="aa868e656b518567a95b11b2f14c5db8001b11a0" +PKG_SHA256="373e59a9a59feb26e04b90eaa7ffadcc0d3c4c043a8e501817d1bfb921e8433d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="LGPL with additional notes" +PKG_SITE="https://github.com/libretro/opera-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of 4DO/libfreedo to libretro." +PKG_LONGDESC="Port of 4DO/libfreedo to libretro." +PKG_TOOLCHAIN="make" + + +make_target() { + make CC=$CC CXX=$CXX AR=$AR +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp opera_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/parallel-n64/package.mk b/packages/games/libretro/parallel-n64/package.mk new file mode 100644 index 000000000..9f1f4fabc --- /dev/null +++ b/packages/games/libretro/parallel-n64/package.mk @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="parallel-n64" +PKG_VERSION="0a67445ce63513584d92e5c57ea87efe0da9b3bd" +PKG_SHA256="141205571de2a5c0646ee4d33d32e71d86c8f4a75e43aba73c103c62cc15affd" +PKG_REV="2" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/parallel-n64" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain $OPENGLES" +PKG_SECTION="libretro" +PKG_SHORTDESC="Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus." +PKG_LONGDESC="Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus." +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" +PKG_PATCH_DIRS+="${DEVICE}" + +if [[ "$ARCH" == "arm" ]]; then + PKG_MAKE_OPTS_TARGET=" platform=${PROJECT}" + + if [[ "${DEVICE}" =~ RG351 ]]; then + PKG_MAKE_OPTS_TARGET=" platform=Odroidgoa" + else + PKG_MAKE_OPTS_TARGET=" platform=Amlogic" + fi +else + PKG_MAKE_OPTS_TARGET=" platform=emuelec64-armv8" + +fi + +pre_configure_target() { + sed -i 's/"GFX Plugin; auto|glide64|gln64|rice/"GFX Plugin; rice|auto|glide64|gln64/g' $PKG_BUILD/libretro/libretro.c + #sed -i 's/"Resolution (restart); 320x240|640x480|960x720/"Resolution (restart); 640x480|320x240|960x720/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"Framerate (restart); original|fullspeed"/"Framerate (restart); fullspeed|original"/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"GFX Accuracy (restart); veryhigh|high|medium|low"/"GFX Accuracy (restart); low|veryhigh|high|medium"/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"(Glide64) Texture Filtering; automatic|N64 3-point|bilinear|nearest"/"(Glide64) Texture Filtering; nearest|automatic|N64 3-point|bilinear"/g' $PKG_BUILD/libretro/libretro.c +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + if [[ "$ARCH" == "aarch64" ]] + then + cp -vP $PKG_BUILD/../../build.${DISTRO}-${DEVICE}.arm/parallel-n64-*/.install_pkg/usr/lib/libretro/parallel_n64_libretro.so ${INSTALL}/usr/lib/libretro/ + else + cp parallel_n64_libretro.so $INSTALL/usr/lib/libretro/ + fi +} diff --git a/packages/games/libretro/parallel-n64/patches/RG351MP b/packages/games/libretro/parallel-n64/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/parallel-n64/patches/RG351P/parallel-n64-add_rumble.patch b/packages/games/libretro/parallel-n64/patches/RG351P/parallel-n64-add_rumble.patch new file mode 100644 index 000000000..b08e7336e --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/RG351P/parallel-n64-add_rumble.patch @@ -0,0 +1,30 @@ +diff -rupN parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501.orig/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c +--- parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501.orig/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c 2020-12-01 18:13:36.858538746 -0500 ++++ parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c 2020-12-01 20:21:41.806421568 -0500 +@@ -257,15 +257,22 @@ EXPORT void CALL inputControllerCommand( + + if ((dwAddress == PAK_IO_RUMBLE) && (rumble.set_rumble_state)) + { ++ FILE *fp; + if (*Data) + { +- rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0xFFFF); +- rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0xFFFF); ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "10"); ++ fclose(fp); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0xFFFF); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0xFFFF); + } + else + { +- rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0); +- rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0); ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "1000000"); ++ fclose(fp); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0); + } + } + } diff --git a/packages/games/libretro/parallel-n64/patches/RG351V b/packages/games/libretro/parallel-n64/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/parallel-n64/patches/aarch64/01-gcc-10.patch b/packages/games/libretro/parallel-n64/patches/aarch64/01-gcc-10.patch new file mode 100644 index 000000000..52f155887 --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/aarch64/01-gcc-10.patch @@ -0,0 +1,11 @@ +diff -rupN parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c parallel-n64.new/mupen64plus-core/src/r4300/r4300.c +--- parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:25.028974337 -0500 ++++ parallel-n64.new/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:53.761102557 -0500 +@@ -50,7 +50,6 @@ + unsigned int r4300emu = 0; + unsigned int count_per_op = COUNT_PER_OP_DEFAULT; + unsigned int llbit; +-int stop; + #if NEW_DYNAREC < NEW_DYNAREC_ARM + int64_t reg[32], hi, lo; + uint32_t next_interrupt; diff --git a/packages/games/libretro/parallel-n64/patches/aarch64/parallel-n64-add_platform.patch b/packages/games/libretro/parallel-n64/patches/aarch64/parallel-n64-add_platform.patch new file mode 100644 index 000000000..a968cb7bf --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/aarch64/parallel-n64-add_platform.patch @@ -0,0 +1,80 @@ +diff -rupN parallel-n64.orig/Makefile parallel-n64.new/Makefile +--- parallel-n64.orig/Makefile 2021-01-03 08:49:41.024463975 -0500 ++++ parallel-n64.new/Makefile 2021-01-03 08:50:26.568582023 -0500 +@@ -2,8 +2,8 @@ DEBUG=0 + PERF_TEST=0 + HAVE_SHARED_CONTEXT=0 + WITH_CRC=brumme +-FORCE_GLES=0 +-HAVE_OPENGL=1 ++FORCE_GLES=1 ++HAVE_OPENGL=0 + HAVE_VULKAN_DEBUG=0 + GLIDEN64=0 + GLIDEN64CORE=0 +@@ -11,7 +11,7 @@ GLIDEN64ES=0 + HAVE_RSP_DUMP=0 + HAVE_RDP_DUMP=0 + HAVE_RICE=1 +-HAVE_PARALLEL?=0 ++HAVE_PARALLEL?=1 + HAVE_PARALLEL_RSP?=0 + STATIC_LINKING=0 + WANT_LLVM_OVERRIDE=0 +@@ -240,25 +240,24 @@ ifneq (,$(findstring unix,$(platform))) + LDFLAGS += -static-libgcc -static-libstdc++ + endif + +- ####################################### +- # Generic ARMV8 - cross - No GL +- ifneq (,$(findstring armv8,$(platform))) +- CC = aarch64-linux-gnu-gcc +- CXX = aarch64-linux-gnu-g++ +- CPUFLAGS += -DNO_ASM -DARM -DARM_ASM -DDONT_WANT_ARM_OPTIMIZATIONS -DARM_FIX -DCLASSIC -DARM64 +- LDFLAGS += -static-libgcc -static-libstdc++ +- GLES = 0 +- HAVE_NEON = 0 +- WITH_DYNAREC=aarch64 +- ifneq (,$(findstring neon,$(platform))) +- CPUFLAGS += -D__NEON_OPT -mfpu=neon +- HAVE_NEON = 1 +- endif +- endif ++ ####################################### ++ # EmuELEC 64bit ARMV8 - cross - No GL ++ifneq (,$(findstring emuelec64-armv8,$(platform))) ++ CPUFLAGS += -DNO_ASM -DDONT_WANT_ARM_OPTIMIZATIONS -DARM_FIX -DCLASSIC -DARM64 ++ LDFLAGS += -static-libgcc #-static-libstdc++ ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv3 ++ HAVE_OPENGL = 0 ++ HAVE_NEON = 1 ++ FORCE_GLES = 1 ++ WITH_DYNAREC=aarch64 ++ PLATFORM_EXT := unix ++ + + ####################################### + # Generic ARM +- ifneq (,$(findstring armv,$(platform))) ++ else ifneq (,$(findstring armv,$(platform))) + CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -DNOSSE + WITH_DYNAREC=arm + ifneq (,$(findstring neon,$(platform))) +@@ -279,6 +278,15 @@ else ifneq (,$(findstring imx6,$(platfor + PLATFORM_EXT := unix + WITH_DYNAREC=arm + HAVE_NEON=1 ++ ASFLAGS += -D__ARM_NEON__ -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno \ ++ -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard + + # OS X + else ifneq (,$(findstring osx,$(platform))) diff --git a/packages/games/libretro/parallel-n64/patches/arm/01-gcc-10.patch b/packages/games/libretro/parallel-n64/patches/arm/01-gcc-10.patch new file mode 100644 index 000000000..52f155887 --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/arm/01-gcc-10.patch @@ -0,0 +1,11 @@ +diff -rupN parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c parallel-n64.new/mupen64plus-core/src/r4300/r4300.c +--- parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:25.028974337 -0500 ++++ parallel-n64.new/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:53.761102557 -0500 +@@ -50,7 +50,6 @@ + unsigned int r4300emu = 0; + unsigned int count_per_op = COUNT_PER_OP_DEFAULT; + unsigned int llbit; +-int stop; + #if NEW_DYNAREC < NEW_DYNAREC_ARM + int64_t reg[32], hi, lo; + uint32_t next_interrupt; diff --git a/packages/games/libretro/parallel-n64/patches/arm/parallel-n64-add_platform.patch b/packages/games/libretro/parallel-n64/patches/arm/parallel-n64-add_platform.patch new file mode 100644 index 000000000..abed20058 --- /dev/null +++ b/packages/games/libretro/parallel-n64/patches/arm/parallel-n64-add_platform.patch @@ -0,0 +1,62 @@ +--- a/Makefile ++++ b/Makefile +@@ -280,6 +280,59 @@ + PLATFORM_EXT := unix + WITH_DYNAREC=arm + HAVE_NEON=1 ++ ++# Emuelec Amlogic ++else ifneq (,$(findstring Amlogic,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv2 ++ CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -D__NEON_OPT -DNOSSE -DARM_FIX -DCLASSIC ++ PLATFORM_EXT := unix ++ WITH_DYNAREC=arm ++ HAVE_NEON=1 ++ ++ ifneq (,$(findstring Amlogic-ng,$(platform))) ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a73 -mtune=cortex-a73.cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ else ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a53 -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ endif ++ ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno ++ ifneq (,$(findstring Amlogic-ng,$(platform))) ++ CPUFLAGS += -marm -mtune=cortex-a73.cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ else ++ CPUFLAGS += -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ endif ++ ++# Emuelec OdroidGoA ++else ifneq (,$(findstring Odroidgoa,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv2 ++ CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -D__NEON_OPT -DNOSSE -DARM_FIX -DCLASSIC ++ PLATFORM_EXT := unix ++ WITH_DYNAREC=arm ++ HAVE_NEON=1 ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a35 -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno ++ CPUFLAGS += -marm -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard + + # OS X + else ifneq (,$(findstring osx,$(platform))) diff --git a/packages/games/libretro/parallel-n64_gln64/package.mk b/packages/games/libretro/parallel-n64_gln64/package.mk new file mode 100644 index 000000000..e793c6d04 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/package.mk @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="parallel-n64_gln64" +PKG_VERSION="0a67445ce63513584d92e5c57ea87efe0da9b3bd" +PKG_SHA256="141205571de2a5c0646ee4d33d32e71d86c8f4a75e43aba73c103c62cc15affd" +PKG_REV="2" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/parallel-n64" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain $OPENGLES core-info" +PKG_SECTION="libretro" +PKG_SHORTDESC="Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus." +PKG_LONGDESC="Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus." +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="-lto" +PKG_PATCH_DIRS+="${DEVICE}" + +if [[ "$ARCH" == "arm" ]]; then + PKG_MAKE_OPTS_TARGET=" platform=${PROJECT}" + + if [[ "${DEVICE}" =~ RG351 ]]; then + PKG_MAKE_OPTS_TARGET=" platform=Odroidgoa" + else + PKG_MAKE_OPTS_TARGET=" platform=Amlogic" + fi +else + PKG_MAKE_OPTS_TARGET=" platform=emuelec64-armv8" + +fi + +pre_configure_target() { + sed -i 's/info->library_name = "ParaLLEl N64";/info->library_name = "ParaLLEl N64 GLN64";/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"GFX Plugin; auto|glide64|gln64|rice/"GFX Plugin; gln64|auto|glide64|rice/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"Resolution (restart); 320x240|640x480|960x720/"Resolution (restart); 640x480|320x240|960x720/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"Framerate (restart); original|fullspeed"/"Framerate (restart); fullspeed|original"/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"GFX Accuracy (restart); veryhigh|high|medium|low"/"GFX Accuracy (restart); medium|veryhigh|high|low"/g' $PKG_BUILD/libretro/libretro.c + sed -i 's/"(Glide64) Texture Filtering; automatic|N64 3-point|bilinear|nearest"/"(Glide64) Texture Filtering; nearest|automatic|N64 3-point|bilinear"/g' $PKG_BUILD/libretro/libretro.c +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + if [[ "$DEVICE" =~ RG351 ]] && [[ "$ARCH" == "aarch64" ]] + then + cp -vP $PKG_BUILD/../../build.${DISTRO}-${DEVICE}.arm/parallel-n64_gln64-*/.install_pkg/usr/lib/libretro/parallel_n64_gln64_libretro.so ${INSTALL}/usr/lib/libretro/parallel_n64_gln64_libretro.so + cp -vP $PKG_BUILD/../core-info-*/parallel_n64_libretro.info ${INSTALL}/usr/lib/libretro/parallel_n64_gln64_libretro.info + sed -i 's/ParaLLEl N64/ParaLLEl N64 GLN64/g' $INSTALL/usr/lib/libretro/parallel_n64_gln64_libretro.info + else + cp parallel_n64_libretro.so $INSTALL/usr/lib/libretro/parallel_n64_gln64_libretro.so + fi +} diff --git a/packages/games/libretro/parallel-n64_gln64/patches/RG351MP b/packages/games/libretro/parallel-n64_gln64/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/parallel-n64_gln64/patches/RG351P/parallel-n64-add_rumble.patch b/packages/games/libretro/parallel-n64_gln64/patches/RG351P/parallel-n64-add_rumble.patch new file mode 100644 index 000000000..b08e7336e --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/RG351P/parallel-n64-add_rumble.patch @@ -0,0 +1,30 @@ +diff -rupN parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501.orig/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c +--- parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501.orig/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c 2020-12-01 18:13:36.858538746 -0500 ++++ parallel-n64-cfb9789e13ccbeaabd928203566346c05709d501/mupen64plus-core/src/plugin/emulate_game_controller_via_libretro.c 2020-12-01 20:21:41.806421568 -0500 +@@ -257,15 +257,22 @@ EXPORT void CALL inputControllerCommand( + + if ((dwAddress == PAK_IO_RUMBLE) && (rumble.set_rumble_state)) + { ++ FILE *fp; + if (*Data) + { +- rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0xFFFF); +- rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0xFFFF); ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "10"); ++ fclose(fp); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0xFFFF); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0xFFFF); + } + else + { +- rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0); +- rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0); ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "1000000"); ++ fclose(fp); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_WEAK, 0); ++ //rumble.set_rumble_state(Control, RETRO_RUMBLE_STRONG, 0); + } + } + } diff --git a/packages/games/libretro/parallel-n64_gln64/patches/RG351V b/packages/games/libretro/parallel-n64_gln64/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/parallel-n64_gln64/patches/aarch64/01-gcc-10.patch b/packages/games/libretro/parallel-n64_gln64/patches/aarch64/01-gcc-10.patch new file mode 100644 index 000000000..52f155887 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/aarch64/01-gcc-10.patch @@ -0,0 +1,11 @@ +diff -rupN parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c parallel-n64.new/mupen64plus-core/src/r4300/r4300.c +--- parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:25.028974337 -0500 ++++ parallel-n64.new/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:53.761102557 -0500 +@@ -50,7 +50,6 @@ + unsigned int r4300emu = 0; + unsigned int count_per_op = COUNT_PER_OP_DEFAULT; + unsigned int llbit; +-int stop; + #if NEW_DYNAREC < NEW_DYNAREC_ARM + int64_t reg[32], hi, lo; + uint32_t next_interrupt; diff --git a/packages/games/libretro/parallel-n64_gln64/patches/aarch64/parallel-n64-add_platform.patch b/packages/games/libretro/parallel-n64_gln64/patches/aarch64/parallel-n64-add_platform.patch new file mode 100644 index 000000000..a968cb7bf --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/aarch64/parallel-n64-add_platform.patch @@ -0,0 +1,80 @@ +diff -rupN parallel-n64.orig/Makefile parallel-n64.new/Makefile +--- parallel-n64.orig/Makefile 2021-01-03 08:49:41.024463975 -0500 ++++ parallel-n64.new/Makefile 2021-01-03 08:50:26.568582023 -0500 +@@ -2,8 +2,8 @@ DEBUG=0 + PERF_TEST=0 + HAVE_SHARED_CONTEXT=0 + WITH_CRC=brumme +-FORCE_GLES=0 +-HAVE_OPENGL=1 ++FORCE_GLES=1 ++HAVE_OPENGL=0 + HAVE_VULKAN_DEBUG=0 + GLIDEN64=0 + GLIDEN64CORE=0 +@@ -11,7 +11,7 @@ GLIDEN64ES=0 + HAVE_RSP_DUMP=0 + HAVE_RDP_DUMP=0 + HAVE_RICE=1 +-HAVE_PARALLEL?=0 ++HAVE_PARALLEL?=1 + HAVE_PARALLEL_RSP?=0 + STATIC_LINKING=0 + WANT_LLVM_OVERRIDE=0 +@@ -240,25 +240,24 @@ ifneq (,$(findstring unix,$(platform))) + LDFLAGS += -static-libgcc -static-libstdc++ + endif + +- ####################################### +- # Generic ARMV8 - cross - No GL +- ifneq (,$(findstring armv8,$(platform))) +- CC = aarch64-linux-gnu-gcc +- CXX = aarch64-linux-gnu-g++ +- CPUFLAGS += -DNO_ASM -DARM -DARM_ASM -DDONT_WANT_ARM_OPTIMIZATIONS -DARM_FIX -DCLASSIC -DARM64 +- LDFLAGS += -static-libgcc -static-libstdc++ +- GLES = 0 +- HAVE_NEON = 0 +- WITH_DYNAREC=aarch64 +- ifneq (,$(findstring neon,$(platform))) +- CPUFLAGS += -D__NEON_OPT -mfpu=neon +- HAVE_NEON = 1 +- endif +- endif ++ ####################################### ++ # EmuELEC 64bit ARMV8 - cross - No GL ++ifneq (,$(findstring emuelec64-armv8,$(platform))) ++ CPUFLAGS += -DNO_ASM -DDONT_WANT_ARM_OPTIMIZATIONS -DARM_FIX -DCLASSIC -DARM64 ++ LDFLAGS += -static-libgcc #-static-libstdc++ ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv3 ++ HAVE_OPENGL = 0 ++ HAVE_NEON = 1 ++ FORCE_GLES = 1 ++ WITH_DYNAREC=aarch64 ++ PLATFORM_EXT := unix ++ + + ####################################### + # Generic ARM +- ifneq (,$(findstring armv,$(platform))) ++ else ifneq (,$(findstring armv,$(platform))) + CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -DNOSSE + WITH_DYNAREC=arm + ifneq (,$(findstring neon,$(platform))) +@@ -279,6 +278,15 @@ else ifneq (,$(findstring imx6,$(platfor + PLATFORM_EXT := unix + WITH_DYNAREC=arm + HAVE_NEON=1 ++ ASFLAGS += -D__ARM_NEON__ -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno \ ++ -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard + + # OS X + else ifneq (,$(findstring osx,$(platform))) diff --git a/packages/games/libretro/parallel-n64_gln64/patches/arm/01-gcc-10.patch b/packages/games/libretro/parallel-n64_gln64/patches/arm/01-gcc-10.patch new file mode 100644 index 000000000..52f155887 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/arm/01-gcc-10.patch @@ -0,0 +1,11 @@ +diff -rupN parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c parallel-n64.new/mupen64plus-core/src/r4300/r4300.c +--- parallel-n64.orig/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:25.028974337 -0500 ++++ parallel-n64.new/mupen64plus-core/src/r4300/r4300.c 2021-01-24 13:07:53.761102557 -0500 +@@ -50,7 +50,6 @@ + unsigned int r4300emu = 0; + unsigned int count_per_op = COUNT_PER_OP_DEFAULT; + unsigned int llbit; +-int stop; + #if NEW_DYNAREC < NEW_DYNAREC_ARM + int64_t reg[32], hi, lo; + uint32_t next_interrupt; diff --git a/packages/games/libretro/parallel-n64_gln64/patches/arm/parallel-n64-add_platform.patch b/packages/games/libretro/parallel-n64_gln64/patches/arm/parallel-n64-add_platform.patch new file mode 100644 index 000000000..abed20058 --- /dev/null +++ b/packages/games/libretro/parallel-n64_gln64/patches/arm/parallel-n64-add_platform.patch @@ -0,0 +1,62 @@ +--- a/Makefile ++++ b/Makefile +@@ -280,6 +280,59 @@ + PLATFORM_EXT := unix + WITH_DYNAREC=arm + HAVE_NEON=1 ++ ++# Emuelec Amlogic ++else ifneq (,$(findstring Amlogic,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv2 ++ CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -D__NEON_OPT -DNOSSE -DARM_FIX -DCLASSIC ++ PLATFORM_EXT := unix ++ WITH_DYNAREC=arm ++ HAVE_NEON=1 ++ ++ ifneq (,$(findstring Amlogic-ng,$(platform))) ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a73 -mtune=cortex-a73.cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ else ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a53 -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ endif ++ ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno ++ ifneq (,$(findstring Amlogic-ng,$(platform))) ++ CPUFLAGS += -marm -mtune=cortex-a73.cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ else ++ CPUFLAGS += -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ endif ++ ++# Emuelec OdroidGoA ++else ifneq (,$(findstring Odroidgoa,$(platform))) ++ TARGET := $(TARGET_NAME)_libretro.so ++ LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T ++ fpic = -fPIC ++ GLES = 1 ++ GL_LIB := -lGLESv2 ++ CPUFLAGS += -DNO_ASM -DARM -D__arm__ -DARM_ASM -D__NEON_OPT -DNOSSE -DARM_FIX -DCLASSIC ++ PLATFORM_EXT := unix ++ WITH_DYNAREC=arm ++ HAVE_NEON=1 ++ ASFLAGS += -D__ARM_NEON__ -marm -mcpu=cortex-a35 -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ ++ CPUFLAGS += -O2 \ ++ -fno-lto -fuse-linker-plugin -fno-semantic-interposition -fno-trapping-math \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=32 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fno-strict-aliasing -fmerge-all-constants -fno-math-errno ++ CPUFLAGS += -marm -mtune=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard + + # OS X + else ifneq (,$(findstring osx,$(platform))) diff --git a/packages/games/libretro/pcsx_rearmed/package.mk b/packages/games/libretro/pcsx_rearmed/package.mk new file mode 100644 index 000000000..b5ef6d301 --- /dev/null +++ b/packages/games/libretro/pcsx_rearmed/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020 Trond Haugland (trondah@gmail.com) + +PKG_NAME="pcsx_rearmed" +PKG_VERSION="f2585a3793deaa1aabf01b8713188d79bd0b57ee" +PKG_SHA256="1242769138817c55878fba67d8ac73ccbd71d08a964d1f3a99318b01fac30877" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/pcsx_rearmed" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_SHORTDESC="ARM optimized PCSX fork" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+speed -gold" +PKG_PATCH_DIRS+="${DEVICE}" + +make_target() { + cd ${PKG_BUILD} + if [ ! "${ARCH}" = "aarch64" ]; then + make -f Makefile.libretro GIT_VERSION=${PKG_VERSION} platform=rpi3 + fi +} + +makeinstall_target() { + INSTALLTO="/usr/lib/libretro/" + + mkdir -p ${INSTALL}${INSTALLTO} + cd ${PKG_BUILD} + if [ "${ARCH}" = "aarch64" ]; then + cp -vP ${PKG_BUILD}/../../build.${DISTRO}-${DEVICE}.arm/pcsx_rearmed-*/.install_pkg/usr/lib/libretro/pcsx_rearmed_libretro.so ${INSTALL}${INSTALLTO} + else + cp pcsx_rearmed_libretro.so ${INSTALL}${INSTALLTO} + fi +} diff --git a/packages/games/libretro/pcsx_rearmed/patches/RG351MP b/packages/games/libretro/pcsx_rearmed/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/pcsx_rearmed/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/pcsx_rearmed/patches/RG351P/libretro-pcsx-rearmed-0002-rumble.patch b/packages/games/libretro/pcsx_rearmed/patches/RG351P/libretro-pcsx-rearmed-0002-rumble.patch new file mode 100644 index 000000000..9f1c4cc11 --- /dev/null +++ b/packages/games/libretro/pcsx_rearmed/patches/RG351P/libretro-pcsx-rearmed-0002-rumble.patch @@ -0,0 +1,26 @@ +diff --git a/frontend/libretro.c b/frontend/libretro.c +index d0a0da7..1c20ba9 100644 +--- a/frontend/libretro.c ++++ b/frontend/libretro.c +@@ -495,8 +495,19 @@ void plat_trigger_vibrate(int pad, int low, int high) + + if (in_enable_vibration) + { +- rumble_cb(pad, RETRO_RUMBLE_STRONG, high << 8); +- rumble_cb(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0); ++ int total_strength; ++ if(high > 0){ ++ total_strength = 1000000 - (((double)high * 1000000) / 255.0); ++ } else if (low > 0){ ++ total_strength = 100000; //We only have one motor, so this will have to do to make it weak enough ++ } else { ++ total_strength = 1000000; //turn it off ++ } ++ ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", total_strength); ++ fclose(fp); + } + } + diff --git a/packages/games/libretro/pcsx_rearmed/patches/RG351V b/packages/games/libretro/pcsx_rearmed/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/pcsx_rearmed/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/picodrive/package.mk b/packages/games/libretro/picodrive/package.mk new file mode 100644 index 000000000..f2a8cde8f --- /dev/null +++ b/packages/games/libretro/picodrive/package.mk @@ -0,0 +1,33 @@ +PKG_NAME="picodrive" +PKG_VERSION="3edf1a00f64e0f22331233bb1638170115b2ac2e" +PKG_LICENSE="MAME" +PKG_SITE="https://github.com/libretro/picodrive" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Libretro implementation of PicoDrive. (Sega Megadrive/Genesis/Sega Master System/Sega GameGear/Sega CD/32X)" +PKG_LONGDESC="This is yet another Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS emulator, which was written having ARM-based handheld devices in mind (such as smartphones and handheld consoles like GP2X and Pandora), but also runs on non-ARM little-endian hardware too." +GET_HANDLER_SUPPORT="git" +PKG_BUILD_FLAGS="-gold" +PKG_TOOLCHAIN="make" + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +PKG_PATCH_DIRS="${PROJECT}" + +configure_target() { + : +} + +make_target() { + cd $PKG_BUILD +# $PKG_BUILD/configure --platform=generic + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/picodrive_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/pokemini/package.mk b/packages/games/libretro/pokemini/package.mk new file mode 100644 index 000000000..d63117e9d --- /dev/null +++ b/packages/games/libretro/pokemini/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="pokemini" +PKG_VERSION="b24883d9bddaa3ee32f06a6f2e361581414dc155" +PKG_SHA256="0f2ec8312f472599aefcb9fdd448609f542660a96372eb0fd0df4998ab107483" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/pokemini" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Obscure nintendo handheld emulator (functional,no color files or savestates currently)" +PKG_LONGDESC="Obscure nintendo handheld emulator (functional,no color files or savestates currently)" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_PATCH_DIRS+="${DEVICE}" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp pokemini_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/pokemini/patches/RG351MP b/packages/games/libretro/pokemini/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/pokemini/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/pokemini/patches/RG351P/rumble.patch b/packages/games/libretro/pokemini/patches/RG351P/rumble.patch new file mode 100644 index 000000000..c60c9aa53 --- /dev/null +++ b/packages/games/libretro/pokemini/patches/RG351P/rumble.patch @@ -0,0 +1,33 @@ +diff --git a/libretro/libretro.c b/libretro/libretro.c +index 4c0ec1b..ad71408 100644 +--- a/libretro/libretro.c ++++ b/libretro/libretro.c +@@ -173,8 +173,12 @@ static void ActivateControllerRumble(void) + (rumble_strength_prev == rumble_strength)) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, rumble_strength); +- rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, rumble_strength); ++ uint pwm_duty_cycle = 1000000 - (int)(((double)rumble_strength / 65535.0) * 1000000.0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", pwm_duty_cycle); ++ fclose(fp); ++ + rumble_strength_prev = rumble_strength; + } + +@@ -186,8 +190,11 @@ static void DeactivateControllerRumble(void) + (rumble_strength_prev == 0)) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, 0); +- rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, 0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", 1000000); ++ fclose(fp); ++ + rumble_strength_prev = 0; + } + diff --git a/packages/games/libretro/pokemini/patches/RG351V b/packages/games/libretro/pokemini/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/pokemini/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/potator/package.mk b/packages/games/libretro/potator/package.mk new file mode 100644 index 000000000..baeff7020 --- /dev/null +++ b/packages/games/libretro/potator/package.mk @@ -0,0 +1,24 @@ +PKG_NAME="potator" +PKG_VERSION="3e3bfd787306d5a074a91bfd9baee2f9cc3b82f3" +PKG_SHA256="95952073bca7db2fce3747059dea1d809246026928d8785a5ba11edd6e5c6214" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/potator" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A Watara Supervision Emulator based on Normmatt version." +PKG_LONGDESC="A Watara Supervision Emulator based on Normmatt version." +PKG_TOOLCHAIN="make" + + +make_target() { + make -C platform/libretro/ platform=aarch64 +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp platform/libretro/potator_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/ppsspp/package.mk b/packages/games/libretro/ppsspp/package.mk new file mode 100644 index 000000000..f18429c2c --- /dev/null +++ b/packages/games/libretro/ppsspp/package.mk @@ -0,0 +1,60 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="ppsspp" +PKG_VERSION="824805ec1e60568a9c68c525245882df553c7427" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/hrydgard/ppsspp" +PKG_URL="https://github.com/hrydgard/ppsspp.git" +PKG_DEPENDS_TARGET="toolchain SDL2 ffmpeg libzip" +PKG_LONGDESC="A PSP emulator for Android, Windows, Mac, Linux and Blackberry 10, written in C++." +GET_HANDLER_SUPPORT="git" + +PKG_LIBNAME="ppsspp_libretro.so" +PKG_LIBPATH="lib/$PKG_LIBNAME" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DLIBRETRO=ON \ + -DUSE_SYSTEM_FFMPEG=ON \ + -DUSING_X11_VULKAN=OFF" + + if [ "${ARCH}" = "arm" ] && [ ! "${TARGET_CPU}" = "arm1176jzf-s" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DARMV7=ON" + elif [ "${TARGET_CPU}" = "arm1176jzf-s" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DARM=ON" + fi + + if [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_CMAKE_OPTS_TARGET+=" -DUSING_FBDEV=ON \ + -DUSING_EGL=ON \ + -DUSING_GLES2=ON" + fi +} + +pre_make_target() { + # fix cross compiling + find $PKG_BUILD -name flags.make -exec sed -i "s:isystem :I:g" \{} \; + find $PKG_BUILD -name build.ninja -exec sed -i "s:isystem :I:g" \{} \; +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_LIBPATH $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/ppsspp/patches/ppsspp-x86_64-fix.patch b/packages/games/libretro/ppsspp/patches/ppsspp-x86_64-fix.patch new file mode 100644 index 000000000..e4aec51ba --- /dev/null +++ b/packages/games/libretro/ppsspp/patches/ppsspp-x86_64-fix.patch @@ -0,0 +1,12 @@ +diff -Naur ppsspp-00051fd/ext/glew/glew.c ppsspp-00051fd.patch/ext/glew/glew.c +--- ppsspp-00051fd/ext/glew/glew.c 2018-12-24 10:48:13.869315087 +0100 ++++ ppsspp-00051fd.patch/ext/glew/glew.c 2018-12-24 10:50:23.969537401 +0100 +@@ -20872,8 +20872,6 @@ + return r; + #elif defined(_WIN32) + return wglewInit(); +-#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ +- return glxewInit(); + #else + return r; + #endif /* _WIN32 */ diff --git a/packages/games/libretro/prboom/package.mk b/packages/games/libretro/prboom/package.mk new file mode 100644 index 000000000..7f7a23668 --- /dev/null +++ b/packages/games/libretro/prboom/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="prboom" +PKG_VERSION="0f5927db4fb7e61f32bc9eccc5f809e54f71a371" +PKG_SHA256="7e8a098d347421db1cb867633cf8bb084479282320b538d8fe42f9f1d1c870b8" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/libretro-prboom" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="libretro implementation of Doom" +PKG_LONGDESC="libretro implementation of Doom" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp prboom_libretro.so $INSTALL/usr/lib/libretro/prboom_libretro.so +} diff --git a/packages/games/libretro/prboom/patches/01_351p_resolution.patch b/packages/games/libretro/prboom/patches/01_351p_resolution.patch new file mode 100644 index 000000000..70fb57eee --- /dev/null +++ b/packages/games/libretro/prboom/patches/01_351p_resolution.patch @@ -0,0 +1,34 @@ +diff --git a/libretro/libretro.c b/libretro/libretro.c +index f68d93f..63efdcf 100644 +--- a/libretro/libretro.c ++++ b/libretro/libretro.c +@@ -385,7 +385,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) + info->geometry.base_height = SCREENHEIGHT; + info->geometry.max_width = SCREENWIDTH; + info->geometry.max_height = SCREENHEIGHT; +- info->geometry.aspect_ratio = 4.0 / 3.0; ++ info->geometry.aspect_ratio = 3.0 / 2.0; + } + + +diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h +index e764703..dc65f4a 100644 +--- a/libretro/libretro_core_options.h ++++ b/libretro/libretro_core_options.h +@@ -33,6 +33,7 @@ struct retro_core_option_definition option_defs_us[] = { + "Configure the resolution. Requires a restart.", + { + { "320x200", NULL }, ++ { "480x320", NULL }, + { "640x400", NULL }, + { "960x600", NULL }, + { "1280x800", NULL }, +@@ -42,7 +43,7 @@ struct retro_core_option_definition option_defs_us[] = { + { "2560x1600", NULL }, + { NULL, NULL }, + }, +- "320x200" ++ "480x320" + }, + { + "prboom-mouse_on", diff --git a/packages/games/libretro/prosystem/package.mk b/packages/games/libretro/prosystem/package.mk new file mode 100644 index 000000000..a2f8d4d33 --- /dev/null +++ b/packages/games/libretro/prosystem/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="prosystem" +PKG_VERSION="f8652c7f2b0edc81685d03204d4963fc4ea9eccd" +PKG_SHA256="bd55930b3139f5f4b9be61b9049e074cfa23aab36aafb3e5daaaec6d9db0a403" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/prosystem-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of ProSystem to libretro." +PKG_LONGDESC="Port of ProSystem to libretro." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp prosystem_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/puae/package.mk b/packages/games/libretro/puae/package.mk new file mode 100644 index 000000000..b86ed87a3 --- /dev/null +++ b/packages/games/libretro/puae/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="puae" +PKG_VERSION="f151bab41034b715628a2c62ce224fd0f581a132" +PKG_SHA256="6b4d1335aa3a7f6eace82e6a3ba7430cbc8b6765ea5a7f367126be6ad4d5875d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/libretro-uae" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="WIP libretro port of UAE (P-UAE and libco) Expect bugs" +PKG_LONGDESC="WIP libretro port of UAE (P-UAE and libco) Expect bugs" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DARM -marm" + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp puae_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/px68k/package.mk b/packages/games/libretro/px68k/package.mk new file mode 100644 index 000000000..f70a2073f --- /dev/null +++ b/packages/games/libretro/px68k/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="px68k" +PKG_VERSION="ea6e5a7ac00b6472cafca0132fddf854ec7bd666" +PKG_SHA256="c2ceeb1eb40aba9376a82ddbe76f28ab24bf74cf26ec387c8f42bb3b1dc151e9" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Unknown" +PKG_SITE="https://github.com/libretro/px68k-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Portable SHARP X68000 Emulator for PSP, Android and other platforms" +PKG_LONGDESC="Portable SHARP X68000 Emulator for PSP, Android and other platforms" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp px68k_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/px68k/patches/RG351MP b/packages/games/libretro/px68k/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/px68k/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/px68k/patches/RG351P/rumble.patch b/packages/games/libretro/px68k/patches/RG351P/rumble.patch new file mode 100644 index 000000000..93b8dd4dd --- /dev/null +++ b/packages/games/libretro/px68k/patches/RG351P/rumble.patch @@ -0,0 +1,26 @@ +diff --git a/libretro.c b/libretro.c +index fc68189..b87787e 100644 +--- a/libretro.c ++++ b/libretro.c +@@ -1362,13 +1362,17 @@ static void rumbleFrames(void) + { + if (opt_rumble_enabled && FDD_IsReading) + { +- rumble_cb(0, RETRO_RUMBLE_STRONG, 0x8000); +- rumble_cb(0, RETRO_RUMBLE_WEAK, 0x800); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", 1); ++ fclose(fp); + } + else + { +- rumble_cb(0, RETRO_RUMBLE_STRONG, 0); +- rumble_cb(0, RETRO_RUMBLE_WEAK, 0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", 1000000); ++ fclose(fp); + } + } + diff --git a/packages/games/libretro/px68k/patches/RG351V b/packages/games/libretro/px68k/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/px68k/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/quasi88/package.mk b/packages/games/libretro/quasi88/package.mk new file mode 100644 index 000000000..8213452ac --- /dev/null +++ b/packages/games/libretro/quasi88/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="quasi88" +PKG_VERSION="f16f5b7a466fb4e48f40b778a968807dfda6afdc" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="BSD3" +PKG_SITE="https://github.com/libretro/quasi88-libretro" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A port of QUASI88, a PC-8800 series emulator by Showzoh Fukunaga, to the libretro API" +PKG_LONGDESC="A port of QUASI88, a PC-8800 series emulator by Showzoh Fukunaga, to the libretro API" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp quasi88_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/quicknes/package.mk b/packages/games/libretro/quicknes/package.mk new file mode 100644 index 000000000..980ab45c8 --- /dev/null +++ b/packages/games/libretro/quicknes/package.mk @@ -0,0 +1,50 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="quicknes" +PKG_VERSION="71b8000b33daab8ed488f8707ccd8d5b623443f8" +PKG_SHA256="c884a6610999177815d7b4c66a5821d3d5c498595c03b65936e1fd3e87593e54" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="LGPLv2.1+" +PKG_SITE="https://github.com/libretro/QuickNES_Core" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="The QuickNES core library, originally by Shay Green, heavily modified" +PKG_LONGDESC="The QuickNES core library, originally by Shay Green, heavily modified" +PKG_BUILD_FLAGS="-gold" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + VERSION='GIT_VERSION ?= ' + VERSION+=${PKG_VERSION:0:7} + sed -i "s/GIT_VERSION ?= \" \$(shell git describe --dirty --always --tags)\"/${VERSION}/g" $PKG_BUILD/Makefile + make +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp quicknes_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/race/package.mk b/packages/games/libretro/race/package.mk new file mode 100644 index 000000000..2f5abcf73 --- /dev/null +++ b/packages/games/libretro/race/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="race" +PKG_VERSION="b8264bbaa0878e2d0ebae8ca60bd886c5971e255" +PKG_SHA256="51633d70e45e89d46dc97c1990b3d5cb0ff2cba7773023a16392db825f9ffa6b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/RACE" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="This is the RACE NGPC emulator modified by theelf to run on the PSP." +PKG_LONGDESC="This is the RACE NGPC emulator modified by theelf to run on the PSP." +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp race_libretro.so $INSTALL/usr/lib/libretro/ +} \ No newline at end of file diff --git a/packages/games/libretro/reminiscence/package.mk b/packages/games/libretro/reminiscence/package.mk new file mode 100644 index 000000000..b1a42830d --- /dev/null +++ b/packages/games/libretro/reminiscence/package.mk @@ -0,0 +1,49 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="reminiscence" +PKG_VERSION="dbf2f5964c21f36e045ccd2cb50ac2513fdca75d" +PKG_SHA256="88e039c45679b804bf70be5405a13c647ce8a0ba351e5490286401027b028c28" +PKG_ARCH="any" +PKG_SITE="https://github.com/libretro/REminiscence" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Gregory Montoir's Flashback emulator, running as a libretro core." +PKG_LONGDESC="Port of Gregory Montoir's Flashback emulator, running as a libretro core." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +configure_target () { + : # nothing to do +} + +make_target() { + cd $PKG_BUILD + make +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp reminiscence_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/sameboy/package.mk b/packages/games/libretro/sameboy/package.mk new file mode 100644 index 000000000..0da7aafef --- /dev/null +++ b/packages/games/libretro/sameboy/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="sameboy" +PKG_VERSION="fb3c7dd7d89df1f696e4cde33a868e141c927790" +PKG_SHA256="e2f65e729d97bd0f8113dd72e20fb99d50b8dc3622ab18ba7692eb77124cd01c" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/sameboy" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_GIT_CLONE_BRANCH="buildbot" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Gameboy and Gameboy Color emulator written in C" +PKG_LONGDESC="Gameboy and Gameboy Color emulator written in C" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -C libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp libretro/sameboy_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/sameduck/package.mk b/packages/games/libretro/sameduck/package.mk new file mode 100644 index 000000000..04fa8d9fe --- /dev/null +++ b/packages/games/libretro/sameduck/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="sameduck" +PKG_VERSION="a5e5462f79164d21053f81fc680bfa9f59a2bf59" +PKG_SHA256="3d6b14c98a0f455dba758df0cde72b57426f68fa76ce578ae38b4053a65e35ed" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/LIJI32/SameBoy" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_GIT_CLONE_BRANCH="SameDuck" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Mega Duck/Cougar Boy emulator written in C" +PKG_LONGDESC="Mega Duck/Cougar Boy emulator written in C" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -C libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp build/bin/sameduck_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/scummvm/package.mk b/packages/games/libretro/scummvm/package.mk new file mode 100644 index 000000000..730d9d1b3 --- /dev/null +++ b/packages/games/libretro/scummvm/package.mk @@ -0,0 +1,57 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="scummvm" +PKG_VERSION="4c6f0bb94320c80420316813a0226b156398073a" +PKG_SHA256="b94ce825c4d20e4038a27a0abc3540ea09a2c8dc3a588f847b4f1376fe65a48a" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/diablodiab/scummvm" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="ScummVM with libretro backend." +PKG_LONGDESC="ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_BUILD_FLAGS="-lto" + +pre_configure_target() { + cd .. + rm -rf .$TARGET_NAME +} + +configure_target() { + : +} + +make_target() { +# sed -i 's/ENABLE_AGS/\/\/ENABLE_AGS/g' backends/platform/libretro/build/config.hd + make -C backends/platform/libretro/build CXXFLAGS="$CXXFLAGS -DHAVE_POSIX_MEMALIGN=1" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp backends/platform/libretro/build/scummvm_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/smsplus-gx/package.mk b/packages/games/libretro/smsplus-gx/package.mk new file mode 100644 index 000000000..d081a4194 --- /dev/null +++ b/packages/games/libretro/smsplus-gx/package.mk @@ -0,0 +1,50 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="smsplus-gx" +PKG_VERSION="3f1ffede55bcfe0168caa484a00bf041ab591abf" +PKG_SHA256="ccc848dff2b23bca7b1295697267bfa1d876e934a3f5f78001ccf35bb29f1dee" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/smsplus-gx" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="SMS Plus GX is an enhanced version" +PKG_LONGDESC="SMS Plus is an open-source Sega Master System and Game Gear emulator written by Charles MacDonald." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DALIGN_LONG" + fi + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp smsplus_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/snes9x/package.mk b/packages/games/libretro/snes9x/package.mk new file mode 100644 index 000000000..fc70f2e44 --- /dev/null +++ b/packages/games/libretro/snes9x/package.mk @@ -0,0 +1,50 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="snes9x" +PKG_VERSION="fb93aedd612537e233c6872a5d7ebe65e8169ade" +PKG_SHA256="a9d1d690850375e2720597daa763d0e6644c4d20cc2eee0d0d4ec07d3497bdcd" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Snes9x - Portable Super Nintendo Entertainment System (TM) emulator" +PKG_LONGDESC="Snes9x - Portable Super Nintendo Entertainment System (TM) emulator" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + if [ "$ARCH" == "arm" ]; then + CXXFLAGS="$CXXFLAGS -DARM" + fi + + make -C libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp libretro/snes9x_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/snes9x2002/package.mk b/packages/games/libretro/snes9x2002/package.mk new file mode 100644 index 000000000..a806380cf --- /dev/null +++ b/packages/games/libretro/snes9x2002/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="snes9x2002" +PKG_VERSION="e16cb16efa00765b1bc3b8fee195680efb1542c7" +PKG_SHA256="68d19be6cec1f44d4a1f01d1d63aab4d372b73ec07de6369a45b81535b022021" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x2002" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Snes9x 2002." +PKG_LONGDESC="Snes9x 2002. Port of SNES9x 1.39 for libretro (was previously called PocketSNES). Heavily optimized for ARM." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp snes9x2002_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/snes9x2005_plus/package.mk b/packages/games/libretro/snes9x2005_plus/package.mk new file mode 100644 index 000000000..cc9f0d53d --- /dev/null +++ b/packages/games/libretro/snes9x2005_plus/package.mk @@ -0,0 +1,41 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="snes9x2005_plus" +PKG_VERSION="88a46f7c085f6e2accc4c777e264b9b5cd41cf0e" +PKG_SHA256="4d57dde2d1ed67e0945c24a85f1f84a980ee4b13013643abc928497915ca6abc" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x2005" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Snes9x 2005 Plus." +PKG_LONGDESC="Snes9x 2005 Plus. Port of SNES9x 1.43 for libretro (was previously called CAT SFC) with enabled BLARRG APU." +PKG_TOOLCHAIN="make" + +PKG_MAKE_OPTS_TARGET="USE_BLARGG_APU=1 platform=armv8-hardfloat-neon" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp snes9x2005_plus_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/snes9x2005_plus/patches/01-snes9x2005_plux-01-fix-fpic.patch b/packages/games/libretro/snes9x2005_plus/patches/01-snes9x2005_plux-01-fix-fpic.patch new file mode 100644 index 000000000..3868c0280 --- /dev/null +++ b/packages/games/libretro/snes9x2005_plus/patches/01-snes9x2005_plux-01-fix-fpic.patch @@ -0,0 +1,26 @@ +--- a/Makefile ++++ b/Makefile +@@ -74,9 +74,10 @@ + else ifneq (,$(findstring armv,$(platform))) + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC ++ FLAGS += $(fpic) + SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T +- CC = gcc +- CXX = g++ ++ #CC = gcc ++ #CXX = g++ + PLATFORM_DEFINES += -marm + ifneq (,$(findstring softfloat,$(platform))) + PLATFORM_DEFINES += -mfloat-abi=softfp +@@ -84,8 +85,8 @@ + PLATFORM_DEFINES += -mfloat-abi=hard + endif + ifneq (,$(findstring neon,$(platform))) +- FLAGS += -mfpu=neon +- ASFLAGS += -mfpu=neon ++ #FLAGS += -mfpu=neon ++ #ASFLAGS += -mfpu=neon + HAVE_NEON = 1 + endif + PLATFORM_DEFINES += -DARM diff --git a/packages/games/libretro/snes9x2010/package.mk b/packages/games/libretro/snes9x2010/package.mk new file mode 100644 index 000000000..8918faa50 --- /dev/null +++ b/packages/games/libretro/snes9x2010/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="snes9x2010" +PKG_VERSION="714b1c8e08c7580430190119b07e793405773ac2" +PKG_SHA256="e6a1106dbed204c642a7eec037b63ac32e56f12cf27df838288861ed6da77070" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Non-commercial" +PKG_SITE="https://github.com/libretro/snes9x2010" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Snes9x 2010." +PKG_LONGDESC="Snes9x 2010. Port of Snes9x 1.52+ to Libretro (previously called SNES9x Next). Rewritten in C and several optimizations and speedhacks." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp snes9x2010_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/snes9x2010/patches/snes9x2010-add-oga.patch b/packages/games/libretro/snes9x2010/patches/snes9x2010-add-oga.patch new file mode 100644 index 000000000..80f797f28 --- /dev/null +++ b/packages/games/libretro/snes9x2010/patches/snes9x2010-add-oga.patch @@ -0,0 +1,32 @@ +--- a/Makefile.libretro ++++ b/Makefile.libretro +@@ -344,6 +344,29 @@ + endif + ####################################### + ++ ++######################################### ++# (armv8 a35, hard point, neon based) ### ++# Odroid Go Advance ++else ifeq ($(platform), goa_armv8_a35) ++TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined ++ CFLAGS += -Ofast \ ++ -flto=4 -fuse-linker-plugin \ ++ -fdata-sections -ffunction-sections -Wl,--gc-sections \ ++ -fno-stack-protector -fno-ident -fomit-frame-pointer \ ++ -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ ++ -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ ++ -fmerge-all-constants -fno-math-errno \ ++ -marm -mcpu=cortex-a35 -mfpu=neon-fp-armv8 -mfloat-abi=hard ++ CXXFLAGS += $(CFLAGS) ++ CPPFLAGS += $(CFLAGS) ++ ASFLAGS += $(CFLAGS) ++ HAVE_NEON = 1 ++ ARCH = arm ++ BUILTIN_GPU = neon ++ USE_DYNAREC = 1 + # Xbox 360 + else ifeq ($(platform), xenon) + EXT=a diff --git a/packages/games/libretro/stella-2014/package.mk b/packages/games/libretro/stella-2014/package.mk new file mode 100644 index 000000000..d10b31b24 --- /dev/null +++ b/packages/games/libretro/stella-2014/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="stella-2014" +PKG_VERSION="934c7a2a44ef038af529b68950ddba4f7ea3478e" +PKG_SHA256="8a4d10ce4646f0d474efc339e4db9211dd36bbf3089e98f236367368b231a8d9" +PKG_REV="1" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/libretro/stella2014-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Stella to libretro." +PKG_LONGDESC="Stella is a multi-platform Atari 2600 VCS emulator released under the GNU General Public License (GPL)." +PKG_TOOLCHAIN="make" + +pre_configure_target() { +PKG_MAKE_OPTS_TARGET=" -C $PKG_BUILD/ -f Makefile platform=emuelec-arm64" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/stella2014_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/stella-2014/patches/stella-2014-01-makefile.patch b/packages/games/libretro/stella-2014/patches/stella-2014-01-makefile.patch new file mode 100644 index 000000000..773df8cfc --- /dev/null +++ b/packages/games/libretro/stella-2014/patches/stella-2014-01-makefile.patch @@ -0,0 +1,19 @@ +--- a/Makefile ++++ b/Makefile +@@ -83,6 +83,16 @@ + fpic += -mmacosx-version-min=10.7 + endif + ++# EmuELEC for Amlogic devices ++else ifeq ($(platform), emuelec-arm64) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined ++ CXXFLAGS += -lpthread -DARM64 ++ LDFLAGS += -lpthread -static-libgcc -lstdc++ ++ ARCH = arm64 ++ USE_DYNAREC = 1 ++ + # iOS + else ifneq (,$(findstring ios,$(platform))) + TARGET := $(TARGET_NAME)_libretro_ios.dylib diff --git a/packages/games/libretro/stella/package.mk b/packages/games/libretro/stella/package.mk new file mode 100644 index 000000000..b1eb2c591 --- /dev/null +++ b/packages/games/libretro/stella/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="stella" +PKG_VERSION="f619b4e5cb01eefe0c01dedc01b452b3f74aab26" +PKG_SHA256="2c02f7449b297a90c4ee34d31eb22f71dd233c1de35890092417a071d0d708f3" +PKG_REV="1" +PKG_LICENSE="GPL2" +PKG_SITE="https://github.com/stella-emu/stella" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Stella to libretro." +PKG_LONGDESC="Stella is a multi-platform Atari 2600 VCS emulator released under the GNU General Public License (GPL)." +PKG_TOOLCHAIN="make" + +pre_configure_target() { +if [ "$ARCH" == "arm" ]; then +PKG_MAKE_OPTS_TARGET=" -C $PKG_BUILD/src/libretro -f Makefile platform=emuelec" +else +PKG_MAKE_OPTS_TARGET=" -C $PKG_BUILD/src/libretro -f Makefile platform=emuelec-arm64" +fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/src/libretro/stella_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/stella/patches/stella-01-emuelec-platform.patch b/packages/games/libretro/stella/patches/stella-01-emuelec-platform.patch new file mode 100644 index 000000000..8e22a8815 --- /dev/null +++ b/packages/games/libretro/stella/patches/stella-01-emuelec-platform.patch @@ -0,0 +1,30 @@ +--- a/src/libretro/Makefile ++++ b/src/libretro/Makefile +@@ -137,6 +137,27 @@ + endif + endif + ++# EmuELEC for Amlogic devices ++else ifeq ($(platform), emuelec) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined ++ CXXFLAGS += -lpthread -marm -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7ve -DARM ++ LDFLAGS += -lpthread -static-libgcc -lstdc++ ++ HAVE_NEON = 1 ++ ARCH = arm ++ BUILTIN_GPU = neon ++ USE_DYNAREC = 1 ++else ifeq ($(platform), emuelec-arm64) ++ TARGET := $(TARGET_NAME)_libretro.so ++ fpic := -fPIC ++ SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined ++ CXXFLAGS += -lpthread -DARM64 ++ LDFLAGS += -lpthread -static-libgcc -lstdc++ ++ ARCH = arm64 ++ USE_DYNAREC = 1 ++ ++ + # iOS + else ifneq (,$(findstring ios,$(platform))) + CXXFLAGS += $(LTO) $(PTHREAD_FLAGS) -stdlib=libc++ diff --git a/packages/games/libretro/swanstation/package.mk b/packages/games/libretro/swanstation/package.mk new file mode 100644 index 000000000..ac208a383 --- /dev/null +++ b/packages/games/libretro/swanstation/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Maintenance 2020 351ELEC team (https://github.com/fewtarius/351ELEC) + +PKG_NAME="swanstation" +PKG_VERSION="cc3946b2b3bd10282bc46078c245db09f6e68836" +PKG_SHA256="285be1d0c1c53d61653ef3f648da752f4e686c1e3f9cf8bb06853fbaed0e20c2" +PKG_ARCH="aarch64" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/swanstation" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain nasm:host $OPENGLES" +PKG_SECTION="libretro" +PKG_SHORTDESC="SwanStation - PlayStation 1, aka. PSX Emulator" +PKG_TOOLCHAIN="cmake" +PKG_BUILD_FLAGS="-lto" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET+=" -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON " +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/.$TARGET_NAME/swanstation_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/tgbdual/package.mk b/packages/games/libretro/tgbdual/package.mk new file mode 100644 index 000000000..3a9df9878 --- /dev/null +++ b/packages/games/libretro/tgbdual/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="tgbdual" +PKG_VERSION="1e0c4f931d8c5e859e6d3255d67247d7a2987434" +PKG_SHA256="86fdbeec998e751e051fe80ecfd92ed5020b2436e01a4e40815718479174923a" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/tgbdual-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="libretro port of TGB Dual" +PKG_LONGDESC="TGB Dual is an open source (GPLv2) GB/GBC emulator with game link cable support." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp tgbdual_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/tyrquake/package.mk b/packages/games/libretro/tyrquake/package.mk new file mode 100644 index 000000000..d396a6760 --- /dev/null +++ b/packages/games/libretro/tyrquake/package.mk @@ -0,0 +1,49 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="tyrquake" +PKG_VERSION="19aa11e965a6dbb31d418e99bcd14d86eb822b20" +PKG_SHA256="45649e890666e860797960825d99475350f329a1ae29d01a53188662c1ae9c55" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/tyrquake" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Libretro port of Tyrquake (Quake 1 engine)" +PKG_LONGDESC="Libretro port of Tyrquake (Quake 1 engine)" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +pre_configure_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DARM -marm" + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp tyrquake_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/tyrquake/patches/RG351MP b/packages/games/libretro/tyrquake/patches/RG351MP new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/tyrquake/patches/RG351MP @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/tyrquake/patches/RG351P/01_351p_resolution.patch b/packages/games/libretro/tyrquake/patches/RG351P/01_351p_resolution.patch new file mode 100644 index 000000000..a98a7264a --- /dev/null +++ b/packages/games/libretro/tyrquake/patches/RG351P/01_351p_resolution.patch @@ -0,0 +1,43 @@ +diff --git a/common/libretro.c b/common/libretro.c +index 4f48b90..8d28885 100644 +--- a/common/libretro.c ++++ b/common/libretro.c +@@ -572,7 +572,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) + info->geometry.base_height = height; + info->geometry.max_width = width; + info->geometry.max_height = height; +- info->geometry.aspect_ratio = 4.0 / 3.0; ++ info->geometry.aspect_ratio = 3.0 / 2.0; + } + + void retro_set_environment(retro_environment_t cb) +diff --git a/common/libretro_core_options.h b/common/libretro_core_options.h +index e15b3a3..8eff659 100644 +--- a/common/libretro_core_options.h ++++ b/common/libretro_core_options.h +@@ -42,6 +42,7 @@ struct retro_core_option_definition option_defs_us[] = { + { "400x224", NULL }, + { "400x240", NULL }, + { "480x272", NULL }, ++ { "480x320", NULL }, + { "512x224", NULL }, + { "512x240", NULL }, + { "512x384", NULL }, +@@ -71,7 +72,7 @@ struct retro_core_option_definition option_defs_us[] = { + #elif defined(DINGUX) + "320x240" + #else +- "320x200" ++ "480x320" + #endif + }, + { +@@ -145,7 +146,7 @@ struct retro_core_option_definition option_defs_us[] = { + { "enabled", "Enabled" }, + { NULL, NULL }, + }, +- "disabled" ++ "enabled" + }, + { + "tyrquake_analog_deadzone", diff --git a/packages/games/libretro/tyrquake/patches/RG351P/rumble.patch b/packages/games/libretro/tyrquake/patches/RG351P/rumble.patch new file mode 100644 index 000000000..65118c1c8 --- /dev/null +++ b/packages/games/libretro/tyrquake/patches/RG351P/rumble.patch @@ -0,0 +1,32 @@ +diff --git a/common/libretro.c b/common/libretro.c +index 4f48b90..db07276 100644 +--- a/common/libretro.c ++++ b/common/libretro.c +@@ -270,7 +270,12 @@ void retro_set_rumble_damage(int damage) + if (strength == rumble_damage_strength) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength); ++ uint pwm_duty_cycle = 1000000 - (int)(((double)strength / 65535.0) * 1000000.0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", pwm_duty_cycle); ++ fclose(fp); ++ + rumble_damage_strength = strength; + } + +@@ -296,7 +301,12 @@ void retro_set_rumble_touch(unsigned intensity, float duration) + if (strength == rumble_touch_strength) + return; + +- rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, strength); ++ uint pwm_duty_cycle = 1000000 - (int)(((double)strength / 65535.0) * 1000000.0); ++ FILE *fp; ++ fp = fopen("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "w"); ++ fprintf(fp, "%u", pwm_duty_cycle); ++ fclose(fp); ++ + rumble_touch_strength = strength; + } + diff --git a/packages/games/libretro/tyrquake/patches/RG351V b/packages/games/libretro/tyrquake/patches/RG351V new file mode 120000 index 000000000..0067f8043 --- /dev/null +++ b/packages/games/libretro/tyrquake/patches/RG351V @@ -0,0 +1 @@ +RG351P \ No newline at end of file diff --git a/packages/games/libretro/uae4arm/package.mk b/packages/games/libretro/uae4arm/package.mk new file mode 100644 index 000000000..39be8acbf --- /dev/null +++ b/packages/games/libretro/uae4arm/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="uae4arm" +PKG_VERSION="4d2e723667a84fcdca73102eb91a83b3c60edba3" +PKG_SHA256="9293d7e690079ff1a55c3df993a74274fbfcbe05196ee70c273ba02fa38df268" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Chips-fr/uae4arm-rpi" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain flac mpg123" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of uae4arm for libretro (rpi/android)" +PKG_LONGDESC="Port of uae4arm for libretro (rpi/android) " + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro platform=unix_aarch64 "CPU_FLAGS=-mcpu=cortex-a35+crypto+crc" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp uae4arm_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/uzem/package.mk b/packages/games/libretro/uzem/package.mk new file mode 100644 index 000000000..fcf750a1d --- /dev/null +++ b/packages/games/libretro/uzem/package.mk @@ -0,0 +1,43 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="uzem" +PKG_VERSION="675b4485b776fe5166612192466c95a25a927a63" +PKG_SHA256="aa860e8cc1fa5050c4d9994059a2ed321b529a1813a37956b07eb98ca9519510" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/libretro/libretro-uzem" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_PATCH_DIRS="libretro" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A retro-minimalist game console engine for the ATMega644" +PKG_LONGDESC="A retro-minimalist game console engine for the ATMega644" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp uzem_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/vba-next/package.mk b/packages/games/libretro/vba-next/package.mk new file mode 100644 index 000000000..8fc820a9d --- /dev/null +++ b/packages/games/libretro/vba-next/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="vba-next" +PKG_VERSION="b218f48bb27b5d3885fa4076ff325922b5acd817" +PKG_SHA256="9aec4b44da688ab4f13c4c960d936a5ff793b5bb5c58446bf2b1aea128de8619" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/vba-next" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Optimized port of VBA-M to Libretro." +PKG_LONGDESC="Optimized port of VBA-M to Libretro. " + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vba_next_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/vbam/package.mk b/packages/games/libretro/vbam/package.mk new file mode 100644 index 000000000..66795eb4a --- /dev/null +++ b/packages/games/libretro/vbam/package.mk @@ -0,0 +1,48 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="vbam" +PKG_VERSION="254f6effebe882b7d3d29d9e417c6aeeabc08026" +PKG_SHA256="0c96037a925d715c47a1d96c36107f25fbd31c990dd28754d71a64873f518c6d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vbam-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="A fork of VBA-M with libretro integration" +PKG_LONGDESC="VBA-M is a [Super] Game Boy [Color / Advance] emulator for Windows, Linux & Mac." + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_USE_CMAKE="no" + +make_target() { + make -C ../src/libretro -f Makefile +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp ../src/libretro/vbam_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/vecx/package.mk b/packages/games/libretro/vecx/package.mk new file mode 100644 index 000000000..d78b5ecd2 --- /dev/null +++ b/packages/games/libretro/vecx/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="vecx" +PKG_VERSION="28d6efc8972313903d0802a736ff8c3bc115e78f" +PKG_SHA256="8584af54ce532c4bb37a20a023eda9fcfa90a5d2bea66d5d65abeeab183836eb" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2|LGPLv2.1" +PKG_SITE="https://github.com/libretro/libretro-vecx" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="libretro adaptation of vecx" +PKG_LONGDESC="libretro adaptation of vecx" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro HAS_GPU=1 HAS_GLES=1 +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp vecx_libretro.so $INSTALL/usr/lib/libretro/vecx_libretro.so +} \ No newline at end of file diff --git a/packages/games/libretro/vice/package.mk b/packages/games/libretro/vice/package.mk new file mode 100644 index 000000000..16865f40b --- /dev/null +++ b/packages/games/libretro/vice/package.mk @@ -0,0 +1,63 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="vice" +PKG_VERSION="81e9837fe4aee32c2e88967fa2f0ca3de240f735" +PKG_SHA256="0c91f6c2d8a144706e590f04f6abd9afcdefe8625c95497f576601e25d0cbf2b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/vice-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Versatile Commodore 8-bit Emulator version 3.0" +PKG_LONGDESC="Versatile Commodore 8-bit Emulator version 3.0" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" +PKG_BUILD_FLAGS="-lto" + +make_target() { + if [ "$ARCH" == "arm" ]; then + CFLAGS="$CFLAGS -DARM -DALIGN_DWORD -mstructure-size-boundary=32 -mthumb-interwork -falign-functions=16 -marm" + fi + if [ ! -d "built" ] + then + mkdir built + fi + for EMUTYPE in x128 x64sc x64dtv xscpu64 xplus4 xvic xcbm5x0 xcbm2 xpet x64 + do + make clean + make EMUTYPE=${EMUTYPE} + mv vice_*_libretro.so built + done +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp built/vice_x128_libretro.so $INSTALL/usr/lib/libretro/ + cp built/vice_x64_libretro.so $INSTALL/usr/lib/libretro/ + cp built/vice_xplus4_libretro.so $INSTALL/usr/lib/libretro/ + cp built/vice_xvic_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/virtualjaguar/package.mk b/packages/games/libretro/virtualjaguar/package.mk new file mode 100644 index 000000000..85e23236e --- /dev/null +++ b/packages/games/libretro/virtualjaguar/package.mk @@ -0,0 +1,42 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="virtualjaguar" +PKG_VERSION="5a293de747823dc0a9ceba0dd878ef75e9a9d920" +PKG_SHA256="9435674689c48e7ac61c0c49a972c84410e4e07dc65be487ccf2d1ae302cd3a8" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/virtualjaguar-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of Virtual Jaguar to Libretro" +PKG_LONGDESC="Port of Virtual Jaguar to Libretro" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp virtualjaguar_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/xmil/package.mk b/packages/games/libretro/xmil/package.mk new file mode 100644 index 000000000..544fd0b7c --- /dev/null +++ b/packages/games/libretro/xmil/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="xmil" +PKG_VERSION="b07506c0cae31d260db28cb079148857d6ca2e93" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="Unknown" +PKG_SITE="https://github.com/r-type/xmil-libretro" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Libretro port of X Millennium Sharp X1 emulator" +PKG_LONGDESC="Libretro port of X Millennium Sharp X1 emulator" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +make_target() { + cd $PKG_BUILD + make -C libretro +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp $PKG_BUILD/libretro/x1_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/xrick/package.mk b/packages/games/libretro/xrick/package.mk new file mode 100644 index 000000000..23f8b9aa2 --- /dev/null +++ b/packages/games/libretro/xrick/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="xrick" +PKG_VERSION="f91e4c8a45d5eacf0a733af219fed33d6e7277ee" +PKG_SHA256="53ef5b36e73b3bc1593bfab70abd130e4677181241c6662441275a7583619c69" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/libretro/xrick-libretro" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Rick Dangerous Game Engine" +PKG_LONGDESC="Rick Dangerous Game Engine" + +PKG_IS_ADDON="no" +PKG_TOOLCHAIN="make" +PKG_AUTORECONF="no" + +make_target() { + make -f Makefile.libretro CC=$CC +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp xrick_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/libretro/yabasanshiro/package.mk b/packages/games/libretro/yabasanshiro/package.mk new file mode 100644 index 000000000..9a6f1e82e --- /dev/null +++ b/packages/games/libretro/yabasanshiro/package.mk @@ -0,0 +1,47 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="yabasanshiro" +PKG_VERSION="2848d5053fef1a69f68c600b65a1b9e0d915056c" +PKG_GIT_CLONE_BRANCH="yabasanshiro" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPLv2" +PKG_SITE="https://github.com/libretro/yabause" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain $OPENGLES" +PKG_PRIORITY="optional" +PKG_SECTION="libretro" +PKG_SHORTDESC="Port of YabaSanshiro to libretro." +PKG_LONGDESC="Port of YabaSanshiro to libretro." +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_configure_target() { + # For some reason linkin to GLESv2 gives error, so we link it to GLESv3 + sed -i "s|-lGLESv2|-lGLESv3|g" $PKG_BUILD/yabause/src/libretro/Makefile.common + sed -i "s|-mcpu=cortex-a53 -mtune=cortex-a53|-mcpu=cortex-a35 -mtune=cortex-a35|g" $PKG_BUILD/yabause/src/libretro/Makefile + PKG_MAKE_OPTS_TARGET+=" -C yabause/src/libretro platform=arm64_cortex_a53_gles3" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libretro + cp yabause/src/libretro/yabasanshiro_libretro.so $INSTALL/usr/lib/libretro/ +} diff --git a/packages/games/native/moonlight/enet/package.mk b/packages/games/native/moonlight/enet/package.mk new file mode 100644 index 000000000..356494795 --- /dev/null +++ b/packages/games/native/moonlight/enet/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="enet" +PKG_VERSION="2cc0e7c78045fe2275e7959eb7b9992fe4fd038d" +PKG_SITE="https://github.com/lsalzman/enet" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_LICENSE="" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A network communication layer on top of UDP (User Datagram Protocol)." +PKG_TOOLCHAIN="autotools" + diff --git a/packages/games/native/moonlight/package.mk b/packages/games/native/moonlight/package.mk new file mode 100644 index 000000000..f1ed402a9 --- /dev/null +++ b/packages/games/native/moonlight/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="moonlight" +PKG_VERSION="5b6639c8a76c4bbb5e0b4bcfe41b8df136608885" +PKG_ARCH="any" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/irtimmer/moonlight-embedded" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain opus libevdev alsa enet" +PKG_SHORTDESC="Moonlight Embedded is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built for Linux." +PKG_TOOLCHAIN="cmake" +GET_HANDLER_SUPPORT="git" + diff --git a/packages/games/native/moonlight/patches/001-rotation.patch b/packages/games/native/moonlight/patches/001-rotation.patch new file mode 100644 index 000000000..98696a6f0 --- /dev/null +++ b/packages/games/native/moonlight/patches/001-rotation.patch @@ -0,0 +1,222 @@ +From fd0cff622860903d4146a15062cfb0ecce300b28 Mon Sep 17 00:00:00 2001 +From: krishenriksen +Date: Mon, 1 Feb 2021 09:21:07 +0700 +Subject: [PATCH 1/2] Rotation and tearing fix on Rockchip video backend for + rg351p + +--- + cmake/FindRockchip.cmake | 10 ++++-- + src/video/rk.c | 77 ++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 83 insertions(+), 4 deletions(-) + +diff --git a/cmake/FindRockchip.cmake b/cmake/FindRockchip.cmake +index 83764dd2..1ad3f938 100644 +--- a/cmake/FindRockchip.cmake ++++ b/cmake/FindRockchip.cmake +@@ -8,7 +8,13 @@ find_library(DRM_LIBRARY + NAMES libdrm.so + DOC "Path to libdrm Library" + PATHS /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/arm-linux-gnueabihf) +-mark_as_advanced(DRM_INCLUDE_DIR) ++mark_as_advanced(DRM_LIBRARY) ++ ++find_library(RGA_LIBRARY ++ NAMES librga.so ++ DOC "Path to librga Library" ++ PATHS /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/arm-linux-gnueabihf) ++mark_as_advanced(RGA_LIBRARY) + + find_path(ROCKCHIP_INCLUDE_DIR + NAMES rk_mpi.h +@@ -26,4 +32,4 @@ include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(Rockchip DEFAULT_MSG ROCKCHIP_INCLUDE_DIR ROCKCHIP_LIBRARY) + + set(ROCKCHIP_INCLUDE_DIRS ${ROCKCHIP_INCLUDE_DIR} ${DRM_INCLUDE_DIR}) +-set(ROCKCHIP_LIBRARIES ${ROCKCHIP_LIBRARY} ${DRM_LIBRARY}) ++set(ROCKCHIP_LIBRARIES ${ROCKCHIP_LIBRARY} ${DRM_LIBRARY} ${RGA_LIBRARY}) +diff --git a/src/video/rk.c b/src/video/rk.c +index 44526443..af9451d7 100644 +--- a/src/video/rk.c ++++ b/src/video/rk.c +@@ -37,15 +37,19 @@ + #include + + #include ++#include + + #define READ_BUF_SIZE 0x00100000 + #define MAX_FRAMES 16 ++#define MAX_DEST_BUFFERS 3 + #define RK_H264 7 + #define RK_H265 16777220 + + void *pkt_buf = NULL; + int fd; + int fb_id; ++int fb_id_rot[MAX_DEST_BUFFERS]; ++int prime_fd_rot[MAX_DEST_BUFFERS]; + uint32_t plane_id, crtc_id; + int frm_eos; + int crtc_width; +@@ -78,6 +82,7 @@ struct { + + void *display_thread(void *param) { + ++ static int index = 0; + int ret; + + while (!frm_eos) { +@@ -94,8 +99,9 @@ void *display_thread(void *param) { + return NULL; + } + } +- _fb_id = fb_id; + ++ _fb_id = fb_id_rot[index]; ++ index = (index + 1) % MAX_DEST_BUFFERS; + fb_id = 0; + ret = pthread_mutex_unlock(&mutex); + assert(!ret); +@@ -110,10 +116,13 @@ void *display_thread(void *param) { + + void *frame_thread(void *param) { + ++ static int index = 0; + int count = 0; + int ret; + int i; + MppFrame frame = NULL; ++ rga_info_t src_info = {0}; ++ rga_info_t dst_info = {0}; + + while (!frm_eos) { + +@@ -137,7 +146,15 @@ void *frame_thread(void *param) { + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + assert((fmt == MPP_FMT_YUV420SP) || (fmt == MPP_FMT_YUV420SP_10BIT)); +- ++ printf("Frame WxH=%dx%d WSxHs=%dx%d\n", frm_width, frm_height, hor_stride, ver_stride); ++ ++#if 1 ++ // position overlay, expand to full screen ++ fb_x = 0; ++ fb_y = 0; ++ fb_width = crtc_width; ++ fb_height = crtc_height; ++#else + // position overlay, scale to ratio + float crt_ratio = (float)crtc_width/crtc_height; + float frame_ratio = (float)frm_width/frm_height; +@@ -153,6 +170,47 @@ void *frame_thread(void *param) { + fb_x = 0; + fb_y = (crtc_height-fb_height)/2; + } ++#endif ++ for (int i = 0; i < MAX_DEST_BUFFERS; i++) { ++ // new DRM buffer for rotated screen ++ struct drm_mode_create_dumb dmcd2 = {0}; ++ dmcd2.bpp = fmt==MPP_FMT_YUV420SP?8:10; ++ dmcd2.width = hor_stride; ++ dmcd2.height = ver_stride*2; // documentation say not v*2/3 but v*2 (additional info included) ++ do { ++ ret = ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcd2); ++ } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); ++ ++ struct drm_prime_handle dph2 = {0}; ++ dph2.handle = dmcd2.handle; ++ dph2.fd = -1; ++ do { ++ ret = ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph2); ++ } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); ++ assert(!ret); ++ ++ prime_fd_rot[i] = dph2.fd; ++ ++ uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; ++ handles[0] = dmcd2.handle; ++ offsets[0] = 0; ++ pitches[0] = hor_stride; ++ handles[1] = dmcd2.handle; ++ offsets[1] = hor_stride * ver_stride; ++ pitches[1] = hor_stride; ++ ret = drmModeAddFB2(fd, frm_width, frm_height, fmt==MPP_FMT_YUV420SP?DRM_FORMAT_NV12:DRM_FORMAT_NV12_10, handles, pitches, offsets, &fb_id_rot[i], 0); ++ assert(!ret); ++ } ++ // setup rotation ++ src_info.mmuFlag = 1; ++ src_info.rotation = HAL_TRANSFORM_ROT_270; ++ ++ rga_set_rect(&src_info.rect, 0, 0, frm_width, frm_height, mpp_frame_get_hor_stride(frame), mpp_frame_get_ver_stride(frame), RK_FORMAT_YCbCr_420_SP); ++ ++ dst_info.fd = prime_fd_rot[index]; ++ dst_info.mmuFlag = 1; ++ ++ rga_set_rect(&dst_info.rect, 0, 0, frm_width, frm_height, mpp_frame_get_hor_stride(frame), mpp_frame_get_ver_stride(frame), RK_FORMAT_YCbCr_420_SP); + + // create new external frame group and allocate (commit flow) new DRM buffers and DRM FB + assert(!mpi_frm_grp); +@@ -220,6 +278,15 @@ void *frame_thread(void *param) { + // send DRM FB to display thread + ret = pthread_mutex_lock(&mutex); + assert(!ret); ++ ++ src_info.fd = frame_to_drm[i].prime_fd; ++ dst_info.fd = prime_fd_rot[index]; ++ index = (index + 1) % MAX_DEST_BUFFERS; ++ ++ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) { ++ fprintf(stderr, "Failed to do rga blit\n"); ++ } ++ + fb_id = frame_to_drm[i].fb_id; + ret = pthread_cond_signal(&cond); + assert(!ret); +@@ -359,6 +426,10 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte + // hide cursor by move in left lower corner + drmModeMoveCursor(fd, crtc_id, 0, crtc_height); + ++ // RGA Setup ++ ++ c_RkRgaInit(); ++ + // MPI SETUP + + pkt_buf = malloc(READ_BUF_SIZE); +@@ -442,6 +513,8 @@ void rk_cleanup() { + mpp_destroy(mpi_ctx); + free(pkt_buf); + ++ c_RkRgaDeInit(); ++ + drmModeFreePlane(ovr); + drmModeFreePlaneResources(plane_resources); + drmModeFreeEncoder(encoder); + +From a812c83ea9946e08854443e4c1ace8a5cb78eb3a Mon Sep 17 00:00:00 2001 +From: Kris Henriksen +Date: Mon, 1 Feb 2021 02:47:54 +0000 +Subject: [PATCH 2/2] added required mode for rockchip + +--- + src/video/rk.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/video/rk.c b/src/video/rk.c +index af9451d7..e40f2c60 100644 +--- a/src/video/rk.c ++++ b/src/video/rk.c +@@ -36,6 +36,13 @@ + #include + #include + ++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2') /* 2x2 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV21_10 fourcc_code('N', 'A', '2', '1') /* 2x2 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV16_10 fourcc_code('N', 'A', '1', '6') /* 2x1 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV61_10 fourcc_code('N', 'A', '6', '1') /* 2x1 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV24_10 fourcc_code('N', 'A', '2', '4') /* non-subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV42_10 fourcc_code('N', 'A', '4', '2') /* non-subsampled Cb:Cr plane */ ++ + #include + #include + diff --git a/packages/games/tools/351files/package.mk b/packages/games/tools/351files/package.mk new file mode 100644 index 000000000..9bcfd3908 --- /dev/null +++ b/packages/games/tools/351files/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351elec) + +PKG_NAME="351files" +PKG_VERSION="bab7144d2b3dccdc090445608d0a21210e3d438b" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Tardigrade-nx/351Files" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_image SDL2_gfx SDL2_ttf" +PKG_PRIORITY="optional" +PKG_SECTION="tools" +PKG_SHORTDESC="A Single panel file Manager tailored for Anbernic 351 devices: RG351V/MP and RG351P/M. Can be easily adapted to any Linux-based device." + +PKG_PATCH_DIRS="${DEVICE}" + +make_target() { + make DEVICE=${DEVICE} RES_PATH=/usr/share/351files/res START_PATH=/storage/roms SDL2_CONFIG=${SYSROOT_PREFIX}/usr/bin/sdl2-config CC=$CXX +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + mkdir -p $INSTALL/usr/share/351files + cp 351Files $INSTALL/usr/bin/ + cp -rf res $INSTALL/usr/share/351files/ +} + diff --git a/packages/games/tools/351files/patches/RG351MP/rg351mp.patch b/packages/games/tools/351files/patches/RG351MP/rg351mp.patch new file mode 100644 index 000000000..c56194bc8 --- /dev/null +++ b/packages/games/tools/351files/patches/RG351MP/rg351mp.patch @@ -0,0 +1,64 @@ +diff --git a/Makefile b/Makefile +index 7b9afa5..bd964f1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,5 +1,6 @@ + TARGET = 351Files + ++# DEVICE ?= RG351MP + # DEVICE ?= RG351P + # DEVICE ?= RG351V + # DEVICE ?= RGB10 +diff --git a/src/def.h b/src/def.h +index 92d1a01..db4fec4 100644 +--- a/src/def.h ++++ b/src/def.h +@@ -85,6 +85,21 @@ + #define KEYBOARD_MARGIN 8 + #define KEYBOARD_KEY_SPACING 4 + ++// Parameters for RG351MP ++#elif defined(DEVICE_RG351MP) ++ #define SCREEN_WIDTH 640 ++ #define SCREEN_HEIGHT 480 ++ #define HARDWARE_ACCELERATION 0 ++ #define FULLSCREEN 1 ++ #define FONT_NAME "NotoSans-Regular.ttf" ++ #define FONT_NAME_MONO "NotoSansMono-Regular.ttf" ++ #define FONT_SIZE 20 ++ #define LINE_HEIGHT 32 ++ #define ICON_SIZE 24 ++ #define MARGIN_X 10 ++ #define KEYBOARD_MARGIN 8 ++ #define KEYBOARD_KEY_SPACING 4 ++ + // Paramaters for desktop PC + #else + #define SCREEN_WIDTH 640 +@@ -124,7 +139,25 @@ + #define VIEWER_SCROLL_SPEED 20 + + // Button events +-#if defined(DEVICE_RG351P) ++#if defined(DEVICE_RG351MP) ++ #define BUTTON_PRESSED_UP event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 8 ++ #define BUTTON_PRESSED_DOWN event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 9 ++ #define BUTTON_PRESSED_LEFT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 10 ++ #define BUTTON_PRESSED_RIGHT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 11 ++ #define BUTTON_PRESSED_PAGEUP event.type == SDL_JOYBUTTONDOWN && (event.jbutton.button == 4 || event.jbutton.button == 6) ++ #define BUTTON_PRESSED_PAGEDOWN event.type == SDL_JOYBUTTONDOWN && (event.jbutton.button == 5 || event.jbutton.button == 7) ++ #define BUTTON_PRESSED_VALIDATE event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 1 ++ #define BUTTON_PRESSED_BACK event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 0 ++ #define BUTTON_PRESSED_MENU_CONTEXT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 3 ++ #define BUTTON_PRESSED_SELECT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 2 ++ #define BUTTON_HELD_UP SDL_JoystickGetButton(g_joystick, 8) ++ #define BUTTON_HELD_DOWN SDL_JoystickGetButton(g_joystick, 9) ++ #define BUTTON_HELD_LEFT SDL_JoystickGetButton(g_joystick, 10) ++ #define BUTTON_HELD_RIGHT SDL_JoystickGetButton(g_joystick, 11) ++ #define BUTTON_HELD_PAGEUP SDL_JoystickGetButton(g_joystick, 4) || SDL_JoystickGetButton(g_joystick, 6) ++ #define BUTTON_HELD_PAGEDOWN SDL_JoystickGetButton(g_joystick, 5) || SDL_JoystickGetButton(g_joystick, 7) ++ #define BUTTON_HELD_SELECT SDL_JoystickGetButton(g_joystick, 2) ++#elif defined(DEVICE_RG351P) + #define BUTTON_PRESSED_UP event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_UP + #define BUTTON_PRESSED_DOWN event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_DOWN + #define BUTTON_PRESSED_LEFT event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_LEFT diff --git a/packages/games/tools/351files/patches/RG552/rg552.patch b/packages/games/tools/351files/patches/RG552/rg552.patch new file mode 100644 index 000000000..4aee9b961 --- /dev/null +++ b/packages/games/tools/351files/patches/RG552/rg552.patch @@ -0,0 +1,64 @@ +diff --git a/Makefile b/Makefile +index 7b9afa5..bd964f1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,5 +1,6 @@ + TARGET = 351Files + ++# DEVICE ?= RG552 + # DEVICE ?= RG351P + # DEVICE ?= RG351V + # DEVICE ?= RGB10 +diff --git a/src/def.h b/src/def.h +index 92d1a01..db4fec4 100644 +--- a/src/def.h ++++ b/src/def.h +@@ -85,6 +85,21 @@ + #define KEYBOARD_MARGIN 8 + #define KEYBOARD_KEY_SPACING 4 + ++// Parameters for RG552 ++#elif defined(DEVICE_RG552) ++ #define SCREEN_WIDTH 1152 ++ #define SCREEN_HEIGHT 1920 ++ #define HARDWARE_ACCELERATION 0 ++ #define FULLSCREEN 1 ++ #define FONT_NAME "NotoSans-Regular.ttf" ++ #define FONT_NAME_MONO "NotoSansMono-Regular.ttf" ++ #define FONT_SIZE 20 ++ #define LINE_HEIGHT 32 ++ #define ICON_SIZE 24 ++ #define MARGIN_X 10 ++ #define KEYBOARD_MARGIN 8 ++ #define KEYBOARD_KEY_SPACING 4 ++ + // Paramaters for desktop PC + #else + #define SCREEN_WIDTH 640 +@@ -124,7 +139,25 @@ + #define VIEWER_SCROLL_SPEED 20 + + // Button events +-#if defined(DEVICE_RG351P) ++#if defined(DEVICE_RG552) ++ #define BUTTON_PRESSED_UP event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 13 ++ #define BUTTON_PRESSED_DOWN event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 14 ++ #define BUTTON_PRESSED_LEFT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 15 ++ #define BUTTON_PRESSED_RIGHT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 16 ++ #define BUTTON_PRESSED_PAGEUP event.type == SDL_JOYBUTTONDOWN && (event.jbutton.button == 4 || event.jbutton.button == 6) ++ #define BUTTON_PRESSED_PAGEDOWN event.type == SDL_JOYBUTTONDOWN && (event.jbutton.button == 5 || event.jbutton.button == 7) ++ #define BUTTON_PRESSED_VALIDATE event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 1 ++ #define BUTTON_PRESSED_BACK event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 0 ++ #define BUTTON_PRESSED_MENU_CONTEXT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 2 ++ #define BUTTON_PRESSED_SELECT event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 3 ++ #define BUTTON_HELD_UP SDL_JoystickGetButton(g_joystick, 13) ++ #define BUTTON_HELD_DOWN SDL_JoystickGetButton(g_joystick, 14) ++ #define BUTTON_HELD_LEFT SDL_JoystickGetButton(g_joystick, 15) ++ #define BUTTON_HELD_RIGHT SDL_JoystickGetButton(g_joystick, 16) ++ #define BUTTON_HELD_PAGEUP SDL_JoystickGetButton(g_joystick, 4) || SDL_JoystickGetButton(g_joystick, 6) ++ #define BUTTON_HELD_PAGEDOWN SDL_JoystickGetButton(g_joystick, 5) || SDL_JoystickGetButton(g_joystick, 7) ++ #define BUTTON_HELD_SELECT SDL_JoystickGetButton(g_joystick, 3) ++#elif defined(DEVICE_RG351P) + #define BUTTON_PRESSED_UP event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_UP + #define BUTTON_PRESSED_DOWN event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_DOWN + #define BUTTON_PRESSED_LEFT event.type == SDL_JOYHATMOTION && event.jhat.value == SDL_HAT_LEFT diff --git a/packages/games/tools/axe11/X11/.gitignore b/packages/games/tools/axe11/X11/.gitignore new file mode 100644 index 000000000..b43616ad7 --- /dev/null +++ b/packages/games/tools/axe11/X11/.gitignore @@ -0,0 +1,2 @@ +# Add & Override for this directory and it's subdirectories +XlibConf.h diff --git a/packages/games/tools/axe11/X11/ImUtil.h b/packages/games/tools/axe11/X11/ImUtil.h new file mode 100644 index 000000000..779e1dc15 --- /dev/null +++ b/packages/games/tools/axe11/X11/ImUtil.h @@ -0,0 +1,30 @@ + +#ifndef _X11_IMUTIL_H_ +#define _X11_IMUTIL_H_ + +extern int +_XGetScanlinePad( + Display *dpy, + int depth); + +extern int +_XGetBitsPerPixel( + Display *dpy, + int depth); + +extern int +_XSetImage( + XImage *srcimg, + XImage *dstimg, + int x, + int y); + +extern int +_XReverse_Bytes( + unsigned char *bpt, + int nb); +extern void +_XInitImageFuncPtrs( + XImage *image); + +#endif /* _X11_IMUTIL_H_ */ diff --git a/packages/games/tools/axe11/X11/XKBlib.h b/packages/games/tools/axe11/X11/XKBlib.h new file mode 100644 index 000000000..dd532b224 --- /dev/null +++ b/packages/games/tools/axe11/X11/XKBlib.h @@ -0,0 +1,1149 @@ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifndef _X11_XKBLIB_H_ +#define _X11_XKBLIB_H_ + +#include +#include + +typedef struct _XkbAnyEvent { + int type; /* XkbAnyEvent */ + unsigned long serial; /* # of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XKB event minor code */ + unsigned int device; /* device ID */ +} XkbAnyEvent; + +typedef struct _XkbNewKeyboardNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbNewKeyboardNotify */ + int device; /* device ID */ + int old_device; /* device ID of previous keyboard */ + int min_key_code; /* minimum key code */ + int max_key_code; /* maximum key code */ + int old_min_key_code;/* min key code of previous kbd */ + int old_max_key_code;/* max key code of previous kbd */ + unsigned int changed; /* changed aspects of the keyboard */ + char req_major; /* major and minor opcode of req */ + char req_minor; /* that caused change, if applicable */ +} XkbNewKeyboardNotifyEvent; + +typedef struct _XkbMapNotifyEvent { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbMapNotify */ + int device; /* device ID */ + unsigned int changed; /* fields which have been changed */ + unsigned int flags; /* reserved */ + int first_type; /* first changed key type */ + int num_types; /* number of changed key types */ + KeyCode min_key_code; + KeyCode max_key_code; + KeyCode first_key_sym; + KeyCode first_key_act; + KeyCode first_key_behavior; + KeyCode first_key_explicit; + KeyCode first_modmap_key; + KeyCode first_vmodmap_key; + int num_key_syms; + int num_key_acts; + int num_key_behaviors; + int num_key_explicit; + int num_modmap_keys; + int num_vmodmap_keys; + unsigned int vmods; /* mask of changed virtual mods */ +} XkbMapNotifyEvent; + +typedef struct _XkbStateNotifyEvent { + int type; /* XkbAnyEvent */ + unsigned long serial; /* # of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbStateNotify */ + int device; /* device ID */ + unsigned int changed; /* mask of changed state components */ + int group; /* keyboard group */ + int base_group; /* base keyboard group */ + int latched_group; /* latched keyboard group */ + int locked_group; /* locked keyboard group */ + unsigned int mods; /* modifier state */ + unsigned int base_mods; /* base modifier state */ + unsigned int latched_mods; /* latched modifiers */ + unsigned int locked_mods; /* locked modifiers */ + int compat_state; /* compatibility state */ + unsigned char grab_mods; /* mods used for grabs */ + unsigned char compat_grab_mods;/* grab mods for non-XKB clients */ + unsigned char lookup_mods; /* mods sent to clients */ + unsigned char compat_lookup_mods; /* mods sent to non-XKB clients */ + int ptr_buttons; /* pointer button state */ + KeyCode keycode; /* keycode that caused the change */ + char event_type; /* KeyPress or KeyRelease */ + char req_major; /* Major opcode of request */ + char req_minor; /* Minor opcode of request */ +} XkbStateNotifyEvent; + +typedef struct _XkbControlsNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbControlsNotify */ + int device; /* device ID */ + unsigned int changed_ctrls; /* controls with changed sub-values */ + unsigned int enabled_ctrls; /* controls currently enabled */ + unsigned int enabled_ctrl_changes;/* controls just {en,dis}abled */ + int num_groups; /* total groups on keyboard */ + KeyCode keycode; /* key that caused change or 0 */ + char event_type; /* type of event that caused change */ + char req_major; /* if keycode==0, major and minor */ + char req_minor; /* opcode of req that caused change */ +} XkbControlsNotifyEvent; + +typedef struct _XkbIndicatorNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbIndicatorNotify */ + int device; /* device ID */ + unsigned int changed; /* indicators with new state or map */ + unsigned int state; /* current state of all indicators */ +} XkbIndicatorNotifyEvent; + +typedef struct _XkbNamesNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbNamesNotify */ + int device; /* device ID */ + unsigned int changed; /* names that have changed */ + int first_type; /* first key type with new name */ + int num_types; /* number of key types with new names */ + int first_lvl; /* first key type new new level names */ + int num_lvls; /* # of key types w/new level names */ + int num_aliases; /* total number of key aliases*/ + int num_radio_groups;/* total number of radio groups */ + unsigned int changed_vmods; /* virtual modifiers with new names */ + unsigned int changed_groups; /* groups with new names */ + unsigned int changed_indicators;/* indicators with new names */ + int first_key; /* first key with new name */ + int num_keys; /* number of keys with new names */ +} XkbNamesNotifyEvent; + +typedef struct _XkbCompatMapNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbCompatMapNotify */ + int device; /* device ID */ + unsigned int changed_groups; /* groups with new compat maps */ + int first_si; /* first new symbol interp */ + int num_si; /* number of new symbol interps */ + int num_total_si; /* total # of symbol interps */ +} XkbCompatMapNotifyEvent; + +typedef struct _XkbBellNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbBellNotify */ + int device; /* device ID */ + int percent; /* requested volume as a % of maximum */ + int pitch; /* requested pitch in Hz */ + int duration; /* requested duration in useconds */ + int bell_class; /* (input extension) feedback class */ + int bell_id; /* (input extension) ID of feedback */ + Atom name; /* "name" of requested bell */ + Window window; /* window associated with event */ + Bool event_only; /* "event only" requested */ +} XkbBellNotifyEvent; + +typedef struct _XkbActionMessage { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbActionMessage */ + int device; /* device ID */ + KeyCode keycode; /* key that generated the event */ + Bool press; /* true if act caused by key press */ + Bool key_event_follows;/* true if key event also generated */ + int group; /* effective group */ + unsigned int mods; /* effective mods */ + char message[XkbActionMessageLength+1]; + /* message -- leave space for NUL */ +} XkbActionMessageEvent; + +typedef struct _XkbAccessXNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbAccessXNotify */ + int device; /* device ID */ + int detail; /* XkbAXN_* */ + int keycode; /* key of event */ + int sk_delay; /* current slow keys delay */ + int debounce_delay; /* current debounce delay */ +} XkbAccessXNotifyEvent; + +typedef struct _XkbExtensionDeviceNotify { + int type; /* XkbAnyEvent */ + unsigned long serial; /* of last req processed by server */ + Bool send_event; /* is this from a SendEvent request? */ + Display * display; /* Display the event was read from */ + Time time; /* milliseconds */ + int xkb_type; /* XkbExtensionDeviceNotify */ + int device; /* device ID */ + unsigned int reason; /* reason for the event */ + unsigned int supported; /* mask of supported features */ + unsigned int unsupported; /* mask of unsupported features */ + /* that some app tried to use */ + int first_btn; /* first button that changed */ + int num_btns; /* range of buttons changed */ + unsigned int leds_defined; /* indicators with names or maps */ + unsigned int led_state; /* current state of the indicators */ + int led_class; /* feedback class for led changes */ + int led_id; /* feedback id for led changes */ +} XkbExtensionDeviceNotifyEvent; + +typedef union _XkbEvent { + int type; + XkbAnyEvent any; + XkbNewKeyboardNotifyEvent new_kbd; + XkbMapNotifyEvent map; + XkbStateNotifyEvent state; + XkbControlsNotifyEvent ctrls; + XkbIndicatorNotifyEvent indicators; + XkbNamesNotifyEvent names; + XkbCompatMapNotifyEvent compat; + XkbBellNotifyEvent bell; + XkbActionMessageEvent message; + XkbAccessXNotifyEvent accessx; + XkbExtensionDeviceNotifyEvent device; + XEvent core; +} XkbEvent; + +typedef struct _XkbKbdDpyState XkbKbdDpyStateRec,*XkbKbdDpyStatePtr; + + /* XkbOpenDisplay error codes */ +#define XkbOD_Success 0 +#define XkbOD_BadLibraryVersion 1 +#define XkbOD_ConnectionRefused 2 +#define XkbOD_NonXkbServer 3 +#define XkbOD_BadServerVersion 4 + + /* Values for XlibFlags */ +#define XkbLC_ForceLatin1Lookup (1<<0) +#define XkbLC_ConsumeLookupMods (1<<1) +#define XkbLC_AlwaysConsumeShiftAndLock (1<<2) +#define XkbLC_IgnoreNewKeyboards (1<<3) +#define XkbLC_ControlFallback (1<<4) +#define XkbLC_ConsumeKeysOnComposeFail (1<<29) +#define XkbLC_ComposeLED (1<<30) +#define XkbLC_BeepOnComposeFail (1<<31) + +#define XkbLC_AllComposeControls (0xc0000000) +#define XkbLC_AllControls (0xc000001f) + +_XFUNCPROTOBEGIN + +extern Bool XkbIgnoreExtension( + Bool /* ignore */ +); + +extern Display *XkbOpenDisplay( + char * /* name */, + int * /* ev_rtrn */, + int * /* err_rtrn */, + int * /* major_rtrn */, + int * /* minor_rtrn */, + int * /* reason */ +); + +extern Bool XkbQueryExtension( + Display * /* dpy */, + int * /* opcodeReturn */, + int * /* eventBaseReturn */, + int * /* errorBaseReturn */, + int * /* majorRtrn */, + int * /* minorRtrn */ +); + +extern Bool XkbUseExtension( + Display * /* dpy */, + int * /* major_rtrn */, + int * /* minor_rtrn */ +); + +extern Bool XkbLibraryVersion( + int * /* libMajorRtrn */, + int * /* libMinorRtrn */ +); + +extern unsigned int XkbSetXlibControls( + Display* /* dpy */, + unsigned int /* affect */, + unsigned int /* values */ +); + +extern unsigned int XkbGetXlibControls( + Display* /* dpy */ +); + +extern unsigned int XkbXlibControlsImplemented(void); + +typedef Atom (*XkbInternAtomFunc)( + Display * /* dpy */, + _Xconst char * /* name */, + Bool /* only_if_exists */ +); + +typedef char * (*XkbGetAtomNameFunc)( + Display * /* dpy */, + Atom /* atom */ +); + +extern void XkbSetAtomFuncs( + XkbInternAtomFunc /* getAtom */, + XkbGetAtomNameFunc /* getName */ +); + +extern KeySym XkbKeycodeToKeysym( + Display * /* dpy */, +#if NeedWidePrototypes + unsigned int /* kc */, +#else + KeyCode /* kc */, +#endif + int /* group */, + int /* level */ +); + +extern unsigned int XkbKeysymToModifiers( + Display * /* dpy */, + KeySym /* ks */ +); + +extern Bool XkbLookupKeySym( + Display * /* dpy */, + KeyCode /* keycode */, + unsigned int /* modifiers */, + unsigned int * /* modifiers_return */, + KeySym * /* keysym_return */ +); + +extern int XkbLookupKeyBinding( + Display * /* dpy */, + KeySym /* sym_rtrn */, + unsigned int /* mods */, + char * /* buffer */, + int /* nbytes */, + int * /* extra_rtrn */ +); + +extern Bool XkbTranslateKeyCode( + XkbDescPtr /* xkb */, + KeyCode /* keycode */, + unsigned int /* modifiers */, + unsigned int * /* modifiers_return */, + KeySym * /* keysym_return */ +); + +extern int XkbTranslateKeySym( + Display * /* dpy */, + KeySym * /* sym_return */, + unsigned int /* modifiers */, + char * /* buffer */, + int /* nbytes */, + int * /* extra_rtrn */ +); + +extern Bool XkbSetAutoRepeatRate( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* delay */, + unsigned int /* interval */ +); + +extern Bool XkbGetAutoRepeatRate( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int * /* delayRtrn */, + unsigned int * /* intervalRtrn */ +); + +extern Bool XkbChangeEnabledControls( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* affect */, + unsigned int /* values */ +); + +extern Bool XkbDeviceBell( + Display * /* dpy */, + Window /* win */, + int /* deviceSpec */, + int /* bellClass */, + int /* bellID */, + int /* percent */, + Atom /* name */ +); + +extern Bool XkbForceDeviceBell( + Display * /* dpy */, + int /* deviceSpec */, + int /* bellClass */, + int /* bellID */, + int /* percent */ +); + +extern Bool XkbDeviceBellEvent( + Display * /* dpy */, + Window /* win */, + int /* deviceSpec */, + int /* bellClass */, + int /* bellID */, + int /* percent */, + Atom /* name */ +); + +extern Bool XkbBell( + Display * /* dpy */, + Window /* win */, + int /* percent */, + Atom /* name */ +); + +extern Bool XkbForceBell( + Display * /* dpy */, + int /* percent */ +); + +extern Bool XkbBellEvent( + Display * /* dpy */, + Window /* win */, + int /* percent */, + Atom /* name */ +); + +extern Bool XkbSelectEvents( + Display * /* dpy */, + unsigned int /* deviceID */, + unsigned int /* affect */, + unsigned int /* values */ +); + +extern Bool XkbSelectEventDetails( + Display * /* dpy */, + unsigned int /* deviceID */, + unsigned int /* eventType */, + unsigned long /* affect */, + unsigned long /* details */ +); + +extern void XkbNoteMapChanges( + XkbMapChangesPtr /* old */, + XkbMapNotifyEvent * /* new */, + unsigned int /* wanted */ +); + +extern void XkbNoteNameChanges( + XkbNameChangesPtr /* old */, + XkbNamesNotifyEvent * /* new */, + unsigned int /* wanted */ +); + +extern Status XkbGetIndicatorState( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int * /* pStateRtrn */ +); + +extern Status XkbGetDeviceIndicatorState( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* ledClass */, + unsigned int /* ledID */, + unsigned int * /* pStateRtrn */ +); + +extern Status XkbGetIndicatorMap( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +extern Bool XkbSetIndicatorMap( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +#define XkbNoteIndicatorMapChanges(o,n,w) \ + ((o)->map_changes|=((n)->map_changes&(w))) +#define XkbNoteIndicatorStateChanges(o,n,w)\ + ((o)->state_changes|=((n)->state_changes&(w))) +#define XkbGetIndicatorMapChanges(d,x,c) \ + (XkbGetIndicatorMap((d),(c)->map_changes,x)) +#define XkbChangeIndicatorMaps(d,x,c) \ + (XkbSetIndicatorMap((d),(c)->map_changes,x)) + +extern Bool XkbGetNamedIndicator( + Display * /* dpy */, + Atom /* name */, + int * /* pNdxRtrn */, + Bool * /* pStateRtrn */, + XkbIndicatorMapPtr /* pMapRtrn */, + Bool * /* pRealRtrn */ +); + +extern Bool XkbGetNamedDeviceIndicator( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* ledClass */, + unsigned int /* ledID */, + Atom /* name */, + int * /* pNdxRtrn */, + Bool * /* pStateRtrn */, + XkbIndicatorMapPtr /* pMapRtrn */, + Bool * /* pRealRtrn */ +); + +extern Bool XkbSetNamedIndicator( + Display * /* dpy */, + Atom /* name */, + Bool /* changeState */, + Bool /* state */, + Bool /* createNewMap */, + XkbIndicatorMapPtr /* pMap */ +); + +extern Bool XkbSetNamedDeviceIndicator( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* ledClass */, + unsigned int /* ledID */, + Atom /* name */, + Bool /* changeState */, + Bool /* state */, + Bool /* createNewMap */, + XkbIndicatorMapPtr /* pMap */ +); + +extern Bool XkbLockModifiers( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* affect */, + unsigned int /* values */ +); + +extern Bool XkbLatchModifiers( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* affect */, + unsigned int /* values */ +); + +extern Bool XkbLockGroup( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* group */ +); + +extern Bool XkbLatchGroup( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* group */ +); + +extern Bool XkbSetServerInternalMods( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* affectReal */, + unsigned int /* realValues */, + unsigned int /* affectVirtual */, + unsigned int /* virtualValues */ +); + +extern Bool XkbSetIgnoreLockMods( + Display * /* dpy */, + unsigned int /* deviceSpec */, + unsigned int /* affectReal */, + unsigned int /* realValues */, + unsigned int /* affectVirtual */, + unsigned int /* virtualValues */ +); + + +extern Bool XkbVirtualModsToReal( + XkbDescPtr /* xkb */, + unsigned int /* virtual_mask */, + unsigned int * /* mask_rtrn */ +); + +extern Bool XkbComputeEffectiveMap( + XkbDescPtr /* xkb */, + XkbKeyTypePtr /* type */, + unsigned char * /* map_rtrn */ +); + +extern Status XkbInitCanonicalKeyTypes( + XkbDescPtr /* xkb */, + unsigned int /* which */, + int /* keypadVMod */ +); + +extern XkbDescPtr XkbAllocKeyboard( + void +); + +extern void XkbFreeKeyboard( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeDesc */ +); + +extern Status XkbAllocClientMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nTypes */ +); + +extern Status XkbAllocServerMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nActions */ +); + +extern void XkbFreeClientMap( + XkbDescPtr /* xkb */, + unsigned int /* what */, + Bool /* freeMap */ +); + +extern void XkbFreeServerMap( + XkbDescPtr /* xkb */, + unsigned int /* what */, + Bool /* freeMap */ +); + +extern XkbKeyTypePtr XkbAddKeyType( + XkbDescPtr /* xkb */, + Atom /* name */, + int /* map_count */, + Bool /* want_preserve */, + int /* num_lvls */ +); + +extern Status XkbAllocIndicatorMaps( + XkbDescPtr /* xkb */ +); + +extern void XkbFreeIndicatorMaps( + XkbDescPtr /* xkb */ +); + +extern XkbDescPtr XkbGetMap( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */ +); + +extern Status XkbGetUpdatedMap( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* desc */ +); + +extern Status XkbGetMapChanges( + Display * /* dpy */, + XkbDescPtr /* xkb */, + XkbMapChangesPtr /* changes */ +); + + +extern Status XkbRefreshKeyboardMapping( + XkbMapNotifyEvent * /* event */ +); + +extern Status XkbGetKeyTypes( + Display * /* dpy */, + unsigned int /* first */, + unsigned int /* num */, + XkbDescPtr /* xkb */ +); + +extern Status XkbGetKeySyms( + Display * /* dpy */, + unsigned int /* first */, + unsigned int /* num */, + XkbDescPtr /* xkb */ +); + +extern Status XkbGetKeyActions( + Display * /* dpy */, + unsigned int /* first */, + unsigned int /* num */, + XkbDescPtr /* xkb */ +); + +extern Status XkbGetKeyBehaviors( + Display * /* dpy */, + unsigned int /* firstKey */, + unsigned int /* nKeys */, + XkbDescPtr /* desc */ +); + +extern Status XkbGetVirtualMods( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* desc */ +); + +extern Status XkbGetKeyExplicitComponents( + Display * /* dpy */, + unsigned int /* firstKey */, + unsigned int /* nKeys */, + XkbDescPtr /* desc */ +); + +extern Status XkbGetKeyModifierMap( + Display * /* dpy */, + unsigned int /* firstKey */, + unsigned int /* nKeys */, + XkbDescPtr /* desc */ +); + +extern Status XkbGetKeyVirtualModMap( + Display * /* dpy */, + unsigned int /* first */, + unsigned int /* num */, + XkbDescPtr /* xkb */ +); + +extern Status XkbAllocControls( + XkbDescPtr /* xkb */, + unsigned int /* which*/ +); + +extern void XkbFreeControls( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern Status XkbGetControls( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +extern Bool XkbSetControls( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +extern void XkbNoteControlsChanges( + XkbControlsChangesPtr /* old */, + XkbControlsNotifyEvent * /* new */, + unsigned int /* wanted */ +); + +#define XkbGetControlsChanges(d,x,c) XkbGetControls(d,(c)->changed_ctrls,x) +#define XkbChangeControls(d,x,c) XkbSetControls(d,(c)->changed_ctrls,x) + +extern Status XkbAllocCompatMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nInterpret */ +); + +extern void XkbFreeCompatMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern Status XkbGetCompatMap( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* xkb */ +); + +extern Bool XkbSetCompatMap( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* xkb */, + Bool /* updateActions */ +); + +extern XkbSymInterpretPtr XkbAddSymInterpret( + XkbDescPtr /* xkb */, + XkbSymInterpretPtr /* si */, + Bool /* updateMap */, + XkbChangesPtr /* changes */ +); + +extern Status XkbAllocNames( + XkbDescPtr /* xkb */, + unsigned int /* which */, + int /* nTotalRG */, + int /* nTotalAliases */ +); + +extern Status XkbGetNames( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* desc */ +); + +extern Bool XkbSetNames( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* firstType */, + unsigned int /* nTypes */, + XkbDescPtr /* desc */ +); + +extern Bool XkbChangeNames( + Display * /* dpy */, + XkbDescPtr /* xkb */, + XkbNameChangesPtr /* changes */ +); + +extern void XkbFreeNames( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeMap */ +); + + +extern Status XkbGetState( + Display * /* dpy */, + unsigned int /* deviceSpec */, + XkbStatePtr /* rtrnState */ +); + +extern Bool XkbSetMap( + Display * /* dpy */, + unsigned int /* which */, + XkbDescPtr /* desc */ +); + +extern Bool XkbChangeMap( + Display* /* dpy */, + XkbDescPtr /* desc */, + XkbMapChangesPtr /* changes */ +); + +extern Bool XkbSetDetectableAutoRepeat( + Display * /* dpy */, + Bool /* detectable */, + Bool * /* supported */ +); + +extern Bool XkbGetDetectableAutoRepeat( + Display * /* dpy */, + Bool * /* supported */ +); + +extern Bool XkbSetAutoResetControls( + Display * /* dpy */, + unsigned int /* changes */, + unsigned int * /* auto_ctrls */, + unsigned int * /* auto_values */ +); + +extern Bool XkbGetAutoResetControls( + Display * /* dpy */, + unsigned int * /* auto_ctrls */, + unsigned int * /* auto_ctrl_values */ +); + +extern Bool XkbSetPerClientControls( + Display * /* dpy */, + unsigned int /* change */, + unsigned int * /* values */ +); + +extern Bool XkbGetPerClientControls( + Display * /* dpy */, + unsigned int * /* ctrls */ +); + +extern Status XkbCopyKeyType( + XkbKeyTypePtr /* from */, + XkbKeyTypePtr /* into */ +); + +extern Status XkbCopyKeyTypes( + XkbKeyTypePtr /* from */, + XkbKeyTypePtr /* into */, + int /* num_types */ +); + +extern Status XkbResizeKeyType( + XkbDescPtr /* xkb */, + int /* type_ndx */, + int /* map_count */, + Bool /* want_preserve */, + int /* new_num_lvls */ +); + +extern KeySym *XkbResizeKeySyms( + XkbDescPtr /* desc */, + int /* forKey */, + int /* symsNeeded */ +); + +extern XkbAction *XkbResizeKeyActions( + XkbDescPtr /* desc */, + int /* forKey */, + int /* actsNeeded */ +); + +extern Status XkbChangeTypesOfKey( + XkbDescPtr /* xkb */, + int /* key */, + int /* num_groups */, + unsigned int /* groups */, + int * /* newTypes */, + XkbMapChangesPtr /* pChanges */ +); + +extern Status XkbChangeKeycodeRange( + XkbDescPtr /* xkb */, + int /* minKC */, + int /* maxKC */, + XkbChangesPtr /* changes */ +); + +/***====================================================================***/ + +extern XkbComponentListPtr XkbListComponents( + Display * /* dpy */, + unsigned int /* deviceSpec */, + XkbComponentNamesPtr /* ptrns */, + int * /* max_inout */ +); + +extern void XkbFreeComponentList( + XkbComponentListPtr /* list */ +); + +extern XkbDescPtr XkbGetKeyboard( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */ +); + +extern XkbDescPtr XkbGetKeyboardByName( + Display * /* dpy */, + unsigned int /* deviceSpec */, + XkbComponentNamesPtr /* names */, + unsigned int /* want */, + unsigned int /* need */, + Bool /* load */ +); + +/***====================================================================***/ + +extern int XkbKeyTypesForCoreSymbols( /* returns # of groups */ + XkbDescPtr /* xkb */, /* keyboard device */ + int /* map_width */, /* width of core KeySym array */ + KeySym * /* core_syms */, /* always mapWidth symbols */ + unsigned int /* protected */, /* explicit key types */ + int * /* types_inout */, /* always four type indices */ + KeySym * /* xkb_syms_rtrn */ /* must have enough space */ +); + +extern Bool XkbApplyCompatMapToKey( /* False only on error */ + XkbDescPtr /* xkb */, /* keymap to be edited */ + KeyCode /* key */, /* key to be updated */ + XkbChangesPtr /* changes */ /* resulting changes to map */ +); + +extern Bool XkbUpdateMapFromCore( /* False only on error */ + XkbDescPtr /* xkb */, /* XKB keyboard to be edited */ + KeyCode /* first_key */, /* first changed key */ + int /* num_keys */, /* number of changed keys */ + int /* map_width */, /* width of core keymap */ + KeySym * /* core_keysyms */, /* symbols from core keymap */ + XkbChangesPtr /* changes */ /* resulting changes */ +); + +/***====================================================================***/ + +extern XkbDeviceLedInfoPtr XkbAddDeviceLedInfo( + XkbDeviceInfoPtr /* devi */, + unsigned int /* ledClass */, + unsigned int /* ledId */ +); + +extern Status XkbResizeDeviceButtonActions( + XkbDeviceInfoPtr /* devi */, + unsigned int /* newTotal */ +); + +extern XkbDeviceInfoPtr XkbAllocDeviceInfo( + unsigned int /* deviceSpec */, + unsigned int /* nButtons */, + unsigned int /* szLeds */ +); + +extern void XkbFreeDeviceInfo( + XkbDeviceInfoPtr /* devi */, + unsigned int /* which */, + Bool /* freeDevI */ +); + +extern void XkbNoteDeviceChanges( + XkbDeviceChangesPtr /* old */, + XkbExtensionDeviceNotifyEvent * /* new */, + unsigned int /* wanted */ +); + +extern XkbDeviceInfoPtr XkbGetDeviceInfo( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */, + unsigned int /* ledClass */, + unsigned int /* ledID */ +); + +extern Status XkbGetDeviceInfoChanges( + Display * /* dpy */, + XkbDeviceInfoPtr /* devi */, + XkbDeviceChangesPtr /* changes */ +); + +extern Status XkbGetDeviceButtonActions( + Display * /* dpy */, + XkbDeviceInfoPtr /* devi */, + Bool /* all */, + unsigned int /* first */, + unsigned int /* nBtns */ +); + +extern Status XkbGetDeviceLedInfo( + Display * /* dpy */, + XkbDeviceInfoPtr /* devi */, + unsigned int /* ledClass (class, XIDflt, XIAll) */, + unsigned int /* ledId (id, XIDflt, XIAll) */, + unsigned int /* which (XkbXI_Indicator{Names,Map}Mask */ +); + +extern Bool XkbSetDeviceInfo( + Display * /* dpy */, + unsigned int /* which */, + XkbDeviceInfoPtr /* devi */ +); + +extern Bool XkbChangeDeviceInfo( + Display* /* dpy */, + XkbDeviceInfoPtr /* desc */, + XkbDeviceChangesPtr /* changes */ +); + +extern Bool XkbSetDeviceLedInfo( + Display * /* dpy */, + XkbDeviceInfoPtr /* devi */, + unsigned int /* ledClass */, + unsigned int /* ledID */, + unsigned int /* which */ +); + +extern Bool XkbSetDeviceButtonActions( + Display * /* dpy */, + XkbDeviceInfoPtr /* devi */, + unsigned int /* first */, + unsigned int /* nBtns */ +); + +/***====================================================================***/ + +extern char XkbToControl( + char /* c */ +); + +/***====================================================================***/ + +extern Bool XkbSetDebuggingFlags( + Display * /* dpy */, + unsigned int /* mask */, + unsigned int /* flags */, + char * /* msg */, + unsigned int /* ctrls_mask */, + unsigned int /* ctrls */, + unsigned int * /* rtrn_flags */, + unsigned int * /* rtrn_ctrls */ +); + +extern Bool XkbApplyVirtualModChanges( + XkbDescPtr /* xkb */, + unsigned int /* changed */, + XkbChangesPtr /* changes */ +); + +extern Bool XkbUpdateActionVirtualMods( + XkbDescPtr /* xkb */, + XkbAction * /* act */, + unsigned int /* changed */ +); + +extern void XkbUpdateKeyTypeVirtualMods( + XkbDescPtr /* xkb */, + XkbKeyTypePtr /* type */, + unsigned int /* changed */, + XkbChangesPtr /* changes */ +); + +_XFUNCPROTOEND + +#endif /* _X11_XKBLIB_H_ */ diff --git a/packages/games/tools/axe11/X11/Xcms.h b/packages/games/tools/axe11/X11/Xcms.h new file mode 100644 index 000000000..663185410 --- /dev/null +++ b/packages/games/tools/axe11/X11/Xcms.h @@ -0,0 +1,815 @@ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * DESCRIPTION + * Public include file for X Color Management System + */ +#ifndef _X11_XCMS_H_ +#define _X11_XCMS_H_ + +#include + +/* The Xcms structs are full of implicit padding to properly align members. + We can't clean that up without breaking ABI, so tell clang not to bother + complaining about it. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + + /* + * XCMS Status Values + */ +#define XcmsFailure 0 +#define XcmsSuccess 1 +#define XcmsSuccessWithCompression 2 + + /* + * Color Space Format ID's + * Color Space ID's are of XcmsColorFormat type. + * + * bit 31 + * 0 == Device-Independent + * 1 == Device-Dependent + * + * bit 30: + * 0 == Registered with X Consortium + * 1 == Unregistered + */ +#define XcmsUndefinedFormat (XcmsColorFormat)0x00000000 +#define XcmsCIEXYZFormat (XcmsColorFormat)0x00000001 +#define XcmsCIEuvYFormat (XcmsColorFormat)0x00000002 +#define XcmsCIExyYFormat (XcmsColorFormat)0x00000003 +#define XcmsCIELabFormat (XcmsColorFormat)0x00000004 +#define XcmsCIELuvFormat (XcmsColorFormat)0x00000005 +#define XcmsTekHVCFormat (XcmsColorFormat)0x00000006 +#define XcmsRGBFormat (XcmsColorFormat)0x80000000 +#define XcmsRGBiFormat (XcmsColorFormat)0x80000001 + + /* + * State of XcmsPerScrnInfo + */ +#define XcmsInitNone 0x00 /* no initialization attempted */ +#define XcmsInitSuccess 0x01 /* initialization successful */ +#define XcmsInitFailure 0xff /* failure, use defaults */ + +#define DisplayOfCCC(ccc) ((ccc)->dpy) +#define ScreenNumberOfCCC(ccc) ((ccc)->screenNumber) +#define VisualOfCCC(ccc) ((ccc)->visual) +#define ClientWhitePointOfCCC(ccc) (&(ccc)->clientWhitePt) +#define ScreenWhitePointOfCCC(ccc) (&(ccc)->pPerScrnInfo->screenWhitePt) +#define FunctionSetOfCCC(ccc) ((ccc)->pPerScrnInfo->functionSet) + +typedef unsigned long XcmsColorFormat; /* Color Space Format ID */ + +typedef double XcmsFloat; + + /* + * Device RGB + */ +typedef struct { + unsigned short red; /* scaled from 0x0000 to 0xffff */ + unsigned short green; /* scaled from 0x0000 to 0xffff */ + unsigned short blue; /* scaled from 0x0000 to 0xffff */ +} XcmsRGB; + + /* + * RGB Intensity + */ +typedef struct { + XcmsFloat red; /* 0.0 - 1.0 */ + XcmsFloat green; /* 0.0 - 1.0 */ + XcmsFloat blue; /* 0.0 - 1.0 */ +} XcmsRGBi; + + /* + * CIE XYZ + */ +typedef struct { + XcmsFloat X; + XcmsFloat Y; + XcmsFloat Z; +} XcmsCIEXYZ; + + /* + * CIE u'v'Y + */ +typedef struct { + XcmsFloat u_prime; /* 0.0 - 1.0 */ + XcmsFloat v_prime; /* 0.0 - 1.0 */ + XcmsFloat Y; /* 0.0 - 1.0 */ +} XcmsCIEuvY; + + /* + * CIE xyY + */ +typedef struct { + XcmsFloat x; /* 0.0 - 1.0 */ + XcmsFloat y; /* 0.0 - 1.0 */ + XcmsFloat Y; /* 0.0 - 1.0 */ +} XcmsCIExyY; + + /* + * CIE L*a*b* + */ +typedef struct { + XcmsFloat L_star; /* 0.0 - 100.0 */ + XcmsFloat a_star; + XcmsFloat b_star; +} XcmsCIELab; + + /* + * CIE L*u*v* + */ +typedef struct { + XcmsFloat L_star; /* 0.0 - 100.0 */ + XcmsFloat u_star; + XcmsFloat v_star; +} XcmsCIELuv; + + /* + * TekHVC + */ +typedef struct { + XcmsFloat H; /* 0.0 - 360.0 */ + XcmsFloat V; /* 0.0 - 100.0 */ + XcmsFloat C; /* 0.0 - 100.0 */ +} XcmsTekHVC; + + /* + * PAD + */ +typedef struct { + XcmsFloat pad0; + XcmsFloat pad1; + XcmsFloat pad2; + XcmsFloat pad3; +} XcmsPad; + + + /* + * XCMS Color Structure + */ +typedef struct { + union { + XcmsRGB RGB; + XcmsRGBi RGBi; + XcmsCIEXYZ CIEXYZ; + XcmsCIEuvY CIEuvY; + XcmsCIExyY CIExyY; + XcmsCIELab CIELab; + XcmsCIELuv CIELuv; + XcmsTekHVC TekHVC; + XcmsPad Pad; + } spec; /* the color specification */ + unsigned long pixel; /* pixel value (as needed) */ + XcmsColorFormat format; /* the specification format */ +} XcmsColor; + + + /* + * XCMS Per Screen related data + */ + +typedef struct _XcmsPerScrnInfo { + XcmsColor screenWhitePt; /* Screen White point */ + XPointer functionSet; /* pointer to Screen Color Characterization */ + /* Function Set structure */ + XPointer screenData; /* pointer to corresponding Screen Color*/ + /* Characterization Data */ + unsigned char state; /* XcmsInitNone, XcmsInitSuccess, XcmsInitFailure */ + char pad[3]; +} XcmsPerScrnInfo; + +typedef struct _XcmsCCC *XcmsCCC; + +typedef Status (*XcmsCompressionProc)( /* Gamut Compression Proc */ + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +typedef Status (*XcmsWhiteAdjustProc)( /* White Point Adjust Proc */ + XcmsCCC /* ccc */, + XcmsColor* /* initial_white_point*/, + XcmsColor* /* target_white_point*/, + XcmsColorFormat /* target_format */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + + /* + * XCMS Color Conversion Context + */ +typedef struct _XcmsCCC { + Display *dpy; /* X Display */ + int screenNumber; /* X screen number */ + Visual *visual; /* X Visual */ + XcmsColor clientWhitePt; /* Client White Point */ + XcmsCompressionProc gamutCompProc; /* Gamut Compression Function */ + XPointer gamutCompClientData; /* Gamut Comp Func Client Data */ + XcmsWhiteAdjustProc whitePtAdjProc; /* White Point Adjustment Function */ + XPointer whitePtAdjClientData; /* White Pt Adj Func Client Data */ + XcmsPerScrnInfo *pPerScrnInfo; /* pointer to per screen information */ + /* associated with the above display */ + /* screenNumber */ +} XcmsCCCRec; + +typedef Status (*XcmsScreenInitProc)( /* Screen Initialization Proc */ + Display* /* dpy */, + int /* screen_number */, + XcmsPerScrnInfo* /* screen_info */ +); + +typedef void (*XcmsScreenFreeProc)( + XPointer /* screenData */ +); + + /* + * Function List Pointer -- pointer to an array of function pointers. + * The end of list is indicated by a NULL pointer. + */ +/* + * XXX: The use of the XcmsConversionProc type is broken. The + * device-independent colour conversion code uses it as: + +typedef Status (*XcmsConversionProc)(XcmsCCC, XcmsColor *, XcmsColor *, + unsigned int); + + * while the device-dependent code uses it as: + +typedef Status (*XcmsConversionProc)(XcmsCCC, XcmsColor *, unsigned int, + Bool *); + + * Until this is reworked, it's probably best to leave it unprotoized. + * The code works regardless. + */ +typedef Status (*XcmsDDConversionProc)( /* using device-dependent version */ + XcmsCCC /* ccc */, + XcmsColor* /* pcolors_in_out */, + unsigned int /* ncolors */, + Bool* /* pCompressed */ + ); + +typedef Status (*XcmsDIConversionProc)( /* using device-independent version */ + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* pcolors_in_out */, + unsigned int /* ncolors */ + ); + +typedef XcmsDIConversionProc XcmsConversionProc; +typedef XcmsConversionProc *XcmsFuncListPtr; + +typedef int (*XcmsParseStringProc)( /* Color String Parsing Proc */ + char* /* color_string */, + XcmsColor* /* color_return */ +); + + /* + * Color Space -- per Color Space related data (Device-Independent + * or Device-Dependent) + */ +typedef struct _XcmsColorSpace { + const char *prefix; /* Prefix of string format. */ + XcmsColorFormat id; /* Format ID number. */ + XcmsParseStringProc parseString; + /* String format parsing function */ + XcmsFuncListPtr to_CIEXYZ; /* Pointer to an array of function */ + /* pointers such that when the */ + /* functions are executed in sequence */ + /* will convert a XcmsColor structure */ + /* from this color space to CIEXYZ */ + /* space. */ + XcmsFuncListPtr from_CIEXYZ;/* Pointer to an array of function */ + /* pointers such that when the */ + /* functions are executed in sequence */ + /* will convert a XcmsColor structure */ + /* from CIEXYZ space to this color */ + /* space. */ + int inverse_flag; /* If 1, indicates that for 0 <= i < n */ + /* where n is the number of function */ + /* pointers in the lists to_CIEXYZ */ + /* and from_CIEXYZ; for each function */ + /* to_CIEXYZ[i] its inverse function */ + /* is from_CIEXYZ[n - i]. */ + +} XcmsColorSpace; + + /* + * Screen Color Characterization Function Set -- per device class + * color space conversion functions. + */ +typedef struct _XcmsFunctionSet { + XcmsColorSpace **DDColorSpaces; + /* Pointer to an array of pointers to */ + /* Device-DEPENDENT color spaces */ + /* understood by this SCCFuncSet. */ + XcmsScreenInitProc screenInitProc; + /* Screen initialization function that */ + /* reads Screen Color Characterization*/ + /* Data off properties on the screen's*/ + /* root window. */ + XcmsScreenFreeProc screenFreeProc; + /* Function that frees the SCCData */ + /* structures. */ +} XcmsFunctionSet; + +_XFUNCPROTOBEGIN + +extern Status XcmsAddColorSpace ( + XcmsColorSpace* /* pColorSpace */ +); + +extern Status XcmsAddFunctionSet ( + XcmsFunctionSet* /* functionSet */ +); + +extern Status XcmsAllocColor ( + Display* /* dpy */, + Colormap /* colormap */, + XcmsColor* /* color_in_out */, + XcmsColorFormat /* result_format */ +); + +extern Status XcmsAllocNamedColor ( + Display* /* dpy */, + Colormap /* colormap */, + _Xconst char* /* color_string */, + XcmsColor* /* color_scrn_return */, + XcmsColor* /* color_exact_return */, + XcmsColorFormat /* result_format */ +); + +extern XcmsCCC XcmsCCCOfColormap ( + Display* /* dpy */, + Colormap /* colormap */ +); + +extern Status XcmsCIELabClipab( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELabClipL( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELabClipLab( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELabQueryMaxC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* L_star */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELabQueryMaxL ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELabQueryMaxLC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELabQueryMinL ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELabToCIEXYZ ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIELabWhiteShiftColors( + XcmsCCC /* ccc */, + XcmsColor* /* initial_white_point*/, + XcmsColor* /* target_white_point*/, + XcmsColorFormat /* target_format */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELuvClipL( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELuvClipLuv( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELuvClipuv( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIELuvQueryMaxC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* L_star */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELuvQueryMaxL ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELuvQueryMaxLC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELuvQueryMinL ( + XcmsCCC /* ccc */, + XcmsFloat /* hue_angle */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsCIELuvToCIEuvY ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIELuvWhiteShiftColors( + XcmsCCC /* ccc */, + XcmsColor* /* initial_white_point*/, + XcmsColor* /* target_white_point*/, + XcmsColorFormat /* target_format */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIEXYZToCIELab ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIEXYZToCIEuvY ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIEXYZToCIExyY ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIEXYZToRGBi ( + XcmsCCC /* ccc */, + XcmsColor* /* colors */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsCIEuvYToCIELuv ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIEuvYToCIEXYZ ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIEuvYToTekHVC ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsCIExyYToCIEXYZ ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern XcmsColor *XcmsClientWhitePointOfCCC ( + XcmsCCC /* ccc */ +); + +extern Status XcmsConvertColors ( + XcmsCCC /* ccc */, + XcmsColor* /* colorArry_in_out */, + unsigned int /* nColors */, + XcmsColorFormat /* targetFormat */, + Bool* /* compArry_return */ +); + +extern XcmsCCC XcmsCreateCCC ( + Display* /* dpy */, + int /* screenNumber */, + Visual* /* visual */, + XcmsColor* /* clientWhitePt */, + XcmsCompressionProc /* gamutCompProc */, + XPointer /* gamutCompClientData */, + XcmsWhiteAdjustProc /* whitePtAdjProc */, + XPointer /* whitePtAdjClientData */ +); + +extern XcmsCCC XcmsDefaultCCC ( + Display* /* dpy */, + int /* screenNumber */ +); + +extern Display *XcmsDisplayOfCCC ( + XcmsCCC /* ccc */ +); + +extern XcmsColorFormat XcmsFormatOfPrefix ( + char* /* prefix */ +); + +extern void XcmsFreeCCC ( + XcmsCCC /* ccc */ +); + +extern Status XcmsLookupColor ( + Display* /* dpy */, + Colormap /* colormap */, + _Xconst char* /* color_string */, + XcmsColor* /* pColor_exact_in_out */, + XcmsColor* /* pColor_scrn_in_out */, + XcmsColorFormat /* result_format */ +); + +extern char *XcmsPrefixOfFormat ( + XcmsColorFormat /* id */ +); + +extern Status XcmsQueryBlack ( + XcmsCCC /* ccc */, + XcmsColorFormat /* target_format */, + XcmsColor* /* color_return */ +); + +extern Status XcmsQueryBlue ( + XcmsCCC /* ccc */, + XcmsColorFormat /* target_format */, + XcmsColor* /* color_return */ +); + +extern Status XcmsQueryColor ( + Display* /* dpy */, + Colormap /* colormap */, + XcmsColor* /* pColor_in_out */, + XcmsColorFormat /* result_format */ +); + +extern Status XcmsQueryColors ( + Display* /* dpy */, + Colormap /* colormap */, + XcmsColor* /* colorArry_in_out */, + unsigned int /* nColors */, + XcmsColorFormat /* result_format */ +); + +extern Status XcmsQueryGreen ( + XcmsCCC /* ccc */, + XcmsColorFormat /* target_format */, + XcmsColor* /* color_return */ +); + +extern Status XcmsQueryRed ( + XcmsCCC /* ccc */, + XcmsColorFormat /* target_format */, + XcmsColor* /* color_return */ +); + +extern Status XcmsQueryWhite ( + XcmsCCC /* ccc */, + XcmsColorFormat /* target_format */, + XcmsColor* /* color_return */ +); + +extern Status XcmsRGBiToCIEXYZ ( + XcmsCCC /* ccc */, + XcmsColor* /* colors */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsRGBiToRGB ( + XcmsCCC /* ccc */, + XcmsColor* /* colors */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsRGBToRGBi ( + XcmsCCC /* ccc */, + XcmsColor* /* colors */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern int XcmsScreenNumberOfCCC ( + XcmsCCC /* ccc */ +); + +extern XcmsColor *XcmsScreenWhitePointOfCCC ( + XcmsCCC /* ccc */ +); + +extern XcmsCCC XcmsSetCCCOfColormap( + Display* /* dpy */, + Colormap /* colormap */, + XcmsCCC /* ccc */ +); + +extern XcmsCompressionProc XcmsSetCompressionProc ( + XcmsCCC /* ccc */, + XcmsCompressionProc /* compression_proc */, + XPointer /* client_data */ +); + +extern XcmsWhiteAdjustProc XcmsSetWhiteAdjustProc ( + XcmsCCC /* ccc */, + XcmsWhiteAdjustProc /* white_adjust_proc */, + XPointer /* client_data */ +); + +extern Status XcmsSetWhitePoint ( + XcmsCCC /* ccc */, + XcmsColor* /* color */ +); + +extern Status XcmsStoreColor ( + Display* /* dpy */, + Colormap /* colormap */, + XcmsColor* /* pColor_in */ +); + +extern Status XcmsStoreColors ( + Display* /* dpy */, + Colormap /* colormap */, + XcmsColor* /* colorArry_in */, + unsigned int /* nColors */, + Bool* /* compArry_return */ +); + +extern Status XcmsTekHVCClipC( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsTekHVCClipV( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsTekHVCClipVC( + XcmsCCC /* ccc */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + unsigned int /* index */, + Bool* /* compression_flags_return */ +); + +extern Status XcmsTekHVCQueryMaxC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue */, + XcmsFloat /* value */, + XcmsColor* /* color_return */ +); + +extern Status XcmsTekHVCQueryMaxV ( + XcmsCCC /* ccc */, + XcmsFloat /* hue */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsTekHVCQueryMaxVC ( + XcmsCCC /* ccc */, + XcmsFloat /* hue */, + XcmsColor* /* color_return */ +); + +extern Status XcmsTekHVCQueryMaxVSamples ( + XcmsCCC /* ccc */, + XcmsFloat /* hue */, + XcmsColor* /* colors_return */, + unsigned int /* nsamples */ +); + +extern Status XcmsTekHVCQueryMinV ( + XcmsCCC /* ccc */, + XcmsFloat /* hue */, + XcmsFloat /* chroma */, + XcmsColor* /* color_return */ +); + +extern Status XcmsTekHVCToCIEuvY ( + XcmsCCC /* ccc */, + XcmsColor* /* white_point */, + XcmsColor* /* colors */, + unsigned int /* ncolors */ +); + +extern Status XcmsTekHVCWhiteShiftColors( + XcmsCCC /* ccc */, + XcmsColor* /* initial_white_point*/, + XcmsColor* /* target_white_point*/, + XcmsColorFormat /* target_format */, + XcmsColor* /* colors_in_out */, + unsigned int /* ncolors */, + Bool* /* compression_flags_return */ +); + +extern Visual *XcmsVisualOfCCC ( + XcmsCCC /* ccc */ +); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +_XFUNCPROTOEND + +#endif /* _X11_XCMS_H_ */ diff --git a/packages/games/tools/axe11/X11/Xlib-xcb.h b/packages/games/tools/axe11/X11/Xlib-xcb.h new file mode 100644 index 000000000..a21e2bef0 --- /dev/null +++ b/packages/games/tools/axe11/X11/Xlib-xcb.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett + * This file is licensed under the MIT license. See the file COPYING. */ + +#ifndef _X11_XLIB_XCB_H_ +#define _X11_XLIB_XCB_H_ + +#include +#include +#include + +_XFUNCPROTOBEGIN + +xcb_connection_t *XGetXCBConnection(Display *dpy); + +enum XEventQueueOwner { XlibOwnsEventQueue = 0, XCBOwnsEventQueue }; +void XSetEventQueueOwner(Display *dpy, enum XEventQueueOwner owner); + +_XFUNCPROTOEND + +#endif /* _X11_XLIB_XCB_H_ */ diff --git a/packages/games/tools/axe11/X11/Xlib.h b/packages/games/tools/axe11/X11/Xlib.h new file mode 100644 index 000000000..5faf83bed --- /dev/null +++ b/packages/games/tools/axe11/X11/Xlib.h @@ -0,0 +1,4025 @@ +/* + +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + + +/* + * Xlib.h - Header definition and support file for the C subroutine + * interface library (Xlib) to the X Window System Protocol (V11). + * Structures and symbols starting with "_" are private to the library. + */ +#ifndef _X11_XLIB_H_ +#define _X11_XLIB_H_ + +#define XlibSpecificationRelease 6 + +#include + +#if defined(__SCO__) || defined(__UNIXWARE__) +#include +#endif + +#include + +/* applications should not depend on these two headers being included! */ +#include +#include + +#ifndef X_WCHAR +#include +#else +#ifdef __UNIXOS2__ +#include +#else +/* replace this with #include or typedef appropriate for your system */ +typedef unsigned long wchar_t; +#endif +#endif + + +extern int +_Xmblen( + char *str, + int len + ); + +/* API mentioning "UTF8" or "utf8" is an XFree86 extension, introduced in + November 2000. Its presence is indicated through the following macro. */ +#define X_HAVE_UTF8_STRING 1 + +/* The Xlib structs are full of implicit padding to properly align members. + We can't clean that up without breaking ABI, so tell clang not to bother + complaining about it. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +typedef char *XPointer; + +#define Bool int +#define Status int +#define True 1 +#define False 0 + +#define QueuedAlready 0 +#define QueuedAfterReading 1 +#define QueuedAfterFlush 2 + +#define ConnectionNumber(dpy) (((_XPrivDisplay)(dpy))->fd) +#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root) +#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) +#define DefaultRootWindow(dpy) (ScreenOfDisplay(dpy,DefaultScreen(dpy))->root) +#define DefaultVisual(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_visual) +#define DefaultGC(dpy, scr) (ScreenOfDisplay(dpy,scr)->default_gc) +#define BlackPixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->black_pixel) +#define WhitePixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->white_pixel) +#define AllPlanes ((unsigned long)~0L) +#define QLength(dpy) (((_XPrivDisplay)(dpy))->qlen) +#define DisplayWidth(dpy, scr) (ScreenOfDisplay(dpy,scr)->width) +#define DisplayHeight(dpy, scr) (ScreenOfDisplay(dpy,scr)->height) +#define DisplayWidthMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mwidth) +#define DisplayHeightMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mheight) +#define DisplayPlanes(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth) +#define DisplayCells(dpy, scr) (DefaultVisual(dpy,scr)->map_entries) +#define ScreenCount(dpy) (((_XPrivDisplay)(dpy))->nscreens) +#define ServerVendor(dpy) (((_XPrivDisplay)(dpy))->vendor) +#define ProtocolVersion(dpy) (((_XPrivDisplay)(dpy))->proto_major_version) +#define ProtocolRevision(dpy) (((_XPrivDisplay)(dpy))->proto_minor_version) +#define VendorRelease(dpy) (((_XPrivDisplay)(dpy))->release) +#define DisplayString(dpy) (((_XPrivDisplay)(dpy))->display_name) +#define DefaultDepth(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth) +#define DefaultColormap(dpy, scr)(ScreenOfDisplay(dpy,scr)->cmap) +#define BitmapUnit(dpy) (((_XPrivDisplay)(dpy))->bitmap_unit) +#define BitmapBitOrder(dpy) (((_XPrivDisplay)(dpy))->bitmap_bit_order) +#define BitmapPad(dpy) (((_XPrivDisplay)(dpy))->bitmap_pad) +#define ImageByteOrder(dpy) (((_XPrivDisplay)(dpy))->byte_order) +#define NextRequest(dpy) (((_XPrivDisplay)(dpy))->request + 1) +#define LastKnownRequestProcessed(dpy) (((_XPrivDisplay)(dpy))->last_request_read) + +/* macros for screen oriented applications (toolkit) */ +#define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)(dpy))->screens[scr]) +#define DefaultScreenOfDisplay(dpy) ScreenOfDisplay(dpy,DefaultScreen(dpy)) +#define DisplayOfScreen(s) ((s)->display) +#define RootWindowOfScreen(s) ((s)->root) +#define BlackPixelOfScreen(s) ((s)->black_pixel) +#define WhitePixelOfScreen(s) ((s)->white_pixel) +#define DefaultColormapOfScreen(s)((s)->cmap) +#define DefaultDepthOfScreen(s) ((s)->root_depth) +#define DefaultGCOfScreen(s) ((s)->default_gc) +#define DefaultVisualOfScreen(s)((s)->root_visual) +#define WidthOfScreen(s) ((s)->width) +#define HeightOfScreen(s) ((s)->height) +#define WidthMMOfScreen(s) ((s)->mwidth) +#define HeightMMOfScreen(s) ((s)->mheight) +#define PlanesOfScreen(s) ((s)->root_depth) +#define CellsOfScreen(s) (DefaultVisualOfScreen((s))->map_entries) +#define MinCmapsOfScreen(s) ((s)->min_maps) +#define MaxCmapsOfScreen(s) ((s)->max_maps) +#define DoesSaveUnders(s) ((s)->save_unders) +#define DoesBackingStore(s) ((s)->backing_store) +#define EventMaskOfScreen(s) ((s)->root_input_mask) + +/* + * Extensions need a way to hang private data on some structures. + */ +typedef struct _XExtData { + int number; /* number returned by XRegisterExtension */ + struct _XExtData *next; /* next item on list of data for structure */ + int (*free_private)( /* called to free private storage */ + struct _XExtData *extension + ); + XPointer private_data; /* data private to this extension. */ +} XExtData; + +/* + * This file contains structures used by the extension mechanism. + */ +typedef struct { /* public to extension, cannot be changed */ + int extension; /* extension number */ + int major_opcode; /* major op-code assigned by server */ + int first_event; /* first event number for the extension */ + int first_error; /* first error number for the extension */ +} XExtCodes; + +/* + * Data structure for retrieving info about pixmap formats. + */ + +typedef struct { + int depth; + int bits_per_pixel; + int scanline_pad; +} XPixmapFormatValues; + + +/* + * Data structure for setting graphics context. + */ +typedef struct { + int function; /* logical operation */ + unsigned long plane_mask;/* plane mask */ + unsigned long foreground;/* foreground pixel */ + unsigned long background;/* background pixel */ + int line_width; /* line width */ + int line_style; /* LineSolid, LineOnOffDash, LineDoubleDash */ + int cap_style; /* CapNotLast, CapButt, + CapRound, CapProjecting */ + int join_style; /* JoinMiter, JoinRound, JoinBevel */ + int fill_style; /* FillSolid, FillTiled, + FillStippled, FillOpaeueStippled */ + int fill_rule; /* EvenOddRule, WindingRule */ + int arc_mode; /* ArcChord, ArcPieSlice */ + Pixmap tile; /* tile pixmap for tiling operations */ + Pixmap stipple; /* stipple 1 plane pixmap for stipping */ + int ts_x_origin; /* offset for tile or stipple operations */ + int ts_y_origin; + Font font; /* default text font for text operations */ + int subwindow_mode; /* ClipByChildren, IncludeInferiors */ + Bool graphics_exposures;/* boolean, should exposures be generated */ + int clip_x_origin; /* origin for clipping */ + int clip_y_origin; + Pixmap clip_mask; /* bitmap clipping; other calls for rects */ + int dash_offset; /* patterned/dashed line information */ + char dashes; +} XGCValues; + +/* + * Graphics context. The contents of this structure are implementation + * dependent. A GC should be treated as opaque by application code. + */ + +typedef struct _XGC +#ifdef XLIB_ILLEGAL_ACCESS +{ + XExtData *ext_data; /* hook for extension to hang data */ + GContext gid; /* protocol ID for graphics context */ + /* there is more to this structure, but it is private to Xlib */ +} +#endif +*GC; + +/* + * Visual structure; contains information about colormapping possible. + */ +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + VisualID visualid; /* visual id of this visual */ +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ class of screen (monochrome, etc.) */ +#else + int class; /* class of screen (monochrome, etc.) */ +#endif + unsigned long red_mask, green_mask, blue_mask; /* mask values */ + int bits_per_rgb; /* log base 2 of distinct color values */ + int map_entries; /* color map entries */ +} Visual; + +/* + * Depth structure; contains information for each possible depth. + */ +typedef struct { + int depth; /* this depth (Z) of the depth */ + int nvisuals; /* number of Visual types at this depth */ + Visual *visuals; /* list of visuals possible at this depth */ +} Depth; + +/* + * Information about the screen. The contents of this structure are + * implementation dependent. A Screen should be treated as opaque + * by application code. + */ + +struct _XDisplay; /* Forward declare before use for C++ */ + +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + struct _XDisplay *display;/* back pointer to display structure */ + Window root; /* Root window id. */ + int width, height; /* width and height of screen */ + int mwidth, mheight; /* width and height of in millimeters */ + int ndepths; /* number of depths possible */ + Depth *depths; /* list of allowable depths on the screen */ + int root_depth; /* bits per pixel */ + Visual *root_visual; /* root visual */ + GC default_gc; /* GC for the root root visual */ + Colormap cmap; /* default color map */ + unsigned long white_pixel; + unsigned long black_pixel; /* White and Black pixel values */ + int max_maps, min_maps; /* max and min color maps */ + int backing_store; /* Never, WhenMapped, Always */ + Bool save_unders; + long root_input_mask; /* initial root input mask */ +} Screen; + +/* + * Format structure; describes ZFormat data the screen will understand. + */ +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + int depth; /* depth of this image format */ + int bits_per_pixel; /* bits/pixel at this depth */ + int scanline_pad; /* scanline must padded to this multiple */ +} ScreenFormat; + +/* + * Data structure for setting window attributes. + */ +typedef struct { + Pixmap background_pixmap; /* background or None or ParentRelative */ + unsigned long background_pixel; /* background pixel */ + Pixmap border_pixmap; /* border of the window */ + unsigned long border_pixel; /* border pixel value */ + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to use in restoring planes */ + Bool save_under; /* should bits under be saved? (popups) */ + long event_mask; /* set of events that should be saved */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Colormap colormap; /* color map to be associated with window */ + Cursor cursor; /* cursor to be displayed (or None) */ +} XSetWindowAttributes; + +typedef struct { + int x, y; /* location of window */ + int width, height; /* width and height of window */ + int border_width; /* border width of window */ + int depth; /* depth of window */ + Visual *visual; /* the associated visual structure */ + Window root; /* root of screen containing window */ +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ InputOutput, InputOnly*/ +#else + int class; /* InputOutput, InputOnly*/ +#endif + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to be used when restoring planes */ + Bool save_under; /* boolean, should bits under be saved? */ + Colormap colormap; /* color map to be associated with window */ + Bool map_installed; /* boolean, is color map currently installed*/ + int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + long all_event_masks; /* set of events all people have interest in*/ + long your_event_mask; /* my event mask */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Screen *screen; /* back pointer to correct screen */ +} XWindowAttributes; + +/* + * Data structure for host setting; getting routines. + * + */ + +typedef struct { + int family; /* for example FamilyInternet */ + int length; /* length of address, in bytes */ + char *address; /* pointer to where to find the bytes */ +} XHostAddress; + +/* + * Data structure for ServerFamilyInterpreted addresses in host routines + */ +typedef struct { + int typelength; /* length of type string, in bytes */ + int valuelength; /* length of value string, in bytes */ + char *type; /* pointer to where to find the type string */ + char *value; /* pointer to where to find the address */ +} XServerInterpretedAddress; + +/* + * Data structure for "image" data, used by image manipulation routines. + */ +typedef struct _XImage { + int width, height; /* size of image */ + int xoffset; /* number of pixels offset in X direction */ + int format; /* XYBitmap, XYPixmap, ZPixmap */ + char *data; /* pointer to image data */ + int byte_order; /* data byte order, LSBFirst, MSBFirst */ + int bitmap_unit; /* quant. of scanline 8, 16, 32 */ + int bitmap_bit_order; /* LSBFirst, MSBFirst */ + int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ + int depth; /* depth of image */ + int bytes_per_line; /* accelerator to next line */ + int bits_per_pixel; /* bits per pixel (ZPixmap) */ + unsigned long red_mask; /* bits in z arrangement */ + unsigned long green_mask; + unsigned long blue_mask; + XPointer obdata; /* hook for the object routines to hang on */ + struct funcs { /* image manipulation routines */ + struct _XImage *(*create_image)( + struct _XDisplay* /* display */, + Visual* /* visual */, + unsigned int /* depth */, + int /* format */, + int /* offset */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + int /* bitmap_pad */, + int /* bytes_per_line */); + int (*destroy_image) (struct _XImage *); + unsigned long (*get_pixel) (struct _XImage *, int, int); + int (*put_pixel) (struct _XImage *, int, int, unsigned long); + struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int); + int (*add_pixel) (struct _XImage *, long); + } f; +} XImage; + +/* + * Data structure for XReconfigureWindow + */ +typedef struct { + int x, y; + int width, height; + int border_width; + Window sibling; + int stack_mode; +} XWindowChanges; + +/* + * Data structure used by color operations + */ +typedef struct { + unsigned long pixel; + unsigned short red, green, blue; + char flags; /* do_red, do_green, do_blue */ + char pad; +} XColor; + +/* + * Data structures for graphics operations. On most machines, these are + * congruent with the wire protocol structures, so reformatting the data + * can be avoided on these architectures. + */ +typedef struct { + short x1, y1, x2, y2; +} XSegment; + +typedef struct { + short x, y; +} XPoint; + +typedef struct { + short x, y; + unsigned short width, height; +} XRectangle; + +typedef struct { + short x, y; + unsigned short width, height; + short angle1, angle2; +} XArc; + + +/* Data structure for XChangeKeyboardControl */ + +typedef struct { + int key_click_percent; + int bell_percent; + int bell_pitch; + int bell_duration; + int led; + int led_mode; + int key; + int auto_repeat_mode; /* On, Off, Default */ +} XKeyboardControl; + +/* Data structure for XGetKeyboardControl */ + +typedef struct { + int key_click_percent; + int bell_percent; + unsigned int bell_pitch, bell_duration; + unsigned long led_mask; + int global_auto_repeat; + char auto_repeats[32]; +} XKeyboardState; + +/* Data structure for XGetMotionEvents. */ + +typedef struct { + Time time; + short x, y; +} XTimeCoord; + +/* Data structure for X{Set,Get}ModifierMapping */ + +typedef struct { + int max_keypermod; /* The server's max # of keys per modifier */ + KeyCode *modifiermap; /* An 8 by max_keypermod array of modifiers */ +} XModifierKeymap; + + +/* + * Display datatype maintaining display specific data. + * The contents of this structure are implementation dependent. + * A Display should be treated as opaque by application code. + */ +#ifndef XLIB_ILLEGAL_ACCESS +typedef struct _XDisplay Display; +#endif + +struct _XPrivate; /* Forward declare before use for C++ */ +struct _XrmHashBucketRec; + +typedef struct +#ifdef XLIB_ILLEGAL_ACCESS +_XDisplay +#endif +{ + XExtData *ext_data; /* hook for extension to hang data */ + struct _XPrivate *private1; + int fd; /* Network socket. */ + int private2; + int proto_major_version;/* major version of server's X protocol */ + int proto_minor_version;/* minor version of servers X protocol */ + char *vendor; /* vendor of the server hardware */ + XID private3; + XID private4; + XID private5; + int private6; + XID (*resource_alloc)( /* allocator function */ + struct _XDisplay* + ); + int byte_order; /* screen byte order, LSBFirst, MSBFirst */ + int bitmap_unit; /* padding and data requirements */ + int bitmap_pad; /* padding requirements on bitmaps */ + int bitmap_bit_order; /* LeastSignificant or MostSignificant */ + int nformats; /* number of pixmap formats in list */ + ScreenFormat *pixmap_format; /* pixmap format list */ + int private8; + int release; /* release of the server */ + struct _XPrivate *private9, *private10; + int qlen; /* Length of input event queue */ + unsigned long last_request_read; /* seq number of last event read */ + unsigned long request; /* sequence number of last request. */ + XPointer private11; + XPointer private12; + XPointer private13; + XPointer private14; + unsigned max_request_size; /* maximum number 32 bit words in request*/ + struct _XrmHashBucketRec *db; + int (*private15)( + struct _XDisplay* + ); + char *display_name; /* "host:display" string used on this connect*/ + int default_screen; /* default screen for operations */ + int nscreens; /* number of screens on this server*/ + Screen *screens; /* pointer to list of screens */ + unsigned long motion_buffer; /* size of motion buffer */ + unsigned long private16; + int min_keycode; /* minimum defined keycode */ + int max_keycode; /* maximum defined keycode */ + XPointer private17; + XPointer private18; + int private19; + char *xdefaults; /* contents of defaults from server */ + /* there is more to this structure, but it is private to Xlib */ +} +#ifdef XLIB_ILLEGAL_ACCESS +Display, +#endif +*_XPrivDisplay; + +#undef _XEVENT_ +#ifndef _XEVENT_ +/* + * Definitions of specific events. + */ +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + unsigned int keycode; /* detail */ + Bool same_screen; /* same screen flag */ +} XKeyEvent; +typedef XKeyEvent XKeyPressedEvent; +typedef XKeyEvent XKeyReleasedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + unsigned int button; /* detail */ + Bool same_screen; /* same screen flag */ +} XButtonEvent; +typedef XButtonEvent XButtonPressedEvent; +typedef XButtonEvent XButtonReleasedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + char is_hint; /* detail */ + Bool same_screen; /* same screen flag */ +} XMotionEvent; +typedef XMotionEvent XPointerMovedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + int mode; /* NotifyNormal, NotifyGrab, NotifyUngrab */ + int detail; + /* + * NotifyAncestor, NotifyVirtual, NotifyInferior, + * NotifyNonlinear,NotifyNonlinearVirtual + */ + Bool same_screen; /* same screen flag */ + Bool focus; /* boolean focus */ + unsigned int state; /* key or button mask */ +} XCrossingEvent; +typedef XCrossingEvent XEnterWindowEvent; +typedef XCrossingEvent XLeaveWindowEvent; + +typedef struct { + int type; /* FocusIn or FocusOut */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* window of event */ + int mode; /* NotifyNormal, NotifyWhileGrabbed, + NotifyGrab, NotifyUngrab */ + int detail; + /* + * NotifyAncestor, NotifyVirtual, NotifyInferior, + * NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer, + * NotifyPointerRoot, NotifyDetailNone + */ +} XFocusChangeEvent; +typedef XFocusChangeEvent XFocusInEvent; +typedef XFocusChangeEvent XFocusOutEvent; + +/* generated on EnterWindow and FocusIn when KeyMapState selected */ +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + char key_vector[32]; +} XKeymapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int x, y; + int width, height; + int count; /* if non-zero, at least this many more */ +} XExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; + int x, y; + int width, height; + int count; /* if non-zero, at least this many more */ + int major_code; /* core is CopyArea or CopyPlane */ + int minor_code; /* not defined in the core */ +} XGraphicsExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; + int major_code; /* core is CopyArea or CopyPlane */ + int minor_code; /* not defined in the core */ +} XNoExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int state; /* Visibility state */ +} XVisibilityEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; /* parent of the window */ + Window window; /* window id of window created */ + int x, y; /* window location */ + int width, height; /* size of window */ + int border_width; /* border width */ + Bool override_redirect; /* creation should be overridden */ +} XCreateWindowEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; +} XDestroyWindowEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Bool from_configure; +} XUnmapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Bool override_redirect; /* boolean, is override set... */ +} XMapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; +} XMapRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Window parent; + int x, y; + Bool override_redirect; +} XReparentEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int x, y; + int width, height; + int border_width; + Window above; + Bool override_redirect; +} XConfigureEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int x, y; +} XGravityEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int width, height; +} XResizeRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; + int x, y; + int width, height; + int border_width; + Window above; + int detail; /* Above, Below, TopIf, BottomIf, Opposite */ + unsigned long value_mask; +} XConfigureRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int place; /* PlaceOnTop, PlaceOnBottom */ +} XCirculateEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; + int place; /* PlaceOnTop, PlaceOnBottom */ +} XCirculateRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom atom; + Time time; + int state; /* NewValue, Deleted */ +} XPropertyEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom selection; + Time time; +} XSelectionClearEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window owner; + Window requestor; + Atom selection; + Atom target; + Atom property; + Time time; +} XSelectionRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window requestor; + Atom selection; + Atom target; + Atom property; /* ATOM or None */ + Time time; +} XSelectionEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Colormap colormap; /* COLORMAP or None */ +#if defined(__cplusplus) || defined(c_plusplus) + Bool c_new; /* C++ */ +#else + Bool new; +#endif + int state; /* ColormapInstalled, ColormapUninstalled */ +} XColormapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom message_type; + int format; + union { + char b[20]; + short s[10]; + long l[5]; + } data; +} XClientMessageEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* unused */ + int request; /* one of MappingModifier, MappingKeyboard, + MappingPointer */ + int first_keycode; /* first keycode */ + int count; /* defines range of change w. first_keycode*/ +} XMappingEvent; + +typedef struct { + int type; + Display *display; /* Display the event was read from */ + XID resourceid; /* resource id */ + unsigned long serial; /* serial number of failed request */ + unsigned char error_code; /* error code of failed request */ + unsigned char request_code; /* Major op-code of failed request */ + unsigned char minor_code; /* Minor op-code of failed request */ +} XErrorEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display;/* Display the event was read from */ + Window window; /* window on which event was requested in event mask */ +} XAnyEvent; + + +/*************************************************************** + * + * GenericEvent. This event is the standard event for all newer extensions. + */ + +typedef struct + { + int type; /* of event. Always GenericEvent */ + unsigned long serial; /* # of last request processed */ + Bool send_event; /* true if from SendEvent request */ + Display *display; /* Display the event was read from */ + int extension; /* major opcode of extension that caused the event */ + int evtype; /* actual event type. */ + } XGenericEvent; + +typedef struct { + int type; /* of event. Always GenericEvent */ + unsigned long serial; /* # of last request processed */ + Bool send_event; /* true if from SendEvent request */ + Display *display; /* Display the event was read from */ + int extension; /* major opcode of extension that caused the event */ + int evtype; /* actual event type. */ + unsigned int cookie; + void *data; +} XGenericEventCookie; + +/* + * this union is defined so Xlib can always use the same sized + * event structure internally, to avoid memory fragmentation. + */ +typedef union _XEvent { + int type; /* must not be changed; first element */ + XAnyEvent xany; + XKeyEvent xkey; + XButtonEvent xbutton; + XMotionEvent xmotion; + XCrossingEvent xcrossing; + XFocusChangeEvent xfocus; + XExposeEvent xexpose; + XGraphicsExposeEvent xgraphicsexpose; + XNoExposeEvent xnoexpose; + XVisibilityEvent xvisibility; + XCreateWindowEvent xcreatewindow; + XDestroyWindowEvent xdestroywindow; + XUnmapEvent xunmap; + XMapEvent xmap; + XMapRequestEvent xmaprequest; + XReparentEvent xreparent; + XConfigureEvent xconfigure; + XGravityEvent xgravity; + XResizeRequestEvent xresizerequest; + XConfigureRequestEvent xconfigurerequest; + XCirculateEvent xcirculate; + XCirculateRequestEvent xcirculaterequest; + XPropertyEvent xproperty; + XSelectionClearEvent xselectionclear; + XSelectionRequestEvent xselectionrequest; + XSelectionEvent xselection; + XColormapEvent xcolormap; + XClientMessageEvent xclient; + XMappingEvent xmapping; + XErrorEvent xerror; + XKeymapEvent xkeymap; + XGenericEvent xgeneric; + XGenericEventCookie xcookie; + long pad[24]; +} XEvent; +#endif + +#define XAllocID(dpy) ((*((_XPrivDisplay)(dpy))->resource_alloc)((dpy))) + +/* + * per character font metric information. + */ +typedef struct { + short lbearing; /* origin to left edge of raster */ + short rbearing; /* origin to right edge of raster */ + short width; /* advance to next char's origin */ + short ascent; /* baseline to top edge of raster */ + short descent; /* baseline to bottom edge of raster */ + unsigned short attributes; /* per char flags (not predefined) */ +} XCharStruct; + +/* + * To allow arbitrary information with fonts, there are additional properties + * returned. + */ +typedef struct { + Atom name; + unsigned long card32; +} XFontProp; + +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + Font fid; /* Font id for this font */ + unsigned direction; /* hint about direction the font is painted */ + unsigned min_char_or_byte2;/* first character */ + unsigned max_char_or_byte2;/* last character */ + unsigned min_byte1; /* first row that exists */ + unsigned max_byte1; /* last row that exists */ + Bool all_chars_exist;/* flag if all characters have non-zero size*/ + unsigned default_char; /* char to print for undefined character */ + int n_properties; /* how many properties there are */ + XFontProp *properties; /* pointer to array of additional properties*/ + XCharStruct min_bounds; /* minimum bounds over all existing char*/ + XCharStruct max_bounds; /* maximum bounds over all existing char*/ + XCharStruct *per_char; /* first_char to last_char information */ + int ascent; /* log. extent above baseline for spacing */ + int descent; /* log. descent below baseline for spacing */ +} XFontStruct; + +/* + * PolyText routines take these as arguments. + */ +typedef struct { + char *chars; /* pointer to string */ + int nchars; /* number of characters */ + int delta; /* delta between strings */ + Font font; /* font to print it in, None don't change */ +} XTextItem; + +typedef struct { /* normal 16 bit characters are two bytes */ + unsigned char byte1; + unsigned char byte2; +} XChar2b; + +typedef struct { + XChar2b *chars; /* two byte characters */ + int nchars; /* number of characters */ + int delta; /* delta between strings */ + Font font; /* font to print it in, None don't change */ +} XTextItem16; + + +typedef union { Display *display; + GC gc; + Visual *visual; + Screen *screen; + ScreenFormat *pixmap_format; + XFontStruct *font; } XEDataObject; + +typedef struct { + XRectangle max_ink_extent; + XRectangle max_logical_extent; +} XFontSetExtents; + +/* unused: +typedef void (*XOMProc)(); + */ + +typedef struct _XOM *XOM; +typedef struct _XOC *XOC, *XFontSet; + +typedef struct { + char *chars; + int nchars; + int delta; + XFontSet font_set; +} XmbTextItem; + +typedef struct { + wchar_t *chars; + int nchars; + int delta; + XFontSet font_set; +} XwcTextItem; + +#define XNRequiredCharSet "requiredCharSet" +#define XNQueryOrientation "queryOrientation" +#define XNBaseFontName "baseFontName" +#define XNOMAutomatic "omAutomatic" +#define XNMissingCharSet "missingCharSet" +#define XNDefaultString "defaultString" +#define XNOrientation "orientation" +#define XNDirectionalDependentDrawing "directionalDependentDrawing" +#define XNContextualDrawing "contextualDrawing" +#define XNFontInfo "fontInfo" + +typedef struct { + int charset_count; + char **charset_list; +} XOMCharSetList; + +typedef enum { + XOMOrientation_LTR_TTB, + XOMOrientation_RTL_TTB, + XOMOrientation_TTB_LTR, + XOMOrientation_TTB_RTL, + XOMOrientation_Context +} XOrientation; + +typedef struct { + int num_orientation; + XOrientation *orientation; /* Input Text description */ +} XOMOrientation; + +typedef struct { + int num_font; + XFontStruct **font_struct_list; + char **font_name_list; +} XOMFontInfo; + +typedef struct _XIM *XIM; +typedef struct _XIC *XIC; + +typedef void (*XIMProc)( + XIM, + XPointer, + XPointer +); + +typedef Bool (*XICProc)( + XIC, + XPointer, + XPointer +); + +typedef void (*XIDProc)( + Display*, + XPointer, + XPointer +); + +typedef unsigned long XIMStyle; + +typedef struct { + unsigned short count_styles; + XIMStyle *supported_styles; +} XIMStyles; + +#define XIMPreeditArea 0x0001L +#define XIMPreeditCallbacks 0x0002L +#define XIMPreeditPosition 0x0004L +#define XIMPreeditNothing 0x0008L +#define XIMPreeditNone 0x0010L +#define XIMStatusArea 0x0100L +#define XIMStatusCallbacks 0x0200L +#define XIMStatusNothing 0x0400L +#define XIMStatusNone 0x0800L + +#define XNVaNestedList "XNVaNestedList" +#define XNQueryInputStyle "queryInputStyle" +#define XNClientWindow "clientWindow" +#define XNInputStyle "inputStyle" +#define XNFocusWindow "focusWindow" +#define XNResourceName "resourceName" +#define XNResourceClass "resourceClass" +#define XNGeometryCallback "geometryCallback" +#define XNDestroyCallback "destroyCallback" +#define XNFilterEvents "filterEvents" +#define XNPreeditStartCallback "preeditStartCallback" +#define XNPreeditDoneCallback "preeditDoneCallback" +#define XNPreeditDrawCallback "preeditDrawCallback" +#define XNPreeditCaretCallback "preeditCaretCallback" +#define XNPreeditStateNotifyCallback "preeditStateNotifyCallback" +#define XNPreeditAttributes "preeditAttributes" +#define XNStatusStartCallback "statusStartCallback" +#define XNStatusDoneCallback "statusDoneCallback" +#define XNStatusDrawCallback "statusDrawCallback" +#define XNStatusAttributes "statusAttributes" +#define XNArea "area" +#define XNAreaNeeded "areaNeeded" +#define XNSpotLocation "spotLocation" +#define XNColormap "colorMap" +#define XNStdColormap "stdColorMap" +#define XNForeground "foreground" +#define XNBackground "background" +#define XNBackgroundPixmap "backgroundPixmap" +#define XNFontSet "fontSet" +#define XNLineSpace "lineSpace" +#define XNCursor "cursor" + +#define XNQueryIMValuesList "queryIMValuesList" +#define XNQueryICValuesList "queryICValuesList" +#define XNVisiblePosition "visiblePosition" +#define XNR6PreeditCallback "r6PreeditCallback" +#define XNStringConversionCallback "stringConversionCallback" +#define XNStringConversion "stringConversion" +#define XNResetState "resetState" +#define XNHotKey "hotKey" +#define XNHotKeyState "hotKeyState" +#define XNPreeditState "preeditState" +#define XNSeparatorofNestedList "separatorofNestedList" + +#define XBufferOverflow -1 +#define XLookupNone 1 +#define XLookupChars 2 +#define XLookupKeySym 3 +#define XLookupBoth 4 + +typedef void *XVaNestedList; + +typedef struct { + XPointer client_data; + XIMProc callback; +} XIMCallback; + +typedef struct { + XPointer client_data; + XICProc callback; +} XICCallback; + +typedef unsigned long XIMFeedback; + +#define XIMReverse 1L +#define XIMUnderline (1L<<1) +#define XIMHighlight (1L<<2) +#define XIMPrimary (1L<<5) +#define XIMSecondary (1L<<6) +#define XIMTertiary (1L<<7) +#define XIMVisibleToForward (1L<<8) +#define XIMVisibleToBackword (1L<<9) +#define XIMVisibleToCenter (1L<<10) + +typedef struct _XIMText { + unsigned short length; + XIMFeedback *feedback; + Bool encoding_is_wchar; + union { + char *multi_byte; + wchar_t *wide_char; + } string; +} XIMText; + +typedef unsigned long XIMPreeditState; + +#define XIMPreeditUnKnown 0L +#define XIMPreeditEnable 1L +#define XIMPreeditDisable (1L<<1) + +typedef struct _XIMPreeditStateNotifyCallbackStruct { + XIMPreeditState state; +} XIMPreeditStateNotifyCallbackStruct; + +typedef unsigned long XIMResetState; + +#define XIMInitialState 1L +#define XIMPreserveState (1L<<1) + +typedef unsigned long XIMStringConversionFeedback; + +#define XIMStringConversionLeftEdge (0x00000001) +#define XIMStringConversionRightEdge (0x00000002) +#define XIMStringConversionTopEdge (0x00000004) +#define XIMStringConversionBottomEdge (0x00000008) +#define XIMStringConversionConcealed (0x00000010) +#define XIMStringConversionWrapped (0x00000020) + +typedef struct _XIMStringConversionText { + unsigned short length; + XIMStringConversionFeedback *feedback; + Bool encoding_is_wchar; + union { + char *mbs; + wchar_t *wcs; + } string; +} XIMStringConversionText; + +typedef unsigned short XIMStringConversionPosition; + +typedef unsigned short XIMStringConversionType; + +#define XIMStringConversionBuffer (0x0001) +#define XIMStringConversionLine (0x0002) +#define XIMStringConversionWord (0x0003) +#define XIMStringConversionChar (0x0004) + +typedef unsigned short XIMStringConversionOperation; + +#define XIMStringConversionSubstitution (0x0001) +#define XIMStringConversionRetrieval (0x0002) + +typedef enum { + XIMForwardChar, XIMBackwardChar, + XIMForwardWord, XIMBackwardWord, + XIMCaretUp, XIMCaretDown, + XIMNextLine, XIMPreviousLine, + XIMLineStart, XIMLineEnd, + XIMAbsolutePosition, + XIMDontChange +} XIMCaretDirection; + +typedef struct _XIMStringConversionCallbackStruct { + XIMStringConversionPosition position; + XIMCaretDirection direction; + XIMStringConversionOperation operation; + unsigned short factor; + XIMStringConversionText *text; +} XIMStringConversionCallbackStruct; + +typedef struct _XIMPreeditDrawCallbackStruct { + int caret; /* Cursor offset within pre-edit string */ + int chg_first; /* Starting change position */ + int chg_length; /* Length of the change in character count */ + XIMText *text; +} XIMPreeditDrawCallbackStruct; + +typedef enum { + XIMIsInvisible, /* Disable caret feedback */ + XIMIsPrimary, /* UI defined caret feedback */ + XIMIsSecondary /* UI defined caret feedback */ +} XIMCaretStyle; + +typedef struct _XIMPreeditCaretCallbackStruct { + int position; /* Caret offset within pre-edit string */ + XIMCaretDirection direction; /* Caret moves direction */ + XIMCaretStyle style; /* Feedback of the caret */ +} XIMPreeditCaretCallbackStruct; + +typedef enum { + XIMTextType, + XIMBitmapType +} XIMStatusDataType; + +typedef struct _XIMStatusDrawCallbackStruct { + XIMStatusDataType type; + union { + XIMText *text; + Pixmap bitmap; + } data; +} XIMStatusDrawCallbackStruct; + +typedef struct _XIMHotKeyTrigger { + KeySym keysym; + int modifier; + int modifier_mask; +} XIMHotKeyTrigger; + +typedef struct _XIMHotKeyTriggers { + int num_hot_key; + XIMHotKeyTrigger *key; +} XIMHotKeyTriggers; + +typedef unsigned long XIMHotKeyState; + +#define XIMHotKeyStateON (0x0001L) +#define XIMHotKeyStateOFF (0x0002L) + +typedef struct { + unsigned short count_values; + char **supported_values; +} XIMValuesList; + +_XFUNCPROTOBEGIN + +#if defined(WIN32) && !defined(_XLIBINT_) +#define _Xdebug (*_Xdebug_p) +#endif + +extern int _Xdebug; + +extern XFontStruct *XLoadQueryFont( + Display* /* display */, + _Xconst char* /* name */ +); + +extern XFontStruct *XQueryFont( + Display* /* display */, + XID /* font_ID */ +); + + +extern XTimeCoord *XGetMotionEvents( + Display* /* display */, + Window /* w */, + Time /* start */, + Time /* stop */, + int* /* nevents_return */ +); + +extern XModifierKeymap *XDeleteModifiermapEntry( + XModifierKeymap* /* modmap */, +#if NeedWidePrototypes + unsigned int /* keycode_entry */, +#else + KeyCode /* keycode_entry */, +#endif + int /* modifier */ +); + +extern XModifierKeymap *XGetModifierMapping( + Display* /* display */ +); + +extern XModifierKeymap *XInsertModifiermapEntry( + XModifierKeymap* /* modmap */, +#if NeedWidePrototypes + unsigned int /* keycode_entry */, +#else + KeyCode /* keycode_entry */, +#endif + int /* modifier */ +); + +extern XModifierKeymap *XNewModifiermap( + int /* max_keys_per_mod */ +); + +extern XImage *XCreateImage( + Display* /* display */, + Visual* /* visual */, + unsigned int /* depth */, + int /* format */, + int /* offset */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + int /* bitmap_pad */, + int /* bytes_per_line */ +); +extern Status XInitImage( + XImage* /* image */ +); +extern XImage *XGetImage( + Display* /* display */, + Drawable /* d */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* plane_mask */, + int /* format */ +); +extern XImage *XGetSubImage( + Display* /* display */, + Drawable /* d */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* plane_mask */, + int /* format */, + XImage* /* dest_image */, + int /* dest_x */, + int /* dest_y */ +); + +/* + * X function declarations. + */ +extern Display *XOpenDisplay( + _Xconst char* /* display_name */ +); + +extern void XrmInitialize( + void +); + +extern char *XFetchBytes( + Display* /* display */, + int* /* nbytes_return */ +); +extern char *XFetchBuffer( + Display* /* display */, + int* /* nbytes_return */, + int /* buffer */ +); +extern char *XGetAtomName( + Display* /* display */, + Atom /* atom */ +); +extern Status XGetAtomNames( + Display* /* dpy */, + Atom* /* atoms */, + int /* count */, + char** /* names_return */ +); +extern char *XGetDefault( + Display* /* display */, + _Xconst char* /* program */, + _Xconst char* /* option */ +); +extern char *XDisplayName( + _Xconst char* /* string */ +); +extern char *XKeysymToString( + KeySym /* keysym */ +); + +extern int (*XSynchronize( + Display* /* display */, + Bool /* onoff */ +))( + Display* /* display */ +); +extern int (*XSetAfterFunction( + Display* /* display */, + int (*) ( + Display* /* display */ + ) /* procedure */ +))( + Display* /* display */ +); +extern Atom XInternAtom( + Display* /* display */, + _Xconst char* /* atom_name */, + Bool /* only_if_exists */ +); +extern Status XInternAtoms( + Display* /* dpy */, + char** /* names */, + int /* count */, + Bool /* onlyIfExists */, + Atom* /* atoms_return */ +); +extern Colormap XCopyColormapAndFree( + Display* /* display */, + Colormap /* colormap */ +); +extern Colormap XCreateColormap( + Display* /* display */, + Window /* w */, + Visual* /* visual */, + int /* alloc */ +); +extern Cursor XCreatePixmapCursor( + Display* /* display */, + Pixmap /* source */, + Pixmap /* mask */, + XColor* /* foreground_color */, + XColor* /* background_color */, + unsigned int /* x */, + unsigned int /* y */ +); +extern Cursor XCreateGlyphCursor( + Display* /* display */, + Font /* source_font */, + Font /* mask_font */, + unsigned int /* source_char */, + unsigned int /* mask_char */, + XColor _Xconst * /* foreground_color */, + XColor _Xconst * /* background_color */ +); +extern Cursor XCreateFontCursor( + Display* /* display */, + unsigned int /* shape */ +); +extern Font XLoadFont( + Display* /* display */, + _Xconst char* /* name */ +); +extern GC XCreateGC( + Display* /* display */, + Drawable /* d */, + unsigned long /* valuemask */, + XGCValues* /* values */ +); +extern GContext XGContextFromGC( + GC /* gc */ +); +extern void XFlushGC( + Display* /* display */, + GC /* gc */ +); +extern Pixmap XCreatePixmap( + Display* /* display */, + Drawable /* d */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* depth */ +); +extern Pixmap XCreateBitmapFromData( + Display* /* display */, + Drawable /* d */, + _Xconst char* /* data */, + unsigned int /* width */, + unsigned int /* height */ +); +extern Pixmap XCreatePixmapFromBitmapData( + Display* /* display */, + Drawable /* d */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* fg */, + unsigned long /* bg */, + unsigned int /* depth */ +); +extern Window XCreateSimpleWindow( + Display* /* display */, + Window /* parent */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* border_width */, + unsigned long /* border */, + unsigned long /* background */ +); +extern Window XGetSelectionOwner( + Display* /* display */, + Atom /* selection */ +); +extern Window XCreateWindow( + Display* /* display */, + Window /* parent */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* border_width */, + int /* depth */, + unsigned int /* class */, + Visual* /* visual */, + unsigned long /* valuemask */, + XSetWindowAttributes* /* attributes */ +); +extern Colormap *XListInstalledColormaps( + Display* /* display */, + Window /* w */, + int* /* num_return */ +); +extern char **XListFonts( + Display* /* display */, + _Xconst char* /* pattern */, + int /* maxnames */, + int* /* actual_count_return */ +); +extern char **XListFontsWithInfo( + Display* /* display */, + _Xconst char* /* pattern */, + int /* maxnames */, + int* /* count_return */, + XFontStruct** /* info_return */ +); +extern char **XGetFontPath( + Display* /* display */, + int* /* npaths_return */ +); +extern char **XListExtensions( + Display* /* display */, + int* /* nextensions_return */ +); +extern Atom *XListProperties( + Display* /* display */, + Window /* w */, + int* /* num_prop_return */ +); +extern XHostAddress *XListHosts( + Display* /* display */, + int* /* nhosts_return */, + Bool* /* state_return */ +); +_X_DEPRECATED +extern KeySym XKeycodeToKeysym( + Display* /* display */, +#if NeedWidePrototypes + unsigned int /* keycode */, +#else + KeyCode /* keycode */, +#endif + int /* index */ +); +extern KeySym XLookupKeysym( + XKeyEvent* /* key_event */, + int /* index */ +); +extern KeySym *XGetKeyboardMapping( + Display* /* display */, +#if NeedWidePrototypes + unsigned int /* first_keycode */, +#else + KeyCode /* first_keycode */, +#endif + int /* keycode_count */, + int* /* keysyms_per_keycode_return */ +); +extern KeySym XStringToKeysym( + _Xconst char* /* string */ +); +extern long XMaxRequestSize( + Display* /* display */ +); +extern long XExtendedMaxRequestSize( + Display* /* display */ +); +extern char *XResourceManagerString( + Display* /* display */ +); +extern char *XScreenResourceString( + Screen* /* screen */ +); +extern unsigned long XDisplayMotionBufferSize( + Display* /* display */ +); +extern VisualID XVisualIDFromVisual( + Visual* /* visual */ +); + +/* multithread routines */ + +extern Status XInitThreads( + void +); + +extern void XLockDisplay( + Display* /* display */ +); + +extern void XUnlockDisplay( + Display* /* display */ +); + +/* routines for dealing with extensions */ + +extern XExtCodes *XInitExtension( + Display* /* display */, + _Xconst char* /* name */ +); + +extern XExtCodes *XAddExtension( + Display* /* display */ +); +extern XExtData *XFindOnExtensionList( + XExtData** /* structure */, + int /* number */ +); +extern XExtData **XEHeadOfExtensionList( + XEDataObject /* object */ +); + +/* these are routines for which there are also macros */ +extern Window XRootWindow( + Display* /* display */, + int /* screen_number */ +); +extern Window XDefaultRootWindow( + Display* /* display */ +); +extern Window XRootWindowOfScreen( + Screen* /* screen */ +); +extern Visual *XDefaultVisual( + Display* /* display */, + int /* screen_number */ +); +extern Visual *XDefaultVisualOfScreen( + Screen* /* screen */ +); +extern GC XDefaultGC( + Display* /* display */, + int /* screen_number */ +); +extern GC XDefaultGCOfScreen( + Screen* /* screen */ +); +extern unsigned long XBlackPixel( + Display* /* display */, + int /* screen_number */ +); +extern unsigned long XWhitePixel( + Display* /* display */, + int /* screen_number */ +); +extern unsigned long XAllPlanes( + void +); +extern unsigned long XBlackPixelOfScreen( + Screen* /* screen */ +); +extern unsigned long XWhitePixelOfScreen( + Screen* /* screen */ +); +extern unsigned long XNextRequest( + Display* /* display */ +); +extern unsigned long XLastKnownRequestProcessed( + Display* /* display */ +); +extern char *XServerVendor( + Display* /* display */ +); +extern char *XDisplayString( + Display* /* display */ +); +extern Colormap XDefaultColormap( + Display* /* display */, + int /* screen_number */ +); +extern Colormap XDefaultColormapOfScreen( + Screen* /* screen */ +); +extern Display *XDisplayOfScreen( + Screen* /* screen */ +); +extern Screen *XScreenOfDisplay( + Display* /* display */, + int /* screen_number */ +); +extern Screen *XDefaultScreenOfDisplay( + Display* /* display */ +); +extern long XEventMaskOfScreen( + Screen* /* screen */ +); + +extern int XScreenNumberOfScreen( + Screen* /* screen */ +); + +typedef int (*XErrorHandler) ( /* WARNING, this type not in Xlib spec */ + Display* /* display */, + XErrorEvent* /* error_event */ +); + +extern XErrorHandler XSetErrorHandler ( + XErrorHandler /* handler */ +); + + +typedef int (*XIOErrorHandler) ( /* WARNING, this type not in Xlib spec */ + Display* /* display */ +); + +extern XIOErrorHandler XSetIOErrorHandler ( + XIOErrorHandler /* handler */ +); + +typedef void (*XIOErrorExitHandler) ( /* WARNING, this type not in Xlib spec */ + Display*, /* display */ + void* /* user_data */ +); + +extern void XSetIOErrorExitHandler ( + Display*, /* display */ + XIOErrorExitHandler, /* handler */ + void* /* user_data */ +); + +extern XPixmapFormatValues *XListPixmapFormats( + Display* /* display */, + int* /* count_return */ +); +extern int *XListDepths( + Display* /* display */, + int /* screen_number */, + int* /* count_return */ +); + +/* ICCCM routines for things that don't require special include files; */ +/* other declarations are given in Xutil.h */ +extern Status XReconfigureWMWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */, + unsigned int /* mask */, + XWindowChanges* /* changes */ +); + +extern Status XGetWMProtocols( + Display* /* display */, + Window /* w */, + Atom** /* protocols_return */, + int* /* count_return */ +); +extern Status XSetWMProtocols( + Display* /* display */, + Window /* w */, + Atom* /* protocols */, + int /* count */ +); +extern Status XIconifyWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */ +); +extern Status XWithdrawWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */ +); +extern Status XGetCommand( + Display* /* display */, + Window /* w */, + char*** /* argv_return */, + int* /* argc_return */ +); +extern Status XGetWMColormapWindows( + Display* /* display */, + Window /* w */, + Window** /* windows_return */, + int* /* count_return */ +); +extern Status XSetWMColormapWindows( + Display* /* display */, + Window /* w */, + Window* /* colormap_windows */, + int /* count */ +); +extern void XFreeStringList( + char** /* list */ +); +extern int XSetTransientForHint( + Display* /* display */, + Window /* w */, + Window /* prop_window */ +); + +/* The following are given in alphabetical order */ + +extern int XActivateScreenSaver( + Display* /* display */ +); + +extern int XAddHost( + Display* /* display */, + XHostAddress* /* host */ +); + +extern int XAddHosts( + Display* /* display */, + XHostAddress* /* hosts */, + int /* num_hosts */ +); + +extern int XAddToExtensionList( + struct _XExtData** /* structure */, + XExtData* /* ext_data */ +); + +extern int XAddToSaveSet( + Display* /* display */, + Window /* w */ +); + +extern Status XAllocColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* screen_in_out */ +); + +extern Status XAllocColorCells( + Display* /* display */, + Colormap /* colormap */, + Bool /* contig */, + unsigned long* /* plane_masks_return */, + unsigned int /* nplanes */, + unsigned long* /* pixels_return */, + unsigned int /* npixels */ +); + +extern Status XAllocColorPlanes( + Display* /* display */, + Colormap /* colormap */, + Bool /* contig */, + unsigned long* /* pixels_return */, + int /* ncolors */, + int /* nreds */, + int /* ngreens */, + int /* nblues */, + unsigned long* /* rmask_return */, + unsigned long* /* gmask_return */, + unsigned long* /* bmask_return */ +); + +extern Status XAllocNamedColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color_name */, + XColor* /* screen_def_return */, + XColor* /* exact_def_return */ +); + +extern int XAllowEvents( + Display* /* display */, + int /* event_mode */, + Time /* time */ +); + +extern int XAutoRepeatOff( + Display* /* display */ +); + +extern int XAutoRepeatOn( + Display* /* display */ +); + +extern int XBell( + Display* /* display */, + int /* percent */ +); + +extern int XBitmapBitOrder( + Display* /* display */ +); + +extern int XBitmapPad( + Display* /* display */ +); + +extern int XBitmapUnit( + Display* /* display */ +); + +extern int XCellsOfScreen( + Screen* /* screen */ +); + +extern int XChangeActivePointerGrab( + Display* /* display */, + unsigned int /* event_mask */, + Cursor /* cursor */, + Time /* time */ +); + +extern int XChangeGC( + Display* /* display */, + GC /* gc */, + unsigned long /* valuemask */, + XGCValues* /* values */ +); + +extern int XChangeKeyboardControl( + Display* /* display */, + unsigned long /* value_mask */, + XKeyboardControl* /* values */ +); + +extern int XChangeKeyboardMapping( + Display* /* display */, + int /* first_keycode */, + int /* keysyms_per_keycode */, + KeySym* /* keysyms */, + int /* num_codes */ +); + +extern int XChangePointerControl( + Display* /* display */, + Bool /* do_accel */, + Bool /* do_threshold */, + int /* accel_numerator */, + int /* accel_denominator */, + int /* threshold */ +); + +extern int XChangeProperty( + Display* /* display */, + Window /* w */, + Atom /* property */, + Atom /* type */, + int /* format */, + int /* mode */, + _Xconst unsigned char* /* data */, + int /* nelements */ +); + +extern int XChangeSaveSet( + Display* /* display */, + Window /* w */, + int /* change_mode */ +); + +extern int XChangeWindowAttributes( + Display* /* display */, + Window /* w */, + unsigned long /* valuemask */, + XSetWindowAttributes* /* attributes */ +); + +extern Bool XCheckIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern Bool XCheckMaskEvent( + Display* /* display */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern Bool XCheckTypedEvent( + Display* /* display */, + int /* event_type */, + XEvent* /* event_return */ +); + +extern Bool XCheckTypedWindowEvent( + Display* /* display */, + Window /* w */, + int /* event_type */, + XEvent* /* event_return */ +); + +extern Bool XCheckWindowEvent( + Display* /* display */, + Window /* w */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XCirculateSubwindows( + Display* /* display */, + Window /* w */, + int /* direction */ +); + +extern int XCirculateSubwindowsDown( + Display* /* display */, + Window /* w */ +); + +extern int XCirculateSubwindowsUp( + Display* /* display */, + Window /* w */ +); + +extern int XClearArea( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + Bool /* exposures */ +); + +extern int XClearWindow( + Display* /* display */, + Window /* w */ +); + +extern int XCloseDisplay( + Display* /* display */ +); + +extern int XConfigureWindow( + Display* /* display */, + Window /* w */, + unsigned int /* value_mask */, + XWindowChanges* /* values */ +); + +extern int XConnectionNumber( + Display* /* display */ +); + +extern int XConvertSelection( + Display* /* display */, + Atom /* selection */, + Atom /* target */, + Atom /* property */, + Window /* requestor */, + Time /* time */ +); + +extern int XCopyArea( + Display* /* display */, + Drawable /* src */, + Drawable /* dest */, + GC /* gc */, + int /* src_x */, + int /* src_y */, + unsigned int /* width */, + unsigned int /* height */, + int /* dest_x */, + int /* dest_y */ +); + +extern int XCopyGC( + Display* /* display */, + GC /* src */, + unsigned long /* valuemask */, + GC /* dest */ +); + +extern int XCopyPlane( + Display* /* display */, + Drawable /* src */, + Drawable /* dest */, + GC /* gc */, + int /* src_x */, + int /* src_y */, + unsigned int /* width */, + unsigned int /* height */, + int /* dest_x */, + int /* dest_y */, + unsigned long /* plane */ +); + +extern int XDefaultDepth( + Display* /* display */, + int /* screen_number */ +); + +extern int XDefaultDepthOfScreen( + Screen* /* screen */ +); + +extern int XDefaultScreen( + Display* /* display */ +); + +extern int XDefineCursor( + Display* /* display */, + Window /* w */, + Cursor /* cursor */ +); + +extern int XDeleteProperty( + Display* /* display */, + Window /* w */, + Atom /* property */ +); + +extern int XDestroyWindow( + Display* /* display */, + Window /* w */ +); + +extern int XDestroySubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XDoesBackingStore( + Screen* /* screen */ +); + +extern Bool XDoesSaveUnders( + Screen* /* screen */ +); + +extern int XDisableAccessControl( + Display* /* display */ +); + + +extern int XDisplayCells( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayHeight( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayHeightMM( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayKeycodes( + Display* /* display */, + int* /* min_keycodes_return */, + int* /* max_keycodes_return */ +); + +extern int XDisplayPlanes( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayWidth( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayWidthMM( + Display* /* display */, + int /* screen_number */ +); + +extern int XDrawArc( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + int /* angle1 */, + int /* angle2 */ +); + +extern int XDrawArcs( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XArc* /* arcs */, + int /* narcs */ +); + +extern int XDrawImageString( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* string */, + int /* length */ +); + +extern int XDrawImageString16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst XChar2b* /* string */, + int /* length */ +); + +extern int XDrawLine( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x1 */, + int /* y1 */, + int /* x2 */, + int /* y2 */ +); + +extern int XDrawLines( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* mode */ +); + +extern int XDrawPoint( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */ +); + +extern int XDrawPoints( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* mode */ +); + +extern int XDrawRectangle( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XDrawRectangles( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XRectangle* /* rectangles */, + int /* nrectangles */ +); + +extern int XDrawSegments( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XSegment* /* segments */, + int /* nsegments */ +); + +extern int XDrawString( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* string */, + int /* length */ +); + +extern int XDrawString16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst XChar2b* /* string */, + int /* length */ +); + +extern int XDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XTextItem* /* items */, + int /* nitems */ +); + +extern int XDrawText16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XTextItem16* /* items */, + int /* nitems */ +); + +extern int XEnableAccessControl( + Display* /* display */ +); + +extern int XEventsQueued( + Display* /* display */, + int /* mode */ +); + +extern Status XFetchName( + Display* /* display */, + Window /* w */, + char** /* window_name_return */ +); + +extern int XFillArc( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + int /* angle1 */, + int /* angle2 */ +); + +extern int XFillArcs( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XArc* /* arcs */, + int /* narcs */ +); + +extern int XFillPolygon( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* shape */, + int /* mode */ +); + +extern int XFillRectangle( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XFillRectangles( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XRectangle* /* rectangles */, + int /* nrectangles */ +); + +extern int XFlush( + Display* /* display */ +); + +extern int XForceScreenSaver( + Display* /* display */, + int /* mode */ +); + +extern int XFree( + void* /* data */ +); + +extern int XFreeColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern int XFreeColors( + Display* /* display */, + Colormap /* colormap */, + unsigned long* /* pixels */, + int /* npixels */, + unsigned long /* planes */ +); + +extern int XFreeCursor( + Display* /* display */, + Cursor /* cursor */ +); + +extern int XFreeExtensionList( + char** /* list */ +); + +extern int XFreeFont( + Display* /* display */, + XFontStruct* /* font_struct */ +); + +extern int XFreeFontInfo( + char** /* names */, + XFontStruct* /* free_info */, + int /* actual_count */ +); + +extern int XFreeFontNames( + char** /* list */ +); + +extern int XFreeFontPath( + char** /* list */ +); + +extern int XFreeGC( + Display* /* display */, + GC /* gc */ +); + +extern int XFreeModifiermap( + XModifierKeymap* /* modmap */ +); + +extern int XFreePixmap( + Display* /* display */, + Pixmap /* pixmap */ +); + +extern int XGeometry( + Display* /* display */, + int /* screen */, + _Xconst char* /* position */, + _Xconst char* /* default_position */, + unsigned int /* bwidth */, + unsigned int /* fwidth */, + unsigned int /* fheight */, + int /* xadder */, + int /* yadder */, + int* /* x_return */, + int* /* y_return */, + int* /* width_return */, + int* /* height_return */ +); + +extern int XGetErrorDatabaseText( + Display* /* display */, + _Xconst char* /* name */, + _Xconst char* /* message */, + _Xconst char* /* default_string */, + char* /* buffer_return */, + int /* length */ +); + +extern int XGetErrorText( + Display* /* display */, + int /* code */, + char* /* buffer_return */, + int /* length */ +); + +extern Bool XGetFontProperty( + XFontStruct* /* font_struct */, + Atom /* atom */, + unsigned long* /* value_return */ +); + +extern Status XGetGCValues( + Display* /* display */, + GC /* gc */, + unsigned long /* valuemask */, + XGCValues* /* values_return */ +); + +extern Status XGetGeometry( + Display* /* display */, + Drawable /* d */, + Window* /* root_return */, + int* /* x_return */, + int* /* y_return */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + unsigned int* /* border_width_return */, + unsigned int* /* depth_return */ +); + +extern Status XGetIconName( + Display* /* display */, + Window /* w */, + char** /* icon_name_return */ +); + +extern int XGetInputFocus( + Display* /* display */, + Window* /* focus_return */, + int* /* revert_to_return */ +); + +extern int XGetKeyboardControl( + Display* /* display */, + XKeyboardState* /* values_return */ +); + +extern int XGetPointerControl( + Display* /* display */, + int* /* accel_numerator_return */, + int* /* accel_denominator_return */, + int* /* threshold_return */ +); + +extern int XGetPointerMapping( + Display* /* display */, + unsigned char* /* map_return */, + int /* nmap */ +); + +extern int XGetScreenSaver( + Display* /* display */, + int* /* timeout_return */, + int* /* interval_return */, + int* /* prefer_blanking_return */, + int* /* allow_exposures_return */ +); + +extern Status XGetTransientForHint( + Display* /* display */, + Window /* w */, + Window* /* prop_window_return */ +); + +extern int XGetWindowProperty( + Display* /* display */, + Window /* w */, + Atom /* property */, + long /* long_offset */, + long /* long_length */, + Bool /* delete */, + Atom /* req_type */, + Atom* /* actual_type_return */, + int* /* actual_format_return */, + unsigned long* /* nitems_return */, + unsigned long* /* bytes_after_return */, + unsigned char** /* prop_return */ +); + +extern Status XGetWindowAttributes( + Display* /* display */, + Window /* w */, + XWindowAttributes* /* window_attributes_return */ +); + +extern int XGrabButton( + Display* /* display */, + unsigned int /* button */, + unsigned int /* modifiers */, + Window /* grab_window */, + Bool /* owner_events */, + unsigned int /* event_mask */, + int /* pointer_mode */, + int /* keyboard_mode */, + Window /* confine_to */, + Cursor /* cursor */ +); + +extern int XGrabKey( + Display* /* display */, + int /* keycode */, + unsigned int /* modifiers */, + Window /* grab_window */, + Bool /* owner_events */, + int /* pointer_mode */, + int /* keyboard_mode */ +); + +extern int XGrabKeyboard( + Display* /* display */, + Window /* grab_window */, + Bool /* owner_events */, + int /* pointer_mode */, + int /* keyboard_mode */, + Time /* time */ +); + +extern int XGrabPointer( + Display* /* display */, + Window /* grab_window */, + Bool /* owner_events */, + unsigned int /* event_mask */, + int /* pointer_mode */, + int /* keyboard_mode */, + Window /* confine_to */, + Cursor /* cursor */, + Time /* time */ +); + +extern int XGrabServer( + Display* /* display */ +); + +extern int XHeightMMOfScreen( + Screen* /* screen */ +); + +extern int XHeightOfScreen( + Screen* /* screen */ +); + +extern int XIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern int XImageByteOrder( + Display* /* display */ +); + +extern int XInstallColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern KeyCode XKeysymToKeycode( + Display* /* display */, + KeySym /* keysym */ +); + +extern int XKillClient( + Display* /* display */, + XID /* resource */ +); + +extern Status XLookupColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color_name */, + XColor* /* exact_def_return */, + XColor* /* screen_def_return */ +); + +extern int XLowerWindow( + Display* /* display */, + Window /* w */ +); + +extern int XMapRaised( + Display* /* display */, + Window /* w */ +); + +extern int XMapSubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XMapWindow( + Display* /* display */, + Window /* w */ +); + +extern int XMaskEvent( + Display* /* display */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XMaxCmapsOfScreen( + Screen* /* screen */ +); + +extern int XMinCmapsOfScreen( + Screen* /* screen */ +); + +extern int XMoveResizeWindow( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XMoveWindow( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */ +); + +extern int XNextEvent( + Display* /* display */, + XEvent* /* event_return */ +); + +extern int XNoOp( + Display* /* display */ +); + +extern Status XParseColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* spec */, + XColor* /* exact_def_return */ +); + +extern int XParseGeometry( + _Xconst char* /* parsestring */, + int* /* x_return */, + int* /* y_return */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern int XPeekEvent( + Display* /* display */, + XEvent* /* event_return */ +); + +extern int XPeekIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern int XPending( + Display* /* display */ +); + +extern int XPlanesOfScreen( + Screen* /* screen */ +); + +extern int XProtocolRevision( + Display* /* display */ +); + +extern int XProtocolVersion( + Display* /* display */ +); + + +extern int XPutBackEvent( + Display* /* display */, + XEvent* /* event */ +); + +extern int XPutImage( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XImage* /* image */, + int /* src_x */, + int /* src_y */, + int /* dest_x */, + int /* dest_y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XQLength( + Display* /* display */ +); + +extern Status XQueryBestCursor( + Display* /* display */, + Drawable /* d */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestSize( + Display* /* display */, + int /* class */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestStipple( + Display* /* display */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestTile( + Display* /* display */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern int XQueryColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* def_in_out */ +); + +extern int XQueryColors( + Display* /* display */, + Colormap /* colormap */, + XColor* /* defs_in_out */, + int /* ncolors */ +); + +extern Bool XQueryExtension( + Display* /* display */, + _Xconst char* /* name */, + int* /* major_opcode_return */, + int* /* first_event_return */, + int* /* first_error_return */ +); + +extern int XQueryKeymap( + Display* /* display */, + char [32] /* keys_return */ +); + +extern Bool XQueryPointer( + Display* /* display */, + Window /* w */, + Window* /* root_return */, + Window* /* child_return */, + int* /* root_x_return */, + int* /* root_y_return */, + int* /* win_x_return */, + int* /* win_y_return */, + unsigned int* /* mask_return */ +); + +extern int XQueryTextExtents( + Display* /* display */, + XID /* font_ID */, + _Xconst char* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XQueryTextExtents16( + Display* /* display */, + XID /* font_ID */, + _Xconst XChar2b* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern Status XQueryTree( + Display* /* display */, + Window /* w */, + Window* /* root_return */, + Window* /* parent_return */, + Window** /* children_return */, + unsigned int* /* nchildren_return */ +); + +extern int XRaiseWindow( + Display* /* display */, + Window /* w */ +); + +extern int XReadBitmapFile( + Display* /* display */, + Drawable /* d */, + _Xconst char* /* filename */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + Pixmap* /* bitmap_return */, + int* /* x_hot_return */, + int* /* y_hot_return */ +); + +extern int XReadBitmapFileData( + _Xconst char* /* filename */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + unsigned char** /* data_return */, + int* /* x_hot_return */, + int* /* y_hot_return */ +); + +extern int XRebindKeysym( + Display* /* display */, + KeySym /* keysym */, + KeySym* /* list */, + int /* mod_count */, + _Xconst unsigned char* /* string */, + int /* bytes_string */ +); + +extern int XRecolorCursor( + Display* /* display */, + Cursor /* cursor */, + XColor* /* foreground_color */, + XColor* /* background_color */ +); + +extern int XRefreshKeyboardMapping( + XMappingEvent* /* event_map */ +); + +extern int XRemoveFromSaveSet( + Display* /* display */, + Window /* w */ +); + +extern int XRemoveHost( + Display* /* display */, + XHostAddress* /* host */ +); + +extern int XRemoveHosts( + Display* /* display */, + XHostAddress* /* hosts */, + int /* num_hosts */ +); + +extern int XReparentWindow( + Display* /* display */, + Window /* w */, + Window /* parent */, + int /* x */, + int /* y */ +); + +extern int XResetScreenSaver( + Display* /* display */ +); + +extern int XResizeWindow( + Display* /* display */, + Window /* w */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XRestackWindows( + Display* /* display */, + Window* /* windows */, + int /* nwindows */ +); + +extern int XRotateBuffers( + Display* /* display */, + int /* rotate */ +); + +extern int XRotateWindowProperties( + Display* /* display */, + Window /* w */, + Atom* /* properties */, + int /* num_prop */, + int /* npositions */ +); + +extern int XScreenCount( + Display* /* display */ +); + +extern int XSelectInput( + Display* /* display */, + Window /* w */, + long /* event_mask */ +); + +extern Status XSendEvent( + Display* /* display */, + Window /* w */, + Bool /* propagate */, + long /* event_mask */, + XEvent* /* event_send */ +); + +extern int XSetAccessControl( + Display* /* display */, + int /* mode */ +); + +extern int XSetArcMode( + Display* /* display */, + GC /* gc */, + int /* arc_mode */ +); + +extern int XSetBackground( + Display* /* display */, + GC /* gc */, + unsigned long /* background */ +); + +extern int XSetClipMask( + Display* /* display */, + GC /* gc */, + Pixmap /* pixmap */ +); + +extern int XSetClipOrigin( + Display* /* display */, + GC /* gc */, + int /* clip_x_origin */, + int /* clip_y_origin */ +); + +extern int XSetClipRectangles( + Display* /* display */, + GC /* gc */, + int /* clip_x_origin */, + int /* clip_y_origin */, + XRectangle* /* rectangles */, + int /* n */, + int /* ordering */ +); + +extern int XSetCloseDownMode( + Display* /* display */, + int /* close_mode */ +); + +extern int XSetCommand( + Display* /* display */, + Window /* w */, + char** /* argv */, + int /* argc */ +); + +extern int XSetDashes( + Display* /* display */, + GC /* gc */, + int /* dash_offset */, + _Xconst char* /* dash_list */, + int /* n */ +); + +extern int XSetFillRule( + Display* /* display */, + GC /* gc */, + int /* fill_rule */ +); + +extern int XSetFillStyle( + Display* /* display */, + GC /* gc */, + int /* fill_style */ +); + +extern int XSetFont( + Display* /* display */, + GC /* gc */, + Font /* font */ +); + +extern int XSetFontPath( + Display* /* display */, + char** /* directories */, + int /* ndirs */ +); + +extern int XSetForeground( + Display* /* display */, + GC /* gc */, + unsigned long /* foreground */ +); + +extern int XSetFunction( + Display* /* display */, + GC /* gc */, + int /* function */ +); + +extern int XSetGraphicsExposures( + Display* /* display */, + GC /* gc */, + Bool /* graphics_exposures */ +); + +extern int XSetIconName( + Display* /* display */, + Window /* w */, + _Xconst char* /* icon_name */ +); + +extern int XSetInputFocus( + Display* /* display */, + Window /* focus */, + int /* revert_to */, + Time /* time */ +); + +extern int XSetLineAttributes( + Display* /* display */, + GC /* gc */, + unsigned int /* line_width */, + int /* line_style */, + int /* cap_style */, + int /* join_style */ +); + +extern int XSetModifierMapping( + Display* /* display */, + XModifierKeymap* /* modmap */ +); + +extern int XSetPlaneMask( + Display* /* display */, + GC /* gc */, + unsigned long /* plane_mask */ +); + +extern int XSetPointerMapping( + Display* /* display */, + _Xconst unsigned char* /* map */, + int /* nmap */ +); + +extern int XSetScreenSaver( + Display* /* display */, + int /* timeout */, + int /* interval */, + int /* prefer_blanking */, + int /* allow_exposures */ +); + +extern int XSetSelectionOwner( + Display* /* display */, + Atom /* selection */, + Window /* owner */, + Time /* time */ +); + +extern int XSetState( + Display* /* display */, + GC /* gc */, + unsigned long /* foreground */, + unsigned long /* background */, + int /* function */, + unsigned long /* plane_mask */ +); + +extern int XSetStipple( + Display* /* display */, + GC /* gc */, + Pixmap /* stipple */ +); + +extern int XSetSubwindowMode( + Display* /* display */, + GC /* gc */, + int /* subwindow_mode */ +); + +extern int XSetTSOrigin( + Display* /* display */, + GC /* gc */, + int /* ts_x_origin */, + int /* ts_y_origin */ +); + +extern int XSetTile( + Display* /* display */, + GC /* gc */, + Pixmap /* tile */ +); + +extern int XSetWindowBackground( + Display* /* display */, + Window /* w */, + unsigned long /* background_pixel */ +); + +extern int XSetWindowBackgroundPixmap( + Display* /* display */, + Window /* w */, + Pixmap /* background_pixmap */ +); + +extern int XSetWindowBorder( + Display* /* display */, + Window /* w */, + unsigned long /* border_pixel */ +); + +extern int XSetWindowBorderPixmap( + Display* /* display */, + Window /* w */, + Pixmap /* border_pixmap */ +); + +extern int XSetWindowBorderWidth( + Display* /* display */, + Window /* w */, + unsigned int /* width */ +); + +extern int XSetWindowColormap( + Display* /* display */, + Window /* w */, + Colormap /* colormap */ +); + +extern int XStoreBuffer( + Display* /* display */, + _Xconst char* /* bytes */, + int /* nbytes */, + int /* buffer */ +); + +extern int XStoreBytes( + Display* /* display */, + _Xconst char* /* bytes */, + int /* nbytes */ +); + +extern int XStoreColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* color */ +); + +extern int XStoreColors( + Display* /* display */, + Colormap /* colormap */, + XColor* /* color */, + int /* ncolors */ +); + +extern int XStoreName( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */ +); + +extern int XStoreNamedColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color */, + unsigned long /* pixel */, + int /* flags */ +); + +extern int XSync( + Display* /* display */, + Bool /* discard */ +); + +extern int XTextExtents( + XFontStruct* /* font_struct */, + _Xconst char* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XTextExtents16( + XFontStruct* /* font_struct */, + _Xconst XChar2b* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XTextWidth( + XFontStruct* /* font_struct */, + _Xconst char* /* string */, + int /* count */ +); + +extern int XTextWidth16( + XFontStruct* /* font_struct */, + _Xconst XChar2b* /* string */, + int /* count */ +); + +extern Bool XTranslateCoordinates( + Display* /* display */, + Window /* src_w */, + Window /* dest_w */, + int /* src_x */, + int /* src_y */, + int* /* dest_x_return */, + int* /* dest_y_return */, + Window* /* child_return */ +); + +extern int XUndefineCursor( + Display* /* display */, + Window /* w */ +); + +extern int XUngrabButton( + Display* /* display */, + unsigned int /* button */, + unsigned int /* modifiers */, + Window /* grab_window */ +); + +extern int XUngrabKey( + Display* /* display */, + int /* keycode */, + unsigned int /* modifiers */, + Window /* grab_window */ +); + +extern int XUngrabKeyboard( + Display* /* display */, + Time /* time */ +); + +extern int XUngrabPointer( + Display* /* display */, + Time /* time */ +); + +extern int XUngrabServer( + Display* /* display */ +); + +extern int XUninstallColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern int XUnloadFont( + Display* /* display */, + Font /* font */ +); + +extern int XUnmapSubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XUnmapWindow( + Display* /* display */, + Window /* w */ +); + +extern int XVendorRelease( + Display* /* display */ +); + +extern int XWarpPointer( + Display* /* display */, + Window /* src_w */, + Window /* dest_w */, + int /* src_x */, + int /* src_y */, + unsigned int /* src_width */, + unsigned int /* src_height */, + int /* dest_x */, + int /* dest_y */ +); + +extern int XWidthMMOfScreen( + Screen* /* screen */ +); + +extern int XWidthOfScreen( + Screen* /* screen */ +); + +extern int XWindowEvent( + Display* /* display */, + Window /* w */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XWriteBitmapFile( + Display* /* display */, + _Xconst char* /* filename */, + Pixmap /* bitmap */, + unsigned int /* width */, + unsigned int /* height */, + int /* x_hot */, + int /* y_hot */ +); + +extern Bool XSupportsLocale (void); + +extern char *XSetLocaleModifiers( + const char* /* modifier_list */ +); + +extern XOM XOpenOM( + Display* /* display */, + struct _XrmHashBucketRec* /* rdb */, + _Xconst char* /* res_name */, + _Xconst char* /* res_class */ +); + +extern Status XCloseOM( + XOM /* om */ +); + +extern char *XSetOMValues( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern char *XGetOMValues( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern Display *XDisplayOfOM( + XOM /* om */ +); + +extern char *XLocaleOfOM( + XOM /* om */ +); + +extern XOC XCreateOC( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern void XDestroyOC( + XOC /* oc */ +); + +extern XOM XOMOfOC( + XOC /* oc */ +); + +extern char *XSetOCValues( + XOC /* oc */, + ... +) _X_SENTINEL(0); + +extern char *XGetOCValues( + XOC /* oc */, + ... +) _X_SENTINEL(0); + +extern XFontSet XCreateFontSet( + Display* /* display */, + _Xconst char* /* base_font_name_list */, + char*** /* missing_charset_list */, + int* /* missing_charset_count */, + char** /* def_string */ +); + +extern void XFreeFontSet( + Display* /* display */, + XFontSet /* font_set */ +); + +extern int XFontsOfFontSet( + XFontSet /* font_set */, + XFontStruct*** /* font_struct_list */, + char*** /* font_name_list */ +); + +extern char *XBaseFontNameListOfFontSet( + XFontSet /* font_set */ +); + +extern char *XLocaleOfFontSet( + XFontSet /* font_set */ +); + +extern Bool XContextDependentDrawing( + XFontSet /* font_set */ +); + +extern Bool XDirectionalDependentDrawing( + XFontSet /* font_set */ +); + +extern Bool XContextualDrawing( + XFontSet /* font_set */ +); + +extern XFontSetExtents *XExtentsOfFontSet( + XFontSet /* font_set */ +); + +extern int XmbTextEscapement( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern int XwcTextEscapement( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern int Xutf8TextEscapement( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern int XmbTextExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern int XwcTextExtents( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern int Xutf8TextExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status XmbTextPerCharExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status XwcTextPerCharExtents( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status Xutf8TextPerCharExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern void XmbDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XmbTextItem* /* text_items */, + int /* nitems */ +); + +extern void XwcDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XwcTextItem* /* text_items */, + int /* nitems */ +); + +extern void Xutf8DrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XmbTextItem* /* text_items */, + int /* nitems */ +); + +extern void XmbDrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XwcDrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern void Xutf8DrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XmbDrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XwcDrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern void Xutf8DrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern XIM XOpenIM( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */ +); + +extern Status XCloseIM( + XIM /* im */ +); + +extern char *XGetIMValues( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern char *XSetIMValues( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern Display *XDisplayOfIM( + XIM /* im */ +); + +extern char *XLocaleOfIM( + XIM /* im*/ +); + +extern XIC XCreateIC( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern void XDestroyIC( + XIC /* ic */ +); + +extern void XSetICFocus( + XIC /* ic */ +); + +extern void XUnsetICFocus( + XIC /* ic */ +); + +extern wchar_t *XwcResetIC( + XIC /* ic */ +); + +extern char *XmbResetIC( + XIC /* ic */ +); + +extern char *Xutf8ResetIC( + XIC /* ic */ +); + +extern char *XSetICValues( + XIC /* ic */, ... +) _X_SENTINEL(0); + +extern char *XGetICValues( + XIC /* ic */, ... +) _X_SENTINEL(0); + +extern XIM XIMOfIC( + XIC /* ic */ +); + +extern Bool XFilterEvent( + XEvent* /* event */, + Window /* window */ +); + +extern int XmbLookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern int XwcLookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + wchar_t* /* buffer_return */, + int /* wchars_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern int Xutf8LookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern XVaNestedList XVaCreateNestedList( + int /*unused*/, ... +) _X_SENTINEL(0); + +/* internal connections for IMs */ + +extern Bool XRegisterIMInstantiateCallback( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */, + XIDProc /* callback */, + XPointer /* client_data */ +); + +extern Bool XUnregisterIMInstantiateCallback( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */, + XIDProc /* callback */, + XPointer /* client_data */ +); + +typedef void (*XConnectionWatchProc)( + Display* /* dpy */, + XPointer /* client_data */, + int /* fd */, + Bool /* opening */, /* open or close flag */ + XPointer* /* watch_data */ /* open sets, close uses */ +); + + +extern Status XInternalConnectionNumbers( + Display* /* dpy */, + int** /* fd_return */, + int* /* count_return */ +); + +extern void XProcessInternalConnection( + Display* /* dpy */, + int /* fd */ +); + +extern Status XAddConnectionWatch( + Display* /* dpy */, + XConnectionWatchProc /* callback */, + XPointer /* client_data */ +); + +extern void XRemoveConnectionWatch( + Display* /* dpy */, + XConnectionWatchProc /* callback */, + XPointer /* client_data */ +); + +extern void XSetAuthorization( + char * /* name */, + int /* namelen */, + char * /* data */, + int /* datalen */ +); + +extern int _Xmbtowc( + wchar_t * /* wstr */, + char * /* str */, + int /* len */ +); + +extern int _Xwctomb( + char * /* str */, + wchar_t /* wc */ +); + +extern Bool XGetEventData( + Display* /* dpy */, + XGenericEventCookie* /* cookie*/ +); + +extern void XFreeEventData( + Display* /* dpy */, + XGenericEventCookie* /* cookie*/ +); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +_XFUNCPROTOEND + +#endif /* _X11_XLIB_H_ */ diff --git a/packages/games/tools/axe11/X11/XlibConf.h.in b/packages/games/tools/axe11/X11/XlibConf.h.in new file mode 100644 index 000000000..8f36ac1d9 --- /dev/null +++ b/packages/games/tools/axe11/X11/XlibConf.h.in @@ -0,0 +1,37 @@ +/* + * Copyright © 2005 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _XLIBCONF_H_ +#define _XLIBCONF_H_ +/* + * This header file exports defines necessary to correctly + * use Xlibint.h both inside Xlib and by external libraries + * such as extensions. + */ + +/* Threading support? */ +#undef XTHREADS + +/* Use multi-threaded libc functions? */ +#undef XUSE_MTSAFE_API + +#endif /* _XLIBCONF_H_ */ diff --git a/packages/games/tools/axe11/X11/Xlibint.h b/packages/games/tools/axe11/X11/Xlibint.h new file mode 100644 index 000000000..abcc59acb --- /dev/null +++ b/packages/games/tools/axe11/X11/Xlibint.h @@ -0,0 +1,1444 @@ + +/* + +Copyright 1984, 1985, 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef _X11_XLIBINT_H_ +#define _X11_XLIBINT_H_ 1 + +/* + * Xlibint.h - Header definition and support file for the internal + * support routines used by the C subroutine interface + * library (Xlib) to the X Window System. + * + * Warning, there be dragons here.... + */ + +#include +#include +#include /* to declare xEvent */ +#include /* for configured options like XTHREADS */ + +/* The Xlib structs are full of implicit padding to properly align members. + We can't clean that up without breaking ABI, so tell clang not to bother + complaining about it. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#ifdef WIN32 +#define _XFlush _XFlushIt +#endif + +struct _XGC +{ + XExtData *ext_data; /* hook for extension to hang data */ + GContext gid; /* protocol ID for graphics context */ + Bool rects; /* boolean: TRUE if clipmask is list of rectangles */ + Bool dashes; /* boolean: TRUE if dash-list is really a list */ + unsigned long dirty;/* cache dirty bits */ + XGCValues values; /* shadow structure of values */ +}; + +struct _XDisplay +{ + XExtData *ext_data; /* hook for extension to hang data */ + struct _XFreeFuncs *free_funcs; /* internal free functions */ + int fd; /* Network socket. */ + int conn_checker; /* ugly thing used by _XEventsQueued */ + int proto_major_version;/* maj. version of server's X protocol */ + int proto_minor_version;/* minor version of server's X protocol */ + char *vendor; /* vendor of the server hardware */ + XID resource_base; /* resource ID base */ + XID resource_mask; /* resource ID mask bits */ + XID resource_id; /* allocator current ID */ + int resource_shift; /* allocator shift to correct bits */ + XID (*resource_alloc)( /* allocator function */ + struct _XDisplay* + ); + int byte_order; /* screen byte order, LSBFirst, MSBFirst */ + int bitmap_unit; /* padding and data requirements */ + int bitmap_pad; /* padding requirements on bitmaps */ + int bitmap_bit_order; /* LeastSignificant or MostSignificant */ + int nformats; /* number of pixmap formats in list */ + ScreenFormat *pixmap_format; /* pixmap format list */ + int vnumber; /* Xlib's X protocol version number. */ + int release; /* release of the server */ + struct _XSQEvent *head, *tail; /* Input event queue. */ + int qlen; /* Length of input event queue */ + unsigned long last_request_read; /* seq number of last event read */ + unsigned long request; /* sequence number of last request. */ + char *last_req; /* beginning of last request, or dummy */ + char *buffer; /* Output buffer starting address. */ + char *bufptr; /* Output buffer index pointer. */ + char *bufmax; /* Output buffer maximum+1 address. */ + unsigned max_request_size; /* maximum number 32 bit words in request*/ + struct _XrmHashBucketRec *db; + int (*synchandler)( /* Synchronization handler */ + struct _XDisplay* + ); + char *display_name; /* "host:display" string used on this connect*/ + int default_screen; /* default screen for operations */ + int nscreens; /* number of screens on this server*/ + Screen *screens; /* pointer to list of screens */ + unsigned long motion_buffer; /* size of motion buffer */ + volatile unsigned long flags; /* internal connection flags */ + int min_keycode; /* minimum defined keycode */ + int max_keycode; /* maximum defined keycode */ + KeySym *keysyms; /* This server's keysyms */ + XModifierKeymap *modifiermap; /* This server's modifier keymap */ + int keysyms_per_keycode;/* number of rows */ + char *xdefaults; /* contents of defaults from server */ + char *scratch_buffer; /* place to hang scratch buffer */ + unsigned long scratch_length; /* length of scratch buffer */ + int ext_number; /* extension number on this display */ + struct _XExten *ext_procs; /* extensions initialized on this display */ + /* + * the following can be fixed size, as the protocol defines how + * much address space is available. + * While this could be done using the extension vector, there + * may be MANY events processed, so a search through the extension + * list to find the right procedure for each event might be + * expensive if many extensions are being used. + */ + Bool (*event_vec[128])( /* vector for wire to event */ + Display * /* dpy */, + XEvent * /* re */, + xEvent * /* event */ + ); + Status (*wire_vec[128])( /* vector for event to wire */ + Display * /* dpy */, + XEvent * /* re */, + xEvent * /* event */ + ); + KeySym lock_meaning; /* for XLookupString */ + struct _XLockInfo *lock; /* multi-thread state, display lock */ + struct _XInternalAsync *async_handlers; /* for internal async */ + unsigned long bigreq_size; /* max size of big requests */ + struct _XLockPtrs *lock_fns; /* pointers to threads functions */ + void (*idlist_alloc)( /* XID list allocator function */ + Display * /* dpy */, + XID * /* ids */, + int /* count */ + ); + /* things above this line should not move, for binary compatibility */ + struct _XKeytrans *key_bindings; /* for XLookupString */ + Font cursor_font; /* for XCreateFontCursor */ + struct _XDisplayAtoms *atoms; /* for XInternAtom */ + unsigned int mode_switch; /* keyboard group modifiers */ + unsigned int num_lock; /* keyboard numlock modifiers */ + struct _XContextDB *context_db; /* context database */ + Bool (**error_vec)( /* vector for wire to error */ + Display * /* display */, + XErrorEvent * /* he */, + xError * /* we */ + ); + /* + * Xcms information + */ + struct { + XPointer defaultCCCs; /* pointer to an array of default XcmsCCC */ + XPointer clientCmaps; /* pointer to linked list of XcmsCmapRec */ + XPointer perVisualIntensityMaps; + /* linked list of XcmsIntensityMap */ + } cms; + struct _XIMFilter *im_filters; + struct _XSQEvent *qfree; /* unallocated event queue elements */ + unsigned long next_event_serial_num; /* inserted into next queue elt */ + struct _XExten *flushes; /* Flush hooks */ + struct _XConnectionInfo *im_fd_info; /* _XRegisterInternalConnection */ + int im_fd_length; /* number of im_fd_info */ + struct _XConnWatchInfo *conn_watchers; /* XAddConnectionWatch */ + int watcher_count; /* number of conn_watchers */ + XPointer filedes; /* struct pollfd cache for _XWaitForReadable */ + int (*savedsynchandler)( /* user synchandler when Xlib usurps */ + Display * /* dpy */ + ); + XID resource_max; /* allocator max ID */ + int xcmisc_opcode; /* major opcode for XC-MISC */ + struct _XkbInfoRec *xkb_info; /* XKB info */ + struct _XtransConnInfo *trans_conn; /* transport connection object */ + struct _X11XCBPrivate *xcb; /* XCB glue private data */ + + /* Generic event cookie handling */ + unsigned int next_cookie; /* next event cookie */ + /* vector for wire to generic event, index is (extension - 128) */ + Bool (*generic_event_vec[128])( + Display * /* dpy */, + XGenericEventCookie * /* Xlib event */, + xEvent * /* wire event */); + /* vector for event copy, index is (extension - 128) */ + Bool (*generic_event_copy_vec[128])( + Display * /* dpy */, + XGenericEventCookie * /* in */, + XGenericEventCookie * /* out*/); + void *cookiejar; /* cookie events returned but not claimed */ +#ifndef LONG64 + unsigned long last_request_read_upper32bit; + unsigned long request_upper32bit; +#endif + + struct _XErrorThreadInfo *error_threads; + + XIOErrorExitHandler exit_handler; + void *exit_handler_data; +}; + +#define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n) + +/* + * access "last_request_read" and "request" with 64bit + * warning: the value argument of the SET-macros must not + * have any side-effects because it may get called twice. + */ +#ifndef LONG64 +/* accessors for 32-bit unsigned long */ + +#define X_DPY_GET_REQUEST(dpy) \ + ( \ + ((uint64_t)(((struct _XDisplay*)dpy)->request)) \ + + (((uint64_t)(((struct _XDisplay*)dpy)->request_upper32bit)) << 32) \ + ) + +#define X_DPY_SET_REQUEST(dpy, value) \ + ( \ + (((struct _XDisplay*)dpy)->request = \ + (value) & 0xFFFFFFFFUL), \ + (((struct _XDisplay*)dpy)->request_upper32bit = \ + ((uint64_t)(value)) >> 32), \ + (void)0 /* don't use the result */ \ + ) + +#define X_DPY_GET_LAST_REQUEST_READ(dpy) \ + ( \ + ((uint64_t)(((struct _XDisplay*)dpy)->last_request_read)) \ + + ( \ + ((uint64_t)( \ + ((struct _XDisplay*)dpy)->last_request_read_upper32bit \ + )) << 32 \ + ) \ + ) + +#define X_DPY_SET_LAST_REQUEST_READ(dpy, value) \ + ( \ + (((struct _XDisplay*)dpy)->last_request_read = \ + (value) & 0xFFFFFFFFUL), \ + (((struct _XDisplay*)dpy)->last_request_read_upper32bit = \ + ((uint64_t)(value)) >> 32), \ + (void)0 /* don't use the result */ \ + ) + +/* + * widen a 32-bit sequence number to a 64 sequence number. + * This macro makes the following assumptions: + * - ulseq refers to a sequence that has already been sent + * - ulseq means the most recent possible sequence number + * with these lower 32 bits. + * + * The following optimization is used: + * The comparison result is taken a 0 or 1 to avoid a branch. + */ +#define X_DPY_WIDEN_UNSIGNED_LONG_SEQ(dpy, ulseq) \ + ( \ + ((uint64_t)ulseq) \ + + \ + (( \ + ((uint64_t)(((struct _XDisplay*)dpy)->request_upper32bit)) \ + - (uint64_t)( \ + (ulseq) > (((struct _XDisplay*)dpy)->request) \ + ) \ + ) << 32) \ + ) + +#define X_DPY_REQUEST_INCREMENT(dpy) \ + ( \ + ((struct _XDisplay*)dpy)->request++, \ + ( \ + (((struct _XDisplay*)dpy)->request == 0) ? ( \ + ((struct _XDisplay*)dpy)->request_upper32bit++ \ + ) : 0 \ + ), \ + (void)0 /* don't use the result */ \ + ) + + +#define X_DPY_REQUEST_DECREMENT(dpy) \ + ( \ + ( \ + (((struct _XDisplay*)dpy)->request == 0) ? (\ + ((struct _XDisplay*)dpy)->request--, /* wrap */ \ + ((struct _XDisplay*)dpy)->request_upper32bit-- \ + ) : ( \ + ((struct _XDisplay*)dpy)->request-- \ + ) \ + ), \ + (void)0 /* don't use the result */ \ + ) + +#else +/* accessors for 64-bit unsigned long */ +#define X_DPY_GET_REQUEST(dpy) \ + (((struct _XDisplay*)dpy)->request) +#define X_DPY_SET_REQUEST(dpy, value) \ + ((struct _XDisplay*)dpy)->request = (value) + +#define X_DPY_GET_LAST_REQUEST_READ(dpy) \ + (((struct _XDisplay*)dpy)->last_request_read) +#define X_DPY_SET_LAST_REQUEST_READ(dpy, value) \ + ((struct _XDisplay*)dpy)->last_request_read = (value) + +#define X_DPY_WIDEN_UNSIGNED_LONG_SEQ(dpy, ulseq) ulseq + +#define X_DPY_REQUEST_INCREMENT(dpy) ((struct _XDisplay*)dpy)->request++ +#define X_DPY_REQUEST_DECREMENT(dpy) ((struct _XDisplay*)dpy)->request-- +#endif + + +#ifndef _XEVENT_ +/* + * _QEvent datatype for use in input queueing. + */ +typedef struct _XSQEvent +{ + struct _XSQEvent *next; + XEvent event; + unsigned long qserial_num; /* so multi-threaded code can find new ones */ +} _XQEvent; +#endif + +#include +#ifdef __sgi +#define _SGI_MP_SOURCE /* turn this on to get MP safe errno */ +#endif +#include +#define _XBCOPYFUNC _Xbcopy +#include +#include + +/* Utek leaves kernel macros around in include files (bleah) */ +#ifdef dirty +#undef dirty +#endif + +#include +#include + +#include + +_XFUNCPROTOBEGIN + +/* + * The following definitions can be used for locking requests in multi-threaded + * address spaces. + */ +#ifdef XTHREADS +/* Author: Stephen Gildea, MIT X Consortium + * + * declarations for C Threads locking + */ + +typedef struct _LockInfoRec *LockInfoPtr; + +/* interfaces for locking.c */ +struct _XLockPtrs { + /* used by all, including extensions; do not move */ + void (*lock_display)( + Display *dpy +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char *file + , int line +#endif + ); + void (*unlock_display)( + Display *dpy +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char *file + , int line +#endif + ); +}; + +#if defined(WIN32) && !defined(_XLIBINT_) +#define _XCreateMutex_fn (*_XCreateMutex_fn_p) +#define _XFreeMutex_fn (*_XFreeMutex_fn_p) +#define _XLockMutex_fn (*_XLockMutex_fn_p) +#define _XUnlockMutex_fn (*_XUnlockMutex_fn_p) +#define _Xglobal_lock (*_Xglobal_lock_p) +#endif + +/* in XlibInt.c */ +extern void (*_XCreateMutex_fn)( + LockInfoPtr /* lock */ +); +extern void (*_XFreeMutex_fn)( + LockInfoPtr /* lock */ +); +extern void (*_XLockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif +); +extern void (*_XUnlockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif +); + +extern LockInfoPtr _Xglobal_lock; + +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) +#define LockDisplay(d) if ((d)->lock_fns) (*(d)->lock_fns->lock_display)((d),__FILE__,__LINE__) +#define UnlockDisplay(d) if ((d)->lock_fns) (*(d)->lock_fns->unlock_display)((d),__FILE__,__LINE__) +#define _XLockMutex(lock) if (_XLockMutex_fn) (*_XLockMutex_fn)(lock,__FILE__,__LINE__) +#define _XUnlockMutex(lock) if (_XUnlockMutex_fn) (*_XUnlockMutex_fn)(lock,__FILE__,__LINE__) +#else +/* used everywhere, so must be fast if not using threads */ +#define LockDisplay(d) if ((d)->lock_fns) (*(d)->lock_fns->lock_display)(d) +#define UnlockDisplay(d) if ((d)->lock_fns) (*(d)->lock_fns->unlock_display)(d) +#define _XLockMutex(lock) if (_XLockMutex_fn) (*_XLockMutex_fn)(lock) +#define _XUnlockMutex(lock) if (_XUnlockMutex_fn) (*_XUnlockMutex_fn)(lock) +#endif +#define _XCreateMutex(lock) if (_XCreateMutex_fn) (*_XCreateMutex_fn)(lock); +#define _XFreeMutex(lock) if (_XFreeMutex_fn) (*_XFreeMutex_fn)(lock); + +#else /* XTHREADS */ +#define LockDisplay(dis) +#define _XLockMutex(lock) +#define _XUnlockMutex(lock) +#define UnlockDisplay(dis) +#define _XCreateMutex(lock) +#define _XFreeMutex(lock) +#endif + +#define Xfree(ptr) free((ptr)) + +/* + * Note that some machines do not return a valid pointer for malloc(0), in + * which case we provide an alternate under the control of the + * define MALLOC_0_RETURNS_NULL. This is necessary because some + * Xlib code expects malloc(0) to return a valid pointer to storage. + */ +#if defined(MALLOC_0_RETURNS_NULL) || defined(__clang_analyzer__) + +# define Xmalloc(size) malloc((size_t)((size) == 0 ? 1 : (size))) +# define Xrealloc(ptr, size) realloc((ptr), (size_t)((size) == 0 ? 1 : (size))) +# define Xcalloc(nelem, elsize) calloc((size_t)((nelem) == 0 ? 1 : (nelem)), (size_t)(elsize)) + +#else + +# define Xmalloc(size) malloc((size_t)(size)) +# define Xrealloc(ptr, size) realloc((ptr), (size_t)(size)) +# define Xcalloc(nelem, elsize) calloc((size_t)(nelem), (size_t)(elsize)) + +#endif + +#include + +#define LOCKED 1 +#define UNLOCKED 0 + +#ifndef BUFSIZE +#define BUFSIZE 2048 /* X output buffer size. */ +#endif +#ifndef PTSPERBATCH +#define PTSPERBATCH 1024 /* point batching */ +#endif +#ifndef WLNSPERBATCH +#define WLNSPERBATCH 50 /* wide line batching */ +#endif +#ifndef ZLNSPERBATCH +#define ZLNSPERBATCH 1024 /* thin line batching */ +#endif +#ifndef WRCTSPERBATCH +#define WRCTSPERBATCH 10 /* wide line rectangle batching */ +#endif +#ifndef ZRCTSPERBATCH +#define ZRCTSPERBATCH 256 /* thin line rectangle batching */ +#endif +#ifndef FRCTSPERBATCH +#define FRCTSPERBATCH 256 /* filled rectangle batching */ +#endif +#ifndef FARCSPERBATCH +#define FARCSPERBATCH 256 /* filled arc batching */ +#endif +#ifndef CURSORFONT +#define CURSORFONT "cursor" /* standard cursor fonts */ +#endif + +/* + * Display flags + */ +#define XlibDisplayIOError (1L << 0) +#define XlibDisplayClosing (1L << 1) +#define XlibDisplayNoXkb (1L << 2) +#define XlibDisplayPrivSync (1L << 3) +#define XlibDisplayProcConni (1L << 4) /* in _XProcessInternalConnection */ +#define XlibDisplayReadEvents (1L << 5) /* in _XReadEvents */ +#define XlibDisplayReply (1L << 5) /* in _XReply */ +#define XlibDisplayWriting (1L << 6) /* in _XFlushInt, _XSend */ +#define XlibDisplayDfltRMDB (1L << 7) /* mark if RM db from XGetDefault */ + +/* + * X Protocol packetizing macros. + */ + +/* Leftover from CRAY support - was defined empty on all non-Cray systems */ +#define WORD64ALIGN + +/** + * Return a len-sized request buffer for the request type. This function may + * flush the output queue. + * + * @param dpy The display connection + * @param type The request type + * @param len Length of the request in bytes + * + * @returns A pointer to the request buffer with a few default values + * initialized. + */ +extern void *_XGetRequest(Display *dpy, CARD8 type, size_t len); + +/* GetReqSized is the same as GetReq but allows the caller to specify the + * size in bytes. 'sz' must be a multiple of 4! */ + +#define GetReqSized(name, sz, req) \ + req = (x##name##Req *) _XGetRequest(dpy, X_##name, sz) + +/* + * GetReq - Get the next available X request packet in the buffer and + * return it. + * + * "name" is the name of the request, e.g. CreatePixmap, OpenFont, etc. + * "req" is the name of the request pointer. + * + */ + +#define GetReq(name, req) \ + GetReqSized(name, SIZEOF(x##name##Req), req) + +/* GetReqExtra is the same as GetReq, but allocates "n" additional + bytes after the request. "n" must be a multiple of 4! */ + +#define GetReqExtra(name, n, req) \ + GetReqSized(name, SIZEOF(x##name##Req) + n, req) + +/* + * GetResReq is for those requests that have a resource ID + * (Window, Pixmap, GContext, etc.) as their single argument. + * "rid" is the name of the resource. + */ + +#define GetResReq(name, rid, req) \ + req = (xResourceReq *) _XGetRequest(dpy, X_##name, SIZEOF(xResourceReq)); \ + req->id = (rid) + +/* + * GetEmptyReq is for those requests that have no arguments + * at all. + */ + +#define GetEmptyReq(name, req) \ + req = (xReq *) _XGetRequest(dpy, X_##name, SIZEOF(xReq)) + +/* + * MakeBigReq sets the CARD16 "req->length" to 0 and inserts a new CARD32 + * length, after req->length, before the data in the request. The new length + * includes the "n" extra 32-bit words. + * + * Do not use MakeBigReq if there is no data already in the request. + * req->length must already be >= 2. + */ +#ifdef LONG64 +#define MakeBigReq(req,n) \ + { \ + CARD64 _BRdat; \ + CARD32 _BRlen = req->length - 1; \ + req->length = 0; \ + _BRdat = ((CARD32 *)req)[_BRlen]; \ + memmove(((char *)req) + 8, ((char *)req) + 4, (_BRlen - 1) << 2); \ + ((CARD32 *)req)[1] = _BRlen + n + 2; \ + Data32(dpy, &_BRdat, 4); \ + } +#else +#define MakeBigReq(req,n) \ + { \ + CARD32 _BRdat; \ + CARD32 _BRlen = req->length - 1; \ + req->length = 0; \ + _BRdat = ((CARD32 *)req)[_BRlen]; \ + memmove(((char *)req) + 8, ((char *)req) + 4, (_BRlen - 1) << 2); \ + ((CARD32 *)req)[1] = _BRlen + n + 2; \ + Data32(dpy, &_BRdat, 4); \ + } +#endif + +/* + * SetReqLen increases the count of 32-bit words in the request by "n", + * or by "badlen" if "n" is too large. + * + * Do not use SetReqLen if "req" does not already have data after the + * xReq header. req->length must already be >= 2. + */ +#ifndef __clang_analyzer__ +#define SetReqLen(req,n,badlen) \ + if ((req->length + n) > (unsigned)65535) { \ + if (dpy->bigreq_size) { \ + MakeBigReq(req,n) \ + } else { \ + n = badlen; \ + req->length += n; \ + } \ + } else \ + req->length += n +#else +#define SetReqLen(req,n,badlen) \ + req->length += n +#endif + +#define SyncHandle() \ + if (dpy->synchandler) (*dpy->synchandler)(dpy) + +extern void _XFlushGCCache(Display *dpy, GC gc); +#define FlushGC(dpy, gc) \ + if ((gc)->dirty) _XFlushGCCache((dpy), (gc)) +/* + * Data - Place data in the buffer and pad the end to provide + * 32 bit word alignment. Transmit if the buffer fills. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to a data buffer. + * "len" is the length of the data buffer. + */ +#ifndef DataRoutineIsProcedure +#define Data(dpy, data, len) {\ + if (dpy->bufptr + (len) <= dpy->bufmax) {\ + memcpy(dpy->bufptr, data, (int)(len));\ + dpy->bufptr += ((len) + 3) & ~3;\ + } else\ + _XSend(dpy, data, len);\ +} +#endif /* DataRoutineIsProcedure */ + + +/* Allocate bytes from the buffer. No padding is done, so if + * the length is not a multiple of 4, the caller must be + * careful to leave the buffer aligned after sending the + * current request. + * + * "type" is the type of the pointer being assigned to. + * "ptr" is the pointer being assigned to. + * "n" is the number of bytes to allocate. + * + * Example: + * xTextElt *elt; + * BufAlloc (xTextElt *, elt, nbytes) + */ + +#define BufAlloc(type, ptr, n) \ + if (dpy->bufptr + (n) > dpy->bufmax) \ + _XFlush (dpy); \ + ptr = (type) dpy->bufptr; \ + memset(ptr, '\0', n); \ + dpy->bufptr += (n); + +#define Data16(dpy, data, len) Data((dpy), (_Xconst char *)(data), (len)) +#define _XRead16Pad(dpy, data, len) _XReadPad((dpy), (char *)(data), (len)) +#define _XRead16(dpy, data, len) _XRead((dpy), (char *)(data), (len)) +#ifdef LONG64 +#define Data32(dpy, data, len) _XData32(dpy, (_Xconst long *)data, len) +extern int _XData32( + Display *dpy, + _Xconst long *data, + unsigned len +); +extern void _XRead32( + Display *dpy, + long *data, + long len +); +#else +#define Data32(dpy, data, len) Data((dpy), (_Xconst char *)(data), (len)) +#define _XRead32(dpy, data, len) _XRead((dpy), (char *)(data), (len)) +#endif + +#define PackData16(dpy,data,len) Data16 (dpy, data, len) +#define PackData32(dpy,data,len) Data32 (dpy, data, len) + +/* Xlib manual is bogus */ +#define PackData(dpy,data,len) PackData16 (dpy, data, len) + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ + (((cs)->rbearing|(cs)->lbearing| \ + (cs)->ascent|(cs)->descent) == 0)) + +/* + * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit + * character. If the character is in the column and exists, then return the + * appropriate metrics (note that fonts with common per-character metrics will + * return min_bounds). If none of these hold true, try again with the default + * char. + */ +#define CI_GET_CHAR_INFO_1D(fs,col,def,cs) \ +{ \ + cs = def; \ + if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ + if (fs->per_char == NULL) { \ + cs = &fs->min_bounds; \ + } else { \ + cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ + if (CI_NONEXISTCHAR(cs)) cs = def; \ + } \ + } \ +} + +#define CI_GET_DEFAULT_INFO_1D(fs,cs) \ + CI_GET_CHAR_INFO_1D (fs, fs->default_char, NULL, cs) + + + +/* + * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and + * column. This is used for fonts that have more than row zero. + */ +#define CI_GET_CHAR_INFO_2D(fs,row,col,def,cs) \ +{ \ + cs = def; \ + if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ + col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ + if (fs->per_char == NULL) { \ + cs = &fs->min_bounds; \ + } else { \ + cs = &fs->per_char[((row - fs->min_byte1) * \ + (fs->max_char_or_byte2 - \ + fs->min_char_or_byte2 + 1)) + \ + (col - fs->min_char_or_byte2)]; \ + if (CI_NONEXISTCHAR(cs)) cs = def; \ + } \ + } \ +} + +#define CI_GET_DEFAULT_INFO_2D(fs,cs) \ +{ \ + unsigned int r = (fs->default_char >> 8); \ + unsigned int c = (fs->default_char & 0xff); \ + CI_GET_CHAR_INFO_2D (fs, r, c, NULL, cs); \ +} + + +/* srcvar must be a variable for large architecture version */ +#define OneDataCard32(dpy,dstaddr,srcvar) \ + { *(CARD32 *)(dstaddr) = (srcvar); } + + +typedef struct _XInternalAsync { + struct _XInternalAsync *next; + /* + * handler arguments: + * rep is the generic reply that caused this handler + * to be invoked. It must also be passed to _XGetAsyncReply. + * buf and len are opaque values that must be passed to + * _XGetAsyncReply or _XGetAsyncData. + * data is the closure stored in this struct. + * The handler returns True iff it handled this reply. + */ + Bool (*handler)( + Display* /* dpy */, + xReply* /* rep */, + char* /* buf */, + int /* len */, + XPointer /* data */ + ); + XPointer data; +} _XAsyncHandler; + +/* + * This struct is part of the ABI and is defined by value + * in user-code. This means that we cannot make + * the sequence-numbers 64bit. + */ +typedef struct _XAsyncEState { + unsigned long min_sequence_number; + unsigned long max_sequence_number; + unsigned char error_code; + unsigned char major_opcode; + unsigned short minor_opcode; + unsigned char last_error_received; + int error_count; +} _XAsyncErrorState; + +extern void _XDeqAsyncHandler(Display *dpy, _XAsyncHandler *handler); +#define DeqAsyncHandler(dpy,handler) { \ + if (dpy->async_handlers == (handler)) \ + dpy->async_handlers = (handler)->next; \ + else \ + _XDeqAsyncHandler(dpy, handler); \ + } + +typedef void (*FreeFuncType) ( + Display* /* display */ +); + +typedef int (*FreeModmapType) ( + XModifierKeymap* /* modmap */ +); + +/* + * This structure is private to the library. + */ +typedef struct _XFreeFuncs { + FreeFuncType atoms; /* _XFreeAtomTable */ + FreeModmapType modifiermap; /* XFreeModifiermap */ + FreeFuncType key_bindings; /* _XFreeKeyBindings */ + FreeFuncType context_db; /* _XFreeContextDB */ + FreeFuncType defaultCCCs; /* _XcmsFreeDefaultCCCs */ + FreeFuncType clientCmaps; /* _XcmsFreeClientCmaps */ + FreeFuncType intensityMaps; /* _XcmsFreeIntensityMaps */ + FreeFuncType im_filters; /* _XFreeIMFilters */ + FreeFuncType xkb; /* _XkbFreeInfo */ +} _XFreeFuncRec; + +/* types for InitExt.c */ +typedef int (*CreateGCType) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +); + +typedef int (*CopyGCType)( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +); + +typedef int (*FlushGCType) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +); + +typedef int (*FreeGCType) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +); + +typedef int (*CreateFontType) ( + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +); + +typedef int (*FreeFontType) ( + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +); + +typedef int (*CloseDisplayType) ( + Display* /* display */, + XExtCodes* /* codes */ +); + +typedef int (*ErrorType) ( + Display* /* display */, + xError* /* err */, + XExtCodes* /* codes */, + int* /* ret_code */ +); + +typedef char* (*ErrorStringType) ( + Display* /* display */, + int /* code */, + XExtCodes* /* codes */, + char* /* buffer */, + int /* nbytes */ +); + +typedef void (*PrintErrorType)( + Display* /* display */, + XErrorEvent* /* ev */, + void* /* fp */ +); + +typedef void (*BeforeFlushType)( + Display* /* display */, + XExtCodes* /* codes */, + _Xconst char* /* data */, + long /* len */ +); + +/* + * This structure is private to the library. + */ +typedef struct _XExten { /* private to extension mechanism */ + struct _XExten *next; /* next in list */ + XExtCodes codes; /* public information, all extension told */ + CreateGCType create_GC; /* routine to call when GC created */ + CopyGCType copy_GC; /* routine to call when GC copied */ + FlushGCType flush_GC; /* routine to call when GC flushed */ + FreeGCType free_GC; /* routine to call when GC freed */ + CreateFontType create_Font; /* routine to call when Font created */ + FreeFontType free_Font; /* routine to call when Font freed */ + CloseDisplayType close_display; /* routine to call when connection closed */ + ErrorType error; /* who to call when an error occurs */ + ErrorStringType error_string; /* routine to supply error string */ + char *name; /* name of this extension */ + PrintErrorType error_values; /* routine to supply error values */ + BeforeFlushType before_flush; /* routine to call when sending data */ + struct _XExten *next_flush; /* next in list of those with flushes */ +} _XExtension; + +/* extension hooks */ + +#ifdef DataRoutineIsProcedure +extern void Data(Display *dpy, char *data, long len); +#endif +extern int _XError( + Display* /* dpy */, + xError* /* rep */ +); +extern int _XIOError( + Display* /* dpy */ +); +extern int (*_XIOErrorFunction)( + Display* /* dpy */ +); +extern int (*_XErrorFunction)( + Display* /* dpy */, + XErrorEvent* /* error_event */ +); +extern void _XEatData( + Display* /* dpy */, + unsigned long /* n */ +) _X_COLD; +extern void _XEatDataWords( + Display* /* dpy */, + unsigned long /* n */ +) _X_COLD; +#if defined(__SUNPRO_C) /* Studio compiler alternative to "cold" attribute */ +# pragma rarely_called(_XEatData, _XEatDataWords) +#endif +extern char *_XAllocScratch( + Display* /* dpy */, + unsigned long /* nbytes */ +); +extern char *_XAllocTemp( + Display* /* dpy */, + unsigned long /* nbytes */ +); +extern void _XFreeTemp( + Display* /* dpy */, + char* /* buf */, + unsigned long /* nbytes */ +); +extern Visual *_XVIDtoVisual( + Display* /* dpy */, + VisualID /* id */ +); +extern unsigned long _XSetLastRequestRead( + Display* /* dpy */, + xGenericReply* /* rep */ +); +extern int _XGetHostname( + char* /* buf */, + int /* maxlen */ +); +extern Screen *_XScreenOfWindow( + Display* /* dpy */, + Window /* w */ +); +extern Bool _XAsyncErrorHandler( + Display* /* dpy */, + xReply* /* rep */, + char* /* buf */, + int /* len */, + XPointer /* data */ +); +extern char *_XGetAsyncReply( + Display* /* dpy */, + char* /* replbuf */, + xReply* /* rep */, + char* /* buf */, + int /* len */, + int /* extra */, + Bool /* discard */ +); +extern void _XGetAsyncData( + Display* /* dpy */, + char * /* data */, + char * /* buf */, + int /* len */, + int /* skip */, + int /* datalen */, + int /* discardtotal */ +); +extern void _XFlush( + Display* /* dpy */ +); +extern int _XEventsQueued( + Display* /* dpy */, + int /* mode */ +); +extern void _XReadEvents( + Display* /* dpy */ +); +extern int _XRead( + Display* /* dpy */, + char* /* data */, + long /* size */ +); +extern void _XReadPad( + Display* /* dpy */, + char* /* data */, + long /* size */ +); +extern void _XSend( + Display* /* dpy */, + _Xconst char* /* data */, + long /* size */ +); +extern Status _XReply( + Display* /* dpy */, + xReply* /* rep */, + int /* extra */, + Bool /* discard */ +); +extern void _XEnq( + Display* /* dpy */, + xEvent* /* event */ +); +extern void _XDeq( + Display* /* dpy */, + _XQEvent* /* prev */, + _XQEvent* /* qelt */ +); + +extern Bool _XUnknownWireEvent( + Display* /* dpy */, + XEvent* /* re */, + xEvent* /* event */ +); + +extern Bool _XUnknownWireEventCookie( + Display* /* dpy */, + XGenericEventCookie* /* re */, + xEvent* /* event */ +); + +extern Bool _XUnknownCopyEventCookie( + Display* /* dpy */, + XGenericEventCookie* /* in */, + XGenericEventCookie* /* out */ +); + +extern Status _XUnknownNativeEvent( + Display* /* dpy */, + XEvent* /* re */, + xEvent* /* event */ +); + +extern Bool _XWireToEvent(Display *dpy, XEvent *re, xEvent *event); +extern Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we); +extern Bool _XPollfdCacheInit(Display *dpy); +extern void _XPollfdCacheAdd(Display *dpy, int fd); +extern void _XPollfdCacheDel(Display *dpy, int fd); +extern XID _XAllocID(Display *dpy); +extern void _XAllocIDs(Display *dpy, XID *ids, int count); + +extern int _XFreeExtData( + XExtData* /* extension */ +); + +extern int (*XESetCreateGC( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, GC, XExtCodes* +); + +extern int (*XESetCopyGC( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, GC, XExtCodes* +); + +extern int (*XESetFlushGC( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, GC, XExtCodes* +); + +extern int (*XESetFreeGC( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, GC, XExtCodes* +); + +extern int (*XESetCreateFont( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, XFontStruct*, XExtCodes* +); + +extern int (*XESetFreeFont( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, XFontStruct*, XExtCodes* +); + +extern int (*XESetCloseDisplay( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + XExtCodes* /* codes */ + ) /* proc */ +))( + Display*, XExtCodes* +); + +extern int (*XESetError( + Display* /* display */, + int /* extension */, + int (*) ( + Display* /* display */, + xError* /* err */, + XExtCodes* /* codes */, + int* /* ret_code */ + ) /* proc */ +))( + Display*, xError*, XExtCodes*, int* +); + +extern char* (*XESetErrorString( + Display* /* display */, + int /* extension */, + char* (*) ( + Display* /* display */, + int /* code */, + XExtCodes* /* codes */, + char* /* buffer */, + int /* nbytes */ + ) /* proc */ +))( + Display*, int, XExtCodes*, char*, int +); + +extern void (*XESetPrintErrorValues ( + Display* /* display */, + int /* extension */, + void (*)( + Display* /* display */, + XErrorEvent* /* ev */, + void* /* fp */ + ) /* proc */ +))( + Display*, XErrorEvent*, void* +); + +extern Bool (*XESetWireToEvent( + Display* /* display */, + int /* event_number */, + Bool (*) ( + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ + ) /* proc */ +))( + Display*, XEvent*, xEvent* +); + +extern Bool (*XESetWireToEventCookie( + Display* /* display */, + int /* extension */, + Bool (*) ( + Display* /* display */, + XGenericEventCookie* /* re */, + xEvent* /* event */ + ) /* proc */ +))( + Display*, XGenericEventCookie*, xEvent* +); + +extern Bool (*XESetCopyEventCookie( + Display* /* display */, + int /* extension */, + Bool (*) ( + Display* /* display */, + XGenericEventCookie* /* in */, + XGenericEventCookie* /* out */ + ) /* proc */ +))( + Display*, XGenericEventCookie*, XGenericEventCookie* +); + + +extern Status (*XESetEventToWire( + Display* /* display */, + int /* event_number */, + Status (*) ( + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ + ) /* proc */ +))( + Display*, XEvent*, xEvent* +); + +extern Bool (*XESetWireToError( + Display* /* display */, + int /* error_number */, + Bool (*) ( + Display* /* display */, + XErrorEvent* /* he */, + xError* /* we */ + ) /* proc */ +))( + Display*, XErrorEvent*, xError* +); + +extern void (*XESetBeforeFlush( + Display* /* display */, + int /* error_number */, + void (*) ( + Display* /* display */, + XExtCodes* /* codes */, + _Xconst char* /* data */, + long /* len */ + ) /* proc */ +))( + Display*, XExtCodes*, _Xconst char*, long +); + +/* internal connections for IMs */ + +typedef void (*_XInternalConnectionProc)( + Display* /* dpy */, + int /* fd */, + XPointer /* call_data */ +); + + +extern Status _XRegisterInternalConnection( + Display* /* dpy */, + int /* fd */, + _XInternalConnectionProc /* callback */, + XPointer /* call_data */ +); + +extern void _XUnregisterInternalConnection( + Display* /* dpy */, + int /* fd */ +); + +extern void _XProcessInternalConnection( + Display* /* dpy */, + struct _XConnectionInfo* /* conn_info */ +); + +/* Display structure has pointers to these */ + +struct _XConnectionInfo { /* info from _XRegisterInternalConnection */ + int fd; + _XInternalConnectionProc read_callback; + XPointer call_data; + XPointer *watch_data; /* set/used by XConnectionWatchProc */ + struct _XConnectionInfo *next; +}; + +struct _XConnWatchInfo { /* info from XAddConnectionWatch */ + XConnectionWatchProc fn; + XPointer client_data; + struct _XConnWatchInfo *next; +}; + +#ifdef __UNIXOS2__ +extern char* __XOS2RedirRoot( + char* +); +#endif + +extern int _XTextHeight( + XFontStruct* /* font_struct */, + _Xconst char* /* string */, + int /* count */ +); + +extern int _XTextHeight16( + XFontStruct* /* font_struct */, + _Xconst XChar2b* /* string */, + int /* count */ +); + +#if defined(WIN32) + +extern int _XOpenFile( + _Xconst char* /* path */, + int /* flags */ +); + +extern int _XOpenFileMode( + _Xconst char* /* path */, + int /* flags */, + mode_t /* mode */ +); + +extern void* _XFopenFile( + _Xconst char* /* path */, + _Xconst char* /* mode */ +); + +extern int _XAccessFile( + _Xconst char* /* path */ +); +#else +#define _XOpenFile(path,flags) open(path,flags) +#define _XOpenFileMode(path,flags,mode) open(path,flags,mode) +#define _XFopenFile(path,mode) fopen(path,mode) +#endif + +/* EvToWire.c */ +extern Status _XEventToWire(Display *dpy, XEvent *re, xEvent *event); + +extern int _XF86LoadQueryLocaleFont( + Display* /* dpy */, + _Xconst char* /* name*/, + XFontStruct** /* xfp*/, + Font* /* fidp */ +); + +extern void _XProcessWindowAttributes ( + Display *dpy, + xChangeWindowAttributesReq *req, + unsigned long valuemask, + XSetWindowAttributes *attributes); + +extern int _XDefaultError( + Display *dpy, + XErrorEvent *event); + +extern int _XDefaultIOError( + Display *dpy); + +extern void _XDefaultIOErrorExit( + Display *dpy, + void *user_data); + +extern void _XSetClipRectangles ( + Display *dpy, + GC gc, + int clip_x_origin, int clip_y_origin, + XRectangle *rectangles, + int n, + int ordering); + +Status _XGetWindowAttributes( + Display *dpy, + Window w, + XWindowAttributes *attr); + +int _XPutBackEvent ( + Display *dpy, + XEvent *event); + +extern Bool _XIsEventCookie( + Display *dpy, + XEvent *ev); + +extern void _XFreeEventCookies( + Display *dpy); + +extern void _XStoreEventCookie( + Display *dpy, + XEvent *ev); + +extern Bool _XFetchEventCookie( + Display *dpy, + XGenericEventCookie *ev); + +extern Bool _XCopyEventCookie( + Display *dpy, + XGenericEventCookie *in, + XGenericEventCookie *out); + +/* lcFile.c */ + +extern void xlocaledir( + char *buf, + int buf_len +); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +_XFUNCPROTOEND + +#endif /* _X11_XLIBINT_H_ */ diff --git a/packages/games/tools/axe11/X11/Xlocale.h b/packages/games/tools/axe11/X11/Xlocale.h new file mode 100644 index 000000000..db46e70cb --- /dev/null +++ b/packages/games/tools/axe11/X11/Xlocale.h @@ -0,0 +1,37 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef _X11_XLOCALE_H_ +#define _X11_XLOCALE_H_ + +#include +#include + +#include + +#endif /* _X11_XLOCALE_H_ */ diff --git a/packages/games/tools/axe11/X11/Xregion.h b/packages/games/tools/axe11/X11/Xregion.h new file mode 100644 index 000000000..cf10f86df --- /dev/null +++ b/packages/games/tools/axe11/X11/Xregion.h @@ -0,0 +1,190 @@ +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +#ifndef _X11_XREGION_H_ +#define _X11_XREGION_H_ + +typedef struct { + short x1, x2, y1, y2; +} Box, BOX, BoxRec, *BoxPtr; + +typedef struct { + short x, y, width, height; +}RECTANGLE, RectangleRec, *RectanglePtr; + +#define TRUE 1 +#define FALSE 0 +#define MAXSHORT 32767 +#define MINSHORT -MAXSHORT +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +/* + * clip region + */ + +typedef struct _XRegion { + long size; + long numRects; + BOX *rects; + BOX extents; +} REGION; + +/* Xutil.h contains the declaration: + * typedef struct _XRegion *Region; + */ + +/* 1 if two BOXs overlap. + * 0 if two BOXs do not overlap. + * Remember, x2 and y2 are not in the region + */ +#define EXTENTCHECK(r1, r2) \ + ((r1)->x2 > (r2)->x1 && \ + (r1)->x1 < (r2)->x2 && \ + (r1)->y2 > (r2)->y1 && \ + (r1)->y1 < (r2)->y2) + +/* + * update region extents + */ +#define EXTENTS(r,idRect){\ + if((r)->x1 < (idRect)->extents.x1)\ + (idRect)->extents.x1 = (r)->x1;\ + if((r)->y1 < (idRect)->extents.y1)\ + (idRect)->extents.y1 = (r)->y1;\ + if((r)->x2 > (idRect)->extents.x2)\ + (idRect)->extents.x2 = (r)->x2;\ + if((r)->y2 > (idRect)->extents.y2)\ + (idRect)->extents.y2 = (r)->y2;\ + } + +/* + * Check to see if there is enough memory in the present region. + */ +#define MEMCHECK(reg, rect, firstrect){\ + if ((reg)->numRects >= ((reg)->size - 1)){\ + BoxPtr tmpRect = Xrealloc ((firstrect), \ + (2 * (sizeof(BOX)) * ((reg)->size))); \ + if (tmpRect == NULL) \ + return(0);\ + (firstrect) = tmpRect; \ + (reg)->size *= 2;\ + (rect) = &(firstrect)[(reg)->numRects];\ + }\ + } + +/* this routine checks to see if the previous rectangle is the same + * or subsumes the new rectangle to add. + */ + +#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ + (!(((Reg)->numRects > 0)&&\ + ((R-1)->y1 == (Ry1)) &&\ + ((R-1)->y2 == (Ry2)) &&\ + ((R-1)->x1 <= (Rx1)) &&\ + ((R-1)->x2 >= (Rx2)))) + +/* add a rectangle to the given Region */ +#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ + if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + EXTENTS((r), (reg));\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + + + +/* add a rectangle to the given Region */ +#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ + if ((rx1 < rx2) && (ry1 < ry2) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + +#define EMPTY_REGION(pReg) pReg->numRects = 0 + +#define REGION_NOT_EMPTY(pReg) pReg->numRects + +#define INBOX(r, x, y) \ + ( ( ((r).x2 > x)) && \ + ( ((r).x1 <= x)) && \ + ( ((r).y2 > y)) && \ + ( ((r).y1 <= y)) ) + +/* + * number of points to buffer before sending them off + * to scanlines() : Must be an even number + */ +#define NUMPTSTOBUFFER 200 + +/* + * used to allocate buffers for points and link + * the buffers together + */ +typedef struct _POINTBLOCK { + XPoint pts[NUMPTSTOBUFFER]; + struct _POINTBLOCK *next; +} POINTBLOCK; + +#endif /* _X11_XREGION_H_ */ diff --git a/packages/games/tools/axe11/X11/Xresource.h b/packages/games/tools/axe11/X11/Xresource.h new file mode 100644 index 000000000..6dbb3ce46 --- /dev/null +++ b/packages/games/tools/axe11/X11/Xresource.h @@ -0,0 +1,358 @@ + +/*********************************************************** + +Copyright 1987, 1988, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _X11_XRESOURCE_H_ +#define _X11_XRESOURCE_H_ + +#ifndef _XP_PRINT_SERVER_ +#include +#endif + +/**************************************************************** + **************************************************************** + *** *** + *** *** + *** X Resource Manager Intrinsics *** + *** *** + *** *** + **************************************************************** + ****************************************************************/ + +_XFUNCPROTOBEGIN + +/**************************************************************** + * + * Memory Management + * + ****************************************************************/ + +extern char *Xpermalloc( + unsigned int /* size */ +); + +/**************************************************************** + * + * Quark Management + * + ****************************************************************/ + +typedef int XrmQuark, *XrmQuarkList; +#define NULLQUARK ((XrmQuark) 0) + +typedef char *XrmString; +#define NULLSTRING ((XrmString) 0) + +/* find quark for string, create new quark if none already exists */ +extern XrmQuark XrmStringToQuark( + _Xconst char* /* string */ +); + +extern XrmQuark XrmPermStringToQuark( + _Xconst char* /* string */ +); + +/* find string for quark */ +extern XrmString XrmQuarkToString( + XrmQuark /* quark */ +); + +extern XrmQuark XrmUniqueQuark( + void +); + +#define XrmStringsEqual(a1, a2) (strcmp(a1, a2) == 0) + + +/**************************************************************** + * + * Conversion of Strings to Lists + * + ****************************************************************/ + +typedef enum {XrmBindTightly, XrmBindLoosely} XrmBinding, *XrmBindingList; + +extern void XrmStringToQuarkList( + _Xconst char* /* string */, + XrmQuarkList /* quarks_return */ +); + +extern void XrmStringToBindingQuarkList( + _Xconst char* /* string */, + XrmBindingList /* bindings_return */, + XrmQuarkList /* quarks_return */ +); + +/**************************************************************** + * + * Name and Class lists. + * + ****************************************************************/ + +typedef XrmQuark XrmName; +typedef XrmQuarkList XrmNameList; +#define XrmNameToString(name) XrmQuarkToString(name) +#define XrmStringToName(string) XrmStringToQuark(string) +#define XrmStringToNameList(str, name) XrmStringToQuarkList(str, name) + +typedef XrmQuark XrmClass; +typedef XrmQuarkList XrmClassList; +#define XrmClassToString(c_class) XrmQuarkToString(c_class) +#define XrmStringToClass(c_class) XrmStringToQuark(c_class) +#define XrmStringToClassList(str,c_class) XrmStringToQuarkList(str, c_class) + + + +/**************************************************************** + * + * Resource Representation Types and Values + * + ****************************************************************/ + +typedef XrmQuark XrmRepresentation; +#define XrmStringToRepresentation(string) XrmStringToQuark(string) +#define XrmRepresentationToString(type) XrmQuarkToString(type) + +typedef struct { + unsigned int size; + XPointer addr; +} XrmValue, *XrmValuePtr; + + +/**************************************************************** + * + * Resource Manager Functions + * + ****************************************************************/ + +typedef struct _XrmHashBucketRec *XrmHashBucket; +typedef XrmHashBucket *XrmHashTable; +typedef XrmHashTable XrmSearchList[]; +typedef struct _XrmHashBucketRec *XrmDatabase; + + +extern void XrmDestroyDatabase( + XrmDatabase /* database */ +); + +extern void XrmQPutResource( + XrmDatabase* /* database */, + XrmBindingList /* bindings */, + XrmQuarkList /* quarks */, + XrmRepresentation /* type */, + XrmValue* /* value */ +); + +extern void XrmPutResource( + XrmDatabase* /* database */, + _Xconst char* /* specifier */, + _Xconst char* /* type */, + XrmValue* /* value */ +); + +extern void XrmQPutStringResource( + XrmDatabase* /* database */, + XrmBindingList /* bindings */, + XrmQuarkList /* quarks */, + _Xconst char* /* value */ +); + +extern void XrmPutStringResource( + XrmDatabase* /* database */, + _Xconst char* /* specifier */, + _Xconst char* /* value */ +); + +extern void XrmPutLineResource( + XrmDatabase* /* database */, + _Xconst char* /* line */ +); + +extern Bool XrmQGetResource( + XrmDatabase /* database */, + XrmNameList /* quark_name */, + XrmClassList /* quark_class */, + XrmRepresentation* /* quark_type_return */, + XrmValue* /* value_return */ +); + +extern Bool XrmGetResource( + XrmDatabase /* database */, + _Xconst char* /* str_name */, + _Xconst char* /* str_class */, + char** /* str_type_return */, + XrmValue* /* value_return */ +); + +extern Bool XrmQGetSearchList( + XrmDatabase /* database */, + XrmNameList /* names */, + XrmClassList /* classes */, + XrmSearchList /* list_return */, + int /* list_length */ +); + +extern Bool XrmQGetSearchResource( + XrmSearchList /* list */, + XrmName /* name */, + XrmClass /* class */, + XrmRepresentation* /* type_return */, + XrmValue* /* value_return */ +); + +/**************************************************************** + * + * Resource Database Management + * + ****************************************************************/ + +#ifndef _XP_PRINT_SERVER_ + +extern void XrmSetDatabase( + Display* /* display */, + XrmDatabase /* database */ +); + +extern XrmDatabase XrmGetDatabase( + Display* /* display */ +); + +#endif /* !_XP_PRINT_SERVER_ */ + +extern XrmDatabase XrmGetFileDatabase( + _Xconst char* /* filename */ +); + +extern Status XrmCombineFileDatabase( + _Xconst char* /* filename */, + XrmDatabase* /* target */, + Bool /* override */ +); + +extern XrmDatabase XrmGetStringDatabase( + _Xconst char* /* data */ /* null terminated string */ +); + +extern void XrmPutFileDatabase( + XrmDatabase /* database */, + _Xconst char* /* filename */ +); + +extern void XrmMergeDatabases( + XrmDatabase /* source_db */, + XrmDatabase* /* target_db */ +); + +extern void XrmCombineDatabase( + XrmDatabase /* source_db */, + XrmDatabase* /* target_db */, + Bool /* override */ +); + +#define XrmEnumAllLevels 0 +#define XrmEnumOneLevel 1 + +extern Bool XrmEnumerateDatabase( + XrmDatabase /* db */, + XrmNameList /* name_prefix */, + XrmClassList /* class_prefix */, + int /* mode */, + Bool (*)( + XrmDatabase* /* db */, + XrmBindingList /* bindings */, + XrmQuarkList /* quarks */, + XrmRepresentation* /* type */, + XrmValue* /* value */, + XPointer /* closure */ + ) /* proc */, + XPointer /* closure */ +); + +extern const char *XrmLocaleOfDatabase( + XrmDatabase /* database */ +); + + +/**************************************************************** + * + * Command line option mapping to resource entries + * + ****************************************************************/ + +typedef enum { + XrmoptionNoArg, /* Value is specified in OptionDescRec.value */ + XrmoptionIsArg, /* Value is the option string itself */ + XrmoptionStickyArg, /* Value is characters immediately following option */ + XrmoptionSepArg, /* Value is next argument in argv */ + XrmoptionResArg, /* Resource and value in next argument in argv */ + XrmoptionSkipArg, /* Ignore this option and the next argument in argv */ + XrmoptionSkipLine, /* Ignore this option and the rest of argv */ + XrmoptionSkipNArgs /* Ignore this option and the next + OptionDescRes.value arguments in argv */ +} XrmOptionKind; + +typedef struct { + char *option; /* Option abbreviation in argv */ + char *specifier; /* Resource specifier */ + XrmOptionKind argKind; /* Which style of option it is */ + XPointer value; /* Value to provide if XrmoptionNoArg */ +} XrmOptionDescRec, *XrmOptionDescList; + + +extern void XrmParseCommand( + XrmDatabase* /* database */, + XrmOptionDescList /* table */, + int /* table_count */, + _Xconst char* /* name */, + int* /* argc_in_out */, + char** /* argv_in_out */ +); + +_XFUNCPROTOEND + +#endif /* _X11_XRESOURCE_H_ */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/packages/games/tools/axe11/X11/Xutil.h b/packages/games/tools/axe11/X11/Xutil.h new file mode 100644 index 000000000..62cdf5556 --- /dev/null +++ b/packages/games/tools/axe11/X11/Xutil.h @@ -0,0 +1,838 @@ + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _X11_XUTIL_H_ +#define _X11_XUTIL_H_ + +/* You must include before including this file */ +#include +#include + +/* The Xlib structs are full of implicit padding to properly align members. + We can't clean that up without breaking ABI, so tell clang not to bother + complaining about it. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +/* + * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding + * value (x, y, width, height) was found in the parsed string. + */ +#define NoValue 0x0000 +#define XValue 0x0001 +#define YValue 0x0002 +#define WidthValue 0x0004 +#define HeightValue 0x0008 +#define AllValues 0x000F +#define XNegative 0x0010 +#define YNegative 0x0020 + +/* + * new version containing base_width, base_height, and win_gravity fields; + * used with WM_NORMAL_HINTS. + */ +typedef struct { + long flags; /* marks which fields in this structure are defined */ + int x, y; /* obsolete for new window mgrs, but clients */ + int width, height; /* should set so old wm's don't mess up */ + int min_width, min_height; + int max_width, max_height; + int width_inc, height_inc; + struct { + int x; /* numerator */ + int y; /* denominator */ + } min_aspect, max_aspect; + int base_width, base_height; /* added by ICCCM version 1 */ + int win_gravity; /* added by ICCCM version 1 */ +} XSizeHints; + +/* + * The next block of definitions are for window manager properties that + * clients and applications use for communication. + */ + +/* flags argument in size hints */ +#define USPosition (1L << 0) /* user specified x, y */ +#define USSize (1L << 1) /* user specified width, height */ + +#define PPosition (1L << 2) /* program specified position */ +#define PSize (1L << 3) /* program specified size */ +#define PMinSize (1L << 4) /* program specified minimum size */ +#define PMaxSize (1L << 5) /* program specified maximum size */ +#define PResizeInc (1L << 6) /* program specified resize increments */ +#define PAspect (1L << 7) /* program specified min and max aspect ratios */ +#define PBaseSize (1L << 8) /* program specified base for incrementing */ +#define PWinGravity (1L << 9) /* program specified window gravity */ + +/* obsolete */ +#define PAllHints (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect) + + + +typedef struct { + long flags; /* marks which fields in this structure are defined */ + Bool input; /* does this application rely on the window manager to + get keyboard input? */ + int initial_state; /* see below */ + Pixmap icon_pixmap; /* pixmap to be used as icon */ + Window icon_window; /* window to be used as icon */ + int icon_x, icon_y; /* initial position of icon */ + Pixmap icon_mask; /* icon mask bitmap */ + XID window_group; /* id of related window group */ + /* this structure may be extended in the future */ +} XWMHints; + +/* definition for flags of XWMHints */ + +#define InputHint (1L << 0) +#define StateHint (1L << 1) +#define IconPixmapHint (1L << 2) +#define IconWindowHint (1L << 3) +#define IconPositionHint (1L << 4) +#define IconMaskHint (1L << 5) +#define WindowGroupHint (1L << 6) +#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint| \ +IconPositionHint|IconMaskHint|WindowGroupHint) +#define XUrgencyHint (1L << 8) + +/* definitions for initial window state */ +#define WithdrawnState 0 /* for windows that are not mapped */ +#define NormalState 1 /* most applications want to start this way */ +#define IconicState 3 /* application wants to start as an icon */ + +/* + * Obsolete states no longer defined by ICCCM + */ +#define DontCareState 0 /* don't know or care */ +#define ZoomState 2 /* application wants to start zoomed */ +#define InactiveState 4 /* application believes it is seldom used; */ + /* some wm's may put it on inactive menu */ + + +/* + * new structure for manipulating TEXT properties; used with WM_NAME, + * WM_ICON_NAME, WM_CLIENT_MACHINE, and WM_COMMAND. + */ +typedef struct { + unsigned char *value; /* same as Property routines */ + Atom encoding; /* prop type */ + int format; /* prop data format: 8, 16, or 32 */ + unsigned long nitems; /* number of data items in value */ +} XTextProperty; + +#define XNoMemory -1 +#define XLocaleNotSupported -2 +#define XConverterNotFound -3 + +typedef enum { + XStringStyle, /* STRING */ + XCompoundTextStyle, /* COMPOUND_TEXT */ + XTextStyle, /* text in owner's encoding (current locale)*/ + XStdICCTextStyle, /* STRING, else COMPOUND_TEXT */ + /* The following is an XFree86 extension, introduced in November 2000 */ + XUTF8StringStyle /* UTF8_STRING */ +} XICCEncodingStyle; + +typedef struct { + int min_width, min_height; + int max_width, max_height; + int width_inc, height_inc; +} XIconSize; + +typedef struct { + char *res_name; + char *res_class; +} XClassHint; + +#ifdef XUTIL_DEFINE_FUNCTIONS +extern int XDestroyImage( + XImage *ximage); +extern unsigned long XGetPixel( + XImage *ximage, + int x, int y); +extern int XPutPixel( + XImage *ximage, + int x, int y, + unsigned long pixel); +extern XImage *XSubImage( + XImage *ximage, + int x, int y, + unsigned int width, unsigned int height); +extern int XAddPixel( + XImage *ximage, + long value); +#else +/* + * These macros are used to give some sugar to the image routines so that + * naive people are more comfortable with them. + */ +#define XDestroyImage(ximage) \ + ((*((ximage)->f.destroy_image))((ximage))) +#define XGetPixel(ximage, x, y) \ + ((*((ximage)->f.get_pixel))((ximage), (x), (y))) +#define XPutPixel(ximage, x, y, pixel) \ + ((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))) +#define XSubImage(ximage, x, y, width, height) \ + ((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height))) +#define XAddPixel(ximage, value) \ + ((*((ximage)->f.add_pixel))((ximage), (value))) +#endif + +/* + * Compose sequence status structure, used in calling XLookupString. + */ +typedef struct _XComposeStatus { + XPointer compose_ptr; /* state table pointer */ + int chars_matched; /* match state */ +} XComposeStatus; + +/* + * Keysym macros, used on Keysyms to test for classes of symbols + */ +#define IsKeypadKey(keysym) \ + (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal)) + +#define IsPrivateKeypadKey(keysym) \ + (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF)) + +#define IsCursorKey(keysym) \ + (((KeySym)(keysym) >= XK_Home) && ((KeySym)(keysym) < XK_Select)) + +#define IsPFKey(keysym) \ + (((KeySym)(keysym) >= XK_KP_F1) && ((KeySym)(keysym) <= XK_KP_F4)) + +#define IsFunctionKey(keysym) \ + (((KeySym)(keysym) >= XK_F1) && ((KeySym)(keysym) <= XK_F35)) + +#define IsMiscFunctionKey(keysym) \ + (((KeySym)(keysym) >= XK_Select) && ((KeySym)(keysym) <= XK_Break)) + +#ifdef XK_XKB_KEYS +#define IsModifierKey(keysym) \ + ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \ + || (((KeySym)(keysym) >= XK_ISO_Lock) && \ + ((KeySym)(keysym) <= XK_ISO_Level5_Lock)) \ + || ((KeySym)(keysym) == XK_Mode_switch) \ + || ((KeySym)(keysym) == XK_Num_Lock)) +#else +#define IsModifierKey(keysym) \ + ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \ + || ((KeySym)(keysym) == XK_Mode_switch) \ + || ((KeySym)(keysym) == XK_Num_Lock)) +#endif +/* + * opaque reference to Region data type + */ +typedef struct _XRegion *Region; + +/* Return values from XRectInRegion() */ + +#define RectangleOut 0 +#define RectangleIn 1 +#define RectanglePart 2 + + +/* + * Information used by the visual utility routines to find desired visual + * type from the many visuals a display may support. + */ + +typedef struct { + Visual *visual; + VisualID visualid; + int screen; + int depth; +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ */ +#else + int class; +#endif + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int colormap_size; + int bits_per_rgb; +} XVisualInfo; + +#define VisualNoMask 0x0 +#define VisualIDMask 0x1 +#define VisualScreenMask 0x2 +#define VisualDepthMask 0x4 +#define VisualClassMask 0x8 +#define VisualRedMaskMask 0x10 +#define VisualGreenMaskMask 0x20 +#define VisualBlueMaskMask 0x40 +#define VisualColormapSizeMask 0x80 +#define VisualBitsPerRGBMask 0x100 +#define VisualAllMask 0x1FF + +/* + * This defines a window manager property that clients may use to + * share standard color maps of type RGB_COLOR_MAP: + */ +typedef struct { + Colormap colormap; + unsigned long red_max; + unsigned long red_mult; + unsigned long green_max; + unsigned long green_mult; + unsigned long blue_max; + unsigned long blue_mult; + unsigned long base_pixel; + VisualID visualid; /* added by ICCCM version 1 */ + XID killid; /* added by ICCCM version 1 */ +} XStandardColormap; + +#define ReleaseByFreeingColormap ((XID) 1L) /* for killid field above */ + + +/* + * return codes for XReadBitmapFile and XWriteBitmapFile + */ +#define BitmapSuccess 0 +#define BitmapOpenFailed 1 +#define BitmapFileInvalid 2 +#define BitmapNoMemory 3 + +/**************************************************************** + * + * Context Management + * + ****************************************************************/ + + +/* Associative lookup table return codes */ + +#define XCSUCCESS 0 /* No error. */ +#define XCNOMEM 1 /* Out of memory */ +#define XCNOENT 2 /* No entry in table */ + +typedef int XContext; + +#define XUniqueContext() ((XContext) XrmUniqueQuark()) +#define XStringToContext(string) ((XContext) XrmStringToQuark(string)) + +_XFUNCPROTOBEGIN + +/* The following declarations are alphabetized. */ + +extern XClassHint *XAllocClassHint ( + void +); + +extern XIconSize *XAllocIconSize ( + void +); + +extern XSizeHints *XAllocSizeHints ( + void +); + +extern XStandardColormap *XAllocStandardColormap ( + void +); + +extern XWMHints *XAllocWMHints ( + void +); + +extern int XClipBox( + Region /* r */, + XRectangle* /* rect_return */ +); + +extern Region XCreateRegion( + void +); + +extern const char *XDefaultString (void); + +extern int XDeleteContext( + Display* /* display */, + XID /* rid */, + XContext /* context */ +); + +extern int XDestroyRegion( + Region /* r */ +); + +extern int XEmptyRegion( + Region /* r */ +); + +extern int XEqualRegion( + Region /* r1 */, + Region /* r2 */ +); + +extern int XFindContext( + Display* /* display */, + XID /* rid */, + XContext /* context */, + XPointer* /* data_return */ +); + +extern Status XGetClassHint( + Display* /* display */, + Window /* w */, + XClassHint* /* class_hints_return */ +); + +extern Status XGetIconSizes( + Display* /* display */, + Window /* w */, + XIconSize** /* size_list_return */, + int* /* count_return */ +); + +extern Status XGetNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */ +); + +extern Status XGetRGBColormaps( + Display* /* display */, + Window /* w */, + XStandardColormap** /* stdcmap_return */, + int* /* count_return */, + Atom /* property */ +); + +extern Status XGetSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + Atom /* property */ +); + +extern Status XGetStandardColormap( + Display* /* display */, + Window /* w */, + XStandardColormap* /* colormap_return */, + Atom /* property */ +); + +extern Status XGetTextProperty( + Display* /* display */, + Window /* window */, + XTextProperty* /* text_prop_return */, + Atom /* property */ +); + +extern XVisualInfo *XGetVisualInfo( + Display* /* display */, + long /* vinfo_mask */, + XVisualInfo* /* vinfo_template */, + int* /* nitems_return */ +); + +extern Status XGetWMClientMachine( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern XWMHints *XGetWMHints( + Display* /* display */, + Window /* w */ +); + +extern Status XGetWMIconName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern Status XGetWMName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern Status XGetWMNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + long* /* supplied_return */ +); + +extern Status XGetWMSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + long* /* supplied_return */, + Atom /* property */ +); + +extern Status XGetZoomHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* zhints_return */ +); + +extern int XIntersectRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern void XConvertCase( + KeySym /* sym */, + KeySym* /* lower */, + KeySym* /* upper */ +); + +extern int XLookupString( + XKeyEvent* /* event_struct */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + XComposeStatus* /* status_in_out */ +); + +extern Status XMatchVisualInfo( + Display* /* display */, + int /* screen */, + int /* depth */, + int /* class */, + XVisualInfo* /* vinfo_return */ +); + +extern int XOffsetRegion( + Region /* r */, + int /* dx */, + int /* dy */ +); + +extern Bool XPointInRegion( + Region /* r */, + int /* x */, + int /* y */ +); + +extern Region XPolygonRegion( + XPoint* /* points */, + int /* n */, + int /* fill_rule */ +); + +extern int XRectInRegion( + Region /* r */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XSaveContext( + Display* /* display */, + XID /* rid */, + XContext /* context */, + _Xconst char* /* data */ +); + +extern int XSetClassHint( + Display* /* display */, + Window /* w */, + XClassHint* /* class_hints */ +); + +extern int XSetIconSizes( + Display* /* display */, + Window /* w */, + XIconSize* /* size_list */, + int /* count */ +); + +extern int XSetNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */ +); + +extern void XSetRGBColormaps( + Display* /* display */, + Window /* w */, + XStandardColormap* /* stdcmaps */, + int /* count */, + Atom /* property */ +); + +extern int XSetSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */, + Atom /* property */ +); + +extern int XSetStandardProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + Pixmap /* icon_pixmap */, + char** /* argv */, + int /* argc */, + XSizeHints* /* hints */ +); + +extern void XSetTextProperty( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */, + Atom /* property */ +); + +extern void XSetWMClientMachine( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern int XSetWMHints( + Display* /* display */, + Window /* w */, + XWMHints* /* wm_hints */ +); + +extern void XSetWMIconName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern void XSetWMName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern void XSetWMNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */ +); + +extern void XSetWMProperties( + Display* /* display */, + Window /* w */, + XTextProperty* /* window_name */, + XTextProperty* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void XmbSetWMProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void Xutf8SetWMProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void XSetWMSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */, + Atom /* property */ +); + +extern int XSetRegion( + Display* /* display */, + GC /* gc */, + Region /* r */ +); + +extern void XSetStandardColormap( + Display* /* display */, + Window /* w */, + XStandardColormap* /* colormap */, + Atom /* property */ +); + +extern int XSetZoomHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* zhints */ +); + +extern int XShrinkRegion( + Region /* r */, + int /* dx */, + int /* dy */ +); + +extern Status XStringListToTextProperty( + char** /* list */, + int /* count */, + XTextProperty* /* text_prop_return */ +); + +extern int XSubtractRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern int XmbTextListToTextProperty( + Display* display, + char** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern int XwcTextListToTextProperty( + Display* display, + wchar_t** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern int Xutf8TextListToTextProperty( + Display* display, + char** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern void XwcFreeStringList( + wchar_t** list +); + +extern Status XTextPropertyToStringList( + XTextProperty* /* text_prop */, + char*** /* list_return */, + int* /* count_return */ +); + +extern int XmbTextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + char*** list_return, + int* count_return +); + +extern int XwcTextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + wchar_t*** list_return, + int* count_return +); + +extern int Xutf8TextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + char*** list_return, + int* count_return +); + +extern int XUnionRectWithRegion( + XRectangle* /* rectangle */, + Region /* src_region */, + Region /* dest_region_return */ +); + +extern int XUnionRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern int XWMGeometry( + Display* /* display */, + int /* screen_number */, + _Xconst char* /* user_geometry */, + _Xconst char* /* default_geometry */, + unsigned int /* border_width */, + XSizeHints* /* hints */, + int* /* x_return */, + int* /* y_return */, + int* /* width_return */, + int* /* height_return */, + int* /* gravity_return */ +); + +extern int XXorRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +_XFUNCPROTOEND + +#endif /* _X11_XUTIL_H_ */ diff --git a/packages/games/tools/axe11/X11/cursorfont.h b/packages/games/tools/axe11/X11/cursorfont.h new file mode 100644 index 000000000..c69d508f4 --- /dev/null +++ b/packages/games/tools/axe11/X11/cursorfont.h @@ -0,0 +1,111 @@ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef _X11_CURSORFONT_H_ +#define _X11_CURSORFONT_H_ + +#define XC_num_glyphs 154 +#define XC_X_cursor 0 +#define XC_arrow 2 +#define XC_based_arrow_down 4 +#define XC_based_arrow_up 6 +#define XC_boat 8 +#define XC_bogosity 10 +#define XC_bottom_left_corner 12 +#define XC_bottom_right_corner 14 +#define XC_bottom_side 16 +#define XC_bottom_tee 18 +#define XC_box_spiral 20 +#define XC_center_ptr 22 +#define XC_circle 24 +#define XC_clock 26 +#define XC_coffee_mug 28 +#define XC_cross 30 +#define XC_cross_reverse 32 +#define XC_crosshair 34 +#define XC_diamond_cross 36 +#define XC_dot 38 +#define XC_dotbox 40 +#define XC_double_arrow 42 +#define XC_draft_large 44 +#define XC_draft_small 46 +#define XC_draped_box 48 +#define XC_exchange 50 +#define XC_fleur 52 +#define XC_gobbler 54 +#define XC_gumby 56 +#define XC_hand1 58 +#define XC_hand2 60 +#define XC_heart 62 +#define XC_icon 64 +#define XC_iron_cross 66 +#define XC_left_ptr 68 +#define XC_left_side 70 +#define XC_left_tee 72 +#define XC_leftbutton 74 +#define XC_ll_angle 76 +#define XC_lr_angle 78 +#define XC_man 80 +#define XC_middlebutton 82 +#define XC_mouse 84 +#define XC_pencil 86 +#define XC_pirate 88 +#define XC_plus 90 +#define XC_question_arrow 92 +#define XC_right_ptr 94 +#define XC_right_side 96 +#define XC_right_tee 98 +#define XC_rightbutton 100 +#define XC_rtl_logo 102 +#define XC_sailboat 104 +#define XC_sb_down_arrow 106 +#define XC_sb_h_double_arrow 108 +#define XC_sb_left_arrow 110 +#define XC_sb_right_arrow 112 +#define XC_sb_up_arrow 114 +#define XC_sb_v_double_arrow 116 +#define XC_shuttle 118 +#define XC_sizing 120 +#define XC_spider 122 +#define XC_spraycan 124 +#define XC_star 126 +#define XC_target 128 +#define XC_tcross 130 +#define XC_top_left_arrow 132 +#define XC_top_left_corner 134 +#define XC_top_right_corner 136 +#define XC_top_side 138 +#define XC_top_tee 140 +#define XC_trek 142 +#define XC_ul_angle 144 +#define XC_umbrella 146 +#define XC_ur_angle 148 +#define XC_watch 150 +#define XC_xterm 152 + +#endif /* _X11_CURSORFONT_H_ */ diff --git a/packages/games/tools/axe11/X11/extensions/XKBgeom.h b/packages/games/tools/axe11/X11/extensions/XKBgeom.h new file mode 100644 index 000000000..380fa18b3 --- /dev/null +++ b/packages/games/tools/axe11/X11/extensions/XKBgeom.h @@ -0,0 +1,662 @@ +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifndef _XKBGEOM_H_ +#define _XKBGEOM_H_ + +#include + +#ifdef XKB_IN_SERVER +#define XkbAddGeomKeyAlias SrvXkbAddGeomKeyAlias +#define XkbAddGeomColor SrvXkbAddGeomColor +#define XkbAddGeomDoodad SrvXkbAddGeomDoodad +#define XkbAddGeomKey SrvXkbAddGeomKey +#define XkbAddGeomOutline SrvXkbAddGeomOutline +#define XkbAddGeomOverlay SrvXkbAddGeomOverlay +#define XkbAddGeomOverlayRow SrvXkbAddGeomOverlayRow +#define XkbAddGeomOverlayKey SrvXkbAddGeomOverlayKey +#define XkbAddGeomProperty SrvXkbAddGeomProperty +#define XkbAddGeomRow SrvXkbAddGeomRow +#define XkbAddGeomSection SrvXkbAddGeomSection +#define XkbAddGeomShape SrvXkbAddGeomShape +#define XkbAllocGeomKeyAliases SrvXkbAllocGeomKeyAliases +#define XkbAllocGeomColors SrvXkbAllocGeomColors +#define XkbAllocGeomDoodads SrvXkbAllocGeomDoodads +#define XkbAllocGeomKeys SrvXkbAllocGeomKeys +#define XkbAllocGeomOutlines SrvXkbAllocGeomOutlines +#define XkbAllocGeomPoints SrvXkbAllocGeomPoints +#define XkbAllocGeomProps SrvXkbAllocGeomProps +#define XkbAllocGeomRows SrvXkbAllocGeomRows +#define XkbAllocGeomSectionDoodads SrvXkbAllocGeomSectionDoodads +#define XkbAllocGeomSections SrvXkbAllocGeomSections +#define XkbAllocGeomOverlays SrvXkbAllocGeomOverlays +#define XkbAllocGeomOverlayRows SrvXkbAllocGeomOverlayRows +#define XkbAllocGeomOverlayKeys SrvXkbAllocGeomOverlayKeys +#define XkbAllocGeomShapes SrvXkbAllocGeomShapes +#define XkbAllocGeometry SrvXkbAllocGeometry +#define XkbFreeGeomKeyAliases SrvXkbFreeGeomKeyAliases +#define XkbFreeGeomColors SrvXkbFreeGeomColors +#define XkbFreeGeomDoodads SrvXkbFreeGeomDoodads +#define XkbFreeGeomProperties SrvXkbFreeGeomProperties +#define XkbFreeGeomOverlayKeys SrvXkbFreeGeomOverlayKeys +#define XkbFreeGeomOverlayRows SrvXkbFreeGeomOverlayRows +#define XkbFreeGeomOverlays SrvXkbFreeGeomOverlays +#define XkbFreeGeomKeys SrvXkbFreeGeomKeys +#define XkbFreeGeomRows SrvXkbFreeGeomRows +#define XkbFreeGeomSections SrvXkbFreeGeomSections +#define XkbFreeGeomPoints SrvXkbFreeGeomPoints +#define XkbFreeGeomOutlines SrvXkbFreeGeomOutlines +#define XkbFreeGeomShapes SrvXkbFreeGeomShapes +#define XkbFreeGeometry SrvXkbFreeGeometry +#endif + +typedef struct _XkbProperty { + char *name; + char *value; +} XkbPropertyRec,*XkbPropertyPtr; + +typedef struct _XkbColor { + unsigned int pixel; + char * spec; +} XkbColorRec,*XkbColorPtr; + +typedef struct _XkbPoint { + short x; + short y; +} XkbPointRec, *XkbPointPtr; + +typedef struct _XkbBounds { + short x1,y1; + short x2,y2; +} XkbBoundsRec, *XkbBoundsPtr; +#define XkbBoundsWidth(b) (((b)->x2)-((b)->x1)) +#define XkbBoundsHeight(b) (((b)->y2)-((b)->y1)) + +/* + * In the following structs, this pattern is used for dynamically sized arrays: + * foo is an array for which sz_foo entries are allocated & num_foo are used + */ + +typedef struct _XkbOutline { + unsigned short num_points; + unsigned short sz_points; + unsigned short corner_radius; + XkbPointPtr points; +} XkbOutlineRec, *XkbOutlinePtr; + +typedef struct _XkbShape { + Atom name; + unsigned short num_outlines; + unsigned short sz_outlines; + XkbOutlinePtr outlines; + XkbOutlinePtr approx; + XkbOutlinePtr primary; + XkbBoundsRec bounds; +} XkbShapeRec, *XkbShapePtr; +#define XkbOutlineIndex(s,o) ((int)((o)-&(s)->outlines[0])) + +typedef struct _XkbShapeDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short color_ndx; + unsigned short shape_ndx; +} XkbShapeDoodadRec, *XkbShapeDoodadPtr; +#define XkbShapeDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbShapeDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbSetShapeDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) +#define XkbSetShapeDoodadShape(g,d,s) ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbTextDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + short width; + short height; + unsigned short color_ndx; + char * text; + char * font; +} XkbTextDoodadRec, *XkbTextDoodadPtr; +#define XkbTextDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbSetTextDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) + +typedef struct _XkbIndicatorDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short shape_ndx; + unsigned short on_color_ndx; + unsigned short off_color_ndx; +} XkbIndicatorDoodadRec, *XkbIndicatorDoodadPtr; +#define XkbIndicatorDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbIndicatorDoodadOnColor(g,d) (&(g)->colors[(d)->on_color_ndx]) +#define XkbIndicatorDoodadOffColor(g,d) (&(g)->colors[(d)->off_color_ndx]) +#define XkbSetIndicatorDoodadOnColor(g,d,c) \ + ((d)->on_color_ndx= (c)-&(g)->colors[0]) +#define XkbSetIndicatorDoodadOffColor(g,d,c) \ + ((d)->off_color_ndx= (c)-&(g)->colors[0]) +#define XkbSetIndicatorDoodadShape(g,d,s) \ + ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbLogoDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; + unsigned short color_ndx; + unsigned short shape_ndx; + char * logo_name; +} XkbLogoDoodadRec, *XkbLogoDoodadPtr; +#define XkbLogoDoodadColor(g,d) (&(g)->colors[(d)->color_ndx]) +#define XkbLogoDoodadShape(g,d) (&(g)->shapes[(d)->shape_ndx]) +#define XkbSetLogoDoodadColor(g,d,c) ((d)->color_ndx= (c)-&(g)->colors[0]) +#define XkbSetLogoDoodadShape(g,d,s) ((d)->shape_ndx= (s)-&(g)->shapes[0]) + +typedef struct _XkbAnyDoodad { + Atom name; + unsigned char type; + unsigned char priority; + short top; + short left; + short angle; +} XkbAnyDoodadRec, *XkbAnyDoodadPtr; + +typedef union _XkbDoodad { + XkbAnyDoodadRec any; + XkbShapeDoodadRec shape; + XkbTextDoodadRec text; + XkbIndicatorDoodadRec indicator; + XkbLogoDoodadRec logo; +} XkbDoodadRec, *XkbDoodadPtr; + +#define XkbUnknownDoodad 0 +#define XkbOutlineDoodad 1 +#define XkbSolidDoodad 2 +#define XkbTextDoodad 3 +#define XkbIndicatorDoodad 4 +#define XkbLogoDoodad 5 + +typedef struct _XkbKey { + XkbKeyNameRec name; + short gap; + unsigned char shape_ndx; + unsigned char color_ndx; +} XkbKeyRec, *XkbKeyPtr; +#define XkbKeyShape(g,k) (&(g)->shapes[(k)->shape_ndx]) +#define XkbKeyColor(g,k) (&(g)->colors[(k)->color_ndx]) +#define XkbSetKeyShape(g,k,s) ((k)->shape_ndx= (s)-&(g)->shapes[0]) +#define XkbSetKeyColor(g,k,c) ((k)->color_ndx= (c)-&(g)->colors[0]) + +typedef struct _XkbRow { + short top; + short left; + unsigned short num_keys; + unsigned short sz_keys; + int vertical; + XkbKeyPtr keys; + XkbBoundsRec bounds; +} XkbRowRec, *XkbRowPtr; + +typedef struct _XkbSection { + Atom name; + unsigned char priority; + short top; + short left; + unsigned short width; + unsigned short height; + short angle; + unsigned short num_rows; + unsigned short num_doodads; + unsigned short num_overlays; + unsigned short sz_rows; + unsigned short sz_doodads; + unsigned short sz_overlays; + XkbRowPtr rows; + XkbDoodadPtr doodads; + XkbBoundsRec bounds; + struct _XkbOverlay *overlays; +} XkbSectionRec, *XkbSectionPtr; + +typedef struct _XkbOverlayKey { + XkbKeyNameRec over; + XkbKeyNameRec under; +} XkbOverlayKeyRec,*XkbOverlayKeyPtr; + +typedef struct _XkbOverlayRow { + unsigned short row_under; + unsigned short num_keys; + unsigned short sz_keys; + XkbOverlayKeyPtr keys; +} XkbOverlayRowRec,*XkbOverlayRowPtr; + +typedef struct _XkbOverlay { + Atom name; + XkbSectionPtr section_under; + unsigned short num_rows; + unsigned short sz_rows; + XkbOverlayRowPtr rows; + XkbBoundsPtr bounds; +} XkbOverlayRec,*XkbOverlayPtr; + +typedef struct _XkbGeometry { + Atom name; + unsigned short width_mm; + unsigned short height_mm; + char * label_font; + XkbColorPtr label_color; + XkbColorPtr base_color; + unsigned short sz_properties; + unsigned short sz_colors; + unsigned short sz_shapes; + unsigned short sz_sections; + unsigned short sz_doodads; + unsigned short sz_key_aliases; + unsigned short num_properties; + unsigned short num_colors; + unsigned short num_shapes; + unsigned short num_sections; + unsigned short num_doodads; + unsigned short num_key_aliases; + XkbPropertyPtr properties; + XkbColorPtr colors; + XkbShapePtr shapes; + XkbSectionPtr sections; + XkbDoodadPtr doodads; + XkbKeyAliasPtr key_aliases; +} XkbGeometryRec; +#define XkbGeomColorIndex(g,c) ((int)((c)-&(g)->colors[0])) + +#define XkbGeomPropertiesMask (1<<0) +#define XkbGeomColorsMask (1<<1) +#define XkbGeomShapesMask (1<<2) +#define XkbGeomSectionsMask (1<<3) +#define XkbGeomDoodadsMask (1<<4) +#define XkbGeomKeyAliasesMask (1<<5) +#define XkbGeomAllMask (0x3f) + +typedef struct _XkbGeometrySizes { + unsigned int which; + unsigned short num_properties; + unsigned short num_colors; + unsigned short num_shapes; + unsigned short num_sections; + unsigned short num_doodads; + unsigned short num_key_aliases; +} XkbGeometrySizesRec,*XkbGeometrySizesPtr; + +_XFUNCPROTOBEGIN + +extern XkbPropertyPtr +XkbAddGeomProperty( + XkbGeometryPtr /* geom */, + char * /* name */, + char * /* value */ +); + +extern XkbKeyAliasPtr +XkbAddGeomKeyAlias( + XkbGeometryPtr /* geom */, + char * /* alias */, + char * /* real */ +); + +extern XkbColorPtr +XkbAddGeomColor( + XkbGeometryPtr /* geom */, + char * /* spec */, + unsigned int /* pixel */ +); + +extern XkbOutlinePtr +XkbAddGeomOutline( + XkbShapePtr /* shape */, + int /* sz_points */ +); + +extern XkbShapePtr +XkbAddGeomShape( + XkbGeometryPtr /* geom */, + Atom /* name */, + int /* sz_outlines */ +); + +extern XkbKeyPtr +XkbAddGeomKey( + XkbRowPtr /* row */ +); + +extern XkbRowPtr +XkbAddGeomRow( + XkbSectionPtr /* section */, + int /* sz_keys */ +); + +extern XkbSectionPtr +XkbAddGeomSection( + XkbGeometryPtr /* geom */, + Atom /* name */, + int /* sz_rows */, + int /* sz_doodads */, + int /* sz_overlays */ +); + +extern XkbOverlayPtr +XkbAddGeomOverlay( + XkbSectionPtr /* section */, + Atom /* name */, + int /* sz_rows */ +); + +extern XkbOverlayRowPtr +XkbAddGeomOverlayRow( + XkbOverlayPtr /* overlay */, + int /* row_under */, + int /* sz_keys */ +); + +extern XkbOverlayKeyPtr +XkbAddGeomOverlayKey( + XkbOverlayPtr /* overlay */, + XkbOverlayRowPtr /* row */, + char * /* over */, + char * /* under */ +); + +extern XkbDoodadPtr +XkbAddGeomDoodad( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */, + Atom /* name */ +); + + +extern void +XkbFreeGeomKeyAliases( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomColors( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomDoodads( + XkbDoodadPtr /* doodads */, + int /* nDoodads */, + Bool /* freeAll */ +); + + +extern void +XkbFreeGeomProperties( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlayKeys( + XkbOverlayRowPtr /* row */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlayRows( + XkbOverlayPtr /* overlay */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOverlays( + XkbSectionPtr /* section */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomKeys( + XkbRowPtr /* row */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomRows( + XkbSectionPtr /* section */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomSections( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + + +extern void +XkbFreeGeomPoints( + XkbOutlinePtr /* outline */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomOutlines( + XkbShapePtr /* shape */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeomShapes( + XkbGeometryPtr /* geom */, + int /* first */, + int /* count */, + Bool /* freeAll */ +); + +extern void +XkbFreeGeometry( + XkbGeometryPtr /* geom */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern Status +XkbAllocGeomProps( + XkbGeometryPtr /* geom */, + int /* nProps */ +); + +extern Status +XkbAllocGeomKeyAliases( + XkbGeometryPtr /* geom */, + int /* nAliases */ +); + +extern Status +XkbAllocGeomColors( + XkbGeometryPtr /* geom */, + int /* nColors */ +); + +extern Status +XkbAllocGeomShapes( + XkbGeometryPtr /* geom */, + int /* nShapes */ +); + +extern Status +XkbAllocGeomSections( + XkbGeometryPtr /* geom */, + int /* nSections */ +); + +extern Status +XkbAllocGeomOverlays( + XkbSectionPtr /* section */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomOverlayRows( + XkbOverlayPtr /* overlay */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomOverlayKeys( + XkbOverlayRowPtr /* row */, + int /* num_needed */ +); + +extern Status +XkbAllocGeomDoodads( + XkbGeometryPtr /* geom */, + int /* nDoodads */ +); + +extern Status +XkbAllocGeomSectionDoodads( + XkbSectionPtr /* section */, + int /* nDoodads */ +); + +extern Status +XkbAllocGeomOutlines( + XkbShapePtr /* shape */, + int /* nOL */ +); + +extern Status +XkbAllocGeomRows( + XkbSectionPtr /* section */, + int /* nRows */ +); + +extern Status +XkbAllocGeomPoints( + XkbOutlinePtr /* ol */, + int /* nPts */ +); + +extern Status +XkbAllocGeomKeys( + XkbRowPtr /* row */, + int /* nKeys */ +); + +extern Status +XkbAllocGeometry( + XkbDescPtr /* xkb */, + XkbGeometrySizesPtr /* sizes */ +); + +extern Status +XkbSetGeometry( + Display * /* dpy */, + unsigned /* deviceSpec */, + XkbGeometryPtr /* geom */ +); + +extern Bool +XkbComputeShapeTop( + XkbShapePtr /* shape */, + XkbBoundsPtr /* bounds */ +); + +extern Bool +XkbComputeShapeBounds( + XkbShapePtr /* shape */ +); + +extern Bool +XkbComputeRowBounds( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */, + XkbRowPtr /* row */ +); + +extern Bool +XkbComputeSectionBounds( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* section */ +); + +extern char * +XkbFindOverlayForKey( + XkbGeometryPtr /* geom */, + XkbSectionPtr /* wanted */, + char * /* under */ +); + +extern Status +XkbGetGeometry( + Display * /* dpy */, + XkbDescPtr /* xkb */ +); + +extern Status +XkbGetNamedGeometry( + Display * /* dpy */, + XkbDescPtr /* xkb */, + Atom /* name */ +); + +_XFUNCPROTOEND + +#endif /* _XKBSTR_H_ */ diff --git a/packages/games/tools/axe11/X11/extensions/xf86vmode.h b/packages/games/tools/axe11/X11/extensions/xf86vmode.h new file mode 100644 index 000000000..a7a3c5d71 --- /dev/null +++ b/packages/games/tools/axe11/X11/extensions/xf86vmode.h @@ -0,0 +1,298 @@ +/* + +Copyright 1995 Kaleb S. KEITHLEY + +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 Kaleb S. KEITHLEY 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. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _XF86VIDMODE_H_ +#define _XF86VIDMODE_H_ + +#include +#include +#include + +#define CLKFLAG_PROGRAMABLE 1 + +#ifdef XF86VIDMODE_EVENTS +#define XF86VidModeNotify 0 +#define XF86VidModeNumberEvents (XF86VidModeNotify + 1) + +#define XF86VidModeNotifyMask 0x00000001 + +#define XF86VidModeNonEvent 0 +#define XF86VidModeModeChange 1 +#else +#define XF86VidModeNumberEvents 0 +#endif + +#define XF86VidModeBadClock 0 +#define XF86VidModeBadHTimings 1 +#define XF86VidModeBadVTimings 2 +#define XF86VidModeModeUnsuitable 3 +#define XF86VidModeExtensionDisabled 4 +#define XF86VidModeClientNotLocal 5 +#define XF86VidModeZoomLocked 6 +#define XF86VidModeNumberErrors (XF86VidModeZoomLocked + 1) + +#define XF86VM_READ_PERMISSION 1 +#define XF86VM_WRITE_PERMISSION 2 + +#ifndef _XF86VIDMODE_SERVER_ + +typedef struct { + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} XF86VidModeModeLine; + +typedef struct { + unsigned int dotclock; + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} XF86VidModeModeInfo; + +typedef struct { + float hi; + float lo; +} XF86VidModeSyncRange; + +typedef struct { + char* vendor; + char* model; + float EMPTY; + unsigned char nhsync; + XF86VidModeSyncRange* hsync; + unsigned char nvsync; + XF86VidModeSyncRange* vsync; +} XF86VidModeMonitor; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent req */ + Display *display; /* Display the event was read from */ + Window root; /* root window of event screen */ + int state; /* What happened */ + int kind; /* What happened */ + Bool forced; /* extents of new region */ + Time time; /* event timestamp */ +} XF86VidModeNotifyEvent; + +typedef struct { + float red; /* Red Gamma value */ + float green; /* Green Gamma value */ + float blue; /* Blue Gamma value */ +} XF86VidModeGamma; + + +#define XF86VidModeSelectNextMode(disp, scr) \ + XF86VidModeSwitchMode(disp, scr, 1) +#define XF86VidModeSelectPrevMode(disp, scr) \ + XF86VidModeSwitchMode(disp, scr, -1) + +_XFUNCPROTOBEGIN + +Bool XF86VidModeQueryVersion( + Display* /* dpy */, + int* /* majorVersion */, + int* /* minorVersion */ +); + +Bool XF86VidModeQueryExtension( + Display* /* dpy */, + int* /* event_base */, + int* /* error_base */ +); + +Bool XF86VidModeSetClientVersion( + Display* /* dpy */ +); + +Bool XF86VidModeGetModeLine( + Display* /* dpy */, + int /* screen */, + int* /* dotclock */, + XF86VidModeModeLine* /* modeline */ +); + +Bool XF86VidModeGetAllModeLines( + Display* /* dpy */, + int /* screen */, + int* /* modecount */, + XF86VidModeModeInfo*** /* modelinesPtr */ +); + +Bool XF86VidModeAddModeLine( + Display* /* dpy */, + int /* screen */, + XF86VidModeModeInfo* /* new modeline */, + XF86VidModeModeInfo* /* after modeline */ +); + +Bool XF86VidModeDeleteModeLine( + Display* /* dpy */, + int /* screen */, + XF86VidModeModeInfo* /* modeline */ +); + +Bool XF86VidModeModModeLine( + Display* /* dpy */, + int /* screen */, + XF86VidModeModeLine* /* modeline */ +); + +Status XF86VidModeValidateModeLine( + Display* /* dpy */, + int /* screen */, + XF86VidModeModeInfo* /* modeline */ +); + +Bool XF86VidModeSwitchMode( + Display* /* dpy */, + int /* screen */, + int /* zoom */ +); + +Bool XF86VidModeSwitchToMode( + Display* /* dpy */, + int /* screen */, + XF86VidModeModeInfo* /* modeline */ +); + +Bool XF86VidModeLockModeSwitch( + Display* /* dpy */, + int /* screen */, + int /* lock */ +); + +Bool XF86VidModeGetMonitor( + Display* /* dpy */, + int /* screen */, + XF86VidModeMonitor* /* monitor */ +); + +Bool XF86VidModeGetViewPort( + Display* /* dpy */, + int /* screen */, + int* /* x return */, + int* /* y return */ +); + +Bool XF86VidModeSetViewPort( + Display* /* dpy */, + int /* screen */, + int /* x */, + int /* y */ +); + +Bool XF86VidModeGetDotClocks( + Display* /* dpy */, + int /* screen */, + int* /* flags return */, + int* /* number of clocks return */, + int* /* max dot clock return */, + int** /* clocks return */ +); + +Bool XF86VidModeGetGamma( + Display* /* dpy */, + int /* screen */, + XF86VidModeGamma* /* Gamma */ +); + +Bool XF86VidModeSetGamma( + Display* /* dpy */, + int /* screen */, + XF86VidModeGamma* /* Gamma */ +); + +Bool XF86VidModeSetGammaRamp( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool XF86VidModeGetGammaRamp( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool XF86VidModeGetGammaRampSize( + Display* /* dpy */, + int /* screen */, + int* /* size */ +); + +Bool XF86VidModeGetPermissions( + Display* /* dpy */, + int /* screen */, + int* /* permissions */ +); + +_XFUNCPROTOEND + +#endif + +#endif diff --git a/packages/games/tools/axe11/package.mk b/packages/games/tools/axe11/package.mk new file mode 100644 index 000000000..06c5e4ae0 --- /dev/null +++ b/packages/games/tools/axe11/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC + +PKG_NAME="axe11" +PKG_VERSION="77813264827823bcbd617ca0f2b2da3e6abb1e7a" +PKG_SHA256="bcdc27316bba492af9f05d25dc07f2a2ac718807393796fc87b2c794bd458e14" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/JohnnyonFlame/axe11" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain gl4es" +PKG_LONGDESC="A Proof-of-Concept libX11 Shim for Gamemaker Games to run under Box86 with GL4ES (and the necessary set of hacks on top of it)." + +pre_configure_target() { + sed -i "s|sdl2-config|$SYSROOT_PREFIX/usr/bin/sdl2-config|g" Makefile + cp -r $PKG_DIR/X11 $SYSROOT_PREFIX/usr/include +} + +post_make_target() { + rm -rf $SYSROOT_PREFIX/usr/include/X11 +} diff --git a/packages/games/tools/axe11/patches/01-compile-fix.patch b/packages/games/tools/axe11/patches/01-compile-fix.patch new file mode 100644 index 000000000..220a81b4c --- /dev/null +++ b/packages/games/tools/axe11/patches/01-compile-fix.patch @@ -0,0 +1,12 @@ +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ +-CROSS_PREFIX=arm-linux-gnueabihf- +-CCACHE?= +-CC=$(CCACHE) $(CROSS_PREFIX)gcc ++#CROSS_PREFIX=arm-linux-gnueabihf- ++#CCACHE?= ++#CC=$(CCACHE) $(CROSS_PREFIX)gcc + SDL_CONFIG=$(CROSS_PREFIX)pkg-config sdl2 + + USE_SDL?=1 diff --git a/packages/games/tools/box64/package.mk b/packages/games/tools/box64/package.mk new file mode 100644 index 000000000..2accc1667 --- /dev/null +++ b/packages/games/tools/box64/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="box64" +PKG_VERSION="06bbf93bf876c107ff41593a75fe6fa8a6d6a779" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/ptitSeb/box64" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain gl4es" +PKG_LONGDESC="Box64 - Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices" +PKG_TOOLCHAIN="cmake" +GET_HANDLER_SUPPORT="git" + +PKG_CMAKE_OPTS_TARGET=" -DRK3326=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo" + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/box64/lib + cp $PKG_BUILD/x64lib/* $INSTALL/usr/share/box64/lib + cp $PKG_BUILD/.${TARGET_NAME}/box64 $INSTALL/usr/share/box64/ +} diff --git a/packages/games/tools/box86/package.mk b/packages/games/tools/box86/package.mk new file mode 100644 index 000000000..b792c2ae3 --- /dev/null +++ b/packages/games/tools/box86/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="box86" +PKG_VERSION="844566a78ae3c995c3c575d5822616e5e783fe39" +PKG_REV="1" +PKG_ARCH="arm" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/ptitSeb/box86" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain gl4es" +PKG_LONGDESC="Box86 - Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET=" -DGOA_CLONE=1 -DCMAKE_BUILD_TYPE=Release" + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/box86/lib + cp $PKG_BUILD/x86lib/* $INSTALL/usr/share/box86/lib + cp $PKG_BUILD/.${TARGET_NAME}/box86 $INSTALL/usr/share/box86/ +} diff --git a/packages/games/tools/capsimg/package.mk b/packages/games/tools/capsimg/package.mk new file mode 100644 index 000000000..7c4265158 --- /dev/null +++ b/packages/games/tools/capsimg/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="capsimg" +PKG_VERSION="457d420848145de6541e47296405b1938830900a" +PKG_SHA256="d32c4d802301e33abef067837a20bc8bc5d9769154820b99408c6a967e8cd402" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/FrodeSolheim/capsimg" +PKG_URL="https://github.com/FrodeSolheim/capsimg/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="SPS Decoder Library 5.1 (formerly IPF Decoder Lib)" +PKG_TOOLCHAIN="make" +PKG_PATCH_DIRS+="${DEVICE}" + +PKG_MAKE_OPTS_TARGET="-C CAPSImg" + +pre_configure_target() { + cd .. + ./bootstrap + ./configure --host=${TARGET_NAME} +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib + cp -v CAPSImg/libcapsimage.so.5.1 ${INSTALL}/usr/lib/ + ln -sf libcapsimage.so.5.1 ${INSTALL}/usr/lib/libcapsimage.so.5 + ln -sf libcapsimage.so.5.1 ${INSTALL}/usr/lib/libcapsimage.so + mkdir -p ${INSTALL}/usr/local/include/caps5 + cp -v LibIPF/* ${INSTALL}/usr/local/include/caps5 +} diff --git a/packages/games/tools/gamecontrollerdb/package.mk b/packages/games/tools/gamecontrollerdb/package.mk new file mode 100644 index 000000000..bab5c502a --- /dev/null +++ b/packages/games/tools/gamecontrollerdb/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +PKG_NAME="gamecontrollerdb" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_SECTION="tools" +PKG_SHORTDESC="SDL Game Controller DB" +PKG_TOOLCHAIN="manual" + +make_target() { + echo +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/config/SDL-GameControllerDB + + if [ "$DEVICE" == "RG351P" ] || [ "$DEVICE" == "RG351V" ]; then + cat <${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt +03000000091200000031000011010000,OpenSimHardware OSH PB Controller,a:b0,b:b1,y:b3,x:b2,start:b6,back:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,leftstick:b8,guide:b9,leftx:a0~,lefty:a1~,rightx:a2,righty:a3,platform:Linux, +EOF + elif [ "$DEVICE" == "RG351MP" ]; then + cat <${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt +190000004b4800000011000000010000,GO-Super Gamepad,x:b2,a:b1,b:b0,y:b3,back:b12,start:b13,dpleft:b10,dpdown:b9,dpright:b11,dpup:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b14,guide:b15,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux, +EOF + elif [ "$DEVICE" == "RG552" ]; then + cat <${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt +190000004b4800000111000000010000,retrogame_joypad,platform:Linux,a:b1,b:b0,x:b2,y:b3,back:b8,start:b9,rightstick:b12,leftstick:b11,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3, +EOF + fi + + cat ${PKG_DIR}/sources/gamecontrollerdb.txt >>${INSTALL}/usr/config/SDL-GameControllerDB/gamecontrollerdb.txt +} diff --git a/packages/games/tools/gamecontrollerdb/sources/gamecontrollerdb.txt b/packages/games/tools/gamecontrollerdb/sources/gamecontrollerdb.txt new file mode 100644 index 000000000..97f38ae8d --- /dev/null +++ b/packages/games/tools/gamecontrollerdb/sources/gamecontrollerdb.txt @@ -0,0 +1,1521 @@ +# Game Controller DB for SDL in 2.0.16 format +# Source: https://github.com/gabomdq/SDL_GameControllerDB + +# Windows +03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, +03000000d0160000040d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000050d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000060d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000070d000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000600a000000000000,4Play,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, +03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000151000000000000,8BitDo M30 ModKit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows, +03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows, +03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000290000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, +03000000c82d00003038000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, +03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00002038000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000531000000000000,8BitDo Wireless Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000d81d00000e00000000000000,AC02,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, +030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006d0400000bc2000000000000,Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, +03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows, +030000006f0e00001301000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001302000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001304000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001413000000000000,Afterglow,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00003901000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ab1200000103000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000f9000000000000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows, +03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows, +03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000ef0500000300000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000230000000000000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, +030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows, +030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000000055000000000000,Betop BFM Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, +030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows, +030000001a1c00000001000000000000,Datel,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, +03000000c0160000e105000000000000,Dual,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows, +030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows, +030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000317300000100000000000000,DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +030000006e0500000a20000000000000,Elecom DUX60 MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, +03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adater,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000320000000000000,Elecom U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:brightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, +03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000790000003018000000000000,F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00003900000000000000,F300 Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008401000000000000,Faceoff Deluxe Audio Wired Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:aefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000380700002847000000000000,FightPad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700001847000000000000,FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700008031000000000000,FightStick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows, +03000000b50700000399000000000000,Firestorm 2,a2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows, +03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows, +03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows, +030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, +03000000ac0500002d02000000000000,G2U,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000341a000005f7000000000000,GameCube,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows, +03000000430b00000500000000000000,GameCube,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows, +03000000790000004718000000000000,GameCube,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, +03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000ac0500003d03000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00001110000000000000,GameStick Bluetooth Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows, +030000008f0e00001411000000000000,Gamo2 Divaller PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,ltx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a2,start:b9,x:b3,y:b4,platform:Windows, +030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstk:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fd0500003902000000000000,Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, +03000000fd0500002a26000000000000,Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500002f26000000000000,Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, +030000000d0f00004900000000000000,Hatsune Miku Sho PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, +030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008600000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000ba00000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00002500000000000000,Hori Fiting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005100000000000000,Hori Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001000000000000000,Hori Fighting Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000f0d00000010000000000000,Hori Fighting Stick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003200000000000000,Hori Fighting Stick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c000000000000000,Hori Fighting Stick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00000d00000000000000,Hori Fighting Stick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00003701000000000000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows, +030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002100000000000000,Hori Fighting Stick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpght:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, +030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows, +030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2up:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ab000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b07,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b08,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002301000000000000,Hori Wired PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f0000c100000000000000,Horipad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005b1c00002400000000000000,Horipad Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +030000000d0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows, +03000000696400006964000000000000,iDroidCon Bluetooth Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +030000006f0e00002401000000000000,Injustice FightStick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,plaorm:Windows, +03000000491900000304000000000000,Ipega PG9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, +030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, +030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000250900000017000000000000,Joypad to USB Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows, +03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows, +03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,pform:Windows, +030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, +030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, +03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttriggea2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005032000000000000,Mad Catz FightPad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005082000000000000,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008433000000000000,Mad Catz FightStick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008483000000000000,Mad Catz FightStick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008134000000000000,Mad Catz FightStick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz FightStick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick1,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001888000000000000,Mad Catz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008081000000000000,Mad Catz SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000003807000038b7000000000000,MadCatz FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +78696e70757403000000000000000000,MadCatz Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000380700008232000000000000,MadCatz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008731000000000000,MadCatz PlayStation FightStick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000003807000056a8000000000000,MadCatz PS3 Wireless Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dprht:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, +0300000079000000ae18000000000000,Mega Drive,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000c0160000990a000000000000,Mega Drive,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows, +030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows, +030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, +030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows, +03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dplef0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows, +030000005b1c00002500000000000000,Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000ad1b00003ef0000000000000,MLG FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700006382000000000000,MLG GamePad PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-rigy:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, +030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000eb0300000000000000000000,NeGcon USB Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows, +0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, +03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, +03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, +03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +030000007e05000019200000000000,Nintendo Switch N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows, +030000007e0500001720000000000000,Nintendo Switch Online Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows, +03000000550900001472000000000000,NVIDIA Controller v01.04,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows, +03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows, +030000005509000000b4000000000000,NVIDIA Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000004b120000014d000000000000,Nyko Airflo,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, +03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows, +030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:,start:b7,x:b2,y:b3,platform:Windows, +030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, +03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows, +030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000d9040000160f000000000000,Playstation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c183000000000000,PlayStation Game Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d620000013a7000000000000,PowerA Wired Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000084ca0000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, +03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightsulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, +030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows, +030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dprig:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows, +03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dple:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f10e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000001a1e00020c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows, +03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0efttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, +03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +030000009b2800002300000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800006900000000000000,Raphnet Technologies 3DO USB Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800000800000000000000,Raphnet Technologies Dreamcast USB Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows, +030000009b2800003200000000000000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800006000000000000000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800001800000000000000,Raphnet Technologies Jaguar USB Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, +030000009b2800000200000000000000,Raphnet Technologies NES USB Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, +030000009b2800004300000000000000,Raphnet Technologies Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000009b2800000500000000000000,Raphnet Technologies Saturn Adapter 2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000300000000000000,Raphnet Technologies SNES USB Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +030000009b2800005600000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b28005700000000000000,Raphnet Technologies SNES USB Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800001e00000000000000,Raphnet Technologies Vectrex USB Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, +030000009b2800002b00000000000000,Raphnet Technologies Wii Classic USB Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002c00000000000000,Raphnet Technologies Wii Classic USB Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000011000000000000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000bd12000013d0000000000000,Retrolink USB Sega Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, +03000000bd12000015d0000000000000,Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows, +030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4pleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows, +03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000dff00000000000Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows, +03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows, +03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows, +030000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows, +03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000c01100000051000000000000,Satechi Bluetooth Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, +03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +0300000000050000289b000000000000,Sega Saturn Adapter 2,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, +03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, +03000000120c00001c1e000000000000,SnakeByte GamePad 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:bleftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, +03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000001214000000000000,SteelSeries Frea:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, +03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, +03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000003014000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000381000003114000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003847000000000000,Street Fighter Fighting Stick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, +030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000d620000011a7000000000000,Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000f600000000000000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, +030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows, +03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, +03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3 in 1 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f0400000ed0000000000000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, +030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000004f04000007d0000000000000,TMini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, +03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, +03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,30000000b0400003065000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000242f00006e00000000000000,USB Game Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, +03000000300f00000701000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000341a00002308000000000000,USB Game Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000666600000188000000000000,USB Game Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000666600000288000000000000,USB Game Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000006b1400000203000000000000,USB Game Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000790000000a00000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000b404000081c6000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001503000000000000,USB Game Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000bd12000012d0000000000000,USB Game Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000ff1100004133000000000000,USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000001a18000000000000,Venom,a:b1,b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, +03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ff02000000000000,Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ea02000000000000,Wireless Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, +03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftsticb10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows, +03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000fdfa0000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows, +03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Winws, +030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,ltx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000450c00002043000000000000,Xeox Gamepad SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000ac0500005b05000000000000,Xiaoji Gamesir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000120c0000101e000000000000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, + +# Mac OS X +030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00004028000000010000,8Bitdo SN30 GamePad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,bacb10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000531000000020000,8BitDo Wireless Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightsticb8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000ef0500000300000000020000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, +03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, +03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac X, +03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00000300000007010000,GreenAsia USB Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, +030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, +030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000005030000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006d04000018c2000000010000,Logitech RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, +0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrir:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X, +030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X, +030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000011a7000000020000,Nintendo Switch Core Plus Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d620000011a7000010050000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, +030000006f0e00000901000002010000,PDP Versus Fightingad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000104000000010000,Raz Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000321500000011000000010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000c6240000fefa000000000000,Rock Candy Gamepad for PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X, +03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +030000000400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, +030000004c050000e60c000000010000,Sony DualSense,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +05000000556e6b6e6f776e2048494400,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platrm:Mac OS X, +03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +030000004f0400000ed0000000020000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000702000003060000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006f0e00000104000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:bb:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000050b000003090000,Xbox Elite Wireless Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400003a54000000000000,Xbox One PowerA Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000011050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigg:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000120c0000100e000000010000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000101e000000010000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, + +# Linux +03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, +03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000190000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, +05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000031000011010000,8BitDo Wireless Adapter (DInput),a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +050000005e040000e002000030110000,8BitDo Zero 2 (XInput),a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000020060000,Afterglow Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100000008200000011010000,Akishop Customs PS360 v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstk:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, +05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +05000000050b00000045000031000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +05000000050b00000045000040000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux, +05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,platform:Linux, +03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, +05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000ef0500000300000000010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:,start:b9,x:b3,y:b0,platform:Linux, +03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000666600006706000000010000,Boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, +03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000022f6000011010000,Cyborg V3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000ac0500002d0200001b010000,Gamesir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000bc2000005656000011010000,Gamesir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,eft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, +030000008f0e00001200000010010000,GreenAsia USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Game Gamepqd,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +030000000d0f00008500000010010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00001000000011010000,Hori Fighting Stick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000003f5000033050000,Hori Fighting Stick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux, +030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000aa00000011010000,Hori Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,ltx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f0000c100000011010000,Horipad S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux, +03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000d80400008200000003000000,IMS PCU0 Gamepad,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I73000,a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +0500000049190000020400001b010000,Ipega PG 9069 Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000632500007505000011010000,Ipega PG 9099 Bluetooth Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttriggea5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, +050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, +030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000019200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, +030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, +05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005032000011010000,Mad Catz FightPad PRO PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005082000011010000,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000380700008034000011010000,Mad Catz fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008433000011010000,Mad Catz FightStick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008483000011010000,Mad Catz FightStick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000380700008532000010010000,Madcatz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, +0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefhoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux, +030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +030000005e0400000700000000010000,Microsoft SideWinder Game Pad USB,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, +030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux, +030000005e0400008e02000056210000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000004010000,Microsoft Xbox 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000062230000,Microsoft Xbox 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000050b000003090000,Microsoft Xbox One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000e302000003020000,Microsoft Xbox One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000001010000,Microsoft Xbox One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000dd02000003020000,Microsoft Xbox One pad 2015,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platforinux, +030000005e040000d102000003020000,Microsoft Xbox One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea02000008040000,Microsoft Xbox One S pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008502000000010000,Microsoft Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008902000021010000,Microsoft Xbox pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:,x:b2,y:b3,platform:Linux, +030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f1f00000800000011010000,Neogeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux, +060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, +03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, +060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b9,b:b8,back:b5,leftshoulder:b2,leftstick:b6,leftx:a1,lefty:a0~,rightshoulder:b4,start:b0,x:b7,y:b10,platform:Linux, +03000000d620000013a7000011010000,Nintendo Switch PowerA Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshouer:b4,leftstick:b10,leftx:a1~,lefty:a0~,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux, +050000007e0500001720000001000000,Nintendo Switch SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux, +03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, +05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux, +03000000790000001c18000011010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5ightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e0000b802000001010000,PDP Afterglow Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000b802000013020000,PDP Afterglow Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00008001000011010000,PDP Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00000901000011010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d9040000160f000000010000,Playstation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightsck:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d62000000228000001010000,PowerA Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000220000001010000,PowerA Wired Controller for Xbox One and Xbox Series,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c62400001a54000001010000,PowerA Xbox One Mini Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start9,x:b0,y:b3,platform:Linux, +030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +03000000300f00001210000010010000,Qanba Joystick Plus,a0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, +030000009b2800004200000001010000,Raphnet Technologies Dual NES to USB v2.0,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, +030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008916000000fd000024010000,Razer Onza Tournament Edition,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000011000011010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,lex:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux, +0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux, +0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V1 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux, +03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux, +03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000a306000018f5000010010000,Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, +03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, +03000000a30c00002500000011010000,Sega Genesis Mini 3B controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, +030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000f025000021c1000010010000,Shanwan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000632500007505000010010000,Shanwan PS3 PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000bc2000000055000010010000,Shanwan PS3 PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005f140000c501000010010000,Shanwan Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000004c050000e60c000011810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000e60c000000810000,Sony DualSense,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e0400008e02000073050000,Speedlink Torid Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,starb7,x:b2,y:b3,platform:Linux, +03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, +03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000457500002211000010010000,SZMY Power Gpad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000008f0e00001431000010010000,SZMY Power PS3 gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3 in 1 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f0400000ed0000011010000,Thrustmaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux, +030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004f04000026b3000002040000,Thrustmaster Gamepad GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000025b000002020000,Thrustmaster GPX Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +03000000571d00002000000010010000,Tomee SNES USB Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +03000000790000001100000011010000,USB Saturn Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, +03000000790000002201000011010000,USB Saturn Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +03000000b40400000a01000000010000,USB Saturn Pad,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, +030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00000702000011010000,Victx Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +050000000d0f0000f600000001000000,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400009102000007010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000000010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000007010000,Xbox 360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000000010000,Xbox 360 Wireless EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000014010000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshlder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +0000000058626f782047616d65706100,Xbox Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea02000000000000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b000007050000,Xbox One Wireless Controller (Model 1914),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dp:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000202000000010000,Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000450c00002043000010010000,XEOX Gamepad SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ac0500005b05000010010000,Xiaoji Gamesir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, +03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000120c0000100e000011010000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightsk:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000101e000011010000,Zeroplus P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, + +# Android +38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, +33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, +39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, +64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, +66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, +66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, +62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Andrd, +05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, +61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, +05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, +36666264316630653965636634386234,8BitDo Wireless Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platformndroid, +33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +32333634613735616163326165323731,Amazon Luna Game Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, +05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, +0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android, +31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, +64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, +65346535636333663931613264643164,Joy Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, +33346566643039343630376565326335,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +35313531613435623366313835326238,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +38383665633039363066383334653465,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39363561613936303237333537383931,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b1x:b0,y:b2,platform:Android, +31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +32303165626138343962363666346165,Mars,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +31323564663862633234646330373138,Mega Drive,a:b23,b:b22,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, +33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, +30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,leftshoulder:b20,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, +64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, +050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, +34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstic7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005509000014720000df7f3f00,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, +62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,leftshoulder:b9,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, +61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, +32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, +61363034663839376638653463633865,PS3,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66366539656564653432353139356536,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66383132326164626636313737373037,PS3,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30303839663330346632363232623138,PS4,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +31326235383662333266633463653332,PS4,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, +31663838336334393132303338353963,PS4,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34613139376634626133336530386430,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37626233336235343937333961353732,PS4,a:b0b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38393161636261653636653532386639,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63313733393535663339656564343962,PS4,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63393662363836383439353064663939,PS4,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65366465656364636137653363376531,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +66613532303965383534396638613230,PS4,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, +38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, +33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, +66386565396238363534313863353065,Sanwa Mobile,a:b21,b:b22,leftshoulder:b23,leftx:a0,lefty:a1,rightshoulder:b24,platform:Android, +32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +37316565396364386635383230353365,Saturn,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +38613865396530353338373763623431,Saturn,a:b0,b:b1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, +61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dplt:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +32633532643734376632656664383733,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +61303162353165316365336436343139,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, +63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, +050000004f0400000ed00000fffe3f00,ThrustMaster eSwap PRO Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, +30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b23,paddle2:b24,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30386438313564306161393537333663,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +33333034646336346339646538643633,Wii Classic,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +30306539356238653637313730656134,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +30396232393162346330326334636566,Xbox 360,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38313038323730383864666463383533,Xbox 360,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65353331386662343338643939643636,Xbox 360,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65613532386633373963616462363038,Xbox 360,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, +050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,le:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, +36616131643361333337396261666433,Xbox Wireless Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000001727000044310000ffff3f00,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, + +# iOS +05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, +4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, +050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,platform:iOS, +050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, +05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, +05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, +050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,plaorm:iOS, diff --git a/packages/games/tools/gl4es/package.mk b/packages/games/tools/gl4es/package.mk new file mode 100644 index 000000000..963a17baa --- /dev/null +++ b/packages/games/tools/gl4es/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="gl4es" +PKG_VERSION="83b074dcb0028e239da2ad9789db80cc1d5f2544" +PKG_SHA256="2031be77b49398cdf945c110e59530a48113c35fd69c0a7381be21fc9eaccc79" +PKG_GIT_CLONE_BRANCH="sk_hacks" +PKG_SITE="https://github.com/JohnnyonFlame/gl4es" +PKG_LICENSE="GPL" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES}" +PKG_LONGDESC=" GL4ES is a OpenGL 2.1/1.5 to GL ES 2.0/1.1 translation library, with support for Pandora, ODroid, OrangePI, CHIP, Raspberry PI, Android, Emscripten and AmigaOS4. " +PKG_TOOLCHAIN="cmake-make" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET=" -DNOX11=1 -DODROID=1 -DGBM=ON -DCMAKE_BUILD_TYPE=Release " +} diff --git a/packages/games/tools/gptokeyb/Makefile b/packages/games/tools/gptokeyb/Makefile new file mode 100644 index 000000000..1bc9c6e90 --- /dev/null +++ b/packages/games/tools/gptokeyb/Makefile @@ -0,0 +1,12 @@ +CXX ?= gcc +CFLAGS += -W -Wall -std=c++11 + +BINARY = gptokeyb +LIBRARIES = -levdev -lSDL2 +SOURCES = "gptokeyb.cpp" + +all: + $(CXX) $(CFLAGS) $(SOURCES) -o $(BINARY) $(LIBRARIES) + +clean: + rm -f $(BINARY) \ No newline at end of file diff --git a/packages/games/tools/gptokeyb/package.mk b/packages/games/tools/gptokeyb/package.mk new file mode 100644 index 000000000..3d699b98a --- /dev/null +++ b/packages/games/tools/gptokeyb/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="gptokeyb" +PKG_VERSION="c643c0c063b04ff2f8a317b64d42dea47c315063" +PKG_ARCH="aarch64" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/EmuELEC/gptokeyb" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain libevdev SDL2" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_make_target() { + cp -f $PKG_DIR/Makefile $PKG_BUILD + CFLAGS+=" -I$(get_build_dir SDL2)/include -D_REENTRANT" + CFLAGS+=" -I$(get_build_dir libevdev)" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_BUILD/gptokeyb $INSTALL/usr/bin +} + diff --git a/packages/games/tools/gptokeyb/patches/0001-build_fix.patch b/packages/games/tools/gptokeyb/patches/0001-build_fix.patch new file mode 100644 index 000000000..01906ed86 --- /dev/null +++ b/packages/games/tools/gptokeyb/patches/0001-build_fix.patch @@ -0,0 +1,16 @@ +diff --git a/gptokeyb.cpp b/gptokeyb.cpp +index d604f37..a00ce50 100644 +--- a/gptokeyb.cpp ++++ b/gptokeyb.cpp +@@ -42,8 +42,8 @@ + #include + #include + +-#include +-#include ++#include ++#include + + #include + #include + diff --git a/packages/games/tools/jstest-sdl/package.mk b/packages/games/tools/jstest-sdl/package.mk new file mode 100644 index 000000000..4f9c430c5 --- /dev/null +++ b/packages/games/tools/jstest-sdl/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="jstest-sdl" +PKG_VERSION="bdf1465c978204725c086c5a56bbcc0a7f7dda48" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/dhwz/jstest-sdl" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain SDL2 ncurses" +PKG_SHORTDESC="Simple SDL joystick test application for the console" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_configure_target() { + sed -i "s|sdl2-config|$SYSROOT_PREFIX/usr/bin/sdl2-config|g" Makefile +} + +makeinstall_target(){ + mkdir -p $INSTALL/usr/bin + cp jstest-sdl $INSTALL/usr/bin +} diff --git a/packages/games/tools/libglu/gl.pc b/packages/games/tools/libglu/gl.pc new file mode 100644 index 000000000..728dfaaa4 --- /dev/null +++ b/packages/games/tools/libglu/gl.pc @@ -0,0 +1,10 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=/usr/lib +includedir=${prefix}/include + +Name: gl +Description: gl4es gl library +Version: 0.1.0 +Libs: -L${libdir} -lGL +Cflags: -I${includedir} diff --git a/packages/games/tools/libglu/package.mk b/packages/games/tools/libglu/package.mk new file mode 100644 index 000000000..e06cb9a47 --- /dev/null +++ b/packages/games/tools/libglu/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="libglu" +PKG_VERSION="2fed2bda2b725d2b9e32c435b48d5141cc95827f" +PKG_SHA256="8a016d32fc1fed742f10ba8e4bc32151598f6273a0dbabec15ba47c44151c879" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/ptitSeb/GLU" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain gl4es" +PKG_LONGDESC=" GL4ES is a OpenGL 2.1/1.5 to GL ES 2.0/1.1 translation library, with support for Pandora, ODroid, OrangePI, CHIP, Raspberry PI, Android, Emscripten and AmigaOS4. " + +PKG_CONFIGURE_OPTS_TARGET="--disable-static --enable-shared" + +pre_configure_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/include/GL + cp -rf $(get_build_dir gl4es)/.install_pkg/usr/lib/gl4es/libGL.so.1 ${SYSROOT_PREFIX}/usr/lib/libGL.so + cp -rf $(get_build_dir gl4es)/include/GL/gl.h ${SYSROOT_PREFIX}/usr/include/GL/gl.h + cp -rf ${PKG_DIR}/gl.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig +} + +post_install_target() { + rm ${SYSROOT_PREFIX}/usr/lib/libGL.so + rm ${SYSROOT_PREFIX}/usr/include/GL/gl.h + rm ${SYSROOT_PREFIX}/usr/lib/pkgconfig/gl.pc +} diff --git a/packages/games/tools/libgo2/package.mk b/packages/games/tools/libgo2/package.mk new file mode 100644 index 000000000..c0896cdae --- /dev/null +++ b/packages/games/tools/libgo2/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="libgo2" +PKG_VERSION="bc992566bb86f2fe0c8d981d4db46e2e2beb5b0e" +PKG_SHA256="89ad1cf229d581fa8e4498f4f4c526215176e79885e935bd7dc48c5872655f92" +PKG_ARCH="arm aarch64" +PKG_LICENSE="LGPL" +PKG_DEPENDS_TARGET="toolchain libevdev librga" +PKG_SITE="https://github.com/OtherCrashOverride/libgo2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Support library for the ODROID-GO Advance " +PKG_TOOLCHAIN="make" + +if [ "${DEVICE}" = "RG351P" ] || [ "${DEVICE}" = "RG552" ] +then + PKG_PATCH_DIRS="RG351P" +else + PKG_PATCH_DIRS="RG351V" +fi + +PKG_MAKE_OPTS_TARGET=" config=release ARCH= INCLUDES=-I$SYSROOT_PREFIX/usr/include/libdrm -I$SYSROOT_PREFIX/usr/include " + +makeinstall_target() { +mkdir -p $INSTALL/usr/lib +cp libgo2.so $INSTALL/usr/lib + +mkdir -p $SYSROOT_PREFIX/usr/include/go2 +cp src/*.h $SYSROOT_PREFIX/usr/include/go2 + +mkdir -p $SYSROOT_PREFIX/usr/lib +cp libgo2.so $SYSROOT_PREFIX/usr/lib +} + diff --git a/packages/games/tools/libgo2/patches/RG351V/0001-remove_rotation.patch b/packages/games/tools/libgo2/patches/RG351V/0001-remove_rotation.patch new file mode 100644 index 000000000..8ca88bf92 --- /dev/null +++ b/packages/games/tools/libgo2/patches/RG351V/0001-remove_rotation.patch @@ -0,0 +1,32 @@ +From 0475adef34dd591096e6a8619c8f2bf0d2ba4392 Mon Sep 17 00:00:00 2001 +From: christianhaitian +Date: Fri, 9 Apr 2021 01:44:58 -0400 +Subject: [PATCH] Remove rotation + +--- + src/display.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/display.c b/src/display.c +index 52b2827..4f3dc3b 100644 +--- a/src/display.c ++++ b/src/display.c +@@ -601,15 +601,15 @@ void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidt + break; + + case GO2_ROTATION_DEGREES_90: +- src.rotation = HAL_TRANSFORM_ROT_90; ++ src.rotation = 0; + break; + + case GO2_ROTATION_DEGREES_180: +- src.rotation = HAL_TRANSFORM_ROT_180; ++ src.rotation = 0; + break; + + case GO2_ROTATION_DEGREES_270: +- src.rotation = HAL_TRANSFORM_ROT_270; ++ src.rotation = 0; + break; + + default: diff --git a/packages/games/tools/retroarch-assets/package.mk b/packages/games/tools/retroarch-assets/package.mk new file mode 100644 index 000000000..003688008 --- /dev/null +++ b/packages/games/tools/retroarch-assets/package.mk @@ -0,0 +1,38 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="retroarch-assets" +PKG_VERSION="6320719b9977ec99b7b8aa02003997f8e82ff47d" +PKG_SHA256="fbf9cd274e07c4ed8f118a8142cb8e8aafc088a34a309ce6c2006c2a6647d598" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/retroarch-assets" +PKG_URL="https://github.com/libretro/retroarch-assets/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="RetroArch assets. Background and icon themes for the menu drivers." +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + cd ../ + rm -rf .$TARGET_NAME +} + +makeinstall_target() { + make install INSTALLDIR="$INSTALL/usr/share/retroarch-assets" +} diff --git a/packages/games/tools/retroarch-overlays/package.mk b/packages/games/tools/retroarch-overlays/package.mk new file mode 100644 index 000000000..38e86bb1d --- /dev/null +++ b/packages/games/tools/retroarch-overlays/package.mk @@ -0,0 +1,41 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="retroarch-overlays" +PKG_VERSION="c543bb3c3a1a72be88f829d66966bc5b36fc86b3" +PKG_SHA256="9baf13b24f9e8fb180b516c9205bdd2f50408a086045523f9722896abb153f65" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libretro/common-overlays" +PKG_URL="https://github.com/libretro/common-overlays/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Collection of overlay files for use with libretro frontends, such as RetroArch." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/retroarch-overlays + cp -r * $INSTALL/usr/share/retroarch-overlays +} + +#post_makeinstall_target() { +#rm -rf /usr/share/retroarch-overlays/gamepads +#rm -rf /usr/share/retroarch-overlays/misc +#rm -rf /usr/share/retroarch-overlays/ipad +#rm -rf /usr/share/retroarch-overlays/keyboards +#} diff --git a/packages/games/tools/rg351p-js2xbox/package.mk b/packages/games/tools/rg351p-js2xbox/package.mk new file mode 100644 index 000000000..fe4226a95 --- /dev/null +++ b/packages/games/tools/rg351p-js2xbox/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="rg351p-js2xbox" +PKG_VERSION="5010b9b3734ea5741e359236a2b1a19f0d240bde" +PKG_ARCH="aarch64" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/christianhaitian/RG351P_virtual-gamepad" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp rg351p-js2xbox $INSTALL/usr/bin +} + diff --git a/packages/games/tools/rs97-commander-sdl2/package.mk b/packages/games/tools/rs97-commander-sdl2/package.mk new file mode 100644 index 000000000..2a57101b6 --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="rs97-commander-sdl2" +PKG_VERSION="7d0b939508602c1035283d9062d258d695ad1f0f" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/dhwz/rs97-commander-sdl2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_image SDL2_gfx SDL2_ttf patchelf" +PKG_PRIORITY="optional" +PKG_SECTION="tools" +PKG_SHORTDESC="Two-pane commander for RetroFW and RG-350 (fork of Dingux Commander)" + +pre_configure_target() { + if [ "${DEVICE}" = "RG351V" ] || [ "${DEVICE}" = "RG351P" ] + then + sed -i 's|std::ifstream cFile ("/tmp/joypads/"+gamepad+".cfg");|std::ifstream cFile ("/tmp/joypads/"+gamepad+"_SDL.cfg");|g' window.cpp + fi + sed -i "s|sdl2-config|${SYSROOT_PREFIX}/usr/bin/sdl2-config|" Makefile + + if [ "${DEVICE}" = "RG351V" ] || [ "${DEVICE}" = "RG351MP" ] + then + PKG_MAKE_OPTS_TARGET=" RG351V=1 CC=$CXX" + else + PKG_MAKE_OPTS_TARGET=" RG351P=1 CC=$CXX" + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + mkdir -p $INSTALL/usr/share/DinguxCommander/ + cp DinguxCommander $INSTALL/usr/bin/ + cp -rf res $INSTALL/usr/share/DinguxCommander/ +} diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351P/001-rs97-commander-path.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/001-rs97-commander-path.patch new file mode 100644 index 000000000..caea4681a --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/001-rs97-commander-path.patch @@ -0,0 +1,12 @@ +diff -rupN rs97.orig/Makefile rs97.new/Makefile +--- rs97.orig/Makefile 2021-01-30 19:16:54.824692064 -0500 ++++ rs97.new/Makefile 2021-01-30 19:17:40.041809856 -0500 +@@ -1,7 +1,7 @@ + CC ?= g++ + target = DinguxCommander + +-RESDIR ?= /emuelec/configs/fm/res/ ++RESDIR ?= /storage/.config/distribution/configs/fm/res/ + FILE_SYSTEM ?= /storage + PATH_DEFAULT ?= /media + PATH_DEFAULT_RIGHT ?= /storage/roms diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351P/002-button-reverse.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/002-button-reverse.patch new file mode 100644 index 000000000..078695e56 --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/002-button-reverse.patch @@ -0,0 +1,27 @@ +From f85e1d9a1292b81cdc5ea23bc5aa8953150fa69c Mon Sep 17 00:00:00 2001 +From: Zul <24516067+zulhailmie@users.noreply.github.com> +Date: Sat, 6 Feb 2021 12:45:39 +0800 +Subject: [PATCH] Reverse button A & B + +Key definitions can be found in def.h +--- + window.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/window.cpp b/window.cpp +index c85350d..a48a28a 100755 +--- a/window.cpp ++++ b/window.cpp +@@ -159,10 +159,10 @@ std::string input_start_btn; + key_event.key.keysym.sym = MYKEY_RIGHT; + // std::cout << "You pressed right! " << '\n'; + } else if (button.find("button="+input_a_btn+" s") != std::string::npos) { +- key_event.key.keysym.sym = MYKEY_PARENT; ++ key_event.key.keysym.sym = MYKEY_OPEN; + // std::cout << "You pressed a! " << '\n'; + } else if (button.find("button="+input_b_btn+" s") != std::string::npos) { +- key_event.key.keysym.sym = MYKEY_OPEN; ++ key_event.key.keysym.sym = MYKEY_PARENT; + // std::cout << "You pressed b! " << '\n'; + } else if (button.find("button="+input_x_btn+" s") != std::string::npos) { + key_event.key.keysym.sym = MYKEY_OPERATION; diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351P/003-linespacing-fix.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/003-linespacing-fix.patch new file mode 100644 index 000000000..b61b164cf --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351P/003-linespacing-fix.patch @@ -0,0 +1,34 @@ +From b695fba79982000a7ca1f5ec2c13e8cf5b1204b6 Mon Sep 17 00:00:00 2001 +From: Zul <24516067+zulhailmie@users.noreply.github.com> +Date: Sun, 7 Mar 2021 18:30:00 +0800 +Subject: [PATCH] Fix cropped text issue + +--- + Makefile | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/Makefile b/Makefile +index 6da5345..92f3c1a 100644 +--- a/Makefile ++++ b/Makefile +@@ -11,13 +11,15 @@ ifeq ($(ODROIDGO), 1) + SCREENW := 480 + SCREENH := 320 + FONTSIZE := 8 +- HEADERH := 17 + H_PADDING_TOP := 3 +- FOOTERH := 13 +- F_PADDING_TOP := 1 +- LINEH := 15 ++ F_PADDING_TOP := 3 + FONTTOUSE := $(RESDIR)/Fiery_Turk.ttf +- VIEWER_LINE_H := 13 ++ MAXLINES := 20 ++ LINESPACE := $(shell echo $$(($(SCREENH)/$(MAXLINES)))) ++ HEADERH := $(LINESPACE) ++ FOOTERH := $(LINESPACE) ++ LINEH := $(LINESPACE) ++ VIEWER_LINE_H := $(LINESPACE) + else + # todo detect resolution and set window to corrext size + SCREENW ?= 1920 diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351V/001-rs97-commander-path.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/001-rs97-commander-path.patch new file mode 100644 index 000000000..caea4681a --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/001-rs97-commander-path.patch @@ -0,0 +1,12 @@ +diff -rupN rs97.orig/Makefile rs97.new/Makefile +--- rs97.orig/Makefile 2021-01-30 19:16:54.824692064 -0500 ++++ rs97.new/Makefile 2021-01-30 19:17:40.041809856 -0500 +@@ -1,7 +1,7 @@ + CC ?= g++ + target = DinguxCommander + +-RESDIR ?= /emuelec/configs/fm/res/ ++RESDIR ?= /storage/.config/distribution/configs/fm/res/ + FILE_SYSTEM ?= /storage + PATH_DEFAULT ?= /media + PATH_DEFAULT_RIGHT ?= /storage/roms diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351V/002-button-reverse.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/002-button-reverse.patch new file mode 100644 index 000000000..078695e56 --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/002-button-reverse.patch @@ -0,0 +1,27 @@ +From f85e1d9a1292b81cdc5ea23bc5aa8953150fa69c Mon Sep 17 00:00:00 2001 +From: Zul <24516067+zulhailmie@users.noreply.github.com> +Date: Sat, 6 Feb 2021 12:45:39 +0800 +Subject: [PATCH] Reverse button A & B + +Key definitions can be found in def.h +--- + window.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/window.cpp b/window.cpp +index c85350d..a48a28a 100755 +--- a/window.cpp ++++ b/window.cpp +@@ -159,10 +159,10 @@ std::string input_start_btn; + key_event.key.keysym.sym = MYKEY_RIGHT; + // std::cout << "You pressed right! " << '\n'; + } else if (button.find("button="+input_a_btn+" s") != std::string::npos) { +- key_event.key.keysym.sym = MYKEY_PARENT; ++ key_event.key.keysym.sym = MYKEY_OPEN; + // std::cout << "You pressed a! " << '\n'; + } else if (button.find("button="+input_b_btn+" s") != std::string::npos) { +- key_event.key.keysym.sym = MYKEY_OPEN; ++ key_event.key.keysym.sym = MYKEY_PARENT; + // std::cout << "You pressed b! " << '\n'; + } else if (button.find("button="+input_x_btn+" s") != std::string::npos) { + key_event.key.keysym.sym = MYKEY_OPERATION; diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351V/003-linespacing-fix.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/003-linespacing-fix.patch new file mode 100644 index 000000000..b61b164cf --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/003-linespacing-fix.patch @@ -0,0 +1,34 @@ +From b695fba79982000a7ca1f5ec2c13e8cf5b1204b6 Mon Sep 17 00:00:00 2001 +From: Zul <24516067+zulhailmie@users.noreply.github.com> +Date: Sun, 7 Mar 2021 18:30:00 +0800 +Subject: [PATCH] Fix cropped text issue + +--- + Makefile | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/Makefile b/Makefile +index 6da5345..92f3c1a 100644 +--- a/Makefile ++++ b/Makefile +@@ -11,13 +11,15 @@ ifeq ($(ODROIDGO), 1) + SCREENW := 480 + SCREENH := 320 + FONTSIZE := 8 +- HEADERH := 17 + H_PADDING_TOP := 3 +- FOOTERH := 13 +- F_PADDING_TOP := 1 +- LINEH := 15 ++ F_PADDING_TOP := 3 + FONTTOUSE := $(RESDIR)/Fiery_Turk.ttf +- VIEWER_LINE_H := 13 ++ MAXLINES := 20 ++ LINESPACE := $(shell echo $$(($(SCREENH)/$(MAXLINES)))) ++ HEADERH := $(LINESPACE) ++ FOOTERH := $(LINESPACE) ++ LINEH := $(LINESPACE) ++ VIEWER_LINE_H := $(LINESPACE) + else + # todo detect resolution and set window to corrext size + SCREENW ?= 1920 diff --git a/packages/games/tools/rs97-commander-sdl2/patches/RG351V/004-resolution.patch b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/004-resolution.patch new file mode 100644 index 000000000..96702d436 --- /dev/null +++ b/packages/games/tools/rs97-commander-sdl2/patches/RG351V/004-resolution.patch @@ -0,0 +1,32 @@ +diff -rupN rs97.orig/def.h rs97.new/def.h +--- rs97.orig/def.h 2020-09-01 03:33:45.000000000 -0400 ++++ rs97.new/def.h 2021-04-10 09:04:57.030358139 -0400 +@@ -17,12 +17,12 @@ + + #ifndef SCREEN_WIDTH + // #define SCREEN_WIDTH 320 +-#define SCREEN_WIDTH 480 ++#define SCREEN_WIDTH 640 + #endif + + #ifndef SCREEN_HEIGHT + // #define SCREEN_HEIGHT 240 +-#define SCREEN_HEIGHT 320 ++#define SCREEN_HEIGHT 480 + #endif + + #ifndef SCREEN_BPP +diff -rupN rs97.orig/Makefile rs97.new/Makefile +--- rs97.orig/Makefile 2020-09-01 03:33:45.000000000 -0400 ++++ rs97.new/Makefile 2021-04-10 09:05:13.174397946 -0400 +@@ -8,8 +8,8 @@ PATH_DEFAULT_RIGHT ?= /storage/roms + + # set variables for the OGA screen + ifeq ($(ODROIDGO), 1) +- SCREENW := 480 +- SCREENH := 320 ++ SCREENW := 640 ++ SCREENH := 480 + FONTSIZE := 8 + HEADERH := 17 + H_PADDING_TOP := 3 diff --git a/packages/graphics/SDL/SDL_net/package.mk b/packages/graphics/SDL/SDL_net/package.mk new file mode 100644 index 000000000..e5c8ef38c --- /dev/null +++ b/packages/graphics/SDL/SDL_net/package.mk @@ -0,0 +1,34 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 2 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="SDL_net" +PKG_VERSION="1.2.8" +PKG_SHA256="5f4a7a8bb884f793c278ac3f3713be41980c5eedccecff0260411347714facb4" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libsdl.org/" +PKG_URL="https://www.libsdl.org/projects/SDL_net/release/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain yasm:host alsa-lib systemd dbus SDL SDL_net:host" +PKG_DEPENDS_HOST="SDL:host" +PKG_SECTION="multimedia" +PKG_SHORTDESC="This is a small sample cross-platform networking library, with a sample chat client and server application." +PKG_LONGDESC="This is a small sample cross-platform networking library, with a sample chat client and server application." + +PKG_IS_ADDON="no" +PKG_USE_CMAKE="no" +PKG_AUTORECONF="no" diff --git a/packages/graphics/SDL/SDL_sound/package.mk b/packages/graphics/SDL/SDL_sound/package.mk new file mode 100644 index 000000000..8a0ee2b89 --- /dev/null +++ b/packages/graphics/SDL/SDL_sound/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="SDL_sound" +PKG_VERSION="f0d57c9b72d8" +PKG_SHA256="f4848b27a79dd9bcf4720c1751730772472f501ddf5432be2e93a146fa7e57cb" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.icculus.org/SDL_sound/" +PKG_URL="http://hg.icculus.org/icculus/SDL_sound/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib SDL2" +PKG_LONGDESC="SDL_sound library" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --disable-speex \ + ac_cv_path_SDL2_CONFIG=$SYSROOT_PREFIX/usr/bin/sdl2-config" + +post_unpack() { + touch $PKG_BUILD/README +} + +pre_configure_target() { + export LDFLAGS="$LDFLAGS -lm" +} + +post_makeinstall_target() { + ln -sf ${PKG_ORIG_SYSROOT_PREFIX:-${SYSROOT_PREFIX}}/usr/include/SDL/SDL_sound.h ${PKG_ORIG_SYSROOT_PREFIX:-${SYSROOT_PREFIX}}/usr/include/SDL2/SDL_sound.h +} diff --git a/packages/graphics/SDL/package.mk b/packages/graphics/SDL/package.mk new file mode 100644 index 000000000..d8cfc9c6b --- /dev/null +++ b/packages/graphics/SDL/package.mk @@ -0,0 +1,119 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 2 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="SDL" +PKG_VERSION="92927a9b689c55c5879add79378e24f9443f56f4" +#PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libsdl.org/" +PKG_URL="https://github.com/libsdl-org/SDL-1.2/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain yasm:host alsa-lib systemd dbus SDL:host" +PKG_SECTION="multimedia" +PKG_SHORTDESC="SDL: A cross-platform Graphic API" +PKG_LONGDESC="Simple DirectMedia Layer is a cross-platform multimedia library designed to provide fast access to the graphics framebuffer and audio device. It is used by MPEG playback software, emulators, and many popular games, including the award winning Linux port of 'Civilization: Call To Power.' Simple DirectMedia Layer supports Linux, Win32, BeOS, MacOS, Solaris, IRIX, and FreeBSD." + +PKG_IS_ADDON="no" +PKG_USE_CMAKE="no" +PKG_AUTORECONF="no" + +PKG_CONFIGURE_OPTS_TARGET="--enable-shared \ + --enable-libc \ + --enable-gcc-atomics \ + --enable-atomic \ + --enable-audio \ + --enable-render \ + --enable-events \ + --enable-joystick \ + --enable-haptic \ + --enable-power \ + --enable-filesystem \ + --enable-threads \ + --enable-timers \ + --enable-file \ + --enable-loadso \ + --enable-cpuinfo \ + --enable-assembly \ + --disable-altivec \ + --disable-oss \ + --enable-alsa --disable-alsatest --enable-alsa-shared \ + --with-alsa-prefix=$SYSROOT_PREFIX/usr/lib \ + --with-alsa-inc-prefix=$SYSROOT_PREFIX/usr/include \ + --disable-esd --disable-esdtest --disable-esd-shared \ + --disable-arts --disable-arts-shared \ + --disable-nas --enable-nas-shared \ + --disable-sndio --enable-sndio-shared \ + --disable-diskaudio \ + --disable-dummyaudio \ + --disable-video-wayland --enable-video-wayland-qt-touch --disable-wayland-shared \ + --disable-video-mir --disable-mir-shared \ + --disable-video-cocoa \ + --enable-video-directfb --enable-directfb-shared \ + --disable-fusionsound --disable-fusionsound-shared \ + --disable-video-dummy \ + --enable-libudev \ + --enable-dbus \ + --disable-input-tslib \ + --enable-pthreads --enable-pthread-sem \ + --disable-directx \ + --enable-sdl-dlopen \ + --disable-clock_gettime \ + --disable-rpath \ + --disable-render-d3d \ + --enable-arm-neon" + + +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --enable-video --disable-video-x11 --disable-x11-shared" +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-xcursor --disable-video-x11-xinerama" +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-xinput --disable-video-x11-xrandr" +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-scrnsaver --disable-video-x11-xshape" +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-vm --without-x" + +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET --disable-video --disable-video-x11 --disable-x11-shared" +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-xcursor --disable-video-x11-xinerama" +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-xinput --disable-video-x11-xrandr" +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-scrnsaver --disable-video-x11-xshape" +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET --disable-video-x11-vm --without-x" + + +if [ ! "$OPENGL" = "no" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $OPENGL glu" + + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --enable-video-opengl --disable-video-opengles" +else + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-video-opengl --enable-video-opengles --enable-video-fbcon" +fi + +if [ "$PULSEAUDIO_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET pulseaudio" + + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --enable-pulseaudio --enable-pulseaudio-shared" +else + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --disable-pulseaudio --disable-pulseaudio-shared" +fi + +pre_make_target() { +# dont build parallel + MAKEFLAGS=-j1 +} + +post_makeinstall_target() { + sed -i "s:\(['=\" ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" $SYSROOT_PREFIX/usr/bin/sdl-config + + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/SDL/yasm/package.mk b/packages/graphics/SDL/yasm/package.mk new file mode 100644 index 000000000..049a4473c --- /dev/null +++ b/packages/graphics/SDL/yasm/package.mk @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 2 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="yasm" +PKG_VERSION="1.3.0" +PKG_SHA256="3dce6601b495f5b3d45b59f7d2492a340ee7e84b5beca17e48f862502bd5603f" +PKG_ARCH="any" +PKG_LICENSE="BSD" +PKG_SITE="http://www.tortall.net/projects/yasm/" +PKG_URL="http://www.tortall.net/projects/yasm/releases/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="" +PKG_SECTION="toolchain/lang" +PKG_SHORTDESC="yasm: A complete rewrite of the NASM assembler" +PKG_LONGDESC="Yasm is a complete rewrite of the NASM assembler under the new BSD License (some portions are under other licenses, see COPYING for details). It is designed from the ground up to allow for multiple assembler syntaxes to be supported (eg, NASM, TASM, GAS, etc.) in addition to multiple output object formats and even multiple instruction sets. Another primary module of the overall design is an optimizer module." + +PKG_IS_ADDON="no" +PKG_USE_CMAKE="no" +PKG_AUTORECONF="no" + +PKG_CONFIGURE_OPTS_HOST="--disable-debug \ + --disable-warnerror \ + --disable-profiling \ + --disable-gcov \ + --disable-python \ + --disable-python-bindings \ + --enable-nls \ + --disable-rpath \ + --without-dmalloc \ + --with-gnu-ld \ + --without-libiconv-prefix \ + --without-libintl-prefix" diff --git a/packages/graphics/SDL2-14/package.mk b/packages/graphics/SDL2-14/package.mk new file mode 100644 index 000000000..9eb4a7619 --- /dev/null +++ b/packages/graphics/SDL2-14/package.mk @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="SDL2-14" +PKG_VERSION="0f1dedabd1bb1af84e368e00b3ededbb9fce996f" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/dhwz/SDL2" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib systemd dbus $OPENGLES pulseaudio libsamplerate" +PKG_LONGDESC="Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware." +PKG_TOOLCHAIN="cmake-make" + +PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libdrm librga" + +pre_configure_target(){ + PKG_CMAKE_OPTS_TARGET="-DSDL_STATIC=OFF \ + -DLIBC=ON \ + -DGCC_ATOMICS=ON \ + -DALTIVEC=OFF \ + -DOSS=OFF \ + -DALSA=ON \ + -DALSA_SHARED=ON \ + -DJACK=OFF \ + -DJACK_SHARED=OFF \ + -DESD=OFF \ + -DESD_SHARED=OFF \ + -DARTS=OFF \ + -DARTS_SHARED=OFF \ + -DNAS=OFF \ + -DNAS_SHARED=OFF \ + -DLIBSAMPLERATE=ON \ + -DLIBSAMPLERATE_SHARED=ON \ + -DSNDIO=OFF \ + -DDISKAUDIO=OFF \ + -DDUMMYAUDIO=OFF \ + -DVIDEO_WAYLAND=OFF \ + -DVIDEO_WAYLAND_QT_TOUCH=ON \ + -DWAYLAND_SHARED=OFF \ + -DVIDEO_MIR=OFF \ + -DMIR_SHARED=OFF \ + -DVIDEO_COCOA=OFF \ + -DVIDEO_DIRECTFB=OFF \ + -DVIDEO_VIVANTE=OFF \ + -DDIRECTFB_SHARED=OFF \ + -DFUSIONSOUND=OFF \ + -DFUSIONSOUND_SHARED=OFF \ + -DVIDEO_DUMMY=OFF \ + -DINPUT_TSLIB=OFF \ + -DPTHREADS=ON \ + -DPTHREADS_SEM=ON \ + -DDIRECTX=OFF \ + -DSDL_DLOPEN=ON \ + -DCLOCK_GETTIME=OFF \ + -DRPATH=OFF \ + -DRENDER_D3D=OFF \ + -DVIDEO_X11=OFF \ + -DVIDEO_OPENGLES=ON \ + -DVIDEO_VULKAN=OFF \ + -DVIDEO_KMSDRM=ON \ + -DPULSEAUDIO=ON" + export LDFLAGS="${LDFLAGS} -lrga" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib + cp $PKG_BUILD/.${TARGET_NAME}/libSDL2-2.0.so.0.14.1 $INSTALL/usr/lib/libSDL2-2.0.so.0.14.0 + chmod +x $INSTALL/usr/lib/libSDL2-2.0.so.0.14.0 +} diff --git a/packages/graphics/SDL2/package.mk b/packages/graphics/SDL2/package.mk new file mode 100644 index 000000000..c9817322d --- /dev/null +++ b/packages/graphics/SDL2/package.mk @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) +# Copyright (C) 2022-present Fewtarius + +PKG_NAME="SDL2" +PKG_VERSION="2.0.16" +PKG_SHA256="65be9ff6004034b5b2ce9927b5a4db1814930f169c4b2dae0a1e4697075f287b" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libsdl.org/" +PKG_URL="https://www.libsdl.org/release/SDL2-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib systemd dbus ${OPENGLES} pulseaudio libdrm librga" +PKG_LONGDESC="Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware." +PKG_DEPENDS_HOST="toolchain:host distutilscross:host" +PKG_PATCH_DIRS+="${DEVICE}" + + +pre_make_host() { + sed -i "s| -lrga||g" ${PKG_BUILD}/CMakeLists.txt +} + +pre_make_target() { + if ! `grep -rnw "${PKG_BUILD}/CMakeLists.txt" -e '-lrga'`; then + sed -i "s|--no-undefined|--no-undefined -lrga|" ${PKG_BUILD}/CMakeLists.txt + fi +} + +pre_configure_target(){ + PKG_CMAKE_OPTS_TARGET="-DSDL_STATIC=OFF \ + -DLIBC=ON \ + -DGCC_ATOMICS=ON \ + -DALTIVEC=OFF \ + -DOSS=OFF \ + -DALSA=ON \ + -DALSA_SHARED=ON \ + -DJACK=OFF \ + -DJACK_SHARED=OFF \ + -DESD=OFF \ + -DESD_SHARED=OFF \ + -DARTS=OFF \ + -DARTS_SHARED=OFF \ + -DNAS=OFF \ + -DNAS_SHARED=OFF \ + -DLIBSAMPLERATE=OFF \ + -DLIBSAMPLERATE_SHARED=OFF \ + -DSNDIO=OFF \ + -DDISKAUDIO=OFF \ + -DDUMMYAUDIO=OFF \ + -DVIDEO_WAYLAND=OFF \ + -DVIDEO_WAYLAND_QT_TOUCH=ON \ + -DWAYLAND_SHARED=OFF \ + -DVIDEO_MIR=OFF \ + -DMIR_SHARED=OFF \ + -DVIDEO_COCOA=OFF \ + -DVIDEO_DIRECTFB=OFF \ + -DVIDEO_VIVANTE=OFF \ + -DDIRECTFB_SHARED=OFF \ + -DFUSIONSOUND=OFF \ + -DFUSIONSOUND_SHARED=OFF \ + -DVIDEO_DUMMY=OFF \ + -DINPUT_TSLIB=OFF \ + -DPTHREADS=ON \ + -DPTHREADS_SEM=ON \ + -DDIRECTX=OFF \ + -DSDL_DLOPEN=ON \ + -DCLOCK_GETTIME=OFF \ + -DRPATH=OFF \ + -DRENDER_D3D=OFF \ + -DVIDEO_X11=OFF \ + -DVIDEO_OPENGLES=ON \ + -DVIDEO_VULKAN=OFF \ + -DVIDEO_KMSDRM=ON \ + -DPULSEAUDIO=ON" +} + +post_makeinstall_target() { + sed -e "s:\(['=LI]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i $SYSROOT_PREFIX/usr/bin/sdl2-config + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/SDL2/patches/0001-kmsdrm-Workaround-missing-gbm_bo_get_offset-and-SDL_.patch b/packages/graphics/SDL2/patches/0001-kmsdrm-Workaround-missing-gbm_bo_get_offset-and-SDL_.patch new file mode 100644 index 000000000..7af1506cd --- /dev/null +++ b/packages/graphics/SDL2/patches/0001-kmsdrm-Workaround-missing-gbm_bo_get_offset-and-SDL_.patch @@ -0,0 +1,52 @@ +From b2d17230779c9da13433dc9f3abf37ee1e6da85d Mon Sep 17 00:00:00 2001 +From: JohnnyonFlame +Date: Sat, 4 Dec 2021 02:38:47 +0000 +Subject: [PATCH] kmsdrm: Workaround missing gbm_bo_get_offset and + SDL_GL_CONTEXT_PROFILE defaults + +--- + src/video/kmsdrm/SDL_kmsdrmopengles.c | 14 ++++++++++---- + src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +- + 2 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c +index 55a53df76..3d76284fd 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c ++++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c +@@ -41,11 +41,17 @@ KMSDRM_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor) + { + /* if SDL was _also_ built with the Raspberry Pi driver (so we're + definitely a Pi device), default to GLES2. */ +-#if SDL_VIDEO_DRIVER_RPI +- *mask = SDL_GL_CONTEXT_PROFILE_ES; +- *major = 2; +- *minor = 0; ++ /* JohnnyonFlame: We want to use GLESv2 as a default for compatibility ++ with SDL 2.0.10 builds, but offer the ability to use the OpenGL defaults ++ if ever needed. */ ++#ifndef SDL_VIDEO_DRIVER_RPI ++ if (!SDL_getenv("SDL_DEFAULT_CONTEXT_PROFILE")) + #endif ++ { ++ *mask = SDL_GL_CONTEXT_PROFILE_ES; ++ *major = 2; ++ *minor = 0; ++ } + } + + int +diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h +index ea3d8d116..b17f823c9 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmsym.h ++++ b/src/video/kmsdrm/SDL_kmsdrmsym.h +@@ -104,7 +104,7 @@ SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo)) + SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo)) + SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo)) + SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_format,(struct gbm_bo *bo)) +-SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane)) ++//SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane)) + SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo)) + SDL_KMSDRM_SYM(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count)) + SDL_KMSDRM_SYM(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo)) +-- +2.25.1 diff --git a/packages/graphics/SDL2/patches/0002-egl_swapinterval_fix.patch b/packages/graphics/SDL2/patches/0002-egl_swapinterval_fix.patch new file mode 100644 index 000000000..f1d094bce --- /dev/null +++ b/packages/graphics/SDL2/patches/0002-egl_swapinterval_fix.patch @@ -0,0 +1,25 @@ +diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c +index 87d693e8d..891d588c4 100644 +--- a/src/video/SDL_egl.c ++++ b/src/video/SDL_egl.c +@@ -1032,7 +1032,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface) + return NULL; + } + +- _this->egl_data->egl_swapinterval = 0; ++ _this->egl_data->egl_swapinterval = 1; + + if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) { + /* Save the SDL error set by SDL_EGL_MakeCurrent */ +diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c +index 3d76284fd..72163286b 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c ++++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c +@@ -82,6 +82,7 @@ int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) { + return SDL_SetError("EGL not initialized"); + } + ++ interval = 1; + if (interval == 0 || interval == 1) { + _this->egl_data->egl_swapinterval = interval; + } else { diff --git a/packages/graphics/SDL2/patches/RG351P/0005-SDL-2.0.16.rotation.patch b/packages/graphics/SDL2/patches/RG351P/0005-SDL-2.0.16.rotation.patch new file mode 100644 index 000000000..baa4a8c92 --- /dev/null +++ b/packages/graphics/SDL2/patches/RG351P/0005-SDL-2.0.16.rotation.patch @@ -0,0 +1,360 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -557,7 +557,7 @@ + check_c_compiler_flag("" HAVE_NO_UNDEFINED) + set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) + if(HAVE_NO_UNDEFINED AND NOT (USE_CLANG AND WINDOWS)) +- list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined") ++ list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined -lrga") + endif() + endif() + endif() +diff --git a/Makefile.in b/Makefile.in +index 65ccc55..bf4e3aa 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -22,7 +22,7 @@ CC = @CC@ + INCLUDE = @INCLUDE@ + CFLAGS = @BUILD_CFLAGS@ + EXTRA_CFLAGS = @EXTRA_CFLAGS@ +-LDFLAGS = @BUILD_LDFLAGS@ ++LDFLAGS = @BUILD_LDFLAGS@ -lrga + EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ + LIBTOOL = @LIBTOOL@ + INSTALL = @INSTALL@ +diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c +index 55a53df..21fb124 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c ++++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c +@@ -34,6 +34,9 @@ + #define EGL_PLATFORM_GBM_MESA 0x31D7 + #endif + ++extern rga_info_t src_info; ++extern rga_info_t dst_info; ++ + /* EGL implementation of SDL OpenGL support */ + + void +@@ -92,6 +95,7 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { + SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); + KMSDRM_FBInfo *fb_info; + int ret = 0; ++ struct gbm_bo* rga_buffer = NULL; + + /* Always wait for the previous issued flip before issuing a new one, + even if you do async flips. */ +@@ -135,12 +139,26 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { + } + + /* Get an actual usable fb for the next front buffer. */ +- fb_info = KMSDRM_FBFromBO(_this, windata->next_bo); ++ if (src_info.fd) { ++ close(src_info.fd); ++ } ++ src_info.fd = KMSDRM_gbm_bo_get_fd(windata->next_bo); ++ dst_info.fd = viddata->rga_buffer_prime_fds[viddata->rga_buffer_index]; ++ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) { ++ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, ++ "Failed to rga blit\n"); ++ } ++ ++ rga_buffer = viddata->rga_buffers[viddata->rga_buffer_index]; ++ fb_info = KMSDRM_FBFromBO(_this, rga_buffer); ++ + if (!fb_info) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get a framebuffer"); + return 0; + } + ++ viddata->rga_buffer_index = (viddata->rga_buffer_index + 1) % RGA_BUFFERS_MAX; ++ + if (!windata->bo) { + /* On the first swap, immediately present the new front buffer. Before + drmModePageFlip can be used the CRTC has to be configured to use +diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h +index ea3d8d1..d3b123b 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmsym.h ++++ b/src/video/kmsdrm/SDL_kmsdrmsym.h +@@ -121,6 +121,7 @@ SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm, + SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf)) + SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf)) + SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo)) ++SDL_KMSDRM_SYM(int,gbm_bo_get_fd,(struct gbm_bo *bo)) + + + #undef SDL_KMSDRM_MODULE +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c +index cedc739..f585a69 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c +@@ -44,6 +44,7 @@ + #include "SDL_kmsdrmopengles.h" + #include "SDL_kmsdrmmouse.h" + #include "SDL_kmsdrmdyn.h" ++#include + #include "SDL_kmsdrmvulkan.h" + #include + #include +@@ -71,6 +72,9 @@ static SDL_bool openbsd69orgreater = SDL_FALSE; + #define EGL_PLATFORM_GBM_MESA 0x31D7 + #endif + ++rga_info_t src_info = {0}; ++rga_info_t dst_info = {0}; ++ + static int + check_modestting(int devindex) + { +@@ -332,6 +336,46 @@ KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data) + SDL_free(fb_info); + } + ++static void ++KMSDRM_InitRotateBuffer(_THIS, int frameWidth, int frameHeight) ++{ ++ int l_frameHeight; ++ SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); ++ ++ // initialize 2D raster graphic acceleration unit (RGA) ++ c_RkRgaInit(); ++ ++ l_frameHeight = frameHeight; ++ if(l_frameHeight % 32 != 0) { ++ l_frameHeight = (frameHeight + 32) & (~31); ++ } ++ ++ // create buffers for RGA with adjusted stride ++ for (int i = 0; i < RGA_BUFFERS_MAX; ++i) ++ { ++ viddata->rga_buffers[i] = KMSDRM_gbm_bo_create(viddata->gbm_dev, ++ frameWidth, l_frameHeight, ++ GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); ++ assert(viddata->rga_buffers[i]); ++ ++ viddata->rga_buffer_prime_fds[i] = KMSDRM_gbm_bo_get_fd(viddata->rga_buffers[i]); ++ } ++ viddata->rga_buffer_index = 0; ++ ++ // setup rotation ++ src_info.fd = -1; ++ src_info.mmuFlag = 1; ++ src_info.rotation = HAL_TRANSFORM_ROT_270; ++ ++ // swap width and height and adjust stride here because our source buffer is 480x854 ++ rga_set_rect(&src_info.rect, 0, 0, frameHeight, frameWidth, l_frameHeight, frameWidth, RK_FORMAT_BGRA_8888); ++ ++ dst_info.fd = -1; ++ dst_info.mmuFlag = 1; ++ ++ rga_set_rect(&dst_info.rect, 0, 0, frameWidth, frameHeight, frameWidth, frameHeight, RK_FORMAT_BGRA_8888); ++} ++ + KMSDRM_FBInfo * + KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo) + { +@@ -704,8 +748,8 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource + modedata->mode_index = mode_index; + + display.driverdata = dispdata; +- display.desktop_mode.w = dispdata->mode.hdisplay; +- display.desktop_mode.h = dispdata->mode.vdisplay; ++ display.desktop_mode.w = dispdata->mode.vdisplay; ++ display.desktop_mode.h = dispdata->mode.hdisplay; + display.desktop_mode.refresh_rate = dispdata->mode.vrefresh; + display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888; + display.desktop_mode.driverdata = modedata; +@@ -980,7 +1024,7 @@ KMSDRM_DirtySurfaces(SDL_Window *window) { + or SetWindowFullscreen, send a fake event for now since the actual + recreation is deferred */ + KMSDRM_GetModeToSet(window, &mode); +- SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.hdisplay, mode.vdisplay); ++ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.vdisplay, mode.hdisplay); + } + + /* This determines the size of the fb, which comes from the GBM surface +@@ -1016,13 +1060,13 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) + mode that's set in sync with what SDL_video.c thinks is set */ + KMSDRM_GetModeToSet(window, &dispdata->mode); + +- display->current_mode.w = dispdata->mode.hdisplay; +- display->current_mode.h = dispdata->mode.vdisplay; ++ display->current_mode.w = dispdata->mode.vdisplay; ++ display->current_mode.h = dispdata->mode.hdisplay; + display->current_mode.refresh_rate = dispdata->mode.vrefresh; + display->current_mode.format = SDL_PIXELFORMAT_ARGB8888; + + windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, +- dispdata->mode.hdisplay, dispdata->mode.vdisplay, ++ dispdata->mode.vdisplay, dispdata->mode.hdisplay, + surface_fmt, surface_flags); + + if (!windata->gs) { +@@ -1046,7 +1090,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) + ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context); + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, +- dispdata->mode.hdisplay, dispdata->mode.vdisplay); ++ dispdata->mode.vdisplay, dispdata->mode.hdisplay); + + windata->egl_surface_dirty = SDL_FALSE; + +@@ -1151,8 +1195,8 @@ KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display) + modedata->mode_index = i; + } + +- mode.w = conn->modes[i].hdisplay; +- mode.h = conn->modes[i].vdisplay; ++ mode.w = conn->modes[i].vdisplay; ++ mode.h = conn->modes[i].hdisplay; + mode.refresh_rate = conn->modes[i].vrefresh; + mode.format = SDL_PIXELFORMAT_ARGB8888; + mode.driverdata = modedata; +@@ -1264,6 +1308,14 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window) + /*********************************************************************/ + SDL_free(window->driverdata); + window->driverdata = NULL; ++ ++ for (int i = 0; i < RGA_BUFFERS_MAX; ++i) { ++ close(viddata->rga_buffer_prime_fds[i]); ++ } ++ if (src_info.fd) { ++ close(src_info.fd); ++ } ++ c_RkRgaDeInit(); + } + + /**********************************************************************/ +@@ -1283,6 +1335,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) + NativeDisplayType egl_display; + drmModeModeInfo *mode; + int ret = 0; ++ SDL_DisplayData *data; + + /* Allocate window internal data */ + windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); +@@ -1391,6 +1444,9 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + ++ data = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; ++ KMSDRM_InitRotateBuffer(_this, data->mode.hdisplay, data->mode.vdisplay); ++ + /* Tell the app that the window has moved to top-left. */ + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, 0, 0); + +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h +index b172eb9..c4bd1f5 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h +@@ -32,6 +32,10 @@ + #include + #include + #include ++#include ++#include ++ ++#define RGA_BUFFERS_MAX (3) + + typedef struct SDL_VideoData + { +@@ -53,6 +57,10 @@ typedef struct SDL_VideoData + open 1 FD and create 1 gbm device. */ + SDL_bool gbm_init; + ++ struct gbm_bo* rga_buffers[RGA_BUFFERS_MAX]; ++ int rga_buffer_prime_fds[RGA_BUFFERS_MAX]; ++ int rga_buffer_index; ++ + } SDL_VideoData; + + +diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c +index b45909027..231d5b1d6 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c ++++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c +@@ -73,6 +73,7 @@ KMSDRM_DestroyCursorBO (_THIS, SDL_VideoDisplay *display) + if (dispdata->cursor_bo) { + KMSDRM_gbm_bo_destroy(dispdata->cursor_bo); + dispdata->cursor_bo = NULL; ++ dispdata->cursor_bo_drm_fd = -1; + } + } + +@@ -116,6 +117,8 @@ KMSDRM_CreateCursorBO (SDL_VideoDisplay *display) { + SDL_SetError("Could not create GBM cursor BO"); + return; + } ++ ++ dispdata->cursor_bo_drm_fd = viddata->drm_fd; + } + + /* Remove a cursor buffer from a display's DRM cursor BO. */ +@@ -384,11 +387,9 @@ KMSDRM_WarpMouseGlobal(int x, int y) + + /* And now update the cursor graphic position on screen. */ + if (dispdata->cursor_bo) { +- int drm_fd; + int ret = 0; + +- drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(dispdata->cursor_bo)); +- ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, x, y); ++ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, x, y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); +@@ -437,7 +438,6 @@ static void + KMSDRM_MoveCursor(SDL_Cursor * cursor) + { + SDL_Mouse *mouse = SDL_GetMouse(); +- int drm_fd; + int ret = 0; + + /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity! +@@ -452,9 +452,7 @@ KMSDRM_MoveCursor(SDL_Cursor * cursor) + return; + } + +- drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(dispdata->cursor_bo)); +- +- ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y); ++ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); +diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h +index 90d128582..e368c5d0d 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmsym.h ++++ b/src/video/kmsdrm/SDL_kmsdrmsym.h +@@ -95,7 +95,6 @@ SDL_KMSDRM_SYM(int,drmModeSetPlane,(int fd, uint32_t plane_id, uint32_t crtc_id, + /* Planes stuff ends. */ + + SDL_KMSDRM_MODULE(GBM) +-SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) + SDL_KMSDRM_SYM(int,gbm_device_is_format_supported,(struct gbm_device *gbm, + uint32_t format, uint32_t usage)) + SDL_KMSDRM_SYM(void,gbm_device_destroy,(struct gbm_device *gbm)) +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c +index dbc1b4455..3308dd963 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c +@@ -555,6 +555,7 @@ KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resources) { + /* Initialize some of the members of the new display's driverdata + to sane values. */ + dispdata->cursor_bo = NULL; ++ dispdata->cursor_bo_drm_fd = -1; + + /* Since we create and show the default cursor on KMSDRM_InitMouse(), + and we call KMSDRM_InitMouse() when we create a window, we have to know +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h +index b172eb90f..566fc852d 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h +@@ -77,6 +77,7 @@ typedef struct SDL_DisplayData + where we may not have an SDL_Cursor at all (so no SDL_Cursor driverdata). + There's only one cursor GBM BO because we only support one cursor. */ + struct gbm_bo *cursor_bo; ++ int cursor_bo_drm_fd; + uint64_t cursor_w, cursor_h; + + SDL_bool default_cursor_init; diff --git a/packages/graphics/SDL2/patches/RG552/0005-SDL-2.0.16.rotation.patch b/packages/graphics/SDL2/patches/RG552/0005-SDL-2.0.16.rotation.patch new file mode 100644 index 000000000..baa4a8c92 --- /dev/null +++ b/packages/graphics/SDL2/patches/RG552/0005-SDL-2.0.16.rotation.patch @@ -0,0 +1,360 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -557,7 +557,7 @@ + check_c_compiler_flag("" HAVE_NO_UNDEFINED) + set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) + if(HAVE_NO_UNDEFINED AND NOT (USE_CLANG AND WINDOWS)) +- list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined") ++ list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined -lrga") + endif() + endif() + endif() +diff --git a/Makefile.in b/Makefile.in +index 65ccc55..bf4e3aa 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -22,7 +22,7 @@ CC = @CC@ + INCLUDE = @INCLUDE@ + CFLAGS = @BUILD_CFLAGS@ + EXTRA_CFLAGS = @EXTRA_CFLAGS@ +-LDFLAGS = @BUILD_LDFLAGS@ ++LDFLAGS = @BUILD_LDFLAGS@ -lrga + EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ + LIBTOOL = @LIBTOOL@ + INSTALL = @INSTALL@ +diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c +index 55a53df..21fb124 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c ++++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c +@@ -34,6 +34,9 @@ + #define EGL_PLATFORM_GBM_MESA 0x31D7 + #endif + ++extern rga_info_t src_info; ++extern rga_info_t dst_info; ++ + /* EGL implementation of SDL OpenGL support */ + + void +@@ -92,6 +95,7 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { + SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); + KMSDRM_FBInfo *fb_info; + int ret = 0; ++ struct gbm_bo* rga_buffer = NULL; + + /* Always wait for the previous issued flip before issuing a new one, + even if you do async flips. */ +@@ -135,12 +139,26 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { + } + + /* Get an actual usable fb for the next front buffer. */ +- fb_info = KMSDRM_FBFromBO(_this, windata->next_bo); ++ if (src_info.fd) { ++ close(src_info.fd); ++ } ++ src_info.fd = KMSDRM_gbm_bo_get_fd(windata->next_bo); ++ dst_info.fd = viddata->rga_buffer_prime_fds[viddata->rga_buffer_index]; ++ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) { ++ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, ++ "Failed to rga blit\n"); ++ } ++ ++ rga_buffer = viddata->rga_buffers[viddata->rga_buffer_index]; ++ fb_info = KMSDRM_FBFromBO(_this, rga_buffer); ++ + if (!fb_info) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get a framebuffer"); + return 0; + } + ++ viddata->rga_buffer_index = (viddata->rga_buffer_index + 1) % RGA_BUFFERS_MAX; ++ + if (!windata->bo) { + /* On the first swap, immediately present the new front buffer. Before + drmModePageFlip can be used the CRTC has to be configured to use +diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h +index ea3d8d1..d3b123b 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmsym.h ++++ b/src/video/kmsdrm/SDL_kmsdrmsym.h +@@ -121,6 +121,7 @@ SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm, + SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf)) + SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf)) + SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo)) ++SDL_KMSDRM_SYM(int,gbm_bo_get_fd,(struct gbm_bo *bo)) + + + #undef SDL_KMSDRM_MODULE +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c +index cedc739..f585a69 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c +@@ -44,6 +44,7 @@ + #include "SDL_kmsdrmopengles.h" + #include "SDL_kmsdrmmouse.h" + #include "SDL_kmsdrmdyn.h" ++#include + #include "SDL_kmsdrmvulkan.h" + #include + #include +@@ -71,6 +72,9 @@ static SDL_bool openbsd69orgreater = SDL_FALSE; + #define EGL_PLATFORM_GBM_MESA 0x31D7 + #endif + ++rga_info_t src_info = {0}; ++rga_info_t dst_info = {0}; ++ + static int + check_modestting(int devindex) + { +@@ -332,6 +336,46 @@ KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data) + SDL_free(fb_info); + } + ++static void ++KMSDRM_InitRotateBuffer(_THIS, int frameWidth, int frameHeight) ++{ ++ int l_frameHeight; ++ SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); ++ ++ // initialize 2D raster graphic acceleration unit (RGA) ++ c_RkRgaInit(); ++ ++ l_frameHeight = frameHeight; ++ if(l_frameHeight % 32 != 0) { ++ l_frameHeight = (frameHeight + 32) & (~31); ++ } ++ ++ // create buffers for RGA with adjusted stride ++ for (int i = 0; i < RGA_BUFFERS_MAX; ++i) ++ { ++ viddata->rga_buffers[i] = KMSDRM_gbm_bo_create(viddata->gbm_dev, ++ frameWidth, l_frameHeight, ++ GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); ++ assert(viddata->rga_buffers[i]); ++ ++ viddata->rga_buffer_prime_fds[i] = KMSDRM_gbm_bo_get_fd(viddata->rga_buffers[i]); ++ } ++ viddata->rga_buffer_index = 0; ++ ++ // setup rotation ++ src_info.fd = -1; ++ src_info.mmuFlag = 1; ++ src_info.rotation = HAL_TRANSFORM_ROT_270; ++ ++ // swap width and height and adjust stride here because our source buffer is 480x854 ++ rga_set_rect(&src_info.rect, 0, 0, frameHeight, frameWidth, l_frameHeight, frameWidth, RK_FORMAT_BGRA_8888); ++ ++ dst_info.fd = -1; ++ dst_info.mmuFlag = 1; ++ ++ rga_set_rect(&dst_info.rect, 0, 0, frameWidth, frameHeight, frameWidth, frameHeight, RK_FORMAT_BGRA_8888); ++} ++ + KMSDRM_FBInfo * + KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo) + { +@@ -704,8 +748,8 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource + modedata->mode_index = mode_index; + + display.driverdata = dispdata; +- display.desktop_mode.w = dispdata->mode.hdisplay; +- display.desktop_mode.h = dispdata->mode.vdisplay; ++ display.desktop_mode.w = dispdata->mode.vdisplay; ++ display.desktop_mode.h = dispdata->mode.hdisplay; + display.desktop_mode.refresh_rate = dispdata->mode.vrefresh; + display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888; + display.desktop_mode.driverdata = modedata; +@@ -980,7 +1024,7 @@ KMSDRM_DirtySurfaces(SDL_Window *window) { + or SetWindowFullscreen, send a fake event for now since the actual + recreation is deferred */ + KMSDRM_GetModeToSet(window, &mode); +- SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.hdisplay, mode.vdisplay); ++ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.vdisplay, mode.hdisplay); + } + + /* This determines the size of the fb, which comes from the GBM surface +@@ -1016,13 +1060,13 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) + mode that's set in sync with what SDL_video.c thinks is set */ + KMSDRM_GetModeToSet(window, &dispdata->mode); + +- display->current_mode.w = dispdata->mode.hdisplay; +- display->current_mode.h = dispdata->mode.vdisplay; ++ display->current_mode.w = dispdata->mode.vdisplay; ++ display->current_mode.h = dispdata->mode.hdisplay; + display->current_mode.refresh_rate = dispdata->mode.vrefresh; + display->current_mode.format = SDL_PIXELFORMAT_ARGB8888; + + windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, +- dispdata->mode.hdisplay, dispdata->mode.vdisplay, ++ dispdata->mode.vdisplay, dispdata->mode.hdisplay, + surface_fmt, surface_flags); + + if (!windata->gs) { +@@ -1046,7 +1090,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) + ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context); + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, +- dispdata->mode.hdisplay, dispdata->mode.vdisplay); ++ dispdata->mode.vdisplay, dispdata->mode.hdisplay); + + windata->egl_surface_dirty = SDL_FALSE; + +@@ -1151,8 +1195,8 @@ KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display) + modedata->mode_index = i; + } + +- mode.w = conn->modes[i].hdisplay; +- mode.h = conn->modes[i].vdisplay; ++ mode.w = conn->modes[i].vdisplay; ++ mode.h = conn->modes[i].hdisplay; + mode.refresh_rate = conn->modes[i].vrefresh; + mode.format = SDL_PIXELFORMAT_ARGB8888; + mode.driverdata = modedata; +@@ -1264,6 +1308,14 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window) + /*********************************************************************/ + SDL_free(window->driverdata); + window->driverdata = NULL; ++ ++ for (int i = 0; i < RGA_BUFFERS_MAX; ++i) { ++ close(viddata->rga_buffer_prime_fds[i]); ++ } ++ if (src_info.fd) { ++ close(src_info.fd); ++ } ++ c_RkRgaDeInit(); + } + + /**********************************************************************/ +@@ -1283,6 +1335,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) + NativeDisplayType egl_display; + drmModeModeInfo *mode; + int ret = 0; ++ SDL_DisplayData *data; + + /* Allocate window internal data */ + windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); +@@ -1391,6 +1444,9 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + ++ data = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; ++ KMSDRM_InitRotateBuffer(_this, data->mode.hdisplay, data->mode.vdisplay); ++ + /* Tell the app that the window has moved to top-left. */ + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, 0, 0); + +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h +index b172eb9..c4bd1f5 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h +@@ -32,6 +32,10 @@ + #include + #include + #include ++#include ++#include ++ ++#define RGA_BUFFERS_MAX (3) + + typedef struct SDL_VideoData + { +@@ -53,6 +57,10 @@ typedef struct SDL_VideoData + open 1 FD and create 1 gbm device. */ + SDL_bool gbm_init; + ++ struct gbm_bo* rga_buffers[RGA_BUFFERS_MAX]; ++ int rga_buffer_prime_fds[RGA_BUFFERS_MAX]; ++ int rga_buffer_index; ++ + } SDL_VideoData; + + +diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c +index b45909027..231d5b1d6 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c ++++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c +@@ -73,6 +73,7 @@ KMSDRM_DestroyCursorBO (_THIS, SDL_VideoDisplay *display) + if (dispdata->cursor_bo) { + KMSDRM_gbm_bo_destroy(dispdata->cursor_bo); + dispdata->cursor_bo = NULL; ++ dispdata->cursor_bo_drm_fd = -1; + } + } + +@@ -116,6 +117,8 @@ KMSDRM_CreateCursorBO (SDL_VideoDisplay *display) { + SDL_SetError("Could not create GBM cursor BO"); + return; + } ++ ++ dispdata->cursor_bo_drm_fd = viddata->drm_fd; + } + + /* Remove a cursor buffer from a display's DRM cursor BO. */ +@@ -384,11 +387,9 @@ KMSDRM_WarpMouseGlobal(int x, int y) + + /* And now update the cursor graphic position on screen. */ + if (dispdata->cursor_bo) { +- int drm_fd; + int ret = 0; + +- drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(dispdata->cursor_bo)); +- ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, x, y); ++ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, x, y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); +@@ -437,7 +438,6 @@ static void + KMSDRM_MoveCursor(SDL_Cursor * cursor) + { + SDL_Mouse *mouse = SDL_GetMouse(); +- int drm_fd; + int ret = 0; + + /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity! +@@ -452,9 +452,7 @@ KMSDRM_MoveCursor(SDL_Cursor * cursor) + return; + } + +- drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(dispdata->cursor_bo)); +- +- ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y); ++ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); +diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h +index 90d128582..e368c5d0d 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmsym.h ++++ b/src/video/kmsdrm/SDL_kmsdrmsym.h +@@ -95,7 +95,6 @@ SDL_KMSDRM_SYM(int,drmModeSetPlane,(int fd, uint32_t plane_id, uint32_t crtc_id, + /* Planes stuff ends. */ + + SDL_KMSDRM_MODULE(GBM) +-SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) + SDL_KMSDRM_SYM(int,gbm_device_is_format_supported,(struct gbm_device *gbm, + uint32_t format, uint32_t usage)) + SDL_KMSDRM_SYM(void,gbm_device_destroy,(struct gbm_device *gbm)) +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c +index dbc1b4455..3308dd963 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c +@@ -555,6 +555,7 @@ KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resources) { + /* Initialize some of the members of the new display's driverdata + to sane values. */ + dispdata->cursor_bo = NULL; ++ dispdata->cursor_bo_drm_fd = -1; + + /* Since we create and show the default cursor on KMSDRM_InitMouse(), + and we call KMSDRM_InitMouse() when we create a window, we have to know +diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h +index b172eb90f..566fc852d 100644 +--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h ++++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h +@@ -77,6 +77,7 @@ typedef struct SDL_DisplayData + where we may not have an SDL_Cursor at all (so no SDL_Cursor driverdata). + There's only one cursor GBM BO because we only support one cursor. */ + struct gbm_bo *cursor_bo; ++ int cursor_bo_drm_fd; + uint64_t cursor_w, cursor_h; + + SDL_bool default_cursor_init; diff --git a/packages/graphics/bcm2835-driver/package.mk b/packages/graphics/bcm2835-driver/package.mk new file mode 100644 index 000000000..39bb891c0 --- /dev/null +++ b/packages/graphics/bcm2835-driver/package.mk @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bcm2835-driver" +PKG_VERSION="66fc5eaac3d0af1d5a7ffa616086cbfaefd72e98" +PKG_SHA256="373872b00d566fbc8873125336b3a09696e85602d2e49a48c0b5c5cabb15d989" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.broadcom.com" +PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain dtc" +PKG_LONGDESC="OpenMAX-bcm2835: OpenGL-ES and OpenMAX driver for BCM2835" +PKG_TOOLCHAIN="manual" + +# Set SoftFP ABI or HardFP ABI +if [ "${TARGET_FLOAT}" = "soft" ]; then + PKG_FLOAT="softfp" +else + PKG_FLOAT="hardfp" +fi + +makeinstall_target() { + # Install vendor header files + mkdir -p ${SYSROOT_PREFIX}/usr/include + if [ "${OPENGLES}" = "bcm2835-driver" ]; then + cp -PRv ${PKG_FLOAT}/opt/vc/include/* ${SYSROOT_PREFIX}/usr/include + else + for f in $(cd ${PKG_FLOAT}/opt/vc/include; ls | grep -v "GL"); do + cp -PRv ${PKG_FLOAT}/opt/vc/include/$f ${SYSROOT_PREFIX}/usr/include + done + fi + + # Install EGL, OpenGL ES, Open VG, etc. vendor libs & pkgconfigs + mkdir -p ${SYSROOT_PREFIX}/usr/lib + if [ "${OPENGLES}" = "bcm2835-driver" ]; then + cp -PRv ${PKG_FLOAT}/opt/vc/lib/*.so ${SYSROOT_PREFIX}/usr/lib + ln -sf ${SYSROOT_PREFIX}/usr/lib/libbrcmEGL.so ${SYSROOT_PREFIX}/usr/lib/libEGL.so + ln -sf ${SYSROOT_PREFIX}/usr/lib/libbrcmGLESv2.so ${SYSROOT_PREFIX}/usr/lib/libGLESv2.so + cp -PRv ${PKG_FLOAT}/opt/vc/lib/*.a ${SYSROOT_PREFIX}/usr/lib + cp -PRv ${PKG_FLOAT}/opt/vc/lib/pkgconfig ${SYSROOT_PREFIX}/usr/lib + else + for f in $(cd ${PKG_FLOAT}/opt/vc/lib; ls *.so *.a | grep -Ev "^lib(EGL|GL)"); do + cp -PRv ${PKG_FLOAT}/opt/vc/lib/$f ${SYSROOT_PREFIX}/usr/lib + done + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + for f in $(cd ${PKG_FLOAT}/opt/vc/lib/pkgconfig; ls | grep -v "gl"); do + cp -PRv ${PKG_FLOAT}/opt/vc/lib/pkgconfig/$f ${SYSROOT_PREFIX}/usr/lib/pkgconfig + done + fi + + # Update prefix in vendor pkgconfig files + for PKG_CONFIGS in $(find "${SYSROOT_PREFIX}/usr/lib" -type f -name "*.pc" 2>/dev/null); do + sed -e "s#prefix=/opt/vc#prefix=/usr#g" -i "${PKG_CONFIGS}" + done + + # Create symlinks to /opt/vc to satisfy hardcoded include & lib paths + mkdir -p ${SYSROOT_PREFIX}/opt/vc + ln -sf ${SYSROOT_PREFIX}/usr/lib ${SYSROOT_PREFIX}/opt/vc/lib + ln -sf ${SYSROOT_PREFIX}/usr/include ${SYSROOT_PREFIX}/opt/vc/include + + # Install EGL, OpenGL ES and other vendor libs + mkdir -p ${INSTALL}/usr/lib + if [ "${OPENGLES}" = "bcm2835-driver" ]; then + cp -PRv ${PKG_FLOAT}/opt/vc/lib/*.so ${INSTALL}/usr/lib + ln -sf /usr/lib/libbrcmEGL.so ${INSTALL}/usr/lib/libEGL.so + ln -sf /usr/lib/libbrcmEGL.so ${INSTALL}/usr/lib/libEGL.so.1 + ln -sf /usr/lib/libbrcmGLESv2.so ${INSTALL}/usr/lib/libGLESv2.so + ln -sf /usr/lib/libbrcmGLESv2.so ${INSTALL}/usr/lib/libGLESv2.so.2 + else + for f in $(cd ${PKG_FLOAT}/opt/vc/lib; ls *.so | grep -Ev "^lib(EGL|GL)"); do + cp -PRv ${PKG_FLOAT}/opt/vc/lib/$f ${INSTALL}/usr/lib + done + fi + + # Install useful tools + mkdir -p ${INSTALL}/usr/bin + cp -PRv ${PKG_FLOAT}/opt/vc/bin/dtoverlay ${INSTALL}/usr/bin + ln -s dtoverlay ${INSTALL}/usr/bin/dtparam + cp -PRv ${PKG_FLOAT}/opt/vc/bin/vcdbg ${INSTALL}/usr/bin + cp -PRv ${PKG_FLOAT}/opt/vc/bin/vcgencmd ${INSTALL}/usr/bin + cp -PRv ${PKG_FLOAT}/opt/vc/bin/vcmailbox ${INSTALL}/usr/bin + cp -PRv ${PKG_FLOAT}/opt/vc/bin/tvservice ${INSTALL}/usr/bin + cp -PRv ${PKG_FLOAT}/opt/vc/bin/edidparser ${INSTALL}/usr/bin + + # Create symlinks to /opt/vc to satisfy hardcoded lib paths + mkdir -p ${INSTALL}/opt/vc + ln -sf /usr/bin ${INSTALL}/opt/vc/bin + ln -sf /usr/lib ${INSTALL}/opt/vc/lib +} + +post_install() { + # unbind Framebuffer console + if [ "${OPENGLES}" = "bcm2835-driver" ]; then + enable_service unbind-console.service + fi +} diff --git a/packages/graphics/bcm2835-driver/system.d/unbind-console.service b/packages/graphics/bcm2835-driver/system.d/unbind-console.service new file mode 100644 index 000000000..af5e5d44c --- /dev/null +++ b/packages/graphics/bcm2835-driver/system.d/unbind-console.service @@ -0,0 +1,11 @@ +[Unit] +Description=unbind Framebuffer console + +ConditionPathExists=/sys/class/vtconsole/vtcon1/bind + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'echo 0 > /sys/class/vtconsole/vtcon1/bind' + +[Install] +WantedBy=graphical.target diff --git a/packages/graphics/cairo/package.mk b/packages/graphics/cairo/package.mk new file mode 100644 index 000000000..92b2742bd --- /dev/null +++ b/packages/graphics/cairo/package.mk @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="cairo" +PKG_VERSION="1.14.10" +PKG_SHA256="7e87878658f2c9951a14fc64114d4958c0e65ac47530b8ac3078b2ce41b66a09" +PKG_LICENSE="LGPL" +PKG_SITE="http://cairographics.org/" +PKG_URL="http://cairographics.org/releases/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib freetype fontconfig glib libpng pixman" +PKG_LONGDESC="Cairo is a vector graphics library with cross-device output support." +PKG_TOOLCHAIN="configure" # ToDo + +if [ "$OPENGL" != "no" ]; then + PKG_DEPENDS_TARGET+=" $OPENGL" +fi + +if [ "$OPENGLES" != "no" ]; then + PKG_DEPENDS_TARGET+=" $OPENGLES" +fi + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libXrender libX11 mesa" + PKG_CAIRO_CONFIG="--x-includes="$SYSROOT_PREFIX/usr/include" \ + --x-libraries="$SYSROOT_PREFIX/usr/lib" \ + --enable-xlib \ + --enable-xlib-xrender \ + --enable-gl \ + --enable-glx \ + --disable-glesv2 \ + --disable-egl \ + --with-x" + +elif [ "$DISPLAYSERVER" = "weston" ]; then + PKG_CAIRO_CONFIG="--disable-xlib \ + --disable-xlib-xrender \ + --disable-gl \ + --disable-glx \ + --enable-glesv2 \ + --enable-egl \ + --without-x" +else + PKG_CAIRO_CONFIG="--disable-xlib \ + --disable-xlib-xrender \ + --disable-gl \ + --disable-glx \ + --disable-glesv2 \ + --disable-egl \ + --without-x" +fi + +PKG_CONFIGURE_OPTS_TARGET="$PKG_CAIRO_CONFIG \ + --disable-silent-rules \ + --enable-shared \ + --disable-static \ + --disable-gtk-doc \ + --enable-largefile \ + --enable-atomic \ + --disable-gcov \ + --disable-valgrind \ + --disable-xcb \ + --disable-xlib-xcb \ + --disable-xcb-shm \ + --disable-qt \ + --disable-quartz \ + --disable-quartz-font \ + --disable-quartz-image \ + --disable-win32 \ + --disable-win32-font \ + --disable-skia \ + --disable-os2 \ + --disable-beos \ + --disable-cogl \ + --disable-drm \ + --disable-gallium \ + --enable-png \ + --disable-directfb \ + --disable-vg \ + --disable-wgl \ + --disable-script \ + --enable-ft \ + --enable-fc \ + --enable-ps \ + --enable-pdf \ + --enable-svg \ + --disable-test-surfaces \ + --disable-tee \ + --disable-xml \ + --enable-pthread \ + --enable-gobject=yes \ + --disable-full-testing \ + --disable-trace \ + --enable-interpreter \ + --disable-symbol-lookup \ + --enable-some-floating-point \ + --with-gnu-ld" diff --git a/packages/graphics/ftgl/package.mk b/packages/graphics/ftgl/package.mk new file mode 100644 index 000000000..9e89044af --- /dev/null +++ b/packages/graphics/ftgl/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="ftgl" +PKG_VERSION="2.1.2" +PKG_SHA256="0f61d978c28cd5d78daded591f5b03f71248c0a51c7965733e8729c874265f50" +PKG_LICENSE="GPL" +PKG_SITE="http://sourceforge.net/projects/ftgl/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain freetype" +PKG_LONGDESC="a free cross-platform Open Source C++ library that uses Freetype2 to simplify rendering fonts in OpenGL applications" + +PKG_CMAKE_OPTS_TARGET="-DOUTPUT_DIR=$SYSROOT_PREFIX/usr" diff --git a/packages/graphics/ftgl/patches/ftgl-01-cmake.patch b/packages/graphics/ftgl/patches/ftgl-01-cmake.patch new file mode 100644 index 000000000..35e1be103 --- /dev/null +++ b/packages/graphics/ftgl/patches/ftgl-01-cmake.patch @@ -0,0 +1,35 @@ +From c6dea8249d50f1f463db6ca89bc582259c54b86a Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 4 Jul 2015 12:42:40 +0300 +Subject: [PATCH] cmake + +--- + CMakeLists.txt | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 CMakeLists.txt + +diff --git a/CMakeLists.txt b/CMakeLists.txt +new file mode 100644 +index 0000000..18791c4 +--- /dev/null ++++ b/CMakeLists.txt +@@ -0,0 +1,16 @@ ++project(ftgl) ++ ++cmake_minimum_required(VERSION 2.6) ++enable_language(CXX) ++ ++include(ExternalProject) ++ ++externalproject_add(ftgl ++ SOURCE_DIR ${CMAKE_SOURCE_DIR} ++ UPDATE_COMMAND cd unix && autoreconf -vif ++ CONFIGURE_COMMAND cd unix && CXXFLAGS=-fpermissive ./configure --prefix=${OUTPUT_DIR} --with-freetype-prefix=${OUTPUT_DIR} --with-pic ++ BUILD_COMMAND cd unix && make ++ INSTALL_COMMAND "" ++ BUILD_IN_SOURCE 1) ++ ++install(CODE "execute_process(COMMAND make install WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/unix)") +-- +1.7.10.4 + diff --git a/packages/graphics/ftgl/patches/ftgl-01-ftgl-disable-docs.patch b/packages/graphics/ftgl/patches/ftgl-01-ftgl-disable-docs.patch new file mode 100644 index 000000000..6ff2f2cc4 --- /dev/null +++ b/packages/graphics/ftgl/patches/ftgl-01-ftgl-disable-docs.patch @@ -0,0 +1,12 @@ +--- ftgl.orig/unix/Makefile 2014-08-04 17:21:22.210742862 +0200 ++++ ftgl/unix/Makefile 2003-01-12 22:27:04.000000000 +0100 +@@ -1,7 +1,7 @@ + top_builddir=. + -include $(top_builddir)/Make.conf + +-SUBDIRS = src demo docs ++SUBDIRS = src demo + + AUTOGEN = Make.conf config.log config.status libtool autom4te.cache ftgl.pc + AUTOGEN_MAINT = aclocal.m4 acinclude.m4 config.guess config.sub configure ltmain.sh install-sh + diff --git a/packages/graphics/giflib/package.mk b/packages/graphics/giflib/package.mk new file mode 100644 index 000000000..7da0497bb --- /dev/null +++ b/packages/graphics/giflib/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="giflib" +PKG_VERSION="5.1.4" +PKG_SHA256="df27ec3ff24671f80b29e6ab1c4971059c14ac3db95406884fc26574631ba8d5" +PKG_LICENSE="OSS" +PKG_SITE="http://giflib.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/giflib/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_HOST="zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="giflib: giflib service library" + +PKG_CONFIGURE_OPTS_HOST="--disable-shared --enable-static" +PKG_CONFIGURE_OPTS_TARGET="--with-sysroot=$SYSROOT_PREFIX" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/giflib/patches/giflib-01-fix-reallocarray-exception.patch b/packages/graphics/giflib/patches/giflib-01-fix-reallocarray-exception.patch new file mode 100644 index 000000000..f2158c66c --- /dev/null +++ b/packages/graphics/giflib/patches/giflib-01-fix-reallocarray-exception.patch @@ -0,0 +1,34 @@ +--- a/lib/dgif_lib.c ++++ b/lib/dgif_lib.c +@@ -23,6 +23,8 @@ + #include "gif_lib.h" + #include "gif_lib_private.h" + ++extern void *reallocarray(void *optr, size_t nmemb, size_t size); ++ + /* compose unsigned little endian value */ + #define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8)) + +--- a/lib/gif_lib.h ++++ b/lib/gif_lib.h +@@ -244,9 +244,6 @@ + GifPixelType ColorTransIn2[]); + extern int GifBitSize(int n); + +-extern void * +-reallocarray(void *optr, size_t nmemb, size_t size); +- + /****************************************************************************** + Support for the in-core structures allocation (slurp mode). + ******************************************************************************/ +--- a/lib/gifalloc.c ++++ b/lib/gifalloc.c +@@ -10,6 +10,8 @@ + + #include "gif_lib.h" + ++extern void *reallocarray(void *optr, size_t nmemb, size_t size); ++ + #define MAX(x, y) (((x) > (y)) ? (x) : (y)) + + /****************************************************************************** diff --git a/packages/graphics/glew/package.mk b/packages/graphics/glew/package.mk new file mode 100644 index 000000000..d40b93795 --- /dev/null +++ b/packages/graphics/glew/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glew" +PKG_VERSION="2.1.0" +PKG_SHA256="04de91e7e6763039bc11940095cd9c7f880baba82196a7765f727ac05a993c95" +PKG_LICENSE="BSD" +PKG_SITE="http://glew.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/glew/glew/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tgz" +PKG_DEPENDS_TARGET="toolchain libX11" +PKG_LONGDESC="A cross-platform C/C++ extension loading library." + +make_target() { + make CC="$CC" LD="$CC" AR="$AR" \ + POPT="$CFLAGS" LDFLAGS.EXTRA="$LDFLAGS" \ + GLEW_DEST="/usr" LIBDIR="/usr/lib" lib/libGLEW.a glew.pc +} + +makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -PR lib/libGLEW.a $SYSROOT_PREFIX/usr/lib + + mkdir -p $SYSROOT_PREFIX/usr/lib/pkgconfig + cp -PR glew.pc $SYSROOT_PREFIX/usr/lib/pkgconfig + + mkdir -p $SYSROOT_PREFIX/usr/include + cp -PR include/GL $SYSROOT_PREFIX/usr/include +} diff --git a/packages/graphics/glew/patches/glew-01-fix-pkgconf.patch b/packages/graphics/glew/patches/glew-01-fix-pkgconf.patch new file mode 100644 index 000000000..30c38f819 --- /dev/null +++ b/packages/graphics/glew/patches/glew-01-fix-pkgconf.patch @@ -0,0 +1,11 @@ +diff -Naur glew-1.13.0/glew.pc.in glew-1.13.0.patch/glew.pc.in +--- glew-1.13.0/glew.pc.in 2015-08-10 13:47:22.000000000 +0200 ++++ glew-1.13.0.patch/glew.pc.in 2015-11-19 10:01:42.694904497 +0100 +@@ -1,6 +1,6 @@ + prefix=@prefix@ + exec_prefix=${prefix} +-libdir=@libdir@ ++libdir=${exec_prefix}/lib + includedir=${prefix}/include + + Name: glew diff --git a/packages/graphics/glfw/package.mk b/packages/graphics/glfw/package.mk new file mode 100644 index 000000000..10bcc3440 --- /dev/null +++ b/packages/graphics/glfw/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="glfw" +PKG_VERSION="2.7.9" +PKG_SHA256="b7276dcadc85a07077834d1043f11ffd6a3a379647bb94361b4abc3ffca75e7d" +PKG_ARCH="x86_64" +PKG_LICENSE="BSD" +PKG_SITE="http://glfw.org" +PKG_URL="$SOURCEFORGE_SRC/glfw/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain mesa glu" +PKG_LONGDESC="provides a simple API for creating windows, contexts and surfaces, receiving input and events" + +if [ "$OPENGL" = "no" ] ; then + exit 0 +fi + +make_target() { + make x11 PREFIX=$SYSROOT_PREFIX/usr +} + +makeinstall_target() { + make x11-install PREFIX=$SYSROOT_PREFIX/usr +} diff --git a/packages/graphics/glm/package.mk b/packages/graphics/glm/package.mk new file mode 100644 index 000000000..11a95d2c0 --- /dev/null +++ b/packages/graphics/glm/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="glm" +PKG_VERSION="0.9.9.5" +PKG_SHA256="4fe34860ce69156f63eea6c3d84c91cadfc330353cf275ff394aef4e163cafee" +PKG_LICENSE="MIT" +PKG_SITE="https://glm.g-truc.net/" +PKG_URL="https://github.com/g-truc/glm/releases/download/$PKG_VERSION/glm-$PKG_VERSION.zip" +PKG_SOURCE_DIR="glm" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="OpenGL Mathematics (GLM)" diff --git a/packages/graphics/glu/package.mk b/packages/graphics/glu/package.mk new file mode 100644 index 000000000..05580f4bb --- /dev/null +++ b/packages/graphics/glu/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="glu" +PKG_VERSION="9.0.0" +PKG_SHA256="3d19cca9b26ec4048dd22e3d294acd43e080a3205a29ff47765bd514571ea8f9" +PKG_LICENSE="OSS" +PKG_SITE="http://cgit.freedesktop.org/mesa/glu/" +PKG_URL="http://cgit.freedesktop.org/mesa/glu/snapshot/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain mesa" +PKG_LONGDESC="libglu is the The OpenGL utility library" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-silent-rules \ + --disable-debug \ + --disable-osmesa \ + --with-gnu-ld" diff --git a/packages/graphics/gpu-viv-bin-mx6q/package.mk b/packages/graphics/gpu-viv-bin-mx6q/package.mk new file mode 100644 index 000000000..a47d43338 --- /dev/null +++ b/packages/graphics/gpu-viv-bin-mx6q/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="gpu-viv-bin-mx6q" +PKG_VERSION="3.10.17-1.0.2-hfp" +PKG_SHA256="fcf5cc1c2507d77b6ecaef6defd63fbd604be5a765f86922530cb423a595a592" +PKG_ARCH="arm" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.freescale.com" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain gpu-viv-g2d" +PKG_LONGDESC="gpu-viv-bin-mx6q: OpenGL-ES and VIVANTE driver for imx6q" + +make_target() { + : # nothing to make +} + +makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/include + cp -PRv usr/include/* $SYSROOT_PREFIX/usr/include + + LIBS_COPY="usr/lib/libEGL-fb.so \ + usr/lib/libEGL.so* \ + usr/lib/libGLES_CL.so \ + usr/lib/libGLES_CM.so \ + usr/lib/libGLESv1_CL.so* \ + usr/lib/libGLESv1_CM.so* \ + usr/lib/libGLESv2-fb.so \ + usr/lib/libGLESv2.so* \ + usr/lib/libGLSLC.so* \ + usr/lib/libGAL-fb.so \ + usr/lib/libGAL.so* \ + usr/lib/libVIVANTE-fb.so \ + usr/lib/libVIVANTE.so* \ + usr/lib/libOpenCL.so" + + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -PRv $LIBS_COPY $SYSROOT_PREFIX/usr/lib + + mkdir -p $INSTALL/usr/lib + cp -PRv $LIBS_COPY $INSTALL/usr/lib +} + +post_install() { + enable_service unbind-console.service +} diff --git a/packages/graphics/imagemagick/package.mk b/packages/graphics/imagemagick/package.mk new file mode 100644 index 000000000..e39e94db2 --- /dev/null +++ b/packages/graphics/imagemagick/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="imagemagick" +PKG_VERSION="7.0.10-62" +#PKG_SHA256="" +PKG_LICENSE="http://www.imagemagick.org/script/license.php" +PKG_SITE="http://www.imagemagick.org/" +PKG_URL="https://github.com/ImageMagick/ImageMagick/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Software suite to create, edit, compose, or convert bitmap images" + +PKG_CONFIGURE_OPTS_TARGET="--disable-openmp \ + --disable-static \ + --enable-shared \ + --with-pango=no \ + --with-utilities=yes \ + --with-x=no" + +makeinstall_target() { + make install DESTDIR=$INSTALL $PKG_MAKEINSTALL_OPTS_TARGET +} diff --git a/packages/graphics/imx-gpu-viv/package.mk b/packages/graphics/imx-gpu-viv/package.mk new file mode 100644 index 000000000..4284b6a6b --- /dev/null +++ b/packages/graphics/imx-gpu-viv/package.mk @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="imx-gpu-viv" +if [ "$LINUX" = "imx6-3.14-sr" ]; then + PKG_VERSION="5.0.11.p4.5-hfp" + PKG_SHA256="2dfcacd17f8009b1a235a2df2b398f22afccb6f671953e442c04cd74234312f0" +elif [ "$LINUX" = "imx6-4.4-xbian" ]; then + PKG_VERSION="5.0.11.p7.4-hfp" + PKG_SHA256="252b2a8badbc74ca91916490782225affba3908813374baaa7d6267f1de9dae6" +else + exit 0 +fi +PKG_ARCH="arm" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.freescale.com" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="imx-gpu-viv: OpenGL-ES and VIVANTE driver for imx6q" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/include + cp -PRv gpu-core/usr/include/* $SYSROOT_PREFIX/usr/include + cp -PRv g2d/usr/include/* $SYSROOT_PREFIX/usr/include + + LIBS_COPY="gpu-core/usr/lib/libEGL-fb.so \ + gpu-core/usr/lib/libEGL.so* \ + gpu-core/usr/lib/libGLES_CL.so* \ + gpu-core/usr/lib/libGLES_CM.so* \ + gpu-core/usr/lib/libGLESv1_CL.so* \ + gpu-core/usr/lib/libGLESv1_CM.so* \ + gpu-core/usr/lib/libGLESv2-fb.so \ + gpu-core/usr/lib/libGLESv2.so* \ + gpu-core/usr/lib/libGLSLC.so* \ + gpu-core/usr/lib/libGAL-fb.so \ + gpu-core/usr/lib/libGAL.so* \ + gpu-core/usr/lib/libVIVANTE-fb.so \ + gpu-core/usr/lib/libVIVANTE.so* \ + gpu-core/usr/lib/libOpenCL.so \ + gpu-core/usr/lib/libVSC.so \ + g2d/usr/lib/libg2d*.so*" + + # missing in 5.0.11.p7.4-hfp + if [ "$PKG_VERSION" = "5.0.11.p4.5-hfp" ]; then + LIBS_COPY="$LIBS_COPY \ + gpu-core/usr/lib/libGAL_egl.fb.so \ + gpu-core/usr/lib/libGAL_egl.so*" + fi + + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -PRv $LIBS_COPY $SYSROOT_PREFIX/usr/lib + + mkdir -p $INSTALL/usr/lib + cp -PRv $LIBS_COPY $INSTALL/usr/lib +} + +post_install() { + enable_service unbind-console.service +} diff --git a/packages/graphics/kmscube/package.mk b/packages/graphics/kmscube/package.mk new file mode 100644 index 000000000..f12bed34c --- /dev/null +++ b/packages/graphics/kmscube/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kmscube" +PKG_VERSION="98f31bf" +PKG_SHA256="78b52b9e606f0d3444e10ea2ed7c0c03a87f1ad2ef99e35036551395faade041" +PKG_LICENSE="GPL" +PKG_SITE="https://cgit.freedesktop.org/mesa/kmscube" +PKG_URL="https://cgit.freedesktop.org/mesa/kmscube/snapshot/$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Example KMS/GBM/EGL application" +PKG_TOOLCHAIN="autotools" + +if [ "$OPENGLES_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET+=" $OPENGLES" +elif [ "$OPENGL_SUPPORT" = "yes" ]; then + echo "kmscube only supports OpenGLESv2" + exit 0 +fi diff --git a/packages/graphics/lcms2/package.mk b/packages/graphics/lcms2/package.mk new file mode 100644 index 000000000..b1133698f --- /dev/null +++ b/packages/graphics/lcms2/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lcms2" +PKG_VERSION="2.9" +PKG_SHA256="8e23a09dc81af856db37941a4ea26acdf6a45b0281ec5b7ee94b5a4e9f7afbf7" +PKG_LICENSE="MIT" +PKG_SITE="http://www.littlecms.com" +PKG_URL="https://github.com/mm2/Little-CMS/archive/lcms${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain tiff" +PKG_LONGDESC="An small-footprint color management engine, with special focus on accuracy and performance." diff --git a/packages/graphics/libde265/package.mk b/packages/graphics/libde265/package.mk new file mode 100644 index 000000000..f9f5ecf08 --- /dev/null +++ b/packages/graphics/libde265/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libde265" +PKG_VERSION="50987014f7b041079ac1961352781904b691cf7b" +PKG_SHA256="5cdefeb099141608331efe9a9bd33dad271e5810438b654e53e4d2359acdc12a" +PKG_LICENSE="LGPLv3" +PKG_SITE="http://www.libde265.org" +PKG_URL="https://github.com/strukturag/libde265/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Open h.265 video codec implementation." +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-encoder \ + --disable-sherlock265" + +pre_configure_target() { + cd .. + ./autogen.sh +} diff --git a/packages/graphics/libdrm/package.mk b/packages/graphics/libdrm/package.mk new file mode 100644 index 000000000..f2548c81e --- /dev/null +++ b/packages/graphics/libdrm/package.mk @@ -0,0 +1,54 @@ + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdrm" +PKG_VERSION="2.4.108" +PKG_SHA256="a1d7948cbc536763fde14b4beb5e4da7867607966d4cf46301087e8b8fe3d6a0" +PKG_LICENSE="GPL" +PKG_SITE="http://dri.freedesktop.org" +PKG_URL="http://dri.freedesktop.org/libdrm/libdrm-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libpciaccess" +PKG_LONGDESC="The userspace interface library to kernel DRM services." +PKG_TOOLCHAIN="meson" + +get_graphicdrivers + +PKG_MESON_OPTS_TARGET="-Dlibkms=false \ + -Dnouveau=false \ + -Domap=false \ + -Dexynos=false \ + -Dtegra=false \ + -Dcairo-tests=false \ + -Dman-pages=false \ + -Dvalgrind=false \ + -Dfreedreno-kgsl=false \ + -Dinstall-test-programs=false \ + -Dudev=false" + +listcontains "${GRAPHIC_DRIVERS}" "(iris|i915|i965)" && + PKG_MESON_OPTS_TARGET+=" -Dintel=true" || PKG_MESON_OPTS_TARGET+=" -Dintel=false" + +listcontains "${GRAPHIC_DRIVERS}" "(r200|r300|r600|radeonsi)" && + PKG_MESON_OPTS_TARGET+=" -Dradeon=true" || PKG_MESON_OPTS_TARGET+=" -Dradeon=false" + +listcontains "${GRAPHIC_DRIVERS}" "radeonsi" && + PKG_MESON_OPTS_TARGET+=" -Damdgpu=true" || PKG_MESON_OPTS_TARGET+=" -Damdgpu=false" + +listcontains "${GRAPHIC_DRIVERS}" "vmware" && + PKG_MESON_OPTS_TARGET+=" -Dvmwgfx=true" || PKG_MESON_OPTS_TARGET+=" -Dvmwgfx=false" + +listcontains "${GRAPHIC_DRIVERS}" "vc4" && + PKG_MESON_OPTS_TARGET+=" -Dvc4=true" || PKG_MESON_OPTS_TARGET+=" -Dvc4=false" + +listcontains "${GRAPHIC_DRIVERS}" "freedreno" && + PKG_MESON_OPTS_TARGET+=" -Dfreedreno=true" || PKG_MESON_OPTS_TARGET+=" -Dfreedreno=false" + +listcontains "${GRAPHIC_DRIVERS}" "etnaviv" && + PKG_MESON_OPTS_TARGET+=" -Detnaviv=true" || PKG_MESON_OPTS_TARGET+=" -Detnaviv=false" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -a ${PKG_BUILD}/.${TARGET_NAME}/tests/modetest/modetest ${INSTALL}/usr/bin/ +} diff --git a/packages/graphics/libepoxy/package.mk b/packages/graphics/libepoxy/package.mk new file mode 100644 index 000000000..b01dcfe41 --- /dev/null +++ b/packages/graphics/libepoxy/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +# libepoxy (actually) needs to be built shared, to avoid +# (EE) Failed to load /usr/lib/xorg/modules/libglamoregl.so: +# /usr/lib/xorg/modules/libglamoregl.so: undefined symbol: epoxy_eglCreateImageKHR +# in Xorg.log + +PKG_NAME="libepoxy" +PKG_VERSION="1.5.3" +PKG_SHA256="002958c5528321edd53440235d3c44e71b5b1e09b9177e8daf677450b6c4433d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/anholt/libepoxy" +PKG_URL="https://github.com/anholt/libepoxy/releases/download/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Epoxy is a library for handling OpenGL function pointer management for you." +PKG_TOOLCHAIN="autotools" + +if [ "$OPENGL" != "no" ]; then + PKG_DEPENDS_TARGET+=" $OPENGL" +fi + +if [ "$OPENGLES" != "no" ]; then + PKG_DEPENDS_TARGET+=" $OPENGLES" +fi + +if [ "$DISPLAYSERVER" != "x11" ]; then + PKG_CONFIGURE_OPTS_TARGET="--disable-glx" +fi + +if [ "$PROJECT" == "Amlogic" -o "$PROJECT" == "Amlogic-ng" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --disable-egl" +fi diff --git a/packages/graphics/libheif/package.mk b/packages/graphics/libheif/package.mk new file mode 100644 index 000000000..a9634bc26 --- /dev/null +++ b/packages/graphics/libheif/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libheif" +PKG_VERSION="1.5.1" +PKG_SHA256="b134d0219dd2639cc13b8a8bcb8f264834593dd0417da1973fbe96e810918a8b" +PKG_LICENSE="LGPLv3" +PKG_SITE="http://www.libde265.org" +PKG_URL="https://github.com/strukturag/libheif/releases/download/v$PKG_VERSION/libheif-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libde265 libjpeg-turbo libpng" +PKG_LONGDESC="A HEIF file format decoder and encoder." +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-go \ + --disable-examples \ + --disable-tests" diff --git a/packages/graphics/libhybris/package.mk b/packages/graphics/libhybris/package.mk new file mode 100644 index 000000000..c7cb5ee4f --- /dev/null +++ b/packages/graphics/libhybris/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="libhybris" +PKG_VERSION="c21320b3c9bd043d05c95550a72b47f43016cfec" +PKG_SHA256="c71d8dc18b4784ad80c120869ec21b34fcdd1503be738f3ea0f51b9489001c60" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/kszaq/libhybris" +PKG_URL="https://github.com/kszaq/libhybris/archive/$PKG_VERSION.tar.gz" +PKG_SOURCE_DIR="$PKG_NAME-$PKG_VERSION*/hybris" +PKG_DEPENDS_TARGET="toolchain android-headers" +PKG_LONGDESC="Allows to run bionic-based HW adaptations in glibc systems - libs." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_TARGET="--enable-arch=$TARGET_ARCH \ + --with-default-egl-platform=fbdev \ + --with-android-headers=$BUILD/android-headers-25 \ + --with-default-hybris-ld-library-path=/system/lib \ + --enable-mali-quirks" + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/lib/malihybris + mv $INSTALL/usr/lib/libEGL* $INSTALL/usr/lib/malihybris + mv $INSTALL/usr/lib/libGLES* $INSTALL/usr/lib/malihybris +} diff --git a/packages/graphics/libjpeg-turbo/package.mk b/packages/graphics/libjpeg-turbo/package.mk new file mode 100644 index 000000000..125fb1743 --- /dev/null +++ b/packages/graphics/libjpeg-turbo/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libjpeg-turbo" +PKG_VERSION="2.0.2" +PKG_SHA256="b45255bd476c19c7c6b198c07c0487e8b8536373b82f2b38346b32b4fa7bb942" +PKG_LICENSE="GPL" +PKG_SITE="https://libjpeg-turbo.org/" +PKG_URL="https://github.com/libjpeg-turbo/libjpeg-turbo/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A high-speed version of libjpeg for x86 and x86-64 processors which uses SIMD." +PKG_BUILD_FLAGS="+pic +pic:host" + +PKG_CMAKE_OPTS_HOST="-DENABLE_STATIC=ON \ + -DENABLE_SHARED=OFF \ + -DWITH_JPEG8=ON \ + -DWITH_SIMD=OFF" + +PKG_CMAKE_OPTS_TARGET="-DENABLE_STATIC=ON \ + -DENABLE_SHARED=OFF \ + -DWITH_JPEG8=ON" + +if target_has_feature "(neon|sse)"; then + PKG_CMAKE_OPTS_TARGET+=" -DWITH_SIMD=ON" +else + PKG_CMAKE_OPTS_TARGET+=" -DWITH_SIMD=OFF" +fi + +if [ $TARGET_ARCH = "x86_64" ]; then + PKG_DEPENDS_HOST+=" nasm:host" + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/libmali/package.mk b/packages/graphics/libmali/package.mk new file mode 100644 index 000000000..0017a3f20 --- /dev/null +++ b/packages/graphics/libmali/package.mk @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2021-present Fewtarius + +PKG_NAME="libmali" +PKG_ARCH="arm aarch64" +PKG_LICENSE="nonfree" +PKG_SITE="https://github.com/LibreELEC/libmali" +PKG_URL="https://github.com/rockchip-linux/libmali.git" +PKG_VERSION="ad4c289" +PKG_GIT_CLONE_DEPTH=1 +GET_HANDLER_SUPPORT="git" +PKG_DEPENDS_TARGET="toolchain libdrm" +PKG_LONGDESC="OpenGL ES user-space binary for the ARM Mali GPU family" + +if [[ "${DEVICE}" =~ RG351 ]] +then + PKG_PATCH_DIRS+="RG351" +else + PKG_PATCH_DIRS+="${DEVICE}" +fi + +MALIVERSION="1.9.0" + +PKG_STAMP="${MALI_FAMILY}" + +if [ "${TARGET_ARCH}" = "aarch64" ]; then + INSTARCH="aarch64-linux-gnu" +elif [ "${TARGET_ARCH}" = "arm" ]; then + INSTARCH="arm-linux-gnueabihf" +fi + +PKG_CMAKE_OPTS_TARGET+=" -DMALI_ARCH=${INSTARCH}" + +pre_configure_target() { + if [ -e "${PKG_BUILD}/CMakeLists.txt" ] + then + sed -i "s#arm-linux-gnueabihf/libmali-bifrost-g31-rxp0-wayland-gbm.so#${INSTARCH}/${MALIDRIVER}.so#g" ${PKG_BUILD}/CMakeLists.txt + fi +} + +post_makeinstall_target() { + rm -f "${INSTALL}/usr/lib/*mali*" + + cp -f "${PKG_BUILD}/lib/${INSTARCH}/${MALIDRIVER}.so" "${SYSROOT_PREFIX}/usr/lib" + cp -f "${PKG_BUILD}/lib/${INSTARCH}/${MALIDRIVER}.so" "${INSTALL}/usr/lib" + + ln -sf "${MALIDRIVER}.so" "${SYSROOT_PREFIX}/usr/lib/libmali.so.${MALIVERSION}" + ln -sf "${MALIDRIVER}.so" "${INSTALL}/usr/lib/libmali.so.${MALIVERSION}" + + ln -sf libmali.so.${MALIVERSION} ${SYSROOT_PREFIX}/usr/lib/libvulkan.so.1 + ln -sf libmali.so.${MALIVERSION} ${INSTALL}/usr/lib/libvulkan.so.1 + ln -sf libvulkan.so.1 ${SYSROOT_PREFIX}/usr/lib/libvulkan.so + ln -sf libvulkan.so.1 ${INSTALL}/usr/lib/libvulkan.so + + ln -sf libmali.so.${MALIVERSION} ${SYSROOT_PREFIX}/usr/lib/libmali.so.1 + ln -sf libmali.so.${MALIVERSION} ${INSTALL}/usr/lib/libmali.so.1 + + ln -sf libmali.so.1 ${SYSROOT_PREFIX}/usr/lib/libmali.so + ln -sf libmali.so.1 ${INSTALL}/usr/lib/libmali.so + + ln -sf libmali.so.1 ${SYSROOT_PREFIX}/usr/lib/libgbm.so.1 + ln -sf libgbm.so.1 ${SYSROOT_PREFIX}/usr/lib/libgbm.so + ln -sf libmali.so.1 ${INSTALL}/usr/lib/libgbm.so.1 + ln -sf libgbm.so.1 ${INSTALL}/usr/lib/libgbm.so + + for lib in \ + libGLESv1_CM.so.1 \ + libGLESv1_CM.so \ + libGLESv2.so.2 \ + libGLESv2.so \ + libGLESv3.so.3 \ + libGLESv3.so \ + libEGL.so.1 \ + libEGL.so \ + libMaliOpenCL.so.1 \ + libMaliOpenCL.so + do + rm -f ${INSTALL}/usr/lib/${lib} + ln -sf libmali.so ${INSTALL}/usr/lib/${lib} + rm -f ${SYSROOT_PREFIX}/usr/lib/${lib} + ln -sf libmali.so ${SYSROOT_PREFIX}/usr/lib/${lib} + done + rm -f $(ls ${INSTALL}/usr/lib/libmali-* | grep -v ${MALIDRIVER}) +} diff --git a/packages/graphics/libmali/patches/RG351/mali-bitfrost-001-gbminclude.patch b/packages/graphics/libmali/patches/RG351/mali-bitfrost-001-gbminclude.patch new file mode 100644 index 000000000..8a209c425 --- /dev/null +++ b/packages/graphics/libmali/patches/RG351/mali-bitfrost-001-gbminclude.patch @@ -0,0 +1,12 @@ +diff --git a/include/EGL/eglplatform.h b/include/EGL/eglplatform.h +index 184e204..746a7ec 100644 +--- a/include/EGL/eglplatform.h ++++ b/include/EGL/eglplatform.h +@@ -1,6 +1,7 @@ + #ifndef __eglplatform_h_ + #define __eglplatform_h_ + ++#include + /* + ** Copyright (c) 2007-2016 The Khronos Group Inc. + ** diff --git a/packages/graphics/libmali/patches/RG552/mali-bitfrost-001-gbminclude.patch b/packages/graphics/libmali/patches/RG552/mali-bitfrost-001-gbminclude.patch new file mode 100644 index 000000000..8a209c425 --- /dev/null +++ b/packages/graphics/libmali/patches/RG552/mali-bitfrost-001-gbminclude.patch @@ -0,0 +1,12 @@ +diff --git a/include/EGL/eglplatform.h b/include/EGL/eglplatform.h +index 184e204..746a7ec 100644 +--- a/include/EGL/eglplatform.h ++++ b/include/EGL/eglplatform.h +@@ -1,6 +1,7 @@ + #ifndef __eglplatform_h_ + #define __eglplatform_h_ + ++#include + /* + ** Copyright (c) 2007-2016 The Khronos Group Inc. + ** diff --git a/packages/graphics/libmali/system.d/libmali-setup.service b/packages/graphics/libmali/system.d/libmali-setup.service new file mode 100644 index 000000000..b1eb1b42d --- /dev/null +++ b/packages/graphics/libmali/system.d/libmali-setup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Setup symlink for ARM Mali library +Before=graphical.target +After=multi-user.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/libmali-setup + +[Install] +WantedBy=multi-user.target diff --git a/packages/graphics/libpng/package.mk b/packages/graphics/libpng/package.mk new file mode 100644 index 000000000..8aa5700ee --- /dev/null +++ b/packages/graphics/libpng/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libpng" +PKG_VERSION="1.6.37" +PKG_SHA256="505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca" +PKG_LICENSE="LibPNG2" +PKG_SITE="http://www.libpng.org/" +PKG_URL="$SOURCEFORGE_SRC/libpng/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="An extensible file format for the lossless, portable, well-compressed storage of raster images." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic +pic:host" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_lib_z_zlibVersion=yes \ + --enable-static \ + --enable-shared" + +PKG_CONFIGURE_OPTS_HOST="--enable-static --disable-shared" + +pre_configure_host() { + export CPPFLAGS="$CPPFLAGS -I$TOOLCHAIN/include" +} + +pre_configure_target() { + export CPPFLAGS="$CPPFLAGS -I$SYSROOT_PREFIX/usr/include" +} + +post_makeinstall_target() { + sed -e "s:\([\"'= ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" \ + -e "s:libs=\"-lpng16\":libs=\"-lpng16 -lz\":g" \ + -i $SYSROOT_PREFIX/usr/bin/libpng*-config + + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/libpng17/package.mk b/packages/graphics/libpng17/package.mk new file mode 100644 index 000000000..a3bd21f33 --- /dev/null +++ b/packages/graphics/libpng17/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libpng17" +PKG_VERSION="1.7.0beta89" +PKG_SHA256="1fad2475a24174f5b4ad237b8b899a2c0583237f108c2288a6e2ac5c3537147a" +PKG_LICENSE="LibPNG2" +PKG_SITE="http://www.libpng.org/" +PKG_URL="$SOURCEFORGE_SRC/libpng/libpng-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="An extensible file format for the lossless, portable, well-compressed storage of raster images." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic +pic:host" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_lib_z_zlibVersion=yes \ + --enable-shared \ + --disable-static" + +PKG_CONFIGURE_OPTS_HOST="--enable-shared --disable-static" + +pre_configure_host() { + export CPPFLAGS="$CPPFLAGS -I$TOOLCHAIN/include" +} + +pre_configure_target() { + export CPPFLAGS="$CPPFLAGS -I$SYSROOT_PREFIX/usr/include" +} + +post_makeinstall_target() { + sed -e "s:\([\"'= ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" \ + -e "s:libs=\"-lpng17\":libs=\"-lpng17 -lz\":g" \ + -i $SYSROOT_PREFIX/usr/bin/libpng*-config + + rm -rf $INSTALL/usr/lib/libpng.so +} diff --git a/packages/graphics/libprojectM/package.mk b/packages/graphics/libprojectM/package.mk new file mode 100644 index 000000000..fcc073611 --- /dev/null +++ b/packages/graphics/libprojectM/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libprojectM" +PKG_VERSION="v3.1.2" +PKG_SHA256="d59f61806f4e0e89bb42c494514ee295b3a7c4893432a1d38607777040a90823" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/projectM-visualizer/projectm" +PKG_URL="https://github.com/projectM-visualizer/projectm/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain freetype glm $OPENGL" +PKG_LONGDESC="A MilkDrop compatible opensource music visualizer." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --disable-qt \ + --disable-pulseaudio \ + --disable-jack \ + --enable-preset-subdirs" + +# workaround due broken release files, remove at next bump +pre_configure_target() { + ./autogen.sh +} diff --git a/packages/graphics/libraw/package.mk b/packages/graphics/libraw/package.mk new file mode 100644 index 000000000..e91599b26 --- /dev/null +++ b/packages/graphics/libraw/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libraw" +PKG_VERSION="0.19.5" +PKG_SHA256="40a262d7cc71702711a0faec106118ee004f86c86cc228281d12d16da03e02f5" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.libraw.org/" +PKG_URL="http://www.libraw.org/data/LibRaw-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libjpeg-turbo lcms2" +PKG_LONGDESC="A library for reading RAW files obtained from digital photo cameras (CRW/CR2, NEF, RAF, DNG, and others)" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-openmp \ + --enable-jpeg \ + --disable-jasper \ + --enable-lcms \ + --disable-examples" diff --git a/packages/graphics/mesa/package.mk b/packages/graphics/mesa/package.mk new file mode 100644 index 000000000..e9564db03 --- /dev/null +++ b/packages/graphics/mesa/package.mk @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mesa" +PKG_VERSION="19.1.7" +PKG_SHA256="97c9f6a6127bee5ab21c3fe63ff3e0bd73a7966415f92f66500b0b276b7150da" +PKG_LICENSE="OSS" +PKG_SITE="http://www.mesa3d.org/" +PKG_URL="https://github.com/mesa3d/mesa/archive/mesa-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain expat libdrm Mako:host" +PKG_LONGDESC="Mesa is a 3-D graphics library with an API." +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+lto" + +get_graphicdrivers + +PKG_MESON_OPTS_TARGET="-Ddri-drivers=${DRI_DRIVERS// /,} \ + -Dgallium-drivers=${GALLIUM_DRIVERS// /,} \ + -Dgallium-extra-hud=false \ + -Dgallium-xvmc=false \ + -Dgallium-omx=disabled \ + -Dgallium-nine=false \ + -Dgallium-opencl=disabled \ + -Dshader-cache=true \ + -Dshared-glapi=true \ + -Dopengl=true \ + -Dgbm=true \ + -Degl=true \ + -Dglvnd=false \ + -Dasm=true \ + -Dvalgrind=false \ + -Dlibunwind=false \ + -Dlmsensors=false \ + -Dbuild-tests=false \ + -Dselinux=false \ + -Dosmesa=none" + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xorgproto libXext libXdamage libXfixes libXxf86vm libxcb libX11 libxshmfence libXrandr" + export X11_INCLUDES= + PKG_MESON_OPTS_TARGET+=" -Dplatforms=x11,drm -Ddri3=true -Dglx=dri" +elif [ "$DISPLAYSERVER" = "weston" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET wayland wayland-protocols" + PKG_MESON_OPTS_TARGET+=" -Dplatforms=wayland,drm -Ddri3=false -Dglx=disabled" +else + PKG_MESON_OPTS_TARGET+=" -Dplatforms=drm -Ddri3=false -Dglx=disabled" +fi + +if [ "$LLVM_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET elfutils llvm" + export LLVM_CONFIG="$SYSROOT_PREFIX/usr/bin/llvm-config-host" + PKG_MESON_OPTS_TARGET+=" -Dllvm=true" +else + PKG_MESON_OPTS_TARGET+=" -Dllvm=false" +fi + +if [ "$VDPAU_SUPPORT" = "yes" -a "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libvdpau" + PKG_MESON_OPTS_TARGET+=" -Dgallium-vdpau=true" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-vdpau=false" +fi + +if [ "$VAAPI_SUPPORT" = "yes" ] && listcontains "$GRAPHIC_DRIVERS" "(r600|radeonsi)"; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libva" + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=true" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-va=false" +fi + +if listcontains "$GRAPHIC_DRIVERS" "vmware"; then + PKG_MESON_OPTS_TARGET+=" -Dgallium-xa=true" +else + PKG_MESON_OPTS_TARGET+=" -Dgallium-xa=false" +fi + +if [ "$OPENGLES_SUPPORT" = "yes" ]; then + PKG_MESON_OPTS_TARGET+=" -Dgles1=false -Dgles2=true" +else + PKG_MESON_OPTS_TARGET+=" -Dgles1=false -Dgles2=false" +fi + +# Temporary workaround: +# Listed libraries are static, while mesa expects shared ones. This breaks the +# dependency tracking. The following has some ideas on how to address that. +# https://github.com/LibreELEC/LibreELEC.tv/pull/2163 +pre_configure_target() { + if [ "$DISPLAYSERVER" = "x11" ]; then + export LIBS="-lxcb-dri3 -lxcb-dri2 -lxcb-xfixes -lxcb-present -lxcb-sync -lxshmfence -lz" + fi +} + +post_makeinstall_target() { + # Similar hack is needed on EGL, GLES* front. Might as well drop it and test the GLVND? + if [ "$DISPLAYSERVER" = "x11" ]; then + # rename and relink for cooperate with nvidia drivers + rm -rf $INSTALL/usr/lib/libGL.so + rm -rf $INSTALL/usr/lib/libGL.so.1 + ln -sf libGL.so.1 $INSTALL/usr/lib/libGL.so + ln -sf /var/lib/libGL.so $INSTALL/usr/lib/libGL.so.1 + mv $INSTALL/usr/lib/libGL.so.1.2.0 $INSTALL/usr/lib/libGL_mesa.so.1 + fi +} diff --git a/packages/graphics/opengl-mali/package.mk b/packages/graphics/opengl-mali/package.mk new file mode 100644 index 000000000..ce009109d --- /dev/null +++ b/packages/graphics/opengl-mali/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="opengl-mali" +PKG_VERSION="20130520" +PKG_SHA256="4832c8b56fa2b844ff5ead96185a83e08731767062ed711b86fd70543211a9db" +PKG_ARCH="arm" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.arm.com/products/multimedia/mali-graphics-hardware/mali-400-mp.php" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="opengl-mali: OpenGL-ES and Mali driver for Mali 400 GPUs" + +make_target() { + : # nothing todo +} + +makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/include + cp -PR src/include/* $SYSROOT_PREFIX/usr/include + + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -PR src/lib/*.so* $SYSROOT_PREFIX/usr/lib + ln -sf libEGL.so.1.4 $SYSROOT_PREFIX/usr/lib/libEGL.so + ln -sf libGLESv1_CM.so.1.1 $SYSROOT_PREFIX/usr/lib/libGLESv1_CM.so + ln -sf libGLESv2.so.2.0 $SYSROOT_PREFIX/usr/lib/libGLESv2.so + + mkdir -p $INSTALL/usr/lib + cp -PR src/lib/*.so* $INSTALL/usr/lib + ln -sf libEGL.so.1.4 $INSTALL/usr/lib/libEGL.so + ln -sf libGLESv1_CM.so.1.1 $INSTALL/usr/lib/libGLESv1_CM.so + ln -sf libGLESv2.so.2.0 $INSTALL/usr/lib/libGLESv2.so +} diff --git a/packages/graphics/opengl-meson-t82x/package.mk b/packages/graphics/opengl-meson-t82x/package.mk new file mode 100644 index 000000000..5bd4ca425 --- /dev/null +++ b/packages/graphics/opengl-meson-t82x/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="opengl-meson-t82x" +PKG_VERSION="d3e7cfed0c2b92640d874bb8c8c16d7ed832fdd4" +PKG_SHA256="b4c9b2319da9b1d4aec4e401ee2bf7853303d75df4a192da7bd1e18353ec1334" +PKG_LICENSE="nonfree" +PKG_SITE="https://github.com/CoreELEC/opengl-meson-t82x" +PKG_URL="https://github.com/CoreELEC/opengl-meson-t82x/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libhybris opengl-meson" +PKG_SOURCE_DIR="$PKG_NAME-$PKG_VERSION*" +PKG_LONGDESC="OpenGL ES pre-compiled libraries for Mali GPUs. The libraries were extracted from Khadas VIM2 Android firmware." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/system + cp -a system/* $INSTALL/system +} + +post_install() { + enable_service unbind-console.service +} diff --git a/packages/graphics/opengl-meson-t82x/system.d/unbind-console.service b/packages/graphics/opengl-meson-t82x/system.d/unbind-console.service new file mode 100644 index 000000000..a79c37ad1 --- /dev/null +++ b/packages/graphics/opengl-meson-t82x/system.d/unbind-console.service @@ -0,0 +1,11 @@ +[Unit] +Description=Unbind framebuffer console + +ConditionPathExists=/sys/class/vtconsole/vtcon1/bind + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'echo 0 > /sys/class/vtconsole/vtcon1/bind' + +[Install] +WantedBy=graphical.target diff --git a/packages/graphics/opengl-meson/package.mk b/packages/graphics/opengl-meson/package.mk new file mode 100644 index 000000000..474171988 --- /dev/null +++ b/packages/graphics/opengl-meson/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="opengl-meson" +PKG_VERSION="8-r5p1-01rel0-armhf" +PKG_SHA256="b2ad356f0f8c06c8bca077fe2dd5568b83e1879d32bea20c551ab1bf72402c29" +PKG_LICENSE="nonfree" +PKG_SITE="http://openlinux.amlogic.com:8000/download/ARM/filesystem/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="OpenGL ES pre-compiled libraries for Mali GPUs found in Amlogic Meson SoCs." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/ + cp -PR usr/lib/libMali.so $INSTALL/usr/lib/ + + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -PR usr/lib/libMali.so $SYSROOT_PREFIX/usr/lib + + ln -sf /var/lib/libEGL.so $INSTALL/usr/lib/libEGL.so + ln -sf /usr/lib/libEGL.so $INSTALL/usr/lib/libEGL.so.1 + ln -sf /usr/lib/libEGL.so $INSTALL/usr/lib/libEGL.so.1.0.0 + ln -sf /var/lib/libGLESv1_CM.so $INSTALL/usr/lib/libGLESv1_CM.so + ln -sf /usr/lib/libGLESv1_CM.so $INSTALL/usr/lib/libGLESv1_CM.so.1 + ln -sf /usr/lib/libGLESv1_CM.so $INSTALL/usr/lib/libGLESv1_CM.so.1.0.1 + ln -sf /var/lib/libGLESv2.so $INSTALL/usr/lib/libGLESv2.so + ln -sf /usr/lib/libGLESv2.so $INSTALL/usr/lib/libGLESv2.so.2 + ln -sf /usr/lib/libGLESv2.so $INSTALL/usr/lib/libGLESv2.so.2.0.0 + ln -sf /var/lib/libGLESv3.so $INSTALL/usr/lib/libGLESv3.so + ln -sf /usr/lib/libGLESv3.so $INSTALL/usr/lib/libGLESv3.so.3 + ln -sf /usr/lib/libGLESv3.so $INSTALL/usr/lib/libGLESv3.so.3.0.0 + + mkdir -p $INSTALL/usr/sbin + cp $PKG_DIR/scripts/libmali-overlay-setup $INSTALL/usr/sbin +} + +post_install() { + enable_service libmali.service +} diff --git a/packages/graphics/opengl-meson/scripts/libmali-overlay-setup b/packages/graphics/opengl-meson/scripts/libmali-overlay-setup new file mode 100755 index 000000000..bf5d1d858 --- /dev/null +++ b/packages/graphics/opengl-meson/scripts/libmali-overlay-setup @@ -0,0 +1,19 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +MALI450_DIR=/usr/lib +MALIHYBRIS_DIR=/usr/lib/malihybris + +if [ -e /proc/device-tree/mali@d00c0000/compatible ]; then + ln -sf "$MALI450_DIR/libMali.so" /var/lib/libEGL.so + ln -sf "$MALI450_DIR/libMali.so" /var/lib/libGLESv1_CM.so + ln -sf "$MALI450_DIR/libMali.so" /var/lib/libGLESv2.so + ln -sf "$MALI450_DIR/libMali.so" /var/lib/libGLESv3.so +elif [ -e /proc/device-tree/t82x@d00c0000/compatible ]; then + ln -sf "$MALIHYBRIS_DIR/libEGL.so.1.0.0" /var/lib/libEGL.so + ln -sf "$MALIHYBRIS_DIR/libGLESv1_CM.so.1.0.1" /var/lib/libGLESv1_CM.so + ln -sf "$MALIHYBRIS_DIR/libGLESv2.so.2.0.0" /var/lib/libGLESv2.so + ln -sf "$MALIHYBRIS_DIR/libGLESv3.so.3.0.0" /var/lib/libGLESv3.so +fi diff --git a/packages/graphics/opengl-meson/system.d/libmali.service b/packages/graphics/opengl-meson/system.d/libmali.service new file mode 100644 index 000000000..c83c77697 --- /dev/null +++ b/packages/graphics/opengl-meson/system.d/libmali.service @@ -0,0 +1,11 @@ +[Unit] +Description=Create libMali overlay for specific AML device +After=var.mount +Before=kodi.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/libmali-overlay-setup + +[Install] +WantedBy=local-fs.target diff --git a/packages/graphics/soil/package.mk b/packages/graphics/soil/package.mk new file mode 100644 index 000000000..1c6f5d87f --- /dev/null +++ b/packages/graphics/soil/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="soil" +PKG_VERSION="1.16" +PKG_SHA256="5f2d8a8c78e81d29df07f0f97c34fa2f75187bcadfdc7222cbd026859acaff2f" +PKG_LICENSE="CCPL" +PKG_SITE="http://www.lonesock.net/soil.html" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain mesa" +PKG_LONGDESC="A tiny C lib primarily for loading textures into OpenGL" +PKG_BUILD_FLAGS="+pic" + +pre_make_target() { + sed "s/1.07-20071110/$PKG_VERSION/" -i Makefile +} + +pre_makeinstall_target() { + export DESTDIR=$SYSROOT_PREFIX +} diff --git a/packages/graphics/soil/patches/soil-0001_fix-makefile.patch b/packages/graphics/soil/patches/soil-0001_fix-makefile.patch new file mode 100644 index 000000000..505530ce5 --- /dev/null +++ b/packages/graphics/soil/patches/soil-0001_fix-makefile.patch @@ -0,0 +1,47 @@ +--- /dev/null 2015-06-05 20:37:04.396503995 +0200 ++++ b/Makefile 2016-01-27 22:47:09.795982961 +0100 +@@ -0,0 +1,44 @@ ++CC ?= gcc ++INSTALL_FILE = install -p -m 644 ++INSTALL_DIR = install -p -d ++LN = ln -s ++RM = rm -fv ++CFLAGS += -c -O2 -Wall ++LDFLAGS += ++ ++SRC = src ++CFILES = $(SRC)/image_DXT.c $(SRC)/image_helper.c $(SRC)/SOIL.c $(SRC)/stb_image_aug.c ++OFILES = $(CFILES:.c=.o) ++LIBNAME = libSOIL ++VERSION = 1.07-20071110 ++MAJOR = 1 ++ ++HFILES = $(SRC)/SOIL.h $(SRC)/image_DXT.h $(SRC)/image_helper.h \ ++ $(SRC)/stbi_DDS_aug.h $(SRC)/stbi_DDS_aug_c.h $(SRC)/stb_image_aug.h ++AFILE = libSOIL.a ++INCLUDEDIR = /usr/include/SOIL ++LIBDIR = /usr/lib ++ ++all: $(OFILES) lib ++ ++%.o: %.c ++ $(CC) $(CFLAGS) $< -o $@ ++ ++lib: $(OFILES) ++ # create static library ++ $(AR) -cvq $(LIBNAME).a $(OFILES) ++ ++install: ++ $(INSTALL_DIR) $(DESTDIR)/$(INCLUDEDIR) ++ $(INSTALL_FILE) $(HFILES) $(DESTDIR)/$(INCLUDEDIR) ++ $(INSTALL_DIR) $(DESTDIR)/$(LIBDIR) ++ $(INSTALL_FILE) $(AFILE) $(DESTDIR)/$(LIBDIR) ++ ++clean: ++ $(RM) *.o ++ $(RM) *~ ++ ++distclean: ++ $(RM) $(AFILE) $(SOFILE) ++ ++.PHONY: all lib clean distclean diff --git a/packages/graphics/tiff/package.mk b/packages/graphics/tiff/package.mk new file mode 100644 index 000000000..84f9f421e --- /dev/null +++ b/packages/graphics/tiff/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tiff" +PKG_VERSION="4.0.10" +PKG_SHA256="2c52d11ccaf767457db0c46795d9c7d1a8d8f76f68b0b800a3dfe45786b996e4" +PKG_LICENSE="OSS" +PKG_SITE="http://www.remotesensing.org/libtiff/" +PKG_URL="http://download.osgeo.org/libtiff/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libjpeg-turbo zlib" +PKG_LONGDESC="libtiff is a library for reading and writing TIFF files." +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-mdi \ + --enable-cxx \ + --with-jpeg-lib-dir=$SYSROOT_PREFIX/usr/lib \ + --with-jpeg-include-dir=$SYSROOT_PREFIX/usr/include \ + --without-x" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/graphics/vsxu/package.mk b/packages/graphics/vsxu/package.mk new file mode 100644 index 000000000..54e015dc0 --- /dev/null +++ b/packages/graphics/vsxu/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vsxu" +PKG_VERSION="0.5.1" +PKG_SHA256="6707b230ba6cb28c5b19ec6163722b801dd30afed8f966b57e188761b4d54b8e" +PKG_ARCH="i386 x86_64" +PKG_LICENSE="GPL" +PKG_SITE="http://www.vsxu.com" +# repackaged from https://github.com/vovoid/vsxu/archive/$PKG_VERSION.tar.gz +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain $OPENGL libX11 glew glfw zlib libpng libjpeg-turbo freetype" +PKG_LONGDESC="an OpenGL-based programming environment to visualize music and create graphic effects" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=0 \ + -DVSXU_STATIC=1 \ + -DCMAKE_POSITION_INDEPENDENT_CODE=1 \ + -DCMAKE_CXX_FLAGS=-I$SYSROOT_PREFIX/usr/include/freetype2" + +pre_configure_target(){ + export LDFLAGS="$LDFLAGS -lX11" +} + +post_makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/lib/vsxu + cp -PR $INSTALL/usr/lib/* $SYSROOT_PREFIX/usr/lib + + mkdir -p $SYSROOT_PREFIX/usr/include/ + cp -RP $INSTALL/usr/include/* $SYSROOT_PREFIX/usr/include + + mkdir -p $SYSROOT_PREFIX/usr/share/ + cp -RP $INSTALL/usr/share/vsxu $SYSROOT_PREFIX/usr/share +} diff --git a/packages/graphics/vsxu/patches/vsxu-01-fix-order.patch b/packages/graphics/vsxu/patches/vsxu-01-fix-order.patch new file mode 100644 index 000000000..8709295fc --- /dev/null +++ b/packages/graphics/vsxu/patches/vsxu-01-fix-order.patch @@ -0,0 +1,75 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 1e61faf..435cf29 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -389,10 +389,11 @@ add_definitions(-DVSXU_INSTALL_LIB_DIR="${VSXU_INSTALL_LIB_DIR}") + ################################################################################ + # VSXU LIBRARIES ############################################################### + ################################################################################ +-add_subdirectory(engine) + add_subdirectory(engine_audiovisual) + add_subdirectory(engine_graphics) ++# order matters - need to add plugins before engine to create static glue + add_subdirectory(plugins) ++add_subdirectory(engine) + add_subdirectory(widget) + + ################################################################################ +--- vsxu-0.5.1/CMakeLists.txt.orig 2015-05-12 14:43:04.427596836 +0200 ++++ vsxu-0.5.1/CMakeLists.txt 2015-05-12 14:43:13.995596648 +0200 +@@ -56,27 +56,6 @@ + endif() + + ################################################################################ +-# The pkg-config file +-################################################################################ +-IF (UNIX OR VSXU_WINDOWS_LIB_BUILD) +- if (VSXU_STATIC EQUAL 1 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugins/static_factory_pkgconfig_libs") +- file (STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/plugins/static_factory_pkgconfig_libs" VSXU_PLUGIN_PKGCONFIG_LIBS) +- CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/libvsxu.pc.in.static +- ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc +- @ONLY) +- +- else() +- CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/libvsxu.pc.in.dynamic +- ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc +- @ONLY) +- endif() +- +- INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc +- DESTINATION ${VSXU_INSTALL_LIB_DIR}/pkgconfig) +-ENDIF() +- +- +-################################################################################ + # CPACK OPTIONS ################################################################ + ################################################################################ + SET(CPACK_PACKAGE_NAME "vsxu") +@@ -417,6 +396,27 @@ + add_subdirectory(tools/vsxl) + endif(UNIX) + ++################################################################################ ++# The pkg-config file ++################################################################################ ++IF (UNIX OR VSXU_WINDOWS_LIB_BUILD) ++ if (VSXU_STATIC EQUAL 1 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugins/static_factory_pkgconfig_libs") ++ file (STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/plugins/static_factory_pkgconfig_libs" VSXU_PLUGIN_PKGCONFIG_LIBS) ++ CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/libvsxu.pc.in.static ++ ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc ++ @ONLY) ++ ++ else() ++ CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/libvsxu.pc.in.dynamic ++ ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc ++ @ONLY) ++ endif() ++ ++ INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/libvsxu.pc ++ DESTINATION ${VSXU_INSTALL_LIB_DIR}/pkgconfig) ++ENDIF() ++ ++ + + + diff --git a/packages/graphics/vsxu/patches/vsxu-02-fix-glfw.patch b/packages/graphics/vsxu/patches/vsxu-02-fix-glfw.patch new file mode 100644 index 000000000..6df9c7bb0 --- /dev/null +++ b/packages/graphics/vsxu/patches/vsxu-02-fix-glfw.patch @@ -0,0 +1,27 @@ +--- vsxu-0.5.1/cmake/modules/FindGLFW.cmake.orig 2015-05-12 14:22:23.123621176 +0200 ++++ vsxu-0.5.1/cmake/modules/FindGLFW.cmake 2015-05-12 14:23:14.863620161 +0200 +@@ -19,6 +19,14 @@ + # TODO: + # Allow the user to select to link to a shared library or to a static library. + ++find_package(PkgConfig) ++ ++pkg_check_modules(GLFW libglfw) ++set(GLFW_INCLUDE_PATH ${GLFW_INCLUDE_DIRS}) ++set(GLFW_LIBRARY ${GLFW_LIBRARIES} -lXrandr) ++ ++if(NOT GLFW_FOUND) ++ + #Search for the include file... + FIND_PATH(GLFW_INCLUDE_PATH GL/glfw.h DOC "Path to GLFW include directory." + HINTS +@@ -45,5 +53,7 @@ + ${GLFW_ROOT_DIR}/lib-msvc100/release # added by ptr + ) + ++endif() ++ + INCLUDE(FindPackageHandleStandardArgs) +-FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW DEFAULT_MSG GLFW_LIBRARY GLFW_INCLUDE_PATH) +\ No newline at end of file ++FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW DEFAULT_MSG GLFW_LIBRARY GLFW_INCLUDE_PATH) diff --git a/packages/graphics/vsxu/patches/vsxu-03-fix-exr.patch b/packages/graphics/vsxu/patches/vsxu-03-fix-exr.patch new file mode 100644 index 000000000..34530a5f8 --- /dev/null +++ b/packages/graphics/vsxu/patches/vsxu-03-fix-exr.patch @@ -0,0 +1,11 @@ +--- vsxu-0.5.1/plugins/src/texture/CMakeLists.txt.orig 2015-05-12 14:04:42.659641970 +0200 ++++ vsxu-0.5.1/plugins/src/texture/CMakeLists.txt 2015-05-12 14:05:43.315640780 +0200 +@@ -8,7 +8,7 @@ + + message("configuring vsxu module " ${module_id}) + +-include_directories(/usr/include/OpenEXR) ++#include_directories(/usr/include/OpenEXR) + + # set defines for MOD_CM, MOD_DM, MOD_NM + CREATE_STATIC_GLUE(${module_id}) diff --git a/packages/graphics/vsxu/patches/vsxu-04-fix-freetype.patch b/packages/graphics/vsxu/patches/vsxu-04-fix-freetype.patch new file mode 100644 index 000000000..36213245c --- /dev/null +++ b/packages/graphics/vsxu/patches/vsxu-04-fix-freetype.patch @@ -0,0 +1,11 @@ +--- vsxu-0.5.1/plugins/src/render.text/CMakeLists.txt.orig 2015-05-12 14:07:20.367638877 +0200 ++++ vsxu-0.5.1/plugins/src/render.text/CMakeLists.txt 2015-05-12 14:07:24.371638799 +0200 +@@ -20,7 +20,7 @@ + endif(WIN32) + + if(UNIX) +- include_directories(/usr/include/freetype2) ++ # include_directories(/usr/include/freetype2) + endif(UNIX) + + # include common diff --git a/packages/graphics/vulkan-headers/package.mk b/packages/graphics/vulkan-headers/package.mk new file mode 100644 index 000000000..5cd09e776 --- /dev/null +++ b/packages/graphics/vulkan-headers/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="vulkan-headers" +PKG_VERSION="ec2db85225ab410bc6829251bef6c578aaed5868" +#PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="apache-2.0" +PKG_DEPENDS_TARGET="toolchain" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Headers" +PKG_URL="${PKG_SITE}/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Vulkan header files and API registry" + diff --git a/packages/graphics/vulkan-loader/package.mk b/packages/graphics/vulkan-loader/package.mk new file mode 100644 index 000000000..17d4ebd0d --- /dev/null +++ b/packages/graphics/vulkan-loader/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="vulkan-loader" +PKG_VERSION="6fcd515be5b305d9a68ba94b911f84c76a30887e" +#PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="apache-2.0" +PKG_DEPENDS_TARGET="toolchain vulkan-headers" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Loader" +PKG_URL="${PKG_SITE}/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Khronos official Vulkan ICD desktop loader for Windows, Linux, and MacOS." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF" + diff --git a/packages/graphics/vulkan-tools/package.mk b/packages/graphics/vulkan-tools/package.mk new file mode 100644 index 000000000..a8171afad --- /dev/null +++ b/packages/graphics/vulkan-tools/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="vulkan-tools" +PKG_VERSION="a03938051ff67dac3e13dd011238fccc529e1fa5" +#PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="apache-2.0" +PKG_DEPENDS_TARGET="toolchain vulkan-headers" +PKG_SITE="https://github.com/KhronosGroup/Vulkan-Tools" +PKG_URL="${PKG_SITE}/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Khronos official Vulkan Tools and Utilities for Windows, Linux, Android, and MacOS." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_WSI_XCB_SUPPORT=OFF \ + -DBUILD_WSI_XLIB_SUPPORT=OFF \ + -DBUILD_WSI_WAYLAND_SUPPORT=OFF \ + -DBUILD_CUBE=OFF" + diff --git a/packages/jelos/config/distribution/configs/all/autoconf.cfg b/packages/jelos/config/distribution/configs/all/autoconf.cfg new file mode 100644 index 000000000..92edc5548 --- /dev/null +++ b/packages/jelos/config/distribution/configs/all/autoconf.cfg @@ -0,0 +1 @@ +8bitdo_hack = "0" diff --git a/packages/jelos/config/distribution/configs/all/bluetooth.cfg b/packages/jelos/config/distribution/configs/all/bluetooth.cfg new file mode 100644 index 000000000..709f97348 --- /dev/null +++ b/packages/jelos/config/distribution/configs/all/bluetooth.cfg @@ -0,0 +1 @@ +connect_mode="default" diff --git a/packages/jelos/config/distribution/configs/atari800.cfg b/packages/jelos/config/distribution/configs/atari800.cfg new file mode 100644 index 000000000..155f546a7 --- /dev/null +++ b/packages/jelos/config/distribution/configs/atari800.cfg @@ -0,0 +1,109 @@ +Atari 800 Emulator, Version 3.1.0 +ROM_OS_A_NTSC= +ROM_OS_A_PAL=/storage/roms/bios/ATARIOSA.ROM +ROM_OS_B_NTSC= +ROM_OS_AA00R10= +ROM_OS_AA00R11= +ROM_OS_BB00R1= +ROM_OS_BB01R2=/storage/roms/bios/ATARIXL.ROM +ROM_OS_BB02R3= +ROM_OS_BB02R3V4= +ROM_OS_CC01R4= +ROM_OS_BB01R3= +ROM_OS_BB01R4= +ROM_OS_BB01R59= +ROM_OS_BB01R59A= +ROM_5200=/storage/roms/bios/5200.rom +ROM_5200_A=/storage/roms/bios/5200a.rom +ROM_BASIC_A=/storage/roms/bios/BASIC_Rev_A.rom +ROM_BASIC_B=/storage/roms/bios/BASIC_Rev_B.rom +ROM_BASIC_C=/storage/roms/bios/ATARIBAS.ROM +ROM_XEGAME= +ROM_400/800_CUSTOM=/storage/roms/bios/ATARIOSB.ROM +ROM_XL/XE_CUSTOM= +ROM_5200_CUSTOM= +ROM_BASIC_CUSTOM= +ROM_XEGAME_CUSTOM= +OS_400/800_VERSION=AUTO +OS_XL/XE_VERSION=AUTO +OS_5200_VERSION=AUTO +BASIC_VERSION=AUTO +XEGS_GAME_VERSION=AUTO +H1_DIR= +H2_DIR= +H3_DIR= +H4_DIR= +HD_READ_ONLY=1 +PRINT_COMMAND=lpr %s +SCREEN_REFRESH_RATIO=1 +MACHINE_TYPE=Atari 5200 +DEFAULT_TV_MODE=NTSC +MOSAIC_RAM_NUM_BANKS=0 +AXLON_RAM_NUM_BANKS=0 +ENABLE_MAPRAM=0 +DISABLE_BASIC=1 +ENABLE_SIO_PATCH=0 +ENABLE_SLOW_XEX_LOADING=0 +ENABLE_H_PATCH=0 +ENABLE_P_PATCH=0 +ENABLE_NEW_POKEY=1 +KEYBOARD_LEDS=0 +F_KEYS=0 +BUILTIN_GAME=0 +KEYBOARD_DETACHED=0 +1200XL_JUMPER=0 +CFG_SAVE_ON_EXIT=0 +MIO_ROM= +BLACK_BOX_ROM= +PROTO80_ROM= +CARTRIDGE_FILENAME= +CARTRIDGE_TYPE=0 +CARTRIDGE_PIGGYBACK_FILENAME= +CARTRIDGE_PIGGYBACK_TYPE=0 +CARTRIDGE_AUTOREBOOT=1 +CASSETTE_FILENAME= +CASSETTE_LOADED=0 +CASSETTE_WRITE_PROTECT=0 +RTIME=1 +XEP80_CHARSET= +AF80_ROM= +AF80_CHARSET= +COLOURS_NTSC_SATURATION=0 +COLOURS_NTSC_CONTRAST=0 +COLOURS_NTSC_BRIGHTNESS=0 +COLOURS_NTSC_GAMMA=2.35 +COLOURS_NTSC_HUE=0 +COLOURS_NTSC_GTIA_DELAY=26.8 +COLOURS_NTSC_EXTERNAL_PALETTE= +COLOURS_NTSC_EXTERNAL_PALETTE_LOADED=0 +COLOURS_NTSC_ADJUST_EXTERNAL_PALETTE=0 +COLOURS_PAL_SATURATION=0 +COLOURS_PAL_CONTRAST=0 +COLOURS_PAL_BRIGHTNESS=0 +COLOURS_PAL_GAMMA=2.35 +COLOURS_PAL_HUE=0 +COLOURS_PAL_GTIA_DELAY=23.2 +COLOURS_PAL_EXTERNAL_PALETTE= +COLOURS_PAL_EXTERNAL_PALETTE_LOADED=0 +COLOURS_PAL_ADJUST_EXTERNAL_PALETTE=0 +ARTIFACT_NTSC=NONE +ARTIFACT_PAL=NONE +ARTIFACT_NTSC_MODE=0 +SCREEN_SHOW_SPEED=0 +SCREEN_SHOW_IO_ACTIVITY=1 +SCREEN_SHOW_IO_COUNTER=0 +SCREEN_SHOW_1200XL_LEDS=1 +FILTER_NTSC_SHARPNESS=-0.5 +FILTER_NTSC_RESOLUTION=-0.1 +FILTER_NTSC_ARTIFACTS=0 +FILTER_NTSC_FRINGING=0 +FILTER_NTSC_BLEED=0 +FILTER_NTSC_BURST_PHASE=0 +SOUND_ENABLED=1 +SOUND_RATE=44100 +SOUND_BITS=16 +SOUND_BUFFER_MS=0 +SOUND_LATENCY=20 +RAM_SIZE=16 +STEREO_POKEY=0 +BUILTIN_BASIC=0 diff --git a/packages/jelos/config/distribution/configs/distribution.conf b/packages/jelos/config/distribution/configs/distribution.conf new file mode 100644 index 000000000..ff2ed4940 --- /dev/null +++ b/packages/jelos/config/distribution/configs/distribution.conf @@ -0,0 +1,187 @@ +global.analogue=1 +ssh.enabled=1 +samba.enabled=0 +bluetooth.enabled=0 +global.maxperf=0 +boot=Emulationstation +splash.enabled=0 +advmame_auto_gamepad=0 +system.hostname=JELOS +rotate.root.password=1 +wifi.enabled=0 +audio.bgmusic=1 +controllers.bluetooth.enabled=1 +system.language=en_US +system.timezone=America/New_York +global.retroarch.menu_driver=ozone +global.ratio=core +global.autosave=2 +global.incrementalsavestates=0 +global.runahead=0 +global.secondinstance=0 +global.retroachievements=0 +global.retroachievements.hardcore=0 +global.retroachievements.leaderboards=disabled +global.retroachievements.challengeindicators=0 +global.retroachievements.richpresence=0 +global.retroachievements.testunofficial=0 +global.retroachievements.soundenable=0 +global.retroachievements.verbose=0 +global.retroachievements.screenshot=0 +global.retroachievements.username= +global.retroachievements.password= +audio.display_titles=1 +audio.persystem=0 +global.netplay=0 +global.netplay.port=55435 +global.netplay.relay=none +audio.device=headphone +audio.volume=75 +3do.maxperf=1 +3do.ratio=4/3 +3do.integerscale=1 +3do.rewind=0 +amiga.ratio=4/3 +amiga.integerscale=1 +amigacd32.ratio=4/3 +amigacd32.integerscale=1 +amstradcpc.integerscale=1 +arcade.maxperf=1 +arcade.autosave=0 +atari2600.integerscale=1 +atari5200.integerscale=1 +atari7800.integerscale=1 +atari800.integerscale=1 +atarilynx.integerscale=1 +atarilynx.ratio=core +atarist.integerscale=1 +atomiswave.maxperf=1 +atomiswave.ratio=4/3 +atomiswave.integerscale=1 +cps1.integerscale=1 +cps2.integerscale=1 +cps3.integerscale=1 +colecovision.ratio=4/3 +colecovision.integerscale=1 +c128.integerscale=1 +c16.integerscale=1 +c64.integerscale=1 +daphne.ratio=4/3 +daphne.integerscale=1 +dreamcast.maxperf=1 +dreamcast.ratio=4/3 +dreamcast.integerscale=1 +easyrpg.integerscale=1 +famicom.ratio=4/3 +famicom.integerscale=1 +fbn.ratio=core +fbn.integerscale=1 +fds.ratio=4/3 +fds.integerscale=1 +gamegear.integerscale=1 +gb.integerscale=1 +gba.ratio=3/2 +gbah.ratio=3/2 +gbc.integerscale=1 +gbch.integerscale=1 +gbh.integerscale=1 +genesis.ratio=4/3 +genesis.integerscale=1 +genh.ratio=4/3 +genh.integerscale=1 +ggh.integerscale=1 +intellivision.ratio=4/3 +intellivision.integerscale=1 +j2me.maxperf=1 +mame.autosave=0 +mame.maxperf=1 +mame.integerscale=1 +mastersystem.integerscale=1 +megacd.ratio=4/3 +megacd.integerscale=1 +megaduck.integerscale=1 +megadrive.ratio=4/3 +megadrive.integerscale=1 +megadrive-japan.ratio=4/3 +megadrive-japan.integerscale=1 +msx.ratio=4/3 +msx.integerscale=1 +msx2.ratio=4/3 +msx2.integerscale=1 +n64.maxperf=1 +n64.ratio=4/3 +n64.integerscale=1 +nds.maxperf=1 +naomi.maxperf=1 +naomi.ratio=4/3 +naomi.integerscale=1 +neocd.ratio=4/3 +neocd.integerscale=1 +neogeo.ratio=4/3 +neogeo.integerscale=1 +nes.ratio=4/3 +nes.integerscale=1 +nesh.ratio=4/3 +nesh.integerscale=1 +ngp.integerscale=1 +ngpc.intergerscale=1 +odyssey2.ratio=4/3 +odyssey2.integerscale=1 +pc.maxperf=1 +pc.ratio=4/3 +pc.integerscale=1 +pc-9800.ratio=4/3 +pc-9800.integerscale=1 +pcengine.ratio=4/3 +pcengine.integerscale=1 +pcenginecd.ratio=4/3 +pcenginecd.integerscale=1 +pcfx.maxperf=1 +pcfx.ratio=4/3 +pcfx.integerscale=1 +pokemini.ratio=3/2 +psp.maxperf=1 +pspminis.maxperf=1 +psx.ratio=4/3 +psx.integerscale=1 +saturn.ratio=4/3 +saturn.integerscale=1 +sc-3000.integerscale=1 +sega32x.ratio=4/3 +sega32x.integerscale=1 +segacd.ratio=4/3 +segacd.integerscale=1 +sfc.ratio=4/3 +sfc.integerscale=1 +sg-1000.integerscale=1 +snes.ratio=4/3 +snes.integerscale=1 +snesh.ratio=4/3 +snesh.integerscale=1 +snesmsu1.ratio=4/3 +snesmsu1.integerscale=1 +supergrafx.ratio=4/3 +supergrafx.integerscale=1 +supervision.integerscale=1 +tg16.ratio=4/3 +tg16.integerscale=1 +tg16cd.ratio=4/3 +tg16cd.integerscale=1 +uzebox.integerscale=1 +uzebox.integerscale=1 +vectrex.ratio=3/4 +vectrex.integerscale=1 +vic20.ratio=4/3 +vic20.integerscale=1 +videopac.ratio=4/3 +videopac.integerscale=1 +virtualboy.integerscale=1 +virtualboy.maxperf=1 +wonderswan.integerscale=1 +wonderswancolor.integerscale=1 +x68000.ratio=4/3 +x68000.integerscale=1 +zxspectrum.ratio=4/3 +zxspectrum.integerscale=1 +zx81.ratio=4/3 +zx81.integerscale=1 diff --git a/packages/jelos/config/distribution/configs/tz b/packages/jelos/config/distribution/configs/tz new file mode 100644 index 000000000..fe39d982c --- /dev/null +++ b/packages/jelos/config/distribution/configs/tz @@ -0,0 +1,593 @@ +Africa/Abidjan +Africa/Accra +Africa/Addis_Ababa +Africa/Algiers +Africa/Asmara +Africa/Asmera +Africa/Bamako +Africa/Bangui +Africa/Banjul +Africa/Bissau +Africa/Blantyre +Africa/Brazzaville +Africa/Bujumbura +Africa/Cairo +Africa/Casablanca +Africa/Ceuta +Africa/Conakry +Africa/Dakar +Africa/Dar_es_Salaam +Africa/Djibouti +Africa/Douala +Africa/El_Aaiun +Africa/Freetown +Africa/Gaborone +Africa/Harare +Africa/Johannesburg +Africa/Juba +Africa/Kampala +Africa/Khartoum +Africa/Kigali +Africa/Kinshasa +Africa/Lagos +Africa/Libreville +Africa/Lome +Africa/Luanda +Africa/Lubumbashi +Africa/Lusaka +Africa/Malabo +Africa/Maputo +Africa/Maseru +Africa/Mbabane +Africa/Mogadishu +Africa/Monrovia +Africa/Nairobi +Africa/Ndjamena +Africa/Niamey +Africa/Nouakchott +Africa/Ouagadougou +Africa/Porto-Novo +Africa/Sao_Tome +Africa/Timbuktu +Africa/Tripoli +Africa/Tunis +Africa/Windhoek +America/Adak +America/Anchorage +America/Anguilla +America/Antigua +America/Araguaina +America/Argentina/Buenos_Aires +America/Argentina/Catamarca +America/Argentina/ComodRivadavia +America/Argentina/Cordoba +America/Argentina/Jujuy +America/Argentina/La_Rioja +America/Argentina/Mendoza +America/Argentina/Rio_Gallegos +America/Argentina/Salta +America/Argentina/San_Juan +America/Argentina/San_Luis +America/Argentina/Tucuman +America/Argentina/Ushuaia +America/Aruba +America/Asuncion +America/Atikokan +America/Atka +America/Bahia +America/Bahia_Banderas +America/Barbados +America/Belem +America/Belize +America/Blanc-Sablon +America/Boa_Vista +America/Bogota +America/Boise +America/Buenos_Aires +America/Cambridge_Bay +America/Campo_Grande +America/Cancun +America/Caracas +America/Catamarca +America/Cayenne +America/Cayman +America/Chicago +America/Chihuahua +America/Coral_Harbour +America/Cordoba +America/Costa_Rica +America/Creston +America/Cuiaba +America/Curacao +America/Danmarkshavn +America/Dawson +America/Dawson_Creek +America/Denver +America/Detroit +America/Dominica +America/Edmonton +America/Eirunepe +America/El_Salvador +America/Ensenada +America/Fort_Nelson +America/Fort_Wayne +America/Fortaleza +America/Glace_Bay +America/Godthab +America/Goose_Bay +America/Grand_Turk +America/Grenada +America/Guadeloupe +America/Guatemala +America/Guayaquil +America/Guyana +America/Halifax +America/Havana +America/Hermosillo +America/Indiana/Indianapolis +America/Indiana/Knox +America/Indiana/Marengo +America/Indiana/Petersburg +America/Indiana/Tell_City +America/Indiana/Vevay +America/Indiana/Vincennes +America/Indiana/Winamac +America/Indianapolis +America/Inuvik +America/Iqaluit +America/Jamaica +America/Jujuy +America/Juneau +America/Kentucky/Louisville +America/Kentucky/Monticello +America/Knox_IN +America/Kralendijk +America/La_Paz +America/Lima +America/Los_Angeles +America/Louisville +America/Lower_Princes +America/Maceio +America/Managua +America/Manaus +America/Marigot +America/Martinique +America/Matamoros +America/Mazatlan +America/Mendoza +America/Menominee +America/Merida +America/Metlakatla +America/Mexico_City +America/Miquelon +America/Moncton +America/Monterrey +America/Montevideo +America/Montreal +America/Montserrat +America/Nassau +America/New_York +America/Nipigon +America/Nome +America/Noronha +America/North_Dakota/Beulah +America/North_Dakota/Center +America/North_Dakota/New_Salem +America/Ojinaga +America/Panama +America/Pangnirtung +America/Paramaribo +America/Phoenix +America/Port-au-Prince +America/Port_of_Spain +America/Porto_Acre +America/Porto_Velho +America/Puerto_Rico +America/Punta_Arenas +America/Rainy_River +America/Rankin_Inlet +America/Recife +America/Regina +America/Resolute +America/Rio_Branco +America/Rosario +America/Santa_Isabel +America/Santarem +America/Santiago +America/Santo_Domingo +America/Sao_Paulo +America/Scoresbysund +America/Shiprock +America/Sitka +America/St_Barthelemy +America/St_Johns +America/St_Kitts +America/St_Lucia +America/St_Thomas +America/St_Vincent +America/Swift_Current +America/Tegucigalpa +America/Thule +America/Thunder_Bay +America/Tijuana +America/Toronto +America/Tortola +America/Vancouver +America/Virgin +America/Whitehorse +America/Winnipeg +America/Yakutat +America/Yellowknife +Antarctica/Casey +Antarctica/Davis +Antarctica/DumontDUrville +Antarctica/Macquarie +Antarctica/Mawson +Antarctica/McMurdo +Antarctica/Palmer +Antarctica/Rothera +Antarctica/South_Pole +Antarctica/Syowa +Antarctica/Troll +Antarctica/Vostok +Arctic/Longyearbyen +Asia/Aden +Asia/Almaty +Asia/Amman +Asia/Anadyr +Asia/Aqtau +Asia/Aqtobe +Asia/Ashgabat +Asia/Ashkhabad +Asia/Atyrau +Asia/Baghdad +Asia/Bahrain +Asia/Baku +Asia/Bangkok +Asia/Barnaul +Asia/Beirut +Asia/Bishkek +Asia/Brunei +Asia/Calcutta +Asia/Chita +Asia/Choibalsan +Asia/Chongqing +Asia/Chungking +Asia/Colombo +Asia/Dacca +Asia/Damascus +Asia/Dhaka +Asia/Dili +Asia/Dubai +Asia/Dushanbe +Asia/Famagusta +Asia/Gaza +Asia/Harbin +Asia/Hebron +Asia/Ho_Chi_Minh +Asia/Hong_Kong +Asia/Hovd +Asia/Irkutsk +Asia/Istanbul +Asia/Jakarta +Asia/Jayapura +Asia/Jerusalem +Asia/Kabul +Asia/Kamchatka +Asia/Karachi +Asia/Kashgar +Asia/Kathmandu +Asia/Katmandu +Asia/Khandyga +Asia/Kolkata +Asia/Krasnoyarsk +Asia/Kuala_Lumpur +Asia/Kuching +Asia/Kuwait +Asia/Macao +Asia/Macau +Asia/Magadan +Asia/Makassar +Asia/Manila +Asia/Muscat +Asia/Nicosia +Asia/Novokuznetsk +Asia/Novosibirsk +Asia/Omsk +Asia/Oral +Asia/Phnom_Penh +Asia/Pontianak +Asia/Pyongyang +Asia/Qatar +Asia/Qostanay +Asia/Qyzylorda +Asia/Rangoon +Asia/Riyadh +Asia/Saigon +Asia/Sakhalin +Asia/Samarkand +Asia/Seoul +Asia/Shanghai +Asia/Singapore +Asia/Srednekolymsk +Asia/Taipei +Asia/Tashkent +Asia/Tbilisi +Asia/Tehran +Asia/Tel_Aviv +Asia/Thimbu +Asia/Thimphu +Asia/Tokyo +Asia/Tomsk +Asia/Ujung_Pandang +Asia/Ulaanbaatar +Asia/Ulan_Bator +Asia/Urumqi +Asia/Ust-Nera +Asia/Vientiane +Asia/Vladivostok +Asia/Yakutsk +Asia/Yangon +Asia/Yekaterinburg +Asia/Yerevan +Atlantic/Azores +Atlantic/Bermuda +Atlantic/Canary +Atlantic/Cape_Verde +Atlantic/Faeroe +Atlantic/Faroe +Atlantic/Jan_Mayen +Atlantic/Madeira +Atlantic/Reykjavik +Atlantic/South_Georgia +Atlantic/St_Helena +Atlantic/Stanley +Australia/ACT +Australia/Adelaide +Australia/Brisbane +Australia/Broken_Hill +Australia/Canberra +Australia/Currie +Australia/Darwin +Australia/Eucla +Australia/Hobart +Australia/LHI +Australia/Lindeman +Australia/Lord_Howe +Australia/Melbourne +Australia/NSW +Australia/North +Australia/Perth +Australia/Queensland +Australia/South +Australia/Sydney +Australia/Tasmania +Australia/Victoria +Australia/West +Australia/Yancowinna +Brazil/Acre +Brazil/DeNoronha +Brazil/East +Brazil/West +CET +CST6CDT +Canada/Atlantic +Canada/Central +Canada/Eastern +Canada/Mountain +Canada/Newfoundland +Canada/Pacific +Canada/Saskatchewan +Canada/Yukon +Chile/Continental +Chile/EasterIsland +Cuba +EET +EST +EST5EDT +Egypt +Eire +Etc/GMT +Etc/GMT+0 +Etc/GMT+1 +Etc/GMT+10 +Etc/GMT+11 +Etc/GMT+12 +Etc/GMT+2 +Etc/GMT+3 +Etc/GMT+4 +Etc/GMT+5 +Etc/GMT+6 +Etc/GMT+7 +Etc/GMT+8 +Etc/GMT+9 +Etc/GMT-0 +Etc/GMT-1 +Etc/GMT-10 +Etc/GMT-11 +Etc/GMT-12 +Etc/GMT-13 +Etc/GMT-14 +Etc/GMT-2 +Etc/GMT-3 +Etc/GMT-4 +Etc/GMT-5 +Etc/GMT-6 +Etc/GMT-7 +Etc/GMT-8 +Etc/GMT-9 +Etc/GMT0 +Etc/Greenwich +Etc/UCT +Etc/UTC +Etc/Universal +Etc/Zulu +Europe/Amsterdam +Europe/Andorra +Europe/Astrakhan +Europe/Athens +Europe/Belfast +Europe/Belgrade +Europe/Berlin +Europe/Bratislava +Europe/Brussels +Europe/Bucharest +Europe/Budapest +Europe/Busingen +Europe/Chisinau +Europe/Copenhagen +Europe/Dublin +Europe/Gibraltar +Europe/Guernsey +Europe/Helsinki +Europe/Isle_of_Man +Europe/Istanbul +Europe/Jersey +Europe/Kaliningrad +Europe/Kiev +Europe/Kirov +Europe/Lisbon +Europe/Ljubljana +Europe/London +Europe/Luxembourg +Europe/Madrid +Europe/Malta +Europe/Mariehamn +Europe/Minsk +Europe/Monaco +Europe/Moscow +Europe/Nicosia +Europe/Oslo +Europe/Paris +Europe/Podgorica +Europe/Prague +Europe/Riga +Europe/Rome +Europe/Samara +Europe/San_Marino +Europe/Sarajevo +Europe/Saratov +Europe/Simferopol +Europe/Skopje +Europe/Sofia +Europe/Stockholm +Europe/Tallinn +Europe/Tirane +Europe/Tiraspol +Europe/Ulyanovsk +Europe/Uzhgorod +Europe/Vaduz +Europe/Vatican +Europe/Vienna +Europe/Vilnius +Europe/Volgograd +Europe/Warsaw +Europe/Zagreb +Europe/Zaporozhye +Europe/Zurich +GB +GB-Eire +GMT +GMT+0 +GMT-0 +GMT0 +Greenwich +HST +Hongkong +Iceland +Indian/Antananarivo +Indian/Chagos +Indian/Christmas +Indian/Cocos +Indian/Comoro +Indian/Kerguelen +Indian/Mahe +Indian/Maldives +Indian/Mauritius +Indian/Mayotte +Indian/Reunion +Iran +Israel +Jamaica +Japan +Kwajalein +Libya +MET +MST +MST7MDT +Mexico/BajaNorte +Mexico/BajaSur +Mexico/General +NZ +NZ-CHAT +Navajo +PRC +PST8PDT +Pacific/Apia +Pacific/Auckland +Pacific/Bougainville +Pacific/Chatham +Pacific/Chuuk +Pacific/Easter +Pacific/Efate +Pacific/Enderbury +Pacific/Fakaofo +Pacific/Fiji +Pacific/Funafuti +Pacific/Galapagos +Pacific/Gambier +Pacific/Guadalcanal +Pacific/Guam +Pacific/Honolulu +Pacific/Johnston +Pacific/Kiritimati +Pacific/Kosrae +Pacific/Kwajalein +Pacific/Majuro +Pacific/Marquesas +Pacific/Midway +Pacific/Nauru +Pacific/Niue +Pacific/Norfolk +Pacific/Noumea +Pacific/Pago_Pago +Pacific/Palau +Pacific/Pitcairn +Pacific/Pohnpei +Pacific/Ponape +Pacific/Port_Moresby +Pacific/Rarotonga +Pacific/Saipan +Pacific/Samoa +Pacific/Tahiti +Pacific/Tarawa +Pacific/Tongatapu +Pacific/Truk +Pacific/Wake +Pacific/Wallis +Pacific/Yap +Poland +Portugal +ROC +ROK +Singapore +Turkey +UCT +US/Alaska +US/Aleutian +US/Arizona +US/Central +US/East-Indiana +US/Eastern +US/Hawaii +US/Indiana-Starke +US/Michigan +US/Mountain +US/Pacific +US/Pacific-New +US/Samoa +UTC +Universal +W-SU +WET +Zulu diff --git a/packages/jelos/config/distribution/modules/351Files.sh b/packages/jelos/config/distribution/modules/351Files.sh new file mode 100644 index 000000000..4b7c73868 --- /dev/null +++ b/packages/jelos/config/distribution/modules/351Files.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +. /etc/profile +jslisten set "killall 351Files" +source /usr/bin/env.sh +joy2keyStart + +351Files diff --git a/packages/jelos/config/distribution/modules/Remove ._ Files.sh b/packages/jelos/config/distribution/modules/Remove ._ Files.sh new file mode 100755 index 000000000..e1d5b98dd --- /dev/null +++ b/packages/jelos/config/distribution/modules/Remove ._ Files.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +. /etc/profile +source /usr/bin/env.sh +clear >/dev/console +systemctl stop emustation +message_stream "Cleaning ._ files from /storage/roms" +find /storage/roms -iname '._*' -exec rm -rf {} \; +clear >/dev/console +systemctl start emustation diff --git a/packages/jelos/config/distribution/modules/Start 32bit Retroarch.sh b/packages/jelos/config/distribution/modules/Start 32bit Retroarch.sh new file mode 100755 index 000000000..5da3b25f2 --- /dev/null +++ b/packages/jelos/config/distribution/modules/Start 32bit Retroarch.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +source /usr/bin/env.sh +source /etc/profile + +jslisten set "killall retroarch32" + +set_kill_keys "retroarch32" +export LD_LIBRARY_PATH="/usr/lib32" +/usr/bin/retroarch32 --appendconfig /usr/config/retroarch/retroarch32bit-append.cfg +/usr/bin/clear-retroarch.sh diff --git a/packages/jelos/config/distribution/modules/Start 64bit Retroarch.sh b/packages/jelos/config/distribution/modules/Start 64bit Retroarch.sh new file mode 100755 index 000000000..cb298b839 --- /dev/null +++ b/packages/jelos/config/distribution/modules/Start 64bit Retroarch.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +source /usr/bin/env.sh +source /etc/profile + +jslisten set "killall retroarch" + +/usr/bin/retroarch --appendconfig /usr/config/retroarch/retroarch64bit-append.cfg +/usr/bin/clear-retroarch.sh diff --git a/packages/jelos/config/distribution/modules/Start PPSSPP.sh b/packages/jelos/config/distribution/modules/Start PPSSPP.sh new file mode 100755 index 000000000..3fe1d1155 --- /dev/null +++ b/packages/jelos/config/distribution/modules/Start PPSSPP.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +source /usr/bin/env.sh +source /etc/profile + +jslisten set "killall PPSSPPSDL" + +cp -rf /storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt /storage/roms/gamedata/ppsspp/assets/gamecontrollerdb.txt + +/usr/bin/PPSSPPSDL diff --git a/packages/jelos/config/distribution/modules/Start ScummVM.sh b/packages/jelos/config/distribution/modules/Start ScummVM.sh new file mode 100644 index 000000000..5f26fbeb2 --- /dev/null +++ b/packages/jelos/config/distribution/modules/Start ScummVM.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC + +source /usr/bin/env.sh +source /etc/profile + +jslisten set "killall scummvm" + +/usr/bin/scummvm.start sa diff --git a/packages/jelos/config/distribution/modules/downloaded_images/clean-thumb.png b/packages/jelos/config/distribution/modules/downloaded_images/clean-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..9b89d2260c1ace5798eb7b62e18694567f2b5e49 GIT binary patch literal 16952 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%0ArCYE+;F^Y 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 T>~Wv`ZwECcEyV(Pi~Iiv<+STM literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/clean.png b/packages/jelos/config/distribution/modules/downloaded_images/clean.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3b83e40300901f967fe0b0bf69520119d1f053 GIT binary patch literal 24024 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 literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/filemanager-thumb.png b/packages/jelos/config/distribution/modules/downloaded_images/filemanager-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..98bafd2ec9fc0a0a62ab604e26ef315351462fff GIT binary patch literal 12922 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 JnTmDT{{WPTcMkvn literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/filemanager.png b/packages/jelos/config/distribution/modules/downloaded_images/filemanager.png new file mode 100644 index 0000000000000000000000000000000000000000..d50b6c680e64f5f8916638de732f779db1d56b12 GIT binary patch literal 21002 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 L`njxgN@xNA#wg4K literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/ppsspp.png b/packages/jelos/config/distribution/modules/downloaded_images/ppsspp.png new file mode 100644 index 0000000000000000000000000000000000000000..78b6c2ffbb8e53cb95c3d14a76f60d6168506e4d GIT binary patch literal 26263 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 literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/retroarch32-thumb.png b/packages/jelos/config/distribution/modules/downloaded_images/retroarch32-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..c06fbbebcd04c7d52401ab9ad9edbdbbf839f143 GIT binary patch literal 16291 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 literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/retroarch32.png b/packages/jelos/config/distribution/modules/downloaded_images/retroarch32.png new file mode 100644 index 0000000000000000000000000000000000000000..399ac4603de0ad476547c972ab240817b645b019 GIT binary patch literal 22279 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 QkcLJJr>9n_aw+700fMGoasU7T literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/scummvm.png b/packages/jelos/config/distribution/modules/downloaded_images/scummvm.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc5d4a714d2f42f75ec67861f4982ff5ae33d37 GIT binary patch literal 24180 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 I>zopr0DYOrqyPW_ literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/downloaded_images/template.png b/packages/jelos/config/distribution/modules/downloaded_images/template.png new file mode 100644 index 0000000000000000000000000000000000000000..5a8542ba8846a0882ecca8ad0385975e51203487 GIT binary patch literal 7568 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 literal 0 HcmV?d00001 diff --git a/packages/jelos/config/distribution/modules/gamelist.xml b/packages/jelos/config/distribution/modules/gamelist.xml new file mode 100644 index 000000000..5753ab905 --- /dev/null +++ b/packages/jelos/config/distribution/modules/gamelist.xml @@ -0,0 +1,82 @@ + + + + + ./Start PPSSPP.sh + Start PPSSPP + Run the PPSSPP emulator without starting a game. + 351ELEC + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/ppsspp-thumb.png + ./downloaded_images/ppsspp.png + + + + ./Start ScummVM.sh + Start ScummVM + Run the ScummVM emulator without starting a game. + 351ELEC + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/scummvm-thumb.png + ./downloaded_images/scummvm.png + + + + ./Start 32bit Retroarch.sh + Start 32bit RetroArch + Run 32bit RetroArch + 351ELEC + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/retroarch32-thumb.png + ./downloaded_images/retroarch32.png + + + + ./Start 64bit Retroarch.sh + Start 64bit RetroArch + Run 64bit RetroArch + 351ELEC + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/retroarch64-thumb.png + ./downloaded_images/retroarch64.png + + + + ./Remove ._ Files.sh + Run Remove ._ Files + Removes hidden ._ files created by the MacOS filesystem + 351ELEC + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/clean-thumb.png + ./downloaded_images/clean.png + + + + ./351Files.sh + 351Files + Single panel file manager + Tardigrade + 351ELEC + 1.0 + 2021 + Script + ./downloaded_images/filemanager-thumb.png + ./downloaded_images/filemanager.png + + + diff --git a/packages/jelos/gamepads/GO-Super Gamepad.cfg b/packages/jelos/gamepads/GO-Super Gamepad.cfg new file mode 100644 index 000000000..7d34c0580 --- /dev/null +++ b/packages/jelos/gamepads/GO-Super Gamepad.cfg @@ -0,0 +1,53 @@ +input_device = "GO-Super Gamepad" +input_driver = "udev" +input_vendor_id = "484B" +input_product_id = "1100" + +input_b_btn = "0" +input_a_btn = "1" +input_x_btn = "2" +input_y_btn = "3" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "6" +input_r2_btn = "7" + +input_up_btn = "8" +input_down_btn = "9" +input_left_btn = "10" +input_right_btn = "11" + +input_select_btn = "12" +input_start_btn = "13" + +input_l3_btn = "14" +input_r3_btn = "15" + +input_l_x_plus_axis = "+0" +input_l_x_minus_axis = "-0" +input_l_y_plus_axis = "+1" +input_l_y_minus_axis = "-1" + +input_r_x_plus_axis = "+2" +input_r_x_minus_axis = "-2" +input_r_y_plus_axis = "+3" +input_r_y_minus_axis = "-3" + + +# Hotkeys +input_enable_hotkey_btn = "12" +input_exit_emulator_btn = "13" + +input_screenshot_btn = "0" +input_pause_toggle_btn = "1" +input_menu_toggle_btn = "2" +input_fps_toggle_btn = "3" + +input_state_slot_increase_btn = "8" +input_state_slot_decrease_btn = "9" + +input_load_state_btn = "4" +input_save_state_btn = "5" + +input_rewind_btn = "6" +input_toggle_fast_forward_btn = "7" \ No newline at end of file diff --git a/packages/jelos/gamepads/OpenSimHardware OSH PB Controller.cfg b/packages/jelos/gamepads/OpenSimHardware OSH PB Controller.cfg new file mode 100755 index 000000000..3ce54afbc --- /dev/null +++ b/packages/jelos/gamepads/OpenSimHardware OSH PB Controller.cfg @@ -0,0 +1,51 @@ +input_device = "OpenSimHardware OSH PB Controller" +input_driver = "udev" +input_vendor_id = "4617" +input_product_id = "12544" + +input_b_btn = "16" +input_a_btn = "15" +input_x_btn = "17" +input_y_btn = "18" +input_l_btn = "19" +input_r_btn = "20" +input_l2_btn = "25" +input_r2_btn = "26" + +input_select_btn = "22" +input_start_btn = "21" + +input_l3_btn = "23" +input_r3_btn = "24" + +input_up_btn = "h0up" +input_down_btn = "h0down" +input_left_btn = "h0left" +input_right_btn = "h0right" + +input_l_x_plus_axis = "-0" +input_l_x_minus_axis = "+0" +input_l_y_plus_axis = "-1" +input_l_y_minus_axis = "+1" + +input_r_x_plus_axis = "+2" +input_r_x_minus_axis = "-2" +input_r_y_plus_axis = "+3" +input_r_y_minus_axis = "-3" + +input_enable_hotkey_btn = "22" +input_exit_emulator_btn = "21" + +input_screenshot_btn = "16" +input_pause_toggle_btn = "15" +input_menu_toggle_btn = "17" +input_fps_toggle_btn = "18" + +input_state_slot_decrease_btn = "h0down" +input_state_slot_increase_btn = "h0up" + +input_load_state_btn = "19" +input_save_state_btn = "20" + +input_rewind_btn = "25" +input_toggle_fast_forward_btn = "26" \ No newline at end of file diff --git a/packages/jelos/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg b/packages/jelos/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg new file mode 100644 index 000000000..f9905f278 --- /dev/null +++ b/packages/jelos/gamepads/OpenSimHardware OSH PB Controller_SDL.cfg @@ -0,0 +1,41 @@ +input_device = "OpenSimHardware OSH PB Controller" +input_driver = "udev" +input_vendor_id = "4617" +input_product_id = "12544" +input_r_y_plus_axis = "+3" +input_l3_btn = "8" +input_r_x_minus_axis = "-2" +input_l_btn = "4" +input_load_state_btn = "4" +input_start_btn = "6" +input_exit_emulator_btn = "6" +input_l_y_minus_axis = "-1" +input_up_btn = "h0up" +input_volume_up_btn = "h0up" +input_r_y_minus_axis = "-3" +input_a_btn = "0" +input_b_btn = "1" +input_screenshot_btn = "16" +input_enable_hotkey_btn = "7" +input_down_btn = "h0down" +input_volume_down_btn = "h0down" +input_l_x_plus_axis = "+0" +input_l_y_plus_axis = "+1" +input_r_btn = "5" +input_save_state_btn = "5" +input_r2_btn = "11" +input_hold_fast_forward_btn = "11" +input_r3_btn = "9" +input_fps_toggle_btn = "9" +input_right_btn = "h0right" +input_state_slot_increase_btn = "h0right" +input_x_btn = "2" +input_menu_toggle_btn = "2" +input_select_btn = "7" +input_l_x_minus_axis = "-0" +input_y_btn = "3" +input_left_btn = "h0left" +input_state_slot_decrease_btn = "h0left" +input_r_x_plus_axis = "+2" +input_l2_btn = "10" +input_rewind_btn = "10" diff --git a/packages/jelos/gamepads/retrogame_joypad.cfg b/packages/jelos/gamepads/retrogame_joypad.cfg new file mode 100644 index 000000000..48b25f86f --- /dev/null +++ b/packages/jelos/gamepads/retrogame_joypad.cfg @@ -0,0 +1,29 @@ +input_driver = "udev" +input_device = "retrogame_joypad" +input_vendor_id = "18507" +input_product_id = "4353" +input_b_btn = "0" +input_y_btn = "3" +input_select_btn = "8" +input_start_btn = "9" +input_up_btn = "13" +input_down_btn = "14" +input_left_btn = "15" +input_right_btn = "16" +input_a_btn = "1" +input_x_btn = "2" +input_l_btn = "4" +input_r_btn = "5" +input_l2_btn = "6" +input_r2_btn = "7" +input_l3_btn = "11" +input_r3_btn = "12" +input_l_x_plus_axis = "+0" +input_l_x_minus_axis = "-0" +input_l_y_plus_axis = "+1" +input_l_y_minus_axis = "-1" +input_r_x_plus_axis = "+2" +input_r_x_minus_axis = "-2" +input_r_y_plus_axis = "+3" +input_r_y_minus_axis = "-3" +input_gun_trigger_mbtn = "1" diff --git a/packages/jelos/package.mk b/packages/jelos/package.mk new file mode 100644 index 000000000..baa0c7a36 --- /dev/null +++ b/packages/jelos/package.mk @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="jelos" +PKG_VERSION="${OS_VERSION}" +PKG_ARCH="any" +PKG_LICENSE="proprietary" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain ${OPENGLES}" +PKG_SHORTDESC="JELOS Meta Package" +PKG_LONGDESC="JELOS Meta Package" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="make" + +PKG_UI="emulationstation" + +PKG_EMUS="common-shaders glsl-shaders libretro-database retroarch ${LIBRETRO_CORES} advancemame \ + hatarisa openbor scummvmsa duckstation PPSSPPSDL" + +LIBRETRO_CORES="2048 81 atari800 beetle-gba beetle-lynx beetle-ngp beetle-pce beetle-pcfx \ + beetle-supafaust beetle-supergrafx beetle-vb beetle-wswan bluemsx cannonball \ + cap32 crocods daphne dinothawr dosbox-svn dosbox-pure easyrpg fbalpha2012 \ + fbalpha2019 fbneo fceumm fmsx flycast freechaf freeintv freej2me fuse-libretro \ + gambatte gearboy gearcoleco gearsystem genesis-plus-gx genesis-plus-gx-wide gme \ + gpsp gw-libretro handy hatari mame2000 mame2003-plus mame2010 mame2015 mame \ + meowpc98 mgba mrboom mupen64plus mupen64plus-nx neocd_libretro nestopia np2kai \ + nxengine o2em opera parallel-n64 parallel-n64_gln64 pcsx_rearmed picodrive \ + pokemini potator ppsspp prboom prosystem puae px68k quasi88 quicknes race \ + reminiscence sameboy sameduck scummvm smsplus-gx snes9x snes9x2002 snes9x2005_plus \ + snes9x2010 stella stella-2014 swanstation TIC-80 tgbdual tyrquake xrick uae4arm \ + uzem vba-next vbam vecx vice yabasanshiro xmil" + +PKG_COMPAT="lib32 gamecontrollerdb" + +PKG_TOOLS="plymouth-lite grep wget ffmpeg libjpeg-turbo MC util-linux xmlstarlet sixaxis jslisten \ + evtest mpv bluetool jslisten gnupg gzip patchelf imagemagick rg351p-js2xbox gptokeyb \ + system-utils textviewer 351files jstest-sdl terminus-font vim bash pyudev dialog six git \ + dbus-python pygobject coreutils" + +PKG_EXPERIMENTAL="" + +PKG_DEPENDS_TARGET+=" ${PKG_UI} ${PKG_TOOLS} ${PKG_EMUS} ${LIBRETRO_CORES} ${PKG_COMPAT} ${PKG_EXPERIMENTAL}" + +make_target() { + : +} + +makeinstall_target() { + + mkdir -p ${INSTALL}/usr/config/ + rsync -av ${PKG_DIR}/config/* ${INSTALL}/usr/config/ + ln -sf /storage/.config/distribution ${INSTALL}/distribution + find ${INSTALL}/usr/config/distribution/ -type f -exec chmod o+x {} \; + + mkdir -p ${INSTALL}/usr/bin/ + + ## Compatibility links for ports + ln -s /storage/roms ${INSTALL}/roms + ln -sf /storage/roms/opt ${INSTALL}/opt + +} + +post_install() { + # Remove unnecesary Retroarch Assets and overlays + for i in branding nuklear nxrgui pkg switch wallpapers zarch COPYING; do + rm -rf "${INSTALL}/usr/share/retroarch-assets/$i" + done + + for i in automatic dot-art flatui neoactive pixel retroactive retrosystem systematic convert.sh NPMApng2PMApng.py; do + rm -rf "${INSTALL}/usr/share/retroarch-assets/xmb/$i" + done + + mkdir -p ${INSTALL}/etc/retroarch-joypad-autoconfig + cp -r ${PKG_DIR}/gamepads/* ${INSTALL}/etc/retroarch-joypad-autoconfig + ln -sf jelos.target ${INSTALL}/usr/lib/systemd/system/default.target + + mkdir -p ${INSTALL}/etc/profile.d + cp ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/device.config ${INSTALL}/etc/profile.d/01-deviceconfig + + # Split this up into other packages + cp ${PKG_DIR}/sources/autostart/autostart ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/lib/autostart/${DEVICE} + mkdir -p ${INSTALL}/usr/lib/autostart/common + mkdir -p ${INSTALL}/usr/lib/autostart/sounds + mkdir -p ${INSTALL}/usr/lib/autostart/daemons + cp ${PKG_DIR}/sources/autostart/sounds/* ${INSTALL}/usr/lib/autostart/sounds + cp ${PKG_DIR}/sources/autostart/common/* ${INSTALL}/usr/lib/autostart/common + cp ${PKG_DIR}/sources/autostart/daemons/* ${INSTALL}/usr/lib/autostart/daemons + cp ${PKG_DIR}/sources/autostart/${DEVICE}/* ${INSTALL}/usr/lib/autostart/${DEVICE} + chmod -R 0755 ${INSTALL}/usr/lib/autostart ${INSTALL}/usr/bin/autostart + enable_service jelos-autostart.service + + # Issue banner + cp ${PKG_DIR}/sources/issue ${INSTALL}/etc + ln -s /etc/issue ${INSTALL}/etc/motd + cat <> ${INSTALL}/etc/issue +==> Build Date: ${BUILD_DATE} +==> Version: ${OS_VERSION} +EOF + + cp ${PKG_DIR}/sources/shutdown.sh ${INSTALL}/usr/bin + cp ${PKG_DIR}/sources/pico-8.sh ${INSTALL}/usr/bin + cp ${PKG_DIR}/sources/scripts/* ${INSTALL}/usr/bin + + if [[ ${DEVICE} =~ RG351 ]]; then + cp ${PKG_DIR}/sources/asound/rg351/asound.conf ${INSTALL}/usr/config/ + elif [[ ${DEVICE} =~ RG552 ]]; then + cp ${PKG_DIR}/sources/asound/rg552/asound.conf ${INSTALL}/usr/config/ + cp ${PKG_DIR}/sources/asound/rg552/asound.state ${INSTALL}/usr/config/ + fi + + rm -f ${INSTALL}/usr/bin/{sh,bash,busybox,sort} + cp $(get_build_dir busybox)/.install_pkg/usr/bin/busybox ${INSTALL}/usr/bin + cp $(get_build_dir bash)/.install_pkg/usr/bin/bash ${INSTALL}/usr/bin + cp $(get_build_dir coreutils)/.install_pkg/usr/bin/sort ${INSTALL}/usr/bin + + ln -sf bash ${INSTALL}/usr/bin/sh + mkdir -p ${INSTALL}/etc + echo "/usr/bin/bash" >>${INSTALL}/etc/shells + echo "/usr/bin/sh" >>${INSTALL}/etc/shells + + echo "chmod 4755 ${INSTALL}/usr/bin/bash" >> ${FAKEROOT_SCRIPT} + echo "chmod 4755 ${INSTALL}/usr/bin/busybox" >> ${FAKEROOT_SCRIPT} + find ${INSTALL}/usr/ -type f -iname "*.sh" -exec chmod +x {} \; + +} diff --git a/packages/jelos/profile.d/02-distribution b/packages/jelos/profile.d/02-distribution new file mode 100644 index 000000000..a321ec93f --- /dev/null +++ b/packages/jelos/profile.d/02-distribution @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +. /etc/os-release + +export PATH="$PATH:/usr/local/bin:/usr/bin:/storage/bin" + +export SDL_GAMECONTROLLERCONFIG_FILE="/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt" + +J_DIR="/storage/.config/distribution" +J_CONF="${J_DIR}/configs/distribution.conf" +ES_CONF="/storage/.emulationstation/es_settings.cfg" +EE_DEVICE=${HW_DEVICE} + +JSLISTENCONF="/storage/.config/distribution/configs/jslisten.cfg" + +get_setting() { + awk -F: '/'${1}'/ { st = index($0,"=");print substr($0,st+1)}' ${J_CONF} +} + +set_setting() { + sed -i "/$1=/d" "${J_CONF}" + [ $2 == "disable" ] && echo "#${1}=" >> "${J_CONF}" || echo "${1}=${2}" >> "${J_CONF}" +} + +set_audio() { + case ${1} in + "default") + AUDIO="alsa" + ;; + *) + AUDIO=${1} + ;; + esac + /usr/bin/rr_audio.sh ${AUDIO} +} + +get_es_setting() { + echo $(sed -n "s|\s*<${1} name=\"${2}\" value=\"\(.*\)\" />|\1|p" ${ES_CONF}) +} + +check_bios() { + +PLATFORM="${1}" +CORE="${2}" +EMULATOR="${3}" +ROMNAME="${4}" +LOG="${5}" + +if [[ -z "$LOG" ]]; then + LOG="/var/log/exec.log" + cat /etc/motd > "$LOG" +fi + +MISSINGBIOS="$(batocera-systems --strictfilter ${PLATFORM})" +if [ "$?" == "2" ]; then + +# formating so it looks nice :) +PLATFORMNAME="${MISSINGBIOS##*>}" # read from -P onwards +PLATFORMNAME="${PLATFORMNAME%%MISSING*}" # until a space is found +PLATFORMNAME=$(echo $PLATFORMNAME | sed -e 's/\\n//g') + +if [[ -f "${LOG}" ]]; then +echo "${CORE} ${EMULATOR} ${ROMNAME}" >> $LOG +echo "${PLATFORMNAME} missing BIOS - Could not find all BIOS: " >> $LOG +echo "please make sure you copied the files into the corresponding folder " >> $LOG +echo "${MISSINGBIOS}" >> $LOG +fi + MISSINGBIOS=$(echo "$MISSINGBIOS" | sed -e 's/$/\\n/g') + + /usr/bin/error.sh "${PLATFORMNAME} missing BIOS" "Could not find all BIOS/files in /storage/roms, the game may not work:\n\n ${MISSINGBIOS}\n\nPlease make sure you copied the files into the corresponding folder." + error_process="$!" + pkill -P $error_process +fi +} + +# read config files from /storage/.config/profile.d + for config in /storage/.config/profile.d/*; do + if [ -f "$config" ] ; then + . $config + fi +done diff --git a/packages/jelos/profile.d/98-jslisten b/packages/jelos/profile.d/98-jslisten new file mode 100644 index 000000000..a2fbb74bb --- /dev/null +++ b/packages/jelos/profile.d/98-jslisten @@ -0,0 +1,81 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/os-release + +export PATH="$PATH:/usr/local/bin:/usr/bin:/storage/bin" + +jslisten() { + JSLISTENCONF="/storage/.config/distribution/configs/jslisten.cfg" + if [ "$1" == "set" ] + then + systemctl stop jslisten + + cat <${JSLISTENCONF} +[Generic] +program="/usr/bin/killall ${2}" +button1=${DEVICE_BTN_TL} +button2=${DEVICE_BTN_SELECT} +button3=${DEVICE_BTN_START} +evdev="auto" + +[BrightnessUp] +program="/usr/bin/brightness up" +button1=${DEVICE_BTN_TL} +button2=${DEVICE_BTN_DPAD_UP} +evdev="auto" + +[BrightnessDown] +program="/usr/bin/brightness down" +button1=${DEVICE_BTN_TL} +button2=${DEVICE_BTN_DPAD_DOWN} +evdev="auto" + +EOF + if [ "$2" == "mpv" ] + then + + cat <>${JSLISTENCONF} +[exit] +program="/usr/bin/manage_mpv.sh quit" +button1=${DEVICE_BTN_TL} +button2=${DEVICE_BTN_SELECT} +button3=${DEVICE_BTN_START} + +[Pause] +program="/usr/bin/manage_mpv.sh pause" +button1=${DEVICE_BTN_START} +evdev="auto" + +[Skip5s] +program="/usr/bin/manage_mpv.sh skip5s" +button1=${DEVICE_BTN_TR} +evdev="auto" + +[Back5s] +program="/usr/bin/manage_mpv.sh back5s" +button1=${DEVICE_BTN_TL} +evdev="auto" + +[Skip60s] +program="/usr/bin/manage_mpv.sh skip60s" +button1=${DEVICE_BTN_TR2} +evdev="auto" + +[Back60s] +program="/usr/bin/manage_mpv.sh back60s" +button1=${DEVICE_BTN_TL2} +evdev="auto" + +EOF + fi + systemctl start jslisten + elif [ "$1" == "stop" ] + then + systemctl stop jslisten + elif [ "$1" == "start" ] + then + systemctl start jslisten + fi +} diff --git a/packages/jelos/profile.d/99-freqfunctions b/packages/jelos/profile.d/99-freqfunctions new file mode 100644 index 000000000..599250b94 --- /dev/null +++ b/packages/jelos/profile.d/99-freqfunctions @@ -0,0 +1,25 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/os-release + +set_gov() { + for HANDLE in ${CPU_FREQ} ${GPU_FREQ} ${DMC_FREQ} + do + echo $1 >${HANDLE} 2>/dev/null || echo dmc_$1 >${HANDLE} 2>/dev/null + done +} + +maxperf() { + set_gov performance +} + +normperf() { + set_gov ondemand +} + +powersave() { + set_gov powersave +} + diff --git a/packages/jelos/sources/asound/rg351/asound.conf b/packages/jelos/sources/asound/rg351/asound.conf new file mode 100644 index 000000000..6078b59e1 --- /dev/null +++ b/packages/jelos/sources/asound/rg351/asound.conf @@ -0,0 +1,20 @@ +pcm.!default { + type plug + slave.pcm "dmixer" +} + +pcm.dmixer { + type dmix + ipc_key 1024 + slave { + pcm "hw:0,0" + period_time 0 + period_size 1024 + buffer_size 4096 + rate 44100 + } + bindings { + 0 0 + 1 1 + } +} diff --git a/packages/jelos/sources/asound/rg552/asound.conf b/packages/jelos/sources/asound/rg552/asound.conf new file mode 100644 index 000000000..493409a72 --- /dev/null +++ b/packages/jelos/sources/asound/rg552/asound.conf @@ -0,0 +1,24 @@ +pcm.!default { + type plug + slave.pcm "softvol" +} + +pcm.softvol { + type softvol + slave { + pcm "dmix" + } + control { + name "Master" + card 0 + } +} + +ctl.!default { + type hw + card 0 +} +ctl.softvol { + type hw + card 0 +} diff --git a/packages/jelos/sources/asound/rg552/asound.state b/packages/jelos/sources/asound/rg552/asound.state new file mode 100644 index 000000000..9dec26e1e --- /dev/null +++ b/packages/jelos/sources/asound/rg552/asound.state @@ -0,0 +1,472 @@ +state.es8316 { + control.1 { + iface MIXER + name 'HP Playback Volume' + value.0 0 + value.1 0 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 0' + dbmin -4800 + dbmax -4800 + dbvalue.0 -4800 + dbvalue.1 -4800 + } + } + control.2 { + iface MIXER + name 'HPMixer Gain' + value.0 0 + value.1 0 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 7' + dbmin -1200 + dbmax -150 + dbvalue.0 -1200 + dbvalue.1 -1200 + } + } + control.3 { + iface MIXER + name 'DAC Playback Volume' + value.0 192 + value.1 192 + comment { + access 'read write' + type INTEGER + count 2 + range '0 - 192' + dbmin -9999999 + dbmax 0 + dbvalue.0 0 + dbvalue.1 0 + } + } + control.4 { + iface MIXER + name 'Enable DAC Soft Ramp' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.5 { + iface MIXER + name 'DAC Soft Ramp Rate' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 4' + } + } + control.6 { + iface MIXER + name 'Playback Polarity' + value Normal + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Normal + item.1 'R Invert' + item.2 'L Invert' + item.3 'L + R Invert' + } + } + control.7 { + iface MIXER + name 'DAC Notch Filter' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.8 { + iface MIXER + name 'DAC Double Fs Mode' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.9 { + iface MIXER + name 'DAC Volume Control-LeR' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 1' + } + } + control.10 { + iface MIXER + name 'DAC Stereo Enhancement' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 7' + } + } + control.11 { + iface MIXER + name 'MIC Boost' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.12 { + iface MIXER + name 'Input PGA' + value 6 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 8' + } + } + control.13 { + iface MIXER + name 'ADC Capture Volume' + value 192 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 192' + dbmin -9999999 + dbmax 0 + dbvalue.0 0 + } + } + control.14 { + iface MIXER + name 'ADC Soft Ramp' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.15 { + iface MIXER + name 'Capture Polarity' + value Normal + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Normal + item.1 Invert + } + } + control.16 { + iface MIXER + name 'ADC Double FS Mode' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.17 { + iface MIXER + name 'ALC Capture Target Volume' + value 10 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 10' + } + } + control.18 { + iface MIXER + name 'ALC Capture Max PGA' + value 13 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 28' + } + } + control.19 { + iface MIXER + name 'ALC Capture Min PGA' + value 8 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 28' + } + } + control.20 { + iface MIXER + name 'ALC Capture Function' + value On + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 Off + item.1 On + } + } + control.21 { + iface MIXER + name 'ALC Capture Hold Time' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 10' + } + } + control.22 { + iface MIXER + name 'ALC Capture Decay Time' + value 0 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 10' + } + } + control.23 { + iface MIXER + name 'ALC Capture Attack Time' + value 5 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 10' + } + } + control.24 { + iface MIXER + name 'ALC Capture NG Threshold' + value 1 + comment { + access 'read write' + type INTEGER + count 1 + range '0 - 31' + } + } + control.25 { + iface MIXER + name 'ALC Capture NG Type' + value 'Mute ADC Output' + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 'Constant PGA Gain' + item.1 'Mute ADC Output' + } + } + control.26 { + iface MIXER + name 'ALC Capture NG Switch' + value true + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.27 { + iface MIXER + name 'Differential Mux' + value lin1-rin1 + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 lin1-rin1 + item.1 lin2-rin2 + item.2 'lin1-rin1 with 20db Boost' + item.3 'lin2-rin2 with 20db Boost' + } + } + control.28 { + iface MIXER + name 'Digital Mic Mux' + value 'dmic disable' + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 'dmic disable' + item.1 'dmic data at high level' + item.2 'dmic data at low level' + } + } + control.29 { + iface MIXER + name 'DAC SRC Mux' + value 'LDATA TO LDAC, RDATA TO RDAC' + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 'LDATA TO LDAC, RDATA TO RDAC' + item.1 'LDATA TO LDAC, LDATA TO RDAC' + item.2 'RDATA TO LDAC, RDATA TO RDAC' + item.3 'RDATA TO LDAC, LDATA TO RDAC' + } + } + control.30 { + iface MIXER + name 'Left Hp mux' + value lin1-rin1 + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 lin1-rin1 + item.1 lin2-rin2 + item.2 'lin-rin with Boost' + item.3 'lin-rin with Boost and PGA' + } + } + control.31 { + iface MIXER + name 'Right Hp mux' + value lin1-rin1 + comment { + access 'read write' + type ENUMERATED + count 1 + item.0 lin1-rin1 + item.1 lin2-rin2 + item.2 'lin-rin with Boost' + item.3 'lin-rin with Boost and PGA' + } + } + control.32 { + iface MIXER + name 'LLIN Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.33 { + iface MIXER + name 'Left DAC Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.34 { + iface MIXER + name 'RLIN Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.35 { + iface MIXER + name 'Right DAC Switch' + value false + comment { + access 'read write' + type BOOLEAN + count 1 + } + } + control.36 { + iface MIXER + name Master + value.0 255 + value.1 255 + comment { + access 'read write user' + type INTEGER + count 2 + range '0 - 255' + tlv '0000000100000008ffffec1400000014' + dbmin -5100 + dbmax 0 + dbvalue.0 0 + dbvalue.1 0 + } + } +} +state.HDMI { + control.1 { + iface PCM + name ELD + value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + comment { + access 'read volatile' + type BYTES + count 128 + } + } + control.2 { + iface PCM + name 'AUDIO MODE' + value 0 + comment { + access 'read write volatile' + type INTEGER + count 1 + range '0 - 2' + } + } + control.3 { + iface PCM + name 'Playback Channel Map' + value.0 0 + value.1 0 + value.2 0 + value.3 0 + value.4 0 + value.5 0 + value.6 0 + value.7 0 + comment { + access read + type INTEGER + count 8 + range '0 - 36' + } + } +} diff --git a/packages/jelos/sources/autostart/RG552/001-alsa b/packages/jelos/sources/autostart/RG552/001-alsa new file mode 100755 index 000000000..f56eabdb6 --- /dev/null +++ b/packages/jelos/sources/autostart/RG552/001-alsa @@ -0,0 +1,38 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile +. /etc/os-release + +# Copy in the configuration +if [ ! -e "/storage/.config/asound.conf" ] +then + cp /usr/config/asound.conf /storage/.config +fi + +# Link Alsa state +if [ ! -e "/storage/.config/asound.state" ] +then + cp /usr/config/asound.state /storage/.config/ +fi + +if [ ! -e "/storage/.config/asound.state" ] +then + mkdir -p /var/lib/alsa + ln -s /storage/.config/asound.state /var/lib/alsa/asound.state +fi + +alsactl --no-ucm init +alsactl --no-ucm restore -f /storage/.config/asound.state +aplay /usr/lib/autostart/sounds/silence.ogg + +VOL=$(get_setting "audio.volume" 2>/dev/null) +if [[ "${HW_DEVICE}" =~ RG552 ]] +then + MIXER="Master" + else + MIXER="Playback" +fi +alsactl --no-ucm store -f /storage/.config/asound.state +amixer set "${MIXER}" ${VOL}% diff --git a/packages/jelos/sources/autostart/autostart b/packages/jelos/sources/autostart/autostart new file mode 100755 index 000000000..8e4284f8f --- /dev/null +++ b/packages/jelos/sources/autostart/autostart @@ -0,0 +1,34 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2020 Fewtarius (https://github.com/fewtarius) + +. /etc/profile +. /etc/os-release + +BOOTLOG="/var/log/boot.log" +maxperf 2>&1 >${BOOTLOG} + +/usr/bin/show_splash intro 2>&1 >>${BOOTLOG} + +### Run common start scripts +for script in /usr/lib/autostart/common/* +do + echo "Executing ${script}" 2>&1 >>${BOOTLOG} + ${script} 2>&1 >>${BOOTLOG} +done + +### Run device specific start scripts +for script in /usr/lib/autostart/${HW_DEVICE}/* +do + echo "Executing ${script}" 2>&1 >>${BOOTLOG} + ${script} 2>&1 >>${BOOTLOG} +done + +normperf 2>&1 >>${BOOTLOG} + +clear >/dev/console + +### Lock is a prerequisite for emustation +rm /var/lock/start.games 2>&1 >>${BOOTLOG} +touch /var/lock/start.games 2>&1 >>${BOOTLOG} +systemctl start emustation 2>&1 >>${BOOTLOG} diff --git a/packages/jelos/sources/autostart/common/001-setup b/packages/jelos/sources/autostart/common/001-setup new file mode 100755 index 000000000..219dbcdfe --- /dev/null +++ b/packages/jelos/sources/autostart/common/001-setup @@ -0,0 +1,35 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +if [ -d "/storage/.config/distribution/configs" ] +then + EXCLUDE="--exclude=configs" +fi + +rsync -a /usr/config/.OS* /storage/.config +rsync -a --delete ${EXCLUDE} /usr/config/distribution/ /storage/.config/distribution/ +rsync -a --delete /usr/config/locale/ /storage/.config/emulationstation/locale/ + +cp -f /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt /storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt +cp -f /usr/config/ppsspp/PSP/SYSTEM/controls.ini /storage/.config/ppsspp/PSP/SYSTEM/controls.ini + +if [ ! -L "/storage/.emulationstation" ] +then + ln -sf /storage/.config/emulationstation /storage/.emulationstation +fi + +if [ -d "/storage/cache/.cores" ] +then + rm -rf /storage/cache/.cores +fi + +if [ ! -d "/tmp/cache" ] +then + mkdir /tmp/cache +fi + +ln -sf /tmp/cache /storage/cache/.cores + diff --git a/packages/jelos/sources/autostart/common/002-kernel b/packages/jelos/sources/autostart/common/002-kernel new file mode 100755 index 000000000..44129d934 --- /dev/null +++ b/packages/jelos/sources/autostart/common/002-kernel @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +sysctl vm.swappiness=1 diff --git a/packages/jelos/sources/autostart/common/003-logging b/packages/jelos/sources/autostart/common/003-logging new file mode 100755 index 000000000..c6e7748af --- /dev/null +++ b/packages/jelos/sources/autostart/common/003-logging @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +if [ ! -d "/var/log/retroarch" ] +then + mkdir /var/log/retroarch +fi + +if [ -d "/storage/.config/retroarch/logs" ] +then + rm -rf /storage/.config/retroarch/logs +fi + +ln -s /var/log/retroarch /storage/.config/retroarch/logs diff --git a/packages/jelos/sources/autostart/common/004-pico8 b/packages/jelos/sources/autostart/common/004-pico8 new file mode 100755 index 000000000..b7bfb73b6 --- /dev/null +++ b/packages/jelos/sources/autostart/common/004-pico8 @@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +PICO_DIR="/storage/roms/pico-8" +if [ ! -d "${PICO_DIR}" ] +then + mkdir "${PICO_DIR}" +fi +cp -f "/usr/bin/pico-8.sh" "${PICO_DIR}/Start Pico-8.sh" + diff --git a/packages/jelos/sources/autostart/common/005-brightness b/packages/jelos/sources/autostart/common/005-brightness new file mode 100755 index 000000000..6977a6465 --- /dev/null +++ b/packages/jelos/sources/autostart/common/005-brightness @@ -0,0 +1,21 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +### Variables may need to be device specific here. +BRIGHTNESS=$(get_setting system.brightness) +if [[ ! "${BRIGHTNESS}" =~ [0-9] ]] +then + BRIGHTNESS=${DEVICE_BRIGHTNESS} +fi + +# Ensure user doesn't get "locked out" with super low brightness +if [[ "${BRIGHTNESS}" -lt "3" ]] +then + BRIGHTNESS=3 +fi +BRIGHTNESS=$(printf "%.0f" ${BRIGHTNESS}) +printf "%.0f" $(echo "${BRIGHTNESS} * 2.56" | bc) > /sys/class/backlight/backlight/brightness +set_setting system.brightness ${BRIGHTNESS} diff --git a/packages/jelos/sources/autostart/common/006-rootpw b/packages/jelos/sources/autostart/common/006-rootpw new file mode 100755 index 000000000..ca2c072a3 --- /dev/null +++ b/packages/jelos/sources/autostart/common/006-rootpw @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +ROTATION=$(get_setting rotate.root.password) +if [ "${ROTATION}" == "0" ] +then + set_setting root.password "MANUALLY SET" + exit 0 +fi + +LPC=$(awk -F: '/^root/{print $3}' /storage/.cache/shadow) +CURRENT=$(awk -F: '/^root/{print $2}' /storage/.cache/shadow) + +# Randomly generate the root password on startup +ROOTPASS=$(openssl rand -base64 10 2>/dev/null | sed "s#==##g") + +# Turn it into a usable hash +NEW=$(cryptpw -m sha512 "${ROOTPASS}" 2>/dev/null) + +# Set the root password. +sed -i "s#root:${CURRENT}:${LPC}::::::#root:${NEW}:${LPC}::::::#g" /storage/.cache/shadow 2>/dev/null + +# Create a root user and set the password. +echo -ne "${ROOTPASS}\n${ROOTPASS}\n" | smbpasswd -sa root 2>/dev/null + +# Save the password so we can display it in ES +set_setting root.password "${ROOTPASS}" diff --git a/packages/jelos/sources/autostart/common/007-deviceutils b/packages/jelos/sources/autostart/common/007-deviceutils new file mode 100755 index 000000000..d31dc6423 --- /dev/null +++ b/packages/jelos/sources/autostart/common/007-deviceutils @@ -0,0 +1,33 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +if [ "${DEVICE_HAS_FAN}" == "true" ] +then + systemctl start fancontrol +else + systemctl stop fancontrol +fi + +if [ "${DEVICE_POWER_LED}" == "true" ] +then + systemctl start battery +else + systemctl stop battery +fi + +if [ "${DEVICE_FAKE_JACKSENSE}" == "true" ] +then + systemctl start headphones +else + systemctl stop headphones +fi + +if [ "${DEVICE_VOLUMECTL}" == "true" ] +then + systemctl start volume +else + systemctl stop volume +fi diff --git a/packages/jelos/sources/autostart/common/008-wifi b/packages/jelos/sources/autostart/common/008-wifi new file mode 100755 index 000000000..3d89d7115 --- /dev/null +++ b/packages/jelos/sources/autostart/common/008-wifi @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +if [ "$(get_setting wifi.enabled)" == "0" ] || [ "$1" == "disable" ] +then + connmanctl disable wifi +elif [ "$(get_setting wifi.enabled)" == "1" ] || [ "$1" == "enable" ] +then + connmanctl enable wifi +fi diff --git a/packages/jelos/sources/autostart/common/009-networkservices b/packages/jelos/sources/autostart/common/009-networkservices new file mode 100755 index 000000000..61f7fec29 --- /dev/null +++ b/packages/jelos/sources/autostart/common/009-networkservices @@ -0,0 +1,35 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +for service in /usr/lib/autostart/daemons +do + if [ ! -d "/storage/.cache/services" ] + then + mkdir -p "/storage/.cache/services" + fi + + if [ -e "/storage/.cache/services/${CONF}" ] + then + rm -f "/storage/.cache/services/${CONF}" + fi + + statemgr() { + for daemon in ${DAEMONS[@]} + do + systemctl ${1} ${daemon} + done + } + + case "$STATE" in + "1") + touch "/storage/.cache/services/${CONF}" + statemgr start + ;; + *) + statemgr stop + ;; + esac +done diff --git a/packages/jelos/sources/autostart/daemons/001-ssh b/packages/jelos/sources/autostart/daemons/001-ssh new file mode 100644 index 000000000..1967dc5df --- /dev/null +++ b/packages/jelos/sources/autostart/daemons/001-ssh @@ -0,0 +1,4 @@ +STATE=$(get_setting ssh.enabled) +SVC="sshd" +CONF="sshd.conf" +DAEMONS=("sshd") diff --git a/packages/jelos/sources/autostart/daemons/002-samba b/packages/jelos/sources/autostart/daemons/002-samba new file mode 100644 index 000000000..116e0caf9 --- /dev/null +++ b/packages/jelos/sources/autostart/daemons/002-samba @@ -0,0 +1,4 @@ +STATE=$(get_setting samba.enabled) +SVC="samba" +CONF="smb.conf" +DAEMONS=("nmbd" "smbd") diff --git a/packages/jelos/sources/autostart/sounds/silence.ogg b/packages/jelos/sources/autostart/sounds/silence.ogg new file mode 100644 index 000000000..e69de29bb diff --git a/packages/jelos/sources/issue b/packages/jelos/sources/issue new file mode 100644 index 000000000..34b4cc8e0 --- /dev/null +++ b/packages/jelos/sources/issue @@ -0,0 +1,8 @@ + + ╱╱╭┳â”â”â”┳╮╱╱╭â”â”â”┳â”â”â”â•® + ╱╱┃┃╭â”â”┫┃╱╱┃╭â”╮┃╭â”╮┃ + ╱╱┃┃╰â”â”┫┃╱╱┃┃╱┃┃╰â”â”â•® + ╭╮┃┃╭â”â”┫┃╱╭┫┃╱┃┣â”â”╮┃ + ┃╰╯┃╰â”â”┫╰â”╯┃╰â”╯┃╰â”╯┃ + â•°â”â”â”»â”â”â”â”»â”â”â”â”»â”â”â”â”»â”â”â”╯ + diff --git a/packages/jelos/sources/pico-8.sh b/packages/jelos/sources/pico-8.sh new file mode 100644 index 000000000..fcd29fb23 --- /dev/null +++ b/packages/jelos/sources/pico-8.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +# Source predefined functions and variables +. /etc/profile + +if [ ! -z "${1}" ] +then + OPTIONS="-run" + CART="${1}" +else + OPTIONS="-splore" +fi + +if [ ! -d "/storage/roms/pico-8" ] +then + mkdir -p "/storage/roms/pico-8" + echo "Extract your purchased pico-8 binaries and place them in the pico-8 directory on your games partition" >/tmp/logs/exec.log +fi + +cp -f /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt /storage/roms/pico-8/sdl_controllers.txt + +unset MYARCH +TEST=$(ldd /usr/bin/emulationstation | grep 64) +if [ $? == 0 ] +then + patchelf --set-interpreter /usr/lib32/ld-linux-armhf.so.3 /storage/roms/pico-8/pico8_dyn + export LD_LIBRARY_PATH=/usr/lib32 +fi + +/storage/roms/pico-8/pico8_dyn -home -root_path /storage/roms/pico-8 -joystick 0 ${OPTIONS} "${CART}" + +ret_error=$? + +exit $ret_error diff --git a/packages/jelos/sources/scripts/backuptool b/packages/jelos/sources/scripts/backuptool new file mode 100755 index 000000000..55427a0d4 --- /dev/null +++ b/packages/jelos/sources/scripts/backuptool @@ -0,0 +1,30 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020 Fewtarius (https://github.com/fewtarius) + +BACKUPFILE="/storage/roms/backup/BACKUP.zip" +mkdir -p "/storage/roms/backup" + +case "${1}" in + "restore") + systemctl stop emustation + unzip -o ${BACKUPFILE} -d / + systemctl start emustation + ;; + "backup") + [ -f "${BACKUPFILE}" ] && rm "${BACKUPFILE}" + [ -z "$2" ] && systemctl stop emustation + zip -9 -r ${BACKUPFILE} \ + /storage/.cache/bluetooth/* \ + /storage/.cache/connman* \ + /storage/.config/distribution/configs/distribution.conf \ + /storage/.emulationstation/es_*.cfg \ + /tmp/joypads/* \ + /storage/.config/ppsspp/* \ + /storage/.config/retroarch/* \ + /storage/.emulationstation/scripts/* + [ -z "${2}" ] && systemctl start emustation + ;; +esac diff --git a/packages/jelos/sources/scripts/batocera-bluetooth b/packages/jelos/sources/scripts/batocera-bluetooth new file mode 100755 index 000000000..d5b7dce7e --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-bluetooth @@ -0,0 +1,110 @@ +#!/bin/bash + +ACTION=$1 +shift + +do_help() { + echo "${1} list" >&2 + echo "${1} trust" >&2 + echo "${1} remove " >&2 +} + +do_list() { + find /storage/.cache/bluetooth -type f -name info | + while read FILE + do + if grep -qE '^Trusted=true$' "${FILE}" + then + DEVNAME=$(grep -E '^Name=' "${FILE}" | sed -e s+"^Name="++) + DEVADDR=$(basename $(dirname "${FILE}")) + echo "${DEVADDR} ${DEVNAME}" + fi + done +} + +do_remove() { + DEV="${1}" + + # output is never nice + if ! (echo "untrust ${DEV}" ; echo "remove ${DEV}") | bluetoothctl >/dev/null 2>/dev/null + then + return 1 + fi + + return 0 +} + +do_trust() { + NPID=$(pgrep -f batocera-bluetooth-agent) + test -z "${NPID}" && return 0 + + touch "/var/run/bt_status" || retrun 1 + LAST_MSG=$(cat "/var/run/bt_status") + + # start discovering + kill -10 "${NPID}" + + trap "kill -12 ${NPID}" 2 3 + + N=30 + while test $N -gt 0 + do + NEW_MSG=$(cat "/var/run/bt_status") + if test "${LAST_MSG}" != "${NEW_MSG}" + then + LAST_MSG="${NEW_MSG}" + echo "${NEW_MSG}" + fi + sleep 1 + let N-- + done + + # stop discovering + kill -12 "${NPID}" + +} + +do_starttrust() { + NPID=$(pgrep -f batocera-bluetooth-agent) + test -z "${NPID}" && exit 0 + + # start discovering + kill -10 "${NPID}" +} + +do_stoptrust() { + NPID=$(pgrep -f batocera-bluetooth-agent) + test -z "${NPID}" && exit 0 + + # stop discovering + kill -12 "${NPID}" +} + +case "${ACTION}" in + "list") + do_list + ;; + "trust") + do_trust + ;; + "starttrust") + do_starttrust + ;; + "stoptrust") + do_stoptrust + ;; + "remove") + if test $# = 1 + then + do_remove "${1}" || exit 1 + else + do_help "${0}" + exit 1 + fi + ;; + *) + do_help "${0}" + exit 1 +esac + +exit 0 diff --git a/packages/jelos/sources/scripts/batocera-bluetooth-agent b/packages/jelos/sources/scripts/batocera-bluetooth-agent new file mode 100755 index 000000000..20eef4f33 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-bluetooth-agent @@ -0,0 +1,461 @@ +#!/usr/bin/python + +from __future__ import absolute_import, print_function + +from optparse import OptionParser, make_option +import dbus +import dbus.service +import dbus.mainloop.glib +import bluezutils +import time +import os +import logging +import signal +from gi.repository import GLib + +AGENT_INTERFACE = 'org.bluez.Agent1' + +gadapter = None +gdiscovering = False +gdevices = {} +g_devices_seen = {} + +logging.basicConfig(filename='/var/log/bluetooth-agent.log', level=logging.DEBUG, format='%(asctime)s %(message)s') + +def bool2str(val, valiftrue, valiffalse): + if val: + return valiftrue + else: + return valiffalse + +def logging_status(msg): + with open("/var/run/bt_status", "w") as file: + file.write(msg + "\n") + +def connect_device(path, address, properties, forceConnect, typeInput, typeAudio): + global gdiscovering + + devName = "" + trusted = False + connected = False + + # avoid devices without interesting information + if "Trusted" not in properties: + return + if "Connected" not in properties: + return + + rproperties = {} + # Get the adapter name and bt mac + for key, value in properties.items(): + if type(value) is dbus.String: + value = value.encode('ascii', 'replace') + rproperties[key] = value + + trusted = rproperties["Trusted"] + paired = rproperties["Paired"] + devName = getDevName(rproperties) + shortDevName = getShortDevName(rproperties) + connected = rproperties["Connected"] + + # skip non input devices + if "Icon" not in properties: + logging.info("Skipping device {} (no type)".format(getDevName(rproperties))); + return + + if not ( (typeInput and properties["Icon"].startswith("input")) or (typeAudio and properties["Icon"].startswith("audio-card")) ): + logging.info("Skipping device {} because of type {}".format(getDevName(rproperties), properties["Icon"])); + return + + blacklistAddr, blacklistName = getBlacklistAddrAndName(properties) + + # add device to the seen list + if blacklistAddr not in g_devices_seen: + g_devices_seen[blacklistAddr] = { "name": blacklistName } + updateKnownDevicesList(g_devices_seen) + + # skip blacklisted devices + if blacklistAddr is not None and isDeviceBlacklisted(blacklistAddr): + logging.info("Skipping blacklisted device {}".format(blacklistName)) + return + + logging.info("event for " + devName + "(paired=" + bool2str(paired, "paired", "not paired") + ", trusted=" + bool2str(trusted, "trusted", "untrusted") + ", connected=" + bool2str(connected, "connected", "disconnected") + ")") + + # skipping connected devices + if paired and trusted and connected: + logging.info("Skipping already connected device {}".format(getDevName(rproperties))); + return + + if not paired: + if connected == False and gdiscovering: + doParing(address, devName, shortDevName) + return + + # now it is paired + if not trusted and (gdiscovering or forceConnect): + logging.info("Trusting (" + devName + ")") + logging_status("Trusting " + shortDevName + "...") + bluezProps = dbus.Interface(bus.get_object("org.bluez", path), "org.freedesktop.DBus.Properties") + bluezProps.Set("org.bluez.Device1", "Trusted", True) + + # now it is paired and trusted + # Connect if Trusted and paired + if not connected or forceConnect: + doConnect(address, devName, shortDevName) + +def doParing(address, devName, shortDevName): + logging.info("Pairing... (" + devName + ")") + logging_status("Pairing " + shortDevName + "...") + device = bluezutils.find_device(address) + try: + device.Pair() + except Exception as e: + logging.info("Pairing failed (" + devName + ")") + logging_status("Pairing failed (" + shortDevName + ")") + +def doConnect(address, devName, shortDevName): + global gadapter + global gdiscovering + + try: + # discovery stopped during connection to help some devices + if gdiscovering: + logging.info("Stop discovery") + gadapter.StopDiscovery() + + device = bluezutils.find_device(address) + ntry=5 + while ntry > 0: + ntry = ntry -1 + try: + logging.info("Connecting... (" + devName + ")") + logging_status("Connecting " + shortDevName + "...") + device.Connect() + logging.info("Connected successfully (" + devName + ")") + logging_status("Connected successfully (" + shortDevName + ")") + + if gdiscovering: + logging.info("Start discovery") + gadapter.StartDiscovery() + return + except dbus.exceptions.DBusException as err: + logging.info("dbus: " + err.get_dbus_message()) + time.sleep(1) + except Exception as err: + logging.info("Connection failed (" + devName + ")") + time.sleep(1) + + logging.info("Connection failed. Give up. (" + devName + ")") + logging_status("Connection failed. Give up. (" + shortDevName + ")") + if gdiscovering: + logging.info("Start discovery") + gadapter.StartDiscovery() + except Exception as e: + if gdiscovering: + logging.info("Start discovery") + gadapter.StartDiscovery() + # don't raise, while startdiscovery doesn't like it + #raise e + +def getDevName(properties): + #devName = properties["Name"] + " (" + properties["Address"] + ", " + properties["Icon"] + ")" + #devStatus = "Trusted=" + str(properties["Trusted"]) + ", paired=" + str(properties["Paired"]) + ", connected=" + str(properties["Connected"]), ", blocked=" + str(properties["Blocked"]) + #devTech = "legacyPairing: " + str(properties["LegacyPairing"]) # + ", RSSI: " + properties["RSSI"] + + if "Name" in properties and "Address" in properties and "Icon" in properties: + return str(properties["Name"]) + " (" + str(properties["Address"]) + ", " + str(properties["Icon"]) + ")" + + if "Name" in properties and "Address" in properties: + return str(properties["Name"]) + " (" + str(properties["Address"]) + ")" + + if "Name" in properties and "Icon" in properties: + return str(properties["Name"]) + " (" + str(properties["Icon"]) + ")" + + if "Name" in properties: + return str(properties["Name"]) + + if "Address" in properties and "Icon" in properties: + return str(properties["Address"]) + " (" + str(properties["Icon"]) + ")" + + if "Address" in properties: + return str(properties["Address"]) + + if "Icon" in properties: + return str(properties["Icon"]) + + return "unknown" + +def updateKnownDevicesList(g_devices_seen): + f = open("/var/run/bluetooth_seen", "w") + for key in g_devices_seen: + f.write("{} {}\n".format(key, g_devices_seen[key]["name"])) + f.close() + +def isDeviceBlacklisted(blacklistAddr): + datafile = "/var/lib/bluetooth/bluetooth_blacklisted" + + # reread the file each time in case somebody changed it + if not os.path.isfile(datafile): + return False + + with open(datafile) as file: + lines = file.readlines() + for line in lines: + if line[0:len(blacklistAddr)] == blacklistAddr: + return True + + return False + +def getBlacklistAddrAndName(properties): + if "Address" not in properties: + return None + address = str(properties["Address"]) + name = "" + + if "Name" in properties: + name = str(properties["Name"]) + elif "Icon" in properties: + name = str(properties["Icon"]) + else: + name = "unknown" + + return address, name + +def getShortDevName(properties): + if "Name" in properties: + return str(properties["Name"]) + + if "Address" in properties: + return str(properties["Address"]) + + if "Icon" in properties: + return str(properties["Icon"]) + + return "unknown" + +def getBluetoothWantedTypes(): + if not os.path.isfile("/var/run/bt_types"): + logging.info("no bt_types file") + return True, True + + btype = "" + with open("/var/run/bt_types", "r") as file: + btype = file.read().strip() + logging.info("bt_type: {}".format(btype)) + + if btype == "": + return True, True + if btype == "pad": + return True, False + if btype == "audio": + return False, True + return False, False + +def interfaces_added(path, interfaces): + global gdevices + + if "org.bluez.Device1" not in interfaces: + return + if not interfaces["org.bluez.Device1"]: + return + + properties = interfaces["org.bluez.Device1"] + + if path in gdevices: + gdevices[path] = merge2dicts(gdevices[path], properties) + else: + gdevices[path] = properties + + if "Address" in gdevices[path]: + typeInput, typeAudio = getBluetoothWantedTypes() + connect_device(path, properties["Address"], gdevices[path], False, typeInput, typeAudio) + +def properties_changed(interface, changed, invalidated, path): + global gdevices + + if interface != "org.bluez.Device1": + return + + if path in gdevices: + gdevices[path] = merge2dicts(gdevices[path], changed) + else: + gdevices[path] = changed + + #logging.info("Properties changed:") + #logging.info(changed) + #logging.info(invalidated) + + if "Paired" in changed and changed["Paired"] == True: + # ok, do as in simple-agent, trust and connect + typeInput, typeAudio = getBluetoothWantedTypes() + connect_device(path, gdevices[path]["Address"], gdevices[path], True, typeInput, typeAudio) + return + + # ok, it is now connected, what else ? + if "Connected" in changed and changed["Connected"] == True: + return + + if "Connected" in changed and changed["Connected"] == False: + logging.info("Skipping (property Connected changed to False)"); + return + + if "Address" in gdevices[path]: + typeInput, typeAudio = getBluetoothWantedTypes() + connect_device(path, gdevices[path]["Address"], gdevices[path], False, typeInput, typeAudio) + +def merge2dicts(d1, d2): + res = d1.copy() + res.update(d2) + return res + +def user_signal_start_discovery(signum, frame): + global gdiscovering + global gadapter + + try: + if gdiscovering == False: + gdiscovering = True + logging.info("Start discovery (signal)") + gadapter.StartDiscovery() + except: + pass + +def user_signal_stop_discovery(signum, frame): + global gdiscovering + global gadapter + + try: + if gdiscovering: + gdiscovering = False + logging.info("Stop discovery (signal)") + gadapter.StopDiscovery() + except: + pass + +class Agent(dbus.service.Object): + exit_on_release = True + + def set_exit_on_release(self, exit_on_release): + self.exit_on_release = exit_on_release + + @dbus.service.method(AGENT_INTERFACE, in_signature="", out_signature="") + def Release(self): + logging.info("agent: Release") + if self.exit_on_release: + mainloop.quit() + + @dbus.service.method(AGENT_INTERFACE, in_signature="os", out_signature="") + def AuthorizeService(self, device, uuid): + logging.info("agent: AuthorizeService") + return + + @dbus.service.method(AGENT_INTERFACE, in_signature="o", out_signature="s") + def RequestPinCode(self, device): + logging.info("RequestPinCode (%s)" % (device)) + return "0000" + + @dbus.service.method(AGENT_INTERFACE, in_signature="o", out_signature="u") + def RequestPasskey(self, device): + logging.info("RequestPasskey (%s)" % (device)) + return 0 + + @dbus.service.method(AGENT_INTERFACE, in_signature="ouq", out_signature="") + def DisplayPasskey(self, device, passkey, entered): + logging.info("agent: DisplayPasskey (%s, %06u entered %u)" % (device, passkey, entered)) + + @dbus.service.method(AGENT_INTERFACE, in_signature="os", out_signature="") + def DisplayPinCode(self, device, pincode): + logging.info("agent: DisplayPinCode (%s, %s)" % (device, pincode)) + + @dbus.service.method(AGENT_INTERFACE, in_signature="ou", out_signature="") + def RequestConfirmation(self, device, passkey): + logging.info("agent: RequestConfirmation") + return + + @dbus.service.method(AGENT_INTERFACE, in_signature="o", out_signature="") + def RequestAuthorization(self, device): + logging.info("agent: RequestAuthorization") + return + + @dbus.service.method(AGENT_INTERFACE, in_signature="", out_signature="") + def Cancel(self): + logging.info("agent: Cancel") + +def do_main_loop(dev_id): + global gadapter + + # adapter + try: + adapter = bluezutils.find_adapter(dev_id) + except: + # try to find any adapter + adapter = bluezutils.find_adapter(None) + logging.info("adapter found") + + gadapter = adapter + adapters = {} + + om = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager") + objects = om.GetManagedObjects() + for path, interfaces in objects.items(): + if "org.bluez.Device1" in interfaces: + gdevices[path] = interfaces["org.bluez.Device1"] + if "org.bluez.Adapter1" in interfaces: + adapters[path] = interfaces["org.bluez.Adapter1"] + + adapter_props = adapters[adapter.object_path] + logging.info(adapter_props["Name"] + "(" + adapter_props["Address"] + "), powered=" + str(adapter_props["Powered"])) + + # power on adapter if needed + if adapter_props["Powered"] == 0: + try: + logging.info("powering on adapter ("+ adapter_props["Address"] +")") + adapterSetter = dbus.Interface(bus.get_object("org.bluez", adapter.object_path), "org.freedesktop.DBus.Properties") + adapterSetter.Set("org.bluez.Adapter1", "Powered", True) + except: + pass # hum, not nice + + gdiscovering = False + + # events + # use events while i manage to stop discovery only from the process having started it + signal.signal(signal.SIGUSR1, user_signal_start_discovery) + signal.signal(signal.SIGUSR2, user_signal_stop_discovery) + + mainloop = GLib.MainLoop() + mainloop.run() + +if __name__ == '__main__': + # options + option_list = [ make_option("-i", "--device", action="store", type="string", dest="dev_id") ] + parser = OptionParser(option_list=option_list) + (options, args) = parser.parse_args() + + # initialize the seen devices file + updateKnownDevicesList(g_devices_seen) + + # register dbus + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + bus = dbus.SystemBus() + + bus.add_signal_receiver(interfaces_added, dbus_interface = "org.freedesktop.DBus.ObjectManager", signal_name = "InterfacesAdded") + bus.add_signal_receiver(properties_changed, dbus_interface = "org.freedesktop.DBus.Properties", signal_name = "PropertiesChanged", arg0 = "org.bluez.Device1", path_keyword = "path") + + # register the agent + agentpath = "/storage/.cache/agent" + obj = bus.get_object("org.bluez", "/org/bluez") + manager = dbus.Interface(obj, "org.bluez.AgentManager1") + manager.RegisterAgent(agentpath, "NoInputNoOutput") + manager.RequestDefaultAgent(agentpath) + agent = Agent(bus, agentpath) + logging.info("agent registered") + + # run the agent, allows some tries while hardware can take time to initiate + time.sleep(5) + try: + do_main_loop(options.dev_id) + except Exception as e: + logging.error("agent fails") + logging.error(e, exc_info=True) + raise + logging.error("agent gave up") diff --git a/packages/jelos/sources/scripts/batocera-brightness b/packages/jelos/sources/scripts/batocera-brightness new file mode 100755 index 000000000..e6cf0f20b --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-brightness @@ -0,0 +1,52 @@ +#!/bin/bash + +if test ! -e /sys/class/backlight/backlight/brightness +then + echo "no brightness found" >&2 + exit 1 +fi + +setValue() { + NEWVAL=$1 + XMAX=$2 + + test "${NEWVAL}" -lt 0 && NEWVAL=0 + test "${NEWVAL}" -gt "${XMAX}" && NEWVAL="${XMAX}" + + echo "${NEWVAL}" > /sys/class/backlight/backlight/brightness +} + +# get +if test $# = 0 +then + X=$(cat /sys/class/backlight/backlight/brightness) + XMAX=$(cat /sys/class/backlight/backlight/max_brightness) + echo $(expr "${X}" "*" "100" / "${XMAX}") + exit 0 +fi + +# set +if test $# = 1 +then + XMAX=$(cat /sys/class/backlight/backlight/max_brightness) + NEWVAL=$(expr "${1}" "*" "${XMAX}" / 100) + setValue "${NEWVAL}" "${XMAX}" + exit 0 +fi + +# set + +if test $# = 2 +then + X=$(cat /sys/class/backlight/backlight/brightness) + XMAX=$(cat /sys/class/backlight/backlight/max_brightness) + DELTA=$(expr "${2}" '*' ${XMAX} / 100) + NEWVAL=$(expr "${X}" "${1}" "${DELTA}") + setValue "${NEWVAL}" "${XMAX}" + exit 0 +fi + +# help +echo "${0}" >&2 +echo "${0} + 10" >&2 +echo "${0} - 20" >&2 +exit 1 diff --git a/packages/jelos/sources/scripts/batocera-config b/packages/jelos/sources/scripts/batocera-config new file mode 100755 index 000000000..ff9ace948 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-config @@ -0,0 +1,358 @@ +#!/bin/bash + +. /etc/profile +. /etc/os-release + +if [ ! "$1" ];then + echo -e "usage : batocera-config [command] [args]\nWith command in\n\toverscan [enable|disable]\n\tlsaudio\n\tgetaudio\n\taudio [hdmi|jack|auto|custom|x,y]\n\tcanupdate\n\tupdate\n\twifi [enable|disable] ssid key\n\tstorage [current|list|INTERNAL|ANYEXTERNAL|RAM|DEV UUID]\n\tsetRootPassword [password]\n\tgetRootPassword\n\ttz [|tz]" + exit 1 +fi +configFile="/storage/.config/distribution/configs/config.txt" +storageFile="/storage/.config/distribution/configs/batocera-boot.conf" +command="$1" +mode="$2" +extra1="$3" +extra2="$4" +extra3="$5" +extra4="$6" +arch=${HW_DEVICE} + +updateurl="https://127.0.0.1" + +preBootConfig() { + mount -o remount,rw /boot +} + +postBootConfig() { + mount -o remount,ro /boot +} + +bato_config_set_value () { + key=$1 + value=$2 + [ -z "$value" ] && value=0 + cat "$configFile" | grep "$key" + valPresent=$? + if [ "$valPresent" != "0" ];then + echo "$key=$value" >> "$configFile" + else + sed -i "s/#\?$key=.*/$key=$value/g" "$configFile" + fi +} + +#log=/userdata/system/logs/batocera.log +#systemsetting="python /usr/lib/python2.7/site-packages/configgen/settings/batoceraSettings.py" + +log=/var/log/systemsettings.log +systemsetting="/usr/bin/batocera-settings" + + +echo "----config ----" >> $log + +if [ "$command" == "getRootPassword" ]; then + # security disabled, force the default one without changing boot configuration + securityenabled="`$systemsetting -command load -key system.security.enabled`" + if [ "$securityenabled" != "1" ];then + echo "linux" + exit 0 + fi + + ENCPASSWD=$(grep -E '^[ \t]*rootshadowpassword[ \t]*=' "${storageFile}" | sed -e s+'^[ \t]*rootshadowpassword[ \t]*='++) + if test -z "${ENCPASSWD}" + then + exit 1 + fi + if ! batocera-encode decode "${ENCPASSWD}" + then + exit 1 + fi + exit 0 +fi + +if [ "$command" == "setRootPassword" ]; then + PASSWD=${2} + + # security disabled, don't change + securityenabled="`$systemsetting -command load -key system.security.enabled`" + if [ "$securityenabled" != "1" ];then + exit 0 + fi + + # if no password if provided, generate one + if test -z "${PASSWD}" + then + PASSWD=$(tr -cd _A-Z-a-z-0-9 < /dev/urandom | fold -w8 | head -n1) + fi + PASSWDENC=$(batocera-encode encode "${PASSWD}") + + preBootConfig + if grep -qE '^[ \t]*rootshadowpassword[ \t]*=' "${storageFile}" + then + # update it + if ! sed -i -e s@'^[ \t]*rootshadowpassword[ \t]*=.*$'@"rootshadowpassword=${PASSWDENC}"@ "${storageFile}" + then + postBootConfig + exit 1 + fi + postBootConfig + exit 0 + else + # create it + if ! echo "rootshadowpassword=${PASSWDENC}" >> "${storageFile}" + then + postBootConfig + exit 1 + fi + postBootConfig + exit 0 + fi +fi + +if [ "$command" == "overscan" ]; then +if [ "$mode" == "set" ];then +# set will set overscan values abd also enable this mode + if [ -z "$extra1" ] || [ -z "$extra2" ] || [ -z "$extra3" ] || [ -z "$extra4" ]; then + echo "$0 $command $mode needs 4 arguments:" + echo "$0 $command $mode overscan_left overscan_right overscan_top overscan_bottom" + exit 2 + fi + preBootConfig + [ -f "$configFile" ] || touch "$configFile" + + echo "setting overscan values $extra1 $extra2 $extra3 $extra4 " >> $log + bato_config_set_value disable_overscan 0 + bato_config_set_value overscan_scale 1 + bato_config_set_value overscan_left "$extra1" + bato_config_set_value overscan_right "$extra2" + bato_config_set_value overscan_top "$extra3" + bato_config_set_value overscan_bottom "$extra4" + + postBootConfig + exit 0 + +fi +if [ -f "$configFile" ];then + preBootConfig + if [ "$mode" == "enable" ];then + echo "enabling overscan" >> $log + bato_config_set_value disable_overscan 0 + bato_config_set_value overscan_scale 1 + elif [ "$mode" == "disable" ];then + echo "disabling overscan" >> $log + bato_config_set_value disable_overscan 1 + bato_config_set_value overscan_scale 0 + else + postBootConfig + exit 1 + fi + postBootConfig + exit 0 +else + exit 2 +fi +fi + +if [ "$command" == "lsoutputs" ] +then + echo "auto" + batocera-resolution listOutputs +fi + +if [ "$command" == "lsaudio" ];then + if [[ "${arch}" =~ "rpi" ]] + then + echo "hdmi" + echo "jack" + echo "auto" + elif [[ "${arch}" =~ "x86" ]];then + echo "auto" + echo "custom" + LANG=C aplay -l | grep -E '^card [0-9]*:' | sed -e s+'^card \([0-9]*\): \([^,]*\), device \([0-9]*\): [^\[]* \[\([^]]*\)].*$'+'\1,\3 \4 \2'+ + else + echo "auto" + fi +fi + +if [ "$command" == "getaudio" ];then + $systemsetting -command load -key audio.device + exit 0 +fi + +if [ "$command" == "audio" ];then + # this code is specific to the rpi + # don't set it on other boards + # find a more generic way would be nice + if [[ "${arch}" =~ "rpi" ]] + then + # this is specific to the rpi + cmdVal="0" + if [ "$mode" == "hdmi" ];then + cmdVal="2" + elif [ "$mode" == "jack" ];then + cmdVal="1" + fi + echo "setting audio output mode : $mode" >> $log + amixer cset numid=3 $cmdVal || exit 1 + elif [[ "${arch}" =~ "x86" ]] + then + # auto: no .asoundrc file + # custom: don't touch the .asoundrc file + # any other, create the .asoundrd file + if [ "$mode" == "auto" ];then + rm -rf /userdata/system/.asoundrc || exit 1 + elif [ "$mode" != "custom" ];then + if echo "${mode}" | grep -qE '^[0-9]*,[0-9]* ' + then + cardnb=$(echo "${mode}" | sed -e s+'^\([0-9]*\),.*$'+'\1'+) + devicenb=$(echo "${mode}" | sed -e s+'^[0-9]*,\([0-9]*\) .*$'+'\1'+) + cat > /userdata/system/.asoundrc <> $log + + # on my pc, the master is turned off at boot + # i don't know what are the rules to set here. + amixer set ${DEVICE_AUDIO_MIXER} unmute || exit 1 + amixer set ${DEVICE_AUDIO_MIXER} -- ${mode}% || exit 1 + + # maximize the sound to be sure it's not 0, allow errors + amixer set PCM -- 100% #|| exit 1 + amixer set Headphone -- 100% #|| exit 1 + exit 0 + fi + exit 12 +fi + +if [ "$command" == "gpiocontrollers" ];then + command="module" + mode="load" + extra1="mk_arcade_joystick_rpi" + extra2="map=1,2" +fi + +if [ "$command" == "module" ];then + modulename="$extra1" + map="$extra2" + # remove in all cases + rmmod /lib/modules/`uname -r`/extra/${modulename}.ko >> $log + + if [ "$mode" == "load" ];then + echo "loading module $modulename args = $map" >> $log + insmod /lib/modules/`uname -r`/extra/${modulename}.ko $map >> $log + [ "$?" ] || exit 1 + fi + exit 0 +fi + +if [ "$command" == "canupdate" ];then + available=$(updatecheck canupdate) + echo "$available" + if [[ "$available" != "no" ]]; then + exit 0 + fi + exit 12 +fi + +if [ "$command" == "update" ];then + 351elec-upgrade + exit $? +fi + +if [[ "$command" == "wifi" ]]; then + ssid="$3" + psk="$4" + ### Reminder: Rewrite this stuff. + if [[ "$mode" == "enable" ]]; then + /usr/lib/autostart/${HW_DEVICE}/002-wifi enable + echo "configure wifi" >> $log + mkdir -p "/storage/.cache/connman" || exit 1 + cat > "/storage/.cache/connman/wifi.config" <> "/storage/.cache/connman/wifi.config" + fi + connmanctl enable wifi || exit 1 + connmanctl scan wifi || exit 1 + exit 0 + fi + if [[ "$mode" =~ "start" ]]; then + if [[ "$mode" != "forcestart" ]]; then + settingsWlan="`$systemsetting -command load -key wifi.enabled`" + if [ "$settingsWlan" != "1" ];then + exit 1 + fi + fi + connmanctl enable wifi || exit 1 + connmanctl scan wifi || exit 1 + exit 0 + fi + if [[ "$mode" == "disable" ]]; then + connmanctl disable wifi + /usr/lib/autostart/${HW_DEVICE}/002-wifi disable + exit $? + fi + if [[ "$mode" == "list" ]]; then + WAVAILABLE=$(connmanctl services | cut -b 5- | sed -e s+'^\([^ ]*\).*$'+'\1'+ | grep -vE '^Wired$|^$') + if test -n "${ssid}" + then + echo "${WAVAILABLE}" | grep -qE '^'"${ssid}"'$' || echo "${ssid}" + fi + echo "${WAVAILABLE}" + exit 0 + fi +fi + +if [[ "$command" == "storage" ]]; then + exit 0; +fi + +if [[ "$command" == "forgetBT" ]]; then + killall -9 hcitool + systemctl stop bluetooth + rm -rf /storage/.cache/bluetooth/* + systemctl start bluetooth + exit 0 +fi + +if [ "$command" == "tz" ];then + if test "$mode" == "" + then + cat /storage/.config/distribution/configs/tz + else + if test -f "/usr/share/zoneinfo/${mode}" + then + echo "TIMEZONE=${mode}" > /storage/.cache/timezone + systemctl restart tz-data.service + fi + fi + exit $? +fi + +exit 10 diff --git a/packages/jelos/sources/scripts/batocera-es-thebezelproject b/packages/jelos/sources/scripts/batocera-es-thebezelproject new file mode 100755 index 000000000..8e9d15713 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-es-thebezelproject @@ -0,0 +1,339 @@ +#! /bin/bash +# +# Download and install The Bezel Project for Batocera +# +# @evoflash and @lbrpdx on Batocera Forums and Discord +# +# Usage: +# batocera-es-thebezelproject 'list', 'install or remove ' +# +# + +DECODIR="/storage/roms/" +ROMSDIR="/storage/roms/" +DEFAULTBEZELDIR="default/systems/" +BEZELPROJECTDIR="bezels/" +BEZELPROJECTGAMESDIR="${BEZELPROJECTDIR}" +BEZELPROJECTSYSTEMDIR="${BEZELPROJECTDIR}" +BEZELSLIST="https://pastebin.com/raw/C4wdxTMv" +LOCALBEZELSLIST="/storage/.config/distribution/configs/bezels.txt" +# bezels.txt must be a plain file with the format 'bezel_name https://githubURL' (spaces or tabs) +# Example of a bezels.txt file: +# fba https://github.com/thebezelproject/bezelproject-MAME +# snes https://github.com/thebezelproject/bezelproject-SNES +DEBUG=0 +EE_TMP="/tmp/overlays" + +############################### +# +function usage() { + echo "$(basename $0) - downloads and installs The Bezel Project for Batocera" + echo " " + echo "It accepts three modes: 'list', 'install' and 'remove' '" + echo "- 'list' for the list of systems installed on the system, and available within TheBezelProject, and if they are" + echo " [A]vailable to install, [I]nstalled or [?]unknown." + echo "- 'install ' to install the bezels for this ." + echo "- 'remove ' to remove the bezels for this ." + echo "- 'remove all' to remove all the bezels." + echo " " + echo "If you have a local $LOCALBEZELSLIST file," + echo "it will override the one hosted on Batocera website." + return 1 +} + +############################### +# check if url format is valid +function check_url() { + [[ "$1" =~ ^(https?|ftp)://.*$ ]] && echo "[A]" || echo "[?]" +} + +############################### +# return the git name +function git_name() { + echo "$1" | sed "s,.*/\(.*\),\1," +} + +############################### +# return the number of files in a directory +function files_count() { + echo `find "$1" -maxdepth 1 -type f -name "[!.]*" | wc -l` +} + +############################### +# +function list() { + local count=0 + local fn=$(date +"%s") + local tmp="$EE_TMP/bezels_$fn" + local filescount + local systemname + local url + + [ $DEBUG -eq 1 ] && echo "DEBUG: path to bezels ${DECODIR}${BEZELPROJECTGAMESDIR}" + echo "* 351ELEC bezels *" + + # create temporary files in /tmp + if [ -f $LOCALBEZELSLIST ]; then + cp -f "$LOCALBEZELSLIST" "${tmp}" + else + curl -H 'Cache-Control: no-cache' -sfL "$BEZELSLIST" -o "${tmp}" || return 1 + sed -i 's/\r$//' "${tmp}" + fi + + # reading bezels list from configuration file + while IFS=$' \t' read systemname url ; do + [ -z "${systemname}" ] && continue + let count+=1 + [ $DEBUG -eq 1 ] && echo "DEBUG: bezels for system ${systemname} (from bezels list)" + # check if roms/ directory exist + if [ ! -d "${ROMSDIR}${systemname}" ]; then continue; fi + # there is at least one file in each roms/ directory (i.e. _info.txt) + filescount=$(files_count "${ROMSDIR}${systemname}") + if [ "${filescount}" -le 1 ]; then continue; fi + # check if url is valid and return [A] else [?] + ia=$(check_url "${url}") + # if games/ directory exist we assume the bezels are already installed + if [ -d "${DECODIR}${BEZELPROJECTGAMESDIR}${systemname}" ]; then ia="[I]"; fi + echo "$ia ${systemname} - ${url}" + done < "${tmp}" + + [ $DEBUG -eq 1 ] && echo "DEBUG: there are $count systems (from bezels list)" + rm "${tmp}" +} + +############################### +# +function install() { + local count=0 + local installed_count=0 + local fn=$(date +"%s") + local tmp="$EE_TMP/bezels_$fn" + local gitname + local gitsystem + local filescount + local filename + local romname + local systemname + local url + local systemtoinstall="$1" + local systemfound=0 + + [ $DEBUG -eq 1 ] && echo "DEBUG: path to bezels ${DECODIR}${BEZELPROJECTGAMESDIR}" + + # create temporary files in /tmp + if [ -f $LOCALBEZELSLIST ]; then + cp -f "$LOCALBEZELSLIST" "${tmp}" + else + curl -H 'Cache-Control: no-cache' -sfL "$BEZELSLIST" -o "${tmp}" || return 1 + sed -i 's/\r$//' "${tmp}" + fi + + # reading bezels list from configuration file + while IFS=$' \t' read systemname url ; do + [ -z "${systemname}" ] && continue + [ $DEBUG -eq 1 ] && echo "DEBUG: bezels for system ${systemname} (from bezels list)" + [ "${systemname}" != "${systemtoinstall}" ] && continue + # check if url is valid and return [A] else [?] + ia=$(check_url "${url}") + if [ "$ia" != "[A]" ]; then + echo "Error - invalid bezels URL ${url}" + return 1 + else + systemfound=1 + break + fi + done < "${tmp}" + rm "${tmp}" + + # in case of TheBezelProject does not own the system we want to install + if [ "$systemfound" -eq 0 ]; then + echo -n "Error - system ${systemtoinstall} could not be found in " + [ -f $LOCALBEZELSLIST ] && echo "$LOCALBEZELSLIST" || echo "$BEZELSLIST" + return 1 + fi + + # check if roms/ directory exists + if [ ! -d "${ROMSDIR}${systemtoinstall}" ]; then + echo "Error - ROMs directory for system ${systemtoinstall} could not be found" + return 1 + fi + + # there is at least one file in each roms/ directory (i.e. _info.txt) + filescount=$(files_count "${ROMSDIR}${systemtoinstall}") + [ $DEBUG -eq 1 ] && echo "DEBUG: roms files count ${filescount}" + if [ "${filescount}" -le 1 ]; then + echo "Error - ROMs directory for system ${systemtoinstall} is empty" + return 1 + fi + + # create temporary directory in /tmp + fn=$(date +"%s") + tmp="$EE_TMP/dl_$fn" + [ $DEBUG -eq 1 ] && echo "DEBUG: path to roms ${ROMSDIR}${systemtoinstall}" + [ $DEBUG -eq 1 ] && echo "DEBUG: path for downloading ${tmp}" + # extract gitname from the url + gitname=$(git_name "${url}") + # keep only the final word for searching sub-folders of /retroarch/overlay/GameBezels/ + gitsystem=${gitname#bezelproject-} + mkdir -p "${tmp}" + cd "${tmp}" + echo "Downloading bezels for system ${systemtoinstall}" + [ $DEBUG -eq 1 ] && echo "DEBUG: URL: ${url} OUT: ${gitname}.zip GITNAME: $gitname GITSYSTEM: $gitsystem" + curl -H 'Cache-Control: no-cache' -sfL "${url}/archive/master.zip" -o "${gitname}.zip" + # error while downloading ? + if [[ "$?" -ne 0 || ! -f "${gitname}.zip" ]]; then + echo "Error - ${gitname} zip file could not be downloaded from ${url}" + # leave current directory and remove all downloads + cd + rm -r "${tmp}" + return 1 + fi + + # if it doesn't already exist, create the games bezels directory + if [ ! -d "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}" ]; then + [ $DEBUG -eq 1 ] && echo "DEBUG: creating ${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}" + mkdir -p "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}" + else + [ $DEBUG -eq 1 ] && echo "DEBUG: directory ${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall} already exist" + fi + + # if it doesn't already exist, create the systems bezels directory + if [ ! -d "${DECODIR}${BEZELPROJECTSYSTEMDIR}" ]; then + [ $DEBUG -eq 1 ] && echo "DEBUG: creating ${DECODIR}${BEZELPROJECTSYSTEMDIR}" + mkdir -p "${DECODIR}${BEZELPROJECTSYSTEMDIR}" + else + [ $DEBUG -eq 1 ] && echo "DEBUG: directory ${DECODIR}${BEZELPROJECTSYSTEMDIR} already exist" + fi + + # unzip archive for working on and remove the zip file + echo "Installing/Updating bezels for system ${systemtoinstall}..." + unzip -q "${gitname}.zip" + mv "${gitname}-master" "${gitname}" + rm "${gitname}.zip" + + # install games bezels if provided by TheBezelProject + echo "installing games bezels" + echo 0 > "/tmp/bcount" + echo 0 > "/tmp/bicount" + find "${ROMSDIR}${systemtoinstall}" -maxdepth 1 -type f -iname "[!.]*" | sort -V | + while read filename; do + filename=$(basename "$filename") + romname=${filename%%.*} + [ -z "${romname}" ] && continue + count=$((count + 1)) + echo $count > "/tmp/bcount" + [ $DEBUG -eq 1 ] && echo "DEBUG: count -> $count" + [ $DEBUG -eq 1 ] && echo "DEBUG: rom -> ${romname}" + if [ "${systemtoinstall}" == "mame" ] || [ "${systemtoinstall}" == "arcade" ] || [ "${systemtoinstall}" == "fba" ] || [ "${systemtoinstall}" == "neogeo" ]; then + # is there a matching PNG for arcade rom name ? + EE_REALSYSTEM="ArcadeBezels" + else + EE_REALSYSTEM="GameBezels/${gitsystem}" + fi + + if [ -f "${tmp}/${gitname}/retroarch/overlay/$EE_REALSYSTEM/${romname}.png" ]; then + [ $DEBUG -eq 1 ] && echo "DEBUG: found PNG for ${romname}" + # copy the matching PNG + cp "${tmp}/${gitname}/retroarch/overlay/$EE_REALSYSTEM/${romname}.png" "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}" + cp "${tmp}/${gitname}/retroarch/overlay/$EE_REALSYSTEM/${romname}.cfg" "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}" + sed -i '/overlay0_overlay/d' "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}/${romname}.cfg" + echo "overlay0_overlay = \"${romname}.png\"" >> "${DECODIR}${BEZELPROJECTGAMESDIR}${systemtoinstall}/${romname}.cfg" + installed_count=$((installed_count + 1)) + echo $installed_count > "/tmp/bicount" + [ $DEBUG -eq 1 ] && echo "DEBUG: installed_count -> $installed_count" + fi + done + echo "Bezels found" $(cat /tmp/bcount) "Bezels installed" $(cat /tmp/bicount) + rm /tmp/bcount + rm /tmp/bicount + + # install system bezel if provided by TheBezelProject + echo "installing system bezel" + # * Arcade * + if [ "${systemtoinstall}" == "mame" ] || [ "${systemtoinstall}" == "arcade" ] || [ "${systemtoinstall}" == "fba" ] || [ "${systemtoinstall}" == "neogeo" ]; then + # copy the HORIZONTAL system bezel to the correct directory and rename it + cp "${tmp}/${gitname}/retroarch/overlay/MAME-Horizontal.png" "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}.png" + else + # * Other * + filescount=$(find "${tmp}/${gitname}/retroarch/overlay" -maxdepth 1 -type f -name "*.png" | wc -l) + if [ "${filescount}" -eq 1 ]; then + rm -f "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemname}.png" + rm -f "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemname}.info" + # copy the system bezel to the correct directory and rename it + filename=$(ls -1 "${tmp}/${gitname}"/retroarch/overlay/*.png) + [ $DEBUG -eq 1 ] && echo "DEBUG: $filename ${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.png" + cp "$filename" "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.png" + filename=${filename%.*} + [ $DEBUG -eq 1 ] && echo "DEBUG: ${filename}.cfg ${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.cfg" + cp "${filename}.cfg" "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.cfg" + sed -i '/overlay0_overlay/d' "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.cfg" + echo "overlay0_overlay = \"default.png\"" >> "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}/default.cfg" + else + # make a symbolic link to the Batocera's bezel default system pack + ln -fs "${DECODIR}${DEFAULTBEZELDIR}${systemtoinstall}.png" "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}.png" + ln -fs "${DECODIR}${DEFAULTBEZELDIR}${systemtoinstall}.info" "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemtoinstall}.info" + fi + fi + +# # install default bezel (i.e. system not supported in TheBezelProject) +# echo "installing default bezels" +# if [ -d "${DECODIR}${BEZELPROJECTDIR}" ]; then +# echo "TODO : install the @fery65's default.png bezel" +# fi + + # leave current directory and remove all downloads + echo "Bezels for system ${systemtoinstall} are now installed" + cd + rm -r "${tmp}" +} + +############################### +# +function remove() { + systemname="$1" + + # do we want to remove all TheBezelProject ? + if [ "${systemname}" == "all" ]; then + if [ -d "${DECODIR}${BEZELPROJECTDIR}" ]; then + read -p "Do you wish to remove all bezels ? " yn + if [[ "$yn" = "y" || "$yn" = "Y" ]]; then + rm -rf "${DECODIR}${BEZELPROJECTDIR}" + fi + else + echo "Error - bezels directory ${DECODIR}${BEZELPROJECTDIR} is not valid" + return 1 + fi + else + # check if games/ directory exist + if [ ! -d "${DECODIR}${BEZELPROJECTGAMESDIR}${systemname}" ]; then + echo "Error - bezels for system ${systemname} could not be found" + return 1 + else + rm -rf "${DECODIR}${BEZELPROJECTGAMESDIR}${systemname}" + rm -f "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemname}.png" + rm -f "${DECODIR}${BEZELPROJECTSYSTEMDIR}${systemname}.info" + fi + fi +} + +############################### +#### Main loop +# +command="$1" +system="$2" +count=1 +installed_count=1 +if [ ! -d "${DECODIR}" ]; then + echo "Error - decorations directory ${DECODIR} is not valid" + exit 1 +fi + +if [[ "$command" == "list" ]]; then + list +elif [[ "$command" == "install" && -n "$system" ]]; then + install "$system" +elif [[ "$command" == "remove" && -n "$system" ]]; then + remove "$system" +else + usage +fi diff --git a/packages/jelos/sources/scripts/batocera-info b/packages/jelos/sources/scripts/batocera-info new file mode 120000 index 000000000..e55cf7223 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-info @@ -0,0 +1 @@ +jelos-info \ No newline at end of file diff --git a/packages/jelos/sources/scripts/batocera-resolution b/packages/jelos/sources/scripts/batocera-resolution new file mode 100755 index 000000000..fcaf8a03e --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-resolution @@ -0,0 +1,18 @@ +#!/bin/bash + +ACTION=$1 +shift + +FILEMODES="/sys/class/graphics/fb0/modes" + +case "${ACTION}" in + "listModes") + ;; + "setMode") + ;; + "currentMode"|"currentResolution") + # mode can be different from resolution (ie on rpi) + test -e "${FILEMODES}" && head -1 "${FILEMODES}" | sed -e s+'^[^:]:\([0-9]*\)x\([0-9]*\)[a-z]*.*$'+'\1x\2'+ + ;; +esac +exit 0 diff --git a/packages/jelos/sources/scripts/batocera-retroachievements-info b/packages/jelos/sources/scripts/batocera-retroachievements-info new file mode 100755 index 000000000..29d19fcb2 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-retroachievements-info @@ -0,0 +1,104 @@ +#!/bin/bash +# +# Get RetroAchievements information for Batocera +# +# @lbrpdx on Batocera Forums and Discord +# +# 20191124 - v2 with now outputs in XML format (for Batocera 5.25+) +# 20200113 - updated for retroachievements.org HTML changes +# 20200124 - added badges for each game played +# 20200304 - fixed a bug in rare cases where a RA game has no success icons +# 20200410 - updated for retroachievements.org HTML changes, again +# 20200625 - retroachievements.org HTML changes, again +# 20201104 - retroachievements.org HTML changes, again, again +# +# Usage: +# batocera-retroachievements-info +# +CONFIGFILE="/storage/.config/distribution/configs/distribution.conf" +TIMEOUT=4 # seconds before timeout (>2 sec) +USER="" + +############################### +# +function usage() { + echo "$0 username" + echo " - where username is the RetroAchievements username you want to check out" + exit 1 +} + +############################### +# +function process() { + fn=$(date +"%s") + tmpfile=/tmp/ra_$fn + curl -H 'Cache-Control: no-cache' -m "$TIMEOUT" -o $tmpfile https://retroachievements.org/user/$USER 2>/dev/null + if [ x"$?" != x0 ]; then + echo "" + echo "" + echo " $fn" + echo " RetroAchievements website is too slow to respond" + echo "" + exit 1; + fi + cat "$tmpfile" | awk -v FS="(


      Member Since: |
      Account Type:)" '{print $2}' | uniq) + parsedid=$(echo "$idcard" | sed -e "/^[[:blank:]]*$/d" | sed -e "s;\(.*\)
      Last Activity: \(.*\);\1@\2;") + avcompletion=$(cat "$tmpfile" | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(
      Average Completion: |
      Site Rank:)" '{print $2}' | sed -e "/^[[:blank:]]*$/d" | uniq) + points=$(cat "$tmpfile"_2 | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(
       |)" '{print $2}' | sed -e "s;(\([0-9]*\) points);\1;") + if [ x"$points" != x ] && [ "$points" -ge 1 ]; then + rank=$(cat "$tmpfile"_2 | sed -e "/^[[:blank:]]*$/d" | awk -v FS="(globalRanking.php|

      )" '{print $3}' | sed -e "s/\?[a-zA-Z0-9=&;']*>//" -e "s;;;" -e "s;%).*;%);") + ## For future use: UserPic is RetroAchievements' user avatar - however the S3 bucket is protected. + # UserPic=$(cat $tmpfile | grep 'meta property=.og:image. content=' | cut -d= -f3 | awk -F\' '{print $2}') + # Workaround: use the line below + UserPic="https://retroachievements.org/UserPic/$USER".png + pic="" + curl -H 'Cache-Control: no-cache' -m "$TIMEOUT" -f -s "$UserPic" >/dev/null 2>/dev/null + if [ x"$?" == x0 ]; then + pic=" $UserPic\n" + fi + echo "" + echo "" + echo " $fn" + echo " $USER" + echo " $points" + echo " $rank" + echo " $avcompletion" + echo -ne "$pic" + echo "$parsedid" | sed -e "s;\(.*\)@\(.*\); \1\n \2;" + xmllint --html "$tmpfile" 2>/dev/null | grep '.*points.' | sed -e "/^[[:blank:]]*$/d" | sed -e 's:\(.*\)points\.
      :\1points\@\\\n:g;' > "$tmpfile"_2 + cat "$tmpfile"_2 | awk -v FS="(href=\"/[gG]ame/[0-9]*\">|@)" '{print $2}' | sed -e "s;

      \(Last played[ 0-9:-]*\)
      \(.*\);@\2@\1;" | sed -e "s;achievements, ;achievements@;" | sed -e "s;Earned ;;" | sed -e "/^[[:blank:]]*$/d" > "$tmpfile"_st + cat "$tmpfile"_2 | grep -e 'div class="bb_inline" onmouseover' -e '^$' | sed "s:.*src=\"\(.*/Badge/.*\.png\)\".*:\1:" | sed "s;^$;https://batocera.org/favicon-64.png;" > "$tmpfile"_ba + i=0 + if [ $(cat "$tmpfile"_ba | wc -l) -eq $(cat "$tmpfile"_st | wc -l) ]; then + while IFS= read -r line || [[ -n "$line" ]]; do + i=$((i+1)) + echo "$line" | sed -e "s;\(.*\)@\(.*\) achievements@\(.*\) points@Last played \(.*\); \n \1\n \2\n \3\n \4;" + cat "$tmpfile"_ba | head -n "$i" | tail -n 1 | sed "s:^: :;s:$::" + echo " " + done < "$tmpfile"_st + else + echo "$res" | sed -e "s;\(.*\)@\(.*\) achievements@\(.*\) points@Last played \(.*\); \n \1\n \2\n \3\n \4\n ;" + fi + echo "
      " + else + echo "" + echo "" + echo " $fn" + echo " Player $USER hasn't unlocked any RetroAchievement yet" + echo "" + fi + rm "$tmpfile" "$tmpfile"_2 "$tmpfile"_st "$tmpfile"_ba 2>/dev/null +} + +#### Main loop +# +if [ $# -lt 1 ]; then + [ -f "$CONFIGFILE" ] && USER=$(grep -E "^[ \t]*global.retroachievements.username=" "$CONFIGFILE" | cut -d= -f2 | uniq) +else + tmp="$1" + [ x"${tmp::1}" == "x-" ] && usage || USER="$1" +fi + +[ x"$USER" == x ] && usage || process + diff --git a/packages/jelos/sources/scripts/batocera-scraper b/packages/jelos/sources/scripts/batocera-scraper new file mode 100755 index 000000000..ee407c36c --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-scraper @@ -0,0 +1,79 @@ +#!/bin/bash + +systemsetting="/usr/bin/batocera-settings" +syslang=$($systemsetting -command load -key system.language) +IMGSTYLE=$($systemsetting -command load -key scrapper.style) + +if test $# = 1 +then + DOSYS=$1 +fi + +# supported languages : en, fr, es, de, pt +case "${syslang}" in + fr_FR) + sslang=fr,en + ;; + es_ES) + sslang=es,en + ;; + de_DE) + sslang=de,en + ;; + pt_PT) + sslang=pt,en + ;; + pt_BR) + sslang=pt,en + ;; + *) + sslang=en +esac + +if test -z "${IMGSTYLE}" +then + IMGSTYLE="b,f,a,l,3b,s" +fi + +do_scrap() { + LRDIR=$1 + NF=$(ls "${LRDIR}" | grep -vE '\.txt$|\.xml$' | wc -l) + if test "${NF}" -gt 0 + then + BASEDIR=$(basename "${LRDIR}") + echo "GAME: system ${BASEDIR}" + EXTRAOPT= + + for x in "mame" "fba" "fba_libretro" "neogeo" + do + test "${LRDIR}" = "/storage/roms/${x}" && EXTRAOPT="-mame" + done + + (cd "${LRDIR}" && sselph-scraper -console_src ss,gdb,ovgdb -lang "${sslang}" -console_img "${IMGSTYLE}" -download_videos -workers 5 ${EXTRAOPT}) 2>&1 + fi +} + +# find system to scrape +(if test -n "${DOSYS}" + then + test -d "/storage/roms/${DOSYS}" && echo "/storage/roms/${DOSYS}" + else + find /storage/roms -maxdepth 1 -mindepth 1 -type d + fi) | + while read RDIR1 + do + # read the 2 next dir + read RDIR2 + read RDIR3 + read RDIR4 + + do_scrap "${RDIR1}" & + test -n "${RDIR2}" && do_scrap "${RDIR2}" & + test -n "${RDIR3}" && do_scrap "${RDIR3}" & + test -n "${RDIR4}" && do_scrap "${RDIR4}" & + wait + + done + +# synchronize to not make the usb/sdcard slowing down once finnished +sync diff --git a/packages/jelos/sources/scripts/batocera-settings b/packages/jelos/sources/scripts/batocera-settings new file mode 100755 index 000000000..0c4a2c069 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-settings @@ -0,0 +1,267 @@ +#!/bin/bash + +# batocera-settings can mimic batoceraSettings.py +# goal: abolish this python script, it's useless for the sake of the load feature only +# get a more user friendly environment for setting, getting and saving keys +# +# Usage of BASE COMMAND: +# longform: --command --key --value +# +# shortform: +# +# --command load write enable disable status +# --key any key in distribution.conf (kodi.enabled...) +# --value any alphanumerical string +# use quotation marks to avoid globbing use slashes escape special characters + +# This script reads only 1st occurrence if string and writes only to this first hit +# +# This script uses #-Character to comment values +# +# If there is a boolean value (0,1) then then enable and disable command will set the corresponding +# boolean value. + +# Examples: +# 'batocera-settings --command load --key wifi.enabled' will print out 0 or 1 +# 'batocera-settings --command write --key wifi.ssid -value "This is my NET"' will set 'wlan.ssid=This is my NET' +# 'batocera-settings enable wifi.ssid' will remove # from configfile (activate) +# 'batocera-settings disable wifi.enabled' will set key wifi.enabled=0 +# 'botocera-settings /myown/config.file --command status --key my.key' will output status of own config.file and my.key + +# by cyperghost - 2019/12/30 + +##### INITS ##### +BATOCERA_CONFIGFILE="/storage/.config/distribution/configs/distribution.conf" +COMMENT_CHAR_SEARCH="[#|;]" +COMMENT_CHAR="#" +##### INITS ##### + +##### Function Calls ##### + +function get_config() { + #Will search for key.value and #key.value for only one occurrence + #If the character is the COMMENT CHAR then set value to it + #Otherwise strip till the equal-char to obtain value + local val + local ret + val="$(grep -E -m1 "^\s*$1\s*=" $BATOCERA_CONFIGFILE)" + ret=$? + if [[ $ret -eq 1 ]]; then + val="$(grep -E -m1 "^$COMMENT_CHAR_SEARCH\s*$1\s*=" $BATOCERA_CONFIGFILE)" + ret=$? + [[ $ret -eq 0 ]] && val=$COMMENT_CHAR + else + #Maybe here some finetuning to catch key.value = ENTRY without blanks + val="${val#*=}" + fi + echo "$val" + return $ret +} + +function set_config() { + #Will search for first key.name at beginning of line and write value to it + sed -i "1,/^\(\s*$1\s*=\).*/s//\1$2/" "$BATOCERA_CONFIGFILE" +} + +function uncomment_config() { + #Will search for first Comment Char at beginning of line and remove it + sed -i "1,/^$COMMENT_CHAR_SEARCH\(\s*$1\)/s//\1/" "$BATOCERA_CONFIGFILE" +} + +function comment_config() { + #Will search for first key.name at beginning of line and add a comment char to it + sed -i "1,/^\(\s*$1\)/s//$COMMENT_CHAR\1/" "$BATOCERA_CONFIGFILE" +} + +function check_argument() { + # This method does not accept arguments starting with '-'. + if [[ -z "$2" || "$2" =~ ^- ]]; then + echo >&2 + echo "ERROR: '$1' is missing an argument." >&2 + echo >&2 + echo "Just type '$0' to see usage page." >&2 + echo >&2 + return 1 + fi +} + +function dash_style() { + #This function is needed to "simulate" the python script with single dash + #commands. It will also accept the more common posix double dashes + #Accept dashes and double dashes and build new array ii with parameter set + #The else-branch can be used for the shortform + + for i in --command --key --value; do + if [[ -z "$1" ]]; then + continue + elif [[ "$i" =~ ^-{0,1}"${1,,}" ]]; then + check_argument $1 $2 + [[ $? -eq 0 ]] || exit 1 + ii+=("$2") + shift 2 + else + ii+=("$1") + shift 1 + fi + done +} + + +function usage() { +val=" Usage of BASE COMMAND: + + --command --key --value + + shortform: + + --command load write enable disable status + --key any key in distribution.conf (kodi.enabled...) + --value any alphanumerical string + use quotation marks to avoid globbing + + For write command --value must be provided + + exit codes: exit 0 = value is available, proper exit + exit 1 = general error + exit 2 = file error + exit 10 = value found, but empty + exit 11 = value found, but not activated + exit 12 = value not found + + If you don't set a filename then default is '~/storage/.config/distribution.conf'" + +echo "$val" + +} +##### Function Calls ##### + +##### MAIN FUNCTION ##### +function main() { + + #Filename parsed? + if [[ -f "$1" ]]; then + BATOCERA_CONFIGFILE="$1" + shift + else + [[ -f "$BATOCERA_CONFIGFILE" ]] || { echo "not found: $BATOCERA_CONFIGFILE" >&2; exit 2; } + fi + + #How much arguments are parsed, up to 6 then it is the long format + #up to 3 then it is the short format + if [[ ${#@} -eq 0 || ${#@} -gt 6 ]]; then + usage + exit 1 + else + dash_style "$@" + command="${ii[0]}" + keyvalue="${ii[1]}" + newvalue="${ii[2]}" + unset ii + fi + + [[ -z $keyvalue ]] && { echo "error: Please provide a proper keyvalue" >&2; exit 1; } + + # value processing, switch case + case "${command,,}" in + + "read"|"get"|"load") + val="$(get_config $keyvalue)" + ret=$? + [[ "$val" == "$COMMENT_CHAR" ]] && exit 11 + [[ -z "$val" && $ret -eq 0 ]] && exit 10 + [[ -z "$val" && $ret -eq 1 ]] && exit 12 + [[ -n "$val" ]] && echo "$val" && exit 0 + ;; + + "stat"|"status") + val="$(get_config $keyvalue)" + ret=$? + [[ -f "$BATOCERA_CONFIGFILE" ]] && echo "ok: found '$BATOCERA_CONFIGFILE'" >&2 || echo "error: not found '$BATOCERA_CONFIGFILE'" >&2 + [[ -w "$BATOCERA_CONFIGFILE" ]] && echo "ok: r/w file '$BATOCERA_CONFIGFILE'" >&2 || echo "error: r/o file '$BATOCERA_CONFIGFILE'" >&2 + [[ -z "$val" && $ret -eq 1 ]] && echo "error: '$keyvalue' not found!" >&2 + [[ -z "$val" && $ret -eq 0 ]] && echo "error: '$keyvalue' is empty - use 'comment' command to retrieve" >&2 + [[ "$val" == "$COMMENT_CHAR" ]] && echo "error: '$keyvalue' is commented $COMMENT_CHAR!" >&2 && val= + [[ -n "$val" ]] && echo "ok: '$keyvalue' $val" + exit 0 + ;; + + "set"|"write"|"save") + #Is file write protected? + [[ -w "$BATOCERA_CONFIGFILE" ]] || { echo "r/o file: $BATOCERA_CONFIGFILE" >&2; exit 2; } + #We can comment line above to erase keys, it's much saver to check if a value is setted + [[ -z "$newvalue" ]] && echo "error: '$keyvalue' needs value to be setted" >&2 && exit 1 + + val="$(get_config $keyvalue)" + ret=$? + if [[ "$val" == "$COMMENT_CHAR" ]]; then + echo "$keyvalue: hashed out!" >&2 + uncomment_config "$keyvalue" + set_config "$keyvalue" "$newvalue" + echo "$keyvalue: set from '$val' to '$newvalue'" >&2 + exit 0 + elif [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" >&2 + exit 12 + elif [[ "$val" != "$newvalue" ]]; then + set_config "$keyvalue" "$newvalue" + exit 0 + fi + ;; + + "uncomment"|"enable"|"activate") + val="$(get_config $keyvalue)" + ret=$? + # Boolean + if [[ "$val" == "$COMMENT_CHAR" ]]; then + uncomment_config "$keyvalue" + echo "$keyvalue: removed '$COMMENT_CHAR', key is active" >&2 + elif [[ "$val" == "0" ]]; then + set_config "$keyvalue" "1" + echo "$keyvalue: boolean set '1'" >&2 + elif [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" && exit 2 + fi + ;; + + "comment"|"disable"|"remark") + val="$(get_config $keyvalue)" + ret=$? + # Boolean + [[ "$val" == "$COMMENT_CHAR" || "$val" == "0" ]] && exit 0 + if [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" >&2 && exit 12 + elif [[ "$val" == "1" ]]; then + set_config "$keyvalue" "0" + echo "$keyvalue: boolean set to '0'" >&2 + else + comment_config "$keyvalue" + echo "$keyvalue: added '$COMMENT_CHAR', key is not active" >&2 + fi + ;; + + *) + echo "ERROR: invalid command '$command'" >&2 + exit 1 + ;; + esac +} +##### MAIN FUNCTION ##### + +##### MAIN CALL ##### + +# Prepare arrays from fob python script +# Keyword for python call is mimic_python +# Attention the unset is needed to eliminate first argument (python basefile) + +if [[ "${#@}" -eq 1 && "$1" =~ "mimic_python" ]]; then + #batoceraSettings.py fob + readarray -t arr <<< "$1" + unset arr[0] +else + #regular call by shell + arr=("$@") +fi + +main "${arr[@]}" + +##### MAIN CALL ##### diff --git a/packages/jelos/sources/scripts/batocera-systems b/packages/jelos/sources/scripts/batocera-systems new file mode 100755 index 000000000..5ba58e7c4 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-systems @@ -0,0 +1,612 @@ +#!/usr/bin/env python + +from __future__ import print_function + +from hashlib import md5 +from os.path import isfile +from collections import OrderedDict +import sys + +systems = { + + # Atari + "atari5200": {"name": "Atari 5200", "biosFiles": [{"md5": "281f20ea4320404ec820fb7ec0693b38", "file": "bios/5200.rom"}]}, + + "atari800": {"name": "Atari 800", "biosFiles": [{"md5": "06daac977823773a3eea3422fd26a703", "file": "bios/ATARIXL.ROM"}, + {"md5": "0bac0c6a50104045d902df4503a4c30b", "file": "bios/ATARIBAS.ROM"}, + {"md5": "eb1f32f5d9f382db1bbfb8d7f9cb343a", "file": "bios/ATARIOSA.ROM"}, + {"md5": "a3e8d617c95d08031fe1b20d541434b2", "file": "bios/ATARIOSB.ROM"}]}, + + "atari7800": {"name": "Atari 7800", "biosFiles": [{"md5": "0763f1ffb006ddbe32e52d497ee848ae", "file": "bios/7800 BIOS (U).rom"}]}, + + "atarist": {"name": "Atari ST", "biosFiles": [{"md5": "b2a8570de2e850c5acf81cb80512d9f6", "file": "bios/tos.img"}]}, + + "atarilynx": {"name": "Lynx", "biosFiles": [{"md5": "fcd403db69f54290b51035d82f835e7b", "file": "bios/lynxboot.img"}]}, + + + # Colecovision + "colecovision": {"name": "Colecovision", "biosFiles": [{"md5": "", "file": "bios/Machines/COL - Bit Corporation Dina/config.ini"}, + {"md5": "1de922acdd742d31349c2801e9768c35", "file": "bios/Machines/COL - Bit Corporation Dina/czz50-1.rom"}, + {"md5": "72b089dc55b7fe7ffb5028f365e8c045", "file": "bios/Machines/COL - Bit Corporation Dina/czz50-2.rom"}, + {"md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/Machines/COL - ColecoVision/coleco.rom"}, + {"md5": "", "file": "bios/Machines/COL - ColecoVision/config.ini"}, + {"md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/Machines/COL - ColecoVision with Opcode Memory Extension/coleco.rom"}, + {"md5": "", "file": "bios/Machines/COL - ColecoVision with Opcode Memory Extension/config.ini"}, + {"md5": "", "file": "bios/Machines/COL - Spectravideo SVI-603 Coleco/config.ini"}, + {"md5": "c60a2e85572c0ccb69505a7646d5c1b6", "file": "bios/Machines/COL - Spectravideo SVI-603 Coleco/SVI603.ROM"}, + {"md5": "", "file": "bios/Databases/colecodb.xml"}, + {"md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/colecovision.rom"}, + {"md5": "2c66f5911e5b42b8ebe113403548eee7", "file": "bios/BIOS.col"}]}, + + + # Commodore + "amiga": {"name": "Amiga/CD32", "biosFiles": [{"md5": "89da1838a24460e4b93f4f0c5d92d48d", "file": "bios/CDTV Extended-ROM v1.0 (1991)(Commodore)(CDTV)[!].rom"}, + {"md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/Kickstart v1.2 r33.180 (1986)(Commodore)(A500-A1000-A2000)[!].rom"}, + {"md5": "68c9c0826f6c0ca20546d588ee77391c", "file": "bios/Kickstart v1.2 rev 33.166 (1986)(Commodore)(A1000).rom"}, + {"md5": "192d6d950d0ed3df8040b788502831c2", "file": "bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[o].rom"}, + {"md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/Kickstart v1.3 r34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV)[!].rom"}, + {"md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/Kickstart v2.04 r37.175 (1991)(Commodore)(A500+)[!].rom"}, + {"md5": "465646c9b6729f77eea5314d1f057951", "file": "bios/Kickstart v2.05 r37.350 (1992)(Commodore)(A600HD)[!].rom"}, + {"md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/Kickstart v3.1 r40.60 (1993)(Commodore)(CD32).rom"}, + {"md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A1200)[!].rom"}, + {"md5": "413590e50098a056cfec418d3df0212d", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A3000).rom"}, + {"md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/Kickstart v3.1 r40.68 (1993)(Commodore)(A4000).rom"}, + {"md5": "85ad74194e87c08904327de1a9443b7a", "file": "bios/kick33180.A500"}, + {"md5": "82a21c1890cae844b3df741f2762d48d", "file": "bios/kick34005.A500"}, + {"md5": "dc10d7bdd1b6f450773dfb558477c230", "file": "bios/kick37175.A500"}, + {"md5": "5f8924d013dd57a89cf349f4cdedc6b1", "file": "bios/kick40060.CD32"}, + {"md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/kick40060.CD32.ext"}, + {"md5": "e40a5dfb3d017ba8779faba30cbd1c8e", "file": "bios/kick40063.A600"}, + {"md5": "646773759326fbac3b2311fd8c8793ee", "file": "bios/kick40068.A1200"}, + {"md5": "9bdedde6a4f33555b4a270c8ca53297d", "file": "bios/kick40068.A4000"}, + {"md5": "bb72565701b1b6faece07d68ea5da639", "file": "bios/CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom"}]}, + + + # Magnavox and Philips + "o2em": {"name": "Odyssey 2", "biosFiles": [{"md5": "562d5ebf9e030a40d6fabfc2f33139fd", "file": "bios/o2rom.bin"}, + {"md5": "f1071cdb0b6b10dde94d3bc8a6146387", "file": "bios/c52.bin"}, + {"md5": "c500ff71236068e0dc0d0603d265ae76", "file": "bios/g7400.bin"}, + {"md5": "279008e4a0db2dc5f1c048853b033828", "file": "bios/jopac.bin"}]}, + + + # Mattel + "intellivision": {"name": "Mattel Intellivision", "biosFiles": [{"md5": "62e761035cb657903761800f4437b8af", "file": "bios/exec.bin"}, + {"md5": "0cd5946c6473e42e8e4c2137785e427f", "file": "bios/grom.bin"}, + {"md5": "2e72a9a2b897d330a35c8b07a6146c52", "file": "bios/ECS.bin"}, + {"md5": "d5530f74681ec6e0f282dab42e6b1c5f", "file": "bios/IVOICE.bin"}]}, + + + # Microsoft + "msx": {"name": "MSX", "biosFiles": [{"md5": "", "file": "bios/Machines/Forte II Games - Pesadelo/config.ini"}, + {"md5": "", "file": "bios/Machines/Forte II Games - Pesadelo/pesadelo.rom"}, + {"md5": "", "file": "bios/Machines/MSX/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX/MSX.ROM"}, + {"md5": "", "file": "bios/Machines/MSX/MSX2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX/MSX2EXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX/MSX2P.ROM"}, + {"md5": "", "file": "bios/Machines/MSX/MSX2PEXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX/MSXDOS2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX - Al Alamiah AX-170/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Arabic/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Brazilian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Brazilian/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX - C-BIOS/cbios.txt"}, + {"md5": "", "file": "bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom"}, + {"md5": "", "file": "bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom"}, + {"md5": "", "file": "bios/Machines/MSX - C-BIOS/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Canon V-10/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Canon V-20/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Daewoo DPC-100/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Daewoo DPC-180/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Daewoo DPC-200/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Estonian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Frael Bruc 100-1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - French/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - German/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - German/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX - Goldstar FC-200/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Gradiente Expert 1.0/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Gradiente Expert 1.1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Gradiente Expert 1.3/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Gradiente Expert DDPlus/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Gradiente Expert Plus/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Japanese/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Japanese/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX - JVC HC-7GB/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Korean/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Korean/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX - Mitsubishi ML-F80/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Mitsubishi ML-FX1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National CF-1200/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Panasonic FS-A1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Panasonic FS-A1 (a)/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Panasonic FS-A1F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Panasonic FS-A1FM/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Panasonic FS-A1MK2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8220/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8220 (a)/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8245/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8245F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8250/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8255/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8280/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips NMS-8280G/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips VG-8230/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips VG-8235/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sharp Epcom HotBit 1.2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sharp Epcom HotBit 1.3b/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sharp Epcom HotBit 1.3p/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-10P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-201/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-201P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-20P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-501P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-55D/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-55P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-75D/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sony HB-75P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Spanish/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Spectravideo SVI-728/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Spectravideo SVI-738/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Spectravideo SVI-738-2 CUC/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Spectravideo SVI-738-2 JP Grobler/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Spectravideo SVI-738-2 LC Grosso/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Swedish/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Talent TPC-310/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Toshiba HX-23/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Toshiba HX-23F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Virtual Haesung Console/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Yamaha CX7M/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Yamaha CX7M-128/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSX.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSX2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSX2EXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSX2P.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSX2PEXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+/MSXDOS2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Brazilian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/cbios.txt"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/cbios_logo_msx2+.rom"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/cbios_main_msx2+.rom"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/cbios_music.rom"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/cbios_sub.rom"}, + {"md5": "", "file": "bios/Machines/MSX2+ - C-BIOS/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Ciel Expert 3 IDE/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Ciel Expert 3 Turbo/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Spectravideo SVI-738 Swedish/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Swedish/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Swedish/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX - Talent DPC-200/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Talent DPC-200A/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Toshiba HX-10/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Toshiba HX-10S/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Toshiba HX-20/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha CX5M-1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha CX5M-128/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha CX5M-2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha CX5MII/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS303/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503II/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503IIR/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503M/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yashica YC-64/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yeno DPC-64/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yeno MX64/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2/MSX.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2/MSX2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2/MSX2EXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2/MSX2P.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2/MSX2PEXT.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2/MSXDOS2.ROM"}, + {"md5": "", "file": "bios/Machines/MSX2 - Al Alamiah AX-350/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Al Alamiah AX-370/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Arabic/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Arabic/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Brazilian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Brazilian/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - C-BIOS/cbios.txt"}, + {"md5": "", "file": "bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom"}, + {"md5": "", "file": "bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom"}, + {"md5": "", "file": "bios/Machines/MSX2 - C-BIOS/cbios_sub.rom"}, + {"md5": "", "file": "bios/Machines/MSX2 - C-BIOS/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Daewoo CPC-300/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Daewoo CPC-300E/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Daewoo CPC-400/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Daewoo CPC-400S/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Estonian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - French/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - French/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - German/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - German/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Gradiente Expert 2.0/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Japanese/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Japanese/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Korean/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Korean/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-4500/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-4600/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-4700/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-5000/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-5500F1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - National FS-5500F2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Daewoo DPC-200E/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National CF-2000/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sharp Epcom HotBit 1.1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Spectravideo SVI-738 Henrik Gilvad/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Yamaha YIS503IIR Estonian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Only PSG/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Only PSG/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips VG-8235F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Spanish/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Spanish/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2+ - European/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National CF-2700/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National CF-3000/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National CF-3300/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National FS-1300/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - National FS-4000/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Olympia PHC-2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Olympia PHC-28/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Panasonic CF-2700G/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips NMS-801/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8000/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8010/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8010F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8020-00/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8020-20/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Philips VG-8020F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Pioneer PX-7/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Pioneer PX-V60/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Russian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sanyo MPC-100/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sanyo MPC-64/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sanyo PHC-28L/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sanyo PHC-28S/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX - Sanyo Wavy MPC-10/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Gradiente Expert AC88+/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Gradiente Expert DDX+/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - MSXPLAYer 2003/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Panasonic FS-A1FX/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Panasonic FS-A1WSX/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Panasonic FS-A1WX/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Panasonic FS-A1WX (a)/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sanyo Wavy PHC-35J/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sanyo Wavy PHC-70FD1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sanyo Wavy PHC-70FD2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sony HB-F1XDJ/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sony HB-F1XV/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2+ - Sony HB-F9S+/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR - European/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR - Panasonic FS-A1GT/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR - Panasonic FS-A1ST/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR - Panasonic FS-A1ST (a)/config.ini"}, + {"md5": "", "file": "bios/Machines/MSXturboR - Panasonic FS-A1ST (b)/config.ini"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2G.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXDOS23.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/ARAB1.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/ARABIC.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/BEERIDE.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/FMPAC.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/GCVMX80.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/HANGUL.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/KANJI.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MICROSOLDISK.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MOONSOUND.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2AR.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2AREXT.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2BR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2BREXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2EXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2FR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2FREXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2GEXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2HAN.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2J.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2JEXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2KR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2KREXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2P.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2PEXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2PMUS.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2R.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2R2.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2REXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2SE.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2SP.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSX2SPEXT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXAR.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXBR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXDOS2.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXFR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXG.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXHAN.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXJ.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXKANJI.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXKR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXR.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXR2.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXSE.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXSP.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXTR.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXTREXT.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXTRMUS.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/MSXTROPT.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/NATIONALDISK.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/NOVAXIS.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/nowindDos1.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/nowindDos2.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/PAINT.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/PANASONICDISK.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/PHILIPSDISK.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/RS232.ROM"}, + {"md5": "", "file": "bios/Machines/Shared Roms/Shared.txt"}, + {"md5": "", "file": "bios/Machines/Shared Roms/SUNRISEIDE.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/SWP.rom"}, + {"md5": "", "file": "bios/Machines/Shared Roms/XBASIC2.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-318/config.ini"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-318/svi318.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328/config.ini"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328/svi328.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Column/config.ini"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi328a.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Column/svi806.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/config.ini"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi328a.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 80 Swedish/svi806se.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 MK2/config.ini"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 MK2/svi328a.rom"}, + {"md5": "", "file": "bios/Machines/SVI - Spectravideo SVI-328 MK2/svi806.rom"}, + {"md5": "", "file": "bios/Machines/Turbo-R/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Philips VG-8240/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Russian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Russian/hardwareconfig.xml"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sanyo Wavy MPC-25FD/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sanyo Wavy PHC-23/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sharp Epcom HotBit 2.0/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F1/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F1II/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F1XD/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F1XDMK2/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F500/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F500P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F700D/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F700F/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F700P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F700S/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F900/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F900 (a)/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F9P/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F9P Russian/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-F9S/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-G900AP/config.ini"}, + {"md5": "", "file": "bios/Machines/MSX2 - Sony HB-G900P/config.ini"}]}, + + + # NEC + "pcengine": {"name": "PC Engine", "biosFiles": [{"md5": "38179df8f4ac870017db21ebcbf53114;ff1a674273fe3540ccef576376407d1d", "file": "bios/syscard3.pce"}]}, + + "pcfx": {"name": "PC-FX", "biosFiles": [{"md5": "08e36edbea28a017f79f8d4f7ff9b6d7", "file": "bios/pcfx.rom"}]}, + + "supergrafx": {"name": "Supergrafx", "biosFiles": [{"md5": "38179df8f4ac870017db21ebcbf53114;ff1a674273fe3540ccef576376407d1d", "file": "bios/syscard3.pce"}, + {"md5": "", "file": "bios/syscard2.pce"}, + {"md5": "", "file": "bios/syscard1.pce"}, + {"md5": "", "file": "bios/gexpress.pce"}]}, + + "pc88": {"name": "NEC - PC-8800", "biosFiles": [{"md5": "", "file": "bios/quasi88/DISK.ROM"}, + {"md5": "", "file": "bios/quasi88/N88.ROM"}, + {"md5": "", "file": "bios/quasi88/N88N.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_0.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_1.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_2.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_3.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_KNJ1.ROM"}, + {"md5": "", "file": "bios/quasi88/N88_KNJ2.ROM"}]}, + + # Nintendo + "fds": {"name": "Nintendo Family Computer Disk System", "biosFiles": [{"md5": "", "file": "bios/NstDatabase.xml"}, + {"md5": "ca30b50f880eb660a320674ed365ef7a", "file": "bios/disksys.rom"}]}, + + "gb": {"name": "Game Boy", "biosFiles": [{"md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin"}, + {"md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin"}]}, + + "gbc": {"name": "Game Boy Color", "biosFiles": [{"md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin"}, + {"md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin"}]}, + + "gba": {"name": "Game Boy Advance", "biosFiles": [{"md5": "a860e8c0b6d573d191e4ec7db1b1e4f6", "file": "bios/gba_bios.bin"}, + {"md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin"}, + {"md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin"}, + {"md5": "d574d4f9c12f305074798f54c091a8b4", "file": "bios/sgb_bios.bin"}]}, + + "n64": {"name": "Nintendo 64", "biosFiles": [{"md5": "8d3d9f294b6e174bc7b1d2fd1c727530", "file": "bios/64DD_IPL.bin"}]}, + + "nds": {"name": "Nintendo DS", "biosFiles": [{"md5": "145eaef5bd3037cbc247c213bb3da1b3", "file": "bios/firmware.bin"}, + {"md5": "df692a80a5b1bc90728bc3dfc76cd948", "file": "bios/bios7.bin"}, + {"md5": "a392174eb3e572fed6447e956bde4b25", "file": "bios/bios9.bin"}]}, + + "satellaview": {"name": "Satellaview", "biosFiles": [{"md5": "fed4d8242cfbed61343d53d48432aced;96cf17bf589fcbfa6f8de2dc84f19fa2", "file": "bios/BS-X.bin"}]}, + + "sufami": {"name": "Sufami", "biosFiles": [{"md5": "d3a44ba7d42a74d3ac58cb9c14c6a5ca", "file": "bios/STBIOS.bin"}]}, + + + # Panasonic, Sanyo and Goldstar + "3do": {"name": "3DO", "biosFiles": [{"md5": "f47264dd47fe30f73ab3c010015c155b", "file": "bios/panafz1.bin"}, + {"md5": "51f2f43ae2f3508a14d9f56597e2d3ce", "file": "bios/panafz10.bin"}, + {"md5": "8639fd5e549bd6238cfee79e3e749114", "file": "bios/goldstar.bin"}, + {"md5": "35fa1a1ebaaeea286dc5cd15487c13ea", "file": "bios/sanyotry.bin"}, + {"md5": "8970fc987ab89a7f64da9f8a8c4333ff", "file": "bios/3do_arcade_saot.bin"}]}, + + + # Sega + "naomi": {"name": "Naomi", "biosFiles": [{"md5": "3bffafac42a7767d8dcecf771f5552ba", "file": "bios/dc/naomi_boot.bin"}, + {"md5": "e63d892cdb8b532351dc7020bb60b6f4", "file": "bios/dc/naomi.zip"}]}, + + "atomiswave": {"name": "Atomiswave", "biosFiles": [{"md5": "0ec5ae5b5a5c4959fa8b43fcf8687f7c", "file": "bios/dc/awbios.zip"}]}, + + "dreamcast": {"name": "Dreamcast", "biosFiles": [{"md5": "e10c53c2f8b90bab96ead2d368858623", "file": "bios/dc/dc_boot.bin"}, + {"md5": "0a93f7940c455905bea6e392dfde92a4", "file": "bios/dc/dc_flash.bin"}]}, + + "gamegear": {"name": "Game Gear", "biosFiles": [{"md5": "672e104c3be3a238301aceffc3b23fd6", "file": "bios/bios.gg"}]}, + + "mastersystem": {"name": "MasterSystem", "biosFiles": [{"md5": "840481177270d5642a14ca71ee72844c", "file": "bios/bios_E.sms"}, + {"md5": "840481177270d5642a14ca71ee72844c", "file": "bios/bios_U.sms"}, + {"md5": "24a519c53f67b00640d0048ef7089105", "file": "bios/bios_J.sms"}]}, + + "saturn": {"name": "Sega Saturn", "biosFiles": [{"md5": "af5828fdff51384f99b3c4926be27762", "file": "bios/saturn_bios.bin"}, + {"md5": "85ec9ca47d8f6807718151cbcca8b964", "file": "bios/sega_101.bin"}, + {"md5": "3240872c70984b6cbfda1586cab68dbe", "file": "bios/mpr-17933.bin"}, + {"md5": "255113ba943c92a54facd25a10fd780c", "file": "bios/mpr-18811-mx.ic1"}, + {"md5": "1cd19988d1d72a3e7caa0b73234c96b4", "file": "bios/mpr-19367-mx.ic1"}, + {"md5": "53a094ad3a188f86de4e64624fe9b3ca", "file": "bios/stvbios.zip"}]}, + + "segacd": {"name": "Sega CD", "biosFiles": [{"md5": "e66fa1dc5820d254611fdcdba0662372", "file": "bios/bios_CD_E.bin"}, + {"md5": "854b9150240a198070150e4566ae1290", "file": "bios/bios_CD_U.bin"}, + {"md5": "278a9397d192149e84e820ac621a8edd", "file": "bios/bios_CD_J.bin"}]}, + + "sc-3000": {"name": "SC-3000", "biosFiles": [{"md5": "", "file": "bios/Machines/SEGA - SC-3000/config.ini"}]}, + + + # Sharp + "x68000": {"name": "Sharp x68000", "biosFiles": [{"md5": "", "file": "bios/keropi/iplrom.dat"}, + {"md5": "", "file": "bios/keropi/iplrom30.dat"}, + {"md5": "", "file": "bios/keropi/iplromco.dat"}, + {"md5": "", "file": "bios/keropi/iplromxv.dat"}, + {"md5": "", "file": "bios/keropi/cgrom.dat"}]}, + + "x1": {"name": "Sharp X1", "biosFiles": [{"md5": "eeeea1cd29c6e0e8b094790ae969bfa7", "file": "bios/xmil/IPLROM.X1"}, + {"md5": "851e4a5936f17d13f8c39a980cf00d77", "file": "bios/xmil/IPLROM.X1T"}]}, + + + # SNK + "neogeo": {"name": "NeoGeo", "biosFiles": [{"md5": "", "file": "neogeo/neogeo.zip"}]}, + + "neogeocd": {"name": "NeoGeo CD", "biosFiles": [{"md5": "", "file": "neogeo/neogeo.zip"}, + {"md5": "", "file": "bios/neocdz.zip"}, + {"md5": "e255264d85d5765013b1b2fa8109dd53", "file": "bios/neocd/ng-lo.rom"}, + {"md5": "f39572af7584cb5b3f70ae8cc848aba2", "file": "bios/neocd/neocd_z.rom"}]}, + + + # Sony Computer Entertainment + "psx": {"name": "PSX", "biosFiles": [{"md5": "8dd7d5296a650fac7319bce665a6a53c", "file": "bios/scph5500.bin"}, + {"md5": "490f666e1afb15b7362b406ed1cea246", "file": "bios/scph5501.bin"}, + {"md5": "32736f17079d0b2b7024407c39bd3050", "file": "bios/scph5502.bin"}]}, + + + # Sinclair + "zxspectrum": {"name": "ZX Spectrum", "biosFiles": [{"md5": "", "file": "bios/128p-0.rom"}, + {"md5": "", "file": "bios/128p-1.rom"}, + {"md5": "", "file": "bios/trdos.rom"}, + {"md5": "", "file": "bios/gluck.rom"}, + {"md5": "", "file": "bios/256s-0.rom"}, + {"md5": "", "file": "bios/256s-1.rom"}, + {"md5": "", "file": "bios/256s-2.rom"}, + {"md5": "", "file": "bios/256s-3.rom"}]}, + + + } + + +class BiosStatus: + MISSING = "MISSING" + UNTESTED = "UNTESTED" + + +def md5sum(filename, blocksize=65536): + hash = md5() + with open(filename, "rb") as f: + for block in iter(lambda: f.read(blocksize), b""): + hash.update(block) + return hash.hexdigest() + + +def checkBios(systems, prefix): + missingBios = {} + for system in systems.keys(): + for file in systems[system]["biosFiles"]: + x = 0 + filepath = prefix + "/" + file["file"] + if ";" in file["md5"]: + filehashes = file["md5"].split(";") + else: + filehashes = (file["md5"],) + if isfile(filepath): + md5 = md5sum(filepath) + if md5 not in filehashes and file["md5"] != "": + if system not in missingBios: + missingBios[system] = {} + for filehash in filehashes: + x += 1 + missingBios[system][file["file"]+"(hash%s)" % x] = {"status": BiosStatus.UNTESTED, "md5": filehash, "file": file["file"]} + else: + if system not in missingBios: + missingBios[system] = {} + for filehash in filehashes: + x += 1 + missingBios[system][file["file"]+"(hash%s)" % x] = {"status": BiosStatus.MISSING, "md5": filehash, "file": file["file"]} + return missingBios + + +# Returns True if missing, False if nothing is missing +def displayMissingBios(systems, missingBios): + sortedMissingBios = OrderedDict(sorted(missingBios.items())) + if sortedMissingBios: + for system in sortedMissingBios: + print("> {}".format(systems[system]["name"])) + for file in sortedMissingBios[system].keys(): + md5str = "-" + if sortedMissingBios[system][file]["md5"] != "": + md5str = sortedMissingBios[system][file]["md5"] + print("{} {} {}".format(sortedMissingBios[system][file]["status"], md5str, sortedMissingBios[system][file]["file"])) + return True + else: + print("No missing bios") + return False + + +def createReadme(systems): + for system in sorted(systems): + print("{}:".format(systems[system]["name"])) + for bios in systems[system]["biosFiles"]: + if ";" in bios["md5"]: + filehashes = bios["md5"].split(";") + else: + filehashes = (bios["md5"],) + for filehash in filehashes: + print("{:32} {}".format(filehash, "/storage/roms/" + bios["file"])) + print("") + +if __name__ == '__main__': + if len(sys.argv) == 1: + prefix = "/storage/roms/" + if displayMissingBios(systems, checkBios(systems, prefix)): + exit(2) + elif sys.argv[1] == "--createReadme": + createReadme(systems) + elif len(sys.argv) == 3 and sys.argv[1] in ["--filter", "--strictfilter"]: + prefix = "/storage/roms/" + lowered_name = sys.argv[2].lower() + + filtered_systems = {} + for system in systems: + lowered_system = system.lower() + lowered_system_name = systems[system]['name'].lower() + + if ((lowered_name == lowered_system or lowered_name == lowered_system_name) or + (sys.argv[1] == "--filter" and (lowered_name in lowered_system or lowered_name in lowered_system_name))): + filtered_systems[system] = systems[system] + + if len(filtered_systems) == 0: + print("No system named {} found".format(sys.argv[2])) + exit(1) + + if displayMissingBios(filtered_systems, checkBios(filtered_systems, prefix)): + exit(2) diff --git a/packages/jelos/sources/scripts/batocera-wifi b/packages/jelos/sources/scripts/batocera-wifi new file mode 100755 index 000000000..71d04ebe1 --- /dev/null +++ b/packages/jelos/sources/scripts/batocera-wifi @@ -0,0 +1,38 @@ +#!/bin/bash + +ACTION=$1 +shift + +do_help() { + echo "${1} scanlist" >&2 + echo "${1} list" >&2 +} + +remove_last_word() { + echo "${@:1:$#-1}" +} + +do_list() { + connmanctl services | while read; do + if [[ $REPLY == *'wifi_'* ]]; then + WITHOUT_PREFIX=${REPLY:4} + echo $(remove_last_word $WITHOUT_PREFIX) + fi + done +} + +do_scanlist() { + connmanctl scan wifi >/dev/null 2>/dev/null + do_list +} + +case "${ACTION}" in + "list") + do_list + ;; + "scanlist") + do_scanlist + ;; + *) + do_help "${0}" +esac diff --git a/packages/jelos/sources/scripts/bezels.sh b/packages/jelos/sources/scripts/bezels.sh new file mode 100755 index 000000000..e2c580c83 --- /dev/null +++ b/packages/jelos/sources/scripts/bezels.sh @@ -0,0 +1,217 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present SumavisionQ5 (https://github.com/SumavisionQ5) +# Modifications by Shanti Gilbert (https://github.com/shantigilbert) + +PLATFORM="$1" + +ROMNAME=$(basename "${2%.*}") +RACONFIG="/storage/.config/retroarch/retroarch.cfg" +OPACITY="1.000000" +AR_INDEX="23" +BEZELDIR="/storage/roms/bezels" +INIFILE="/storage/.config/distribution/bezels/settings.ini" +DEFAULT_BEZEL="false" + +case $PLATFORM in + "arcade"|"fba"|"fbn"|"neogeo"|"mame"|cps*) + PLATFORM="ARCADE" + ;; + "default") + if [ -f "/storage/.config/bezels_enabled" ]; then + clear_bezel + sed -i '/input_overlay = "/d' $RACONFIG + rm "/storage/.config/bezels_enabled" + fi + exit 0 + ;; + "RETROPIE") + # fbterm does not need bezels + exit 0 + ;; +esac + + if [ ! -f "/storage/.config/bezels_enabled" ]; then + touch /storage/.config/bezels_enabled + fi + +# we make sure the platform is all lowercase +PLATFORM=${PLATFORM,,} + +# if a backup does not exists make a copy of retroarch.cfg so we can return to it when we disable bezels + # for future use...maybe + #if [ ! -f "$RACONFIG.org" ]; then + # cp "$RACONFIG" "$RACONFIG.org" + #fi + +# bezelmap.cfg in $BEZELDIR/ is to share bezels between arcade clones and parent. +BEZELMAP="/storage/.config/distribution/bezels/arcademap.cfg" +BZLNAME=$(sed -n "/"$PLATFORM"_"$ROMNAME" = /p" "$BEZELMAP") +BZLNAME="${BZLNAME#*\"}" +BZLNAME="${BZLNAME%\"*}" +OVERLAYDIR1=$(find $BEZELDIR/$PLATFORM -maxdepth 1 -iname "$ROMNAME*.cfg" | sort -V | head -n 1) +[ ! -z "$BZLNAME" ] && OVERLAYDIR2=$(find $BEZELDIR/$PLATFORM -maxdepth 1 -iname "$BZLNAME*.cfg" | sort -V | head -n 1) +OVERLAYDIR3="$BEZELDIR/$PLATFORM/default.cfg" + +clear_bezel() { + sed -i '/aspect_ratio_index = "/d' $RACONFIG + sed -i '/custom_viewport_width = "/d' $RACONFIG + sed -i '/custom_viewport_height = "/d' $RACONFIG + sed -i '/custom_viewport_x = "/d' $RACONFIG + sed -i '/custom_viewport_y = "/d' $RACONFIG + sed -i '/video_scale_integer = "/d' $RACONFIG + sed -i '/input_overlay_opacity = "/d' $RACONFIG + echo 'video_scale_integer = "false"' >> $RACONFIG + echo 'input_overlay_opacity = "0.150000"' >> $RACONFIG + } + +set_bezel() { +# $OPACITY: input_overlay_opacity +# $AR_INDEX: aspect_ratio_index +# $1: custom_viewport_width +# $2: custom_viewport_height +# $3: ustom_viewport_x +# $4: custom_viewport_y +# $5: video_scale_integer +# $6: video_scale + + clear_bezel + sed -i '/input_overlay_opacity = "/d' $RACONFIG + sed -i "1i input_overlay_opacity = \"$OPACITY\"" $RACONFIG + sed -i "2i aspect_ratio_index = \"$AR_INDEX\"" $RACONFIG + sed -i "3i custom_viewport_width = \"$1\"" $RACONFIG + sed -i "4i custom_viewport_height = \"$2\"" $RACONFIG + sed -i "5i custom_viewport_x = \"$3\"" $RACONFIG + sed -i "6i custom_viewport_y = \"$4\"" $RACONFIG + sed -i "7i video_scale_integer = \"$5\"" $RACONFIG + } + +check_overlay_dir() { + +# The bezel will be searched and used in following order: +# 1.$OVERLAYDIR1 will be used, if it does not exist, then +# 2.$OVERLAYDIR2 will be used, if it does not exist, then +# 3.$OVERLAYDIR2 platform default bezel as "$BEZELDIR/"$PLATFORM"/default.cfg\" will be used. +# 4.Default bezel at "$BEZELDIR/default.cfg\" will be used. + + sed -i '/input_overlay = "/d' $RACONFIG + + if [ -f "$OVERLAYDIR1" ]; then + echo -e "input_overlay = \""$OVERLAYDIR1"\"\n" >> $RACONFIG + elif [ -f "$OVERLAYDIR2" ]; then + echo -e "input_overlay = \""$OVERLAYDIR2"\"\n" >> $RACONFIG + elif [ -f "$OVERLAYDIR3" ]; then + echo -e "input_overlay = \""$OVERLAYDIR3"\"\n" >> $RACONFIG + else + echo -e "input_overlay = \"$BEZELDIR/default.cfg\"\n" >> $RACONFIG + DEFAULT_BEZEL="true" + fi +} + +# Only 720P and 1080P can use bezels. For 480p/i and 576p/i we just delete bezel config. +hdmimode=$(cat /sys/class/display/mode) + +case $hdmimode in + 480*) + sed -i '/input_overlay = "/d' $RACONFIG + clear_bezel + ;; + 576*) + sed -i '/input_overlay = "/d' $RACONFIG + clear_bezel + ;; + 720p*) + + check_overlay_dir "$PLATFORM" + case "$PLATFORM" in + "gba") + set_bezel "467" "316" "405" "190" "false" + ;; + "gamegear") + set_bezel "780" "580" "245" "70" "false" + ;; + "gb") + set_bezel "429" "380" "420" "155" "false" + ;; + "gbc") + set_bezel "430" "380" "425" "155" "false" + ;; + "ngp") + set_bezel "461" "428" "407" "145" "false" + ;; + "ngpc") + set_bezel "460" "428" "407" "145" "false" + ;; + "wonderswan") + set_bezel "645" "407" "325" "150" "false" + ;; + "wonderswancolor") + set_bezel "643" "405" "325" "150" "false" + ;; + *) + # delete aspect_ratio_index to make sure video is expanded fullscreen. Only certain handheld platforms need custom_viewport. + clear_bezel + sed -i '/input_overlay_opacity = "/d' $RACONFIG + sed -i "1i input_overlay_opacity = \"$OPACITY\"" $RACONFIG + ;; + esac + ;; + # For Amlogic TV box, the following resolution is 1080p/i. + 1080*) + check_overlay_dir "$PLATFORM" + case "$1" in + "gba") + set_bezel "698" "472" "609" "288" "false" + ;; + "gamegear") + set_bezel "1160" "850" "380" "120" "false" + ;; + "gb") + set_bezel "625" "565" "645" "235" "false" + ;; + "gbc") + set_bezel "625" "565" "645" "235" "false" + ;; + "ngp") + set_bezel "700" "635" "610" "220" "false" + ;; + "ngpc") + set_bezel "700" "640" "610" "215" "false" + ;; + "wonderswan") + set_bezel "950" "605" "490" "225" "false" + ;; + "wonderswancolor") + set_bezel "950" "605" "490" "225" "false" + ;; + *) + clear_bezel + sed -i '/input_overlay_opacity = "/d' $RACONFIG + sed -i "1i input_overlay_opacity = \"$OPACITY\"" $RACONFIG + ;; + esac + ;; +esac + + if [ "$DEFAULT_BEZEL" = "true" ]; then + set_bezel "1427" "1070" "247" "10" "false" + fi + +# If we disable bezel in setting.ini for certain platform, we just delete bezel config. +Bezel=$(sed -n "/"$PLATFORM"_Bezel = /p" $INIFILE) +Bezel="${Bezel#*\"}" +Bezel="${Bezel%\"*}" +if [ "$Bezel" = "OFF" ]; then +sed -i '/input_overlay = "/d' $RACONFIG +fi + +# Note: +# 1. Different handheld platforms have different bezels, they may need different viewport value even for same platform. +# So, I think this script should be stored in $BEZELDIR/ or some place wich can be modified by users. +# 2. For Arcade games, I created a bezelmap.cfg in $BEZELDIR/ in order to share bezels between arcade clones and parent. +# In fact, ROMs of other platforms can share certain bezel if you write mapping relationship in bezelmap.cfg. +# 3. I modified es_systems.cfg to set $1 as platfrom for all platfrom. +# For some libretro core such as /usr/bin/sx05reRunEmu.sh LIBRETRO scummvm %ROM%, $1 not right platform value, +# you may need some tunings on them. +# 4. I am a Linux noob, so the codes are a mess. Sorry for that:) diff --git a/packages/jelos/sources/scripts/brightness b/packages/jelos/sources/scripts/brightness new file mode 100755 index 000000000..f5ea4b91c --- /dev/null +++ b/packages/jelos/sources/scripts/brightness @@ -0,0 +1,64 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +MIN=1 +MAX=100 +STEP=1 +if [[ -n "$2" ]]; then + STEP=$2 +fi + +# Ensure set_setting exists in all contexts +if ! type set_setting &>/dev/null +then + source /etc/profile +fi + +if [ ! -f /sys/class/backlight/backlight/brightness ] +then + echo "ERROR: There is no BRIGHTNESS object to manage." + exit 1 +fi + +stepUp() { + getBrightness + MYBRIGHTNESS=$? + NEWBRIGHTNESS=$((${MYBRIGHTNESS}+${STEP})) + if (( ${NEWBRIGHTNESS} > ${MAX} )) + then + NEWBRIGHTNESS=${MAX} + fi + echo "${NEWBRIGHTNESS}" > /sys/class/backlight/backlight/brightness + set_setting system.brightness ${NEWBRIGHTNESS} +} + +stepDown() { + getBrightness + MYBRIGHTNESS=$? + NEWBRIGHTNESS=$((${MYBRIGHTNESS}-${STEP})) + if (( ${NEWBRIGHTNESS} < ${MIN} )) + then + NEWBRIGHTNESS=${MIN} + fi + echo "${NEWBRIGHTNESS}" > /sys/class/backlight/backlight/brightness + set_setting system.brightness ${NEWBRIGHTNESS} +} +getBrightness() { + local BRIGHTNESS=$(cat /sys/class/backlight/backlight/brightness) + return ${BRIGHTNESS} +} + + +case ${1} in + "up") + stepUp ${BRIGHTNESS} + ;; + "down") + stepDown ${BRIGHTNESS} + ;; + *) + getBrightness + echo $? + ;; +esac diff --git a/packages/jelos/sources/scripts/emustation-config b/packages/jelos/sources/scripts/emustation-config new file mode 100755 index 000000000..761b1ccf8 --- /dev/null +++ b/packages/jelos/sources/scripts/emustation-config @@ -0,0 +1,44 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +# Source predefined functions and variables +. /etc/profile + +TZ=$(get_setting system.timezone) +echo -n "TIMEZONE=$TZ" > /storage/.cache/timezone +systemctl restart tz-data.service + +# create charmap used for translations +locale=$(get_setting system.language) +if [ $? == "0" ] +then + charmap="UTF-8" + lang="${locale}.${charmap}" + locpath="/storage/.config/emulationstation/locale" + i18npath="$locpath/i18n" + localepath="$locpath/$lang" + + if [ ! -d $localepath ]; then + export I18NPATH=$i18npath + maxperf + /usr/bin/localedef -f $charmap -i $locale $localepath + normperf + fi + + export LOCPATH=$locpath + export LANG=$lang + export LANGUAGE=$lang + systemctl import-environment LANG + systemctl import-environment LOCPATH + systemctl import-environment I18NPATH + systemctl import-environment LANGUAGE +fi + +if [[ ! -f "/storage/.newcfg" ]]; then + touch /storage/.newcfg +fi + +exit 0 diff --git a/packages/jelos/sources/scripts/error.sh b/packages/jelos/sources/scripts/error.sh new file mode 100755 index 000000000..e452ae30e --- /dev/null +++ b/packages/jelos/sources/scripts/error.sh @@ -0,0 +1,19 @@ +#!/usr/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC + +. /etc/profile + +clear >/dev/console +if [ -n "$1" ] +then + text_viewer -w -e -t "BIOS ERROR" -m "$*" +else + ERROR=$(tail -n 25 /var/log/es_launch_stderr.log) + if [ !-z "${ERROR}" ]; + then + text_viewer -w -e -t ERROR -m "${ERROR}" + fi +fi + +clear >/dev/console diff --git a/packages/jelos/sources/scripts/factoryreset b/packages/jelos/sources/scripts/factoryreset new file mode 100755 index 000000000..ea1520a84 --- /dev/null +++ b/packages/jelos/sources/scripts/factoryreset @@ -0,0 +1,20 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022 Fewtarius (https://github.com/fewtarius) + +case "${1}" in + "retroarch") + rm -f /storage/.config/retroarch/retroarch.cfg + cp -rf /usr/config/retroarch/retroarch.cfg /storage/.config/retroarch/retroarch.cfg + ;; + "ALL") + systemctl stop emustation + cd / + find /storage -mindepth 1 \( ! -regex '^/storage/.update.*' -a ! -regex '^/storage/roms.*' \) -delete + mkdir /storage/.config/ + sync + systemctl reboot + ;; +esac diff --git a/packages/jelos/sources/scripts/find.sh b/packages/jelos/sources/scripts/find.sh new file mode 100755 index 000000000..d363e3b2e --- /dev/null +++ b/packages/jelos/sources/scripts/find.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +find / -type d \( -path /var/media -o -path /storage/roms \) -prune -o -iname *${1}* -print diff --git a/packages/jelos/sources/scripts/getfilters b/packages/jelos/sources/scripts/getfilters new file mode 100755 index 000000000..800f12247 --- /dev/null +++ b/packages/jelos/sources/scripts/getfilters @@ -0,0 +1,10 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022 Fewtarius (https://github.com/fewtarius) + +find /usr/share/retroarch/filters/64bit/video/ -name '*.filt' -print0 | + while IFS= read -r -d '' line; do + echo ${line#/usr/share/retroarch/filters/64bit/video/}, +done diff --git a/packages/jelos/sources/scripts/getshaders b/packages/jelos/sources/scripts/getshaders new file mode 100755 index 000000000..79777471a --- /dev/null +++ b/packages/jelos/sources/scripts/getshaders @@ -0,0 +1,10 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022 Fewtarius (https://github.com/fewtarius) + +find /tmp/shaders -name '*.glslp' -print0 | + while IFS= read -r -d '' line; do + echo ${line#/tmp/shaders/}, +done diff --git a/packages/jelos/sources/scripts/jelos-info b/packages/jelos/sources/scripts/jelos-info new file mode 100755 index 000000000..0ada0565b --- /dev/null +++ b/packages/jelos/sources/scripts/jelos-info @@ -0,0 +1,77 @@ +#!/bin/bash + +source /etc/os-release + +### short version (for osd) +if test "$1" = "--short" +then + BATT=$(cat /sys/class/power_supply/{BAT,bat}*/uevent 2>/dev/null | grep -E "^POWER_SUPPLY_CAPACITY=" | sed -e s+'^POWER_SUPPLY_CAPACITY='++ | sort -rn | head -1) + DT=$(date +%H:%M) + if test -n "${BATT}" + then + echo "Battery: ${BATT}% - ${DT}" + else + echo "${DT}" + fi + exit 0 +fi +### + +### Fix this +V_OS=${NAME} + +TEST=$(ldd /usr/bin/emulationstation | grep 64) +if [ $? == 0 ] +then + V_OSARCH="aarch64" +else + V_OSARCH="arm" +fi + +V_CPUNB=$(grep -E $'^processor\t:' /proc/cpuinfo | wc -l) +V_CPUMODEL1=$(grep -E $'^model name\t:' /proc/cpuinfo | head -1 | sed -e s+'^model name\t: '++) +V_SYSTEM=$(uname -rs) +V_ARCH=$(uname -m) + +[[ "$V_CPUMODEL1" ]] || V_CPUMODEL1="${HW_CPU}" + +V_CPUFREQ=$(( $(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq) / 1000 )) +V_CPUMAXFREQ=$(( $(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq) / 1000 )) + +# battery +BATT=$(cat /sys/class/power_supply/{BAT,bat}*/uevent 2>/dev/null | grep -E "^POWER_SUPPLY_CAPACITY=" | sed -e s+'^POWER_SUPPLY_CAPACITY='++ | sort -rn | head -1) + +# PAD Battery +for PADBAT in /sys/class/power_supply/*/device/uevent +do + # HID devices only + PADNAME=$(grep -E '^HID_NAME=' "${PADBAT}" | sed -e s+'^HID_NAME='++) + if test -n "${PADNAME}" + then + # parent of parent / uevent + BATTUEVENT=$(dirname "${PADBAT}") + BATTUEVENT=$(dirname "${BATTUEVENT}")/uevent + BATT=$(grep -E "^POWER_SUPPLY_CAPACITY=" "${BATTUEVENT}" | sed -e s+'^POWER_SUPPLY_CAPACITY='++ | sort -rn | head -1) + echo "${PADNAME}: ${BATT}%" + fi +done + +# temperature +# Unit: millidegree Celsius +TEMPE=$(cat /sys/devices/virtual/thermal/thermal_zone*/temp 2>/dev/null | sort -rn | head -1 | sed -e s+"[0-9][0-9][0-9]$"++) + +echo "OPERATING SYSTEM: ${V_OS}" +echo "CPU: ${V_CPUMODEL1} (${V_CPUNB} Cores)" +if test -n "${TEMPE}" +then + echo "CPU TEMPERATURE: ${TEMPE}°" +fi +echo "CURRENT FREQUENCY: ${V_CPUFREQ}MHz" +echo "MAXIMUM FREQUENCY: ${V_CPUMAXFREQ}MHz" +echo "KERNEL: ${V_SYSTEM} (${V_ARCH})" +echo "OS ARCHITECTURE: ${V_OSARCH}" +echo "OS BUILD ID: ${BUILD_ID:0:7}" +if test -n "${BATT}" +then + echo "BATTERY: ${BATT}%" +fi diff --git a/packages/jelos/sources/scripts/manage_mpv.sh b/packages/jelos/sources/scripts/manage_mpv.sh new file mode 100755 index 000000000..1be673324 --- /dev/null +++ b/packages/jelos/sources/scripts/manage_mpv.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present ShantiGilbert, RedWolfTech, Fewtarius + +function sendkey() { + echo '{"command":["keypress", "'${1}'"]}' | socat - "/tmp/mpvsocket" +} + +case "$1" in + "pause") + sendkey "p" + ;; + "skip5s") + sendkey "RIGHT" + ;; + "back5s") + sendkey "LEFT" + ;; + "skip60s") + sendkey "UP" + ;; + "back60s") + sendkey "DOWN" + ;; + "quit") + sendkey "q" + ;; +esac + diff --git a/packages/jelos/sources/scripts/mpv_video.sh b/packages/jelos/sources/scripts/mpv_video.sh new file mode 100755 index 000000000..564cc1e75 --- /dev/null +++ b/packages/jelos/sources/scripts/mpv_video.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +/usr/bin/mpv --input-ipc-server=/tmp/mpvsocket "${1}" +exit 0 diff --git a/packages/jelos/sources/scripts/rr_audio.sh b/packages/jelos/sources/scripts/rr_audio.sh new file mode 100755 index 000000000..5eb995370 --- /dev/null +++ b/packages/jelos/sources/scripts/rr_audio.sh @@ -0,0 +1,157 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking@gmail.com) +# Copyright (C) 2022-present Fewtarius + +. /etc/profile + +# Set common paths and defaults +export PULSE_RUNTIME_PATH=/run/pulse + RR_AUDIO_DEVICE="hw:$(get_setting audio_device)" + [ $RR_AUDIO_DEVICE = "hw:" ] && RR_PA_UDEV="true" || RR_PA_UDEV="false" + echo "Set-Audio: Using audio device $RR_AUDIO_DEVICE" + RR_PA_TSCHED="true" + RR_AUDIO_VOLUME=$(get_setting "audio.volume" 2>/dev/null) + MIXER="${DEVICE_AUDIO_MIXER}" + RR_AUDIO_BACKEND="PulseAudio" + + +pulseaudio_sink_load() { + + if [ ${RR_AUDIO_BACKEND} = "PulseAudio" ];then + systemctl restart pulseaudio + if [ "${RR_PA_TSCHED}" = "false" ]; then + TSCHED="tsched=0" + echo "Set-Audio: PulseAudio will disable timer-based audio scheduling" + else + TSCHED="tsched=1" + echo "Set-Audio: PulseAudio will enable timer-based audio scheduling" + fi + + if [ ! -z "$(pactl list modules short | grep module-null-sink)" ];then + if [ "${RR_PA_UDEV}" = "true" ]; then + pactl load-module module-udev-detect $TSCHED > /dev/null + pactl set-sink-volume "$(pactl info | grep 'Default Sink:' | cut -d ' ' -f 3)" ${RR_AUDIO_VOLUME}% + if [ ! -z "$(pactl list modules short | grep module-alsa-card)" ];then + echo "Set-Audio: PulseAudio module-udev-detect loaded, setting a volume of "${RR_AUDIO_VOLUME}"%" + echo "Set-Audio: PulseAudio will use sink "$(pactl list sinks short) + echo "Set-Audio: PulseAudio module-udev-detect failed to load" + fi + else + pactl load-module module-alsa-sink device="${RR_AUDIO_DEVICE}" name="temp_sink" ${TSCHED} > /dev/null + pactl set-sink-volume alsa_output.temp_sink ${RR_AUDIO_VOLUME}% + if [ ! -z "$(pactl list modules short | grep module-alsa-sink)" ];then + echo "Set-Audio: PulseAudio module-alsa-sink loaded, setting a volume of "${RR_AUDIO_VOLUME}"%" + echo "Set-Audio: PulseAudio will use sink "$(pactl list sinks short) + else + echo "Set-Audio: PulseAudio module-alsa-sink failed to load" + fi + fi + fi + fi +} + +# Unload PulseAudio sink +pulseaudio_sink_unload() { + + if [ ${RR_AUDIO_BACKEND} = "PulseAudio" ]; then + if [ "${RR_PA_UDEV}" = "true" ] && [ ! -z "$(pactl list modules short 2>/dev/null | grep module-alsa-card)" ]; then + pactl set-sink-volume "$(pactl info 2>/dev/null | grep 'Default Sink:' | cut -d ' ' -f 3)" ${RR_AUDIO_VOLUME}% >/dev/null 2>&1 + pactl unload-module module-udev-detect >/dev/null 2>&1 + pactl unload-module module-alsa-card >/dev/null 2>&1 + echo "Set-Audio: PulseAudio module-udev-detect unloaded" + elif [ "${RR_PA_UDEV}" = "false" ] && [ ! -z "$(pactl list modules short 2>/dev/null| grep module-alsa-sink)" ]; then + pactl set-sink-volume alsa_output.temp_sink ${RR_AUDIO_VOLUME}% >/dev/null 2>&1 + NUMBER="$(pactl list modules short 2>/dev/null | grep "name=temp_sink" | awk '{print $1;}')" + if [ -n "${NUMBER}" ]; then + pactl unload-module "${NUMBER}" >/dev/null 2>&1 + fi + echo "Set-Audio: PulseAudio module-alsa-sink unloaded" + else + echo "Set-Audio: neither the PulseAudio module module-alsa-card or module-alsa-sink was found. Nothing to unload" + fi + + # Restore ALSA Master volume to 100% + amixer -q set ${MIXER},0 ${RR_AUDIO_VOLUME}% unmute >/dev/null 2>&1 + echo "Set-Audio: ALSA mixer restore volume to ${RR_AUDIO_VOLUME}%" + fi + systemctl stop pulseaudio >/dev/null 2>&1 +} + +# Start FluidSynth +fluidsynth_service_start() { + + if [ ${RR_AUDIO_BACKEND} = "PulseAudio" ] && [ ! "$(systemctl is-active fluidsynth)" = "active" ]; then + systemctl start fluidsynth + if [ "$(systemctl is-active fluidsynth)" = "active" ]; then + echo "Set-Audio: FluidSynth service loaded successfully" + else + echo "Set-Audio: FluidSynth service failed to load" + fi + fi +} + +# Stop FluidSynth +fluidsynth_service_stop() { + + + if [ "$(systemctl is-active fluidsynth)" = "active" ]; then + systemctl stop fluidsynth + if [ ! "$(systemctl is-active fluidsynth)" = "active" ]; then + echo "Set-Audio: FluidSynth service successfully stopped" + else + echo "Set-Audio: FluidSynth service failed to stop" + fi + fi +} + +# SDL2: Set audio driver to Pulseaudio or ALSA +set_SDL_audiodriver() { + + if [ ${RR_AUDIO_BACKEND} = "PulseAudio" ]; then + export SDL_AUDIODRIVER=pulseaudio + else + export SDL_AUDIODRIVER=alsa + fi + echo "Set-Audio: SDL2 set environment variable SDL_AUDIODRIVER="${SDL_AUDIODRIVER} +} + +# RETROARCH: Set audio & midi driver +set_RA_audiodriver() { + + RETROARCH_HOME=/storage/.config/retroarch + RETROARCH_CONFIG=${RETROARCH_HOME}/retroarch.cfg + + if [ -f ${RETROARCH_CONFIG} ]; then + if [ ${RR_AUDIO_BACKEND} = "PulseAudio" ]; then + sed -e "s/audio_driver = \"alsathread\"/audio_driver = \"pulse\"/" -i ${RETROARCH_CONFIG} + sed -e "s/midi_driver = \"null\"/midi_driver = \"alsa\"/" -i ${RETROARCH_CONFIG} + sed -e "s/midi_output = \"Off\"/midi_output = \"FluidSynth\"/" -i ${RETROARCH_CONFIG} + echo "Set-Audio: Retroarch force audio driver to PulseAudio & MIDI output to FluidSynth" + else + sed -e "s/audio_driver = \"pulse\"/audio_driver = \"alsathread\"/" -i ${RETROARCH_CONFIG} + sed -e "s/midi_driver = \"alsa\"/midi_driver = \"null\"/" -i ${RETROARCH_CONFIG} + sed -e "s/midi_output = \"FluidSynth\"/midi_output = \"Off\"/" -i ${RETROARCH_CONFIG} + echo "Set-Audio: Retroarch force audio driver to ALSA & disable MIDI output" + fi + fi +} + +case "$1" in + "pulseaudio") + pulseaudio_sink_unload + fluidsynth_service_stop + pulseaudio_sink_load + ;; + "fluidsynth") + pulseaudio_sink_unload + pulseaudio_sink_load + fluidsynth_service_stop + fluidsynth_service_start + ;; + "alsa") + pulseaudio_sink_unload + fluidsynth_service_stop + RR_AUDIO_BACKEND="alsa" + ;; +esac + set_SDL_audiodriver diff --git a/packages/jelos/sources/scripts/runemu.sh b/packages/jelos/sources/scripts/runemu.sh new file mode 100755 index 000000000..48e6b5bc2 --- /dev/null +++ b/packages/jelos/sources/scripts/runemu.sh @@ -0,0 +1,489 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +# Source predefined functions and variables +. /etc/profile +. /etc/os-release + +# Command line schema +# $1 = Game/Port +# $2 = Platform +# $3 = Core +# $4 = Emulator + +### Define the variables used throughout the script +BTENABLED=$(get_setting bluetooth.enabled) +CFG="/storage/.emulationstation/es_settings.cfg" +VERBOSE=false +LOGSDIR="/var/log" +LOGFILE="exec.log" +TBASH="/usr/bin/bash" +RATMPCONF="/storage/.config/retroarch/retroarch.cfg" +RAAPPENDCONF="/tmp/raappend.cfg" +NETPLAY="No" +SHADERTMP="/tmp/shader" +OUTPUT_LOG="${LOGSDIR}/${LOGFILE}" +### Do not change the variables below as it may break things. +MYNAME=$(basename "$0") + +### Enable logging +if [ "$(get_es_setting string LogLevel)" == "minimal" ]; then + LOG=false +else + LOG=true + VERBOSE=true +fi + +arguments="$@" +PLATFORM="${arguments##*-P}" # read from -P onwards +PLATFORM="${PLATFORM%% *}" # until a space is found +CORE="${arguments##*--core=}" # read from --core= onwards +CORE="${CORE%% *}" # until a space is found +EMULATOR="${arguments##*--emulator=}" # read from --emulator= onwards +EMULATOR="${EMULATOR%% *}" # until a space is found +ROMNAME="$1" +BASEROMNAME=${ROMNAME##*/} +GAMEFOLDER="${ROMNAME//${BASEROMNAME}}" + + +### Determine if we're running a Libretro core and append the libretro suffix +if [[ $EMULATOR = "retroarch" ]]; then + EMU="${CORE}_libretro" + RETROARCH="yes" +elif [[ $EMULATOR = "mupen64plussa" ]]; then + EMU="M64P" +else + EMU="${CORE}" +fi + +# freej2me needs the JDK to be downloaded on the first run +if [[ ${EMU} == "freej2me_libretro" ]]; then + /usr/bin/freej2me.sh + JAVA_HOME='/storage/jdk' + export JAVA_HOME + PATH="$JAVA_HOME/bin:$PATH" + export PATH +fi + +# easyrpg needs runtime files to be downloaded on the first run +if [[ ${EMU} == "easyrpg_libretro" ]]; then + /usr/bin/easyrpg.sh +fi + +### If we're running a port, assume it's libretro +### Re-evaluate as not all ports may be libretro cores +### perhaps rewrite to use ^ functionality +[[ ${PLATFORM} = "ports" ]] && RETROARCH="yes" + +# check if we started as host for a game +if [[ "$arguments" == *"--host"* ]]; then + NETPLAY="${arguments##*--host}" # read from --host onwards + NETPLAY="${NETPLAY%%--nick*}" # until --nick is found + NETPLAY="--host $NETPLAY --nick" +fi + +# check if we are trying to connect to a client on netplay +if [[ "$arguments" == *"--connect"* ]]; then + NETPLAY="${arguments##*--connect}" # read from --connect onwards + NETPLAY="${NETPLAY%%--nick*}" # until --nick is found + NETPLAY="--connect $NETPLAY --nick" +fi + +### Set the performance mode +if [ $(get_setting "maxperf" "${PLATFORM}" "${ROMNAME##*/}") == "0" ]; then + normperf & + EMUPERF="${SLOW_CORES}" +else + maxperf & + EMUPERF="${FAST_CORES}" +fi + +# Disable netplay by default +set_setting "netplay.client.ip" "disable" +set_setting "netplay.client.port" "disable" + +### Function Library + +function log() { + if [ ${LOG} == true ] + then + if [[ ! -d "$LOGSDIR" ]] + then + mkdir -p "$LOGSDIR" + fi + echo "${MYNAME}: $1" 2>&1 | tee -a ${LOGSDIR}/${LOGFILE} + else + echo "${MYNAME}: $1" + fi +} + +function loginit() { + if [ ${LOG} == true ] + then + if [ -e ${LOGSDIR}/${LOGFILE} ] + then + rm -f ${LOGSDIR}/${LOGFILE} + fi + cat <${LOGSDIR}/${LOGFILE} +Emulation Run Log - Started at $(date) + +ARG1: $1 +ARG2: $2 +ARG3: $3 +ARG4: $4 +ARGS: $* +PLATFORM: $PLATFORM +ROM NAME: ${ROMNAME} +BASE ROM NAME: ${ROMNAME##*/} +USING CONFIG: ${RATMPCONF} +USING APPENDCONFIG : ${RAAPPENDCONF} + +EOF + else + log "Emulation Run Log - Started at $(date)" + fi +} + +function quit() { + $VERBOSE && log "Cleaning up and exiting" + bluetooth enable + jslisten stop + clear_screen + ${TBASH} /usr/bin/show_splash exit + normperf + set_audio default + exit $1 +} + +function clear_screen() { + $VERBOSE && log "Clearing screen" + clear >/dev/console +} + +function bluetooth() { + if [ "$1" == "disable" ] + then + $VERBOSE && log "Disabling BT" + if [[ "$BTENABLED" == "1" ]] + then + NPID=$(pgrep -f batocera-bluetooth-agent) + if [[ ! -z "$NPID" ]]; then + kill "$NPID" + fi + fi + elif [ "$1" == "enable" ] + then + $VERBOSE && log "Enabling BT" + if [[ "$BTENABLED" == "1" ]] + then + systemd-run batocera-bluetooth-agent + fi + fi +} + +function setaudio() { + $VERBOSE && log "Setting up audio" + AUDIO_DEVICE="hw:$(get_setting audio_device)" + if [ $AUDIO_DEVICE = "hw:" ] + then + AUDIO_DEVICE="hw:0,0" + fi + sed -i "s|pcm \"hw:.*|pcm \"${AUDIO_DEVICE}\"|" /storage/.config/asound.conf + set_audio alsa +} + +### Main Screen Turn On + +loginit "$1" "$2" "$3" "$4" +clear_screen +bluetooth disable +jslisten stop + +### Per emulator/core configurations +if [ -z ${RETROARCH} ] +then + $VERBOSE && log "Configuring for a non-libretro emulator" + case ${PLATFORM} in + "atarist") + if [ "$EMU" = "HATARISA" ] + then + jslisten set "hatari" + RUNTHIS='${TBASH} /usr/bin/hatari.start "${ROMNAME}"' + fi + ;; + "openbor") + jslisten set "OpenBOR" + RUNTHIS='${TBASH} /usr/bin/openbor.sh "${ROMNAME}"' + ;; + "setup") + RUNTHIS='${TBASH} "${ROMNAME}"' + ;; + "mame"|"arcade") + jslisten set "advmame" + if [ "$EMU" = "AdvanceMame" ] + then + RUNTHIS='${TBASH} /usr/bin/advmame.sh "${ROMNAME}"' + fi + ;; + "nds") + jslisten set "drastic" + RUNTHIS='${TBASH} /usr/bin/drastic.sh "${ROMNAME}"' + ;; + "pico-8") + jslisten set "pico8_dyn" + RUNTHIS='${TBASH} /usr/bin/pico-8.sh "${ROMNAME}"' + ;; + "ecwolf") + jslisten set "ecwolf" + if [ "$EMU" = "ecwolf" ] + then + RUNTHIS='${TBASH} /usr/bin/ecwolf.sh "${ROMNAME}"' + fi + ;; + "doom") + if [ "$EMU" = "lzdoom" ] + then + jslisten set "lzdoom" + RUNTHIS='${TBASH} /usr/bin/lzdoom.sh "${ROMNAME}"' + elif [ "$EMU" = "gzdoom" ] + then + jslisten set "gzdoom" + RUNTHIS='${TBASH} /usr/bin/gzdoom.sh "${ROMNAME}"' + fi + ;; + "build") + if [ "$EMU" = "raze" ] + then + jslisten set "raze" + RUNTHIS='${TBASH} /usr/bin/raze.sh "${ROMNAME}"' + fi + ;; + "solarus") + if [ "$EMU" = "solarus" ] + then + jslisten set "solarus-run" + RUNTHIS='${TBASH} /usr/bin/solarus.sh "${ROMNAME}"' + fi + ;; + "n64") + jslisten set "mupen64plus" + if [ "$EMU" = "M64P" ] + then + RUNTHIS='${TBASH} /usr/bin/m64p.sh "${CORE}" "${ROMNAME}"' + fi + ;; + "amiga"|"amigacd32") + jslisten set "amiberry" + if [ "$EMU" = "AMIBERRY" ] + then + RUNTHIS='${TBASH} /usr/bin/amiberry.start "${ROMNAME}"' + fi + ;; + "scummvm") + jslisten set "scummvm" + RUNTHIS='${TBASH} /usr/bin/scummvm.start sa "${ROMNAME}"' + ;; + "daphne") + jslisten set "hypseus" + if [ "$EMU" = "HYPSEUS" ] + then + RUNTHIS='${TBASH} /usr/bin/hypseus.start.sh "${ROMNAME}"' + fi + ;; + "pc") + jslisten set "dosbox dosbox-x" + if [ "$EMU" = "DOSBOXSDL2" ] + then + RUNTHIS='${TBASH} /usr/bin/dosbox.start -conf "${GAMEFOLDER}dosbox-SDL2.conf"' + elif [ "$EMU" = "DOSBOX-X" ] + then + RUNTHIS='${TBASH} /usr/bin/dosbox-x.start -conf "${GAMEFOLDER}dosbox-SDL2.conf"' + fi + ;; + "psp"|"pspminis") + jslisten set "PPSSPPSDL" + if [ "$EMU" = "PPSSPPSDL" ] + then + RUNTHIS='${TBASH} /usr/bin/ppsspp.sh "${ROMNAME}"' + fi + ;; + "neocd") + jslisten set "retroarch" + if [ "$EMU" = "fbneo" ] + then + RUNTHIS='/usr/bin/retroarch -L /tmp/cores/fbneo_libretro.so --subsystem neocd --config ${RATMPCONF} --appendconfig ${RAAPPENDCONF} "${ROMNAME}"' + fi + ;; + "mplayer") + jslisten set "mpv" + RUNTHIS='${TBASH} /usr/bin/mpv_video.sh "${ROMNAME}"' + ;; + "shell") + RUNTHIS='${TBASH} "${ROMNAME}"' + ;; + esac +else + $VERBOSE && log "Configuring for a libretro core" + + ### Set jslisten to kill the appropriate retroarch + jslisten set "retroarch retroarch32" + setaudio alsa + + ### Check if we need retroarch 32 bits or 64 bits + RABIN="retroarch" + if [[ "${CORE}" =~ "pcsx_rearmed" ]] || [[ "${CORE}" =~ "parallel_n64" ]] + then + export LD_LIBRARY_PATH="/usr/lib32" + RABIN="retroarch32" + fi + + # Platform specific configurations + case ${PLATFORM} in + "doom") + # EXT can be wad, WAD, iwad, IWAD, pwad, PWAD or doom + EXT=${ROMNAME#*.} + + # If its not a simple wad (extension .doom) read the file and parse the data + if [ ${EXT} == "doom" ]; then + dos2unix "${1}" + while IFS== read -r key value; do + if [ "$key" == "IWAD" ]; then + ROMNAME="$value" + fi + done < "${1}" + fi + ;; + esac + + RUNTHIS='${EMUPERF} /usr/bin/${RABIN} -L /tmp/cores/${EMU}.so --config ${RATMPCONF} --appendconfig ${RAAPPENDCONF} "${ROMNAME}"' + CONTROLLERCONFIG="${arguments#*--controllers=*}" + + if [[ "$arguments" == *"-state_slot"* ]]; then + CONTROLLERCONFIG="${CONTROLLERCONFIG%% -state_slot*}" # until -state is found + SNAPSHOT="${arguments#*-state_slot *}" # -state_slot x + SNAPSHOT="${SNAPSHOT%% -*}" + if [[ "$arguments" == *"-autosave"* ]]; then + CONTROLLERCONFIG="${CONTROLLERCONFIG%% -autosave*}" # until -autosave is found + AUTOSAVE="${arguments#*-autosave *}" # -autosave x + AUTOSAVE="${AUTOSAVE%% -*}" + else + AUTOSAVE="" + fi + else + CONTROLLERCONFIG="${CONTROLLERCONFIG%% --*}" # until a -- is found + SNAPSHOT="" + AUTOSAVE="" + fi + +# CORE=${EMU%%_*} + + ### Configure netplay + if [[ ${NETPLAY} != "No" ]]; then + NETPLAY_NICK=$(get_setting netplay.nickname) + [[ -z "$NETPLAY_NICK" ]] && NETPLAY_NICK="351ELEC" + + if [[ "${NETPLAY}" == *"connect"* ]]; then + NETPLAY_PORT="${arguments##*--port }" # read from -netplayport onwards + NETPLAY_PORT="${NETPLAY_PORT%% *}" # until a space is found + NETPLAY_IP="${arguments##*--connect }" # read from -netplayip onwards + NETPLAY_IP="${NETPLAY_IP%% *}" # until a space is found + set_setting "netplay.client.ip" "${NETPLAY_IP}" + set_setting "netplay.client.port" "${NETPLAY_PORT}" + RUNTHIS=$(echo ${RUNTHIS} | sed "s|--config|--connect ${NETPLAY_IP}\|${NETPLAY_PORT} --nick ${NETPLAY_NICK} --config|") + else + RUNTHIS=$(echo ${RUNTHIS} | sed "s|--config|${NETPLAY} --nick ${NETPLAY_NICK} --config|") + fi + + fi + + # Platform specific configurations + case ${PLATFORM} in + "atomiswave") + rm ${ROMNAME}.nvmem* + ;; + "ports") + PORTCORE="${arguments##*-C}" # read from -C onwards + EMU="${PORTCORE%% *}_libretro" # until a space is found + PORTSCRIPT="${arguments##*-SC}" # read from -SC onwards + ;; + "scummvm") + GAMEDIR=$(cat "${ROMNAME}" | awk 'BEGIN {FS="\""}; {print $2}') + cd "${GAMEDIR}" + RUNTHIS='${TBASH} /usr/bin/scummvm.start libretro .' + ;; + esac +fi + +if [ -e "${SHADERTMP}" ] +then + rm -f "${SHADERTMP}" +fi + +if [[ ${PLATFORM} == "ports" ]]; then + (/usr/bin/setsettings.sh "${PLATFORM}" "${PORTSCRIPT}" "${CORE}" --controllers="${CONTROLLERCONFIG}" --autosave="${AUTOSAVE}" --snapshot="${SNAPSHOT}" >${SHADERTMP}) & +else + (/usr/bin/setsettings.sh "${PLATFORM}" "${ROMNAME}" "${CORE}" --controllers="${CONTROLLERCONFIG}" --autosave="${AUTOSAVE}" --snapshot="${SNAPSHOT}" >${SHADERTMP}) & +fi +SETSETTINGS_PID=$! + +clear_screen +$VERBOSE && log "Show splash screen" +# Show splash screen if enabled +SPL=$(get_setting splash.enabled) +[ "$SPL" -eq "1" ] && (${TBASH} /usr/bin/show_splash "${ROMNAME}") & + +### Wait for background jobs to complete before continuing. +wait ${SETSETTINGS_PID} #Don't wait for show splash + +### If setsettings wrote data in the background, grab it and assign it to SHADERSET +if [ -e "${SHADERTMP}" ] +then + SHADERSET=$(cat ${SHADERTMP}) + rm -f ${SHADERTMP} + $VERBOSE && log "Shader set to ${SHADERSET}" +fi + +if [[ ${SHADERSET} != 0 ]]; then + RUNTHIS=$(echo ${RUNTHIS} | sed "s|--config|${SHADERSET} --config|") +fi + +clear_screen +$VERBOSE && log "executing game: ${ROMNAME}" +$VERBOSE && log "script to execute: ${RUNTHIS}" +# If the rom is a shell script just execute it, useful for DOSBOX and ScummVM scan scripts +if [[ "${ROMNAME}" == *".sh" ]]; then + $VERBOSE && log "Executing shell script ${ROMNAME}" + "${ROMNAME}" &>>${OUTPUT_LOG} + ret_error=$? +else + $VERBOSE && log "Executing $(eval echo ${RUNTHIS})" + eval ${RUNTHIS} &>>${OUTPUT_LOG} + ret_error=$? +fi + +clear_screen + +$VERBOSE && log "Checking errors: ${ret_error} " +if [ "${ret_error}" == "0" ] +then + quit 0 +else + log "exiting with $ret_error" + + # Check for missing bios if needed + REQUIRESBIOS=(atari5200 atari800 atari7800 atarilynx colecovision amiga amigacd32 o2em intellivision pcengine pcenginecd pcfx fds segacd saturn dreamcast naomi atomiswave x68000 neogeo neogeocd msx msx2 sc-3000) + + (for e in "${REQUIRESBIOS[@]}"; do [[ "${e}" == "${PLATFORM}" ]] && exit 0; done) && RB=0 || RB=1 + if [ $RB == 0 ]; then + CBPLATFORM="${PLATFORM}" + [[ "${CBPLATFORM}" == "msx2" ]] && CBPLATFORM="msx" + [[ "${CBPLATFORM}" == "pcenginecd" ]] && CBPLATFORM="pcengine" + [[ "${CBPLATFORM}" == "amigacd32" ]] && CBPLATFORM="amiga" + check_bios "${CBPLATFORM}" "${CORE}" "${EMULATOR}" "${ROMNAME}" "${LOGSDIR}/${LOGFILE}" + fi + quit 1 +fi + diff --git a/packages/jelos/sources/scripts/setemu.sh b/packages/jelos/sources/scripts/setemu.sh new file mode 100755 index 000000000..e71d6a40a --- /dev/null +++ b/packages/jelos/sources/scripts/setemu.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +## workaround for ES performance with big conf files +## This is no longer in use! + +EE_CONF="/storage/.config/distribution/configs/emuoptions.conf" + +[ ! -f ${EE_CONF} ] && touch ${EE_CONF} + +case "$1" in +"set") + PAT=$(echo "$2" | sed -e 's|\"|\\"|g' | sed -e 's|\[|\\\[|g' | sed -e 's|\]|\\\]|g') + sed -i "/$PAT/d" "${EE_CONF}" + S2=${2} + S3=${3} + shift 2 + if [ "${S3}" != "auto" ]; then + [ ${S3} == "disable" ] && echo "#${S2}=" >> "${EE_CONF}" || echo "${S2}=${@}" >> "${EE_CONF}" + fi + ;; +"get") + PAT=$(echo ${2} | sed -e 's|\"|\\"|g' | sed -e 's|\[|\\\[|g' | sed -e 's|\]|\\\]|g' | sed -e 's|(|\\\(|g' | sed -e 's|)|\\\)|g') + PAT="^${PAT}=(.*)" + EES=$(cat "${EE_CONF}" | grep -oE "${PAT}") + echo "${EES##*=}" + ;; +esac diff --git a/packages/jelos/sources/scripts/setsettings.sh b/packages/jelos/sources/scripts/setsettings.sh new file mode 100755 index 000000000..d7d726546 --- /dev/null +++ b/packages/jelos/sources/scripts/setsettings.sh @@ -0,0 +1,734 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +# TODO: Set Atari800 to Atari5200 when neeeded / done? +# TODO: retroachivements / done? +# I use ${} for easier reading + +# IMPORTANT: This script should not return (echo) anything other than the shader if its set + +. /etc/profile +. /etc/os-release + +RETROACHIEVEMENTS=(arcade atari2600 atari7800 atarilynx colecovision famicom fbn fds gamegear gb gba gbah gbc gbch gbh genesis genh ggh intellivision mastersystem megacd megadrive megadrive-japan msx msx2 n64 neogeo neogeocd nes nesh ngp ngpc odyssey2 pcengine pcenginecd pcfx pokemini psp psx sega32x segacd sfc sg-1000 snes snesh snesmsu1 supergrafx supervision tg16 tg16cd vectrex virtualboy wonderswan wonderswancolor) +NOREWIND=(sega32x psx zxspectrum odyssey2 mame n64 dreamcast atomiswave naomi neogeocd saturn psp pspminis) +NORUNAHEAD=(psp sega32x n64 dreamcast atomiswave naomi neogeocd saturn) +# The following systems are listed as they don't need the Analogue D-Pad mode on RA +NOANALOGUE=(n64 psx wonderswan wonderswancolor psp pspminis dreamcast) +IS32BITCORE=(pcsx_rearmed parallel_n64) + +INDEXRATIOS=(4/3 16/9 16/10 16/15 21/9 1/1 2/1 3/2 3/4 4/1 9/16 5/4 6/5 7/9 8/3 8/7 19/12 19/14 30/17 32/9 config squarepixel core custom) +CONF="/storage/.config/distribution/configs/distribution.conf" +SOURCERACONF="/usr/config/retroarch/retroarch.cfg" +RACONF="/storage/.config/retroarch/retroarch.cfg" +RAAPPENDCONF="/tmp/raappend.cfg" +RACORECONF="/storage/.config/retroarch/retroarch-core-options.cfg" +TMP_BEZEL="/tmp/351elec-bezel.cfg" +SNAPSHOTS="/storage/roms/savestates" +PLATFORM=${1,,} +ROM="${2##*/}" +CORE=${3,,} +SHADERSET=0 +LOGSDIR="/var/log" +LOGFILE="exec.log" +EE_DEVICE=${HW_DEVICE} + +#Autosave +AUTOSAVE="$@" +AUTOSAVE="${AUTOSAVE#*--autosave=*}" +AUTOSAVE="${AUTOSAVE% --*}" + +#Snapshot +SNAPSHOT="$@" +SNAPSHOT="${SNAPSHOT#*--snapshot=*}" + +### Enable logging +if [ "$(get_es_setting string LogLevel)" == "minimal" ]; then + LOG=false +else + LOG=true + VERBOSE=true +fi + +function log() { + if [ ${LOG} == true ]; then + if [[ ! -d "$LOGSDIR" ]]; then + mkdir -p "$LOGSDIR" + fi + DATE=$(date +"%b %d %H:%M:%S") + echo "${DATE} ${MYNAME}: $1" 2>&1 >> ${LOGSDIR}/${LOGFILE} + fi +} + +## Create / delete raappend.cfg +echo -n > "${RAAPPENDCONF}" + +### Move operations to /tmp so we're not writing to the microSD slowing us down. +### Also test the file to ensure it's not 0 bytes which can happen if someone presses reset. +if [ ! -s ${RACONF} ]; then + log "Fix broken RA conf" + cp -f "${SOURCERACONF}" "${RACONF}" +fi + +if [ ! -d "${SNAPSHOTS}/${PLATFORM}" ]; then + mkdir -p "${SNAPSHOTS}/${PLATFORM}" +fi + +function doexit() { + log "Exiting.." + sync + exit 0 +} + +function get_setting() { + log "Get Settings function (${1})" + #We look for the setting on the ROM first, if not found we search for platform and lastly we search globally + escaped_rom_name=$(echo "${ROM}" | sed -E 's|([][])|\\\1|g') + PAT="s|^${PLATFORM}\[\"${escaped_rom_name}\"\][\.-]${1}=\(.*\)|\1|p" + EES=$(sed -n "${PAT}" "${CONF}" | head -1) + + if [ -z "${EES}" ]; then + PAT="s|^${PLATFORM}[\.-]${1}=\(.*\)|\1|p" + EES=$(sed -n "${PAT}" "${CONF}" | head -1) + fi + + if [ -z "${EES}" ]; then + PAT="s|^global[\.-].*${1}=\(.*\)|\1|p" + EES=$(sed -n "${PAT}" "${CONF}" | head -1) + fi + + [ -z "${EES}" ] && EES="false" +} + + +function array_contains () { + local array="$1[@]" + local seeking=$2 + local in=1 + for element in "${!array}"; do + if [[ $element == "$seeking" ]]; then + in=0 + break + fi + done + return $in +} + +## Logging +log "setsettings.sh" +log "Platform: ${PLATFORM}" +log "ROM: ${ROM}" +log "Core: ${CORE}" + +## +## Global Setting that have to stay in retroarch.cfg +## All setttings that should apply when retroarch is run as standalone +## + +### Wifi +## Cleanup old settings first +#sed -i "/wifi_enabled/d" ${RACONF} +## Get configuration from distribution.conf and set to retroarch.cfg +#if [ "$(get_setting wifi.enabled)" = "1" ]; then +# echo 'wifi_enabled = "true"' >> ${RACONF} +#else +# echo 'wifi_enabled = "false"' >> ${RACONF} +#fi + +# RA menu rgui, ozone, glui or xmb (fallback if everthing else fails) +# if empty (auto in ES) do nothing to enable configuration in RA +get_setting "retroarch.menu_driver" +if [ "${EES}" != "false" ]; then + # delete setting only if we set new ones + # therefore configuring in RA is still possible + sed -i "/menu_driver/d" ${RACONF} + sed -i "/menu_linear_filter/d" ${RACONF} + # Set new menu driver + if [ "${EES}" == "rgui" ]; then + # menu_liner_filter is only needed for rgui + echo 'menu_driver = "rgui"' >> ${RACONF} + echo 'menu_linear_filter = "true"' >> ${RACONF} + elif [ "${EES}" == "ozone" ]; then + echo 'menu_driver = "ozone"' >> ${RACONF} + elif [ "${EES}" == "glui" ]; then + echo 'menu_driver = "glui"' >> ${RACONF} + else + # play it save and set xmb if nothing else matches + echo 'menu_driver = "xmb"' >> ${RACONF} + fi +fi + + +## +## Global Settings that go into the temorary config file +## + +## FPS +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "showFPS" +[ "${EES}" == "1" ] && echo 'fps_show = "true"' >> ${RAAPPENDCONF} || echo 'fps_show = "false"' >> ${RAAPPENDCONF} + + +## RetroAchievements / Cheevos +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "retroachievements" +for i in "${!RETROACHIEVEMENTS[@]}"; do + if [[ "${RETROACHIEVEMENTS[$i]}" = "${PLATFORM}" ]]; then + if [ "${EES}" == "1" ]; then + echo 'cheevos_enable = "true"' >> ${RAAPPENDCONF} + get_setting "retroachievements.username" + echo "cheevos_username = \"${EES}\"" >> ${RAAPPENDCONF} + get_setting "retroachievements.password" + echo "cheevos_password = \"${EES}\"" >> ${RAAPPENDCONF} + + # retroachievements_hardcore_mode + get_setting "retroachievements.hardcore" + [ "${EES}" == "1" ] && echo 'cheevos_hardcore_mode_enable = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_hardcore_mode_enable = "false"' >> ${RAAPPENDCONF} + + # retroachievements_leaderboards + get_setting "retroachievements.leaderboards" + if [ "${EES}" == "enabled" ]; then + echo 'cheevos_leaderboards_enable = "true"' >> ${RAAPPENDCONF} + elif [ "${EES}" == "trackers only" ]; then + echo 'cheevos_leaderboards_enable = "trackers"' >> ${RAAPPENDCONF} + elif [ "${EES}" == "notifications only" ]; then + echo 'cheevos_leaderboards_enable = "notifications"' >> ${RAAPPENDCONF} + else + echo 'cheevos_leaderboards_enable = "false"' >> ${RAAPPENDCONF} + fi + + # retroachievements_verbose_mode + get_setting "retroachievements.verbose" + [ "${EES}" == "1" ] && echo 'cheevos_verbose_enable = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_verbose_enable = "false"' >> ${RAAPPENDCONF} + + # retroachievements_automatic_screenshot + get_setting "retroachievements.screenshot" + [ "${EES}" == "1" ] && echo 'cheevos_auto_screenshot = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_auto_screenshot = "false"' >> ${RAAPPENDCONF} + + # cheevos_richpresence_enable + get_setting "retroachievements.richpresence" + [ "${EES}" == "1" ] && echo 'cheevos_richpresence_enable = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_richpresence_enable = "false"' >> ${RAAPPENDCONF} + + # cheevos_challenge_indicators + get_setting "retroachievements.challengeindicators" + [ "${EES}" == "1" ] && echo 'cheevos_challenge_indicators = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_challenge_indicators = "false"' >> ${RAAPPENDCONF} + + # cheevos_test_unofficial + get_setting "retroachievements.testunofficial" + [ "${EES}" == "1" ] && echo 'cheevos_test_unofficial = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_test_unofficial = "false"' >> ${RAAPPENDCONF} + + # cheevos_badges_enable + get_setting "retroachievements.badges" + [ "${EES}" == "1" ] && echo 'cheevos_badges_enable = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_badges_enable = "false"' >> ${RAAPPENDCONF} + + # cheevos_start_active + get_setting "retroachievements.active" + [ "${EES}" == "1" ] && echo 'cheevos_start_active = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_start_active = "false"' >> ${RAAPPENDCONF} + + # cheevos_unlock_sound_enable + get_setting "retroachievements.soundenable" + [ "${EES}" == "1" ] && echo 'cheevos_unlock_sound_enable = "true"' >> ${RAAPPENDCONF} || echo 'cheevos_unlock_sound_enable = "false"' >> ${RAAPPENDCONF} + else + echo 'cheevos_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_username = ""' >> ${RAAPPENDCONF} + echo 'cheevos_password = ""' >> ${RAAPPENDCONF} + echo 'cheevos_hardcore_mode_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_leaderboards_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_verbose_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_test_unofficial = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_unlock_sound_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_auto_screenshot = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_badges_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_start_active = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_richpresence_enable = "false"' >> ${RAAPPENDCONF} + echo 'cheevos_challenge_indicators = "false"' >> ${RAAPPENDCONF} + fi + fi +done + +## Netplay +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "netplay" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'netplay = false' >> ${RAAPPENDCONF} +else + echo 'netplay = true' >> ${RAAPPENDCONF} + get_setting "netplay.mode" + NETPLAY_MODE=${EES} + # Security : hardcore mode disables save states, which would kill netplay + sed -i '/cheevos_hardcore_mode_enable =/d' ${RAAPPENDCONF} + echo 'cheevos_hardcore_mode_enable = "false"' >> ${RAAPPENDCONF} + + if [[ "${NETPLAY_MODE}" == "host" ]]; then + # Quite strangely, host mode requires netplay_mode to be set to false when launched from command line + echo 'netplay_mode = false' >> ${RAAPPENDCONF} + echo 'netplay_client_swap_input = false' >> ${RAAPPENDCONF} + get_setting "netplay.port" + echo "netplay_ip_port = ${EES}" >> ${RAAPPENDCONF} + elif [[ "${NETPLAY_MODE}" == "client" ]]; then + # But client needs netplay_mode = true ... bug ? + echo 'netplay_mode = true' >> ${RAAPPENDCONF} + get_setting "netplay.client.ip" + echo "netplay_ip_address = ${EES}" >> ${RAAPPENDCONF} + get_setting "netplay.client.port" + echo "netplay_ip_port = ${EES}" >> ${RAAPPENDCONF} + echo 'netplay_client_swap_input = true' >> ${RAAPPENDCONF} + fi # Host or Client + + # relay + get_setting "netplay.relay" + if [[ ! -z "${EES}" && "${EES}" != "false" ]]; then + echo 'netplay_use_mitm_server = true' >> ${RAAPPENDCONF} + echo "netplay_mitm_server = ${EES}" >> ${RAAPPENDCONF} + else + echo 'netplay_use_mitm_server = false' >> ${RAAPPENDCONF} + # sed -i "/netplay_mitm_server/d" ${RACONF} + fi + + get_setting "netplay.frames" + echo "netplay_delay_frames = ${EES}" >> ${RAAPPENDCONF} + get_setting "netplay.nickname" + echo "netplay_nickname = ${EES}" >> ${RAAPPENDCONF} + # spectator mode + get_setting "netplay.spectator" + [ "${EES}" == "1" ] && echo 'netplay_spectator_mode_enable = true' >> ${RAAPPENDCONF} || echo 'netplay_spectator_mode_enable = false' >> ${RAAPPENDCONF} + get_setting "netplay_public_announce" + [ "${EES}" == "1" ] && echo 'netplay_public_announce = true' >> ${RAAPPENDCONF} || echo 'netplay_public_announce = false' >> ${RAAPPENDCONF} +fi + +## AI Translation Service +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "ai_service_enabled" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'ai_service_enable = "false"' >> ${RAAPPENDCONF} +else + # Translation table to get the values RA needs + declare -A LangCodes=( ["false"]="0" + ["En"]="1" + ["Fr"]="3" + ["Pt"]="49" + ["De"]="5" + ["El"]="30" + ["Es"]="2" + ["Cs"]="8" + ["Da"]="9" + ["Hr"]="11" + ["Hu"]="35" + ["It"]="4" + ["Ja"]="6" + ["Ko"]="12" + ["Nl"]="7" + ["Nn"]="46" + ["Po"]="48" + ["Ro"]="50" + ["Ru"]="51" + ["Sv"]="10" + ["Tr"]="59" + ["Zh"]="13" + ) + echo 'ai_service_enable = "true"' >> ${RAAPPENDCONF} + get_setting "ai_target_lang" + AI_LANG=${EES} + # [[ "$AI_LANG" == "false" ]] && AI_LANG="0" + get_setting "ai_service_url" + AI_URL=${EES} + echo "ai_service_target_lang = \"${LangCodes[${AI_LANG}]}\"" >> ${RAAPPENDCONF} + if [ "${AI_URL}" == "false" ] || [ "${AI_URL}" == "auto" ] || [ "${AI_URL}" == "none" ]; then + echo "ai_service_url = \"http://ztranslate.net/service?api_key=BATOCERA&mode=Fast&output=png&target_lang=${AI_LANG}" >> ${RAAPPENDCONF} + else + echo "ai_service_url = \"${AI_URL}&mode=Fast&output=png&target_lang=${AI_LANG}" >> ${RAAPPENDCONF} + fi +fi + +## +## Global/System/Game specific settings +## + +## Ratio +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "ratio" +if [[ "${EES}" == "false" ]]; then + # 22 is the "Core Provided" aspect ratio and its set by default if no other is selected + echo 'aspect_ratio_index = "22"' >> ${RAAPPENDCONF} +else +for i in "${!INDEXRATIOS[@]}"; do + if [[ "${INDEXRATIOS[$i]}" = "${EES}" ]]; then + break + fi +done + echo "aspect_ratio_index = \"${i}\"" >> ${RAAPPENDCONF} +fi + +## Bilinear filtering +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "smooth" +[ "${EES}" == "1" ] && echo 'video_smooth = "true"' >> ${RAAPPENDCONF} || echo 'video_smooth = "false"' >> ${RAAPPENDCONF} + +## Video Integer Scale +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "integerscale" +[ "${EES}" == "1" ] && echo 'video_scale_integer = "true"' >> ${RAAPPENDCONF} || echo 'video_scale_integer = "false"' >> ${RAAPPENDCONF} + +## RGA Scaling / CTX Scaling +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "rgascale" +[ "${EES}" == "1" ] && echo 'video_ctx_scaling = "true"' >> ${RAAPPENDCONF} || echo 'video_ctx_scaling = "false"' >> ${RAAPPENDCONF} + +## Shaderset +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "shaderset" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'video_shader_enable = "false"' >> ${RAAPPENDCONF} + echo 'video_shader = ""' >> ${RAAPPENDCONF} +else + echo "video_shader = \"${EES}\"" >> ${RAAPPENDCONF} + echo 'video_shader_enable = "true"' >> ${RAAPPENDCONF} + echo "--set-shader /tmp/shaders/${EES}" +fi + +## Filterset +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "filterset" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ]; then + echo 'video_filter = ""' >> ${RAAPPENDCONF} +else + # Turn off RGA scaling first - just in case + sed -i "/video_ctx_scaling/d" ${RAAPPENDCONF} + echo 'video_ctx_scaling = "false"' >> ${RAAPPENDCONF} + if array_contains IS32BITCORE ${CORE}; then + echo "video_filter = \"/usr/share/retroarch/filters/32bit/video/${EES}\"" >> ${RAAPPENDCONF} + else + echo "video_filter = \"/usr/share/retroarch/filters/64bit/video/${EES}\"" >> ${RAAPPENDCONF} + fi +fi + +## Set correct path for video- and audio-filters +if array_contains IS32BITCORE ${CORE}; then + echo 'audio_filter_dir = "/usr/share/retroarch/filters/32bit/audio"' >> ${RAAPPENDCONF} + echo 'video_filter_dir = "/usr/share/retroarch/filters/32bit/video"' >> ${RAAPPENDCONF} +else + echo 'audio_filter_dir = "/usr/share/retroarch/filters/64bit/audio"' >> ${RAAPPENDCONF} + echo 'video_filter_dir = "/usr/share/retroarch/filters/64bit/video"' >> ${RAAPPENDCONF} +fi + +## Rewind +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "rewind" +(for e in "${NORUNAHEAD[@]}"; do [[ "${e}" == "${PLATFORM}" ]] && exit 0; done) && RA=0 || RA=1 +if [ $RA == 1 ] && [ "${EES}" == "1" ]; then + echo 'rewind_enable = "true"' >> ${RAAPPENDCONF} +else + echo 'rewind_enable = "false"' >> ${RAAPPENDCONF} +fi + +## Incrementalsavestates +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "incrementalsavestates" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'savestate_auto_index = "false"' >> ${RAAPPENDCONF} + echo 'savestate_max_keep = "50"' >> ${RAAPPENDCONF} +else + echo 'savestate_auto_index = "true"' >> ${RAAPPENDCONF} + echo 'savestate_max_keep = "0"' >> ${RAAPPENDCONF} +fi + +## Autosave +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "autosave" +if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'savestate_auto_save = "false"' >> ${RAAPPENDCONF} + echo 'savestate_auto_load = "false"' >> ${RAAPPENDCONF} +else + echo 'savestate_auto_save = "true"' >> ${RAAPPENDCONF} + echo 'savestate_auto_load = "true"' >> ${RAAPPENDCONF} +fi + +## Snapshots +echo 'savestate_directory = "'"${SNAPSHOTS}/${PLATFORM}"'"' >> ${RAAPPENDCONF} +if [ ! -z ${SNAPSHOT} ] +then + sed -i "/savestate_auto_load =/d" ${RAAPPENDCONF} + sed -i "/savestate_auto_save =/d" ${RAAPPENDCONF} + if [ ${AUTOSAVE} == "1" ]; then + echo 'savestate_auto_load = "true"' >> ${RAAPPENDCONF} + echo 'savestate_auto_save = "true"' >> ${RAAPPENDCONF} + else + echo 'savestate_auto_load = "false"' >> ${RAAPPENDCONF} + echo 'savestate_auto_save = "false"' >> ${RAAPPENDCONF} + fi + echo "state_slot = \"${SNAPSHOT}\"" >> ${RAAPPENDCONF} +fi + +## Runahead +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "runahead" +(for e in "${NORUNAHEAD[@]}"; do [[ "${e}" == "${PLATFORM}" ]] && exit 0; done) && RA=0 || RA=1 +if [ $RA == 1 ]; then + if [ "${EES}" == "false" ] || [ "${EES}" == "none" ] || [ "${EES}" == "0" ]; then + echo 'run_ahead_enabled = "false"' >> ${RAAPPENDCONF} + echo 'run_ahead_frames = "1"' >> ${RAAPPENDCONF} + else + echo 'run_ahead_enabled = "true"' >> ${RAAPPENDCONF} + echo "run_ahead_frames = \"${EES}\"" >> ${RAAPPENDCONF} + fi +fi + +## Secondinstance +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "secondinstance" +(for e in "${NORUNAHEAD[@]}"; do [[ "${e}" == "${PLATFORM}" ]] && exit 0; done) && RA=0 || RA=1 +if [ $RA == 1 ]; then + [ "${EES}" == "1" ] && echo 'run_ahead_secondary_instance = "true"' >> ${RAAPPENDCONF} || echo 'run_ahead_secondary_instance = "false"' >> ${RAAPPENDCONF} +fi + + +## D-Pad to Analogue support, option in ES is missing atm but is managed as global.analogue=1 in distribution.conf (that is made by postupdate.sh) +# Get configuration from distribution.conf and set to retroarch.cfg +get_setting "analogue" +(for e in "${NOANALOGUE[@]}"; do [[ "${e}" == "${PLATFORM}" ]] && exit 0; done) && RA=1 || RA=0 +if [ $RA == 1 ] || [ "${EES}" == "false" ] || [ "${EES}" == "0" ]; then + echo 'input_player1_analog_dpad_mode = "0"' >> ${RAAPPENDCONF} +else + echo 'input_player1_analog_dpad_mode = "1"' >> ${RAAPPENDCONF} +fi + +## +## Settings for special cores +## + +## atari800 core needs other settings when emulation atari5200 +if [ "${CORE}" == "atari800" ]; then + log "Atari 800 section" + ATARICONF="/storage/.config/distribution/configs/atari800.cfg" + ATARI800CONF="/storage/.config/retroarch/config/Atari800/Atari800.opt" + [[ ! -f "$ATARI800CONF" ]] && touch "$ATARI800CONF" + + sed -i "/atari800_system =/d" ${RACORECONF} + sed -i "/RAM_SIZE=/d" ${ATARICONF} + sed -i "/STEREO_POKEY=/d" ${ATARICONF} + sed -i "/BUILTIN_BASIC=/d" ${ATARICONF} + sed -i "/atari800_system =/d" ${ATARI800CONF} + + if [ "${PLATFORM}" == "atari5200" ]; then + echo "atari800_system = \"5200\"" >> ${RACORECONF} + echo "atari800_system = \"5200\"" >> ${ATARI800CONF} + echo "RAM_SIZE=16" >> ${ATARICONF} + echo "STEREO_POKEY=0" >> ${ATARICONF} + echo "BUILTIN_BASIC=0" >> ${ATARICONF} + else + echo "atari800_system = \"800XL (64K)\"" >> ${RACORECONF} + echo "atari800_system = \"800XL (64K)\"" >> ${ATARI800CONF} + echo "RAM_SIZE=64" >> ${ATARICONF} + echo "STEREO_POKEY=1" >> ${ATARICONF} + echo "BUILTIN_BASIC=1" >> ${ATARICONF} + fi +fi + +## Gambatte +if [ "${CORE}" == "gambatte" ]; then + log "Gambatte section" + GAMBATTECONF="/storage/.config/retroarch/config/Gambatte/Gambatte.opt" + if [ ! -f "$GAMBATTECONF" ]; then + # set some defaults + echo 'gambatte_gbc_color_correction = "disabled"' > ${GAMBATTECONF} + else + sed -i "/gambatte_gb_colorization =/d" ${GAMBATTECONF} + sed -i "/gambatte_gb_internal_palette =/d" ${GAMBATTECONF} + fi + get_setting "renderer.colorization" + if [ "${EES}" == "false" ] || [ "${EES}" == "auto" ] || [ "${EES}" == "none" ]; then + echo "gambatte_gb_colorization = \"disabled\"" >> ${GAMBATTECONF} + elif [ "${EES}" == "Best Guess" ]; then + echo "gambatte_gb_colorization = \"auto\"" >> ${GAMBATTECONF} + elif [ "${EES}" == "GBC" ] || [ "${EES}" == "SGB" ]; then + echo "gambatte_gb_colorization = \"${EES}\"" >> ${GAMBATTECONF} + else + echo "gambatte_gb_colorization = \"internal\"" >> ${GAMBATTECONF} + echo "gambatte_gb_internal_palette = \"${EES}\"" >> ${GAMBATTECONF} + fi +fi + +# We set up the controller index +#sed -i "/input_libretro_device_p1/d" ${RACONF} +CONTROLLERS="$@" +CONTROLLERS="${CONTROLLERS#*--controllers=*}" + +for i in 1 2 3 4 5; do +log "Controller section (${1})" +if [[ "$CONTROLLERS" == *p${i}* ]]; then +PINDEX="${CONTROLLERS#*-p${i}index }" +PINDEX="${PINDEX%% -p${i}guid*}" +#sed -i "/input_player${i}_joypad_index =/d" ${RACONF} +echo "input_player${i}_joypad_index = \"${PINDEX}\"" >> ${RAAPPENDCONF} + +# Setting controller type for different cores +if [ "${PLATFORM}" == "atari5200" ]; then + sed -i "/input_libretro_device_p${i}/d" ${RAAPPENDCONF} + echo "input_libretro_device_p${i} = \"513\"" >> ${RAAPPENDCONF} +fi + +fi +done + +## +## Bezels / Decorations +## + +# List of possible Bezel Folders +BEZELDIR=(/tmp/overlays/bezels /storage/roms/bezels) +# Define the resolutions of the differen systems (0:x 1:y 2:width 3:height) as seen in Scaling -> Aspect Ration -> Custom +# RG351P/M=480x320 +# RG351V=640x480 +if [ "${EE_DEVICE}" == "RG351P" ]; then + declare -A SystemViewport=( + ['standard']="1 1 479 319" + ['gb']="80 16 320 288" + ['gbc']="80 16 320 288" + ['supervision']="80 0 320 320" + ['gamegear']="80 16 320 288" + ['pokemini']="96 64 288 192" + ['ngp']="80 8 320 304" + ['ngpc']="80 8 320 304" + ['wonderswan']="16 16 448 288" + ['wonderswancolor']="16 16 448 288" + ) +else #Must be the V then + declare -A SystemViewport=( + ['standard']="1 1 639 479" + ['gb']="80 24 480 432" + ['gbc']="80 24 480 432" + ['supervision']="80 0 480 480" + ['gamegear']="80 24 480 432" + ['pokemini']="128 112 384 256" + ['ngp']="80 12 480 456" + ['ngpc']="80 12 480 456" + ['wonderswan']="96 96 448 288" + ['wonderswancolor']="96 96 448 288" + ) +fi +# Get configuration from distribution.conf and set to retroarch.cfg +BEZEL=$(get_setting 'bezel' ${PLATFORM} "${ROM}") +if [[ -z "${BEZEL}" ]]; then + BEZEL=default +fi +log "bezel: ${BEZEL} platform: ${PLATFORM} rom: ${ROM}" + +if [ "${BEZEL}" != "false" ] && [ "${BEZEL}" != "none" ] && [ "${BEZEL}" != "0" ] && [ ${SystemViewport[${PLATFORM}]+_} ]; then + # set path + for p in ${BEZELDIR[@]}; do + if [ -d "${p}"/"${BEZEL}" ]; then + path="${p}"/"${BEZEL}" + fi + done + + BEZEL_SYSTEM=$(get_setting 'bezel.system.override' ${PLATFORM} "${ROM}") + if [[ -z "${BEZEL_SYSTEM}" || "${BEZEL_SYSTEM}" == "AUTO" ]]; then + BEZEL_SYSTEM=${PLATFORM} + fi + BEZEL_SYSTEM_PNG=${path}/systems/${BEZEL_SYSTEM}.png + log "Bezel system png: ${BEZEL_SYSTEM_PNG}" + + GAME_BEZEL_OVERRIDE=$(get_setting 'bezel.game.override' ${PLATFORM} "${ROM}") + log "Game bezel override: ${GAME_BEZEL_OVERRIDE}" + if [[ -z "${GAME_BEZEL_OVERRIDE}" || "${GAME_BEZEL_OVERRIDE}" == "AUTO" ]]; then + + log "No game specific override found. Looking for games" + # is there a $ROM.cfg? + # excatctly the same / just the name / default + # Random bezels have to match $ROM./d+.cfg + romdir="${path}/systems/${BEZEL_SYSTEM}/games" + pushd "${romdir}" &> /dev/null + for romname in "${ROM%.*}" "${ROM%% (*}" "default"; do + log "Looking at: ${romdir}/${romname}" + # Somehow the regex of the busybox find does not know about "+" WTF? + pattern=".*${romname}"\\.[0-9][0-9]*\\.cfg + readarray -t filelist < <(find "${romdir}" -regex "${pattern}" -exec basename "{}" \;) + log "file list: ${filelist}" + count=${#filelist[*]} + if [ ${count} -gt 0 ]; then + ran=$(($RANDOM%${count})) + game_cfg="${romdir}/${filelist[${ran}]}" + log "Using random config: ${game_cfg}" + break + elif [ -f "${romdir}/${romname}".cfg ]; then + game_cfg="${romdir}/${romname}".cfg + log "Using rom config: ${game_cfg}" + break + fi + done + popd &> /dev/null + else + game_cfg=${path}/systems/${BEZEL_SYSTEM}/games/${GAME_BEZEL_OVERRIDE}.cfg + fi + if [[ -f "${game_cfg}" ]]; then + log "game config file exists: ${game_cfg}" + contents=$(cat "${game_cfg}" | awk '{$1=$1};1') #awk strips off leading/trailing whitespace + BEZEL_SYSTEM_PNG=${path}/systems/${BEZEL_SYSTEM}/games/${contents} + fi + log "bezel png: ${BEZEL_SYSTEM_PNG}" + if [[ -f "${BEZEL_SYSTEM_PNG}" ]]; then + + # create the temporary bezel for retroarch + echo "overlays = 1" > ${TMP_BEZEL} + echo "overlay0_full_screen = true" >> ${TMP_BEZEL} + echo "overlay0_normalized = true" >> ${TMP_BEZEL} + echo "overlay0_overlay = \"${BEZEL_SYSTEM_PNG}\"" >> ${TMP_BEZEL} + count=0 + if [[ -d "${path}/systems/${BEZEL_SYSTEM}/overlays/" ]]; then + for overlay_png in $(ls -1 ${path}/systems/${BEZEL_SYSTEM}/overlays/*.png) ; do + + overlay_name="${overlay_png%.*}" + overlay_name="$(basename ${overlay_name})" + overlay_setting=$(get_setting "bezel.overlay.${overlay_name}" ${PLATFORM} "${ROM}") + if [[ "${overlay_setting}" == "0" ]];then + continue + fi + log "Adding overlay. name: ${overlay_name} overlay setting: ${overlay_setting} png: ${overlay_png}" + echo "overlay0_desc${count}_overlay = \"${overlay_png}\"" >> ${TMP_BEZEL} + echo "overlay0_desc${count} = \"nul,0.5,0.5,rect,0.5,0.5\"" >> ${TMP_BEZEL} + count=$(expr $count + 1) + done + fi + echo "overlay0_descs = ${count}" >> ${TMP_BEZEL} + bezelcfg="${TMP_BEZEL}" + fi +fi +if [[ -n "${bezelcfg}" ]]; then + log "using bezel" + # configure bezel + echo 'input_overlay_enable = "true"' >> ${RAAPPENDCONF} + echo "input_overlay = \"${bezelcfg}\"" >> ${RAAPPENDCONF} + echo 'input_overlay_hide_in_menu = "true"' >> ${RAAPPENDCONF} + echo 'input_overlay_opacity = "1.000000"' >> ${RAAPPENDCONF} + echo 'input_overlay_show_inputs = "2"' >> ${RAAPPENDCONF} + # delete / set scaling and aspect ratio: + sed -i "/video_scale_integer/d" ${RAAPPENDCONF} + sed -i "/aspect_ratio_index/d" ${RAAPPENDCONF} + echo 'video_scale_integer = "false"' >> ${RAAPPENDCONF} + echo 'aspect_ratio_index = "23"' >> ${RAAPPENDCONF} + # configure custom scaling + # needs some grouping to reflect the hack systems as well (i. e. gb=gb, gbh, gbc and gbch) + declare -a resolution=(${SystemViewport[${PLATFORM}]}) + echo "custom_viewport_x = \"${resolution[0]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_y = \"${resolution[1]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_width = \"${resolution[2]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_height = \"${resolution[3]}\"" >> ${RAAPPENDCONF} +else + log "not using bezel" + # disable decorations + echo 'input_overlay_enable = "false"' >> ${RAAPPENDCONF} + # set standard resolution for custom scaling + declare -a resolution=(${SystemViewport["standard"]}) + echo "custom_viewport_x = \"${resolution[0]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_y = \"${resolution[1]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_width = \"${resolution[2]}\"" >> ${RAAPPENDCONF} + echo "custom_viewport_height = \"${resolution[3]}\"" >> ${RAAPPENDCONF} +fi + +## +## Clean Exit +## +doexit diff --git a/packages/jelos/sources/scripts/show_splash b/packages/jelos/sources/scripts/show_splash new file mode 100755 index 000000000..c171cd705 --- /dev/null +++ b/packages/jelos/sources/scripts/show_splash @@ -0,0 +1,39 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present SumavisionQ5 (https://github.com/SumavisionQ5) +# Modifications by Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +. /etc/profile + +SPLASH_TYPE="$1" + +hres="$(fbset 2>/dev/null | awk '/geometry/ { print $2 }')" + +if [ "$SPLASH_TYPE" == "intro" ] || [ "$SPLASH_TYPE" == "exit" ] || [ "$SPLASH_TYPE" == "shutdown" ] +then + if [ "${DISPLAY_ROTATED}" == true ] + then + SPLASH="/usr/config/splash/splash-${hres}l.png" + else + SPLASH="/usr/config/splash/splash-${hres}.png" + fi +fi + +[[ "${PLATFORM}" != "intro" ]] && VIDEO=0 || VIDEO=$(get_setting bootvideo.enabled) + +if [[ -f "/storage/.config/distribution/configs/novideo" ]] && [[ ${VIDEO} != "1" ]] +then + /usr/bin/ply-image "${SPLASH}" > /dev/null 2>&1 +else + # Show intro video + SPLASH=${VIDEOSPLASH} + set_audio alsa + /usr/bin/mpv "$SPLASH" > /dev/null 2>&1 + touch "/storage/.config/distribution/configs/novideo" +fi + +# Wait for the time specified in splash_delay setting in distribution.conf +SPLASHTIME=$(get_setting splash.delay) +[ ! -z "$SPLASHTIME" ] && sleep $SPLASHTIME diff --git a/packages/jelos/sources/scripts/timeinfo b/packages/jelos/sources/scripts/timeinfo new file mode 100755 index 000000000..b23c0a37e --- /dev/null +++ b/packages/jelos/sources/scripts/timeinfo @@ -0,0 +1,22 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-2022 Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2022-present Fewtarius (https://github.com/fewtarius) + +function get_timezone() { + readlink -f /etc/localtime | sed 's;/usr/share/zoneinfo/;;' +} + +function list_timezones() { + cat /usr/share/zoneinfo/zone1970.tab | grep -v "^#" | awk '{ print $3"," }' | sort -u +} + +case "${1}" in + "current_timezone") + get_timezone + ;; + "timezones") + list_timezones + ;; +esac diff --git a/packages/jelos/sources/shutdown.sh b/packages/jelos/sources/shutdown.sh new file mode 100755 index 000000000..e56a5d639 --- /dev/null +++ b/packages/jelos/sources/shutdown.sh @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +# Source predefined functions and variables +. /etc/profile + +# Show splash screen +/usr/bin/show_splash shutdown + +shutdown $* diff --git a/packages/jelos/system.d/jelos-autostart.service b/packages/jelos/system.d/jelos-autostart.service new file mode 100644 index 000000000..4a36abc00 --- /dev/null +++ b/packages/jelos/system.d/jelos-autostart.service @@ -0,0 +1,13 @@ +[Unit] +Description=JELOS user autostart script +Before=emulationstation.service +After=graphical.target + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=-/bin/sh -c ". /etc/profile; exec /bin/sh /usr/bin/autostart" +RemainAfterExit=yes + +[Install] +WantedBy=jelos.target diff --git a/packages/jelos/system.d/jelos.target b/packages/jelos/system.d/jelos.target new file mode 100644 index 000000000..0e800322c --- /dev/null +++ b/packages/jelos/system.d/jelos.target @@ -0,0 +1,9 @@ +[Unit] +Description=jelos +Requires=multi-user.target graphical.target +After=graphical.target +Conflicts=rescue.target +AllowIsolate=yes + +[Install] +Alias=default.target diff --git a/packages/jelos/system.d/jslisten.service b/packages/jelos/system.d/jslisten.service new file mode 100644 index 000000000..63831f345 --- /dev/null +++ b/packages/jelos/system.d/jslisten.service @@ -0,0 +1,12 @@ +[Unit] +Description=hotkey service +Before=emulationstation.service +After=graphical.target + +[Service] +Environment=HOME=/storage +ExecStart=/usr/bin/jslisten --mode hold +Restart=on-failure + +[Install] +WantedBy=jslisten.target diff --git a/packages/jelos/system.d/jslisten.target b/packages/jelos/system.d/jslisten.target new file mode 100644 index 000000000..4c434b69b --- /dev/null +++ b/packages/jelos/system.d/jslisten.target @@ -0,0 +1,8 @@ +[Unit] +Description=jslisten +Requires=multi-user.target +Conflicts=rescue.target +AllowIsolate=yes + +[Install] +Alias=default.target diff --git a/packages/jelos/tmpfiles.d/jelos-dirs.conf b/packages/jelos/tmpfiles.d/jelos-dirs.conf new file mode 100644 index 000000000..6209d527a --- /dev/null +++ b/packages/jelos/tmpfiles.d/jelos-dirs.conf @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +d /storage/roms 0755 root root - - +d /tmp/cache +d /storage/roms/3do 0755 root root - - +d /storage/roms/amiga 0755 root root - - +d /storage/roms/amigacd32 0755 root root - - +d /storage/roms/amstradcpc 0755 root root - - +d /storage/roms/arcade 0755 root root - - +d /storage/roms/atari800 0755 root root - - +d /storage/roms/atari2600 0755 root root - - +d /storage/roms/atari5200 0755 root root - - +d /storage/roms/atari7800 0755 root root - - +d /storage/roms/atarilynx 0755 root root - - +d /storage/roms/atarist 0755 root root - - +d /storage/roms/atomiswave 0755 root root - - +d /storage/roms/BGM 0755 root root - - +d /storage/roms/bezels 0755 root root - - +d /storage/roms/bios 0755 root root - - +d /storage/roms/build 0755 root root - - +d /storage/roms/c16 0755 root root - - +d /storage/roms/c64 0755 root root - - +d /storage/roms/c128 0755 root root - - +d /storage/roms/channelf 0755 root root - - +d /storage/roms/coleco 0755 root root - - +d /storage/roms/daphne 0755 root root - - +d /storage/roms/daphne/roms 0755 root root - - +d /storage/roms/daphne/sound 0755 root root - - +d /storage/roms/doom 0755 root root - - +d /storage/roms/dreamcast 0755 root root - - +d /storage/roms/easyrpg 0755 root root - - +d /storage/roms/eduke 0755 root root - - +d /storage/roms/ecwolf 0755 root root - - +d /storage/roms/famicom 0755 root root - - +d /storage/roms/fbneo 0755 root root - - +d /storage/roms/fds 0755 root root - - +d /storage/roms/gameandwatch 0755 root root - - +d /storage/roms/gamegear 0755 root root - - +d /storage/roms/gb 0755 root root - - +d /storage/roms/gba 0755 root root - - +d /storage/roms/gbc 0755 root root - - +d /storage/roms/genesis 0755 root root - - +d /storage/roms/intellivision 0755 root root - - +d /storage/roms/j2me 0755 root root - - +d /storage/roms/mame 0755 root root - - +d /storage/roms/mastersystem 0755 root root - - +d /storage/roms/megacd 0755 root root - - +d /storage/roms/megaduck 0755 root root - - +d /storage/roms/megadrive 0755 root root - - +d /storage/roms/megadrive-japan 0755 root root - - +d /storage/roms/mplayer 0755 root root - - +d /storage/roms/msx 0755 root root - - +d /storage/roms/msx2 0755 root root - - +d /storage/roms/n64 0755 root root - - +d /storage/roms/naomi 0755 root root - - +d /storage/roms/nds 0755 root root - - +d /storage/roms/neocd 0755 root root - - +d /storage/roms/neogeo 0755 root root - - +d /storage/roms/nes 0755 root root - - +d /storage/roms/ngp 0755 root root - - +d /storage/roms/ngpc 0755 root root - - +d /storage/roms/odyssey 0755 root root - - +d /storage/roms/openbor 0755 root root - - +d /storage/roms/opt 0755 root root - - +d /storage/roms/pc 0755 root root - - +d /storage/roms/pc88 0755 root root - - +d /storage/roms/pc98 0755 root root - - +d /storage/roms/pcengine 0755 root root - - +d /storage/roms/pcenginecd 0755 root root - - +d /storage/roms/pcfx 0755 root root - - +d /storage/roms/pico-8 0755 root root - - +d /storage/roms/pokemini 0755 root root - - +d /storage/roms/psp 0755 root root - - +d /storage/roms/pspminis 0755 root root - - +d /storage/roms/psx 0755 root root - - +d /storage/roms/satellaview 0755 root root - - +d /storage/roms/saturn 0755 root root - - +d /storage/roms/sc-3000 0755 root root - - +d /storage/roms/screenshots 0755 root root - - +d /storage/roms/scummvm 0755 root root - - +d /storage/roms/scummvm/games 0755 root root - - +d /storage/roms/sega32x 0755 root root - - +d /storage/roms/segacd 0755 root root - - +d /storage/roms/sfc 0755 root root - - +d /storage/roms/sg-1000 0755 root root - - +d /storage/roms/sgfx 0755 root root - - +d /storage/roms/savestates 0755 root root - - +d /storage/roms/snes 0755 root root - - +d /storage/roms/snesmsu1 0755 root root - - +d /storage/roms/solarus 0755 root root - - +d /storage/roms/sufami 0755 root root - - +d /storage/roms/supervision 0755 root root - - +d /storage/roms/tg16 0755 root root - - +d /storage/roms/tg16cd 0755 root root - - +d /storage/roms/tic-80 0755 root root - - +d /storage/roms/uzebox 0755 root root - - +d /storage/roms/vectrex 0755 root root - - +d /storage/roms/vic20 0755 root root - - +d /storage/roms/videopac 0755 root root - - +d /storage/roms/virtualboy 0755 root root - - +d /storage/roms/wonderswan 0755 root root - - +d /storage/roms/wonderswancolor 0755 root root - - +d /storage/roms/x1 0755 root root - - +d /storage/roms/x68000 0755 root root - - +d /storage/roms/zx81 0755 root root - - +d /storage/roms/zxspectrum 0755 root root - - +d /storage/roms/ports 0755 root root - - diff --git a/packages/jelos/udev.d/99-pandora_pk7.rules b/packages/jelos/udev.d/99-pandora_pk7.rules new file mode 100644 index 000000000..38609515e --- /dev/null +++ b/packages/jelos/udev.d/99-pandora_pk7.rules @@ -0,0 +1,2 @@ +# Needed for device GZ RX CO.,LTD. RX Gamepad from Pandora's Key 7 +ATTRS{name}=="GZ RX CO.,LTD. RX Gamepad",ACTION=="add",ENV{ID_INPUT_TABLET}="0",ENV{ID_INPUT_JOYSTICK}:="1" diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/changelog.txt b/packages/kernel/linux-driver-addons/dvb/crazycat/changelog.txt new file mode 100755 index 000000000..32d81ca42 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial add-on diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/icon/icon.png b/packages/kernel/linux-driver-addons/dvb/crazycat/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22a6c6a0d90344f27d68561d8d44115debdfe89a GIT binary patch literal 68596 zcmV)8K*qm`P);}4|o_>$}|o#QPX>7hOg$JZy^{Ns3i zfk)Ba-~GKWz&ZlZZ=6m?LhJ&lphuawqNQ3?_o^z7oJt> zz@Lp{e0N00;|1R1nCL?o6?=TRkCDvYpVM(wx{ndp#}WF?V|RQ)A3m&GbeGtaVdaiE$G}Hl1rsM0l{5 z_LJ(?^}`!zd#~s8t6%UNlvT&Dv~53F{A` zBvL(wknrv&r1~;XqTSEY*p~@$EChdegu)&YV5xoiCVS+T_kQu}Fi%YV;#&@|5PYvD zuio#Iv=3|!KFVeOw|?#3-ja_f1h>a0Zof-&?)okqb0iM{osSvM<7?jl>%gD&BQ73a zkN9-}kN?BVVSU!1A34BB5AYG&A0DC{z~jH?fMp-#pda?4Xph+b#ct1W(2uf)1ApDJ zVCTr2jtH~Y*uCewga=DV)InUX`q9L)`*A^P@4x1V>|X}E?{=4P|2*vN1N)v|8C!d6 zXL-xjgL`42qCUg*OdSXAK zHC7$yc^_Y2`lTP#f?gBAIp(F{Acj7aE2pVedHjjI~YX$GsilD)}4U2 z-H+2azK(!&4}*9Y1GyKwgzBL`yq{eX`6cF%I`CU}TnZlIOFtY`cvx$;J&cpKkMPzU z1C7T4Sn3eR=lD9v8FYMr9xANgBVgI1p6VFL+{p~OWsCX8r1vgkf&sRKk z9F1Q%+;8ZJyEhi|A902Ua`W|}POgKSf?uEzTpiGz+W$vkZ#&}NPD!M_->37p9_)ep zVcGq`urE*uZokOH-cvw2^83AF9=EB(Iu85su{@sl$0Mco)aRi5af9GfUVB`cb9~(z z^{~gwyTg~^S^V~Sbew;m1X#x*I8vs2g%7nSvBl?ICSTSVz?8wC?lc6ltl}>(bx!nW*Ww8V-^J?N0{-e*v7 z7tiFujOU|4E44SyuJ-=U=`Oy&f=8Ljs6Yk2A4j3@>v0T#VNn!kSsFzV7*^YMUEB5T zKn4ad6U=&;$aU{e)dLR+kNjz`#=+j}IsNJv`~}f|8QUDz@PEb*ecul~&?=hE7V|}3 z6j2n0K^P@TmZwRY_&NY!U0+?j{Ql)?wdsf9!}QkO!`1_j8jd-vyLcefXZbSNM?Ze| zM9e-)S;dSL{sCA`Q`dD(T^VD7ECru>dimt(vuBINB2MBcCTaztk9T%mf3;jhVdVSY zUth1Awk6S0R^12HviEvx?)|X|9@B$=Zx4k1?WbrDeSALd0^iNrkJ?e2}jL7SQ4F=AcUWmUCpJ5B>2DG0(iAq4~Zy1HKJtJO3a zWvxT24>8N$_hlVJ!bg+8d4J!Jd9ho#C-V9+VEvYGN&Q4OO#68cilag}7jPy3jjweS z1k2^g@BZeSZ@&KB#l`tzHVZ?)8-{wfZJMU8o2shnwg$sezCwI>a(b3zd7LDGIqhqT z9spX#_`d%G%(`=UI-KYAV{(c=FC5)}V7}ioJmS=?jJ|`a_aOEDKi?zQkEijcZuQ#F zzB2q{5d+%M_f(RlaTw=W{`}dqfB5@>?LbzPSA4hRJd3WIP~6k!;&Z3A2i zbf}f@gJ}i8EBrFRH6b=sAE+ECfcUA4J&ecnZl>PHvd6Fh6=aNt2G>t|Br-Dc+Cg3&YT3}bxIF2_{&dIet8m;c-;r_%gv3K`9zw(YR z9TI*-rMbQP$@4i6IRDTtg5ZA`kw4#@xwZR}pSi<9`t4Nf$3Jl>_N63C1S{=XGXhZ_QfL3ljd&mX6cYL3Yfc2Sx<%1X?Bv_m* zilPX$j~k{1l1TfF#bPZ<*=n=h?lwC>m(OSV0Z5-eTTi8aSTOv{!*cg%CzqEOXBUfNuB@ud+O0t?$Wq%3{Q$Ov#fe-@^M(gO2#nKy07L>v;pdYGvT*PF zzQYe?%h7swO1ahhmRDa65byY#A1`3t%3THccvc0WA4QSx>zjvCc~KZ=d6uSB6XK!9 zqP<>k{`99mzkdC?>jrB$MecB`XipzZ`va)@g+%*(M}o=<3m$MDd6u1>oIZVWd4766 zpUwOr807`DqAF_~J>g24_nsHRN*%4Haq6u{J(h=6${4NNY1;0#+j7?r_>C)yR_acx z3+|emA-Q-&tHlTO>ceaQQsaQY-Apa0FK*U3^Xr%AXQz2qAjA{B=%hix z0<1_nP?}*Nu}P_$gt{5J30#V@(P;`ifpm zX0bd$40y6U$+A2OLolgn7ywtev9hxl1FB{jh;oKI)C7L(Yr!mLFo%9X%-^<6)3#WC zxK=4`7#L1X)AVgOVO{!bZp8=2G4tCPja#lB+;4{y|H+dlw}MypSM^i}MV&qpu)vP2 zAxlCuF&RAMJqVT|!F4ul(>K=_9WjYi!AktT9wCOdcO-t=)DZKxi60<2B>(q9t^7P4zdw``c%imzQVf z|M0he`@jCzf8gKmU%c3qrBZ$n#me%tqxrdNmBSp&&##xcRjA^=p0A56eR^^B-m`9$03)(L=OoHH(=CrYAi$GV{ng5=Bv(rnC7R;XLBOD2k1sTiw=y#FC~T znx-Cx0k_|KSL^dvA>qD4{GP`*{;KTf`}_!Z*AMe+AV0)zs$>JgY=mDW1w#&MWPwCpcsd=3qU_U2I`1|f70 z!y-$bU7r8rKm5(*#VOP0qNbu)jtvWnswL|K6H;yanzbfRfQV@)>BTKzmGr7)EtK8$Seu;b9L6Sb^py_cYeq_4V6VzA}Co zJvl#(w0?SVUf1<*SHHc!o@LjYx~aRN?s`O-Qb_CX5!E`_wMqf4f?$^C%lTq4EAk|p zh90!Hq1{5sTcf-w2))P#n(1>4=X@b}yMF28(wB()m zLHFSAcZ9gdFQSF@;vhI%EHBPZPEHof#T-1hYwB{lX`5h0U*^5prmubw`Ah82IFWq>opj(Ei9i}}SlH`-skd9wxu0M!~N&LltZl(%0I;@$@s zz==>m2a({D%ge=LF`wmW5|2Z(U6p-X0Z9Vpr#v%yqs0OfggT@Il#7SQonJ~5e1`aO z><7U#*;a%M*6u`&Vkjl0(|gF@T8m$CH5z*FM`F>(g;uvc$%DN;vxAv5Olnw`_X&R&m5CiK?O+VDlcIpRmE~a_CIE?Yjd7k0v?~R&! zUP>)v@%HNKdcEFm%ere>BSHdjPZIe(-dV99dH&!vSsbTflxNwKi_51^p5z!|+^nJN z8Zg)a!x{VT3jiOL^nu2~v zlMElh(OB@@BAN#^p6+CS@T2a^!`u|R&Cbt{ZQGFhO-fsZ5tL1B?gvrYg9n~Ta^I75 zJHW^v``()j7U(=lGK70^jIoM*ziAp{#@+h*jnC5C`Fs)h(JU{5FlxrB12hHFkR?l( zr>EQP_T}r>uU@|y2cv@EAhw+LArj1@_)>CP^B~ za57oN`7pT;;`ZU*`3M5_M56^y1tP@?G&mIa^av;f2}|jQJorHuC%C2lFpRiUb%PuD z7mLvk@6j#HIQwvK-LHX2aD2EwYj|aRu{|}r_(rvhZPVa&}E%j7y= z_Qp;_VTmy;4&?T(yK*Kc+fKR;wq04(eLt|h#4z62Fo>wM@A0b=A))yx1=cZo|4a}G ze)VWaxz#VcoVyW$2~Gh*9NRmh^ ztnWVJifUW=o(4YUS)PPRoSLZac2y0?o2IGldnuMy>&o_buB_j;Hux-_We-qK z^=mVPtAbLqJiRzwo-AgI#T<8N=(!u%)HRz*Xa(*XAolY}hH$R{S#mFZFYsv&GY*LL zTO09f^mMlSR zIX#%a9gUtXgE&fTDsoa|2Q@OMzhn*C*~tk|46$fawU|I)1V(CkJ{`99UQea|YRa>y zFQQG}BrO7|BWLOIU&@$Vzf<~#DrTTg=ZmM$F3!)+(li9G>f51j8+_2CaF>QaER>Oo z8XgAAkCI07eqgjeNTnh5bqEDndq535{=#iO578oGc;5^-;z-q~@{%k|vfK~Dv1#g_ zC0e*Cf2kaF_p|RW(?=PnuzIdJejUIFhCh12xyI zSRAG#N%OpzXglszEsf<`>3rvw^iRPo>wQqt_VGsa?~eard%gDq^s`lv_OE*k{Ccxx z&T~JCV#INIo+V(MX%dDJ%a7Y;yV;gyiNB20BJiJg=fORREQt{WK7aP~^86e@-`MxN z?FvYOfISXF=_wxyZ(^B^Z$nRG(Fhc~ae)ux4uya%F9=zo0MHt(C&_q#RGx-uf|JQZ zKMi%X*>3R+=qQ*km)R_DhM}K^X6Qzih5oSM`Gfm%(0ZybnJ5ar2x!`Uy%C>U5;+NA zY01d?^mtMe<&>oQZ8jisn7K;SLm%4X{WNQF_T@J-mdn4# zlQ8C{>e{{ou$$xj#S=w}cv%Ddfx1Q%{?5#f4y%(4iYMX=V?7sA@zDI?du(+0Vw?r1 zdPj{sxdK-y3_=QwTFmF?XQ!v9%h@c?Kw+5G?yIu8UahXLaowA$swh>Hx+r`{pcU}w z;`Hq4Q*f)3EQ#3uVMO%S7}II_0xUG(N|gA5ulYbg#iq>z#S65#VjCPV=J4jUL6sya z3Bt@P2Zn|S;Y&VbPkI% z#W{6jZMHJ;CXaS-MiN=fTG7cO=6nTI1w-33hzn_<32&$N0l z8wy4}b?FC-lVup^{XlR8O#pI*Ec}UZm?AHd>lMHYM=P639&0UU#aPKjC7ySKDDoG& z(9sM>vjBzY6Nn9gQvEpgoY?#t`q3lU^&|`9-#86K6eh(<95b5Ifg$Y}rcw6P0$Lf; z9%^J>$K0f-?bu@&0MR&^$>AO4XySA)CY*v?`lgk~JMaTsL|LBB`I;?6lD=3J6iy{6 z&SaX#Sy2?TVm2$@zRj+$uRyh^DW{smg8ZDFodDzT9-LLvwnNt-+D0G;w&sbt_(k}5 zi~(s}GG4~e`yt$a_I~bh-rcUO;mZfS_iW%KY(%Jo+h4N!-D)aefsoJ(sCoCX3}bEA zVW`Av7qbQvHwvOOBJlKT6n7cs>8S^bLd+GQRZkd`9Pc=sU!3K$nNnw%`K!%#6uL4i zGVVe~5y;14UR-ZB05wcEU=3oW7U9y!JXt6bNFW0cBLU!qk^GBS%pEaFtFiCP(AOXc zZ6g^NHhSqfRXKS>Zl$q33|<*+p%79~1Caud zW*|1tDFuC<>}aqeMSxR$B8-6KZP#HethPE1F|M^_$f_D6--?g>Uo;J#_mhV1N6Peh z4C~8}-{Do7Ti4o)j^H;He@e9FE25juGj0jZ9yoo&SS>S=f(VFzT9m4!GJ8_TQ^(2 zy1v6VGG!CS6j~S>mM>?ES;qcUj6g@3{t^me0vAKy_5doNRl6;BAcL6ZggCx%V9e}L z9J|0V03x{Ru%Y-pTUuGe$Ez_TQH4GFiHwp_biqTvS%n& zX*U~ObX;I@jzca#i6YD~ytr0#8uz1M7LP{kK&Uk+JpiE)&RnmrMl*Cn_w@O*#q#9z z>|_*)5Jf|@vWcwt#(@O&gv}5~01ukaW_XAEWsWl_cV%C9fDzXHF6MEBi9Lacad!1A zvDQM?a8|$${5(lwL^o`x0Zil`DEBXE^n`#k?7^^ZrlO;nM*e3f4dC(>6F{_Zp;Fuz zFLazN=Dv`!whn+wJ-;i($lUSAE;Yk-wbJ!Ytu_AcFTO(vdU_ zVc^X0)7?EOG-N2PCXnDk4}s+Bh*g?%M8bN|U6!-!PF5T+$L($h9y&^}4M1M6*Q?bv z&QM4kWu<#1Ww86W-rr9S>-hQsY+=3i5Ho~U#V%>Ag-tQ>Dp3HvL=E3&MKi?=7Q?hi zHt9pdPa+nXJeT+3(mx6@lN^sFMr_t=Zs`dl6X!}jo9DU7KsI{uIR#7r9{hk_G>k6O zBx7ngJ~>&==JT%YU+dTFX)UGMva?A&gy-xpnH`@-j~iq@sZ$WdvLBabm9fGgxN%@) z3%{jgiKJ{2RQC905TTGWf8>dCyHa^As3BDdahxDJlLj-u^S+$Q#c>GIR8unmkPnO`*znmUF|5E~f(!y3iYzbk42K5c zs>;p!`puiyuds~FXZbA4IPw!PaR>uV1P6rqn!1R7bXs3ZOPE(@vduU-F6osfZmEzb zZ+#gtKh)tg4OIy+-IY}{f^dddAtpqgo6Qzr3Jz%BajTCh%29jh?7GKPEBFnUbA0^- z&$2f;RtHv?o$>=|sWOeh;F2|LSiz^6vEJCUtrZH!Pg`JzFGBbL@fM|~7T7{?LDVBb zS&sR(TCWl15wOB&wpiq|dEGQ`-dus3jI@PNECXVhE^&dmYv#v8b|N$MjqoJ)qpX#P zGsu)8Az}&(+(HCk9)h(%14Jk(NMgfuo6oI%aI3Dz2M~yH8p}=|fXd5KM4UbyyG+wn zWwizL5Vtz7XINz7C;-(G%<^j8;`BpOE|nzFEYHtQPSP}^z=JBOtRLoOImhL`^1R({ zhe5+P0asqWS|e^=Ea#wyfZ*rPpMU+$@6ON9G1R+qyIQSSYFux(>$g>1t*)+`y6l=7 zA?pwY2n@T}?}*7gQ-)!HyJ9sFiq=-{{@ICDRSebHRNlzqfP=FJ%EzyyT`pZ0BE>xs z4}-AVZJ99?`iYV45lwfU_-gQYKlZ@db6R5$glYx9;c|W%(H;=CeMHp%uC=<`^B3h1 z{vA|6X(3}JkL{la;;WH+lGjaQ6pi0Mjd}yF{KX9%EOg@K!*x+zlgJqU=sC;90 znDi}OR$2OMg+-EhQe4n6RsuMI%q0mJ*8KeZ46!HT!LE--9^B+viZ>!QY}yJp0AB%k z#eV{TFf=EN`SN6m=WW(p!${|!fcF7-2fpS} z#>*{2pPt8TXNz&d?aks$CBzhQxMC3~S*#@T>24M<-Q_&ksj%bT0o|(^y*7xKRpuwW zTjPXLuBaHLs>6PuasPqL{lK61FHg*F-_!j8F|m*H1Gsq#r7tj-R^_(6r!b<{kX~m?!z~o?TLSQBan{XSxw`@$+qv`UR`Z=TTGj0 zUwu8F75Mymv$c}sXV=z_^Gy_4X6RZox=?PQ#)$GQk*VSjI;sRgGLyB_`Kt9g`4YAmGw%d};Ah#m8iCEs%O)AuIGmXUTV(#=yyzW-K?2 z&k(#8MMe?&*$F<;08F(vP_i%toglmP@9AkmjS_H5w-OgNhb3R$e+#W&WBMJBFXm8;Z6J+a6i!9 z74l*Pn?uvIqWQ8_RkmG?J19ZCZQU7Epm!xsfc2q2LaT@JynkV0cFbYj+RJG|!^l1B zVK9aWv6LB|bP^9N^HQ>(&qZ8Ga$R=L#6H<$RK%{ryzLVqrpKGugEdG%$tY8xV%|fX z*N;QpHtX%WA3CtRufO>QVVTqgu{Sy^eEMDzF;d?qR$cTCw9c0fpg}Ac1HeHjHeJ-b z1}=j=;d`55q&9Mh6K*0Y4qDsjYXdLG7cE>h+plO3>#_(n; z(MNVN6O(8PL=o{)77z#0ObehfAP$vk;&xyualb2f_!s|e#XiiJ2zy@4rXk8w){g`3 zfwyDdBNRl~xLRFrR%@We*blNnsmE!+XykbTbfb9&klIuDx=3PCD_gp_QkD%^jkCp1 z7&!;DvhuWZy4KD)Hk9&pPsA&@ErQytI%Hy=yP_08AYvS7q};PjA^t*JWbeoE;L&sO zb^z;cbXX6xbH~q|mn&yuN3T{ShY6?){lASrSTQ4&9FiwH=Qo;i5kpUYFFWUa%S|Fo zIjTiZr5-Sba7j54rkyaW$H~NYbY@sx-@SSJ2Jgl+y12Z|^E^sY0L|2oW}HCBCRX#v zuDtUepvaTOyqs6k?llG^iBPC#`@|OT$I@+)U*J>_;{eE_IKjs;OZ#4u`{aI<<;!f8 zY0Q1YZoApOy?(RWT-VL6qu1czHV`nOvn0b8A@(%Fw(=qkSq>QD2%F7DvfF-30TThM zuIsDotL=7ch2rHDVa52KF;BpxVzK%Rq$3d^6lb*EY^rhxN@z)H6uwDKV>NVA!mQ$$ zo0S-5kKVA9dIE-~iQP}#`!O!mWEtsflqA+jO}Y*w&gZQrpJcVDl6=<`_-?C|CZchg z$PY2lkQdG#LT$*Y|Hn{QD zRpOP!e$bQ0N_0*VTG;eSNhm>kUhD%;1WA zsR?GAC4l0x9rOdY_kUs!TKl-VZcpp?s|CK;KSIPR`HI(=?i>z^}ol zTH1$Mz``(29m24I{w^%X5n?5OvJ1B_`?J&3Pd&}61S#0=6n7{LL>#J_!EV@fXHzB z-*hYI6#VibAN8W}=@-v}98B2p#zBdXHus!H&H*gT04$#!3kS)28%=4VghrIYkDUQ< zcuf3oiO#buA#jAU$m0kmqU1cB&GR&$Nx|M&mYCjG2&RCF2o-^T%jHRyCi8i|-NYLY z^RW#mUI4qH60<5xoL8J=;+@&L>c5VOcFca}*{JpgRKzL%4gjOXG%wR zJss^BJknMLC*D+bNqx7Nn#Ym#0-_Jqr+vvSJOEaTw~-t90V}t&0;dXm1QC-BQUh9t z@Xhlgrqvj1QdRbhuP1R7f*1m@uA=Db%^S=R;A>OYl8_offe^?6-_t0nxz8a9C&|av zWj%Bqqd@6?3V32cQm7NKy)g1_x(#C4z*UE?tcUk+a8(K(789d=L&F$0X`6&$@k9{j zwl(f>z{H=2=&`MLTaQ&TE`)nTLhrN zroj=NcYppCh_G3$zW(}~r_Y||d2;#W66CF}8@8(o!lGan3DM1Jy`|tO ztR)>DD(kf!_v0;f1}Ww?5Vsn3Krc{b5Ms8zcM1e9YZ_9>&Ku*)9`9pw zvm`{6==ZKJhgm65FC4aShcwL*3F3#q5SkR`N#ASH+=9HQP|EkF`2q(_2r9v1J_A@H zjMH9XF%+WSWR3`t;C6>)L8M`w@FOP4W0oILy@BAdse6Q(^yiBs5xsFgKpYyBbaXZ% zSO?uyeym-slH+Ak{nH{&ZG9hXZjiz#5y5LvT)D{KaRzyaeZk?J|G0flHfTu@ek#gw*XmfEtTIP3p}ZS)1YYp%5LcDsz#8gL^_K5h=WM_Ujd1I z@G>1pVG>X<#8{04EU)EmiQGZSUg^JneRe#kKIuVyFzMpsF5zb(+Q-{*jx2W5qT&$^ z0cH#TZbI3W7rPaD?@B6!ZS1XN-0`4;OyKch)E6>lampYHw269{w<9yde7}`#wgeLg zn8N+M3Lo@9Ig`yjjhuZG{w8feV9>FH~WdqPjN>RNG;9`Da97tFdcy9fQmRyiefJDouRu66=zZd zE^=8~zAzsMN}DqCCnJfq!;u_(4+mAU{hkyF#$r2x`_a|4BDTifm={*mG+y%$Yi`$C_ zWv@`C5EH=Mxet|>8iazh?IT(!HZPFY27xb|P;6A;dKt*`eX}f!w+VwXJz3F9Ork!W zBvsGa9ZQ92ApQ=R;hLNBfnV3%o42ob<@VLDQlH!PAobzVAhmoK$4Rrjk7eThkDa^ zlW`VaK^SDLC?xw7KUc~O+@uS|y1@@rVq<#0B++s)2a7b*&FVmXm<~C#Vh+I|F-q(> zG}d;#lfmO0+EHw3aK%X+0yJaRmIK>pQh{h3W8LCy{WvM#sGuFkvM#r~4Y1fX$Z@3g zLy-FX`E}q*?02VsOP6tEShx1%xMx%Z-eSGr1)}Z&@C3?CtbG=Zr3ifZR8tHudc{Cw z5wa@kNc%n^rX?a|r^4OUorqY} zil&KL{7xD(0Hb2ID+6Vta-#JZiWX@$o6qpssw#V&O1TA!)%BubtL5^>#?N&v1=fo^ zYV6q{ej2P7d-%pI$($`8xm#rE7(uH<7RLxV<#6G>f%H376PtR?=L=v>kry~Gx=~Cw zY6GXvC3Th7k3eVKgecA^G;14c1`Newv50|p5y_Y*TzH^TltY17ebRnC44`CIhh7kO zquH$KAjpN}T{(_c`Ug3z&wSbroKV=?rEvMW6AU+so24>Jf(Av>C{)u!zbg)yV{D|o-P>Ytc zox&}ir}HKB_|6-(BmhU)ix#V_snMVJlR2z>h>b~(= zl-ST0I>}Ue;D}=&MciW6Mem3>o@E)(3Ks@)hZu3_8Yu%9jBeV&RQPZDoW&}P`_bEi z*7mfPcV;rT0#(OE{1*YNy%B?a8Lb9G7;*tn5;Ymop%a$G&t17THTH&(F?!Mi{==W7 zG>55~Ng$8XaN7OJPMl*>tJS9MIywwUl6V{_^^`*ADBw(g{En{ymiv2 zCTwVz!VGk3<>+j%fG_R`d^|~FR}MsaHS(`i7s%!vuYv%pU8;*JszJDm1f>kS=yhXy zpJYU<6g)_?dEZ2l7s;2T-o!_cmw5xt9{oH=*1Oa+hZO+; zM+!{zEYFKHr7)stZ%_>Qg$OfEdNaP=Y=@E_I+LfkV6-^-hNi3LFXp0;yrb7W0@hIs z^7$zBLFU5BqD!GQh1A?fvrM}C;>|!Scl+MgoE6fThyA;TU5vW0@K2&Gn0jtIwxW8X z8A7?ik{(DABGWc03lgI+#+QI1$%py*L0Ava0{_-k&B7pouyDH}G9}E&-~c0c?hQ?y zSX30{^d0mk=AxK9lTelR^AcWyLm9SMq$0rYn7SHV*F_MMHcfj`7_cHpbI%T(s25GD zo4g1b9IQ^i9hSiJ*C+@^W1#Bqp}P7iq{I1rhb|+?eZ_y^|JdlzuWTMI7ah zgg`n)628KTFzrTMQ&K>qe9Oi{7%$c|BD70b@5#y_&-4ub!XnRr)8Mj!SUcl{CbCXF zD~dQt^4ToOlLlv!tujV{)2?aXu67;$|GH7~aoz`oI0sfjc&LDNSM&byS<|pghhYa( zFKQA~&(;@vE7zKkZVh7OCrWs?KR=3q{Dy-`^>iRvt>7kZbUhu|b4tsvefsJJ41WSP zlJUy2YNMzK)h^jzj(6^Xgeaa4fQ9|!WfsgMBUf%2D#gjxV#c81KFw2*^!sMovOJF4H1YGc4^BR$D;S+=O z@)WlKlBrlw2D}c_7*uPs-O`69O(aU9ARsSh;8_IL(KfV2X@P=3AD~>(J7%CQV{MEbTq37SB<+D{&rDr{{?!Jaz1pdl>PNXZXk+ zSi+Vp3tBSk&eleJN~ap2-uL27Pd`+i9r>xx6#LLueYe|gU%!5{SzTdKSw+cDV8r4$l?X;2bvxyv<=X-8~|k?!ZCSddea%xbaXzc zo3;aONfQ?3&StZW?!&~gx~`e+9t&DCr~Ix^u+F1ubacTJV!t$H36AkPoPu;9^PH!s zSoewV0$`V>^*1&QeyA5?LHC3xnvxVu$0013S}#qi1Ih~$kg!-@fKL2M>Y_bhF5Zv` zT#UZS3gfg;yIl#uD(TjMC^HoXSI`%%r??iEh>r(1P){!%#FqGz>MCw!f)G*D;F5s8 zSXNt6Enr}21KpXPadD5UkK@$$SvSC*9d;@~P&b>aSFhf_{C;!wcIvw#rII#|#PloB zqZR8Jk*9@eu;_-x$zs0QHr?2bs_%_7tpBTL;L!&f2bOfV_wtebeHoWbx=C!YB1E>= z$B9E(-R%Sz*WPHGvX(TF-;DuH^bfZ3Hb{$go( zNu&T;afd#N@GD@M?C4Yc#ikX2s+*34th@uoNet6ku5VZvPOc+^$lK|-&`Ac39t=b8 zPd-Lw9+CdnArx zfs{-eM48e?EMTh-Y9qkEyq-mnG*#YQU2opLZMJJHBPXXP=O-tZr>9_$tX^t63^kac z4`QZ>k9n5TOrpr*T^#{(Wq(w%{>MP$Pyy=^$J)-kfr3RF1qv7djv}oJC+_8&NMnqI+W&9bST!Y1iGhO(=sq*12Jw)X^$EM<#FNy9Yaz!FA^Ve zd})^FCyOOMK1xg~+m0rR5ns{=J&Zt+Lb}ZRex7E`6Nw>~D|2yOe@4+Pj81egNsClV zVkgdB10CEc>u)--$}&bUf@OJ;VskB~y;xc-ReoY^NI!L6i@Y>@{6%6~!{Y-Y6KO~R zP?LNf0$a8e!z+$bx;RrxFF7upQ`b_f1*D{{70ICJ3NXCG7?^=Ni4K9X@f7$bP!w>C zyOKzw8;{O2cw{+7PyMz0_(NbMAlMr`@asHm*c6FtSHQhKBx z0Bsv&0@FFbQ*KI6^l}*_$ILm=Gqlmnx`;>tF$xR)q)7zO3)4IaBey^4dI@5d&e)2y z@I~vyDmf;e^)Q<4Zf95+oQk7+D2-8l@+hX#Je-Ix#Wx~=C3|tDjg($Gb-v4#OGi~t z`SjTuXr70kEavk(&qi_kYP*K!rwn@O$;nMXyhq2o-L|ag8<9{1&!iQ=ad7>ax$)Lb zh6cw@{ou$NxfXk2XzsUCDXO_INGE8^eM~>R*|=ca8}1m;GJ{w@AgU847ZnNpQE@#Y zWE&CW0&+cXVhgo?1bs`hG|ZBDmOVK?dwy|-kZ|aTR_pC{v)$oaG0+i?>xVOZogb!b z(3r)sQ`Q}=ukI=A`q^E=JFdCh6JpPg~=Y#IByy)qXtfoiKQ*B3F{;| zt(&g#p4g2#bN4J2dl~M{MJ^xDCS4~>{0T}TE}9W=2LW1|q--cH1#Fm)2!rOcxpX|u zihM!kQQfd&S`9cd=ulPFY^;-#ULh6(w9(dzo~8q0M|xC=gYEE1YK{_77Fv&?dR-BJLj2 z2efHg>FBpxuUETrhi?QubW|1W%ctMOkVvvjDi=qw;v(N8!4wIa3iQx-)Z^mh*n(TL zPE)gqkR$~owiNPxU==qOr&ic&%km(t(l`sUJWv+zm?g<#mWN3SFsu4uTUEQN?uMRC zD?HOxjThEI)~7Sz8`gqFn&wed20`n&UKXyo?t@zPZ*`V`_Q8VBnYPDu?NdWe-kJ6!T&>%LrlC>9g3hIZe;b&aki# zQVUHt7|+h<{prc+#H6pJ?ZpW>j*}dC6=wvCek{v&yRDg@rY^y!L9{Cvy^H8 zPH?ie(3xaOzfg9*0ptK%XL+8ALn#2E8%UU_CKm@{ZZ-!2Kr#_ zc3T=DgVeNa8BdNz&*G@9Yy1m<%aWvuD>Du|k~s1t5r2va6@zA;s;`Y}YwsD&>P7&a zVtWa07qasfKuQ~WPt#VJYLFzFShG!-rx^_6Qu0AXft68)eImP#oX92BeV;8S;*jGO zLSaSqTC`AD=&Fairq;f%gX2Ubr?kQX3;;CpG~kp`(qjxHDT3o#M4E>$YiW2fD3TjXa+NRivL-D6XNj z3}r%Ea~el%NSHM=^X&30_u~MxsP7s|-jf`+h}-;01cI~Pu9@Is6=6dMt2jy|aW5tX z9zOfz@=4RMc^{P)Hx@S*KfyT@(ozP7uU@_YzPZhTOsWn~n%Zg8ilUJ0RU}@=^o>ZE zaYyiLVno4yfb(uC+8n^4h;S^!3@GICxp5Hri6?c2OcWZ%b1XknY;T4iN1}+G(v$(O zJbB!31$R@n_eaFBl$s&r1ee5cs0AZ&aIVQ>fa9cy!VLH<6^%ZrXomoka(A~oY;RnH z)G;u;3jhfA1%@8z%@xr$H_(*$ZL+w}o4igTHbKOND2%^lm-t?MwCJiXeX*jpCFKeh z;mPteO%tZK`<5M^sXt&U8W`gIXQ)D=={S@0EqzWr!?q60W_N90HFddTe~5m-3>Dcy z!d8NcAZQR%0uY(GlGIM5rPY{F5~oF|%BrC!bBfqfYViW#2IyB%`#8D;XS8q;LxVVQ zZQuh9hIMgyQG#I&PB+`@FqXna`WhB_4s6?Pw|_Pkmm;|;Rtues=do#Fl$F^NvQjF@Pi>513nATf@px2L9UH{0zj zpU-ATPJ>R_B=i}~fvwk$9!U}*}tR6NC|p3mpNj^%O*48?WP7eNwK05$wXE6P^! z4eT!~<&e@;$ha~<>15+f^L-(4bZ}R){Yo68SWC(7YR@KItc+sW0kI4`mmP1IMAQPq zo()7OGSR8Dvr(*XtnH;CoAfyZ42nmq4hV5&z1?7(OTMZ~ngfl_!0Yim+h61rd`Yx? zAi)3A_x-)N0fC+$Mu8tnB@RWRpeZ_IsSXxq%y7#v&`Ohf9!d8W>?(>{%!QY)U)OCn zpBMAR?1EeEOQ9ZVAeDMGE1O#hH3P924th=8tEx&0i7EAFqIx1kqzUs%3^t?Klk~p0 z%S7zE%5;0LtY)oAKZsXUENUzwS5eGluQMb-P(v``xREG9jS>+Qpvtn7XwN=ftyUIM z9zbg`pRHzj57IXo&$+IQzO)9C3TJ-tw5zt_Nzc4Kl?QPgN^2UxNtUDlR<L}l3MUGyG=?=~felcJo2aZGu)Vk!_f4y*ix0)y$Ct`VIz~u2H(?3m z-gg#f3K;E&28Su~l=k^qLcK0)O1{8aD~Ob^HivPvK{3ss@NyP&@PNiRU<;VT3sU= zdiwMUjsUbmcqZ!6wxRh+0E|F$zv%#rn~DM0Ks?gXf#z5s0a=3ymi0;^2N5S7sp%^^Ig;*(zYAUj!}0VModHI4KQ zqcV$92E>wsw0EA(iZqEAvx2RsStcDwBE4fWuJ2>fM3?{psV^XCoueus7yw7btTDj& zBFlh7_yG;m+1}Mk`G7RuQZ|s5ik_=iBtp5CX%e&D*eP=KJ#Hqj@gnylSs+CtFQ@(r z15n3IxGGSNmR`LS2G9m|x?#K01(w>0D9$mY!)U9w>$h*OU%YsQS6Ob^N`t?E)h!_GE6|3uB+oXQ1e3SSOPI;$7Bel%hV9EhGxWc9HvP#4~3cF zadS_N5>bc%l^auq&Frd@omFLU_DI!;FkU{YlgTt1_=agJcEW5ES zd$?OVNW@I2gw%V0In~3e{Ob)y$nfK z$n6Uz(b;Rr_)J+TMMb@$=$246PQGW@CfbtH;=>6gv{(hQI2<*r3!U2-Ptuxq>b4tP zQ#ZHE*_8RtGN-4~izXJ5?njuL;A-o-dV6*K{dX_^{Qb+cvzS;v>?)APT&E>1$22y1J^$8s8NsImRcToRx`iD}{k^8d2CT z$#I7;vK%liPs;={MKg(27W;+)s3wMf0d2{G(AhQ{XZ16BqPAroQ99q?++45Oh&uaB zc1i}O>@DI@X~E5}^v9`c+Uf1p`sK^lz^vV_WCvCH?3?#aSReLzKGr|q31A&JU+;E# za)F5?r$rNxg8>d%8c<41`33$ z?!+&F)>Ev-VK*GAogz=lZK!t=yHA9hJSbiL2on{HWf;&6e3uELFjZNBuokEX1{BK9 z5jyu3I&U7pNmMTXOtvm6jChuZZT;&z}o0vhp} z4|+S=Ns)fh?%s;`v>$1D=F>RU6%q)1OcX1)w3k6}NLdzJ76EEm$>d925rEQDP7F&l z>>6AU?oMOXW;9-1_p8nBYPD(GmSMOK+&;jM>DB&Bs|ThR3U2$Nk45P}k$M-?E1KA) zd6v}KIJB-b7c+@@lHT<9HfPNp6~LZ<^Y*Vg`obWZJGb61$3fkeM**4%`bH>O7|Fs>?LZ!5~jhPv(nxMzSMXHZ3NoysTlEm<3~bfVA_Vq5@&H zksZHDgFOMLrE_)&Ud93FT7WBM?vW1`IRz~4k+Mxjdm5Q1A zAnJ(8wF}FdCJgCtfItkqhDF9bgJ6qzOqo+mLF1<_&&GLVY@v!G1;dCyuM z?&MLGJ~9#2^~{7NVH~mq(@7qrPMZlhcCV-DyK)@ZxE?zW5Vdvs5`14-*V}E`w)g^k zSPe9ZV4)=k+L)hAVBG^|J!ER|^Vb%9+~ww;BqyoXk{uPvDrd*-S(TBuZ@U*|9SP!ZL88B+c5kiKH2i zwES~6>O5#&SFD?1kL65>*^2ATW!dL-65UcM9?tVPqG(ILx@T=oQw@CsT7x42Es892 z?M@Ng0heCBNW|fbjqLFaBY)@|k46BqEGLO~^?os_NX(>P|wYZdJ zNyQA!XxMoh_~q^hJL3cchGCQjJJNAcI#EZQ9ZHJ}>wr&<5h7#*HVT3@@Lx#;N~+%e zHnjR>(D~)x+6N3>_BS%DBTn5;RA_}{xjr;T)TDLW2HPD1MA^-^l%&)6vu*pP8~fqx zyvXMYSVnK+&P-+t`I|q>EF~1?Z}6Iw^?JxV?ML8uW3Z|#Ny&WcIioZ+)f%j{Ce5qY)MIM$U+#O z4U=OQW>bpU%w`LEL}jeMF^D+Js!9M!5@ac{U{x6lZM zu3eBYBQ`6PeiIlt3a=PO3rI+BK_U@O6~`D^NaNX_#{v&CgGbdBE#H}l@<1GW>J<8s z-G+$i0Jur3p&dst(-NZ}BcqxG3D90-b4s%IV`x1;3(|CkcyL#CX1&{%J=rar&LVhE z+O7eydky~Kmk)QdT+$k=2Y+peb}9|)J9IBi2LS zNs`hu&-?9mTUI+G9ROLK!&f|CEP4YxguwBHod?CxG+Zv11wJYEQtBOG_7oQk z>~J_v;yiD5n_aot<;6?~KHbiT9#I*9@?^P0xW-QIz$vm4*UOonHk8%VE!d15vs2oW zZeVekr|HGnDWC`;7y?d5HbSX0UQ~;kK7XxiO}N``L3Z*yJ3BwcpISC4lPEUxyzixm zngfE*1>%1%U1g=6n81NJ%FuUI<4dy)fEAj6yb-~qFTE$M)GE=lnBuP%0oyc1u04@L zBuGTm(v4_f{z_XNxOP8QTrPr$oxqf90VxrqrPm-(%y@0@5?e;%aWA6oH1+G!_U(I< zhU0{~)0cmKetsNiW0X-bP4VBumuUo4hjcfbf{`*+)cHPxfjSqVag;9qPWF|o?dr>hi8{ph6Q zyY3p&dyxiwH^L+_pFe#DLWlRH)Reh4thC%=XN#1z06c&% z^@Ear8YOtMltieEZZPl-dZXVg)hY3Fs@l&em(K1Uqi@D}sPT_X5rAI#+ z%H<_$_gE~+VHaOA;ja{?u``%29gL<4m^GBl$T_b=8pCpPq3@)E+rOjlFSjNlk?)2nzxmZfSFCTB^ z_EbL^FUYd2m=y>C`?jx21a^GU$uipNk7A*&gaC|b;B zQd>8;mab)8V)7$!TAnP1vEP*?LdLeO^1L`ZJ(sWY$dUZ2+ec^O$W9? zWP+T)H-)1wO|zMQilaP9W0nUn$t68usoS7B*Y`<9!3w2kZ72<5vs}s&JyE^cQC0%+ zbf2Vcy~j;IkhzKO${4{u7+GyCsrT5E9=J4su$qNDprf-IXQ%zJs+w*Xq*P(Qv{zq# zGw=O7?5}3n?Bf8egWDOA5X`7a2$wH%O=fDP_Qkk{dJ)AUxmEnZRZp0c)nn5rZE|fEHb`+$PLOwZk60wPw zJk8^2wd#}7iKh%tj^4)vD}p92i9L!u3d-16BMIpPkua@Kt?3vbSk&T~1@hE&lgF}3 z!vaH}nLP^M>BcbHI85nRfgubHRkdmyxnlt8cXE0f#o3~2SDW3Wyw!H4L}vQ_br|&O z7G{vWg?D`7i5@Iq*~3Ct7O;$>>cNzjw!_>lq%KmbZ^Q?R`}%Q~E#{(`9KE`#ciZi1 zwchS_Qgx`D2p}Z0@FX=eQO;;glB6T6kNd0ZH`10SqWY00C|y}rF~whuo4}_4m}Z!o zvSAj+h-};gF8EH+Ko0{1Tz*gtIT!_?X0e!cEH~_!v+f6`|9em?uLcT4h&1WaLYXEl z4cI6M6py`9xlw2YD|6~&De0JiKeO5F?CfmdKIGUm^?HMOZYbJd&CE#kWe840Z)ooE zF`Mr(1eRtrlMp;yWK44f8cqwhVs>i~WokE!or{?zI>Sh^>wHE{n=isK_Gb+xY-158 z8J4H1q>`91a%DPlnAVEE-`qsh0ag|%WuoGg&C`N-x%8^Ki_>dxt?cS`)ub4k17leB zAW!rd65bD9Q3b^`5dW3Fn+n8aU^dw}6F%m%ol_-u)@E~rY+cg>3$CxPTQ(l-xzcDm zn{uTSkw$XEq-tvR3-d{`K&jTN6;t3RXW$g$m`qc}_7iOS?s?qc7dujMBBt5sFgR&9 z*d2b~_Fc`k%uF`nXiSgIXO~Z&0FG9x)!Vmkz_0)enE6^Pfqm&*N_7Aa8%VUPq?bLj z@~mbgKk>(|D;tnMYBt7c0M`QJqoG7u4nrroB`spj31m*oPNKMmDdU)(^nUm77b}~o zOq%;r&NRjB&=Uht`nuVb)inz$*W6AGXoW%ZErgB47k$(2Ls*~ym6D!4u^#~Y0ze#f zszJbhMV)S2BfL*J=Pl{D#*VXqBNjlX5l>+9!U&Mn=S8uYpWxEA@} z>rw3z-f?4%pZVzf{cf=em}pBbo+!jH20N@@kv_%7HDGmiB~lHOavz^M05(Jhi2w$G z5U_O%>6mn^7(~-RfB1y@r5!>-AkB;s6SK>7jKTC~^vSh~{xkGK;mL>q40D)W;bR(G z4g3nsI?Q+4IrtteV$!r=KM1>8UyB6XNaw*o+#9AFvlrGU`&Q_p#I2J{yhq&T1Ee(#c}$(|g?2qz1WF5A*?Rg$H7o=g7P6XAkHl@yWp;;a`+K8=hLOsU9b7(B<$@O7Y2 zqVxzoU9o0J3Nk}lp0Y=(@fl=J(yx%~0%6J*3oXhh7(pWb_53KJ6Ch!n0uvjvTsmRP zZms-KgsQYL!<(fqS(x}?j9|C#@ogKOW?(8TYXvLy}-dCUj~iVgQrG zInZmmcIvD&rUr;5Sq?NQ!2Y5%WF?+-pQhA)>?&r{xw8hw5yxTb89-Olv3!mZN+k0O9GzTr&{_i8hQazG~v>VfNAMa zi?GzgH-afrzajk@0f6kg6A(X@4kdS{MK!^ejW}EO?GS?I6c5yh-G3VE(XftSUxDLJ zknR3UBBec-bVHU_^U8*Zb%0Hyv;~zuqYR$3+hL~zfoq%0IZJC`reY#7MBtrb-eoxV;_ck7z$QZbGLH>%sPvAv4CbW z-u2eN#o_BliOT@QWyQ`EfZc>ze9_cPt7(ME7$9j+*Z>tZ?HN3_;a~;|NpJ6SHy&rUDS&oXWlAf_Yw zyM0^PA?1*>=>)!pfiAZNMVaMEfuUh7EpM9`&sZacIis_OzLC1iMum&DZ!;=9c;0mT z7qH(sEPKntcK>%@>SXvdi=f>iRFSUriZ&^Dz5!sNj-wbskLZ;q8lOvJy5B_XrC3(%+bpPG=S2x+qhxggNEM0WAaBx`xU4 zC_=uJ89dtuELoCowCvakq!uYun6uN_KxVB$KI@- zjai{}h=BlAE7^m!Lbx_xEQ{G3gY)L<`ak~b_y7Da|KmUZ^FOaQYiX6*iZ49a=oE+H zY+iiz?Abs3{onlW|Jy%?G2^!&1o-K(?*Wwv=$L4up23->8u7NExO5aNE}BzJxC6eV zzrcd&(T}lqn;5`x-jA-^VkDcmAKKqevVJ_f?V-cY?O(v7NV@K))icHj&jvYwP8$?K>ow~7Ao#9lawR{VFYMZXyvF=)EoCTf=6>4ZxLBCEw zHDcIFr0+n_NlW)G@Dt!c+jfXKZ7j(-8!;-xoM(>>lO>s$e1%Qj0XJHcO+ zc8mBKQ6Gg2X&Q+-tSon%)pcF&R@?0#{`6;8fe1kPNAK?d!W7vvuP@qk zz{+@|c_NV(S7wCokeM4YvrK zS^JVc?*(=S))=!#!&pigG+QpymIdIE#p+m?K6z zS)QIQPw-ux^j;oVlf#Y=FJHgn)-i%vRDk4Z49K&0CeLx9eB) zR|PZLIRZqs3S&}9mZNU$SDSTJ*Eq>7YanZ75th#Iy_nfF5T4j)(1oSqs>U4$+BBP} z?Zi@$fJGhE82W?Y3H@nosHN)-ttmDe!&{Wl{SKqyQ@d5|gHO(LX{H<6R8hQq%>5Tr-K`d?y z+*%B^=S!MTHHK7AhcTrOGMpNtiu+&!u)4q%^aRRtdzAE~@B6B*uCL$t*MWKWQnKrL z_qq4|oER8n2{4z9c#8z$M;mld5l?3Ce%Ya=z%!ikApHdnxe83POO z34BYPk~Fo)LBVTU$~ar;(x>LLA`-ct9>n4&z8r(IRO_1`Xv`Q?*y zz*e5do}XZPvyD~*=&Q@suH4k1k6qi(W^>VM(iK_~@Xp=EbmD146F!NX*xf?W9ni_3 zL|MQ{8SD>dp~c>dOOiYmdGQCbuaVbi~1O3RgwkJ4gbfDI2|l{;-Zh-w0@k~{DQM{sLl0zpR&t0<-N2e;r_A&neE22j zK{=-Fa&nIAg5m_uN7Ir{QO4c7PGcJOexT(G3lE1rnl9=_KLC>8e(uUNZy=ebtUc}H zR7euWbfFUWI}ou5U=>Edgi*HQWru4h>gsyEe)9a;A3p!=#fumF{D2<}q+#z0{Q%6! zc33YLgZ81>;lO<3emikJ1IT7x&gH1K^r1r7ogf)j=z-EXW$qA^BLLNyJ(3Et!ZwV%Iu`M3Z5?|%E+ z-&Iw6c6w)Zer5+D3daqYR9VJpWI0wcOZ*^QESDfb;Dsm?Up#%X+pIr(`sDQN^z7`E z_FKc?m@|WOgLLV^o5X&Zh}V?J+$l2~WTZ-Opp5l8J9JLbe`3IqW+xxTu* zx_VU?RoT{Rj~APwG*s4!>-xRwtQMS)6V!uP{edA0wQ_xlq8JBH(q2s+OGBOf#Pl87 z3R>K_qxlzJ9T#U}ZXl}9G){(qMXN!|);Co_fa4uN_+D@~Pz_j!-NcJ)KnPllbE0^G`ng10A%g8doL?eTLeT zTk+7qXC0AU9dj5d!B;p?3BTxR*s8e8J8}|9$P~wixXX#Zv4!FG(x3lobA{6nwnK6Y zSnuzt0&#I%J(DpM*RU)Wiz>F$rrm zndAr&Dw`OziG<6tP#9`|0$OTu+?Wn^(%A|nZIp!!d;YX~!ZK5R+vSIx!#7>C%d_V< zH&0%@!q?Sq513sf$^7KR54?e9DRfKWu%1D`n$tTMckbM&yT%QCC-ipPE$x%5YS@k^ zrzfCrev;N@Vb(Q!X0Bt5BqZDnXj+t(xVJb$wMNN|pd%Q*DRgXuWiOx&Yrn1ft{MDg zv^qJNBxW@X(l}n=0tO+Eq$u!w22F}xyXkvy!^bZ^f4RSOV)x-s9-ZI0Teaj>O41wp6&|9bbfXQJZdciCF1G%DMb}|2Cn$|vnQ75zko6c0c)};_-7$#aT|oc zTvn=<>u{IQ!WVsd#;zaRR1 z>hbfZudc7~gY)J5-h=zAlNDChA;d@n^fu z));%r&^g52fE|TFIG?3}p?+w^Maz&4S)&p+L0lvD_JRoPmD!Kl->UDKHB`4COr{d2 zXa;0+)WBivE46G|{)#tC$t_CeC>3rTMOmX%FH8JWC5eq+ZkqhsNH?Wk+ zbOv8ValkH2gaS*_LC2APcQio<8>5!W-}`k{X^#Uo!%U?e{s1soQ>_dl_WdX`B~(c5 z^TRI7nqdgj`2NEOKl#arcwMad&3Xr{;=~DUTkzIypM3rl_3G)_iG=WkA#0xj%RLtt z)EBQ_0WWCfp3cn4^6aWD+aYKqbfO$21s3aHiwP_`x=;*i^%igeXNMYaqJ5wwCsIhE zhEe{#pE`QEkkfD)+_z?n$*F2!=(86uKKblZ9NMq{^56Y0|Lgzu)1Up>KmPVNMV=q_ zo5|==kb_ooOrWSXH=9?pSMx<|*%PqF4}C+;@Xpjt$qdBZI!U6cX~PK2?oX!k=mja6YWgc69YI4Vqx;d}Yg-siGX+w?5WDPjz)Pug0p<7GZ&FszM z+i`!E31qfB!oZJ$5NosTJA>o2gASb111_G!J+lO4W)`8sVjTRy=NxGw>cmNmFFawI zq&ey!PUKnQ$IOXlqL~+ni;VPEJQrn4)dMX1rs*bSh|@rNdU}SZ&kn+>wuh$Hwh%l$ zV9oPq&za*oO=oAPs4rdDkCJ53cNAU~#iyS=1}a8B{b_;~J1QJ(Yc(hzaXs*|pmpF` zP1jO_MR}P_QPMY+cJFu*0+up4AQVS9LT0880_awc>XjXP*@o~eH!-crG%wfJ&tJTF z_WZf;M}PA-|MS29_y2o3U%tA!B3EUq4fpKC=xQ7ru)uP2eRDZyJAbuWxV~@kmND#h z5#9qpDoz;X+u5D-4?p;DWZ+{376^(ovZSq>g4>^US<{b##UVE`QF|+~j>Q{;TM|mg zkOz;ui77r@<94@u`SSU-`WC#Br|;!*d}}v9`&}h>{0JY@>)wPVJA)ma7zS&Stb|E% zsH3A0iB*V{gp6^a)0+;|Le=L)peM6A7z)-vD=p!!>unl=hQ1ftwg;rcVu?9~9HG>! zmC@SHz%&ew8looLz)&h*dl| z{lxelqoWV!u@b}!d($X=I>!%OOJtT(2v4#ZVbSF{i13G_(!nydRTzrNAPfN&{Bvy= zHN#AAHaF|d_R$CP4?q0q=O6#vFjbs}j_)YP8v8*gD%(^Ga;$;k=oY0f=! zf?!H#xY~9jW`IDqPW(*g5#})-dRuO)6h$;3ek(+Qs=n)WFN4ai9 zH)PR2`2ki;S>}YOZV*4G31BuF6SKXl(hh^gY<};sogCLs=E?_>lgHnItsbdUjo>Lis> zXFLl$5y&QU8pJGNG{i`Y{$K!J%}Rg?W{^aInYve3>)r0ft5>KT)7kv=>`Wi31ZX>! z;~2J-vbIda2uWj3*D(f7jJiyNyA)uh_zJ_6+KGhQ2-Jqk0ibra%us|ELE!V}=z_ti z=;?KS4{B3-#k2fWy01=8#;LnV>zi)~l*|v)L3yWnZ{H_a*JR z0bA?2U>eCW(pBD81@ETj%uDb#2yl%X;4wp6G%6;_#)Y70($e;CPQhF*r+;IEtlU zoW9t1|FLaQeRJn(zlX>4ePURq&8mqCO$Il3I_#8GO4Ag@tWD1oc4cBkDRFwC_#8`L zEM%lXT%$td_?t<&J9{0XH07$b#MN>lcF42gIekVhi^coUbBZ<5tcou(fR3_Cs|r`-5hoq3O;V|M~Q1QU^y?c!+t;XqrMAD zoH7HIIZS7W^E|a(>~I0%in3VWY_mfSniM2H-K87{>mQixa-5j$9+R1-oDJ;sdC0|K z3>Z~wF0KL%Tu_LyqzXm}2n6gJG;tAUKY84&*N;E@e0SKT=`sj?(MA|WKOV}uDDt)` zjDhye#(*OnB?glIr4l!IY|4!^4jhQu*^zN6Z8d7>Qljf9i^knK^n*Eyktme5N!Qjj6-rnTSPH%)E1AD!!?D+| zAjF5yYf)Qec_@IyHMnE#G2m%k)1ixiGOD}~YxX8D%R^BBuv&)Ycy-r!rH^N<>dFto zmFLB?Sr|r~OKj@%^Yafs{P67TJPPB>t5<*f|NghX|L=dNO$+4MDbg6Y+Bv6U%4Qta z;LuO>mMQB4!=(?PTE=4O6HZl8(CP-SOS!zGM+LP9v63w|uIB;hWlWZ&1P-zh$zXY( zgUw2Sj6;4FLCxT_cD3DZcl#ax+;`jk{*ym^3V8dc-~ax1|Mc6-%a?sq8O)=XzPh9m z%I^216Tq}YPHC6Hx&id!W)R5)kj*eN&TdLFMk^Ow>3KlgaAdc{865C6$;dD{kJ<7* z(Ka}K?h|?w6FgA-+moXbJYy8PwBk^=waYgFdG;;*ywznrc3OlD>5hhs;Blo-7W3{T z|DdUq>zLw7j#U!IVU)%(zNM)v$xt`6sk<#vrn(XlC8JJSWeo>-0^tDraxHB&js-za zIs8pP^#h6~1zxkyb1dcp;L){3-IQeoz-s%J4p}T+xa6735!#}LAuTb?VaV{ifrTMY;ZJ)GVzU^=q zZ=_RvT>)%Ru{th8bvz#os;?OZq(`z}@92q@^F-5XYV`38%9gnTT!6lA2Y_A=?6$Z& z%uvIAP_}d@T_=eXW(A=DZ=2g7=-XYw_v<0{ZIdMgNNNDwsX1O_pv1ApL0r$-BcD|7 zG6GQKSTqgZuw0MviX4Ds?$*F)c!OuD9F#@HETKV8 z%`F5O#wL_-1J$zd^E^k&!CH^;&Nx&Y3zbl9)P^>-`xM#g>kB-u%FSlI+wD-e$su)D zSC_y0{qKspTCX>|{hkcf5RLBZtwu>dr7*&I9k}f{HeS9gb6__J6^Fu64?1pLmi;so z`Jq8cNQ+TkS-eP3bBhs`{G^X!aSb zc7eQmz`DHyyiHv#!^=vPS2D;fmfs*lqbZKx{A5!h37+7&WDG9tlh|c%yVhm@ooa7e z+h8ftySI$k!#z9TcuL3=Jn@%dZ+f6Pg5t1VFQM(+w8!rf+R)}jdC0S($a<0>5k`0( zP^@J?tGv8gzqq>Y$9{D>KN|-piu@`e^=n&v+j6y9EEY<}Wf+wl#y$z4oUphSu&PyJ z>?}*yq8vd`%kc)U_sObULs*F=yPr7lS(3C(T~NZVJV2Xeit9Xg|MbyQfiO~PAaZ=V zCDcXL#*Od!lcYCK_JCLG8vH5``#nAEha&`(b-CMb7ptY?Ig8WP@^p25i2}8j7%xsN z8e$zyv47x8%ookpkCT!TWrmV`mZo?|%A)M6qAqfvw=U)7UNG6?vHe8)H_^CD0E_#E zVxA?@AC7P8{yO(WCedz~CnqQO??1e{zRvSZ+cv1z_73m;MB$e-hTey^^)18t`gOHn zz3lvv|Cn!fu$8oI9i5p>gBE5ihfG6=Joefdlg9*O#i&pq%V0^6s-fg_KVnH?d3Y>v z$Pi>hkUf=AXMswp4oF8;ApRFO3&xcTDX)RVfBua45P%S&6a@i#&+9@z0oJ$~e{J(3*>5C{gG~fuhCyIOvjz z_$4JB+wfD%BDA!WuQjVEfk$v6)AYDEhnfk;-V?<|4n|-3z>OnZl|2iVyHEx9K zN8LNswt%Lx5hDlR_mViofzhCuoxB>jucRK=J@P@yLQ^QTwAhTX*Gdc$WRVKHGA>FB z8bPZ`3tG}7IbEG3Q7rj7-S_tc{(f4_+us75zW@7)U;7B<b1iR)1UB1FD2a!@E1KJp3eu*j_S;=mmiWu% zat>s%EtAKMYse8vk!`&xIF#i|0WqJ;(GY{MZt5*_YR7YR} zELohV8$&EoI-=BIOJ!5b%9#e&a|u}T1;7G4;cI9cdaqP9wF@-Ms{k7V`_Plb&)BXP zf>%UovN}6kEth^2rQ_61Q@U7`WxYS_-QaOe>84Q><;~5SzM!Us<9Yh@^Uv;H;M+_y z|GR(u`%nJx`z+g0OCe#eD7$EF6DPFdq+*`6Jcj9VIbr`dk^YCTV6n3PZx0FRl)G9k^N&MFv36t>84GwRkq(3hpg}F7S&4uCBazyzg2Z#`FE3{`8}|slqtE+-$R^2dh{!#c!OYbKvZH zvw8gZGtUnXhr@sPKmU)v{cr#Eu-nS5PCEfBI>`GzGh90!KWHBCDk~1`!8`0vaj&!Q zY)d6kFi&El@X$B(dT&txR!uud#Uvw*re4WPMj(L@00YmqfL$VUGKaRO8LLHg|LF8M z5iqe?nw+1V-@kkDPaAtQ*TngZjG^SdsyH7LxPJ9{fXpfRLNY4GEi*M>NnKcf3EC~ z4|P-0!i4HjN{w&}E?HEe++aKmCt73{L?RhFJP~RRGNf@psl^U%L;v);$gz?^%;GRe zWI+O;upqH&4cW_^lnq1x_Mu8~qnbjbxzlI zpFaNd^6KivlV|_w|M`!f|KSf^U9&8cgg%M1P>%T4P^rQ4uVMSFswp6#M@7r9nW+ad z&*CH^v`K2{kXs#OQ|<9vR0vciwVAumqfcEvtx>pGGV zivq_9j*6xm+<>KY5rF9%C;S56Ht(@n^~M|A*=E|6f)Ga`;;YcD_#uJM^53< znA~$*e8AgIw)uummM;Aa@U$(%N2@#oV1bl1Skm-`tE!Q$qZT;BwZJJ8<_4~$7vp(8 zvs;E%B%>901BgMGCaKa<7+%Dt5X6-x`ad9?}{t~%-PE1nx-y{GBL)M;rOM#W&HAPn`arS zSdRNC8CRm%LU!yXW{7!IhdNs8$#9^7GcJ=um-@j3BB)M@D=P<=9bC)vvr|yTG);-% z_^&K>+bv#kzFOcI?%g>%Jz1jUv_Y~0KS>hQilARO9MH+@t1F=A>2i4w1>wmF&WRhi zy$l@6=TB6=mdx3(|L72{z*s?z9g&n!9}2oTi8Ws@C!rCNfO*qKdta89|&B%s(J+iWJY zt_xsbpItplLV0DC_ol8|V>cAx^g!6M!r zva)UgqA99PA$Q#P3!<|Xtzk{qBHKBp5zdkYDyum3Y;(Y?XNT?PdZ=^MUpF`F?RtZn5lfaL zD3*c~KtR;5rfj7G3O#{zibRd0-b>0**?nxMmUcJbS51S85kG%%c81dP;_MEee{=oh z>GM~Ym)BR9RaJx>Es9SUD^O0R$ue1fK)Ke|<$k@ndG+eBI|ROaaUoG8dx2Z53^H0>Nl4Aq-BY_K$YhOw>75m zk6Q=dBz(MUkeI%UpZyb(PH#)Xw`WOy((}2z7mIZXyVsN& zb-*E-`Sq+6wcLS~&Z`RkZz_75sm-8eIQE^evUKRQJO1)q_?6404u#ElT zkmor#A=W>ttF9-JWHhzM8rc!Q9qto?D0&odNZ6mD1t9`%lT7Pz@>;cyRhKxAIP&kD zod7=Z*B5us&Q4FCJ%72`Y$};`%n3cCCCLy>`l(79%j1GnrJ9D5;>u5Z|N}NN~ zfUF8o_(zk^-!y#uAWF|a#hLFGu-@uHjWu_&r7bIpbW;ohKzV8^hX$I)u~8##bzlv~ zByw@?-xJb6A^MI3JjO8AL*3~d3cXY%2%dIv41Z>*sefGQbX>Bm4sZy5Bx7)`czCid zF=YDA_5ul{&^m#UNj42uVLwiR?S1sYPmF^x>n2ap1j} zrQ7WmOD>(y?mf7FcIV9GcwnBR#M^KCrU_kl7RD!wSrUd*HvqrZyKS+#vie4K4N5lZ z2)YjEiIP?<>PbAyz{4S-EKSUW2|=Dq{NfRsA~rkP@`#PPMf7dEPLkuNrdGDa(PPt! zn4&rX?H=8~|K}fnoE6p0=H|)MCyyUL2HVPZo4U;KoVfJV&9^OBYm&q`i}Uk~^HWrW z%OnaN%jw#_7VlL{wkOGg2T^#EMgcvsF07GB(0JQ=w%pB;iVKUW+_a-1^ZI8W260GK zAi%ciXidg#_v*Ik{yshcII=ZlVcm(;QBnoR&R|xKh!>7dFmnGLv2+I}`1Q6gmb(;B zdaiuB*{kV~7YMGO?IL&qGy(YAW!3JT0e#eZS+* zK$T^C5It0Mr*q&`bdt^%NsOhL?RM1;hYM!cU%q;w#twiL`k~8^cQVVaZD{;p8tu?3 z8idAlRgMGK;Rp^nr_R?BbrUu5wBj;`rWHj$=lfVo52mYpy0$u2-|>P1cUC7SU}<2f z5AI(q<}+Z{cDE5Z2yO(eYeq&CC2@Rl=NzQ+&e=JwAcldF@|IEdH zK#nor#;Hh4wbyJ_9O+og4XjG|JN?y1Ivb3lDU=#$~8 z7kFNm%;rvjS2s`)oiFCU{OBXq^`CrV-`w2nuGTz1rClJ z1?l;GF;A0a8Yiep@rq?Jmc=~q-Q`?>sk^?uZt7~jSfoiRsb5OM1X<~VyEwiFhP665 zoh2!Nwrv4O-Ket_Wr)Y*mY_4Rij_P^ZBTFMS-ydFuI)Bv18A>`0+cN=RTQ`n?%oBN z{OE&+MMW)Jb^wn+aKAWIMa4Q>oQqeBC(U9;QJC?~ zu_y6m6fdpg+K?_hRU?)of_rf4(P37!VTpW{Gtg|qDYq;SS%x|p@2q-ljPnj_!*}_4 z|DzxIM%T-~^5kFp_5R4y{RhNir*G%If32#S^aoQ?Z3srfwPf>5+YRe!W%7y96izYF z$gXSgS7cH2SLw9{a^H%`fs@PwvnDJ>4Hwg)v7YL-p?LrYW-?RKi^tMLF{(@ES- z%XTz}it$`2H{GJuVsW}!EmHiStJ;d=_j4ME!?k3*0mFUN1jpzOgOw7lL_TCht0R-rERJRMkMHf709cgsZBI?p!~hk*j- z#0L-W-Fx)l0sp?NxAMq~9H-%!bm*$fsvL6G;$_)OmYO+CK=Hxmi?(`xlWw9Yt1TPv zO+VUVLOoC`C*jUEITY;;Mbc_>{*&5w_Tsd*ow3~XvEe)7__pNzyw{)i>09f8P494h zz859o`^D_O%Aqi*l<=TSKDskZQa+fL&IPn&)a3O*?a`=-Rt_D?#%2H=dOZ@$S+!nb z6c{qtP?x1kCD1ZmQc9o27-%Rw4OCs*+V>OifFEtx8>2U|ta9xNL4PjKc5RcXrBzih z9I)%`AW)9uhfJpb;NJb%3sy;Tb#;{&Szb~uU``E4PgPeyz?0L}#l`u2K8urZ!D29A z_YK%#5D!DgR&f|viYU-`Q6KiAO$)_h6=bEa$K(DRcha~w0f?rZ@Niu1+Bja1xEwE% z*r@B^FM780GNUKMHASBFBCK^>ny}-qiUVk8J@uWpSjJ(1i|A6A%B$E^WmorAS2J_0 zC=D3~La7@CfeFy7t9-vl$%)ry?ahliS(9TjGqpEu@IJ*LBzE7mCz&P66H`PF%$^Xf zz9rs_)aXjD5Twh&8!R@kt=u`@+}Li*!yix&>-)>>O!^d0;?yvzBk)RPV^O9+DUawL zn9+=ti_iEd10C#}OuZNgh+nD5O-=3(>as|+#xeOo$#Y6CnC^G-oWkXp+h^F6b<#(H ze(lQfT^5Sefdw>(cP0FS#-DEAkGiU=i+ZX$!!j$sMgf?_>BZ_a@q!0;?q)@{+wZpf zZ4GwUH2XX=)O7#B-A5lhOw-twp4muDrNGrO)GP`T9Ly}OX;I2eL96XLgYE=4B#x+X zERx}{Y(ZH%7Fqo1W#EVd#GZ59VUzO{XyXKo4$c59sNR(SH6&H2F7pf=DiXt1*Y~-X z3R>44#-Y)-3>4`G*xBM9%8=*9_4<0h=dQ({lBIh4xNW+B zdk-uDBbR15Au;&vW@A2Fb~0V3ibN5z~4?o_%?Ox}Ulx42&=gbhC~F$$ffoWS!t)_Yw) zwQTNZMVaMQS|o8CctLz|K24`!RYjRo4bXL{?`+39JwG`;J;5K!GC%CLSy2p4Ww6w; z+#qx!<$x_F$=cz7QLl<#q)kR=S{+RhimITpK`GaCW&h2RF}(?lh6*y%knWq*evG2E zMzOLYAWWoDOe$=MERND~HUmAT8Cv7u3(wZ|R$1YQ>ce5jnHolHpzNzqZTmQAZ!)@G zq^$rL=5NzptEZDPeNiR4hZt)b4wY)L>-lsgWL`H2U`GmNN^!@-QG=Kb3ScpOQf#qp zJ@d@l#sI!dghp|Fd3m|rZE@Xik?Nahy5H`BiYU>EmO*lI zCedbb7ZChJNt}+U1377zz%QBm7xYu+@wrWD`-;bkjPuZb+3~-vH5 zL0wPE44C(9c?nKEi@(pPgWXuA8^`xW$z~_z4;_coO8_Q7zpn8iz+3#qzWc3j@(-3_ zeMeobulTZ)arC-0crV7a)Ei4u5z%dz9x|4=vCD#!$oPg?&`Rg3dbSxb3XIj3!F+Zx zerbCF43nuc{a`n=li>b?0aW%)(={d=pgqt?N>l)hwP1~< z-L=R>747kf(@CTXk@(xbwJq4`kd-AecCCDzf5)NcJIv&E( zrdZPcFh=uulO2p+9AbEfw=9$pqHLdfrkqlE)pnv%7xjaZLWWsfOm{v`9y5rPi^z5u zT*yxV)m04DU{im=-o z#JOPr#fg)oDuWwwN?~VAFe4dr3clyqhpMr%Y7Me7LQV~^LZ zhPIl7F9NVaWAM6KHMQY*qO!HYN3GV7z*vELl+VBem)Z7?>Ec9NWtK|jVQ|LUUE1{n z+hf2qh%1iOc9kn_sW$|b?}FtR&Xh#axLo2QP*i1%piYM>-<5kHvXcbMS!~EI2(Ah$ z%C@Z?Nu_5#Md0HiD%-IL@0O665O| zjZQyAW-z_|Vcqty-s<7ms9EUE;9?EYGuNZ9i^vevv1%NZ-ufbipt(EN=+INuS<_RO zH+ht16ODs8AI;oAkS_Le9Z6sf{J@ueC_0)NV$EV1+ChE<4uLe$oRgKB4cKbBp8M&x z+>}0ba?|Y_)&j(|xih}ddWeH&NJa4|J!ID_^4SkYC z04ZTgX3qs{gRr<>=miPIp+nysoT=_6yR&?*U%IOX!QggnHPi)GF>qRqojEkBsivmt zy#ScyiR%G1Ys#8*Qt8m**Z>e65V9w*0}5O*nrTr}`ay(Z&-Hv<8eD^#^)8;*Fqu$G zyB(?_xHYF3$uk+$udY1a62>8`iWWq&X-bs0z?#sFq6l{sP|%jKjQc#_>721BNyP(8 zjTF9-D1+i!F>7#?w*7Rp+~GS-N@l;_Ho$?B{poDiH)b+#VCx$Lkhj8|_mss=w@vqN z<^d>~I4PoYQ9&YPc1B|2r%{wuVw$4iYGOtfc#~^Nd!DO;I;@d;bGg$Cq#egY95K=Y zV2SwKrmOfMLe;6KL{)4L#3F_bF_dqH;mcSL!$)-t7iIAju+kf$=KxQCtWKoR5uq6H zg6@NLS99KEG-{BLibM>rR27ay{_v-U4t0_kYpSVtxWm>{R|*m&SzsV6{opn=T?aWf zYsX}(%d)bg?GAMhpqcmy?$@CP>o}0qc2(C^J+4yUj!oJ2 z?7`8!BJijJP0|_o6i#6f&sOfdy0(ZtapiEk@W94MI04*3#wM5N%pSjEbt9g#H(b@A zURL9wE?vpy20HURIVA-;$Zi!Xcib{Y(T+NfWaG*k42Ek;cq;ytWv5Fgd&=hqF|U>u zzSQ(bEBCL6R>s@wscw5%w~v4G?q=#BJCPnx&q>!Omw;ssgGns`H^lgu2sDyu>^gKT zkl{I{=WA$bGKpf#(i3$kD>x(U%lr!O*pnVcGs@po~Fe7gb%^6X2Oa5IEQ>FGOQd(M!jgT;C2t)VUrpmMtIwLmUIQ z589!qfiP{|H)Ye(u0C(-BAvx2=cj;hFA8M%vbPP-WE2ro<8d`Csi1LXo2u@{Qihgj z;7Z-DW1_U48*>S9w6Z#{`NXv(BRYZHY4GC`yTh^bzABYWU*fJofjgZW#P67*u}OA8 zObz-HD?L(#)-p?Nx7{8N`?_h~ST)>g8h)g^gs+M3d(@01HVgtIJ@Ka(pC_eb%SDGE zTU#<7$cbi_bAl}5BEyb0kw_=ekA}|slyC$24&aq7;z>zRB~nea!jyuCjk8HlQ*#Na zQSXi!beS{ywpEgSJd#-TT({(IqBs{%Om>b835geh1$_mu+K)mh5*6)1DC3R2w2hd6 z0W#NiEneL32dzbNe9tC7y;6RI;?zDdhJlxZE>ixL!RYD+t()JR~;03V%W~vy~$!ItK_3mC?OgS z(_%y`ZJ2v@%DTF&n!fW~+m8a8zYW`bWIh&^V^ez%l8OG3A*XiIWZ! zu}ue%R97{S6?~f8owm3Z;*P`-b)%(1tSPGMkmc7mH|x#1EDE~I>g)Rji{$TOt$kbT z<=c84`#r&-Fa77~%Lwqdi)6=Fll{C&CgEN?wuu)UC(E#!@Y%Lh=hy?qNz_A$_a;+h z*buQK(ry|wX35$!#T4rpUMS3sF5etY_4>PI#!O>rwW3KBi$eM3^ zA}1!GigF^$Ha%q-T3OFomq`jdTcW%88<++2204d3p}OjAmU@<$ztDD13M2w67onIG zdA=Ksk+Mkyfs8lnbzSD58wQ9{g~gonx2kCCX1BX(>Qao`$HgoK3f}dyW1+$q7*x|3qT%pR zfrdUvQ`Ocu1JjTcdQhjy=s1qv%kG|HA}t_K*}YWTyjutz#i3EYHZ>zTBX@&k-dyfh zw92BdM2$1dio^Z@kZnX@VF>g6mkjGY?Q?%mUgtXoEH(YxXF7c=SL|Q=2z|-N>iBPB zk}wH(nT&tV@e_*|>JQw}BTfxsl+xBUHJmgHbzYk_D2*f%UpO(>PU4OoQ*@+)G}Hyi zn6(n!l5-?)+HlJh*Fb|FQl^qb8Vyj#L7e9j7%cr5N}D)m?Ivjoyr3nEsRLyu6uE&Jg2Kc@1T+{#*Z%Uw z3#{GEddoD`vg1}|U6mQuG^<%~v#vTUl5{>xPESrEfJGb+ZC7sh2S%nI@zivQa6zmFWu9HQJ`UBfM*&)*LTh$-ouZ(P>i$sY1>hO)1>LryI80`4=$Uq% zSCwn$mRYuBNc1YhlTfNk{Tyu<=+%I?ZbZq<;5C~`wmzo_De5J^wX~#xHw*q0-3}*l zOzx?}DoZ9GzHS#9|7unEJ`@PwU(v*O3|Q~SRhz#4kxfUROk3{7Qp8Crs%5%jA*v|P z?iq5^c8%?HeM6Z8AVcDa*?ht0eE``pj%YIyVgv`|bETc*WXev2mogT@c9&2t(JUV4 zT15QAB5}}Bf!efLEZI46&7DQDog(Rzf=@Et*&}ABSPvZ!ojdu17=ls@Y18c>0!T%1 z;xX`0?Rc~UahZhoHcjSU*C$I{ln{p#7GOk&L$=@Si@c&!#i#-=z-xm5UYGmBZto{iyqM3M6JUqs zx#U(H$DtPlP69uB*lzKa9Wr1ajse__$%<|X*mFxqCJb8~X%xj^WTNAA{cY3z zEpAgnbGT=xv=W^~leU^MBz>MtiZ)4o=h~=-99kN9piHk#X~bevW&|f`CJiEyWO^rC zG?v6r9LLuNssC&}jVpha*B1AdH@8b-755FNecr2{TH)OFK0y)#TM`&2f2PH~(K z-KNfg4;G;_4dWQB$+W3#Fj!^tbPk8Z_0`S#`f9h`G*#`|wh_ggz8;IRt<;v9FE$NX zbbCuN&!HhS{fvux%5ggp;N!>*eu%xIJSbr_dM<=kcg@j4m#cwx zSEjZy*A=BD6{UphFfoQh(S#@c{p^U#>mGlCm5CB-c?y}tiAzdB90-qSw3JA(W%H54 zF@Tu5?W(enQgoEo3=Yf=JU>R|6o-Dm9+fzM>fKLT*7QRu_T}UnZe1k_XjbZa91nDT zM_a0aZ@IQG#&Jy3^uwS1Y`s4`fARe4`uf$2%SLu9T|Y>C7Yxl4LuhLl?7?WWVgo*9 zP%$7P{J`;ioGMc(=zM&r=~g%`=F9sJ9^U`p(dnJLK0^{^OG9Gf+omnDY`@>-MUI03 zflA|emL#6*iMJTYR6leeWt<-OBlf?jv@MHPwcO>TpA}Ed7I}(DKnIx==p`A$^hN`a z?YNT;A0(3+a08+nDW15ho3f}u>%alQC=1%!3~$=)U;M)lwod!@8PTe533foh2c3Y4j1_6w)y$b@WhFrH9^v`T-7IZ|Q@WdS==&NQ-!6w`B;)++S1 zR7dYWQln8PbaFRM>7s=OS0s1R)w0-8p&mGc zP1mMTJed*m2LsBz-Q&_Ni*moqMj6BwAhR6LtD6RJ69m4ZM<})U;F2;8*|l88RpNT5 zr{}-=^M7}Jv)Syk!T7sux6kX6dWj)qM5$#)rWM#!yc^xnbTw!v&>2|c1{PkXY??hD zdD#M>lgK+=-G6ZZ&p!V6(MLZGlNq6u6Ux1K{K?(Gz%_Jd>D+bPBnB%?<0!<1VL9H> zVXQx@;KazvmN!l9+B#u)d+1 zp)0EcTNg->ROPi z2b8$3Lm6V%VM&Ok9}ianT(}jcv>DCuJWSnMViFfshpO-$Bk@^F{(O_ z6X4nP)%NCQgO^Qb2?{j4OxtxuS&EOH1tJ$k(Q0+Fn9l;w1t_yKGz@jsd9!GB=iV=W z{p*|cO_rB`_~iFx&avX1$^zS3c+OcE*-@Z;`xxFKjtvyV_Cr=4uGX8Emsjg-Kf2!H z!MzVYcyRar{quYGsp(@ zaep!TW24Iw!v+o^iv0lvoe~)%=Q`-Brtb(V(mG?mSJ5Ly`utAcs?jpFRkI#roNU?h z*ULs1tIYmu2WBZ+LEy4E4|*_=qj5!xE)whrbi|%$Qze#9T0z07lqiW$PEUcwSe|h%%9HA(|@UBgLkE>48DB0*x_>i$cU|03`)v(O zLM8EG$tEezJ-zGL^XAOX=(wU|5c$I7@c!L zB@XOoaVHVa1nBWR;G@@bKvze%XqzUMZaNp9gLV4RQFGPG6p5I$upcHuc87B^egKMx z=b(kdkahCFQpKSz7IPF!i^b~f&N-+{1A0Q;Lr|90VYkJ?jng=YLPmTsG1LY{G;F7A zTGc7v4<9`G$*=R01)Cdm?f5ExjuI)~Uox z0VS;+nRKs_?jQas$G>q(P+4uGQ$FZ6>iMp?1u2I`un)8n-_uE)k!94`GCYU(64&lI zYduXOT&X0HaQf;)Ik%7ZzUltMXfnQzdJ?iF5(80G4<0pmD6Jvj|SABg7w zx8jsTGlv6Ch}oq8I~wS82GBAHJ7qLQ$-cB7A-oFTwz1+@CrU;V|e|N5_hS?S4%0n*o!0BNgy>N2Po<(OpK zRJdAh+f268v$dya8Dm=d)Fo(|jy0$rh1AkjtPe-J{Z;kAk!!IGm5EB(qOfIv(9>xY zqE<1FN;@TWJTD#X7Ts}l+QG6ayx_>75Q=eSw&9;Y9zUvmt#5i!+uz|aPCuMCNkX8+ zT}B2)^z^>XI6IL$_*766MNqB%#*)BxQMfA0ryD0b*-RVldc3j{$vXWEZ3k?w zX&S)wY_S4h*|sMwsnX=60!dD(j@FU@6>wu(N91Ai@*HI zFMg4po#7cNu$@TaaOuRUfv{?D-e4>X)MBO55r?|a_GvXrIOk9`D_>W37Cf4ZS(DE6 zQWhB~4X;M}kxDua?s?+%(f-S^UR%GCo^d-=$AW#K zB>eGEt#5cyEBhV5(CuEVA<_Y9uCoc!Gk8XnS={w=9V~O%VWX!zcj0^H7PiAElgVtT zQv-q85cM5+4i*Zkv(9Ku6jgLtV2TaZUgBCKwwn^abA(0SzGbEdm?IC_%aiUhWldF8 zl~SkZKC-18osr=>gU2SaDc&^#UsA|8z}|hCj%66NMaqZ2Bv6Aqt0Z)jepD* zWRW~E*=ta^60Xaqwd9T>HJs8D>ynH($(AeS?SLjRS)^44E}Ly1E&6fkvOIhK;@Pto zPjr6YE&&4zcNI>H$*P9lrv!8tQXWN@?zT5w%YU};} z`jGq4A#mNB!{NnY3xHjX{mJ>o{K5Ux2M^93Jd9UMobS+dukQ_%G{}Z2O~L3Q)-YEU zR~q#m3vR;*Lw4n&BnrY9BiI*a0eF)@!! zoRn>wYTQ;DeB!h}wlW}k*za#{*3X_jef-&{FJC>+ivxbndTro%i&nRQ^|+k zCf%D@nR#B;_3n^?QDt>im6@5Gv4=|ms=1-M;ZQQCTSb^Y??%TFIa23qY8+wKeW z>b4~Oq3sgB_xp!`>R}vrf~32F`@L1s)xcpViq(iZaw)14y4I$<6oWfO)yb3zCfpA~ zvcRRNVBoZgCHCT)o6w;_n(-oN=V&4xCbR92Dk?0iZqkF(RB~~zP#VuvddUoo*ojV( zM#jx~;@>FgriQ3RCE39X{5T8({5xu;EMuR3V%vT!%R0--f&y-K`a?egtI~mqsKR{T zTh8Zck^~-r%)n`vP3wno6fpV$zzk@urpgd$Y%p_9PM5~`Q=k>9)Zea_pMUbn^{bbg z^>tR2IGmG{lk-OpKlu319{%j3lZ(4<6iU2KFA`51px?EGYn+s0vN3LrhAZCi;8eIq zRgD*#;w1Ic*r4u#J@rv0r8v5zwCfj*UZp!vaRbq)?eK#g6|Vzlj~rL}dOBK6_a}KZ z*&cL#uqH}p^J2T*zPh}+e07P(_0=Uhcvquil& zqe_gbG+qJVOp}%ey?7#zx&Rcr0j-QzqFFV%4y2~h`fh_JE%s#7>J;Q_GWAv_8HLC` zBTnSF9&Q%7;C%j z#-<%C*Gpzga6Di@)zF@*9}UkR$I$hC|McYKmw*22S(>g+magyBU30zLRG^cFu{b^X z=odf#>92lu{@`Jlr0rnzd4W^F!2w;mrmf1VuWPo*eTPkNgGp*QP%nyP9+K>jLNLiy zlQ(Caw8IXAFi0txcPcKcAcwtJ5~8H;olbNkJ&O9GsC4+W>y1e-9(B@gT z-R^E~Hk%b0_}ib)P3_s6&rRkBCSwY%0N)x^)-9sB$c@%vn{5Xq_amq`H51) zX1Bg!PwTKPvVJmxG`aie(Z&6HK@{QWtE%SSrZK7@0%-)ztMUw|ANp*+aX^6afjUKv zay5x28tNkN3)w}WU7?s~$T+!U(Kr#;n4}M9STkP(e~%*9c4@DSdYl7>HB*KteH%3~ z)h;?D(YEaZ)KI-T2dlM?p^s+8hNMYzgh%>S zdj5vE&?%0$X)k5#$jfY3nm1rTX);Tf%ZT1A9;c&ql0pywt!Q!O2SA3Z1bJ~yg`y|~ z(t(SGVT|>hL@_;7iLawfqV!`waO2GZ1>^J{Ad_;Z2J7FT^Ng|^W*!=JxR+@iI!<+M zwjZ0S6<1S6QroV#JUP32|G{Rzz1nQDETaG{2yh|Frrz!MEhv_n`0a+-8Aid_5@o_RVO(RG_07k#f12$(sgw3=wC6=XTKM_ib>+AskW6Cs@n0^>6;1;mn z>oT5OOMO*UTJTQv=z2#dqsun{jz(#@n@X37lQgq9EuupmUPIJ)tQjpWKIML!2;tdm zm#_&-0ucEGpa#A03(oFRZ9R5%}?eYa;u9%<-1`Jgn)&> za%dG_*Wf?ktF2`ko^BlKp4*9o?9TcgPGyi%+e9U)NOLJN zHBIWMgpcwzAR$D|@j{)8BbS0+=G7_n;+{!Pch&-jhHEtt(7Ck|MDgAG_qw4~GGe*k zt-1SQOt&5PA5YW$`&@^zDw*1<8D*NLZQCdene8H?1XMAj&G|GM1juBLY0&YC-CfGC zSbSjN>7iwr1SHDQ%+8VIQBxFLjLaKFEYB2p)NUOOh#O8dhhabia{jaH`tx*tc6R5^ zoeQvlrft`oO?k*h;7AbJ!ezjbz>M;|Sg*G?H(QiCcsX!}l}k~0lBB-tiDay=+L~!S zOy4maOA9S25O2y#o7v+fL8BZ)$N4mMStv>kLf5tf4(@;xc62rB_}%ny8^)ponJOb0X$+-EVLThpn}i#KVDD((jAE)*k6scB^q*VYU`!$tO- ziIh%nLi7VI@l9Q6Ykw~aJ}4zUI#Ul~6(cEVBQdv=AVP7i_dMd9%hsNaV@4I}Y!CQ> zl9JWDuIq8CorWzg&kr6v`~WbA0{PjqC%f$$DEhjwC9YksLv+3mRo{DEININ@!~I4M z<((cbo3-*0#iw8TE$rp`ffsn3of(*?2k7x6VoPkQ*#2g>UIYsiMu^ens9j7Yo9lG~ zg*uuA>W2hG8xn{&YDE_68kq{50VZgNVro^9z1!|U4LD2ZxU1Evex9Nzsq`MN%c9(D z_q*Mpu2|+o5z0d^s}0#EhcWmTf885H{dL-1v->)D1kEJ&3~u z$jEM+QGRdQU^jqo{0Nn-Wm#nzXjWck+ucnww6;SRP#o>*WVJe3&gOFzUD-Z!ZLcaS zUWuj+EL#l&NFF;?V%k%WBWl;$1HH2+86DsbsU%oNls$+&;eUu2Qn`LMwP8MI~+kA#mkcuRC-vhd7iiZzU#&k=#b@r5v)=$ zt~i-R%xn(9K(_1cVRuNWAdQ$_K^*V~lw(yTb1*y9Y#=vSkU`+%fM(VL3$z^vw(RTn zuq#~4vrVhA%c^XehFXk*zEOEm7x-cvnJKPZLk}=bW+}K>82HSQt{TfzRBd(xzIU^} z2F{^`oy8Fd5(w4Mv?#NQ)}AYRb4JMmF%4URz@q8~33bFk+HxJ7RtU860tR;V4E4e> z(+Z{pog5w1wVb~(ncR#UfJdXNhSN}>RMeT7(krCaED-nSFqjRqNknTv!o9@gRCU$Y zoUZ~h-h1FJPfjb`5SXORU|KpRmU&qn>bfG6{uhq#-@8WEkD!P3W4i3R)yhZ}U`^9$ zz#@l=l*fr3ZIGpl1@Xp`uDm4d5rvq9Fo+2ZzsrkuSPRUE%IG8~Uc#plm|8rm3v!EXz>Z4oYbyc!{N&S3V%b^=(yWhf;K> zz*>VIEC9%==((#mR2>kh(C!GMSl|#Z>dG@6uu|KnYfKJIIPB*0S?E!#uEc!MmP^R) zy@YnfF)eNeREVgP9UIrKlb|6>rno&n0&p4QF<6MZAL2VEsU2d)*DLMD!zPyt1S8dD zP0#m1H_lOLxAm4BalhXeB|W22E#5gl2Qvh);Vd}4Gz?;GW;Ip0S#S2ceGYU#95QBw zY4fzHBv9Up;BTAm?+seLkqgS8KRYAbj}pZ+KFtAd~m_=3AT~8@F{@v!r1MLC9uIhp+ zEj1mt4p86vZVN(!<4IPmZ*lT@egK9ILyODF>{Q#dCHU0#Da$AQK>?X00IYsOjW;R| z2b#=)B>x1YQOYnKQyO`>afQc_4uu2pokquE!ZV3Fl#z_wNzkHGslM?elk~9G>-DQw zmseMuRl+r!&z7s@3e**7%NAo^;#Kg5_`Zi{j-zy+ZUNXsAL< ztCoX`o*%}u)#>@^>1h~7hHSb&dwF?ty#cpE0fzOqT(Tz=$0>N*ZqNDz90#BmL@_{< z#tsg9F{ra#pQFpNN5u*mm(mUEHYErg}1 z8X$$rQ5jx<)yv%kd}~v8K1UtBmhS2uE{A8ijHpI6*p}cgbS_lvuLEav#A#hO_+L|5 z%hjnDM&fKgMT3_n+_E%f3KD1~@$$|naUI}Mlj-z^-A>}ZHy9%K5T%<5s51Lb*d1P% z4(=w9*<$Roi%V)Y_E;6&Alr$C^a8mvXi-fj!=Q3M5nscRSAsb^d9mB=z;qA0Y`fk$ zj$Jn>y>q+^aTJ}OUnEg9m&!a}&iA|B{&0|1pefeL#>-bv-UDUn_qE$^-(IV42&&%v znVlxtwQ4CHD1{t2G#Rxg+QaD(`f+Tz4Ud{;!paYaQF3c6>baPdM^ltZ%(aqaes*?p zc6zp4E`e5nyCN@MzPfq#{25jea3YN2v(uBavpe&}9IG4XlhX{Q!qN@t3+lNvjd0lW z2`Cz%UV$Ak276^ij`dZRbr?igZ;oZ^;2iqGn=by(Z+sDL`FHQ#i=wD1OAsC}jKK+M z-c{`Tv5)N7_nc`^T`g%>mKlVu*g|v$9m3RPJKZoEJh72Y2~aKYDw@RS z;IDgBkh9tR-o^dH!`=M{_viC@6i0Y9nvF3=+t%|1|M;8#sy`C{@}u%CuAuMh3j8hr z>&HRq-be@EWIgG;&%7vo$wcRdR3~ZYqGO=xg6m>U0kE#OyEyPYn@aYU8|_Lg#+@LX zU0mFI`0&AEF~@Ts4p~vG5BvSgmzVo}7KSnY6|@TlAK1-ivlH7n701bPxdIgdZh^#s z>TvD5en8_s&J5E#l*A#sx?Ud+d6Fc{`P}vFmL8>?vPP}Q%}=d#pUq-ElD2F2S;l;d z`8iS&aX4j>_9e-~qd2-gzE_y<@ZuqA{*vIGcO2!SvL$v-ey2Fpgs2z)O;eT=V9 z^obLDreo#2bN<$PcXyvY9p?1RbkB76yz7j|J=ImacI~S7sb{Tst>^L4L&AY)#UwX! z9dFPdHd{@gG6l$C;ry}cq~at~6kyk@gefv)X(Gy0pavm}?VltwOlB-41^%$;tI7nx zc5qfEA|~?)6FB_DCws1ZGG9Q17*K}{TVK($5qJ4qQf(v^MJ_2r0_}y@6mAX|zrik3^~1oXpk;)t}{3o?V$1-S~Orodcm z&xKbQhQ8xF0J@!SZ>_eT2#XcR3L1o(0!HcCZkUQ#?Bc=}H8O=65sxz*B#21gJ&>a? zMt?v+6u?&?Zu-aox=MEO6p57LNR19D6);+2m5K#*BDs%gAbe4z1xZ!V4J;(hB8X#X z0R&$a9;#ADSfR({li{+NT(vq8qsy7v??bvba2ylf4zm9_0@!z4XE+?RT8&z5y;7|d z@fP`o?8V0Clmnat^8{;5@6M?n?(x&1_iUT1C(8hs-+>PZ4 zmy7~73YgH1fVm-Bjr3u6(Cy+JaThK~O4Cf!3b7N4iGh4so@JN-9ukh>urALe#;64P zBj3lOSb(V<4}1sr=6rvs!(}t!I>2j5EV#+k6X~NO1LkZpl}UQqLhStyWQj|XYwVc9 zHz7oMF&@jivW!y9G0`&fy#NqjmXwLfNnnB#6V*ne*=W=OGl8L+<|yg6a%^~ZU}h%Z zSG&_J6bdOVgP_gxBYnUyiPjB6>+TPx=zap~PY=OB@y%<h*qGsE(;ZA%}aB{I+};8_#ZYO!35!T^Zbu-|KU+P!`so|h$VSD8$D zYI6F_!a_Qe?hkr4D)u2Rh>{HJ8QbEyq?8uJvlu3}dIM5Gjt1BV*${C_W)&3@Ss7tag;LZby4AQsiJPv3N{cE8hTw+8wU_xFH*8Tz0%7!~xCl2&-tWnG;! z0GTvROsOJyXJg#DNM@8mY;Xn68ip~M!xTa^jz^(EI2A5Tx<$)j=5Ck$K^{u)RUHtM5@m~C#^EN#dEZI(D`91+8c9~NvJbBXy4>l`A2u;;ht z)~zHfbfZN5lVcP~3d1as#)6E-!wp4QMUNLrj-wFh%vhm({=$WYg#}fSS60`TS61t_ zx@n9|+Xhsco|-;)_H1#i2%mm~XckXSPQr6F8jZEJH65}eLuVNl(C*@;%j4y;F&Zx3 zy0Nyl8aN)Z2GUyvr;^QOCn}ROGqb4_pw(byc?IiJs58Mq20C7;zz=q8hXKA$8~fFD z_(4r+01#NNCbQOni6RgDi}l=yINS4N$eIQG0B)i~o*M>0tW3}LqreHg{&28XU#m6O zO-oNMj%8Yqn&z}@N>o)==0XN8i0cSppvJKlkq6gvkOIBOR$e>M@8SD!8MU zH9BK#SY0Dol9C@2=f^}iCXo%r*#q3SjZsYk+t4|7!=jrb*ymf8LwZ!Pb_Pf^8V=Ui z*W2y3ZM%@QmdoQLDgaxVbQ;K4t-blElHxe3x`0m!nfbP!U8%P{k zN*EvW;~jeHxATWPkSy%{36d6{*v6q?EUBb3DN^o{SS)P$kQk=Y>1uiW?Add3^9zC~ zEv>9vdHs#$l@(wRnM_7RxtP@C^wha?=Tueg^?(y$W3}Hy?);7}FI>JR&5IEA#rd%)2~ z?JnTzYOmY!T|2pWw&QlX-LwW5Ba>FrsA%XzE|$1$F^QoWAUirA3S!I?6&)X-Bmll8 zp++F?zcQ?VrXI2^2r^tZ)OAI~LhHeew+Gw4$oM#V>+p$L0b$cI z$%T>bZ5pgnG17Zp)U<|m$c3sqL)E59UE)_5B`sPpv5JOun9FB@Mxh%ReECZt60mI(zWgnbQSyaCwSq^IB%$4^-(I@i?Q~I~27rc% zN$a_vGF+e9oP6+vcSa=0iV1-1z8PN(i<^;fJNP!K@ust`3 zL(|r~{dTicYc}iMPRG&BfuB*4hp#* zy4C`A5z`QWK-M&^R;%&y%P+nB!xtOPx+F^JOdik~I4q>$`9gkrdU|GN=HkVR6BE^& zH>=mLUu!gKqhTL~Oi@V#UAwUhZ?lw1HI!-5{n&q*#K|H_3a;GNH!W(hqa2N6TDGdC zh`yeb(zL0GiJ9r?v3x;?)zWUQudlT`Jy>tDiW;EB^7z8pbCcDoqN>eKXVB|*JMC__ z+iWzN&4wh2uyW2U%$JI#u|h$VgjTCluhr^}n(I2UB&0+%aEA4%sd8n!1l%f<&FQ02 zqgm^AT7W8|NCfGlD3#UoZby^SOvGff8J1IBmuHyJ zMysG$0$PO608|KltSkF-+aIaM+OegU64iS>Z!0y3@FKvrWd(%=J>P|lX=0)>F*OOPVXxc94S}=@pg=5HeZUxEp@`lPuIm!xL^%vN z$OM5-FerygEReBroY76g!U14ihfJ^q{A0D#teK-h5TFw(>3!NjEC9m5bq4*u$V%9I z5E74TA;K(~DACKJh&rHHtL7CoaRwp{RlvE3?lg+E<7O+7Z)eyIRvY1eM71v<9p}U> zh|Cp51c*h{9pun=*0yjU+;rfT_Ie}8sXY%p6J1iR!=Y%$j(S~e>rFIenYhzwtgS6w zyLJWW@BsQi1;5NZX!U3;!22y}Z#|we ztOp8P2vv!WGP5ykND>oVtv(S^NN3Wjrd6wx@ZD~^ZoS!DU0YjUucL%ZHa9yrU#V1J z3Bj>OBfZ^j1CG>d>+t;#SmRiBK9>W!bpG7=VzC5^sW<3Dh6vQk^F0My+)xW{7-NIcbmPl<`4HAjvYliE2! ztqo{McILw5zeG|$k=Y~Sd;lfr14cwvHO~ux4fc9H*KGnYDJVxDr*SsC;CZC^0p(&) z^&#FEHsppwK(|h_xxTu(G&u>0_)Mu-u2!mpVSjyXZDn<--D!?SeR#Uzu=nU07am$; zzCeNeLB4B=t5%}bzQwZ=#rGf#93sMk)6A(9!H5rSYZsZ$P4Gs7siUi5fGVXtJPdzUmp&Kng+kkLxuzdA`JXo zEf@hns6Yq7^C^hOBS9=~PnD$|g;W3^C*4wpwy<6A6u0Ih3wcRQR3;X3=W4uim)c?R2x5?3r`(v)JIC z1}f1fiX{V7Kp#0c4g z5M7o;6!)m6E#%3Kj;7%^c)KowPy@t#}Y#qyB1I` z8pXmi^q0pvIdHNtaw3$x3t1D+8<-lr#$hg>hKrX@r;}PZfW04LPXiD_33(K9t2pVl zA_`VSUYbj~s5oMW5pQII$=StRB52Lv#(=Ddd;oNfBh49zT7Z_ejcpB{*R~x8(#%R_ zDqkqp)@#?Vzp=7%3trvkphCE{nSxO6gkiX` zrMPp?!NVtjUWEt7{}88=MZ|9?_5v1oF8&AUPNiB+O17q9KpxTW4`A`k%*~!Tb7pd4 zQdL#MFxS@CAcHe)o5i_ZKH2d~XR{0Q^Or8;E)^iu^2*ZU&0CFH&9F?77$gGsF)b7B zSt^w-UAlDU?7Sq&>+5URu3l@kTW}9ZMd5sG8`h@_Cs!zp&CkyPFX#Z3Ycv5UWkn^w z^@$q=)^1QhSyB4^9xO{(=($`$l#~#Sut>8OizRvVk2lcSe%R~igRW}~1IG+piwS*^ zi3Q+SkV8g{!ZB$@Os4@Uum=sNg)o@}WWhcz52ckYfJ^vwHk(UlvS_MG%xn;tuxCvq zN?DLH3amg(u!+2?gtn-dFOpr3IN3>!;!P^fChc=Ek9`s{*sarF6JDkgl4RF&Ol5sGB2p6{&Q9nlqUfU;4pT z8c0j;beHhBf)yqpWbzhO#es)-afkvezDN8c7?fgwG!5VhFzDL#o0e&gm&*$a3*~Z& ziI~;(8Y~3hR_#s~3-GEUGT3b-sq%DTW`1sVer^udR;%6awA-y#3sN%`Qk%32WCIqD zW$3V|3S)U(ag!6WB15)#d+8RWoUla8F0$D@(7gF0|Fam%f$dz=`$^eTK zZA!8K2x%an&xMiSKo8U|5Jx~R4h8(M=?I0SV8sS5U{$x*9QC{K?7%lX%M3j`4jhGv zfY3z(W5+J$jqoaDKBb9@EODv=sh;k5z=cS=hr@V`9}1F-Dl%l)+j3nGEfjGskVTn2 z(m0B4U789o6|r%$S%?^fPP80Jw~^@qcZ}nttAGiKha~onBDnE@TvlY;sKKYhW7A}? zsa(zxAI9;erPW)vmf*UYmUZszxet8c$MX4t^gXFoTk}wW5M8S+%h;}fOpLgF$bw1B znroQm)Z`3&EfE<%;(x?#>=e@h9lA?+j4N!U^h;*VfQX=oXozk%3@ovsu92yD}mh&?OO+*1n0;?zXt;`#IGjJCeIdi(Zrzt{DB zHw9ninJmya-~uRs7y2npJ%8c+x$_saRI1tPF5bEYRL!#OOg0L4RP{4)!_)XnqwEp*w&fH2%tD27|$Rt*(!T#3va$8v-}NmP;JpVJye&_5nHT z{Z1R83Pst0QiTB|W;l(^36K%WL8LG!ohL&ctV*mTKw=k&oP;SIF+$~;h>b$vV-e$` z$htk!jnQZXOMJthSr9`a2`T|eOr-#}9BkajZwF*v#5WDa`J$w6Gr}f#9A`pzW&|v( z$sw}nqfxU7XWJSMba*&i{HdwQxw+{|r2_ARqG)i(*I$1FGH3vrC!cr{SSq}ii;LIm z^>uiSxKR*=E~*R$TNp%uDb)4h>gp1_q0MF^>A>3BqvSReve;u&eZBKZ9E(#F9$Dy! zkNOe23vB4l908?pJ=EgEMn_r3lC2kv6~-=JxCD8hPj=2rWeiwvufF=~&6_t(6KBwf zYn}^70plcRcaL z#6+dnZ7<%sdE>?nlR%HErQjTZy4aQt%URL1VyTqLWgwTS)z>Y{lobis6LvO?|!o61})|d%4@~!7ELtGiMgg zyyG43c=E|7W@cuq)l$Nk;A`ggt=ohC@Z!Y_7tUWO6mnOtrbPVefa?>&p!IM+suYJ}ogfq3?1fj}&;tki4k zkh3^0rgc2Fhl?n{ZkoEG1ARL)cODks)MRxu>@O{^EH2&#J|W9eUQyt#K@b9Y0Wd;Y z7yOd~hB6rGJ+#~6(^{JJTL!q^I9AsUBWvUf1vqx2SvL&}a!=x#6_R2$PV~CI4Y=0p zc6z;*J{Yh;pm4m1W=i*}2)dv9aRZ+(N6>TgP}6&h&lndw;Pw zzHkP8z5vt7)@sb7ZiGX;!lG^IAr2J~0!!zdDPWx#h>R1EgwSsmV+xHyFT@F>c*j?6lj)NFVfj06Xw7SVuAm5tcH~5i1?+-t6`I@Wo!Mt#>*t zzzP{9>o!`Ce9w1W2k-?}Xkn~0du9QWw(E;G-@rn9*YiR}Ac8TeG9w#?xSC5jRg5ePENLxdPMda~F!$p>-N()alo@EQjglPT*o zKy^N!&7(z-f(DBMD#ai@4N=L3v}AGH+RBN;P@LcgLwr+BeYm!|`pV0%y!hgaZ$P?N ztLeI)BJko57gRGFxbPgDR+R#w+uf9>k(>Kf1$Or}H)4Ff|17B?USs)DA{vZ`9PJsgf8 z`BF3`SICKi1XRniEI4yP5>lBIC$NK2zc=Vwwke7tAWhFMV@gq(ab1v8h7rn0>=aaajgLu_aP4?PGUHToVY)P0jAFkpjr?zQHZ;uiN_#7 zXgZV5X42`Drl`0H$f5sDK$^~xJPC>GET1TP68KBxXyD2RXgS0Np69Ntti1UA^Z)Pr z-+%4(*Xy-9T&@joTk#H%gm1A8DQoNXrc?R+@4>-}KOBdhs-uINsrNzZtKqYQ1FAsG?ODS4914p)jURj|E z3tz!TazHDtOWr2x}3_{em+-FByo#tk?W9ay%3kR&UB z2Zm)1`#oS8K)sT#b4(K9<$KZ4w9|@_Rw0GL#sNR@5?c#korqRQjW`xlLR|Ac02Uju zXe1T`j3mCwDWrgDC51w&fO#lAis+9*e4NB^vb-?{O*$`#bv;WI%E)XEscOO9ec!Fu z*Pnmxx$iym%qy?F(rUGn?}Hry5Y}wguU>t9Fw~1<)e9FMd)HI%nx3A4H^MLsNQZCU zylLCk{K8zdT0VdN93-h&=?c7<(72FnO>XaC*s*K89mVJhI^a`KhV{VAcjM$!O8n+g zqZhcz)XdD&Pd`0ByWl!5pw;uwKYM%eCae?kJ)C$bkY>}3PM;W7bT*fnnVp@Tn**e{ zwRr3Ljcd(j6YxS31=F^>y&l}z1G2y{>9jg=>C(I3`=0l`{{xMB^9TR$*%x1W3GyJa zoN=ct0#HL33d8`Y9O_2lEHSE;hZYLec#7)BXc-|Ws>0!@O(aM%V5>eFbvo_Au#e1) zXHDDebvq~%uWEoCkkbx2T^~IrP@dFBtcwAg-Iy6Uu4Y;p;76GZs;!3+Bzhb=o}rl_ zi(VV}(jzpKhf9Qv3k?Ku&=AW~==KAEtzc@5L(b%~1RMT=$VMeejL3u_J|!`OW zNYXOLafX9_zuyC}y}7vf!V53F`pPSC^};aRN*lMN6q5H0@Tk$O*|yv34#FrNE0iu@ ze(chv%bxEJM}tPAj%Bwv01`YsJw%kPs*Iu}~Pz>;-b*LKmw0kF&_8VfSo>uA{h5C+(Z zDFY}(Bf|h@B%$##i@N5ntzi8g{rJ!f*)k!I)l>!h%seC-3{Jx^cE}8DH|sbl&r1Uv z;zdr;cw$x!8zX!bu^!LkDao0O%4>oeKU#>p&E~!a@}hUB%g^5DSDG z3V&fT4@4#k;ZgvjHIDivw)axY4i^j)Glao_qL=l}F(P)SCIz-9n;>i_pKTZ^o0@ee1 z&*4)_8m+ORDV0i}J$v@4r`~<>(#3qfFdB|(>$OI`0ca(PDzS$^tz^iA67vFhxa)ch z!$UsuV?X|5W5uyoUU})o7hhVdtpT9GI+JiPh4;hIG)A^*15=uutUmt4lka}_dlW78 z@++@?_q*S_e)9(KFYLBQ`AuAw*f0+qrs3o%JxeA32AOsaUI3J^(>3J>_kHi3nwnf)S^3ZZ`aj?M{{IYh z+^`4sq}r&miMw(n4FZTEwuii?rGS<++U?O`2&60xR1EtSLc=rx86b^AGe4HKY|Izo zwBQ!tF(zZ8*-Q}NzGUROrtR5|f?hfrFUx)y4|I#=ZKR1jPQ%zy)U|AQZZ`-rnx-k( zxd54y>!JZ#UpI$_W%}4N&I-g&9`$KNS=CTHy;#hllDZ-yRtluPE&yzij&=bZ)6iWy zB(sEM_9kL1%Wk#mkT}2c>MK{?cw=dKX*d`{Zpduf-0lfjJ1`|Nm4M%Od-bbtygmmh z`RqcaG6A_fe6S>NNS zH+mF(j^PT0LOz#=rKc)duiG=>Gp_3^E32(miww`$+D)YNwpXV0(KrL%FN7c zE|&*_P^+&s8cj$pv9~B9S}v^TaKPYvSRC10?&9Uk@B6?9&YnAGSoVuQeEA2@{$Oc& z1#%<65gZ#vkvv%2*basYpmCJXXH_l53z9z4Tg`T_*BvVs3&m1CSAb_9>3Wu9(y0{S z2P|APHw0`I1jrLn^B3h0B8F&;0-s^Rkc(NFmjLagR2s;YrklKJqO<`fZY-Q*WTPsy z?fZGp1~o9tCi|G0`cYXaw?tTiKhbqr5K60 zcS*o2O19n-eL*|`P)^JQArXG|*=JvQ(^Y&f9#z zPmOu;qr$Kr*1JWFSOiE1At6##ZF*{YVsaYtn0~L{X}3$`Wmq!3UVk_oGUTI726RJC z5Xn?6W80?hyRaaqr>C)WrN}S5@Z9aCTd?rpAf6WxV;D5HAS%gBN=schf8pt;pFV%# z0{r6IwW~jT`G=5hdcL2M(rCaXqlOEXgW1rutkF;>Hmjw=Skdv^cDK_V^m~JWC@YYu zsp*tI40Kb6&pXzRL?IA(6oNv&5DOxY4u0roDtN9JIbIlXj1aPsC!qw4luo5XhU<;= z_F!OoZj{U$^Q;4B>w10^x`A)lE}Re+%!tI41uz=N0ukYhvCPlH?ZB6SUM(yv%*^3D zwnWS(Vlvf)vJqJR!WLYXh+7eD8Dh1KIe2L3I&hzxH*WyYCpqADgxZk51b}5(z(n2Mi*yE5`Z6-%j4Nx!O+n<6xJK0Y>JwKr3%DF zB2{F_9UzDB;M*8m)&a0=ILzea{IO)b(+DNa-; z-to?NU4HCwNR(Dr*Is=U3;DWX#0(EhHNcz+%T^*A!oi0l9Zn;a&P@@Qux7JK92N|0 zk@v_@V4{~|Iq)pNuoN5uB+D-#1KSbq13*@*%8CQv7a3T;R*-6mq`n34niYhxv3$Ct zVUgYsu_a360A+yKMIKP3$Z~L?5_kKMqeTIcnnCqXNsbsc#4=EX)$UZLh<;k**=!oU z=fjAIU7`6qHe3<$ix7L25xbyEu7k(1KznYD)|)=Q0^@+ z-yAPj=H}+}g{-Qo0OVohk4A&RphxrqV@ZCp3_=bC)Bx7tP{&4USm~*B7S?=#s!>5ImEwrBfJ;nC z0TEapz1s8n+}xS@nb~RJ4Zy|vSb~9^DZqY7BKDLlG{A^Tx%}9rOK0cLsIuDa_HNv` zasB!tP$r&}6d65D4a0GGPZBwi3>bT4N(g9FwK}QDN~6)J)#|XcuwwxE3;HJjS^;RH zhC4QSLJsNUAJ^w_M=ll^PUb}x{s7aFf|wN~mW=8V<5T$T$|9dq42Ps0l;vbe zCY3c@CS+p}ogU!PiTai2pxiMq!Z>~lR2_s^?LezdS_CI-4~Cuf_2pKxuBl2Ggfg&6 zoR@NeVUdkZ_V%sY@CxIQE0rohVCUw}kOr`@)xzz<#7>nKvnXI4uYhlUNQ+Xcn$P0s zf2mZ4@7Y!x#fC?Q4%nos3Lur`Sf({XqaHeHrM+L`85-&@9 zq~I(gpkcW*20);jR;^y|bh^20PC;!c2^OB`I)*;7O*5^j5--L9W9g1D&_gc-Ruw18 zQa%)yc_RVN6mq+*O1#K>&(@SiyOcc}!Hw2jKHC zMGQECPH=ofAC3ln-58+}yKeQi@UewiM551ZG}o?Nc@=(!OO;M##tNlOI@jxU zfPxY2e6d!q0hl_D3+Xnb^IA$Jo2w2`Fi0WkE+GZ1W0wp99>|yvrhr=k3c%v-cDw8A z>xOB<5>+)67;qhLI2tBfNJPdH^-q9vVPljV!h+1?Go|Xdq{-c0dvS4bWo-pg3{i$} z?|5sHHZhIK=kp8mbK~W4(=gg*3o5SqX4I_eINA?LKgBY%L)`ls!U8& zs#ViAyRBBgJAm_HGOVVmDV%?1;84T<0Mb?9FqjOYB|R!la10BpF~$u6lm`XmLbfMM z5s*dfl@f@u9s|6Q;aQ1eGn$f5DaMHN9Q4v+L)5d91W5t7AqXvrGUUspV!2Ql3xIY- z4S+EZO%=6r1vSC|wbR)wz#NN4iX4jsizI_6&PVb;B8e=7$oxo`Xy`iDpx1O=i!TIyfiU0y#P?v?lj ze=6hE*_j1M8sQX{mlqkTgmquLg!fq{J2g8HhqqzFlPWNFZ%$OErzQnKXw>VAw{N#v z9UQMgJt-`Iz`F8@5h>h(G+r@@Sux|2wn?7PW^$QK#`C>)y94ZOr0XH}o#I}9GESX5 zVJ??DGk*qhPt;d801{1DpTofrJ2qo9Lni$|i7`4#adI3E(`B=%xw+YLxzuTOAd4|A zH2;Hx;^}2G0B_Bq4j>D;Aww_$I3UU0q*x3^9tCG2HiE;$YsJRTmTGwKn5)! zi1U^x@|vRL(y5V_a$Vi^V%N4It0N-qnxd+*sG#nGmWI?XLYY9zfMhU^H7!*vm9U3k zX0}ushulh*(If(nipU-(N>UpG&7^%4E;;6eSiSOn!!(+$1{!5IfM%M^E_1Cd)vCLF zf8m`XG7qb&swuKuE>8f$PfgFGXtm=EM?Keb2ZJ75F|22aB78R$3Z;C$FflR35Ydh; ztULm5ar=jZ0mojU_OqSNW1 zZXYkKudlAGtonW=%Q9)^Mhs<$H3K#=p)-x2&SYn1W;5CB)vMQ*R#qWl5r`+dAc`qX zg>R@%VmL)!fPR; z;Mfle#};sUi6}CVKft>m)wq-RN4Rqo{w>!)8{baJFFqQ{U07`^_!X&dR3~@7$Q|WZR zm>(;Sjg4U^RJ~qXTdP^RwJBG!@kL5@AthjNmo8t(WwWU9(CIDi7|>GGg0D)gHJpf zj@E0n+e=HeS`8IS-`dS^pJ@rt_?y`#?6*O(BAOUdz8hT<@m3)*FpBGJ2XJ%$96O|zH*H+iM&8{^-br(*=DHSGSw%VqF zhCKe*<;jU^uh)ge2{3}DdA{H454wY4hz+agy$*kqoDR3r0`v`)tJN|*1>hzmeUL_? zG^fBrY6gq|uoF%jDUYE8?IIum-~!0$SdNv54F`$haH5gU5$-1NOb{^amfjN?fh3w# zq9CbSDi?%4j;x?cg@;quo@qpm=bN?*%qt>z1?U6$VK$ougesLv)$(|$SWIU$Kr1e> z@8XDED#vV&hBGKI7NA8fxqwJMfx!+(09fdC4Ga;BZo8`N_xUa-dmXlAwmS{1_-Sb( zR;J9(&fB(u-LJ%+9ze~sbkbfI0yr}Xo!Sgq#-f1r@adJNs->~Q)Ks-RRu~yZzt?Ma zdWLB@u=IgT1YzPnr7E(>^NwXf{;>5CChiGDk^l};z;1J(K7+vk)n;%@kU`DQBo`zh z%hKH3?Adc?ZOgfS;|72LFeb-!nyt=YIKajq+jhMKB8hJ(u|-7DJdUeWC#w@x(=_X~ zI^2TIVzMMFlBTFJ$HD{Q4}ct`horF00X@Q9KF3KWhY0>fLLw;vi5N*z;hzy7VTFx& zZ4l3!4J&3<Zz>0eQX)x4fx`ybZJHs=523`?0H8pVTxQb2NchBmsy`yVa~U zo1IQqx7^XlK##0#qD!ixXqqChq)#%LMJ9p$pOTbKq3SOi#U}7F(?UPKOqxsx$7B!( z-!p;d%ca8H9Izze`nBsTD{Gf7Uc7YiQmfruURee<2kZ&?RFKr#Ne?(#vmxqmu>b~e z3d_q&^+p|VFrP2LGLjV;vQa=Fw50F@NmLjilof?V^Hj8PMlE?kAlCAzj|We&Dc6Nl zf0863&mud21YV*fZNw~-n4IAbpc}Y249r>eWR(x`? zjx=mX05WUq>#k$h8cox2Lxwj|r)5JoCQ;-ATq|U=g?uiZQeEFiN#6hk?2=y7a%oH! zrO|LS9P}ZvQWP26-yPozeWGTCm;hhrXV0F4Z}mo_dG+dbeWX{a6Y~r6wMMPpY&hhL zJ&fY56eh7{-?~!3x=b7lZubX$P1OK;aPyAk6yQPv52qUjz?B4%M{`raI|{4n6p4~LnGV8E4uLcs2m&c8BbD-#b)^bG_k6_ppIb?{@p}A&nT$^+Vt$8yt#b2_uLyDYXI|DW5lO zR}_SR4~XHqSjgq3CZ~X6)LTtMHvnvaOnF2*9s7;gjY`?{)WrD<=R|?Owz9ldt3m3N z%_1`ca%AW_c1SUAPMmBL|0T{bJP#R4quK2B`*2T9#f9g3xJyXf+!-JySXl}~RDVGU z`N#`AAE_BBAOSMq91%_cCvu+=ZbTAcD%^!c?F8(xWMVO?brJ1C0lUz#1q}Wl65mWF z2aL@$ah94vp;Q@Vx3n}wp->nfufRnZFO~D@EM$lzpGAgAWaEh$4k-+g+lfU6c2r=& zzt`(szqxqh#*KETLs~|-qrhhxw94H1#f zmG~%{B|^vRDoFR3zz(I#2}eIb&gIO!5VHYdvpQZ6DnpvW?y z)x<<)Y^-29=)2{60sJaN^%xKN1zD&(I<}{#rl!iJatCscX45i;`HaRyfnlO;pW|TN zYWq^%wr+78SC%DUAGQt2lMQr@%pC`YWy9HF?`VuOjFxTrF3$15I&(Z5);`X-pp^n@ zgC;w5kQPR042wH_92w#xgU3m$1LnB`A14qSV=F+&a}q-u)M0Hi*v$}(48t<*0EdLd z3=peaeymU&D;05ausB{QrZ58V*NC1XXXXzT*TEq)|sj_&$y72vQyRSGciuV`7)`#L_14lXQ&iBx1=a2hB63i}3K^9r1@MFCyCa--w6LQoRBW919bto0gw6N7;Ds?(y(LB@ zNW_GR(Ss;3A&2;dxm%ocevuvpks$(Az=9MtkYwZ{Km&a(Ipk90?-HtR(n2| z&t`JSv{Gr26N%9*3;CZ&W}S)XAiLQqir5tqk!ASLb+K{m2Fga?tfTzS5z?z2m<3$V zaV+FnN?O;4zF#U7#wz0z-ChUvHt>w!QexjeZcUNvq!-;!c4a>#g5o&SixqSZNE3V@ zfn{O0Xc$2Tr>Q`rvWh4S`n`6m)$b2<97=XL;$Ag9HI>a}mToUCudEDp9bg0iE%3v{ zhyiDkqd-$LmGKH>UiDgSd3hC*yL_QgDwp6{YW3P+(BH8t-nvj(MUjEI#Bpfb=%9x! zU^wWE;!VVP0VR#~kq(F^i4x>g{23?5dL7QhmtM~%7OBNA}X*XLx0os zI7HPKtboa~s3<5GgL+vJ+TNsmNSqx91@1^At0;>aWS5u`swqv?BqAd!5a%w}0rtfT zG60l>QdaSN<`b=tA zk|=13oK36gl)_+n-b}Q5L!2VS4gpxIkc_RYtghD^Hc=)aTXV?OP{JJZ!x)o}sY&?Q zFE6j$ym$Avh=GT&@ELQA9bynpG$Ug32hQki-$eFWlEtWer|4_L+rYQe-E?McCT~ z5Gi1J9{t?aAo3B0;H9C;ilpE}B}o=|L_tYHS5lFb`I9YCghk?d!;>y86k!O-)*F%2 z1SchnC`x2F(NlpXlE<R&S3q zKy$=)us`Srp4aYnaUjsaY>{+e#-bpoDv<`}xQS{dt!buZ)@rqSqXSF4T&|9fmw~CR ztSkdrgS(NYYIe8SlZazCnk33-5sF zf#|r{cZFM-3X3C&~%2TMyVyk3r^ge-A06_T`2AV0+DbH<2a1f(lYh;yNb+n}*Txu)b*jgCy%qYH`(f|d3){)M8pUfy@a{>?_ADs0k$aX{?Y=YjA9UKYTL-9m{>7JWE-sFA{Xq2U2m-!-FaboBE)|=_qOedXPEF0&Hl+Nv@4L*Q8s|Kk z$s`4=qa;~C3V;hRVZ1r!O8h|s%eFe5E&vvQ2KvKn&g21nv``%(NNVuRrcna05TaQs z=5x6-3-h^ruHWlJc-WN40FMEp0|z%OgJ_mB30m!5w|v5z&=3sr7aP?)N$y4zV$k6w z#E0qUh#Rjx79`^D11G~rJZdyBWRsN48sZiuFw_2E zuwJWOxq9`7FTVo$V6WHTGZB7Z-%mh`WmyGU3b~={xv5lYqB_;>wuq*?$Lu8-PlE#1 zalx$Q0~&9ZS3`6F3@yj&4~-~{yfD@cGa%TM6k{L*42L5CHP_!5uG^U7kreY3is`j9DJs)r(twQp z0n`CC!YmZf%5?(E@og7DHmN0%xgeGt0d5b-en12~tC-8cNoq=3;FScdd4>m?6(es# zNj>a44UtO%XTnXzWE2t7Kmu-w1rCRrd@N~dCG~tJN&Y+_X*goZv&4lEd*%Vw48!R5 zd$*RBuUxtI%ImM+yt#;DgS!lzA8@G%aEd7W;2>sUtR$iDYyq;uPPa|AgI$VN_X}7L zV4q?$*?x3&v$ifWtZmcvc*7?3si3c$-o|txj^lZrZ-oxQINU1VSou5;q)3q!KoL!K}nHrWyt+w9p_ecRfVmM}d_w*K7Bi+~%Fgnu&XbVwIg$}$fF3_Yj^?8$t5YfB99=OVrPLVMS;B5&bTEyO zwS_ov9YrFXo`4PX*m4m$PK3kWfWo@nBA8dIn?`Bndf5?yE^GN)qt>Lgg81^QE8II)@MayLikjk3| zDhm;Lnebq|??J7XOVpfZMqwI5i~KCZr` zfW;(ZB^yMH44*`sIUTlcNs@*(Hf%~w!GU`HL8sfbEQjNTY$lsZX-Pq<-y1|kdo$kX zt9&cJAkH^hN`>DT*ht}q5fYuG!+=a>WBUcrKmaUcHV6-hSz-9*hU1PB3_PyW*8zHU z!zvrV@SL%{lh)FJp(#~iBP`evl`IBlp@Vo6MWq-u_JYK&Rf++^SRnxPL_;)&NZf@< zvWod5TIYoDU?(;m8{Ug{Wishhs^9A`udOv2EkGF*hF26(l3mw9 zcT)$}1CQe?+o0;riaX0GaFA>cpwTc9;X+iN@v&nRhj2oUv^c>Z((6PSAKrsY7YJC+;4>MS6s$fmWFqDUM*^9B|Z55+K%(;@ApAsb>INV>s&xFa@j zu!;9*Ok`Ul^o;f#$U8@-(QLPyt#+;6fIszSv(-WgR%V+e>YiRWhxoC0dqg8|v1ysZ z(V*Awl}Zzeq~&w@d~Ph0$=i;_p_#VzfD=_(!=iCt#dv13B+qOPYLJoMn8)E?esfoG zV;z#AJ)DT1n5fDsdfVK-z0~XX0c+q_5oS{{AP(_aU{KaPj+kAhRmq_=P0i)9uIG}9 zFgAGMek2+CA%Mb=85>Lv6Jv{LQ(JC7+LF8+U_+*j{jG-O_J?M-KLWHWj^zqK|1ud> zRwYqP3l*^>QQ!qG;1`!PH4yz!4v@t6iAbkh~|dl<+AOfxO<}c8<6?LAP8LF7fCf7*Em6tEq{vbR10uV z)3j_Z3+W1(o{12+Jb$~yIFXu*H%$x8lDa~ zp{l8>0#Jn&G;C9lQW|8jkTuFGaf^*`t1ti}#fQXYp24Z<02S{b(==P%ZnM)u!B)uq z`n};$2X45-z4>AFG2Dq{nR>HTuT&c4@d-&1)9G|BH)cB~V(}`oyC;jrF)F&#*sliv z=65o-N(VL$8-@wF*=Qgj^ExPCkk4oHxuDlWNny_;ITO~U;b&w+icBclMyY=H(Uei!##T)_q@YK!s`csS%Z-wiGnO4+5#>K#7bQ*YMBLrAj&oNZFnBnRH} z18|Z`-xRPO*?e%v2X~8GF`IH$Kuxd|l+B8g1h}KBDOJ&2GR;Hgeqtgr6%uE|klAZH zkMvq{f{4uoC|Tosi3kifK*Y>Jw$<*81zXzW+j-5lR5958GTEf%pNvN05TYyrazT11 ziXyyV7bV_p)W~ws-aS!jKh{vS|NDzhYomUxwi-t)q`wwvsD9R z&SuBpH3H|_{w+l-Sro8N4~lIL~Rwq%qKYYFX1wYF~Dkqhs*^X@YFo*;FCv{~Q^o2Jnlbo>BlW2hUWBnPJ- z?|TOZg{0#OAFd_Tdg z#D#b}8#-Lr-Hl~CQFZ@9@196{2Y@>~c69LK^V{4t3>-ivy_T(;XcANbKQDJ3>aRx)x+$mt4y7xv9G*!t$ zJ}9e@S~#}l5W&AhRfgGTAbBTXVLm8o87-YoImBfe1r{)(?Ukm7xSsdSl1|xT-psh) zQr)9wUlgz&+Il;RdIZO^XtARxsv<>kG}QIsXk^nI8qsRsUR)Y?u_)*zxX;hx(J_0L)ZHNk1jLEs&@lCpF-k0*5B^!_IbM;K zY&w(HGB_+vls}m$rkm>z;d4SvY$><8FNQ_8D()vXu3j7;#bv}vKb*VqQ8ACfxg8=X z8f`uG+i#W;eJNmSiX>-J>5-C7)b;#0*z7fpkCY_R*g`B~(un*Z@FRM`DZ_ebh;@XY zI~*=E)HHA|V&`+nCN4DYOqPko8n^ZK z(YQy3MK8g9LCO*55%5V5eBZJx_<{z0CGZ=Sz%g7DMzoCbFz7g? zR1~m|LrQo=fQ3fKToj`XI>R#_@~rS~F*0#)V58V~z0eDZ<$aV$dQzx*ke?HhgGcmI zP{2CP{EZ`liJ^2IzIWF4U-0kZ_n|PK%-4;Nr4Tr&d>(7iI z=v(the=ZOCL-@A$VUOtWG$lObD;PiQci;|y6~(R}KqBac0q`Hou}$n64esh|9bS{j z3o}W@a%xMG9D_KO&UtM0N9#VF0=eN4jBI!M2Iz15V+If+%tV zx_LS9pSvYY%Fu~68Ye9%U>)bG2l~Yi4YSojOXvPbw-IilyU6CS=*}sM41fEc=Qxh< zy{S8Vf`p}L(4c^I+yjuscHG`@DDoT-t5&aXJ9jsi!;k`&EJ}&UiAQq6EsrdEg=w5T zz}m5SLHB`<&vn2WmglwmL-;!gBS5Y#pQ{~S4|g~S(dUcMjo!gzFxv1;eTxYKee-D? zljZfcAHkgri+*5_&vigr1UOVlpA=Y`C}4KihK{bXN`&efQmnb`LOqik3Jd3 z>w&!shj6R|va0RR0@i)K z3&&qyINm1TeAF6PNmVR9cJIjS(j^rJz8GOS|>SSN@K9<@y=-N2zi0gJ}T;8_%{XgmnOqMx(<*Y`0mtv;yp zJ0{oRZBFAZ&ho*&pa=A9Crs-2UW3-K?!X!7`5mY05FgrE#;5UZicjwcodOmO8Z=I1 zP{5)=g9ZgG8Z>Copnye#28~BHPWCP#6^o>A3;l>3yUTNw*ZgENEc#KTZwvj19J|YN zl-Hc5gfwW-I59y1iv|rECno4<&S{9bxw#+tksmq8Jr@@jpL_1Pdw7aZed<#eE?n4t zOTAwI#y7sPyu5sG=lqFJeB!LzW(*E?>@JWeB>kfeE#TO7mbq@tfDCNDxBzm zmH$V7^hc_y9{eHQZg*v6<<(bT{r>mA|DErA=O9nEU%CGFW@%r`aAO7%%x8L%uZ++`s?|Rq454*OuwzRbL%rnn?`O9CX9}Joj(m0Os z@sEG}uFwjiSS$h%0AzgWOJ92a`R9M{_kQor_a6)fd)^KQ0djW_=lp>Wd|>yDrfKfr zR(FL~KpbHP=m2pCQHlF9^mK4M5|EZf!LVcjQE_8Y zX%=Y`L}-p8i=^2M5`qe?ENKah5(q_-5sZ)!5=kJHO3lMQbI$ypzf*teol{k>Ufp}^ z`@U24?tOMbp^#{l5smEvx-!>)Vo~bI3nMz$*fmOX9QV_t(g0S|Pq8|UrHM-4PYE$= zTyW;iJHx@Rn8-V(>BcdQgs8hnq_*O$om$s(_pfk*v|LbRIfHR1b8;Kf35(~tFTV0q zssck|Z>hkHABQ#>?VSH>)0Pkv%uW^(5uw3gU{OtWjcK&*$Xoa4W78{cgLVV$13m|? z%uEzZu)%MVF1RMehA+l26J-JGSVO0sy7CK1iq>va0U6H=)_?mfSsu?$Cf&{eb}T9? zvPD*|h&Hto`s;_y#eWQHP6FvhU2Xi6A05o2X zRi^c`7jLiw0-_XY=GPNwGG~jRZl)H%}%^jw)}&7hv2BDPl=AeI^nTX^bB(lq#)Rc>%AjXY5?C z(oo3<U93eIn@Z*||3^k6ajwso& z+0U>voM4<{d7lBx2BGO2idStN&Cy(H#7%M{j&$d^=D+ta+CLwM5HWOCtM15(WXOvd z^2}3`j0p`ZJLsMLhinY0xGtvvNXWHVEeO_)>pFG8(Z!E~4fG}T2UqHZ58i9dEw22% z@;!aqRJ_&#`s)NZMUe)_H9X$~#Q-Np>@_Tq(Z6uSaSS0pk>n)u!5bzmh^f<*tepzw z&48CQJ1K=RMbUO3JQU{1x%&Z#$=9Aj7;G_CRf}WO)L=x6*=T%-{%yWnY{)8HBL#yr z$GyvR8lskhkqI3dA3GFC!@fUM2R>_eJxK)Rbp}hCDdjVbYCeP_5ZVjEK#Zl2wV-Mr z^lm4w=1(!Q4K}xAe>ULV~=*0BXCOzSu7RMrrv>syxWy=9xHr;kiD2d`DQQda#GKmE;vN*-rei*x$vr zwYXmC0-wFwm8`wD=e=)a&`X5xYFbkqUOj;*sX}Z7K-OHk&WdTAW->@q%{Xs;F>|SS z{Ws5dJy2=bXi!00_UFiD$d>u_GInms2=AR8J+F$=?>24k1Z(u5e0PH>y$?`fYVsN0 zlSGodM4U|sy^m4mfrs`jq#Ww1OiKSpPS(Kj@ho#iF_xhhvL}p!rKP180~SPGyI??R z)iz%S8KxND4B9albC_Y!*)N{163T-U{HQ^`iW8GlCJ*m+!iRws3D>kNj5{v?-{&P`{W$RMTIiP zgky8IR6BM%9oG67x_!1awc~2cJdrUT5~=4`SOeC}19jGrbRRNp{uLo8QSjv8u@Udh zW}y?D$0^q}*<4vI8TrI&oeNAqkPSk{VU0Vw*sJSsT{T?p?4#?mYCWpg2C1Jf+;R)j za;}LvBdlfS!+Ck+iZojMiTd%Sti8wEU~Sz~ehn-AoPeeZBM;uG`~p*M(KN|d0wyxj7ZfCI6wL64>Aq$P}2!-?G9S1upYNjvl@K`X1(!Z~Q4mZm;3`^5m|N!knHvAX z@0J7b@rt`YVHm1xUFPwAqiYpG&Cih%SH&z)m|Dtbq1`I^2r9Nlu_a7w-x`9SHCH(WyS+a>o?&9915BsRDl$W`EtDHp?&h^od4y@|JHEJ n-7R+v`uRU;^w_^beY#9szREMpNw}G90=B)oBX-sAh`Ri5zL$C} literal 0 HcmV?d00001 diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/package.mk b/packages/kernel/linux-driver-addons/dvb/crazycat/package.mk new file mode 100644 index 000000000..b209dad27 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/package.mk @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="crazycat" +PKG_VERSION="ca1ea9fc2cfaedfc32bd0ac628e03e9aa379e3ad" +PKG_SHA256="6b44a96d82c4a3e052864a995baceaede46b37c048c5718a6f62a009492d08ff" +PKG_LICENSE="GPL" +PKG_SITE="https://bitbucket.org/CrazyCat/media_build" +PKG_URL="https://bitbucket.org/CrazyCat/media_build/get/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux media_tree_cc" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory media_tree_cc)" +PKG_SECTION="driver.dvb" +PKG_LONGDESC="DVB driver for TBS cards with CrazyCats additions" + +PKG_IS_ADDON="embedded" +PKG_IS_KERNEL_PKG="yes" +PKG_ADDON_IS_STANDALONE="yes" +PKG_ADDON_NAME="DVB drivers for TBS" +PKG_ADDON_TYPE="xbmc.service" +PKG_ADDON_VERSION="${ADDON_VERSION}.${PKG_REV}" + +if [ "$PROJECT" = "Amlogic-ng" ]; then + PKG_PATCH_DIRS="amlogic-4.9" + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET media_tree_aml" + PKG_NEED_UNPACK="$PKG_NEED_UNPACK $(get_pkg_directory media_tree_aml)" +fi + +pre_make_target() { + export KERNEL_VER=$(get_module_dir) + export LDFLAGS="" +} + +make_target() { + cp -RP $(get_build_dir media_tree_cc)/* $PKG_BUILD/linux + if [ "$PROJECT" = "Amlogic-ng" ]; then + cp -Lr $(get_build_dir media_tree_aml)/* $PKG_BUILD/linux + echo "obj-y += video_dev/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo "obj-y += dvb/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo 'source "drivers/media/platform/meson/dvb/Kconfig"' >> "$PKG_BUILD/linux/drivers/media/platform/Kconfig" + sed -e 's/ && RC_CORE//g' -i $PKG_BUILD/linux/drivers/media/usb/dvb-usb/Kconfig + fi + + # make config all + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) allyesconfig + + # hack to workaround media_build bug + if [ "$PROJECT" = Rockchip ]; then + sed -e 's/CONFIG_DVB_CXD2820R=m/# CONFIG_DVB_CXD2820R is not set/g' -i v4l/.config + sed -e 's/CONFIG_DVB_LGDT3306A=m/# CONFIG_DVB_LGDT3306A is not set/g' -i v4l/.config +# elif [ "$PROJECT" = "Amlogic-ng" ]; then +# sed -e 's/# CONFIG_MEDIA_TUNER_TDA18250 is not set/CONFIG_MEDIA_TUNER_TDA18250=m/g' -i $PKG_BUILD/v4l/.config + fi + + # add menuconfig to edit .config + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) +} + +makeinstall_target() { + install_driver_addon_files "$PKG_BUILD/v4l/" +} diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-02-disable-modules.patch b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-02-disable-modules.patch new file mode 100644 index 000000000..7bd7b533f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-02-disable-modules.patch @@ -0,0 +1,15 @@ +--- a/v4l/scripts/make_kconfig.pl ++++ b/v4l/scripts/make_kconfig.pl +@@ -626,6 +626,12 @@ ($$) + close OUT; + + # These options should default to off ++disable_config('MEDIA_ANALOG_TV_SUPPORT'); ++disable_config('MEDIA_CAMERA_SUPPORT'); ++disable_config('MEDIA_CEC_SUPPORT'); ++disable_config('SOC_CAMERA'); ++disable_config('VIDEO_SAA7146_VV'); ++disable_config('RC_CORE'); + disable_config('DVB_AV7110_FIRMWARE'); + disable_config('DVB_CINERGYT2_TUNING'); + disable_config('VIDEO_HELPER_CHIPS_AUTO'); diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-03-config_mycompat_h.patch b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-03-config_mycompat_h.patch new file mode 100644 index 000000000..1050fb340 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/amlogic-4.9/driver.dvb.crazycat-03-config_mycompat_h.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/v4l/config-mycompat.h +@@ -0,0 +1,8 @@ ++#undef smp_mb__after_atomic ++#define smp_mb__after_atomic() smp_mb() /*mb*/ ++#undef NEED_SMP_MB_AFTER_ATOMIC ++#undef writel_relaxed ++#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) ++#undef NEED_WRITEL_RELAXED ++#undef NEED_PM_RUNTIME_GET ++#undef NEED_OF_NODE_NAME_EQ +-- diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/patches/driver.dvb.crazycat-01-remove-rmmod.pl.patch b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/driver.dvb.crazycat-01-remove-rmmod.pl.patch new file mode 100644 index 000000000..b7a80a643 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/patches/driver.dvb.crazycat-01-remove-rmmod.pl.patch @@ -0,0 +1,13 @@ +[Patch] without this patch you need to install libproc-processtable-perl at host system + +--- a/v4l/Makefile ++++ b/v4l/Makefile +@@ -51,7 +51,7 @@ + @echo Kernel build directory is $(OUTDIR) + $(MAKE) -C ../linux apply_patches + $(MAKE) -C $(OUTDIR) SUBDIRS=$(PWD) $(MYCFLAGS) modules +- ./scripts/rmmod.pl check ++# ./scripts/rmmod.pl check + # $(MAKE) checkpatch + + mismatch:: prepare firmware diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat/source/default.py b/packages/kernel/linux-driver-addons/dvb/crazycat/source/default.py new file mode 100644 index 000000000..c8f85a76f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat/source/default.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/changelog.txt b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/changelog.txt new file mode 100755 index 000000000..32d81ca42 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial add-on diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/icon/icon.png b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22a6c6a0d90344f27d68561d8d44115debdfe89a GIT binary patch literal 68596 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 literal 0 HcmV?d00001 diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/package.mk b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/package.mk new file mode 100644 index 000000000..c8c2755f0 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/package.mk @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="crazycat_aml" +PKG_VERSION="835dc72da3ee63df7f4057bd0507887454c005d1" +PKG_SHA256="3d68d368a9eda15688c6686caa854a045a753740ec93553d80a4bcfc14c2950a" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://bitbucket.org/CrazyCat/media_build" +PKG_URL="https://bitbucket.org/CrazyCat/media_build/get/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux media_tree_cc_aml media_tree_aml" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory media_tree_cc_aml) $(get_pkg_directory media_tree_aml)" +PKG_SECTION="driver.dvb" +PKG_LONGDESC="DVB driver for TBS cards with CrazyCats additions" + +PKG_IS_ADDON="embedded" +PKG_IS_KERNEL_PKG="yes" +PKG_ADDON_IS_STANDALONE="yes" +PKG_ADDON_NAME="DVB drivers for TBS" +PKG_ADDON_TYPE="xbmc.service" +PKG_ADDON_VERSION="${ADDON_VERSION}.${PKG_REV}" + +case "$LINUX" in + amlogic-3.14) + PKG_PATCH_DIRS="amlogic-3.14" + ;; +esac + +pre_make_target() { + export KERNEL_VER=$(get_module_dir) + export LDFLAGS="" +} + +make_target() { + cp -RP $(get_build_dir media_tree_cc_aml)/* $PKG_BUILD/linux + rm -rf $PKG_BUILD/linux/drivers/media/platform/meson/wetek + rm -rf $PKG_BUILD/linux/drivers/media/platform/meson/dvb-avl + cp -Lr $(get_build_dir media_tree_aml)/* $PKG_BUILD/linux + + # compile modules + echo "obj-y += video_dev/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo "obj-y += dvb/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo 'source "drivers/media/platform/meson/dvb/Kconfig"' >> "$PKG_BUILD/linux/drivers/media/platform/Kconfig" + sed -e 's/ && RC_CORE//g' -i $PKG_BUILD/linux/drivers/media/usb/dvb-usb/Kconfig + + # make config all + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) allyesconfig + + # deactivate several build options + sed '/CONFIG_VIDEO_S5C73M3=m/d' -i $PKG_BUILD/v4l/.config + + # enable AML drivers + echo "CONFIG_V4L_AMLOGIC_VIDEO=m" >> $PKG_BUILD/v4l/.config + echo "CONFIG_VIDEOBUF_RESOURCE=m" >> $PKG_BUILD/v4l/.config + + # hack to workaround media_build bug + sed -e 's/CONFIG_VIDEO_SAA7146_VV=m/# CONFIG_VIDEO_SAA7146_VV is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_S5K5BAF=m/# CONFIG_VIDEO_S5K5BAF is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_TVP514X=m/# CONFIG_VIDEO_TVP514X is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_TVP7002=m/# CONFIG_VIDEO_TVP7002 is not set/g' -i $PKG_BUILD/v4l/.config + + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) +} + +makeinstall_target() { + install_driver_addon_files "$PKG_BUILD/v4l/" +} diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-02-disable-modules.patch b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-02-disable-modules.patch new file mode 100644 index 000000000..e2659408e --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-02-disable-modules.patch @@ -0,0 +1,13 @@ +--- a/v4l/scripts/make_kconfig.pl ++++ b/v4l/scripts/make_kconfig.pl +@@ -626,6 +626,10 @@ ($$) + close OUT; + + # These options should default to off ++disable_config('MEDIA_ANALOG_TV_SUPPORT'); ++disable_config('MEDIA_CAMERA_SUPPORT'); ++disable_config('MEDIA_CEC_SUPPORT'); ++disable_config('SOC_CAMERA'); + disable_config('DVB_AV7110_FIRMWARE'); + disable_config('DVB_CINERGYT2_TUNING'); + disable_config('VIDEO_HELPER_CHIPS_AUTO'); diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-03-config_mycompat_h.patch b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-03-config_mycompat_h.patch new file mode 100644 index 000000000..9cfce1bf4 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/amlogic-3.14/driver.dvb.crazycat_aml-03-config_mycompat_h.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/v4l/config-mycompat.h +@@ -0,0 +1,11 @@ ++#undef smp_mb__after_atomic ++#define smp_mb__after_atomic() smp_mb() /*mb*/ ++#undef NEED_SMP_MB_AFTER_ATOMIC ++#undef __pfn_to_phys ++#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) ++#undef NEED_PFN_TO_PHYS ++#undef writel_relaxed ++#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) ++#undef NEED_WRITEL_RELAXED ++#undef NEED_PM_RUNTIME_GET ++#undef NEED_OF_NODE_NAME_EQ +-- diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/driver.dvb.crazycat_aml-01-remove-rmmod.pl.patch b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/driver.dvb.crazycat_aml-01-remove-rmmod.pl.patch new file mode 100644 index 000000000..b7a80a643 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/patches/driver.dvb.crazycat_aml-01-remove-rmmod.pl.patch @@ -0,0 +1,13 @@ +[Patch] without this patch you need to install libproc-processtable-perl at host system + +--- a/v4l/Makefile ++++ b/v4l/Makefile +@@ -51,7 +51,7 @@ + @echo Kernel build directory is $(OUTDIR) + $(MAKE) -C ../linux apply_patches + $(MAKE) -C $(OUTDIR) SUBDIRS=$(PWD) $(MYCFLAGS) modules +- ./scripts/rmmod.pl check ++# ./scripts/rmmod.pl check + # $(MAKE) checkpatch + + mismatch:: prepare firmware diff --git a/packages/kernel/linux-driver-addons/dvb/crazycat_aml/source/default.py b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/source/default.py new file mode 100644 index 000000000..c8f85a76f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/crazycat_aml/source/default.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/package.mk b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/package.mk new file mode 100644 index 000000000..a10062e09 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="media_tree" +PKG_VERSION="2019-07-11-22be8233b34f" +PKG_SHA256="14363b1aacfe59805a1fe93739caed53036879e7b871f1d8d7061527c3cb9eb8" +PKG_LICENSE="GPL" +PKG_SITE="https://git.linuxtv.org/media_tree.git" +PKG_URL="http://linuxtv.org/downloads/drivers/linux-media-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Source of Linux Kernel media_tree subsystem to build with media_build." +PKG_TOOLCHAIN="manual" + +case "$LINUX" in + amlogic-4.9) + PKG_PATCH_DIRS="amlogic-4.9" + ;; +esac + +unpack() { + mkdir -p $PKG_BUILD/ + tar -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.bz2 -C $PKG_BUILD/ +} + +post_unpack() { + # hack/workaround for borked upstream kernel/media_build + # without removing atomisp there a lot additional includes that + # slowdown build process after modpost from 3min to 6min + # even if atomisp is disabled via kernel.conf + rm -rf $PKG_BUILD/drivers/staging/media/atomisp + sed -i 's|^.*drivers/staging/media/atomisp.*$||' \ + $PKG_BUILD/drivers/staging/media/Kconfig +} diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree-06-of-node.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree-06-of-node.patch new file mode 100644 index 000000000..ba4e47a24 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree-06-of-node.patch @@ -0,0 +1,23 @@ +--- a/drivers/media/v4l2-core/v4l2-fwnode.c 2019-04-02 00:31:42.224001000 +0200 ++++ b/drivers/media/v4l2-core/v4l2-fwnode.c 2019-04-02 00:31:42.256001000 +0200 +@@ -553,6 +553,20 @@ + } + EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); + ++bool of_node_name_eq(const struct device_node *np, const char *name) ++{ ++ const char *node_name; ++ size_t len; ++ ++ if (!np) ++ return false; ++ ++ node_name = kbasename(np->full_name); ++ len = strchrnul(node_name, '@') - node_name; ++ ++ return (strlen(name) == len) && (strncmp(node_name, name, len) == 0); ++} ++ + int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, + struct v4l2_fwnode_link *link) + { diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch new file mode 100644 index 000000000..5703ddc2f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch @@ -0,0 +1,74 @@ +diff -ur a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c 2019-07-10 23:44:44.000000000 +0100 ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c 2019-12-18 04:54:05.614904632 +0000 +@@ -443,6 +443,42 @@ + } + EXPORT_SYMBOL(v4l2_m2m_job_finish); + ++void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ dprintk("Called by an instance not currently running\n"); ++ return; ++ } ++ ++ list_del(&m2m_dev->curr_ctx->queue); ++ m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); ++ m2m_dev->curr_ctx->job_flags |= TRANS_ABORT; ++ wake_up(&m2m_dev->curr_ctx->finished); ++ m2m_dev->curr_ctx = NULL; ++ ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++} ++EXPORT_SYMBOL(v4l2_m2m_job_pause); ++ ++void v4l2_m2m_job_resume(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ m2m_ctx->job_flags &= ~TRANS_ABORT; ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ ++ v4l2_m2m_try_schedule(m2m_ctx); ++ v4l2_m2m_try_run(m2m_dev); ++} ++EXPORT_SYMBOL(v4l2_m2m_job_resume); ++ + int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_requestbuffers *reqbufs) + { +diff -ur a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +--- a/include/media/v4l2-mem2mem.h 2019-07-10 23:44:45.000000000 +0100 ++++ b/include/media/v4l2-mem2mem.h 2019-12-18 04:54:31.579097310 +0000 +@@ -573,6 +573,24 @@ + return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx); + } + ++/* ++ * v4l2_m2m_job_pause() - paused the schedule of data which from the job queue. ++ * ++ * @m2m_dev: opaque pointer to the internal data to handle M2M context ++ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx ++ */ ++void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx); ++ ++ /* ++ * v4l2_m2m_job_resume() - resumed the schedule of data which from the job que. ++ * ++ * @m2m_dev: opaque pointer to the internal data to handle M2M context ++ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx ++ */ ++void v4l2_m2m_job_resume(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx); ++ + /** + * v4l2_m2m_buf_remove_by_buf() - take off exact buffer from the list of ready + * buffers diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-m88ds3103b.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-m88ds3103b.patch new file mode 100644 index 000000000..c079433e0 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-01-m88ds3103b.patch @@ -0,0 +1,746 @@ +From: Brad Love +https://git.linuxtv.org/brad/media_tree.git/log/?h=Montage-3103b.v2 +support for m88ds3103b + +diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +index 3a367a5..0d3b81d 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.c ++++ b/drivers/media/dvb-frontends/m88ds3103.c +@@ -64,6 +64,92 @@ err: + return ret; + } + ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for one transaction, then writes will be allowed. ++ */ ++static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) ++{ ++ struct i2c_client *client = dev->client; ++ u8 buf[] = {reg, data}; ++ u8 val; ++ int ret; ++ struct i2c_msg msg = { ++ .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x11; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, &msg, 1); ++ if (ret != 1) { ++ dev_dbg(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n", ++ dev->dt_addr, ret, reg, data); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, data); ++ ++ return 0; ++} ++ ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for two transactions, then reads will be allowed. ++ */ ++static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) ++{ ++ struct i2c_client *client = dev->client; ++ int ret; ++ u8 val; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = dev->dt_addr, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, ++ { ++ .addr = dev->dt_addr, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 1 ++ } ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x12; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, msg, 2); ++ if (ret != 2) { ++ dev_dbg(&client->dev, "0x%02x (err=%d, reg=0x%02x)\n", ++ dev->dt_addr, ret, reg); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, b1[0]); ++ ++ return b1[0]; ++} ++ + /* + * Get the demodulator AGC PWM voltage setting supplied to the tuner. + */ +@@ -288,6 +374,253 @@ err: + return ret; + } + ++static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) ++{ ++ struct i2c_client *client = dev->client; ++ struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; ++ u32 adc_Freq_MHz[3] = {96, 93, 99}; ++ u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; ++ u32 offset_MHz[3]; ++ u32 max_offset = 0; ++ u32 old_setting = dev->mclk; ++ u32 tuner_freq_MHz = c->frequency / 1000; ++ u8 i; ++ char big_symbol = 0; ++ ++ big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; ++ ++ if (big_symbol) { ++ reg16 = 115; ++ } else { ++ reg16 = 96; ++ ++ /* TODO: IS THIS NECESSARY ? */ ++ for (i = 0; i < 3; i++) { ++ offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; ++ ++ if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) ++ offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; ++ ++ if (offset_MHz[i] > max_offset) { ++ max_offset = offset_MHz[i]; ++ reg16 = reg16_list[i]; ++ dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; ++ ++ if (big_symbol) ++ dev->mclk /= 2; ++ ++ dev_dbg(&client->dev, "modifying mclk %u -> %u\n", ++ old_setting, dev->mclk); ++ } ++ } ++ } ++ ++ if (dev->mclk == 93000000) ++ regmap_write(dev->regmap, 0xA0, 0x42); ++ else if (dev->mclk == 96000000) ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ else if (dev->mclk == 99000000) ++ regmap_write(dev->regmap, 0xA0, 0x46); ++ else if (dev->mclk == 110250000) ++ regmap_write(dev->regmap, 0xA0, 0x4E); ++ else ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ ++ if (big_symbol) ++ reg15 |= 0x02; ++ else ++ reg15 &= ~0x02; ++ ++ m88ds3103b_dt_write(dev, 0x15, reg15); ++ m88ds3103b_dt_write(dev, 0x16, reg16); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ ++static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) ++{ ++ u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; ++ u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0, pll_ldpc_mode; ++ u16 pll_div_fb, N; ++ u32 div; ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ reg16 = m88ds3103b_dt_read(dev, 0x16); ++ reg1D = m88ds3103b_dt_read(dev, 0x1D); ++ ++ if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { ++ if (reg16 == 92) ++ tmp = 93; ++ else if (reg16 == 100) ++ tmp = 99; ++ else ++ tmp = 96; ++ ++ mclk_khz *= tmp; ++ mclk_khz /= 96; ++ } ++ ++ pll_ldpc_mode = (reg15 >> 1) & 0x01; ++ ++ pll_div_fb = (reg15 & 0x01) << 8; ++ pll_div_fb += reg16; ++ pll_div_fb += 32; ++ ++ div = 9000 * pll_div_fb * 4; ++ div /= mclk_khz; ++ ++ if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { ++ reg11 |= 0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 34) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 8) && (f0 != 0)) ++ f0 = 8; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 8) && (f1 != 0)) ++ f1 = 8; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 8) && (f2 != 0)) ++ f2 = 8; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 8) && (f3 != 0)) ++ f3 = 8; ++ } else { ++ reg11 &= ~0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 48) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 9) && (f0 != 0)) ++ f0 = 9; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 9) && (f1 != 0)) ++ f1 = 9; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 9) && (f2 != 0)) ++ f2 = 9; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 9) && (f3 != 0)) ++ f3 = 9; ++ } ++ ++ sm = N - 1; ++ ++ /* Write to registers */ ++ //reg15 &= 0x01; ++ //reg15 |= (pll_div_fb >> 8) & 0x01; ++ ++ //reg16 = pll_div_fb & 0xFF; ++ ++ reg1D &= ~0x03; ++ reg1D |= sm; ++ reg1D |= 0x80; ++ ++ reg1E = ((f3 << 4) + f2) & 0xFF; ++ reg1F = ((f1 << 4) + f0) & 0xFF; ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ m88ds3103b_dt_write(dev, 0x1D, reg1D); ++ m88ds3103b_dt_write(dev, 0x1E, reg1E); ++ m88ds3103b_dt_write(dev, 0x1F, reg1F); ++ ++ m88ds3103b_dt_write(dev, 0x17, 0xc1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, 0x0A); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ + static int m88ds3103_set_frontend(struct dvb_frontend *fe) + { + struct m88ds3103_dev *dev = fe->demodulator_priv; +@@ -298,7 +631,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ + u8 buf[3]; + u16 u16tmp; +- u32 tuner_frequency_khz, target_mclk; ++ u32 tuner_frequency_khz, target_mclk, u32tmp; + s32 s32tmp; + static const struct reg_sequence reset_buf[] = { + {0x07, 0x80}, {0x07, 0x00} +@@ -321,6 +654,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + + /* Disable demod clock path */ + if (dev->chip_id == M88RS6000_CHIP_ID) { ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = regmap_read(dev->regmap, 0xb2, &u32tmp); ++ if (ret) ++ goto err; ++ if (u32tmp == 0x01) { ++ ret = regmap_write(dev->regmap, 0x00, 0x00); ++ if (ret) ++ goto err; ++ ret = regmap_write(dev->regmap, 0xb2, 0x00); ++ if (ret) ++ goto err; ++ } ++ } ++ + ret = regmap_write(dev->regmap, 0x06, 0xe0); + if (ret) + goto err; +@@ -346,7 +693,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + tuner_frequency_khz = c->frequency; + } + +- /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ ++ /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ + if (dev->chip_id == M88RS6000_CHIP_ID) { + if (c->symbol_rate > 45010000) + dev->mclk = 110250000; +@@ -358,6 +705,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + target_mclk = 144000000; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_select_mclk(dev); ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ } ++ + /* Enable demod clock path */ + ret = regmap_write(dev->regmap, 0x06, 0x00); + if (ret) +@@ -469,12 +821,42 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); + if (ret) + goto err; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ buf[0] = m88ds3103b_dt_read(dev, 0x15); ++ buf[1] = m88ds3103b_dt_read(dev, 0x16); ++ ++ if (c->symbol_rate > 45010000) { ++ buf[0] &= ~0x03; ++ buf[0] |= 0x02; ++ buf[0] |= ((147 - 32) >> 8) & 0x01; ++ buf[1] = (147 - 32) & 0xFF; ++ ++ dev->mclk = 110250 * 1000; ++ } else { ++ buf[0] &= ~0x03; ++ buf[0] |= ((128 - 32) >> 8) & 0x01; ++ buf[1] = (128 - 32) & 0xFF; ++ ++ dev->mclk = 96000 * 1000; ++ } ++ m88ds3103b_dt_write(dev, 0x15, buf[0]); ++ m88ds3103b_dt_write(dev, 0x16, buf[1]); ++ ++ regmap_read(dev->regmap, 0x30, &u32tmp); ++ u32tmp &= ~0x80; ++ regmap_write(dev->regmap, 0x30, u32tmp & 0xff); ++ } ++ + ret = regmap_write(dev->regmap, 0xf1, 0x01); + if (ret) + goto err; +- ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); +- if (ret) +- goto err; ++ ++ if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); ++ if (ret) ++ goto err; ++ } + } + + switch (dev->cfg->ts_mode) { +@@ -488,6 +870,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + break; + case M88DS3103_TS_PARALLEL: + u8tmp = 0x02; ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ u8tmp = 0x01; ++ u8tmp1 = 0x01; ++ } + break; + case M88DS3103_TS_CI: + u8tmp = 0x03; +@@ -516,6 +902,12 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8tmp1 = 0x3f; + u8tmp2 = 0x3f; + break; ++ case M88DS3103_TS_PARALLEL: ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); ++ if (ret) ++ goto err; ++ } + default: + u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); + u8tmp1 = u16tmp / 2 - 1; +@@ -543,6 +935,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + u8tmp = 0x06; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ + ret = regmap_write(dev->regmap, 0xc3, 0x08); + if (ret) + goto err; +@@ -578,6 +973,16 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable/disable 192M LDPC clock */ ++ ret = m88ds3103_update_bits(dev, 0x29, 0x10, ++ (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); ++ if (ret) ++ goto err; ++ ++ ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); ++ } ++ + dev_dbg(&client->dev, "carrier offset=%d\n", + (tuner_frequency_khz - c->frequency)); + +@@ -654,10 +1059,13 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "found a '%s' in cold state\n", + m88ds3103_ops.info.name); + +- if (dev->chip_id == M88RS6000_CHIP_ID) ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ name = M88DS3103B_FIRMWARE; ++ else if (dev->chip_id == M88RS6000_CHIP_ID) + name = M88RS6000_FIRMWARE; + else + name = M88DS3103_FIRMWARE; ++ + /* request the firmware, this will block and timeout */ + ret = request_firmware(&firmware, name, &client->dev); + if (ret) { +@@ -704,6 +1112,12 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "firmware version: %X.%X\n", + (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_dt_write(dev, 0x21, 0x92); ++ m88ds3103b_dt_write(dev, 0x15, 0x6C); ++ m88ds3103b_dt_write(dev, 0x17, 0xC1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ } + warm: + /* warm state */ + dev->warm = true; +@@ -1393,6 +1807,8 @@ static int m88ds3103_probe(struct i2c_client *client, + goto err_kfree; + + dev->chip_id = utmp >> 1; ++ dev->chiptype = (u8)id->driver_data; ++ + dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); + + switch (dev->chip_id) { +@@ -1470,6 +1886,19 @@ static int m88ds3103_probe(struct i2c_client *client, + /* setup callbacks */ + pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; + pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable i2c repeater for tuner */ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ /* get frontend address */ ++ ret = regmap_read(dev->regmap, 0x29, &utmp); ++ if (ret) ++ goto err_kfree; ++ dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; ++ dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr); ++ } ++ + return 0; + err_kfree: + kfree(dev); +@@ -1491,7 +1920,9 @@ static int m88ds3103_remove(struct i2c_client *client) + } + + static const struct i2c_device_id m88ds3103_id_table[] = { +- {"m88ds3103", 0}, ++ {"m88ds3103", M88DS3103_CHIPTYPE_3103}, ++ {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, ++ {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, + {} + }; + MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); +@@ -1513,3 +1944,4 @@ MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver"); + MODULE_LICENSE("GPL"); + MODULE_FIRMWARE(M88DS3103_FIRMWARE); + MODULE_FIRMWARE(M88RS6000_FIRMWARE); ++MODULE_FIRMWARE(M88DS3103B_FIRMWARE); +diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h +index c825032..d656ec2 100644 +--- a/drivers/media/dvb-frontends/m88ds3103_priv.h ++++ b/drivers/media/dvb-frontends/m88ds3103_priv.h +@@ -16,11 +16,17 @@ + #include + #include + +-#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" +-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++#define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw" ++#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" ++#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++ + #define M88RS6000_CHIP_ID 0x74 + #define M88DS3103_CHIP_ID 0x70 + ++#define M88DS3103_CHIPTYPE_3103 0 ++#define M88DS3103_CHIPTYPE_RS6000 1 ++#define M88DS3103_CHIPTYPE_3103B 2 ++ + struct m88ds3103_dev { + struct i2c_client *client; + struct regmap_config regmap_config; +@@ -35,10 +41,13 @@ struct m88ds3103_dev { + struct i2c_mux_core *muxc; + /* auto detect chip id to do different config */ + u8 chip_id; ++ /* chip type to differentiate m88rs6000 from m88ds3103b */ ++ u8 chiptype; + /* main mclk is calculated for M88RS6000 dynamically */ + s32 mclk; + u64 post_bit_error; + u64 post_bit_count; ++ u8 dt_addr; + }; + + struct m88ds3103_reg_val { +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 1283c7c..6561f7b 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2397,6 +2397,20 @@ const struct em28xx_board em28xx_boards[] = { + .has_dvb = 1, + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, + }, ++ /* ++ * 2013:0259 PCTV DVB-S2 Stick (461e_v2) ++ * Empia EM28178, Montage M88DS3103b, Montage M88TS2022, Allegro A8293 ++ */ ++ [EM28178_BOARD_PCTV_461E_V2] = { ++ .def_i2c_bus = 1, ++ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ .name = "PCTV DVB-S2 Stick (461e v2)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_461e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ }, + /* + * 2013:025f PCTV tripleStick (292e). + * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 +@@ -2678,6 +2692,10 @@ struct usb_device_id em28xx_id_table[] = { + .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, + { USB_DEVICE(0x2013, 0x0258), + .driver_info = EM28178_BOARD_PCTV_461E }, ++ { USB_DEVICE(0x2013, 0x0461), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, ++ { USB_DEVICE(0x2013, 0x0259), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, + { USB_DEVICE(0x2013, 0x025f), + .driver_info = EM28178_BOARD_PCTV_292E }, + { USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */ +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index a73faf1..e2ddc25 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -1219,6 +1219,65 @@ static int em28178_dvb_init_pctv_461e(struct em28xx *dev) + return 0; + } + ++static int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev) ++{ ++ struct em28xx_dvb *dvb = dev->dvb; ++ struct i2c_adapter *i2c_adapter; ++ struct m88ds3103_platform_data m88ds3103_pdata = {}; ++ struct ts2020_config ts2020_config = {}; ++ struct a8293_platform_data a8293_pdata = {}; ++ ++ /* attach demod */ ++ m88ds3103_pdata.clk = 27000000; ++ m88ds3103_pdata.i2c_wr_max = 33; ++ m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; ++ m88ds3103_pdata.ts_clk = 16000; ++ m88ds3103_pdata.ts_clk_pol = 1; ++ m88ds3103_pdata.agc = 0x99; ++ m88ds3103_pdata.agc_inv = 1; ++ m88ds3103_pdata.spec_inv = 1; ++ dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b", ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x6a, &m88ds3103_pdata); ++ ++ if (!dvb->i2c_client_demod) { ++ pr_err("%s() FUCK\n", __func__); ++ return -ENODEV; ++ } ++ ++ dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); ++ i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); ++ ++ /* attach tuner */ ++ ts2020_config.fe = dvb->fe[0]; ++ dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", ++ i2c_adapter, ++ 0x60, &ts2020_config); ++ if (!dvb->i2c_client_tuner) { ++ pr_err("%s() FUCK2\n", __func__); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ /* delegate signal strength measurement to tuner */ ++ dvb->fe[0]->ops.read_signal_strength = ++ dvb->fe[0]->ops.tuner_ops.get_rf_strength; ++ ++ /* attach SEC */ ++ a8293_pdata.dvb_frontend = dvb->fe[0]; ++ dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x08, &a8293_pdata); ++ if (!dvb->i2c_client_sec) { ++ pr_err("%s() FUCK3\n", __func__); ++ dvb_module_release(dvb->i2c_client_tuner); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int em28178_dvb_init_pctv_292e(struct em28xx *dev) + { + struct em28xx_dvb *dvb = dev->dvb; +@@ -1860,6 +1919,11 @@ static int em28xx_dvb_init(struct em28xx *dev) + if (result) + goto out_free; + break; ++ case EM28178_BOARD_PCTV_461E_V2: ++ result = em28178_dvb_init_pctv_461e_v2(dev); ++ if (result) ++ goto out_free; ++ break; + case EM28178_BOARD_PCTV_292E: + result = em28178_dvb_init_pctv_292e(dev); + if (result) +diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h +index a551072..1affdd1 100644 +--- a/drivers/media/usb/em28xx/em28xx.h ++++ b/drivers/media/usb/em28xx/em28xx.h +@@ -149,6 +149,7 @@ + #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 + #define EM2884_BOARD_TERRATEC_H6 101 + #define EM2882_BOARD_ZOLID_HYBRID_TV_STICK 102 ++#define EM28178_BOARD_PCTV_461E_V2 103 + + /* Limits minimum and default number of buffers */ + #define EM28XX_MIN_BUF 4 +-- +2.17.1 diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-02-add-t230c2.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-02-add-t230c2.patch new file mode 100644 index 000000000..c67b37845 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-02-add-t230c2.patch @@ -0,0 +1,217 @@ +From: Thomas Hollstegge +[v3] media: dvbsky: Add support for MyGica T230C v2 +https://lore.kernel.org/patchwork/cover/904817/ + +diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c +index 4d43424..3402b96 100644 +--- a/drivers/media/dvb-frontends/si2168.c ++++ b/drivers/media/dvb-frontends/si2168.c +@@ -96,13 +96,15 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) + dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire); + + /* set TS_MODE property */ +- memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); ++ memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6); + if (acquire) + cmd.args[4] |= dev->ts_mode; + else + cmd.args[4] |= SI2168_TS_TRISTATE; + if (dev->ts_clock_gapped) + cmd.args[4] |= 0x40; ++ cmd.args[4] |= (dev->ts_clock_mode & 0x03) << 4; ++ + cmd.wlen = 6; + cmd.rlen = 4; + ret = si2168_cmd_execute(client, &cmd); +@@ -644,6 +646,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + ++ /* set TS frequency */ ++ if (dev->ts_clock_freq) { ++ memcpy(cmd.args, "\x14\x00\x0d\x10", 4); ++ cmd.args[4] = ((dev->ts_clock_freq / 10000) >> 0) & 0xff; ++ cmd.args[5] = ((dev->ts_clock_freq / 10000) >> 8) & 0xff; ++ cmd.wlen = 6; ++ cmd.rlen = 4; ++ ret = si2168_cmd_execute(client, &cmd); ++ if (ret) ++ goto err; ++ } ++ + memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6); + cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; + cmd.wlen = 6; +@@ -1057,6 +1071,10 @@ static int si2168_probe(struct i2c_client *client, + dev->ts_mode = config->ts_mode; + dev->ts_clock_inv = config->ts_clock_inv; + dev->ts_clock_gapped = config->ts_clock_gapped; ++ dev->ts_clock_mode = config->ts_clock_mode; ++ if (dev->ts_clock_mode == 0) ++ dev->ts_clock_mode = SI2168_TS_CLOCK_MODE_AUTO_ADAPT; ++ dev->ts_clock_freq = config->ts_clock_freq; + dev->spectral_inversion = config->spectral_inversion; + + dev_info(&client->dev, "Silicon Labs Si2168-%c%d%d successfully identified\n", +diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h +index d519edd..3f52ee8 100644 +--- a/drivers/media/dvb-frontends/si2168.h ++++ b/drivers/media/dvb-frontends/si2168.h +@@ -47,6 +47,14 @@ struct si2168_config { + /* TS clock gapped */ + bool ts_clock_gapped; + ++ /* TS clock mode */ ++#define SI2168_TS_CLOCK_MODE_AUTO_ADAPT 0x01 ++#define SI2168_TS_CLOCK_MODE_MANUAL 0x02 ++ u8 ts_clock_mode; ++ ++ /* TS clock frequency (for manual mode) */ ++ u32 ts_clock_freq; ++ + /* Inverted spectrum */ + bool spectral_inversion; + }; +diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h +index 2d362e1..8173d6c 100644 +--- a/drivers/media/dvb-frontends/si2168_priv.h ++++ b/drivers/media/dvb-frontends/si2168_priv.h +@@ -48,6 +48,8 @@ struct si2168_dev { + u8 ts_mode; + bool ts_clock_inv; + bool ts_clock_gapped; ++ u8 ts_clock_mode; ++ u32 ts_clock_freq; + bool spectral_inversion; + }; + +diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c +index e28bd88..4a4c6ae 100644 +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c +@@ -583,6 +583,66 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) + return 0; + } + ++static int dvbsky_mygica_t230c_v2_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvbsky_state *state = adap_to_priv(adap); ++ struct dvb_usb_device *d = adap_to_d(adap); ++ struct i2c_adapter *i2c_adapter; ++ struct i2c_client *client_demod, *client_tuner; ++ struct i2c_board_info info; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ ++ /* attach demod */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &i2c_adapter; ++ si2168_config.fe = &adap->fe[0]; ++ si2168_config.ts_mode = SI2168_TS_PARALLEL; ++ si2168_config.ts_clock_inv = 1; ++ si2168_config.ts_clock_mode = SI2168_TS_CLOCK_MODE_MANUAL; ++ si2168_config.ts_clock_freq = 10000000; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", sizeof(info.type)); ++ info.addr = 0x64; ++ info.platform_data = &si2168_config; ++ ++ request_module("si2168"); ++ client_demod = i2c_new_device(&d->i2c_adap, &info); ++ if (!client_demod || !client_demod->dev.driver) ++ goto fail_demod_device; ++ if (!try_module_get(client_demod->dev.driver->owner)) ++ goto fail_demod_module; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = adap->fe[0]; ++ si2157_config.if_port = 0; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2141", sizeof(info.type)); ++ info.addr = 0x60; ++ info.platform_data = &si2157_config; ++ ++ request_module("si2157"); ++ client_tuner = i2c_new_device(i2c_adapter, &info); ++ if (!client_tuner || !client_tuner->dev.driver) ++ goto fail_tuner_device; ++ if (!try_module_get(client_tuner->dev.driver->owner)) ++ goto fail_tuner_module; ++ ++ state->i2c_client_demod = client_demod; ++ state->i2c_client_tuner = client_tuner; ++ return 0; ++ ++fail_tuner_module: ++ i2c_unregister_device(client_tuner); ++fail_tuner_device: ++ module_put(client_demod->dev.driver->owner); ++fail_demod_module: ++ i2c_unregister_device(client_demod); ++fail_demod_device: ++ return -ENODEV; ++} ++ + + static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) + { +@@ -762,6 +822,33 @@ static struct dvb_usb_device_properties mygica_t230c_props = { + } + }; + ++static struct dvb_usb_device_properties mygica_t230c_v2_props = { ++ .driver_name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .adapter_nr = adapter_nr, ++ .size_of_priv = sizeof(struct dvbsky_state), ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ .generic_bulk_ctrl_endpoint_response = 0x81, ++ .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY, ++ ++ .i2c_algo = &dvbsky_i2c_algo, ++ .frontend_attach = dvbsky_mygica_t230c_v2_attach, ++ .init = dvbsky_init, ++ .get_rc_config = dvbsky_get_rc_config, ++ .streaming_ctrl = dvbsky_streaming_ctrl, ++ .identify_state = dvbsky_identify_state, ++ .exit = dvbsky_exit, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), ++ } ++ } ++}; ++ ++ + static const struct usb_device_id dvbsky_id_table[] = { + { DVB_USB_DEVICE(0x0572, 0x6831, + &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, +@@ -797,6 +884,9 @@ static const struct usb_device_id dvbsky_id_table[] = { + { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C, + &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C", + RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, ++ { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_V2, ++ &mygica_t230c_v2_props, "MyGica Mini DVB-T2 USB Stick T230C v2", ++ RC_MAP_TOTAL_MEDIA_IN_HAND_02) }, + { } + }; + MODULE_DEVICE_TABLE(usb, dvbsky_id_table); +diff --git a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h +index f9e73b4..d606248 100644 +--- a/include/media/dvb-usb-ids.h ++++ b/include/media/dvb-usb-ids.h +@@ -387,6 +387,7 @@ + #define USB_PID_MYGICA_D689 0xd811 + #define USB_PID_MYGICA_T230 0xc688 + #define USB_PID_MYGICA_T230C 0xc689 ++#define USB_PID_MYGICA_T230C_V2 0xc68a + #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 + #define USB_PID_ELGATO_EYETV_DTT 0x0021 + #define USB_PID_ELGATO_EYETV_DTT_2 0x003f +-- +2.17.1 + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-04-fix-blocking-demux.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-04-fix-blocking-demux.patch new file mode 100644 index 000000000..a633e3994 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-04-fix-blocking-demux.patch @@ -0,0 +1,140 @@ +From d8e559ad66feeffa31eb473a9c9bce51d0863079 Mon Sep 17 00:00:00 2001 +From: alexelec +Date: Mon, 11 Feb 2019 11:09:50 +0200 +Subject: [PATCH] dvb-core: fix blocking demux + +--- + drivers/media/dvb-core/dmxdev.c | 37 +++++++++++++++++++------ + drivers/media/dvb-core/dvb_ringbuffer.c | 1 + + drivers/media/dvb-core/dvb_ringbuffer.h | 1 + + 3 files changed, 31 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c +index c0363f1b..da9ad1c8 100644 +--- a/drivers/media/dvb-core/dmxdev.c ++++ b/drivers/media/dvb-core/dmxdev.c +@@ -82,7 +82,11 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, + + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || +- (src->error != 0)); ++ (src->error != 0) || ++ (src->do_wait != 1)); ++ if (src->do_wait != 1) ++ ret = -EINTR; ++ + if (ret < 0) + break; + +@@ -955,6 +959,23 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, + return ret; + } + ++ ++static int dvb_demux_lock_filter(struct dmxdev_filter *dmxdevfilter) ++{ ++ int ret; ++ ++ dmxdevfilter->buffer.do_wait = 0; ++ ++ if (waitqueue_active(&dmxdevfilter->buffer.queue)) ++ wake_up(&dmxdevfilter->buffer.queue); ++ ++ ret = mutex_lock_interruptible(&dmxdevfilter->mutex); ++ ++ dmxdevfilter->buffer.do_wait = 1; ++ ++ return ret; ++} ++ + static int dvb_demux_do_ioctl(struct file *file, + unsigned int cmd, void *parg) + { +@@ -968,7 +989,7 @@ static int dvb_demux_do_ioctl(struct file *file, + + switch (cmd) { + case DMX_START: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -980,7 +1001,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_STOP: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -989,7 +1010,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_FILTER: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -998,7 +1019,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_PES_FILTER: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -1007,7 +1028,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_BUFFER_SIZE: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -1051,7 +1072,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_ADD_PID: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + ret = -ERESTARTSYS; + break; + } +@@ -1060,7 +1081,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_REMOVE_PID: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + ret = -ERESTARTSYS; + break; + } +diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c +index a5712cd7..d5333f3a 100644 +--- a/drivers/media/dvb-core/dvb_ringbuffer.c ++++ b/drivers/media/dvb-core/dvb_ringbuffer.c +@@ -45,6 +45,7 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) + rbuf->data=data; + rbuf->size=len; + rbuf->error=0; ++ rbuf->do_wait=1; + + init_waitqueue_head(&rbuf->queue); + +diff --git a/include/media/dvb_ringbuffer.h b/include/media/dvb_ringbuffer.h +index 41f04dae..25a853b5 100644 +--- a/include/media/dvb_ringbuffer.h ++++ b/include/media/dvb_ringbuffer.h +@@ -38,6 +38,7 @@ struct dvb_ringbuffer { + int error; + + wait_queue_head_t queue; ++ int do_wait; + spinlock_t lock; + }; + + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-06-fix-si2168-cmd-timeout.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-06-fix-si2168-cmd-timeout.patch new file mode 100644 index 000000000..52cd82847 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-06-fix-si2168-cmd-timeout.patch @@ -0,0 +1,17 @@ +fix si2168 cmd timeout + +Some Si2168 demodulator commands may take 130-140 ms +(DVB-T/T2 tuner MyGica T230C v2). +Details: https://github.com/CoreELEC/CoreELEC/pull/208 + +--- a/drivers/media/dvb-frontends/si2168.c ++++ b/drivers/media/dvb-frontends/si2168.c +@@ -46,7 +46,7 @@ static int si2168_cmd_execute_unlocked(s + + if (cmd->rlen) { + /* wait cmd execution terminate */ +- #define TIMEOUT 70 ++ #define TIMEOUT 200 + timeout = jiffies + msecs_to_jiffies(TIMEOUT); + while (!time_after(jiffies, timeout)) { + ret = i2c_master_recv(client, cmd->args, cmd->rlen); diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-07-fix-si2157-init.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-07-fix-si2157-init.patch new file mode 100644 index 000000000..dec91851f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-07-fix-si2157-init.patch @@ -0,0 +1,16 @@ +Fix compatibility with Si2141 tuner (e.g. MyGica T230C v2) +which needs a next command for proper initialization. + +(Broken by media_tree-01-hauppauge.patch) + +--- a/drivers/media/tuners/si2157.c ++++ b/drivers/media/tuners/si2157.c +@@ -120,7 +120,7 @@ static int si2157_init(struct dvb_fronte + } + cmd.rlen = 1; + ret = si2157_cmd_execute(client, &cmd); +- if (ret) ++ if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN)) + goto err; + + /* Si2141 needs a second command before it answers the revision query */ diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-08-fix-dvbsky-frontend-detach.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-08-fix-dvbsky-frontend-detach.patch new file mode 100644 index 000000000..116480613 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-08-fix-dvbsky-frontend-detach.patch @@ -0,0 +1,20 @@ +media: dvbsky: Avoid leaking dvb frontend + +Source: https://git.linuxtv.org/media_tree.git/commit/drivers/media/usb/dvb-usb-v2?id=fdfa59cd63b184e1e96d51ff170fcac739bc6f6f + +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c +@@ -834,11 +836,11 @@ static struct dvb_usb_device_properties mygica_t230c_v2_props = { + + .i2c_algo = &dvbsky_i2c_algo, + .frontend_attach = dvbsky_mygica_t230c_v2_attach, ++ .frontend_detach = dvbsky_frontend_detach, + .init = dvbsky_init, + .get_rc_config = dvbsky_get_rc_config, + .streaming_ctrl = dvbsky_streaming_ctrl, + .identify_state = dvbsky_identify_state, +- .exit = dvbsky_exit, + + .num_adapters = 1, + .adapter = { + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-09-revert-access_ok.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-09-revert-access_ok.patch new file mode 100644 index 000000000..a8262315b --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-09-revert-access_ok.patch @@ -0,0 +1,215 @@ +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 2019-06-15 02:14:51.909460692 +0200 ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 2019-06-15 02:14:55.029460692 +0200 +@@ -1,4 +1,3 @@ +-// SPDX-License-Identifier: GPL-2.0-only + /* + * ioctl32.c: Conversion between 32bit and 64bit native ioctls. + * Separated from fs stuff by Arnd Bergmann +@@ -159,7 +158,7 @@ + compat_caddr_t p; + u32 clipcount; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + copy_in_user(&p64->w, &p32->w, sizeof(p32->w)) || + assign_in_user(&p64->field, &p32->field) || + assign_in_user(&p64->chromakey, &p32->chromakey) || +@@ -284,7 +283,7 @@ + + static int bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size) + { +- if (!access_ok(p32, sizeof(*p32))) ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32))) + return -EFAULT; + return __bufsize_v4l2_format(p32, size); + } +@@ -336,7 +335,7 @@ + struct v4l2_format32 __user *p32, + void __user *aux_buf, u32 aux_space) + { +- if (!access_ok(p32, sizeof(*p32))) ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32))) + return -EFAULT; + return __get_v4l2_format32(p64, p32, aux_buf, aux_space); + } +@@ -344,7 +343,7 @@ + static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *p32, + u32 *size) + { +- if (!access_ok(p32, sizeof(*p32))) ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32))) + return -EFAULT; + return __bufsize_v4l2_format(&p32->format, size); + } +@@ -353,7 +352,7 @@ + struct v4l2_create_buffers32 __user *p32, + void __user *aux_buf, u32 aux_space) + { +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + copy_in_user(p64, p32, + offsetof(struct v4l2_create_buffers32, format))) + return -EFAULT; +@@ -405,7 +404,7 @@ + static int put_v4l2_format32(struct v4l2_format __user *p64, + struct v4l2_format32 __user *p32) + { +- if (!access_ok(p32, sizeof(*p32))) ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32))) + return -EFAULT; + return __put_v4l2_format32(p64, p32); + } +@@ -413,7 +412,7 @@ + static int put_v4l2_create32(struct v4l2_create_buffers __user *p64, + struct v4l2_create_buffers32 __user *p32) + { +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + copy_in_user(p32, p64, + offsetof(struct v4l2_create_buffers32, format)) || + assign_in_user(&p32->capabilities, &p64->capabilities) || +@@ -435,7 +434,7 @@ + struct v4l2_standard32 __user *p32) + { + /* other fields are not set by the user, nor used by the driver */ +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + assign_in_user(&p64->index, &p32->index)) + return -EFAULT; + return 0; +@@ -444,7 +443,7 @@ + static int put_v4l2_standard32(struct v4l2_standard __user *p64, + struct v4l2_standard32 __user *p32) + { +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + assign_in_user(&p32->index, &p64->index) || + assign_in_user(&p32->id, &p64->id) || + copy_in_user(p32->name, p64->name, sizeof(p32->name)) || +@@ -561,7 +560,7 @@ + u32 type; + u32 length; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + get_user(type, &p32->type) || + get_user(length, &p32->length)) + return -EFAULT; +@@ -594,7 +593,7 @@ + compat_caddr_t p; + int ret; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + assign_in_user(&p64->index, &p32->index) || + get_user(type, &p32->type) || + put_user(type, &p64->type) || +@@ -633,7 +632,7 @@ + return -EFAULT; + + uplane32 = compat_ptr(p); +- if (!access_ok(uplane32, ++ if (!access_ok(VERIFY_READ, uplane32, + num_planes * sizeof(*uplane32))) + return -EFAULT; + +@@ -692,7 +691,7 @@ + compat_caddr_t p; + int ret; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + assign_in_user(&p32->index, &p64->index) || + get_user(type, &p64->type) || + put_user(type, &p32->type) || +@@ -782,7 +781,7 @@ + { + compat_caddr_t tmp; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + get_user(tmp, &p32->base) || + put_user_force(compat_ptr(tmp), &p64->base) || + assign_in_user(&p64->capability, &p32->capability) || +@@ -797,7 +796,7 @@ + { + void *base; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + get_user(base, &p64->base) || + put_user(ptr_to_compat((void __user *)base), &p32->base) || + assign_in_user(&p32->capability, &p64->capability) || +@@ -894,7 +893,7 @@ + { + u32 count; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + get_user(count, &p32->count)) + return -EFAULT; + if (count > V4L2_CID_MAX_CTRLS) +@@ -914,7 +913,7 @@ + u32 n; + compat_caddr_t p; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + assign_in_user(&p64->which, &p32->which) || + get_user(count, &p32->count) || + put_user(count, &p64->count) || +@@ -930,7 +929,7 @@ + if (get_user(p, &p32->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(ucontrols, count * sizeof(*ucontrols))) ++ if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; + if (aux_space < count * sizeof(*kcontrols)) + return -EFAULT; +@@ -980,7 +979,7 @@ + * with __user causes smatch warnings, so instead declare it + * without __user and cast it as a userspace pointer where needed. + */ +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + assign_in_user(&p32->which, &p64->which) || + get_user(count, &p64->count) || + put_user(count, &p32->count) || +@@ -995,7 +994,7 @@ + if (get_user(p, &p32->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(ucontrols, count * sizeof(*ucontrols))) ++ if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; + + for (n = 0; n < count; n++) { +@@ -1044,7 +1043,7 @@ + static int put_v4l2_event32(struct v4l2_event __user *p64, + struct v4l2_event32 __user *p32) + { +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + assign_in_user(&p32->type, &p64->type) || + copy_in_user(&p32->u, &p64->u, sizeof(p64->u)) || + assign_in_user(&p32->pending, &p64->pending) || +@@ -1070,7 +1069,7 @@ + { + compat_uptr_t tmp; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) || + assign_in_user(&p64->pad, &p32->pad) || + assign_in_user(&p64->start_block, &p32->start_block) || + assign_in_user_cast(&p64->blocks, &p32->blocks) || +@@ -1086,7 +1085,7 @@ + { + void *edid; + +- if (!access_ok(p32, sizeof(*p32)) || ++ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) || + assign_in_user(&p32->pad, &p64->pad) || + assign_in_user(&p32->start_block, &p64->start_block) || + assign_in_user(&p32->blocks, &p64->blocks) || + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-10-revert-serialize-reset-messages-in-m88ds3103_set_frontend.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-10-revert-serialize-reset-messages-in-m88ds3103_set_frontend.patch new file mode 100644 index 000000000..15c4b1e80 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree/patches/media_tree-10-revert-serialize-reset-messages-in-m88ds3103_set_frontend.patch @@ -0,0 +1,28 @@ +diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +index 123f2a3..403f428 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.c ++++ b/drivers/media/dvb-frontends/m88ds3103.c +@@ -309,9 +309,6 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u16 u16tmp; + u32 tuner_frequency_khz, target_mclk; + s32 s32tmp; +- static const struct reg_sequence reset_buf[] = { +- {0x07, 0x80}, {0x07, 0x00} +- }; + + dev_dbg(&client->dev, + "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", +@@ -324,7 +321,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + } + + /* reset */ ++ ret = regmap_write(dev->regmap, 0x07, 0x80); ++ if (ret) ++ goto err; ++ ++ ret = regmap_write(dev->regmap, 0x07, 0x00); +- ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); + if (ret) + goto err; + + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_aml/package.mk b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_aml/package.mk new file mode 100644 index 000000000..b1d35e10c --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_aml/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="media_tree_aml" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/CoreELEC" +PKG_DEPENDS_TARGET="toolchain" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Source of Linux Kernel amlogic drivers to build with media_build." +PKG_TOOLCHAIN="manual" + +case "$LINUX" in + amlogic-3.14) + PKG_VERSION="f9a4b158183866c589ee8c06ab740f41aa08fa66" + PKG_SHA256="ff629f20b39749e6523571409c74c38a27ba0101b0ffe2a1ecea3e4dafea6dd2" + PKG_URL="https://github.com/CoreELEC/media_tree_aml/archive/${PKG_VERSION}.tar.gz" + ;; + amlogic-4.9) + PKG_VERSION="a87a02aa4cad4b5835f20ed756799f3a6a74f9af" + PKG_SHA256="c598e78a637963389699c157ccae92d2c158a55335570b2c2bdc5acef316b9b7" + PKG_URL="https://github.com/CoreELEC/media_tree_aml/archive/${PKG_VERSION}.tar.gz" + ;; +esac + +unpack() { + mkdir -p $PKG_BUILD/ + tar -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz -C $PKG_BUILD/../ +} diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/package.mk b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/package.mk new file mode 100644 index 000000000..f309331f1 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="media_tree_cc" +PKG_VERSION="2019-07-10" +PKG_SHA256="c1d4467a7771d4a3e3f80cdce7065b4a1a9b61a306f35586e4c198812661e883" +PKG_LICENSE="GPL" +PKG_SITE="https://bitbucket.org/CrazyCat/media_build/downloads/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Source of Linux Kernel media_tree subsystem to build with media_build." +PKG_TOOLCHAIN="manual" + +case "$LINUX" in + amlogic-4.9) + PKG_PATCH_DIRS="amlogic-4.9" + ;; +esac + +unpack() { + mkdir -p $PKG_BUILD/ + tar -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.bz2 -C $PKG_BUILD/ +} + +post_unpack() { + # hack/workaround for borked upstream kernel/media_build + # without removing atomisp there a lot additional includes that + # slowdown build process after modpost from 3min to 6min + # even if atomisp is disabled via kernel.conf + rm -rf $PKG_BUILD/drivers/staging/media/atomisp + sed -i 's|^.*drivers/staging/media/atomisp.*$||' \ + $PKG_BUILD/drivers/staging/media/Kconfig +} diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch new file mode 100644 index 000000000..5703ddc2f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_01-m2m-job-resume-pause.patch @@ -0,0 +1,74 @@ +diff -ur a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c 2019-07-10 23:44:44.000000000 +0100 ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c 2019-12-18 04:54:05.614904632 +0000 +@@ -443,6 +443,42 @@ + } + EXPORT_SYMBOL(v4l2_m2m_job_finish); + ++void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ dprintk("Called by an instance not currently running\n"); ++ return; ++ } ++ ++ list_del(&m2m_dev->curr_ctx->queue); ++ m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); ++ m2m_dev->curr_ctx->job_flags |= TRANS_ABORT; ++ wake_up(&m2m_dev->curr_ctx->finished); ++ m2m_dev->curr_ctx = NULL; ++ ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++} ++EXPORT_SYMBOL(v4l2_m2m_job_pause); ++ ++void v4l2_m2m_job_resume(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); ++ m2m_ctx->job_flags &= ~TRANS_ABORT; ++ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); ++ ++ v4l2_m2m_try_schedule(m2m_ctx); ++ v4l2_m2m_try_run(m2m_dev); ++} ++EXPORT_SYMBOL(v4l2_m2m_job_resume); ++ + int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_requestbuffers *reqbufs) + { +diff -ur a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +--- a/include/media/v4l2-mem2mem.h 2019-07-10 23:44:45.000000000 +0100 ++++ b/include/media/v4l2-mem2mem.h 2019-12-18 04:54:31.579097310 +0000 +@@ -573,6 +573,24 @@ + return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx); + } + ++/* ++ * v4l2_m2m_job_pause() - paused the schedule of data which from the job queue. ++ * ++ * @m2m_dev: opaque pointer to the internal data to handle M2M context ++ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx ++ */ ++void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx); ++ ++ /* ++ * v4l2_m2m_job_resume() - resumed the schedule of data which from the job que. ++ * ++ * @m2m_dev: opaque pointer to the internal data to handle M2M context ++ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx ++ */ ++void v4l2_m2m_job_resume(struct v4l2_m2m_dev *m2m_dev, ++ struct v4l2_m2m_ctx *m2m_ctx); ++ + /** + * v4l2_m2m_buf_remove_by_buf() - take off exact buffer from the list of ready + * buffers diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_cc-06-of-node.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_cc-06-of-node.patch new file mode 100644 index 000000000..ba4e47a24 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/amlogic-4.9/media_tree_cc-06-of-node.patch @@ -0,0 +1,23 @@ +--- a/drivers/media/v4l2-core/v4l2-fwnode.c 2019-04-02 00:31:42.224001000 +0200 ++++ b/drivers/media/v4l2-core/v4l2-fwnode.c 2019-04-02 00:31:42.256001000 +0200 +@@ -553,6 +553,20 @@ + } + EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); + ++bool of_node_name_eq(const struct device_node *np, const char *name) ++{ ++ const char *node_name; ++ size_t len; ++ ++ if (!np) ++ return false; ++ ++ node_name = kbasename(np->full_name); ++ len = strchrnul(node_name, '@') - node_name; ++ ++ return (strlen(name) == len) && (strncmp(node_name, name, len) == 0); ++} ++ + int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, + struct v4l2_fwnode_link *link) + { diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/media_tree_cc-01-m88ds3103b.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/media_tree_cc-01-m88ds3103b.patch new file mode 100644 index 000000000..c079433e0 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc/patches/media_tree_cc-01-m88ds3103b.patch @@ -0,0 +1,746 @@ +From: Brad Love +https://git.linuxtv.org/brad/media_tree.git/log/?h=Montage-3103b.v2 +support for m88ds3103b + +diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +index 3a367a5..0d3b81d 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.c ++++ b/drivers/media/dvb-frontends/m88ds3103.c +@@ -64,6 +64,92 @@ err: + return ret; + } + ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for one transaction, then writes will be allowed. ++ */ ++static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) ++{ ++ struct i2c_client *client = dev->client; ++ u8 buf[] = {reg, data}; ++ u8 val; ++ int ret; ++ struct i2c_msg msg = { ++ .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x11; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, &msg, 1); ++ if (ret != 1) { ++ dev_dbg(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n", ++ dev->dt_addr, ret, reg, data); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, data); ++ ++ return 0; ++} ++ ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for two transactions, then reads will be allowed. ++ */ ++static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) ++{ ++ struct i2c_client *client = dev->client; ++ int ret; ++ u8 val; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = dev->dt_addr, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, ++ { ++ .addr = dev->dt_addr, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 1 ++ } ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x12; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, msg, 2); ++ if (ret != 2) { ++ dev_dbg(&client->dev, "0x%02x (err=%d, reg=0x%02x)\n", ++ dev->dt_addr, ret, reg); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, b1[0]); ++ ++ return b1[0]; ++} ++ + /* + * Get the demodulator AGC PWM voltage setting supplied to the tuner. + */ +@@ -288,6 +374,253 @@ err: + return ret; + } + ++static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) ++{ ++ struct i2c_client *client = dev->client; ++ struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; ++ u32 adc_Freq_MHz[3] = {96, 93, 99}; ++ u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; ++ u32 offset_MHz[3]; ++ u32 max_offset = 0; ++ u32 old_setting = dev->mclk; ++ u32 tuner_freq_MHz = c->frequency / 1000; ++ u8 i; ++ char big_symbol = 0; ++ ++ big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; ++ ++ if (big_symbol) { ++ reg16 = 115; ++ } else { ++ reg16 = 96; ++ ++ /* TODO: IS THIS NECESSARY ? */ ++ for (i = 0; i < 3; i++) { ++ offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; ++ ++ if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) ++ offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; ++ ++ if (offset_MHz[i] > max_offset) { ++ max_offset = offset_MHz[i]; ++ reg16 = reg16_list[i]; ++ dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; ++ ++ if (big_symbol) ++ dev->mclk /= 2; ++ ++ dev_dbg(&client->dev, "modifying mclk %u -> %u\n", ++ old_setting, dev->mclk); ++ } ++ } ++ } ++ ++ if (dev->mclk == 93000000) ++ regmap_write(dev->regmap, 0xA0, 0x42); ++ else if (dev->mclk == 96000000) ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ else if (dev->mclk == 99000000) ++ regmap_write(dev->regmap, 0xA0, 0x46); ++ else if (dev->mclk == 110250000) ++ regmap_write(dev->regmap, 0xA0, 0x4E); ++ else ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ ++ if (big_symbol) ++ reg15 |= 0x02; ++ else ++ reg15 &= ~0x02; ++ ++ m88ds3103b_dt_write(dev, 0x15, reg15); ++ m88ds3103b_dt_write(dev, 0x16, reg16); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ ++static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) ++{ ++ u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; ++ u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0, pll_ldpc_mode; ++ u16 pll_div_fb, N; ++ u32 div; ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ reg16 = m88ds3103b_dt_read(dev, 0x16); ++ reg1D = m88ds3103b_dt_read(dev, 0x1D); ++ ++ if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { ++ if (reg16 == 92) ++ tmp = 93; ++ else if (reg16 == 100) ++ tmp = 99; ++ else ++ tmp = 96; ++ ++ mclk_khz *= tmp; ++ mclk_khz /= 96; ++ } ++ ++ pll_ldpc_mode = (reg15 >> 1) & 0x01; ++ ++ pll_div_fb = (reg15 & 0x01) << 8; ++ pll_div_fb += reg16; ++ pll_div_fb += 32; ++ ++ div = 9000 * pll_div_fb * 4; ++ div /= mclk_khz; ++ ++ if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { ++ reg11 |= 0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 34) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 8) && (f0 != 0)) ++ f0 = 8; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 8) && (f1 != 0)) ++ f1 = 8; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 8) && (f2 != 0)) ++ f2 = 8; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 8) && (f3 != 0)) ++ f3 = 8; ++ } else { ++ reg11 &= ~0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 48) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 9) && (f0 != 0)) ++ f0 = 9; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 9) && (f1 != 0)) ++ f1 = 9; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 9) && (f2 != 0)) ++ f2 = 9; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 9) && (f3 != 0)) ++ f3 = 9; ++ } ++ ++ sm = N - 1; ++ ++ /* Write to registers */ ++ //reg15 &= 0x01; ++ //reg15 |= (pll_div_fb >> 8) & 0x01; ++ ++ //reg16 = pll_div_fb & 0xFF; ++ ++ reg1D &= ~0x03; ++ reg1D |= sm; ++ reg1D |= 0x80; ++ ++ reg1E = ((f3 << 4) + f2) & 0xFF; ++ reg1F = ((f1 << 4) + f0) & 0xFF; ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ m88ds3103b_dt_write(dev, 0x1D, reg1D); ++ m88ds3103b_dt_write(dev, 0x1E, reg1E); ++ m88ds3103b_dt_write(dev, 0x1F, reg1F); ++ ++ m88ds3103b_dt_write(dev, 0x17, 0xc1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, 0x0A); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ + static int m88ds3103_set_frontend(struct dvb_frontend *fe) + { + struct m88ds3103_dev *dev = fe->demodulator_priv; +@@ -298,7 +631,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ + u8 buf[3]; + u16 u16tmp; +- u32 tuner_frequency_khz, target_mclk; ++ u32 tuner_frequency_khz, target_mclk, u32tmp; + s32 s32tmp; + static const struct reg_sequence reset_buf[] = { + {0x07, 0x80}, {0x07, 0x00} +@@ -321,6 +654,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + + /* Disable demod clock path */ + if (dev->chip_id == M88RS6000_CHIP_ID) { ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = regmap_read(dev->regmap, 0xb2, &u32tmp); ++ if (ret) ++ goto err; ++ if (u32tmp == 0x01) { ++ ret = regmap_write(dev->regmap, 0x00, 0x00); ++ if (ret) ++ goto err; ++ ret = regmap_write(dev->regmap, 0xb2, 0x00); ++ if (ret) ++ goto err; ++ } ++ } ++ + ret = regmap_write(dev->regmap, 0x06, 0xe0); + if (ret) + goto err; +@@ -346,7 +693,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + tuner_frequency_khz = c->frequency; + } + +- /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ ++ /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ + if (dev->chip_id == M88RS6000_CHIP_ID) { + if (c->symbol_rate > 45010000) + dev->mclk = 110250000; +@@ -358,6 +705,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + target_mclk = 144000000; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_select_mclk(dev); ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ } ++ + /* Enable demod clock path */ + ret = regmap_write(dev->regmap, 0x06, 0x00); + if (ret) +@@ -469,12 +821,42 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); + if (ret) + goto err; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ buf[0] = m88ds3103b_dt_read(dev, 0x15); ++ buf[1] = m88ds3103b_dt_read(dev, 0x16); ++ ++ if (c->symbol_rate > 45010000) { ++ buf[0] &= ~0x03; ++ buf[0] |= 0x02; ++ buf[0] |= ((147 - 32) >> 8) & 0x01; ++ buf[1] = (147 - 32) & 0xFF; ++ ++ dev->mclk = 110250 * 1000; ++ } else { ++ buf[0] &= ~0x03; ++ buf[0] |= ((128 - 32) >> 8) & 0x01; ++ buf[1] = (128 - 32) & 0xFF; ++ ++ dev->mclk = 96000 * 1000; ++ } ++ m88ds3103b_dt_write(dev, 0x15, buf[0]); ++ m88ds3103b_dt_write(dev, 0x16, buf[1]); ++ ++ regmap_read(dev->regmap, 0x30, &u32tmp); ++ u32tmp &= ~0x80; ++ regmap_write(dev->regmap, 0x30, u32tmp & 0xff); ++ } ++ + ret = regmap_write(dev->regmap, 0xf1, 0x01); + if (ret) + goto err; +- ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); +- if (ret) +- goto err; ++ ++ if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); ++ if (ret) ++ goto err; ++ } + } + + switch (dev->cfg->ts_mode) { +@@ -488,6 +870,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + break; + case M88DS3103_TS_PARALLEL: + u8tmp = 0x02; ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ u8tmp = 0x01; ++ u8tmp1 = 0x01; ++ } + break; + case M88DS3103_TS_CI: + u8tmp = 0x03; +@@ -516,6 +902,12 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8tmp1 = 0x3f; + u8tmp2 = 0x3f; + break; ++ case M88DS3103_TS_PARALLEL: ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); ++ if (ret) ++ goto err; ++ } + default: + u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); + u8tmp1 = u16tmp / 2 - 1; +@@ -543,6 +935,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + u8tmp = 0x06; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ + ret = regmap_write(dev->regmap, 0xc3, 0x08); + if (ret) + goto err; +@@ -578,6 +973,16 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable/disable 192M LDPC clock */ ++ ret = m88ds3103_update_bits(dev, 0x29, 0x10, ++ (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); ++ if (ret) ++ goto err; ++ ++ ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); ++ } ++ + dev_dbg(&client->dev, "carrier offset=%d\n", + (tuner_frequency_khz - c->frequency)); + +@@ -654,10 +1059,13 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "found a '%s' in cold state\n", + m88ds3103_ops.info.name); + +- if (dev->chip_id == M88RS6000_CHIP_ID) ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ name = M88DS3103B_FIRMWARE; ++ else if (dev->chip_id == M88RS6000_CHIP_ID) + name = M88RS6000_FIRMWARE; + else + name = M88DS3103_FIRMWARE; ++ + /* request the firmware, this will block and timeout */ + ret = request_firmware(&firmware, name, &client->dev); + if (ret) { +@@ -704,6 +1112,12 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "firmware version: %X.%X\n", + (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_dt_write(dev, 0x21, 0x92); ++ m88ds3103b_dt_write(dev, 0x15, 0x6C); ++ m88ds3103b_dt_write(dev, 0x17, 0xC1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ } + warm: + /* warm state */ + dev->warm = true; +@@ -1393,6 +1807,8 @@ static int m88ds3103_probe(struct i2c_client *client, + goto err_kfree; + + dev->chip_id = utmp >> 1; ++ dev->chiptype = (u8)id->driver_data; ++ + dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); + + switch (dev->chip_id) { +@@ -1470,6 +1886,19 @@ static int m88ds3103_probe(struct i2c_client *client, + /* setup callbacks */ + pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; + pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable i2c repeater for tuner */ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ /* get frontend address */ ++ ret = regmap_read(dev->regmap, 0x29, &utmp); ++ if (ret) ++ goto err_kfree; ++ dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; ++ dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr); ++ } ++ + return 0; + err_kfree: + kfree(dev); +@@ -1491,7 +1920,9 @@ static int m88ds3103_remove(struct i2c_client *client) + } + + static const struct i2c_device_id m88ds3103_id_table[] = { +- {"m88ds3103", 0}, ++ {"m88ds3103", M88DS3103_CHIPTYPE_3103}, ++ {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, ++ {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, + {} + }; + MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); +@@ -1513,3 +1944,4 @@ MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver"); + MODULE_LICENSE("GPL"); + MODULE_FIRMWARE(M88DS3103_FIRMWARE); + MODULE_FIRMWARE(M88RS6000_FIRMWARE); ++MODULE_FIRMWARE(M88DS3103B_FIRMWARE); +diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h +index c825032..d656ec2 100644 +--- a/drivers/media/dvb-frontends/m88ds3103_priv.h ++++ b/drivers/media/dvb-frontends/m88ds3103_priv.h +@@ -16,11 +16,17 @@ + #include + #include + +-#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" +-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++#define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw" ++#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" ++#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++ + #define M88RS6000_CHIP_ID 0x74 + #define M88DS3103_CHIP_ID 0x70 + ++#define M88DS3103_CHIPTYPE_3103 0 ++#define M88DS3103_CHIPTYPE_RS6000 1 ++#define M88DS3103_CHIPTYPE_3103B 2 ++ + struct m88ds3103_dev { + struct i2c_client *client; + struct regmap_config regmap_config; +@@ -35,10 +41,13 @@ struct m88ds3103_dev { + struct i2c_mux_core *muxc; + /* auto detect chip id to do different config */ + u8 chip_id; ++ /* chip type to differentiate m88rs6000 from m88ds3103b */ ++ u8 chiptype; + /* main mclk is calculated for M88RS6000 dynamically */ + s32 mclk; + u64 post_bit_error; + u64 post_bit_count; ++ u8 dt_addr; + }; + + struct m88ds3103_reg_val { +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 1283c7c..6561f7b 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2397,6 +2397,20 @@ const struct em28xx_board em28xx_boards[] = { + .has_dvb = 1, + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, + }, ++ /* ++ * 2013:0259 PCTV DVB-S2 Stick (461e_v2) ++ * Empia EM28178, Montage M88DS3103b, Montage M88TS2022, Allegro A8293 ++ */ ++ [EM28178_BOARD_PCTV_461E_V2] = { ++ .def_i2c_bus = 1, ++ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ .name = "PCTV DVB-S2 Stick (461e v2)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_461e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ }, + /* + * 2013:025f PCTV tripleStick (292e). + * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 +@@ -2678,6 +2692,10 @@ struct usb_device_id em28xx_id_table[] = { + .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, + { USB_DEVICE(0x2013, 0x0258), + .driver_info = EM28178_BOARD_PCTV_461E }, ++ { USB_DEVICE(0x2013, 0x0461), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, ++ { USB_DEVICE(0x2013, 0x0259), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, + { USB_DEVICE(0x2013, 0x025f), + .driver_info = EM28178_BOARD_PCTV_292E }, + { USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */ +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index a73faf1..e2ddc25 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -1219,6 +1219,65 @@ static int em28178_dvb_init_pctv_461e(struct em28xx *dev) + return 0; + } + ++static int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev) ++{ ++ struct em28xx_dvb *dvb = dev->dvb; ++ struct i2c_adapter *i2c_adapter; ++ struct m88ds3103_platform_data m88ds3103_pdata = {}; ++ struct ts2020_config ts2020_config = {}; ++ struct a8293_platform_data a8293_pdata = {}; ++ ++ /* attach demod */ ++ m88ds3103_pdata.clk = 27000000; ++ m88ds3103_pdata.i2c_wr_max = 33; ++ m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; ++ m88ds3103_pdata.ts_clk = 16000; ++ m88ds3103_pdata.ts_clk_pol = 1; ++ m88ds3103_pdata.agc = 0x99; ++ m88ds3103_pdata.agc_inv = 1; ++ m88ds3103_pdata.spec_inv = 1; ++ dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b", ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x6a, &m88ds3103_pdata); ++ ++ if (!dvb->i2c_client_demod) { ++ pr_err("%s() FUCK\n", __func__); ++ return -ENODEV; ++ } ++ ++ dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); ++ i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); ++ ++ /* attach tuner */ ++ ts2020_config.fe = dvb->fe[0]; ++ dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", ++ i2c_adapter, ++ 0x60, &ts2020_config); ++ if (!dvb->i2c_client_tuner) { ++ pr_err("%s() FUCK2\n", __func__); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ /* delegate signal strength measurement to tuner */ ++ dvb->fe[0]->ops.read_signal_strength = ++ dvb->fe[0]->ops.tuner_ops.get_rf_strength; ++ ++ /* attach SEC */ ++ a8293_pdata.dvb_frontend = dvb->fe[0]; ++ dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x08, &a8293_pdata); ++ if (!dvb->i2c_client_sec) { ++ pr_err("%s() FUCK3\n", __func__); ++ dvb_module_release(dvb->i2c_client_tuner); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int em28178_dvb_init_pctv_292e(struct em28xx *dev) + { + struct em28xx_dvb *dvb = dev->dvb; +@@ -1860,6 +1919,11 @@ static int em28xx_dvb_init(struct em28xx *dev) + if (result) + goto out_free; + break; ++ case EM28178_BOARD_PCTV_461E_V2: ++ result = em28178_dvb_init_pctv_461e_v2(dev); ++ if (result) ++ goto out_free; ++ break; + case EM28178_BOARD_PCTV_292E: + result = em28178_dvb_init_pctv_292e(dev); + if (result) +diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h +index a551072..1affdd1 100644 +--- a/drivers/media/usb/em28xx/em28xx.h ++++ b/drivers/media/usb/em28xx/em28xx.h +@@ -149,6 +149,7 @@ + #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 + #define EM2884_BOARD_TERRATEC_H6 101 + #define EM2882_BOARD_ZOLID_HYBRID_TV_STICK 102 ++#define EM28178_BOARD_PCTV_461E_V2 103 + + /* Limits minimum and default number of buffers */ + #define EM28XX_MIN_BUF 4 +-- +2.17.1 diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/package.mk b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/package.mk new file mode 100644 index 000000000..61f607f68 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="media_tree_cc_aml" +PKG_VERSION="2018-09-23" +PKG_SHA256="3b0cf3699317c04d9184b7e25056065fd374b20b851ee86a63ea2c70e219ee9e" +PKG_LICENSE="GPL" +PKG_SITE="https://bitbucket.org/CrazyCat/media_build/downloads/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain media_tree_aml" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory media_tree_aml)" +PKG_LONGDESC="Source of Linux Kernel media_tree subsystem to build with media_build." +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p $PKG_BUILD/ + tar -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.xz -C $PKG_BUILD/ +} + +post_unpack() { + # hack/workaround for borked upstream kernel/media_build + # without removing atomisp there a lot additional includes that + # slowdown build process after modpost from 3min to 6min + # even if atomisp is disabled via kernel.conf + rm -rf $PKG_BUILD/drivers/staging/media/atomisp + sed -i 's|^.*drivers/staging/media/atomisp.*$||' \ + $PKG_BUILD/drivers/staging/media/Kconfig +} + +configure() { + rm -rf $PKG_BUILD/drivers/media/platform/meson/dvb + cp -Lr $(get_build_dir media_tree_aml)/* $PKG_BUILD/ + echo 'source "drivers/media/platform/meson/dvb/Kconfig"' >> "$PKG_BUILD/drivers/media/platform/Kconfig" + echo 'source "drivers/media/platform/meson/video_dev/Kconfig"' >> "$PKG_BUILD/drivers/media/platform/Kconfig" +} diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-01-m88ds3103b.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-01-m88ds3103b.patch new file mode 100644 index 000000000..c079433e0 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-01-m88ds3103b.patch @@ -0,0 +1,746 @@ +From: Brad Love +https://git.linuxtv.org/brad/media_tree.git/log/?h=Montage-3103b.v2 +support for m88ds3103b + +diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +index 3a367a5..0d3b81d 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.c ++++ b/drivers/media/dvb-frontends/m88ds3103.c +@@ -64,6 +64,92 @@ err: + return ret; + } + ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for one transaction, then writes will be allowed. ++ */ ++static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) ++{ ++ struct i2c_client *client = dev->client; ++ u8 buf[] = {reg, data}; ++ u8 val; ++ int ret; ++ struct i2c_msg msg = { ++ .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x11; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, &msg, 1); ++ if (ret != 1) { ++ dev_dbg(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n", ++ dev->dt_addr, ret, reg, data); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, data); ++ ++ return 0; ++} ++ ++/* ++ * m88ds3103b demod has an internal device related to clocking. First the i2c ++ * gate must be opened, for two transactions, then reads will be allowed. ++ */ ++static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) ++{ ++ struct i2c_client *client = dev->client; ++ int ret; ++ u8 val; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = dev->dt_addr, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, ++ { ++ .addr = dev->dt_addr, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 1 ++ } ++ }; ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x00); ++ ++ val = 0x12; ++ ret = regmap_write(dev->regmap, 0x03, val); ++ if (ret) ++ dev_dbg(&client->dev, "fail=%d\n", ret); ++ ++ ret = i2c_transfer(dev->client->adapter, msg, 2); ++ if (ret != 2) { ++ dev_dbg(&client->dev, "0x%02x (err=%d, reg=0x%02x)\n", ++ dev->dt_addr, ret, reg); ++ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ return -EREMOTEIO; ++ } ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n", ++ dev->dt_addr, reg, b1[0]); ++ ++ return b1[0]; ++} ++ + /* + * Get the demodulator AGC PWM voltage setting supplied to the tuner. + */ +@@ -288,6 +374,253 @@ err: + return ret; + } + ++static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) ++{ ++ struct i2c_client *client = dev->client; ++ struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; ++ u32 adc_Freq_MHz[3] = {96, 93, 99}; ++ u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; ++ u32 offset_MHz[3]; ++ u32 max_offset = 0; ++ u32 old_setting = dev->mclk; ++ u32 tuner_freq_MHz = c->frequency / 1000; ++ u8 i; ++ char big_symbol = 0; ++ ++ big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; ++ ++ if (big_symbol) { ++ reg16 = 115; ++ } else { ++ reg16 = 96; ++ ++ /* TODO: IS THIS NECESSARY ? */ ++ for (i = 0; i < 3; i++) { ++ offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; ++ ++ if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) ++ offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; ++ ++ if (offset_MHz[i] > max_offset) { ++ max_offset = offset_MHz[i]; ++ reg16 = reg16_list[i]; ++ dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; ++ ++ if (big_symbol) ++ dev->mclk /= 2; ++ ++ dev_dbg(&client->dev, "modifying mclk %u -> %u\n", ++ old_setting, dev->mclk); ++ } ++ } ++ } ++ ++ if (dev->mclk == 93000000) ++ regmap_write(dev->regmap, 0xA0, 0x42); ++ else if (dev->mclk == 96000000) ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ else if (dev->mclk == 99000000) ++ regmap_write(dev->regmap, 0xA0, 0x46); ++ else if (dev->mclk == 110250000) ++ regmap_write(dev->regmap, 0xA0, 0x4E); ++ else ++ regmap_write(dev->regmap, 0xA0, 0x44); ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ ++ if (big_symbol) ++ reg15 |= 0x02; ++ else ++ reg15 &= ~0x02; ++ ++ m88ds3103b_dt_write(dev, 0x15, reg15); ++ m88ds3103b_dt_write(dev, 0x16, reg16); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, (u8)(big_symbol ? 0x0E : 0x0A)); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ ++static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) ++{ ++ u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; ++ u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0, pll_ldpc_mode; ++ u16 pll_div_fb, N; ++ u32 div; ++ ++ reg15 = m88ds3103b_dt_read(dev, 0x15); ++ reg16 = m88ds3103b_dt_read(dev, 0x16); ++ reg1D = m88ds3103b_dt_read(dev, 0x1D); ++ ++ if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { ++ if (reg16 == 92) ++ tmp = 93; ++ else if (reg16 == 100) ++ tmp = 99; ++ else ++ tmp = 96; ++ ++ mclk_khz *= tmp; ++ mclk_khz /= 96; ++ } ++ ++ pll_ldpc_mode = (reg15 >> 1) & 0x01; ++ ++ pll_div_fb = (reg15 & 0x01) << 8; ++ pll_div_fb += reg16; ++ pll_div_fb += 32; ++ ++ div = 9000 * pll_div_fb * 4; ++ div /= mclk_khz; ++ ++ if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { ++ reg11 |= 0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 34) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 8) && (f0 != 0)) ++ f0 = 8; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 8) && (f1 != 0)) ++ f1 = 8; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 8) && (f2 != 0)) ++ f2 = 8; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 8) && (f3 != 0)) ++ f3 = 8; ++ } else { ++ reg11 &= ~0x02; ++ ++ if (div <= 32) { ++ N = 2; ++ ++ f0 = 0; ++ f1 = div / N; ++ f2 = div - f1; ++ f3 = 0; ++ } else if (div <= 48) { ++ N = 3; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = div - f0 - f1; ++ f3 = 0; ++ } else if (div <= 64) { ++ N = 4; ++ ++ f0 = div / N; ++ f1 = (div - f0) / (N - 1); ++ f2 = (div - f0 - f1) / (N - 2); ++ f3 = div - f0 - f1 - f2; ++ } else { ++ N = 4; ++ ++ f0 = 16; ++ f1 = 16; ++ f2 = 16; ++ f3 = 16; ++ } ++ ++ if (f0 == 16) ++ f0 = 0; ++ else if ((f0 < 9) && (f0 != 0)) ++ f0 = 9; ++ ++ if (f1 == 16) ++ f1 = 0; ++ else if ((f1 < 9) && (f1 != 0)) ++ f1 = 9; ++ ++ if (f2 == 16) ++ f2 = 0; ++ else if ((f2 < 9) && (f2 != 0)) ++ f2 = 9; ++ ++ if (f3 == 16) ++ f3 = 0; ++ else if ((f3 < 9) && (f3 != 0)) ++ f3 = 9; ++ } ++ ++ sm = N - 1; ++ ++ /* Write to registers */ ++ //reg15 &= 0x01; ++ //reg15 |= (pll_div_fb >> 8) & 0x01; ++ ++ //reg16 = pll_div_fb & 0xFF; ++ ++ reg1D &= ~0x03; ++ reg1D |= sm; ++ reg1D |= 0x80; ++ ++ reg1E = ((f3 << 4) + f2) & 0xFF; ++ reg1F = ((f1 << 4) + f0) & 0xFF; ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x40); ++ m88ds3103b_dt_write(dev, 0x11, 0x08); ++ m88ds3103b_dt_write(dev, 0x1D, reg1D); ++ m88ds3103b_dt_write(dev, 0x1E, reg1E); ++ m88ds3103b_dt_write(dev, 0x1F, reg1F); ++ ++ m88ds3103b_dt_write(dev, 0x17, 0xc1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ ++ usleep_range(5000, 5500); ++ ++ m88ds3103b_dt_write(dev, 0x05, 0x00); ++ m88ds3103b_dt_write(dev, 0x11, 0x0A); ++ ++ usleep_range(5000, 5500); ++ ++ return 0; ++} ++ + static int m88ds3103_set_frontend(struct dvb_frontend *fe) + { + struct m88ds3103_dev *dev = fe->demodulator_priv; +@@ -298,7 +631,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ + u8 buf[3]; + u16 u16tmp; +- u32 tuner_frequency_khz, target_mclk; ++ u32 tuner_frequency_khz, target_mclk, u32tmp; + s32 s32tmp; + static const struct reg_sequence reset_buf[] = { + {0x07, 0x80}, {0x07, 0x00} +@@ -321,6 +654,20 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + + /* Disable demod clock path */ + if (dev->chip_id == M88RS6000_CHIP_ID) { ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = regmap_read(dev->regmap, 0xb2, &u32tmp); ++ if (ret) ++ goto err; ++ if (u32tmp == 0x01) { ++ ret = regmap_write(dev->regmap, 0x00, 0x00); ++ if (ret) ++ goto err; ++ ret = regmap_write(dev->regmap, 0xb2, 0x00); ++ if (ret) ++ goto err; ++ } ++ } ++ + ret = regmap_write(dev->regmap, 0x06, 0xe0); + if (ret) + goto err; +@@ -346,7 +693,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + tuner_frequency_khz = c->frequency; + } + +- /* select M88RS6000 demod main mclk and ts mclk from tuner die. */ ++ /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ + if (dev->chip_id == M88RS6000_CHIP_ID) { + if (c->symbol_rate > 45010000) + dev->mclk = 110250000; +@@ -358,6 +705,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + target_mclk = 144000000; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_select_mclk(dev); ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ } ++ + /* Enable demod clock path */ + ret = regmap_write(dev->regmap, 0x06, 0x00); + if (ret) +@@ -469,12 +821,42 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08); + if (ret) + goto err; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ buf[0] = m88ds3103b_dt_read(dev, 0x15); ++ buf[1] = m88ds3103b_dt_read(dev, 0x16); ++ ++ if (c->symbol_rate > 45010000) { ++ buf[0] &= ~0x03; ++ buf[0] |= 0x02; ++ buf[0] |= ((147 - 32) >> 8) & 0x01; ++ buf[1] = (147 - 32) & 0xFF; ++ ++ dev->mclk = 110250 * 1000; ++ } else { ++ buf[0] &= ~0x03; ++ buf[0] |= ((128 - 32) >> 8) & 0x01; ++ buf[1] = (128 - 32) & 0xFF; ++ ++ dev->mclk = 96000 * 1000; ++ } ++ m88ds3103b_dt_write(dev, 0x15, buf[0]); ++ m88ds3103b_dt_write(dev, 0x16, buf[1]); ++ ++ regmap_read(dev->regmap, 0x30, &u32tmp); ++ u32tmp &= ~0x80; ++ regmap_write(dev->regmap, 0x30, u32tmp & 0xff); ++ } ++ + ret = regmap_write(dev->regmap, 0xf1, 0x01); + if (ret) + goto err; +- ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); +- if (ret) +- goto err; ++ ++ if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80); ++ if (ret) ++ goto err; ++ } + } + + switch (dev->cfg->ts_mode) { +@@ -488,6 +870,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + break; + case M88DS3103_TS_PARALLEL: + u8tmp = 0x02; ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ u8tmp = 0x01; ++ u8tmp1 = 0x01; ++ } + break; + case M88DS3103_TS_CI: + u8tmp = 0x03; +@@ -516,6 +902,12 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + u8tmp1 = 0x3f; + u8tmp2 = 0x3f; + break; ++ case M88DS3103_TS_PARALLEL: ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ ret = m88ds3103_update_bits(dev, 0x29, 0x01, u8tmp1); ++ if (ret) ++ goto err; ++ } + default: + u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); + u8tmp1 = u16tmp / 2 - 1; +@@ -543,6 +935,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + else + u8tmp = 0x06; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ m88ds3103b_set_mclk(dev, target_mclk / 1000); ++ + ret = regmap_write(dev->regmap, 0xc3, 0x08); + if (ret) + goto err; +@@ -578,6 +973,16 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) + if (ret) + goto err; + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable/disable 192M LDPC clock */ ++ ret = m88ds3103_update_bits(dev, 0x29, 0x10, ++ (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); ++ if (ret) ++ goto err; ++ ++ ret = m88ds3103_update_bits(dev, 0xc9, 0x08, 0x08); ++ } ++ + dev_dbg(&client->dev, "carrier offset=%d\n", + (tuner_frequency_khz - c->frequency)); + +@@ -654,10 +1059,13 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "found a '%s' in cold state\n", + m88ds3103_ops.info.name); + +- if (dev->chip_id == M88RS6000_CHIP_ID) ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) ++ name = M88DS3103B_FIRMWARE; ++ else if (dev->chip_id == M88RS6000_CHIP_ID) + name = M88RS6000_FIRMWARE; + else + name = M88DS3103_FIRMWARE; ++ + /* request the firmware, this will block and timeout */ + ret = request_firmware(&firmware, name, &client->dev); + if (ret) { +@@ -704,6 +1112,12 @@ static int m88ds3103_init(struct dvb_frontend *fe) + dev_info(&client->dev, "firmware version: %X.%X\n", + (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); + ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ m88ds3103b_dt_write(dev, 0x21, 0x92); ++ m88ds3103b_dt_write(dev, 0x15, 0x6C); ++ m88ds3103b_dt_write(dev, 0x17, 0xC1); ++ m88ds3103b_dt_write(dev, 0x17, 0x81); ++ } + warm: + /* warm state */ + dev->warm = true; +@@ -1393,6 +1807,8 @@ static int m88ds3103_probe(struct i2c_client *client, + goto err_kfree; + + dev->chip_id = utmp >> 1; ++ dev->chiptype = (u8)id->driver_data; ++ + dev_dbg(&client->dev, "chip_id=%02x\n", dev->chip_id); + + switch (dev->chip_id) { +@@ -1470,6 +1886,19 @@ static int m88ds3103_probe(struct i2c_client *client, + /* setup callbacks */ + pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; + pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; ++ ++ if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { ++ /* enable i2c repeater for tuner */ ++ m88ds3103_update_bits(dev, 0x11, 0x01, 0x01); ++ ++ /* get frontend address */ ++ ret = regmap_read(dev->regmap, 0x29, &utmp); ++ if (ret) ++ goto err_kfree; ++ dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; ++ dev_err(&client->dev, "dt addr is 0x%02x", dev->dt_addr); ++ } ++ + return 0; + err_kfree: + kfree(dev); +@@ -1491,7 +1920,9 @@ static int m88ds3103_remove(struct i2c_client *client) + } + + static const struct i2c_device_id m88ds3103_id_table[] = { +- {"m88ds3103", 0}, ++ {"m88ds3103", M88DS3103_CHIPTYPE_3103}, ++ {"m88rs6000", M88DS3103_CHIPTYPE_RS6000}, ++ {"m88ds3103b", M88DS3103_CHIPTYPE_3103B}, + {} + }; + MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); +@@ -1513,3 +1944,4 @@ MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver"); + MODULE_LICENSE("GPL"); + MODULE_FIRMWARE(M88DS3103_FIRMWARE); + MODULE_FIRMWARE(M88RS6000_FIRMWARE); ++MODULE_FIRMWARE(M88DS3103B_FIRMWARE); +diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h +index c825032..d656ec2 100644 +--- a/drivers/media/dvb-frontends/m88ds3103_priv.h ++++ b/drivers/media/dvb-frontends/m88ds3103_priv.h +@@ -16,11 +16,17 @@ + #include + #include + +-#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" +-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++#define M88DS3103B_FIRMWARE "dvb-demod-m88ds3103b.fw" ++#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw" ++#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw" ++ + #define M88RS6000_CHIP_ID 0x74 + #define M88DS3103_CHIP_ID 0x70 + ++#define M88DS3103_CHIPTYPE_3103 0 ++#define M88DS3103_CHIPTYPE_RS6000 1 ++#define M88DS3103_CHIPTYPE_3103B 2 ++ + struct m88ds3103_dev { + struct i2c_client *client; + struct regmap_config regmap_config; +@@ -35,10 +41,13 @@ struct m88ds3103_dev { + struct i2c_mux_core *muxc; + /* auto detect chip id to do different config */ + u8 chip_id; ++ /* chip type to differentiate m88rs6000 from m88ds3103b */ ++ u8 chiptype; + /* main mclk is calculated for M88RS6000 dynamically */ + s32 mclk; + u64 post_bit_error; + u64 post_bit_count; ++ u8 dt_addr; + }; + + struct m88ds3103_reg_val { +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 1283c7c..6561f7b 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2397,6 +2397,20 @@ const struct em28xx_board em28xx_boards[] = { + .has_dvb = 1, + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, + }, ++ /* ++ * 2013:0259 PCTV DVB-S2 Stick (461e_v2) ++ * Empia EM28178, Montage M88DS3103b, Montage M88TS2022, Allegro A8293 ++ */ ++ [EM28178_BOARD_PCTV_461E_V2] = { ++ .def_i2c_bus = 1, ++ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ .name = "PCTV DVB-S2 Stick (461e v2)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_461e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ }, + /* + * 2013:025f PCTV tripleStick (292e). + * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 +@@ -2678,6 +2692,10 @@ struct usb_device_id em28xx_id_table[] = { + .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, + { USB_DEVICE(0x2013, 0x0258), + .driver_info = EM28178_BOARD_PCTV_461E }, ++ { USB_DEVICE(0x2013, 0x0461), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, ++ { USB_DEVICE(0x2013, 0x0259), ++ .driver_info = EM28178_BOARD_PCTV_461E_V2 }, + { USB_DEVICE(0x2013, 0x025f), + .driver_info = EM28178_BOARD_PCTV_292E }, + { USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */ +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index a73faf1..e2ddc25 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -1219,6 +1219,65 @@ static int em28178_dvb_init_pctv_461e(struct em28xx *dev) + return 0; + } + ++static int em28178_dvb_init_pctv_461e_v2(struct em28xx *dev) ++{ ++ struct em28xx_dvb *dvb = dev->dvb; ++ struct i2c_adapter *i2c_adapter; ++ struct m88ds3103_platform_data m88ds3103_pdata = {}; ++ struct ts2020_config ts2020_config = {}; ++ struct a8293_platform_data a8293_pdata = {}; ++ ++ /* attach demod */ ++ m88ds3103_pdata.clk = 27000000; ++ m88ds3103_pdata.i2c_wr_max = 33; ++ m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL; ++ m88ds3103_pdata.ts_clk = 16000; ++ m88ds3103_pdata.ts_clk_pol = 1; ++ m88ds3103_pdata.agc = 0x99; ++ m88ds3103_pdata.agc_inv = 1; ++ m88ds3103_pdata.spec_inv = 1; ++ dvb->i2c_client_demod = dvb_module_probe("m88ds3103", "m88ds3103b", ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x6a, &m88ds3103_pdata); ++ ++ if (!dvb->i2c_client_demod) { ++ pr_err("%s() FUCK\n", __func__); ++ return -ENODEV; ++ } ++ ++ dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod); ++ i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod); ++ ++ /* attach tuner */ ++ ts2020_config.fe = dvb->fe[0]; ++ dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022", ++ i2c_adapter, ++ 0x60, &ts2020_config); ++ if (!dvb->i2c_client_tuner) { ++ pr_err("%s() FUCK2\n", __func__); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ /* delegate signal strength measurement to tuner */ ++ dvb->fe[0]->ops.read_signal_strength = ++ dvb->fe[0]->ops.tuner_ops.get_rf_strength; ++ ++ /* attach SEC */ ++ a8293_pdata.dvb_frontend = dvb->fe[0]; ++ dvb->i2c_client_sec = dvb_module_probe("a8293", NULL, ++ &dev->i2c_adap[dev->def_i2c_bus], ++ 0x08, &a8293_pdata); ++ if (!dvb->i2c_client_sec) { ++ pr_err("%s() FUCK3\n", __func__); ++ dvb_module_release(dvb->i2c_client_tuner); ++ dvb_module_release(dvb->i2c_client_demod); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int em28178_dvb_init_pctv_292e(struct em28xx *dev) + { + struct em28xx_dvb *dvb = dev->dvb; +@@ -1860,6 +1919,11 @@ static int em28xx_dvb_init(struct em28xx *dev) + if (result) + goto out_free; + break; ++ case EM28178_BOARD_PCTV_461E_V2: ++ result = em28178_dvb_init_pctv_461e_v2(dev); ++ if (result) ++ goto out_free; ++ break; + case EM28178_BOARD_PCTV_292E: + result = em28178_dvb_init_pctv_292e(dev); + if (result) +diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h +index a551072..1affdd1 100644 +--- a/drivers/media/usb/em28xx/em28xx.h ++++ b/drivers/media/usb/em28xx/em28xx.h +@@ -149,6 +149,7 @@ + #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 + #define EM2884_BOARD_TERRATEC_H6 101 + #define EM2882_BOARD_ZOLID_HYBRID_TV_STICK 102 ++#define EM28178_BOARD_PCTV_461E_V2 103 + + /* Limits minimum and default number of buffers */ + #define EM28XX_MIN_BUF 4 +-- +2.17.1 diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-02-linux-901-extend-rc6-toggle-support.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-02-linux-901-extend-rc6-toggle-support.patch new file mode 100644 index 000000000..bd455908d --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-02-linux-901-extend-rc6-toggle-support.patch @@ -0,0 +1,53 @@ +From 3f1f8303b6e0be751d7a7c55031c8ab840ed5c1a Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Fri, 24 Aug 2018 23:31:51 +0200 +Subject: [PATCH] media: rc: ir-rc6-decoder: enable toggle bit for Kathrein + RCU-676 remote + +The Kathrein RCU-676 remote uses the 32-bit rc6 protocol and toggles +bit 15 (0x8000) on repeated button presses, like MCE remotes. + +Add it's customer code 0x80460000 to the 32-bit rc6 toggle +handling code to get proper scancodes and toggle reports. + +Signed-off-by: Matthias Reichl +--- + drivers/media/rc/ir-rc6-decoder.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c +index 68487ce9f79b..d96aed1343e4 100644 +--- a/drivers/media/rc/ir-rc6-decoder.c ++++ b/drivers/media/rc/ir-rc6-decoder.c +@@ -40,6 +40,7 @@ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ + #define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ ++#define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ + #endif +@@ -242,13 +243,17 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) + toggle = 0; + break; + case 32: +- if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { ++ switch (scancode & RC6_6A_LCC_MASK) { ++ case RC6_6A_MCE_CC: ++ case RC6_6A_KATHREIN_CC: + protocol = RC_PROTO_RC6_MCE; + toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; +- } else { ++ break; ++ default: + protocol = RC_PROTO_RC6_6A_32; + toggle = 0; ++ break; + } + break; + default: +-- +2.11.0 + + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-03-linux-902-extend-rc6-toggle-support-for-zotac.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-03-linux-902-extend-rc6-toggle-support-for-zotac.patch new file mode 100644 index 000000000..65fe5fd6c --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-03-linux-902-extend-rc6-toggle-support-for-zotac.patch @@ -0,0 +1,41 @@ +From ae1ccaa3587c0bd3d6d01841fa2e668cdf738f1e Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 3 Feb 2019 14:24:00 +0100 +Subject: [PATCH] media: rc: ir-rc6-decoder: enable toggle bit for Zotac + remotes + +The Zotac RC2604323/01G and RC2604329/02BG remotes use the 32-bit +rc6 protocol and toggle bit 15 (0x8000) on repeated button presses, +like MCE remotes. + +Add the customer code 0x80340000 to the 32-bit rc6 toggle +handling code to get proper scancodes and toggle reports. + +Signed-off-by: Matthias Reichl +--- + drivers/media/rc/ir-rc6-decoder.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c +index d96aed1343e4..5cc302fa4daa 100644 +--- a/drivers/media/rc/ir-rc6-decoder.c ++++ b/drivers/media/rc/ir-rc6-decoder.c +@@ -40,6 +40,7 @@ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ + #define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ ++#define RC6_6A_ZOTAC_CC 0x80340000 /* Zotac customer code */ + #define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ +@@ -246,6 +247,7 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) + switch (scancode & RC6_6A_LCC_MASK) { + case RC6_6A_MCE_CC: + case RC6_6A_KATHREIN_CC: ++ case RC6_6A_ZOTAC_CC: + protocol = RC_PROTO_RC6_MCE; + toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; +-- +2.20.1 + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-04-fix-tbs5520se.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-04-fix-tbs5520se.patch new file mode 100644 index 000000000..5919df3e7 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-04-fix-tbs5520se.patch @@ -0,0 +1,22 @@ +https://bitbucket.org/CrazyCat/linux_media/commits/ebd9c45524383e09d993563f4bd3cc765796b38a/raw +https://forum.libreelec.tv/thread/14405-dual-tbs-5520se-libreelec-9-0-0-intel-generic/?postID=110926#post110926 +fixes TBS5520se scanning of frequencies + +From: CrazyCat +Date: Mon, 12 Nov 2018 19:49:55 +0200 +Subject: [PATCH] si2183: Fixed minimal frequency for DVB-C. + +diff --git a/drivers/media/dvb-frontends/si2183.c b/drivers/media/dvb-frontends/si2183.c +index f1cc0da..333abd0 100644 +--- a/drivers/media/dvb-frontends/si2183.c ++++ b/drivers/media/dvb-frontends/si2183.c +@@ -1335,7 +1335,7 @@ static int si2183_set_property(struct dvb_frontend *fe, + break; + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: +- fe->ops.info.frequency_min_hz = 470 * MHz; ++ fe->ops.info.frequency_min_hz = 47 * MHz; + fe->ops.info.frequency_max_hz = 862 * MHz; + fe->ops.info.frequency_stepsize_hz = 62500; + break; + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-05-fix-si2168-timeout.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-05-fix-si2168-timeout.patch new file mode 100644 index 000000000..6d8dcf6d4 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-05-fix-si2168-timeout.patch @@ -0,0 +1,18 @@ +https://github.com/CoreELEC/CoreELEC/pull/208 +fix si2168 tunning timeout + +Some demuxer si2168 commands may take 130-140 ms +(DVB-T/T2 tuner MyGica T230C v2). + + +--- a/drivers/media/dvb-frontends/si2168.c ++++ b/drivers/media/dvb-frontends/si2168.c +@@ -42,7 +42,7 @@ static int si2168_cmd_execute(struct i2c + + if (cmd->rlen) { + /* wait cmd execution terminate */ +- #define TIMEOUT 70 ++ #define TIMEOUT 200 + timeout = jiffies + msecs_to_jiffies(TIMEOUT); + while (!time_after(jiffies, timeout)) { + ret = i2c_master_recv(client, cmd->args, cmd->rlen); diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-06-dmxdev-buffer.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-06-dmxdev-buffer.patch new file mode 100644 index 000000000..9d71d124c --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-06-dmxdev-buffer.patch @@ -0,0 +1,19 @@ +https://github.com/CoreELEC/CoreELEC/pull/208 +various checksum and continuity errors workaround + +Workaround for various discontinuity, invalid checksum, Continuity +counter error and Transport error indicator errors which happens +randomly at 1/25 channel switches (DVB-T/T2 tuner MyGica T230C v2 +at ARM plaform - Amlogic S912). + +--- a/include/media/dmxdev.h ++++ b/include/media/dmxdev.h +@@ -187,7 +187,7 @@ struct dmxdev { + struct dmx_frontend *dvr_orig_fe; + + struct dvb_ringbuffer dvr_buffer; +-#define DVR_BUFFER_SIZE (10*188*1024) ++#define DVR_BUFFER_SIZE (4*10*188*1024) + + struct dvb_vb2_ctx dvr_vb2_ctx; + diff --git a/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-99-build-fix.patch b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-99-build-fix.patch new file mode 100644 index 000000000..56880254f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/depends/media_tree_cc_aml/patches/media_tree_cc_aml-99-build-fix.patch @@ -0,0 +1,860 @@ +diff --git a/drivers/media/dvb-frontends/mxl58x.c b/drivers/media/dvb-frontends/mxl58x.c +index a6f2c68..45c4f9e 100644 +--- a/drivers/media/dvb-frontends/mxl58x.c ++++ b/drivers/media/dvb-frontends/mxl58x.c +@@ -158,7 +158,7 @@ static int write_register(struct mxl *state, u32 reg, u32 val) + dev_err(&state->base->i2c->dev,"i2c write error\n"); + return stat; + } +- ++/* + static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) + { + int stat; +@@ -181,7 +181,7 @@ static int write_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) + mutex_unlock(&state->base->i2c_lock); + return stat; + } +- ++*/ + static int write_firmware_block(struct mxl *state, + u32 reg, u32 size, u8 *regDataPtr) + { +@@ -282,7 +282,7 @@ static int update_by_mnemonic(struct mxl *state, + stat = write_register(state, reg, data); + return stat; + } +- ++/* + static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width, + u32 *toAddr, u8 *toLsbPos, u8 *toWidth) + { +@@ -293,7 +293,7 @@ static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width, + if (toWidth) + *toWidth = width; + } +- ++*/ + static int firmware_is_alive(struct mxl *state) + { + u32 hb0, hb1; +@@ -329,7 +329,7 @@ static int get_algo(struct dvb_frontend *fe) + { + return DVBFE_ALGO_HW; + } +- ++/* + static int CfgDemodAbortTune(struct mxl *state) + { + MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd; +@@ -340,7 +340,7 @@ static int CfgDemodAbortTune(struct mxl *state) + BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, cmdSize, &abortTuneCmd, cmdBuff); + return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE, &cmdBuff[0]); + } +- ++*/ + static int send_master_cmd(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) + { +@@ -375,7 +375,7 @@ static int send_burst(struct dvb_frontend *fe, + MXL_HYDRA_DISEQC_TX_MSG_T diseqcMsgPtr; + u8 cmdSize = sizeof(MXL_HYDRA_DISEQC_TX_MSG_T); + u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; +- int i = 0,ret = 0; ++ int ret = 0; + + if (!mode) + return 0; +@@ -544,7 +544,8 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) + p->pre_bit_count.len = 1; + p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; + p->pre_bit_count.stat[0].uvalue = reg[3]; +- dev_dbg(&state->base->i2c->dev,"pre_bit_error=%u pre_bit_count=%u\n", p->pre_bit_error.stat[0].uvalue, p->pre_bit_count.stat[0].uvalue); ++ dev_dbg(&state->base->i2c->dev,"pre_bit_error=%u pre_bit_count=%u\n", ++ (unsigned int)p->pre_bit_error.stat[0].uvalue, (unsigned int)p->pre_bit_count.stat[0].uvalue); + break; + default: + break; +@@ -579,7 +580,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) + default: + break; + } +- dev_dbg(&state->base->i2c->dev,"post_bit_error=%u post_bit_count=%u\n", p->post_bit_error.stat[0].uvalue, p->post_bit_count.stat[0].uvalue); ++ dev_dbg(&state->base->i2c->dev,"post_bit_error=%u post_bit_count=%u\n", (unsigned int)p->post_bit_error.stat[0].uvalue, (unsigned int)p->post_bit_count.stat[0].uvalue); + + return 0; + } +@@ -1072,6 +1073,7 @@ static int firmware_download(struct mxl *state, u32 mbinBufferSize, + return status; + } + ++#if 0 + static int cfg_ts_pad_mux(struct mxl *state, MXL_BOOL_E enableSerialTS) + { + int status = 0; +@@ -1177,7 +1179,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, MXL_HYDRA_ + {XPT_TS_CLK_OUT_EN2}, {XPT_TS_CLK_OUT_EN3}, + {XPT_TS_CLK_OUT_EN4}, {XPT_TS_CLK_OUT_EN5}, + {XPT_TS_CLK_OUT_EN6}, {XPT_TS_CLK_OUT_EN7} }; +- MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = { ++/* MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = { + {PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL}, + {PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL}, + {PAD_MUX_DIGIO_08_PINMUX_SEL}, {PAD_MUX_DIGIO_03_PINMUX_SEL} }; +@@ -1185,7 +1187,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId, MXL_HYDRA_ + {PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL}, + {PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL}, + {PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL} }; +- ++*/ + if (MXL_ENABLE == mpegOutParamPtr->enable) { + cfg_ts_pad_mux(state, MXL_TRUE); + SET_REG_FIELD_DATA(XPT_ENABLE_PARALLEL_OUTPUT, MXL_FALSE); +@@ -1320,7 +1322,7 @@ static int config_mux(struct mxl *state) + SET_REG_FIELD_DATA(XPT_STREAM_MUXMODE1, 1); + return 0; + } +- ++#endif + static int config_dis(struct mxl *state, u32 id) + { + MXL_HYDRA_DISEQC_ID_E diseqcId = id; +@@ -1344,9 +1346,9 @@ static int config_dis(struct mxl *state, u32 id) + + static int load_fw(struct mxl *state) + { +- struct mxl58x_cfg *cfg = state->base->cfg; ++// struct mxl58x_cfg *cfg = state->base->cfg; + int stat = 0; +- u8 *buf; ++// u8 *buf; + + const struct firmware *fw; + +@@ -1357,7 +1359,7 @@ static int load_fw(struct mxl *state) + if (stat) + return stat; + +- stat = firmware_download(state, fw->size, fw->data); ++ stat = firmware_download(state, fw->size, (u8 *)fw->data); + + release_firmware(fw); + +@@ -1396,8 +1398,8 @@ static int probe(struct mxl *state) + { + struct mxl58x_cfg *cfg = state->base->cfg; + u32 chipver; +- int fw, status, j; +- MXL_HYDRA_MPEGOUT_PARAM_T mpegInterfaceCfg; ++ int fw, status; ++// MXL_HYDRA_MPEGOUT_PARAM_T mpegInterfaceCfg; + + fw = firmware_is_alive(state); + +diff --git a/drivers/media/dvb-frontends/si2183.c b/drivers/media/dvb-frontends/si2183.c +index 0c512b5..98914b1 100644 +--- a/drivers/media/dvb-frontends/si2183.c ++++ b/drivers/media/dvb-frontends/si2183.c +@@ -28,12 +28,19 @@ + #define SI2183_PROP_MODE 0x100a + #define SI2183_PROP_DVBC_CONST 0x1101 + #define SI2183_PROP_DVBC_SR 0x1102 ++#define SI2183_PROP_DVBC_AFC 0x1103 + #define SI2183_PROP_DVBT_HIER 0x1201 ++#define SI2183_PROP_DVBT_AFC 0x1202 ++#define SI2183_PROP_DVBT2_AFC 0x1301 + #define SI2183_PROP_DVBT2_MODE 0x1304 + #define SI2183_PROP_DVBS2_SR 0x1401 ++#define SI2183_PROP_DVBS2_AFC 0x1402 + #define SI2183_PROP_DVBS_SR 0x1501 ++#define SI2183_PROP_DVBS_AFC 0x1502 + #define SI2183_PROP_MCNS_CONST 0x1601 + #define SI2183_PROP_MCNS_SR 0x1602 ++#define SI2183_PROP_MCNS_AFC 0x1603 ++#define SI2183_PROP_DVBC2_AFC 0x1701 + + #define SI2183_ARGLEN 30 + struct si2183_cmd { +@@ -47,6 +54,7 @@ static const struct dvb_frontend_ops si2183_ops; + LIST_HEAD(silist); + + struct si_base { ++ struct mutex i2c_mutex; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + struct i2c_mux_core *muxc; + #endif +@@ -74,6 +82,7 @@ struct si2183_dev { + u8 ts_mode; + bool ts_clock_inv; + bool ts_clock_gapped; ++ u8 start_clk_mode; + + int fef_pin; + bool fef_inv; +@@ -176,11 +185,12 @@ err: + + static int si2183_cmd_execute(struct i2c_client *client, struct si2183_cmd *cmd) + { ++ struct si2183_dev *dev = i2c_get_clientdata(client); + int ret; + +- i2c_lock_adapter(client->adapter); ++ mutex_lock(&dev->base->i2c_mutex); + ret = si2183_cmd_execute_unlocked(client, cmd); +- i2c_unlock_adapter(client->adapter); ++ mutex_unlock(&dev->base->i2c_mutex); + + return ret; + } +@@ -202,7 +212,7 @@ static int si2183_set_prop(struct i2c_client *client, u16 prop, u16 *val) + *val = (cmd.args[2] | (cmd.args[3] << 8)); + return ret; + } +- ++/* + static int si2183_get_prop(struct i2c_client *client, u16 prop, u16 *val) + { + struct si2183_cmd cmd; +@@ -218,7 +228,7 @@ static int si2183_get_prop(struct i2c_client *client, u16 prop, u16 *val) + *val = (cmd.args[2] | (cmd.args[3] << 8)); + return ret; + } +- ++*/ + static int si2183_read_status(struct dvb_frontend *fe, enum fe_status *status) + { + struct i2c_client *client = fe->demodulator_priv; +@@ -282,6 +292,12 @@ static int si2183_read_status(struct dvb_frontend *fe, enum fe_status *status) + cmd.rlen = 14; + snr_mul = 2; + break; ++ case SYS_DVBC2: ++ memcpy(cmd.args, "\x91\x01", 2); ++ cmd.wlen = 2; ++ cmd.rlen = 16; ++ snr_mul = 2; ++ break; + default: + ret = -EINVAL; + goto err; +@@ -427,7 +443,7 @@ static int si2183_set_dvbc(struct dvb_frontend *fe) + { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct i2c_client *client = fe->demodulator_priv; +- struct si2183_cmd cmd; ++// struct si2183_cmd cmd; + int ret; + u16 prop; + +@@ -474,6 +490,14 @@ static int si2183_set_dvbc(struct dvb_frontend *fe) + return ret; + } + ++ /* AFC range */ ++ prop = 100; ++ ret = si2183_set_prop(client, SI2183_PROP_DVBC_AFC, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c AFC range\n"); ++ return ret; ++ } ++ + return 0; + } + +@@ -481,7 +505,7 @@ static int si2183_set_mcns(struct dvb_frontend *fe) + { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct i2c_client *client = fe->demodulator_priv; +- struct si2183_cmd cmd; ++// struct si2183_cmd cmd; + int ret; + u16 prop; + +@@ -528,6 +552,41 @@ static int si2183_set_mcns(struct dvb_frontend *fe) + return ret; + } + ++ /* AFC range */ ++ prop = 200; ++ ret = si2183_set_prop(client, SI2183_PROP_MCNS_AFC, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set mcns AFC range\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int si2183_set_dvbc2(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct i2c_client *client = fe->demodulator_priv; ++ struct si2183_cmd cmd; ++ int ret; ++ u16 prop; ++ ++ /* dvb-c2 mode */ ++ prop = 0xb8; ++ ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c2 mode\n"); ++ return ret; ++ } ++ ++ /* AFC range */ ++ prop = 550; ++ ret = si2183_set_prop(client, SI2183_PROP_DVBC2_AFC, &prop); ++ if (ret) { ++ dev_err(&client->dev, "err set dvb-c2 AFC range\n"); ++ return ret; ++ } ++ + return 0; + } + +@@ -765,7 +824,9 @@ static int si2183_set_frontend(struct dvb_frontend *fe) + case SYS_DVBT2: + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: ++ case SYS_DVBC_ANNEX_C: + case SYS_ISDBT: ++ case SYS_DVBC2: + dev->RF_switch(dev->base->i2c,dev->rf_in,1); + break; + +@@ -801,11 +862,15 @@ static int si2183_set_frontend(struct dvb_frontend *fe) + ret = si2183_set_dvbt(fe); + break; + case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: + ret = si2183_set_dvbc(fe); + break; + case SYS_DVBC_ANNEX_B: + ret = si2183_set_mcns(fe); + break; ++ case SYS_DVBC2: ++ ret = si2183_set_dvbc2(fe); ++ break; + case SYS_ISDBT: + ret = si2183_set_isdbt(fe); + break; +@@ -856,6 +921,10 @@ static int si2183_init(struct dvb_frontend *fe) + + /* initialize */ + memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); ++ if (dev->start_clk_mode) { ++ cmd.args[3] = 0; ++ cmd.args[5] = 0x6; ++ } + cmd.wlen = 13; + cmd.rlen = 0; + ret = si2183_cmd_execute(client, &cmd); +@@ -883,6 +952,9 @@ static int si2183_init(struct dvb_frontend *fe) + + /* power up */ + memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); ++ if (dev->start_clk_mode) { ++ cmd.args[6] = 0x30; ++ } + cmd.wlen = 8; + cmd.rlen = 1; + ret = si2183_cmd_execute(client, &cmd); +@@ -1392,8 +1464,8 @@ err: + + static const struct dvb_frontend_ops si2183_ops = { + .delsys = {SYS_DVBT, SYS_DVBT2, SYS_ISDBT, +- SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, +- SYS_DVBS, SYS_DVBS2, SYS_DSS}, ++ SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C, ++ SYS_DVBS, SYS_DVBS2, SYS_DVBC2}, + .info = { + .name = "Silicon Labs Si2183", + .symbol_rate_min = 1000000, +@@ -1462,7 +1534,7 @@ static int si2183_probe(struct i2c_client *client, + struct si2183_config *config = client->dev.platform_data; + struct si2183_dev *dev; + struct si_base *base; +- int ret; ++ int ret = 0; + + dev_dbg(&client->dev, "\n"); + +@@ -1487,6 +1559,7 @@ static int si2183_probe(struct i2c_client *client, + dev->base = base; + list_add(&base->silist, &silist); + ++ mutex_init(&base->i2c_mutex); + #ifdef SI2183_USE_I2C_MUX + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + /* create mux i2c adapter for tuner */ +@@ -1532,6 +1605,7 @@ static int si2183_probe(struct i2c_client *client, + dev->sat_agc_inv = config->sat_agc_inv; + dev->RF_switch = config->RF_switch; + dev->rf_in = config->rf_in; ++ dev->start_clk_mode = config->start_clk_mode; + dev->fw_loaded = false; + dev->stat_resp = 0; + +diff --git a/drivers/media/dvb-frontends/si2183.h b/drivers/media/dvb-frontends/si2183.h +index 106e11c..41ab0d9 100644 +--- a/drivers/media/dvb-frontends/si2183.h ++++ b/drivers/media/dvb-frontends/si2183.h +@@ -44,6 +44,9 @@ struct si2183_config { + /* TS clock gapped */ + bool ts_clock_gapped; + ++ /* 0 terrestrial mode 1: satellite mode */ ++ u8 start_clk_mode; ++ + /* Tuner control pins */ + #define SI2183_MP_NOT_USED 1 + #define SI2183_MP_A 2 +diff --git a/drivers/media/dvb-frontends/stid135/stid135-fe.c b/drivers/media/dvb-frontends/stid135/stid135-fe.c +index 700854d..9454695 100644 +--- a/drivers/media/dvb-frontends/stid135/stid135-fe.c ++++ b/drivers/media/dvb-frontends/stid135/stid135-fe.c +@@ -336,7 +336,7 @@ static int stid135_set_parameters(struct dvb_frontend *fe) + + static int stid135_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p) + { +- struct stv *state = fe->demodulator_priv; ++// struct stv *state = fe->demodulator_priv; + + return 0; + } +diff --git a/drivers/media/dvb-frontends/stid135/stid135_drv.c b/drivers/media/dvb-frontends/stid135/stid135_drv.c +index ab47144..b30c6b0 100644 +--- a/drivers/media/dvb-frontends/stid135/stid135_drv.c ++++ b/drivers/media/dvb-frontends/stid135/stid135_drv.c +@@ -2759,8 +2759,8 @@ fe_lla_error_t FE_STiD135_GetRFLevel(fe_stid135_handle_t handle, + u8 exp; + u32 Agc2x1000; + u32 InterpolatedGvanax1000; +- s32 PchRFx1000; +- s32 Pbandx1000; ++ s32 PchRFx1000 = 0; ++ s32 Pbandx1000 = 0; + s32 agcrf_path; + struct fe_stid135_internal_param *pParams; + fe_lla_error_t error = FE_LLA_NO_ERROR; +@@ -5152,6 +5152,8 @@ fe_lla_error_t fe_stid135_diseqc_init(fe_stid135_handle_t handle, + reg_value |= 0x00000100; + error |= ChipSetOneRegister(pParams->handle_soc, (u16)REG_RSTID135_SYSCFG_NORTH_SYSTEM_CONFIG1000, reg_value); + break; ++ default: ++ break; + } + + error |= ChipSetField(pParams->handle_demod, +@@ -10028,6 +10030,8 @@ fe_lla_error_t fe_stid135_init_before_bb_flt_calib(fe_stid135_handle_t handle, F + error |= ChipSetField(pParams->handle_demod, FLD_FSTID135_AFE_AFE_AGC4_CTRL_AGC4_BB_CTRL, 3); /* set AGC1 manually, 0x7F */ + error |= ChipSetOneRegister(pParams->handle_demod, (u16)REG_RSTID135_AFE_AFE_AGC4_BB_PWM, 0xCF); //7F + break; ++ default: ++ break; + } + + error |= ChipSetOneRegister(pParams->handle_demod, (u16)REG_RC8CODEW_DVBSX_DEMOD_DMDCFGMD(FE_SAT_DEMOD_1), 0x40); //idee PG 20/04/2017 +@@ -10149,6 +10153,8 @@ fe_lla_error_t fe_stid135_uninit_after_bb_flt_calib(fe_stid135_handle_t handle, + ChipSetOneRegister(pParams->handle_demod, (u16)REG_RSTID135_AFE_AFE_AGC4_CTRL, 0x00); + ChipSetOneRegister(pParams->handle_demod, (u16)REG_RSTID135_AFE_AFE_AGC4_BB_PWM, 0x00); + break; ++ default: ++ break; + } + Oxford_StopBBcal(pParams->handle_demod, tuner_nb); + +@@ -10596,13 +10602,13 @@ fe_lla_error_t fe_stid135_bb_flt_calib(fe_stid135_handle_t handle, FE_OXFORD_Tun + { + s32 fld_value = 0; + u32 measure_h1, measure_h3; +- u32 ratio, ratio_threshold = 174; /* 174 because 10xlog(174/10)=12.4dB */ ++ u32 ratio = 0, ratio_threshold = 174; /* 174 because 10xlog(174/10)=12.4dB */ + fe_lla_error_t error = FE_LLA_NO_ERROR; + BOOL calib_value_found = FALSE; + s32 epsilon = 5; + s32 start_index = 0; + s32 end_index; +- s32 middle_index; ++ s32 middle_index = 0; + struct fe_stid135_internal_param *pParams; + s32 best_i_cal = 0x00, best_q_cal = 0x00; + +diff --git a/drivers/media/dvb-frontends/tas2101.c b/drivers/media/dvb-frontends/tas2101.c +index 010ea59..4c43a82 100644 +--- a/drivers/media/dvb-frontends/tas2101.c ++++ b/drivers/media/dvb-frontends/tas2101.c +@@ -637,9 +637,9 @@ err3: + err2: + i2c_del_mux_adapter(priv->i2c_demod); + #endif +-#endif + err1: + kfree(priv); ++#endif + err: + dev_err(&i2c->dev, "%s: Error attaching frontend\n", KBUILD_MODNAME); + return NULL; +diff --git a/drivers/media/tuners/av201x.c b/drivers/media/tuners/av201x.c +index 07c379e..989e3da 100644 +--- a/drivers/media/tuners/av201x.c ++++ b/drivers/media/tuners/av201x.c +@@ -229,7 +229,7 @@ static int AV201x_level_dBm_10[] = { 90, -50, -263, -361, -463, -563, -66 + + static int av201x_get_rf_strength(struct dvb_frontend *fe, u16 *st) + { +- struct av201x_priv *priv = fe->tuner_priv; ++// struct av201x_priv *priv = fe->tuner_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int if_agc, index, table_length, slope, *x, *y; + +diff --git a/drivers/media/tuners/r848.c b/drivers/media/tuners/r848.c +index de601f7..05efce0 100644 +--- a/drivers/media/tuners/r848.c ++++ b/drivers/media/tuners/r848.c +@@ -72,13 +72,13 @@ static int r848_wr(struct r848_priv *priv, u8 addr, u8 data) + return r848_wrm(priv, buf, 2); + } + +-/* read one register */ ++/* read one register * + static int r848_rd(struct r848_priv *priv, u8 addr, u8 *data) + { + return r848_rdm(priv, addr, data, 1); + } +- +-/* read register, apply masks, write back */ ++*/ ++/* read register, apply masks, write back * + static int r848_regmask(struct r848_priv *priv, + u8 reg, u8 setmask, u8 clrmask) + { +@@ -92,7 +92,7 @@ static int r848_regmask(struct r848_priv *priv, + } + return r848_wr(priv, reg, b | setmask); + } +- ++*/ + static int r848_get_lock_status(struct r848_priv *priv, u8 *lock) + { + int ret; +@@ -123,7 +123,7 @@ static int R848_Muti_Read( struct r848_priv *priv,u8* IMR_Result_Data) + u8 ReadMax = 0; + u8 ReadMin = 255; + u8 ReadData = 0; +- I2C_LEN_TYPE R848_I2C_Len; ++// I2C_LEN_TYPE R848_I2C_Len; + + u8 buf[2]; + int ret; +@@ -333,7 +333,7 @@ int I2C_Write(struct r848_priv *priv, I2C_TYPE *R848_I2C) + R848_ErrCode R848_Cal_Prepare( struct r848_priv *priv,u8 u1CalFlag) + { + R848_Cal_Info_Type Cal_Info; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + // I2C_LEN_TYPE R848_I2C_Len; + u8 R848_IMR_Cal_Type = R848_IMR_CAL; + int ret; +@@ -673,8 +673,8 @@ R848_ErrCode R848_Cal_Prepare( struct r848_priv *priv,u8 u1CalFlag) + R848_ErrCode R848_Xtal_Check( struct r848_priv *priv) + { + u8 i = 0; +- I2C_TYPE R848_I2C; +- I2C_LEN_TYPE R848_I2C_Len; ++// I2C_TYPE R848_I2C; ++// I2C_LEN_TYPE R848_I2C_Len; + + u8 buf[3]; + int ret; +@@ -899,8 +899,8 @@ R848_ErrCode R848_PLL( struct r848_priv *priv,u32 LO_Freq, R848_Standard_Type R8 + u8 R848_XtalDiv = XTAL_DIV2; + + +- I2C_TYPE R848_I2C; +- I2C_LEN_TYPE R848_I2C_Len; ++// I2C_TYPE R848_I2C; ++// I2C_LEN_TYPE R848_I2C_Len; + + //TF, NA fix + u1RfFlag = (priv->cfg->R848_Array[14] & 0x01); //R22[0] +@@ -1384,7 +1384,7 @@ R848_ErrCode R848_MUX( struct r848_priv *priv,u32 LO_KHz, u32 RF_KHz, R848_Stand + u8 Reg08_IMR_Gain = 0; + u8 Reg09_IMR_Phase = 0; + u8 Reg03_IMR_Iqcap = 0; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + Freq_Info1 = R848_Freq_Sel(LO_KHz, RF_KHz, R848_Standard); + + +@@ -1512,7 +1512,7 @@ R848_ErrCode R848_IQ_Tree( struct r848_priv *priv,u8 FixPot, u8 FlucPot, u8 PotR + u8 TreeCunt = 0; + u8 TreeTimes = 3; + u8 PntReg = 0; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + + if(PotReg == 0x10) + PntReg = 0x11; //phase control +@@ -1652,7 +1652,7 @@ R848_ErrCode R848_IMR_Cross( struct r848_priv *priv,R848_SectType* IQ_Pont, u8* + u8 CrossCount = 0; + u8 Reg16 = priv->cfg->R848_Array[8] & 0xC0; + u8 Reg17 = priv->cfg->R848_Array[9] & 0xC0; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + + memset(&Compare_Temp, 0, sizeof(R848_SectType)); + Compare_Temp.Value = 255; +@@ -1824,7 +1824,7 @@ R848_ErrCode R848_CompreStep( struct r848_priv *priv,R848_SectType* StepArry, u8 + { + int ret; + R848_SectType StepTemp; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + //min value already saved in StepArry[0] + StepTemp.Phase_Y = StepArry[0].Phase_Y; + StepTemp.Gain_X = StepArry[0].Gain_X; +@@ -1877,7 +1877,7 @@ R848_ErrCode R848_IMR_Iqcap( struct r848_priv *priv,R848_SectType* IQ_Point) + { + R848_SectType Compare_Temp; + int i = 0, ret; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + + //Set Gain/Phase to right setting + // R848_I2C.RegAddr = 0x10; // R16[5:0] +@@ -1930,7 +1930,7 @@ R848_ErrCode R848_IQ( struct r848_priv *priv,R848_SectType* IQ_Pont) + u8 VGA_Count = 0; + u8 VGA_Read = 0; + u8 X_Direction; // 1:X, 0:Y +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + + + // increase VGA power to let image significant +@@ -2084,7 +2084,7 @@ R848_ErrCode R848_F_IMR( struct r848_priv *priv,R848_SectType* IQ_Pont) + R848_SectType Compare_Bet[3]; + u8 VGA_Count = 0; + u8 VGA_Read = 0; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + + //VGA + for(VGA_Count=11; VGA_Count < 16; VGA_Count ++) +@@ -2184,7 +2184,7 @@ R848_ErrCode R848_SetTF( struct r848_priv *priv,u32 u4FreqKHz, u8 u1TfType) + u8 u1TF_Set_Result2 = 0; + u8 u1TF_tmp1, u1TF_tmp2; + u8 u1TFCalNum = R848_TF_HIGH_NUM; +- I2C_TYPE R848_I2C; ++// I2C_TYPE R848_I2C; + u8 R848_TF = 0; + + if(u4FreqKHzcfg->R848_Array[7] = (priv->cfg->R848_Array[7] & 0xE0) | u1MixerGain; +- R848_I2C.Data = priv->cfg->R848_Array[7]; +- if(I2C_Write(priv,&R848_I2C) != RT_Success) +- return RT_Fail; ++ R848_I2C.Data = priv->cfg->R848_Array[7]; ++ if(I2C_Write(priv,&R848_I2C) != RT_Success) ++ return RT_Fail; + + //write I2C to set RingPLL + R848_I2C.RegAddr = 0x27; +@@ -2768,9 +2768,9 @@ u8 R848_Filt_Cal_ADC( struct r848_priv *priv,u32 IF_Freq, u8 R848_BW, u8 FilCal + } + + if(u1FilterCode==16) +- u1FilterCodeResult = 15; ++ u1FilterCodeResult = 15; + +- return u1FilterCodeResult; ++ return u1FilterCodeResult; + + } + +@@ -3730,6 +3730,8 @@ R848_SysFreq_Info_Type R848_SysFreq_Sel(struct r848_priv *priv,R848_Standard_Typ + case R848_DVB_T2_1_7M_IF_5M: + R848_SysFreq_Info.AGC_CLK = 0x1C; //250Hz R26[4:2] + break; ++ default: ++ break; + } + } + break; +@@ -3755,7 +3757,7 @@ R848_ErrCode R848_RfGainMode( struct r848_priv *priv,R848_RF_Gain_TYPE R848_RfGa + u8 RfGain = 0; + u8 LnaGain = 0; + I2C_TYPE R848_I2C; +- I2C_LEN_TYPE R848_I2C_Len; ++// I2C_LEN_TYPE R848_I2C_Len; + + if(R848_RfGainType==RF_MANUAL) + { +@@ -4438,10 +4440,10 @@ static int r848_init(struct dvb_frontend *fe) + { + struct r848_priv *priv = fe->tuner_priv; + int ret; +- dev_dbg(&priv->i2c->dev, "%s()\n", __func__); +- + u8 i; + ++ dev_dbg(&priv->i2c->dev, "%s()\n", __func__); ++ + if (priv->inited == 1) + return 0; + +diff --git a/drivers/media/tuners/stv6120.c b/drivers/media/tuners/stv6120.c +index 0980f51..f25d60a 100644 +--- a/drivers/media/tuners/stv6120.c ++++ b/drivers/media/tuners/stv6120.c +@@ -364,7 +364,7 @@ static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) + int cf_index = (CutOffFrequency / 1000000) - 5; + u32 Frequency = (LocalFrequency + 500) / 1000; // Hz -> kHz + u32 fvco, div, frac; +- u8 Icp, tmp; ++ u8 Icp; //, tmp; + + u8 PDIV, P; + +diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c +index 12c5b68..2a05f13 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c ++++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c +@@ -717,8 +717,10 @@ static int register_dvb(struct cx231xx_dvb *dvb, + + return 0; + ++#if 0 + fail_create_graph: + dvb_net_release(&dvb->net); ++#endif + fail_fe_conn: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + fail_fe_mem: +diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c +index 6eee95d..5c2ef8a 100644 +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c +@@ -546,6 +546,7 @@ static int dvbsky_t330_attach(struct dvb_usb_adapter *adap) + return 0; + } + ++#if 0 + static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) + { + struct dvbsky_state *state = adap_to_priv(adap); +@@ -580,7 +581,7 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) + + return 0; + } +- ++#endif + + static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) + { +@@ -731,7 +732,7 @@ static struct dvb_usb_device_properties dvbsky_t330_props = { + } + } + }; +- ++#if 0 + static struct dvb_usb_device_properties mygica_t230c_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, +@@ -757,7 +758,7 @@ static struct dvb_usb_device_properties mygica_t230c_props = { + } + } + }; +- ++#endif + static const struct usb_device_id dvbsky_id_table[] = { + { DVB_USB_DEVICE(0x0572, 0x6831, + &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, +diff --git a/drivers/media/usb/dvb-usb/cycitv.c b/drivers/media/usb/dvb-usb/cycitv.c +index ba2b8c9..33340c2 100644 +--- a/drivers/media/usb/dvb-usb/cycitv.c ++++ b/drivers/media/usb/dvb-usb/cycitv.c +@@ -283,7 +283,7 @@ struct cycitv_adapter_state { + + static int cycitv_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + { +- struct cycitv_adapter_state *state = (struct cycitv_adapter_state *)adap->priv; ++// struct cycitv_adapter_state *state = (struct cycitv_adapter_state *)adap->priv; + u8 obuf[0x40], ibuf[0x40]; + u8 tsckinv ; + deb_info("%s onoff=%d\n", __func__,onoff); +@@ -593,7 +593,8 @@ static int cycitv_power_ctrl(struct dvb_usb_device *d, int i) + if (i && !state->initialized) { + state->initialized = 1; + /* reset board */ +- dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); ++ if (dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0)) ++ return 0; + } + + return 0; +@@ -665,7 +666,7 @@ static int cycitv_frontend_attach(struct dvb_usb_adapter *d) + { + struct dvb_usb_device *dev = d->dev; + struct cycitv_state *s = (struct cycitv_state *)dev->priv; +- struct cycitv_adapter_state *state = (struct cycitv_adapter_state *)d->priv; ++// struct cycitv_adapter_state *state = (struct cycitv_adapter_state *)d->priv; + int id; + + deb_info("cycitv_frontend_attach 00!\n"); +@@ -697,6 +698,7 @@ static int cycitv_frontend_attach(struct dvb_usb_adapter *d) + return -EIO; + } + ++#if 0 + static struct rc_map_table rc_map_cycitv_table_mygica[] = { + { 0x25, KEY_POWER }, /* right-bottom Red */ + { 0x0a, KEY_MUTE }, /* -/-- */ +@@ -780,6 +782,7 @@ static int cycitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) + + return 0; + } ++#endif + enum cycitv_table_entry { + GENIATECH_DEV_COLD, + GENIATECH_DEV_WORK, +diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c +index 866ed1f..1b898b7 100644 +--- a/drivers/media/usb/dvb-usb/dw2102.c ++++ b/drivers/media/usb/dvb-usb/dw2102.c +@@ -1144,13 +1144,13 @@ static struct stv0900_config prof_7500_stv0900_config = { + .tun1_type = 3, + .set_lock_led = dw210x_led_ctrl, + }; +- ++/* + static struct ds3000_config su3000_ds3000_config = { + .demod_address = 0x68, + .ci_mode = 1, + .set_lock_led = dw210x_led_ctrl, + }; +- ++*/ + static struct ds3k_config su3000_ds3k_config = { + .demod_address = 0x68, + .ci_mode = 0, +@@ -1390,11 +1390,11 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *adap) + { + struct dvb_usb_device *d = adap->dev; + struct dw2102_state *state = d->priv; +- struct i2c_adapter *i2c_adapter; +- struct i2c_client *client; +- struct i2c_board_info board_info; +- struct m88ds3103_platform_data m88ds3103_pdata = {}; +- struct ts2020_config ts2020_config = {}; ++// struct i2c_adapter *i2c_adapter; ++// struct i2c_client *client; ++// struct i2c_board_info board_info; ++// struct m88ds3103_platform_data m88ds3103_pdata = {}; ++// struct ts2020_config ts2020_config = {}; + + mutex_lock(&d->data_mutex); + diff --git a/packages/kernel/linux-driver-addons/dvb/digital_devices/changelog.txt b/packages/kernel/linux-driver-addons/dvb/digital_devices/changelog.txt new file mode 100755 index 000000000..32d81ca42 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/digital_devices/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial add-on diff --git a/packages/kernel/linux-driver-addons/dvb/digital_devices/icon/icon.png b/packages/kernel/linux-driver-addons/dvb/digital_devices/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..10c6edc2676b3b90863e49d8ed66f2ecdbf896a2 GIT binary patch literal 32470 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 literal 0 HcmV?d00001 diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/package.mk b/packages/kernel/linux-driver-addons/dvb/dvb-latest/package.mk new file mode 100644 index 000000000..5245df288 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/package.mk @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="dvb-latest" +PKG_VERSION="0f25e6fb13b6bc345218800ad9ac863deb2ee9c8" +PKG_SHA256="71294995cff2bc556bcf9aa7ade595a4ccd91a1972b73d1e537d99d2ce86dbed" +PKG_LICENSE="GPL" +PKG_SITE="http://git.linuxtv.org/media_build.git" +PKG_URL="https://git.linuxtv.org/media_build.git/snapshot/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux media_tree" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory media_tree)" +PKG_SECTION="driver.dvb" +PKG_LONGDESC="DVB drivers from the latest kernel (media_build)" + +PKG_IS_ADDON="embedded" +PKG_IS_KERNEL_PKG="yes" +PKG_ADDON_IS_STANDALONE="yes" +PKG_ADDON_NAME="DVB drivers from the latest kernel" +PKG_ADDON_TYPE="xbmc.service" +PKG_ADDON_VERSION="${ADDON_VERSION}.${PKG_REV}" + +if [ "$PROJECT" = "Amlogic" -o "$PROJECT" = "Amlogic-ng" ]; then + PKG_PATCH_DIRS="amlogic-common" + case "$LINUX" in + amlogic-3.14) + PKG_PATCH_DIRS+=" amlogic-3.14" + ;; + amlogic-4.9) + PKG_PATCH_DIRS+=" amlogic-4.9" + ;; + esac + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET media_tree_aml" + PKG_NEED_UNPACK="$PKG_NEED_UNPACK $(get_pkg_directory media_tree_aml)" +fi + +pre_make_target() { + export KERNEL_VER=$(get_module_dir) + export LDFLAGS="" +} + +make_target() { + cp -RP $(get_build_dir media_tree)/* $PKG_BUILD/linux + + if [ "$PROJECT" = "Amlogic" -o "$PROJECT" = "Amlogic-ng" ]; then + cp -Lr $(get_build_dir media_tree_aml)/* $PKG_BUILD/linux + + # compile modules + echo "obj-y += video_dev/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo "obj-y += dvb/" >> "$PKG_BUILD/linux/drivers/media/platform/meson/Makefile" + echo 'source "drivers/media/platform/meson/dvb/Kconfig"' >> "$PKG_BUILD/linux/drivers/media/platform/Kconfig" + sed -e 's/ && RC_CORE//g' -i $PKG_BUILD/linux/drivers/media/usb/dvb-usb/Kconfig + fi + + # make config all + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) allyesconfig + + # hack to workaround media_build bug + if [ "$PROJECT" = "Amlogic" ]; then + sed -e 's/CONFIG_DVB_LGDT3306A=m/# CONFIG_DVB_LGDT3306A is not set/g' -i v4l/.config + sed -e 's/CONFIG_VIDEO_S5C73M3=m/# CONFIG_VIDEO_S5C73M3 is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_SAA7146_VV=m/# CONFIG_VIDEO_SAA7146_VV is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_OV2659=m/# CONFIG_VIDEO_OV2659 is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_OV5647=m/# CONFIG_VIDEO_OV5647 is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_S5K5BAF=m/# CONFIG_VIDEO_S5K5BAF is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_VIVID=m/# CONFIG_VIDEO_VIVID is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_TVP514X=m/# CONFIG_VIDEO_TVP514X is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_TVP7002=m/# CONFIG_VIDEO_TVP7002 is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_CADENCE_CSI2RX=m/# CONFIG_VIDEO_CADENCE_CSI2RX is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/CONFIG_VIDEO_CADENCE_CSI2TX=m/# CONFIG_VIDEO_CADENCE_CSI2TX is not set/g' -i $PKG_BUILD/v4l/.config + sed -e 's/# CONFIG_MEDIA_TUNER_TDA18250 is not set/CONFIG_MEDIA_TUNER_TDA18250=m/g' -i $PKG_BUILD/v4l/.config + fi + + kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) +} + +makeinstall_target() { + install_driver_addon_files "$PKG_BUILD/v4l/" +} diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-01-config_mycompat_h.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-01-config_mycompat_h.patch new file mode 100644 index 000000000..9cfce1bf4 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-01-config_mycompat_h.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/v4l/config-mycompat.h +@@ -0,0 +1,11 @@ ++#undef smp_mb__after_atomic ++#define smp_mb__after_atomic() smp_mb() /*mb*/ ++#undef NEED_SMP_MB_AFTER_ATOMIC ++#undef __pfn_to_phys ++#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) ++#undef NEED_PFN_TO_PHYS ++#undef writel_relaxed ++#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) ++#undef NEED_WRITEL_RELAXED ++#undef NEED_PM_RUNTIME_GET ++#undef NEED_OF_NODE_NAME_EQ +-- diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-02-disable-modules.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-02-disable-modules.patch new file mode 100644 index 000000000..e570906f7 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-3.14/driver.dvb.dvb-latest-02-disable-modules.patch @@ -0,0 +1,14 @@ +--- a/v4l/scripts/make_kconfig.pl ++++ b/v4l/scripts/make_kconfig.pl +@@ -626,6 +626,11 @@ ($$) + close OUT; + + # These options should default to off ++disable_config('MEDIA_ANALOG_TV_SUPPORT'); ++disable_config('MEDIA_CAMERA_SUPPORT'); ++disable_config('MEDIA_CEC_SUPPORT'); ++disable_config('SOC_CAMERA'); ++disable_config('RC_CORE'); + disable_config('DVB_AV7110_FIRMWARE'); + disable_config('DVB_CINERGYT2_TUNING'); + disable_config('VIDEO_HELPER_CHIPS_AUTO'); diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-01-config_mycompat_h.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-01-config_mycompat_h.patch new file mode 100644 index 000000000..1050fb340 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-01-config_mycompat_h.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/v4l/config-mycompat.h +@@ -0,0 +1,8 @@ ++#undef smp_mb__after_atomic ++#define smp_mb__after_atomic() smp_mb() /*mb*/ ++#undef NEED_SMP_MB_AFTER_ATOMIC ++#undef writel_relaxed ++#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) ++#undef NEED_WRITEL_RELAXED ++#undef NEED_PM_RUNTIME_GET ++#undef NEED_OF_NODE_NAME_EQ +-- diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-02-disable-modules.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-02-disable-modules.patch new file mode 100644 index 000000000..dc90455f3 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-4.9/driver.dvb.dvb-latest-02-disable-modules.patch @@ -0,0 +1,17 @@ +--- a/v4l/scripts/make_kconfig.pl ++++ b/v4l/scripts/make_kconfig.pl +@@ -626,6 +626,12 @@ ($$) + close OUT; + + # These options should default to off ++disable_config('MEDIA_ANALOG_TV_SUPPORT'); ++disable_config('MEDIA_CAMERA_SUPPORT'); ++disable_config('MEDIA_CEC_SUPPORT'); ++disable_config('SOC_CAMERA'); ++disable_config('VIDEO_SAA7146_VV'); ++disable_config('RC_CORE'); + disable_config('DVB_AV7110_FIRMWARE'); + disable_config('DVB_CINERGYT2_TUNING'); + disable_config('VIDEO_HELPER_CHIPS_AUTO'); + + diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-03-versions.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-03-versions.patch new file mode 100644 index 000000000..d2e415f10 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-03-versions.patch @@ -0,0 +1,13 @@ +--- a/v4l/versions.txt 2018-06-26 18:42:30.000000000 +0200 ++++ b/v4l/versions.txt 2018-08-14 15:28:29.713517240 +0200 +@@ -24,10 +24,6 @@ + VIDEO_ADV748X + + [4.7.0] +-# needs i2c_mux_alloc +-DVB_RTL2830 +-DVB_RTL2832 +-DVB_M88DS3103 + # needs struct i2c_mux_core + DVB_AF9013 + diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-06-sched_signal-fix.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-06-sched_signal-fix.patch new file mode 100644 index 000000000..57991cbdd --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/amlogic-common/driver.dvb.dvb-latest-06-sched_signal-fix.patch @@ -0,0 +1,72 @@ +diff --git a/backports/v4.10_sched_signal.patch b/backports/v4.10_sched_signal.patch +index fbed946..59e275e 100644 +--- a/backports/v4.10_sched_signal.patch ++++ b/backports/v4.10_sched_signal.patch +@@ -86,66 +86,6 @@ + + /* If you have already X v4l cards, then set this to X. This way + the device numbers stay matched. Example: you have a WinTV card +-diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h +-index 6b099da..81f3c19 100644 +---- a/drivers/media/pci/ivtv/ivtv-driver.h +-+++ b/drivers/media/pci/ivtv/ivtv-driver.h +-@@ -39,38 +39,37 @@ +- * using information provided by Jiun-Kuei Jung @ AVerMedia. +- */ +- +--#include +--#include +-+#include +- #include +--#include +-+#include +- #include +--#include +--#include +--#include +- #include +- #include +-+#include +-+#include +-+#include +-+#include +-+#include +- #include +--#include +-+#include +-+#include +- #include +-+#include +- #include +--#include +--#include +-+#include +- #include +-+#include +- #include +--#include +-+#include +- +--#include +--#include +-+#include +-+#include +-+#include +- #include +--#include +- #include +- #include +- #include +--#include +--#include +--#include +-- +--#include +-+#include +- +- /* Memory layout */ +- #define IVTV_ENCODER_OFFSET 0x00000000 + diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c + index 5708f69..e306544 100644 + --- a/drivers/media/pci/pt1/pt1.c + diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch new file mode 100644 index 000000000..13435136c --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-01-remove-rmmod.pl.patch @@ -0,0 +1,11 @@ +diff --git a/v4l/Makefile b/v4l/Makefile +--- a/v4l/Makefile ++++ b/v4l/Makefile +@@ -51,7 +51,6 @@ default:: prepare firmware + @echo Kernel build directory is $(OUTDIR) + $(MAKE) -C ../linux apply_patches + $(MAKE) -C $(OUTDIR) SUBDIRS=$(PWD) $(MYCFLAGS) modules +- ./scripts/rmmod.pl check + # $(MAKE) checkpatch + + mismatch:: prepare firmware diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-02-add-to-backports.patch b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-02-add-to-backports.patch new file mode 100644 index 000000000..825e14183 --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/patches/driver.dvb.dvb-latest-02-add-to-backports.patch @@ -0,0 +1,17 @@ +--- a/backports/backports.txt ++++ b/backports/backports.txt +@@ -31,6 +31,4 @@ + add v4.18_add_map_atomic.patch + +-[4.20.255] +-add v4.20_access_ok.patch + + [4.17.255] +@@ -91,6 +89,5 @@ + + [4.1.255] +-add v4.1_pat_enabled.patch + add v4.1_drop_fwnode.patch + + [4.0.255] +-- diff --git a/packages/kernel/linux-driver-addons/dvb/dvb-latest/source/default.py b/packages/kernel/linux-driver-addons/dvb/dvb-latest/source/default.py new file mode 100644 index 000000000..c8f85a76f --- /dev/null +++ b/packages/kernel/linux-driver-addons/dvb/dvb-latest/source/default.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) diff --git a/packages/kernel/linux-drivers/RTL8188EU/package.mk b/packages/kernel/linux-drivers/RTL8188EU/package.mk new file mode 100644 index 000000000..0988a36f5 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8188EU/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8188EU" +PKG_VERSION="9a56f32c2a46be5b81f0eedf49ad44ea8f10bfae" +PKG_SHA256="c8f225ff85cdc49e4a043773234e42de38aac0d2c9322829dac21c2ba72fed87" +PKG_LICENSE="GPL" +# realtek: PKG_SITE="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=274&DownTypeID=3&GetDown=false&Downloads=true" +PKG_SITE="https://github.com/lwfinger/rtl8188eu" +PKG_URL="https://github.com/lwfinger/rtl8188eu/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL81xxEU Linux 3.x driver" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8192CU/package.mk b/packages/kernel/linux-drivers/RTL8192CU/package.mk new file mode 100644 index 000000000..8f22b9e8f --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192CU/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8192CU" +PKG_VERSION="f32ef3984db7c7f7644edec0fa28a63a47b1a7d6" +PKG_SHA256="7e8df7cce0918630121c7493a6333d392b3099b1126e8c355aa221cee032c80b" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/pvaret/rtl8192cu-fixes" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL81xxCU Linux 3.x driver" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0001-add_device_ID_330d.patch b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0001-add_device_ID_330d.patch new file mode 100644 index 000000000..f318ddd44 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0001-add_device_ID_330d.patch @@ -0,0 +1,12 @@ +diff -Naur RTL8192CU-v4.0.2_9000.20130911/hal/rtl8192c/usb/usb_halinit.c RTL8192CU-v4.0.2_9000.20130911.patch/hal/rtl8192c/usb/usb_halinit.c +--- RTL8192CU-v4.0.2_9000.20130911/hal/rtl8192c/usb/usb_halinit.c 2013-09-11 05:56:55.000000000 +0200 ++++ RTL8192CU-v4.0.2_9000.20130911.patch/hal/rtl8192c/usb/usb_halinit.c 2014-04-01 20:17:59.270739417 +0200 +@@ -3509,6 +3509,8 @@ + pHalData->CustomerID = RT_CID_DLINK; + else if((pHalData->EEPROMVID == 0x2001) && (pHalData->EEPROMPID == 0x330a)) + pHalData->CustomerID = RT_CID_DLINK; ++ else if((pHalData->EEPROMVID == 0x2001) && (pHalData->EEPROMPID == 0x330d)) ++ pHalData->CustomerID = RT_CID_DLINK; + break; + case EEPROM_CID_WHQL: + /* diff --git a/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0002-fix_310_proc2.patch b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0002-fix_310_proc2.patch new file mode 100644 index 000000000..40cb8e33e --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0002-fix_310_proc2.patch @@ -0,0 +1,29 @@ +--- a/os_dep/linux/os_intfs.c 2013-09-11 05:56:55.000000000 +0200 ++++ b/os_dep/linux/os_intfs.c 2013-11-12 00:30:41.158248277 +0100 +@@ -277,6 +277,18 @@ + + #define RTW_PROC_NAME DRV_NAME + ++#ifndef create_proc_entry ++/* dummy routines */ ++void rtw_proc_remove_one(struct net_device *dev) ++{ ++} ++ ++void rtw_proc_init_one(struct net_device *dev) ++{ ++} ++ ++#else /* create_proc_entry not defined */ ++ + void rtw_proc_init_one(struct net_device *dev) + { + struct proc_dir_entry *dir_dev = NULL; +@@ -751,6 +763,7 @@ + } + } + } ++#endif /* create_proc_entry not defined */ + #endif + + uint loadparam( _adapter *padapter, _nic_hdl pnetdev); diff --git a/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0101-gcc-4.9.patch b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0101-gcc-4.9.patch new file mode 100644 index 000000000..614bde4a1 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0101-gcc-4.9.patch @@ -0,0 +1,22 @@ +diff -Naur RTL8192CU-v4.0.2_9000.20130911/os_dep/linux/pci_intf.c RTL8192CU-v4.0.2_9000.20130911.patch/os_dep/linux/pci_intf.c +--- RTL8192CU-v4.0.2_9000.20130911/os_dep/linux/pci_intf.c 2013-09-11 05:56:55.000000000 +0200 ++++ RTL8192CU-v4.0.2_9000.20130911.patch/os_dep/linux/pci_intf.c 2014-04-22 23:25:02.082908033 +0200 +@@ -1963,7 +1963,6 @@ + + RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_entry\n")); + DBG_871X("rtw driver version=%s\n", DRIVERVERSION); +- DBG_871X("Build at: %s %s\n", __DATE__, __TIME__); + pci_drvpriv.drv_registered = _TRUE; + + rtw_suspend_lock_init(); +diff -Naur RTL8192CU-v4.0.2_9000.20130911/os_dep/linux/usb_intf.c RTL8192CU-v4.0.2_9000.20130911.patch/os_dep/linux/usb_intf.c +--- RTL8192CU-v4.0.2_9000.20130911/os_dep/linux/usb_intf.c 2013-09-11 05:56:55.000000000 +0200 ++++ RTL8192CU-v4.0.2_9000.20130911.patch/os_dep/linux/usb_intf.c 2014-04-22 23:25:21.337862827 +0200 +@@ -1577,7 +1577,6 @@ + RT_TRACE(_module_hci_intfs_c_,_drv_err_,("+rtw_drv_entry\n")); + + DBG_871X(DRV_NAME " driver version=%s\n", DRIVERVERSION); +- DBG_871X("build time: %s %s\n", __DATE__, __TIME__); + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)) + //console_suspend_enabled=0; diff --git a/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0102-gcc-5.patch b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0102-gcc-5.patch new file mode 100644 index 000000000..fba7307c5 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192CU/patches/RTL8192CU-0102-gcc-5.patch @@ -0,0 +1,25 @@ +diff -Naur RTL8192CU-v4.0.2_9000.20130911/include/ieee80211.h RTL8192CU-v4.0.2_9000.20130911.patch/include/ieee80211.h +--- RTL8192CU-v4.0.2_9000.20130911/include/ieee80211.h 2013-09-11 05:56:55.000000000 +0200 ++++ RTL8192CU-v4.0.2_9000.20130911.patch/include/ieee80211.h 2015-11-03 14:05:03.789280151 +0100 +@@ -1194,18 +1194,18 @@ + (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \ + (((Addr[5]) & 0xff) == 0xff)) + #else +-extern __inline int is_multicast_mac_addr(const u8 *addr) ++static __inline int is_multicast_mac_addr(const u8 *addr) + { + return ((addr[0] != 0xff) && (0x01 & addr[0])); + } + +-extern __inline int is_broadcast_mac_addr(const u8 *addr) ++static __inline int is_broadcast_mac_addr(const u8 *addr) + { + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + } + +-extern __inline int is_zero_mac_addr(const u8 *addr) ++static __inline int is_zero_mac_addr(const u8 *addr) + { + return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ + (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); diff --git a/packages/kernel/linux-drivers/RTL8192DU/package.mk b/packages/kernel/linux-drivers/RTL8192DU/package.mk new file mode 100644 index 000000000..1392852e6 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8192DU" +PKG_VERSION="72b53f8a6c2a6696d60791df4455c3073fffc4e4" +PKG_SHA256="dec3cc45601c2c6dab47816523cb5a5731393d34cc75ec0f96a91191d3563fdd" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lwfinger/rtl8192du" +PKG_URL="https://github.com/lwfinger/rtl8192du/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8192DU Linux 3.x driver" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0001-remove_overlapping_pids.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0001-remove_overlapping_pids.patch new file mode 100644 index 000000000..97a7bf70d --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0001-remove_overlapping_pids.patch @@ -0,0 +1,12 @@ +diff -Naur RTL8192DU-085e206/os_dep/usb_intf.c RTL8192DU-085e206.patch/os_dep/usb_intf.c +--- RTL8192DU-085e206/os_dep/usb_intf.c 2014-03-25 15:48:57.000000000 +0100 ++++ RTL8192DU-085e206.patch/os_dep/usb_intf.c 2014-04-11 09:23:12.097223906 +0200 +@@ -137,7 +137,7 @@ + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8194)},/* 8192DU-VS */ \ + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8111)},/* Realtek 5G dongle for WiFi Display */ \ + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0193)},/* 8192DE-VAU */ \ +- {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8171)},/* 8192DU-VC */ \ ++/* {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8171)}, 8192DU-VC overlaps with in-kernel rtl8192se */ \ + /*=== Customer ID ===*/ \ + /****** 8192DU-VC ********/ \ + {USB_DEVICE(0x2019, 0xAB2C)},/* PCI - Abocm */ \ diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0002-PR61.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0002-PR61.patch new file mode 100644 index 000000000..aeee5937a --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0002-PR61.patch @@ -0,0 +1,64 @@ +From d295ee29d71a7969047fbe5042cec471408632c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20Peron?= + <1859302+clementperon@users.noreply.github.com> +Date: Wed, 6 Jun 2018 17:40:54 +0200 +Subject: [PATCH] Change __vfs_read_alt to __vfs_read + +For kernel from 4.1 to 4.10 there is no call_read_iter used in new_sync_read. +Why create a new __vfs_read_alt whereas the __vfs_read is exported and seems to do exactly the same. + +Remove __vfs_read_alt code and it's dependencies and use the __vfs_read function instead +--- + os_dep/osdep_service.c | 32 +------------------------------- + 1 file changed, 1 insertion(+), 31 deletions(-) + +diff --git a/os_dep/osdep_service.c b/os_dep/osdep_service.c +index 286096a..9dd3d2b 100644 +--- a/os_dep/osdep_service.c ++++ b/os_dep/osdep_service.c +@@ -40,36 +40,6 @@ atomic_t _malloc_cnt = ATOMIC_INIT(0); + atomic_t _malloc_size = ATOMIC_INIT(0); + #endif /* DBG_MEMORY_LEAK */ + +- +-static ssize_t new_sync_read(struct file *filp, void __user *buf, __kernel_size_t len, loff_t *ppos) +-{ +- struct iovec iov; +- struct kiocb kiocb; +- struct iov_iter iter; +- ssize_t ret; +- +- iov.iov_base = buf; +- iov.iov_len = len; +- init_sync_kiocb(&kiocb, filp); +- kiocb.ki_pos = *ppos; +- iov_iter_init(&iter, READ, &iov, 1, len); +- +- ret = call_read_iter(filp, &kiocb, &iter); +- BUG_ON(ret == -EIOCBQUEUED); +- *ppos = kiocb.ki_pos; +- return ret; +-} +- +-static ssize_t __vfs_read_alt(struct file *file, char __user *buf, size_t count, +- loff_t *pos) +-{ +- if (file->f_op->read) +- return file->f_op->read(file, buf, count, pos); +- else if (file->f_op->read_iter) +- return new_sync_read(file, (void *)buf, (__kernel_size_t)count, pos); +- else +- return -EINVAL; +-} + /* + * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE + * @return: one of RTW_STATUS_CODE +@@ -1086,7 +1056,7 @@ static int readFile(struct file *fp,char *buf,int len) + + while(sum= KERNEL_VERSION(4, 1, 0)) +- rlen = __vfs_read_alt(fp, buf+sum, len-sum, &fp->f_pos); ++ rlen = __vfs_read(fp, buf+sum, len-sum, &fp->f_pos); + #else + rlen = fp->f_op->read(fp, buf+sum, len-sum, &fp->f_pos); + #endif diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0003-fix-vfs-read.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0003-fix-vfs-read.patch new file mode 100644 index 000000000..ecc26a678 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0003-fix-vfs-read.patch @@ -0,0 +1,27 @@ +From 9e477ff7fb1626f188e0d3314799371a5cce8681 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Wed, 13 Jun 2018 18:54:09 +0100 +Subject: [PATCH] fix vfs_read with 4.14.y+ + +--- + os_dep/osdep_service.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/os_dep/osdep_service.c b/os_dep/osdep_service.c +index 9dd3d2b..bd1df96 100644 +--- a/os_dep/osdep_service.c ++++ b/os_dep/osdep_service.c +@@ -1055,7 +1055,9 @@ static int readFile(struct file *fp,char *buf,int len) + return -EPERM; + + while(sum= KERNEL_VERSION(4, 1, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) ++ rlen = kernel_read(fp, buf+sum, len-sum, &fp->f_pos); ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + rlen = __vfs_read(fp, buf+sum, len-sum, &fp->f_pos); + #else + rlen = fp->f_op->read(fp, buf+sum, len-sum, &fp->f_pos); +-- +2.14.1 + diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0004-revert-fix-for-old-kernels.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0004-revert-fix-for-old-kernels.patch new file mode 100644 index 000000000..4f9414180 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/RTL8192DU-0004-revert-fix-for-old-kernels.patch @@ -0,0 +1,29 @@ +From ad504e6bd4df0210904a10d57ddc48670bc41675 Mon Sep 17 00:00:00 2001 +From: 5schatten +Date: Thu, 21 Mar 2019 22:26:31 +0100 +Subject: [PATCH] Revert "rtl8192du: Fix builds for kernels older than 4.11.0" + +This reverts commit 01722435acb1d62c9453b86161d2d8b99d702648. +--- + os_dep/osdep_service.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/os_dep/osdep_service.c b/os_dep/osdep_service.c +index 9efffc4..99a424f 100644 +--- a/os_dep/osdep_service.c ++++ b/os_dep/osdep_service.c +@@ -34,14 +34,6 @@ + + #define RT_TAG '1178' + +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) +-static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, +- struct iov_iter *iter) +-{ +- return file->f_op->read_iter(kio, iter); +-} +-#endif +- + #ifdef DBG_MEMORY_LEAK + #include + atomic_t _malloc_cnt = ATOMIC_INIT(0); diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0101-PR63.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0101-PR63.patch new file mode 100644 index 000000000..0cabd59f8 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0101-PR63.patch @@ -0,0 +1,25 @@ +From fb85a57a5cd6241cc8c066c5efc5b43781b0e42d Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Wed, 13 Jun 2018 06:43:10 +0100 +Subject: [PATCH] aarch64/4.4.y: implicit declaration of function + 'csum_ipv6_magic' + +--- + core/rtw_br_ext.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/core/rtw_br_ext.c b/core/rtw_br_ext.c +index da9c5e5..19af0fe 100644 +--- a/core/rtw_br_ext.c ++++ b/core/rtw_br_ext.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #endif + #endif + +-- +2.14.1 + diff --git a/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0102-fix-multiple-definitions.patch b/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0102-fix-multiple-definitions.patch new file mode 100644 index 000000000..04ca403f6 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192DU/patches/aarch64/RTL8192DU-0102-fix-multiple-definitions.patch @@ -0,0 +1,26 @@ +diff --git a/include/ieee80211.h b/include/ieee80211.h +index 3c28a0b..2268fbd 100644 +--- a/include/ieee80211.h ++++ b/include/ieee80211.h +@@ -969,18 +969,18 @@ enum ieee80211_state { + #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" + #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] + +-extern __inline int is_multicast_mac_addr(const u8 *addr) ++static __inline int is_multicast_mac_addr(const u8 *addr) + { + return ((addr[0] != 0xff) && (0x01 & addr[0])); + } + +-extern __inline int is_broadcast_mac_addr(const u8 *addr) ++static __inline int is_broadcast_mac_addr(const u8 *addr) + { + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + } + +-extern __inline int is_zero_mac_addr(const u8 *addr) ++static __inline int is_zero_mac_addr(const u8 *addr) + { + return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ + (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); diff --git a/packages/kernel/linux-drivers/RTL8192EU/package.mk b/packages/kernel/linux-drivers/RTL8192EU/package.mk new file mode 100644 index 000000000..37c0f7616 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192EU/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8192EU" +PKG_VERSION="0a7199b457b25edc4d9534158a068e486b1c8bb0" +PKG_SHA256="defee6fda236bc9d77cd5cf0ceca8e86f820a1f9fa5d63c5ca7c369be1a3513e" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Mange/rtl8192eu-linux-driver" +PKG_URL="https://github.com/Mange/rtl8192eu-linux-driver/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8192EU Linux 3.x driver" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n \ + USER_EXTRA_CFLAGS="-Wno-error=date-time" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8192EU/patches/RTL8192EU-0101-gcc-5.patch b/packages/kernel/linux-drivers/RTL8192EU/patches/RTL8192EU-0101-gcc-5.patch new file mode 100644 index 000000000..06b040858 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8192EU/patches/RTL8192EU-0101-gcc-5.patch @@ -0,0 +1,25 @@ +diff -Naur a/include/ieee80211.h b/include/ieee80211.h +--- a/include/ieee80211.h ++++ b/include/ieee80211.h +@@ -1314,18 +1314,18 @@ + (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \ + (((Addr[5]) & 0xff) == 0xff)) + #else +-extern __inline int is_multicast_mac_addr(const u8 *addr) ++static __inline int is_multicast_mac_addr(const u8 *addr) + { + return ((addr[0] != 0xff) && (0x01 & addr[0])); + } + +-extern __inline int is_broadcast_mac_addr(const u8 *addr) ++static __inline int is_broadcast_mac_addr(const u8 *addr) + { + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + } + +-extern __inline int is_zero_mac_addr(const u8 *addr) ++static __inline int is_zero_mac_addr(const u8 *addr) + { + return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ + (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); diff --git a/packages/kernel/linux-drivers/RTL8812AU/package.mk b/packages/kernel/linux-drivers/RTL8812AU/package.mk new file mode 100644 index 000000000..467f0d0ca --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8812AU/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8812AU" +PKG_VERSION="d88d8b2e2a1b33ebdd62b8a5de307b37c39d8477" +PKG_SHA256="c5b2fcc6cbf6901e63f75ece49a8ce3219004536cfc585b9815b34d943c9f311" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/MilhouseVH/RTL8812AU" +PKG_URL="https://github.com/MilhouseVH/RTL8812AU/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8812AU Linux 3.x driver" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8812AU/patches/aarch64/RTL8812AU-02-fix-multiple-definitions.patch b/packages/kernel/linux-drivers/RTL8812AU/patches/aarch64/RTL8812AU-02-fix-multiple-definitions.patch new file mode 100644 index 000000000..263a97057 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8812AU/patches/aarch64/RTL8812AU-02-fix-multiple-definitions.patch @@ -0,0 +1,38 @@ +From 92d01b516a77be6f21f6a3611c39f23e03fe4594 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 10 Jul 2017 20:11:37 +0100 +Subject: [PATCH] fix multiple definitions + +--- + include/ieee80211.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/ieee80211.h b/include/ieee80211.h +index 7a50a07..84aad12 100644 +--- a/include/ieee80211.h ++++ b/include/ieee80211.h +@@ -1481,18 +1481,18 @@ enum ieee80211_state { + (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \ + (((Addr[5]) & 0xff) == 0xff)) + #else +-extern __inline int is_multicast_mac_addr(const u8 *addr) ++static __inline int is_multicast_mac_addr(const u8 *addr) + { + return (addr[0] != 0xff) && (0x01 & addr[0]); + } + +-extern __inline int is_broadcast_mac_addr(const u8 *addr) ++static __inline int is_broadcast_mac_addr(const u8 *addr) + { + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + } + +-extern __inline int is_zero_mac_addr(const u8 *addr) ++static __inline int is_zero_mac_addr(const u8 *addr) + { + return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ + (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); +-- +2.7.4 + diff --git a/packages/kernel/linux-drivers/RTL8814AU/package.mk b/packages/kernel/linux-drivers/RTL8814AU/package.mk new file mode 100644 index 000000000..a3ed9b12e --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8814AU/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8814AU" +PKG_VERSION="a0c44795f06d846b656ebac3310ba8f80f41333d" +PKG_SHA256="b4da15f5160cf402d6b2d274cb8bc9c77ca4b533df63a76c9109fe97233cec03" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/tpircher/rtl8814AU" +PKG_URL="https://github.com/tpircher/rtl8814AU/archive/$PKG_VERSION.tar.gz" +PKG_SOURCE_DIR="rtl8814AU-$PKG_VERSION*" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_SECTION="driver" +PKG_SHORTDESC="Realtek RTL8814AU Linux drivers" +PKG_LONGDESC="Realtek RTL8814AU Linux drivers" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make V=1 \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/RTL8814AU/patches/RTL8814AU-01-fix-multiple-definitions.patch b/packages/kernel/linux-drivers/RTL8814AU/patches/RTL8814AU-01-fix-multiple-definitions.patch new file mode 100644 index 000000000..edb44e791 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8814AU/patches/RTL8814AU-01-fix-multiple-definitions.patch @@ -0,0 +1,38 @@ +From 9e81b6a530a4ec156a1d517fe543fc43e9dacfc5 Mon Sep 17 00:00:00 2001 +From: cdu13a +Date: Fri, 12 Oct 2018 21:15:23 -0400 +Subject: Fix Definitions + +--- + include/ieee80211.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/ieee80211.h b/include/ieee80211.h +index c374413..0743754 100644 +--- a/include/ieee80211.h ++++ b/include/ieee80211.h +@@ -1388,18 +1388,18 @@ enum ieee80211_state { + (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \ + (((Addr[5]) & 0xff) == 0xff)) + #else +-extern __inline int is_multicast_mac_addr(const u8 *addr) ++static __inline int is_multicast_mac_addr(const u8 *addr) + { + return ((addr[0] != 0xff) && (0x01 & addr[0])); + } + +-extern __inline int is_broadcast_mac_addr(const u8 *addr) ++static __inline int is_broadcast_mac_addr(const u8 *addr) + { + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + } + +-extern __inline int is_zero_mac_addr(const u8 *addr) ++static __inline int is_zero_mac_addr(const u8 *addr) + { + return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \ + (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00)); +-- +2.17.1 + diff --git a/packages/kernel/linux-drivers/RTL8821CU/package.mk b/packages/kernel/linux-drivers/RTL8821CU/package.mk new file mode 100644 index 000000000..9ab774983 --- /dev/null +++ b/packages/kernel/linux-drivers/RTL8821CU/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="RTL8821CU" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/smp79/rtl8821CU" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_SECTION="driver" +PKG_LONGDESC="Realtek RTL8821CU Linux driver" +PKG_IS_KERNEL_PKG="yes" + +case "$LINUX" in + amlogic-3.14) + PKG_VERSION="178fcbf4f1bf5b94580b5708016d0b2c2ded1720" + PKG_SHA256="29d3e053dd1fad37ee03de65e4ed2b25a4fb9aaf8bb6bd435da477753d03ad26" + PKG_URL="https://github.com/smp79/rtl8821CU/archive/$PKG_VERSION.tar.gz" + PKG_SOURCE_DIR="rtl8821CU-$PKG_VERSION*" + ;; + amlogic-4.9|odroid-go-a-4.4) + PKG_VERSION="f7910283478ac1b508ff163d30e4b374bf99f7cb" + PKG_SHA256="b2128cbc23ecf9b17bbbd9652a2453d73403276a56b11eb8a795d168156cd53e" + PKG_URL="https://github.com/smp79/rtl8821CU/archive/$PKG_VERSION.tar.gz" + PKG_SOURCE_DIR="rtl8821CU-$PKG_VERSION*" + ;; +esac + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_POWER_SAVING=n +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8152-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8152-aml/package.mk new file mode 100644 index 000000000..6fea089f8 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8152-aml/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="RTL8152-aml" +PKG_VERSION="cee2df544a6013a8efe4ed1493f594ca50b8d3c8" +PKG_SHA256="fadfebca469e2203e5aee1c727a7e3916f85a3a5f499c08fce0138bc67c1c92e" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/bb-qq/r8152" +PKG_URL="https://github.com/bb-qq/r8152/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8152/RTL8153/RTL8156 Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +make_target() { + LDFLAGS="" make -C $(kernel_path) M=$PKG_BUILD \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/package.mk new file mode 100644 index 000000000..a8ac047d2 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8188EU-aml" +PKG_VERSION="2d358c5" +PKG_SHA256="adf31d56d3a94bca814f1bd0de24af61fae85d25a259124b5d16c1d23cc72c91" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8188eu" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8188eu/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8188EU Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c +} + +make_target() { + LDFLAGS="" make -C $(kernel_path) M=$PKG_BUILD/rtl8xxx_EU \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/patches/RTL8188EU-aml-0001-Add-support-for-a-few-USB-dongles.patch b/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/patches/RTL8188EU-aml-0001-Add-support-for-a-few-USB-dongles.patch new file mode 100644 index 000000000..5a36dca7b --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8188EU-aml/patches/RTL8188EU-aml-0001-Add-support-for-a-few-USB-dongles.patch @@ -0,0 +1,29 @@ +From b67364bd4236f890238fb44df1bbba228b42ffe1 Mon Sep 17 00:00:00 2001 +From: kszaq +Date: Mon, 2 Oct 2017 11:13:42 +0200 +Subject: [PATCH] Add support for a few USB dongles + +--- + rtl8xxx_EU/os_dep/linux/usb_intf.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/rtl8xxx_EU/os_dep/linux/usb_intf.c b/rtl8xxx_EU/os_dep/linux/usb_intf.c +index 2fbffd6..4892838 100755 +--- a/rtl8xxx_EU/os_dep/linux/usb_intf.c ++++ b/rtl8xxx_EU/os_dep/linux/usb_intf.c +@@ -138,6 +138,12 @@ static struct usb_device_id rtw_usb_id_tbl[] = { + /*=== Customer ID ===*/ + /****** 8188EUS ********/ + {USB_DEVICE(0x07B8, 0x8179), .driver_info = RTL8188E}, /* Abocom - Abocom */ ++ {USB_DEVICE(0x0DF6, 0x0076), .driver_info = RTL8188E}, /* Sitecom N150 v2 */ ++ {USB_DEVICE(0x2001, 0x330F), .driver_info = RTL8188E}, /* DLink DWA-125 REV D1 */ ++ {USB_DEVICE(0x2001, 0x3310), .driver_info = RTL8188E}, /* Dlink DWA-123 REV D1 */ ++ {USB_DEVICE(0x2001, 0x3311), .driver_info = RTL8188E}, /* DLink GO-USB-N150 REV B1 */ ++ {USB_DEVICE(0x056E, 0x4008), .driver_info = RTL8188E}, /* Elecom WDC-150SU2M */ ++ {USB_DEVICE(0x2357, 0x010c), .driver_info = RTL8188E}, /* TP-Link TL-WN722N v2 */ + #endif + + #ifdef CONFIG_RTL8812A +-- +2.7.4 + diff --git a/packages/kernel/linux-drivers/amlogic/RTL8189ES-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8189ES-aml/package.mk new file mode 100644 index 000000000..89bbbc183 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8189ES-aml/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8189ES-aml" +PKG_VERSION="f971e4b" +PKG_SHA256="a87d891e3a42d70429b39f01216775dee95b0dc9093f9576ca7417e74f21ee2b" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8189es" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8189es/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8189ES Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl8189ES \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8189FS-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8189FS-aml/package.mk new file mode 100644 index 000000000..eb209ed44 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8189FS-aml/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="RTL8189FS-aml" +PKG_VERSION="11cdc07dd29ab4055ec76974e246708ae8457605" +PKG_SHA256="ea777e31551fb54446d9591d19c4ada0ce0ba9a6655e0e55c60693dafc4a9801" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8189ftv" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8189ftv/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8189FS Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl8189FS \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8723BS-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8723BS-aml/package.mk new file mode 100644 index 000000000..4bdab1beb --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8723BS-aml/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8723BS-aml" +PKG_VERSION="ee9d86a" +PKG_SHA256="4d1c5fe0d05edbf5eab96dfe5ff99b7d56c098f4d4d317351fa25e75606de094" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8723bs" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8723bs/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8723BS Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl8723BS \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8723DS-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8723DS-aml/package.mk new file mode 100644 index 000000000..eadb590ab --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8723DS-aml/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8723DS-aml" +PKG_VERSION="fb4adf7" +PKG_SHA256="00da0a7773286df38e8785be2891025e4fa6c4ff5ace9450e54cae85f143847e" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8723ds" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8723ds/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8723DS Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl8723DS \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8822BS-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8822BS-aml/package.mk new file mode 100644 index 000000000..8a64916b4 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8822BS-aml/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="RTL8822BS-aml" +PKG_VERSION="d2a5452a08084b3838083ba1eda3d1aeab82ee7c" +PKG_SHA256="31fafb5eb875de657c3316df1d72496958edfa16438248ec8f3661605f999ce1" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8822bs" +PKG_URL="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8822bs/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8822BU Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/*/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/*/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/*/core/rtw_ieee80211.c + sed -i 's/rtw_drv_log_level/0/g' $PKG_BUILD/rtl8822BS/core/*.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl8822BS \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} + diff --git a/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/package.mk new file mode 100644 index 000000000..247a05b3e --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="RTL8822BU-aml" +PKG_VERSION="b655ba8114d7def7e6181bfe4635fbb831e2b8d6" +PKG_SHA256="bbb6dab43a0e21654a7796ce07796677bbfda322d74b6a55dd08e3bde4953208" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_realtek_drivers_8822bu" +PKG_URL="https://github.com/cilynx/rtl88x2BU_WiFi_linux_v5.3.1_27678.20180430_COEX20180427-5959/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8822BU Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/core/rtw_ieee80211.c + sed -i 's/rtw_drv_log_level/0/g' $PKG_BUILD/core/*.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/patches/RTL8822BU-aml-01-add_device_ids.patch b/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/patches/RTL8822BU-aml-01-add_device_ids.patch new file mode 100644 index 000000000..818e8e33b --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8822BU-aml/patches/RTL8822BU-aml-01-add_device_ids.patch @@ -0,0 +1,26 @@ +From c50e4cbf3d593f6dc3636b5afe295af215b8890c Mon Sep 17 00:00:00 2001 +From: cdu13a +Date: Thu, 16 Jul 2020 03:53:40 -0400 +Subject: add more device id's + +--- + os_dep/linux/usb_intf.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/os_dep/linux/usb_intf.c b/os_dep/linux/usb_intf.c +index 0c6f3e4..8bba83d 100644 +--- a/os_dep/linux/usb_intf.c ++++ b/os_dep/linux/usb_intf.c +@@ -238,7 +238,8 @@ static struct usb_device_id rtw_usb_id_tbl[] = { + {USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* Alpha - Alpha*/ + {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* Dlink DWA-182*/ + {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* TP-Link Archer T4U V3 */ +- {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* TP-Link Archer T3U V1 */ ++ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* TP-Link Archer T3U V1 */ ++ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* TP-Link Archer T3U Plus */ + {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xB822, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* Edimax EW-7822ULC */ + {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xC822, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* Edimax EW-7822UTC */ + {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff), .driver_info = RTL8822B}, /* ASUS AC1300 USB-AC55 B1 */ +-- +2.17.1 + diff --git a/packages/kernel/linux-drivers/amlogic/RTL8822CS-aml/package.mk b/packages/kernel/linux-drivers/amlogic/RTL8822CS-aml/package.mk new file mode 100644 index 000000000..c279e4d05 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/RTL8822CS-aml/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="RTL8822CS-aml" +PKG_VERSION="4e31d08990bc2a84c937bf17d5be4b899ceb70ed" +PKG_SHA256="6df2e60689830f454111e2cd2c2873c05c9ac8e0f39e8eb1934dbcac62263900" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/CoreELEC/RTL8822CS-aml" +PKG_URL="https://github.com/CoreELEC/RTL8822CS-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL8822CS Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +post_unpack() { + sed -i 's/-DCONFIG_CONCURRENT_MODE//g; s/^CONFIG_POWER_SAVING.*$/CONFIG_POWER_SAVING = n/g; s/^CONFIG_RTW_DEBUG.*/CONFIG_RTW_DEBUG = n/g' $PKG_BUILD/rtl88x2CS/Makefile + sed -i 's/^#define CONFIG_DEBUG.*//g' $PKG_BUILD/rtl88x2CS/include/autoconf.h + sed -i 's/#define DEFAULT_RANDOM_MACADDR.*1/#define DEFAULT_RANDOM_MACADDR 0/g' $PKG_BUILD/rtl88x2CS/core/rtw_ieee80211.c + sed -i 's/rtw_drv_log_level/0/g' $PKG_BUILD/rtl88x2CS/core/*.c +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD/rtl88x2CS \ + ARCH=$TARGET_KERNEL_ARCH \ + KSRC=$(kernel_path) \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + USER_EXTRA_CFLAGS="-fgnu89-inline" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} + diff --git a/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd.conf b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd.conf new file mode 100644 index 000000000..3eac44b78 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd.conf @@ -0,0 +1 @@ +options dhd firmware_path=/usr/lib/firmware/brcm/ nvram_path=/usr/lib/firmware/brcm/ diff --git a/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd_sdio.conf b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd_sdio.conf new file mode 100644 index 000000000..3299adbd1 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/modprobe.d/dhd_sdio.conf @@ -0,0 +1 @@ +options dhd_sdio firmware_path=/usr/lib/firmware/brcm/ nvram_path=/usr/lib/firmware/brcm/ diff --git a/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/package.mk b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/package.mk new file mode 100644 index 000000000..801dac025 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/package.mk @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="ap6xxx-aml" +PKG_VERSION="ba2fbd0174b744521f4a25da796b9f62e9e4f7a7" +PKG_SHA256="60d9f755d2b4d2ae97ac09d92311d527718394e0c02af46b9cdcf30a0dc497b8" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/CoreELEC/ap6xxx-aml" +PKG_URL="https://github.com/CoreELEC/ap6xxx-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="ap6xxx: Linux drivers for AP6xxx WLAN chips used in some devices based on Amlogic SoCs" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + echo + echo "building ap6356s and others" + make -C $PKG_BUILD/bcmdhd.1.363.59.144.x.cn \ + PWD=$PKG_BUILD/bcmdhd.1.363.59.144.x.cn \ + KDIR=$(kernel_path) \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_BCMDHD_DISABLE_WOWLAN=y \ + clean dhd + + if [ "$PROJECT" = "Amlogic-ng" ]; then + echo + echo "building ap6275s" + make -C $PKG_BUILD/bcmdhd.100.10.315.x \ + PWD=$PKG_BUILD/bcmdhd.100.10.315.x \ + KDIR=$(kernel_path) \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + CONFIG_BCMDHD_DISABLE_WOWLAN=y \ + clean bcmdhd_sdio + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' \ + -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} + +post_install() { + if [ "$PROJECT" = "Amlogic" ]; then + rm $INSTALL/usr/lib/modprobe.d/dhd_sdio.conf + rm $INSTALL/usr/lib/udev/rules.d/80-dhd_sdio.rules + fi +} diff --git a/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/udev.d/80-dhd_sdio.rules b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/udev.d/80-dhd_sdio.rules new file mode 100644 index 000000000..fa38c12b5 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ap6xxx-aml/udev.d/80-dhd_sdio.rules @@ -0,0 +1,18 @@ +### Broadcom BCM43752 (AP6275S driver with dhd_sdio kernel module) +### by default kernel module dhd is loaded first and retries few +### times until dhd_sdio is loaded (after almost 2 minutes) +### to speed up load module manually +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:4497", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:4496", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:4495", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:A806", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:A804", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:AAE8", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:AAE7", GOTO="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", ENV{SDIO_ID}=="02D0:4362", GOTO="load_module" +GOTO="end" + +LABEL="load_module" +ENV{MODALIAS}=="?*", ENV{SUBSYSTEM}=="sdio", RUN{builtin}+="kmod load dhd_sdio" + +LABEL="end" diff --git a/packages/kernel/linux-drivers/amlogic/kvimfan-aml/package.mk b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/package.mk new file mode 100644 index 000000000..721d3beb4 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="kvimfan-aml" +PKG_VERSION="1.0" +PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Khadas VIM2 fan control service" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make -C "$(kernel_path)" M="$PKG_BUILD" + +} +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + +} +post_install() { + enable_service kvimfan.service +} diff --git a/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/Makefile b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/Makefile new file mode 100644 index 000000000..ea6f4bf8c --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/Makefile @@ -0,0 +1,2 @@ +obj-m := khadas-fan.o + diff --git a/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/khadas-fan.c b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/khadas-fan.c new file mode 100644 index 000000000..c431f2a89 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/sources/khadas-fan.c @@ -0,0 +1,360 @@ +/* + * gpio-fan.c - driver for fans controlled by GPIO. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KHADAS_FAN_TRIG_TEMP_LEVEL0 50 // 50 degree if not set +#define KHADAS_FAN_TRIG_TEMP_LEVEL1 60 // 60 degree if not set +#define KHADAS_FAN_TRIG_TEMP_LEVEL2 70 // 70 degree if not set +#define KHADAS_FAN_TRIG_MAXTEMP 80 +#define KHADAS_FAN_LOOP_SECS 30 * HZ // 30 seconds +#define KHADAS_FAN_LOOP_PULSE 2 // 20 msec +#define KHADAS_FAN_TEST_LOOP_SECS 5 * HZ // 5 seconds +#define KHADAS_FAN_LOOP_NODELAY_SECS 0 +#define KHADAS_FAN_GPIO_OFF 0 +#define KHADAS_FAN_GPIO_ON 1 + +enum khadas_fan_mode { + KHADAS_FAN_STATE_MANUAL = 0, + KHADAS_FAN_STATE_AUTO, +}; + +enum khadas_fan_level { + KHADAS_FAN_LEVEL_0 = 0, + KHADAS_FAN_LEVEL_1, + KHADAS_FAN_LEVEL_2, + KHADAS_FAN_LEVEL_3, +}; + +enum khadas_fan_enable { + KHADAS_FAN_DISABLE = 0, + KHADAS_FAN_ENABLE, +}; + +struct khadas_fan_data { + struct platform_device *pdev; + struct class *class; + struct delayed_work work; + struct delayed_work fan_test_work; + enum khadas_fan_enable enable; + enum khadas_fan_mode mode; + enum khadas_fan_level level; + int ctrl_gpio0; + int ctrl_gpio1; + int trig_temp_level0; + int trig_temp_level1; + int trig_temp_level2; + int last_level; + int temp; +}; + +struct khadas_fan_data *fan_data = NULL; + +void khadas_fan_level_set(struct khadas_fan_data *fan_data, int level ) +{ + if(3 == fan_data->last_level){ + gpio_set_value(fan_data->ctrl_gpio0, KHADAS_FAN_GPIO_ON); + gpio_set_value(fan_data->ctrl_gpio1, KHADAS_FAN_GPIO_OFF); + }else if(2 == fan_data->last_level){ + gpio_set_value(fan_data->ctrl_gpio0, KHADAS_FAN_GPIO_OFF); + gpio_set_value(fan_data->ctrl_gpio1, KHADAS_FAN_GPIO_ON); + }else if(1 == fan_data->last_level){ + gpio_set_value(fan_data->ctrl_gpio0, KHADAS_FAN_GPIO_ON); + gpio_set_value(fan_data->ctrl_gpio1, KHADAS_FAN_GPIO_ON); + }else{ + gpio_set_value(fan_data->ctrl_gpio0, KHADAS_FAN_GPIO_OFF); + gpio_set_value(fan_data->ctrl_gpio1, KHADAS_FAN_GPIO_OFF); + } + if (fan_data->last_level > 3 && level > 3) + fan_data->last_level--; + else + fan_data->last_level = level; +} + +extern int get_cpu_temp(void); +static void fan_work_func(struct work_struct *_work) +{ + struct khadas_fan_data *fan_data = container_of(_work, + struct khadas_fan_data, work.work); + + int temp, level =1; + + temp = get_cpu_temp(); + + if(temp < 0){ + schedule_delayed_work(&fan_data->work, KHADAS_FAN_LOOP_PULSE); + return; + } + + fan_data->temp = fan_data->temp ? (fan_data->temp + temp) / 2 : temp; + if (fan_data->temp < fan_data->trig_temp_level0) + level = 0; + else if (fan_data->temp < fan_data->trig_temp_level0 + 2) + level = 6; + else if (fan_data->temp < fan_data->trig_temp_level0 + 4) + level = 5; + else if (fan_data->temp < fan_data->trig_temp_level0 + 6) + level = 4; + else if (fan_data->temp < fan_data->trig_temp_level1) + level = 3; + else if (fan_data->temp < fan_data->trig_temp_level2) + level = 2; + + khadas_fan_level_set(fan_data, level); + + if (level > 3) + schedule_delayed_work(&fan_data->work, KHADAS_FAN_LOOP_PULSE); + else + schedule_delayed_work(&fan_data->work, KHADAS_FAN_LOOP_SECS); +} + +static void khadas_fan_set(struct khadas_fan_data *fan_data) +{ + + cancel_delayed_work(&fan_data->work); + + if (fan_data->enable == KHADAS_FAN_DISABLE) { + fan_data->last_level = 0; + khadas_fan_level_set(fan_data,0); + return; + } + switch (fan_data->mode) { + case KHADAS_FAN_STATE_MANUAL: + switch(fan_data->level){ + case KHADAS_FAN_LEVEL_1: + fan_data->last_level = 3; + khadas_fan_level_set(fan_data,3); + break; + case KHADAS_FAN_LEVEL_2: + fan_data->last_level = 2; + khadas_fan_level_set(fan_data,2); + break; + case KHADAS_FAN_LEVEL_3: + fan_data->last_level = 1; + khadas_fan_level_set(fan_data,1); + break; + default: + fan_data->last_level = 0; + khadas_fan_level_set(fan_data,0); + break; + } + break; + + case KHADAS_FAN_STATE_AUTO: + // FIXME: achieve with a better way + schedule_delayed_work(&fan_data->work, KHADAS_FAN_LOOP_PULSE); + break; + + default: + break; + } +} + +static ssize_t fan_enable_show(struct class *cls, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "Fan enable: %d\n", fan_data->enable); +} + +static ssize_t fan_enable_store(struct class *cls, struct class_attribute *attr, + const char *buf, size_t count) +{ + int enable; + + if (kstrtoint(buf, 0, &enable)) + return -EINVAL; + + // 0: manual, 1: auto + if( enable >= 0 && enable < 2 ){ + fan_data->enable = enable; + khadas_fan_set(fan_data); + } + + return count; +} + +static ssize_t fan_mode_show(struct class *cls, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "Fan mode: %d\n", fan_data->mode); +} + +static ssize_t fan_mode_store(struct class *cls, struct class_attribute *attr, + const char *buf, size_t count) +{ + int mode; + + if (kstrtoint(buf, 0, &mode)) + return -EINVAL; + + // 0: manual, 1: auto + if( mode >= 0 && mode < 2 ){ + fan_data->mode = mode; + khadas_fan_set(fan_data); + } + + return count; +} + +static ssize_t fan_level_show(struct class *cls, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "Fan level: %d\n", fan_data->level); +} + +static ssize_t fan_level_store(struct class *cls, struct class_attribute *attr, + const char *buf, size_t count) +{ + int level; + + if (kstrtoint(buf, 0, &level)) + return -EINVAL; + + if( level >= 0 && level < 4){ + fan_data->level = level; + fan_data->last_level = level; + khadas_fan_set(fan_data); + } + + return count; +} + + +static ssize_t fan_temp_show(struct class *cls, + struct class_attribute *attr, char *buf) +{ + int temp = -EINVAL; + temp = get_cpu_temp(); + + return sprintf(buf, "cpu_temp:%d \nFan trigger temperature: pulse-level:%d level0:%d level1:%d level2:%d\n", + temp, fan_data->trig_temp_level0, fan_data->trig_temp_level0 + 6, fan_data->trig_temp_level1, fan_data->trig_temp_level2); +} + +static struct class_attribute fan_class_attrs[] = { + __ATTR(enable, 0644, fan_enable_show, fan_enable_store), + __ATTR(mode, 0644, fan_mode_show, fan_mode_store), + __ATTR(level, 0644, fan_level_show, fan_level_store), + __ATTR(temp, 0444, fan_temp_show, NULL), +}; + +static int khadas_fan_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + int i; + + printk("khadas_fan_probe\n"); + + fan_data = devm_kzalloc(dev, sizeof(struct khadas_fan_data), GFP_KERNEL); + if (!fan_data) + return -ENOMEM; + + ret = of_property_read_u32(dev->of_node, "trig_temp_level0", &fan_data->trig_temp_level0); + if (ret < 0) + fan_data->trig_temp_level0 = KHADAS_FAN_TRIG_TEMP_LEVEL0; + ret = of_property_read_u32(dev->of_node, "trig_temp_level1", &fan_data->trig_temp_level1); + if (ret < 0) + fan_data->trig_temp_level1 = KHADAS_FAN_TRIG_TEMP_LEVEL1; + ret = of_property_read_u32(dev->of_node, "trig_temp_level2", &fan_data->trig_temp_level2); + if (ret < 0) + fan_data->trig_temp_level2 = KHADAS_FAN_TRIG_TEMP_LEVEL2; + + fan_data->ctrl_gpio0 = of_get_named_gpio(dev->of_node, "fan_ctl0", 0); + fan_data->ctrl_gpio1 = of_get_named_gpio(dev->of_node, "fan_ctl1", 0); + if ((gpio_request(fan_data->ctrl_gpio0, "FAN") != 0)|| (gpio_request(fan_data->ctrl_gpio1, "FAN") != 0)) + return -EIO; + + gpio_direction_output(fan_data->ctrl_gpio0, KHADAS_FAN_GPIO_OFF); + gpio_direction_output(fan_data->ctrl_gpio1, KHADAS_FAN_GPIO_OFF); + fan_data->mode = KHADAS_FAN_STATE_AUTO; + fan_data->level = KHADAS_FAN_LEVEL_0; + fan_data->enable = KHADAS_FAN_ENABLE; + fan_data->last_level = 0; + fan_data->temp = 0; + + INIT_DELAYED_WORK(&fan_data->work, fan_work_func); + khadas_fan_level_set(fan_data,0); + schedule_delayed_work(&fan_data->work, KHADAS_FAN_TEST_LOOP_SECS); + + fan_data->pdev = pdev; + platform_set_drvdata(pdev, fan_data); + + fan_data->class = class_create(THIS_MODULE, "fan"); + if (IS_ERR(fan_data->class)) { + return PTR_ERR(fan_data->class); + } + + for (i = 0; i < ARRAY_SIZE(fan_class_attrs); i++){ + ret = class_create_file(fan_data->class, &fan_class_attrs[i]); + if(0!=ret){ + printk("khadas_fan_probe,class_create_file%d failed \n", i); + } + } + dev_info(dev, "trigger temperature is level0:%d, level1:%d, level2:%d.\n", fan_data->trig_temp_level0, fan_data->trig_temp_level1, fan_data->trig_temp_level2); + return 0; +} + +static int khadas_fan_remove(struct platform_device *pdev) +{ + fan_data->enable = KHADAS_FAN_DISABLE; + khadas_fan_set(fan_data); + + return 0; +} + +static void khadas_fan_shutdown(struct platform_device *pdev) +{ + fan_data->enable = KHADAS_FAN_DISABLE; + khadas_fan_set(fan_data); +} + +#ifdef CONFIG_PM +static int khadas_fan_suspend(struct platform_device *pdev, pm_message_t state) +{ + cancel_delayed_work(&fan_data->work); + fan_data->last_level = 0; + khadas_fan_level_set(fan_data, 0); + return 0; +} + +static int khadas_fan_resume(struct platform_device *pdev) +{ + khadas_fan_set(fan_data); + return 0; +} +#endif + +static struct of_device_id of_khadas_fan_match[] = { + { .compatible = "fanctl", }, + {}, +}; + +static struct platform_driver khadas_fan_driver = { + .probe = khadas_fan_probe, +#ifdef CONFIG_PM + .suspend = khadas_fan_suspend, + .resume = khadas_fan_resume, +#endif + .remove = khadas_fan_remove, + .shutdown = khadas_fan_shutdown, + .driver = { + .name = "fanctl", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(of_khadas_fan_match), + }, +}; + +module_platform_driver(khadas_fan_driver); + +MODULE_AUTHOR("kenny "); +MODULE_DESCRIPTION("khadas GPIO Fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/packages/kernel/linux-drivers/amlogic/kvimfan-aml/system.d/kvimfan.service b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/system.d/kvimfan.service new file mode 100644 index 000000000..5f3514d76 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/kvimfan-aml/system.d/kvimfan.service @@ -0,0 +1,12 @@ +[Unit] +Description=Khadas VIM fan control module loader +ConditionPathExists=/proc/device-tree/fan/compatible +After=kernel-overlays.service + +[Service] +Type=oneshot +ExecStart=/bin/sh -c '[ `cat /proc/device-tree/fan/compatible` = "fanctl" ] && /sbin/modprobe khadas_fan' +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/packages/kernel/linux-drivers/amlogic/media_modules-aml/modules-load.d/media_modules.conf b/packages/kernel/linux-drivers/amlogic/media_modules-aml/modules-load.d/media_modules.conf new file mode 100644 index 000000000..37dd816c2 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/media_modules-aml/modules-load.d/media_modules.conf @@ -0,0 +1,17 @@ +amvdec_avs2 +amvdec_avs +amvdec_mavs +amvdec_h264 +amvdec_h264mvc +amvdec_h265 +amvdec_mh264 +amvdec_mjpeg +amvdec_mmjpeg +amvdec_mmpeg12 +amvdec_mmpeg4 +amvdec_mpeg12 +amvdec_mpeg4 +amvdec_ports +amvdec_real +amvdec_vc1 +amvdec_vp9 diff --git a/packages/kernel/linux-drivers/amlogic/media_modules-aml/package.mk b/packages/kernel/linux-drivers/amlogic/media_modules-aml/package.mk new file mode 100644 index 000000000..f3221c0b9 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/media_modules-aml/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="media_modules-aml" +PKG_VERSION="7d412c8b21023c1b7372c7206f5d09208147044f" +PKG_SHA256="d7b632cbd71dc651c188cc7827f6d30ea570e8bc0b2eacf9d8e6462190b490dc" +PKG_LICENSE="GPL" +PKG_SITE="https://coreelec.org" +PKG_URL="https://github.com/CoreELEC/media_modules-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="$PKG_NAME: Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/drivers \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H265=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VP9=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \ + CONFIG_AMLOGIC_MEDIA_VENC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VENC_H265=m +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/002-fix-building.patch b/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/002-fix-building.patch new file mode 100644 index 000000000..3758ddc01 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/002-fix-building.patch @@ -0,0 +1,100 @@ +diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c +index e7b85fb..6d1bdc2 100644 +--- a/drivers/amvdec_ports/aml_vcodec_vfm.c ++++ b/drivers/amvdec_ports/aml_vcodec_vfm.c +@@ -57,8 +57,6 @@ static void vdec_vf_put(struct vframe_s *vf, void *op_arg) + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + vfq_push(&vfm->vf_que_recycle, vf); + + /* schedule capture work. */ +@@ -100,7 +98,7 @@ void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id) + fb->m.mem[1].addr, fb->m.mem[1].size, + fb->m.mem[2].addr, fb->m.mem[2].size); + +- if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) ++ if (vfp && vf) + vf_put(vf, receiver); + } + +diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c +index 02848b8..6a3d076 100644 +--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c +@@ -593,8 +593,6 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_v4l2_buffe + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; +diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c +index 59ce85f..11a1d6f 100644 +--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c +@@ -407,8 +407,6 @@ static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffe + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; +diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c +index 8bc5faa..fda0b33 100644 +--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c +@@ -352,8 +352,6 @@ static void vdec_mjpeg_get_vf(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buf + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; +diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c +index cdde95b..ce76cec 100644 +--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c +@@ -344,8 +344,6 @@ static void vdec_mpeg12_get_vf(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_b + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; +diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c +index 7a40a4a..80a140b 100644 +--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c +@@ -353,8 +353,6 @@ static void vdec_mpeg4_get_vf(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buf + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; +diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c +index 5b3bbab..823426c 100644 +--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c ++++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c +@@ -397,8 +397,6 @@ static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer + return; + } + +- atomic_set(&vf->use_cnt, 1); +- + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; diff --git a/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/003-multi-decoders-limit-maximum-number-of-decoder.patch b/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/003-multi-decoders-limit-maximum-number-of-decoder.patch new file mode 100644 index 000000000..601a6e453 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/media_modules-aml/patches/003-multi-decoders-limit-maximum-number-of-decoder.patch @@ -0,0 +1,43 @@ +From b99d31bfbc2cc973355ab5541908f0ee820b24fa Mon Sep 17 00:00:00 2001 +From: Portisch +Date: Fri, 27 Dec 2019 20:11:58 +0100 +Subject: [PATCH] multi decoders: limit maximum number of decoder in parallel + to 1 Kodi can only handle one decoder (12/2019). Because of threading + issues in Kodi it is needed to limit the multi decoder instances to a + maximum of 1. If Kodi do implement multiple decoder support in parallel + this decoder limit needs to be reverted. + +--- + drivers/frame_provider/decoder/utils/vdec.h | 2 +- + drivers/frame_provider/decoder/utils/vdec_profile.c | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h +index 18d7cd1..56f044a 100644 +--- a/drivers/frame_provider/decoder/utils/vdec.h ++++ b/drivers/frame_provider/decoder/utils/vdec.h +@@ -45,7 +45,7 @@ struct device *get_vdec_device(void); + int vdec_module_init(void); + void vdec_module_exit(void); + +-#define MAX_INSTANCE_MUN 9 ++#define MAX_INSTANCE_MUN 1 + + #define VDEC_DEBUG_SUPPORT + +diff --git a/drivers/frame_provider/decoder/utils/vdec_profile.c b/drivers/frame_provider/decoder/utils/vdec_profile.c +index d00987a..55e5213 100644 +--- a/drivers/frame_provider/decoder/utils/vdec_profile.c ++++ b/drivers/frame_provider/decoder/utils/vdec_profile.c +@@ -42,8 +42,6 @@ static uint dec_time_stat_reset; + + struct dentry *root, *event; + +-#define MAX_INSTANCE_MUN 9 +- + struct vdec_profile_time_stat_s { + int time_6ms_less_cnt; + int time_6_9ms_cnt; +-- +2.17.1 + diff --git a/packages/kernel/linux-drivers/amlogic/mt7601u-aml/package.mk b/packages/kernel/linux-drivers/amlogic/mt7601u-aml/package.mk new file mode 100644 index 000000000..7e306f25e --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7601u-aml/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mt7601u-aml" +PKG_VERSION="4e61a61" +PKG_SHA256="814a63d8654f87a76cc06425ad2120daa32646f5220341a26296e4a6643b013a" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7601" +PKG_URL="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7601/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mt7601u Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make -C $(kernel_path) M=$PKG_BUILD \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/$(get_full_firmware_dir) + cp $PKG_BUILD/RT2870STA_7601.dat $INSTALL/$(get_full_firmware_dir) +} diff --git a/packages/kernel/linux-drivers/amlogic/mt7601u-aml/patches/mt7601u-aml-001-firmware-path.patch b/packages/kernel/linux-drivers/amlogic/mt7601u-aml/patches/mt7601u-aml-001-firmware-path.patch new file mode 100644 index 000000000..5df89a381 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7601u-aml/patches/mt7601u-aml-001-firmware-path.patch @@ -0,0 +1,13 @@ +diff --git a/include/os/rt_linux.h b/include/os/rt_linux.h +index 0303698..36dd603 100755 +--- a/include/os/rt_linux.h ++++ b/include/os/rt_linux.h +@@ -159,7 +159,7 @@ typedef struct usb_ctrlrequest devctrlrequest; + #ifdef ALLWINNER + #define STA_PROFILE_PATH "/system/vendor/modules/RT2870STA_7601.dat" + #else +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7601.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7601.dat" + #endif + #define STA_DRIVER_VERSION "JEDI.L0.MP1.mt7601u.v1.2" + #define DRIVER_ROLE "STA" diff --git a/packages/kernel/linux-drivers/amlogic/mt7603u-aml/package.mk b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/package.mk new file mode 100644 index 000000000..1cd4d4ffc --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mt7603u-aml" +PKG_VERSION="0c53dfb" +PKG_SHA256="9e3eab02f3c3dd7de373c5d631c2069771e6ad783ecda36a484030ab4ec0ccec" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7603" +PKG_URL="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7603/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mt7603u Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make LINUX_SRC=$(kernel_path) \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + RT28xx_DIR=$PKG_BUILD \ + -f $PKG_BUILD/Makefile +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/$(get_full_firmware_dir) + cp $PKG_BUILD/conf/MT7603USTA.dat $INSTALL/$(get_full_firmware_dir) +} diff --git a/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-001-firmware-path.patch b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-001-firmware-path.patch new file mode 100644 index 000000000..3cf74f011 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-001-firmware-path.patch @@ -0,0 +1,38 @@ +diff --git a/include/os/rt_linux.h b/include/os/rt_linux.h +index 9ddc4ea..258907a 100755 +--- a/include/os/rt_linux.h ++++ b/include/os/rt_linux.h +@@ -201,7 +201,7 @@ typedef struct usb_ctrlrequest devctrlrequest; + + #ifdef CONFIG_STA_SUPPORT + #ifdef RTMP_MAC_PCI +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7603.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7603.dat" + #define STA_DRIVER_VERSION "3.0.0.0" + #ifdef MULTIPLE_CARD_SUPPORT + #define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat" +@@ -210,12 +210,12 @@ typedef struct usb_ctrlrequest devctrlrequest; + + #ifdef RTMP_MAC_USB + #ifdef HE_BD_CFG80211_SUPPORT +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7603.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7603.dat" + #else + #ifdef USE_CHIP_DEPENDENT_PROFILE_NAME +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7603.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7603.dat" + #else +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7603.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7603.dat" + #endif /* USE_CHIP_DEPENDENT_PROFILE_NAME */ + #endif /* HE_BD_CFG80211_SUPPORT */ + #define STA_DRIVER_VERSION "JEDI.L0.MP1.mt7603u.v1.8" +@@ -227,7 +227,7 @@ typedef struct usb_ctrlrequest devctrlrequest; + + + #ifdef RTMP_MAC_SDIO +-#define STA_PROFILE_PATH "/system/etc/wifi/RT2870STA_7603.dat" ++#define STA_PROFILE_PATH "/lib/firmware/RT2870STA_7603.dat" + #define STA_DRIVER_VERSION "3.0.0.0" + #ifdef MULTIPLE_CARD_SUPPORT + #define CARD_INFO_PATH "/etc/Wireless/RT2870STA/RT2870STACard.dat" diff --git a/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-002-fix-building.patch b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-002-fix-building.patch new file mode 100644 index 000000000..7939d752f --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-002-fix-building.patch @@ -0,0 +1,13 @@ +diff --git a/Makefile b/Makefile +index 65d0a5c..7fc16f4 100755 +--- a/Makefile ++++ b/Makefile +@@ -234,7 +234,7 @@ endif + ifeq ($(PREALLOC), YES) + #build prealloc.ko + cp -f $(RT28xx_DIR)/os/linux/Makefile.6.prealloc $(RT28xx_DIR)/os/linux/Makefile +- $(MAKE) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules ++ $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules + endif + cp -f $(RT28xx_DIR)/os/linux/Makefile.6 $(RT28xx_DIR)/os/linux/Makefile + ifeq ($(PLATFORM),DM6446) diff --git a/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-003-fix-build-the-vpeter-way.patch b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-003-fix-build-the-vpeter-way.patch new file mode 100644 index 000000000..a8d0ce6f3 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7603u-aml/patches/mt7603u-aml-003-fix-build-the-vpeter-way.patch @@ -0,0 +1,67 @@ +diff --git a/Makefile b/Makefile +index 65d0a5c..9f665ba 100755 +--- a/Makefile ++++ b/Makefile +@@ -184,7 +184,7 @@ THREADX: + $(MAKE) -C $(RT28xx_DIR)/os/Threadx -f $(RT28xx_DIR)/os/ThreadX/Makefile + + LINUX: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + + ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile +@@ -330,7 +330,7 @@ endif + + uninstall: + ifeq ($(TARGET), LINUX) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 uninstall + else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 uninstall +@@ -339,7 +339,7 @@ endif + + install: + ifeq ($(TARGET), LINUX) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 install + else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 install +@@ -347,7 +347,7 @@ endif + endif + + libwapi: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.libwapi.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -357,7 +357,7 @@ endif + + osutil: + ifeq ($(OSABL),YES) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -371,7 +371,7 @@ endif + + osnet: + ifeq ($(OSABL),YES) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -384,7 +384,7 @@ endif + endif + + osdrv: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else diff --git a/packages/kernel/linux-drivers/amlogic/mt7610u-aml/package.mk b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/package.mk new file mode 100644 index 000000000..fb5023c58 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.tv) + +PKG_NAME="mt7610u-aml" +PKG_VERSION="c7a38f2bdde7a9e70f5d0753d4810f32dd1f6720" +PKG_SHA256="84bfa9aa8b56f7db4b43fac56a6b9e267bf8cb13f94aeff22d1aa38a7a965e86" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/osmc/mt7610u" +PKG_URL="https://github.com/osmc/mt7610u/archive/$PKG_VERSION.tar.gz" +PKG_SOURCE_DIR="mt7610u-$PKG_VERSION/mt7610u" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mt7610u Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make LINUX_SRC=$(kernel_path) \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + RT28xx_DIR=$PKG_BUILD \ + -f $PKG_BUILD/Makefile +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0001-fix-cross-compiling.patch b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0001-fix-cross-compiling.patch new file mode 100644 index 000000000..67283c205 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0001-fix-cross-compiling.patch @@ -0,0 +1,29 @@ +diff --git a/Makefile b/Makefile +index 38fcc3e..91a6aec 100644 +--- a/Makefile ++++ b/Makefile +@@ -24,7 +24,7 @@ OSABL = NO + + ifneq ($(TARGET),THREADX) + #RT28xx_DIR = home directory of RT28xx source code +-RT28xx_DIR = $(shell pwd) ++RT28xx_DIR ?= $(shell pwd) + endif + + include $(RT28xx_DIR)/os/linux/config.mk +@@ -196,11 +196,12 @@ endif + + ifeq ($(PLATFORM),PC) + # Linux 2.6 +-LINUX_SRC = /lib/modules/$(shell uname -r)/build ++LINUX_SRC ?= /lib/modules/$(shell uname -r)/build + # Linux 2.4 Change to your local setting + #LINUX_SRC = /usr/src/linux-2.4 +-LINUX_SRC_MODULE = /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless/ +-CROSS_COMPILE = ++LINUX_SRC_MODULE ?= /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless/ ++CROSS_COMPILE ?=aarch64-linux-gnu- ++ARCH ?=arm64 + endif + + ifeq ($(PLATFORM),INTELP6) diff --git a/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0002-support-more-cards.patch b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0002-support-more-cards.patch new file mode 100644 index 000000000..8762b3e62 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-0002-support-more-cards.patch @@ -0,0 +1,33 @@ +diff --git a/common/rtusb_dev_id.c b/common/rtusb_dev_id.c +index 1855e06..8146402 100644 +--- a/common/rtusb_dev_id.c ++++ b/common/rtusb_dev_id.c +@@ -36,7 +36,27 @@ + /* module table */ + USB_DEVICE_ID rtusb_dev_id[] = { + #ifdef MT76x0 +- {USB_DEVICE(0x0E8D,0x7610)}, /* MT7610U */ ++ { USB_DEVICE(0x148F, 0x7610) }, /* MT7610U */ ++ { USB_DEVICE(0x13B1, 0x003E) }, /* Linksys AE6000 */ ++ { USB_DEVICE(0x0E8D, 0x7610) }, /* Sabrent NTWLAC */ ++ { USB_DEVICE(0x7392, 0xa711) }, /* Edimax 7711mac */ ++ { USB_DEVICE(0x7392, 0xb711) }, /* Edimax / Elecom */ ++ { USB_DEVICE(0x148f, 0x761a) }, /* TP-Link TL-WDN5200 */ ++ { USB_DEVICE(0x148f, 0x760a) }, /* TP-Link unknown */ ++ { USB_DEVICE(0x0b05, 0x17d1) }, /* Asus USB-AC51 */ ++ { USB_DEVICE(0x0b05, 0x17db) }, /* Asus USB-AC50 */ ++ { USB_DEVICE(0x0df6, 0x0075) }, /* Sitecom WLA-3100 */ ++ { USB_DEVICE(0x2019, 0xab31) }, /* Planex GW-450D */ ++ { USB_DEVICE(0x2001, 0x3d02) }, /* D-LINK DWA-171 rev B1 */ ++ { USB_DEVICE(0x0586, 0x3425) }, /* Zyxel NWD6505 */ ++ { USB_DEVICE(0x07b8, 0x7610) }, /* AboCom AU7212 */ ++ { USB_DEVICE(0x04bb, 0x0951) }, /* I-O DATA WN-AC433UK */ ++ { USB_DEVICE(0x057c, 0x8502) }, /* AVM FRITZ!WLAN USB Stick AC 430 */ ++ { USB_DEVICE(0x293c, 0x5702) }, /* Comcast Xfinity KXW02AAA */ ++ { USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */ ++ { USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */ ++ { USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */ ++ { USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */ + #endif + { }/* Terminating entry */ + }; diff --git a/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-aml-003-fix-build-the-vpeter-way.patch b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-aml-003-fix-build-the-vpeter-way.patch new file mode 100644 index 000000000..b9b181798 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7610u-aml/patches/mt7610u-aml-003-fix-build-the-vpeter-way.patch @@ -0,0 +1,116 @@ +diff --git a/Makefile b/Makefile +index 38fcc3e..3836bb3 100644 +--- a/Makefile ++++ b/Makefile +@@ -340,7 +340,7 @@ THREADX: + $(MAKE) -C $(RT28xx_DIR)/os/Threadx -f $(RT28xx_DIR)/os/ThreadX/Makefile + + LINUX: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + + ifeq ($(OSABL),YES) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile +@@ -468,7 +468,7 @@ endif + + uninstall: + ifeq ($(TARGET), LINUX) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 uninstall + else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 uninstall +@@ -477,7 +477,7 @@ endif + + install: + ifeq ($(TARGET), LINUX) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 install + else + $(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 install +@@ -485,7 +485,7 @@ endif + endif + + libwapi: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.libwapi.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -495,7 +495,7 @@ endif + + osutil: + ifeq ($(OSABL),YES) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4.util $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -506,7 +506,7 @@ endif + + osnet: + ifeq ($(OSABL),YES) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4.netif $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +@@ -516,7 +516,7 @@ endif + endif + + osdrv: +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + cp -f os/linux/Makefile.4 $(RT28xx_DIR)/os/linux/Makefile + $(MAKE) -C $(RT28xx_DIR)/os/linux/ + else +diff --git a/os/linux/config.mk b/os/linux/config.mk +index 4ffdfd7..956fe85 100644 +--- a/os/linux/config.mk ++++ b/os/linux/config.mk +@@ -894,7 +894,7 @@ WFLAGS += -DRT_BIG_ENDIAN -DINF_TWINPASS + endif + + ifeq ($(PLATFORM),INF_DANUBE) +-ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ifneq (,) + # Linux 2.4 + WFLAGS += -DINF_DANUBE -DRT_BIG_ENDIAN + else +@@ -998,7 +998,7 @@ export CFLAGS + endif + + ifeq ($(PLATFORM),INF_DANUBE) +- ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ ifneq (,) + CFLAGS := $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic + else + CFLAGS := $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic +@@ -1032,7 +1032,7 @@ export CFLAGS + endif + + ifeq ($(PLATFORM),PC) +- ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ ifneq (,) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS +@@ -1098,7 +1098,7 @@ export CFLAGS + endif + + ifeq ($(PLATFORM),MT85XX) +- ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ ifneq (,) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS +@@ -1120,7 +1120,7 @@ ifeq ($(PLATFORM),MT85XX) + endif + + ifeq ($(PLATFORM),NXP_TV550) +- ifneq (,$(findstring 2.4,$(LINUX_SRC))) ++ ifneq (,) + # Linux 2.4 + CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=mips -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS) + export CFLAGS diff --git a/packages/kernel/linux-drivers/amlogic/mt7668-aml/package.mk b/packages/kernel/linux-drivers/amlogic/mt7668-aml/package.mk new file mode 100644 index 000000000..24eca0e6c --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/mt7668-aml/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.tv) + +PKG_NAME="mt7668-aml" +PKG_VERSION="fd76e10404b220c552fc7951f5a359b56d599e3b" +PKG_SHA256="1fb62a608b9ce8ba8157a8025ba0d76ad1d085510b27982e4af33575d2841308" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7668" +PKG_URL="https://github.com/khadas/android_hardware_wifi_mtk_drivers_mt7668/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mt7668 Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make EXTRA_CFLAGS="-w" \ + KERNELDIR=$(kernel_path) \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + -f $PKG_BUILD/Makefile +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/$(get_full_firmware_dir) + cp $PKG_BUILD/7668_firmware/* $INSTALL/$(get_full_firmware_dir) +} diff --git a/packages/kernel/linux-drivers/amlogic/qca9377-aml/package.mk b/packages/kernel/linux-drivers/amlogic/qca9377-aml/package.mk new file mode 100644 index 000000000..b0aa61511 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/qca9377-aml/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="qca9377-aml" +PKG_VERSION="311e24939b53d0cbaf303cde3ed1dc22349602a9" +PKG_SHA256="238e0174ec5ca3f87c184fade5eb7d1e4522d6af279aac6bd87f8bab24fc13ad" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://boundarydevices.com/new-silex-wifi-802-11ac-bt4-1-module/" +PKG_URL="https://github.com/boundarydevices/qcacld-2.0/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="qca9377 Linux Driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +PKG_PATCH_DIRS="$LINUX" + +post_unpack() { + sed -i 's,-Wall,,g; s,-Werror,,g' $PKG_BUILD/Kbuild + sed -i 's,CDEFINES :=,CDEFINES := -Wno-misleading-indentation -Wno-unused-variable -Wno-unused-function,g' $PKG_BUILD/Kbuild +} + +pre_make_target() { + unset LDFLAGS + unset CFLAGS +} + +make_target() { + make KERNEL_SRC="$(kernel_path)" \ + ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-3.14/qca9377-aml-001-Modify-SDIO-and-firmware-handling-to-support-chips-u.patch b/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-3.14/qca9377-aml-001-Modify-SDIO-and-firmware-handling-to-support-chips-u.patch new file mode 100644 index 000000000..87f428b59 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-3.14/qca9377-aml-001-Modify-SDIO-and-firmware-handling-to-support-chips-u.patch @@ -0,0 +1,538 @@ +From 7d4ee23fb20cc5e17d8d79db20a0d6704ac3df6c Mon Sep 17 00:00:00 2001 +From: kszaq +Date: Tue, 10 Jan 2017 22:43:12 +0100 +Subject: [PATCH] Modify SDIO and firmware handling to support chips used in + Amlogic devices + +--- + CORE/HDD/src/wlan_hdd_cfg.c | 10 +- + CORE/HDD/src/wlan_hdd_main.c | 180 ++++++++++++++++++++- + CORE/SERVICES/BMI/ol_fw.c | 8 +- + CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c | 6 - + .../sdio/linux/native_sdio/include/hif_internal.h | 2 +- + CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c | 62 +++---- + 6 files changed, 209 insertions(+), 59 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c +index 14524ef..439b18a 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg.c ++++ b/CORE/HDD/src/wlan_hdd_cfg.c +@@ -60,6 +60,8 @@ + #include + #include + ++extern int qca_request_firmware(const struct firmware **firmware_p, const char *name,struct device *device); ++ + static char *mac_param; + module_param_named(mac, mac_param, charp, S_IRUGO); + MODULE_PARM_DESC(mac, "mac address override"); +@@ -4411,11 +4413,11 @@ VOS_STATUS hdd_parse_config_ini(hdd_context_t* pHddCtx) + + memset(cfgIniTable, 0, sizeof(cfgIniTable)); + +- status = request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); ++ status = qca_request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); + + if(status) + { +- printk("%s: request_firmware failed %d",__func__, status); ++ printk("%s: qca_request_firmware failed %d",__func__, status); + vos_status = VOS_STATUS_E_FAILURE; + goto config_exit; + } +@@ -5104,11 +5106,11 @@ VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx) + } + + memset(macTable, 0, sizeof(macTable)); +- status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); ++ status = qca_request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + + if (status) + { +- hddLog(VOS_TRACE_LEVEL_WARN, "%s: request_firmware failed %d", ++ hddLog(VOS_TRACE_LEVEL_WARN, "%s: qca_request_firmware failed %d", + __func__, status); + vos_status = VOS_STATUS_E_FAILURE; + return vos_status; +diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c +index 00db789..7926902 100644 +--- a/CORE/HDD/src/wlan_hdd_main.c ++++ b/CORE/HDD/src/wlan_hdd_main.c +@@ -239,6 +239,163 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, + /* + * Android DRIVER command structures + */ ++//tkun add ++ typedef char A_CHAR; ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++ #define GET_INODE_FROM_FILEP(filp) \ ++ (filp)->f_path.dentry->d_inode ++ #else ++ #define GET_INODE_FROM_FILEP(filp) \ ++ (filp)->f_dentry->d_inode ++ #endif ++// #define A_MALLOC(size) kmalloc((size), GFP_KERNEL) ++ #define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) ++// #define A_FREE(addr) kfree(addr);addr=NULL; ++//#define A_MEMCPY(dst, src, len) memcpy((dst), (src), (len)) ++// #define A_MEMZERO(addr, len) memset((addr), 0, (len)) ++ #define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) ++ #define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++ ++ char qcafwpath[256] = "/lib/firmware"; ++ ++ int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *wbuf, size_t length) ++ { ++ int ret = 0; ++ struct file *filp = (struct file *)-ENOENT; ++ mm_segment_t oldfs; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ ++ // printk("%s: filename %s \n",__func__,filename); ++ do { ++ int mode = (wbuf) ? O_RDWR : O_RDONLY; ++ filp = filp_open(filename, mode, S_IRUSR); ++ if (IS_ERR(filp) || !filp->f_op) { ++ printk("%s: file %s filp_open error\n", __FUNCTION__, filename); ++ ret = -ENOENT; ++ break; ++ } ++ ++ if (length==0) { ++ /* Read the length of the file only */ ++ struct inode *inode; ++ ++ inode = GET_INODE_FROM_FILEP(filp); ++ if (!inode) { ++ // printk("%s: Get inode from %s failed\n", __FUNCTION__, filen ame); ++ ret = -ENOENT; ++ break; ++ } ++ ret = i_size_read(inode->i_mapping->host); ++ break; ++ } ++ ++ if (wbuf) { ++ if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) { ++// printk("%s: Write %u bytes to file %s error %d\n", __FUNCTION__, ++ // length, filename, ret); ++ break; ++ } ++ } else { ++ if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) { ++// printk ("%s: Read %u bytes from file %s error %d\n", __FUNCTION__, ++ // length, filename, ret); ++ break; ++ } ++ } ++ } while (0); ++ ++ if (!IS_ERR(filp)) { ++ filp_close(filp, NULL); ++ } ++ set_fs(oldfs); ++ ++ return ret; ++ } ++ ++ ++ int android_request_firmware(const struct firmware **firmware_p, const char *name,struct device *device) ++ { ++ int ret = 0; ++ struct firmware *firmware; ++ char filename[256]; ++ const char *raw_filename = name; ++ *firmware_p = firmware = A_MALLOC(sizeof(*firmware)); ++ if (!firmware) ++ return -ENOMEM; ++ A_MEMZERO(firmware, sizeof(*firmware)); ++ do { ++ size_t length, bufsize, bmisize; ++ ++ if (snprintf(filename, sizeof(filename), "%s/%s", qcafwpath, ++ raw_filename) >= sizeof(filename)) { ++ printk("snprintf: %s/%s\n", qcafwpath, raw_filename); ++ ret = -1; ++ break; ++ } ++ if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) { ++ break; ++ } else { ++ length = ret; ++ } ++ ++ if (strcmp(raw_filename, "softmac") == 0) { ++ bufsize = length = 17; ++ } else { ++ bufsize = ALIGN(length, PAGE_SIZE); ++ bmisize = A_ROUND_UP(length, 4); ++ bufsize = max(bmisize, bufsize); ++ } ++ firmware->data = vmalloc(bufsize); ++ firmware->size = length; ++ ++ // printk("AR6K: %s(): raw_filename=%s, bufsize=%d\n", __FUNCTION__, ra w_filename, bufsize); ++ ++ if (!firmware->data) { ++ printk("%s: Cannot allocate buffer for firmware\n", __FUNCTION__); ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) { ++// printk("%s: file read error, ret %d request %d\n", __FUNCTION__,ret,length); ++// ret = -1; ++ break; ++ } ++ ++ } while (0); ++ ++ if (ret<0) { ++ if (firmware) { ++ if (firmware->data) ++ vfree(firmware->data); ++ A_FREE(firmware); ++ } ++ *firmware_p = NULL; ++ } else { ++ ret = 0; ++ } ++ return ret; ++ } ++ ++ void android_release_firmware(const struct firmware *firmware) ++ { ++ if (firmware) { ++ if (firmware->data) ++ vfree(firmware->data); ++ kfree(firmware); ++ } ++ } ++extern int qca_request_firmware(const struct firmware **firmware_p,const char *name,struct device *device) ++ { ++ // int uevent = 1; ++ ++ //return _request_firmware(firmware_p, name, device, uevent, false); ++ ++ return android_request_firmware(firmware_p, name,device); ++ ++ ++ } + struct android_wifi_reassoc_params { + unsigned char bssid[18]; + int channel; +@@ -7801,7 +7958,7 @@ VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBuf + + ENTER(); + +- status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); ++ status = qca_request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + + if(status || !pHddCtx->fw || !pHddCtx->fw->data) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); +@@ -7842,7 +7999,7 @@ VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName, + + ENTER(); + +- status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); ++ status = qca_request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + + if(status || !pHddCtx->fw || !pHddCtx->fw->data) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); +@@ -12886,15 +13043,34 @@ static int hdd_driver_init( void) + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++extern int wifi_setup_dt(void); ++extern void wifi_teardown_dt(void); ++#endif ++extern void extern_wifi_set_enable(int is_on); ++extern void sdio_reinit(void); ++ + #ifdef MODULE + static int __init hdd_module_init ( void) + { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++ wifi_setup_dt(); ++#endif ++ extern_wifi_set_enable(0); ++ mdelay(200); ++ extern_wifi_set_enable(1); ++ mdelay(200); ++sdio_reinit(); ++ + return hdd_driver_init(); + } + #else /* #ifdef MODULE */ + static int __init hdd_module_init ( void) + { + /* Driver initialization is delayed to fwpath_changed_handler */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++wifi_teardown_dt(); ++#endif + return 0; + } + #endif /* #ifdef MODULE */ +diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c +index 466dbbc..95f1aee 100644 +--- a/CORE/SERVICES/BMI/ol_fw.c ++++ b/CORE/SERVICES/BMI/ol_fw.c +@@ -118,7 +118,7 @@ static int ol_get_fw_files_for_target(struct ol_fw_files *pfw_files, + return 0; + } + #endif +- ++extern int qca_request_firmware(const struct firmware **firmware_p, const char *name,struct device *device); + #ifdef HIF_USB + static A_STATUS ol_usb_extra_initialization(struct ol_softc *scn); + #endif +@@ -164,7 +164,7 @@ static int ol_transfer_single_bin_file(struct ol_softc *scn, + __func__)); + } + +- if (request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) ++ if (qca_request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Failed to get %s\n", +@@ -492,7 +492,7 @@ static int ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + break; + } + +- if (request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) ++ if (qca_request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) + { + printk("%s: Failed to get %s\n", __func__, filename); + +@@ -506,7 +506,7 @@ static int ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + filename = scn->fw_files.board_data; + printk("%s: Trying to load default %s\n", + __func__, filename); +- if (request_firmware(&fw_entry, filename, ++ if (qca_request_firmware(&fw_entry, filename, + scn->sc_osdev->device) != 0) { + printk("%s: Failed to get %s\n", + __func__, filename); +diff --git a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c +index c99020e..6bafed8 100644 +--- a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c ++++ b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c +@@ -234,12 +234,6 @@ ath_hif_sdio_remove(void *context, void *hif_handle) + { + ENTER(); + +- if (!sc) { +- VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, +- "Global SDIO context is NULL"); +- return A_ERROR; +- } +- + athdiag_procfs_remove(); + + #ifndef TARGET_DUMP_FOR_NON_QC_PLATFORM +diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h +index 382e38c..234bc09 100644 +--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h ++++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h +@@ -112,7 +112,7 @@ struct hif_device { + A_BOOL swap_mailbox; + }; + +-#define HIF_DMA_BUFFER_SIZE (4 * 1024) ++#define HIF_DMA_BUFFER_SIZE (56 * 1024) + #define CMD53_FIXED_ADDRESS 1 + #define CMD53_INCR_ADDRESS 2 + +diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c +index 1c54002..03401fd 100644 +--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c ++++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c +@@ -64,7 +64,8 @@ + ((request->request & HIF_WRITE)&& \ + (request->address >= 0x1000 && request->address < 0x1FFFF)) + #endif +-unsigned int mmcbusmode = 0; ++//unsigned int mmcbusmode = 0; ++unsigned int mmcbusmode = 5; + module_param(mmcbusmode, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + MODULE_PARM_DESC(mmcbusmode, "Set MMC driver Bus Mode: 1-SDR12, 2-SDR25, 3-SDR50, 4-DDR50, 5-SDR104"); + EXPORT_SYMBOL(mmcbusmode); +@@ -74,7 +75,9 @@ module_param(mmcbuswidth, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + MODULE_PARM_DESC(mmcbuswidth, "Set MMC driver Bus Width: 1-1Bit, 4-4Bit, 8-8Bit"); + EXPORT_SYMBOL(mmcbuswidth); + +-unsigned int mmcclock = 0; ++//unsigned int mmcclock = 0; ++//unsigned int mmcclock = 166666666; ++unsigned int mmcclock = 200000000; + module_param(mmcclock, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + MODULE_PARM_DESC(mmcclock, "Set MMC driver Clock value"); + EXPORT_SYMBOL(mmcclock); +@@ -95,7 +98,7 @@ unsigned int asyncintdelay = 2; + module_param(asyncintdelay, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + MODULE_PARM_DESC(asyncintdelay, "Delay clock count for aysnc interrupt, 2 is default, vaild values are 1 and 2"); + #else +-unsigned int asyncintdelay = 0; ++unsigned int asyncintdelay = 2; + module_param(asyncintdelay, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + MODULE_PARM_DESC(asyncintdelay, "Delay clock count for aysnc interrupt, 0 is default, vaild values are 1 and 2"); + #endif +@@ -412,12 +415,6 @@ __HIFReadWrite(HIF_DEVICE *device, + tbuffer = device->dma_buffer; + /* copy the write data to the dma buffer */ + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); +- if (length > HIF_DMA_BUFFER_SIZE) { +- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, +- ("AR6000: Invalid write length: %d\n", length)); +- status = A_EINVAL; +- break; +- } + memcpy(tbuffer, buffer, length); + bounced = TRUE; + } else { +@@ -440,12 +437,6 @@ __HIFReadWrite(HIF_DEVICE *device, + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer != NULL); + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); +- if (length > HIF_DMA_BUFFER_SIZE) { +- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, +- ("AR6000: Invalid read length: %d\n", length)); +- status = A_EINVAL; +- break; +- } + tbuffer = device->dma_buffer; + bounced = TRUE; + } else { +@@ -695,7 +686,7 @@ static int async_task(void *param) + complete_and_exit(&device->async_completion, 0); + return 0; + } +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) ++#if 1 + static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp) + { + struct mmc_command cmd; +@@ -719,6 +710,7 @@ static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, + return err; + } + #endif ++//extern int sdio_reset_comm(struct mmc_card *card); + A_STATUS ReinitSDIO(HIF_DEVICE *device) + { + A_INT32 err = 0; +@@ -733,10 +725,12 @@ A_STATUS ReinitSDIO(HIF_DEVICE *device) + host = card->host; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n")); ++ ++// err = sdio_reset_comm(card); ++#if 1 + sdio_claim_host(func); + + do { +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + /* 2.6.32 kernel does part of the SDIO initalization upon resume */ + A_BOOL lt_2_6_32 = (LINUX_VERSION_CODEocr) { +- /* Issue CMD5, arg = 0 */ +- err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); +- if (err) { +- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); +- break; +- } +- host->ocr = resp; +- } + + /* Issue CMD5, arg = ocr. Wait till card is ready */ + for (i=0;i<100;i++) { +- err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); ++ err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); + break; +@@ -828,7 +813,7 @@ A_STATUS ReinitSDIO(HIF_DEVICE *device) + break; + } + } +-#endif ++ + /* Enable high speed */ + if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n")); +@@ -891,7 +876,7 @@ A_STATUS ReinitSDIO(HIF_DEVICE *device) + + sdio_release_host(func); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n")); +- ++#endif + return (err) ? A_ERROR : A_OK; + } + +@@ -1320,6 +1305,7 @@ static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id + /* + TODO: MMC SDIO3.0 Setting should also be modified in ReInit() function when Power Manage work. + */ ++#if 1 + { + A_UINT32 clock, clock_set = 12500000; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) +@@ -1576,7 +1562,7 @@ TODO: MMC SDIO3.0 Setting should also be modified in ReInit() function when Powe + + sdio_release_host(func); + } +- ++#endif + spin_lock_init(&device->lock); + + spin_lock_init(&device->asynclock); +@@ -2068,12 +2054,10 @@ static int hifDeviceSuspend(struct device *dev) + return -1; + } + } else { +- if (wma_suspend_target(temp_module, 0)) { +- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("PDEV Suspend Failed\n")); +- return -1; +- } ++ if (wma_suspend_target(temp_module, 0)) { ++ printk(KERN_ERR "wma_suspend_target failed.\n"); ++ } + } +- + if (pm_flag & MMC_PM_WAKE_SDIO_IRQ){ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: wow enter\n")); + config = HIF_DEVICE_POWER_DOWN; +@@ -2293,9 +2277,7 @@ static HIF_DEVICE * + addHifDevice(struct sdio_func *func) + { + HIF_DEVICE *hifdevice = NULL; +-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && !defined(WITH_BACKPORTS) + int ret = 0; +-#endif + ENTER(); + AR_DEBUG_ASSERT(func != NULL); + hifdevice = (HIF_DEVICE *)A_MALLOC(sizeof(HIF_DEVICE)); +@@ -2308,13 +2290,9 @@ addHifDevice(struct sdio_func *func) + hifdevice->func = func; + hifdevice->powerConfig = HIF_DEVICE_POWER_UP; + hifdevice->DeviceState = HIF_DEVICE_STATE_ON; +-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && !defined(WITH_BACKPORTS) + ret = sdio_set_drvdata(func, hifdevice); ++ + EXIT("status %d", ret); +-#else +- sdio_set_drvdata(func, hifdevice); +- EXIT(); +-#endif + return hifdevice; + } + +-- +2.7.4 + diff --git a/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-4.9/qca9377-aml-001-fix-amlogic-4.9-compatibility.patch b/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-4.9/qca9377-aml-001-fix-amlogic-4.9-compatibility.patch new file mode 100644 index 000000000..af7ad41d0 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/qca9377-aml/patches/amlogic-4.9/qca9377-aml-001-fix-amlogic-4.9-compatibility.patch @@ -0,0 +1,42 @@ +From 3b0a139cea3a9b45db94923d4acba93b0267fc25 Mon Sep 17 00:00:00 2001 +From: Arthur Liberman +Date: Fri, 17 Jul 2020 19:09:18 +0300 +Subject: [PATCH] Fix build on Amlogic's 4.9 kernel + +--- + CORE/HDD/src/wlan_hdd_main.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c +index 00db78995..2afe68e23 100644 +--- a/CORE/HDD/src/wlan_hdd_main.c ++++ b/CORE/HDD/src/wlan_hdd_main.c +@@ -13015,9 +13015,15 @@ static void __exit hdd_module_exit(void) + hdd_driver_exit(); + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) ++#define KERNEL_PARAM const struct kernel_param ++#else ++#define KERNEL_PARAM struct kernel_param ++#endif ++ + #ifdef MODULE + static int fwpath_changed_handler(const char *kmessage, +- struct kernel_param *kp) ++ KERNEL_PARAM *kp) + { + return param_set_copystring(kmessage, kp); + } +@@ -13072,7 +13078,7 @@ static int kickstart_driver(void) + + --------------------------------------------------------------------------*/ + static int fwpath_changed_handler(const char *kmessage, +- struct kernel_param *kp) ++ KERNEL_PARAM *kp) + { + int ret; + +-- +2.20.1 + diff --git a/packages/kernel/linux-drivers/amlogic/qca9377-aml/udev.d/99-qca9377-wireless.rules b/packages/kernel/linux-drivers/amlogic/qca9377-aml/udev.d/99-qca9377-wireless.rules new file mode 100644 index 000000000..3515891f5 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/qca9377-aml/udev.d/99-qca9377-wireless.rules @@ -0,0 +1 @@ +ACTION=="add|change", SUBSYSTEM=="net", ENV{INTERFACE}=="wlan*", ATTRS{vendor}=="0x0271", RUN+="/usr/bin/systemctl restart connman.service" diff --git a/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/package.mk b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/package.mk new file mode 100644 index 000000000..c150e464c --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ssv6xxx-aml-3.14" +PKG_VERSION="1041e7d" +PKG_SHA256="1d96db8eec06c8a2c43f2c8024cc573e2bbce08fb0504fd9b6671224335e7d5f" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="http://libreelec.tv" +PKG_URL="https://sources.libreelec.tv/devel/ssv6xxx-aml-1041e7d.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="ssv6xxx Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + sed -i 's,hw_cap_p2p = on,hw_cap_p2p = off,g' firmware/ssv6051-wifi.cfg +} + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + if [ "$TARGET_KERNEL_ARCH" = "arm64" ]; then + PLATFORM="aml-s905" + else + PLATFORM="aml-s805" + fi + + cd $PKG_BUILD + ./ver_info.pl include/ssv_version.h + cp Makefile.android Makefile + sed -i 's,PLATFORMS =,PLATFORMS = '"$PLATFORM"',g' Makefile + make module SSV_ARCH="$TARGET_KERNEL_ARCH" \ + SSV_CROSS="$TARGET_KERNEL_PREFIX" \ + SSV_KERNEL_PATH="$(kernel_path)" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/$(get_full_firmware_dir)/ssv6051 + cp $PKG_BUILD/firmware/* $INSTALL/$(get_full_firmware_dir)/ssv6051 +} diff --git a/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/patches/ssv6xxx-aml-3.14-001-fix-build-and-firmware-path.patch b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/patches/ssv6xxx-aml-3.14-001-fix-build-and-firmware-path.patch new file mode 100644 index 000000000..c0f46fa1c --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml-3.14/patches/ssv6xxx-aml-3.14-001-fix-build-and-firmware-path.patch @@ -0,0 +1,86 @@ +diff --git a/Makefile.android b/Makefile.android +index 82211e1..0deeee5 100755 +--- a/Makefile.android ++++ b/Makefile.android +@@ -2,10 +2,8 @@ PLATFORMS = + + KBUILD_TOP := $(PWD) + +-SSV_PATH=$(ANDROID_BUILD_TOP)/hardware/wifi/icomm/ssv6xxx/ssv6051/ +- +-include $(SSV_PATH)/ssv6051.cfg +-include $(SSV_PATH)/platform-config.mak ++include ${KBUILD_TOP}/ssv6051.cfg ++include ${KBUILD_TOP}/platform-config.mak + + PWD := $(shell pwd) + +@@ -69,7 +67,7 @@ obj-$(CONFIG_SSV6200_CORE) += $(KMODULE_NAME).o + all:module strip + + module: +- make -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ ++ $(MAKE) -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" M=$(PWD) modules + + install: +@@ -92,6 +90,6 @@ ifneq ($(SSV_STRIP),) + endif + + clean: +- make -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ ++ $(MAKE) -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ + M=$(PWD) clean + rm $(DEF_PARSER_H) +diff --git a/firmware/ssv6051-wifi.cfg b/firmware/ssv6051-wifi.cfg +index 6c3a823..9c623a0 100755 +--- a/firmware/ssv6051-wifi.cfg ++++ b/firmware/ssv6051-wifi.cfg +@@ -11,7 +11,7 @@ + # Priority.3 default firmware + ################################################## + +-firmware_path = /system/etc/wifi/ssv6051/ ++firmware_path = /usr/lib/firmware/ssv6051/ + + ############################################################ + # MAC address + +diff --git a/platform-config.mak b/platform-config.mak +index bf35b70..f02e2b5 100755 +--- a/platform-config.mak ++++ b/platform-config.mak +@@ -5,7 +5,7 @@ CONFIG_SSV6200_CORE=m + ########################################################################### + # Compiler options # + ########################################################################### +-ccflags-y += -Werror ++# ccflags-y += -Werror + + # Enable -g to help debug. Deassembly from .o to .S would help to track to + # the problomatic line from call stack dump. +diff --git a/ssv6051.cfg b/ssv6051.cfg +index 7cf12c2..a6960fa 100755 +--- a/ssv6051.cfg ++++ b/ssv6051.cfg +@@ -16,6 +16,6 @@ ccflags-y += -DCONFIG_SSV_RSSI + #SSV_CROSS = $(ANDROID_BUILD_TOP)/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- + #SSV_KERNEL_PATH = $(ANDROID_BUILD_TOP)/out/target/product/p201/obj/KERNEL_OBJ/ + +-SSV_ARCH = arm64 ++#SSV_ARCH = arm64 + #KMODDESTDIR = $(MODDESTDIR) + +diff --git a/ssvdevice/ssvdevice.c b/ssvdevice/ssvdevice.c +index ff4305e..375827f 100755 +--- a/ssvdevice/ssvdevice.c ++++ b/ssvdevice/ssvdevice.c +@@ -35,7 +35,7 @@ + MODULE_AUTHOR("iComm Semiconductor Co., Ltd"); + MODULE_DESCRIPTION("Shared library for SSV wireless LAN cards."); + MODULE_LICENSE("Dual BSD/GPL"); +-static char *stacfgpath = NULL; ++static char *stacfgpath = "/usr/lib/firmware/ssv6051/ssv6051-wifi.cfg"; + EXPORT_SYMBOL(stacfgpath); + module_param(stacfgpath, charp, 0000); + MODULE_PARM_DESC(stacfgpath, "Get path of sta cfg"); diff --git a/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/package.mk b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/package.mk new file mode 100644 index 000000000..842f412b7 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/package.mk @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ssv6xxx-aml" +PKG_VERSION="d1708e72e7e69ed2b29aa7a48d05be76544c8f1d" +PKG_SHA256="4d8ec5677bd7e61c0ec87deef723433f4c5da927de1df4c4d37fed1507303846" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/khadas/android_hardware_wifi_icomm_drivers_ssv6xxx/" +PKG_URL="https://github.com/khadas/android_hardware_wifi_icomm_drivers_ssv6xxx/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="ssv6xxx Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + if [ "$TARGET_KERNEL_ARCH" = "arm64" ]; then + PLATFORM="aml-s905" + else + PLATFORM="aml-s805" + fi + + cd $PKG_BUILD/ssv6051 + ./ver_info.pl include/ssv_version.h + cp Makefile.android Makefile + sed -i 's,PLATFORMS =,PLATFORMS = '"$PLATFORM"',g' Makefile + make module SSV_ARCH="$TARGET_KERNEL_ARCH" \ + SSV_CROSS="$TARGET_KERNEL_PREFIX" \ + SSV_KERNEL_PATH="$(kernel_path)" +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ssv6051/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/$(get_full_firmware_dir)/ssv6051 + cp -r $PKG_BUILD/ssv6051/image/* $INSTALL/$(get_full_firmware_dir)/ssv6051 +} diff --git a/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/patches/ssv6xxx-aml-001-fix-build-and-firmware-path.patch b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/patches/ssv6xxx-aml-001-fix-build-and-firmware-path.patch new file mode 100644 index 000000000..d039ed529 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/ssv6xxx-aml/patches/ssv6xxx-aml-001-fix-build-and-firmware-path.patch @@ -0,0 +1,134 @@ +diff --git a/ssv6051/Makefile.android b/ssv6051/Makefile.android +index 43c268e..3f2fd8d 100755 +--- a/ssv6051/Makefile.android ++++ b/ssv6051/Makefile.android +@@ -1,8 +1,8 @@ + PLATFORMS = + + KBUILD_TOP := $(PWD) +-include $(KBUILD_TOP)/platforms/$(PLATFORMS).cfg +-include $(KBUILD_TOP)/platforms/platform-config.mak ++include $(KBUILD_TOP)/ssv6051.cfg ++include $(KBUILD_TOP)/platform-config.mak + + PWD := $(shell pwd) + +@@ -57,7 +57,7 @@ KERN_SRCS_S += crypto/sha1-armv4-large.S + endif + + +-KERN_SRCS += platforms/$(PLATFORMS)-generic-wlan.c ++KERN_SRCS += ssv6051-generic-wlan.c + + $(KMODULE_NAME)-y += $(KERN_SRCS_S:.S=.o) + $(KMODULE_NAME)-y += $(KERN_SRCS:.c=.o) +@@ -67,7 +67,7 @@ obj-$(CONFIG_SSV6200_CORE) += $(KMODULE_NAME).o + all:module strip + + module: +- make -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ ++ $(MAKE) -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" M=$(PWD) modules + + install: +@@ -80,7 +80,7 @@ strip: + #cp eagle.ko $(KO_NAME).ko + #cp $(KO_NAME).ko $(DEFAULT_MODULES_DIR) + #cp ssv6200.ko $(DEFAULT_MODULES_DIR) +- cp platforms/$(PLATFORMS)-wifi.cfg image/$(KMODULE_NAME)-wifi.cfg ++ #cp platforms/$(PLATFORMS)-wifi.cfg image/$(KMODULE_NAME)-wifi.cfg + cp $(KMODULE_NAME).ko image/$(KMODULE_NAME).ko + cp platforms/cli image + ifneq ($(SSV_STRIP),) +@@ -90,6 +90,6 @@ ifneq ($(SSV_STRIP),) + endif + + clean: +- make -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ ++ $(MAKE) -C $(SSV_KERNEL_PATH) ARCH=$(SSV_ARCH) CROSS_COMPILE=$(SSV_CROSS) \ + M=$(PWD) clean + +diff --git a/ssv6051/hci/ssv_hci.c b/ssv6051/hci/ssv_hci.c +index f0714ab..07be1c4 100755 +--- a/ssv6051/hci/ssv_hci.c ++++ b/ssv6051/hci/ssv_hci.c +@@ -21,7 +21,9 @@ + #include + #include + #include "hctrl.h" ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)) + extern void sdio_clk_always_on(void); ++#endif + MODULE_AUTHOR("iComm Semiconductor Co., Ltd"); + MODULE_DESCRIPTION("HCI driver for SSV6xxx 802.11n wireless LAN cards."); + MODULE_SUPPORTED_DEVICE("SSV6xxx WLAN cards"); +@@ -1112,7 +1114,9 @@ static int __init ssv6xxx_hci_init(void) + #ifdef CONFIG_SSV6200_CLI_ENABLE + extern struct ssv6xxx_hci_ctrl *ssv_dbg_ctrl_hci; + #endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)) + sdio_clk_always_on(); ++#endif + ctrl_hci = kzalloc(sizeof(*ctrl_hci), GFP_KERNEL); + if (ctrl_hci == NULL) + return -ENOMEM; +diff --git a/ssv6051/image/ssv6051-wifi.cfg b/ssv6051/image/ssv6051-wifi.cfg +index 46429fc..732d0fb 100755 +--- a/ssv6051/image/ssv6051-wifi.cfg ++++ b/ssv6051/image/ssv6051-wifi.cfg +@@ -9,7 +9,7 @@ + # Priority.2 firmware_path + # Priority.3 default firmware + ################################################## +-firmware_path = /vendor/etc/wifi/ssv6051/ ++firmware_path = /usr/lib/firmware/ssv6051/ + #flash_bin_path = /tmp/flash.bin + + ############################################################ +@@ -68,7 +68,7 @@ hw_cap_security = on + hw_cap_sgi_20 = on + hw_cap_sgi_40 = off + hw_cap_ap = on +-hw_cap_p2p = on ++hw_cap_p2p = off + hw_cap_ampdu_rx = on + hw_cap_ampdu_tx = on + use_wpa2_only = 1 +diff --git a/ssv6051/platform-config.mak b/ssv6051/platform-config.mak +index 5c37b23..8b74de6 100755 +--- a/ssv6051/platform-config.mak ++++ b/ssv6051/platform-config.mak +@@ -5,7 +5,7 @@ CONFIG_SSV6200_CORE=m + ########################################################################### + # Compiler options # + ########################################################################### +-ccflags-y += -Werror ++# ccflags-y += -Werror + + # Enable -g to help debug. Deassembly from .o to .S would help to track to + # the problomatic line from call stack dump. +diff --git a/ssv6051/ssv6051.cfg b/ssv6051/ssv6051.cfg +index 3aa643b..9676fec 100755 +--- a/ssv6051/ssv6051.cfg ++++ b/ssv6051/ssv6051.cfg +@@ -21,6 +21,6 @@ ccflags-y += -DAML_WIFI_MAC + #SSV_KERNEL_PATH = $(ANDROID_BUILD_TOP)/out/target/product/m201/obj/KERNEL_OBJ/ + #SSV_CROSS = $(ANDROID_BUILD_TOP)/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi- + #SSV_KERNEL_PATH = $(ANDROID_BUILD_TOP)/hardware/wifi/icomm/drivers/ssv6xxx/ +-SSV_ARCH = arm64 ++#SSV_ARCH = arm64 + #KMODDESTDIR = $(MODDESTDIR) + +diff --git a/ssv6051/ssvdevice/ssvdevice.c b/ssv6051/ssvdevice/ssvdevice.c +index 2e384bc..a520d4e 100755 +--- a/ssv6051/ssvdevice/ssvdevice.c ++++ b/ssv6051/ssvdevice/ssvdevice.c +@@ -36,7 +36,7 @@ + MODULE_AUTHOR("iComm Semiconductor Co., Ltd"); + MODULE_DESCRIPTION("Shared library for SSV wireless LAN cards."); + MODULE_LICENSE("Dual BSD/GPL"); +-static char *stacfgpath = NULL; ++static char *stacfgpath = "/usr/lib/firmware/ssv6051/ssv6051-wifi.cfg"; + EXPORT_SYMBOL(stacfgpath); + module_param(stacfgpath, charp, 0000); + MODULE_PARM_DESC(stacfgpath, "Get path of sta cfg"); diff --git a/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/modules-load.d/wifi_dummy.conf b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/modules-load.d/wifi_dummy.conf new file mode 100644 index 000000000..e3a06c764 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/modules-load.d/wifi_dummy.conf @@ -0,0 +1 @@ +wifi_dummy diff --git a/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/package.mk b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/package.mk new file mode 100644 index 000000000..99a555113 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="wifi_dummy-aml" +PKG_VERSION="1.0" +PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="https://coreelec.org" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="$PKG_NAME: Linux driver" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; +} diff --git a/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/Makefile b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/Makefile new file mode 100644 index 000000000..48447534e --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/Makefile @@ -0,0 +1 @@ +obj-m += wifi_dummy.o diff --git a/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/wifi_dummy.c b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/wifi_dummy.c new file mode 100644 index 000000000..5fdc450d8 --- /dev/null +++ b/packages/kernel/linux-drivers/amlogic/wifi_dummy-aml/sources/wifi_dummy.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("kszaq"); +MODULE_DESCRIPTION("Amlogic WiFi power on and SDIO rescan module"); + +extern void extern_wifi_set_enable(int); +extern void sdio_reinit(void); + +static int __init wifi_dummy_init(void) +{ + printk(KERN_INFO "Triggered SDIO WiFi power on and bus rescan.\n"); + extern_wifi_set_enable(0); + msleep(300); + extern_wifi_set_enable(1); + msleep(300); + sdio_reinit(); + return 0; +} + +static void __exit wifi_dummy_cleanup(void) +{ + printk(KERN_INFO "Cleaning up module.\n"); +} + +module_init(wifi_dummy_init); +module_exit(wifi_dummy_cleanup); diff --git a/packages/kernel/linux-drivers/bcm_sta/package.mk b/packages/kernel/linux-drivers/bcm_sta/package.mk new file mode 100644 index 000000000..0eca39128 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +# Downloadlocation: +# http://www.broadcom.com/support/802.11/linux_sta.php + +PKG_NAME="bcm_sta" +PKG_VERSION="6.30.223.271" +PKG_SHA256="959bcd1e965d294304a4e290cb8e47b7c74b9763094eff4d0b8e6cfb68a6895b" +PKG_ARCH="x86_64" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.broadcom.com/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Broadcom's BCM4311-, BCM4312-, BCM4313-, BCM4321-, BCM4322-, BCM43224-, and BCM43225-based WLAN driver." +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +make_target() { + cd x86-64 + KBUILD_NOPEDANTIC=1 kernel_make V=1 CC=$CC -C $(kernel_path) M=`pwd` BINARCH=$TARGET_KERNEL_ARCH +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/bcm_sta + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0001-change-eth-to-wlan.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0001-change-eth-to-wlan.patch new file mode 100644 index 000000000..7398820ca --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0001-change-eth-to-wlan.patch @@ -0,0 +1,25 @@ +From c51168b8481e84743b50d3d5cba18a4a0a188448 Mon Sep 17 00:00:00 2001 +From: Alberto Milone +Date: Fri, 22 Nov 2013 10:07:33 +0100 +Subject: [PATCH 1/1] Change the network interface name from eth to wlan + +Thanks to Shuduo Sang for the patch. +--- + src/wl/sys/wl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/x86-64/src/wl/sys/wl_linux.c b/x86-64/src/wl/sys/wl_linux.c +index 3ead3c3..b662ff7 100644 +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -235,7 +235,7 @@ module_param(nompc, int, 0); + #define to_str(s) #s + #define quote_str(s) to_str(s) + +-#define BRCM_WLAN_IFNAME eth%d ++#define BRCM_WLAN_IFNAME wlan%d + + static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); + +-- +1.7.9.5 diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0002-user_ioctl.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0002-user_ioctl.patch new file mode 100644 index 000000000..6a4807504 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0002-user_ioctl.patch @@ -0,0 +1,15 @@ +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -1659,11 +1659,7 @@ + } + + WL_LOCK(wl); +- if (!capable(CAP_NET_ADMIN)) { +- bcmerror = BCME_EPERM; +- } else { +- bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); +- } ++ bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); + WL_UNLOCK(wl); + + done1: diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0003-remove-date-time-macros.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0003-remove-date-time-macros.patch new file mode 100644 index 000000000..b402af0fb --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0003-remove-date-time-macros.patch @@ -0,0 +1,22 @@ +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -724,7 +724,7 @@ wl_attach(uint16 vendor, uint16 device, + WL_ALL_PASSIVE_ENAB(wl) ? ", Passive Mode" : "", EPI_VERSION_STR); + + #ifdef BCMDBG +- printf(" (Compiled in " SRCBASE " at " __TIME__ " on " __DATE__ ")"); ++ printf(" (Compiled in " SRCBASE ")"); + #endif + printf("\n"); + +@@ -2049,8 +2049,7 @@ wl_osl_pcie_rc(struct wl_info *wl, uint + void + wl_dump_ver(wl_info_t *wl, struct bcmstrbuf *b) + { +- bcm_bprintf(b, "wl%d: %s %s version %s\n", wl->pub->unit, +- __DATE__, __TIME__, EPI_VERSION_STR); ++ bcm_bprintf(b, "wl%d: version %s\n", wl->pub->unit, EPI_VERSION_STR); + } + + #if defined(BCMDBG) + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0004-null-pointer-crash.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0004-null-pointer-crash.patch new file mode 100644 index 000000000..449492d34 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0004-null-pointer-crash.patch @@ -0,0 +1,11 @@ +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -2160,8 +2160,8 @@ wl_start(struct sk_buff *skb, struct net + wlif = WL_DEV_IF(dev); + wl = WL_INFO(dev); + ++ skb->prev = NULL; + if (WL_ALL_PASSIVE_ENAB(wl) || (WL_RTR() && WL_CONFIG_SMP())) { +- skb->prev = NULL; + + TXQ_LOCK(wl); diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0005-rdtscl.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0005-rdtscl.patch new file mode 100644 index 000000000..d05f910e0 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0005-rdtscl.patch @@ -0,0 +1,15 @@ +--- a/x86-64/src/shared/linux_osl.c 2015-09-19 01:47:15.000000000 +0300 ++++ b/x86-64/src/shared/linux_osl.c 2015-11-21 15:20:30.585902518 +0200 +@@ -932,7 +932,11 @@ + uint cycles; + + #if defined(__i386__) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) ++ cycles = (u32)rdtsc(); ++#else + rdtscl(cycles); ++#endif + #else + cycles = 0; + #endif + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0006-kernel-4.7.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0006-kernel-4.7.patch new file mode 100644 index 000000000..28de86406 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0006-kernel-4.7.patch @@ -0,0 +1,198 @@ +diff -Naur a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c +--- a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c 2016-06-23 14:26:16.911221749 +0100 ++++ b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c 2016-06-23 14:26:49.071406220 +0100 +@@ -236,7 +236,7 @@ + #endif + + #define CHAN2G(_channel, _freq, _flags) { \ +- .band = IEEE80211_BAND_2GHZ, \ ++ .band = NL80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ +@@ -245,7 +245,7 @@ + } + + #define CHAN5G(_channel, _flags) { \ +- .band = IEEE80211_BAND_5GHZ, \ ++ .band = NL80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ +@@ -379,7 +379,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_2ghz = { +- .band = IEEE80211_BAND_2GHZ, ++ .band = NL80211_BAND_2GHZ, + .channels = __wl_2ghz_channels, + .n_channels = ARRAY_SIZE(__wl_2ghz_channels), + .bitrates = wl_g_rates, +@@ -387,7 +387,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_5ghz_a = { +- .band = IEEE80211_BAND_5GHZ, ++ .band = NL80211_BAND_5GHZ, + .channels = __wl_5ghz_a_channels, + .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), + .bitrates = wl_a_rates, +@@ -395,7 +395,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_5ghz_n = { +- .band = IEEE80211_BAND_5GHZ, ++ .band = NL80211_BAND_5GHZ, + .channels = __wl_5ghz_n_channels, + .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), + .bitrates = wl_a_rates, +@@ -1876,8 +1876,8 @@ + wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; + #endif + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); +- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; +- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; ++ wdev->wiphy->bands[NL80211_BAND_2GHZ] = &__wl_band_2ghz; ++ wdev->wiphy->bands[NL80211_BAND_5GHZ] = &__wl_band_5ghz_a; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wdev->wiphy->cipher_suites = __wl_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); +@@ -2000,7 +2000,7 @@ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) + freq = ieee80211_channel_to_frequency(notif_bss_info->channel, + (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ? +- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ); ++ NL80211_BAND_2GHZ : NL80211_BAND_5GHZ); + #else + freq = ieee80211_channel_to_frequency(notif_bss_info->channel); + #endif +@@ -2116,7 +2116,7 @@ + return err; + } + chan = wf_chspec_ctlchan(chanspec); +- band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; ++ band = (chan <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + freq = ieee80211_channel_to_frequency(chan, band); + channel = ieee80211_get_channel(wiphy, freq); + cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, channel, GFP_KERNEL); +@@ -2250,10 +2250,10 @@ + join_params->params.chanspec_list[0] = + ieee80211_frequency_to_channel(chan->center_freq); + +- if (chan->band == IEEE80211_BAND_2GHZ) { ++ if (chan->band == NL80211_BAND_2GHZ) { + chanspec |= WL_CHANSPEC_BAND_2G; + } +- else if (chan->band == IEEE80211_BAND_5GHZ) { ++ else if (chan->band == NL80211_BAND_5GHZ) { + chanspec |= WL_CHANSPEC_BAND_5G; + } + else { +@@ -2885,7 +2885,7 @@ + + if (phy == 'n' || phy == 'a' || phy == 'v') { + wiphy = wl_to_wiphy(wl); +- wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; ++ wiphy->bands[NL80211_BAND_5GHZ] = &__wl_band_5ghz_n; + } + + return err; +diff -Naur a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c 2016-06-23 14:26:22.639254590 +0100 ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c 2016-06-23 14:27:01.507477603 +0100 +@@ -236,7 +236,7 @@ + #endif + + #define CHAN2G(_channel, _freq, _flags) { \ +- .band = IEEE80211_BAND_2GHZ, \ ++ .band = NL80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ +@@ -245,7 +245,7 @@ + } + + #define CHAN5G(_channel, _flags) { \ +- .band = IEEE80211_BAND_5GHZ, \ ++ .band = NL80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ +@@ -379,7 +379,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_2ghz = { +- .band = IEEE80211_BAND_2GHZ, ++ .band = NL80211_BAND_2GHZ, + .channels = __wl_2ghz_channels, + .n_channels = ARRAY_SIZE(__wl_2ghz_channels), + .bitrates = wl_g_rates, +@@ -387,7 +387,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_5ghz_a = { +- .band = IEEE80211_BAND_5GHZ, ++ .band = NL80211_BAND_5GHZ, + .channels = __wl_5ghz_a_channels, + .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), + .bitrates = wl_a_rates, +@@ -395,7 +395,7 @@ + }; + + static struct ieee80211_supported_band __wl_band_5ghz_n = { +- .band = IEEE80211_BAND_5GHZ, ++ .band = NL80211_BAND_5GHZ, + .channels = __wl_5ghz_n_channels, + .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), + .bitrates = wl_a_rates, +@@ -1876,8 +1876,8 @@ + wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; + #endif + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); +- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; +- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; ++ wdev->wiphy->bands[NL80211_BAND_2GHZ] = &__wl_band_2ghz; ++ wdev->wiphy->bands[NL80211_BAND_5GHZ] = &__wl_band_5ghz_a; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wdev->wiphy->cipher_suites = __wl_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); +@@ -2000,7 +2000,7 @@ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) + freq = ieee80211_channel_to_frequency(notif_bss_info->channel, + (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ? +- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ); ++ NL80211_BAND_2GHZ : NL80211_BAND_5GHZ); + #else + freq = ieee80211_channel_to_frequency(notif_bss_info->channel); + #endif +@@ -2116,7 +2116,7 @@ + return err; + } + chan = wf_chspec_ctlchan(chanspec); +- band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; ++ band = (chan <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + freq = ieee80211_channel_to_frequency(chan, band); + channel = ieee80211_get_channel(wiphy, freq); + cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, channel, GFP_KERNEL); +@@ -2250,10 +2250,10 @@ + join_params->params.chanspec_list[0] = + ieee80211_frequency_to_channel(chan->center_freq); + +- if (chan->band == IEEE80211_BAND_2GHZ) { ++ if (chan->band == NL80211_BAND_2GHZ) { + chanspec |= WL_CHANSPEC_BAND_2G; + } +- else if (chan->band == IEEE80211_BAND_5GHZ) { ++ else if (chan->band == NL80211_BAND_5GHZ) { + chanspec |= WL_CHANSPEC_BAND_5G; + } + else { +@@ -2885,7 +2885,7 @@ + + if (phy == 'n' || phy == 'a' || phy == 'v') { + wiphy = wl_to_wiphy(wl); +- wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; ++ wiphy->bands[NL80211_BAND_5GHZ] = &__wl_band_5ghz_n; + } + + return err; diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0007-kernel-4.8.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0007-kernel-4.8.patch new file mode 100644 index 000000000..5f830e2d4 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0007-kernel-4.8.patch @@ -0,0 +1,96 @@ +diff -Naur a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c +--- a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c 2016-09-11 01:59:36.987804240 +0100 ++++ b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c 2016-09-11 02:02:44.876069294 +0100 +@@ -2387,7 +2387,14 @@ + + if (wl->scan_request) { + WL_DBG(("%s: Aborting scan\n", __FUNCTION__)); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = true ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, true); ++#endif + wl->scan_request = NULL; + } + +@@ -2488,7 +2495,14 @@ + + scan_done_out: + if (wl->scan_request) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = false ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, false); ++#endif + wl->scan_request = NULL; + } + rtnl_unlock(); +@@ -2913,7 +2927,14 @@ + s32 err = 0; + + if (wl->scan_request) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = true ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, true); ++#endif + wl->scan_request = NULL; + } + +diff -Naur a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c 2016-09-11 01:59:50.796117742 +0100 ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c 2016-09-11 02:04:12.290053058 +0100 +@@ -2387,7 +2387,14 @@ + + if (wl->scan_request) { + WL_DBG(("%s: Aborting scan\n", __FUNCTION__)); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = true ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, true); ++#endif + wl->scan_request = NULL; + } + +@@ -2488,7 +2495,14 @@ + + scan_done_out: + if (wl->scan_request) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = false ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, false); ++#endif + wl->scan_request = NULL; + } + rtnl_unlock(); +@@ -2913,7 +2927,14 @@ + s32 err = 0; + + if (wl->scan_request) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++ struct cfg80211_scan_info info = { ++ .aborted = true ++ }; ++ cfg80211_scan_done(wl->scan_request, &info); ++#else + cfg80211_scan_done(wl->scan_request, true); ++#endif + wl->scan_request = NULL; + } + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0008-kernel-4.11.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0008-kernel-4.11.patch new file mode 100644 index 000000000..56fb51a95 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0008-kernel-4.11.patch @@ -0,0 +1,68 @@ +From 7e8dddb7a545bc5ba74336ef2aafed1c0b4ceee1 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 13 Mar 2017 20:48:44 +0000 +Subject: [PATCH 1/2] bcm_sta: Fix build for API changes in kernel 4.11 + +--- + x86-64/src/wl/sys/wl_cfg80211_hybrid.c | 4 ++++ + x86-64/src/wl/sys/wl_linux.c | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +index 7b606e0..76ef208 100644 +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +@@ -26,6 +26,10 @@ + #include + #include + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif ++ + #include + #include + #include +diff --git a/x86-64/src/wl/sys/wl_linux.c b/x86-64/src/wl/sys/wl_linux.c +index 0d05100..dca7c71 100644 +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -26,6 +26,10 @@ + #include + #include + #include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif ++ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) + #include + #endif +-- +2.7.4 + + +From 1d066a57a682af0ac42b8d1c65bf7bd1984a54ca Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 13 Mar 2017 20:49:01 +0000 +Subject: [PATCH 2/2] bcm_sta: Remove usage of net_device last_rx member + +--- + x86-64/src/wl/sys/wl_linux.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/x86-64/src/wl/sys/wl_linux.c b/x86-64/src/wl/sys/wl_linux.c +index dca7c71..f3be019 100644 +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -2919,7 +2919,6 @@ wl_monitor(wl_info_t *wl, wl_rxsts_t *rxsts, void *p) + if (skb == NULL) return; + + skb->dev = wl->monitor_dev; +- skb->dev->last_rx = jiffies; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + skb_reset_mac_header(skb); + #else +-- +2.7.4 + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0009-kernel-4.12.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0009-kernel-4.12.patch new file mode 100644 index 000000000..65e691c5d --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0009-kernel-4.12.patch @@ -0,0 +1,75 @@ +From 268500240a551436c5003f5843ff4d090bf3e202 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Thu, 18 May 2017 12:52:55 +0100 +Subject: [PATCH] Fix build with kernel 4.12-rc1 + +--- + x86-64/src/wl/sys/wl_cfg80211_hybrid.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +index 7b606e0..cedf95c 100644 +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +@@ -49,8 +49,13 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO; + u32 wl_dbg_level = WL_DBG_ERR; + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, ++ enum nl80211_iftype type, struct vif_params *params); ++#else + static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); ++#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + static s32 + wl_cfg80211_scan(struct wiphy *wiphy, +@@ -461,10 +466,16 @@ wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len) + return err; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++static s32 ++wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, ++ enum nl80211_iftype type, struct vif_params *params) ++#else + static s32 + wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) ++#endif + { + struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy); + struct wireless_dev *wdev; +@@ -2364,6 +2375,19 @@ wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev, + memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN); + memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); + wl_update_bss_info(wl); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) ++ { ++ struct cfg80211_roam_info roam_info = { ++ .channel = &wl->conf->channel, ++ .bssid = (u8 *)&wl->bssid, ++ .req_ie = conn_info->req_ie, ++ .req_ie_len = conn_info->req_ie_len, ++ .resp_ie = conn_info->resp_ie, ++ .resp_ie_len = conn_info->resp_ie_len, ++ }; ++ cfg80211_roamed(ndev, &roam_info, GFP_KERNEL); ++ } ++#else + cfg80211_roamed(ndev, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) + &wl->conf->channel, +@@ -2371,6 +2395,7 @@ wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev, + (u8 *)&wl->bssid, + conn_info->req_ie, conn_info->req_ie_len, + conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); ++#endif + WL_DBG(("Report roaming result\n")); + + set_bit(WL_STATUS_CONNECTED, &wl->status); +-- +2.7.4 + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0010-kernel-4.15.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0010-kernel-4.15.patch new file mode 100644 index 000000000..d44ceb0f8 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0010-kernel-4.15.patch @@ -0,0 +1,61 @@ +From a893fac9b9e883f39a545e8ce87926cecc26ba12 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sun, 10 Jun 2018 19:13:17 +0100 +Subject: [PATCH] add 4.15.y support + +Credit: https://github.com/UnitedRPMs/broadcom-wl-dkms/blob/5147b5f1867273e2762f777fd724b6523c3ab8dd/008-linux415.patch +--- + x86-64/src/wl/sys/wl_linux.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/x86-64/src/wl/sys/wl_linux.c b/x86-64/src/wl/sys/wl_linux.c +index f7149da..89a3831 100644 +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -97,7 +97,11 @@ struct iw_statistics *wl_get_wireless_stats(struct net_device *dev); + + #include + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) ++static void wl_timer(struct timer_list *tl); ++#else + static void wl_timer(ulong data); ++#endif + static void _wl_timer(wl_timer_t *t); + static struct net_device *wl_alloc_linux_if(wl_if_t *wlif); + +@@ -2296,10 +2300,17 @@ wl_timer_task(wl_task_t *task) + atomic_dec(&t->wl->callbacks); + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) ++static void ++wl_timer(struct timer_list *tl) ++{ ++ wl_timer_t *t = (wl_timer_t *)tl; ++#else + static void + wl_timer(ulong data) + { + wl_timer_t *t = (wl_timer_t *)data; ++#endif + + if (!WL_ALL_PASSIVE_ENAB(t->wl)) + _wl_timer(t); +@@ -2351,9 +2362,13 @@ wl_init_timer(wl_info_t *wl, void (*fn)(void *arg), void *arg, const char *tname + + bzero(t, sizeof(wl_timer_t)); + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) ++ timer_setup(&t->timer, wl_timer, 0); ++#else + init_timer(&t->timer); + t->timer.data = (ulong) t; + t->timer.function = wl_timer; ++#endif + t->wl = wl; + t->fn = fn; + t->arg = arg; +-- +2.14.1 + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0011-fix-kernel-warnings.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0011-fix-kernel-warnings.patch new file mode 100644 index 000000000..2daca4200 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0011-fix-kernel-warnings.patch @@ -0,0 +1,177 @@ +From 6bc816ae3ef424bc52b2736aeb1eb08ab09f38a9 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sun, 10 Jun 2018 19:32:39 +0100 +Subject: [PATCH] fix kernel warnings + +Credit: https://github.com/UnitedRPMs/broadcom-wl-dkms/blob/master/wl-kmod-008_fix_kernel_warnings.patch +--- + x86-64/src/wl/sys/wl_cfg80211_hybrid.c | 88 +++++++++++++++++++++++----------- + 1 file changed, 60 insertions(+), 28 deletions(-) + +diff --git a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +index 2e8625d..4da9b38 100644 +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +@@ -1983,7 +1983,7 @@ static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info + + if (dtoh32(bi->length) > WL_BSS_INFO_MAX) { + WL_DBG(("Beacon is larger than buffer. Discarding\n")); +- return err; ++ return -E2BIG; + } + notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) + + WL_BSS_INFO_MAX, GFP_KERNEL); +@@ -2007,9 +2007,15 @@ static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info + beacon_proberesp->capab_info = cpu_to_le16(bi->capability); + wl_rst_ie(wl); + +- wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); +- wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - +- offsetof(struct wl_cfg80211_bss_info, frame_buf)); ++ err = wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ if (err) ++ goto inform_single_bss_out; ++ ++ err = wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - ++ offsetof(struct wl_cfg80211_bss_info, frame_buf)); ++ if (err) ++ goto inform_single_bss_out; ++ + notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) + + wl_get_ielen(wl); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) +@@ -2021,14 +2027,14 @@ static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info + #endif + if (freq == 0) { + WL_ERR(("Invalid channel, fail to chcnage channel to freq\n")); +- kfree(notif_bss_info); +- return -EINVAL; ++ err = -EINVAL; ++ goto inform_single_bss_out; + } + channel = ieee80211_get_channel(wiphy, freq); + if (unlikely(!channel)) { + WL_ERR(("ieee80211_get_channel error\n")); +- kfree(notif_bss_info); +- return -EINVAL; ++ err = -EINVAL; ++ goto inform_single_bss_out; + } + + WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n", +@@ -2036,28 +2042,35 @@ static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info + mgmt->u.beacon.capab_info, &bi->BSSID)); + + signal = notif_bss_info->rssi * 100; +- cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, +- le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); +- if (unlikely(!cbss)) { +- WL_ERR(("cfg80211_inform_bss_frame error\n")); +- kfree(notif_bss_info); +- return -EINVAL; ++ if (!wl->scan_request) { ++ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, ++ le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); ++ if (unlikely(!cbss)) { ++ WL_ERR(("cfg80211_inform_bss_frame error\n")); ++ err = -ENOMEM; ++ goto inform_single_bss_out; ++ } + } +- +- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); +- notify_ielen = le32_to_cpu(bi->ie_length); ++ else { ++ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); ++ notify_ielen = le32_to_cpu(bi->ie_length); + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) +- cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet), +- 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int, +- (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL); ++ cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet), ++ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int, ++ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL); + #else +- cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, (const u8 *)(bi->BSSID.octet), +- 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int, +- (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL); ++ cbss = cfg80211_inform_bss(wiphy, channel, ++ wl->active_scan ? CFG80211_BSS_FTYPE_PRESP : CFG80211_BSS_FTYPE_BEACON, ++ (const u8 *)(bi->BSSID.octet), ++ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int, ++ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL); + #endif +- +- if (unlikely(!cbss)) +- return -ENOMEM; ++ if (unlikely(!cbss)) { ++ WL_ERR(("cfg80211_inform_bss error\n")); ++ err = -ENOMEM; ++ goto inform_single_bss_out; ++ } ++ } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + cfg80211_put_bss(wiphy, cbss); +@@ -2065,6 +2078,7 @@ static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info + cfg80211_put_bss(cbss); + #endif + ++inform_single_bss_out: + kfree(notif_bss_info); + + return err; +@@ -2331,6 +2345,9 @@ static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl) + if (err) + goto update_bss_info_out; + ++ bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid, ++ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); ++ + ie = ((u8 *)bi) + bi->ie_offset; + ie_len = bi->ie_length; + } else { +@@ -2343,12 +2360,20 @@ static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl) + ie_len = bss->len_information_elements; + #endif + wl->conf->channel = *bss->channel; ++ } ++ ++ if (bss) { + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + cfg80211_put_bss(wiphy, bss); + #else + cfg80211_put_bss(bss); + #endif + } ++ else { ++ WL_DBG(("Could not update BSS\n")); ++ err = -EINVAL; ++ goto update_bss_info_out; ++ } + + tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); + if (tim) { +@@ -2375,10 +2400,17 @@ wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev, + struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl); + s32 err = 0; + +- wl_get_assoc_ies(wl); ++ err = wl_get_assoc_ies(wl); ++ if (err) ++ return err; ++ + memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN); + memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); +- wl_update_bss_info(wl); ++ ++ err = wl_update_bss_info(wl); ++ if (err) ++ return err; ++ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + { + struct cfg80211_roam_info roam_info = { +-- +2.14.1 + diff --git a/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0200-kernel-5.1-rc1-fix.patch b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0200-kernel-5.1-rc1-fix.patch new file mode 100644 index 000000000..09b3329d1 --- /dev/null +++ b/packages/kernel/linux-drivers/bcm_sta/patches/bcm_sta-0200-kernel-5.1-rc1-fix.patch @@ -0,0 +1,68 @@ +From aa1fc45ace58d802d038857b6fed8af9d771fbcc Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 18 Mar 2019 16:29:45 +0000 +Subject: [PATCH] get rid of legacy 'get_ds()' function + +https://github.com/torvalds/linux/commit/736706bee3298208343a76096370e4f6a5c55915 +--- + x86-32/src/wl/sys/wl_cfg80211_hybrid.c | 2 +- + x86-32/src/wl/sys/wl_iw.c | 2 +- + x86-64/src/wl/sys/wl_cfg80211_hybrid.c | 2 +- + x86-64/src/wl/sys/wl_iw.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c +index 7b606e0..51c81bc 100644 +--- a/x86-32/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/x86-32/src/wl/sys/wl_cfg80211_hybrid.c +@@ -450,7 +450,7 @@ wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len) + ifr.ifr_data = (caddr_t)&ioc; + + fs = get_fs(); +- set_fs(get_ds()); ++ set_fs(KERNEL_DS); + #if defined(WL_USE_NETDEV_OPS) + err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); + #else +diff --git a/x86-32/src/wl/sys/wl_iw.c b/x86-32/src/wl/sys/wl_iw.c +index c4c610b..9c3c74e 100644 +--- a/x86-32/src/wl/sys/wl_iw.c ++++ b/x86-32/src/wl/sys/wl_iw.c +@@ -117,7 +117,7 @@ dev_wlc_ioctl( + ifr.ifr_data = (caddr_t) &ioc; + + fs = get_fs(); +- set_fs(get_ds()); ++ set_fs(KERNEL_DS); + #if defined(WL_USE_NETDEV_OPS) + ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); + #else +diff --git a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +index 7b606e0..51c81bc 100644 +--- a/x86-64/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/x86-64/src/wl/sys/wl_cfg80211_hybrid.c +@@ -450,7 +450,7 @@ wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len) + ifr.ifr_data = (caddr_t)&ioc; + + fs = get_fs(); +- set_fs(get_ds()); ++ set_fs(KERNEL_DS); + #if defined(WL_USE_NETDEV_OPS) + err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); + #else +diff --git a/x86-64/src/wl/sys/wl_iw.c b/x86-64/src/wl/sys/wl_iw.c +index c4c610b..9c3c74e 100644 +--- a/x86-64/src/wl/sys/wl_iw.c ++++ b/x86-64/src/wl/sys/wl_iw.c +@@ -117,7 +117,7 @@ dev_wlc_ioctl( + ifr.ifr_data = (caddr_t) &ioc; + + fs = get_fs(); +- set_fs(get_ds()); ++ set_fs(KERNEL_DS); + #if defined(WL_USE_NETDEV_OPS) + ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); + #else +-- +2.14.1 + diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/package.mk b/packages/kernel/linux-drivers/dvbhdhomerun/package.mk new file mode 100644 index 000000000..948c48e14 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dvbhdhomerun" +PKG_VERSION="20130704" +PKG_SHA256="1af817b85b163f3c6c3a9a07410f54875e74513c197709638b4922165e894f54" +PKG_LICENSE="GPL" +PKG_SITE="http://sourceforge.net/projects/dvbhdhomerun/" +PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +#PKG_URL="$SOURCEFORGE_SRC/project/dvbhdhomerun/${PKG_NAME}_${PKG_VERSION}.tar.gz" +#PKG_DEPENDS_TARGET="toolchain linux libhdhomerun" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="A linux DVB driver for the HDHomeRun TV tuner (http://www.silicondust.com)." +PKG_IS_KERNEL_PKG="yes" + +configure_package() { + PKG_CMAKE_SCRIPT="${PKG_BUILD}/userhdhomerun/CMakeLists.txt" +} + +pre_configure_target() { + # use it here to be sure libhdhomerun is already built + PKG_CMAKE_OPTS_TARGET="-DLIBHDHOMERUN_PATH=$(ls -d $BUILD/libhdhomerun-*/)" + + # absolute path + LIBHDHOMERUN_PATH=$(ls -d $BUILD/libhdhomerun-*/) + sed -i "s|SET(LIBHDHOMERUN_PATH .*)|SET(LIBHDHOMERUN_PATH $LIBHDHOMERUN_PATH)|g" ../userhdhomerun/CMakeLists.txt + sed -i "s|/etc/dvbhdhomerun|/tmp/dvbhdhomerun|g" ../userhdhomerun/hdhomerun_tuner.cpp + sed -i "s|/etc/dvbhdhomerun|/tmp/dvbhdhomerun|g" ../userhdhomerun/hdhomerun_controller.cpp +} + +pre_make_target() { + ( cd ../kernel + LDFLAGS="" make dvb_hdhomerun KERNEL_DIR=$(kernel_path) + fix_module_depends dvb_hdhomerun_core.ko "dvb_core" + ) +} + +makeinstall_target() { + cd $PKG_BUILD + mkdir -p $INSTALL/$(get_full_module_dir)/hdhomerun + cp kernel/*.ko $INSTALL/$(get_full_module_dir)/hdhomerun/ + + mkdir -p $INSTALL/usr/bin + cp -PR .$TARGET_NAME/userhdhomerun $INSTALL/usr/bin +} diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-001-conf_file.patch b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-001-conf_file.patch new file mode 100644 index 000000000..d93002d43 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-001-conf_file.patch @@ -0,0 +1,52 @@ +diff -uNr dvbhdhomerun-0.0.15-orig/userhdhomerun/conf_inifile.cpp dvbhdhomerun-0.0.15/userhdhomerun/conf_inifile.cpp +--- dvbhdhomerun-0.0.15-orig/userhdhomerun/conf_inifile.cpp 2013-02-17 22:37:34.000000000 +0100 ++++ dvbhdhomerun-0.0.15/userhdhomerun/conf_inifile.cpp 2013-03-02 10:23:46.000000000 +0100 +@@ -8,6 +8,38 @@ + + using namespace std; + ++// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf ++std::istream& safeGetline(std::istream& is, std::string& t) ++{ ++ t.clear(); ++ ++ // The characters in the stream are read one-by-one using a std::streambuf. ++ // That is faster than reading them one-by-one using the std::istream. ++ // Code that uses streambuf this way must be guarded by a sentry object. ++ // The sentry object performs various tasks, ++ // such as thread synchronization and updating the stream state. ++ ++ std::istream::sentry se(is); ++ std::streambuf* sb = is.rdbuf(); ++ ++ for(;;) { ++ int c = sb->sbumpc(); ++ switch (c) { ++ case '\r': ++ c = sb->sgetc(); ++ if(c == '\n') ++ sb->sbumpc(); ++ return is; ++ case '\n': ++ case EOF: ++ return is; ++ default: ++ t += (char)c; ++ } ++ } ++} ++ ++ + bool ConfIniFile::OpenIniFile(const string& _filename) + { + m_sectionKeyValue.clear(); +@@ -17,7 +49,8 @@ + if(conffile.is_open()) { + string line; + string section; +- while(getline(conffile, line)) { ++ //while(getline(conffile, line)) { ++ while(safeGetline(conffile, line)) { + if(line.empty()) { + //LOG() << " ignore, empty"; + } diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-002-auto_detect.patch b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-002-auto_detect.patch new file mode 100644 index 000000000..9a926b996 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-002-auto_detect.patch @@ -0,0 +1,34 @@ +diff -uNr dvbhdhomerun-0.0.15-orig/userhdhomerun/hdhomerun_tuner.cpp dvbhdhomerun-0.0.15/userhdhomerun/hdhomerun_tuner.cpp +--- dvbhdhomerun-0.0.15-orig/userhdhomerun/hdhomerun_tuner.cpp 2013-02-17 22:37:34.000000000 +0100 ++++ dvbhdhomerun-0.0.15/userhdhomerun/hdhomerun_tuner.cpp 2013-03-02 10:25:15.000000000 +0100 +@@ -97,12 +97,28 @@ + string type(tmp); + LOG() << "Type of device: " << type << endl; + if(type == "hdhomerun_dvbt") { +- LOG() << "Notice, setting to DVB-C!! Use /etc/dvbhdhomerun to change that." << endl; +- m_type = HdhomerunTuner::DVBC; ++ m_type = HdhomerunTuner::DVBT; + } + else if(type == "hdhomerun_atsc") { + m_type = HdhomerunTuner::ATSC; + } ++ else if(type == "hdhomerun3_dvbt") { ++ m_type = HdhomerunTuner::DVBT; ++ } ++ else if(type.find("dvbt") != string::npos) { ++ m_type = HdhomerunTuner::DVBT; ++ } ++ else if(type.find("dvbc") != string::npos) { ++ m_type = HdhomerunTuner::DVBC; ++ } ++ else if(type.find("atsc") != string::npos) { ++ m_type = HdhomerunTuner::ATSC; ++ } ++ ++ if (m_type != HdhomerunTuner::NOT_SET) { ++ LOG() << "Auto detecting tuner type set to \"" << type ++ << "\" based on auto detecting" << endl; ++ } + } + else { + ERR() << "get_model_str from HDHomeRun failed!" << endl; diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-hdhomerun_discover_find_devices_custom_v2.patch b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-hdhomerun_discover_find_devices_custom_v2.patch new file mode 100644 index 000000000..4ecdee325 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-hdhomerun_discover_find_devices_custom_v2.patch @@ -0,0 +1,12 @@ +diff -Naur dvbhdhomerun-20130704/userhdhomerun/hdhomerun_controller.cpp dvbhdhomerun-20130704.patch/userhdhomerun/hdhomerun_controller.cpp +--- dvbhdhomerun-20130704/userhdhomerun/hdhomerun_controller.cpp 2013-02-17 22:37:34.000000000 +0100 ++++ dvbhdhomerun-20130704.patch/userhdhomerun/hdhomerun_controller.cpp 2015-09-23 14:13:00.659818567 +0200 +@@ -71,7 +71,7 @@ + // ...really fragile API design... + memset(devices, 0, sizeof(devices)); + +- int numOfDevices = hdhomerun_discover_find_devices_custom(0, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, devices, m_maxDevices); ++ int numOfDevices = hdhomerun_discover_find_devices_custom_v2(0, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, devices, m_maxDevices); + LOG() << "Num of devices = " << numOfDevices << endl; + + if(numOfDevices == 0) { diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-3.8.4.patch b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-3.8.4.patch new file mode 100644 index 000000000..ccde5f0e4 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-3.8.4.patch @@ -0,0 +1,22 @@ +diff --git a/kernel/dvb_hdhomerun_init.c b/kernel/dvb_hdhomerun_init.c +index d02a322..bd97d5e 100644 +--- a/kernel/dvb_hdhomerun_init.c ++++ b/kernel/dvb_hdhomerun_init.c +@@ -143,7 +143,7 @@ static int dvb_hdhomerun_stop_feed(struct dvb_demux_feed *feed) + return ret; + } + +-static int __devinit dvb_hdhomerun_register(struct dvb_hdhomerun *hdhomerun) ++static int dvb_hdhomerun_register(struct dvb_hdhomerun *hdhomerun) + { + struct dvb_adapter *dvb_adapter; + struct dvb_demux *dvbdemux; +@@ -284,7 +284,7 @@ static void dvb_hdhomerun_unregister(struct dvb_hdhomerun *hdhomerun) + } + + +-static int __devinit dvb_hdhomerun_probe(struct platform_device *plat_dev) ++static int dvb_hdhomerun_probe(struct platform_device *plat_dev) + { + int ret; + struct dvb_hdhomerun *hdhomerun; diff --git a/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-4.2.patch b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-4.2.patch new file mode 100644 index 000000000..d0ecedc54 --- /dev/null +++ b/packages/kernel/linux-drivers/dvbhdhomerun/patches/dvbhdhomerun-linux-4.2.patch @@ -0,0 +1,73 @@ +From 198aef39dee0357524c88ecc0665312c2c72a0d9 Mon Sep 17 00:00:00 2001 +From: HappyHeyoka +Date: Sat, 25 Jul 2015 19:47:50 +1000 +Subject: [PATCH] Track changes to kernel include 'dvb_frontend.h' where + fe_status_t has gone in line with kernel coding style. Changes should be + backwards compatible (famous last words) + +--- + kernel/dvb_hdhomerun_control_messages.h | 2 +- + kernel/dvb_hdhomerun_fe.c | 6 +++--- + userhdhomerun/hdhomerun_control.cpp | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/kernel/dvb_hdhomerun_control_messages.h b/kernel/dvb_hdhomerun_control_messages.h +index 45230b1..c22fc80 100644 +--- a/kernel/dvb_hdhomerun_control_messages.h ++++ b/kernel/dvb_hdhomerun_control_messages.h +@@ -60,7 +60,7 @@ struct dvbhdhomerun_control_mesg { + unsigned int type; + union { + unsigned int frequency; +- fe_status_t fe_status; ++ enum fe_status frontend_status; + int16_t signal_strength; + struct dmx_pes_filter_params dmx_pes_filter; + struct hdhomerun_dvb_demux_feed demux_feed; +diff --git a/kernel/dvb_hdhomerun_fe.c b/kernel/dvb_hdhomerun_fe.c +index a96799b..58be54c 100644 +--- a/kernel/dvb_hdhomerun_fe.c ++++ b/kernel/dvb_hdhomerun_fe.c +@@ -49,7 +49,7 @@ struct dvb_hdhomerun_fe_state { + + extern int hdhomerun_debug_mask; + +-static int dvb_hdhomerun_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) ++static int dvb_hdhomerun_fe_read_status(struct dvb_frontend* fe, enum fe_status* status) + { + struct dvbhdhomerun_control_mesg mesg; + struct dvb_hdhomerun_fe_state* state = fe->demodulator_priv; +@@ -60,7 +60,7 @@ static int dvb_hdhomerun_fe_read_status(struct dvb_frontend* fe, fe_status_t* st + mesg.id = state->id; + hdhomerun_control_post_and_wait(&mesg); + +- *status = mesg.u.fe_status; ++ *status = mesg.u.frontend_status; + + return 0; + } +@@ -203,7 +203,7 @@ static int dvb_hdhomerun_fe_tune(struct dvb_frontend *fe, bool re_tune, + #else + static int dvb_hdhomerun_fe_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, + #endif +- unsigned int mode_flags, unsigned int *delay, fe_status_t *status) ++ unsigned int mode_flags, unsigned int *delay, enum fe_status *status) + { + int ret; + DEBUG_FUNC(1); +diff --git a/userhdhomerun/hdhomerun_control.cpp b/userhdhomerun/hdhomerun_control.cpp +index 63b12f8..912b49d 100644 +--- a/userhdhomerun/hdhomerun_control.cpp ++++ b/userhdhomerun/hdhomerun_control.cpp +@@ -219,9 +219,9 @@ void Control::FE_READ_Status(struct dvbhdhomerun_control_mesg& _mesg) + + HdhomerunTuner* tuner = m_hdhomerun->GetTuner(_mesg.id); + if(tuner) { +- fe_status_t status = (fe_status_t)tuner->ReadStatus(); ++ fe_status status = (fe_status)tuner->ReadStatus(); + +- _mesg.u.fe_status = status; ++ _mesg.u.frontend_status = status; + } + else { + ERR() << "Tuner id does not exist!" << _mesg.id << endl; diff --git a/packages/kernel/linux-drivers/gpu-aml-ng/package.mk b/packages/kernel/linux-drivers/gpu-aml-ng/package.mk new file mode 100644 index 000000000..386df87ab --- /dev/null +++ b/packages/kernel/linux-drivers/gpu-aml-ng/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="gpu-aml-ng" +PKG_VERSION="be29f1f274e3798d3ab2d7c489e47f8de20e8cf3" +PKG_SHA256="06ad5ca2ae39b032477e702169f2ad8b964b36a49d97c3055094943b12a7fa0c" +PKG_LICENSE="GPL" +PKG_SITE="https://coreelec.org" +PKG_URL="https://github.com/khadas/android_hardware_arm_gpu/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="gpu-aml-ng: Linux drivers for Mali GPUs found in Amlogic Meson SoCs" +PKG_IS_KERNEL_PKG="yes" +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + sed -e "s|shell date|shell date -R|g" -i $PKG_BUILD/utgard/*/Kbuild + sed -e "s|USING_GPU_UTILIZATION=1|USING_GPU_UTILIZATION=0|g" -i $PKG_BUILD/utgard/platform/Kbuild.amlogic +} + +pre_make_target() { + ln -s $PKG_BUILD/utgard/platform $PKG_BUILD/utgard/r7p0/platform +} + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/bifrost/r12p0/kernel/drivers/gpu/arm \ + CONFIG_MALI_MIDGARD=m CONFIG_MALI_PLATFORM_NAME="devicetree" + + kernel_make -C $(kernel_path) M=$PKG_BUILD/utgard/r7p0 \ + EXTRA_CFLAGS="-DCONFIG_MALI450=y" \ + CONFIG_MALI400=m CONFIG_MALI450=y +} + +makeinstall_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/bifrost/r12p0/kernel/drivers/gpu/arm \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install + + kernel_make -C $(kernel_path) M=$PKG_BUILD/utgard/r7p0 \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install +} diff --git a/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-01-fix-cp-error.patch b/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-01-fix-cp-error.patch new file mode 100644 index 000000000..0532560e6 --- /dev/null +++ b/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-01-fix-cp-error.patch @@ -0,0 +1,12 @@ +diff -Naur gpu-aml-fe7a4d8.orig/utgard/r5p1/common/mali_group.c gpu-aml-fe7a4d8/utgard/r5p1/common/mali_group.c +--- gpu-aml-fe7a4d8.orig/utgard/r5p1/common/mali_group.c 2017-12-08 12:39:53.000000000 +0100 ++++ gpu-aml-fe7a4d8/utgard/r5p1/common/mali_group.c 2019-03-20 12:43:29.654721108 +0100 +@@ -639,7 +639,7 @@ + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch( +- mali_pp_core_description(group->pp_core), ++ mali_pp_core_description(child->pp_core), + sched_clock(), mali_pp_job_get_tid(job), + 0, mali_pp_job_get_id(job)); + #endif diff --git a/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-02-disable-tracepoints.patch b/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-02-disable-tracepoints.patch new file mode 100644 index 000000000..4f87ec4a3 --- /dev/null +++ b/packages/kernel/linux-drivers/gpu-aml-ng/patches/gpu-aml-ng-02-disable-tracepoints.patch @@ -0,0 +1,75 @@ +From ec748a4e13a77f0cc1f7c0c80114fa167a363a9c Mon Sep 17 00:00:00 2001 +From: cdu13a +Date: Mon, 26 Aug 2019 01:14:34 -0400 +Subject: more fixups for 4.9 + +--- + utgard/r5p1/common/mali_group.c | 4 ++++ + utgard/r5p1/common/mali_scheduler.c | 4 ++++ + utgard/r7p0/common/mali_group.c | 4 ++++ + utgard/r7p0/common/mali_scheduler.c | 4 ++++ + 4 files changed, 16 insertions(+) + +diff --git a/utgard/r5p1/common/mali_group.c b/utgard/r5p1/common/mali_group.c +index e174cdb..04b3e1e 100755 +--- a/utgard/r5p1/common/mali_group.c ++++ b/utgard/r5p1/common/mali_group.c +@@ -29,6 +29,10 @@ + #include "mali_executor.h" + #include + ++#ifdef CONFIG_GPU_TRACEPOINTS ++#undef CONFIG_GPU_TRACEPOINTS ++#endif ++ + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + #include + #include +diff --git a/utgard/r5p1/common/mali_scheduler.c b/utgard/r5p1/common/mali_scheduler.c +index b07f78a..8523c65 100755 +--- a/utgard/r5p1/common/mali_scheduler.c ++++ b/utgard/r5p1/common/mali_scheduler.c +@@ -23,6 +23,10 @@ + #include "mali_memory_dma_buf.h" + #endif + ++#ifdef CONFIG_GPU_TRACEPOINTS ++#undef CONFIG_GPU_TRACEPOINTS ++#endif ++ + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + #include + #include +diff --git a/utgard/r7p0/common/mali_group.c b/utgard/r7p0/common/mali_group.c +index 26cbce4..bb9b21b 100644 +--- a/utgard/r7p0/common/mali_group.c ++++ b/utgard/r7p0/common/mali_group.c +@@ -30,6 +30,10 @@ + #include "mali_executor.h" + #include + ++#ifdef CONFIG_GPU_TRACEPOINTS ++#undef CONFIG_GPU_TRACEPOINTS ++#endif ++ + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + #include + #include +diff --git a/utgard/r7p0/common/mali_scheduler.c b/utgard/r7p0/common/mali_scheduler.c +index 68afc59..b513431 100644 +--- a/utgard/r7p0/common/mali_scheduler.c ++++ b/utgard/r7p0/common/mali_scheduler.c +@@ -30,6 +30,10 @@ + #endif + #endif + ++#ifdef CONFIG_GPU_TRACEPOINTS ++#undef CONFIG_GPU_TRACEPOINTS ++#endif ++ + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + #include + #include +-- +2.17.1 + diff --git a/packages/kernel/linux-drivers/gpu-aml/package.mk b/packages/kernel/linux-drivers/gpu-aml/package.mk new file mode 100644 index 000000000..a38ea5507 --- /dev/null +++ b/packages/kernel/linux-drivers/gpu-aml/package.mk @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gpu-aml" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="http://openlinux.amlogic.com:8000/download/ARM/gpu/" +PKG_VERSION="fe7a4d8" +PKG_SHA256="518f855a2b191e50d09c2d0b3e671b5ed4b5e4db06aa3a718e29ef30cc0d9a57" +PKG_URL="https://github.com/khadas/android_hardware_arm_gpu/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="gpu-aml: Linux drivers for Mali GPUs found in Amlogic Meson SoCs" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +configure_package() { + PKG_UTGARD_VERSION="r5p1" + PKG_UTGARD_BUILD_DIR="$PKG_BUILD/utgard/$PKG_UTGARD_VERSION" + PKG_MIDGARD_VERSION="r16p0" + PKG_MIDGARD_BUILD_DIR="$PKG_BUILD/midgard/$PKG_MIDGARD_VERSION/kernel/drivers/gpu/arm/midgard" +} + +pre_configure_target() { + sed -e "s|shell date|shell date -R|g" -i $PKG_BUILD/utgard/*/Kbuild + sed -e "s|USING_GPU_UTILIZATION=1|USING_GPU_UTILIZATION=0|g" -i $PKG_BUILD/utgard/platform/Kbuild.amlogic +} + +pre_make_target() { + ln -s $PKG_BUILD/utgard/platform $PKG_UTGARD_BUILD_DIR/platform +} + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_MIDGARD_BUILD_DIR \ + EXTRA_CFLAGS="-DCONFIG_MALI_PLATFORM_DEVICETREE -DCONFIG_MALI_BACKEND=gpu" \ + CONFIG_MALI_MIDGARD=m CONFIG_MALI_PLATFORM_DEVICETREE=y CONFIG_MALI_BACKEND=gpu modules + + kernel_make -C $(kernel_path) M=$PKG_UTGARD_BUILD_DIR \ + EXTRA_CFLAGS="-DCONFIG_MALI450=y" \ + CONFIG_MALI400=m CONFIG_MALI450=y +} + +makeinstall_target() { + kernel_make -C $(kernel_path) M=$PKG_MIDGARD_BUILD_DIR \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install + + kernel_make -C $(kernel_path) M=$PKG_UTGARD_BUILD_DIR \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install +} diff --git a/packages/kernel/linux-drivers/gpu-aml/patches/gpu-aml-01-fix-cp-error.patch b/packages/kernel/linux-drivers/gpu-aml/patches/gpu-aml-01-fix-cp-error.patch new file mode 100644 index 000000000..0532560e6 --- /dev/null +++ b/packages/kernel/linux-drivers/gpu-aml/patches/gpu-aml-01-fix-cp-error.patch @@ -0,0 +1,12 @@ +diff -Naur gpu-aml-fe7a4d8.orig/utgard/r5p1/common/mali_group.c gpu-aml-fe7a4d8/utgard/r5p1/common/mali_group.c +--- gpu-aml-fe7a4d8.orig/utgard/r5p1/common/mali_group.c 2017-12-08 12:39:53.000000000 +0100 ++++ gpu-aml-fe7a4d8/utgard/r5p1/common/mali_group.c 2019-03-20 12:43:29.654721108 +0100 +@@ -639,7 +639,7 @@ + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + #if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch( +- mali_pp_core_description(group->pp_core), ++ mali_pp_core_description(child->pp_core), + sched_clock(), mali_pp_job_get_tid(job), + 0, mali_pp_job_get_id(job)); + #endif diff --git a/packages/kernel/linux-drivers/intel_nuc_led/package.mk b/packages/kernel/linux-drivers/intel_nuc_led/package.mk new file mode 100644 index 000000000..c792fe7d7 --- /dev/null +++ b/packages/kernel/linux-drivers/intel_nuc_led/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="intel_nuc_led" +PKG_VERSION="637c07a" +PKG_SHA256="b6c3c6f8a1a306f853f521bd0b6ab3cc876cd10ae8f6d152a72056e93e2866d4" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/milesp20/intel_nuc_led/" +PKG_URL="https://github.com/milesp20/intel_nuc_led/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Intel NUC7i[x]BN and NUC6CAY LED Control for Linux" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make KDIR=$(kernel_path) +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-drivers/mali-midgard/package.mk b/packages/kernel/linux-drivers/mali-midgard/package.mk new file mode 100644 index 000000000..dad97c4de --- /dev/null +++ b/packages/kernel/linux-drivers/mali-midgard/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mali-midgard" +PKG_VERSION="9ce33e456c9320b90f7ce8770262c852a77e4b81" # TX011-SW-99002-r28p0-01rel0 +PKG_SHA256="ef8808d0d0535449cd23410832bcb7433e35568afcbb75683608a7df9dd536bc" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://developer.arm.com/products/software/mali-drivers/" +PKG_URL="https://github.com/LibreELEC/mali-midgard/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mali-midgard: Linux drivers for Mali Midgard GPUs" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +case $PROJECT in + Allwinner) + PKG_EXTRA_CFLAGS="-DCONFIG_MALI_DEVFREQ -DCONFIG_MALI_PLATFORM_DEVICETREE" + PKG_CONFIGS="CONFIG_MALI_DEVFREQ=y" + ;; + Amlogic) + PKG_CONFIGS="CONFIG_MALI_PLATFORM_NAME=meson" + ;; + Rockchip) + PKG_CONFIGS="CONFIG_MALI_PLATFORM_NAME=rk" + ;; +esac + +post_patch() { + # rename kernel module to not clash with mali-bifrost + find $PKG_BUILD -name Kbuild -exec sed -i 's/mali_kbase.o/mali_midgard.o/g; s/mali_kbase-/mali_midgard-/g' {} \; +} + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/product/kernel/drivers/gpu/arm/midgard \ + EXTRA_CFLAGS="${PKG_EXTRA_CFLAGS}" \ + CONFIG_MALI_MIDGARD=m ${PKG_CONFIGS} +} + +makeinstall_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/product/kernel/drivers/gpu/arm/midgard \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install +} diff --git a/packages/kernel/linux-drivers/mali-utgard/package.mk b/packages/kernel/linux-drivers/mali-utgard/package.mk new file mode 100644 index 000000000..2718978db --- /dev/null +++ b/packages/kernel/linux-drivers/mali-utgard/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mali-utgard" +PKG_VERSION="5d89e2a946c7e4dbd7e627202e7bd7c3ed49954a" +PKG_SHA256="c3e6199f58807558eb665357a35e2f86c161fc1a55f27988e604671bc27e98c7" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://developer.arm.com/products/software/mali-drivers/utgard-kernel" +PKG_URL="https://github.com/LibreELEC/mali-utgard/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="mali-utgard: Linux drivers for Mali Utgard GPUs" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +case $PROJECT in + Allwinner) + PKG_MALI_PLATFORM="sunxi" + ;; + Amlogic) + PKG_MALI_PLATFORM="meson" + ;; + Rockchip) + PKG_MALI_PLATFORM="rk" + PKG_EXTRA_CFLAGS="-DCONFIG_MALI_DT" + PKG_CONFIGS="CONFIG_MALI_DT=y" + ;; +esac + +make_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/src/devicedrv/mali \ + MALI_PLATFORM_FILES=platform/${PKG_MALI_PLATFORM}/${PKG_MALI_PLATFORM}.c GIT_REV="" \ + EXTRA_CFLAGS="-DMALI_FAKE_PLATFORM_DEVICE=1 -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH -DCONFIG_MALI400=1 -DCONFIG_MALI450=1 -DCONFIG_MALI470=1 ${PKG_EXTRA_CFLAGS}" \ + CONFIG_MALI400=m CONFIG_MALI450=y CONFIG_MALI470=y CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y ${PKG_CONFIGS} +} + +makeinstall_target() { + kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/src/devicedrv/mali/ \ + INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \ + modules_install +} diff --git a/packages/kernel/linux-drivers/openvfd-driver/package.mk b/packages/kernel/linux-drivers/openvfd-driver/package.mk new file mode 100644 index 000000000..1c3102504 --- /dev/null +++ b/packages/kernel/linux-drivers/openvfd-driver/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Arthur Liberman (arthur_liberman@hotmail.com) + +PKG_NAME="openvfd-driver" +PKG_VERSION="2a48587b7a6a0b80d3f2f1dc7ed8281869d8775a" +PKG_SHA256="6b405d3ef4bceb77e931d4ed0ec0300306ddde8a0d9fe214ca0f7b552b716e74" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/arthur-liberman/linux_openvfd" +PKG_URL="https://github.com/arthur-liberman/linux_openvfd/archive/$PKG_VERSION.tar.gz" +PKG_SOURCE_DIR="linux_openvfd-$PKG_VERSION*" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="openvfd-driver: an open source Linux driver for VFD displays" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + make ARCH=$TARGET_KERNEL_ARCH \ + CROSS_COMPILE=$TARGET_KERNEL_PREFIX \ + -C "$(kernel_path)" M="$PKG_BUILD/driver" + + make OpenVFDService +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + find $PKG_BUILD/ -name \*.ko -not -path '*/\.*' -exec cp {} $INSTALL/$(get_full_module_dir)/$PKG_NAME \; + + mkdir -p $INSTALL/usr/sbin + cp -P OpenVFDService $INSTALL/usr/sbin +} + +post_install() { + enable_service openvfd.service +} diff --git a/packages/kernel/linux-drivers/openvfd-driver/system.d/openvfd.service b/packages/kernel/linux-drivers/openvfd-driver/system.d/openvfd.service new file mode 100644 index 000000000..364d5a500 --- /dev/null +++ b/packages/kernel/linux-drivers/openvfd-driver/system.d/openvfd.service @@ -0,0 +1,15 @@ +[Unit] +Description=OpenVFD Service +ConditionPathExists=/proc/device-tree/openvfd/ +ConditionPathExists=/storage/.config/vfd.conf +After=kodi-autostart.service + +[Service] +EnvironmentFile=/storage/.config/vfd.conf +ExecStart=/bin/sh -c '[ `cat /proc/device-tree/openvfd/compatible` = "open,vfd" ] && /sbin/modprobe openvfd vfd_gpio_clk=${vfd_gpio_clk} vfd_gpio_dat=${vfd_gpio_dat} vfd_gpio_stb=${vfd_gpio_stb:-0,0,0xFF} vfd_gpio0=${vfd_gpio0:-0,0,0xFF} vfd_gpio1=${vfd_gpio1:-0,0,0xFF} vfd_gpio2=${vfd_gpio2:-0,0,0xFF} vfd_gpio3=${vfd_gpio3:-0,0,0xFF} vfd_gpio_protocol=${vfd_gpio_protocol:-0,0} vfd_chars=${vfd_chars} vfd_dot_bits=${vfd_dot_bits} vfd_display_type=${vfd_display_type}; /usr/sbin/OpenVFDService ${clock_12h_format:+-12h}' +ExecStop=/bin/kill -TERM $MAINPID +ExecStopPost=-/usr/sbin/rmmod openvfd +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/packages/kernel/linux-drivers/slice-drivers/package.mk b/packages/kernel/linux-drivers/slice-drivers/package.mk new file mode 100644 index 000000000..614129fdb --- /dev/null +++ b/packages/kernel/linux-drivers/slice-drivers/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="slice-drivers" +PKG_VERSION="8a2bdcd5dc182de899f19b0935d8beeb7f5fdbcb" +PKG_SHA256="ffb3b9ef5a0e6101d661407447257abf136f1ae206a17bd18d9b204e0b29f050" +PKG_ARCH="arm" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/LibreELEC/slice-drivers" +PKG_URL="https://github.com/LibreELEC/slice-drivers/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="linux kernel modules for the Slice box" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make KDIR=$(kernel_path) +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp *.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/kernel/linux-firmware/RTL8188FU/package.mk b/packages/kernel/linux-firmware/RTL8188FU/package.mk new file mode 100644 index 000000000..592aefd70 --- /dev/null +++ b/packages/kernel/linux-firmware/RTL8188FU/package.mk @@ -0,0 +1,18 @@ +PKG_NAME="RTL8188FU" +PKG_VERSION="2614aaf4ee0420f2e3efd62d7de19f7bc719ff66" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lwfinger/rtl8188fu" +PKG_URL="https://github.com/lwfinger/rtl8188fu/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="Realtek RTL81xxFU Linux firmware" +PKG_IS_KERNEL_PKG="yes" + +make_target() { + echo +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/kernel-overlays/base/lib/firmware/rtlwifi + cp firmware/rtl8188fufw.bin ${INSTALL}/usr/lib/kernel-overlays/base/lib/firmware/rtlwifi +} diff --git a/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/package.mk b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/package.mk new file mode 100644 index 000000000..728fc1106 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="brcmfmac_sdio-firmware-aml" +PKG_VERSION="a255fca577bbdb528bdfe9077bb75c044d790054" +PKG_SHA256="552d686fafbf616dbdcd75c7687ff984197c19604813bab264c8d78b11f17818" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/CoreELEC/brcmfmac_sdio-firmware-aml" +PKG_URL="https://github.com/CoreELEC/brcmfmac_sdio-firmware-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Firmware for brcm bluetooth chips used in some Amlogic based devices." + +makeinstall_target() { + DESTDIR=$INSTALL FWDIR=$INSTALL/$(get_kernel_overlay_dir) make install + + cd $INSTALL/$(get_full_firmware_dir)/brcm + for f in *.hcd; do + ln -sr $f $(grep --text -o 'BCM[24]\S*' $f).hcd 2>/dev/null || true + ln -sr $f $(grep --text -o 'BCM[24]\S*' $f | cut -c4-).hcd 2>/dev/null || true + ln -sr $f $(echo $f | sed -r 's/[^.]*/\U&/') 2>/dev/null || true + done + ln -sr bcm4335_V0343.0353.hcd bcm4335a0.hcd 2>/dev/null || true + ln -sr bcm4335_V0343.0353.hcd BCM4335A0.hcd 2>/dev/null || true +} diff --git a/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware-aml.service b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware-aml.service new file mode 100644 index 000000000..e743b398d --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware-aml.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS1 to BlueZ stack using bcm43xx type +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/hciattach -n -s 115200 /dev/ttyS1 bcm43xx 2000000 +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware@.service b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware@.service new file mode 100644 index 000000000..a8fa7044b --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/system.d/brcmfmac_sdio-firmware@.service @@ -0,0 +1,9 @@ +[Unit] +Description=Broadcom sdio firmware update for %I +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStart=/usr/bin/brcm_patchram_plus --patchram /usr/lib/kernel-overlays/base/lib/firmware/brcm/%I.hcd --baudrate 2000000 --use_baudrate_for_download /dev/ttyS1 --enable_hci --no2bytes --tosleep=50000 diff --git a/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/udev.d/80-brcmfmac_sdio.rules b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/udev.d/80-brcmfmac_sdio.rules new file mode 100644 index 000000000..1a204ed63 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/brcmfmac_sdio-firmware-aml/udev.d/80-brcmfmac_sdio.rules @@ -0,0 +1,12 @@ +################################################################################ +# udev rules file for loading brcmfmac_sdio-firmware-aml +################################################################################ + +### Broadcom bcm43362/bcm20710a1 bluetooth device +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0xa962", ACTION=="add", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="brcmfmac_sdio-firmware@bcm20710a1.service", GOTO="end" + +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ACTION=="add", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="brcmfmac_sdio-firmware-aml.service" + +LABEL="end" diff --git a/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/package.mk b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/package.mk new file mode 100644 index 000000000..5a67a1b51 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="qca9377-firmware-aml" +PKG_VERSION="1.0.0-3" +PKG_SHA256="9a9f214943e77e89ce8fc8c0dc5b41bc253478a9d92383a76590993df861f36d" +PKG_ARCH="arm aarch64" +PKG_LICENSE="BSD-3c" +PKG_SITE="http://linode.boundarydevices.com/repos/apt/ubuntu-relx/pool/main/q/qca-firmware/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="qca9377 Linux firmware" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_firmware_dir) + cp -a * $INSTALL/$(get_full_firmware_dir) +} diff --git a/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/system.d/qca9377-firmware-aml.service b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/system.d/qca9377-firmware-aml.service new file mode 100644 index 000000000..4b174f641 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/system.d/qca9377-firmware-aml.service @@ -0,0 +1,16 @@ +[Unit] +Description=Attach /dev/ttyS1 to BlueZ stack using qca type +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/hciattach -n -s 115200 /dev/ttyS1 qca 2000000 +ExecStopPost=/usr/sbin/rfkill block bluetooth +Restart=always +RestartSec=2 +StartLimitInterval=0 +LimitNPROC=1 +TimeoutStopSec=1s diff --git a/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/udev.d/80-qca9377-firmware-aml.rules b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/udev.d/80-qca9377-firmware-aml.rules new file mode 100644 index 000000000..d3dd577bf --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/qca9377-firmware-aml/udev.d/80-qca9377-firmware-aml.rules @@ -0,0 +1,6 @@ +################################################################################ +# udev rules file for loading qca9377-firmware-aml +################################################################################ + +ACTION=="add", SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x0271", ATTRS{device}=="0x0701", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="qca9377-firmware-aml.service" diff --git a/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/package.mk b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/package.mk new file mode 100644 index 000000000..866a7ede7 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="rtkbt-firmware-aml" +PKG_VERSION="763c7195bb0328b45a5679e212ab05150361cc3a" +PKG_SHA256="2996dd867990a14b8d431c789285363ff35f4f2304ce8c92db401122ec43db9a" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/CoreELEC/rtkbt-firmware-aml" +PKG_URL="https://github.com/CoreELEC/rtkbt-firmware-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain rtk_hciattach" +PKG_LONGDESC="Realtek BT Linux firmware" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + FWDIR=$INSTALL/$(get_full_firmware_dir)/rtlbt + + mkdir -p $FWDIR + cp -a $PKG_BUILD/* $FWDIR +} diff --git a/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/system.d/rtkbt-firmware-aml.service b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/system.d/rtkbt-firmware-aml.service new file mode 100644 index 000000000..284cc4744 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/system.d/rtkbt-firmware-aml.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS1 to BlueZ stack using rtk_h5 type +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/rtk_hciattach -n -s 115200 /dev/ttyS1 rtk_h5 +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/udev.d/80-rtkbt-firmware-aml.rules b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/udev.d/80-rtkbt-firmware-aml.rules new file mode 100644 index 000000000..e13046e7f --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtkbt-firmware-aml/udev.d/80-rtkbt-firmware-aml.rules @@ -0,0 +1,11 @@ +################################################################################ +# udev rules file for loading realtek bt firmware +################################################################################ + +ACTION!="add", GOTO="end" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xb723", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rtkbt-firmware-aml.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xb822", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rtkbt-firmware-aml.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xc822", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rtkbt-firmware-aml.service" +GOTO="end" + +LABEL="end" diff --git a/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/package.mk b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/package.mk new file mode 100644 index 000000000..f3510e831 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rtl8723bs_bt" +PKG_VERSION="09eb91f" +PKG_SHA256="4bb8483c4a14a9e0dfc4a6ddca18486caab5f361be2441b91e9e2a399ca9f33e" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lwfinger/rtl8723bs_bt" +PKG_URL="https://github.com/lwfinger/rtl8723bs_bt/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="rtl8723bs_bt Linux firmware" diff --git a/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch new file mode 100644 index 000000000..e4296c08e --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-001-Makefile.patch @@ -0,0 +1,26 @@ +diff --git a/Makefile b/Makefile +index 52506b9..fd196f3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,12 +1,15 @@ + rtk_hciattach:hciattach.c hciattach_rtk.o +- cc -o rtk_hciattach hciattach.c hciattach_rtk.o ++ $(CC) $(CFLAGS) $(LDFLAGS) -o rtk_hciattach hciattach.c hciattach_rtk.o + + hciattach_rtk.o:hciattach_rtk.c +- cc -c hciattach_rtk.c ++ $(CC) $(CFLAGS) $(LDFLAGS) -c hciattach_rtk.c + +-clean: +- rm -f *.o rtk_hciattach ++all: ++ rtk_hciattach + + install: +- mkdir -p /lib/firmware/rtl_bt +- cp -p rtlbt_* /lib/firmware/rtl_bt/. ++ mkdir -p $(DESTDIR)/usr/bin ++ cp -P rtk_hciattach $(DESTDIR)/usr/bin ++ ++clean: ++ rm -f *.o rtk_hciattach diff --git a/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch new file mode 100644 index 000000000..cc57fbe37 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/patches/rtl8723bs_bt-002-firmware_path.patch @@ -0,0 +1,20 @@ +--- a/hciattach_rtk.c 2016-07-18 00:47:52.000000000 +0100 ++++ b/hciattach_rtk.c 2017-12-15 04:27:39.481299996 +0000 +@@ -1419,7 +1419,7 @@ + int ret = 0; + struct stat st; + +- ret = sprintf(firmware_file_name, FIRMWARE_DIRECTORY"rtlbt_fw"); ++ ret = sprintf(firmware_file_name, FIRMWARE_DIRECTORY"rtl8723b_fw"); + + return firmware_file_name; + } +@@ -1504,7 +1504,7 @@ + int ret = 0; + int i = 0; + +- ret = sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY"rtlbt_config"); ++ ret = sprintf(bt_config_file_name, BT_CONFIG_DIRECTORY"rtl8723b_config"); + if (stat(bt_config_file_name, &st) < 0) { + RS_ERR("can't access bt config file:%s, errno:%d\n", bt_config_file_name, errno); + return -1; diff --git a/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service new file mode 100644 index 000000000..61a15f0b9 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/system.d/rtl8723bs_bt-firmware.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS1 to BlueZ stack +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/rtk_hciattach -n -s 115200 /dev/ttyS1 rtk_h5 2000000 +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules new file mode 100644 index 000000000..742f49cd3 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8723bs_bt/udev.d/80-rtl8723_bt.rules @@ -0,0 +1,9 @@ +################################################################################ +# udev rules file for loading rtl8723bs_bt-firmware +################################################################################ + +ACTION!="add", GOTO="end" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xb723", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rtl8723bs_bt-firmware.service" +GOTO="end" + +LABEL="end" diff --git a/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/package.mk b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/package.mk new file mode 100644 index 000000000..ff917b20e --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="rtl8822b_bt" +PKG_VERSION="4dfa50ab6150aa51a6e03bbcd479c8d2e68bfa2b" +PKG_SHA256="bf9205c4ac1a5893cdbd3ca98ab82e5636244fef50e375fc0148a3db7153fe51" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/ChalesYu/rtl8822bs-aml" +PKG_URL="https://github.com/ChalesYu/rtl8822bs-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain rkbin" +PKG_LONGDESC="RTL8822B BT Linux firmware" +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p $PKG_BUILD + tar --strip-components=2 -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz -C $PKG_BUILD rtl8822bs-aml-$PKG_VERSION/bluetooth +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp -a $(get_build_dir rkbin)/firmware/bin/rtk_hciattach $INSTALL/usr/bin/8822b_hciattach + + mkdir -p $INSTALL/$(get_full_firmware_dir)/rtlbt + cp -a $PKG_BUILD/rtl8822b_config.bin $INSTALL/$(get_full_firmware_dir)/rtlbt/rtl8822b_config + cp -a $PKG_BUILD/rtl8822b_fw.bin $INSTALL/$(get_full_firmware_dir)/rtlbt/rtl8822b_fw +} diff --git a/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/system.d/rtl8822b_bt-firmware.service b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/system.d/rtl8822b_bt-firmware.service new file mode 100644 index 000000000..981d3546d --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/system.d/rtl8822b_bt-firmware.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS1 to BlueZ stack +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS1.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/8822b_hciattach -n -s 115200 /dev/ttyS1 rtk_h5 +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/udev.d/80-rtl8822b_bt.rules b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/udev.d/80-rtl8822b_bt.rules new file mode 100644 index 000000000..638037666 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/rtl8822b_bt/udev.d/80-rtl8822b_bt.rules @@ -0,0 +1,9 @@ +################################################################################ +# udev rules file for loading rtl8822b_bt-firmware +################################################################################ + +ACTION!="add", GOTO="end" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xb822", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rtl8822b_bt-firmware.service" +GOTO="end" + +LABEL="end" diff --git a/packages/kernel/linux-firmware/amlogic/wlan-firmware-aml/package.mk b/packages/kernel/linux-firmware/amlogic/wlan-firmware-aml/package.mk new file mode 100644 index 000000000..827428035 --- /dev/null +++ b/packages/kernel/linux-firmware/amlogic/wlan-firmware-aml/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wlan-firmware-aml" +PKG_VERSION="5f5fae7" +PKG_SHA256="a926edbd87b028afcf8048c776859fa2bf0dca006df6a0f6867ce3915bd21494" +PKG_LICENSE="Free-to-use" +PKG_SITE="http://openlinux.amlogic.com:8000/download/ARM/wifi/" +PKG_URL="https://github.com/openwetek/wlan-firmware-aml/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="wlan-firmware-aml: Firmware for various WLAN chips used in the devices based on Amlogic SoCs" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_firmware_dir)/brcm + + # AP6210 + cp -PR bcm_ampak/config/AP6210/Wi-Fi/fw_bcm40181a2*.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/AP6210/Wi-Fi/nvram_ap6210.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/AP6210/BT/bcm20710a1.hcd $INSTALL/$(get_full_firmware_dir)/brcm + + # AP6255 + cp -PR bcm_ampak/config/6255/fw_bcm43455c0_*.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/6255/nvram.txt $INSTALL/$(get_full_firmware_dir)/brcm/nvram_ap6255.txt + cp -P bcm_ampak/config/6255/BT/BCM4345C0.hcd $INSTALL/$(get_full_firmware_dir)/brcm/bcm4345c0.hcd + + # AP6330 + cp -PR bcm_ampak/config/AP6330/Wi-Fi/fw_bcm40183b2*.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/AP6330/Wi-Fi/nvram_ap6330.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/AP6330/BT/bcm40183b2.hcd $INSTALL/$(get_full_firmware_dir)/brcm + + # AP6335 + cp -PR bcm_ampak/config/6335/fw_bcm4339a0_*.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -P bcm_ampak/config/6335/nvram.txt $INSTALL/$(get_full_firmware_dir)/brcm/nvram_ap6335.txt + cp -P bcm_ampak/config/6335/BT/bcm4335c0.hcd $INSTALL/$(get_full_firmware_dir)/brcm +} diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/package.mk b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/package.mk new file mode 100644 index 000000000..6731f6cf3 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="brcmfmac_sdio-firmware-imx" +PKG_VERSION="0.1" +PKG_SHA256="4c8ed8ae39ecd05d7e3aeebc98cf230912cdcc887fa78d5112f981b6f9358b6e" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/LibreELEC/LibreELEC.tv" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Firmware for brcm bluetooth chips used in some Freescale iMX based devices." + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp -av brcm_patchram_plus $INSTALL/usr/bin/ + + mkdir -p $INSTALL/$(get_kernel_overlay_dir)/lib/firmware/ + cp -av firmware/brcm $INSTALL/$(get_kernel_overlay_dir)/lib/firmware/ +} diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/system.d/brcmfmac_sdio-firmware@.service b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/system.d/brcmfmac_sdio-firmware@.service new file mode 100644 index 000000000..fb06133cf --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/system.d/brcmfmac_sdio-firmware@.service @@ -0,0 +1,8 @@ +[Unit] +Description=Broadcom sdio firmware update for %I +ConditionPathExists=/dev/ttymxc3 + +[Service] +Type=simple +RemainAfterExit=yes +ExecStart=/usr/bin/brcm_patchram_plus --patchram /lib/firmware/brcm/%I.hcd --baudrate 3000000 --use_baudrate_for_download /dev/ttymxc3 --enable_hci --no2bytes --tosleep=50000 diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/udev.d/80-brcmfmac_sdio.rules b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/udev.d/80-brcmfmac_sdio.rules new file mode 100644 index 000000000..e29b8e152 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-imx/udev.d/80-brcmfmac_sdio.rules @@ -0,0 +1,19 @@ +################################################################################ +# udev rules file for loading brcmfmac_sdio-firmware +################################################################################ + +ACTION!="add", GOTO="end" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4329", GOTO="begin" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4330", GOTO="begin" +GOTO="end" +LABEL="begin" +### Broadcom bcm4330 bluetooth device +ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4330", \ + ENV{brcm_device}="bcm4330" +### Broadcom bcm4329 bluetooth device +ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4329", \ + ENV{brcm_device}="bcm4329" + +ENV{brcm_device}=="bcm43*", ACTION=="add", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="brcmfmac_sdio-firmware@$env{brcm_device}.service" +LABEL="end" diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/package.mk b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/package.mk new file mode 100644 index 000000000..e02adc11c --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="brcmfmac_sdio-firmware-rpi" +PKG_VERSION="688531da4bcf802a814d9cb0c8b6d62e3b8a3327" +PKG_SHA256="51a33d23127300dffd6ac088f372b83ab862053f5e4dc7130676ebaaa824e626" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/LibreELEC/LibreELEC.tv" +PKG_URL="https://github.com/LibreELEC/$PKG_NAME/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Firmware for brcm bluetooth chips used on RaspberryPi devices." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install +} + +post_makeinstall_target() { + # Install rpi btuart script to bring up Bluetooth + mkdir -p $INSTALL/usr/bin + cp -P $PKG_DIR/scripts/rpi-btuart $INSTALL/usr/bin +} + +post_install() { + enable_service brcmfmac_sdio-firmware.service +} diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/scripts/rpi-btuart b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/scripts/rpi-btuart new file mode 100755 index 000000000..b9c6cee09 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/scripts/rpi-btuart @@ -0,0 +1,26 @@ +#!/bin/sh + +HCIATTACH=/usr/bin/hciattach +if grep -q "Pi 4" /proc/device-tree/model; then + BDADDR= +else + SERIAL=$(cat /proc/device-tree/serial-number | cut -c9-) + B1=${SERIAL:2:2} + B2=${SERIAL:4:2} + B3=${SERIAL:6:2} + BDADDR=$(printf b8:27:eb:%02x:%02x:%02x $((0x$B1 ^ 0xaa)) $((0x$B2 ^ 0xaa)) $((0x$B3 ^ 0xaa))) +fi + +uart0="$(cat /proc/device-tree/aliases/uart0)" +serial1="$(cat /proc/device-tree/aliases/serial1)" + +if [ "$uart0" = "$serial1" ] ; then + uart0_pins="$(wc -c /proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm\,pins | cut -f 1 -d ' ')" + if [ "$uart0_pins" = "16" ] ; then + $HCIATTACH /dev/serial1 bcm43xx 3000000 flow - $BDADDR + else + $HCIATTACH /dev/serial1 bcm43xx 921600 noflow - $BDADDR + fi +else + $HCIATTACH /dev/serial1 bcm43xx 460800 noflow - $BDADDR +fi diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/system.d/brcmfmac_sdio-firmware.service b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/system.d/brcmfmac_sdio-firmware.service new file mode 100644 index 000000000..97809c744 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/system.d/brcmfmac_sdio-firmware.service @@ -0,0 +1,13 @@ +[Unit] +Description=Broadcom sdio firmware update for BCM43430A1 +ConditionFileNotEmpty=/proc/device-tree/soc/gpio@7e200000/bt_pins/brcm,pins +Requires=dev-serial1.device +After=dev-serial1.device network.target + +[Service] +Type=simple +RemainAfterExit=yes +ExecStart=/usr/bin/rpi-btuart + +[Install] +WantedBy=network.target diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/udev.d/90-rpi-add-serial.rules b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/udev.d/90-rpi-add-serial.rules new file mode 100755 index 000000000..334bd37d4 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware-rpi/udev.d/90-rpi-add-serial.rules @@ -0,0 +1,21 @@ +KERNEL=="ttyAMA[01]", PROGRAM="/bin/sh -c '\ + ALIASES=/proc/device-tree/aliases; \ + if [ $(cat $ALIASES/uart0) = $(cat $ALIASES/serial0) ]; then \ + echo 0;\ + elif [ $(cat $ALIASES/uart0) = $(cat $ALIASES/serial1) ]; then \ + echo 1; \ + else \ + exit 1; \ + fi\ + '", SYMLINK+="serial%c" + +KERNEL=="ttyS0", PROGRAM="/bin/sh -c '\ + ALIASES=/proc/device-tree/aliases; \ + if [ $(cat $ALIASES/uart1) = $(cat $ALIASES/serial0) ]; then \ + echo 0; \ + elif [ $(cat $ALIASES/uart1) = $(cat $ALIASES/serial1) ]; then \ + echo 1; \ + else \ + exit 1; \ + fi \ + '", SYMLINK+="serial%c" diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/firmwares/any.dat b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/firmwares/any.dat new file mode 100644 index 000000000..72e8ffc0d --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/firmwares/any.dat @@ -0,0 +1 @@ +* diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/package.mk b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/package.mk new file mode 100644 index 000000000..6b7a22c84 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/package.mk @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="brcmfmac_sdio-firmware" +PKG_VERSION="79932201f7827ec06ec708a44bf583a772ae7522" +PKG_SHA256="b31665e3b0dfd595234241ef233e47f2e12312ce019c9b5c2e02919d0b2ddbc0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/LibreELEC/brcmfmac_sdio-firmware" +PKG_URL="https://github.com/LibreELEC/brcmfmac_sdio-firmware/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Broadcom SDIO firmware used with LibreELEC" +PKG_TOOLCHAIN="manual" + +post_makeinstall_target() { + FW_TARGET_DIR=$INSTALL/$(get_full_firmware_dir) + + if find_file_path firmwares/$PKG_NAME.dat; then + FW_LISTS="${FOUND_PATH}" + else + FW_LISTS="${PKG_DIR}/firmwares/any.dat ${PKG_DIR}/firmwares/${TARGET_ARCH}.dat" + fi + + for fwlist in ${FW_LISTS}; do + [ -f ${fwlist} ] || continue + while read -r fwline; do + [ -z "${fwline}" ] && continue + [[ ${fwline} =~ ^#.* ]] && continue + [[ ${fwline} =~ ^[[:space:]] ]] && continue + + for fwfile in $(cd ${PKG_BUILD} && eval "find ${fwline}"); do + [ -d ${PKG_BUILD}/${fwfile} ] && continue + if [ -f ${PKG_BUILD}/${fwfile} ]; then + mkdir -p $(dirname ${FW_TARGET_DIR}/brcm/${fwfile}) + cp -Lv ${PKG_BUILD}/${fwfile} ${FW_TARGET_DIR}/brcm/${fwfile} + else + echo "ERROR: Firmware file ${fwfile} does not exist - aborting" + exit 1 + fi + done + done < ${fwlist} + done + + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/brcmfmac-firmware-setup $INSTALL/usr/bin +} + +post_install() { + enable_service brcmfmac-firmware.service +} diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/scripts/brcmfmac-firmware-setup b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/scripts/brcmfmac-firmware-setup new file mode 100755 index 000000000..7754cd86b --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/scripts/brcmfmac-firmware-setup @@ -0,0 +1,12 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +DTNAME=$(/usr/bin/dtname) + +if [ "$DTNAME" = "khadas,vim" -o "$DTNAME" = "xunlong,orangepi-win" ]; then + ln -sf /usr/lib/kernel-overlays/base/lib/firmware/brcm/BCM43430A1.vim /usr/lib/firmware/brcm/BCM43430A1.hcd +else + ln -sf /usr/lib/kernel-overlays/base/lib/firmware/brcm/BCM43430A1.def /usr/lib/firmware/brcm/BCM43430A1.hcd +fi diff --git a/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/system.d/brcmfmac-firmware.service b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/system.d/brcmfmac-firmware.service new file mode 100644 index 000000000..062207fd0 --- /dev/null +++ b/packages/kernel/linux-firmware/brcmfmac_sdio-firmware/system.d/brcmfmac-firmware.service @@ -0,0 +1,11 @@ +[Unit] +Description=Broadcom SDIO Firmware Symlink Service +After=kernel-overlays.service +Before=kodi.service + +[Service] +Type=oneshot +ExecStart=/bin/sh -c "/usr/bin/brcmfmac-firmware-setup" + +[Install] +WantedBy=local-fs.target diff --git a/packages/kernel/linux-firmware/dvb-firmware/package.mk b/packages/kernel/linux-firmware/dvb-firmware/package.mk new file mode 100644 index 000000000..da4447d18 --- /dev/null +++ b/packages/kernel/linux-firmware/dvb-firmware/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="dvb-firmware" +PKG_VERSION="1.4.0" +PKG_SHA256="8831e5e9c88e343742083f62bd28ad56b8cbd21bb9fe730ed1c292f6689fe2c3" +PKG_LICENSE="Free-to-use" +PKG_SITE="https://github.com/CoreELEC/dvb-firmware" +PKG_URL="https://github.com/CoreELEC/dvb-firmware/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="dvb-firmware: firmwares for various DVB drivers" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + PKG_FW_DIR="$INSTALL/$(get_kernel_overlay_dir)/lib/firmware" + mkdir -p "$PKG_FW_DIR" + cp -a "$PKG_BUILD/firmware/"* "$PKG_FW_DIR" +} diff --git a/packages/kernel/linux-firmware/firmware-imx/package.mk b/packages/kernel/linux-firmware/firmware-imx/package.mk new file mode 100644 index 000000000..89dd714ef --- /dev/null +++ b/packages/kernel/linux-firmware/firmware-imx/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="firmware-imx" +PKG_VERSION="5.4" +PKG_SHA256="c5bd4bff48cce9715a5d6d2c190ff3cd2262c7196f7facb9b0eda231c92cc223" +PKG_ARCH="arm" +PKG_LICENSE="other" +PKG_SITE="http://www.freescale.com" +PKG_URL="http://www.nxp.com/lgfiles/NMG/MAD/YOCTO/${PKG_NAME}-${PKG_VERSION}.bin" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="firmware-imx: Freescale IMX firmware such as for the VPU" +PKG_TOOLCHAIN="manual" + +unpack() { + cd $(dirname $PKG_BUILD) + sh $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.bin --auto-accept +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_firmware_dir)/vpu + cp -P firmware/vpu/vpu_fw_imx6d.bin $INSTALL/$(get_full_firmware_dir)/vpu + cp -P firmware/vpu/vpu_fw_imx6q.bin $INSTALL/$(get_full_firmware_dir)/vpu +} diff --git a/packages/kernel/linux-firmware/intel-ucode/package.mk b/packages/kernel/linux-firmware/intel-ucode/package.mk new file mode 100644 index 000000000..c603ce244 --- /dev/null +++ b/packages/kernel/linux-firmware/intel-ucode/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="intel-ucode" +PKG_VERSION="20190514" +PKG_SHA256="553858de4315d267d1f259d1146db028eec5112a797379a7a83f5c8a22e626b3" +PKG_ARCH="x86_64" +PKG_LICENSE="other" +PKG_SITE="https://downloadcenter.intel.com/search?keyword=linux+microcode" +PKG_URL="https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/archive/microcode-${PKG_VERSION}.tar.gz" +PKG_LONGDESC="intel-ucode: Intel CPU microcodes" +PKG_TOOLCHAIN="manual" diff --git a/packages/kernel/linux-firmware/intel-ucode/sources/intel-microcode2ucode.c b/packages/kernel/linux-firmware/intel-ucode/sources/intel-microcode2ucode.c new file mode 100644 index 000000000..c1660fae3 --- /dev/null +++ b/packages/kernel/linux-firmware/intel-ucode/sources/intel-microcode2ucode.c @@ -0,0 +1,154 @@ +/* + * Convert Intel microcode.dat into a single binary microcode.bin file + * + * Based on code by Kay Sievers + * Changed to create a single file by Thomas Bächler + */ + + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct microcode_header_intel { + unsigned int hdrver; + unsigned int rev; + unsigned int date; + unsigned int sig; + unsigned int cksum; + unsigned int ldrver; + unsigned int pf; + unsigned int datasize; + unsigned int totalsize; + unsigned int reserved[3]; +}; + +union mcbuf { + struct microcode_header_intel hdr; + unsigned int i[0]; + char c[0]; +}; + +int main(int argc, char *argv[]) +{ + const char *filename = "/lib/firmware/microcode.dat"; + FILE *f; + char line[LINE_MAX]; + char buf[4000000]; + union mcbuf *mc; + size_t bufsize, count, start; + int rc = EXIT_SUCCESS; + + if (argv[1] != NULL) + filename = argv[1]; + + count = 0; + mc = (union mcbuf *) buf; + f = fopen(filename, "re"); + if (f == NULL) { + printf("open %s: %m\n", filename); + rc = EXIT_FAILURE; + goto out; + } + + while (fgets(line, sizeof(line), f) != NULL) { + if (sscanf(line, "%x, %x, %x, %x", + &mc->i[count], + &mc->i[count + 1], + &mc->i[count + 2], + &mc->i[count + 3]) != 4) + continue; + count += 4; + } + fclose(f); + + bufsize = count * sizeof(int); + printf("%s: %lu(%luk) bytes, %zu integers\n", + filename, + bufsize, + bufsize / 1024, + count); + + if (bufsize < sizeof(struct microcode_header_intel)) + goto out; + + f = fopen("microcode.bin", "we"); + if (f == NULL) { + printf("open microcode.bin: %m\n"); + rc = EXIT_FAILURE; + goto out; + } + + start = 0; + for (;;) { + size_t size; + unsigned int family, model, stepping; + unsigned int year, month, day; + + mc = (union mcbuf *) &buf[start]; + + if (mc->hdr.totalsize) + size = mc->hdr.totalsize; + else + size = 2000 + sizeof(struct microcode_header_intel); + + if (mc->hdr.ldrver != 1 || mc->hdr.hdrver != 1) { + printf("unknown version/format:\n"); + rc = EXIT_FAILURE; + break; + } + + /* + * 0- 3 stepping + * 4- 7 model + * 8-11 family + * 12-13 type + * 16-19 extended model + * 20-27 extended family + */ + family = (mc->hdr.sig >> 8) & 0xf; + if (family == 0xf) + family += (mc->hdr.sig >> 20) & 0xff; + model = (mc->hdr.sig >> 4) & 0x0f; + if (family == 0x06) + model += ((mc->hdr.sig >> 16) & 0x0f) << 4; + stepping = mc->hdr.sig & 0x0f; + + year = mc->hdr.date & 0xffff; + month = mc->hdr.date >> 24; + day = (mc->hdr.date >> 16) & 0xff; + + printf("\n"); + printf("signature: 0x%02x\n", mc->hdr.sig); + printf("flags: 0x%02x\n", mc->hdr.pf); + printf("revision: 0x%02x\n", mc->hdr.rev); + printf("date: %04x-%02x-%02x\n", year, month, day); + printf("size: %zu\n", size); + + if (fwrite(mc, size, 1, f) != 1) { + printf("write microcode.bin: %m\n"); + rc = EXIT_FAILURE; + goto out; + } + + start += size; + if (start >= bufsize) + break; + } + fclose(f); + printf("\n"); +out: + return rc; +} diff --git a/packages/kernel/linux-firmware/iwlwifi-firmware/package.mk b/packages/kernel/linux-firmware/iwlwifi-firmware/package.mk new file mode 100644 index 000000000..fd2001e6e --- /dev/null +++ b/packages/kernel/linux-firmware/iwlwifi-firmware/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="iwlwifi-firmware" +PKG_VERSION="19ce5372ff369fe90ba70a0b8ef7e4ffa80a068b" +PKG_SHA256="26b09c74ff5bb19eb1891e1f150759cd3cae10dce3a167fc120f3c81276cac95" +PKG_LICENSE="Free-to-use" +PKG_SITE="https://github.com/LibreELEC/iwlwifi-firmware" +PKG_URL="https://github.com/LibreELEC/iwlwifi-firmware/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="iwlwifi-firmware: firmwares for various Intel WLAN drivers" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install +} diff --git a/packages/kernel/linux-firmware/kernel-firmware/firmwares/any.dat b/packages/kernel/linux-firmware/kernel-firmware/firmwares/any.dat new file mode 100644 index 000000000..f11d145b4 --- /dev/null +++ b/packages/kernel/linux-firmware/kernel-firmware/firmwares/any.dat @@ -0,0 +1,22 @@ +#aarch64 +htc_7010.fw +htc_9271.fw + +ath3k-1.fw +ar5523.bin +carl9170-1.fw +rt2870.bin +rt73.bin +vntwusb.fw + +#mediatek +mt7601u.bin +mt7662*.bin +mediatek/mt7662u*.bin +mediatek/mt7610u.bin + +ath6k/AR6004/hw1.?/bdata.bin +ath9k_htc/* +brcm/* +rtl_bt/* +rtlwifi/* diff --git a/packages/kernel/linux-firmware/kernel-firmware/firmwares/x86_64.dat b/packages/kernel/linux-firmware/kernel-firmware/firmwares/x86_64.dat new file mode 100644 index 000000000..65a8932f8 --- /dev/null +++ b/packages/kernel/linux-firmware/kernel-firmware/firmwares/x86_64.dat @@ -0,0 +1,13 @@ +ath10k/* +ctefx.bin +lbtf_usb.bin +rt2561.bin +rt2561s.bin +rt2661.bin +rt2860.bin +rt3290.bin +ar3k/*.dfu +intel/dsp_fw_{bxtn,cnl,glk,kbl,release}.bin +intel/fw_sst_*.bin* +intel/ibt-*.{ddc,sfi,bseq} +intel/IntcSST2.bin diff --git a/packages/kernel/linux-firmware/kernel-firmware/package.mk b/packages/kernel/linux-firmware/kernel-firmware/package.mk new file mode 100644 index 000000000..4de574275 --- /dev/null +++ b/packages/kernel/linux-firmware/kernel-firmware/package.mk @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kernel-firmware" +PKG_VERSION="20211216" +PKG_LICENSE="other" +PKG_SITE="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/" +PKG_URL="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/snapshot/linux-firmware-$PKG_VERSION.tar.gz" +PKG_NEED_UNPACK="${PROJECT_DIR}/${PROJECT}/packages/${PKG_NAME} ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/packages/${PKG_NAME}" +PKG_LONGDESC="kernel-firmware: kernel related firmware" +PKG_TOOLCHAIN="manual" + +# Install additional miscellaneous drivers +makeinstall_target() { + FW_TARGET_DIR=$INSTALL/$(get_full_firmware_dir) + + if find_file_path config/kernel-firmware.dat; then + FW_LISTS="${FOUND_PATH}" + else + FW_LISTS="${PKG_DIR}/firmwares/any.dat ${PKG_DIR}/firmwares/${TARGET_ARCH}.dat" + fi + + FW_LISTS+=" ${PROJECT_DIR}/${PROJECT}/config/kernel-firmware-any.dat ${PROJECT_DIR}/${PROJECT}/config/kernel-firmware-${TARGET_ARCH}.dat" + + FW_LISTS+=" ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/config/kernel-firmware-any.dat ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/config/kernel-firmware-${TARGET_ARCH}.dat" + + for fwlist in ${FW_LISTS}; do + [ -f "${fwlist}" ] || continue + + while read -r fwline; do + [ -z "${fwline}" ] && continue + [[ ${fwline} =~ ^#.* ]] && continue + [[ ${fwline} =~ ^[[:space:]] ]] && continue + + while read -r fwfile; do + [ -d "${PKG_BUILD}/${fwfile}" ] && continue + + if [ -f "${PKG_BUILD}/${fwfile}" ]; then + mkdir -p "$(dirname "${FW_TARGET_DIR}/${fwfile}")" + cp -Lv "${PKG_BUILD}/${fwfile}" "${FW_TARGET_DIR}/${fwfile}" + else + echo "ERROR: Firmware file ${fwfile} does not exist - aborting" + exit 1 + fi + done <<< "$(cd ${PKG_BUILD} && eval "find "${fwline}"")" + done < "${fwlist}" + done + + PKG_KERNEL_CFG_FILE=$(kernel_config_path) || die + + # The following files are RPi specific and installed by brcmfmac_sdio-firmware-rpi instead. + # They are also not required at all if the kernel is not suitably configured. + if listcontains "${FIRMWARE}" "brcmfmac_sdio-firmware-rpi" || \ + ! grep -q "^CONFIG_BRCMFMAC_SDIO=y" ${PKG_KERNEL_CFG_FILE}; then + rm -fr $FW_TARGET_DIR/brcm/brcmfmac43430*-sdio.* + rm -fr $FW_TARGET_DIR/brcm/brcmfmac43455*-sdio.* + fi + + # brcm pcie firmware is only needed by x86_64 + [ "$TARGET_ARCH" != "x86_64" ] && rm -fr $FW_TARGET_DIR/brcm/*-pcie.* + + # Cleanup - which may be project or device specific + find_file_path scripts/cleanup.sh && ${FOUND_PATH} ${FW_TARGET_DIR} || true +} diff --git a/packages/kernel/linux-firmware/kernel-firmware/patches/kernel-firmware-02-add-brcmfmac-43xxx-configs.patch b/packages/kernel/linux-firmware/kernel-firmware/patches/kernel-firmware-02-add-brcmfmac-43xxx-configs.patch new file mode 100644 index 000000000..493745205 --- /dev/null +++ b/packages/kernel/linux-firmware/kernel-firmware/patches/kernel-firmware-02-add-brcmfmac-43xxx-configs.patch @@ -0,0 +1,188 @@ +From 1e6e0b28cd5b3e621e012169563d45748734b721 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Thu, 29 Nov 2018 23:47:02 +0000 +Subject: [PATCH] add missing brcmfmac434[30,55]-sdio.txt config files + +--- + brcm/brcmfmac43430-sdio.txt | 64 ++++++++++++++++++++++++++++++ + brcm/brcmfmac43455-sdio.txt | 97 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 161 insertions(+) + create mode 100644 brcm/brcmfmac43430-sdio.txt + create mode 100644 brcm/brcmfmac43455-sdio.txt + +diff --git a/brcm/brcmfmac43430-sdio.txt b/brcm/brcmfmac43430-sdio.txt +new file mode 100644 +index 0000000..e644e6a +--- /dev/null ++++ b/brcm/brcmfmac43430-sdio.txt +@@ -0,0 +1,64 @@ ++# NVRAM file for BCM943430WLSELG ++# 2.4 GHz, 20 MHz BW mode ++ ++# The following parameter values are just placeholders, need to be updated. ++manfid=0x2d0 ++prodid=0x0726 ++vendid=0x14e4 ++devid=0x43e2 ++boardtype=0x0726 ++boardrev=0x1202 ++boardnum=22 ++macaddr=00:90:4c:c5:12:38 ++sromrev=11 ++boardflags=0x00404201 ++boardflags3=0x08000000 ++xtalfreq=37400 ++#xtalfreq=19200 ++nocrc=1 ++ag0=255 ++aa2g=1 ++ccode=ALL ++ ++pa0itssit=0x20 ++extpagain2g=0 ++ ++#PA parameters for 2.4GHz, measured at CHIP OUTPUT ++pa2ga0=-168,7161,-820 ++AvVmid_c0=0x0,0xc8 ++cckpwroffset0=5 ++ ++# PPR params ++maxp2ga0=84 ++txpwrbckof=6 ++cckbw202gpo=0 ++legofdmbw202gpo=0x66111111 ++mcsbw202gpo=0x77711111 ++propbw202gpo=0xdd ++ ++# OFDM IIR : ++ofdmdigfilttype=18 ++ofdmdigfilttypebe=18 ++# PAPD mode: ++papdmode=1 ++papdvalidtest=1 ++pacalidx2g=32 ++papdepsoffset=-36 ++papdendidx=61 ++ ++il0macaddr=00:90:4c:c5:12:38 ++wl0id=0x431b ++ ++deadman_to=0xffffffff ++# muxenab: 0x1 for UART enable, 0x2 for GPIOs, 0x8 for JTAG ++muxenab=0x1 ++# CLDO PWM voltage settings - 0x4 - 1.1 volt ++#cldo_pwm=0x4 ++ ++#VCO freq 326.4MHz ++spurconfig=0x3 ++ ++# Experimental Bluetooth coexistence parameters from Cypress ++btc_mode=1 ++btc_params8=0x4e20 ++btc_params1=0x7530 +diff --git a/brcm/brcmfmac43455-sdio.txt b/brcm/brcmfmac43455-sdio.txt +new file mode 100644 +index 0000000..04b6570 +--- /dev/null ++++ b/brcm/brcmfmac43455-sdio.txt +@@ -0,0 +1,97 @@ ++# Cloned from bcm94345wlpagb_p2xx.txt ++NVRAMRev=$Rev: 498373 $ ++sromrev=11 ++vendid=0x14e4 ++devid=0x43ab ++manfid=0x2d0 ++prodid=0x06e4 ++#macaddr=00:90:4c:c5:12:38 ++macaddr=b8:27:eb:74:f2:6c ++nocrc=1 ++boardtype=0x6e4 ++boardrev=0x1304 ++ ++#XTAL 37.4MHz ++xtalfreq=37400 ++ ++btc_mode=1 ++#------------------------------------------------------ ++#boardflags: 5GHz eTR switch by default ++# 2.4GHz eTR switch by default ++# bit1 for btcoex ++boardflags=0x00480201 ++boardflags2=0x40800000 ++boardflags3=0x48200100 ++phycal_tempdelta=15 ++rxchain=1 ++txchain=1 ++aa2g=1 ++aa5g=1 ++tssipos5g=1 ++tssipos2g=1 ++femctrl=0 ++AvVmid_c0=1,165,2,100,2,100,2,100,2,100 ++pa2ga0=-129,6525,-718 ++pa2ga1=-149,4408,-601 ++pa5ga0=-185,6836,-815,-186,6838,-815,-184,6859,-815,-184,6882,-818 ++pa5ga1=-202,4285,-574,-201,4312,-578,-196,4391,-586,-201,4294,-575 ++itrsw=1 ++pdoffsetcckma0=2 ++pdoffset2gperchan=0,-2,1,0,1,0,1,1,1,0,0,-1,-1,0 ++pdoffset2g40ma0=16 ++pdoffset40ma0=0x8888 ++pdoffset80ma0=0x8888 ++extpagain5g=2 ++extpagain2g=2 ++tworangetssi2g=1 ++tworangetssi5g=1 ++# LTECX flags ++# WCI2 ++ltecxmux=0 ++ltecxpadnum=0x0504 ++ltecxfnsel=0x22 ++ltecxgcigpio=0x32 ++ ++maxp2ga0=80 ++ofdmlrbw202gpo=0x0022 ++dot11agofdmhrbw202gpo=0x4442 ++mcsbw202gpo=0x98444422 ++mcsbw402gpo=0x98444422 ++maxp5ga0=82,82,82,82 ++mcsbw205glpo=0xb9555000 ++mcsbw205gmpo=0xb9555000 ++mcsbw205ghpo=0xb9555000 ++mcsbw405glpo=0xb9555000 ++mcsbw405gmpo=0xb9555000 ++mcsbw405ghpo=0xb9555000 ++mcsbw805glpo=0xb9555000 ++mcsbw805gmpo=0xb9555000 ++mcsbw805ghpo=0xb9555000 ++ ++swctrlmap_2g=0x00000000,0x00000000,0x00000000,0x010000,0x3ff ++swctrlmap_5g=0x00100010,0x00200020,0x00200020,0x010000,0x3fe ++swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x3 ++swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x3 ++ ++vcodivmode=1 ++deadman_to=481500000 ++ ++ed_thresh2g=-54 ++ed_thresh5g=-54 ++eu_edthresh2g=-54 ++eu_edthresh5g=-54 ++ldo1=4 ++rawtempsense=0x1ff ++cckPwrIdxCorr=3 ++cckTssiDelay=150 ++ofdmTssiDelay=150 ++txpwr2gAdcScale=1 ++txpwr5gAdcScale=1 ++dot11b_opts=0x3aa85 ++cbfilttype=1 ++fdsslevel_ch11=6 ++ ++# Experimental Bluetooth coexistence parameters from Cypress ++btc_mode=1 ++btc_params8=0x4e20 ++btc_params1=0x7530 +-- +2.14.1 + diff --git a/packages/kernel/linux-firmware/misc-firmware/package.mk b/packages/kernel/linux-firmware/misc-firmware/package.mk new file mode 100644 index 000000000..e186cb18b --- /dev/null +++ b/packages/kernel/linux-firmware/misc-firmware/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="misc-firmware" +PKG_VERSION="9dd2a25" +PKG_SHA256="8788d153cbee0bfd9998aed4cf2e015b373529d4b9c2c35325a08ef390855ec6" +PKG_LICENSE="Free-to-use" +PKG_SITE="https://github.com/LibreELEC/misc-firmware" +PKG_URL="https://github.com/LibreELEC/misc-firmware/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain kernel-firmware" +PKG_LONGDESC="misc-firmware: firmwares for various drivers" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install +} diff --git a/packages/kernel/linux-firmware/rockchip-firmware/modprobe.d/bcmdhd.conf b/packages/kernel/linux-firmware/rockchip-firmware/modprobe.d/bcmdhd.conf new file mode 100644 index 000000000..724420a89 --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/modprobe.d/bcmdhd.conf @@ -0,0 +1 @@ +options bcmdhd firmware_path=/lib/firmware/brcm/ nvram_path=/lib/firmware/brcm/ diff --git a/packages/kernel/linux-firmware/rockchip-firmware/package.mk b/packages/kernel/linux-firmware/rockchip-firmware/package.mk new file mode 100644 index 000000000..dc8416c50 --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rockchip-firmware" +PKG_VERSION="firmware" +PKG_ARCH="arm aarch64" +PKG_LICENSE="nonfree" +PKG_SITE="https://github.com/rockchip-linux" +PKG_URL="" +PKG_DEPENDS_TARGET="rkbin rfkill" +PKG_LONGDESC="rockchip firmware" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libreelec + cp $PKG_DIR/scripts/* $INSTALL/usr/lib/libreelec + + mkdir -p $INSTALL/usr/bin + cp -v $(get_build_dir rkbin)/firmware/bin/rtk_hciattach $INSTALL/usr/bin + + mkdir -p $INSTALL/$(get_full_firmware_dir)/rtlbt + cp -v $(get_build_dir rkbin)/firmware/bluetooth/rtl8723b_* $INSTALL/$(get_full_firmware_dir)/rtlbt + + mkdir -p $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/BCM4345C0.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/BCM4345C5.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/bcm4354a1.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/BCM4354A2.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/BCM4356A2.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/bluetooth/BCM4359C0.hcd $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/fw_bcm43455c0_ag.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/fw_bcm43456c5_ag.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/fw_bcm4354a1_ag.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/fw_bcm4356a2_ag.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/fw_bcm4359c0_ag.bin $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/nvram_ap6255.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/nvram_ap6256.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/nvram_ap6354.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/nvram_ap6356.txt $INSTALL/$(get_full_firmware_dir)/brcm + cp -v $(get_build_dir rkbin)/firmware/wifi/nvram_ap6398s.txt $INSTALL/$(get_full_firmware_dir)/brcm + + mkdir -p $INSTALL/$(get_full_firmware_dir)/rockchip + cp -v $(get_build_dir rkbin)/firmware/rockchip/dptx.bin $INSTALL/$(get_full_firmware_dir)/rockchip +} diff --git a/packages/kernel/linux-firmware/rockchip-firmware/scripts/hciattach-realtek-config b/packages/kernel/linux-firmware/rockchip-firmware/scripts/hciattach-realtek-config new file mode 100755 index 000000000..dacafc928 --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/scripts/hciattach-realtek-config @@ -0,0 +1,17 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +if [ "$(cat /sys/firmware/devicetree/base/model)" = "Rockchip RK3328 TRN9" ]; then + cp -f /usr/lib/kernel-overlays/base/lib/firmware/rtlbt/rtl8723b_config_noflow /var/lib/firmware/rtlbt/rtl8723b_config + + # temporarily disable bluetooth unless bootargs contains bluetooth + BOOTARGS=$(cat /sys/firmware/devicetree/base/chosen/bootargs) && [ "$BOOTARGS" = "${BOOTARGS/bluetooth/}" ] && exit 1 +fi + +if [ -d /var/lib/firmware/updates/rtlbt ]; then + cp -f /var/lib/firmware/updates/rtlbt/* /var/lib/firmware/rtlbt +fi + +exit 0 diff --git a/packages/kernel/linux-firmware/rockchip-firmware/system.d/btattach@.service b/packages/kernel/linux-firmware/rockchip-firmware/system.d/btattach@.service new file mode 100644 index 000000000..7bb104e98 --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/system.d/btattach@.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS0 to BlueZ stack using %I protocol +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS0.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/btattach -B /dev/ttyS0 -P %I +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach-realtek.service b/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach-realtek.service new file mode 100644 index 000000000..733a4ab23 --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach-realtek.service @@ -0,0 +1,12 @@ +[Unit] +Description=Attach /dev/ttyS0 to BlueZ stack +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS0.device + +[Service] +Type=simple +ExecStartPre=/usr/lib/libreelec/hciattach-realtek-config +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/rtk_hciattach -n -s 115200 ttyS0 rtk_h5 +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach@.service b/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach@.service new file mode 100644 index 000000000..ee8db515a --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/system.d/hciattach@.service @@ -0,0 +1,11 @@ +[Unit] +Description=Attach /dev/ttyS0 to BlueZ stack using %I type +Wants=bluetooth.service +Before=bluetooth.service +After=dev-ttyS0.device + +[Service] +Type=simple +ExecStartPre=/usr/sbin/rfkill unblock bluetooth +ExecStart=/usr/bin/hciattach -n -s 115200 ttyS0 %I +ExecStopPost=/usr/sbin/rfkill block bluetooth diff --git a/packages/kernel/linux-firmware/rockchip-firmware/udev.d/80-rockchip-firmware.rules b/packages/kernel/linux-firmware/rockchip-firmware/udev.d/80-rockchip-firmware.rules new file mode 100644 index 000000000..63b0b082f --- /dev/null +++ b/packages/kernel/linux-firmware/rockchip-firmware/udev.d/80-rockchip-firmware.rules @@ -0,0 +1,32 @@ +################################################################################ +# udev rules file for loading rockchip-firmware +################################################################################ + +ACTION!="add", GOTO="end" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0xb723", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x8753", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0626", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0624", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0623", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0524", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0523", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0241", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x024c", ATTRS{device}=="0x0240", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach-realtek.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0xa9bf", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach@bcm43xx.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4354", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach@bcm43xx.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4356", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach@bcm43xx.service" +SUBSYSTEMS=="sdio", ATTRS{vendor}=="0x02d0", ATTRS{device}=="0x4359", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="hciattach@bcm43xx.service" +LABEL="end" diff --git a/packages/kernel/linux-firmware/slice-firmware/package.mk b/packages/kernel/linux-firmware/slice-firmware/package.mk new file mode 100644 index 000000000..74e6a4628 --- /dev/null +++ b/packages/kernel/linux-firmware/slice-firmware/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="slice-firmware" +PKG_VERSION="0f463cc" +PKG_SHA256="27e8bac75d5639ca75d683bb2c9b10398c5d7f54f2cf3337ede6abf98e42f751" +PKG_ARCH="arm" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/FiveNinjas/slice-firmware" +PKG_URL="https://github.com/libreelec/slice-firmware/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_LONGDESC="BCM270x firmware related stuff for Slice" +PKG_TOOLCHAIN="manual" + +make_target() { + if [ "$DEVICE" = "Slice3" ]; then + $(kernel_path)/scripts/dtc/dtc -O dtb -I dts -o dt-blob.bin slice3-dt-blob.dts + elif [ "$DEVICE" = "Slice" ]; then + $(kernel_path)/scripts/dtc/dtc -O dtb -I dts -o dt-blob.bin slice-dt-blob.dts + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/bootloader/ + cp -a $PKG_BUILD/dt-blob.bin $INSTALL/usr/share/bootloader/ +} diff --git a/packages/kernel/linux-firmware/wlan-firmware/package.mk b/packages/kernel/linux-firmware/wlan-firmware/package.mk new file mode 100644 index 000000000..cee9d1120 --- /dev/null +++ b/packages/kernel/linux-firmware/wlan-firmware/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="wlan-firmware" +PKG_VERSION="2142727" +PKG_SHA256="d03e3108ef18ec10774b601d06d8445aebbd3c39f8ea3ab2b20a26c62af3500f" +PKG_LICENSE="Free-to-use" +PKG_SITE="https://github.com/LibreELEC/wlan-firmware" +PKG_URL="https://github.com/LibreELEC/wlan-firmware/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain rfkill" +PKG_LONGDESC="wlan-firmware: firmwares for various WLAN drivers" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install +} diff --git a/packages/kernel/linux/package.mk b/packages/kernel/linux/package.mk new file mode 100644 index 000000000..234b32ba0 --- /dev/null +++ b/packages/kernel/linux/package.mk @@ -0,0 +1,302 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="linux_org" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kernel.org" +PKG_DEPENDS_HOST="ccache:host openssl:host" +PKG_DEPENDS_TARGET="toolchain linux:host cpio:host kmod:host xz:host wireless-regdb keyutils $KERNEL_EXTRA_DEPENDS_TARGET" +PKG_DEPENDS_INIT="toolchain" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory busybox) $PROJECT_DIR/$PROJECT/initramfs" +PKG_LONGDESC="This package contains a precompiled kernel image and the modules." +PKG_IS_KERNEL_PKG="yes" +PKG_STAMP="$KERNEL_TARGET $KERNEL_MAKE_EXTRACMD $KERNEL_UBOOT_EXTRA_TARGET" + +PKG_VERSION="5.10.10" +#PKG_SHA256="" +PKG_URL="https://www.kernel.org/pub/linux/kernel/v5.x/$PKG_NAME-$PKG_VERSION.tar.xz" + +PKG_KERNEL_CFG_FILE=$(kernel_config_path) || die + +if [ -n "$KERNEL_TOOLCHAIN" ]; then + PKG_DEPENDS_HOST="$PKG_DEPENDS_HOST gcc-arm-$KERNEL_TOOLCHAIN:host" + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET gcc-arm-$KERNEL_TOOLCHAIN:host" + HEADERS_ARCH=$TARGET_ARCH +fi + +if [ "$PKG_BUILD_PERF" != "no" ] && grep -q ^CONFIG_PERF_EVENTS= $PKG_KERNEL_CFG_FILE ; then + PKG_BUILD_PERF="yes" + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET binutils elfutils libunwind zlib openssl" +fi + +if [ "$TARGET_ARCH" = "x86_64" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET intel-ucode:host kernel-firmware elfutils:host pciutils" +fi + +if [[ "$KERNEL_TARGET" = uImage* ]]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET u-boot-tools:host" +fi + +if [ "$BUILD_ANDROID_BOOTIMG" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET mkbootimg:host" +fi + +post_patch() { + cp $PKG_KERNEL_CFG_FILE $PKG_BUILD/.config + + # set default hostname based on $DISTRONAME + sed -i -e "s|@DISTRONAME@|$DISTRONAME|g" $PKG_BUILD/.config + + # disable swap support if not enabled + if [ ! "$SWAP_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_SWAP=.*$|# CONFIG_SWAP is not set|" $PKG_BUILD/.config + fi + + # disable nfs support if not enabled + if [ ! "$NFS_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_NFS_FS=.*$|# CONFIG_NFS_FS is not set|" $PKG_BUILD/.config + fi + + # disable cifs support if not enabled + if [ ! "$SAMBA_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_CIFS=.*$|# CONFIG_CIFS is not set|" $PKG_BUILD/.config + fi + + # disable iscsi support if not enabled + if [ ! "$ISCSI_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_SCSI_ISCSI_ATTRS=.*$|# CONFIG_SCSI_ISCSI_ATTRS is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_TCP=.*$|# CONFIG_ISCSI_TCP is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_BOOT_SYSFS=.*$|# CONFIG_ISCSI_BOOT_SYSFS is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_IBFT_FIND=.*$|# CONFIG_ISCSI_IBFT_FIND is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_IBFT=.*$|# CONFIG_ISCSI_IBFT is not set|" $PKG_BUILD/.config + fi + + # install extra dts files + for f in $PROJECT_DIR/$PROJECT/config/*-overlay.dts; do + [ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays || true + done + if [ -n "$DEVICE" ]; then + for f in $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/*-overlay.dts; do + [ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays || true + done + fi +} + +make_host() { + make \ + ARCH=${HEADERS_ARCH:-$TARGET_KERNEL_ARCH} \ + HOSTCC="$TOOLCHAIN/bin/host-gcc" \ + HOSTCXX="$TOOLCHAIN/bin/host-g++" \ + HOSTCFLAGS="$HOST_CFLAGS" \ + HOSTCXXFLAGS="$HOST_CXXFLAGS" \ + HOSTLDFLAGS="$HOST_LDFLAGS" \ + headers_check +} + +makeinstall_host() { + make \ + ARCH=${HEADERS_ARCH:-$TARGET_KERNEL_ARCH} \ + HOSTCC="$TOOLCHAIN/bin/host-gcc" \ + HOSTCXX="$TOOLCHAIN/bin/host-g++" \ + HOSTCFLAGS="$HOST_CFLAGS" \ + HOSTCXXFLAGS="$HOST_CXXFLAGS" \ + HOSTLDFLAGS="$HOST_LDFLAGS" \ + INSTALL_HDR_PATH=dest \ + headers_install + mkdir -p $SYSROOT_PREFIX/usr/include + cp -R dest/include/* $SYSROOT_PREFIX/usr/include +} + +pre_make_target() { + if [ "$TARGET_ARCH" = "x86_64" ]; then + # copy some extra firmware to linux tree + mkdir -p $PKG_BUILD/external-firmware + cp -a $(get_build_dir kernel-firmware)/{amdgpu,amd-ucode,i915,radeon,e100,rtl_nic} $PKG_BUILD/external-firmware + + cp -a $(get_build_dir intel-ucode)/intel-ucode $PKG_BUILD/external-firmware + + FW_LIST="$(find $PKG_BUILD/external-firmware \( -type f -o -type l \) \( -iname '*.bin' -o -iname '*.fw' -o -path '*/intel-ucode/*' \) | sed 's|.*external-firmware/||' | sort | xargs)" + sed -i "s|CONFIG_EXTRA_FIRMWARE=.*|CONFIG_EXTRA_FIRMWARE=\"${FW_LIST}\"|" $PKG_BUILD/.config + fi + + kernel_make oldconfig + + # regdb (backward compatability with pre-4.15 kernels) + if grep -q ^CONFIG_CFG80211_INTERNAL_REGDB= $PKG_BUILD/.config ; then + cp $(get_build_dir wireless-regdb)/db.txt $PKG_BUILD/net/wireless/db.txt + fi + + # copy video firmware (kernel won't compile without it) + [ "$LINUX" = "amlogic-4.9" ] && cp -PR $(get_build_dir media_modules-aml)/firmware $PKG_BUILD/firmware/video || : +} + +make_target() { + kernel_make modules + kernel_make INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) modules_install + rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/build + rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/source + + if [ "$PKG_BUILD_PERF" = "yes" ] ; then + ( cd tools/perf + + # arch specific perf build args + case "$TARGET_ARCH" in + x86_64) + PERF_BUILD_ARGS="ARCH=x86" + ;; + aarch64) + PERF_BUILD_ARGS="ARCH=arm64" + ;; + *) + PERF_BUILD_ARGS="ARCH=$TARGET_ARCH" + ;; + esac + + WERROR=0 \ + NO_LIBPERL=1 \ + NO_LIBPYTHON=1 \ + NO_SLANG=1 \ + NO_GTK2=1 \ + NO_LIBNUMA=1 \ + NO_LIBAUDIT=1 \ + NO_LZMA=1 \ + NO_SDT=1 \ + CROSS_COMPILE="$TARGET_PREFIX" \ + JOBS="$CONCURRENCY_MAKE_LEVEL" \ + make $PERF_BUILD_ARGS + mkdir -p $INSTALL/usr/bin + cp perf $INSTALL/usr/bin + ) + fi + + ( cd $ROOT + rm -rf $BUILD/initramfs + $SCRIPTS/install initramfs + ) + pkg_lock_status "ACTIVE" "linux:target" "build" + + if [ "$BOOTLOADER" = "u-boot" -a -n "$KERNEL_UBOOT_EXTRA_TARGET" ]; then + for extra_target in "$KERNEL_UBOOT_EXTRA_TARGET"; do + kernel_make $extra_target + done + fi + + # arm64 target does not support creating uImage. + # Build Image first, then wrap it using u-boot's mkimage. + if [[ "$TARGET_KERNEL_ARCH" == "arm64" && "$KERNEL_TARGET" == uImage* ]]; then + if [ -z "$KERNEL_UIMAGE_LOADADDR" -o -z "$KERNEL_UIMAGE_ENTRYADDR" ]; then + die "ERROR: KERNEL_UIMAGE_LOADADDR and KERNEL_UIMAGE_ENTRYADDR have to be set to build uImage - aborting" + fi + KERNEL_UIMAGE_TARGET="$KERNEL_TARGET" + KERNEL_TARGET="${KERNEL_TARGET/uImage/Image}" + fi + + # the modules target is required to get a proper Module.symvers + # file with symbols from built-in and external modules. + # Without that it'll contain only the symbols from the kernel + kernel_make $KERNEL_TARGET $KERNEL_MAKE_EXTRACMD modules + + for ce_dtb in arch/$TARGET_KERNEL_ARCH/boot/dts/amlogic/coreelec-*; do + if [ -d $ce_dtb ]; then + cp $ce_dtb/*.dtb arch/$TARGET_KERNEL_ARCH/boot/dts/amlogic 2>/dev/null + fi + done + + if [ "$BUILD_ANDROID_BOOTIMG" = "yes" ]; then + find_file_path bootloader/mkbootimg && source ${FOUND_PATH} + mv -f arch/$TARGET_KERNEL_ARCH/boot/boot.img arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_TARGET + fi + + if [ -n "$KERNEL_UIMAGE_TARGET" ] ; then + # determine compression used for kernel image + KERNEL_UIMAGE_COMP=${KERNEL_UIMAGE_TARGET:7} + KERNEL_UIMAGE_COMP=${KERNEL_UIMAGE_COMP:-none} + + # calculate new load address to make kernel Image unpack to memory area after compressed image + if [ "$KERNEL_UIMAGE_COMP" != "none" ] ; then + COMPRESSED_SIZE=$(stat -t "arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_TARGET" | awk '{print $2}') + # align to 1 MiB + COMPRESSED_SIZE=$(( (($COMPRESSED_SIZE - 1 >> 20) + 1) << 20 )) + PKG_KERNEL_UIMAGE_LOADADDR=$(printf '%X' "$(( $KERNEL_UIMAGE_LOADADDR + $COMPRESSED_SIZE ))") + PKG_KERNEL_UIMAGE_ENTRYADDR=$(printf '%X' "$(( $KERNEL_UIMAGE_ENTRYADDR + $COMPRESSED_SIZE ))") + else + PKG_KERNEL_UIMAGE_LOADADDR=${KERNEL_UIMAGE_LOADADDR} + PKG_KERNEL_UIMAGE_ENTRYADDR=${KERNEL_UIMAGE_ENTRYADDR} + fi + + mkimage -A $TARGET_KERNEL_ARCH \ + -O linux \ + -T kernel \ + -C $KERNEL_UIMAGE_COMP \ + -a $PKG_KERNEL_UIMAGE_LOADADDR \ + -e $PKG_KERNEL_UIMAGE_ENTRYADDR \ + -d arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_TARGET \ + arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_UIMAGE_TARGET + + KERNEL_TARGET="${KERNEL_UIMAGE_TARGET}" + fi +} + +makeinstall_target() { + if [ "$BOOTLOADER" = "u-boot" ]; then + mkdir -p $INSTALL/usr/share/bootloader/device_trees + if [ -d arch/$TARGET_KERNEL_ARCH/boot/dts/amlogic ]; then + cp arch/$TARGET_KERNEL_ARCH/boot/*dtb.img $INSTALL/usr/share/bootloader/ 2>/dev/null || : + # [ "$PROJECT" = "Amlogic-ng" ] && cp arch/$TARGET_KERNEL_ARCH/boot/dts/amlogic/*.dtb $INSTALL/usr/share/bootloader/device_trees 2>/dev/null || : + # TEMP EMUELEC CHANGE: Remnove GXL dtbs from amlogic-NG + if [ "$PROJECT" = "Amlogic-ng" ]; then + cp arch/$TARGET_KERNEL_ARCH/boot/dts/amlogic/*.dtb $INSTALL/usr/share/bootloader/device_trees 2>/dev/null || : + rm $INSTALL/usr/share/bootloader/device_trees/gxl_*.dtb + fi + fi + elif [ "$BOOTLOADER" = "bcm2835-bootloader" ]; then + mkdir -p $INSTALL/usr/share/bootloader/overlays + + # install platform dtbs, but remove upstream kernel dtbs (i.e. without downstream + # drivers and decent USB support) as these are not required by LibreELEC + cp -p arch/$TARGET_KERNEL_ARCH/boot/dts/*.dtb $INSTALL/usr/share/bootloader + rm -f $INSTALL/usr/share/bootloader/bcm283*.dtb + + # install overlay dtbs + for dtb in arch/$TARGET_KERNEL_ARCH/boot/dts/overlays/*.dtbo; do + cp $dtb $INSTALL/usr/share/bootloader/overlays 2>/dev/null || : + done + cp -p arch/$TARGET_KERNEL_ARCH/boot/dts/overlays/README $INSTALL/usr/share/bootloader/overlays + fi +} + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + if [ -n "$INITRAMFS_MODULES" ]; then + mkdir -p $INSTALL/etc + mkdir -p $INSTALL/usr/lib/modules + + for i in $INITRAMFS_MODULES; do + module=`find .install_pkg/$(get_full_module_dir)/kernel -name $i.ko` + if [ -n "$module" ]; then + echo $i >> $INSTALL/etc/modules + cp $module $INSTALL/usr/lib/modules/`basename $module` + fi + done + fi + + if [ "$UVESAFB_SUPPORT" = yes ]; then + mkdir -p $INSTALL/usr/lib/modules + uvesafb=`find .install_pkg/$(get_full_module_dir)/kernel -name uvesafb.ko` + cp $uvesafb $INSTALL/usr/lib/modules/`basename $uvesafb` + fi +} + +post_install() { + mkdir -p $INSTALL/$(get_full_firmware_dir)/ + + # regdb and signature is now loaded as firmware by 4.15+ + if grep -q ^CONFIG_CFG80211_REQUIRE_SIGNED_REGDB= $PKG_BUILD/.config; then + cp $(get_build_dir wireless-regdb)/regulatory.db{,.p7s} $INSTALL/$(get_full_firmware_dir) + fi +} diff --git a/packages/kernel/linux/patches/amlogic-3.14/linux-010_sx05re_set_colordepth.patch b/packages/kernel/linux/patches/amlogic-3.14/linux-010_sx05re_set_colordepth.patch new file mode 100644 index 000000000..f95d11cce --- /dev/null +++ b/packages/kernel/linux/patches/amlogic-3.14/linux-010_sx05re_set_colordepth.patch @@ -0,0 +1,19 @@ +--- a/drivers/amlogic/display/osd/osd_fb.c ++++ b/drivers/amlogic/display/osd/osd_fb.c +@@ -215,11 +215,11 @@ + .yoffset = 0, + .bits_per_pixel = 32, + .grayscale = 0, +- .red = {0, 0, 0}, +- .green = {0, 0, 0}, +- .blue = {0, 0, 0}, +- .transp = {0, 0, 0}, +- .nonstd = 0, ++ .red = {16, 8, 0}, ++ .green = {8, 8, 0}, ++ .blue = {0, 8, 0}, ++ .transp = {24, 0, 0}, ++ .nonstd = 1, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, diff --git a/packages/kernel/linux/patches/amlogic-3.14/linux-011-HID-input-fix-confusion-on-conflicting-mappings.patch b/packages/kernel/linux/patches/amlogic-3.14/linux-011-HID-input-fix-confusion-on-conflicting-mappings.patch new file mode 100644 index 000000000..44b792d27 --- /dev/null +++ b/packages/kernel/linux/patches/amlogic-3.14/linux-011-HID-input-fix-confusion-on-conflicting-mappings.patch @@ -0,0 +1,143 @@ +From 6ce901eb61aa30ba8565c62049ee80c90728ef14 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Mon, 29 Dec 2014 15:21:26 +0100 +Subject: [PATCH] HID: input: fix confusion on conflicting mappings + +On an PC-101/103/104 keyboard (American layout) the 'Enter' key and its +neighbours look like this: + + +---+ +---+ +-------+ + | 1 | | 2 | | 5 | + +---+ +---+ +-------+ + +---+ +-----------+ + | 3 | | 4 | + +---+ +-----------+ + +On a PC-102/105 keyboard (European layout) it looks like this: + + +---+ +---+ +-------+ + | 1 | | 2 | | | + +---+ +---+ +-+ 4 | + +---+ +---+ | | + | 3 | | 5 | | | + +---+ +---+ +-----+ + +(Note that the number of keys is the same, but key '5' is moved down and + the shape of key '4' is changed. Keys '1' to '3' are exactly the same.) + +The keys 1-4 report the same scan-code in HID in both layouts, even though +the keysym they produce is usually different depending on the XKB-keymap +used by user-space. +However, key '5' (US 'backslash'/'pipe') reports 0x31 for the upper layout +and 0x32 for the lower layout, as defined by the HID spec. This is highly +confusing as the linux-input API uses a single keycode for both. + +So far, this was never a problem as there never has been a keyboard with +both of those keys present at the same time. It would have to look +something like this: + + +---+ +---+ +-------+ + | 1 | | 2 | | x31 | + +---+ +---+ +-------+ + +---+ +---+ +-----+ + | 3 | |x32| | 4 | + +---+ +---+ +-----+ + +HID can represent such a keyboard, but the linux-input API cannot. +Furthermore, any user-space mapping would be confused by this and, +luckily, no-one ever produced such hardware. + +Now, the HID input layer fixed this mess by mapping both 0x31 and 0x32 to +the same keycode (KEY_BACKSLASH==0x2b). As only one of both physical keys +is present on a hardware, this works just fine. + +Lets introduce hardware-vendors into this: +------------------------------------------ + +Unfortunately, it seems way to expensive to produce a different device for +American and European layouts. Therefore, hardware-vendors put both keys, +(0x31 and 0x32) on the same keyboard, but only one of them is hooked up +to the physical button, the other one is 'dead'. +This means, they can use the same hardware, with a different button-layout +and automatically produce the correct HID events for American *and* +European layouts. This is unproblematic for normal keyboards, as the +'dead' key will never report any KEY-DOWN events. But RollOver keyboards +send the whole matrix on each key-event, allowing n-key roll-over mode. +This means, we get a 0x31 and 0x32 event on each key-press. One of them +will always be 0, the other reports the real state. As we map both to the +same keycode, we will get spurious key-events, even though the real +key-state never changed. + +The easiest way would be to blacklist 'dead' keys and never handle those. +We could simply read the 'country' tag of USB devices and blacklist either +key according to the layout. But... hardware vendors... want the same +device for all countries and thus many of them set 'country' to 0 for all +devices. Meh.. + +So we have to deal with this properly. As we cannot know which of the keys +is 'dead', we either need a heuristic and track those keys, or we simply +make use of our value-tracking for HID fields. We simply ignore HID events +for absolute data if the data didn't change. As HID tracks events on the +HID level, we haven't done the keycode translation, yet. Therefore, the +'dead' key is tracked independently of the real key, therefore, any events +on it will be ignored. + +This patch simply discards any HID events for absolute data if it didn't +change compared to the last report. We need to ignore relative and +buffered-byte reports for obvious reasons. But those cannot be affected by +this bug, so we're fine. + +Preferably, we'd do this filtering on the HID-core level. But this might +break a lot of custom drivers, if they do not follow the HID specs. +Therefore, we do this late in hid-input just before we inject it into the +input layer (which does the exact same filtering, but on the keycode +level). + +If this turns out to break some devices, we might have to limit filtering +to EV_KEY events. But lets try to do the Right Thing first, and properly +filter any absolute data that didn't change. + +This patch is tagged for 'stable' as it fixes a lot of n-key RollOver +hardware. We might wanna wait with backporting for a while, before we know +it doesn't break anything else, though. + +Cc: +Reported-by: Adam Goode +Reported-by: Fredrik Hallenberg +Tested-by: Fredrik Hallenberg +Signed-off-by: David Herrmann +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-input.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index e0a0f06..84b6899 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1101,6 +1101,22 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + } + ++ /* ++ * Ignore reports for absolute data if the data didn't change. This is ++ * not only an optimization but also fixes 'dead' key reports. Some ++ * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID ++ * 0x31 and 0x32) report multiple keys, even though a localized keyboard ++ * can only have one of them physically available. The 'dead' keys ++ * report constant 0. As all map to the same keycode, they'd confuse ++ * the input layer. If we filter the 'dead' keys on the HID level, we ++ * skip the keycode translation and only forward real events. ++ */ ++ if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | ++ HID_MAIN_ITEM_BUFFERED_BYTE)) && ++ usage->usage_index < field->maxusage && ++ value == field->value[usage->usage_index]) ++ return; ++ + /* report the usage code as scancode if the key status has changed */ + if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) + input_event(input, EV_MSC, MSC_SCAN, usage->hid); +-- +2.9.5 + diff --git a/packages/kernel/linux/patches/amlogic-3.14/linux-012-HID-fixup-the-conflicting-keyboard-mappings-quirk.patch b/packages/kernel/linux/patches/amlogic-3.14/linux-012-HID-fixup-the-conflicting-keyboard-mappings-quirk.patch new file mode 100644 index 000000000..9b67ca849 --- /dev/null +++ b/packages/kernel/linux/patches/amlogic-3.14/linux-012-HID-fixup-the-conflicting-keyboard-mappings-quirk.patch @@ -0,0 +1,34 @@ +From 8e7b341037db1835ee6eea64663013cbfcf33575 Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Tue, 6 Jan 2015 22:34:19 +0100 +Subject: [PATCH] HID: fixup the conflicting keyboard mappings quirk + +The ignore check that got added in 6ce901eb61 ("HID: input: fix confusion +on conflicting mappings") needs to properly check for VARIABLE reports +as well (ARRAY reports should be ignored), otherwise legitimate keyboards +might break. + +Cc: +Fixes: 6ce901eb61 ("HID: input: fix confusion on conflicting mappings") +Reported-by: Fredrik Hallenberg +Reported-by: David Herrmann +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-input.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 84b6899..a758900 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1113,6 +1113,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + */ + if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | + HID_MAIN_ITEM_BUFFERED_BYTE)) && ++ (field->flags & HID_MAIN_ITEM_VARIABLE) && + usage->usage_index < field->maxusage && + value == field->value[usage->usage_index]) + return; +-- +2.9.5 + diff --git a/packages/kernel/linux/patches/amlogic-4.9/linux-010_sx05re_set_colordepth.patch b/packages/kernel/linux/patches/amlogic-4.9/linux-010_sx05re_set_colordepth.patch new file mode 100644 index 000000000..cbb24ffb7 --- /dev/null +++ b/packages/kernel/linux/patches/amlogic-4.9/linux-010_sx05re_set_colordepth.patch @@ -0,0 +1,31 @@ +From f64e727448cd0d16f69009d4f537eb873e87dfae Mon Sep 17 00:00:00 2001 +From: "Mauro (mdrjr) Ribeiro" +Date: Thu, 22 Nov 2018 13:40:49 +0900 +Subject: [PATCH] osd/fb: set default color format for Linux + +Change-Id: I1d95d63215d5567673380740528eff65562bc6df +--- + drivers/amlogic/media/osd/osd_fb.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c +index b5d0698f086e..423120459e43 100644 +--- a/drivers/amlogic/media/osd/osd_fb.c ++++ b/drivers/amlogic/media/osd/osd_fb.c +@@ -221,11 +221,11 @@ static struct fb_var_screeninfo fb_def_var[] = { + .yoffset = 0, + .bits_per_pixel = 32, + .grayscale = 0, +- .red = {0, 0, 0}, +- .green = {0, 0, 0}, +- .blue = {0, 0, 0}, +- .transp = {0, 0, 0}, +- .nonstd = 0, ++ .red = {16, 8, 0}, ++ .green = {8, 8, 0}, ++ .blue = {0, 8, 0}, ++ .transp = {24, 0, 0}, ++ .nonstd = 1, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, diff --git a/packages/kernel/linux/patches/default/linux-051-ouya_controller_support.patch b/packages/kernel/linux/patches/default/linux-051-ouya_controller_support.patch new file mode 100644 index 000000000..8ee3cb27b --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-051-ouya_controller_support.patch @@ -0,0 +1,206 @@ +commit 5a596921a4636e62843a59b7eab7b87b70a6d296 +Author: Lukas Rusak +Date: Sun May 6 22:03:11 2018 -0700 + + HID: add ouya HID driver + + This driver is a simple implementation to get the controller working and mapped properly. + This driver does not include functionality for the touchpad (yet). The original driver + was taken from from the ouya linux tree and has been simplified. It seems there may have + been other versions of the controller present that had a broken report descriptor. I have + removed that for now. + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 60252fd796f6..6be2c454e72e 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -659,6 +659,12 @@ config HID_ORTEK + - Ortek WKB-2000 + - Skycable wireless presenter + ++config HID_OUYA ++ tristate "OUYA Game Controller" ++ depends on USB_HID ++ ---help--- ++ Support for OUYA Game Controller. ++ + config HID_PANTHERLORD + tristate "Pantherlord/GreenAsia game controller" + depends on HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 17a8bd97da9d..4425890934e4 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -71,6 +71,7 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o + obj-$(CONFIG_HID_NTI) += hid-nti.o + obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o + obj-$(CONFIG_HID_ORTEK) += hid-ortek.o ++obj-$(CONFIG_HID_OUYA) += hid-ouya.o + obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o + obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o + obj-$(CONFIG_HID_PENMOUNT) += hid-penmount.o +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 0b5cc910f62e..0528efb825fa 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -859,6 +859,9 @@ + #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 + #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S 0x8003 + ++#define USB_VENDOR_ID_OUYA 0x2836 ++#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001 ++ + #define USB_VENDOR_ID_PLANTRONICS 0x047f + + #define USB_VENDOR_ID_PANASONIC 0x04da +diff --git a/drivers/hid/hid-ouya.c b/drivers/hid/hid-ouya.c +new file mode 100644 +index 000000000000..4344a47b40af +--- /dev/null ++++ b/drivers/hid/hid-ouya.c +@@ -0,0 +1,131 @@ ++/* ++ * HID driver for OUYA Game Controller(s) ++ * ++ * Copyright (c) 2013 OUYA ++ * Copyright (c) 2013 Gregorios Leach ++ * Copyright (c) 2018 Lukas Rusak ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++static const unsigned int ouya_absmap[] = { ++ [0x30] = ABS_X, /* left stick X */ ++ [0x31] = ABS_Y, /* left stick Y */ ++ [0x32] = ABS_Z, /* L2 */ ++ [0x33] = ABS_RX, /* right stick X */ ++ [0x34] = ABS_RY, /* right stick Y */ ++ [0x35] = ABS_RZ, /* R2 */ ++}; ++ ++static const unsigned int ouya_keymap[] = { ++ [0x1] = BTN_SOUTH, /* O */ ++ [0x2] = BTN_WEST, /* U */ ++ [0x3] = BTN_NORTH, /* Y */ ++ [0x4] = BTN_EAST, /* A */ ++ [0x5] = BTN_TL, /* L1 */ ++ [0x6] = BTN_TR, /* R1 */ ++ [0x7] = BTN_THUMBL, /* L3 */ ++ [0x8] = BTN_THUMBR, /* R3 */ ++ [0x9] = BTN_DPAD_UP, /* Up */ ++ [0xa] = BTN_DPAD_DOWN, /* Down */ ++ [0xb] = BTN_DPAD_LEFT, /* Left */ ++ [0xc] = BTN_DPAD_RIGHT, /* Right */ ++ [0xd] = BTN_TL2, /* L2 */ ++ [0xe] = BTN_TR2, /* R2 */ ++ [0xf] = BTN_MODE, /* Power */ ++}; ++ ++static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if (key >= ARRAY_SIZE(ouya_keymap)) ++ return -1; ++ ++ key = ouya_keymap[key]; ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ ++ return 1; ++ ++ } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { ++ unsigned int abs = usage->hid & HID_USAGE; ++ ++ if (abs >= ARRAY_SIZE(ouya_absmap)) ++ return -1; ++ ++ abs = ouya_absmap[abs]; ++ hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id) ++{ ++ int ret; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ hid_err(hdev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE); ++ if (ret) { ++ hid_err(hdev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++ ++err_free: ++ return ret; ++} ++ ++static void ouya_remove(struct hid_device *hdev) ++{ ++ hid_hw_stop(hdev); ++ kfree(hid_get_drvdata(hdev)); ++} ++ ++static const struct hid_device_id ouya_devices[] = { ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, ouya_devices); ++ ++static struct hid_driver ouya_driver = { ++ .name = "ouya", ++ .id_table = ouya_devices, ++ .input_mapping = ouya_input_mapping, ++ .probe = ouya_probe, ++ .remove = ouya_remove, ++}; ++ ++static int __init ouya_init(void) ++{ ++ return hid_register_driver(&ouya_driver); ++} ++ ++static void __exit ouya_exit(void) ++{ ++ hid_unregister_driver(&ouya_driver); ++} ++ ++module_init(ouya_init); ++module_exit(ouya_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lukas Rusak "); ++MODULE_AUTHOR("Gregorios Leach "); ++MODULE_DESCRIPTION("Ouya Controller Driver"); +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 587e2681a53f..b5adc13e0df1 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -538,6 +538,9 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, + #endif ++#if IS_ENABLED(CONFIG_HID_OUYA) ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++#endif + #if IS_ENABLED(CONFIG_HID_PANTHERLORD) + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, diff --git a/packages/kernel/linux/patches/default/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/kernel/linux/patches/default/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 000000000..56e2ca865 --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,72 @@ +From 7051422474e4c4e302ede3d07ffd8ef2682e07a2 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 22 Apr 2014 16:05:14 +0300 +Subject: [PATCH] [RFC] hid/sony: add autorepeat for PS3 remotes + +adapted to 4.6 + +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. + +Signed-off-by: Matt DeVillier +--- + drivers/hid/hid-sony.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 310436a..84f7f41 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1120,6 +1120,25 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} ++ + static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) + { +@@ -2372,6 +2391,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + sony_init_output_report(sc, dualshock4_send_output_report); + } else if (sc->quirks & MOTION_CONTROLLER) { + sony_init_output_report(sc, motion_send_output_report); ++ } else if (sc->quirks & PS3REMOTE) { ++ ret = ps3remote_setup_repeat(hdev); + } else { + ret = 0; + } +-- +2.5.0 diff --git a/packages/kernel/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch b/packages/kernel/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch new file mode 100644 index 000000000..677de3ed7 --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-062-imon_pad_ignore_diagonal.patch @@ -0,0 +1,21 @@ +diff -Naur linux-3.16.1/drivers/media/rc/imon.c linux-3.16.1.patch/drivers/media/rc/imon.c +--- linux-3.16.1/drivers/media/rc/imon.c 2014-08-14 04:36:35.000000000 +0200 ++++ linux-3.16.1.patch/drivers/media/rc/imon.c 2014-08-15 13:57:16.587620642 +0200 +@@ -1344,6 +1344,17 @@ + } + } else { + /* ++ * For users without stabilized, just ignore any value getting ++ * to close to the diagonal. ++ */ ++ if ((abs(rel_y) < 2 && abs(rel_x) < 2) || ++ abs(abs(rel_y) - abs(rel_x)) < 2 ) { ++ spin_lock_irqsave(&ictx->kc_lock, flags); ++ ictx->kc = KEY_UNKNOWN; ++ spin_unlock_irqrestore(&ictx->kc_lock, flags); ++ return; ++ } ++ /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ diff --git a/packages/kernel/linux/patches/default/linux-904-improve-xbox-dvd-remote-performance.patch b/packages/kernel/linux/patches/default/linux-904-improve-xbox-dvd-remote-performance.patch new file mode 100644 index 000000000..5ec182064 --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-904-improve-xbox-dvd-remote-performance.patch @@ -0,0 +1,158 @@ +From 55096db50d8cdbf777c67f672b493ef565a12c38 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Fri, 22 Mar 2019 12:26:17 +0100 +Subject: [PATCH] media: rc: xbox_remote: add protocol and set timeout + +The timestamps in ir-keytable -t output showed that the Xbox DVD +IR dongle decodes scancodes every 64ms. The last scancode of a +longer button press is decodes 64ms after the last-but-one which +indicates the decoder doesn't use a timeout but decodes on the last +edge of the signal. + +267.042629: lirc protocol(unknown): scancode = 0xace +267.042665: event type EV_MSC(0x04): scancode = 0xace +267.042665: event type EV_KEY(0x01) key_down: KEY_1(0x0002) +267.042665: event type EV_SYN(0x00). +267.106625: lirc protocol(unknown): scancode = 0xace +267.106643: event type EV_MSC(0x04): scancode = 0xace +267.106643: event type EV_SYN(0x00). +267.170623: lirc protocol(unknown): scancode = 0xace +267.170638: event type EV_MSC(0x04): scancode = 0xace +267.170638: event type EV_SYN(0x00). +267.234621: lirc protocol(unknown): scancode = 0xace +267.234636: event type EV_MSC(0x04): scancode = 0xace +267.234636: event type EV_SYN(0x00). +267.298623: lirc protocol(unknown): scancode = 0xace +267.298638: event type EV_MSC(0x04): scancode = 0xace +267.298638: event type EV_SYN(0x00). +267.543345: event type EV_KEY(0x01) key_down: KEY_1(0x0002) +267.543345: event type EV_SYN(0x00). +267.570015: event type EV_KEY(0x01) key_up: KEY_1(0x0002) +267.570015: event type EV_SYN(0x00). + +Add a protocol with the repeat value and set the timeout in the +driver to 10ms (to have a bit of headroom for delays) so the Xbox +DVD remote performs more responsive. + +Signed-off-by: Matthias Reichl +--- + Documentation/media/lirc.h.rst.exceptions | 1 + + drivers/media/rc/keymaps/rc-xbox-dvd.c | 2 +- + drivers/media/rc/rc-main.c | 2 ++ + drivers/media/rc/xbox_remote.c | 4 +++- + include/media/rc-map.h | 4 +++- + include/uapi/linux/lirc.h | 2 ++ + 6 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions +index e7a41d4b3d46..f8b5f1a32b7d 100644 +--- a/Documentation/media/lirc.h.rst.exceptions ++++ b/Documentation/media/lirc.h.rst.exceptions +@@ -61,6 +61,7 @@ ignore symbol RC_PROTO_IMON + ignore symbol RC_PROTO_RCMM12 + ignore symbol RC_PROTO_RCMM24 + ignore symbol RC_PROTO_RCMM32 ++ignore symbol RC_PROTO_XBOX_DVD + + # Undocumented macros + +diff --git a/drivers/media/rc/keymaps/rc-xbox-dvd.c b/drivers/media/rc/keymaps/rc-xbox-dvd.c +index af387244636b..42815ab57bff 100644 +--- a/drivers/media/rc/keymaps/rc-xbox-dvd.c ++++ b/drivers/media/rc/keymaps/rc-xbox-dvd.c +@@ -42,7 +42,7 @@ static struct rc_map_list xbox_dvd_map = { + .map = { + .scan = xbox_dvd, + .size = ARRAY_SIZE(xbox_dvd), +- .rc_proto = RC_PROTO_UNKNOWN, ++ .rc_proto = RC_PROTO_XBOX_DVD, + .name = RC_MAP_XBOX_DVD, + } + }; +diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c +index 78e79c37f208..7f1d5b226f68 100644 +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -76,6 +76,7 @@ static const struct { + .scancode_bits = 0x00ffffff, .repeat_period = 114 }, + [RC_PROTO_RCMM32] = { .name = "rc-mm-32", + .scancode_bits = 0xffffffff, .repeat_period = 114 }, ++ [RC_PROTO_XBOX_DVD] = { .name = "xbox-dvd", .repeat_period = 64 }, + }; + + /* Used to keep track of known keymaps */ +@@ -1027,6 +1028,7 @@ static const struct { + { RC_PROTO_BIT_RCMM12 | + RC_PROTO_BIT_RCMM24 | + RC_PROTO_BIT_RCMM32, "rc-mm", "ir-rcmm-decoder" }, ++ { RC_PROTO_BIT_XBOX_DVD, "xbox-dvd", NULL }, + }; + + /** +diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c +index f959cbb94744..79470c09989e 100644 +--- a/drivers/media/rc/xbox_remote.c ++++ b/drivers/media/rc/xbox_remote.c +@@ -148,7 +148,7 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) + struct rc_dev *rdev = xbox_remote->rdev; + + rdev->priv = xbox_remote; +- rdev->allowed_protocols = RC_PROTO_BIT_UNKNOWN; ++ rdev->allowed_protocols = RC_PROTO_BIT_XBOX_DVD; + rdev->driver_name = "xbox_remote"; + + rdev->open = xbox_remote_rc_open; +@@ -157,6 +157,8 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) + rdev->device_name = xbox_remote->rc_name; + rdev->input_phys = xbox_remote->rc_phys; + ++ rdev->timeout = MS_TO_NS(10); ++ + usb_to_input_id(xbox_remote->udev, &rdev->input_id); + rdev->dev.parent = &xbox_remote->interface->dev; + } +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index e5e86d595645..a0000f392362 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -40,6 +40,7 @@ + #define RC_PROTO_BIT_RCMM12 BIT_ULL(RC_PROTO_RCMM12) + #define RC_PROTO_BIT_RCMM24 BIT_ULL(RC_PROTO_RCMM24) + #define RC_PROTO_BIT_RCMM32 BIT_ULL(RC_PROTO_RCMM32) ++#define RC_PROTO_BIT_XBOX_DVD BIT_ULL(RC_PROTO_XBOX_DVD) + + #define RC_PROTO_BIT_ALL \ + (RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \ +@@ -55,7 +56,8 @@ + RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ + RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \ + RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM12 | \ +- RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32) ++ RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32 | \ ++ RC_PROTO_BIT_XBOX_DVD) + /* All rc protocols for which we have decoders */ + #define RC_PROTO_BIT_ALL_IR_DECODER \ + (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ +diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h +index 45fcbf99d72e..f99d9dcae667 100644 +--- a/include/uapi/linux/lirc.h ++++ b/include/uapi/linux/lirc.h +@@ -195,6 +195,7 @@ struct lirc_scancode { + * @RC_PROTO_RCMM12: RC-MM protocol 12 bits + * @RC_PROTO_RCMM24: RC-MM protocol 24 bits + * @RC_PROTO_RCMM32: RC-MM protocol 32 bits ++ * @RC_PROTO_XBOX_DVD: Xbox DVD Movie Playback Kit protocol + */ + enum rc_proto { + RC_PROTO_UNKNOWN = 0, +@@ -224,6 +225,7 @@ enum rc_proto { + RC_PROTO_RCMM12 = 24, + RC_PROTO_RCMM24 = 25, + RC_PROTO_RCMM32 = 26, ++ RC_PROTO_XBOX_DVD = 27, + }; + + #endif +-- +2.20.1 + diff --git a/packages/kernel/linux/patches/default/linux-999-no-lzma-in-x86-perf-build.patch b/packages/kernel/linux/patches/default/linux-999-no-lzma-in-x86-perf-build.patch new file mode 100644 index 000000000..676d0d98c --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-999-no-lzma-in-x86-perf-build.patch @@ -0,0 +1,13 @@ +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index 0294bfb6c5f8..153036bbed7e 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -35,7 +35,7 @@ ifeq ($(SRCARCH),x86) + ifeq (${IS_64_BIT}, 1) + CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated + ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S +- LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma ++ LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind + $(call detected,CONFIG_X86_64) + else + LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind diff --git a/packages/kernel/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/kernel/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch new file mode 100644 index 000000000..16ac49bee --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch @@ -0,0 +1,25 @@ +From c314d9af9d774c052bea324e1a140ccdba0ca070 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 8 Apr 2014 14:02:53 +0300 +Subject: [PATCH] pm: disable async suspend/resume by default + +--- + kernel/power/main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf63..361db93 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -46,7 +46,7 @@ int pm_notifier_call_chain(unsigned long val) + } + + /* If set, devices may be suspended and resumed asynchronously. */ +-int pm_async_enabled = 1; ++int pm_async_enabled = 0; + + static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +-- +1.7.2.5 + diff --git a/packages/kernel/linux/patches/default/linux-999.20-i915-pm-Be-less-agressive-with-clockfreq-changes-on-Bay-Trail.patch b/packages/kernel/linux/patches/default/linux-999.20-i915-pm-Be-less-agressive-with-clockfreq-changes-on-Bay-Trail.patch new file mode 100644 index 000000000..0a68a040d --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-999.20-i915-pm-Be-less-agressive-with-clockfreq-changes-on-Bay-Trail.patch @@ -0,0 +1,89 @@ +From 28ad70a06fb84fe63cd036970db2561b2fd1562b Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 5 Nov 2017 16:51:23 +0100 +Subject: [PATCH v3 1/2] i915: pm: Be less agressive with clockfreq changes on + Bay Trail + +Bay Trail devices are known to hang when changing the frequency often, +this is discussed in great length in: +https://bugzilla.kernel.org/show_bug.cgi?id=109051 + +Commit 6067a27d1f01 ("drm/i915: Avoid tweaking evaluation thresholds +on Baytrail v3") is an attempt to workaround this. Several users in +bko109051 report that an earlier version of this patch, v1: +https://bugzilla.kernel.org/attachment.cgi?id=251471 + +Works better for them and they still see hangs with the merged v3. + +Comparing the 2 versions shows that they are indeed not equivalent, +v1 not only skips writing the GEN6_RP* registers from valleyview_set_rps, +as v3 does. It also contained these modifications to i915_irq.c: + + if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { + if (!vlv_c0_above(dev_priv, + &dev_priv->rps.down_ei, &now, +- dev_priv->rps.down_threshold)) ++ VLV_RP_DOWN_EI_THRESHOLD)) + events |= GEN6_PM_RP_DOWN_THRESHOLD; + dev_priv->rps.down_ei = now; + } + + if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { + if (vlv_c0_above(dev_priv, + &dev_priv->rps.up_ei, &now, +- dev_priv->rps.up_threshold)) ++ VLV_RP_UP_EI_THRESHOLD)) + events |= GEN6_PM_RP_UP_THRESHOLD; + dev_priv->rps.up_ei = now; + } + +Which use less aggressive up/down thresholds, which results in less +GEN6_PM_RP_*_THRESHOLD events and thus in less calls to intel_set_rps() -> +valleyview_set_rps() -> vlv_punit_write(PUNIT_REG_GPU_FREQ_REQ). +With the last call being the likely cause of the hang. + +This commit hardcodes the threshold_up and _down values for Bay Trail to +less aggressive values, reducing the amount of clock frequency changes, +thus avoiding the hangs some people are still seeing with the merged fix. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=109051 +Signed-off-by: Hans de Goede +--- + drivers/gpu/drm/i915/i915_reg.h | 3 +++ + drivers/gpu/drm/i915/intel_pm.c | 5 ++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 68a58cce6ab1..2561af075ebb 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -1355,6 +1355,9 @@ enum i915_power_well_id { + #define VLV_BIAS_CPU_125_SOC_875 (6 << 2) + #define CHV_BIAS_CPU_50_SOC_50 (3 << 2) + ++#define VLV_RP_UP_EI_THRESHOLD 90 ++#define VLV_RP_DOWN_EI_THRESHOLD 70 ++ + /* vlv2 north clock has */ + #define CCK_FUSE_REG 0x8 + #define CCK_FUSE_HPLL_FREQ_MASK 0x3 +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 01966b89be14..177b6caa0a38 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -6096,8 +6096,11 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) + /* When byt can survive without system hang with dynamic + * sw freq adjustments, this restriction can be lifted. + */ +- if (IS_VALLEYVIEW(dev_priv)) ++ if (IS_VALLEYVIEW(dev_priv)) { ++ threshold_up = VLV_RP_UP_EI_THRESHOLD; ++ threshold_down = VLV_RP_DOWN_EI_THRESHOLD; + goto skip_hw_write; ++ } + + I915_WRITE(GEN6_RP_UP_EI, + GT_INTERVAL_FROM_US(dev_priv, ei_up)); +-- +2.14.3 + diff --git a/packages/kernel/linux/patches/default/linux-999.21-intel_idle-Disable-C6N-and-C6S-on-Bay-Trail.patch b/packages/kernel/linux/patches/default/linux-999.21-intel_idle-Disable-C6N-and-C6S-on-Bay-Trail.patch new file mode 100644 index 000000000..8b820cdc8 --- /dev/null +++ b/packages/kernel/linux/patches/default/linux-999.21-intel_idle-Disable-C6N-and-C6S-on-Bay-Trail.patch @@ -0,0 +1,53 @@ +From 945d0eb39d8920854c72ecb743c07d54b738cf7f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 9 Nov 2017 14:21:24 +0100 +Subject: [PATCH v3 2/2] intel_idle: Disable C6N and C6S on Bay Trail + +It seems that Bay Trail SoCs sometimes have issues waking from C6, +a lot of users even report Bay Trail devices only being stable +when passing intel_idle.max_cstate=1 to the kernel. + +This commits disables the C6 states while leaving the C7 states +available so that the cores can still reach deep sleep states. + +There are several indicators that this is part of the solution for +all the users who need to pass intel_idle.max_cstate=1: + +1) The "VLP52 EOI Transactions May Not be Sent if Software + Enters Core C6 During an Interrupt Service Routine" errata. + +2) Several users who need intel_idle.max_cstate=1 indicate in bko109051 + (which has over 800 comments!) that using a shell script which + disables C6N and C6S through sysfs allows them to remove + intel_idle.max_cstate=1 and still have a stable system which does + use the C7 states for power-saving. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=109051 +Signed-off-by: Hans de Goede +--- + drivers/idle/intel_idle.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c +index 5dc7ea4b6bc4..fe05984c9e81 100644 +--- a/drivers/idle/intel_idle.c ++++ b/drivers/idle/intel_idle.c +@@ -221,6 +221,7 @@ static struct cpuidle_state byt_cstates[] = { + .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 300, + .target_residency = 275, ++ .disabled = true, + .enter = &intel_idle, + .enter_s2idle = intel_idle_s2idle, }, + { +@@ -229,6 +230,7 @@ static struct cpuidle_state byt_cstates[] = { + .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 500, + .target_residency = 560, ++ .disabled = true, + .enter = &intel_idle, + .enter_s2idle = intel_idle_s2idle, }, + { +-- +2.14.3 + diff --git a/packages/kernel/linux/patches/linux-004_lower_undefined_mode_timeout.patch b/packages/kernel/linux/patches/linux-004_lower_undefined_mode_timeout.patch new file mode 100644 index 000000000..a0aca61d2 --- /dev/null +++ b/packages/kernel/linux/patches/linux-004_lower_undefined_mode_timeout.patch @@ -0,0 +1,24 @@ +diff -Naur linux-2.6.23-rc9.orig/arch/i386/boot/tty.c linux-2.6.23-rc9/arch/i386/boot/tty.c +--- linux-2.6.23-rc9.orig/arch/x86/boot/tty.c 2007-10-06 12:26:14.000000000 +0200 ++++ linux-2.6.23-rc9/arch/x86/boot/tty.c 2007-10-06 12:37:47.000000000 +0200 +@@ -92,7 +92,7 @@ + + int getchar_timeout(void) + { +- int cnt = 30; ++ int cnt = 3; + int t0, t1; + + t0 = gettime(); +diff -Naur linux-2.6.23-rc9.orig/arch/i386/boot/video.c linux-2.6.23-rc9/arch/i386/boot/video.c +--- linux-2.6.23-rc9.orig/arch/x86/boot/video.c 2007-10-06 12:26:14.000000000 +0200 ++++ linux-2.6.23-rc9/arch/x86/boot/video.c 2007-10-06 12:36:05.000000000 +0200 +@@ -329,7 +329,7 @@ + unsigned int sel; + + puts("Press to see video modes available, " +- " to continue, or wait 30 sec\n"); ++ " to continue, or wait 3 sec\n"); + + kbd_flush(); + while (1) { diff --git a/packages/kernel/linux/patches/linux-007_die_floppy_die.patch b/packages/kernel/linux/patches/linux-007_die_floppy_die.patch new file mode 100644 index 000000000..76db31218 --- /dev/null +++ b/packages/kernel/linux/patches/linux-007_die_floppy_die.patch @@ -0,0 +1,30 @@ +From 4ff58b642f80dedb20533978123d89b5ac9b1ed5 Mon Sep 17 00:00:00 2001 +From: Kyle McMartin +Date: Tue, 30 Mar 2010 00:04:29 -0400 +Subject: die-floppy-die + +Kill the floppy.ko pnp modalias. We were surviving just fine without +autoloading floppy drivers, tyvm. + +Please feel free to register all complaints in the wastepaper bin. +--- + drivers/block/floppy.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 90c4038..f4a0b90 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -4619,8 +4619,7 @@ static const struct pnp_device_id floppy_pnpids[] = { + {"PNP0700", 0}, + {} + }; +- +-MODULE_DEVICE_TABLE(pnp, floppy_pnpids); ++/* MODULE_DEVICE_TABLE(pnp, floppy_pnpids); */ + + #else + +-- +1.7.0.1 + diff --git a/packages/kernel/linux/patches/linux-009_disable_i8042_check_on_apple_mac.patch b/packages/kernel/linux/patches/linux-009_disable_i8042_check_on_apple_mac.patch new file mode 100644 index 000000000..f99d0f900 --- /dev/null +++ b/packages/kernel/linux/patches/linux-009_disable_i8042_check_on_apple_mac.patch @@ -0,0 +1,59 @@ +From 2a79554c864ac58fa2ad982f0fcee2cc2aa33eb5 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 20 May 2010 10:30:31 -0400 +Subject: Disable i8042 checks on Intel Apple Macs + +As those computers never had any i8042 controllers, and the +current lookup code could potentially lock up/hang/wait for +timeout for long periods of time. + +Fixes intermittent hangs on boot on a MacbookAir1,1 + +Signed-off-by: Bastien Nocera +--- + drivers/input/serio/i8042.c | 22 ++++++++++++++++++++++ + 1 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index 6440a8f..4d7cf98 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -1451,6 +1451,22 @@ static struct platform_driver i8042_driver = { + .shutdown = i8042_shutdown, + }; + ++#ifdef CONFIG_DMI ++static struct dmi_system_id __initdata dmi_system_table[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_BIOS_VENDOR, "Apple Computer, Inc.") ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BIOS_VENDOR, "Apple Inc.") ++ }, ++ }, ++ {} ++}; ++#endif /*CONFIG_DMI*/ ++ + static int __init i8042_init(void) + { + struct platform_device *pdev; +@@ -1458,6 +1474,12 @@ static int __init i8042_init(void) + + dbg_init(); + ++#ifdef CONFIG_DMI ++ /* Intel Apple Macs never have an i8042 controller */ ++ if (dmi_check_system(dmi_system_table) > 0) ++ return -ENODEV; ++#endif /*CONFIG_DMI*/ ++ + err = i8042_platform_init(); + if (err) + return err; +-- +1.7.0.1 + diff --git a/packages/kernel/linux/patches/linux-010-usbhid-quirks.patch b/packages/kernel/linux/patches/linux-010-usbhid-quirks.patch new file mode 100644 index 000000000..00c5ceb61 --- /dev/null +++ b/packages/kernel/linux/patches/linux-010-usbhid-quirks.patch @@ -0,0 +1,58 @@ +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index e6cfd32..7aa0ff0 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -163,6 +163,53 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, + ++// Juyao ++ { 0x0314,0x0326,0x040 }, ++ { 0x0314,0x0328,0x040 }, ++ ++// 4NES4SNES ++ { 0x1781,0x0A9D,0x040 }, ++ ++// Retrolink SNES ++ { 0x1292,0x5346,0x040 }, ++ { 0x1292,0x5366,0x040 }, ++ ++// Retrobit Atari to USB Driver ++ { 0x1292,0x4154,0x040 }, ++ ++// Retrobit Genesis to PC USB Adapter ++ { 0x1292,0x4745,0x040 }, ++ ++// Retrode ++ { 0x0403,0x97c1,0x040 }, ++ ++// HuiJia USB GamePad Mayflash Sega Saturn ++ { 0x0e8f,0x3010,0x040 }, ++ ++// HuiJia USB GamePad Mayflash NES SNES ++ { 0x0079,0x1804,0x040 }, ++ ++// Mayflash Dreamcast ++ { 0x0e8f,0x3013,0x040 }, ++ ++// Xin-Mo 2players 20pins ++ { 0x16c0,0x75e1,0x040 }, ++ ++// Xinmo 18 pins USB THT 2P arcade controller THT 2P arcade controller ++ { 0x16c0,0x05e1,0x040 }, ++ ++// USB PS2 Adapter GreenAsia Electronics ++ { 0xe8f,0x1013,0x040 }, ++ ++// HuiJia USB GamePad Mayflash N64 - need test ++ { 0xe8f,0x3013,0x040 }, ++ ++// XCSOURCE 2 Encoder USB - Twin USB Gamepad ++ { 0x810,0xe001,0x040 }, ++ ++// 3H Dual Arcade 2Players ++ { 0x16c0,0x05e0,0x040 }, ++ + { 0, 0 } + }; + diff --git a/packages/kernel/linux/patches/raspberrypi/linux-051-ouya_controller_support.patch b/packages/kernel/linux/patches/raspberrypi/linux-051-ouya_controller_support.patch new file mode 100644 index 000000000..8ee3cb27b --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-051-ouya_controller_support.patch @@ -0,0 +1,206 @@ +commit 5a596921a4636e62843a59b7eab7b87b70a6d296 +Author: Lukas Rusak +Date: Sun May 6 22:03:11 2018 -0700 + + HID: add ouya HID driver + + This driver is a simple implementation to get the controller working and mapped properly. + This driver does not include functionality for the touchpad (yet). The original driver + was taken from from the ouya linux tree and has been simplified. It seems there may have + been other versions of the controller present that had a broken report descriptor. I have + removed that for now. + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 60252fd796f6..6be2c454e72e 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -659,6 +659,12 @@ config HID_ORTEK + - Ortek WKB-2000 + - Skycable wireless presenter + ++config HID_OUYA ++ tristate "OUYA Game Controller" ++ depends on USB_HID ++ ---help--- ++ Support for OUYA Game Controller. ++ + config HID_PANTHERLORD + tristate "Pantherlord/GreenAsia game controller" + depends on HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 17a8bd97da9d..4425890934e4 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -71,6 +71,7 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o + obj-$(CONFIG_HID_NTI) += hid-nti.o + obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o + obj-$(CONFIG_HID_ORTEK) += hid-ortek.o ++obj-$(CONFIG_HID_OUYA) += hid-ouya.o + obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o + obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o + obj-$(CONFIG_HID_PENMOUNT) += hid-penmount.o +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 0b5cc910f62e..0528efb825fa 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -859,6 +859,9 @@ + #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 + #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S 0x8003 + ++#define USB_VENDOR_ID_OUYA 0x2836 ++#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001 ++ + #define USB_VENDOR_ID_PLANTRONICS 0x047f + + #define USB_VENDOR_ID_PANASONIC 0x04da +diff --git a/drivers/hid/hid-ouya.c b/drivers/hid/hid-ouya.c +new file mode 100644 +index 000000000000..4344a47b40af +--- /dev/null ++++ b/drivers/hid/hid-ouya.c +@@ -0,0 +1,131 @@ ++/* ++ * HID driver for OUYA Game Controller(s) ++ * ++ * Copyright (c) 2013 OUYA ++ * Copyright (c) 2013 Gregorios Leach ++ * Copyright (c) 2018 Lukas Rusak ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++static const unsigned int ouya_absmap[] = { ++ [0x30] = ABS_X, /* left stick X */ ++ [0x31] = ABS_Y, /* left stick Y */ ++ [0x32] = ABS_Z, /* L2 */ ++ [0x33] = ABS_RX, /* right stick X */ ++ [0x34] = ABS_RY, /* right stick Y */ ++ [0x35] = ABS_RZ, /* R2 */ ++}; ++ ++static const unsigned int ouya_keymap[] = { ++ [0x1] = BTN_SOUTH, /* O */ ++ [0x2] = BTN_WEST, /* U */ ++ [0x3] = BTN_NORTH, /* Y */ ++ [0x4] = BTN_EAST, /* A */ ++ [0x5] = BTN_TL, /* L1 */ ++ [0x6] = BTN_TR, /* R1 */ ++ [0x7] = BTN_THUMBL, /* L3 */ ++ [0x8] = BTN_THUMBR, /* R3 */ ++ [0x9] = BTN_DPAD_UP, /* Up */ ++ [0xa] = BTN_DPAD_DOWN, /* Down */ ++ [0xb] = BTN_DPAD_LEFT, /* Left */ ++ [0xc] = BTN_DPAD_RIGHT, /* Right */ ++ [0xd] = BTN_TL2, /* L2 */ ++ [0xe] = BTN_TR2, /* R2 */ ++ [0xf] = BTN_MODE, /* Power */ ++}; ++ ++static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if (key >= ARRAY_SIZE(ouya_keymap)) ++ return -1; ++ ++ key = ouya_keymap[key]; ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ ++ return 1; ++ ++ } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { ++ unsigned int abs = usage->hid & HID_USAGE; ++ ++ if (abs >= ARRAY_SIZE(ouya_absmap)) ++ return -1; ++ ++ abs = ouya_absmap[abs]; ++ hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id) ++{ ++ int ret; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ hid_err(hdev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE); ++ if (ret) { ++ hid_err(hdev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++ ++err_free: ++ return ret; ++} ++ ++static void ouya_remove(struct hid_device *hdev) ++{ ++ hid_hw_stop(hdev); ++ kfree(hid_get_drvdata(hdev)); ++} ++ ++static const struct hid_device_id ouya_devices[] = { ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, ouya_devices); ++ ++static struct hid_driver ouya_driver = { ++ .name = "ouya", ++ .id_table = ouya_devices, ++ .input_mapping = ouya_input_mapping, ++ .probe = ouya_probe, ++ .remove = ouya_remove, ++}; ++ ++static int __init ouya_init(void) ++{ ++ return hid_register_driver(&ouya_driver); ++} ++ ++static void __exit ouya_exit(void) ++{ ++ hid_unregister_driver(&ouya_driver); ++} ++ ++module_init(ouya_init); ++module_exit(ouya_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lukas Rusak "); ++MODULE_AUTHOR("Gregorios Leach "); ++MODULE_DESCRIPTION("Ouya Controller Driver"); +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 587e2681a53f..b5adc13e0df1 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -538,6 +538,9 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, + #endif ++#if IS_ENABLED(CONFIG_HID_OUYA) ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++#endif + #if IS_ENABLED(CONFIG_HID_PANTHERLORD) + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, diff --git a/packages/kernel/linux/patches/raspberrypi/linux-052-xbox_dvd_remote_support.patch b/packages/kernel/linux/patches/raspberrypi/linux-052-xbox_dvd_remote_support.patch new file mode 100644 index 000000000..8db97ddb2 --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-052-xbox_dvd_remote_support.patch @@ -0,0 +1,466 @@ +From 4d331d301222dc0585ab8864a842b3e460b1f744 Mon Sep 17 00:00:00 2001 +From: Benjamin Valentin +Date: Thu, 4 Oct 2018 02:57:10 +0200 +Subject: [PATCH] media: rc: add driver for Xbox DVD Movie Playback Kit + +The Xbox DVD Movie Playback Kit is a USB dongle with an IR remote for the +Original Xbox. + +Historically it has been supported by the out-of-tree lirc_xbox driver, +but this one has fallen out of favour and was just dropped from popular +Kodi (formerly XBMC) distributions. + +This driver is heaviely based on the ati_remote driver where all the +boilerplate was taken from - I was mostly just removing code. + +Signed-off-by: Benjamin Valentin +Signed-off-by: Sean Young +--- + drivers/media/rc/Kconfig | 12 + + drivers/media/rc/Makefile | 1 + + drivers/media/rc/keymaps/Makefile | 1 + + drivers/media/rc/keymaps/rc-xbox-dvd.c | 63 +++++ + drivers/media/rc/xbox_remote.c | 306 +++++++++++++++++++++++++ + include/media/rc-map.h | 1 + + 6 files changed, 384 insertions(+) + create mode 100644 drivers/media/rc/keymaps/rc-xbox-dvd.c + create mode 100644 drivers/media/rc/xbox_remote.c + +diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig +index 1021c08a9ba4..8a216068a35a 100644 +--- a/drivers/media/rc/Kconfig ++++ b/drivers/media/rc/Kconfig +@@ -493,6 +493,18 @@ config IR_TANGO + The HW decoder supports NEC, RC-5, RC-6 IR protocols. + When compiled as a module, look for tango-ir. + ++config RC_XBOX_DVD ++ tristate "Xbox DVD Movie Playback Kit" ++ depends on RC_CORE ++ depends on USB_ARCH_HAS_HCD ++ select USB ++ help ++ Say Y here if you want to use the Xbox DVD Movie Playback Kit. ++ These are IR remotes with USB receivers for the Original Xbox (2001). ++ ++ To compile this driver as a module, choose M here: the module will be ++ called xbox_remote. ++ + config IR_ZX + tristate "ZTE ZX IR remote control" + depends on RC_CORE +diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile +index e0340d043fe8..92c163816849 100644 +--- a/drivers/media/rc/Makefile ++++ b/drivers/media/rc/Makefile +@@ -48,3 +48,4 @@ obj-$(CONFIG_IR_SIR) += sir_ir.o + obj-$(CONFIG_IR_MTK) += mtk-cir.o + obj-$(CONFIG_IR_ZX) += zx-irdec.o + obj-$(CONFIG_IR_TANGO) += tango-ir.o ++obj-$(CONFIG_RC_XBOX_DVD) += xbox_remote.o +diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile +index d6b913a3032d..5b1399af6b3a 100644 +--- a/drivers/media/rc/keymaps/Makefile ++++ b/drivers/media/rc/keymaps/Makefile +@@ -116,4 +116,5 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-winfast.o \ + rc-winfast-usbii-deluxe.o \ + rc-su3000.o \ ++ rc-xbox-dvd.o \ + rc-zx-irdec.o +diff --git a/drivers/media/rc/keymaps/rc-xbox-dvd.c b/drivers/media/rc/keymaps/rc-xbox-dvd.c +new file mode 100644 +index 000000000000..af387244636b +--- /dev/null ++++ b/drivers/media/rc/keymaps/rc-xbox-dvd.c +@@ -0,0 +1,63 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// Keytable for Xbox DVD remote ++// Copyright (c) 2018 by Benjamin Valentin ++ ++#include ++#include ++ ++/* based on lircd.conf.xbox */ ++static struct rc_map_table xbox_dvd[] = { ++ {0xa0b, KEY_OK}, ++ {0xaa6, KEY_UP}, ++ {0xaa7, KEY_DOWN}, ++ {0xaa8, KEY_RIGHT}, ++ {0xaa9, KEY_LEFT}, ++ {0xac3, KEY_INFO}, ++ ++ {0xac6, KEY_9}, ++ {0xac7, KEY_8}, ++ {0xac8, KEY_7}, ++ {0xac9, KEY_6}, ++ {0xaca, KEY_5}, ++ {0xacb, KEY_4}, ++ {0xacc, KEY_3}, ++ {0xacd, KEY_2}, ++ {0xace, KEY_1}, ++ {0xacf, KEY_0}, ++ ++ {0xad5, KEY_ANGLE}, ++ {0xad8, KEY_BACK}, ++ {0xadd, KEY_PREVIOUSSONG}, ++ {0xadf, KEY_NEXTSONG}, ++ {0xae0, KEY_STOP}, ++ {0xae2, KEY_REWIND}, ++ {0xae3, KEY_FASTFORWARD}, ++ {0xae5, KEY_TITLE}, ++ {0xae6, KEY_PAUSE}, ++ {0xaea, KEY_PLAY}, ++ {0xaf7, KEY_MENU}, ++}; ++ ++static struct rc_map_list xbox_dvd_map = { ++ .map = { ++ .scan = xbox_dvd, ++ .size = ARRAY_SIZE(xbox_dvd), ++ .rc_proto = RC_PROTO_UNKNOWN, ++ .name = RC_MAP_XBOX_DVD, ++ } ++}; ++ ++static int __init init_rc_map(void) ++{ ++ return rc_map_register(&xbox_dvd_map); ++} ++ ++static void __exit exit_rc_map(void) ++{ ++ rc_map_unregister(&xbox_dvd_map); ++} ++ ++module_init(init_rc_map) ++module_exit(exit_rc_map) ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c +new file mode 100644 +index 000000000000..07ed9be24a60 +--- /dev/null ++++ b/drivers/media/rc/xbox_remote.c +@@ -0,0 +1,306 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// Driver for Xbox DVD Movie Playback Kit ++// Copyright (c) 2018 by Benjamin Valentin ++ ++/* ++ * Xbox DVD Movie Playback Kit USB IR dongle support ++ * ++ * The driver was derived from the ati_remote driver 2.2.1 ++ * and used information from lirc_xbox.c ++ * ++ * Copyright (c) 2011, 2012 Anssi Hannula ++ * Copyright (c) 2004 Torrey Hoffman ++ * Copyright (c) 2002 Vladimir Dergachev ++ * Copyright (c) 2003-2004 Paul Miller ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * Module and Version Information ++ */ ++#define DRIVER_VERSION "1.0.0" ++#define DRIVER_AUTHOR "Benjamin Valentin " ++#define DRIVER_DESC "Xbox DVD USB Remote Control" ++ ++#define NAME_BUFSIZE 80 /* size of product name, path buffers */ ++#define DATA_BUFSIZE 8 /* size of URB data buffers */ ++ ++/* ++ * USB vendor ids for XBOX DVD Dongles ++ */ ++#define VENDOR_GAMESTER 0x040b ++#define VENDOR_MICROSOFT 0x045e ++ ++static const struct usb_device_id xbox_remote_table[] = { ++ /* Gamester Xbox DVD Movie Playback Kit IR */ ++ { ++ USB_DEVICE(VENDOR_GAMESTER, 0x6521), ++ }, ++ /* Microsoft Xbox DVD Movie Playback Kit IR */ ++ { ++ USB_DEVICE(VENDOR_MICROSOFT, 0x0284), ++ }, ++ {} /* Terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, xbox_remote_table); ++ ++struct xbox_remote { ++ struct rc_dev *rdev; ++ struct usb_device *udev; ++ struct usb_interface *interface; ++ ++ struct urb *irq_urb; ++ unsigned char inbuf[DATA_BUFSIZE] __aligned(sizeof(u16)); ++ ++ char rc_name[NAME_BUFSIZE]; ++ char rc_phys[NAME_BUFSIZE]; ++}; ++ ++static int xbox_remote_rc_open(struct rc_dev *rdev) ++{ ++ struct xbox_remote *xbox_remote = rdev->priv; ++ ++ /* On first open, submit the read urb which was set up previously. */ ++ xbox_remote->irq_urb->dev = xbox_remote->udev; ++ if (usb_submit_urb(xbox_remote->irq_urb, GFP_KERNEL)) { ++ dev_err(&xbox_remote->interface->dev, ++ "%s: usb_submit_urb failed!\n", __func__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void xbox_remote_rc_close(struct rc_dev *rdev) ++{ ++ struct xbox_remote *xbox_remote = rdev->priv; ++ ++ usb_kill_urb(xbox_remote->irq_urb); ++} ++ ++/* ++ * xbox_remote_report_input ++ */ ++static void xbox_remote_input_report(struct urb *urb) ++{ ++ struct xbox_remote *xbox_remote = urb->context; ++ unsigned char *data = xbox_remote->inbuf; ++ ++ /* ++ * data[0] = 0x00 ++ * data[1] = length - always 0x06 ++ * data[2] = the key code ++ * data[3] = high part of key code ++ * data[4] = last_press_ms (low) ++ * data[5] = last_press_ms (high) ++ */ ++ ++ /* Deal with strange looking inputs */ ++ if (urb->actual_length != 6 || urb->actual_length != data[1]) { ++ dev_warn(&urb->dev->dev, "Weird data, len=%d: %*ph\n", ++ urb->actual_length, urb->actual_length, data); ++ return; ++ } ++ ++ rc_keydown(xbox_remote->rdev, RC_PROTO_UNKNOWN, ++ le16_to_cpup((__le16*)(data + 2)), 0); ++} ++ ++/* ++ * xbox_remote_irq_in ++ */ ++static void xbox_remote_irq_in(struct urb *urb) ++{ ++ struct xbox_remote *xbox_remote = urb->context; ++ int retval; ++ ++ switch (urb->status) { ++ case 0: /* success */ ++ xbox_remote_input_report(urb); ++ break; ++ case -ECONNRESET: /* unlink */ ++ case -ENOENT: ++ case -ESHUTDOWN: ++ dev_dbg(&xbox_remote->interface->dev, ++ "%s: urb error status, unlink?\n", ++ __func__); ++ return; ++ default: /* error */ ++ dev_dbg(&xbox_remote->interface->dev, ++ "%s: Nonzero urb status %d\n", ++ __func__, urb->status); ++ } ++ ++ retval = usb_submit_urb(urb, GFP_ATOMIC); ++ if (retval) ++ dev_err(&xbox_remote->interface->dev, ++ "%s: usb_submit_urb()=%d\n", ++ __func__, retval); ++} ++ ++static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) ++{ ++ struct rc_dev *rdev = xbox_remote->rdev; ++ ++ rdev->priv = xbox_remote; ++ rdev->allowed_protocols = RC_PROTO_BIT_UNKNOWN; ++ rdev->driver_name = "xbox_remote"; ++ ++ rdev->open = xbox_remote_rc_open; ++ rdev->close = xbox_remote_rc_close; ++ ++ rdev->device_name = xbox_remote->rc_name; ++ rdev->input_phys = xbox_remote->rc_phys; ++ ++ usb_to_input_id(xbox_remote->udev, &rdev->input_id); ++ rdev->dev.parent = &xbox_remote->interface->dev; ++} ++ ++static int xbox_remote_initialize(struct xbox_remote *xbox_remote, ++ struct usb_endpoint_descriptor *endpoint_in) ++{ ++ struct usb_device *udev = xbox_remote->udev; ++ int pipe, maxp; ++ ++ /* Set up irq_urb */ ++ pipe = usb_rcvintpipe(udev, endpoint_in->bEndpointAddress); ++ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); ++ maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; ++ ++ usb_fill_int_urb(xbox_remote->irq_urb, udev, pipe, xbox_remote->inbuf, ++ maxp, xbox_remote_irq_in, xbox_remote, ++ endpoint_in->bInterval); ++ ++ return 0; ++} ++ ++/* ++ * xbox_remote_probe ++ */ ++static int xbox_remote_probe(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *udev = interface_to_usbdev(interface); ++ struct usb_host_interface *iface_host = interface->cur_altsetting; ++ struct usb_endpoint_descriptor *endpoint_in; ++ struct xbox_remote *xbox_remote; ++ struct rc_dev *rc_dev; ++ int err = -ENOMEM; ++ ++ // why is there also a device with no endpoints? ++ if (iface_host->desc.bNumEndpoints == 0) ++ return -ENODEV; ++ ++ if (iface_host->desc.bNumEndpoints != 1) { ++ pr_err("%s: Unexpected desc.bNumEndpoints: %d\n", ++ __func__, iface_host->desc.bNumEndpoints); ++ return -ENODEV; ++ } ++ ++ endpoint_in = &iface_host->endpoint[0].desc; ++ ++ if (!usb_endpoint_is_int_in(endpoint_in)) { ++ pr_err("%s: Unexpected endpoint_in\n", __func__); ++ return -ENODEV; ++ } ++ if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { ++ pr_err("%s: endpoint_in message size==0?\n", __func__); ++ return -ENODEV; ++ } ++ ++ xbox_remote = kzalloc(sizeof(*xbox_remote), GFP_KERNEL); ++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); ++ if (!xbox_remote || !rc_dev) ++ goto exit_free_dev_rdev; ++ ++ /* Allocate URB buffer */ ++ xbox_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!xbox_remote->irq_urb) ++ goto exit_free_buffers; ++ ++ xbox_remote->udev = udev; ++ xbox_remote->rdev = rc_dev; ++ xbox_remote->interface = interface; ++ ++ usb_make_path(udev, xbox_remote->rc_phys, sizeof(xbox_remote->rc_phys)); ++ ++ strlcat(xbox_remote->rc_phys, "/input0", sizeof(xbox_remote->rc_phys)); ++ ++ snprintf(xbox_remote->rc_name, sizeof(xbox_remote->rc_name), "%s%s%s", ++ udev->manufacturer ?: "", ++ udev->manufacturer && udev->product ? " " : "", ++ udev->product ?: ""); ++ ++ if (!strlen(xbox_remote->rc_name)) ++ snprintf(xbox_remote->rc_name, sizeof(xbox_remote->rc_name), ++ DRIVER_DESC "(%04x,%04x)", ++ le16_to_cpu(xbox_remote->udev->descriptor.idVendor), ++ le16_to_cpu(xbox_remote->udev->descriptor.idProduct)); ++ ++ rc_dev->map_name = RC_MAP_XBOX_DVD; /* default map */ ++ ++ xbox_remote_rc_init(xbox_remote); ++ ++ /* Device Hardware Initialization */ ++ err = xbox_remote_initialize(xbox_remote, endpoint_in); ++ if (err) ++ goto exit_kill_urbs; ++ ++ /* Set up and register rc device */ ++ err = rc_register_device(xbox_remote->rdev); ++ if (err) ++ goto exit_kill_urbs; ++ ++ usb_set_intfdata(interface, xbox_remote); ++ ++ return 0; ++ ++exit_kill_urbs: ++ usb_kill_urb(xbox_remote->irq_urb); ++exit_free_buffers: ++ usb_free_urb(xbox_remote->irq_urb); ++exit_free_dev_rdev: ++ rc_free_device(rc_dev); ++ kfree(xbox_remote); ++ ++ return err; ++} ++ ++/* ++ * xbox_remote_disconnect ++ */ ++static void xbox_remote_disconnect(struct usb_interface *interface) ++{ ++ struct xbox_remote *xbox_remote; ++ ++ xbox_remote = usb_get_intfdata(interface); ++ usb_set_intfdata(interface, NULL); ++ if (!xbox_remote) { ++ dev_warn(&interface->dev, "%s - null device?\n", __func__); ++ return; ++ } ++ ++ usb_kill_urb(xbox_remote->irq_urb); ++ rc_unregister_device(xbox_remote->rdev); ++ usb_free_urb(xbox_remote->irq_urb); ++ kfree(xbox_remote); ++} ++ ++/* usb specific object to register with the usb subsystem */ ++static struct usb_driver xbox_remote_driver = { ++ .name = "xbox_remote", ++ .probe = xbox_remote_probe, ++ .disconnect = xbox_remote_disconnect, ++ .id_table = xbox_remote_table, ++}; ++ ++module_usb_driver(xbox_remote_driver); ++ ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_LICENSE("GPL"); +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index bfa3017cecba..d621acadfbf3 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -277,6 +277,7 @@ struct rc_map *rc_map_get(const char *name); + #define RC_MAP_WINFAST "rc-winfast" + #define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe" + #define RC_MAP_SU3000 "rc-su3000" ++#define RC_MAP_XBOX_DVD "rc-xbox-dvd" + #define RC_MAP_ZX_IRDEC "rc-zx-irdec" + + /* +-- +2.17.1 + diff --git a/packages/kernel/linux/patches/raspberrypi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/kernel/linux/patches/raspberrypi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 000000000..56e2ca865 --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,72 @@ +From 7051422474e4c4e302ede3d07ffd8ef2682e07a2 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 22 Apr 2014 16:05:14 +0300 +Subject: [PATCH] [RFC] hid/sony: add autorepeat for PS3 remotes + +adapted to 4.6 + +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. + +Signed-off-by: Matt DeVillier +--- + drivers/hid/hid-sony.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 310436a..84f7f41 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1120,6 +1120,25 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} ++ + static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) + { +@@ -2372,6 +2391,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + sony_init_output_report(sc, dualshock4_send_output_report); + } else if (sc->quirks & MOTION_CONTROLLER) { + sony_init_output_report(sc, motion_send_output_report); ++ } else if (sc->quirks & PS3REMOTE) { ++ ret = ps3remote_setup_repeat(hdev); + } else { + ret = 0; + } +-- +2.5.0 diff --git a/packages/kernel/linux/patches/raspberrypi/linux-062-imon_pad_ignore_diagonal.patch b/packages/kernel/linux/patches/raspberrypi/linux-062-imon_pad_ignore_diagonal.patch new file mode 100644 index 000000000..677de3ed7 --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-062-imon_pad_ignore_diagonal.patch @@ -0,0 +1,21 @@ +diff -Naur linux-3.16.1/drivers/media/rc/imon.c linux-3.16.1.patch/drivers/media/rc/imon.c +--- linux-3.16.1/drivers/media/rc/imon.c 2014-08-14 04:36:35.000000000 +0200 ++++ linux-3.16.1.patch/drivers/media/rc/imon.c 2014-08-15 13:57:16.587620642 +0200 +@@ -1344,6 +1344,17 @@ + } + } else { + /* ++ * For users without stabilized, just ignore any value getting ++ * to close to the diagonal. ++ */ ++ if ((abs(rel_y) < 2 && abs(rel_x) < 2) || ++ abs(abs(rel_y) - abs(rel_x)) < 2 ) { ++ spin_lock_irqsave(&ictx->kc_lock, flags); ++ ictx->kc = KEY_UNKNOWN; ++ spin_unlock_irqrestore(&ictx->kc_lock, flags); ++ return; ++ } ++ /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ diff --git a/packages/kernel/linux/patches/raspberrypi/linux-902-extend-rc6-toggle-support-for-zotac.patch b/packages/kernel/linux/patches/raspberrypi/linux-902-extend-rc6-toggle-support-for-zotac.patch new file mode 100644 index 000000000..65fe5fd6c --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-902-extend-rc6-toggle-support-for-zotac.patch @@ -0,0 +1,41 @@ +From ae1ccaa3587c0bd3d6d01841fa2e668cdf738f1e Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 3 Feb 2019 14:24:00 +0100 +Subject: [PATCH] media: rc: ir-rc6-decoder: enable toggle bit for Zotac + remotes + +The Zotac RC2604323/01G and RC2604329/02BG remotes use the 32-bit +rc6 protocol and toggle bit 15 (0x8000) on repeated button presses, +like MCE remotes. + +Add the customer code 0x80340000 to the 32-bit rc6 toggle +handling code to get proper scancodes and toggle reports. + +Signed-off-by: Matthias Reichl +--- + drivers/media/rc/ir-rc6-decoder.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c +index d96aed1343e4..5cc302fa4daa 100644 +--- a/drivers/media/rc/ir-rc6-decoder.c ++++ b/drivers/media/rc/ir-rc6-decoder.c +@@ -40,6 +40,7 @@ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ + #define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ ++#define RC6_6A_ZOTAC_CC 0x80340000 /* Zotac customer code */ + #define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ +@@ -246,6 +247,7 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) + switch (scancode & RC6_6A_LCC_MASK) { + case RC6_6A_MCE_CC: + case RC6_6A_KATHREIN_CC: ++ case RC6_6A_ZOTAC_CC: + protocol = RC_PROTO_RC6_MCE; + toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; +-- +2.20.1 + diff --git a/packages/kernel/linux/patches/raspberrypi/linux-903-backport-rcmm-ir-decoder.patch b/packages/kernel/linux/patches/raspberrypi/linux-903-backport-rcmm-ir-decoder.patch new file mode 100644 index 000000000..ae2cba849 --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-903-backport-rcmm-ir-decoder.patch @@ -0,0 +1,506 @@ +From da8a71104dda4a85a9d9546ff462542347f8efa6 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Wed, 20 Mar 2019 09:11:53 +0100 +Subject: [PATCH] media: rc: rcmm decoder and encoder + +commit 721074b03411327e7bf41555d4cc7c18f49313f7 upstream. + +media: add support for RCMM infrared remote controls. + +Signed-off-by: Patrick Lerda +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Matthias Reichl +--- + Documentation/media/lirc.h.rst.exceptions | 3 + + MAINTAINERS | 5 + + drivers/media/rc/Kconfig | 13 ++ + drivers/media/rc/Makefile | 1 + + drivers/media/rc/ir-rcmm-decoder.c | 254 ++++++++++++++++++++++ + drivers/media/rc/rc-core-priv.h | 5 + + drivers/media/rc/rc-main.c | 9 + + include/media/rc-map.h | 14 +- + include/uapi/linux/lirc.h | 6 + + tools/include/uapi/linux/lirc.h | 12 + + 10 files changed, 319 insertions(+), 3 deletions(-) + create mode 100644 drivers/media/rc/ir-rcmm-decoder.c + +diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions +index 984b61dc3f2e..e7a41d4b3d46 100644 +--- a/Documentation/media/lirc.h.rst.exceptions ++++ b/Documentation/media/lirc.h.rst.exceptions +@@ -58,6 +58,9 @@ ignore symbol RC_PROTO_SHARP + ignore symbol RC_PROTO_XMP + ignore symbol RC_PROTO_CEC + ignore symbol RC_PROTO_IMON ++ignore symbol RC_PROTO_RCMM12 ++ignore symbol RC_PROTO_RCMM24 ++ignore symbol RC_PROTO_RCMM32 + + # Undocumented macros + +diff --git a/MAINTAINERS b/MAINTAINERS +index 9e9b19ecf6f7..57b60dd42729 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -15837,6 +15837,11 @@ M: David Härdeman + S: Maintained + F: drivers/media/rc/winbond-cir.c + ++RCMM REMOTE CONTROLS DECODER ++M: Patrick Lerda ++S: Maintained ++F: drivers/media/rc/ir-rcmm-decoder.c ++ + WINSYSTEMS EBC-C384 WATCHDOG DRIVER + M: William Breathitt Gray + L: linux-watchdog@vger.kernel.org +diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig +index 1021c08a9ba4..8164a889011a 100644 +--- a/drivers/media/rc/Kconfig ++++ b/drivers/media/rc/Kconfig +@@ -133,6 +133,19 @@ config IR_IMON_DECODER + remote control and you would like to use it with a raw IR + receiver, or if you wish to use an encoder to transmit this IR. + ++config IR_RCMM_DECODER ++ tristate "Enable IR raw decoder for the RC-MM protocol" ++ depends on RC_CORE ++ help ++ Enable this option when you have IR with RC-MM protocol, and ++ you need the software decoder. The driver supports 12, ++ 24 and 32 bits RC-MM variants. You can enable or disable the ++ different modes using the following RC protocol keywords: ++ 'rc-mm-12', 'rc-mm-24' and 'rc-mm-32'. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called ir-rcmm-decoder. ++ + endif #RC_DECODERS + + menuconfig RC_DEVICES +diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile +index e0340d043fe8..fc4058013234 100644 +--- a/drivers/media/rc/Makefile ++++ b/drivers/media/rc/Makefile +@@ -16,6 +16,7 @@ obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o + obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o + obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o + obj-$(CONFIG_IR_IMON_DECODER) += ir-imon-decoder.o ++obj-$(CONFIG_IR_RCMM_DECODER) += ir-rcmm-decoder.o + + # stand-alone IR receivers/transmitters + obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o +diff --git a/drivers/media/rc/ir-rcmm-decoder.c b/drivers/media/rc/ir-rcmm-decoder.c +new file mode 100644 +index 000000000000..f1096ac1e5c5 +--- /dev/null ++++ b/drivers/media/rc/ir-rcmm-decoder.c +@@ -0,0 +1,254 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ir-rcmm-decoder.c - A decoder for the RCMM IR protocol ++// ++// Copyright (C) 2018 by Patrick Lerda ++ ++#include "rc-core-priv.h" ++#include ++#include ++ ++#define RCMM_UNIT 166667 /* nanosecs */ ++#define RCMM_PREFIX_PULSE 416666 /* 166666.666666666*2.5 */ ++#define RCMM_PULSE_0 277777 /* 166666.666666666*(1+2/3) */ ++#define RCMM_PULSE_1 444444 /* 166666.666666666*(2+2/3) */ ++#define RCMM_PULSE_2 611111 /* 166666.666666666*(3+2/3) */ ++#define RCMM_PULSE_3 777778 /* 166666.666666666*(4+2/3) */ ++ ++enum rcmm_state { ++ STATE_INACTIVE, ++ STATE_LOW, ++ STATE_BUMP, ++ STATE_VALUE, ++ STATE_FINISHED, ++}; ++ ++static bool rcmm_mode(const struct rcmm_dec *data) ++{ ++ return !((0x000c0000 & data->bits) == 0x000c0000); ++} ++ ++static int rcmm_miscmode(struct rc_dev *dev, struct rcmm_dec *data) ++{ ++ switch (data->count) { ++ case 24: ++ if (dev->enabled_protocols & RC_PROTO_BIT_RCMM24) { ++ rc_keydown(dev, RC_PROTO_RCMM24, data->bits, 0); ++ data->state = STATE_INACTIVE; ++ return 0; ++ } ++ return -1; ++ ++ case 12: ++ if (dev->enabled_protocols & RC_PROTO_BIT_RCMM12) { ++ rc_keydown(dev, RC_PROTO_RCMM12, data->bits, 0); ++ data->state = STATE_INACTIVE; ++ return 0; ++ } ++ return -1; ++ } ++ ++ return -1; ++} ++ ++/** ++ * ir_rcmm_decode() - Decode one RCMM pulse or space ++ * @dev: the struct rc_dev descriptor of the device ++ * @ev: the struct ir_raw_event descriptor of the pulse/space ++ * ++ * This function returns -EINVAL if the pulse violates the state machine ++ */ ++static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev) ++{ ++ struct rcmm_dec *data = &dev->raw->rcmm; ++ u32 scancode; ++ u8 toggle; ++ int value; ++ ++ if (!(dev->enabled_protocols & (RC_PROTO_BIT_RCMM32 | ++ RC_PROTO_BIT_RCMM24 | ++ RC_PROTO_BIT_RCMM12))) ++ return 0; ++ ++ if (!is_timing_event(ev)) { ++ if (ev.reset) ++ data->state = STATE_INACTIVE; ++ return 0; ++ } ++ ++ switch (data->state) { ++ case STATE_INACTIVE: ++ if (!ev.pulse) ++ break; ++ ++ if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT / 2)) ++ break; ++ ++ data->state = STATE_LOW; ++ data->count = 0; ++ data->bits = 0; ++ return 0; ++ ++ case STATE_LOW: ++ if (ev.pulse) ++ break; ++ ++ if (!eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) ++ break; ++ ++ data->state = STATE_BUMP; ++ return 0; ++ ++ case STATE_BUMP: ++ if (!ev.pulse) ++ break; ++ ++ if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2)) ++ break; ++ ++ data->state = STATE_VALUE; ++ return 0; ++ ++ case STATE_VALUE: ++ if (ev.pulse) ++ break; ++ ++ if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2)) ++ value = 0; ++ else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2)) ++ value = 1; ++ else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2)) ++ value = 2; ++ else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2)) ++ value = 3; ++ else ++ value = -1; ++ ++ if (value == -1) { ++ if (!rcmm_miscmode(dev, data)) ++ return 0; ++ break; ++ } ++ ++ data->bits <<= 2; ++ data->bits |= value; ++ ++ data->count += 2; ++ ++ if (data->count < 32) ++ data->state = STATE_BUMP; ++ else ++ data->state = STATE_FINISHED; ++ ++ return 0; ++ ++ case STATE_FINISHED: ++ if (!ev.pulse) ++ break; ++ ++ if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2)) ++ break; ++ ++ if (rcmm_mode(data)) { ++ toggle = !!(0x8000 & data->bits); ++ scancode = data->bits & ~0x8000; ++ } else { ++ toggle = 0; ++ scancode = data->bits; ++ } ++ ++ if (dev->enabled_protocols & RC_PROTO_BIT_RCMM32) { ++ rc_keydown(dev, RC_PROTO_RCMM32, scancode, toggle); ++ data->state = STATE_INACTIVE; ++ return 0; ++ } ++ ++ break; ++ } ++ ++ data->state = STATE_INACTIVE; ++ return -EINVAL; ++} ++ ++static const int rcmmspace[] = { ++ RCMM_PULSE_0, ++ RCMM_PULSE_1, ++ RCMM_PULSE_2, ++ RCMM_PULSE_3, ++}; ++ ++static int ir_rcmm_rawencoder(struct ir_raw_event **ev, unsigned int max, ++ unsigned int n, u32 data) ++{ ++ int i; ++ int ret; ++ ++ ret = ir_raw_gen_pulse_space(ev, &max, RCMM_PREFIX_PULSE, RCMM_PULSE_0); ++ if (ret) ++ return ret; ++ ++ for (i = n - 2; i >= 0; i -= 2) { ++ const unsigned int space = rcmmspace[(data >> i) & 3]; ++ ++ ret = ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, space); ++ if (ret) ++ return ret; ++ } ++ ++ return ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, RCMM_PULSE_3 * 2); ++} ++ ++static int ir_rcmm_encode(enum rc_proto protocol, u32 scancode, ++ struct ir_raw_event *events, unsigned int max) ++{ ++ struct ir_raw_event *e = events; ++ int ret; ++ ++ switch (protocol) { ++ case RC_PROTO_RCMM32: ++ ret = ir_rcmm_rawencoder(&e, max, 32, scancode); ++ break; ++ case RC_PROTO_RCMM24: ++ ret = ir_rcmm_rawencoder(&e, max, 24, scancode); ++ break; ++ case RC_PROTO_RCMM12: ++ ret = ir_rcmm_rawencoder(&e, max, 12, scancode); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ if (ret < 0) ++ return ret; ++ ++ return e - events; ++} ++ ++static struct ir_raw_handler rcmm_handler = { ++ .protocols = RC_PROTO_BIT_RCMM32 | ++ RC_PROTO_BIT_RCMM24 | ++ RC_PROTO_BIT_RCMM12, ++ .decode = ir_rcmm_decode, ++ .encode = ir_rcmm_encode, ++ .carrier = 36000, ++ .min_timeout = RCMM_PULSE_3 + RCMM_UNIT, ++}; ++ ++static int __init ir_rcmm_decode_init(void) ++{ ++ ir_raw_handler_register(&rcmm_handler); ++ ++ pr_info("IR RCMM protocol handler initialized\n"); ++ return 0; ++} ++ ++static void __exit ir_rcmm_decode_exit(void) ++{ ++ ir_raw_handler_unregister(&rcmm_handler); ++} ++ ++module_init(ir_rcmm_decode_init); ++module_exit(ir_rcmm_decode_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Patrick Lerda"); ++MODULE_DESCRIPTION("RCMM IR protocol decoder"); +diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h +index e847bdad5c51..59c252f24194 100644 +--- a/drivers/media/rc/rc-core-priv.h ++++ b/drivers/media/rc/rc-core-priv.h +@@ -136,6 +136,11 @@ struct ir_raw_event_ctrl { + struct input_dev *idev; + char name[64]; + } imon; ++ struct rcmm_dec { ++ int state; ++ unsigned int count; ++ u32 bits; ++ } rcmm; + }; + + /* Mutex for locking raw IR processing and handler change */ +diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c +index 0f218afdadaa..78e79c37f208 100644 +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -70,6 +70,12 @@ static const struct { + [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 }, + [RC_PROTO_IMON] = { .name = "imon", + .scancode_bits = 0x7fffffff, .repeat_period = 114 }, ++ [RC_PROTO_RCMM12] = { .name = "rc-mm-12", ++ .scancode_bits = 0x00000fff, .repeat_period = 114 }, ++ [RC_PROTO_RCMM24] = { .name = "rc-mm-24", ++ .scancode_bits = 0x00ffffff, .repeat_period = 114 }, ++ [RC_PROTO_RCMM32] = { .name = "rc-mm-32", ++ .scancode_bits = 0xffffffff, .repeat_period = 114 }, + }; + + /* Used to keep track of known keymaps */ +@@ -1018,6 +1024,9 @@ static const struct { + { RC_PROTO_BIT_XMP, "xmp", "ir-xmp-decoder" }, + { RC_PROTO_BIT_CEC, "cec", NULL }, + { RC_PROTO_BIT_IMON, "imon", "ir-imon-decoder" }, ++ { RC_PROTO_BIT_RCMM12 | ++ RC_PROTO_BIT_RCMM24 | ++ RC_PROTO_BIT_RCMM32, "rc-mm", "ir-rcmm-decoder" }, + }; + + /** +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index bfa3017cecba..cf308b73edae 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -37,6 +37,9 @@ + #define RC_PROTO_BIT_XMP BIT_ULL(RC_PROTO_XMP) + #define RC_PROTO_BIT_CEC BIT_ULL(RC_PROTO_CEC) + #define RC_PROTO_BIT_IMON BIT_ULL(RC_PROTO_IMON) ++#define RC_PROTO_BIT_RCMM12 BIT_ULL(RC_PROTO_RCMM12) ++#define RC_PROTO_BIT_RCMM24 BIT_ULL(RC_PROTO_RCMM24) ++#define RC_PROTO_BIT_RCMM32 BIT_ULL(RC_PROTO_RCMM32) + + #define RC_PROTO_BIT_ALL \ + (RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \ +@@ -51,7 +54,8 @@ + RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \ + RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ + RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \ +- RC_PROTO_BIT_IMON) ++ RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM12 | \ ++ RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32) + /* All rc protocols for which we have decoders */ + #define RC_PROTO_BIT_ALL_IR_DECODER \ + (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ +@@ -64,7 +68,9 @@ + RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \ + RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | \ + RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ +- RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON) ++ RC_PROTO_BIT_XMP | RC_PROTO_BIT_IMON | \ ++ RC_PROTO_BIT_RCMM12 | RC_PROTO_BIT_RCMM24 | \ ++ RC_PROTO_BIT_RCMM32) + + #define RC_PROTO_BIT_ALL_IR_ENCODER \ + (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ +@@ -77,7 +83,9 @@ + RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | \ + RC_PROTO_BIT_RC6_6A_24 | \ + RC_PROTO_BIT_RC6_6A_32 | RC_PROTO_BIT_RC6_MCE | \ +- RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON) ++ RC_PROTO_BIT_SHARP | RC_PROTO_BIT_IMON | \ ++ RC_PROTO_BIT_RCMM12 | RC_PROTO_BIT_RCMM24 | \ ++ RC_PROTO_BIT_RCMM32) + + #define RC_SCANCODE_UNKNOWN(x) (x) + #define RC_SCANCODE_OTHER(x) (x) +diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h +index 6b319581882f..45fcbf99d72e 100644 +--- a/include/uapi/linux/lirc.h ++++ b/include/uapi/linux/lirc.h +@@ -192,6 +192,9 @@ struct lirc_scancode { + * @RC_PROTO_XMP: XMP protocol + * @RC_PROTO_CEC: CEC protocol + * @RC_PROTO_IMON: iMon Pad protocol ++ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits ++ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits ++ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits + */ + enum rc_proto { + RC_PROTO_UNKNOWN = 0, +@@ -218,6 +221,9 @@ enum rc_proto { + RC_PROTO_XMP = 21, + RC_PROTO_CEC = 22, + RC_PROTO_IMON = 23, ++ RC_PROTO_RCMM12 = 24, ++ RC_PROTO_RCMM24 = 25, ++ RC_PROTO_RCMM32 = 26, + }; + + #endif +diff --git a/tools/include/uapi/linux/lirc.h b/tools/include/uapi/linux/lirc.h +index f189931042a7..45fcbf99d72e 100644 +--- a/tools/include/uapi/linux/lirc.h ++++ b/tools/include/uapi/linux/lirc.h +@@ -133,6 +133,12 @@ + + #define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) + ++/* ++ * Return the recording timeout, which is either set by ++ * the ioctl LIRC_SET_REC_TIMEOUT or by the kernel after setting the protocols. ++ */ ++#define LIRC_GET_REC_TIMEOUT _IOR('i', 0x00000024, __u32) ++ + /* + * struct lirc_scancode - decoded scancode with protocol for use with + * LIRC_MODE_SCANCODE +@@ -186,6 +192,9 @@ struct lirc_scancode { + * @RC_PROTO_XMP: XMP protocol + * @RC_PROTO_CEC: CEC protocol + * @RC_PROTO_IMON: iMon Pad protocol ++ * @RC_PROTO_RCMM12: RC-MM protocol 12 bits ++ * @RC_PROTO_RCMM24: RC-MM protocol 24 bits ++ * @RC_PROTO_RCMM32: RC-MM protocol 32 bits + */ + enum rc_proto { + RC_PROTO_UNKNOWN = 0, +@@ -212,6 +221,9 @@ enum rc_proto { + RC_PROTO_XMP = 21, + RC_PROTO_CEC = 22, + RC_PROTO_IMON = 23, ++ RC_PROTO_RCMM12 = 24, ++ RC_PROTO_RCMM24 = 25, ++ RC_PROTO_RCMM32 = 26, + }; + + #endif +-- +2.20.1 + diff --git a/packages/kernel/linux/patches/raspberrypi/linux-904-improve-xbox-dvd-remote-performance.patch b/packages/kernel/linux/patches/raspberrypi/linux-904-improve-xbox-dvd-remote-performance.patch new file mode 100644 index 000000000..5ec182064 --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-904-improve-xbox-dvd-remote-performance.patch @@ -0,0 +1,158 @@ +From 55096db50d8cdbf777c67f672b493ef565a12c38 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Fri, 22 Mar 2019 12:26:17 +0100 +Subject: [PATCH] media: rc: xbox_remote: add protocol and set timeout + +The timestamps in ir-keytable -t output showed that the Xbox DVD +IR dongle decodes scancodes every 64ms. The last scancode of a +longer button press is decodes 64ms after the last-but-one which +indicates the decoder doesn't use a timeout but decodes on the last +edge of the signal. + +267.042629: lirc protocol(unknown): scancode = 0xace +267.042665: event type EV_MSC(0x04): scancode = 0xace +267.042665: event type EV_KEY(0x01) key_down: KEY_1(0x0002) +267.042665: event type EV_SYN(0x00). +267.106625: lirc protocol(unknown): scancode = 0xace +267.106643: event type EV_MSC(0x04): scancode = 0xace +267.106643: event type EV_SYN(0x00). +267.170623: lirc protocol(unknown): scancode = 0xace +267.170638: event type EV_MSC(0x04): scancode = 0xace +267.170638: event type EV_SYN(0x00). +267.234621: lirc protocol(unknown): scancode = 0xace +267.234636: event type EV_MSC(0x04): scancode = 0xace +267.234636: event type EV_SYN(0x00). +267.298623: lirc protocol(unknown): scancode = 0xace +267.298638: event type EV_MSC(0x04): scancode = 0xace +267.298638: event type EV_SYN(0x00). +267.543345: event type EV_KEY(0x01) key_down: KEY_1(0x0002) +267.543345: event type EV_SYN(0x00). +267.570015: event type EV_KEY(0x01) key_up: KEY_1(0x0002) +267.570015: event type EV_SYN(0x00). + +Add a protocol with the repeat value and set the timeout in the +driver to 10ms (to have a bit of headroom for delays) so the Xbox +DVD remote performs more responsive. + +Signed-off-by: Matthias Reichl +--- + Documentation/media/lirc.h.rst.exceptions | 1 + + drivers/media/rc/keymaps/rc-xbox-dvd.c | 2 +- + drivers/media/rc/rc-main.c | 2 ++ + drivers/media/rc/xbox_remote.c | 4 +++- + include/media/rc-map.h | 4 +++- + include/uapi/linux/lirc.h | 2 ++ + 6 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions +index e7a41d4b3d46..f8b5f1a32b7d 100644 +--- a/Documentation/media/lirc.h.rst.exceptions ++++ b/Documentation/media/lirc.h.rst.exceptions +@@ -61,6 +61,7 @@ ignore symbol RC_PROTO_IMON + ignore symbol RC_PROTO_RCMM12 + ignore symbol RC_PROTO_RCMM24 + ignore symbol RC_PROTO_RCMM32 ++ignore symbol RC_PROTO_XBOX_DVD + + # Undocumented macros + +diff --git a/drivers/media/rc/keymaps/rc-xbox-dvd.c b/drivers/media/rc/keymaps/rc-xbox-dvd.c +index af387244636b..42815ab57bff 100644 +--- a/drivers/media/rc/keymaps/rc-xbox-dvd.c ++++ b/drivers/media/rc/keymaps/rc-xbox-dvd.c +@@ -42,7 +42,7 @@ static struct rc_map_list xbox_dvd_map = { + .map = { + .scan = xbox_dvd, + .size = ARRAY_SIZE(xbox_dvd), +- .rc_proto = RC_PROTO_UNKNOWN, ++ .rc_proto = RC_PROTO_XBOX_DVD, + .name = RC_MAP_XBOX_DVD, + } + }; +diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c +index 78e79c37f208..7f1d5b226f68 100644 +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -76,6 +76,7 @@ static const struct { + .scancode_bits = 0x00ffffff, .repeat_period = 114 }, + [RC_PROTO_RCMM32] = { .name = "rc-mm-32", + .scancode_bits = 0xffffffff, .repeat_period = 114 }, ++ [RC_PROTO_XBOX_DVD] = { .name = "xbox-dvd", .repeat_period = 64 }, + }; + + /* Used to keep track of known keymaps */ +@@ -1027,6 +1028,7 @@ static const struct { + { RC_PROTO_BIT_RCMM12 | + RC_PROTO_BIT_RCMM24 | + RC_PROTO_BIT_RCMM32, "rc-mm", "ir-rcmm-decoder" }, ++ { RC_PROTO_BIT_XBOX_DVD, "xbox-dvd", NULL }, + }; + + /** +diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c +index f959cbb94744..79470c09989e 100644 +--- a/drivers/media/rc/xbox_remote.c ++++ b/drivers/media/rc/xbox_remote.c +@@ -148,7 +148,7 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) + struct rc_dev *rdev = xbox_remote->rdev; + + rdev->priv = xbox_remote; +- rdev->allowed_protocols = RC_PROTO_BIT_UNKNOWN; ++ rdev->allowed_protocols = RC_PROTO_BIT_XBOX_DVD; + rdev->driver_name = "xbox_remote"; + + rdev->open = xbox_remote_rc_open; +@@ -157,6 +157,8 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) + rdev->device_name = xbox_remote->rc_name; + rdev->input_phys = xbox_remote->rc_phys; + ++ rdev->timeout = MS_TO_NS(10); ++ + usb_to_input_id(xbox_remote->udev, &rdev->input_id); + rdev->dev.parent = &xbox_remote->interface->dev; + } +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index e5e86d595645..a0000f392362 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -40,6 +40,7 @@ + #define RC_PROTO_BIT_RCMM12 BIT_ULL(RC_PROTO_RCMM12) + #define RC_PROTO_BIT_RCMM24 BIT_ULL(RC_PROTO_RCMM24) + #define RC_PROTO_BIT_RCMM32 BIT_ULL(RC_PROTO_RCMM32) ++#define RC_PROTO_BIT_XBOX_DVD BIT_ULL(RC_PROTO_XBOX_DVD) + + #define RC_PROTO_BIT_ALL \ + (RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \ +@@ -55,7 +56,8 @@ + RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ + RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \ + RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM12 | \ +- RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32) ++ RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32 | \ ++ RC_PROTO_BIT_XBOX_DVD) + /* All rc protocols for which we have decoders */ + #define RC_PROTO_BIT_ALL_IR_DECODER \ + (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ +diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h +index 45fcbf99d72e..f99d9dcae667 100644 +--- a/include/uapi/linux/lirc.h ++++ b/include/uapi/linux/lirc.h +@@ -195,6 +195,7 @@ struct lirc_scancode { + * @RC_PROTO_RCMM12: RC-MM protocol 12 bits + * @RC_PROTO_RCMM24: RC-MM protocol 24 bits + * @RC_PROTO_RCMM32: RC-MM protocol 32 bits ++ * @RC_PROTO_XBOX_DVD: Xbox DVD Movie Playback Kit protocol + */ + enum rc_proto { + RC_PROTO_UNKNOWN = 0, +@@ -224,6 +225,7 @@ enum rc_proto { + RC_PROTO_RCMM12 = 24, + RC_PROTO_RCMM24 = 25, + RC_PROTO_RCMM32 = 26, ++ RC_PROTO_XBOX_DVD = 27, + }; + + #endif +-- +2.20.1 + diff --git a/packages/kernel/linux/patches/raspberrypi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/kernel/linux/patches/raspberrypi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch new file mode 100644 index 000000000..16ac49bee --- /dev/null +++ b/packages/kernel/linux/patches/raspberrypi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch @@ -0,0 +1,25 @@ +From c314d9af9d774c052bea324e1a140ccdba0ca070 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 8 Apr 2014 14:02:53 +0300 +Subject: [PATCH] pm: disable async suspend/resume by default + +--- + kernel/power/main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf63..361db93 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -46,7 +46,7 @@ int pm_notifier_call_chain(unsigned long val) + } + + /* If set, devices may be suspended and resumed asynchronously. */ +-int pm_async_enabled = 1; ++int pm_async_enabled = 0; + + static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +-- +1.7.2.5 + diff --git a/packages/kernel/linux/sysctl.d/network.conf b/packages/kernel/linux/sysctl.d/network.conf new file mode 100644 index 000000000..3518d6d96 --- /dev/null +++ b/packages/kernel/linux/sysctl.d/network.conf @@ -0,0 +1 @@ +net.ipv4.tcp_no_metrics_save=1 diff --git a/packages/kernel/linux/sysctl.d/qdisc.conf b/packages/kernel/linux/sysctl.d/qdisc.conf new file mode 100644 index 000000000..ffd7273d3 --- /dev/null +++ b/packages/kernel/linux/sysctl.d/qdisc.conf @@ -0,0 +1 @@ +net.core.default_qdisc = fq_codel diff --git a/packages/kernel/linux/udev.d/30-disable-wakeup.rules b/packages/kernel/linux/udev.d/30-disable-wakeup.rules new file mode 100644 index 000000000..c4769477e --- /dev/null +++ b/packages/kernel/linux/udev.d/30-disable-wakeup.rules @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end" + +DRIVER=="ehci-pci|xhci_hcd", RUN+="/usr/bin/sh -c 'echo disabled > /sys/$devpath/power/wakeup'" + +LABEL="end" diff --git a/packages/kernel/linux/udev.d/40-modeswitch.rules b/packages/kernel/linux/udev.d/40-modeswitch.rules new file mode 100644 index 000000000..8d3b1720c --- /dev/null +++ b/packages/kernel/linux/udev.d/40-modeswitch.rules @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end_modeswitch" +KERNEL!="sr[0-9]*", GOTO="end_modeswitch" +SUBSYSTEM!="block", GOTO="end_modeswitch" + +# Atheros Wireless / Netgear WNDA3200 +ATTRS{idVendor}=="0cf3", ATTRS{idProduct}=="20ff", RUN+="/usr/bin/eject '/dev/%k'" + +LABEL="end_modeswitch" diff --git a/packages/lang/Python2/package.mk b/packages/lang/Python2/package.mk new file mode 100644 index 000000000..f79e6cc78 --- /dev/null +++ b/packages/lang/Python2/package.mk @@ -0,0 +1,125 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="Python2" +# When changing PKG_VERSION remember to sync PKG_PYTHON_VERSION! +PKG_VERSION="2.7.16" +PKG_SHA256="f222ef602647eecb6853681156d32de4450a2c39f4de93bd5b20235f2e660ed7" +PKG_LICENSE="OSS" +PKG_SITE="http://www.python.org/" +PKG_URL="http://www.python.org/ftp/python/$PKG_VERSION/${PKG_NAME::-1}-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="zlib:host bzip2:host sqlite:host" +PKG_DEPENDS_TARGET="toolchain sqlite expat zlib bzip2 openssl libffi Python2:host ncurses readline" +PKG_LONGDESC="Python2 is an interpreted object-oriented programming language." + +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-parallel +lto-parallel" + +PKG_PY_DISABLED_MODULES="_tkinter nis gdbm bsddb ossaudiodev" + +PKG_CONFIGURE_OPTS_HOST="--cache-file=config.cache \ + --without-cxx-main \ + --with-threads \ + --enable-unicode=ucs4" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_file_dev_ptc=no \ + ac_cv_file_dev_ptmx=yes \ + ac_cv_func_lchflags_works=no \ + ac_cv_func_chflags_works=no \ + ac_cv_func_printf_zd=yes \ + ac_cv_buggy_getaddrinfo=no \ + ac_cv_header_bluetooth_bluetooth_h=no \ + ac_cv_header_bluetooth_h=no \ + ac_cv_file__dev_ptmx=no \ + ac_cv_file__dev_ptc=no \ + ac_cv_have_long_long_format=yes \ + --with-threads \ + --enable-unicode=ucs4 \ + --enable-ipv6 \ + --disable-profiling \ + --without-pydebug \ + --without-doc-strings \ + --without-tsc \ + --with-pymalloc \ + --without-fpectl \ + --without-cxx-main \ + --with-system-ffi \ + --enable-optimizations \ + --with-system-expat" +post_patch() { + # This is needed to make sure the Python build process doesn't try to + # regenerate those files with the pgen program. Otherwise, it builds + # pgen for the target, and tries to run it on the host. + touch $PKG_BUILD/Include/graminit.h + touch $PKG_BUILD/Python/graminit.c +} + +make_host() { + make PYTHON_MODULES_INCLUDE="$HOST_INCDIR" \ + PYTHON_MODULES_LIB="$HOST_LIBDIR" \ + PYTHON_DISABLE_MODULES="readline _curses _curses_panel $PKG_PY_DISABLED_MODULES" + + # python distutils per default adds -L$LIBDIR when linking binary extensions + sed -e "s|^ 'LIBDIR':.*| 'LIBDIR': '/usr/lib',|g" -i $(cat pybuilddir.txt)/_sysconfigdata.py +} + +makeinstall_host() { + make PYTHON_MODULES_INCLUDE="$HOST_INCDIR" \ + PYTHON_MODULES_LIB="$HOST_LIBDIR" \ + PYTHON_DISABLE_MODULES="readline _curses _curses_panel $PKG_PY_DISABLED_MODULES" \ + install +} + +post_makeinstall_host() { + rm -fr $PKG_BUILD/.$HOST_NAME/build/temp.* +} + +pre_configure_target() { + export PYTHON_FOR_BUILD=$TOOLCHAIN/bin/python +} + +make_target() { + make CC="$CC" LDFLAGS="$TARGET_LDFLAGS -L." \ + PYTHON_DISABLE_MODULES="$PKG_PY_DISABLED_MODULES" \ + PYTHON_MODULES_INCLUDE="$TARGET_INCDIR" \ + PYTHON_MODULES_LIB="$TARGET_LIBDIR" +} + +makeinstall_target() { + make CC="$CC" DESTDIR=$SYSROOT_PREFIX \ + PYTHON_DISABLE_MODULES="$PKG_PY_DISABLED_MODULES" \ + PYTHON_MODULES_INCLUDE="$TARGET_INCDIR" \ + PYTHON_MODULES_LIB="$TARGET_LIBDIR" \ + install + + make CC="$CC" DESTDIR=$INSTALL \ + PYTHON_DISABLE_MODULES="$PKG_PY_DISABLED_MODULES" \ + PYTHON_MODULES_INCLUDE="$TARGET_INCDIR" \ + PYTHON_MODULES_LIB="$TARGET_LIBDIR" \ + install +} + +post_makeinstall_target() { + rm -fr $PKG_BUILD/.$TARGET_NAME/build/temp.* + + for dir in bsddb idlelib lib-tk lib2to3/tests msilib pydoc_data test unittest; do + rm -rf $INSTALL/usr/lib/python*/$dir + done + + rm -rf $INSTALL/usr/lib/python*/config + rm -rf $INSTALL/usr/bin/2to3 + rm -rf $INSTALL/usr/bin/idle + rm -rf $INSTALL/usr/bin/pydoc + rm -rf $INSTALL/usr/bin/smtpd.py + rm -rf $INSTALL/usr/bin/python*-config + + cd $INSTALL/usr/lib/$PKG_PYTHON_VERSION + $TOOLCHAIN/bin/python -Wi -t -B $PKG_BUILD/Lib/compileall.py -d /usr/lib/$PKG_PYTHON_VERSION -f . + find $INSTALL/usr/lib/$PKG_PYTHON_VERSION -name "*.py" -exec rm -f {} \; &>/dev/null + + # strip + chmod u+w $INSTALL/usr/lib/libpython*.so.* + debug_strip $INSTALL/usr +} diff --git a/packages/lang/Python2/patches/Python2-2.7.11-001_xcompile.patch b/packages/lang/Python2/patches/Python2-2.7.11-001_xcompile.patch new file mode 100644 index 000000000..ef128ab4c --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-001_xcompile.patch @@ -0,0 +1,50 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index bcd83bf..5e54a0d 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -461,6 +463,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt + esac; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ ++ PYTHONXCPREFIX='$(DESTDIR)$(prefix)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + + # Build static library +@@ -1142,7 +1145,9 @@ libainstall: all python-config + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: sharedmods ++ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ ++ --skip-build \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ +diff --git a/setup.py b/setup.py +index a46bf35..528e9df 100644 +--- a/setup.py ++++ b/setup.py +@@ -17,7 +17,7 @@ + from distutils.command.install_lib import install_lib + from distutils.spawn import find_executable + +-cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ ++cross_compiling = ("_PYTHON_HOST_PLATFORM" in os.environ) or ('PYTHONXCPREFIX' in os.environ) + + def get_platform(): + # cross build +@@ -292,6 +292,14 @@ class PyBuildExt(build_ext): + (ext.name, sys.exc_info()[1])) + self.failed.append(ext.name) + return ++ ++ # Inport check will not work when cross-compiling. ++ if os.environ.has_key('PYTHONXCPREFIX'): ++ self.announce( ++ 'WARNING: skipping inport check for cross-compiled: "%s"' % ++ ext.name) ++ return ++ + # Workaround for Mac OS X: The Carbon-based modules cannot be + # reliably imported into a command-line Python + if 'Carbon' in ext.extra_link_args: diff --git a/packages/lang/Python2/patches/Python2-2.7.11-002_xcompile_path.patch b/packages/lang/Python2/patches/Python2-2.7.11-002_xcompile_path.patch new file mode 100644 index 000000000..ec45bb80a --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-002_xcompile_path.patch @@ -0,0 +1,49 @@ +diff --git a/setup.py b/setup.py +index d6ef5be..7a0d8f2 100644 +--- a/setup.py ++++ b/setup.py +@@ -439,13 +439,19 @@ class PyBuildExt(build_ext): + os.unlink(tmpfile) + + def detect_modules(self): +- # Ensure that /usr/local is always used +- if not cross_compiling: +- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') +- add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') +- if cross_compiling: +- self.add_gcc_paths() +- self.add_multiarch_paths() ++ try: ++ modules_include_dirs = os.environ["PYTHON_MODULES_INCLUDE"].split() ++ except KeyError: ++ modules_include_dirs = ['/usr/include'] ++ try: ++ modules_lib_dirs = os.environ["PYTHON_MODULES_LIB"].split() ++ except KeyError: ++ modules_lib_dirs = ['/usr/lib'] ++ self.add_multiarch_paths() ++ for dir in modules_include_dirs: ++ add_dir_to_list(self.compiler.include_dirs, dir) ++ for dir in modules_lib_dirs: ++ add_dir_to_list(self.compiler.library_dirs, dir) + + # Add paths specified in the environment variables LDFLAGS and + # CPPFLAGS for header and library files. +@@ -481,17 +487,6 @@ class PyBuildExt(build_ext): + for directory in reversed(options.dirs): + add_dir_to_list(dir_list, directory) + +- if os.path.normpath(sys.prefix) != '/usr' \ +- and not sysconfig.get_config_var('PYTHONFRAMEWORK'): +- # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework +- # (PYTHONFRAMEWORK is set) to avoid # linking problems when +- # building a framework with different architectures than +- # the one that is currently installed (issue #7473) +- add_dir_to_list(self.compiler.library_dirs, +- sysconfig.get_config_var("LIBDIR")) +- add_dir_to_list(self.compiler.include_dirs, +- sysconfig.get_config_var("INCLUDEDIR")) +- + try: + have_unicode = unicode + except NameError: diff --git a/packages/lang/Python2/patches/Python2-2.7.11-003_xcompile_disable_modules.patch b/packages/lang/Python2/patches/Python2-2.7.11-003_xcompile_disable_modules.patch new file mode 100644 index 000000000..72ebaf3d8 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-003_xcompile_disable_modules.patch @@ -0,0 +1,16 @@ +diff --git a/setup.py b/setup.py +index a46bf35..d6ef5be 100644 +--- a/setup.py ++++ b/setup.py +@@ -33,7 +33,10 @@ host_platform = get_platform() + COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS")) + + # This global variable is used to hold the list of modules to be disabled. +-disabled_module_list = [] ++try: ++ disabled_module_list = os.environ["PYTHON_DISABLE_MODULES"].split() ++except KeyError: ++ disabled_module_list = [] + + def add_dir_to_list(dirlist, dir): + """Add the directory 'dir' to the list 'dirlist' (at the front) if diff --git a/packages/lang/Python2/patches/Python2-2.7.11-004_xcompile_fix_libffi_configure.patch b/packages/lang/Python2/patches/Python2-2.7.11-004_xcompile_fix_libffi_configure.patch new file mode 100644 index 000000000..ff9f3fa03 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-004_xcompile_fix_libffi_configure.patch @@ -0,0 +1,24 @@ +diff --git a/setup.py b/setup.py +index 07af0b6..6426b22 100644 +--- a/setup.py ++++ b/setup.py +@@ -2030,10 +2030,18 @@ class PyBuildExt(build_ext): + if not self.verbose: + config_args.append("-q") + ++ ++ #NOTE: best solution is to add to configure script ++ # as config subdirectory and to exclude darwin ++ # (see configure_ctypes_darwin). ++ #FIXME: lets for now pass all top configure arguments ++ #and do not modify configure script. ++ config_args = sysconfig.get_config_var("CONFIG_ARGS") ++ + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. + cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \ +- % (ffi_builddir, ffi_srcdir, " ".join(config_args)) ++ % (ffi_builddir, ffi_srcdir, config_args) + + res = os.system(cmd) + if res or not os.path.exists(ffi_configfile): diff --git a/packages/lang/Python2/patches/Python2-2.7.11-005_dont_generate_pyo_and_pyc_files.patch b/packages/lang/Python2/patches/Python2-2.7.11-005_dont_generate_pyo_and_pyc_files.patch new file mode 100644 index 000000000..862e3dfd4 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-005_dont_generate_pyo_and_pyc_files.patch @@ -0,0 +1,29 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 918f210..c82366c 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1011,24 +1011,6 @@ libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- $(PYTHON_FOR_BUILD) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ +- -d $(LIBDEST) -f \ +- -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ +- $(DESTDIR)$(LIBDEST) +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- $(PYTHON_FOR_BUILD) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ +- -d $(LIBDEST) -f \ +- -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ +- $(DESTDIR)$(LIBDEST) +- -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- $(PYTHON_FOR_BUILD) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ +- -d $(LIBDEST)/site-packages -f \ +- -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages +- -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- $(PYTHON_FOR_BUILD) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ +- -d $(LIBDEST)/site-packages -f \ +- -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ diff --git a/packages/lang/Python2/patches/Python2-2.7.11-006_fix_ncurse_cppflags.patch b/packages/lang/Python2/patches/Python2-2.7.11-006_fix_ncurse_cppflags.patch new file mode 100644 index 000000000..965d8d2cf --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-006_fix_ncurse_cppflags.patch @@ -0,0 +1,12 @@ +diff -Naur Python-2.7.10.orig/configure Python-2.7.10/configure +--- Python-2.7.10.orig/configure 2015-08-18 12:24:03.016649265 -0700 ++++ Python-2.7.10/configure 2015-08-18 12:23:41.716695873 -0700 +@@ -14215,7 +14215,7 @@ + + # first curses configure check + ac_save_cppflags="$CPPFLAGS" +-CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" ++CPPFLAGS="$CPPFLAGS -I${prefix}/usr/include/ncursesw" + + for ac_header in curses.h ncurses.h + do : diff --git a/packages/lang/Python2/patches/Python2-2.7.11-008-distutils-use-python-sysroot.patch b/packages/lang/Python2/patches/Python2-2.7.11-008-distutils-use-python-sysroot.patch new file mode 100644 index 000000000..7cd748761 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-008-distutils-use-python-sysroot.patch @@ -0,0 +1,54 @@ +Adjust library/header paths for cross-compilation + +When cross-compiling third-party extensions, the get_python_inc() or +get_python_lib() can be called, to return the path to headers or +libraries. However, they use the sys.prefix of the host Python, which +returns incorrect paths when cross-compiling (paths pointing to host +headers and libraries). + +In order to fix this, we introduce the _python_sysroot, _python_prefix +and _python_exec_prefix variables, that allow to override these +values, and get correct header/library paths when cross-compiling +third-party Python modules. + +The _python_sysroot variable is also used to prefix the LIBDIR value +taken from the sysconfigdata module. + +Signed-off-by: Thomas Petazzoni + +Index: b/Lib/distutils/sysconfig.py +=================================================================== +--- a/Lib/distutils/sysconfig.py ++++ b/Lib/distutils/sysconfig.py +@@ -19,8 +19,13 @@ + from distutils.errors import DistutilsPlatformError + + # These are needed in a couple of spots, so just compute them once. +-PREFIX = os.path.normpath(sys.prefix) +-EXEC_PREFIX = os.path.normpath(sys.exec_prefix) ++if "_python_sysroot" in os.environ: ++ _sysroot=os.environ.get('_python_sysroot') ++ PREFIX = os.path.normpath(_sysroot + os.environ.get('_python_prefix')) ++ EXEC_PREFIX = os.path.normpath(_sysroot + os.environ.get('_python_exec_prefix')) ++else: ++ PREFIX = os.path.normpath(sys.prefix) ++ EXEC_PREFIX = os.path.normpath(sys.exec_prefix) + + # Path to the base directory of the project. On Windows the binary may + # live in project/PCBuild9. If we're dealing with an x64 Windows build, +Index: b/Lib/distutils/command/build_ext.py +=================================================================== +--- a/Lib/distutils/command/build_ext.py ++++ b/Lib/distutils/command/build_ext.py +@@ -237,7 +237,10 @@ + if (sysconfig.get_config_var('Py_ENABLE_SHARED')): + if not sysconfig.python_build: + # building third party extensions +- self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) ++ libdir = sysconfig.get_config_var('LIBDIR') ++ if "_python_sysroot" in os.environ: ++ libdir = os.environ.get("_python_sysroot") + libdir ++ self.library_dirs.append(libdir) + else: + # building python standard extensions + self.library_dirs.append('.') diff --git a/packages/lang/Python2/patches/Python2-2.7.11-008-reread-environment.patch b/packages/lang/Python2/patches/Python2-2.7.11-008-reread-environment.patch new file mode 100644 index 000000000..0de2346b9 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-008-reread-environment.patch @@ -0,0 +1,34 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index bf3aed7..7ff5c79 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -464,6 +464,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ + PYTHONXCPREFIX='$(DESTDIR)$(prefix)' \ ++ CONFIG_ARGS="$(CONFIG_ARGS)" \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + + libpython$(VERSION).so: $(LIBRARY_OBJS) +@@ -1104,6 +1105,7 @@ libainstall: all python-config + # This goes into $(exec_prefix) + sharedinstall: sharedmods + CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ ++ CONFIG_ARGS="$(CONFIG_ARGS)" \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ + --skip-build \ + --prefix=$(prefix) \ +diff --git a/setup.py b/setup.py +index 6426b22..d2776dd 100644 +--- a/setup.py ++++ b/setup.py +@@ -32,6 +32,9 @@ host_platform = get_platform() + # Were we compiled --with-pydebug or with #define Py_DEBUG? + COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS")) + ++sysconfig.get_config_vars() ++sysconfig._CONFIG_VARS.update(os.environ) ++ + # This global variable is used to hold the list of modules to be disabled. + try: + disabled_module_list = os.environ["PYTHON_DISABLE_MODULES"].split() diff --git a/packages/lang/Python2/patches/Python2-2.7.11-009-distutils-rpath.patch b/packages/lang/Python2/patches/Python2-2.7.11-009-distutils-rpath.patch new file mode 100644 index 000000000..2da6af4f0 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-009-distutils-rpath.patch @@ -0,0 +1,21 @@ +diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py +index 2aa1cb1..529e2d4 100644 +--- a/Lib/distutils/unixccompiler.py ++++ b/Lib/distutils/unixccompiler.py +@@ -83,6 +83,16 @@ class UnixCCompiler(CCompiler): + if sys.platform == "cygwin": + exe_extension = ".exe" + ++ def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs): ++ """Remove standard library path from rpath""" ++ libraries, library_dirs, runtime_library_dirs = \ ++ CCompiler._fix_lib_args(self, libraries, library_dirs, ++ runtime_library_dirs) ++ libdir = sysconfig.get_config_var('LIBDIR') ++ if runtime_library_dirs and (libdir in runtime_library_dirs): ++ runtime_library_dirs.remove(libdir) ++ return libraries, library_dirs, runtime_library_dirs ++ + def preprocess(self, source, + output_file=None, macros=None, include_dirs=None, + extra_preargs=None, extra_postargs=None): diff --git a/packages/lang/Python2/patches/Python2-2.7.11-010-fix-python-config.patch b/packages/lang/Python2/patches/Python2-2.7.11-010-fix-python-config.patch new file mode 100644 index 000000000..c1cc478da --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-010-fix-python-config.patch @@ -0,0 +1,208 @@ +Add a backport of http://bugs.python.org/issue16235 so we can use +python-config for cross builds. +This basically replaces the python version of python-config with a pure-shell +version that's already preprocessed when installed and doesn't depend +on the sysconfig import that usually leads to bad data/results. + +Signed-off-by: Gustavo Zacarias + +Index: b/configure.ac +=================================================================== +--- a/configure.ac ++++ b/configure.ac +@@ -885,6 +885,7 @@ + + # Other platforms follow + if test $enable_shared = "yes"; then ++ PY_ENABLE_SHARED=1 + AC_DEFINE(Py_ENABLE_SHARED, 1, [Defined if Python is built as a shared library.]) + case $ac_sys_system in + BeOS*) +@@ -945,6 +946,7 @@ + + esac + else # shared is disabled ++ PY_ENABLE_SHARED=0 + case $ac_sys_system in + CYGWIN*) + BLDLIBRARY='$(LIBRARY)' +@@ -1921,6 +1923,9 @@ + AC_SUBST(BLDSHARED) + AC_SUBST(CCSHARED) + AC_SUBST(LINKFORSHARED) ++AC_SUBST(PY_ENABLE_SHARED) ++LIBPL="${prefix}/lib/python${VERSION}/config" ++AC_SUBST(LIBPL) + # SO is the extension of shared libraries `(including the dot!) + # -- usually .so, .sl on HP-UX, .dll on Cygwin + AC_MSG_CHECKING(SO) +@@ -4588,7 +4593,7 @@ + AC_SUBST(ENSUREPIP) + + # generate output files +-AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc) ++AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh) + AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) + AC_OUTPUT + +Index: b/Makefile.pre.in +=================================================================== +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -166,7 +166,7 @@ + SUBDIRSTOO= Include Lib Misc Demo + + # Files and directories to be distributed +-CONFIGFILES= configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in ++CONFIGFILES= configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in Misc/python-config.sh + DISTFILES= README ChangeLog $(CONFIGFILES) + DISTDIRS= $(SUBDIRS) $(SUBDIRSTOO) Ext-dummy + DIST= $(DISTFILES) $(DISTDIRS) +@@ -410,7 +410,7 @@ + + # Default target + all: @DEF_MAKE_ALL_RULE@ +-build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks ++build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks python-config + + # Compile a binary with gcc profile guided optimization. + profile-opt: +@@ -1101,10 +1101,12 @@ + fi; \ + cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen + +-python-config: $(srcdir)/Misc/python-config.in ++python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh + # Substitution happens here, as the completely-expanded BINDIR + # is not available in configure +- sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config ++ sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config.py ++ # Replace makefile compat. variable references with shell script compat. ones; $(VAR) -> ${VAR} ++ sed -e 's,\$$(\([A-Za-z0-9_]*\)),\$$\{\1\},g' Misc/python-config.sh >python-config + + # Install the include files + INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY) +@@ -1163,7 +1165,7 @@ + $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup + $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh + $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config +- rm python-config ++ $(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py + @if [ -s Modules/python.exp -a \ + "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \ + echo; echo "Installing support files for building shared extension modules on AIX:"; \ +@@ -1345,6 +1347,7 @@ + config.cache config.log pyconfig.h Modules/config.c + -rm -rf build platform + -rm -rf $(PYTHONFRAMEWORKDIR) ++ -rm -f python-config.py python-config + + # Make things extra clean, before making a distribution: + # remove all generated files, even Makefile[.pre] +Index: b/Misc/python-config.sh.in +=================================================================== +--- /dev/null ++++ b/Misc/python-config.sh.in +@@ -0,0 +1,102 @@ ++#!/bin/sh ++ ++exit_with_usage () ++{ ++ echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--configdir" ++ exit $1 ++} ++ ++if [ "$1" = "" ] ; then ++ exit_with_usage 1 ++fi ++ ++# Returns the actual prefix where this script was installed to. ++installed_prefix () ++{ ++ RESULT=$(dirname $(cd $(dirname "$1") && pwd -P)) ++ if which readlink >/dev/null 2>&1 ; then ++ RESULT=$(readlink -f "$RESULT") ++ fi ++ echo $RESULT ++} ++ ++prefix_build="@prefix@" ++prefix_real=$(installed_prefix "$0") ++ ++# Use sed to fix paths from their built to locations to their installed to locations. ++prefix=$(echo "$prefix_build" | sed "s#$prefix_build#$prefix_real#") ++exec_prefix_build="@exec_prefix@" ++exec_prefix=$(echo "$exec_prefix_build" | sed "s#$exec_prefix_build#$prefix_real#") ++includedir=$(echo "@includedir@") ++libdir=$(echo "@libdir@") ++CFLAGS=$(echo "@CFLAGS@" | sed "s#$prefix_build#$prefix_real#") ++VERSION="@VERSION@" ++LIBM="@LIBM@" ++LIBC="@LIBC@" ++SYSLIBS="$LIBM $LIBC" ++LIBS="@LIBS@ $SYSLIBS -lpython${VERSION}" ++BASECFLAGS="@BASECFLAGS@" ++LDLIBRARY="@LDLIBRARY@" ++LINKFORSHARED="@LINKFORSHARED@" ++OPT="@OPT@" ++PY_ENABLE_SHARED="@PY_ENABLE_SHARED@" ++LDVERSION="@LDVERSION@" ++LIBDEST=${prefix}/lib/python${VERSION} ++LIBPL=$(echo "@LIBPL@" | sed "s#$prefix_build#$prefix_real#") ++SO="@SO@" ++PYTHONFRAMEWORK="@PYTHONFRAMEWORK@" ++INCDIR="-I$includedir/python${VERSION}" ++PLATINCDIR="-I$includedir/python${VERSION}" ++ ++# Scan for --help or unknown argument. ++for ARG in $* ++do ++ case $ARG in ++ --help) ++ exit_with_usage 0 ++ ;; ++ --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--abiflags|--configdir) ++ ;; ++ *) ++ exit_with_usage 1 ++ ;; ++esac ++done ++ ++for ARG in "$@" ++do ++ case "$ARG" in ++ --prefix) ++ echo "$prefix" ++ ;; ++ --exec-prefix) ++ echo "$exec_prefix" ++ ;; ++ --includes) ++ echo "$INCDIR $PLATINCDIR" ++ ;; ++ --cflags) ++ echo "$INCDIR $PLATINCDIR $BASECFLAGS $CFLAGS $OPT" ++ ;; ++ --libs) ++ echo "$LIBS" ++ ;; ++ --ldflags) ++ LINKFORSHAREDUSED= ++ if [ -z "$PYTHONFRAMEWORK" ] ; then ++ LINKFORSHAREDUSED=$LINKFORSHARED ++ fi ++ LIBPLUSED= ++ if [ "$PY_ENABLE_SHARED" = "0" ] ; then ++ LIBPLUSED="-L$LIBPL" ++ fi ++ echo "$LIBPLUSED -L$libdir $LIBS $LINKFORSHAREDUSED" ++ ;; ++ --extension-suffix) ++ echo "$SO" ++ ;; ++ --configdir) ++ echo "$LIBPL" ++ ;; ++esac ++done diff --git a/packages/lang/Python2/patches/Python2-2.7.11-014-abort-on-failed-modules.patch b/packages/lang/Python2/patches/Python2-2.7.11-014-abort-on-failed-modules.patch new file mode 100644 index 000000000..4bceeb62d --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-014-abort-on-failed-modules.patch @@ -0,0 +1,21 @@ +Abort on failed module build + +When building a Python module fails, the setup.py script currently +doesn't exit with an error, and simply continues. This is not a really +nice behavior, so this patch changes setup.py to abort with an error, +so that the build issue is clearly noticeable. + +Signed-off-by: Thomas Petazzoni + +Index: b/setup.py +=================================================================== +--- a/setup.py ++++ b/setup.py +@@ -283,6 +283,7 @@ + print "Failed to build these modules:" + print_three_column(failed) + print ++ sys.exit(1) + + def build_extension(self, ext): + diff --git a/packages/lang/Python2/patches/Python2-2.7.11-015_no_static_lib.patch b/packages/lang/Python2/patches/Python2-2.7.11-015_no_static_lib.patch new file mode 100644 index 000000000..2a381d54f --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-015_no_static_lib.patch @@ -0,0 +1,51 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 918f210..eb9ee6b 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -438,7 +438,7 @@ coverage: + + + # Build the interpreter +-$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) ++$(BUILDPYTHON): Modules/python.o $(LDLIBRARY) + $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \ + Modules/python.o \ + $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) +@@ -465,18 +465,6 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + +-# Build static library +-# avoid long command lines, same as LIBRARY_OBJS +-$(LIBRARY): $(LIBRARY_OBJS) +- -rm -f $@ +- $(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o +- $(AR) $(ARFLAGS) $@ $(PARSER_OBJS) +- $(AR) $(ARFLAGS) $@ $(OBJECT_OBJS) +- $(AR) $(ARFLAGS) $@ $(PYTHON_OBJS) +- $(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS) +- $(AR) $(ARFLAGS) $@ $(MODOBJS) +- $(RANLIB) $@ +- + libpython$(VERSION).so: $(LIBRARY_OBJS) + if test $(INSTSONAME) != $(LDLIBRARY); then \ + $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ +@@ -1090,18 +1078,6 @@ libainstall: all python-config + else true; \ + fi; \ + done +- @if test -d $(LIBRARY); then :; else \ +- if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ +- if test "$(SO)" = .dll; then \ +- $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \ +- else \ +- $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ +- $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \ +- fi; \ +- else \ +- echo Skip install of $(LIBRARY) - use make frameworkinstall; \ +- fi; \ +- fi + $(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c + $(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o + $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in diff --git a/packages/lang/Python2/patches/Python2-2.7.11-016-default-is-optimized.patch b/packages/lang/Python2/patches/Python2-2.7.11-016-default-is-optimized.patch new file mode 100644 index 000000000..c15125c03 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-016-default-is-optimized.patch @@ -0,0 +1,13 @@ +diff --git a/Python/compile.c b/Python/compile.c +index 1cf53f9..25665b5 100644 +--- a/Python/compile.c ++++ b/Python/compile.c +@@ -32,7 +32,7 @@ + #include "symtable.h" + #include "opcode.h" + +-int Py_OptimizeFlag = 0; ++int Py_OptimizeFlag = 1; + + #define DEFAULT_BLOCK_SIZE 16 + #define DEFAULT_BLOCKS 8 diff --git a/packages/lang/Python2/patches/Python2-2.7.11-017-dont-install-2to3.patch b/packages/lang/Python2/patches/Python2-2.7.11-017-dont-install-2to3.patch new file mode 100644 index 000000000..64c09ddf7 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.11-017-dont-install-2to3.patch @@ -0,0 +1,12 @@ +diff --git a/setup.py b/setup.py +index 69b76e7..7a50cc3 100644 +--- a/setup.py ++++ b/setup.py +@@ -2315,7 +2315,6 @@ def main(): + + # Scripts to install + scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle', +- 'Tools/scripts/2to3', + 'Lib/smtpd.py'] + ) + diff --git a/packages/lang/Python2/patches/Python2-2.7.15-001_disable_restricted_mode.patch b/packages/lang/Python2/patches/Python2-2.7.15-001_disable_restricted_mode.patch new file mode 100644 index 000000000..4a69d6f30 --- /dev/null +++ b/packages/lang/Python2/patches/Python2-2.7.15-001_disable_restricted_mode.patch @@ -0,0 +1,11 @@ +--- a/Include/frameobject.h ++++ b/Include/frameobject.h +@@ -56,7 +56,7 @@ + + #define PyFrame_Check(op) (Py_TYPE(op) == &PyFrame_Type) + #define PyFrame_IsRestricted(f) \ +- ((f)->f_tstate && (f)->f_builtins != (f)->f_tstate->interp->builtins) ++ (0) + + PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, + PyObject *, PyObject *); diff --git a/packages/lang/Python2/patches/aarch64/Python2-001-fix_platform_machine_func_for_32bit_userspace.patch b/packages/lang/Python2/patches/aarch64/Python2-001-fix_platform_machine_func_for_32bit_userspace.patch new file mode 100644 index 000000000..b28cb8627 --- /dev/null +++ b/packages/lang/Python2/patches/aarch64/Python2-001-fix_platform_machine_func_for_32bit_userspace.patch @@ -0,0 +1,14 @@ +diff --git a/Lib/platform.py b/Lib/platform.py +index e04d87f258..4d7bb38564 100755 +--- a/Lib/platform.py ++++ b/Lib/platform.py +@@ -1283,6 +1283,9 @@ def uname(): + system = 'Windows' + release = 'Vista' + ++ if machine == 'aarch64' and sys.maxsize <= 2**32: ++ machine = 'armv7l' ++ + _uname_cache = system,node,release,version,machine,processor + return _uname_cache + diff --git a/packages/lang/Python3/package.mk b/packages/lang/Python3/package.mk new file mode 100644 index 000000000..86ed754e9 --- /dev/null +++ b/packages/lang/Python3/package.mk @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="Python3" +# When changing PKG_VERSION remember to sync PKG_PYTHON_VERSION! +PKG_VERSION="3.8.12" +PKG_SHA256="b1d3a76420375343b5e8a22fceb1ac65b77193e9ed27146524f0a9db058728ea" +PKG_LICENSE="OSS" +PKG_SITE="https://www.python.org/" +PKG_URL="https://www.python.org/ftp/python/${PKG_VERSION}/${PKG_NAME::-1}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="zlib:host bzip2:host libffi:host util-linux:host xz:host" +PKG_DEPENDS_TARGET="toolchain Python3:host sqlite expat zlib bzip2 xz openssl libffi readline ncurses util-linux" +PKG_LONGDESC="Python3 is an interpreted object-oriented programming language." +PKG_TOOLCHAIN="autotools" + +PKG_PYTHON_VERSION="python3.8" + +PKG_PY_DISABLED_MODULES="_tkinter nis gdbm bsddb ossaudiodev" + +PKG_CONFIGURE_OPTS_HOST="ac_cv_prog_HAS_HG=/bin/false + ac_cv_prog_SVNVERSION=/bin/false + --disable-pyc-build + --disable-ossaudiodev + --disable-sqlite3 + --disable-codecs-cjk + --disable-nis + --enable-unicodedata + --enable-openssl + --disable-readline + --disable-bzip2 + --enable-zlib + --enable-xz + --disable-tk + --disable-curses + --disable-pydoc + --disable-test-modules + --enable-lib2to3 + --disable-idle3 + --without-cxx-main + --with-expat=builtin + --with-libmpdec=none + --with-doc-strings + --with-system-ffi + --without-pymalloc + --without-ensurepip +" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_prog_HAS_HG=/bin/false + ac_cv_prog_SVNVERSION=/bin/false + ac_cv_file__dev_ptmx=no + ac_cv_file__dev_ptc=no + ac_cv_have_long_long_format=yes + ac_cv_working_tzset=yes + ac_cv_func_lchflags_works=no + ac_cv_func_chflags_works=no + ac_cv_func_printf_zd=yes + ac_cv_buggy_getaddrinfo=no + ac_cv_header_bluetooth_bluetooth_h=no + ac_cv_header_bluetooth_h=no + --disable-pyc-build + --disable-ossaudiodev + --enable-sqlite3 + --disable-codecs-cjk + --disable-nis + --enable-unicodedata + --enable-openssl + --enable-readline + --enable-bzip2 + --enable-zlib + --enable-xz + --disable-tk + --enable-curses + --disable-pydoc + --disable-test-modules + --enable-lib2to3 + --disable-idle3 + --without-cxx-main + --with-expat=system + --with-libmpdec=none + --with-doc-strings + --with-system-ffi + --without-pymalloc + --without-ensurepip + --enable-ipv6 +" + +pre_configure_host() { + export PYTHON_MODULES_INCLUDE="${HOST_INCDIR}" + export PYTHON_MODULES_LIB="${HOST_LIBDIR}" + export DISABLED_EXTENSIONS="readline _curses _curses_panel ${PKG_PY_DISABLED_MODULES}" +} + +post_make_host() { + # python distutils per default adds -L${LIBDIR} when linking binary extensions + sed -e "s|^ 'LIBDIR':.*| 'LIBDIR': '/usr/lib',|g" -i $(find ${PKG_BUILD}/.${HOST_NAME} -not -path '*/__pycache__/*' -name '_sysconfigdata__*.py') +} + +post_makeinstall_host() { + ln -sf ${PKG_PYTHON_VERSION} ${TOOLCHAIN}/bin/python + + rm -f ${TOOLCHAIN}/bin/smtpd.py* + rm -f ${TOOLCHAIN}/bin/pyvenv + rm -f ${TOOLCHAIN}/bin/pydoc* + + rm -fr ${PKG_BUILD}/.${HOST_NAME}/build/temp.* + + cp ${PKG_BUILD}/Tools/scripts/reindent.py ${TOOLCHAIN}/lib/${PKG_PYTHON_VERSION} +} + +pre_configure_target() { + export PYTHON_MODULES_INCLUDE="${TARGET_INCDIR}" + export PYTHON_MODULES_LIB="${TARGET_LIBDIR}" + export DISABLED_EXTENSIONS="${PKG_PY_DISABLED_MODULES}" +} + +post_makeinstall_target() { + ln -sf ${PKG_PYTHON_VERSION} ${INSTALL}/usr/bin/python + + rm -fr ${PKG_BUILD}/.${TARGET_NAME}/build/temp.* + + PKG_INSTALL_PATH_LIB=${INSTALL}/usr/lib/${PKG_PYTHON_VERSION} + + for dir in config compiler sysconfigdata lib-dynload/sysconfigdata lib2to3/tests test; do + rm -rf ${PKG_INSTALL_PATH_LIB}/${dir} + done + + rm -rf ${PKG_INSTALL_PATH_LIB}/distutils/command/*.exe + + rm -rf ${INSTALL}/usr/bin/pyvenv + rm -rf ${INSTALL}/usr/bin/python*-config + rm -rf ${INSTALL}/usr/bin/smtpd.py ${INSTALL}/usr/bin/smtpd.py.* + + find ${INSTALL} -name '*.o' -delete + + python_compile ${PKG_INSTALL_PATH_LIB} + + # strip + chmod u+w ${INSTALL}/usr/lib/libpython*.so.* + debug_strip ${INSTALL}/usr +} diff --git a/packages/lang/Python3/patches/Python3-0000-default-is-optimized.patch b/packages/lang/Python3/patches/Python3-0000-default-is-optimized.patch new file mode 100644 index 000000000..37c32c328 --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0000-default-is-optimized.patch @@ -0,0 +1,19 @@ +Refreshed MilhouseVH patch from Python3.7. Original message: + +Do *not* enable Py_OptimizeFlag=2 (or higher) as this will stop +__doc__ output from being generated which will prevent the qemu +package for Generic from building. + +--- +diff -aur a/Python/initconfig.c b/Python/initconfig.c +--- a/Python/initconfig.c 2020-07-20 09:01:32.000000000 -0400 ++++ b/Python/initconfig.c 2020-08-08 03:24:02.796189739 -0400 +@@ -147,7 +147,7 @@ + int Py_QuietFlag = 0; /* Needed by sysmodule.c */ + int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */ + int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ +-int Py_OptimizeFlag = 0; /* Needed by compile.c */ ++int Py_OptimizeFlag = 1; /* Needed by compile.c */ + int Py_NoSiteFlag = 0; /* Suppress 'import site' */ + int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */ + int Py_FrozenFlag = 0; /* Needed by getpath.c */ diff --git a/packages/lang/Python3/patches/Python3-0100-buildroot-patches.patch b/packages/lang/Python3/patches/Python3-0100-buildroot-patches.patch new file mode 100644 index 000000000..9c86c12a8 --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0100-buildroot-patches.patch @@ -0,0 +1,1844 @@ +From 586a67bb448290a98df45e9f61d803952d2aa761 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 16:21:31 -0800 +Subject: [PATCH] Make the build of pyc files conditional + +This commit adds a new configure option --disable-pyc-build to disable +the compilation of pyc. + +Signed-off-by: Thomas Petazzoni +[ Andrey Smrinov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 2 ++ + configure.ac | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 502317aa0c..f9011c132a 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1455,6 +1455,7 @@ libinstall: build_all $(srcdir)/Modules/xxmodule.c + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi ++ifeq (@PYC_BUILD@,yes) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ + -j0 -d $(LIBDEST) -f \ +@@ -1482,6 +1483,7 @@ libinstall: build_all $(srcdir)/Modules/xxmodule.c + $(PYTHON_FOR_BUILD) -Wi -OO $(DESTDIR)$(LIBDEST)/compileall.py \ + -j0 -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages ++endif + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +diff --git a/configure.ac b/configure.ac +index a189d42c2c..4690cdba9f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1091,6 +1091,12 @@ fi + + AC_MSG_CHECKING(LDLIBRARY) + ++AC_SUBST(PYC_BUILD) ++ ++AC_ARG_ENABLE(pyc-build, ++ AS_HELP_STRING([--disable-pyc-build], [disable build of pyc files]), ++ [ PYC_BUILD="${enableval}" ], [ PYC_BUILD=yes ]) ++ + # MacOSX framework builds need more magic. LDLIBRARY is the dynamic + # library that we build, but we do not want to link against it (we + # will find it with a -framework option). For this reason there is an +-- +2.20.1 + +From 3b558cfb1670300afece09b957e1e4b7072bce6b Mon Sep 17 00:00:00 2001 +From: Vanya Sergeev +Date: Wed, 23 Dec 2015 11:30:33 +0100 +Subject: [PATCH] Disable buggy_getaddrinfo configure test when cross-compiling + with IPv6 support + +Signed-off-by: Vanya Sergeev +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 4690cdba9f..ffeec102b7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4080,7 +4080,7 @@ fi + + AC_MSG_RESULT($ac_cv_buggy_getaddrinfo) + +-if test $have_getaddrinfo = no || test "$ac_cv_buggy_getaddrinfo" = yes ++if test $have_getaddrinfo = no || test "$cross_compiling" != "yes" -a "$ac_cv_buggy_getaddrinfo" = yes + then + if test $ipv6 = yes + then +-- +2.20.1 + +From 36c138c15515e80f72a570b61da324e55ae3e80c Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 16:33:22 -0800 +Subject: [PATCH] Add infrastructure to disable the build of certain extensions + +Some of the extensions part of the Python core have dependencies on +external libraries (sqlite, tk, etc.) or are relatively big and not +necessarly always useful (CJK codecs for example). By extensions, we +mean part of Python modules that are written in C and therefore +compiled to binary code. + +Therefore, we introduce a small infrastructure that allows to disable +some of those extensions. This can be done inside the configure.ac by +adding values to the DISABLED_EXTENSIONS variable (which is a +word-separated list of extensions). + +The implementation works as follow : + + * configure.ac defines a DISABLED_EXTENSIONS variable, which is + substituted (so that when Makefile.pre is generated from + Makefile.pre.in, the value of the variable is substituted). For + now, this DISABLED_EXTENSIONS variable is empty, later patches will + use it. + + * Makefile.pre.in passes the DISABLED_EXTENSIONS value down to the + variables passed in the environment when calling the setup.py + script that actually builds and installs those extensions. + + * setup.py is modified so that the existing "disabled_module_list" is + filled with those pre-disabled extensions listed in + DISABLED_EXTENSIONS. + +Patch ported to python2.7 by Maxime Ripard , and +then extended by Thomas Petazzoni +. + +Signed-off-by: Thomas Petazzoni +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 6 +++++- + configure.ac | 2 ++ + setup.py | 5 ++++- + 3 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index f9011c132a..e8a6bd5c03 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -205,6 +205,8 @@ FILEMODE= 644 + # configure script arguments + CONFIG_ARGS= @CONFIG_ARGS@ + ++# disabled extensions ++DISABLED_EXTENSIONS= @DISABLED_EXTENSIONS@ + + # Subdirectories with code + SRCDIRS= @SRCDIRS@ +@@ -605,6 +607,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o + esac; \ + echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ ++ DISABLED_EXTENSIONS="$(DISABLED_EXTENSIONS)" \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ +@@ -1601,7 +1604,8 @@ libainstall: @DEF_MAKE_RULE@ python-config + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: sharedmods +- $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ ++ $(RUNSHARED) DISABLED_EXTENSIONS="$(DISABLED_EXTENSIONS)" \ ++ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ +diff --git a/configure.ac b/configure.ac +index ffeec102b7..7872b4dfee 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2958,6 +2958,8 @@ LIBS="$withval $LIBS" + + PKG_PROG_PKG_CONFIG + ++AC_SUBST(DISABLED_EXTENSIONS) ++ + # Check for use of the system expat library + AC_MSG_CHECKING(for --with-system-expat) + AC_ARG_WITH(system_expat, +diff --git a/setup.py b/setup.py +index 20d7f35652..d3f2cc1b37 100644 +--- a/setup.py ++++ b/setup.py +@@ -24,7 +24,10 @@ from distutils.spawn import find_executable + TEST_EXTENSIONS = True + + # This global variable is used to hold the list of modules to be disabled. +-DISABLED_MODULE_LIST = [] ++try: ++ DISABLED_MODULE_LIST = sysconfig.get_config_var("DISABLED_EXTENSIONS").split(" ") ++except KeyError: ++ DISABLED_MODULE_LIST = list() + + + def get_platform(): +-- +2.20.1 + +From f5ed27c9b9efb4756630e5799be14fefdc3b2702 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:33:14 +0100 +Subject: [PATCH] Adjust library/header paths for cross-compilation + +When cross-compiling third-party extensions, the get_python_inc() or +get_python_lib() can be called, to return the path to headers or +libraries. However, they use the sys.prefix of the host Python, which +returns incorrect paths when cross-compiling (paths pointing to host +headers and libraries). + +In order to fix this, we introduce the _python_sysroot, _python_prefix +and _python_exec_prefix variables, that allow to override these +values, and get correct header/library paths when cross-compiling +third-party Python modules. + +Signed-off-by: Thomas Petazzoni +--- + Lib/distutils/command/build_ext.py | 5 ++++- + Lib/distutils/sysconfig.py | 15 +++++++++++---- + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py +index 2d7cdf063f..cba150075c 100644 +--- a/Lib/distutils/command/build_ext.py ++++ b/Lib/distutils/command/build_ext.py +@@ -234,7 +234,10 @@ class build_ext(Command): + if (sysconfig.get_config_var('Py_ENABLE_SHARED')): + if not sysconfig.python_build: + # building third party extensions +- self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) ++ libdir = sysconfig.get_config_var('LIBDIR') ++ if "_python_sysroot" in os.environ: ++ libdir = os.environ.get("_python_sysroot") + libdir ++ self.library_dirs.append(libdir) + else: + # building python standard extensions + self.library_dirs.append('.') +diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py +index b51629eb94..011a437bcd 100644 +--- a/Lib/distutils/sysconfig.py ++++ b/Lib/distutils/sysconfig.py +@@ -18,10 +18,17 @@ from .errors import DistutilsPlatformError + from .util import get_platform, get_host_platform + + # These are needed in a couple of spots, so just compute them once. +-PREFIX = os.path.normpath(sys.prefix) +-EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +-BASE_PREFIX = os.path.normpath(sys.base_prefix) +-BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) ++if "_python_sysroot" in os.environ: ++ _sysroot=os.environ.get('_python_sysroot') ++ PREFIX = os.path.normpath(_sysroot + os.environ.get('_python_prefix')) ++ EXEC_PREFIX = os.path.normpath(_sysroot + os.environ.get('_python_exec_prefix')) ++ BASE_PREFIX = PREFIX ++ BASE_EXEC_PREFIX = EXEC_PREFIX ++else: ++ PREFIX = os.path.normpath(sys.prefix) ++ EXEC_PREFIX = os.path.normpath(sys.exec_prefix) ++ BASE_PREFIX = os.path.normpath(sys.base_prefix) ++ BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) + + # Path to the base directory of the project. On Windows the binary may + # live in project/PCbuild/win32 or project/PCbuild/amd64. +-- +2.20.1 + +From 5bcb991a8de2f1b9bdf44e78894417ed2ee137a5 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:36:00 +0100 +Subject: [PATCH] Don't look in /usr/lib/termcap for libraries + +Signed-off-by: Thomas Petazzoni +--- + setup.py | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/setup.py b/setup.py +index d3f2cc1b37..5d504d7638 100644 +--- a/setup.py ++++ b/setup.py +@@ -955,12 +955,9 @@ class PyBuildExt(build_ext): + pass # Issue 7384: Already linked against curses or tinfo. + elif curses_library: + readline_libs.append(curses_library) +- elif self.compiler.find_library_file(self.lib_dirs + +- ['/usr/lib/termcap'], +- 'termcap'): ++ elif self.compiler.find_library_file(self.lib_dirs, 'termcap'): + readline_libs.append('termcap') + self.add(Extension('readline', ['readline.c'], +- library_dirs=['/usr/lib/termcap'], + extra_link_args=readline_extra_link_args, + libraries=readline_libs)) + else: +-- +2.20.1 + +From b878b174e12a5cb2e1943f1f79d94033c1ee80d7 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:36:27 +0100 +Subject: [PATCH] Don't add multiarch paths + +The add_multiarch_paths() function leads, in certain build +environments, to the addition of host header paths to the CFLAGS, +which is not appropriate for cross-compilation. This patch fixes that +by simply removing the call to add_multiarch_paths() when we're +cross-compiling. + +Investigation done by David . + +Signed-off-by: Thomas Petazzoni +--- + setup.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 5d504d7638..282a592dc6 100644 +--- a/setup.py ++++ b/setup.py +@@ -654,10 +654,10 @@ class PyBuildExt(build_ext): + if not CROSS_COMPILING: + add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') + add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') ++ self.add_multiarch_paths() + # only change this for cross builds for 3.3, issues on Mageia + if CROSS_COMPILING: + self.add_cross_compiling_paths() +- self.add_multiarch_paths() + self.add_ldflags_cppflags() + + def init_inc_lib_dirs(self): +-- +2.20.1 + +From fceda5bae52571213b6671ce0220d1a85b38f8c7 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:43:24 +0100 +Subject: [PATCH] Abort on failed module build + +When building a Python module fails, the setup.py script currently +doesn't exit with an error, and simply continues. This is not a really +nice behavior, so this patch changes setup.py to abort with an error, +so that the build issue is clearly noticeable. + +Signed-off-by: Thomas Petazzoni +--- + setup.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/setup.py b/setup.py +index 282a592dc6..8fda3b4d47 100644 +--- a/setup.py ++++ b/setup.py +@@ -444,6 +444,7 @@ class PyBuildExt(build_ext): + print("Failed to build these modules:") + print_three_column(failed) + print() ++ sys.exit(1) + + if self.failed_on_import: + failed = self.failed_on_import[:] +-- +2.20.1 + +From 91e8058cf9085795db64f43e2c9548926ea46ab0 Mon Sep 17 00:00:00 2001 +From: Baruch Siach +Date: Wed, 23 Dec 2015 11:44:02 +0100 +Subject: [PATCH] Serial ioctl() workaround + +The ioctls.h of some architectures (notably xtensa) references structs from +linux/serial.h. Make sure to include this header as well. + +Also, undef TIOCTTYGSTRUCT that require reference to internal kernel tty_struct, +but isn't actually referenced in modern kernels. + +Signed-off-by: Baruch Siach +--- + Modules/termios.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Modules/termios.c b/Modules/termios.c +index aee7f12c57..ba2ff77d06 100644 +--- a/Modules/termios.c ++++ b/Modules/termios.c +@@ -15,7 +15,9 @@ + #endif + + #include ++#include + #include ++#undef TIOCTTYGSTRUCT + + /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR, + * MDTR, MRI, and MRTS (apparently used internally by some things +-- +2.20.1 + +From 3ec9bbf5bd9cced0005c99d7d65997b119abf2f6 Mon Sep 17 00:00:00 2001 +From: Christophe Vu-Brugier +Date: Wed, 23 Dec 2015 11:44:30 +0100 +Subject: [PATCH] Do not adjust the shebang of Python scripts for + cross-compilation + +The copy_scripts() method in distutils copies the scripts listed in +the setup file and adjusts the first line to refer to the current +Python interpreter. When cross-compiling, this means that the adjusted +shebang refers to the host Python interpreter. + +This patch modifies copy_scripts() to preserve the shebang when +cross-compilation is detected. + +Signed-off-by: Christophe Vu-Brugier +--- + Lib/distutils/command/build_scripts.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Lib/distutils/command/build_scripts.py b/Lib/distutils/command/build_scripts.py +index ccc70e6465..d6d54195c1 100644 +--- a/Lib/distutils/command/build_scripts.py ++++ b/Lib/distutils/command/build_scripts.py +@@ -91,7 +91,7 @@ class build_scripts(Command): + adjust = True + post_interp = match.group(1) or b'' + +- if adjust: ++ if adjust and not '_python_sysroot' in os.environ: + log.info("copying and adjusting %s -> %s", script, + self.build_dir) + updated_files.append(outfile) +-- +2.20.1 + +From 7b3839bcf9f79988fb944cd65717839cde166cb8 Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Thu, 20 Nov 2014 13:24:59 +0100 +Subject: [PATCH] Misc/python-config.sh.in: ensure sed invocations only match + beginning of strings + +The build/real prefix handling using sed breaks if build != real and the +standard include / lib directories are used ($prefix/include and $prefix/lib). + +E.G. + +prefix_build="/usr", libdir="$prefix/lib", includedir="$prefix/include". + +If this gets installed with make DESTDIR="/foo" install, then we end up with +prefix_real = prefix = "/foo/usr" as expected, but +includedir="/foo/foo/usr/include" and libdir="/foo/foo/usr/lib" because of +the double sed invocation (prefix is already expanded). Work around it by +ensuring we only match the beginning of the string. + +Submitted upstream: http://bugs.python.org/issue22907 + +Signed-off-by: Peter Korsgaard +--- + Misc/python-config.sh.in | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in +index 2602fe24c0..a1bc3cd5f7 100644 +--- a/Misc/python-config.sh.in ++++ b/Misc/python-config.sh.in +@@ -24,18 +24,19 @@ installed_prefix () + echo $RESULT + } + ++prefix_build="@prefix@" + prefix_real=$(installed_prefix "$0") + + # Use sed to fix paths from their built-to locations to their installed-to + # locations. Keep prefix & exec_prefix using their original values in case + # they are referenced in other configure variables, to prevent double + # substitution, issue #22140. +-prefix="@prefix@" +-exec_prefix="@exec_prefix@" ++prefix=$(echo "$prefix_build" | sed "s#^$prefix_build#$prefix_real#") ++exec_prefix=$(echo "$exec_prefix_build" | sed "s#^$exec_prefix_build#$prefix_real#") + exec_prefix_real=${prefix_real} +-includedir=$(echo "@includedir@" | sed "s#$prefix#$prefix_real#") +-libdir=$(echo "@libdir@" | sed "s#$prefix#$prefix_real#") +-CFLAGS=$(echo "@CFLAGS@" | sed "s#$prefix#$prefix_real#") ++includedir=$(echo "@includedir@" | sed "s#^$prefix_build#$prefix_real#") ++libdir=$(echo "@libdir@" | sed "s#^$prefix_build#$prefix_real#") ++CFLAGS=$(echo "@CFLAGS@" | sed "s#^$prefix_build#$prefix_real#") + VERSION="@VERSION@" + LIBM="@LIBM@" + LIBC="@LIBC@" +@@ -49,7 +50,7 @@ OPT="@OPT@" + PY_ENABLE_SHARED="@PY_ENABLE_SHARED@" + LDVERSION="@LDVERSION@" + LIBDEST=${prefix_real}/lib/python${VERSION} +-LIBPL=$(echo "@LIBPL@" | sed "s#$prefix#$prefix_real#") ++LIBPL=$(echo "@LIBPL@" | sed "s#^$prefix_build#$prefix_real#") + SO="@EXT_SUFFIX@" + PYTHONFRAMEWORK="@PYTHONFRAMEWORK@" + INCDIR="-I$includedir/python${VERSION}${ABIFLAGS}" +-- +2.20.1 + +From a9affe1f3f98342b682848c9b3f862ee194ff625 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Wed, 23 Dec 2015 11:45:48 +0100 +Subject: [PATCH] Override system locale and set to default when adding gcc + paths + +Forces the use of the default locale in the function +add_gcc_paths, which is called when cross compiling to add the +include and library paths. This is necessary because otherwise +the gcc output is localized and the output parsing fails, which +results in no paths added and detect_modules not able to find +any system library (eg. libz, libssl, etc.) + +[Thomas: patch taken from https://bugs.python.org/issue23767.] + +Signed-off-by: Samuel Cabrero +Signed-off-by: Thomas Petazzoni +--- + setup.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 8fda3b4d47..bb7eb44213 100644 +--- a/setup.py ++++ b/setup.py +@@ -600,7 +600,7 @@ class PyBuildExt(build_ext): + tmpfile = os.path.join(self.build_temp, 'ccpaths') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) +- ret = os.system('%s -E -v - %s 1>/dev/null' % (cc, tmpfile)) ++ ret = os.system('LC_ALL=C %s -E -v - %s 1>/dev/null' % (cc, tmpfile)) + is_gcc = False + is_clang = False + in_incdirs = False +-- +2.20.1 + +From c50b8e7fb9b2e61d4d195a055cd1bbf993cc455f Mon Sep 17 00:00:00 2001 +From: Christophe Vu-Brugier +Date: Wed, 22 Feb 2017 16:48:49 -0800 +Subject: [PATCH] Add importlib fix for PEP 3147 issue + +Python 3 has a new standard for installing .pyc file, called PEP +3147. Unfortunately, this standard requires both the .py and .pyc +files to be installed for a Python module to be found. This is quite +annoying on space-constrained embedded systems, since the .py file is +technically not required for execution. + +This patch changes cache_from_source() and source_from_cache() in +importlib to get rid of the "__pycache__" directory. +This effectively disables PEP 3147 for: + +* The python standard library +* Packages built with distutils or setuptools +* Packages built with automake that use the `py-compile` helper + +Signed-off-by: Christophe Vu-Brugier +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Lib/importlib/_bootstrap_external.py | 44 ++++------------------------ + 1 file changed, 5 insertions(+), 39 deletions(-) + +diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py +index b8ac482994..db034f605a 100644 +--- a/Lib/importlib/_bootstrap_external.py ++++ b/Lib/importlib/_bootstrap_external.py +@@ -306,8 +306,6 @@ def cache_from_source(path, debug_override=None, *, optimization=None): + a True value is the same as setting 'optimization' to the empty string + while a False value is equivalent to setting 'optimization' to '1'. + +- If sys.implementation.cache_tag is None then NotImplementedError is raised. +- + """ + if debug_override is not None: + _warnings.warn('the debug_override parameter is deprecated; use ' +@@ -319,10 +317,7 @@ def cache_from_source(path, debug_override=None, *, optimization=None): + path = _os.fspath(path) + head, tail = _path_split(path) + base, sep, rest = tail.rpartition('.') +- tag = sys.implementation.cache_tag +- if tag is None: +- raise NotImplementedError('sys.implementation.cache_tag is None') +- almost_filename = ''.join([(base if base else rest), sep, tag]) ++ almost_filename = ''.join([(base if base else rest)]) + if optimization is None: + if sys.flags.optimize == 0: + optimization = '' +@@ -359,46 +354,17 @@ def cache_from_source(path, debug_override=None, *, optimization=None): + head.lstrip(path_separators), + filename, + ) +- return _path_join(head, _PYCACHE, filename) ++ return _path_join(head, filename) + + + def source_from_cache(path): + """Given the path to a .pyc. file, return the path to its .py file. + + The .pyc file does not need to exist; this simply returns the path to +- the .py file calculated to correspond to the .pyc file. If path does +- not conform to PEP 3147/488 format, ValueError will be raised. If +- sys.implementation.cache_tag is None then NotImplementedError is raised. +- ++ the .py file calculated to correspond to the .pyc file. + """ +- if sys.implementation.cache_tag is None: +- raise NotImplementedError('sys.implementation.cache_tag is None') +- path = _os.fspath(path) +- head, pycache_filename = _path_split(path) +- found_in_pycache_prefix = False +- if sys.pycache_prefix is not None: +- stripped_path = sys.pycache_prefix.rstrip(path_separators) +- if head.startswith(stripped_path + path_sep): +- head = head[len(stripped_path):] +- found_in_pycache_prefix = True +- if not found_in_pycache_prefix: +- head, pycache = _path_split(head) +- if pycache != _PYCACHE: +- raise ValueError(f'{_PYCACHE} not bottom-level directory in ' +- f'{path!r}') +- dot_count = pycache_filename.count('.') +- if dot_count not in {2, 3}: +- raise ValueError(f'expected only 2 or 3 dots in {pycache_filename!r}') +- elif dot_count == 3: +- optimization = pycache_filename.rsplit('.', 2)[-2] +- if not optimization.startswith(_OPT): +- raise ValueError("optimization portion of filename does not start " +- f"with {_OPT!r}") +- opt_level = optimization[len(_OPT):] +- if not opt_level.isalnum(): +- raise ValueError(f"optimization level {optimization!r} is not an " +- "alphanumeric value") +- base_filename = pycache_filename.partition('.')[0] ++ head, filename = _path_split(path) ++ base_filename = filename.partition('.')[0] + return _path_join(head, base_filename + SOURCE_SUFFIXES[0]) + + +-- +2.20.1 + +From 5ee3e5ad62919c431b1f7b5ff91ddf606582df0e Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:01:18 -0800 +Subject: [PATCH] Add an option to disable installation of test modules + +The Python standard distribution comes with many test modules, that +are not necessarly useful on embedded targets. + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 54 ++++++++++++++++++++++++++++++++----------------- + configure.ac | 5 +++++ + 2 files changed, 41 insertions(+), 18 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index e8a6bd5c03..3abee36f49 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1317,8 +1317,28 @@ maninstall: altmaninstall + + # Install the library + XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax +-LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ +- tkinter/test/test_ttk site-packages test \ ++ ++LIBSUBDIRS= tkinter site-packages \ ++ asyncio \ ++ collections concurrent concurrent/futures encodings \ ++ email email/mime \ ++ ensurepip ensurepip/_bundled \ ++ html json http dbm xmlrpc \ ++ sqlite3 \ ++ logging csv wsgiref urllib \ ++ lib2to3 lib2to3/fixes lib2to3/pgen2 \ ++ ctypes ctypes/macholib \ ++ idlelib idlelib/Icons \ ++ distutils distutils/command $(XMLLIBSUBDIRS) \ ++ importlib \ ++ turtledemo \ ++ multiprocessing multiprocessing/dummy \ ++ unittest \ ++ venv venv/scripts venv/scripts/common venv/scripts/posix \ ++ curses pydoc_data ++ ++TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ ++ tkinter/test/test_ttk test \ + test/audiodata \ + test/capath test/data \ + test/cjkencodings test/decimaltestdata \ +@@ -1376,26 +1396,24 @@ LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ + test/test_importlib/zipdata01 \ + test/test_importlib/zipdata02 \ + test/ziptestdata \ +- asyncio \ + test/test_asyncio \ +- collections concurrent concurrent/futures encodings \ +- email email/mime test/test_email test/test_email/data \ +- ensurepip ensurepip/_bundled \ +- html json test/test_json http dbm xmlrpc \ +- sqlite3 sqlite3/test \ +- logging csv wsgiref urllib \ +- lib2to3 lib2to3/fixes lib2to3/pgen2 lib2to3/tests \ ++ test/test_email test/test_email/data \ ++ test/test_json \ ++ sqlite3/test \ ++ lib2to3/tests \ + lib2to3/tests/data lib2to3/tests/data/fixers \ + lib2to3/tests/data/fixers/myfixes \ +- ctypes ctypes/test ctypes/macholib \ +- idlelib idlelib/Icons idlelib/idle_test \ +- distutils distutils/command distutils/tests $(XMLLIBSUBDIRS) \ ++ ctypes/test \ ++ idlelib/idle_test \ ++ distutils/tests \ ++ test/test_importlib test/test_importlib/builtin \ + test/test_tools test/test_warnings test/test_warnings/data \ +- turtledemo \ +- multiprocessing multiprocessing/dummy \ +- unittest unittest/test unittest/test/testmock \ +- venv venv/scripts venv/scripts/common venv/scripts/posix \ +- curses pydoc_data ++ unittest/test unittest/test/testmock ++ ++ifeq (@TEST_MODULES@,yes) ++LIBSUBDIRS += $(TESTSUBDIRS) ++endif ++ + libinstall: build_all $(srcdir)/Modules/xxmodule.c + @for i in $(SCRIPTDIR) $(LIBDEST); \ + do \ +diff --git a/configure.ac b/configure.ac +index 7872b4dfee..b820d18c7c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3234,6 +3234,11 @@ if test "$posix_threads" = "yes"; then + AC_CHECK_FUNCS(pthread_getcpuclockid) + fi + ++AC_SUBST(TEST_MODULES) ++ ++AC_ARG_ENABLE(test-modules, ++ AS_HELP_STRING([--disable-test-modules], [disable test modules]), ++ [ TEST_MODULES="${enableval}" ], [ TEST_MODULES=yes ]) + + # Check for enable-ipv6 + AH_TEMPLATE(ENABLE_IPV6, [Define if --enable-ipv6 is specified]) +-- +2.20.1 + +From 13a8be57e79f2657c75391bfa524dc1ba4993b02 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:07:56 -0800 +Subject: [PATCH] Add an option to disable pydoc + +It removes 0.5 MB of data from the target plus the pydoc script +itself. + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 8 +++++++- + configure.ac | 6 ++++++ + setup.py | 9 +++++++-- + 3 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 3abee36f49..6fa0549a56 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1289,7 +1289,9 @@ bininstall: altbininstall + -rm -f $(DESTDIR)$(BINDIR)/idle3 + (cd $(DESTDIR)$(BINDIR); $(LN) -s idle$(VERSION) idle3) + -rm -f $(DESTDIR)$(BINDIR)/pydoc3 ++ifeq (@PYDOC@,yes) + (cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc3) ++endif + -rm -f $(DESTDIR)$(BINDIR)/2to3 + (cd $(DESTDIR)$(BINDIR); $(LN) -s 2to3-$(VERSION) 2to3) + if test "x$(LIPO_32BIT_FLAGS)" != "x" ; then \ +@@ -1335,7 +1337,7 @@ LIBSUBDIRS= tkinter site-packages \ + multiprocessing multiprocessing/dummy \ + unittest \ + venv venv/scripts venv/scripts/common venv/scripts/posix \ +- curses pydoc_data ++ curses + + TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ + tkinter/test/test_ttk test \ +@@ -1414,6 +1416,10 @@ ifeq (@TEST_MODULES@,yes) + LIBSUBDIRS += $(TESTSUBDIRS) + endif + ++ifeq (@PYDOC@,yes) ++LIBSUBDIRS += pydoc_data ++endif ++ + libinstall: build_all $(srcdir)/Modules/xxmodule.c + @for i in $(SCRIPTDIR) $(LIBDEST); \ + do \ +diff --git a/configure.ac b/configure.ac +index b820d18c7c..f53cc86d89 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3234,6 +3234,12 @@ if test "$posix_threads" = "yes"; then + AC_CHECK_FUNCS(pthread_getcpuclockid) + fi + ++AC_SUBST(PYDOC) ++ ++AC_ARG_ENABLE(pydoc, ++ AS_HELP_STRING([--disable-pydoc], [disable pydoc]), ++ [ PYDOC="${enableval}" ], [ PYDOC=yes ]) ++ + AC_SUBST(TEST_MODULES) + + AC_ARG_ENABLE(test-modules, +diff --git a/setup.py b/setup.py +index bb7eb44213..748c269960 100644 +--- a/setup.py ++++ b/setup.py +@@ -2401,6 +2401,12 @@ def main(): + # turn off warnings when deprecated modules are imported + import warnings + warnings.filterwarnings("ignore",category=DeprecationWarning) ++ ++ scripts = ['Tools/scripts/idle3', 'Tools/scripts/2to3', ++ 'Lib/smtpd.py'] ++ if not '--disable-pydoc' in sysconfig.get_config_var("CONFIG_ARGS"): ++ scripts += [ 'Tools/scripts/pydoc3' ] ++ + setup(# PyPI Metadata (PEP 301) + name = "Python", + version = sys.version.split()[0], +@@ -2425,8 +2431,7 @@ def main(): + # If you change the scripts installed here, you also need to + # check the PyBuildScripts command above, and change the links + # created by the bininstall target in Makefile.pre.in +- scripts = ["Tools/scripts/pydoc3", "Tools/scripts/idle3", +- "Tools/scripts/2to3"] ++ scripts = scripts + ) + + # --install-platlib +-- +2.20.1 + +From 868823f15bab031caf05dc5e8ce2eac076bfc82b Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:15:31 -0800 +Subject: [PATCH] Add an option to disable lib2to3 + +lib2to3 is a library to convert Python 2.x code to Python 3.x. As +such, it is probably not very useful on embedded system targets. + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 16 ++++++++++++---- + configure.ac | 6 ++++++ + setup.py | 5 +++-- + 3 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 6fa0549a56..3e1f130532 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1293,7 +1293,9 @@ ifeq (@PYDOC@,yes) + (cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc3) + endif + -rm -f $(DESTDIR)$(BINDIR)/2to3 ++ifeq (@LIB2TO3@,yes) + (cd $(DESTDIR)$(BINDIR); $(LN) -s 2to3-$(VERSION) 2to3) ++endif + if test "x$(LIPO_32BIT_FLAGS)" != "x" ; then \ + rm -f $(DESTDIR)$(BINDIR)/python3-32$(EXE); \ + (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-32$(EXE) python3-32$(EXE)) \ +@@ -1328,7 +1330,6 @@ LIBSUBDIRS= tkinter site-packages \ + html json http dbm xmlrpc \ + sqlite3 \ + logging csv wsgiref urllib \ +- lib2to3 lib2to3/fixes lib2to3/pgen2 \ + ctypes ctypes/macholib \ + idlelib idlelib/Icons \ + distutils distutils/command $(XMLLIBSUBDIRS) \ +@@ -1402,9 +1403,6 @@ TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ + test/test_email test/test_email/data \ + test/test_json \ + sqlite3/test \ +- lib2to3/tests \ +- lib2to3/tests/data lib2to3/tests/data/fixers \ +- lib2to3/tests/data/fixers/myfixes \ + ctypes/test \ + idlelib/idle_test \ + distutils/tests \ +@@ -1412,6 +1410,14 @@ TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ + test/test_tools test/test_warnings test/test_warnings/data \ + unittest/test unittest/test/testmock + ++ifeq (@LIB2TO3@,yes) ++LIBSUBDIRS += lib2to3 lib2to3/fixes lib2to3/pgen2 ++TESTSUBDIRS += lib2to3/tests \ ++ lib2to3/tests/data \ ++ lib2to3/tests/data/fixers \ ++ lib2to3/tests/data/fixers/myfixes ++endif ++ + ifeq (@TEST_MODULES@,yes) + LIBSUBDIRS += $(TESTSUBDIRS) + endif +@@ -1511,10 +1517,12 @@ ifeq (@PYC_BUILD@,yes) + -j0 -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + endif ++ifeq (@LIB2TO3@,yes) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt ++endif + + # bpo-21536: Misc/python-config.sh is generated in the build directory + # from $(srcdir)Misc/python-config.sh.in. +diff --git a/configure.ac b/configure.ac +index f53cc86d89..caa8eaf88a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3246,6 +3246,12 @@ AC_ARG_ENABLE(test-modules, + AS_HELP_STRING([--disable-test-modules], [disable test modules]), + [ TEST_MODULES="${enableval}" ], [ TEST_MODULES=yes ]) + ++AC_SUBST(LIB2TO3) ++ ++AC_ARG_ENABLE(lib2to3, ++ AS_HELP_STRING([--disable-lib2to3], [disable lib2to3]), ++ [ LIB2TO3="${enableval}" ], [ LIB2TO3=yes ]) ++ + # Check for enable-ipv6 + AH_TEMPLATE(ENABLE_IPV6, [Define if --enable-ipv6 is specified]) + AC_MSG_CHECKING([if --enable-ipv6 is specified]) +diff --git a/setup.py b/setup.py +index 748c269960..1669797cad 100644 +--- a/setup.py ++++ b/setup.py +@@ -2402,10 +2402,11 @@ def main(): + import warnings + warnings.filterwarnings("ignore",category=DeprecationWarning) + +- scripts = ['Tools/scripts/idle3', 'Tools/scripts/2to3', +- 'Lib/smtpd.py'] ++ scripts = ['Tools/scripts/idle3', 'Lib/smtpd.py'] + if not '--disable-pydoc' in sysconfig.get_config_var("CONFIG_ARGS"): + scripts += [ 'Tools/scripts/pydoc3' ] ++ if not '--disable-lib2to3' in sysconfig.get_config_var("CONFIG_ARGS"): ++ scripts += [ 'Tools/scripts/2to3' ] + + setup(# PyPI Metadata (PEP 301) + name = "Python", +-- +2.20.1 + +From 1a1d13a973d9dcbd6660bfef40cf35c7638f779b Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:20:45 -0800 +Subject: [PATCH] Add option to disable the sqlite3 module + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 7 +++++-- + configure.ac | 9 +++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 3e1f130532..cf9add0bc7 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1328,7 +1328,6 @@ LIBSUBDIRS= tkinter site-packages \ + email email/mime \ + ensurepip ensurepip/_bundled \ + html json http dbm xmlrpc \ +- sqlite3 \ + logging csv wsgiref urllib \ + ctypes ctypes/macholib \ + idlelib idlelib/Icons \ +@@ -1402,7 +1401,6 @@ TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ + test/test_asyncio \ + test/test_email test/test_email/data \ + test/test_json \ +- sqlite3/test \ + ctypes/test \ + idlelib/idle_test \ + distutils/tests \ +@@ -1418,6 +1416,11 @@ TESTSUBDIRS += lib2to3/tests \ + lib2to3/tests/data/fixers/myfixes + endif + ++ifeq (@SQLITE3@,yes) ++LIBSUBDIRS += sqlite3 ++TESTSUBDIRS += sqlite3/test ++endif ++ + ifeq (@TEST_MODULES@,yes) + LIBSUBDIRS += $(TESTSUBDIRS) + endif +diff --git a/configure.ac b/configure.ac +index caa8eaf88a..79a8255f44 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3234,6 +3234,15 @@ if test "$posix_threads" = "yes"; then + AC_CHECK_FUNCS(pthread_getcpuclockid) + fi + ++AC_SUBST(SQLITE3) ++AC_ARG_ENABLE(sqlite3, ++ AS_HELP_STRING([--disable-sqlite3], [disable sqlite3]), ++ [ SQLITE3="${enableval}" ], [ SQLITE3=yes ]) ++ ++if test "$SQLITE3" = "no" ; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _sqlite3" ++fi ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.20.1 + +From c54cb57b3bd80fa2819f6409d5d2b98d82fbfcb2 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:23:42 -0800 +Subject: [PATCH] Add an option to disable the tk module + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 11 ++++++++--- + configure.ac | 9 +++++++++ + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index cf9add0bc7..5d78419fd4 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1322,7 +1322,7 @@ maninstall: altmaninstall + # Install the library + XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax + +-LIBSUBDIRS= tkinter site-packages \ ++LIBSUBDIRS= site-packages \ + asyncio \ + collections concurrent concurrent/futures encodings \ + email email/mime \ +@@ -1339,8 +1339,7 @@ LIBSUBDIRS= tkinter site-packages \ + venv venv/scripts venv/scripts/common venv/scripts/posix \ + curses + +-TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ +- tkinter/test/test_ttk test \ ++TESTSUBDIRS= test \ + test/audiodata \ + test/capath test/data \ + test/cjkencodings test/decimaltestdata \ +@@ -1408,6 +1407,12 @@ TESTSUBDIRS= tkinter/test tkinter/test/test_tkinter \ + test/test_tools test/test_warnings test/test_warnings/data \ + unittest/test unittest/test/testmock + ++ifeq (@TK@,yes) ++LIBSUBDIRS += tkinter ++TESTSUBDIRS += tkinter/test tkinter/test/test_tkinter \ ++ tkinter/test/test_ttk ++endif ++ + ifeq (@LIB2TO3@,yes) + LIBSUBDIRS += lib2to3 lib2to3/fixes lib2to3/pgen2 + TESTSUBDIRS += lib2to3/tests \ +diff --git a/configure.ac b/configure.ac +index 79a8255f44..b5922451cc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3243,6 +3243,15 @@ if test "$SQLITE3" = "no" ; then + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _sqlite3" + fi + ++AC_SUBST(TK) ++AC_ARG_ENABLE(tk, ++ AS_HELP_STRING([--disable-tk], [disable tk]), ++ [ TK="${enableval}" ], [ TK=yes ]) ++ ++if test "$TK" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _tkinter" ++fi ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.20.1 + +From 332373ca25f2dbe5473330666ec49143506a4dc0 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:31:51 -0800 +Subject: [PATCH] Add an option to disable the curses module + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 7 +++++-- + configure.ac | 9 +++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 5d78419fd4..660c292765 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1336,8 +1336,7 @@ LIBSUBDIRS= site-packages \ + turtledemo \ + multiprocessing multiprocessing/dummy \ + unittest \ +- venv venv/scripts venv/scripts/common venv/scripts/posix \ +- curses ++ venv venv/scripts venv/scripts/common venv/scripts/posix + + TESTSUBDIRS= test \ + test/audiodata \ +@@ -1413,6 +1412,10 @@ TESTSUBDIRS += tkinter/test tkinter/test/test_tkinter \ + tkinter/test/test_ttk + endif + ++ifeq (@CURSES@,yes) ++LIBSUBDIRS += curses ++endif ++ + ifeq (@LIB2TO3@,yes) + LIBSUBDIRS += lib2to3 lib2to3/fixes lib2to3/pgen2 + TESTSUBDIRS += lib2to3/tests \ +diff --git a/configure.ac b/configure.ac +index b5922451cc..ea422a86a9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3252,6 +3252,15 @@ if test "$TK" = "no"; then + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _tkinter" + fi + ++AC_SUBST(CURSES) ++AC_ARG_ENABLE(curses, ++ AS_HELP_STRING([--disable-curses], [disable curses]), ++ [ CURSES="${enableval}" ], [ CURSES=yes ]) ++ ++if test "$CURSES" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _curses _curses_panel" ++fi ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.20.1 + +From d88f2d3430bbbe285ae3de5fbc1bde34da7f0478 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 22 Feb 2017 17:40:45 -0800 +Subject: [PATCH] Add an option to disable expat + +This patch replaces the existing --with-system-expat option with a +--with-expat={system,builtin,none} option, which allows to tell Python +whether we want to use the system expat (already installed), the expat +builtin the Python sources, or no expat at all (which disables the +installation of XML modules). + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Samuel Martin +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 6 +++++- + configure.ac | 18 +++++++++++++----- + setup.py | 2 +- + 3 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 660c292765..f49abf8395 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1331,7 +1331,7 @@ LIBSUBDIRS= site-packages \ + logging csv wsgiref urllib \ + ctypes ctypes/macholib \ + idlelib idlelib/Icons \ +- distutils distutils/command $(XMLLIBSUBDIRS) \ ++ distutils distutils/command \ + importlib \ + turtledemo \ + multiprocessing multiprocessing/dummy \ +@@ -1416,6 +1416,10 @@ ifeq (@CURSES@,yes) + LIBSUBDIRS += curses + endif + ++ifeq (@EXPAT@,yes) ++LIBSUBDIRS += $(XMLLIBSUBDIRS) ++endif ++ + ifeq (@LIB2TO3@,yes) + LIBSUBDIRS += lib2to3 lib2to3/fixes lib2to3/pgen2 + TESTSUBDIRS += lib2to3/tests \ +diff --git a/configure.ac b/configure.ac +index ea422a86a9..3c1e2c088d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2961,13 +2961,21 @@ PKG_PROG_PKG_CONFIG + AC_SUBST(DISABLED_EXTENSIONS) + + # Check for use of the system expat library +-AC_MSG_CHECKING(for --with-system-expat) +-AC_ARG_WITH(system_expat, +- AS_HELP_STRING([--with-system-expat], [build pyexpat module using an installed expat library]), ++AC_MSG_CHECKING(for --with-expat) ++AC_ARG_WITH(expat, ++ AS_HELP_STRING([--with-expat], [select which expat version to use: system, builtin, none]), + [], +- [with_system_expat="no"]) ++ [with_expat="builtin"]) + +-AC_MSG_RESULT($with_system_expat) ++AC_MSG_RESULT($with_expat) ++ ++if test "$with_expat" != "none"; then ++ EXPAT=yes ++else ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} pyexpat" ++ EXPAT=no ++fi ++AC_SUBST(EXPAT) + + # Check for use of the system libffi library + AC_MSG_CHECKING(for --with-system-ffi) +diff --git a/setup.py b/setup.py +index 1669797cad..d2727c0da5 100644 +--- a/setup.py ++++ b/setup.py +@@ -1576,7 +1576,7 @@ class PyBuildExt(build_ext): + # + # More information on Expat can be found at www.libexpat.org. + # +- if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"): ++ if '--with-expat=system' in sysconfig.get_config_var("CONFIG_ARGS"): + expat_inc = [] + define_macros = [] + extra_compile_args = [] +-- +2.20.1 + +From 347f359b484c8e34b49f71132701252b966d93aa Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:49:55 +0100 +Subject: [PATCH] Add an option to disable CJK codecs + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 3c1e2c088d..30a92f9c2e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3251,6 +3251,12 @@ if test "$SQLITE3" = "no" ; then + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _sqlite3" + fi + ++AC_ARG_ENABLE(codecs-cjk, ++ AS_HELP_STRING([--disable-codecs-cjk], [disable CJK codecs]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _codecs_kr _codecs_jp _codecs_cn _codecs_tw _codecs_hk _codecs_iso2022" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From ff9bebed083c5d20fe31f94b868f6f1a8c6cc744 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:50:11 +0100 +Subject: [PATCH] Add an option to disable NIS + +NIS is not necessarily available in uClibc, so we need an option to +not compile support for it. + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 30a92f9c2e..20f326db46 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3257,6 +3257,12 @@ AC_ARG_ENABLE(codecs-cjk, + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _codecs_kr _codecs_jp _codecs_cn _codecs_tw _codecs_hk _codecs_iso2022" + fi]) + ++AC_ARG_ENABLE(nis, ++ AS_HELP_STRING([--disable-nis], [disable NIS]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} nis" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From 47f9caca90e6c8c18736e5dfd0acf47aae27eefb Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:50:27 +0100 +Subject: [PATCH] Add an option to disable unicodedata + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 20f326db46..99bbc37b07 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3263,6 +3263,12 @@ AC_ARG_ENABLE(nis, + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} nis" + fi]) + ++AC_ARG_ENABLE(unicodedata, ++ AS_HELP_STRING([--disable-unicodedata], [disable unicodedata]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} unicodedata" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From c3ad1d6fc8f1fa56ee0522389227454710bf7877 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Feb 2017 17:45:14 -0800 +Subject: [PATCH] Add an option to disable IDLE + +IDLE is an IDE embedded into python, written using Tk, so it doesn't make +much sense to have it into our build. + +Signed-off-by: Maxime Ripard +[ Andrey Smirnov: ported to Python 3.6 ] +Signed-off-by: Andrey Smirnov +--- + Makefile.pre.in | 7 ++++++- + configure.ac | 6 ++++++ + setup.py | 4 +++- + 3 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index f49abf8395..bc777e6504 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1287,7 +1287,9 @@ bininstall: altbininstall + -rm -f $(DESTDIR)$(LIBPC)/python3-embed.pc + (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION)-embed.pc python3-embed.pc) + -rm -f $(DESTDIR)$(BINDIR)/idle3 ++ifeq (@IDLE@,yes) + (cd $(DESTDIR)$(BINDIR); $(LN) -s idle$(VERSION) idle3) ++endif + -rm -f $(DESTDIR)$(BINDIR)/pydoc3 + ifeq (@PYDOC@,yes) + (cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc3) +@@ -1330,7 +1332,6 @@ LIBSUBDIRS= site-packages \ + html json http dbm xmlrpc \ + logging csv wsgiref urllib \ + ctypes ctypes/macholib \ +- idlelib idlelib/Icons \ + distutils distutils/command \ + importlib \ + turtledemo \ +@@ -1420,6 +1421,10 @@ ifeq (@EXPAT@,yes) + LIBSUBDIRS += $(XMLLIBSUBDIRS) + endif + ++ifeq (@IDLE@,yes) ++LIBSUBDIRS += idlelib idlelib/Icons ++endif ++ + ifeq (@LIB2TO3@,yes) + LIBSUBDIRS += lib2to3 lib2to3/fixes lib2to3/pgen2 + TESTSUBDIRS += lib2to3/tests \ +diff --git a/configure.ac b/configure.ac +index 99bbc37b07..8c9706582e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3305,6 +3305,12 @@ AC_ARG_ENABLE(lib2to3, + AS_HELP_STRING([--disable-lib2to3], [disable lib2to3]), + [ LIB2TO3="${enableval}" ], [ LIB2TO3=yes ]) + ++AC_SUBST(IDLE) ++ ++AC_ARG_ENABLE(idle3, ++ AS_HELP_STRING([--disable-idle3], [disable idle3 IDE]), ++ [ IDLE="${enableval}" ], [ IDLE=yes ]) ++ + # Check for enable-ipv6 + AH_TEMPLATE(ENABLE_IPV6, [Define if --enable-ipv6 is specified]) + AC_MSG_CHECKING([if --enable-ipv6 is specified]) +diff --git a/setup.py b/setup.py +index d2727c0da5..9f09b3d985 100644 +--- a/setup.py ++++ b/setup.py +@@ -2402,11 +2402,13 @@ def main(): + import warnings + warnings.filterwarnings("ignore",category=DeprecationWarning) + +- scripts = ['Tools/scripts/idle3', 'Lib/smtpd.py'] ++ scripts = [ 'Lib/smtpd.py'] + if not '--disable-pydoc' in sysconfig.get_config_var("CONFIG_ARGS"): + scripts += [ 'Tools/scripts/pydoc3' ] + if not '--disable-lib2to3' in sysconfig.get_config_var("CONFIG_ARGS"): + scripts += [ 'Tools/scripts/2to3' ] ++ if not '--disable-idle3' in sysconfig.get_config_var("CONFIG_ARGS"): ++ scripts += [ 'Tools/scripts/idle3' ] + + setup(# PyPI Metadata (PEP 301) + name = "Python", +-- +2.20.1 + +From c82efeabd2f9b89ff2ecd5261eceeeb3af022ae8 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:51:31 +0100 +Subject: [PATCH] Add an option to disable decimal + +This patch replaces the existing --with-system-libmpdec option with a +--with-libmpdec={system,builtin,none} option, which allows to tell +Python whether we want to use the system libmpdec (already installed), +the libmpdec builtin the Python sources, or no libmpdec at all. + +Signed-off-by: Thomas Petazzoni +[aduskett@gmail.com: Update for python 3.7.0] +Signed-off-by: Adam Duskett +--- + configure.ac | 17 ++++++++++++----- + setup.py | 2 +- + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8c9706582e..e6255babb6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3012,13 +3012,20 @@ fi + AC_SUBST(LIBFFI_INCLUDEDIR) + + # Check for use of the system libmpdec library +-AC_MSG_CHECKING(for --with-system-libmpdec) +-AC_ARG_WITH(system_libmpdec, +- AS_HELP_STRING([--with-system-libmpdec], [build _decimal module using an installed libmpdec library]), ++AC_MSG_CHECKING(for --with-libmpdec) ++AC_ARG_WITH(libmpdec, ++ AS_HELP_STRING([--with-libmpdec], [select which libmpdec version to use: system, builtin, none]), + [], +- [with_system_libmpdec="no"]) ++ [with_libmpdec="builtin"]) + +-AC_MSG_RESULT($with_system_libmpdec) ++AC_MSG_RESULT($with_libmpdec) ++if test "$with_libmpdec" != "none"; then ++ MPDEC=yes ++else ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _decimal" ++ MPDEC=no ++fi ++AC_SUBST(MPDEC) + + # Check whether _decimal should use a coroutine-local or thread-local context + AC_MSG_CHECKING(for --with-decimal-contextvar) +diff --git a/setup.py b/setup.py +index 9f09b3d985..a7f2e23d87 100644 +--- a/setup.py ++++ b/setup.py +@@ -2076,7 +2076,7 @@ class PyBuildExt(build_ext): + # Stefan Krah's _decimal module + extra_compile_args = [] + undef_macros = [] +- if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): ++ if '--with-libmpdec=system' in sysconfig.get_config_var("CONFIG_ARGS"): + include_dirs = [] + libraries = [':libmpdec.so.2'] + sources = ['_decimal/_decimal.c'] +-- +2.20.1 + +From c68234aba844cb1034fdcfb50aef03da454723f9 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Wed, 23 Dec 2015 11:51:58 +0100 +Subject: [PATCH] Add an option to disable the ossaudiodev module + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index e6255babb6..5809233aac 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3042,6 +3042,12 @@ fi + + AC_MSG_RESULT($with_decimal_contextvar) + ++AC_ARG_ENABLE(ossaudiodev, ++ AS_HELP_STRING([--disable-ossaudiodev], [disable OSSAUDIODEV]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} ossaudiodev" ++ fi]) ++ + # Check for support for loadable sqlite extensions + AC_MSG_CHECKING(for --enable-loadable-sqlite-extensions) + AC_ARG_ENABLE(loadable-sqlite-extensions, +-- +2.20.1 + +From 8faf197969bf531279d5c59a5bb2bc3a21acc378 Mon Sep 17 00:00:00 2001 +From: Nicolas Cavallari +Date: Wed, 22 Feb 2017 17:55:59 -0800 +Subject: [PATCH] Add an option to disable openssl support. + +Signed-off-by: Nicolas Cavallari +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 5809233aac..6b09bafda4 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3282,6 +3282,12 @@ AC_ARG_ENABLE(unicodedata, + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} unicodedata" + fi]) + ++AC_ARG_ENABLE(openssl, ++ AS_HELP_STRING([--disable-openssl], [disable openssl support]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} ssl _ssl _hashlib" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From 6e3923f90497ba7230b62fdd3f2dca1cb79852bf Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Tue, 7 Mar 2017 23:29:05 +0100 +Subject: [PATCH] Add an option to disable the readline module + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 6b09bafda4..b64518eed5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3288,6 +3288,12 @@ AC_ARG_ENABLE(openssl, + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} ssl _ssl _hashlib" + fi]) + ++AC_ARG_ENABLE(readline, ++ AS_HELP_STRING([--disable-readline], [disable readline]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} readline" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From e6f44f93db96ed7f3b2baa0e09ea32a32c78c638 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Tue, 7 Mar 2017 23:31:11 +0100 +Subject: [PATCH] Add options to disable zlib, bzip2 and xz modules + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/configure.ac b/configure.ac +index b64518eed5..d07e371c57 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3294,6 +3294,24 @@ AC_ARG_ENABLE(readline, + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} readline" + fi]) + ++AC_ARG_ENABLE(bzip2, ++ AS_HELP_STRING([--disable-bzip2], [disable bzip2]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _bz2" ++ fi]) ++ ++AC_ARG_ENABLE(zlib, ++ AS_HELP_STRING([--disable-zlib], [disable zlib]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} zlib" ++ fi]) ++ ++AC_ARG_ENABLE(xz, ++ AS_HELP_STRING([--disable-xz], [disable xz]), ++ [ if test "$enableval" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _lzma" ++ fi]) ++ + AC_SUBST(TK) + AC_ARG_ENABLE(tk, + AS_HELP_STRING([--disable-tk], [disable tk]), +-- +2.20.1 + +From e3221e3b714374e1e53dc11c9556733bd2807c2c Mon Sep 17 00:00:00 2001 +From: Matt Weber +Date: Fri, 6 Oct 2017 09:54:15 -0500 +Subject: [PATCH] python-config.sh: don't reassign ${prefix} + +When prefix is set to a path like /usr during crossbuild +the sed operations end up executing twice, once for the prefix +reassignment and another for includedir if it is set as a string +including the ${prefix} variable. This results in an issue +when the build directory is under /usr. + +This patch updates the remaining location which uses the prefix +variable to also sed and update to use the real path. + +Upstream bug report: +https://bugs.python.org/issue31713 + +Buildroot bug: +https://bugs.busybox.net/show_bug.cgi?id=10361 + +Fixes failures like the following: +dbus-python-1.2.4 | NOK | http://autobuild.buildroot.net/results/758858efa97b6273c1b470513f5492258a6d8853 + +Signed-off-by: Matthew Weber +--- + Misc/python-config.sh.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in +index a1bc3cd5f7..164d2d3603 100644 +--- a/Misc/python-config.sh.in ++++ b/Misc/python-config.sh.in +@@ -31,7 +31,7 @@ prefix_real=$(installed_prefix "$0") + # locations. Keep prefix & exec_prefix using their original values in case + # they are referenced in other configure variables, to prevent double + # substitution, issue #22140. +-prefix=$(echo "$prefix_build" | sed "s#^$prefix_build#$prefix_real#") ++prefix=$prefix_build + exec_prefix=$(echo "$exec_prefix_build" | sed "s#^$exec_prefix_build#$prefix_real#") + exec_prefix_real=${prefix_real} + includedir=$(echo "@includedir@" | sed "s#^$prefix_build#$prefix_real#") +@@ -49,7 +49,7 @@ LDLIBRARY="@LDLIBRARY@" + OPT="@OPT@" + PY_ENABLE_SHARED="@PY_ENABLE_SHARED@" + LDVERSION="@LDVERSION@" +-LIBDEST=${prefix_real}/lib/python${VERSION} ++LIBDEST=$( echo "${prefix}/lib/python${VERSION}" | sed "s#^$prefix_build#$prefix_real#") + LIBPL=$(echo "@LIBPL@" | sed "s#^$prefix_build#$prefix_real#") + SO="@EXT_SUFFIX@" + PYTHONFRAMEWORK="@PYTHONFRAMEWORK@" +-- +2.20.1 + +From 28008e1e4f0349241d22aace3c54f7e9425c6c1f Mon Sep 17 00:00:00 2001 +From: Adam Duskett +Date: Fri, 20 Jul 2018 10:17:39 -0400 +Subject: [PATCH] Fix cross compiling the uuid module + +Python 3.7 has a new _uuid module, however, the include directory +search path for uuid.h is hardcoded to /usr/include/uuid, which should +not be used when cross-compiling. + +To fix this, use the same solution as the one used by the NIS +detection: append "uuid" to each of the include directories in +"inc_dirs", instead of hardcoding /usr/include/uuid. + +Signed-off-by: Adam Duskett +[Thomas: drop STAGING_DIR based solution, use a solution similar to +the one used for the NIS detection.] +Signed-off-by: Thomas Petazzoni +--- + setup.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index a7f2e23d87..b0274a3f67 100644 +--- a/setup.py ++++ b/setup.py +@@ -1674,7 +1674,8 @@ class PyBuildExt(build_ext): + + def detect_uuid(self): + # Build the _uuid module if possible +- uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"]) ++ uuid_incs = find_file("uuid.h", self.inc_dirs, ++ [os.path.join(inc_dir, 'uuid') for inc_dir in self.inc_dirs]) + if uuid_incs is not None: + if self.compiler.find_library_file(self.lib_dirs, 'uuid'): + uuid_libs = ['uuid'] +-- +2.20.1 + +From 74007603df0921450f14e8626df36140426cc300 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Sat, 18 Aug 2018 10:54:56 +0200 +Subject: [PATCH] Add an option to disable uuid module + +Signed-off-by: Thomas Petazzoni +--- + configure.ac | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/configure.ac b/configure.ac +index d07e371c57..55ab6c3c26 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3330,6 +3330,15 @@ if test "$CURSES" = "no"; then + DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _curses _curses_panel" + fi + ++AC_SUBST(UUID) ++AC_ARG_ENABLE(uuid, ++ AS_HELP_STRING([--disable-uuid], [disable uuid]), ++ [ UUID="${enableval}" ], [ UUID=yes ]) ++ ++if test "$UUID" = "no"; then ++ DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS} _uuid" ++fi ++ + AC_SUBST(PYDOC) + + AC_ARG_ENABLE(pydoc, +-- +2.20.1 + +From 3ddda00652f809a3bd8b4e3f7b0a3a4270b280a6 Mon Sep 17 00:00:00 2001 +From: Adam Duskett +Date: Thu, 16 Aug 2018 14:52:37 -0700 +Subject: [PATCH] fix building on older distributions + +Python > 3.6.3 calls os.replace in the update_file.py script, during the +regen-importlib phase of the build process. + +According to Doc/whatsnew/3.3.rst line 1631, os.replace acts in the same +way as os.rename, however, it is now cross-platform compatible for Windows. + +Because BuildRoot is guaranteed only to be built in POSIX environment, it is +safe to change os.replace back to os.rename. + +This change fixes building on older systems such as CentOS7, that only come +with python 2. + +Signed-off-by: Adam Duskett +--- + Tools/scripts/update_file.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Tools/scripts/update_file.py b/Tools/scripts/update_file.py +index 224585c69b..ef458c0c63 100644 +--- a/Tools/scripts/update_file.py ++++ b/Tools/scripts/update_file.py +@@ -16,7 +16,7 @@ def main(old_path, new_path): + with open(new_path, 'rb') as f: + new_contents = f.read() + if old_contents != new_contents: +- os.replace(new_path, old_path) ++ os.rename(new_path, old_path) + else: + os.unlink(new_path) + +-- +2.20.1 + +From 5932fedd9d1d43a230fa353df434f253e9d2b5a0 Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Fri, 2 Aug 2019 15:53:16 +0200 +Subject: [PATCH] configure.ac: fixup $CC --print-multiarch output for + musl/uclibc GCC 8+ toolchains + +GCC commit 6834b83784dcf0364eb820e8 (multiarch support for non-glibc linux +systems), which is part of GCC 8+, changed the multiarch logic to use +$arch-linux-musl / $arch-linux-uclibc rather than $arch-linux-gnu. + +This then causes the python3 configure script to error out: + +checking for the platform triplet based on compiler characteristics... powerpc-linux-gnu +configure: error: internal configure error for the platform triplet, please file a bug report + +http://autobuild.buildroot.net/results/cb4/cb49c539501342e45cbe5ade82e588fcdf51f05b + +As it requires that the --print-multiarch output (if not empty) matches the +deduced triplet (which always uses -linux-gnu). + +It isn't quite clear why --print-multiarch returns something for a +non-multiarch toolchain on some architectures (E.G. PowerPC), but as a +workaround, rewrite the --print-multiarch output to match older GCC versions +to keep the configure script happy. + +Signed-off-by: Peter Korsgaard +--- + configure.ac | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 55ab6c3c26..4a6d0662ac 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -706,7 +706,9 @@ then + fi + + +-MULTIARCH=$($CC --print-multiarch 2>/dev/null) ++# GCC 8+ returns $arch-linux-{musl,uclibc} for musl/uClibc based ++# toolchains confusing python. Fix that up ++MULTIARCH=$($CC --print-multiarch 2>/dev/null | sed -E 's/-linux-(musl|uclibc)*$/-linux-gnu/') + AC_SUBST(MULTIARCH) + + AC_MSG_CHECKING([for the platform triplet based on compiler characteristics]) +-- +2.20.1 + diff --git a/packages/lang/Python3/patches/Python3-0201-xcompile.patch b/packages/lang/Python3/patches/Python3-0201-xcompile.patch new file mode 100644 index 000000000..eb51f7980 --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0201-xcompile.patch @@ -0,0 +1,53 @@ +diff -aur a/Makefile.pre.in b/Makefile.pre.in +--- a/Makefile.pre.in 2020-08-08 14:28:01.691542199 -0400 ++++ b/Makefile.pre.in 2020-08-08 14:17:51.908512177 -0400 +@@ -607,10 +607,12 @@ + esac; \ + echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ ++ PYTHONXCPREFIX='$(DESTDIR)$(prefix)' \ + DISABLED_EXTENSIONS="$(DISABLED_EXTENSIONS)" \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ ++ PYTHONXCPREFIX='$(DESTDIR)$(prefix)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + + +@@ -1656,8 +1658,10 @@ + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: sharedmods ++ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(RUNSHARED) DISABLED_EXTENSIONS="$(DISABLED_EXTENSIONS)" \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ ++ --skip-build \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ +diff -aur a/setup.py b/setup.py +--- a/setup.py 2020-08-08 14:28:01.695542200 -0400 ++++ b/setup.py 2020-08-08 14:28:36.931543934 -0400 +@@ -41,7 +41,7 @@ + return sys.platform + + +-CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ) ++CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ) or ('PYTHONXCPREFIX' in os.environ) + HOST_PLATFORM = get_platform() + MS_WINDOWS = (HOST_PLATFORM == 'win32') + CYGWIN = (HOST_PLATFORM == 'cygwin') +@@ -487,6 +487,13 @@ + ext.name, level=1) + return + ++ # Import check will not work when cross-compiling. ++ if 'PYTHONXCPREFIX' in os.environ: ++ self.announce( ++ 'WARNING: skipping import check for cross-compiled: "%s"' % ++ ext.name) ++ return ++ + # Workaround for Mac OS X: The Carbon-based modules cannot be + # reliably imported into a command-line Python + if 'Carbon' in ext.extra_link_args: diff --git a/packages/lang/Python3/patches/Python3-0202-xcompile.patch b/packages/lang/Python3/patches/Python3-0202-xcompile.patch new file mode 100644 index 000000000..c09d95a4c --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0202-xcompile.patch @@ -0,0 +1,48 @@ +diff -aur a/setup.py b/setup.py +--- a/setup.py 2020-08-08 14:18:41.978514642 -0400 ++++ b/setup.py 2020-08-08 14:26:09.612536681 -0400 +@@ -656,31 +656,23 @@ + add_dir_to_list(dir_list, directory) + + def configure_compiler(self): +- # Ensure that /usr/local is always used, but the local build +- # directories (i.e. '.' and 'Include') must be first. See issue +- # 10520. +- if not CROSS_COMPILING: +- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') +- add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') ++ try: ++ modules_include_dirs = os.environ["PYTHON_MODULES_INCLUDE"].split() ++ except KeyError: ++ modules_include_dirs = ['/usr/include'] ++ try: ++ modules_lib_dirs = os.environ["PYTHON_MODULES_LIB"].split() ++ except KeyError: ++ modules_lib_dirs = ['/usr/lib'] + self.add_multiarch_paths() +- # only change this for cross builds for 3.3, issues on Mageia +- if CROSS_COMPILING: +- self.add_cross_compiling_paths() ++ for dir in modules_include_dirs: ++ add_dir_to_list(self.compiler.include_dirs, dir) ++ for dir in modules_lib_dirs: ++ add_dir_to_list(self.compiler.library_dirs, dir) ++ + self.add_ldflags_cppflags() + + def init_inc_lib_dirs(self): +- if (not CROSS_COMPILING and +- os.path.normpath(sys.base_prefix) != '/usr' and +- not sysconfig.get_config_var('PYTHONFRAMEWORK')): +- # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework +- # (PYTHONFRAMEWORK is set) to avoid # linking problems when +- # building a framework with different architectures than +- # the one that is currently installed (issue #7473) +- add_dir_to_list(self.compiler.library_dirs, +- sysconfig.get_config_var("LIBDIR")) +- add_dir_to_list(self.compiler.include_dirs, +- sysconfig.get_config_var("INCLUDEDIR")) +- + system_lib_dirs = ['/lib64', '/usr/lib64', '/lib', '/usr/lib'] + system_include_dirs = ['/usr/include'] + # lib_dirs and inc_dirs are used to search for files; diff --git a/packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch b/packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch new file mode 100644 index 000000000..9cf95562a --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0300-generate-legacy-pyc-bytecode.patch @@ -0,0 +1,42 @@ +From dc39d0d93427a92c387e3c1944368d7f08299c06 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sun, 20 Oct 2019 02:32:03 +0100 +Subject: [PATCH] Always generate legacy bytecode (allows removal of py source + code) + +We want to create compiled bytecode for modules in the read-only +squashfs, and we also want to avoid distributing the py source code +which is a waste of space. + +Unfortunately, after PEP3147, it's no longer possible to distribute +pyc bytecode without the corresponding py source code unless the +bytecode is generated using the "legacy" layout (ie. not using __pycache__). + +Since all packages process their Python source code in different ways, +but ultimately all compile it via a call to py_compile.compile(), the +easiest solution is to patch py_compile.compile() so that it only +generates legacy bytecode. + +https://www.python.org/dev/peps/pep-3147/#case-4-legacy-pyc-files-and-source-less-imports +--- + Lib/py_compile.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Lib/py_compile.py b/Lib/py_compile.py +index 8e9dd57..d4b7f4f 100644 +--- a/Lib/py_compile.py ++++ b/Lib/py_compile.py +@@ -119,6 +119,10 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1, + the resulting file would be regular and thus not the same type of file as + it was previously. + """ ++ ++ if cfile: ++ cfile = file + 'c' ++ + if invalidation_mode is None: + invalidation_mode = _get_default_invalidation_mode() + if cfile is None: +-- +2.7.4 + diff --git a/packages/lang/Python3/patches/Python3-0400-fix-bpo5537.patch b/packages/lang/Python3/patches/Python3-0400-fix-bpo5537.patch new file mode 100644 index 000000000..9618fc90e --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0400-fix-bpo5537.patch @@ -0,0 +1,27 @@ +From 7c35472bc734876f940fdc71090ad3d526e95a82 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Fri, 14 Feb 2020 01:33:34 +0000 +Subject: [PATCH] Fix issue 5537 - regression on 32-bit + +https://bugs.python.org/issue5537 +https://forum.kodi.tv/showthread.php?tid=343068&pid=2923934#pid2923934 +--- + Lib/http/cookiejar.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py +index d43a219..53bb391 100644 +--- a/Lib/http/cookiejar.py ++++ b/Lib/http/cookiejar.py +@@ -98,7 +98,7 @@ def time2isoz(t=None): + if t is None: + dt = datetime.datetime.utcnow() + else: +- dt = datetime.datetime.utcfromtimestamp(t) ++ dt = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=t) + return "%04d-%02d-%02d %02d:%02d:%02dZ" % ( + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) + +-- +2.20.1 + diff --git a/packages/lang/Python3/patches/Python3-0500-fix-bpo45262.patch b/packages/lang/Python3/patches/Python3-0500-fix-bpo45262.patch new file mode 100644 index 000000000..b1e671e1c --- /dev/null +++ b/packages/lang/Python3/patches/Python3-0500-fix-bpo45262.patch @@ -0,0 +1,26 @@ +From c4e2aa8d60f722cece55d446e97585b1fa8a6ae7 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Thu, 7 Oct 2021 13:03:27 +0200 +Subject: [PATCH] Prevent use-after-free of running loop holder via cache + +--- + Modules/_asynciomodule.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c +index ecc73d1ca8..56079b0277 100644 +--- a/Modules/_asynciomodule.c ++++ b/Modules/_asynciomodule.c +@@ -3239,6 +3239,9 @@ new_running_loop_holder(PyObject *loop) + static void + PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl) + { ++ if (cached_running_holder == (PyObject *)rl) { ++ cached_running_holder = NULL; ++ } + Py_CLEAR(rl->rl_loop); + PyObject_Free(rl); + } +-- +2.30.2 + diff --git a/packages/lang/dotnet-runtime/changelog.txt b/packages/lang/dotnet-runtime/changelog.txt new file mode 100644 index 000000000..e13b8d5c6 --- /dev/null +++ b/packages/lang/dotnet-runtime/changelog.txt @@ -0,0 +1,32 @@ +110 +- Update to 3.1.5 + +109 +- Fix x86_64 url + +108 +- Update to 3.1.3 + +107 +- Update to 2.2.6 + +106 +- Update to 2.2.4 + +105 +- Update to 2.2.3 + +104 +- Update to 2.2.0 + +103 +- Update to 2.1.6 + +102 +- Update to 2.1.4 + +101 +- Update to 2.1.3 + +100 +- Initial release diff --git a/packages/lang/dotnet-runtime/icon/icon.png b/packages/lang/dotnet-runtime/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7b53b77cd0d0d7051ad3adecb04eeeb3991f53a1 GIT binary patch literal 51118 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 literal 0 HcmV?d00001 diff --git a/packages/lang/dotnet-runtime/package.mk b/packages/lang/dotnet-runtime/package.mk new file mode 100644 index 000000000..7a569768b --- /dev/null +++ b/packages/lang/dotnet-runtime/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +case "$ARCH" in + "aarch64") + PKG_NC_ARCH="arm64" + PKG_SHA256="05875790fbfc487cefb04fc6ff6d9a3ade147f1ae554e859dca60ea6a3c232aa" + PKG_URL="https://download.visualstudio.microsoft.com/download/pr/65291ed8-e931-4605-9d5a-265928a835d0/1a15d18655c8b260170117e9bd1a1cb7/dotnet-runtime-3.1.5-linux-arm64.tar.gz" + ;; + "arm") + PKG_NC_ARCH="arm" + PKG_SHA256="5728786f517410f25c59799f443d0336129d6b1680fd40cb5b40202407949008" + PKG_URL="https://download.visualstudio.microsoft.com/download/pr/15132a5c-f0f4-4373-8b8b-b7e70834d899/cad479dda52359ad43956471274ec932/dotnet-runtime-3.1.5-linux-arm.tar.gz" + ;; + "x86_64") + PKG_NC_ARCH="x64" + PKG_SHA256="ae0a4e9a1e875b46d3201cdad2779572de1c12c0aae36688ae3c3978db319ff5" + PKG_URL="https://download.visualstudio.microsoft.com/download/pr/d00eaeea-6d7b-4e73-9d96-c0234ed3b665/0d25d9d1aeaebdeef01d15370d5cd22b/dotnet-runtime-3.1.5-linux-x64.tar.gz" + ;; +esac + +PKG_NAME="dotnet-runtime" +PKG_VERSION="3.1.5" +PKG_REV="110" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://dotnet.github.io/" +PKG_DEPENDS_TARGET="toolchain curl curl3 krb5 lttng-ust" +PKG_SECTION="tools" +PKG_SHORTDESC=".NET Core Runtime" +PKG_LONGDESC=".NET Core Runtime ($PKG_VERSION) runs applications built with .NET Core, a cross-platform .NET implementation." +PKG_TOOLCHAIN="manual" + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME=".Net Core Runtime" +PKG_ADDON_TYPE="xbmc.python.script" +PKG_MAINTAINER="Anton Voyl (awiouy)" + +addon() { + mkdir -p $ADDON_BUILD/$PKG_ADDON_ID/bin + cp -r $PKG_BUILD/* \ + $ADDON_BUILD/$PKG_ADDON_ID/bin + + mkdir -p $ADDON_BUILD/$PKG_ADDON_ID/libs + cp -L $(get_build_dir curl3)/.install_pkg/usr/lib/libcurl.so.? \ + $(get_build_dir krb5)/.install_pkg/usr/lib/libcom_err.so.? \ + $(get_build_dir krb5)/.install_pkg/usr/lib/libgssapi_krb5.so.? \ + $(get_build_dir krb5)/.install_pkg/usr/lib/libk5crypto.so.? \ + $(get_build_dir krb5)/.install_pkg/usr/lib/libkrb5.so.? \ + $(get_build_dir krb5)/.install_pkg/usr/lib/libkrb5support.so.? \ + $(get_build_dir lttng-ust)/.install_pkg/usr/lib/liblttng-ust.so.? \ + $(get_build_dir lttng-ust)/.install_pkg/usr/lib/liblttng-ust-tracepoint.so.? \ + $ADDON_BUILD/$PKG_ADDON_ID/libs +} diff --git a/packages/lang/dotnet-runtime/source/bin/le_dotnet b/packages/lang/dotnet-runtime/source/bin/le_dotnet new file mode 100644 index 000000000..c5ed97d3c --- /dev/null +++ b/packages/lang/dotnet-runtime/source/bin/le_dotnet @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. /etc/profile +oe_setup_addon tools.dotnet-runtime + +DOTNET_SYSTEM_GLOBALIZATION_INVARIANT="1" \ +LD_LIBRARY_PATH="$ADDON_DIR/libs:$LD_LIBRARY_PATH" \ +dotnet "$@" diff --git a/packages/lang/gcc-arm-aarch64-none-elf/package.mk b/packages/lang/gcc-arm-aarch64-none-elf/package.mk new file mode 100644 index 000000000..c2aa00d5a --- /dev/null +++ b/packages/lang/gcc-arm-aarch64-none-elf/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gcc-arm-aarch64-none-elf" +PKG_VERSION="10.3-2021.07" +PKG_SHA256="768a5db41d93f48838f1c4bfeae26930df2320c09f0dfa798321082fb937955f" +PKG_LICENSE="GPL" +PKG_SITE="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a" +PKG_URL="https://developer.arm.com/-/media/Files/downloads/gnu-a/${PKG_VERSION}/binrel/gcc-arm-${PKG_VERSION}-aarch64-aarch64-none-elf.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="ARM Aarch64 GNU Linux Binary Toolchain" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/lib/gcc-arm-aarch64-none-elf/ + cp -a * ${TOOLCHAIN}/lib/gcc-arm-aarch64-none-elf + + # wrap gcc and g++ with ccache like in gcc package.mk + PKG_GCC_PREFIX="${TOOLCHAIN}/lib/gcc-arm-aarch64-none-elf/bin/aarch64-none-elf-" + + cp "${PKG_GCC_PREFIX}gcc" "${PKG_GCC_PREFIX}gcc.real" +cat > "${PKG_GCC_PREFIX}gcc" << EOF +#!/bin/sh +${TOOLCHAIN}/bin/ccache ${PKG_GCC_PREFIX}gcc.real "\$@" +EOF + + chmod +x "${PKG_GCC_PREFIX}gcc" + + cp "${PKG_GCC_PREFIX}g++" "${PKG_GCC_PREFIX}g++.real" +cat > "${PKG_GCC_PREFIX}g++" << EOF +#!/bin/sh +${TOOLCHAIN}/bin/ccache ${PKG_GCC_PREFIX}g++.real "\$@" +EOF + + chmod +x "${PKG_GCC_PREFIX}g++" +} diff --git a/packages/lang/gcc-arm-aarch64-none-linux-gnu/package.mk b/packages/lang/gcc-arm-aarch64-none-linux-gnu/package.mk new file mode 100644 index 000000000..ff8408c3a --- /dev/null +++ b/packages/lang/gcc-arm-aarch64-none-linux-gnu/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gcc-arm-aarch64-none-linux-gnu" +PKG_VERSION="10.3-2021.07" +PKG_SHA256="1e33d53dea59c8de823bbdfe0798280bdcd138636c7060da9d77a97ded095a84" +PKG_LICENSE="GPL" +PKG_SITE="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a" +PKG_URL="https://developer.arm.com/-/media/Files/downloads/gnu-a/${PKG_VERSION}/binrel/gcc-arm-${PKG_VERSION}-x86_64-aarch64-none-linux-gnu.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="ARM Aarch64 GNU Linux Binary Toolchain" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/lib/gcc-arm-aarch64-none-linux-gnu/ + cp -a * ${TOOLCHAIN}/lib/gcc-arm-aarch64-none-linux-gnu + + # wrap gcc and g++ with ccache like in gcc package.mk + PKG_GCC_PREFIX="${TOOLCHAIN}/lib/gcc-arm-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-" + + cp "${PKG_GCC_PREFIX}gcc" "${PKG_GCC_PREFIX}gcc.real" +cat > "${PKG_GCC_PREFIX}gcc" << EOF +#!/bin/sh +${TOOLCHAIN}/bin/ccache ${PKG_GCC_PREFIX}gcc.real "\$@" +EOF + + chmod +x "${PKG_GCC_PREFIX}gcc" + + cp "${PKG_GCC_PREFIX}g++" "${PKG_GCC_PREFIX}g++.real" +cat > "${PKG_GCC_PREFIX}g++" << EOF +#!/bin/sh +${TOOLCHAIN}/bin/ccache ${PKG_GCC_PREFIX}g++.real "\$@" +EOF + + chmod +x "${PKG_GCC_PREFIX}g++" +} diff --git a/packages/lang/gcc/package.mk b/packages/lang/gcc/package.mk new file mode 100644 index 000000000..bc19b2d05 --- /dev/null +++ b/packages/lang/gcc/package.mk @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gcc" +PKG_VERSION="10.3.0" +PKG_LICENSE="GPL" +PKG_SITE="http://gcc.gnu.org/" +PKG_URL="https://bigsearcher.com/mirrors/gcc/releases/gcc-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_BOOTSTRAP="ccache:host autoconf:host binutils:host gmp:host mpfr:host mpc:host zstd:host" +PKG_DEPENDS_TARGET="toolchain gcc:host" +PKG_DEPENDS_HOST="ccache:host autoconf:host binutils:host gmp:host mpfr:host mpc:host zstd:host glibc" +PKG_DEPENDS_INIT="toolchain" +PKG_LONGDESC="This package contains the GNU Compiler Collection." + +GCC_COMMON_CONFIGURE_OPTS="--target=${TARGET_NAME} \ + --with-sysroot=${SYSROOT_PREFIX} \ + --with-gmp=${TOOLCHAIN} \ + --with-mpfr=${TOOLCHAIN} \ + --with-mpc=${TOOLCHAIN} \ + --with-zstd=${TOOLCHAIN} \ + --with-gnu-as \ + --with-gnu-ld \ + --enable-plugin \ + --enable-lto \ + --enable-gold \ + --enable-ld=default \ + --with-linker-hash-style=gnu \ + --disable-multilib \ + --disable-nls \ + --enable-checking=release \ + --with-default-libstdcxx-abi=gcc4-compatible \ + --without-ppl \ + --without-cloog \ + --disable-libada \ + --disable-libmudflap \ + --disable-libatomic \ + --disable-libitm \ + --disable-libquadmath \ + --disable-libmpx \ + --disable-libssp \ + --enable-__cxa_atexit" + +PKG_CONFIGURE_OPTS_BOOTSTRAP="${GCC_COMMON_CONFIGURE_OPTS} \ + --enable-languages=c \ + --disable-libsanitizer \ + --enable-cloog-backend=isl \ + --disable-shared \ + --disable-threads \ + --disable-libgomp \ + --without-headers \ + --with-newlib \ + --disable-decimal-float \ + ${GCC_OPTS}" + +PKG_CONFIGURE_OPTS_HOST="${GCC_COMMON_CONFIGURE_OPTS} \ + --enable-languages=c,c++ \ + --enable-decimal-float \ + --enable-tls \ + --enable-shared \ + --disable-static \ + --enable-c99 \ + --enable-long-long \ + --enable-threads=posix \ + --disable-libstdcxx-pch \ + --enable-libstdcxx-time \ + --enable-clocale=gnu \ + ${GCC_OPTS}" + +pre_configure_host() { + unset CPP +} + +post_make_host() { + if [ ! "${BUILD_WITH_DEBUG}" = "yes" ]; then + ${TARGET_PREFIX}strip ${TARGET_NAME}/libgomp/.libs/libgomp.so* + ${TARGET_PREFIX}strip ${TARGET_NAME}/libstdc++-v3/src/.libs/libstdc++.so* + fi +} + +post_makeinstall_host() { + cp -PR ${TARGET_NAME}/libstdc++-v3/src/.libs/libstdc++.so* ${SYSROOT_PREFIX}/usr/lib + + GCC_VERSION=$(${TOOLCHAIN}/bin/${TARGET_NAME}-gcc -dumpversion) + DATE="0501$(echo ${GCC_VERSION} | sed 's/\./0/g')" + CROSS_CC=${TARGET_PREFIX}gcc-${GCC_VERSION} + CROSS_CXX=${TARGET_PREFIX}g++-${GCC_VERSION} + + rm -f ${TARGET_PREFIX}gcc + +cat > ${TARGET_PREFIX}gcc < ${TARGET_PREFIX}g++ < +Date: Thu, 24 Apr 2014 22:33:27 +0300 +Subject: [PATCH] allow newer autoconf + +--- + config/override.m4 | 9 --------- + 1 files changed, 0 insertions(+), 9 deletions(-) + +diff --git a/config/override.m4 b/config/override.m4 +index 52bd1c3..6c39656 100644 +--- a/config/override.m4 ++++ b/config/override.m4 +@@ -38,15 +38,6 @@ dnl m4_define([_GCC_AUTOCONF_VERSION], [X.Y]) + dnl in configure.ac before AC_INIT, + dnl without rewriting this file. + dnl Or for updating the whole tree at once with the definition above. +-AC_DEFUN([_GCC_AUTOCONF_VERSION_CHECK], +-[m4_if(m4_defn([_GCC_AUTOCONF_VERSION]), +- m4_defn([m4_PACKAGE_VERSION]), [], +- [m4_fatal([Please use exactly Autoconf ]_GCC_AUTOCONF_VERSION[ instead of ]m4_defn([m4_PACKAGE_VERSION])[.])]) +-]) +-m4_define([AC_INIT], m4_defn([AC_INIT])[ +-_GCC_AUTOCONF_VERSION_CHECK +-]) +- + + dnl Ensure we do not use a buggy M4. + m4_if(m4_index([..wi.d.], [.d.]), [-1], +-- +1.7.2.5 + diff --git a/packages/lang/gcc/patches/gcc-crosscompile-badness.patch b/packages/lang/gcc/patches/gcc-crosscompile-badness.patch new file mode 100644 index 000000000..22aa83167 --- /dev/null +++ b/packages/lang/gcc/patches/gcc-crosscompile-badness.patch @@ -0,0 +1,31 @@ +Index: gcc-4.4+svnr145550/gcc/incpath.c +=================================================================== +--- gcc-4.4+svnr145550.orig/gcc/incpath.c 2009-04-04 13:48:31.000000000 -0700 ++++ gcc-4.4+svnr145550/gcc/incpath.c 2009-04-04 14:49:29.000000000 -0700 +@@ -417,6 +417,26 @@ + p->construct = 0; + p->user_supplied_p = user_supplied_p; + ++ /* A common error when cross compiling is including ++ host headers. This code below will try to fail fast ++ for cross compiling. Currently we consider /usr/include, ++ /opt/include and /sw/include as harmful. */ ++ ++ { ++ /* printf("Adding Path: %s\n", p->name ); */ ++ if( strstr(p->name, "/usr/include" ) == p->name ) { ++ fprintf(stderr, _("CROSS COMPILE Badness: /usr/include in INCLUDEPATH: %s\n"), p->name); ++ abort(); ++ } else if( strstr(p->name, "/sw/include") == p->name ) { ++ fprintf(stderr, _("CROSS COMPILE Badness: /sw/include in INCLUDEPATH: %s\n"), p->name); ++ abort(); ++ } else if( strstr(p->name, "/opt/include") == p->name ) { ++ fprintf(stderr, _("CROSS COMPILE Badness: /opt/include in INCLUDEPATH: %s\n"), p->name); ++ abort(); ++ } ++ } ++ ++ + add_cpp_dir_path (p, chain); + } + diff --git a/packages/lang/jdk-x86_64-zulu/package.mk b/packages/lang/jdk-x86_64-zulu/package.mk new file mode 100644 index 000000000..9fa2bf9e5 --- /dev/null +++ b/packages/lang/jdk-x86_64-zulu/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Peter Vicman (peter.vicman@gmail.com) + +PKG_NAME="jdk-x86_64-zulu" +PKG_VERSION="8.38.0.13-8.0.212" +PKG_SHA256="568e7578f1b20b1e62a8ed2c374bad4eb0e75d221323ccfa6ba8d7bc56cf33cf" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.azul.com/products/zulu-enterprise/" +PKG_URL="https://cdn.azul.com/zulu/bin/zulu${PKG_VERSION%%-*}-ca-jdk${PKG_VERSION##*-}-linux_x64.tar.gz" +PKG_LONGDESC="Zulu, the open Java(TM) platform from Azul Systems." +PKG_TOOLCHAIN="manual" + +post_unpack() { + rm -f $PKG_BUILD/src.zip +} diff --git a/packages/lang/jre.zulu/changelog.txt b/packages/lang/jre.zulu/changelog.txt new file mode 100644 index 000000000..fe01f1b4f --- /dev/null +++ b/packages/lang/jre.zulu/changelog.txt @@ -0,0 +1,2 @@ +100 +- Initial release diff --git a/packages/lang/jre.zulu/icon/icon.png b/packages/lang/jre.zulu/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee3a2d9fb79fa38565e56883539424688cea660 GIT binary patch literal 18090 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 literal 0 HcmV?d00001 diff --git a/packages/lang/jre.zulu/package.mk b/packages/lang/jre.zulu/package.mk new file mode 100644 index 000000000..427a3ae15 --- /dev/null +++ b/packages/lang/jre.zulu/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Peter Vicman (peter.vicman@gmail.com) + +PKG_NAME="jre.zulu" +PKG_VERSION="1.0" +PKG_REV="100" +PKG_LICENSE="GPL2" +PKG_DEPENDS_TARGET="jdk-${TARGET_ARCH}-zulu jre-libbluray libXext chrome-libXtst chrome-libXi chrome-libXrender jre-libXinerama" +PKG_SECTION="tools" +PKG_SHORTDESC="Java Runtime Environment 8 for Blu-ray Disc Java menus from Azul Systems." +PKG_LONGDESC="$PKG_SHORTDESC" +PKG_TOOLCHAIN="manual" + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME="JRE for BD-J menus" +PKG_ADDON_TYPE="xbmc.python.script" + +# find $1.so.[0-9]* in $2 and copy it to dest +_pkg_copy_lib() { + find "$2" -regextype sed -regex ".*/$1\.so\.[0-9]*" \ + -exec cp {} "$ADDON_BUILD/$PKG_ADDON_ID/lib" \; +} + +addon() { + mkdir -p $ADDON_BUILD/$PKG_ADDON_ID/lib + + cp -a $(get_build_dir jdk-${TARGET_ARCH}-zulu)/jre \ + $(get_build_dir jre-libbluray)/.$TARGET_NAME/.libs/*.jar \ + ${PKG_DIR}/profile.d \ + $ADDON_BUILD/$PKG_ADDON_ID + + # copy required libraries for JRE + _pkg_copy_lib libXtst $(get_build_dir chrome-libXtst)/.$TARGET_NAME/src/.libs + _pkg_copy_lib libXi $(get_build_dir chrome-libXi)/.$TARGET_NAME/src/.libs + _pkg_copy_lib libXrender $(get_build_dir chrome-libXrender)/.$TARGET_NAME/src/.libs + _pkg_copy_lib libXinerama $(get_build_dir jre-libXinerama)/.$TARGET_NAME/src/.libs + + if [ "$TARGET_ARCH" = "arm" ]; then + _pkg_copy_lib libX11 $(get_build_dir libX11)/.$TARGET_NAME/src/.libs + _pkg_copy_lib libXext $(get_build_dir libXext)/.$TARGET_NAME/src/.libs + fi +} diff --git a/packages/lang/jre.zulu/profile.d/jre.profile b/packages/lang/jre.zulu/profile.d/jre.profile new file mode 100644 index 000000000..21b43a658 --- /dev/null +++ b/packages/lang/jre.zulu/profile.d/jre.profile @@ -0,0 +1,8 @@ +# point to folder with jre +export JAVA_HOME="/storage/.kodi/addons/tools.jre.zulu" + +# libbluray-*.jar in this folder (need / at the end) +export LIBBLURAY_CP="/storage/.kodi/addons/tools.jre.zulu/" + +# or set file directly +# export LIBBLURAY_CP="/storage/.kodi/addons/tools.jre.zulu/libbluray-j2se-1.0.2.jar" diff --git a/packages/lang/jre.zulu/source/default.py b/packages/lang/jre.zulu/source/default.py new file mode 100644 index 000000000..60d94ff72 --- /dev/null +++ b/packages/lang/jre.zulu/source/default.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) diff --git a/packages/lang/llvm/package.mk b/packages/lang/llvm/package.mk new file mode 100644 index 000000000..da87f31aa --- /dev/null +++ b/packages/lang/llvm/package.mk @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="llvm" +PKG_VERSION="13.0.0" +PKG_SHA256="408d11708643ea826f519ff79761fcdfc12d641a2510229eec459e72f8163020" +PKG_ARCH="x86_64" +PKG_LICENSE="Apache-2.0" +PKG_SITE="http://llvm.org/" +PKG_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${PKG_VERSION}/llvm-${PKG_VERSION}.src.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain llvm:host zlib" +PKG_LONGDESC="Low-Level Virtual Machine (LLVM) is a compiler infrastructure." + +PKG_CMAKE_OPTS_COMMON="-DLLVM_INCLUDE_TOOLS=ON \ + -DLLVM_BUILD_TOOLS=OFF \ + -DLLVM_BUILD_UTILS=OFF \ + -DLLVM_BUILD_EXAMPLES=OFF \ + -DLLVM_INCLUDE_EXAMPLES=OFF \ + -DLLVM_BUILD_TESTS=OFF \ + -DLLVM_INCLUDE_TESTS=OFF \ + -DLLVM_INCLUDE_GO_TESTS=OFF \ + -DLLVM_BUILD_BENCHMARKS=OFF \ + -DLLVM_BUILD_DOCS=OFF \ + -DLLVM_INCLUDE_DOCS=OFF \ + -DLLVM_ENABLE_DOXYGEN=OFF \ + -DLLVM_ENABLE_SPHINX=OFF \ + -DLLVM_ENABLE_OCAMLDOC=OFF \ + -DLLVM_ENABLE_BINDINGS=OFF \ + -DLLVM_TARGETS_TO_BUILD=AMDGPU \ + -DLLVM_ENABLE_TERMINFO=OFF \ + -DLLVM_ENABLE_ASSERTIONS=OFF \ + -DLLVM_ENABLE_WERROR=OFF \ + -DLLVM_ENABLE_ZLIB=ON \ + -DLLVM_ENABLE_LIBXML2=OFF \ + -DLLVM_BUILD_LLVM_DYLIB=ON \ + -DLLVM_LINK_LLVM_DYLIB=ON \ + -DLLVM_OPTIMIZED_TABLEGEN=ON \ + -DLLVM_APPEND_VC_REV=OFF \ + -DLLVM_ENABLE_RTTI=ON \ + -DLLVM_ENABLE_UNWIND_TABLES=OFF \ + -DLLVM_ENABLE_Z3_SOLVER=OFF" + +pre_configure_host() { + CXXFLAGS+=" -DLLVM_CONFIG_EXEC_PREFIX=\\\"${SYSROOT_PREFIX}/usr\\\"" + PKG_CMAKE_OPTS_HOST="${PKG_CMAKE_OPTS_COMMON}" +} + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="${PKG_CMAKE_OPTS_COMMON} \ + -DLLVM_TARGET_ARCH="${TARGET_ARCH}" \ + -DLLVM_TABLEGEN=${TOOLCHAIN}/bin/llvm-tblgen" +} + +make_host() { + ninja ${NINJA_OPTS} llvm-config llvm-tblgen +} + +makeinstall_host() { + cp -a lib/libLLVM-*.so ${TOOLCHAIN}/lib + cp -a bin/llvm-config ${TOOLCHAIN}/bin/llvm-config-host + cp -a bin/llvm-tblgen ${TOOLCHAIN}/bin +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/lib/LLVMHello.so + rm -rf ${INSTALL}/usr/lib/libLTO.so + rm -rf ${INSTALL}/usr/share +} diff --git a/packages/lang/llvm/patches/llvm-config.patch b/packages/lang/llvm/patches/llvm-config.patch new file mode 100644 index 000000000..b50c1a963 --- /dev/null +++ b/packages/lang/llvm/patches/llvm-config.patch @@ -0,0 +1,13 @@ +--- a/tools/llvm-config/llvm-config.cpp 2019-12-15 20:54:21.898634608 +0100 ++++ b/tools/llvm-config/llvm-config.cpp 2019-12-15 20:56:12.280223943 +0100 +@@ -285,6 +285,10 @@ + CurrentExecPrefix = + sys::path::parent_path(sys::path::parent_path(CurrentPath)).str(); + ++#ifdef LLVM_CONFIG_EXEC_PREFIX ++ CurrentExecPrefix = LLVM_CONFIG_EXEC_PREFIX; ++#endif ++ + // Check to see if we are inside a development tree by comparing to possible + // locations (prefix style or CMake style). + if (sys::fs::equivalent(CurrentExecPrefix, LLVM_OBJ_ROOT)) { diff --git a/packages/lang/llvm/patches/no-z3.patch b/packages/lang/llvm/patches/no-z3.patch new file mode 100644 index 000000000..fc468ca3b --- /dev/null +++ b/packages/lang/llvm/patches/no-z3.patch @@ -0,0 +1,47 @@ +Description: + Disable z3 to avoid pulling ocaml into main. + For some reason the cmake option LLVM_ENABLE_Z3_SOLVER was not taken into account +Author: Gianfranco Costamagna + +Last-Update: 2019-11-26 + +Index: llvm-toolchain-9-9.0.0/CMakeLists.txt +=================================================================== +--- llvm-toolchain-9-9.0.0.orig/CMakeLists.txt ++++ llvm-toolchain-9-9.0.0/CMakeLists.txt +@@ -340,24 +340,22 @@ + + set(LLVM_Z3_INSTALL_DIR "" CACHE STRING "Install directory of the Z3 solver.") + +-find_package(Z3 4.7.1) +- +-if (LLVM_Z3_INSTALL_DIR) +- if (NOT Z3_FOUND) +- message(FATAL_ERROR "Z3 >= 4.7.1 has not been found in LLVM_Z3_INSTALL_DIR: ${LLVM_Z3_INSTALL_DIR}.") +- endif() +-endif() +- +-set(LLVM_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}") +- + option(LLVM_ENABLE_Z3_SOLVER + "Enable Support for the Z3 constraint solver in LLVM." +- ${LLVM_ENABLE_Z3_SOLVER_DEFAULT} ++ OFF + ) + + if (LLVM_ENABLE_Z3_SOLVER) +- if (NOT Z3_FOUND) +- message(FATAL_ERROR "LLVM_ENABLE_Z3_SOLVER cannot be enabled when Z3 is not available.") ++ find_package(Z3 4.7.1) ++ ++ if (LLVM_Z3_INSTALL_DIR) ++ if (NOT Z3_FOUND) ++ message(FATAL_ERROR "Z3 >= 4.7.1 has not been found in LLVM_Z3_INSTALL_DIR: ${LLVM_Z3_INSTALL_DIR}.") ++ endif() ++ else() ++ if (NOT Z3_FOUND) ++ message(FATAL_ERROR "LLVM_ENABLE_Z3_SOLVER cannot be enabled when Z3 is not available.") ++ endif() + endif() + + set(LLVM_WITH_Z3 1) diff --git a/packages/lang/mono/package.mk b/packages/lang/mono/package.mk new file mode 100644 index 000000000..9bba439ac --- /dev/null +++ b/packages/lang/mono/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mono" +PKG_VERSION="1.0" +PKG_REV="100" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="tools" +PKG_SHORTDESC="Add-on removed" +PKG_LONGDESC="Add-on removed" +PKG_TOOLCHAIN="manual" + +PKG_ADDON_BROKEN="Mono is no longer maintained and has been removed." + +PKG_IS_ADDON="yes" +PKG_ADDON_NAME="Mono" +PKG_ADDON_TYPE="xbmc.broken" + +addon() { + : +} diff --git a/packages/lang/nasm/package.mk b/packages/lang/nasm/package.mk new file mode 100644 index 000000000..c05f32289 --- /dev/null +++ b/packages/lang/nasm/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nasm" +PKG_VERSION="2.15.05" +PKG_SHA256="3caf6729c1073bf96629b57cee31eeb54f4f8129b01902c73428836550b30a3f" +PKG_ARCH="x86_64" +PKG_LICENSE="BSD" +PKG_SITE="https://www.nasm.us/" +PKG_URL="http://www.nasm.us/pub/nasm/releasebuilds/${PKG_VERSION}/nasm-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The Netwide Assembler, NASM, is an 80x86 and x86-64 assembler designed for portability and modularity." diff --git a/packages/lang/ruby/package.mk b/packages/lang/ruby/package.mk new file mode 100644 index 000000000..15908d6b0 --- /dev/null +++ b/packages/lang/ruby/package.mk @@ -0,0 +1,21 @@ +PKG_NAME="ruby" +PKG_VERSION="2.4" +PKG_MINOR="0" +PKG_LICENSE="Ruby or BSD-2-Clause, BSD-3-Clause, others" +PKG_SITE="http://cache.ruby-lang.org/pub/ruby/" +PKG_URL="${PKG_SITE}/${PKG_VERSION}/ruby-${PKG_VERSION}.${PKG_MINOR}.tar.xz" +PKG_DEPENDS_TARGET="toolchain sqlite expat zlib bzip2 openssl libffi ncurses readline" +PKG_LONGDESC="Ruby is an object-oriented programming language." + +PKG_TOOLCHAIN="autotools" +pre_configure_target() { +} + +make_target() { +} + +makeinstall_target() { +} + +post_makeinstall_target() { +} diff --git a/packages/mediacenter/CoreELEC-settings/package.mk b/packages/mediacenter/CoreELEC-settings/package.mk new file mode 100644 index 000000000..1bf071866 --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="CoreELEC-settings" +PKG_VERSION="cc804f81192b866cc13a7e00180e5e863596657c" +PKG_SHA256="fc8c3901ab9908d2c412a515cbeb5b8a2f90977927446b78470aa14937fdc69a" +PKG_LICENSE="GPL" +PKG_SITE="https://coreelec.org" +PKG_URL="https://github.com/CoreELEC/service.coreelec.settings/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python2 connman pygobject dbus-python" +PKG_LONGDESC="CoreELEC-settings: is a settings dialog for CoreELEC" + +PKG_MAKE_OPTS_TARGET="DISTRONAME=$DISTRONAME ROOT_PASSWORD=$ROOT_PASSWORD" + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET setxkbmap" +else + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET bkeymaps" +fi + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/* $INSTALL/usr/lib/coreelec + + ADDON_INSTALL_DIR=$INSTALL/usr/share/kodi/addons/service.coreelec.settings + + $TOOLCHAIN/bin/python -Wi -t -B $TOOLCHAIN/lib/$PKG_PYTHON_VERSION/compileall.py $ADDON_INSTALL_DIR/resources/lib/ -f + rm -rf $(find $ADDON_INSTALL_DIR/resources/lib/ -name "*.py") + + $TOOLCHAIN/bin/python -Wi -t -B $TOOLCHAIN/lib/$PKG_PYTHON_VERSION/compileall.py $ADDON_INSTALL_DIR/oe.py -f + rm -rf $ADDON_INSTALL_DIR/oe.py +} + +post_install() { + enable_service backup-restore.service + enable_service factory-reset.service +} diff --git a/packages/mediacenter/CoreELEC-settings/scripts/backup-restore b/packages/mediacenter/CoreELEC-settings/scripts/backup-restore new file mode 100755 index 000000000..51222edb8 --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/scripts/backup-restore @@ -0,0 +1,63 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +. /usr/lib/coreelec/functions + +# Get NAME, which is DISTRONAME, ie. CoreELEC +. /etc/os-release + +hidecursor + +BACKUP_FILE=`ls -1 /storage/.restore/??????????????.tar 2>/dev/null | tail -1` + +if [ -f "$BACKUP_FILE" ] ; then + echo "RESTORE IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your ${NAME} device!" + echo "" + + StartProgress spinner "Checking backup file... " + tar tf $BACKUP_FILE &>/dev/null + ret=$? + + if [ $ret -eq 0 ] ; then + StopProgress "OK" + + echo + echo "This may take some time to complete, please be patient." + echo + + StartProgress spinner "Restoring... " + rm -rf /storage/.kodi &>/dev/null + rm -rf /storage/.cache &>/dev/null + rm -rf /storage/.config &>/dev/null + tar xf $BACKUP_FILE -C / &>/dev/null + rm -f $BACKUP_FILE &>/dev/null + # Leave a hint that we just did a restore + echo "RESTORE" > /storage/.config/boot.hint + sync + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + else + StopProgress "FAILED" + + echo + echo "Backup file is not valid, or corrupt." + + echo + StartProgress spinner "Removing file to allow normal restart... " + rm -f $BACKUP_FILE &>/dev/null + sync + StopProgress "done" + + echo + StartProgress countdown "Rebooting in 30s... " 30 "NOW" + fi +fi + +sync +reboot -f diff --git a/packages/mediacenter/CoreELEC-settings/scripts/factory-reset b/packages/mediacenter/CoreELEC-settings/scripts/factory-reset new file mode 100755 index 000000000..6a6e12b7d --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/scripts/factory-reset @@ -0,0 +1,88 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +. /usr/lib/coreelec/functions + +# Get NAME, which is DISTRONAME, ie. CoreELEC +. /etc/os-release + +hidecursor + +label= +target= +uuid= + +get_target() { + for arg in $(cat /proc/cmdline); do + case $arg in + disk=*) + disk="${arg#*=}" + case $disk in + LABEL=*) + label="${disk#*=}" + target="$(blkid -L $label)" + ;; + UUID=*) + uuid="${disk#*=}" + target="$(blkid -U $uuid)" + ;; + /*) + target="$disk" + ;; + esac + ;; + esac + done +} + +show_reset_msg() { + echo "RESET IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your ${NAME} device!" + echo "" +} + +if [ -f /storage/.cache/reset_oe ] ; then + # hard reset + rm -f /storage/.cache/reset_oe + get_target + if [ ! -z $target ] ; then + show_reset_msg + + StartProgress spinner "Performing hard reset... " + umount /storage + mke2fs -t ext4 -m 0 $target &>/dev/null + if [ ! -z $label ] ; then + tune2fs -U random -L $label $target &>/dev/null + fi + if [ ! -z $uuid ] ; then + tune2fs -U $uuid $target &>/dev/null + fi + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + fi +elif [ -f /storage/.cache/reset_xbmc ] ; then + # soft reset + rm -f /storage/.cache/reset_xbmc + get_target + if [ ! -z $target ] ; then + show_reset_msg + + StartProgress spinner "Performing soft reset... " + rm -rf /storage/.??* &>/dev/null + # Leave a hint that we just did a soft reset + mkdir -p /storage/.config + echo "RESET-SOFT" > /storage/.config/boot.hint + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + fi +fi + +sync +reboot -f diff --git a/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.service b/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.service new file mode 100644 index 000000000..3e3e1ead1 --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.service @@ -0,0 +1,10 @@ +[Unit] +Description=Restoring Backup +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/coreelec/backup-restore +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.target b/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.target new file mode 100644 index 000000000..8ade350df --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/system.d/backup-restore.target @@ -0,0 +1,5 @@ +[Unit] +Description=Restoring Backup target +Requires=backup-restore.service +After=backup-restore.service +AllowIsolate=yes diff --git a/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.service b/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.service new file mode 100644 index 000000000..02eba7cec --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.service @@ -0,0 +1,10 @@ +[Unit] +Description=Factory reset +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/coreelec/factory-reset +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.target b/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.target new file mode 100644 index 000000000..28c5aa4f2 --- /dev/null +++ b/packages/mediacenter/CoreELEC-settings/system.d/factory-reset.target @@ -0,0 +1,5 @@ +[Unit] +Description=Factory reset target +Requires=factory-reset.service +After=factory-reset.service +AllowIsolate=yes diff --git a/packages/mediacenter/JsonSchemaBuilder/package.mk b/packages/mediacenter/JsonSchemaBuilder/package.mk new file mode 100644 index 000000000..91fefc90e --- /dev/null +++ b/packages/mediacenter/JsonSchemaBuilder/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="JsonSchemaBuilder" +PKG_VERSION="0" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kodi.tv" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_UNPACK="kodi" +PKG_NEED_UNPACK="$(get_pkg_directory $MEDIACENTER)" +PKG_LONGDESC="kodi-platform:" + +PKG_CMAKE_SCRIPT="$(get_build_dir $MEDIACENTER)/tools/depends/native/JsonSchemaBuilder/CMakeLists.txt" + +PKG_CMAKE_OPTS_HOST="-Wno-dev" + +makeinstall_host() { + mkdir -p $TOOLCHAIN/bin + cp JsonSchemaBuilder $TOOLCHAIN/bin +} diff --git a/packages/mediacenter/LibreELEC-settings/package.mk b/packages/mediacenter/LibreELEC-settings/package.mk new file mode 100644 index 000000000..0ca2883b1 --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="LibreELEC-settings" +PKG_VERSION="42acf2613927fa93d9d8ec9aa1d3135d101db0e0" +PKG_SHA256="5f904cde29454902ea4da3980e88d38a1432ef8eb91995436d3d6ffbddfd260c" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="https://github.com/LibreELEC/service.libreelec.settings/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python2 connman pygobject dbus-python" +PKG_LONGDESC="LibreELEC-settings: is a settings dialog for LibreELEC" + +PKG_MAKE_OPTS_TARGET="DISTRONAME=$DISTRONAME ROOT_PASSWORD=$ROOT_PASSWORD" + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET setxkbmap" +else + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET bkeymaps" +fi + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/lib/libreelec + cp $PKG_DIR/scripts/* $INSTALL/usr/lib/libreelec + + ADDON_INSTALL_DIR=$INSTALL/usr/share/kodi/addons/service.libreelec.settings + + $TOOLCHAIN/bin/python -Wi -t -B $TOOLCHAIN/lib/$PKG_PYTHON_VERSION/compileall.py $ADDON_INSTALL_DIR/resources/lib/ -f + rm -rf $(find $ADDON_INSTALL_DIR/resources/lib/ -name "*.py") + + $TOOLCHAIN/bin/python -Wi -t -B $TOOLCHAIN/lib/$PKG_PYTHON_VERSION/compileall.py $ADDON_INSTALL_DIR/oe.py -f + rm -rf $ADDON_INSTALL_DIR/oe.py +} + +post_install() { + enable_service backup-restore.service + enable_service factory-reset.service +} diff --git a/packages/mediacenter/LibreELEC-settings/scripts/backup-restore b/packages/mediacenter/LibreELEC-settings/scripts/backup-restore new file mode 100755 index 000000000..3ed483a5e --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/scripts/backup-restore @@ -0,0 +1,61 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +. /usr/lib/libreelec/functions + +# Get NAME, which is DISTRONAME, ie. LibreELEC +. /etc/os-release + +hidecursor + +BACKUP_FILE=`ls -1 /storage/.restore/??????????????.tar 2>/dev/null | tail -1` + +if [ -f "$BACKUP_FILE" ] ; then + echo "RESTORE IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your ${NAME} device!" + echo "" + + StartProgress spinner "Checking backup file... " + tar tf $BACKUP_FILE &>/dev/null + ret=$? + + if [ $ret -eq 0 ] ; then + StopProgress "OK" + + echo + echo "This may take some time to complete, please be patient." + echo + + StartProgress spinner "Restoring... " + rm -rf /storage/.kodi &>/dev/null + rm -rf /storage/.cache &>/dev/null + rm -rf /storage/.config &>/dev/null + tar xf $BACKUP_FILE -C / &>/dev/null + rm -f $BACKUP_FILE &>/dev/null + sync + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + else + StopProgress "FAILED" + + echo + echo "Backup file is not valid, or corrupt." + + echo + StartProgress spinner "Removing file to allow normal restart... " + rm -f $BACKUP_FILE &>/dev/null + sync + StopProgress "done" + + echo + StartProgress countdown "Rebooting in 30s... " 30 "NOW" + fi +fi + +sync +reboot -f diff --git a/packages/mediacenter/LibreELEC-settings/scripts/factory-reset b/packages/mediacenter/LibreELEC-settings/scripts/factory-reset new file mode 100755 index 000000000..a619f1d48 --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/scripts/factory-reset @@ -0,0 +1,85 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +. /usr/lib/libreelec/functions + +# Get NAME, which is DISTRONAME, ie. LibreELEC +. /etc/os-release + +hidecursor + +label= +target= +uuid= + +get_target() { + for arg in $(cat /proc/cmdline); do + case $arg in + disk=*) + disk="${arg#*=}" + case $disk in + LABEL=*) + label="${disk#*=}" + target="$(blkid -L $label)" + ;; + UUID=*) + uuid="${disk#*=}" + target="$(blkid -U $uuid)" + ;; + /*) + target="$disk" + ;; + esac + ;; + esac + done +} + +show_reset_msg() { + echo "RESET IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your ${NAME} device!" + echo "" +} + +if [ -f /storage/.cache/reset_oe ] ; then + # hard reset + rm -f /storage/.cache/reset_oe + get_target + if [ ! -z $target ] ; then + show_reset_msg + + StartProgress spinner "Performing hard reset... " + umount /storage + mke2fs -t ext4 -m 0 $target &>/dev/null + if [ ! -z $label ] ; then + tune2fs -U random -L $label $target &>/dev/null + fi + if [ ! -z $uuid ] ; then + tune2fs -U $uuid $target &>/dev/null + fi + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + fi +elif [ -f /storage/.cache/reset_xbmc ] ; then + # soft reset + rm -f /storage/.cache/reset_xbmc + get_target + if [ ! -z $target ] ; then + show_reset_msg + + StartProgress spinner "Performing soft reset... " + rm -rf /storage/.??* &>/dev/null + StopProgress "done!" + + echo + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + fi +fi + +sync +reboot -f diff --git a/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.service b/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.service new file mode 100644 index 000000000..25f06e858 --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.service @@ -0,0 +1,10 @@ +[Unit] +Description=Restoring Backup +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/libreelec/backup-restore +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.target b/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.target new file mode 100644 index 000000000..8ade350df --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/system.d/backup-restore.target @@ -0,0 +1,5 @@ +[Unit] +Description=Restoring Backup target +Requires=backup-restore.service +After=backup-restore.service +AllowIsolate=yes diff --git a/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.service b/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.service new file mode 100644 index 000000000..5b25d73d0 --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.service @@ -0,0 +1,10 @@ +[Unit] +Description=Factory reset +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/libreelec/factory-reset +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.target b/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.target new file mode 100644 index 000000000..28c5aa4f2 --- /dev/null +++ b/packages/mediacenter/LibreELEC-settings/system.d/factory-reset.target @@ -0,0 +1,5 @@ +[Unit] +Description=Factory reset target +Requires=factory-reset.service +After=factory-reset.service +AllowIsolate=yes diff --git a/packages/mediacenter/TexturePacker/package.mk b/packages/mediacenter/TexturePacker/package.mk new file mode 100644 index 000000000..ed8ee075b --- /dev/null +++ b/packages/mediacenter/TexturePacker/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="TexturePacker" +PKG_VERSION="0" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kodi.tv" +PKG_DEPENDS_HOST="lzo:host libpng:host libjpeg-turbo:host giflib:host" +PKG_DEPENDS_UNPACK="kodi" +PKG_NEED_UNPACK="$(get_pkg_directory $MEDIACENTER)" +PKG_LONGDESC="kodi-platform:" + +PKG_CMAKE_SCRIPT="$(get_build_dir $MEDIACENTER)/tools/depends/native/TexturePacker/CMakeLists.txt" + +PKG_CMAKE_OPTS_HOST="-Wno-dev" + +pre_configure_host() { + export CXXFLAGS="$CXXFLAGS -std=c++11 -DTARGET_POSIX -DTARGET_LINUX -D_LINUX -I$(get_build_dir $MEDIACENTER)/xbmc/platform/linux" +} + +makeinstall_host() { + mkdir -p $TOOLCHAIN/bin + cp TexturePacker $TOOLCHAIN/bin +} diff --git a/packages/mediacenter/p8-platform/package.mk b/packages/mediacenter/p8-platform/package.mk new file mode 100644 index 000000000..388a27526 --- /dev/null +++ b/packages/mediacenter/p8-platform/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="p8-platform" +PKG_VERSION="1eb12b1b1efa6747c1e190964854e9e267e3a1e2" +PKG_SHA256="94dba139066a332d048486f817736e4cf4962393c9f892d2c7dd40d9d69ca788" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kodi.tv" +PKG_URL="https://github.com/Pulse-Eight/platform/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Platform support library used by libCEC and binary add-ons for Kodi" + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_INSTALL_LIBDIR:STRING=lib \ + -DCMAKE_INSTALL_LIBDIR_NOARCH:STRING=lib \ + -DCMAKE_INSTALL_PREFIX_TOOLCHAIN=$SYSROOT_PREFIX/usr \ + -DBUILD_SHARED_LIBS=0" + +post_makeinstall_target() { + rm -rf $INSTALL/usr +} diff --git a/packages/mediacenter/p8-platform/patches/p8-platform-01-revert-cc-badness.patch b/packages/mediacenter/p8-platform/patches/p8-platform-01-revert-cc-badness.patch new file mode 100644 index 000000000..c060921a3 --- /dev/null +++ b/packages/mediacenter/p8-platform/patches/p8-platform-01-revert-cc-badness.patch @@ -0,0 +1,28 @@ +From f91594676d1f75530addd87363ccbc6510efb84e Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 8 May 2015 11:19:42 +0300 +Subject: [PATCH] revert cc badness + +this reverts upstream commit 68f8418 +--- + CMakeLists.txt | 6 ------ + 1 file changed, 6 deletions(-) + +diff -Naur a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2016-01-05 23:58:40.000000000 +0100 ++++ b/CMakeLists.txt 2016-01-06 01:26:52.004076744 +0100 +@@ -22,12 +22,6 @@ + src/windows/os-threads.cpp) + endif() + +-set(p8-platform_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/p8-platform") +-IF(WIN32) +- LIST(APPEND p8-platform_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include/p8-platform/windows") +-ENDIF(WIN32) +-set(p8-platform_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) +- + if(NOT ${CORE_SYSTEM_NAME} STREQUAL "") + if(${CORE_SYSTEM_NAME} STREQUAL "osx" OR ${CORE_SYSTEM_NAME} STREQUAL "ios") + list(APPEND p8-platform_LIBRARIES "-framework CoreVideo -framework IOKit") +-- +1.7.10.4 diff --git a/packages/mediacenter/p8-platform/patches/p8-platform-02-cmake_install_prefix_toolchain.patch b/packages/mediacenter/p8-platform/patches/p8-platform-02-cmake_install_prefix_toolchain.patch new file mode 100644 index 000000000..8602c3101 --- /dev/null +++ b/packages/mediacenter/p8-platform/patches/p8-platform-02-cmake_install_prefix_toolchain.patch @@ -0,0 +1,32 @@ +diff --git a/p8-platform-config.cmake.in b/p8-platform-config.cmake.in +index f59418d..df7ed21 100644 +--- a/p8-platform-config.cmake.in ++++ b/p8-platform-config.cmake.in +@@ -10,7 +10,7 @@ + # + # propagate these properties from one build system to the other + set (p8-platform_VERSION "@p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@") +-find_path (p8-platform_INCLUDE_DIRS p8-platform/os.h) ++set (p8-platform_INCLUDE_DIRS @p8-platform_INCLUDE_DIRS@ @CMAKE_INSTALL_PREFIX_TOOLCHAIN@/include/p8-platform) + set (p8-platform_LIBRARY_DIRS "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@") + set (p8-platform_LINKER_FLAGS "@p8-platform_LINKER_FLAGS@") + set (p8-platform_CONFIG_VARS "@p8-platform_CONFIG_VARS@") +@@ -19,7 +19,7 @@ set (p8-platform_CONFIG_VARS "@p8-platform_CONFIG_VARS@") + if(WIN32) + set (p8-platform_LIBRARY "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/p8-platform.lib") + else(WIN32) +- find_library (p8-platform_LIBRARY p8-platform) ++ set (p8-platform_LIBRARY "-L@CMAKE_INSTALL_PREFIX_TOOLCHAIN@/@CMAKE_INSTALL_LIBDIR@ -lp8-platform") + endif(WIN32) + set (p8-platform_LIBRARIES ${p8-platform_LIBRARY} "@p8-platform_LIBRARIES@") + mark_as_advanced (p8-platform_LIBRARY) +diff --git a/p8-platform.pc.in b/p8-platform.pc.in +index f97a2d4..58cd057 100644 +--- a/p8-platform.pc.in ++++ b/p8-platform.pc.in +@@ -7,4 +7,4 @@ Name: @p8-platform_NAME@ + Description: @p8-platform_DESCRIPTION@ @p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@ + Version: @p8-platform_VERSION_MAJOR@.@p8-platform_VERSION_MINOR@.@p8-platform_VERSION_PATCH@ + Libs: -L${libdir} -lp8-platform +-Cflags: -I${includedir} ++Cflags: -I${includedir}/p8-platform diff --git a/packages/multimedia/aom/package.mk b/packages/multimedia/aom/package.mk new file mode 100644 index 000000000..64df532a3 --- /dev/null +++ b/packages/multimedia/aom/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="aom" +PKG_VERSION="990da97d18a80dcdb0cb291ffb91e284e2e25320" +PKG_SHA256="830cc4b00a5fb747144218f1a6bf48c4ddff49670d95acda61313502520c236b" +PKG_LICENSE="BSD" +PKG_SITE="https://www.webmproject.org" +PKG_URL="http://repo.or.cz/aom.git/snapshot/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="AV1 Codec Library" + +PKG_CMAKE_OPTS_TARGET="-DENABLE_CCACHE=1 \ + -DENABLE_DOCS=0 \ + -DENABLE_EXAMPLES=0 \ + -DENABLE_TESTS=0 \ + -DENABLE_TOOLS=0" + +if [ "$TARGET_ARCH" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +if ! target_has_feature neon; then + PKG_CMAKE_OPTS_TARGET+=" -DENABLE_NEON=0 -DENABLE_NEON_ASM=0" +fi diff --git a/packages/multimedia/dav1d/package.mk b/packages/multimedia/dav1d/package.mk new file mode 100644 index 000000000..f8c74b88f --- /dev/null +++ b/packages/multimedia/dav1d/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dav1d" +PKG_VERSION="0.8.1" +#PKG_SHA256="" +PKG_LICENSE="BSD" +PKG_SITE="http://www.jbkempf.com/blog/post/2018/Introducing-dav1d" +PKG_URL="https://code.videolan.org/videolan/dav1d/-/archive/${PKG_VERSION}/dav1d-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="dav1d is an AV1 decoder :)" + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +PKG_MESON_OPTS_TARGET="-Denable_tools=false \ + -Denable_tests=false" diff --git a/packages/multimedia/ffmpeg/package.mk b/packages/multimedia/ffmpeg/package.mk new file mode 100644 index 000000000..4b93a2c96 --- /dev/null +++ b/packages/multimedia/ffmpeg/package.mk @@ -0,0 +1,213 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ffmpeg" +PKG_VERSION="4.3.1-Matrix-Beta1" +PKG_SHA256="0b209a9b15f2335e516bf2ad1249fffc6b55425145f17c9674dc430abf6a67ad" +PKG_LICENSE="LGPLv2.1+" +PKG_SITE="https://ffmpeg.org" +PKG_URL="https://github.com/xbmc/FFmpeg/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib bzip2 gnutls speex x264" +PKG_LONGDESC="FFmpeg is a complete, cross-platform solution to record, convert and stream audio and video." +PKG_BUILD_FLAGS="-gold" + +# Dependencies +get_graphicdrivers + +PKG_FFMPEG_HWACCEL="--enable-hwaccels" + +PKG_FFMPEG_RPI="--disable-mmal" + +if [ "${PROJECT}" = "RPi" ]; then + PKG_PATCH_DIRS="rpi" + PKG_FFMPEG_RPI+=" --disable-rpi --enable-sand" +else + PKG_PATCH_DIRS="v4l2-request v4l2-drmprime" +fi + +PKG_PATCH_DIRS+=" libreelec" + +if [ "${V4L2_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libdrm" + PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm)" + PKG_FFMPEG_V4L2="--enable-v4l2_m2m --enable-libdrm" + + if [ "${PROJECT}" = "Allwinner" -o "${PROJECT}" = "Rockchip" -o "${DEVICE}" = "iMX8" ]; then + PKG_V4L2_REQUEST="yes" + elif [ "${PROJECT}" = "RPi" -a "${DEVICE}" = "RPi4" ]; then + PKG_V4L2_REQUEST="yes" + PKG_FFMPEG_HWACCEL="--disable-hwaccel=h264_v4l2request \ + --disable-hwaccel=mpeg2_v4l2request \ + --disable-hwaccel=vp8_v4l2request \ + --disable-hwaccel=vp9_v4l2request" + else + PKG_V4L2_REQUEST="no" + fi + + if [ "${PKG_V4L2_REQUEST}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" systemd" + PKG_NEED_UNPACK+=" $(get_pkg_directory systemd)" + PKG_FFMPEG_V4L2+=" --enable-libudev --enable-v4l2-request" + else + PKG_FFMPEG_V4L2+=" --disable-libudev --disable-v4l2-request" + fi +else + PKG_FFMPEG_V4L2="--disable-v4l2_m2m --disable-libudev --disable-v4l2-request" +fi + +if [ "${VAAPI_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libva" + PKG_NEED_UNPACK+=" $(get_pkg_directory libva)" + PKG_FFMPEG_VAAPI="--enable-vaapi" +else + PKG_FFMPEG_VAAPI="--disable-vaapi" +fi + +if [ "${VDPAU_SUPPORT}" = "yes" -a "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" libvdpau" + PKG_NEED_UNPACK+=" $(get_pkg_directory libvdpau)" + PKG_FFMPEG_VDPAU="--enable-vdpau" +else + PKG_FFMPEG_VDPAU="--disable-vdpau" +fi + +if build_with_debug; then + PKG_FFMPEG_DEBUG="--enable-debug --disable-stripping" +else + PKG_FFMPEG_DEBUG="--disable-debug --enable-stripping" +fi + +if target_has_feature neon; then + PKG_FFMPEG_FPU="--enable-neon" +else + PKG_FFMPEG_FPU="--disable-neon" +fi + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +if target_has_feature "(neon|sse)"; then + PKG_DEPENDS_TARGET+=" dav1d" + PKG_NEED_UNPACK+=" $(get_pkg_directory dav1d)" + PKG_FFMPEG_AV1="--enable-libdav1d" +else + PKG_FFMPEG_AV1="--disable-libdav1d" +fi + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} +} + +configure_target() { + ./configure --prefix="/usr" \ + --cpu="${TARGET_CPU}" \ + --arch="${TARGET_ARCH}" \ + --enable-cross-compile \ + --cross-prefix="${TARGET_PREFIX}" \ + --sysroot="${SYSROOT_PREFIX}" \ + --sysinclude="${SYSROOT_PREFIX}/usr/include" \ + --target-os="linux" \ + --nm="${NM}" \ + --ar="${AR}" \ + --as="${CC}" \ + --cc="${CC}" \ + --ld="${CC}" \ + --host-cc="${HOST_CC}" \ + --host-cflags="${HOST_CFLAGS}" \ + --host-ldflags="${HOST_LDFLAGS}" \ + --extra-cflags="${CFLAGS}" \ + --extra-ldflags="${LDFLAGS}" \ + --extra-libs="${PKG_FFMPEG_LIBS}" \ + --disable-static \ + --enable-shared \ + --enable-gpl \ + --disable-version3 \ + --enable-logging \ + --disable-doc \ + ${PKG_FFMPEG_DEBUG} \ + --enable-pic \ + --pkg-config="${TOOLCHAIN}/bin/pkg-config" \ + --enable-optimizations \ + --disable-extra-warnings \ + --disable-programs \ + --enable-avdevice \ + --enable-avcodec \ + --enable-avformat \ + --enable-swscale \ + --enable-postproc \ + --enable-avfilter \ + --disable-devices \ + --enable-pthreads \ + --enable-network \ + --enable-gnutls --disable-openssl \ + --disable-gray \ + --enable-swscale-alpha \ + --disable-small \ + --enable-dct \ + --enable-fft \ + --enable-mdct \ + --enable-rdft \ + --disable-crystalhd \ + ${PKG_FFMPEG_V4L2} \ + ${PKG_FFMPEG_VAAPI} \ + ${PKG_FFMPEG_VDPAU} \ + ${PKG_FFMPEG_RPI} \ + --enable-runtime-cpudetect \ + --disable-hardcoded-tables \ + --disable-encoders \ + --enable-encoder=ac3 \ + --enable-encoder=aac \ + --enable-encoder=wmav2 \ + --enable-encoder=mjpeg \ + --enable-encoder=png \ + ${PKG_FFMPEG_HWACCEL} \ + --disable-muxers \ + --enable-muxer=spdif \ + --enable-muxer=adts \ + --enable-muxer=asf \ + --enable-muxer=ipod \ + --enable-muxer=mpegts \ + --enable-demuxers \ + --enable-parsers \ + --enable-bsfs \ + --enable-protocol=http \ + --disable-indevs \ + --disable-outdevs \ + --enable-filters \ + --disable-avisynth \ + --enable-bzlib \ + --disable-lzma \ + --disable-alsa \ + --disable-frei0r \ + --disable-libopencore-amrnb \ + --disable-libopencore-amrwb \ + --disable-libopencv \ + --disable-libdc1394 \ + --disable-libfreetype \ + --disable-libgsm \ + --disable-libmp3lame \ + --disable-libopenjpeg \ + --disable-librtmp \ + ${PKG_FFMPEG_AV1} \ + --enable-libspeex \ + --disable-libtheora \ + --disable-libvo-amrwbenc \ + --disable-libvorbis \ + --disable-libvpx \ + --enable-libx264 \ + --disable-libxavs \ + --disable-libxvid \ + --enable-zlib \ + --enable-asm \ + --enable-ffplay \ + --disable-altivec \ + ${PKG_FFMPEG_FPU} \ + --disable-symver +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share/ffmpeg/examples +} diff --git a/packages/multimedia/ffmpeg/patches/libreelec/ffmpeg-001-libreelec.patch b/packages/multimedia/ffmpeg/patches/libreelec/ffmpeg-001-libreelec.patch new file mode 100644 index 000000000..9db1e9564 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/libreelec/ffmpeg-001-libreelec.patch @@ -0,0 +1,73 @@ +From 823b70bfa0f451a0f8cd0539e1707f7bb7ff5891 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Wed, 10 Apr 2019 13:39:21 -0700 +Subject: [PATCH 1/2] libavcodec/libdav1d: add libdav1d_get_format method to + call ff_get_format + +This will allow applications to properly init the decoder in +cases where a hardware decoder is tried first and and software +decoder is tried after by calling the get_format callback. + +Even though there is no hardware pixel formats available +we still need to return the software pixel format. + +Tested with Kodi by checking if multithreaded software +decoding is properly activated. +--- + libavcodec/libdav1d.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c +index bbb3ec1e6c..d8a7555c29 100644 +--- a/libavcodec/libdav1d.c ++++ b/libavcodec/libdav1d.c +@@ -55,6 +55,16 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = { + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, + }; + ++static enum AVPixelFormat libdav1d_get_format(AVCodecContext *avctx, const Dav1dPicture *p) ++{ ++ enum AVPixelFormat pix_fmts[2], *fmt = pix_fmts; ++ ++ *fmt++ = pix_fmt[p->p.layout][p->seq_hdr->hbd]; ++ *fmt = AV_PIX_FMT_NONE; ++ ++ return ff_get_format(avctx, pix_fmts); ++} ++ + static void libdav1d_log_callback(void *opaque, const char *fmt, va_list vl) + { + AVCodecContext *c = opaque; +@@ -259,6 +269,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) + c->profile = p->seq_hdr->profile; + c->level = ((p->seq_hdr->operating_points[0].major_level - 2) << 2) + | p->seq_hdr->operating_points[0].minor_level; ++ frame->format = c->pix_fmt = libdav1d_get_format(c, p); + frame->width = p->p.w; + frame->height = p->p.h; + if (c->width != p->p.w || c->height != p->p.h) { + +From 1485078472d107806d1d3f52f89e3ff47ae8715c Mon Sep 17 00:00:00 2001 +From: chewitt +Date: Sun, 11 Aug 2019 07:08:19 +0000 +Subject: [PATCH 2/2] add long-term yuv2rgb logging patch + +--- + libswscale/yuv2rgb.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c +index 588462504e..20364ff318 100644 +--- a/libswscale/yuv2rgb.c ++++ b/libswscale/yuv2rgb.c +@@ -688,10 +688,6 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c) + if (t) + return t; + +- av_log(c, AV_LOG_WARNING, +- "No accelerated colorspace conversion found from %s to %s.\n", +- av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat)); +- + switch (c->dstFormat) { + case AV_PIX_FMT_BGR48BE: + case AV_PIX_FMT_BGR48LE: diff --git a/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch new file mode 100644 index 000000000..2497998e5 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch @@ -0,0 +1,58558 @@ +diff --git a/.gitignore b/.gitignore +index 2450ee8fc5..4bcc3ae643 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,6 +1,7 @@ + *.a + *.o + *.o.* ++*.bin + *.d + *.def + *.dll +@@ -26,6 +27,7 @@ + .\#* + /.config + /.version ++/build/ + /ffmpeg + /ffplay + /ffprobe +diff --git a/BUILD.txt b/BUILD.txt +new file mode 100644 +index 0000000000..49ed1f119d +--- /dev/null ++++ b/BUILD.txt +@@ -0,0 +1,55 @@ ++# Setup & Build instructions for testing Argon30 mesa support (on Pi4) ++ ++# These assume that the drm_mmal test for Sand8 has been built on this Pi ++# as build relies on many of the same files ++ ++# 1st get everything required to build ffmpeg ++# If sources aren't already enabled on your Pi then enable them ++sudo su ++sed "s/#deb-src/deb-src/" /etc/apt/sources.list > /tmp/sources.list ++sed "s/#deb-src/deb-src/" /etc/apt/sources.list.d/raspi.list > /tmp/raspi.list ++mv /tmp/sources.list /etc/apt/ ++mv /tmp/raspi.list /etc/apt/sources.list.d/ ++apt update ++ ++# Get dependancies ++sudo apt build-dep ffmpeg ++ ++# Enable H265 V4L2 request decoder ++sudo su ++echo dtoverlay=rpivid-v4l2 >> /boot/config.txt ++reboot ++# Check it has turned up ++ls -la /dev/video* ++# This should include video19 ++# crw-rw----+ 1 root video 81, 7 Aug 4 17:25 /dev/video19 ++ ++# Config ++pi-util/conf_native.sh ++ ++# Build (this is a bit dull) ++# If you want to poke the source the libavdevice/egl_vout.c contains the ++# output code - ++make -j6 ++ ++# Grab test streams ++wget http://www.jell.yfish.us/media/jellyfish-3-mbps-hd-h264.mkv ++wget http://www.jell.yfish.us/media/jellyfish-3-mbps-hd-hevc.mkv ++wget http://www.jell.yfish.us/media/jellyfish-3-mbps-hd-hevc-10bit.mkv ++ ++# Test i420 output (works currently) ++./ffmpeg -no_cvt_hw -vcodec h264_v4l2m2m -i jellyfish-3-mbps-hd-h264.mkv -f vout_egl - ++ ++# Test Sand8 output - doesn't currently work but should once you have ++# Sand8 working in drm_mmal. I can't guarantee that this will work as ++# I can't test this path with a known working format, but the debug looks ++# good. If this doesn't work & drm_mmal does with sand8 then come back to me ++./ffmpeg -no_cvt_hw -hwaccel drm -vcodec hevc -i jellyfish-3-mbps-hd-hevc.mkv -f vout_egl - ++ ++# Test Sand30 - doesn't currently work ++# (Beware that when FFmpeg errors out it often leaves your teminal window ++# in a state where you need to reset it) ++./ffmpeg -no_cvt_hw -hwaccel drm -vcodec hevc -i jellyfish-3-mbps-hd-hevc-10bit.mkv -f vout_egl - ++ ++ ++ +diff --git a/configure b/configure +index 8569a60bf8..277d36cf9a 100755 +--- a/configure ++++ b/configure +@@ -274,6 +274,7 @@ External library support: + --enable-libtls enable LibreSSL (via libtls), needed for https support + if openssl, gnutls or mbedtls is not used [no] + --enable-libtwolame enable MP2 encoding via libtwolame [no] ++ --enable-libudev enable libudev [no] + --enable-libv4l2 enable libv4l2/v4l-utils [no] + --enable-libvidstab enable video stabilization using vid.stab [no] + --enable-libvmaf enable vmaf filter via libvmaf [no] +@@ -336,12 +337,17 @@ External library support: + --enable-libmfx enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no] + --enable-libnpp enable Nvidia Performance Primitives-based code [no] + --enable-mmal enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no] ++ --enable-rpi enable other rpi specific stuff [no] ++ --enable-sand enable sand video formats [rpi] ++ --enable-vout-drm enable the vout_drm module - for internal testing only [no] ++ --enable-vout-egl enable the vout_egl module - for internal testing only [no] + --disable-nvdec disable Nvidia video decoding acceleration (via hwaccel) [autodetect] + --disable-nvenc disable Nvidia video encoding code [autodetect] + --enable-omx enable OpenMAX IL code [no] + --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] + --enable-rkmpp enable Rockchip Media Process Platform code [no] + --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect] ++ --enable-v4l2-request enable V4L2 request API code [no] + --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] + --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] + --disable-videotoolbox disable VideoToolbox code [autodetect] +@@ -1771,6 +1777,7 @@ EXTERNAL_LIBRARY_LIST=" + libdav1d + libdc1394 + libdrm ++ epoxy + libflite + libfontconfig + libfreetype +@@ -1807,6 +1814,7 @@ EXTERNAL_LIBRARY_LIST=" + libtesseract + libtheora + libtwolame ++ libudev + libv4l2 + libvorbis + libvpx +@@ -1861,7 +1869,10 @@ HWACCEL_LIBRARY_LIST=" + mmal + omx + opencl ++ v4l2_request + vulkan ++ rpi4_8 ++ rpi4_10 + " + + DOCUMENT_LIST=" +@@ -1877,12 +1888,16 @@ FEATURE_LIST=" + gray + hardcoded_tables + omx_rpi ++ rpi + runtime_cpudetect + safe_bitstream_reader ++ sand + shared + small + static + swscale_alpha ++ vout_drm ++ vout_egl + " + + # this list should be kept in linking order +@@ -1923,6 +1938,7 @@ SUBSYSTEM_LIST=" + pixelutils + network + rdft ++ rpi + " + + # COMPONENT_LIST needs to come last to ensure correct dependency checking +@@ -2405,9 +2421,11 @@ CONFIG_EXTRA=" + rangecoder + riffdec + riffenc ++ rpi + rtpdec + rtpenc_chain + rv34dsp ++ sand + scene_sad + sinewin + snappy +@@ -2737,6 +2755,8 @@ hap_decoder_select="snappy texturedsp" + hap_encoder_deps="libsnappy" + hap_encoder_select="texturedspenc" + hevc_decoder_select="bswapdsp cabac golomb hevcparse videodsp" ++hevc_rpi_decoder_deps="rpi" ++hevc_rpi_decoder_select="hevc_decoder sand" + huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" + huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" + hymt_decoder_select="huffyuv_decoder" +@@ -2903,6 +2923,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" + dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + nvdec_deps="ffnvcodec" ++v4l2_request_deps="linux_videodev2_h linux_media_h v4l2_timeval_to_ns libdrm libudev" + vaapi_x11_deps="xlib" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -2920,6 +2941,8 @@ h264_dxva2_hwaccel_deps="dxva2" + h264_dxva2_hwaccel_select="h264_decoder" + h264_nvdec_hwaccel_deps="nvdec" + h264_nvdec_hwaccel_select="h264_decoder" ++h264_v4l2request_hwaccel_deps="v4l2_request" ++h264_v4l2request_hwaccel_select="h264_decoder" + h264_vaapi_hwaccel_deps="vaapi" + h264_vaapi_hwaccel_select="h264_decoder" + h264_vdpau_hwaccel_deps="vdpau" +@@ -2934,6 +2957,12 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" + hevc_dxva2_hwaccel_select="hevc_decoder" + hevc_nvdec_hwaccel_deps="nvdec" + hevc_nvdec_hwaccel_select="hevc_decoder" ++hevc_v4l2request_hwaccel_deps="v4l2_request" ++hevc_v4l2request_hwaccel_select="hevc_decoder" ++hevc_rpi4_10_hwaccel_deps="rpi" ++hevc_rpi4_10_hwaccel_select="hevc_decoder" ++hevc_rpi4_8_hwaccel_deps="rpi" ++hevc_rpi4_8_hwaccel_select="hevc_decoder" + hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" + hevc_vaapi_hwaccel_select="hevc_decoder" + hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" +@@ -2962,6 +2991,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2" + mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" + mpeg2_nvdec_hwaccel_deps="nvdec" + mpeg2_nvdec_hwaccel_select="mpeg2video_decoder" ++mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request" ++mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder" + mpeg2_vaapi_hwaccel_deps="vaapi" + mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" + mpeg2_vdpau_hwaccel_deps="vdpau" +@@ -2992,6 +3023,8 @@ vc1_vdpau_hwaccel_deps="vdpau" + vc1_vdpau_hwaccel_select="vc1_decoder" + vp8_nvdec_hwaccel_deps="nvdec" + vp8_nvdec_hwaccel_select="vp8_decoder" ++vp8_v4l2request_hwaccel_deps="v4l2_request" ++vp8_v4l2request_hwaccel_select="vp8_decoder" + vp8_vaapi_hwaccel_deps="vaapi" + vp8_vaapi_hwaccel_select="vp8_decoder" + vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" +@@ -3002,6 +3035,8 @@ vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" + vp9_dxva2_hwaccel_select="vp9_decoder" + vp9_nvdec_hwaccel_deps="nvdec" + vp9_nvdec_hwaccel_select="vp9_decoder" ++vp9_v4l2request_hwaccel_deps="v4l2_request" ++vp9_v4l2request_hwaccel_select="vp9_decoder" + vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" + vp9_vaapi_hwaccel_select="vp9_decoder" + vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9" +@@ -3401,8 +3436,14 @@ sndio_indev_deps="sndio" + sndio_outdev_deps="sndio" + v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" + v4l2_indev_suggest="libv4l2" ++v4l2_outdev_deps="libdrm" + v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h" + v4l2_outdev_suggest="libv4l2" ++vout_drm_outdev_deps="libdrm vout_drm" ++vout_egl_outdev_deps="vout_egl" ++vout_egl_outdev_select="epoxy" ++vout_rpi_outdev_deps="rpi" ++vout_rpi_outdev_select="sand" + vfwcap_indev_deps="vfw32 vfwcap_defines" + xcbgrab_indev_deps="libxcb" + xcbgrab_indev_suggest="libxcb_shm libxcb_shape libxcb_xfixes" +@@ -3618,6 +3659,8 @@ tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" + tonemap_opencl_filter_deps="opencl const_nan" + transpose_opencl_filter_deps="opencl" + transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" ++unsand_filter_deps="rpi" ++unsand_filter_select="sand" + unsharp_opencl_filter_deps="opencl" + uspp_filter_deps="gpl avcodec" + vaguedenoiser_filter_deps="gpl" +@@ -6299,6 +6342,7 @@ enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.4.0" "dav1d + enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open + enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new + enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion ++enabled epoxy && require_pkg_config epoxy epoxy epoxy/egl.h epoxy_egl_version + enabled libfdk_aac && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen || + { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac && + warn "using libfdk without pkg-config"; } } +@@ -6376,6 +6420,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur + enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && + { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || + die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } ++enabled libudev && require_pkg_config libudev libudev libudev.h udev_new + enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl + enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit + enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf +@@ -6430,11 +6475,12 @@ enabled mbedtls && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt + check_lib mbedtls mbedtls/ssl.h mbedtls_ssl_init -lmbedtls -lmbedx509 -lmbedcrypto || + die "ERROR: mbedTLS not found"; } + enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; } +-enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host || ++( enabled rpi || ++ enabled mmal ) && { check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host || + { ! enabled cross_compile && + add_cflags -isystem/opt/vc/include/ -isystem/opt/vc/include/interface/vmcs_host/linux -isystem/opt/vc/include/interface/vcos/pthreads -fgnu89-inline && + add_ldflags -L/opt/vc/lib/ && +- check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } || ++ check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host -lvcos -lvcsm -lvchostif -lvchiq_arm; } || + die "ERROR: mmal not found" && + check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; } + enabled openal && { { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do +@@ -6475,6 +6521,10 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/r + { enabled libdrm || + die "ERROR: rkmpp requires --enable-libdrm"; } + } ++enabled v4l2_request && { enabled libdrm || ++ die "ERROR: v4l2-request requires --enable-libdrm"; } && ++ { enabled libudev || ++ die "ERROR: v4l2-request requires --enable-libudev"; } + enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init + + +@@ -6556,6 +6606,13 @@ if enabled v4l2_m2m; then + check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" + fi + ++check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;" ++check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;" ++check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" ++check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;" ++check_cc vp9_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP9_FRAME;" ++ + check_headers sys/videoio.h + test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete + +diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c +index 2e9448ea2b..faa8501dd0 100644 +--- a/fftools/ffmpeg.c ++++ b/fftools/ffmpeg.c +@@ -2118,8 +2118,8 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) + ifilter->channel_layout != frame->channel_layout; + break; + case AVMEDIA_TYPE_VIDEO: +- need_reinit |= ifilter->width != frame->width || +- ifilter->height != frame->height; ++ need_reinit |= ifilter->width != av_frame_cropped_width(frame) || ++ ifilter->height != av_frame_cropped_height(frame); + break; + } + +@@ -2367,6 +2367,8 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ + if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { + ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames; + } else ++ { ++#if 0 + av_log(ist->dec_ctx, AV_LOG_WARNING, + "video_delay is larger in decoder than demuxer %d > %d.\n" + "If you want to help, upload a sample " +@@ -2374,6 +2376,8 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n", + ist->dec_ctx->has_b_frames, + ist->st->codecpar->video_delay); ++#endif ++ } + } + + if (ret != AVERROR_EOF) +@@ -2400,8 +2404,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ + decoded_frame->top_field_first = ist->top_field_first; + + ist->frames_decoded++; +- +- if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { ++ if (!no_cvt_hw && ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { + err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame); + if (err < 0) + goto fail; +@@ -2913,6 +2916,15 @@ static int init_input_stream(int ist_index, char *error, int error_len) + return ret; + } + ++#if CONFIG_HEVC_RPI_DECODER ++ ret = -1; ++ if (strcmp(codec->name, "hevc_rpi") == 0 && ++ (ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { ++ ist->dec = codec = avcodec_find_decoder_by_name("hevc"); ++ av_log(NULL, AV_LOG_INFO, "Failed to open hevc_rpi - trying hevc\n"); ++ } ++ if (ret < 0) ++#endif + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 0); +diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h +index 828cb2a4ff..55d4db293e 100644 +--- a/fftools/ffmpeg.h ++++ b/fftools/ffmpeg.h +@@ -61,6 +61,7 @@ enum HWAccelID { + HWACCEL_GENERIC, + HWACCEL_VIDEOTOOLBOX, + HWACCEL_QSV, ++ HWACCEL_RPI, + }; + + typedef struct HWAccel { +@@ -590,6 +591,7 @@ extern int video_sync_method; + extern float frame_drop_threshold; + extern int do_benchmark; + extern int do_benchmark_all; ++extern int no_cvt_hw; + extern int do_deinterlace; + extern int do_hex_dump; + extern int do_pkt_dump; +@@ -653,6 +655,7 @@ int ffmpeg_parse_options(int argc, char **argv); + + int videotoolbox_init(AVCodecContext *s); + int qsv_init(AVCodecContext *s); ++int rpi_init(AVCodecContext *s); + + HWDevice *hw_device_get_by_name(const char *name); + int hw_device_init_from_string(const char *arg, HWDevice **dev); +diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c +index 422e1268e9..deb89c076d 100644 +--- a/fftools/ffmpeg_filter.c ++++ b/fftools/ffmpeg_filter.c +@@ -1186,8 +1186,8 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) + + ifilter->format = frame->format; + +- ifilter->width = frame->width; +- ifilter->height = frame->height; ++ ifilter->width = av_frame_cropped_width(frame); ++ ifilter->height = av_frame_cropped_height(frame); + ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; + + ifilter->sample_rate = frame->sample_rate; +diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c +index 2eb4e1c973..98207be2e2 100644 +--- a/fftools/ffmpeg_opt.c ++++ b/fftools/ffmpeg_opt.c +@@ -130,12 +130,22 @@ static const char *opt_name_enc_time_bases[] = {"enc_time_base", NULL + }\ + } + ++#if CONFIG_RPI ++int rpi_init(AVCodecContext *avctx) { ++ return 0; ++} ++#endif ++ + const HWAccel hwaccels[] = { + #if CONFIG_VIDEOTOOLBOX + { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, + #endif + #if CONFIG_LIBMFX + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, ++#endif ++#if CONFIG_RPI ++ { "rpi", rpi_init, HWACCEL_RPI, AV_PIX_FMT_RPI4_8 }, ++ { "rpi", rpi_init, HWACCEL_RPI, AV_PIX_FMT_RPI4_10 }, + #endif + { 0 }, + }; +@@ -155,6 +165,7 @@ float frame_drop_threshold = 0; + int do_deinterlace = 0; + int do_benchmark = 0; + int do_benchmark_all = 0; ++int no_cvt_hw = 0; + int do_hex_dump = 0; + int do_pkt_dump = 0; + int copy_ts = 0; +@@ -755,7 +766,9 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream * + st->codecpar->codec_id = codec->id; + return codec; + } else ++ { + return avcodec_find_decoder(st->codecpar->codec_id); ++ } + } + + /* Add all the streams from the given input file to the global +@@ -3460,6 +3473,8 @@ const OptionDef options[] = { + "add timings for benchmarking" }, + { "benchmark_all", OPT_BOOL | OPT_EXPERT, { &do_benchmark_all }, + "add timings for each task" }, ++ { "no_cvt_hw", OPT_BOOL | OPT_EXPERT, { &no_cvt_hw }, ++ "do not auto-convert hw frames to sw" }, + { "progress", HAS_ARG | OPT_EXPERT, { .func_arg = opt_progress }, + "write program-readable progress information", "url" }, + { "stdin", OPT_BOOL | OPT_EXPERT, { &stdin_interaction }, +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 5a6ea59715..c9d056101d 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -19,6 +19,7 @@ HEADERS = ac3_parser.h \ + mediacodec.h \ + packet.h \ + qsv.h \ ++ rpi_zc.h \ + vaapi.h \ + vdpau.h \ + version.h \ +@@ -138,6 +139,7 @@ OBJS-$(CONFIG_QSVDEC) += qsvdec.o + OBJS-$(CONFIG_QSVENC) += qsvenc.o + OBJS-$(CONFIG_RANGECODER) += rangecoder.o + OBJS-$(CONFIG_RDFT) += rdft.o ++OBJS-$(CONFIG_RPI) += rpi_qpu.o rpi_mailbox.o rpi_zc.o + OBJS-$(CONFIG_RV34DSP) += rv34dsp.o + OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o + OBJS-$(CONFIG_SINEWIN) += sinewin.o sinewin_fixed.o +@@ -153,6 +155,7 @@ OBJS-$(CONFIG_VP3DSP) += vp3dsp.o + OBJS-$(CONFIG_VP56DSP) += vp56dsp.o + OBJS-$(CONFIG_VP8DSP) += vp8dsp.o + OBJS-$(CONFIG_V4L2_M2M) += v4l2_m2m.o v4l2_context.o v4l2_buffers.o v4l2_fmt.o ++OBJS-$(CONFIG_V4L2_REQUEST) += v4l2_request.o v4l2_phase.o + OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o + OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o + +@@ -381,6 +384,15 @@ OBJS-$(CONFIG_HCOM_DECODER) += hcom.o + OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ + hevc_cabac.o hevc_refs.o hevcpred.o \ + hevcdsp.o hevc_filter.o hevc_data.o ++OBJS-$(CONFIG_RPI) += rpi_mem.o \ ++ rpi_mailbox.o rpi_zc.o ++OBJS-$(CONFIG_HEVC_RPI_DECODER) += rpi_hevcdec.o rpi_hevc_mvs.o \ ++ rpi_hevc_cabac.o rpi_hevc_refs.o rpi_hevcpred.o \ ++ rpi_hevcdsp.o rpi_hevc_filter.o rpi_hevc_data.o \ ++ rpi_hevc_shader.o rpi_hevc_shader_template.o \ ++ rpi_hevc_parse.o h2645_parse.o rpi_hevc_ps.o \ ++ rpi_hevc_sei.o rpi_hevc_data.o rpi_qpu.o rpi_mem.o ++OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuvid.o + OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o + OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o + OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o +@@ -902,6 +914,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o + OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o ++OBJS-$(CONFIG_H264_V4L2REQUEST_HWACCEL) += v4l2_request_h264.o + OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o + OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o + OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o +@@ -909,8 +922,11 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o + OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o ++OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o + OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o + OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o ++OBJS-$(CONFIG_HEVC_RPI4_8_HWACCEL) += rpivid_hevc.o ++OBJS-$(CONFIG_HEVC_RPI4_10_HWACCEL) += rpivid_hevc.o + OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o + OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o + OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o +@@ -921,6 +937,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o + OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o ++OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL) += v4l2_request_mpeg2.o + OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o + OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o + OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o +@@ -936,10 +953,12 @@ OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o + OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o + OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o + OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o ++OBJS-$(CONFIG_VP8_V4L2REQUEST_HWACCEL) += v4l2_request_vp8.o + OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o + OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o ++OBJS-$(CONFIG_VP9_V4L2REQUEST_HWACCEL) += v4l2_request_vp9.o + OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o + OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o + OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o +@@ -1261,3 +1280,31 @@ $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h + $(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h + $(SUBDIR)sinewin_fixed.o: $(SUBDIR)sinewin_fixed_tables.h + endif ++ ++ifdef CONFIG_HEVC_RPI_DECODER ++QASM_PY := ../local/bin/qasm.py ++VASMVIDCORE := ../local/bin/vasmvidcore_std ++ ++ifneq ("$(wildcard $(QASM_PY))","") ++$(SUBDIR)rpi_hevc_shader.c: $(SUBDIR)rpi_hevc_shader.qasm ++ $(QASM_PY) -mc_c:rpi_hevc_shader,rpi_hevc_shader,ff_hevc_rpi_shader $< > $@ ++ ++$(SUBDIR)rpi_hevc_shader.h: $(SUBDIR)rpi_hevc_shader.qasm ++ $(QASM_PY) -mc_h:rpi_hevc_shader,rpi_hevc_shader,ff_hevc_rpi_shader $< > $@ ++endif ++ ++ifneq ("$(wildcard $(VASMVIDCORE))","") ++$(SUBDIR)rpi_hevc_transform8.bin: $(SUBDIR)rpi_hevc_transform.s ++ $(VASMVIDCORE) -Fbin -DBIT_DEPTH=8 $< -o $@ ++$(SUBDIR)rpi_hevc_transform10.bin: $(SUBDIR)rpi_hevc_transform.s ++ $(VASMVIDCORE) -Fbin -DBIT_DEPTH=10 $< -o $@ ++ ++$(SUBDIR)rpi_hevc_transform8.h: $(SUBDIR)rpi_hevc_transform8.bin ++ python pi-util/make_array.py $< ++$(SUBDIR)rpi_hevc_transform10.h: $(SUBDIR)rpi_hevc_transform10.bin ++ python pi-util/make_array.py $< ++endif ++ ++$(SUBDIR)rpi_qpu.o: $(SUBDIR)rpi_hevc_transform8.h $(SUBDIR)rpi_hevc_transform10.h ++$(SUBDIR)rpi_hevcdec.o $(SUBDIR)rpi_shader_template.o $(SUBDIR)rpi_qpu.o: $(SUBDIR)rpi_hevc_shader.h ++endif +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index 80f128cade..ac4cf9a90e 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -149,6 +149,7 @@ extern AVCodec ff_hap_decoder; + extern AVCodec ff_hevc_decoder; + extern AVCodec ff_hevc_qsv_decoder; + extern AVCodec ff_hevc_rkmpp_decoder; ++extern AVCodec ff_hevc_rpi_decoder; + extern AVCodec ff_hevc_v4l2m2m_decoder; + extern AVCodec ff_hnm4_video_decoder; + extern AVCodec ff_hq_hqa_decoder; +@@ -890,6 +891,41 @@ static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) + } + } + ++static int codec_supports_format(const AVCodec * const p, const enum AVPixelFormat fmt) ++{ ++ const enum AVPixelFormat *pf = p->pix_fmts; ++ ++ // Assume good if we lack info ++ if (pf == NULL) ++ return 1; ++ if (fmt == AV_PIX_FMT_NONE) ++ return 0; ++ ++ for (; *pf != AV_PIX_FMT_NONE; ++pf) { ++ if (*pf == fmt) ++ return 1; ++ } ++ return 0; ++} ++ ++AVCodec *avcodec_find_decoder_by_id_and_fmt(enum AVCodecID id, enum AVPixelFormat fmt) ++{ ++ const AVCodec *p, *experimental = NULL; ++ void *i = 0; ++ ++ id= remap_deprecated_codec_id(id); ++ while ((p = av_codec_iterate(&i))) { ++ if (av_codec_is_decoder(p) && p->id == id && codec_supports_format(p, fmt)) { ++ if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) { ++ experimental = p; ++ } else ++ return (AVCodec *)p; ++ } ++ p = p->next; ++ } ++ return (AVCodec *)experimental; ++} ++ + static AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *)) + { + const AVCodec *p, *experimental = NULL; +diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile +index c6be814153..442d60efe4 100644 +--- a/libavcodec/arm/Makefile ++++ b/libavcodec/arm/Makefile +@@ -40,6 +40,8 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ + arm/sbrdsp_init_arm.o + OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_init_arm.o + OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_arm.o ++OBJS-$(CONFIG_HEVC_RPI_DECODER) += arm/rpi_hevcdsp_init_arm.o \ ++ arm/rpi_hevcpred_init_arm.o + OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o + OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o + OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_init_arm.o +@@ -140,10 +142,24 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ + NEON-OBJS-$(CONFIG_LLAUDDSP) += arm/lossless_audiodsp_neon.o + NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_neon.o + NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ ++ arm/hevcdsp_idct_neon.o \ + arm/hevcdsp_deblock_neon.o \ + arm/hevcdsp_idct_neon.o \ + arm/hevcdsp_qpel_neon.o \ + arm/hevcdsp_sao_neon.o ++NEON-OBJS-$(CONFIG_HEVC_RPI_DECODER) += arm/rpi_hevcdsp_init_neon.o \ ++ arm/rpi_hevc_misc_neon.o \ ++ arm/rpi_hevcdsp_deblock_neon.o \ ++ arm/rpi_hevcdsp_idct_neon.o \ ++ arm/rpi_hevcdsp_res8_neon.o \ ++ arm/rpi_hevcdsp_res16_neon.o \ ++ arm/rpi_hevcdsp_sao_neon.o \ ++ arm/rpi_hevcpred_init_neon.o \ ++ arm/rpi_hevcpred_intra_angular_neon.o \ ++ arm/rpi_hevcpred_intra_dc_neon.o \ ++ arm/rpi_hevcpred_intra_filter_neon.o \ ++ arm/rpi_hevcpred_intra_hv_neon.o \ ++ arm/rpi_hevcpred_intra_planar_neon.o + NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o + NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ + arm/rv40dsp_neon.o +diff --git a/libavcodec/arm/cabac.h b/libavcodec/arm/cabac.h +index fdbf86b45e..4755f20e2e 100644 +--- a/libavcodec/arm/cabac.h ++++ b/libavcodec/arm/cabac.h +@@ -26,83 +26,209 @@ + #include "libavutil/internal.h" + #include "libavcodec/cabac.h" + ++ + #define get_cabac_inline get_cabac_inline_arm + static av_always_inline int get_cabac_inline_arm(CABACContext *c, +- uint8_t *const state) ++ uint8_t *state) + { +- int bit; +- void *reg_b, *reg_c, *tmp; ++ const uint8_t *mlps_tables = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128; ++ int bit, ptr, low, tmp1, tmp2; ++ __asm__ volatile ( ++ "ldr %[bit], [%[c], %[range_off]] \n\t" ++ "ldrb %[ptr], [%[state]] \n\t" ++ "sub %[tmp1], %[mlps_tables], %[lps_off] \n\t" ++ "and %[tmp2], %[bit], #0xc0 \n\t" ++ "add %[tmp1], %[tmp1], %[ptr] \n\t" ++ "ldr %[low], [%[c], %[low_off]] \n\t" ++ "ldrb %[tmp2], [%[tmp1], %[tmp2], lsl #1] \n\t" ++ "sub %[bit], %[bit], %[tmp2] \n\t" ++ "mov %[tmp1], %[bit] \n\t" ++ "cmp %[low], %[bit], lsl #17 \n\t" ++ "itt ge \n\t" ++ "movge %[tmp1], %[tmp2] \n\t" ++ "mvnge %[ptr], %[ptr] \n\t" ++ "clz %[tmp2], %[tmp1] \n\t" ++ "it ge \n\t" ++ "subge %[low], %[low], %[bit], lsl #17 \n\t" ++ "sub %[tmp2], %[tmp2], #23 \n\t" ++ "and %[bit], %[ptr], #1 \n\t" ++ "ldrb %[mlps_tables], [%[mlps_tables], %[ptr]] \n\t" ++ "lsl %[low], %[low], %[tmp2] \n\t" ++ "lsls %[ptr], %[low], #16 \n\t" ++ "bne 1f \n\t" ++ "ldr %[ptr], [%[c], %[ptr_off]] \n\t" ++ "lsl %[tmp2], %[tmp1], %[tmp2] \n\t" ++#if UNCHECKED_BITSTREAM_READER ++ "strb %[mlps_tables], [%[state]] \n\t" ++ "rbit %[state], %[low] \n\t" ++ "ldrh %[tmp1], [%[ptr]], #2 \n\t" ++#else ++ "ldr %[tmp1], [%[c], %[end_off]] \n\t" ++ "strb %[mlps_tables], [%[state]] \n\t" ++ "rbit %[state], %[low] \n\t" ++ "cmp %[tmp1], %[ptr] \n\t" ++#if CONFIG_THUMB ++ "it cs \n\t" ++ "ldrhcs %[tmp1], [%[ptr]], #2 \n\t" ++#else ++ "ldrcsh %[tmp1], [%[ptr]], #2 \n\t" ++#endif ++#endif ++ "clz %[state], %[state] \n\t" ++ "movw %[mlps_tables], #0xffff \n\t" ++ "sub %[state], %[state], #16 \n\t" ++ "str %[tmp2], [%[c], %[range_off]] \n\t" ++ "rev %[tmp1], %[tmp1] \n\t" ++ "str %[ptr], [%[c], %[ptr_off]] \n\t" ++ "lsr %[tmp1], %[tmp1], #15 \n\t" ++ "sub %[tmp1], %[tmp1], %[mlps_tables] \n\t" ++#if CONFIG_THUMB ++ "lsl %[tmp1], %[tmp1], %[state] \n\t" ++ "add %[low], %[low], %[tmp1] \n\t" ++#else ++ "add %[low], %[low], %[tmp1], lsl %[state] \n\t" ++#endif ++ "str %[low], [%[c], %[low_off]] \n\t" ++ "b 2f \n\t" ++ "1: \n\t" ++ "strb %[mlps_tables], [%[state]] \n\t" ++ "lsl %[tmp1], %[tmp1], %[tmp2] \n\t" ++ "str %[low], [%[c], %[low_off]] \n\t" ++ "str %[tmp1], [%[c], %[range_off]] \n\t" ++ "2: \n\t" ++ : // Outputs ++ [state]"+r"(state), ++ [mlps_tables]"+r"(mlps_tables), ++ [bit]"=&r"(bit), ++ [ptr]"=&r"(ptr), ++ [low]"=&r"(low), ++ [tmp1]"=&r"(tmp1), ++ [tmp2]"=&r"(tmp2) ++ : // Inputs ++ [c]"r"(c), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [end_off]"J"(offsetof(CABACContext, bytestream_end)), ++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ return bit; ++} + +- __asm__ volatile( +- "ldrb %[bit] , [%[state]] \n\t" +- "add %[r_b] , %[tables] , %[lps_off] \n\t" +- "mov %[tmp] , %[range] \n\t" +- "and %[range] , %[range] , #0xC0 \n\t" +- "add %[r_b] , %[r_b] , %[bit] \n\t" +- "ldrb %[range] , [%[r_b], %[range], lsl #1] \n\t" +- "add %[r_b] , %[tables] , %[norm_off] \n\t" +- "sub %[r_c] , %[tmp] , %[range] \n\t" +- "lsl %[tmp] , %[r_c] , #17 \n\t" +- "cmp %[tmp] , %[low] \n\t" +- "it gt \n\t" +- "movgt %[range] , %[r_c] \n\t" +- "itt cc \n\t" +- "mvncc %[bit] , %[bit] \n\t" +- "subcc %[low] , %[low] , %[tmp] \n\t" +- "add %[r_c] , %[tables] , %[mlps_off] \n\t" +- "ldrb %[tmp] , [%[r_b], %[range]] \n\t" +- "ldrb %[r_b] , [%[r_c], %[bit]] \n\t" +- "lsl %[low] , %[low] , %[tmp] \n\t" +- "lsl %[range] , %[range] , %[tmp] \n\t" +- "uxth %[r_c] , %[low] \n\t" +- "strb %[r_b] , [%[state]] \n\t" +- "tst %[r_c] , %[r_c] \n\t" +- "bne 2f \n\t" +- "ldr %[r_c] , [%[c], %[byte]] \n\t" ++#define get_cabac_bypass get_cabac_bypass_arm ++static inline int get_cabac_bypass_arm(CABACContext * const c) ++{ ++ uint32_t low = c->low, range, ptr, tmp; ++ int rv; ++ __asm volatile ( ++ "ldr %[range] , [%[c], %[range_off]] \n\t" ++ "mov %[rv] , #0 \n\t" ++ "ldr %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "lsl %[low] , #1 \n\t" ++#if !UNCHECKED_BITSTREAM_READER ++ "ldr %[tmp] , [%[c], %[end_off]] \n\t" ++#endif ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "itt cs \n\t" ++ "subcs %[low] , %[low], %[range], lsl #17 \n\t" ++ "movcs %[rv] , #1 \n\t" + #if UNCHECKED_BITSTREAM_READER +- "ldrh %[tmp] , [%[r_c]] \n\t" +- "add %[r_c] , %[r_c] , #2 \n\t" +- "str %[r_c] , [%[c], %[byte]] \n\t" ++ "ldrh %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "cmp %[tmp] , %[ptr] \n\t" ++#if CONFIG_THUMB ++ "it cs \n\t" ++ "ldrhcs %[tmp] , [%[ptr]], #2 \n\t" + #else +- "ldr %[r_b] , [%[c], %[end]] \n\t" +- "ldrh %[tmp] , [%[r_c]] \n\t" +- "cmp %[r_c] , %[r_b] \n\t" +- "itt lt \n\t" +- "addlt %[r_c] , %[r_c] , #2 \n\t" +- "strlt %[r_c] , [%[c], %[byte]] \n\t" ++ "ldrcsh %[tmp] , [%[ptr]], #2 \n\t" ++#endif + #endif +- "sub %[r_c] , %[low] , #1 \n\t" +- "add %[r_b] , %[tables] , %[norm_off] \n\t" +- "eor %[r_c] , %[low] , %[r_c] \n\t" +- "rev %[tmp] , %[tmp] \n\t" +- "lsr %[r_c] , %[r_c] , #15 \n\t" +- "lsr %[tmp] , %[tmp] , #15 \n\t" +- "ldrb %[r_c] , [%[r_b], %[r_c]] \n\t" +- "movw %[r_b] , #0xFFFF \n\t" +- "sub %[tmp] , %[tmp] , %[r_b] \n\t" +- "rsb %[r_c] , %[r_c] , #7 \n\t" +- "lsl %[tmp] , %[tmp] , %[r_c] \n\t" +- "add %[low] , %[low] , %[tmp] \n\t" +- "2: \n\t" +- : [bit]"=&r"(bit), +- [low]"+&r"(c->low), +- [range]"+&r"(c->range), +- [r_b]"=&r"(reg_b), +- [r_c]"=&r"(reg_c), +- [tmp]"=&r"(tmp) +- : [c]"r"(c), +- [state]"r"(state), +- [tables]"r"(ff_h264_cabac_tables), +- [byte]"M"(offsetof(CABACContext, bytestream)), +- [end]"M"(offsetof(CABACContext, bytestream_end)), +- [norm_off]"I"(H264_NORM_SHIFT_OFFSET), +- [lps_off]"I"(H264_LPS_RANGE_OFFSET), +- [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128) +- : "memory", "cc" +- ); ++ "lsls %[range] , %[low], #16 \n\t" ++ "bne 1f \n\t" + +- return bit & 1; ++ "str %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "add %[low] , %[low], %[tmp], lsr #15 \n\t" ++ "movw %[tmp] , 0xFFFF \n\t" ++ "sub %[low] , %[tmp] \n\t" ++ "1: \n\t" ++ "str %[low] , [%[c], %[low_off]] \n\t" ++ : // Outputs ++ [rv]"=&r"(rv), ++ [low]"+r"(low), ++ [range]"=&r"(range), ++ [ptr]"=&r"(ptr), ++ [tmp]"=&r"(tmp) ++ : // Inputs ++ [c]"r"(c), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [end_off]"J"(offsetof(CABACContext, bytestream_end)) ++ : // Clobbers ++ "memory", "cc" ++ ); ++ return rv; + } ++ ++ ++#define get_cabac_bypass_sign get_cabac_bypass_sign_arm ++static inline int get_cabac_bypass_sign_arm(CABACContext * const c, int rv) ++{ ++ uint32_t low = c->low, range, ptr, tmp; ++ __asm volatile ( ++ "ldr %[range] , [%[c], %[range_off]] \n\t" ++ "ldr %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "lsl %[low] , #1 \n\t" ++#if !UNCHECKED_BITSTREAM_READER ++ "ldr %[tmp] , [%[c], %[end_off]] \n\t" ++#endif ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "it cs \n\t" ++ "subcs %[low] , %[low], %[range], lsl #17 \n\t" ++ "it cc \n\t" ++ "rsbcc %[rv] , %[rv], #0 \n\t" ++#if UNCHECKED_BITSTREAM_READER ++ "ldrh %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "cmp %[tmp] , %[ptr] \n\t" ++#if CONFIG_THUMB ++ "it cs \n\t" ++ "ldrhcs %[tmp] , [%[ptr]], #2 \n\t" ++#else ++ "ldrcsh %[tmp] , [%[ptr]], #2 \n\t" ++#endif ++#endif ++ "lsls %[range] , %[low], #16 \n\t" ++ "bne 1f \n\t" ++ ++ "str %[ptr] , [%[c], %[ptr_off]] \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "add %[low] , %[low], %[tmp], lsr #15 \n\t" ++ "movw %[tmp] , 0xFFFF \n\t" ++ "sub %[low] , %[tmp] \n\t" ++ "1: \n\t" ++ "str %[low] , [%[c], %[low_off]] \n\t" ++ : // Outputs ++ [rv]"+r"(rv), ++ [low]"+r"(low), ++ [range]"=&r"(range), ++ [ptr]"=&r"(ptr), ++ [tmp]"=&r"(tmp) ++ : // Inputs ++ [c]"r"(c), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [end_off]"J"(offsetof(CABACContext, bytestream_end)) ++ : // Clobbers ++ "memory", "cc" ++ ); ++ return rv; ++} ++ + #endif /* HAVE_ARMV6T2_INLINE */ + + #endif /* AVCODEC_ARM_CABAC_H */ +diff --git a/libavcodec/arm/rpi_hevc_cabac.h b/libavcodec/arm/rpi_hevc_cabac.h +new file mode 100644 +index 0000000000..c88dec6eff +--- /dev/null ++++ b/libavcodec/arm/rpi_hevc_cabac.h +@@ -0,0 +1,607 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * Copyright (C) 2018 John Cox, Ben Avison for Raspberry Pi (Trading) ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_ARM_HEVC_CABAC_H ++#define AVCODEC_ARM_HEVC_CABAC_H ++ ++#include "config.h" ++#if HAVE_ARMV6T2_INLINE ++ ++#define hevc_mem_bits32 hevc_mem_bits32_arm ++static inline uint32_t hevc_mem_bits32_arm(const void * p, const unsigned int bits) ++{ ++ unsigned int n; ++ __asm__ ( ++ "rev %[n], %[x] \n\t" ++ : [n]"=r"(n) ++ : [x]"r"(*(const uint32_t *)((const uint8_t *)p + (bits >> 3))) ++ : ++ ); ++ return n << (bits & 7); ++} ++ ++ ++// --------------------------------------------------------------------------- ++// ++// Helper fns - little bits of code where ARM has an instraction that the ++// compiler doesn't know about / use ++ ++#define trans_scale_sat trans_scale_sat_arm ++static inline int trans_scale_sat_arm(const int level, const unsigned int scale, const unsigned int scale_m, const unsigned int shift) ++{ ++ int rv; ++ int t = ((level * (int)(scale * scale_m)) >> shift) + 1; ++ ++ __asm__ ( ++ "ssat %[rv], #16, %[t], ASR #1 \n\t" ++ : [rv]"=r"(rv) ++ : [t]"r"(t) ++ : ++ ); ++ return rv; ++} ++ ++#define update_rice update_rice_arm ++static inline void update_rice_arm(uint8_t * const stat_coeff, ++ const unsigned int last_coeff_abs_level_remaining, ++ const unsigned int c_rice_param) ++{ ++ int t = last_coeff_abs_level_remaining << 1; ++ __asm__ ( ++ "lsrs %[t], %[t], %[shift] \n\t" ++ ++ "it eq \n\t" ++ "subeq %[stat], %[stat], #1 \n\t" ++ "cmp %[t], #6 \n\t" ++ "adc %[stat], %[stat], #0 \n\t" ++ "usat %[stat], #8, %[stat] \n\t" ++ : [stat]"+r"(*stat_coeff), ++ [t]"+r"(t) ++ : [shift]"r"(c_rice_param) ++ : "cc" ++ ); ++} ++ ++// --------------------------------------------------------------------------- ++// ++// CABAC get loops ++// ++// Where the loop is simple enough we can normally do 10-30% better than the ++// compiler ++ ++// Get the residual greater than 1 bits ++ ++#define get_cabac_greater1_bits get_cabac_greater1_bits_arm ++static inline unsigned int get_cabac_greater1_bits_arm(CABACContext * const c, const unsigned int n, ++ uint8_t * const state0) ++{ ++ unsigned int i, reg_b, st, tmp, bit, rv; ++ __asm__ ( ++ "mov %[i] , #0 \n\t" ++ "mov %[rv] , #0 \n\t" ++ "1: \n\t" ++ "add %[i] , %[i] , #1 \n\t" ++ "cmp %[rv] , #0 \n\t" ++ "ite eq \n\t" ++ "usateq %[st] , #2 , %[i] \n\t" ++ "movne %[st] , #0 \n\t" ++ "sub %[r_b] , %[mlps_tables], %[lps_off] \n\t" ++ "and %[tmp] , %[range] , #0xC0 \n\t" ++ ++ "ldrb %[bit] , [%[state0], %[st]] \n\t" ++ "add %[r_b] , %[r_b] , %[bit] \n\t" ++ "ldrb %[tmp] , [%[r_b], %[tmp], lsl #1] \n\t" ++ "sub %[range] , %[range] , %[tmp] \n\t" ++ ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "ittt ge \n\t" ++ "subge %[low] , %[low] , %[range], lsl #17 \n\t" ++ "movge %[range] , %[tmp] \n\t" ++ "mvnge %[bit] , %[bit] \n\t" ++ ++ "clz %[tmp] , %[range] \n\t" ++ "sub %[tmp] , #23 \n\t" ++ "ldrb %[r_b] , [%[mlps_tables], %[bit]] \n\t" ++ "and %[bit] , %[bit] , #1 \n\t" ++ "strb %[r_b] , [%[state0], %[st]] \n\t" ++ "lsl %[low] , %[low] , %[tmp] \n\t" ++ "orr %[rv] , %[bit] , %[rv], lsl #1 \n\t" ++ "lsl %[range] , %[range] , %[tmp] \n\t" ++ ++// There is a small speed gain from combining both conditions, using a single ++// branch and then working out what that meant later ++ "lsls %[tmp] , %[low] , #16 \n\t" ++ "it ne \n\t" ++ "cmpne %[n] , %[i] \n\t" ++ "bne 1b \n\t" ++ ++// If reload is not required then we must have run out of flags to decode ++ "tst %[tmp] , %[tmp] \n\t" ++ "bne 2f \n\t" ++ ++// Do reload ++ "ldrh %[tmp] , [%[bptr]] , #2 \n\t" ++ "rbit %[bit] , %[low] \n\t" ++ "movw %[r_b] , #0xFFFF \n\t" ++ "clz %[bit] , %[bit] \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "sub %[bit] , %[bit] , #16 \n\t" ++ "cmp %[n] , %[i] \n\t" ++ "rsb %[tmp] , %[r_b] , %[tmp], lsr #15 \n\t" ++ ++#if CONFIG_THUMB ++ "lsl %[tmp] , %[tmp] , %[bit] \n\t" ++ "add %[low] , %[low] , %[tmp] \n\t" ++#else ++ "add %[low] , %[low] , %[tmp], lsl %[bit] \n\t" ++#endif ++ ++ "bne 1b \n\t" ++ "2: \n\t" ++ : [bit]"=&r"(bit), ++ [low]"+r"(c->low), ++ [range]"+r"(c->range), ++ [r_b]"=&r"(reg_b), ++ [bptr]"+r"(c->bytestream), ++ [i]"=&r"(i), ++ [tmp]"=&r"(tmp), ++ [st]"=&r"(st), ++ [rv]"=&r"(rv) ++ : [state0]"r"(state0), ++ [n]"r"(n), ++ [mlps_tables]"r"(ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128), ++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) ++ : "memory", "cc" ++ ); ++ return rv; ++} ++ ++ ++// n must be > 0 on entry ++#define get_cabac_sig_coeff_flag_idxs get_cabac_sig_coeff_flag_idxs_arm ++static inline uint8_t * get_cabac_sig_coeff_flag_idxs_arm(CABACContext * const c, uint8_t * const state0, ++ unsigned int n, ++ const uint8_t * ctx_map, ++ uint8_t * p) ++{ ++ unsigned int reg_b, tmp, st, bit; ++ __asm__ ( ++// Get bin from map ++#if CONFIG_THUMB ++ "add %[ctx_map] , %[n] \n\t" ++ "ldrb %[st] , [%[ctx_map]] \n\t" ++#else ++ "ldrb %[st] , [%[ctx_map], %[n]]! \n\t" ++#endif ++ "1: \n\t" ++ ++// Load state & ranges ++ "ldrb %[bit] , [%[state0], %[st]] \n\t" ++ "and %[tmp] , %[range] , #0xC0 \n\t" ++ "sub %[r_b] , %[mlps_tables], %[lps_off] \n\t" ++ "add %[r_b] , %[r_b] , %[tmp], lsl #1 \n\t" ++ "ldrb %[tmp] , [%[r_b], %[bit]] \n\t" ++ "sub %[range] , %[range] , %[tmp] \n\t" ++ ++ "cmp %[low] , %[range], lsl #17 \n\t" ++ "ittt ge \n\t" ++ "mvnge %[bit] , %[bit] \n\t" ++ "subge %[low] , %[low] , %[range], lsl #17 \n\t" ++ "movge %[range] , %[tmp] \n\t" ++ ++// Renorm ++ "clz %[tmp] , %[range] \n\t" ++ "ldrb %[r_b] , [%[mlps_tables], %[bit]] \n\t" ++ "sub %[tmp] , #23 \n\t" ++ "strb %[r_b] , [%[state0], %[st]] \n\t" ++ "tst %[bit] , #1 \n\t" ++ "ldrb %[st] , [%[ctx_map], #-1]! \n\t" ++ "lsl %[low] , %[low] , %[tmp] \n\t" ++// GCC asm seems to need strbne written differently for thumb and arm ++#if CONFIG_THUMB ++ "it ne \n\t" ++ "strbne %[n] , [%[idx]] , #1 \n\t" ++#else ++ "strneb %[n] , [%[idx]] , #1 \n\t" ++#endif ++ ++// There is a small speed gain from combining both conditions, using a single ++// branch and then working out what that meant later ++ "subs %[n] , %[n] , #1 \n\t" ++ "lsl %[range] , %[range] , %[tmp] \n\t" ++#if CONFIG_THUMB ++ "itt ne \n\t" ++ "lslsne %[tmp] , %[low] , #16 \n\t" ++#else ++ "lslnes %[tmp] , %[low] , #16 \n\t" ++#endif ++ "bne 1b \n\t" ++ ++// If we have bits left then n must be 0 so give up now ++ "lsls %[tmp] , %[low] , #16 \n\t" ++ "bne 2f \n\t" ++ ++// Do reload ++ "ldrh %[tmp] , [%[bptr]] , #2 \n\t" ++ "rbit %[bit] , %[low] \n\t" ++ "movw %[r_b] , #0xFFFF \n\t" ++ "clz %[bit] , %[bit] \n\t" ++ "cmp %[n] , #0 \n\t" ++ "rev %[tmp] , %[tmp] \n\t" ++ "sub %[bit] , %[bit] , #16 \n\t" ++ "rsb %[tmp] , %[r_b] , %[tmp], lsr #15 \n\t" ++ ++#if CONFIG_THUMB ++ "lsl %[tmp] , %[tmp] , %[bit] \n\t" ++ "add %[low] , %[low] , %[tmp] \n\t" ++#else ++ "add %[low] , %[low] , %[tmp], lsl %[bit] \n\t" ++#endif ++ ++// Check to see if we still have more to do ++ "bne 1b \n\t" ++ "2: \n\t" ++ : [bit]"=&r"(bit), ++ [low]"+r"(c->low), ++ [range]"+r"(c->range), ++ [r_b]"=&r"(reg_b), ++ [bptr]"+r"(c->bytestream), ++ [idx]"+r"(p), ++ [n]"+r"(n), ++ [tmp]"=&r"(tmp), ++ [st]"=&r"(st), ++ [ctx_map]"+r"(ctx_map) ++ : [state0]"r"(state0), ++ [mlps_tables]"r"(ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128), ++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) ++ : "memory", "cc" ++ ); ++ ++ return p; ++} ++ ++// --------------------------------------------------------------------------- ++// ++// CABAC_BY22 functions ++ ++ ++#define get_cabac_by22_start get_cabac_by22_start_arm ++static inline void get_cabac_by22_start_arm(CABACContext * const c) ++{ ++ const uint8_t *ptr = c->bytestream; ++ register uint32_t low __asm__("r1"), range __asm__("r2"); ++ uint32_t m, range8, bits; ++#if !USE_BY22_DIV ++ uintptr_t inv; ++#endif ++ ++ av_assert2(offsetof (CABACContext, low) == 0); ++ av_assert2(offsetof (CABACContext, range) == 4); ++ av_assert2(offsetof (CABACContext, by22.range) == offsetof (CABACContext, by22.bits) + 2); ++ __asm__ volatile ( ++ "ldmia %[c], {%[low], %[range]} \n\t" ++ : // Outputs ++ [low]"=r"(low), ++ [range]"=r"(range) ++ : // Inputs ++ [c]"r"(c) ++ : // Clobbers ++ ); ++#if !USE_BY22_DIV ++ inv = (uintptr_t)cabac_by22_inv_range; ++#endif ++ __asm__ volatile ( ++ "ldr %[m], [%[ptr]], #-("AV_STRINGIFY(CABAC_BITS)"/8) \n\t" ++#if !USE_BY22_DIV ++ "uxtb %[range8], %[range] \n\t" ++#endif ++ "rbit %[bits], %[low] \n\t" ++ "lsl %[low], %[low], #22 - "AV_STRINGIFY(CABAC_BITS)" \n\t" ++ "clz %[bits], %[bits] \n\t" ++ "str %[ptr], [%[c], %[ptr_off]] \n\t" ++ "rev %[m], %[m] \n\t" ++ "rsb %[ptr], %[bits], #9 + "AV_STRINGIFY(CABAC_BITS)" \n\t" ++ "eor %[m], %[m], #0x80000000 \n\t" ++#if !USE_BY22_DIV ++ "ldr %[inv], [%[inv], %[range8], lsl #2] \n\t" ++ "pkhbt %[range], %[bits], %[range], lsl #16 \n\t" ++ "str %[range], [%[c], %[bits_off]] \n\t" ++#else ++ "strh %[bits], [%[c], %[bits_off]] \n\t" ++#endif ++#if CONFIG_THUMB ++ "lsr %[m], %[ptr] \n\t" ++ "eor %[range], %[low], %[m] \n\t" ++#else ++ "eor %[range], %[low], %[m], lsr %[ptr] \n\t" ++#endif ++ : // Outputs ++ [ptr]"+&r"(ptr), ++ [low]"+&r"(low), ++ [range]"+&r"(range), ++#if !USE_BY22_DIV ++ [inv]"+&r"(inv), ++#endif ++ [m]"=&r"(m), ++ [range8]"=&r"(range8), ++ [bits]"=&r"(bits) ++ : // Inputs ++ [c]"r"(c), ++ [bits_off]"J"(offsetof (CABACContext, by22.bits)), ++ [ptr_off]"J"(offsetof (CABACContext, bytestream)) ++ : // Clobbers ++ "memory" ++ ); ++ c->low = range; ++#if !USE_BY22_DIV ++ c->range = inv; ++#endif ++} ++ ++#define get_cabac_by22_peek get_cabac_by22_peek_arm ++static inline uint32_t get_cabac_by22_peek_arm(const CABACContext *const c) ++{ ++ uint32_t rv = c->low &~ 1, tmp; ++ __asm__ ( ++ "cmp %[inv] , #0 \n\t" ++ "it ne \n\t" ++ "umullne %[tmp] , %[rv] , %[inv], %[rv] \n\t" ++ : // Outputs ++ [rv]"+r"(rv), ++ [tmp]"=r"(tmp) ++ : // Inputs ++ [inv]"r"(c->range) ++ : // Clobbers ++ "cc" ++ ); ++ return rv << 1; ++} ++ ++#define get_cabac_by22_flush get_cabac_by22_flush_arm ++static inline void get_cabac_by22_flush_arm(CABACContext *const c, const unsigned int n, uint32_t val) ++{ ++ uint32_t bits, ptr, tmp1, tmp2; ++ __asm__ volatile ( ++ "ldrh %[bits], [%[cc], %[bits_off]] \n\t" ++ "ldr %[ptr], [%[cc], %[ptr_off]] \n\t" ++ "rsb %[tmp1], %[n], #32 \n\t" ++ "add %[bits], %[bits], %[n] \n\t" ++ "ldrh %[tmp2], [%[cc], %[range_off]] \n\t" ++ "lsr %[tmp1], %[val], %[tmp1] \n\t" ++ "ldr %[val], [%[cc], %[low_off]] \n\t" ++#if CONFIG_THUMB ++ "add %[ptr], %[ptr], %[bits], lsr #3 \n\t" ++ "ldr %[ptr], [%[ptr]] \n\t" ++#else ++ "ldr %[ptr], [%[ptr], %[bits], lsr #3] \n\t" ++#endif ++ "mul %[tmp1], %[tmp2], %[tmp1] \n\t" ++ "and %[tmp2], %[bits], #7 \n\t" ++ "strh %[bits], [%[cc], %[bits_off]] \n\t" ++ "rev %[ptr], %[ptr] \n\t" ++ "lsl %[tmp1], %[tmp1], #23 \n\t" ++#if CONFIG_THUMB ++ "lsl %[val], %[n] \n\t" ++ "sub %[val], %[tmp1] \n\t" ++#else ++ "rsb %[val], %[tmp1], %[val], lsl %[n] \n\t" ++#endif ++ "lsl %[ptr], %[ptr], %[tmp2] \n\t" ++ "orr %[val], %[val], %[ptr], lsr #9 \n\t" ++ "str %[val], [%[cc], %[low_off]] \n\t" ++ : // Outputs ++ [val]"+r"(val), ++ [bits]"=&r"(bits), ++ [ptr]"=&r"(ptr), ++ [tmp1]"=&r"(tmp1), ++ [tmp2]"=&r"(tmp2) ++ : // Inputs ++ [cc]"r"(c), ++ [n]"r"(n), ++ [bits_off]"J"(offsetof(CABACContext, by22.bits)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)), ++ [range_off]"J"(offsetof(CABACContext, by22.range)), ++ [low_off]"J"(offsetof(CABACContext, low)) ++ : // Clobbers ++ "memory" ++ ); ++} ++ ++#define coeff_abs_level_remaining_decode_bypass coeff_abs_level_remaining_decode_bypass_arm ++static inline int coeff_abs_level_remaining_decode_bypass_arm(CABACContext *const c, unsigned int rice_param) ++{ ++ uint32_t last_coeff_abs_level_remaining; ++ uint32_t prefix, n1, range, n2, ptr, tmp1, tmp2; ++ __asm__ volatile ( ++ "ldr %[remain], [%[cc], %[low_off]] \n\t" ++ "ldr %[prefix], [%[cc], %[range_off]] \n\t" ++ "bic %[remain], %[remain], #1 \n\t" ++ "ldrh %[tmp2], [%[cc], %[by22_bits_off]] \n\t" ++ "ldr %[ptr], [%[cc], %[ptr_off]] \n\t" ++ "cmp %[prefix], #0 \n\t" ++ "it ne \n\t" ++ "umullne %[prefix], %[remain], %[prefix], %[remain] \n\t" ++ "ldrh %[range], [%[cc], %[by22_range_off]] \n\t" ++ "lsl %[remain], %[remain], #1 \n\t" ++ "mvn %[prefix], %[remain] \n\t" ++ "clz %[prefix], %[prefix] \n\t" ++ "rsbs %[n1], %[prefix], #2 \n\t" ++ "bcc 1f \n\t" ++ "adc %[n1], %[rice], %[prefix] \n\t" ++ "add %[tmp2], %[tmp2], %[n1] \n\t" ++ "rsb %[n2], %[n1], #32 \n\t" ++ "and %[tmp1], %[tmp2], #7 \n\t" ++ "strh %[tmp2], [%[cc], %[by22_bits_off]] \n\t" ++ "lsr %[tmp2], %[tmp2], #3 \n\t" ++ "lsr %[n2], %[remain], %[n2] \n\t" ++ "mul %[n2], %[range], %[n2] \n\t" ++ "ldr %[range], [%[cc], %[low_off]] \n\t" ++ "ldr %[ptr], [%[ptr], %[tmp2]] \n\t" ++ "rsb %[tmp2], %[rice], #31 \n\t" ++ "lsl %[remain], %[remain], %[prefix] \n\t" ++ "lsl %[n2], %[n2], #23 \n\t" ++#if CONFIG_THUMB ++ "lsl %[range], %[n1] \n\t" ++ "sub %[range], %[n2] \n\t" ++#else ++ "rsb %[range], %[n2], %[range], lsl %[n1] \n\t" ++#endif ++ "rev %[ptr], %[ptr] \n\t" ++ "lsl %[n2], %[prefix], %[rice] \n\t" ++#if CONFIG_THUMB ++ "lsr %[remain], %[tmp2] \n\t" ++ "add %[remain], %[n2] \n\t" ++#else ++ "add %[remain], %[n2], %[remain], lsr %[tmp2] \n\t" ++#endif ++ "b 3f \n\t" ++ "1: \n\t" ++ "add %[n2], %[rice], %[prefix], lsl #1 \n\t" ++ "cmp %[n2], %[peek_bits_plus_2] \n\t" ++ "bhi 2f \n\t" ++ "sub %[n1], %[n2], #2 \n\t" ++ "add %[tmp2], %[tmp2], %[n1] \n\t" ++ "rsb %[n2], %[n1], #32 \n\t" ++ "strh %[tmp2], [%[cc], %[by22_bits_off]] \n\t" ++ "lsr %[tmp1], %[tmp2], #3 \n\t" ++ "lsr %[n2], %[remain], %[n2] \n\t" ++ "mul %[n2], %[range], %[n2] \n\t" ++ "rsb %[range], %[rice], #34 \n\t" ++ "ldr %[ptr], [%[ptr], %[tmp1]] \n\t" ++ "and %[tmp1], %[tmp2], #7 \n\t" ++ "lsl %[remain], %[remain], %[prefix] \n\t" ++ "ldr %[tmp2], [%[cc], %[low_off]] \n\t" ++ "rsb %[prefix], %[prefix], %[range] \n\t" ++ "orr %[remain], %[remain], #0x80000000 \n\t" ++ "rev %[ptr], %[ptr] \n\t" ++ "lsl %[n2], %[n2], #23 \n\t" ++ "mov %[range], #2 \n\t" ++#if CONFIG_THUMB ++ "lsl %[tmp2], %[n1] \n\t" ++ "sub %[tmp2], %[n2] \n\t" ++#else ++ "rsb %[tmp2], %[n2], %[tmp2], lsl %[n1] \n\t" ++#endif ++ "lsl %[ptr], %[ptr], %[tmp1] \n\t" ++ "lsl %[rice], %[range], %[rice] \n\t" ++ "orr %[range], %[tmp2], %[ptr], lsr #9 \n\t" ++#if CONFIG_THUMB ++ "lsr %[remain], %[prefix] \n\t" ++ "add %[remain], %[rice] \n\t" ++#else ++ "add %[remain], %[rice], %[remain], lsr %[prefix] \n\t" ++#endif ++ "b 4f \n\t" ++ "2: \n\t" ++ "add %[n1], %[tmp2], %[prefix] \n\t" ++#if CONFIG_THUMB ++ "add %[tmp2], %[ptr], %[n1], lsr #3 \n\t" ++ "ldr %[tmp2], [%[tmp2]] \n\t" ++#else ++ "ldr %[tmp2], [%[ptr], %[n1], lsr #3] \n\t" ++#endif ++ "rsb %[tmp1], %[prefix], #32 \n\t" ++ "push {%[rice]} \n\t" ++ "and %[rice], %[n1], #7 \n\t" ++ "lsr %[tmp1], %[remain], %[tmp1] \n\t" ++ "ldr %[ptr], [%[cc], %[low_off]] \n\t" ++ "mul %[remain], %[range], %[tmp1] \n\t" ++ "rev %[tmp2], %[tmp2] \n\t" ++ "rsb %[n2], %[prefix], %[n2] \n\t" ++ "ldr %[tmp1], [%[cc], %[range_off]] \n\t" ++ "lsl %[rice], %[tmp2], %[rice] \n\t" ++ "sub %[tmp2], %[n2], #2 \n\t" ++ "lsl %[remain], %[remain], #23 \n\t" ++#if CONFIG_THUMB ++ "lsl %[ptr], %[prefix] \n\t" ++ "rsb %[remain], %[ptr] \n\t" ++#else ++ "rsb %[remain], %[remain], %[ptr], lsl %[prefix] \n\t" ++#endif ++ "orr %[remain], %[remain], %[rice], lsr #9 \n\t" ++ "add %[prefix], %[n1], %[tmp2] \n\t" ++ "bic %[n1], %[remain], #1 \n\t" ++ "ldr %[ptr], [%[cc], %[ptr_off]] \n\t" ++ "cmp %[tmp1], #0 \n\t" ++ "rsb %[rice], %[tmp2], #32 \n\t" ++ "it ne \n\t" ++ "umullne %[tmp1], %[n1], %[tmp1], %[n1] \n\t" ++ "and %[tmp1], %[prefix], #7 \n\t" ++#if CONFIG_THUMB ++ "add %[ptr], %[ptr], %[prefix], lsr #3 \n\t" ++ "ldr %[ptr], [%[ptr]] \n\t" ++#else ++ "ldr %[ptr], [%[ptr], %[prefix], lsr #3] \n\t" ++#endif ++ "lsl %[n1], %[n1], #1 \n\t" ++ "lsr %[rice], %[n1], %[rice] \n\t" ++ "rsb %[n2], %[n2], #34 \n\t" ++ "mul %[range], %[range], %[rice] \n\t" ++ "pop {%[rice]} \n\t" ++ "rev %[ptr], %[ptr] \n\t" ++ "orr %[n1], %[n1], #0x80000000 \n\t" ++ "strh %[prefix], [%[cc], %[by22_bits_off]] \n\t" ++ "mov %[prefix], #2 \n\t" ++ "lsl %[range], %[range], #23 \n\t" ++#if CONFIG_THUMB ++ "lsl %[remain], %[tmp2] \n\t" ++ "rsb %[range], %[remain] \n\t" ++#else ++ "rsb %[range], %[range], %[remain], lsl %[tmp2] \n\t" ++#endif ++ "lsl %[remain], %[prefix], %[rice] \n\t" ++#if CONFIG_THUMB ++ "lsr %[n1], %[n2] \n\t" ++ "add %[remain], %[n1] \n\t" ++#else ++ "add %[remain], %[remain], %[n1], lsr %[n2] \n\t" ++#endif ++ "3: \n\t" ++ "lsl %[ptr], %[ptr], %[tmp1] \n\t" ++ "orr %[range], %[range], %[ptr], lsr #9 \n\t" ++ "4: \n\t" ++ "str %[range], [%[cc], %[low_off]] \n\t" ++ : // Outputs ++ [remain]"=&r"(last_coeff_abs_level_remaining), ++ [rice]"+r"(rice_param), ++ [prefix]"=&r"(prefix), ++ [n1]"=&r"(n1), ++ [range]"=&r"(range), ++ [n2]"=&r"(n2), ++ [ptr]"=&r"(ptr), ++ [tmp1]"=&r"(tmp1), ++ [tmp2]"=&r"(tmp2) ++ : // Inputs ++ [cc]"r"(c), ++ [peek_bits_plus_2]"I"(CABAC_BY22_PEEK_BITS + 2), ++ [low_off]"J"(offsetof(CABACContext, low)), ++ [range_off]"J"(offsetof(CABACContext, range)), ++ [by22_bits_off]"J"(offsetof(CABACContext, by22.bits)), ++ [by22_range_off]"J"(offsetof(CABACContext, by22.range)), ++ [ptr_off]"J"(offsetof(CABACContext, bytestream)) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ return last_coeff_abs_level_remaining; ++} ++ ++#endif /* HAVE_ARMV6T2_INLINE */ ++ ++#endif /* AVCODEC_ARM_HEVC_CABAC_H */ +diff --git a/libavcodec/arm/rpi_hevc_idct_fn_neon.S b/libavcodec/arm/rpi_hevc_idct_fn_neon.S +new file mode 100644 +index 0000000000..978b7b6947 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevc_idct_fn_neon.S +@@ -0,0 +1,183 @@ ++/* ++ * ARM NEON optimised IDCT functions for HEVC decoding ++ * Copyright (c) 2014 Seppo Tomperi ++ * Copyright (C) 2018 John Cox, ben Avison for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++@ Included multiple times from hevc_idct_neon.S ++@ Macros defined there ++ ++#define DC_SHIFT (15 - BIT_DEPTH) ++#define DC_ADD (1 | (1 << (14 - BIT_DEPTH))) ++#define TRN_SHIFT (20 - BIT_DEPTH) ++ ++function JOIN(ff_hevc_rpi_idct_4x4_dc_neon_, BIT_DEPTH), export=1 ++ ldrsh r1, [r0] ++ add r1, #DC_ADD ++ asr r1, #DC_SHIFT ++ vdup.16 q0, r1 ++ vdup.16 q1, r1 ++ vst1.16 {q0, q1}, [r0] ++ bx lr ++endfunc ++ ++function JOIN(ff_hevc_rpi_idct_8x8_dc_neon_, BIT_DEPTH), export=1 ++ ldrsh r1, [r0] ++ add r2, r0, #32 ++ mov r3, #64 ++ add r1, #DC_ADD ++ asr r1, #DC_SHIFT ++ vdup.16 q8, r1 ++ vdup.16 q9, r1 ++ vst1.16 {q8, q9}, [r0], r3 ++ vst1.16 {q8, q9}, [r2], r3 ++ vst1.16 {q8, q9}, [r0] ++ vst1.16 {q8, q9}, [r2] ++ bx lr ++endfunc ++ ++function JOIN(ff_hevc_rpi_idct_16x16_dc_neon_, BIT_DEPTH), export=1 ++ ldrsh r1, [r0] ++ add r2, r0, #32 ++ mov r3, #64 ++ add r1, #DC_ADD ++ mov ip, #16*16 ++ asr r1, #DC_SHIFT ++ vdup.16 q8, r1 ++ vdup.16 q9, r1 ++1: vst1.16 {q8, q9}, [r0], r3 ++ subs ip, ip, #32 ++ vst1.16 {q8, q9}, [r2], r3 ++ bhi 1b ++ bx lr ++endfunc ++ ++function JOIN(ff_hevc_rpi_idct_32x32_dc_neon_, BIT_DEPTH), export=1 ++ ldrsh r1, [r0] ++ add r2, r0, #32 ++ mov r3, #64 ++ add r1, #DC_ADD ++ mov ip, #32*32 ++ asr r1, #DC_SHIFT ++ vdup.16 q8, r1 ++ vdup.16 q9, r1 ++1: vst1.16 {q8, q9}, [r0], r3 ++ subs ip, ip, #32 ++ vst1.16 {q8, q9}, [r2], r3 ++ bhi 1b ++ bx lr ++endfunc ++ ++ ++function JOIN(ff_hevc_rpi_transform_4x4_neon_, BIT_DEPTH), export=1 ++ vldr.i32 s0, =0x00240053 // 36 and 83 ++ vld1.16 {q14, q15}, [r0 :256] // coeffs ++ ++ tr4_shift #7 ++ ++ vzip.16 d28, d29 ++ vzip.16 d30, d31 ++ vzip.32 q14, q15 ++ ++ tr4_shift #TRN_SHIFT ++ ++ vst4.16 {q14, q15}, [r0 :256] ++ bx lr ++ ++ .ltorg ++endfunc ++ ++ ++ ++function JOIN(ff_hevc_rpi_transform_luma_4x4_neon_, BIT_DEPTH), export=1 ++ vmov.i32 d0, #0x4a // 74 ++ vld1.16 {q14, q15}, [r0 :256] // coeffs ++ vmov.i32 d1, #0x1d // 29 ++ vmov.i32 d2, #0x37 // 55 ++ ++ tr4_luma_shift #7 ++ ++ vzip.16 d28, d29 ++ vzip.16 d30, d31 ++ vzip.32 q14, q15 ++ ++ tr4_luma_shift #TRN_SHIFT ++ ++ vst4.16 {q14, q15}, [r0 :256] ++ bx lr ++endfunc ++ ++function JOIN(ff_hevc_rpi_transform_8x8_neon_, BIT_DEPTH), export=1 ++ add r2, r0, #16 ++ adr r3, tr4f ++ vpush {d8-d15} ++ vld1.16 {d0, d1}, [r3] ++ mov r3, #32 ++ ++ tr8_vert d16, d17, d18, d19, d24, d25, d26, d27, q8, q9, \ ++ "sub r0, r0, #128-8", \ ++ "sub r2, r2, #128-8", \ ++ "cmp r1, #4" ++ ble 2f ++ ++ tr8_vert d20, d21, d22, d23, d28, d29, d30, d31, q10, q11, \ ++ "sub r0, r0, #128+8", \ ++ "sub r2, r2, #128+8+16-32", \ ++ "mov r3, #64" ++ ++ vzip.16 d16, d17 ++ vzip.16 d18, d19 ++ ++ vzip.16 d20, d21 ++ vzip.16 d22, d23 ++ vzip.16 d28, d29 ++ vzip.16 d30, d31 ++ vzip.32 q10, q11 ++ vzip.32 q14, q15 ++1: ++ vzip.16 d24, d25 ++ vzip.16 d26, d27 ++ vzip.32 q8, q9 ++ vzip.32 q12, q13 ++ ++ tr8_horiz d16, d17, d18, d19, d20, d21, d22, d23, q8, q9, TRN_SHIFT ++ tr8_horiz d24, d25, d26, d27, d28, d29, d30, d31, q12, q13, TRN_SHIFT ++ ++ vpop {d8-d15} ++ bx lr ++ ++2: vmov.i64 q10, #0 ++ sub r0, r0, #8 ++ vmov.i64 q11, #0 ++ sub r2, r2, #8+16-32 ++ vmov.i64 q14, #0 ++ mov r3, #64 ++ vmov.i64 q15, #0 ++ ++ vzip.16 d16, d17 ++ vzip.16 d18, d19 ++ ++ b 1b ++ ++endfunc ++ ++#undef DC_SHIFT ++#undef DC_ADD ++#undef TRN_SHIFT ++ +diff --git a/libavcodec/arm/rpi_hevc_misc_neon.S b/libavcodec/arm/rpi_hevc_misc_neon.S +new file mode 100644 +index 0000000000..161bb0d7c9 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevc_misc_neon.S +@@ -0,0 +1,267 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Written by John Cox, Ben Avison ++*/ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++@ rpi_zap_coeff_vals_neon( ++@ uint16_t * buf, [r0] ++@ unsigned int log_n_m2) [r1] ++ ++function rpi_zap_coeff_vals_neon, export=1 ++ mov ip, #1 ++ vmov.i64 q0, #0 ++ teq r1, #0 ++ vmov.i64 q1, #0 ++ beq 2f ++ ++ lsl ip, r1 @ 2, 4 or 8 ++ add r2, r0, #32 ++ lsl ip, r1 @ 4, 16 or 64 = number of 32-byte blocks to zero ++ mov r3, #64 ++1: vst1.8 {q0,q1}, [r0:256], r3 ++ subs ip, #2 ++ vst1.8 {q0,q1}, [r2:256], r3 ++ bne 1b ++ bx lr ++ ++2: vst1.8 {q0,q1}, [r0:256] ++ bx lr ++endfunc ++ ++@ PIC jump tables are more expensive than absolute for A32 code ++.set jent_pic, CONFIG_PIC || CONFIG_THUMB ++ ++@ Jump table entry - if in neon mode the bottom bit must be set ++@ ? There is probably a real asm instruction to do this but I haven't found it ++.macro jent lab ++.if jent_pic ++T .short ((0 + \lab) - (0 + 98b)) / 2 ++A .short (0 + \lab) - (4 + 98b) ++.else ++T .word 1 + \lab ++A .word \lab ++.endif ++.endm ++ ++.set expected_next, 0 ++ ++.macro cpy_compound val, p1, p2, drop_thru=0 ++.if \p1 + \p2 != \val ++.error "Bad addition! \p1 + \p2 != \val" ++.endif ++.if expected_next != 0 && expected_next != \val ++.error "Drop thru failure" ++.endif ++\val\(): ++ push {r0-r3} ++ bl 100\p1\()b ++ pop {r0-r3} ++ add r0, #\p1 ++ add r2, #\p1 ++.if \drop_thru == 0 ++ b \p2\()b ++.set expected_next, 0 ++.else ++.set expected_next, \p2 ++.endif ++.endm ++ ++@ ff_hevc_cpy_blks8x4_neon( ++@ dst [r0] ++@ dst_stride [r1] ++@ src [r2] ++@ src_stride [r3] ++@ width [sp, #0] (bytes) ++@ height) [sp, #4] ++@ ++@ Power of 2 widths are directly coded, all others are done in stripes ++@ We expect the vast majority of calls to be power of 2 ++@ ++@ Currently has min width of 8, but we could make that 4 without issue ++@ Min height is 4 ++ ++function ff_hevc_rpi_cpy_blks8x4_neon, export=1 ++ ldr r12, [sp, #0] ++ push {r11, lr} ++.if jent_pic ++A adr lr, 98f - 2 ++.else ++A adr lr, 98f - 4 ++.endif ++ lsr r12, #3 ++ ldr r11, [sp, #(8 + 4)] ++.if jent_pic ++A lsl r12, #1 ++A ldrsh lr, [lr, r12] ++A add pc, lr ++T tbh [pc, r12, lsl #1] ++.else ++ @ A32 only, Thumb is always PIC ++ ldr pc, [lr, r12, lsl #2] ++.endif ++ ++98: ++T .short 0 @ unused ++ jent 8f ++ jent 16f ++ jent 24f ++ jent 32f ++ jent 40f ++ jent 48f ++ jent 56f ++ jent 64f ++ jent 72f ++ jent 80f ++ jent 88f ++ jent 96f ++ jent 104f ++ jent 112f ++ jent 120f ++ jent 128f ++ ++1008: ++ push {r11, lr} ++8: ++ add lr, r2, r3 ++ lsl r3, #1 ++ add r12, r0, r1 ++ lsl r1, #1 ++1: ++ vld1.32 {d0 }, [r2], r3 ++ vld1.32 {d1 }, [lr], r3 ++ vld1.32 {d2 }, [r2], r3 ++ vld1.32 {d3 }, [lr], r3 ++ subs r11, #4 ++ vst1.32 {d0 }, [r0], r1 ++ vst1.32 {d1 }, [r12], r1 ++ vst1.32 {d2 }, [r0], r1 ++ vst1.32 {d3 }, [r12], r1 ++ bgt 1b ++ pop {r11, pc} ++ ++10016: ++ push {r11, lr} ++16: ++ add lr, r2, r3 ++ lsl r3, #1 ++ add r12, r0, r1 ++ lsl r1, #1 ++1: ++ vld1.32 {q0 }, [r2], r3 ++ vld1.32 {q1 }, [lr], r3 ++ vld1.32 {q2 }, [r2], r3 ++ vld1.32 {q3 }, [lr], r3 ++ subs r11, #4 ++ vst1.32 {q0 }, [r0], r1 ++ vst1.32 {q1 }, [r12], r1 ++ vst1.32 {q2 }, [r0], r1 ++ vst1.32 {q3 }, [r12], r1 ++ bgt 1b ++ pop {r11, pc} ++ ++10032: ++ push {r11, lr} ++32: ++ add lr, r2, r3 ++ lsl r3, #1 ++ add r12, r0, r1 ++ lsl r1, #1 ++1: ++ vld1.32 {q8, q9 }, [r2], r3 ++ vld1.32 {q10, q11}, [lr], r3 ++ vld1.32 {q12, q13}, [r2], r3 ++ vld1.32 {q14, q15}, [lr], r3 ++ subs r11, #4 ++ vst1.32 {q8, q9 }, [r0], r1 ++ vst1.32 {q10, q11}, [r12], r1 ++ vst1.32 {q12, q13}, [r0], r1 ++ vst1.32 {q14, q15}, [r12], r1 ++ bgt 1b ++ pop {r11, pc} ++ ++10064: ++ push {r11, lr} ++64: ++ add lr, r2, #32 ++ add r12, r0, #32 ++1: ++ vld1.32 {q8, q9 }, [r2], r3 ++ vld1.32 {q10, q11}, [lr], r3 ++ vld1.32 {q12, q13}, [r2], r3 ++ vld1.32 {q14, q15}, [lr], r3 ++ subs r11, #2 ++ vst1.32 {q8, q9 }, [r0], r1 ++ vst1.32 {q10, q11}, [r12], r1 ++ vst1.32 {q12, q13}, [r0], r1 ++ vst1.32 {q14, q15}, [r12], r1 ++ bgt 1b ++ pop {r11, pc} ++ ++128: ++ push {r4, r5} ++ @ We could do this with fewer registers if we jump around but I ++ @ have a primative urge to load sequentially ++ mov r4, #64 ++ add lr, r2, #32 ++ add r12, r0, #32 ++ sub r3, r4 ++ sub r1, r4 ++1: ++ vld1.32 {q8, q9 }, [r2], r4 ++ vld1.32 {q10, q11}, [lr], r4 ++ vld1.32 {q12, q13}, [r2], r3 ++ vld1.32 {q14, q15}, [lr], r3 ++ subs r11, #1 ++ vst1.32 {q8, q9 }, [r0], r4 ++ vst1.32 {q10, q11}, [r12], r4 ++ vst1.32 {q12, q13}, [r0], r1 ++ vst1.32 {q14, q15}, [r12], r1 ++ bgt 1b ++ pop {r4, r5, r11, pc} ++ ++@ Use drop_thru where we can ++cpy_compound 104, 64, 40, 1 ++cpy_compound 40, 32, 8 ++ ++cpy_compound 112, 64, 48, 1 ++cpy_compound 48, 32, 16 ++ ++cpy_compound 120, 64, 56, 1 ++cpy_compound 56, 32, 24, 1 ++cpy_compound 24, 16, 8 ++ ++cpy_compound 72, 64, 8 ++cpy_compound 80, 64, 16 ++cpy_compound 88, 64, 24 ++cpy_compound 96, 64, 32 ++ ++ ++endfunc ++ +diff --git a/libavcodec/arm/rpi_hevc_misc_neon.h b/libavcodec/arm/rpi_hevc_misc_neon.h +new file mode 100644 +index 0000000000..9d21f6a882 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevc_misc_neon.h +@@ -0,0 +1,438 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_ARM_RPI_HEVC_MISC_H ++#define AVCODEC_ARM_RPI_HEVC_MISC_H ++ ++#include "config.h" ++#if HAVE_NEON_INLINE && !CONFIG_THUMB ++ ++static av_noinline void ff_hevc_rpi_copy_vert_v2h_neon(uint8_t *dst, const uint8_t *src, ++ int pixel_shift, int height, ++ ptrdiff_t stride_src) ++{ ++ const uint8_t *src2 = src + stride_src; ++ stride_src <<= 1; ++ switch (pixel_shift) ++ { ++ case 2: ++ __asm__ volatile ( ++ "vld1.32 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.32 {d0[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.32 {d1[0]}, [%[src]], %[stride_src] \n\t" ++ "subs %[height], #4 \n\t" ++ "vld1.32 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.32 {d2[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.32 {d2[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.32 {d3[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.32 {d3[1]}, [%[src2]], %[stride_src] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.32 {q0}, [%[dst]]! \n\t" ++ "beq 3f \n\t" ++ "vld1.32 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.32 {d0[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.32 {d1[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.32 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.32 {q1}, [%[dst]]! \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vst1.32 {q0}, [%[dst]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vst1.32 {q1}, [%[dst]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [src]"+r"(src), ++ [src2]"+r"(src2), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ case 1: ++ __asm__ volatile ( ++ "vld1.16 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.16 {d1[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.16 {d0[1]}, [%[src]], %[stride_src] \n\t" ++ "subs %[height], #4 \n\t" ++ "vld1.16 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.16 {d2[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.16 {d3[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.16 {d2[1]}, [%[src]], %[stride_src] \n\t" ++ "vld1.16 {d3[1]}, [%[src2]], %[stride_src] \n\t" ++ "vzip.16 d0, d1 \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.16 {d0}, [%[dst]]! \n\t" ++ "beq 3f \n\t" ++ "vld1.16 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.16 {d1[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.16 {d0[1]}, [%[src]], %[stride_src] \n\t" ++ "vld1.16 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "vzip.16 d2, d3 \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.16 {d2}, [%[dst]]! \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vzip.16 d0, d1 \n\t" ++ "vst1.16 {d0}, [%[dst]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vzip.16 d2, d3 \n\t" ++ "vst1.16 {d2}, [%[dst]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [src]"+r"(src), ++ [src2]"+r"(src2), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ default: ++ __asm__ volatile ( ++ "vld1.8 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[1]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[2]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[2]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[3]}, [%[src]], %[stride_src] \n\t" ++ "subs %[height], #8 \n\t" ++ "vld1.8 {d1[3]}, [%[src2]], %[stride_src] \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.8 {d2[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d3[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d2[1]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d3[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d2[2]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d3[2]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d2[3]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d3[3]}, [%[src2]], %[stride_src] \n\t" ++ "vzip.8 d0, d1 \n\t" ++ "subs %[height], #8 \n\t" ++ "vst1.8 {d0}, [%[dst]]! \n\t" ++ "beq 3f \n\t" ++ "vld1.8 {d0[0]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[0]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[1]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[1]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[2]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[2]}, [%[src2]], %[stride_src] \n\t" ++ "vld1.8 {d0[3]}, [%[src]], %[stride_src] \n\t" ++ "vld1.8 {d1[3]}, [%[src2]], %[stride_src] \n\t" ++ "vzip.8 d2, d3 \n\t" ++ "subs %[height], #8 \n\t" ++ "vst1.8 {d2}, [%[dst]]! \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vzip.8 d0, d1 \n\t" ++ "vst1.8 {d0}, [%[dst]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vzip.8 d2, d3 \n\t" ++ "vst1.8 {d2}, [%[dst]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [src]"+r"(src), ++ [src2]"+r"(src2), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ } ++} ++ ++static av_noinline void ff_hevc_rpi_copy_vert_h2v_neon(uint8_t *dst, const uint8_t *src, ++ int pixel_shift, int height, ++ ptrdiff_t stride_dst) ++{ ++ uint8_t *dst2 = dst + stride_dst; ++ stride_dst <<= 1; ++ switch (pixel_shift) ++ { ++ case 2: ++ __asm__ volatile ( ++ "subs %[height], #4 \n\t" ++ "vld1.32 {q0}, [%[src]]! \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.32 {q1}, [%[src]]! \n\t" ++ "vst1.32 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.32 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.32 {d1[0]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.32 {d1[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "beq 3f \n\t" ++ "vld1.32 {q0}, [%[src]]! \n\t" ++ "vst1.32 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.32 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.32 {d3[0]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.32 {d3[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vst1.32 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.32 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.32 {d1[0]}, [%[dst]] \n\t" ++ "vst1.32 {d1[1]}, [%[dst2]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vst1.32 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.32 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.32 {d3[0]}, [%[dst]] \n\t" ++ "vst1.32 {d3[1]}, [%[dst2]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [dst]"+r"(dst), ++ [dst2]"+r"(dst2), ++ [src]"+r"(src), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ case 1: ++ __asm__ volatile ( ++ "subs %[height], #4 \n\t" ++ "vld1.16 {d0}, [%[src]]! \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.16 {d2}, [%[src]]! \n\t" ++ "vst1.16 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.16 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.16 {d0[2]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.16 {d0[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "beq 3f \n\t" ++ "vld1.16 {d0}, [%[src]]! \n\t" ++ "vst1.16 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.16 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.16 {d2[2]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #4 \n\t" ++ "vst1.16 {d2[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vst1.16 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.16 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.16 {d0[2]}, [%[dst]] \n\t" ++ "vst1.16 {d0[3]}, [%[dst2]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vst1.16 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.16 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.16 {d2[2]}, [%[dst]] \n\t" ++ "vst1.16 {d2[3]}, [%[dst2]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [dst]"+r"(dst), ++ [dst2]"+r"(dst2), ++ [src]"+r"(src), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ default: ++ __asm__ volatile ( ++ "subs %[height], #8 \n\t" ++ "vld1.8 {d0}, [%[src]]! \n\t" ++ "beq 2f \n\t" ++ "1: \n\t" ++ "vld1.8 {d2}, [%[src]]! \n\t" ++ "vst1.8 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[2]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[4]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[5]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[6]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #8 \n\t" ++ "vst1.8 {d0[7]}, [%[dst2]], %[stride_dst] \n\t" ++ "beq 3f \n\t" ++ "vld1.8 {d0}, [%[src]]! \n\t" ++ "vst1.8 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[2]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[4]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[5]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[6]}, [%[dst]], %[stride_dst] \n\t" ++ "subs %[height], #8 \n\t" ++ "vst1.8 {d2[7]}, [%[dst2]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "2: \n\t" ++ "vst1.8 {d0[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[2]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[4]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d0[5]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d0[6]}, [%[dst]] \n\t" ++ "vst1.8 {d0[7]}, [%[dst2]] \n\t" ++ "b 4f \n\t" ++ "3: \n\t" ++ "vst1.8 {d2[0]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[1]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[2]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[3]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[4]}, [%[dst]], %[stride_dst] \n\t" ++ "vst1.8 {d2[5]}, [%[dst2]], %[stride_dst] \n\t" ++ "vst1.8 {d2[6]}, [%[dst]] \n\t" ++ "vst1.8 {d2[7]}, [%[dst2]] \n\t" ++ "4: \n\t" ++ : // Outputs ++ [dst]"+r"(dst), ++ [dst2]"+r"(dst2), ++ [src]"+r"(src), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ } ++} ++ ++static av_noinline void ff_hevc_rpi_copy_vert_v2v_neon(uint8_t *dst, const uint8_t *src, ++ int pixel_shift, int height, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src) ++{ ++ int x, y; ++ switch (pixel_shift) ++ { ++ case 2: ++ __asm__ volatile ( ++ "ldr %[x], [%[src]], %[stride_src] \n\t" ++ "ldr %[y], [%[src]], %[stride_src] \n\t" ++ "str %[x], [%[dst]], %[stride_dst] \n\t" ++ "sub %[height], #2 \n\t" ++ "1: \n\t" ++ "ldr %[x], [%[src]], %[stride_src] \n\t" ++ "str %[y], [%[dst]], %[stride_dst] \n\t" ++ "ldr %[y], [%[src]], %[stride_src] \n\t" ++ "subs %[height], #2 \n\t" ++ "str %[x], [%[dst]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "str %[y], [%[dst]] \n\t" ++ : // Outputs ++ [x]"=&r"(x), ++ [y]"=&r"(y), ++ [src]"+r"(src), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src), ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ case 1: ++ __asm__ volatile ( ++ "ldrh %[x], [%[src]], %[stride_src] \n\t" ++ "ldrh %[y], [%[src]], %[stride_src] \n\t" ++ "strh %[x], [%[dst]], %[stride_dst] \n\t" ++ "sub %[height], #2 \n\t" ++ "1: \n\t" ++ "ldrh %[x], [%[src]], %[stride_src] \n\t" ++ "strh %[y], [%[dst]], %[stride_dst] \n\t" ++ "ldrh %[y], [%[src]], %[stride_src] \n\t" ++ "subs %[height], #2 \n\t" ++ "strh %[x], [%[dst]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "strh %[y], [%[dst]] \n\t" ++ : // Outputs ++ [x]"=&r"(x), ++ [y]"=&r"(y), ++ [src]"+r"(src), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src), ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ default: ++ __asm__ volatile ( ++ "ldrb %[x], [%[src]], %[stride_src] \n\t" ++ "ldrb %[y], [%[src]], %[stride_src] \n\t" ++ "strb %[x], [%[dst]], %[stride_dst] \n\t" ++ "sub %[height], #2 \n\t" ++ "1: \n\t" ++ "ldrb %[x], [%[src]], %[stride_src] \n\t" ++ "strb %[y], [%[dst]], %[stride_dst] \n\t" ++ "ldrb %[y], [%[src]], %[stride_src] \n\t" ++ "subs %[height], #2 \n\t" ++ "strb %[x], [%[dst]], %[stride_dst] \n\t" ++ "bne 1b \n\t" ++ "strb %[y], [%[dst]] \n\t" ++ : // Outputs ++ [x]"=&r"(x), ++ [y]"=&r"(y), ++ [src]"+r"(src), ++ [dst]"+r"(dst), ++ [height]"+r"(height) ++ : // Inputs ++ [stride_src]"r"(stride_src), ++ [stride_dst]"r"(stride_dst) ++ : // Clobbers ++ "cc", "memory" ++ ); ++ break; ++ } ++} ++ ++#define ff_hevc_rpi_copy_vert ff_hevc_rpi_copy_vert_neon ++static inline void ff_hevc_rpi_copy_vert_neon(uint8_t *dst, const uint8_t *src, ++ int pixel_shift, int height, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src) ++{ ++ if (stride_dst == 1 << pixel_shift) ++ ff_hevc_rpi_copy_vert_v2h_neon(dst, src, pixel_shift, height, stride_src); ++ else if (stride_src == 1 << pixel_shift) ++ ff_hevc_rpi_copy_vert_h2v_neon(dst, src, pixel_shift, height, stride_dst); ++ else ++ ff_hevc_rpi_copy_vert_v2v_neon(dst, src, pixel_shift, height, stride_dst, stride_src); ++} ++ ++#endif /* HAVE_NEON_INLINE */ ++ ++#endif /* AVCODEC_ARM_RPI_HEVC_MISC_H */ +diff --git a/libavcodec/arm/rpi_hevc_mv_arm.h b/libavcodec/arm/rpi_hevc_mv_arm.h +new file mode 100644 +index 0000000000..325c26a49b +--- /dev/null ++++ b/libavcodec/arm/rpi_hevc_mv_arm.h +@@ -0,0 +1,93 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Written by John Cox, Ben Avison ++*/ ++ ++#ifndef AVCODEC_ARM_RPI_HEVC_MV_H ++#define AVCODEC_ARM_RPI_HEVC_MV_H ++ ++#if HAVE_ARMV6T2_INLINE ++static inline MvXY mvxy_add_arm(const MvXY a, const MvXY b) ++{ ++ MvXY r; ++ __asm__ ( ++ "sadd16 %[r], %[a], %[b] \n\t" ++ : [r]"=r"(r) ++ : [a]"r"(a), ++ [b]"r"(b) ++ : ++ ); ++ return r; ++} ++#define mvxy_add mvxy_add_arm ++#endif ++ ++#if HAVE_ARMV6T2_INLINE ++#if (defined(__ARM_ARCH_EXT_IDIV__) || defined (__ARM_FEATURE_IDIV)) ++static inline int32_t mv_scale_xy_arm(int32_t xy, int td, int tb) ++{ ++ int t; ++ __asm__ ( ++ "ssat %[td], #8, %[td] \n\t" ++ "ssat %[tb], #8, %[tb] \n\t" ++ "eor %[t], %[td], %[td], asr #31 \n\t" ++ "adds %[t], %[t], %[td], lsr #31 \n\t" ++ "asr %[t], #1 \n\t" ++ "add %[t], #0x4000 \n\t" ++ "it ne \n\t" ++ "sdivne %[t], %[t], %[td] \n\t" ++ "mov %[td], #32 \n\t" ++ "smlabb %[td], %[t], %[tb], %[td] \n\t" ++ "ssat %[td], #13, %[td], asr #6 \n\t" ++ "mov %[tb], #127 \n\t" ++ "smlatb %[t], %[xy], %[td], %[tb] \n\t" ++ "smlabb %[tb], %[xy], %[td], %[tb] \n\t" ++// This takes the sign of x & y for rounding at the "wrong" point ++// (i.e. after adding 127) but for the range of values (-1,-127) ++// where it does the wrong thing you get the right answer (0) anyway ++ "add %[t], %[t], %[t], lsr #31 \n\t" ++ "add %[xy], %[tb], %[tb], lsr #31 \n\t" ++ "ssat %[t], #16, %[t], asr #8 \n\t" ++ "ssat %[xy], #16, %[xy], asr #8 \n\t" ++ "pkhbt %[xy], %[xy], %[t], lsl #16 \n\t" ++ : ++ [t]"=&r"(t), ++ [xy]"+r"(xy), ++ [td]"+r"(td), ++ [tb]"+r"(tb) ++ : ++ : ++ "cc" ++ ); ++ return xy; ++} ++#define mv_scale_xy mv_scale_xy_arm ++#endif ++#endif ++ ++#endif // AVCODEC_ARM_RPI_HEVC_MV_H ++ +diff --git a/libavcodec/arm/rpi_hevcdsp_arm.h b/libavcodec/arm/rpi_hevcdsp_arm.h +new file mode 100644 +index 0000000000..62b9326532 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_arm.h +@@ -0,0 +1,26 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_ARM_HEVCDSP_ARM_H ++#define AVCODEC_ARM_HEVCDSP_ARM_H ++ ++#include "libavcodec/rpi_hevcdsp.h" ++ ++void ff_hevcdsp_rpi_init_neon(HEVCDSPContext *c, const int bit_depth); ++ ++#endif /* AVCODEC_ARM_HEVCDSP_ARM_H */ +diff --git a/libavcodec/arm/rpi_hevcdsp_deblock_neon.S b/libavcodec/arm/rpi_hevcdsp_deblock_neon.S +new file mode 100644 +index 0000000000..88a3b4e5e7 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_deblock_neon.S +@@ -0,0 +1,1634 @@ ++/* ++ * Copyright (c) 2014 Seppo Tomperi ++ * Copyright (C) 2018 John Cox, Ben Avison for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1 ++ */ ++ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++.macro hevc_loop_filter_uv_body1 P1a, P0a, Q0a, Q1a, I1, I2, I3, I4, I5, I6, I7, I8 ++ vsubl.u8 q0, \Q0a, \P0a ++ vsubl.u8 q1, \P1a, \Q1a ++ vdup.16 d4, r2 ++ \I1 ++ vshl.i16 q0, #2 ++ \I2 ++ vadd.i16 q0, q1 ++ \I3 ++ vmovl.u8 q2, d4 ++ \I4 ++ vneg.s16 q1, q2 ++ \I5 ++ vrshr.s16 q0, #3 ++ \I6 ++ \I7 ++ \I8 ++ vmin.s16 q0, q2 ++ vmovl.u8 q2, \Q0a ++ vmax.s16 q0, q1 ++ vaddw.u8 q1, q0, \P0a ++ vsub.i16 q0, q2, q0 ++ vqmovun.s16 \P0a, q1 ++ vqmovun.s16 \Q0a, q0 ++.endm ++ ++ ++.macro hevc_loop_filter_uv_body2 P1a, P1b, P0a, P0b, Q0a, Q0b, Q1a, Q1b, I1, I2, I3, I4, I5, I6, I7 ++ vsubl.u8 q0, \Q0a, \P0a @ q0a - p0a ++ lsr r12, r2, #16 ++ vsubl.u8 q1, \Q0b, \P0b @ q0b - p0b ++ vsubl.u8 q2, \P1a, \Q1a @ p1a - q1a ++ vsubl.u8 q3, \P1b, \Q1b @ p1b - q1b ++ vshl.i16 q0, #2 @ (q0a - p0a) * 4 ++ vshl.i16 q1, #2 @ (q0b - p0b) * 4 ++ vadd.i16 q0, q2 @ ((q0a - p0a) * 4) + p1a - q1a ++ vadd.i16 q1, q3 @ ((q0b - p0b) * 4) + p1b - q1b ++ vdup.16 d4, r2 @ tc0a, tc0b ++ vdup.16 d6, r12 @ tc1a, tc1b ++ vrshr.s16 q0, #3 @ (((q0a - p0a) * 4) + p1a - q1a + 4) >> 3 ++ \I1 ++ vrshr.s16 q1, #3 @ (((q0b - p0b) * 4) + p1b - q1b + 4) >> 3 ++ \I2 ++ vmovl.u8 q2, d4 @ tc0a, tc0b ++ \I3 ++ vmovl.u8 q3, d6 @ tc1a, tc1b ++ \I4 ++ vmin.s16 q0, q2 ++ \I5 ++ vneg.s16 q2, q2 @ -tc0a, -tc0b ++ \I6 ++ vmin.s16 q1, q3 ++ \I7 ++ vneg.s16 q3, q3 @ -tc1a, -tc1b ++ vmax.s16 q0, q2 @ delta0a ++ vmovl.u8 q2, \Q0a ++ vmax.s16 q1, q3 @ delta0b ++ vaddw.u8 q3, q0, \P0a @ p0a + delta0a ++ vsub.i16 q0, q2, q0 @ q0a - delta0a ++ vmovl.u8 q2, \Q0b ++ vsub.i16 q2, q1 @ q0b - delta0b ++ vaddw.u8 q1, \P0b @ p0b + delta0b ++ vqmovun.s16 \Q0a, q0 ++ vqmovun.s16 \P0a, q3 ++ vqmovun.s16 \Q0b, q2 ++ vqmovun.s16 \P0b, q1 ++.endm ++ ++ ++@ Preserves r12 ++@ Clobbers r2 ++@ P0a et al all contain UVUVUVUV ++@ r2 (tc4) contains ++@ [0..7] tc U a ++@ [8..15] tc V a ++ ++.macro hevc_loop_filter_uv_body1_16 P1a, P0a, Q0a, Q1a, bit_depth, I1, I2, I3, I4, I5, I6, I7, I8 ++ vsub.i16 q0, \Q0a, \P0a ++ vsub.i16 q1, \P1a, \Q1a ++ vdup.16 d4, r2 ++ \I1 ++ vshl.i16 q0, #2 ++ \I2 ++ vadd.i16 q0, q1 ++ \I3 ++ vshll.u8 q2, d4, #\bit_depth - 8 ++ \I4 ++ vneg.s16 q1, q2 ++ \I5 ++ vrshr.s16 q0, #3 ++ \I6 ++ \I7 ++ \I8 ++ vmin.s16 q0, q2 ++ vmov.i16 q2, #0 ++ vmax.s16 q0, q1 ++ vadd.i16 \P0a, q0 ++ vsub.i16 \Q0a, q0 ++ vmov.i16 q1, #(1 << \bit_depth) - 1 ++ vmax.s16 \P0a, q2 ++ vmax.s16 \Q0a, q2 ++ vmin.s16 \P0a, q1 ++ vmin.s16 \Q0a, q1 ++.endm ++ ++@ Clobbers r2, r12 ++@ P0a et al all contain UVUVUVUV ++@ r2 (tc4) contains ++@ [0..7] tc U a ++@ [8..15] tc V a ++@ [16..23] tc U b ++@ [24..31] tc V b ++ ++.macro hevc_loop_filter_uv_body2_16 P1a, P1b, P0a, P0b, Q0a, Q0b, Q1a, Q1b, bit_depth, I1, I2, I3, I4, I5, I6, I7 ++ vsub.i16 q0, \Q0a, \P0a @ q0a - p0a ++ lsr r12, r2, #16 ++ vsub.i16 q1, \Q0b, \P0b @ q0b - p0b ++ vsub.i16 q2, \P1a, \Q1a @ p1a - q1a ++ vsub.i16 q3, \P1b, \Q1b @ p1b - q1b ++ vshl.i16 q0, #2 @ (q0a - p0a) * 4 ++ vshl.i16 q1, #2 @ (q0b - p0b) * 4 ++ vadd.i16 q0, q2 @ ((q0a - p0a) * 4) + p1a - q1a ++ vadd.i16 q1, q3 @ ((q0b - p0b) * 4) + p1b - q1b ++ vdup.16 d4, r2 @ tc0a, tc0b ++ vdup.16 d6, r12 @ tc1a, tc1b ++ vrshr.s16 q0, #3 @ (((q0a - p0a) * 4) + p1a - q1a + 4) >> 3 ++ \I1 ++ vrshr.s16 q1, #3 @ (((q0b - p0b) * 4) + p1b - q1b + 4) >> 3 ++ \I2 ++ vshll.u8 q2, d4, #\bit_depth - 8 @ tc0a, tc0b ++ \I3 ++ vshll.u8 q3, d6, #\bit_depth - 8 @ tc1a, tc1b ++ \I4 ++ vmin.s16 q0, q2 ++ \I5 ++ vneg.s16 q2, q2 @ -tc0a, -tc0b ++ \I6 ++ vmin.s16 q1, q3 ++ \I7 ++ vneg.s16 q3, q3 @ -tc1a, -tc1b ++ vmax.s16 q0, q2 @ delta0a ++ vadd.i16 \P0a, q0 @ p0a + delta0a ++ vsub.i16 \Q0a, q0 @ q0a - delta0a ++ vmax.s16 q1, q3 @ delta0b ++ vadd.i16 \P0b, q1 @ p0b + delta0b ++ vsub.i16 \Q0b, q1 @ q0b - delta0b ++ vmov.i16 q2, #0 ++ vmov.i16 q3, #(1 << \bit_depth) - 1 ++ vmax.s16 \P0a, q2 ++ vmax.s16 \Q0a, q2 ++ vmax.s16 \P0b, q2 ++ vmax.s16 \Q0b, q2 ++ vmin.s16 \P0a, q3 ++ vmin.s16 \Q0a, q3 ++ vmin.s16 \P0b, q3 ++ vmin.s16 \Q0b, q3 ++.endm ++ ++ ++ ++@ uint8_t *_no_p, [sp+0] ++@ uint8_t *_no_q) [sp+4] ++ ++.macro hevc_loop_filter_luma_start ++ ldr r12, [r3] ++ ldr r3, [r3, #4] ++ orrs r3, r12, r3, lsl #16 ++ it eq ++ bxeq lr ++ push {r4-r10,lr} @ 32 bytes ++ ldrd r4, r5, [sp, #32] @ &_no_p ++ ldrb r4, [r4] ++ ldrb r5, [r5] ++ movs r10, r4 ++ it ne ++ movne r10, #1 ++ cmp r5, #0 ++ it ne ++ orrne r10, #2 ++.endm ++ ++@ Input: ++@ r2 beta (raw: needs shift for bitdepth > 8) ++@ r3[ 0:15] tc[0] (raw: needs shift for bitdepth > 8) ++@ r3[16:31] tc[1] (raw: needs shift for bitdepth > 8) ++@ ++@ Input & output ++@ 8-bit: d16-d23 (Q3,Q2,Q1,Q0,P0,P1,P2,P3) ++@ 16-bit: q8-q15 ++@ ++@ r1 -r1 ++@ r10 b1->C, b0->N (r10 junk) ++@ ++@ Junks: ++@ r5, r6, r7, r8, r9 ++ ++.macro m_filter_luma bit_depth, Q11, Q15 ++.if \bit_depth == 8 ++ vmovl.u8 q14, d22 @ q2,7 q2,6 ... q2,0 = TQ2' ... Q2' TQ2 ... Q2 ++ vmovl.u8 q13, d21 @ q1,7 q1,6 ... q1,0 = TQ1' ... Q1' TQ1 ... Q1 ++ vmovl.u8 q12, d20 @ q0,7 q0,6 ... q0,0 = TQ0' ... Q0' TQ0 ... Q0 ++ vmovl.u8 \Q11, d19 @ p0,7 p0,6 ... p0,0 = TP0' ... P0' TP0 ... P0 ++ vmovl.u8 q10, d18 @ p1,7 p1,6 ... p1,0 = TP1' ... P1' TP1 ... P1 ++ vmovl.u8 q9, d17 @ p2,7 p2,6 ... p2,0 = TP2' ... P2' TP2 ... P2 ++.endif ++ vadd.i16 q0, q9, \Q11 @ P2 + P0 ++.if \bit_depth > 8 ++ lsl r3, r3, #(\bit_depth - 8) ++.endif ++ vadd.i16 q1, q14, q12 @ Q2 + Q0 ++.if \bit_depth > 8 ++ lsl r2, r2, #(\bit_depth - 8) ++.endif ++ vsub.i16 q0, q10 @ P2 - P1 + P0 ++ lsr r5, r3, #16 ++ vsub.i16 q1, q13 @ Q2 - Q1 + Q0 ++.if \bit_depth == 8 ++ vmovl.u8 q8, d16 @ p3,7 p3,6 ... p3,0 = TP3' ... P3' TP3 ... P3 ++ vmovl.u8 \Q15, d23 @ q3,7 q3,6 ... q3,0 = TQ3' ... Q3' TQ3 ... Q3 ++.endif ++ vabd.s16 q0, q10 @ dp0 = abs(P2 - 2 * P1 + P0) ++ vabd.s16 q1, q13 @ dq0 = abs(Q2 - 2 * Q1 + Q0) ++ vmov.i64 q2, #0xffffffff0000 ++ vbic q0, q2 @ only dp0(') and dp3(') ++ vbic q1, q2 @ only dq0(') and dq3(') ++ vsra.u64 q0, #16 ++ vsra.u64 q1, #16 ++ vdup.16 q3, r2 @ beta ++ vdup.16 d14, r3 @ tC[0] ++ vdup.16 d15, r5 @ tC[1] ++ vabd.s16 q4, q8, \Q11 @ abs(TP3'-TP0' ... P3'-P0' TP3-TP0 ... P3-P0) ++ vmovn.i32 d0, q0 @ dp3' dp0' dp3 dp0 ++ vmovn.i32 d1, q1 @ dq3' dq0' dq3 dq0 ++ vadd.i16 d5, d0, d1 @ d3'=dp3'+dq3' d0'=dp0'+dq0' d3=dp3+dq3 d0=dp0+dq0 ++ vabd.s16 q5, \Q11, q12 @ abs(TP0'-TQ0' ... P0'-Q0' TP0-TQ0 ... P0-Q0) ++ vaba.s16 q4, \Q15, q12 @ +abs(TQ3'-TQ0' ... Q3'-Q0' TQ3-TQ0 ... Q3-Q0) ++ vpadd.i16 d2, d5, d5 @ dontcare dontcare d0'+d3' d0+d3 ++ vshl.s16 q6, q7, #2 @ tC[] * 4 ++ vrhadd.s16 q6, q7 @ tc25 = (tc[] * 5 + 1) >> 1 ++ vcgt.s16 d2, d6, d2 @ if (d0 + d3 < beta) ++ vmov r7, s4 @ (d2) r7 = mask of blocks to apply filtering (16b/block) ++ vshr.s16 q1, q3, #3 @ beta_3 = beta >> 3 ++ cmp r7, #0 ++ beq .Lbypasswrite ++ ++ vcgt.s16 q5, q6, q5 @ if < tc25 ++ vcgt.s16 q4, q1, q4 @ if (abs({T}P[0-3]{'}-{T}P[0-3]{'})+abs({T}Q[0-3]{'}-{T}Q[0-3]{'}) < beta_3) ++ vand q4, q5 ++ vbic d8, d4 ++ vbic d9, d4 ++ vshr.s16 q3, #2 @ beta_2 = beta >> 2 ++ vsra.u64 q4, #16 ++ vshl.s16 d5, #1 @ d3'<<1 d0'<<1 d3<<1 d0<<1 ++ vshl.i16 q7, #1 @ tc2 = tC[] << 1 ++ vcgt.s16 d6, d5 @ if (d3'<<1 < beta_2) etc ++ vmovn.i32 d8, q4 @ beta_3 && tc25 tests, prime block in ms half ++ vand d6, d8 @ && beta_2 tests, prime in ms half ++ vpadd.i16 d0, d1 @ dq0'+dq3' dq0+dq3 dp0'+dp3' dp0+dp3 ++ vneg.s16 q6, q7 @ -tc2 ++ vmovn.i32 d8, q3 ++ vshrn.i32 d6, q3, #16 ++ vand d6, d8 ++ vmov r5, r6, d0 @ r5 = dp0'+dp3' dp0+dp3 r6 = dq0'+dq3' dq0+dq3 ++ vmov r8, s12 @ (d6) r8 = mask of strong filtering blocks (16b/block) ++ vadd.i16 q0, \Q11, q12 @ p0 + q0 ++ ands r9, r7, r8 ++ beq 1f ++ ++ vadd.i16 q2, q0, q10 @ p1 + p0 + q0 ++ vadd.i16 q3, q0, q13 @ p0 + q0 + q1 ++ lsr r3, r9, #16 ++ vadd.i16 q1, q2, q9 @ p2 + p1 + p0 + q0 (new P1 before clipping) ++ vadd.i16 q4, q3, q14 @ p0 + q0 + q1 + q2 (new Q1 before clipping) ++ vadd.i16 q0, q8, q9 @ p3 + p2 ++ vadd.i16 q5, \Q15, q14 @ q2 + q3 ++ vadd.i16 q2, q1 @ p2 + 2 * p1 + 2 * p0 + 2 * q0 ++ vadd.i16 q3, q4 @ 2 * p0 + 2 * q0 + 2 * q1 + q2 ++ vshl.i16 q0, #1 @ 2 * p3 + 2 * p2 ++ vshl.i16 q5, #1 @ 2 * q2 + 2 * q3 ++ vadd.i16 q0, q1 @ 2 * p3 + 3 * p2 + p1 + p0 + q0 (new P2 before clipping) ++ vadd.i16 q5, q4 @ p0 + q0 + q1 + 3 * q2 + 2 * q3 (new Q2 before clipping) ++ vadd.i16 q2, q13 @ p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 (new P0 before clipping) ++ vadd.i16 q3, q10 @ p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 (new Q0 before clipping) ++ vrshr.s16 q0, #3 @ scale, with rounding ++ vrshr.s16 q5, #3 ++ vrshr.s16 q1, #2 ++ vrshr.s16 q4, #2 ++ vrshr.s16 q2, #3 ++ vrshr.s16 q3, #3 ++ vsub.i16 q0, q9 @ find difference ++ vsub.i16 q5, q14 ++ vsub.i16 q1, q10 ++ vsub.i16 q4, q13 ++ vsub.i16 q2, \Q11 ++ vsub.i16 q3, q12 ++ vmax.s16 q0, q6 @ clip difference to -tc2 .. tc2 ++ vmax.s16 q5, q6 ++ vmax.s16 q1, q6 ++ vmax.s16 q4, q6 ++ vmax.s16 q2, q6 ++ vmax.s16 q3, q6 ++ vdup.16 d12, r9 @ expand mask, reuse q6 due to register pressure ++ vdup.16 d13, r3 ++ vmin.s16 q0, q7 ++ vmin.s16 q5, q7 ++ vmin.s16 q1, q7 ++ vmin.s16 q4, q7 ++ vmin.s16 q2, q7 ++ vmin.s16 q3, q7 ++ vadd.i16 q0, q9 @ apply difference ++ vadd.i16 q5, q14 ++ vadd.i16 q1, q10 ++ vadd.i16 q4, q13 ++ vadd.i16 q2, \Q11 ++ vadd.i16 q3, q12 ++ vbit q9, q0, q6 @ apply filtered values according to mask ++ vbit q14, q5, q6 ++ vbit q10, q1, q6 ++ vbit q13, q4, q6 ++ vbit \Q11, q2, q6 ++ vbit q12, q3, q6 ++ vneg.s16 q6, q7 @ restore -tc2 ++ ++1: ++ bics r9, r7, r8 ++ beq 2f ++ ++ vsub.i16 q0, q12, \Q11 @ q0 - p0 ++ vsub.i16 q1, q13, q10 @ q1 - p1 ++ lsr r3, r9, #16 ++ vshl.i16 q2, q0, #3 ++ lsr r7, r5, #16 ++ vadd.i16 q3, q0, q2 @ 9 * (q0 - p0) ++ lsr r8, r6, #16 ++ vshl.i16 q2, q1, #1 ++ vadd.i16 q4, q1, q2 @ 3 * (q1 - p1) ++ vshr.s16 q6, #1 @ -tc = -tc2 >> 1 ++ vsub.i16 q5, q3, q4 ++ vrhadd.s16 q1, q9, \Q11 @ (p2 + p0 + 1) >> 1 ++ vrhadd.s16 q3, q14, q12 @ (q2 + q0 + 1) >> 1 ++ vrshr.s16 q5, #4 @ delta0 = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4 ++ vsub.i16 q1, q10 @ ((p2 + p0 + 1) >> 1) - p1 ++ vsub.i16 q3, q13 @ ((q2 + q0 + 1) >> 1) - q1 ++ vmax.s16 q6, q5 @ ++ vshr.s16 q4, q7, #1 @ tc = tc2 >> 1 ++ vdup.16 q0, r2 @ beta ++ vmin.s16 q6, q4 @ delta0 clamped to [-tc, tc] ++ vshr.s16 q4, #1 @ tc_2 = tc >> 1 ++ vhadd.s16 q1, q6 @ (((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1 ++ vhsub.s16 q3, q6 @ (((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1 ++ vshr.s16 q2, q0, #1 @ beta >> 1 ++ vadd.i16 q2, q0 @ beta + (beta >> 1) ++ vneg.s16 q0, q4 @ -tc_2 ++ vabs.s16 q5, q5 @ abs(original delta0) ++ vshr.s16 q2, #3 @ (beta + (beta >> 1)) >> 3 ++ vmax.s16 q1, q0 ++ vmax.s16 q3, q0 ++ vshl.s16 q0, q7, #2 @ 8 * tc ++ vadd.i16 q7, q0 @ 10 * tc ++ vdup.16 d0, r9 ++ vdup.16 d1, r3 @ q0 = mask of blocks to apply filtering ++ vmin.s16 q1, q4 @ deltap1 = av_clip((((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1, -tc_2, tc_2) ++ vmin.s16 q3, q4 @ deltaq1 = av_clip((((q2 + q0 + 1) >> 1) - q1 + delta0) >> 1, -tc_2, tc_2) ++ vdup.16 d8, r5 @ dp0 + dp3 ++ vdup.16 d9, r7 @ dp0' + dp3' ++ vcgt.s16 q7, q5 @ if ((10 * tc) > abs(delta0)) ++ vdup.16 d10, r6 @ dq0 + dq3 ++ vdup.16 d11, r8 @ dq0' + dq3' ++ vand q7, q0 @ AND block and line masks ++ vcgt.s16 q4, q2, q4 @ if (((beta + (beta >> 1)) >> 3) > dp0 + dp3), i.e. if (nd_p > 1) ++ vadd.i16 q0, q1, q10 @ p1 + deltap1 ++ vcgt.s16 q5, q2, q5 @ if (((beta + (beta >> 1)) >> 3) > dq0 + dq3), i.e. if (nd_q > 1) ++ vadd.i16 q3, q3, q13 @ q1 + deltaq1 ++ vadd.i16 q1, \Q11, q6 @ p0 + delta0 ++ vsub.i16 q2, q12, q6 @ q0 - delta0 ++ vand q4, q7 @ AND nd_p test with block/line masks ++ vand q5, q7 @ AND nd_q test with block/line masks ++ vbit q10, q0, q4 ++ vbit \Q11, q1, q7 ++ vbit q12, q2, q7 ++ vbit q13, q3, q5 ++ ++2: ++.if \bit_depth == 8 ++ vmovn.i16 d16, q8 ++ vmovn.i16 d23, \Q15 ++ neg r1, r1 ++ vqmovun.s16 d17, q9 ++ vqmovun.s16 d18, q10 ++ vqmovun.s16 d19, \Q11 ++ lsls r10, #31 ++ vqmovun.s16 d20, q12 ++ vqmovun.s16 d21, q13 ++ vqmovun.s16 d22, q14 ++.else ++ vmov.i16 q0, #0 ++ vmov.i16 q1, #(1 << \bit_depth - 1) ++ @ q8 & q15 should be unaltered and so don't require clipping ++ neg r1, r1 ++ vmax.s16 q9, q0 ++ vmax.s16 q10, q0 ++ vmax.s16 q11, q0 ++ vmax.s16 q12, q0 ++ vmax.s16 q13, q0 ++ vmax.s16 q14, q0 ++ lsls r10, #31 ++ vmin.s16 q9, q1 ++ vmin.s16 q10, q1 ++ vmin.s16 q11, q1 ++ vmin.s16 q12, q1 ++ vmin.s16 q13, q1 ++ vmin.s16 q14, q1 ++.endif ++ bx lr ++.endm ++ ++function hevc_loop_filter_luma_body ++ m_filter_luma 8, q15, q11 ++endfunc ++ ++@ void ff_hevc_rpi_v_loop_filter_luma_neon_8( ++@ uint8_t *_pix, [r0] ++@ ptrdiff_t _stride, [r1] ++@ int _beta, [r2] ++@ int *_tc, [r3] ++@ uint8_t *_no_p, [sp+0] ++@ uint8_t *_no_q) [sp+4] ++ ++function ff_hevc_rpi_v_loop_filter_luma_neon_8, export=1 ++ hevc_loop_filter_luma_start ++ ++ sub r4, r0, #4 ++ b .Lv_loop_luma_common ++endfunc ++ ++@ void ff_hevc_rpi_v_loop_filter2_luma_neon( ++@ uint8_t * pix_r, [r0] ++@ ptrdiff_t _stride, [r1] ++@ int _beta, [r2] ++@ int tc2, [r3] ++@ int no_f, [sp+0] ++@ uint8_t * pix_l) [sp+4] ++ ++function ff_hevc_rpi_v_loop_filter_luma2_neon_8, export=1 ++ cmp r3, #0 ++ it eq ++ bxeq lr ++ push {r4-r10,lr} @ 32 bytes ++ ldr r4, [sp, #36] ++ ldr r10, [sp, #32] ++ ++.Lv_loop_luma_common: ++ vpush {d8-d15} ++ ++ @ It's slightly faster to do unlaned loads and transpose in the ++ @ 8-bit case, even though it needs more instructions, because ++ @ VLD4.8 is a really slow way to read from memory. ++ vld1.32 {d16[0]}, [r4:32], r1 ++ vld1.32 {d20[0]}, [r0:32], r1 ++ vld1.32 {d16[1]}, [r4:32], r1 ++ vld1.32 {d20[1]}, [r0:32], r1 ++ vld1.32 {d17[0]}, [r4:32], r1 ++ vld1.32 {d21[0]}, [r0:32], r1 ++ vld1.32 {d17[1]}, [r4:32], r1 ++ vld1.32 {d21[1]}, [r0:32], r1 ++ vld1.32 {d18[0]}, [r4:32], r1 ++ vld1.32 {d22[0]}, [r0:32], r1 ++ vld1.32 {d18[1]}, [r4:32], r1 ++ vld1.32 {d22[1]}, [r0:32], r1 ++ vld1.32 {d19[0]}, [r4:32], r1 ++ vld1.32 {d23[0]}, [r0:32], r1 ++ vld1.32 {d19[1]}, [r4:32] ++ vld1.32 {d23[1]}, [r0:32] ++ vuzp.16 q8, q9 ++ vuzp.16 q10, q11 ++ vuzp.8 q8, q9 ++ vuzp.8 q10, q11 ++ vswp d17, d18 ++ vswp d21, d22 ++ ++ bl hevc_loop_filter_luma_body ++ ++ add r6, r4, r1 ++ add r2, r0, r1 ++ lsl r1, #1 ++ ++ vpop {d8-d15} ++ ++ @ no_p[1] ++ bmi 1f ++ vst4.8 {d16[7],d17[7],d18[7],d19[7]}, [r4:32], r1 ++ vst4.8 {d16[6],d17[6],d18[6],d19[6]}, [r6:32], r1 ++ vst4.8 {d16[5],d17[5],d18[5],d19[5]}, [r4:32], r1 ++ vst4.8 {d16[4],d17[4],d18[4],d19[4]}, [r6:32], r1 ++ ++ vst4.8 {d16[3],d17[3],d18[3],d19[3]}, [r4:32], r1 ++ vst4.8 {d16[2],d17[2],d18[2],d19[2]}, [r6:32], r1 ++ vst4.8 {d16[1],d17[1],d18[1],d19[1]}, [r4:32], r1 ++ vst4.8 {d16[0],d17[0],d18[0],d19[0]}, [r6:32] ++1: ++ @ no_q[1] ++ bcs 1f ++ vst4.8 {d20[7],d21[7],d22[7],d23[7]}, [r0:32], r1 ++ vst4.8 {d20[6],d21[6],d22[6],d23[6]}, [r2:32], r1 ++ vst4.8 {d20[5],d21[5],d22[5],d23[5]}, [r0:32], r1 ++ vst4.8 {d20[4],d21[4],d22[4],d23[4]}, [r2:32], r1 ++ ++ vst4.8 {d20[3],d21[3],d22[3],d23[3]}, [r0:32], r1 ++ vst4.8 {d20[2],d21[2],d22[2],d23[2]}, [r2:32], r1 ++ vst4.8 {d20[1],d21[1],d22[1],d23[1]}, [r0:32], r1 ++ vst4.8 {d20[0],d21[0],d22[0],d23[0]}, [r2:32] ++1: ++ pop {r4-r10,pc} ++ ++.Lbypasswrite: ++ vpop {d8-d15} ++ pop {r4-r10,pc} ++endfunc ++ ++.macro m_filter_v_luma_16 bit_depth ++ vpush {d8-d15} ++ ++ @ Uses slightly fewer instructions to do laned loads than unlaned ++ @ and transpose. This also means that we can use the same code for ++ @ both split & unsplit deblock ++ vld4.16 {d16[0], d18[0], d20[0], d22[0]}, [r4], r1 ++ vld4.16 {d24[0], d26[0], d28[0], d30[0]}, [r0], r1 ++ ++ vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r4], r1 ++ vld4.16 {d24[1], d26[1], d28[1], d30[1]}, [r0], r1 ++ ++ vld4.16 {d16[2], d18[2], d20[2], d22[2]}, [r4], r1 ++ vld4.16 {d24[2], d26[2], d28[2], d30[2]}, [r0], r1 ++ ++ vld4.16 {d16[3], d18[3], d20[3], d22[3]}, [r4], r1 ++ vld4.16 {d24[3], d26[3], d28[3], d30[3]}, [r0], r1 ++ ++ vld4.16 {d17[0], d19[0], d21[0], d23[0]}, [r4], r1 ++ vld4.16 {d25[0], d27[0], d29[0], d31[0]}, [r0], r1 ++ ++ vld4.16 {d17[1], d19[1], d21[1], d23[1]}, [r4], r1 ++ vld4.16 {d25[1], d27[1], d29[1], d31[1]}, [r0], r1 ++ ++ vld4.16 {d17[2], d19[2], d21[2], d23[2]}, [r4], r1 ++ vld4.16 {d25[2], d27[2], d29[2], d31[2]}, [r0], r1 ++ ++ vld4.16 {d17[3], d19[3], d21[3], d23[3]}, [r4] ++ vld4.16 {d25[3], d27[3], d29[3], d31[3]}, [r0] ++ ++ bl hevc_loop_filter_luma_body_\bit_depth ++ ++ add r6, r4, r1 ++ add r2, r0, r1 ++ lsl r1, #1 ++ ++ vpop {d8-d15} ++ ++ @ p[1] ++ bmi 1f ++ vst4.16 {d17[3], d19[3], d21[3], d23[3]}, [r4], r1 ++ vst4.16 {d17[2], d19[2], d21[2], d23[2]}, [r6], r1 ++ vst4.16 {d17[1], d19[1], d21[1], d23[1]}, [r4], r1 ++ vst4.16 {d17[0], d19[0], d21[0], d23[0]}, [r6], r1 ++ vst4.16 {d16[3], d18[3], d20[3], d22[3]}, [r4], r1 ++ vst4.16 {d16[2], d18[2], d20[2], d22[2]}, [r6], r1 ++ vst4.16 {d16[1], d18[1], d20[1], d22[1]}, [r4], r1 ++ vst4.16 {d16[0], d18[0], d20[0], d22[0]}, [r6] ++1: ++ @ q[1] ++ bcs 1f ++ vst4.16 {d25[3], d27[3], d29[3], d31[3]}, [r0], r1 ++ vst4.16 {d25[2], d27[2], d29[2], d31[2]}, [r2], r1 ++ vst4.16 {d25[1], d27[1], d29[1], d31[1]}, [r0], r1 ++ vst4.16 {d25[0], d27[0], d29[0], d31[0]}, [r2], r1 ++ vst4.16 {d24[3], d26[3], d28[3], d30[3]}, [r0], r1 ++ vst4.16 {d24[2], d26[2], d28[2], d30[2]}, [r2], r1 ++ vst4.16 {d24[1], d26[1], d28[1], d30[1]}, [r0], r1 ++ vst4.16 {d24[0], d26[0], d28[0], d30[0]}, [r2] ++1: ++ pop {r4-r10,pc} ++.endm ++ ++ ++ ++ ++@ void (*hevc_h_loop_filter_luma)(uint8_t *pix, [r0] ++@ ptrdiff_t stride, [r1] ++@ int beta, [r2] ++@ int32_t *tc, [r3] ++@ uint8_t *no_p, sp[0] ++@ uint8_t *no_q); sp[4] ++@ ++@ Src should always be on 8 byte boundry & all in the same slice ++ ++function ff_hevc_rpi_h_loop_filter_luma_neon_8, export=1 ++ hevc_loop_filter_luma_start ++ b .Lh_loop_filter_luma_common_8 ++endfunc ++ ++function ff_hevc_rpi_h_loop_filter_luma2_neon_8, export=1 ++ cmp r3, #0 ++ it eq ++ bxeq lr ++ push {r4-r10,lr} @ 32 bytes ++ ldr r10, [sp, #32] ++ ++.Lh_loop_filter_luma_common_8: ++ sub r4, r0, r1, lsl #2 ++ add r0, r4, r1 ++ lsl r1, #1 ++ vpush {d8-d15} ++ ++ vld1.8 {d16}, [r4], r1 ++ vld1.8 {d17}, [r0], r1 ++ vld1.8 {d18}, [r4], r1 ++ vld1.8 {d19}, [r0], r1 ++ vld1.8 {d20}, [r4], r1 ++ vld1.8 {d21}, [r0], r1 ++ vld1.8 {d22}, [r4] ++ vld1.8 {d23}, [r0] ++ ++ bl hevc_loop_filter_luma_body ++ ++ add r0, r0, r1, lsl #1 ++ add r2, r4, r1, lsl #1 ++ add r6, r4, r1, asr #1 ++ vpop {d8-d15} ++ ++ @ P2-P0 ++ bcs 1f ++ vst1.8 {d22}, [r4], r1 ++ vst1.8 {d21}, [r6] ++ vst1.8 {d20}, [r4] ++1: ++ @ Q0-Q2 ++ bmi 1f ++ vst1.8 {d19}, [r0], r1 ++ vst1.8 {d18}, [r2] ++ vst1.8 {d17}, [r0] ++1: ++ pop {r4-r10,pc} ++endfunc ++ ++ ++.macro m_filter_h_luma_16 bit_depth ++ sub r4, r0, r1, lsl #2 ++ add r0, r4, r1 ++ lsl r1, #1 ++ vpush {d8-d15} ++ ++ vld1.16 { q8}, [r4], r1 ++ vld1.16 { q9}, [r0], r1 ++ vld1.16 {q10}, [r4], r1 ++ vld1.16 {q11}, [r0], r1 ++ vld1.16 {q12}, [r4], r1 ++ vld1.16 {q13}, [r0], r1 ++ vld1.16 {q14}, [r4] ++ vld1.16 {q15}, [r0] ++ ++ bl hevc_loop_filter_luma_body_\bit_depth ++ ++ add r0, r0, r1, lsl #1 ++ add r2, r4, r1, lsl #1 ++ add r6, r4, r1, asr #1 ++ vpop {d8-d15} ++ ++ @ P2-P0 ++ bcs 1f ++ vst1.16 {q14}, [r4], r1 ++ vst1.16 {q13}, [r6] ++ vst1.16 {q12}, [r4] ++1: ++ bmi 1f ++ vst1.16 {q11}, [r0], r1 ++ vst1.16 {q10}, [r2] ++ vst1.16 { q9}, [r0] ++1: ++ pop {r4-r10,pc} ++.endm ++ ++ ++@ void ff_hevc_rpi_h_loop_filter_uv_neon(uint8_t * src_r, // r0 ++@ unsigned int stride, // r1 ++@ uint32_t tc4, // r2 ++@ unsigned int no_f); // r3 ++@ ++@ no_f ++@ 0 tl P0 ++@ 1 tr P1 ++@ 2 bl Q0 ++@ 3 br Q1 ++@ ++@ Probably not worth having the P/Qa only special case in this direction ++@ Given layout we won't save any memory reads or avoid any cache dirtying ++@ We would save a bit of computation but I expect the partials to be less ++@ common in the H direction than V due to how we arrange deblock. ++ ++function ff_hevc_rpi_h_loop_filter_uv_neon_8, export=1 ++ sub r12, r0, r1 ++ cmp r2, #0 ++ it eq ++ bxeq lr ++ vld1.8 {d26,d27}, [r0] ++ lsl r1, #1 ++ sub r0, r1 ++ vld1.8 {d18,d19}, [r12], r1 ++ vld1.8 {d16,d17}, [r0], r1 ++ vld1.8 {d28,d29}, [r12] ++ ++ hevc_loop_filter_uv_body2 d16, d17, d18, d19, d26, d27, d28, d29, \ ++ "sub r12, r0, r1, asr #1" ++ ++ lsls r3, #29 @ b2 -> N, b3 -> C ++ it pl ++ vstrpl d26, [r0, #0] ++ it cc ++ vstrcc d27, [r0, #8] ++ lsls r3, #2 @ b0 -> N, b1 -> C ++ it pl ++ vstrpl d18, [r12, #0] ++ it cc ++ vstrcc d19, [r12, #8] ++ bx lr ++ ++endfunc ++ ++ ++@ void ff_hevc_rpi_h_loop_filter_uv_neon_10(uint8_t * src_r, // r0 ++@ unsigned int stride, // r1 ++@ uint32_t tc4, // r2 ++@ unsigned int no_f); // r3 ++@ ++@ no-F = b0:no_p[0], b1:no_p[1], b2:no_q[0], b3:no_q[1] ++@ ++@ Macro here actual function near bottom ++ ++.macro m_filter_h_uv_16 bit_depth ++ sub r12, r0, r1 ++ cmp r2, #0 ++ it eq ++ bxeq lr ++ vld1.16 {q12, q13}, [r0] ++ lsl r1, #1 ++ sub r0, r1 ++ vld1.16 {q10, q11}, [r12], r1 ++ vld1.16 {q8, q9 }, [r0], r1 ++ vld1.16 {q14, q15}, [r12] ++ ++ hevc_loop_filter_uv_body2_16 q8, q9, q10, q11, q12, q13, q14, q15, \bit_depth, \ ++ "sub r12, r0, r1, asr #1", \ ++ "cmp r3, #0" ++ ++ bne 1f ++ vst1.16 {q10, q11}, [r12] ++ vst1.16 {q12, q13}, [r0] ++ bx lr ++ ++ @ At least one no_f bit is set ++ @ Which means we need to break this apart in an ugly fashion ++1: ++ lsls r3, #29 @ b2 -> N, b3 -> C ++ itt pl ++ vstrpl d24, [r0, #0] ++ vstrpl d25, [r0, #8] ++ itt cc ++ vstrcc d26, [r0, #16] ++ vstrcc d27, [r0, #24] ++ lsls r3, #2 @ b0 -> N, b1 -> C ++ itt pl ++ vstrpl d20, [r12, #0] ++ vstrpl d21, [r12, #8] ++ itt cc ++ vstrcc d22, [r12, #16] ++ vstrcc d23, [r12, #24] ++ bx lr ++.endm ++ ++ ++@ void ff_hevc_rpi_v_loop_filter_uv2_neon(uint8_t * src_r, // r0 ++@ unsigned int stride, // r1 ++@ uint32_t tc4, // r2 ++@ uint8_t * src_l, // r3 ++@ unsigned int no_f); // sp[0] ++@ ++@ no_f: ++@ 0 tl P0 ++@ 1 tr Q0 ++@ 2 bl P1 ++@ 3 br Q1 ++ ++function ff_hevc_rpi_v_loop_filter_uv2_neon_8, export=1 ++ cmp r2, #0 ++ it eq ++ bxeq lr ++ push {lr} ++ vld2.16 {d16[0], d18[0]}, [r3], r1 ++ vld2.16 {d20[0], d22[0]}, [r0], r1 ++ ++ cmp r2, #0x10000 ++ vld2.16 {d16[1], d18[1]}, [r3], r1 ++ vld2.16 {d20[1], d22[1]}, [r0], r1 ++ ++ vld2.16 {d16[2], d18[2]}, [r3], r1 ++ vld2.16 {d20[2], d22[2]}, [r0], r1 ++ ++ vld2.16 {d16[3], d18[3]}, [r3], r1 ++ vld2.16 {d20[3], d22[3]}, [r0], r1 ++ blo 10f ++ ++ vld2.16 {d17[0], d19[0]}, [r3], r1 ++ vld2.16 {d21[0], d23[0]}, [r0], r1 ++ ++ sub ip, r0, r3 ++ vld2.16 {d17[1], d19[1]}, [r3], r1 ++ vld2.16 {d21[1], d23[1]}, [r0], r1 ++ ++ cmp ip, #4 ++ vld2.16 {d17[2], d19[2]}, [r3], r1 ++ vld2.16 {d21[2], d23[2]}, [r0], r1 ++ ++ vld2.16 {d17[3], d19[3]}, [r3] ++ vld2.16 {d21[3], d23[3]}, [r0] ++ ++ hevc_loop_filter_uv_body2 d16, d17, d18, d19, d20, d21, d22, d23 \ ++ "ldr lr, [sp, #4]", \ ++ "neg r1, r1", \ ++ "it eq; cmpeq lr, #0", \ ++ "add r3, #2", \ ++ "add ip, r3, r1", \ ++ "add r2, r0, r1", \ ++ "lsl r1, #1" ++ ++ bne 1f ++ ++@ Much/most of the time r0 == r3 + 4 and no_f == 0 ++@ so it is worth having this special case ++ vst2.16 {d19[3], d21[3]}, [r3], r1 @ P0b, Q0b ++ vst2.16 {d19[2], d21[2]}, [ip], r1 ++ vst2.16 {d19[1], d21[1]}, [r3], r1 ++ vst2.16 {d19[0], d21[0]}, [ip], r1 ++ vst2.16 {d18[3], d20[3]}, [r3], r1 @ P0a, Q0a ++ vst2.16 {d18[2], d20[2]}, [ip], r1 ++ vst2.16 {d18[1], d20[1]}, [r3] ++ vst2.16 {d18[0], d20[0]}, [ip] ++ pop {pc} ++ ++@ Either split or partial ++1: ++ lsls lr, #29 @ b3 (Q0b) -> C, b2 (P0b) -> N & b31, b1 (Q0a) -> b30, b0 (P0a) -> b29 ++ ittt cs ++ addcs r0, r0, r1, lsl #1 ++ addcs r2, r2, r1, lsl #1 ++ bcs 1f ++ @ Q0b ++ vst1.16 {d21[3]}, [r0], r1 ++ vst1.16 {d21[2]}, [r2], r1 ++ vst1.16 {d21[1]}, [r0], r1 ++ vst1.16 {d21[0]}, [r2], r1 ++1: ++ ittt mi ++ addmi r3, r3, r1, lsl #1 ++ addmi ip, ip, r1, lsl #1 ++ bmi 1f ++ @ P0b ++ vst1.16 {d19[3]}, [r3], r1 ++ vst1.16 {d19[2]}, [ip], r1 ++ vst1.16 {d19[1]}, [r3], r1 ++ vst1.16 {d19[0]}, [ip], r1 ++1: ++ lsls lr, #2 @ b30 (Q0a) -> C, b29 (P0a) -> N & b31 ++ bcs 1f ++ @ Q0a ++ vst1.16 {d20[3]}, [r0], r1 ++ vst1.16 {d20[2]}, [r2], r1 ++ vst1.16 {d20[1]}, [r0] ++ vst1.16 {d20[0]}, [r2] ++1: ++ it mi ++ popmi {pc} ++ @ P0a ++ vst1.16 {d18[3]}, [r3], r1 ++ vst1.16 {d18[2]}, [ip], r1 ++ vst1.16 {d18[1]}, [r3] ++ vst1.16 {d18[0]}, [ip] ++ pop {pc} ++ ++@ Single lump (rather than double) ++10: ++ @ As we have post inced r0/r3 in the load the easiest thing to do is ++ @ to subtract and write forwards, rather than backwards (as above) ++ @ b0 (P0a) -> N, b1 (Q0a) -> C ++ ++ hevc_loop_filter_uv_body1 d16, d18, d20, d22 \ ++ "ldr lr, [sp, #4]", \ ++ "add r3, #2", \ ++ "sub r0, r0, r1, lsl #2", \ ++ "sub r3, r3, r1, lsl #2", \ ++ "lsls lr, #31", \ ++ "add r2, r0, r1", \ ++ "add ip, r3, r1", \ ++ "lsl r1, #1" ++ ++ bcs 3f ++ @ Q0a ++ vst1.16 {d20[0]}, [r0], r1 ++ vst1.16 {d20[1]}, [r2], r1 ++ vst1.16 {d20[2]}, [r0] ++ vst1.16 {d20[3]}, [r2] ++3: ++ it mi ++ popmi {pc} ++ @ P0a ++ vst1.16 {d18[0]}, [r3], r1 ++ vst1.16 {d18[1]}, [ip], r1 ++ vst1.16 {d18[2]}, [r3] ++ vst1.16 {d18[3]}, [ip] ++ pop {pc} ++ ++endfunc ++ ++ ++@ void ff_hevc_rpi_v_loop_filter_uv2_neon(uint8_t * src_r, // r0 ++@ unsigned int stride, // r1 ++@ uint32_t tc4, // r2 ++@ uint8_t * src_l, // r3 ++@ unsigned int no_f); // sp[0] ++@ ++ ++@ no_f ++@ 0 tl P0a ++@ 1 tr Q0a ++@ 2 bl P0b ++@ 3 br Q0b ++ ++@ P1: q8, q12 ++@ P0: q9, q13 ++@ Q0: q10, q14 ++@ Q1: q11, q15 ++ ++.macro m_filter_v_uv2_16 bit_depth ++ cmp r2, #0 ++ it eq ++ bxeq lr ++ push {lr} ++ vld2.32 {d16[0], d18[0]}, [r3], r1 ++ vld2.32 {d20[0], d22[0]}, [r0], r1 ++ ++ cmp r2, #0x10000 ++ vld2.32 {d16[1], d18[1]}, [r3], r1 ++ vld2.32 {d20[1], d22[1]}, [r0], r1 ++ ++ vld2.32 {d17[0], d19[0]}, [r3], r1 ++ vld2.32 {d21[0], d23[0]}, [r0], r1 ++ ++ vld2.32 {d17[1], d19[1]}, [r3], r1 ++ vld2.32 {d21[1], d23[1]}, [r0], r1 ++ blo 10f ++ ++ vld2.32 {d24[0], d26[0]}, [r3], r1 ++ vld2.32 {d28[0], d30[0]}, [r0], r1 ++ ++ sub ip, r0, r3 ++ vld2.32 {d24[1], d26[1]}, [r3], r1 ++ vld2.32 {d28[1], d30[1]}, [r0], r1 ++ ++ cmp ip, #8 ++ vld2.32 {d25[0], d27[0]}, [r3], r1 ++ vld2.32 {d29[0], d31[0]}, [r0], r1 ++ ++ vld2.32 {d25[1], d27[1]}, [r3] ++ vld2.32 {d29[1], d31[1]}, [r0] ++ ++ hevc_loop_filter_uv_body2_16 q8, q12, q9, q13, q10, q14, q11, q15, \bit_depth, \ ++ "ldr lr, [sp, #4]", \ ++ "neg r1, r1", \ ++ "it eq; cmpeq lr, #0", \ ++ "add r3, #4", \ ++ "add ip, r3, r1", \ ++ "add r2, r0, r1", \ ++ "lsl r1, #1" ++ ++ bne 1f ++ ++@ Much/most of the time r0 == r3 + 8 and no_f == 0 ++@ so it is worth having this special case ++ vst2.32 {d27[1], d29[1]}, [r3], r1 @ P0b, Q0b ++ vst2.32 {d27[0], d29[0]}, [ip], r1 ++ vst2.32 {d26[1], d28[1]}, [r3], r1 ++ vst2.32 {d26[0], d28[0]}, [ip], r1 ++ vst2.32 {d19[1], d21[1]}, [r3], r1 @ P0a, Q0a ++ vst2.32 {d19[0], d21[0]}, [ip], r1 ++ vst2.32 {d18[1], d20[1]}, [r3] ++ vst2.32 {d18[0], d20[0]}, [ip] ++ pop {pc} ++ ++@ Either split or partial ++1: ++ lsls lr, #29 @ b3 (Q0b) -> C, b2 (P0b) -> N & b31, b1 (Q0a) -> b30, b0 (P0a) -> b29 ++ ittt cs ++ addcs r0, r0, r1, lsl #1 ++ addcs r2, r2, r1, lsl #1 ++ bcs 1f ++ @ Q0b ++ vst1.32 {d29[1]}, [r0], r1 ++ vst1.32 {d29[0]}, [r2], r1 ++ vst1.32 {d28[1]}, [r0], r1 ++ vst1.32 {d28[0]}, [r2], r1 ++1: ++ ittt mi ++ addmi r3, r3, r1, lsl #1 ++ addmi ip, ip, r1, lsl #1 ++ bmi 1f ++ @ P0b ++ vst1.32 {d27[1]}, [r3], r1 ++ vst1.32 {d27[0]}, [ip], r1 ++ vst1.32 {d26[1]}, [r3], r1 ++ vst1.32 {d26[0]}, [ip], r1 ++1: ++ lsls lr, #2 @ b30 (Q0a) -> C, b29 (P0a) -> N & b31 ++ bcs 1f ++ @ Q0a ++ vst1.32 {d21[1]}, [r0], r1 ++ vst1.32 {d21[0]}, [r2], r1 ++ vst1.32 {d20[1]}, [r0] ++ vst1.32 {d20[0]}, [r2] ++1: ++ it mi ++ popmi {pc} ++ @ P0a ++ vst1.32 {d19[1]}, [r3], r1 ++ vst1.32 {d19[0]}, [ip], r1 ++ vst1.32 {d18[1]}, [r3] ++ vst1.32 {d18[0]}, [ip] ++ pop {pc} ++ ++@ Single lump (rather than double) ++10: ++ @ As we have post inced r0/r3 in the load the easiest thing to do is ++ @ to subtract and write forwards, rather than backwards (as above) ++ @ b0 (P0a) -> N, b1 (Q0a) -> C ++ ++ hevc_loop_filter_uv_body1_16 q8, q9, q10, q11, \bit_depth, \ ++ "ldr lr, [sp, #4]", \ ++ "add r3, #4", \ ++ "sub r0, r0, r1, lsl #2", \ ++ "sub r3, r3, r1, lsl #2", \ ++ "lsls lr, #31", \ ++ "add r2, r0, r1", \ ++ "add ip, r3, r1", \ ++ "lsl r1, #1" ++ ++ bcs 3f ++ @ Q0a ++ vst1.32 {d20[0]}, [r0], r1 ++ vst1.32 {d20[1]}, [r2], r1 ++ vst1.32 {d21[0]}, [r0] ++ vst1.32 {d21[1]}, [r2] ++3: ++ it mi ++ popmi {pc} ++ @ P0a ++ vst1.32 {d18[0]}, [r3], r1 ++ vst1.32 {d18[1]}, [ip], r1 ++ vst1.32 {d19[0]}, [r3] ++ vst1.32 {d19[1]}, [ip] ++ pop {pc} ++.endm ++ ++ ++@ The NEON version is faster under ideal circumstances (i.e. everything in L1) ++@ But in real world testing it is ~20% slower, presumably due to code size ++ ++#if 0 // NEON version ++ ++/* uint32_t ff_hevc_rpi_deblocking_boundary_strengths_neon(int pus, int dup, const HEVCRpiMvField *curr, const HEVCRpiMvField *neigh, ++ * const int *curr_rpl0, const int *curr_rpl1, const int *neigh_rpl0, const int *neigh_rpl1, ++ * int in_inc0, int in_inc1) ++ */ ++function ff_hevc_rpi_deblocking_boundary_strengths_neon, export=1 ++ mov ip, sp ++ push {a1-a3,v1-v8,lr} ++ ldm ip, {v1-v6} ++ cmp a1, #2 ++ bls 2f ++ vpush {d8-d13} ++ sub v5, v5, #10 ++ sub v6, v6, #10 ++1: ++ vld2.32 {d0[0], d2[0]}, [a3]! ++ vld2.32 {d4[0], d6[0]}, [a4]! ++ vmov.u8 q12, #0 ++ ldrb a2, [a3], #1 ++ ldrb ip, [a4], #1 ++ ldrb v8, [a3], #1 ++ ldrb lr, [a4], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d24[0]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d25[0]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d16[0]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d20[0]}, [ip] ++ vld1.32 {d18[0]}, [v8] ++ vld1.32 {d22[0]}, [lr] ++ ++ vld2.32 {d0[1], d2[1]}, [a3]! ++ vld2.32 {d4[1], d6[1]}, [a4]! ++ ldrb a2, [a3], #1 ++ vmov.u16 d12, #1 ++ ldrb ip, [a4], #1 ++ vmov.u16 d13, #2 ++ ldrb v8, [a3], #1 ++ vmov.u16 d27, #4 ++ ldrb lr, [a4], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d24[2]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d25[2]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d16[1]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d20[1]}, [ip] ++ vld1.32 {d18[1]}, [v8] ++ vld1.32 {d22[1]}, [lr] ++ ++ vld2.32 {d1[0], d3[0]}, [a3]! ++ vld2.32 {d5[0], d7[0]}, [a4]! ++ ldrb a2, [a3], #1 ++ ldrb ip, [a4], #1 ++ ldrb lr, [a4], #1 ++ ldrb v8, [a3], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d24[4]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d25[4]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d17[0]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d21[0]}, [ip] ++ vld1.32 {d19[0]}, [v8] ++ vld1.32 {d23[0]}, [lr] ++ ++ vld2.32 {d1[1], d3[1]}, [a3]! ++ vld2.32 {d5[1], d7[1]}, [a4]! ++ ldrb a2, [a3], #1 ++ ldrb ip, [a4], #1 ++ ldrb v8, [a3], #1 ++ ldrb lr, [a4], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d24[6]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d25[6]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d17[1]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d21[1]}, [ip] ++ vld1.32 {d19[1]}, [v8] ++ vld1.32 {d23[1]}, [lr] ++ ++ @ So now we have: ++ @ q0.32[i] = curr[i].mv[0] ++ @ q1.32[i] = curr[i].mv[1] ++ @ q2.32[i] = neigh[i].mv[0] ++ @ q3.32[i] = neigh[i].mv[1] ++ @ q8.32[i] = curr_rpl0[curr[i].ref_idx[0]] ++ @ q9.32[i] = curr_rpl1[curr[i].ref_idx[1]] ++ @ q10.32[i] = neigh_rpl0[neigh[i].ref_idx[0]] ++ @ q11.32[i] = neigh_rpl1[neigh[i].ref_idx[1]] ++ @ d24.16[i] = curr[i].pred_flag ++ @ d25.16[i] = neigh[i].pred_flag ++ ++ vtst.16 d28, d24, d12 ++ vtst.16 d29, d24, d13 ++ vadd.i16 d8, d24, d12 ++ vadd.i16 d9, d25, d12 ++ vtst.16 d30, d25, d12 ++ vtst.16 d31, d25, d13 ++ veor d26, d8, d9 ++ ldr lr, [sp, 6*8 + 1*4] ++ vmovl.s16 q4, d28 ++ vmovl.s16 q5, d29 ++ teq lr, #1 ++ vmovl.s16 q14, d30 ++ it ne ++ lslne v1, lr, #1 ++ vmovl.s16 q15, d31 ++ it ne ++ rsbne v2, v1, #32 ++ vbif q0, q1, q4 ++ vbif q2, q3, q14 ++ vbif q1, q0, q5 ++ vbif q3, q2, q15 ++ vabd.s16 q12, q0, q2 ++ vabd.s16 q2, q1 ++ vabd.s16 q0, q3 ++ vabd.s16 q1, q3 ++ vbif q8, q9, q4 ++ vbif q10, q11, q14 ++ vbif q9, q8, q5 ++ vbif q11, q10, q15 ++ vclt.u16 d6, d24, d27 ++ vclt.u16 d8, d2, d27 ++ vclt.u16 d7, d25, d27 ++ vclt.u16 d9, d3, d27 ++ vclt.u16 d2, d0, d27 ++ vclt.u16 d0, d4, d27 ++ vclt.u16 d3, d1, d27 ++ vclt.u16 d1, d5, d27 ++ vceq.i32 q12, q10, q8 ++ vceq.i32 q10, q9 ++ vceq.i32 q8, q11 ++ vceq.i32 q9, q11 ++ vshrn.i32 d6, q3, #8 ++ vshrn.i32 d7, q4, #8 ++ vshrn.i32 d8, q1, #8 ++ vshrn.i32 d9, q0, #8 ++ vmovn.i32 d4, q12 ++ vmovn.i32 d2, q10 ++ vmovn.i32 d3, q8 ++ vmovn.i32 d5, q9 ++ vand q2, q3 ++ vrev16.8 q3, q3 ++ vand q2, q3 ++ vand q1, q4 ++ vrev16.8 q4, q4 ++ vand q1, q4 ++ vand d4, d5 ++ vand d2, d3 ++ vbic d0, d12, d4 ++ vshr.u16 d26, #2 ++ vbic d0, d2 ++ vmov.i16 d1, #0x5555 ++ vorr d0, d26 ++ bne 10f ++ ++ @ Merge results into result word, no duplicates ++ vmov a2, s0 ++ vmov v8, s1 ++ vmov.u16 ip, d0[1] ++ vmov.u16 lr, d0[3] ++ lsl a2, #30 ++ lsl v8, #30 ++ lsl ip, #30 ++ lsl lr, #30 ++ orr a2, ip, a2, lsr #2 ++ orr v8, lr, v8, lsr #2 ++ orr a2, v8, a2, lsr #4 ++ subs a1, #4 ++ orr v7, a2, v7, lsr #8 ++ bhi 1b ++ ++ mov a1, #32 ++ ldr a3, [sp, #6*8] ++ vpop {d8-d13} ++ sub a1, a1, a3, lsl #1 ++ mov a1, v7, lsr a1 ++ pop {a2-a4,v1-v8,pc} ++10: ++ @ Merge results into result word, with duplicates ++ vmul.i16 d0, d1 ++ vmov a2, s0 ++ vmov v8, s1 ++ vmov.u16 ip, d0[1] ++ vmov.u16 lr, d0[3] ++ lsl a2, v2 ++ subs a1, #4 ++ lsl v8, v2 ++ lsl ip, v2 ++ lsl lr, v2 ++ ldr v2, [sp, #6*8 + 12*4 + 1*4] ++T lsr a2, v1 ++T orr a2, ip, a2 ++A orr a2, ip, a2, lsr v1 ++ lsl ip, v1, #1 ++T lsr v8, v1 ++T orr v8, lr, v8 ++A orr v8, lr, v8, lsr v1 ++ lsl lr, v1, #2 ++T lsr a2, ip ++T orr a2, v8, a2 ++A orr a2, v8, a2, lsr ip ++ ldr v1, [sp, #6*8 + 12*4] ++T lsr v7, lr ++T orr v7, a2, v7 ++A orr v7, a2, v7, lsr lr ++ bhi 1b ++ ++ mov a1, #32 ++ ldrd a3, a4, [sp, #6*8] ++ vpop {d8-d13} ++ mls a1, a3, a4, a1 ++ mls a1, a3, a4, a1 ++ mov a1, v7, lsr a1 ++ pop {a2-a4,v1-v8,pc} ++ ++ ++2: ++ sub v5, v5, #10 ++ sub v6, v6, #10 ++ vmov.u8 d16, #0 ++ blo 3f ++ vld2.32 {d0[0], d1[0]}, [a3]! ++ vld2.32 {d2[0], d3[0]}, [a4]! ++ ldrb a2, [a3], #1 ++ ldrb ip, [a4], #1 ++ ldrb lr, [a4], #1 ++ ldrb v8, [a3], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d16[0]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d16[4]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d4[0]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d5[0]}, [ip] ++ vld1.32 {d6[0]}, [v8] ++ vld1.32 {d7[0]}, [lr] ++ ++3: ++ vld2.32 {d0[1], d1[1]}, [a3]! ++ vld2.32 {d2[1], d3[1]}, [a4]! ++ ldrb a2, [a3], #1 ++ vmov.u16 d17, #1 ++ ldrb ip, [a4], #1 ++ vmov.u16 d18, #2 ++ ldrb v8, [a3], #1 ++ vmov.u16 d19, #4 ++ ldrb lr, [a4], #1 ++ add a2, v1, a2, lsl #2 ++ vld1.8 {d16[2]}, [a3], v5 ++ add ip, v3, ip, lsl #2 ++ vld1.8 {d16[6]}, [a4], v6 ++ add v8, v2, v8, lsl #2 ++ vld1.32 {d4[1]}, [a2] ++ add lr, v4, lr, lsl #2 ++ vld1.32 {d5[1]}, [ip] ++ vld1.32 {d6[1]}, [v8] ++ vld1.32 {d7[1]}, [lr] ++ ++ @ So now we have: ++ @ d0.32[i] = curr[i].mv[0] ++ @ d1.32[i] = curr[i].mv[1] ++ @ d2.32[i] = neigh[i].mv[0] ++ @ d3.32[i] = neigh[i].mv[1] ++ @ d4.32[i] = curr_rpl0[curr[i].ref_idx[0]] ++ @ d5.32[i] = neigh_rpl0[neigh[i].ref_idx[0]] ++ @ d6.32[i] = curr_rpl1[curr[i].ref_idx[1]] ++ @ d7.32[i] = neigh_rpl1[neigh[i].ref_idx[1]] ++ @ d16.16[i] = curr[i].pred_flag ++ @ d16.16[2+i] = neigh[i].pred_flag ++ ++ vtst.16 d20, d16, d17 ++ vtst.16 d22, d16, d18 ++ vadd.i16 d30, d16, d17 ++ vswp d2, d3 ++ ldr lr, [sp, #1*4] ++ vmovl.s16 q10, d20 ++ teq lr, #1 ++ vmovl.s16 q11, d22 ++ it ne ++ lslne v1, lr, #1 ++ vbif d0, d1, d20 ++ vbif d4, d6, d20 ++ vbif d3, d2, d21 ++ vbif d5, d7, d21 ++ vbif d1, d0, d22 ++ vbif d6, d4, d22 ++ vbif d2, d3, d23 ++ vbif d7, d5, d23 ++ vshr.u16 d30, #2 ++ vabd.s16 d24, d0, d3 ++ vabd.s16 d25, d1, d2 ++ vabd.s16 q0, q0, q1 ++ vceq.i32 d2, d4, d5 ++ vceq.i32 d20, d5, d6 ++ vceq.i32 d21, d4, d7 ++ vceq.i32 d3, d6, d7 ++ vclt.u16 d6, d24, d19 ++ vclt.u16 d7, d25, d19 ++ vclt.u16 d22, d1, d19 ++ vclt.u16 d23, d0, d19 ++ vshrn.i32 d6, q3, #8 ++ vmovn.i32 d2, q1 ++ vshrn.i32 d7, q11, #8 ++ vmovn.i32 d3, q10 ++ vand q0, q3, q1 ++ it ne ++ rsbne v2, v1, #32 ++ vrev16.8 q3, q3 ++ vand q0, q3 ++ vsra.u64 d30, #32 ++ vshr.u64 q1, q0, #32 ++ vand q0, q1 ++ vbic d0, d17, d0 ++ vand d30, d30, d17 ++ vbic d0, d1 ++ vmov.i16 d1, #0x5555 ++ vorr d0, d30 ++ bne 10f ++ ++ @ Construct result word, no duplicates ++ cmp a1, #2 ++ vmov.u16 a1, d0[1] ++ vmov.u16 a2, d0[0] ++ it eq ++ orreq a1, a2, a1, lsl #2 ++ pop {a2-a4,v1-v8,pc} ++10: ++ @ Construct result word, with duplicates ++ cmp a1, #2 ++ vmul.i16 d0, d1 ++ vmov a2, s0 ++ vmov.u16 a1, d0[1] ++ lsl a2, #16 ++ pkhbt a1, a1, a1, lsl #16 ++ lsr a2, v2 ++ lsr a1, v2 ++T itt eq ++T lsleq a1, v1 ++T orreq a1, a2, a1 ++A orreq a1, a2, a1, lsl v1 ++ pop {a2-a4,v1-v8,pc} ++endfunc ++ ++ ++ ++#else // non-NEON version ++ ++ ++/* uint32_t ff_hevc_rpi_deblocking_boundary_strengths_neon(int pus, int dup, const HEVCRpiMvField *curr, const HEVCRpiMvField *neigh, ++ * const int *curr_rpl0, const int *curr_rpl1, const int *neigh_rpl0, const int *neigh_rpl1, ++ * int in_inc0, in_inc1) ++ */ ++function ff_hevc_rpi_deblocking_boundary_strengths_neon, export=1 ++ add ip, sp, #4*4 ++ push {a2-a4,v1-v8,lr} ++ mov v6, #32 ++1: ldmdb ip, {v1-v4} ++ ldrsb v5, [a3, #8] @ curr->ref_idx ++ ldrsb v8, [a3, #9] ++ ldrsb ip, [a4, #8] @ neigh->ref_idx ++ ldrsb lr, [a4, #9] ++ ldr v1, [v1, v5, lsl #2] ++ ldrb v5, [a3, #10] @ curr->pred_flag ++ ldr v2, [v2, v8, lsl #2] ++ ldrb v8, [a4, #10] @ neigh->pred_flag ++ ldr v3, [v3, ip, lsl #2] ++ ldr v4, [v4, lr, lsl #2] ++ teq v5, #3 ++ beq 20f ++ teq v8, #3 ++ beq 90f ++ ++ tst v5, #1 ++ itee ne ++ ldrne v5, [a3, #0] @ curr->mv[0] ++ moveq v1, v2 ++ ldreq v5, [a3, #4] @ curr->mv[1] ++ tst v8, #1 ++ itee ne ++ ldrne v8, [a4, #0] @ neigh->mv[0] ++ moveq v3, v4 ++ ldreq v8, [a4, #4] @ neigh->mv[1] ++ teq v1, v3 ++ bne 10f ++ ldr lr, =0xFFFCFFFC ++ ssub16 ip, v8, v5 ++ ssub16 v5, v5, v8 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ @ drop through ++10: it ne ++ movne v5, #1<<30 ++11: ++ sub v6, v6, #2 ++T mov v7, v7, lsr #2 ++ subs a2, a2, #1 ++A orr v7, v5, v7, lsr #2 ++T orr v7, v5, v7 ++ bhi 11b ++ ++ ldrd v3, v4, [sp, #16*4] ++ ldr a2, [sp] ++ add ip, sp, #16*4 ++ subs a1, a1, #1 ++ add a3, a3, v3 ++ add a4, a4, v4 ++ bhi 1b ++ mov a1, v7, lsr v6 ++ pop {a2-a4,v1-v8,pc} ++ ++20: teq v8, #3 ++ bne 10b ++ ++ teq v1, v3 ++ it eq ++ teqeq v2, v4 ++ bne 40f ++ teq v1, v2 ++ bne 30f ++ ++ ldrd v1, v2, [a3] @ curr->mv ++ ldrd v3, v4, [a4] @ neigh->mv ++ ldr lr, =0xFFFCFFFC ++ ssub16 ip, v3, v1 ++ ssub16 v5, v1, v3 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ bne 25f ++ ssub16 ip, v4, v2 ++ ssub16 v5, v2, v4 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ beq 11b ++ @ drop through ++25: ssub16 ip, v4, v1 ++ ssub16 v5, v1, v4 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ bne 10b ++ ssub16 ip, v3, v2 ++ ssub16 v5, v2, v3 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ b 10b ++ ++30: ldrd v1, v2, [a3] @ curr->mv ++ ldrd v3, v4, [a4] @ neigh->mv ++ ldr lr, =0xFFFCFFFC ++ ssub16 ip, v3, v1 ++ ssub16 v5, v1, v3 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ bne 10b ++ ssub16 ip, v4, v2 ++ ssub16 v5, v2, v4 ++ sel v5, v5, ip ++ ands v5, v5, lr ++ b 10b ++ ++40: teq v1, v4 ++ ite eq ++ teqeq v2, v3 ++ bne 10b ++ ++ ldrd v1, v2, [a3] @ curr->mv ++ ldrd v3, v4, [a4] @ neigh->mv ++ ldr lr, =0xFFFCFFFC ++ b 25b ++ ++90: ++ mov v5, #1<<30 ++ b 11b ++endfunc ++ ++ ++#endif ++ ++ ++@ ============================================================================= ++@ ++@ 10 bit ++ ++function hevc_loop_filter_luma_body_10 ++ m_filter_luma 10, q11, q15 ++endfunc ++ ++function ff_hevc_rpi_h_loop_filter_luma_neon_10, export=1 ++ hevc_loop_filter_luma_start ++ b .Lh_loop_luma_common_10 ++endfunc ++ ++function ff_hevc_rpi_h_loop_filter_luma2_neon_10, export=1 ++ cmp r3, #0 ++ it eq ++ bxeq lr ++ push {r4-r10,lr} @ 32 bytes ++ ldr r10, [sp, #32] ++.Lh_loop_luma_common_10: ++ m_filter_h_luma_16 10 ++endfunc ++ ++function ff_hevc_rpi_v_loop_filter_luma_neon_10, export=1 ++ hevc_loop_filter_luma_start ++ sub r4, r0, #8 ++ b .Lv_loop_luma_common_10 ++endfunc ++ ++function ff_hevc_rpi_v_loop_filter_luma2_neon_10, export=1 ++ cmp r3, #0 ++ it eq ++ bxeq lr ++ push {r4-r10,lr} @ 32 bytes ++ ldr r4, [sp, #36] ++ ldr r10, [sp, #32] ++ ++.Lv_loop_luma_common_10: ++ m_filter_v_luma_16 10 ++endfunc ++ ++function ff_hevc_rpi_h_loop_filter_uv_neon_10, export=1 ++ m_filter_h_uv_16 10 ++endfunc ++ ++function ff_hevc_rpi_v_loop_filter_uv2_neon_10, export=1 ++ m_filter_v_uv2_16 10 ++endfunc ++ +diff --git a/libavcodec/arm/rpi_hevcdsp_idct_neon.S b/libavcodec/arm/rpi_hevcdsp_idct_neon.S +new file mode 100644 +index 0000000000..7ed5c7dc52 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_idct_neon.S +@@ -0,0 +1,184 @@ ++/* ++ * Copyright (c) 2014 Seppo Tomperi ++ * Copyright (C) 2018 John Cox, Ben Avison for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++/* uses registers q8 - q13 for temp values */ ++.macro tr4_luma_shift shift ++ vaddl.s16 q8, d28, d30 // c0 = src0 + src2 ++ vaddl.s16 q9, d30, d31 // c1 = src2 + src3 ++ vsubl.s16 q10, d28, d31 // c2 = src0 - src3 ++ vaddl.s16 q11, d28, d31 // src0 + src3 ++ ++ vmul.i32 q12, q8, d1[0] // 29 * c0 ++ vmul.i32 q13, q10, d2[0] // 55 * c2 ++ vmul.i32 q8, q8, d2[0] // 55 * c0 ++ vmull.s16 q14, d29, d0[0] // c3 = 74 * src1 ++ ++ vsubw.s16 q11, q11, d30 // src0 - src2 + src3 ++ vmla.i32 q12, q9, d2[0] // 29 * c0 + 55 * c1 ++ vmls.i32 q13, q9, d1[0] // 55 * c2 - 29 * c1 ++ vmla.i32 q8, q10, d1[0] // 55 * c0 + 29 * c2 ++ ++ vmul.i32 q11, q11, d0[0] // dst2 = 74 * (src0 - src2 + src3) ++ vadd.i32 q12, q12, q14 // dst0 = 29 * c0 + 55 * c1 + c3 ++ vadd.i32 q13, q13, q14 // dst1 = 55 * c2 - 29 * c1 + c3 ++ vsub.i32 q8, q8, q14 // dst3 = 55 * c0 + 29 * c2 - c3 ++ ++ vqrshrn.s32 d28, q12, \shift ++ vqrshrn.s32 d29, q13, \shift ++ vqrshrn.s32 d30, q11, \shift ++ vqrshrn.s32 d31, q8, \shift ++.endm ++ ++/* uses registers q8 - q11 for temp values */ ++.macro tr4_shift shift ++ vmull.s16 q9, d29, d0[0] // 83 * src1 ++ vmull.s16 q8, d29, d0[1] // 36 * src1 ++ vshll.s16 q14, d28, #6 // 64 * src0 ++ vshll.s16 q10, d30, #6 // 64 * src2 ++ vmlal.s16 q9, d31, d0[1] // 83 * src1 + 36 * src3 o0 ++ vmlsl.s16 q8, d31, d0[0] // 36 * src1 - 83 * src3 o1 ++ vadd.s32 q11, q14, q10 // 64 * (src0 + src2) e0 ++ vsub.s32 q10, q14, q10 // 64 * (src0 - src2) e1 ++ vadd.s32 q14, q11, q9 // e0 + o0 ++ vadd.s32 q15, q10, q8 // e1 + o1 ++ vsub.s32 q8, q10, q8 // e1 - o1 ++ vsub.s32 q9, q11, q9 // e0 - o0 ++ ++ vqrshrn.s32 d28, q14, \shift ++ vqrshrn.s32 d29, q15, \shift ++ vqrshrn.s32 d30, q8, \shift ++ vqrshrn.s32 d31, q9, \shift ++.endm ++ ++.macro tr8_process d0, d1, d2, d3, d4, d5, d6, d7, \ ++ tmp0, /* Q reg which doesn't alias with d4, d6 or d7 */ \ ++ tmp1, /* Q reg which doesn't alias with d7 or d0 */ \ ++ shift, I1, I2, I3 ++ ++ vmull.s16 q4, \d1, d1[1] // 89 * src1 ++ \I1 ++ vmull.s16 q5, \d1, d1[0] // 75 * src1 ++ \I2 ++ vmull.s16 q6, \d1, d1[3] // 50 * src1 ++ \I3 ++ vmull.s16 q7, \d1, d1[2] // 18 * src1 ++ vmlal.s16 q4, \d3, d1[0] // 75 * src3 ++ vmlsl.s16 q5, \d3, d1[2] //-18 * src3 ++ vmlsl.s16 q6, \d3, d1[1] //-89 * src3 ++ vmlsl.s16 q7, \d3, d1[3] //-50 * src3 ++ ++ // tr4 ++ vmull.s16 q1, \d2, d0[0] // 83 * src(1*2) ++ vmull.s16 q2, \d2, d0[1] // 36 * src(1*2) ++ ++ vmlal.s16 q4, \d5, d1[3] // 50 * src5 ++ vmlsl.s16 q5, \d5, d1[1] //-89 * src5 ++ vmlal.s16 q6, \d5, d1[2] // 18 * src5 ++ vmlal.s16 q7, \d5, d1[0] // 75 * src5 ++ ++ vshll.s16 q3, \d0, #6 // 64 * src(0*2) ++ vshll.s16 \tmp0, \d4, #6 // 64 * src(2*2) ++ vmlal.s16 q1, \d6, d0[1] // 83 * src(1*2) + 36 * src(3*2) o0 ++ vmlsl.s16 q2, \d6, d0[0] // 36 * src(1*2) - 83 * src(3*2) o1 ++ vadd.i32 \tmp1, q3, \tmp0 // 64 * (src(0*2) + src(2*2)) e0 ++ vsub.i32 \tmp0, q3, \tmp0 // 64 * (src(0*2) - src(2*2)) e1 ++ ++ vmlal.s16 q4, \d7, d1[2] // 18 * src7 ++ vmlsl.s16 q5, \d7, d1[3] //-50 * src7 ++ vmlal.s16 q6, \d7, d1[0] // 75 * src7 ++ vmlsl.s16 q7, \d7, d1[1] //-89 * src7 ++ ++ vsub.i32 q3, \tmp1, q1 // e0 - o0 ++ vadd.i32 \tmp1, \tmp1, q1 // e0 + o0 ++ vadd.i32 q1, \tmp0, q2 // e1 + o1 ++ vsub.i32 q2, \tmp0, q2 // e1 - o1 ++ ++ vadd.i32 \tmp0, \tmp1, q4 // e_8[0] + o_8[0], dst[0] ++ vsub.i32 q4, \tmp1, q4 // e_8[0] - o_8[0], dst[7] ++ vsub.i32 \tmp1, q3, q7 // e_8[3] - o_8[3], dst[4] ++ vadd.i32 q7, q3, q7 // e_8[3] + o_8[3], dst[3] ++ vadd.i32 q3, q1, q5 // e_8[1] + o_8[1], dst[1] ++ vsub.i32 q5, q1, q5 // e_8[1] - o_8[1], dst[6] ++ vsub.i32 q1, q2, q6 // e_8[2] - o_8[2], dst[5] ++ vadd.i32 q6, q2, q6 // e_8[2] + o_8[2], dst[2] ++ vqrshrn.s32 \d0, \tmp0, #\shift ++ vqrshrn.s32 \d4, \tmp1, #\shift ++ vqrshrn.s32 \d1, q3, #\shift ++ vqrshrn.s32 \d5, q1, #\shift ++ vqrshrn.s32 \d2, q6, #\shift ++ vqrshrn.s32 \d6, q5, #\shift ++ vqrshrn.s32 \d3, q7, #\shift ++ vqrshrn.s32 \d7, q4, #\shift ++.endm ++ ++.macro tr8_vert d0, d1, d2, d3, d4, d5, d6, d7, q01, q23, I1, I2, I3 ++ vld1.16 {\d0}, [r0 :64], r3 ++ vld1.16 {\d1}, [r2 :64], r3 ++ vld1.16 {\d2}, [r0 :64], r3 ++ vld1.16 {\d3}, [r2 :64], r3 ++ vld1.16 {\d4}, [r0 :64], r3 ++ vld1.16 {\d5}, [r2 :64], r3 ++ vld1.16 {\d6}, [r0 :64], r3 ++ vld1.16 {\d7}, [r2 :64], r3 ++ ++ tr8_process \ ++ \d0, \d1, \d2, \d3, \d4, \d5, \d6, \d7, \ ++ \q01, \q23, 7, "\I1", "\I2", "\I3" ++.endm ++ ++.macro tr8_horiz d0, d1, d2, d3, d4, d5, d6, d7, q01, q23, shift ++ tr8_process \ ++ \d0, \d1, \d2, \d3, \d4, \d5, \d6, \d7, \ ++ \q01, \q23, \shift ++ ++ vzip.16 \d0, \d4 ++ vzip.16 \d1, \d5 ++ vzip.16 \d2, \d6 ++ vzip.16 \d3, \d7 ++ vst4.16 {\d0-\d3}, [r0 :128], r3 ++ vst4.16 {\d4-\d7}, [r2 :128], r3 ++.endm ++ ++#define BIT_DEPTH 8 ++#include "rpi_hevc_idct_fn_neon.S" ++ ++.text ++ ++.align 4 ++tr4f: ++.word 0x00240053 // 36 and d1[0] = 83 ++.word 0x00000000 ++tr8f: ++.word 0x0059004b // 89, d0[0] = 75 ++.word 0x00320012 // 50, d0[2] = 18 ++tr16: ++.word 0x005a0057 // 90, d2[0] = 87 ++.word 0x00500046 // 80, d2[2] = 70 ++.word 0x0039002b // 57, d2[0] = 43 ++.word 0x00190009 // 25, d2[2] = 9 ++ ++#undef BIT_DEPTH ++#define BIT_DEPTH 10 ++#include "rpi_hevc_idct_fn_neon.S" ++ +diff --git a/libavcodec/arm/rpi_hevcdsp_init_arm.c b/libavcodec/arm/rpi_hevcdsp_init_arm.c +new file mode 100644 +index 0000000000..109fa98c29 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_init_arm.c +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2014 Seppo Tomperi ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/attributes.h" ++#include "libavutil/arm/cpu.h" ++#include "libavcodec/rpi_hevcdsp.h" ++#include "rpi_hevcdsp_arm.h" ++ ++av_cold void ff_hevcdsp_rpi_init_arm(HEVCDSPContext *c, const int bit_depth) ++{ ++ int cpu_flags = av_get_cpu_flags(); ++ ++ if (have_neon(cpu_flags)) ++ ff_hevcdsp_rpi_init_neon(c, bit_depth); ++} +diff --git a/libavcodec/arm/rpi_hevcdsp_init_neon.c b/libavcodec/arm/rpi_hevcdsp_init_neon.c +new file mode 100644 +index 0000000000..9294ab8010 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_init_neon.c +@@ -0,0 +1,467 @@ ++/* ++ * Copyright (c) 2014 Seppo Tomperi ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "config.h" ++#include "libavutil/attributes.h" ++#include "libavutil/arm/cpu.h" ++#include "libavcodec/rpi_hevcdsp.h" ++#include "rpi_hevcdsp_arm.h" ++#include "libavcodec/avcodec.h" ++#include "libavcodec/bit_depth_template.c" ++ ++// NEON inter pred fns for qpel & epel (non-sand) exist in the git repo but ++// have been removed from head as we never use them. ++ ++void ff_hevc_rpi_v_loop_filter_luma_neon_8(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++void ff_hevc_rpi_h_loop_filter_luma_neon_8(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++ ++void ff_hevc_rpi_v_loop_filter_luma_neon_10(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++void ff_hevc_rpi_h_loop_filter_luma_neon_10(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++ ++void ff_hevc_rpi_h_loop_filter_luma2_neon_8(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f); ++void ff_hevc_rpi_v_loop_filter_luma2_neon_8(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f, ++ uint8_t * _pix_l); ++void ff_hevc_rpi_h_loop_filter_uv_neon_8(uint8_t * src, unsigned int stride, uint32_t tc4, ++ unsigned int no_f); ++void ff_hevc_rpi_v_loop_filter_uv2_neon_8(uint8_t * src_r, unsigned int stride, uint32_t tc4, ++ uint8_t * src_l, ++ unsigned int no_f); ++ ++void ff_hevc_rpi_h_loop_filter_luma2_neon_10(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f); ++void ff_hevc_rpi_v_loop_filter_luma2_neon_10(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f, ++ uint8_t * _pix_l); ++void ff_hevc_rpi_h_loop_filter_uv_neon_10(uint8_t * src, unsigned int stride, uint32_t tc4, ++ unsigned int no_f); ++void ff_hevc_rpi_v_loop_filter_uv2_neon_10(uint8_t * src_r, unsigned int stride, uint32_t tc4, ++ uint8_t * src_l, ++ unsigned int no_f); ++ ++void ff_hevc_rpi_transform_4x4_neon_8(int16_t *coeffs, int col_limit); ++void ff_hevc_rpi_transform_8x8_neon_8(int16_t *coeffs, int col_limit); ++void ff_hevc_rpi_idct_4x4_dc_neon_8(int16_t *coeffs); ++void ff_hevc_rpi_idct_8x8_dc_neon_8(int16_t *coeffs); ++void ff_hevc_rpi_idct_16x16_dc_neon_8(int16_t *coeffs); ++void ff_hevc_rpi_idct_32x32_dc_neon_8(int16_t *coeffs); ++void ff_hevc_rpi_transform_luma_4x4_neon_8(int16_t *coeffs); ++ ++void ff_hevc_rpi_transform_4x4_neon_10(int16_t *coeffs, int col_limit); ++void ff_hevc_rpi_transform_8x8_neon_10(int16_t *coeffs, int col_limit); ++void ff_hevc_rpi_idct_4x4_dc_neon_10(int16_t *coeffs); ++void ff_hevc_rpi_idct_8x8_dc_neon_10(int16_t *coeffs); ++void ff_hevc_rpi_idct_16x16_dc_neon_10(int16_t *coeffs); ++void ff_hevc_rpi_idct_32x32_dc_neon_10(int16_t *coeffs); ++void ff_hevc_rpi_transform_luma_4x4_neon_10(int16_t *coeffs); ++ ++void ff_hevc_rpi_add_residual_4x4_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_8x8_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_16x16_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_32x32_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++ ++void ff_hevc_rpi_add_residual_4x4_dc_neon_8(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_8x8_dc_neon_8(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_16x16_dc_neon_8(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_32x32_dc_neon_8(uint8_t *_dst, ptrdiff_t stride, int dc); ++ ++ ++void ff_hevc_rpi_add_residual_4x4_neon_10(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_8x8_neon_10(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_16x16_neon_10(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_32x32_neon_10(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++ ++void ff_hevc_rpi_add_residual_4x4_dc_neon_10(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_8x8_dc_neon_10(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_16x16_dc_neon_10(uint8_t *_dst, ptrdiff_t stride, int dc); ++void ff_hevc_rpi_add_residual_32x32_dc_neon_10(uint8_t *_dst, ptrdiff_t stride, int dc); ++ ++ ++void ff_hevc_rpi_add_residual_4x4_u_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_8x8_u_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_16x16_u_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_4x4_v_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_8x8_v_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_16x16_v_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_4x4_c_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_8x8_c_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_16x16_c_neon_8(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_4x4_dc_c_neon_8(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++void ff_hevc_rpi_add_residual_8x8_dc_c_neon_8(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++void ff_hevc_rpi_add_residual_16x16_dc_c_neon_8(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++ ++ ++void ff_hevc_rpi_add_residual_4x4_u_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_8x8_u_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_16x16_u_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_v); ++void ff_hevc_rpi_add_residual_4x4_v_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_8x8_v_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_16x16_v_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride, int dc_u); ++void ff_hevc_rpi_add_residual_4x4_c_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_8x8_c_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_16x16_c_neon_10(uint8_t *_dst, const int16_t * residual, ++ ptrdiff_t stride); ++void ff_hevc_rpi_add_residual_4x4_dc_c_neon_10(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++void ff_hevc_rpi_add_residual_8x8_dc_c_neon_10(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++void ff_hevc_rpi_add_residual_16x16_dc_c_neon_10(uint8_t *_dst, ptrdiff_t stride, int32_t dc); ++ ++void ff_hevc_rpi_sao_edge_8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++ ++void ff_hevc_rpi_sao_edge_8_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_16_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_32_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_64_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height); ++ ++void ff_hevc_rpi_sao_edge_c_8_neon_8(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_c_16_neon_8(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_c_32_neon_8(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++ ++void ff_hevc_rpi_sao_edge_c_8_neon_10(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_c_16_neon_10(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++void ff_hevc_rpi_sao_edge_c_32_neon_10(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height); ++ ++void ff_hevc_rpi_sao_band_c_8_neon_8(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++void ff_hevc_rpi_sao_band_c_16_neon_8(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++void ff_hevc_rpi_sao_band_c_32_neon_8(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++ ++void ff_hevc_rpi_sao_band_c_8_neon_10(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++void ff_hevc_rpi_sao_band_c_16_neon_10(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++void ff_hevc_rpi_sao_band_c_32_neon_10(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height); ++ ++void ff_hevc_rpi_sao_band_8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++ ++void ff_hevc_rpi_sao_band_8_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_16_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_32_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++void ff_hevc_rpi_sao_band_64_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height); ++ ++ ++uint32_t ff_hevc_rpi_deblocking_boundary_strengths_neon(int pus, int dup, const struct HEVCRpiMvField *curr, const struct HEVCRpiMvField *neigh, ++ const int *curr_rpl0, const int *curr_rpl1, const int *neigh_rpl0, const int *neigh_rpl1, ++ int in_inc0, int in_inc1); ++void ff_hevc_rpi_cpy_blks8x4_neon(uint8_t *dst, unsigned int stride_dst, const uint8_t *src, unsigned stride_src, unsigned int width, unsigned int height); ++ ++ ++static void ff_hevc_rpi_sao_edge_48_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_32_neon_8(_dst, _src, stride_dst, _sao_offset_val, eo, 32, height); ++ ff_hevc_rpi_sao_edge_16_neon_8(_dst + 32, _src + 32, stride_dst, _sao_offset_val, eo, 16, height); ++} ++static void ff_hevc_rpi_sao_edge_48_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_32_neon_10(_dst, _src, stride_dst, _sao_offset_val, eo, 32, height); ++ ff_hevc_rpi_sao_edge_16_neon_10(_dst + 64, _src + 64, stride_dst, _sao_offset_val, eo, 16, height); ++} ++ ++static void ff_hevc_rpi_sao_band_48_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height) ++{ ++ ff_hevc_rpi_sao_band_32_neon_8(_dst, _src, stride_dst, stride_src, sao_offset_val, sao_left_class, 32, height); ++ ff_hevc_rpi_sao_band_16_neon_8(_dst + 32, _src + 32, stride_dst, stride_src, sao_offset_val, sao_left_class, 16, height); ++} ++static void ff_hevc_rpi_sao_band_48_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height) ++{ ++ ff_hevc_rpi_sao_band_32_neon_10(_dst, _src, stride_dst, stride_src, sao_offset_val, sao_left_class, 32, height); ++ ff_hevc_rpi_sao_band_16_neon_10(_dst + 64, _src + 64, stride_dst, stride_src, sao_offset_val, sao_left_class, 16, height); ++} ++ ++#if SAO_FILTER_N == 6 ++static void ff_hevc_rpi_sao_edge_24_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_16_neon_8(_dst, _src, stride_dst, _sao_offset_val, eo, 16, height); ++ ff_hevc_rpi_sao_edge_8_neon_8(_dst + 16, _src + 16, stride_dst, _sao_offset_val, eo, 8, height); ++} ++static void ff_hevc_rpi_sao_edge_24_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *_sao_offset_val, int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_16_neon_10(_dst, _src, stride_dst, _sao_offset_val, eo, 16, height); ++ ff_hevc_rpi_sao_edge_8_neon_10(_dst + 32, _src + 32, stride_dst, _sao_offset_val, eo, 8, height); ++} ++ ++static void ff_hevc_rpi_sao_band_24_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height) ++{ ++ ff_hevc_rpi_sao_band_16_neon_8(_dst, _src, stride_dst, stride_src, sao_offset_val, sao_left_class, 16, height); ++ ff_hevc_rpi_sao_band_8_neon_8(_dst + 16, _src + 16, stride_dst, stride_src, sao_offset_val, sao_left_class, 8, height); ++} ++static void ff_hevc_rpi_sao_band_24_neon_10(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, int width, int height) ++{ ++ ff_hevc_rpi_sao_band_16_neon_10(_dst, _src, stride_dst, stride_src, sao_offset_val, sao_left_class, 16, height); ++ ff_hevc_rpi_sao_band_8_neon_10(_dst + 32, _src + 32, stride_dst, stride_src, sao_offset_val, sao_left_class, 8, height); ++} ++ ++static void ff_hevc_rpi_sao_edge_c_24_neon_8(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_c_16_neon_8(_dst, _src, stride_dst, _sao_offset_val_u, _sao_offset_val_v, eo, 16, height); ++ ff_hevc_rpi_sao_edge_c_8_neon_8(_dst + 32, _src + 32, stride_dst, _sao_offset_val_u, _sao_offset_val_v, eo, 8, height); ++} ++static void ff_hevc_rpi_sao_edge_c_24_neon_10(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *_sao_offset_val_u, const int16_t *_sao_offset_val_v, ++ int eo, int width, int height) ++{ ++ ff_hevc_rpi_sao_edge_c_16_neon_10(_dst, _src, stride_dst, _sao_offset_val_u, _sao_offset_val_v, eo, 16, height); ++ ff_hevc_rpi_sao_edge_c_8_neon_10(_dst + 64, _src + 64, stride_dst, _sao_offset_val_u, _sao_offset_val_v, eo, 8, height); ++} ++ ++static void ff_hevc_rpi_sao_band_c_24_neon_8(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height) ++{ ++ ff_hevc_rpi_sao_band_c_16_neon_8(_dst, _src, stride_dst, stride_src, ++ sao_offset_val_u, sao_left_class_u, sao_offset_val_v, sao_left_class_v, 16, height); ++ ff_hevc_rpi_sao_band_c_8_neon_8(_dst + 32, _src + 32, stride_dst, stride_src, ++ sao_offset_val_u, sao_left_class_u, sao_offset_val_v, sao_left_class_v, 8, height); ++} ++static void ff_hevc_rpi_sao_band_c_24_neon_10(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height) ++{ ++ ff_hevc_rpi_sao_band_c_16_neon_10(_dst, _src, stride_dst, stride_src, ++ sao_offset_val_u, sao_left_class_u, sao_offset_val_v, sao_left_class_v, 16, height); ++ ff_hevc_rpi_sao_band_c_8_neon_10(_dst + 64, _src + 64, stride_dst, stride_src, ++ sao_offset_val_u, sao_left_class_u, sao_offset_val_v, sao_left_class_v, 8, height); ++} ++#endif ++ ++ ++ ++#if RPI_HEVC_SAO_BUF_STRIDE != 160 ++#error SAO edge src stride not 160 - value used in .S ++#endif ++ ++av_cold void ff_hevcdsp_rpi_init_neon(HEVCDSPContext *c, const int bit_depth) ++{ ++ if (bit_depth == 8) { ++ c->hevc_v_loop_filter_luma = ff_hevc_rpi_v_loop_filter_luma_neon_8; ++ c->hevc_v_loop_filter_luma_c = ff_hevc_rpi_v_loop_filter_luma_neon_8; ++ c->hevc_h_loop_filter_luma = ff_hevc_rpi_h_loop_filter_luma_neon_8; ++ c->hevc_h_loop_filter_luma_c = ff_hevc_rpi_h_loop_filter_luma_neon_8; ++ c->hevc_h_loop_filter_luma2 = ff_hevc_rpi_h_loop_filter_luma2_neon_8; ++ c->hevc_v_loop_filter_luma2 = ff_hevc_rpi_v_loop_filter_luma2_neon_8; ++ c->hevc_h_loop_filter_uv = ff_hevc_rpi_h_loop_filter_uv_neon_8; ++ c->hevc_v_loop_filter_uv2 = ff_hevc_rpi_v_loop_filter_uv2_neon_8; ++ c->idct[0] = ff_hevc_rpi_transform_4x4_neon_8; ++ c->idct[1] = ff_hevc_rpi_transform_8x8_neon_8; ++ c->idct_dc[0] = ff_hevc_rpi_idct_4x4_dc_neon_8; ++ c->idct_dc[1] = ff_hevc_rpi_idct_8x8_dc_neon_8; ++ c->idct_dc[2] = ff_hevc_rpi_idct_16x16_dc_neon_8; ++ c->idct_dc[3] = ff_hevc_rpi_idct_32x32_dc_neon_8; ++ c->add_residual[0] = ff_hevc_rpi_add_residual_4x4_neon_8; ++ c->add_residual[1] = ff_hevc_rpi_add_residual_8x8_neon_8; ++ c->add_residual[2] = ff_hevc_rpi_add_residual_16x16_neon_8; ++ c->add_residual[3] = ff_hevc_rpi_add_residual_32x32_neon_8; ++ c->add_residual_dc[0] = ff_hevc_rpi_add_residual_4x4_dc_neon_8; ++ c->add_residual_dc[1] = ff_hevc_rpi_add_residual_8x8_dc_neon_8; ++ c->add_residual_dc[2] = ff_hevc_rpi_add_residual_16x16_dc_neon_8; ++ c->add_residual_dc[3] = ff_hevc_rpi_add_residual_32x32_dc_neon_8; ++ c->add_residual_u[0] = ff_hevc_rpi_add_residual_4x4_u_neon_8; ++ c->add_residual_u[1] = ff_hevc_rpi_add_residual_8x8_u_neon_8; ++ c->add_residual_u[2] = ff_hevc_rpi_add_residual_16x16_u_neon_8; ++ c->add_residual_v[0] = ff_hevc_rpi_add_residual_4x4_v_neon_8; ++ c->add_residual_v[1] = ff_hevc_rpi_add_residual_8x8_v_neon_8; ++ c->add_residual_v[2] = ff_hevc_rpi_add_residual_16x16_v_neon_8; ++ c->add_residual_c[0] = ff_hevc_rpi_add_residual_4x4_c_neon_8; ++ c->add_residual_c[1] = ff_hevc_rpi_add_residual_8x8_c_neon_8; ++ c->add_residual_c[2] = ff_hevc_rpi_add_residual_16x16_c_neon_8; ++ c->add_residual_dc_c[0] = ff_hevc_rpi_add_residual_4x4_dc_c_neon_8; ++ c->add_residual_dc_c[1] = ff_hevc_rpi_add_residual_8x8_dc_c_neon_8; ++ c->add_residual_dc_c[2] = ff_hevc_rpi_add_residual_16x16_dc_c_neon_8; ++ c->transform_4x4_luma = ff_hevc_rpi_transform_luma_4x4_neon_8; ++ c->sao_band_filter[0] = ff_hevc_rpi_sao_band_8_neon_8; ++ c->sao_band_filter[1] = ff_hevc_rpi_sao_band_16_neon_8; ++ c->sao_band_filter[2] = ff_hevc_rpi_sao_band_32_neon_8; ++ c->sao_band_filter[3] = ff_hevc_rpi_sao_band_48_neon_8; ++ c->sao_band_filter[4] = ff_hevc_rpi_sao_band_64_neon_8; ++ c->sao_edge_filter[0] = ff_hevc_rpi_sao_edge_8_neon_8; ++ c->sao_edge_filter[1] = ff_hevc_rpi_sao_edge_16_neon_8; ++ c->sao_edge_filter[2] = ff_hevc_rpi_sao_edge_32_neon_8; ++ c->sao_edge_filter[3] = ff_hevc_rpi_sao_edge_48_neon_8; ++ c->sao_edge_filter[4] = ff_hevc_rpi_sao_edge_64_neon_8; ++#if SAO_FILTER_N == 6 ++ c->sao_band_filter[5] = ff_hevc_rpi_sao_band_24_neon_8; ++ c->sao_edge_filter[5] = ff_hevc_rpi_sao_edge_24_neon_8; ++#endif ++ c->sao_band_filter_c[0] = ff_hevc_rpi_sao_band_c_8_neon_8; ++ c->sao_band_filter_c[1] = ff_hevc_rpi_sao_band_c_16_neon_8; ++ c->sao_band_filter_c[2] = ff_hevc_rpi_sao_band_c_32_neon_8; ++ ++ c->sao_edge_filter_c[0] = ff_hevc_rpi_sao_edge_c_8_neon_8; ++ c->sao_edge_filter_c[1] = ff_hevc_rpi_sao_edge_c_16_neon_8; ++ c->sao_edge_filter_c[2] = ff_hevc_rpi_sao_edge_c_32_neon_8; ++ ++#if SAO_FILTER_N == 6 ++ c->sao_band_filter_c[5] = ff_hevc_rpi_sao_band_c_24_neon_8; ++ c->sao_edge_filter_c[5] = ff_hevc_rpi_sao_edge_c_24_neon_8; ++#endif ++ } ++ else if (bit_depth == 10) { ++ c->hevc_v_loop_filter_luma = ff_hevc_rpi_v_loop_filter_luma_neon_10; ++ c->hevc_v_loop_filter_luma_c = ff_hevc_rpi_v_loop_filter_luma_neon_10; ++ c->hevc_h_loop_filter_luma = ff_hevc_rpi_h_loop_filter_luma_neon_10; ++ c->hevc_h_loop_filter_luma_c = ff_hevc_rpi_h_loop_filter_luma_neon_10; ++ c->hevc_h_loop_filter_luma2 = ff_hevc_rpi_h_loop_filter_luma2_neon_10; ++ c->hevc_v_loop_filter_luma2 = ff_hevc_rpi_v_loop_filter_luma2_neon_10; ++ c->hevc_h_loop_filter_uv = ff_hevc_rpi_h_loop_filter_uv_neon_10; ++ c->hevc_v_loop_filter_uv2 = ff_hevc_rpi_v_loop_filter_uv2_neon_10; ++ c->idct[0] = ff_hevc_rpi_transform_4x4_neon_10; ++ c->idct[1] = ff_hevc_rpi_transform_8x8_neon_10; ++ c->idct_dc[0] = ff_hevc_rpi_idct_4x4_dc_neon_10; ++ c->idct_dc[1] = ff_hevc_rpi_idct_8x8_dc_neon_10; ++ c->idct_dc[2] = ff_hevc_rpi_idct_16x16_dc_neon_10; ++ c->idct_dc[3] = ff_hevc_rpi_idct_32x32_dc_neon_10; ++ c->add_residual[0] = ff_hevc_rpi_add_residual_4x4_neon_10; ++ c->add_residual[1] = ff_hevc_rpi_add_residual_8x8_neon_10; ++ c->add_residual[2] = ff_hevc_rpi_add_residual_16x16_neon_10; ++ c->add_residual[3] = ff_hevc_rpi_add_residual_32x32_neon_10; ++ c->add_residual_dc[0] = ff_hevc_rpi_add_residual_4x4_dc_neon_10; ++ c->add_residual_dc[1] = ff_hevc_rpi_add_residual_8x8_dc_neon_10; ++ c->add_residual_dc[2] = ff_hevc_rpi_add_residual_16x16_dc_neon_10; ++ c->add_residual_dc[3] = ff_hevc_rpi_add_residual_32x32_dc_neon_10; ++ c->add_residual_u[0] = ff_hevc_rpi_add_residual_4x4_u_neon_10; ++ c->add_residual_u[1] = ff_hevc_rpi_add_residual_8x8_u_neon_10; ++ c->add_residual_u[2] = ff_hevc_rpi_add_residual_16x16_u_neon_10; ++ c->add_residual_v[0] = ff_hevc_rpi_add_residual_4x4_v_neon_10; ++ c->add_residual_v[1] = ff_hevc_rpi_add_residual_8x8_v_neon_10; ++ c->add_residual_v[2] = ff_hevc_rpi_add_residual_16x16_v_neon_10; ++ c->add_residual_c[0] = ff_hevc_rpi_add_residual_4x4_c_neon_10; ++ c->add_residual_c[1] = ff_hevc_rpi_add_residual_8x8_c_neon_10; ++ c->add_residual_c[2] = ff_hevc_rpi_add_residual_16x16_c_neon_10; ++ c->add_residual_dc_c[0] = ff_hevc_rpi_add_residual_4x4_dc_c_neon_10; ++ c->add_residual_dc_c[1] = ff_hevc_rpi_add_residual_8x8_dc_c_neon_10; ++ c->add_residual_dc_c[2] = ff_hevc_rpi_add_residual_16x16_dc_c_neon_10; ++ c->transform_4x4_luma = ff_hevc_rpi_transform_luma_4x4_neon_10; ++ c->sao_band_filter[0] = ff_hevc_rpi_sao_band_8_neon_10; ++ c->sao_band_filter[1] = ff_hevc_rpi_sao_band_16_neon_10; ++ c->sao_band_filter[2] = ff_hevc_rpi_sao_band_32_neon_10; ++ c->sao_band_filter[3] = ff_hevc_rpi_sao_band_48_neon_10; ++ c->sao_band_filter[4] = ff_hevc_rpi_sao_band_64_neon_10; ++ ++ c->sao_edge_filter[0] = ff_hevc_rpi_sao_edge_8_neon_10; ++ c->sao_edge_filter[1] = ff_hevc_rpi_sao_edge_16_neon_10; ++ c->sao_edge_filter[2] = ff_hevc_rpi_sao_edge_32_neon_10; ++ c->sao_edge_filter[3] = ff_hevc_rpi_sao_edge_48_neon_10; ++ c->sao_edge_filter[4] = ff_hevc_rpi_sao_edge_64_neon_10; ++#if SAO_FILTER_N == 6 ++ c->sao_band_filter[5] = ff_hevc_rpi_sao_band_24_neon_10; ++ c->sao_edge_filter[5] = ff_hevc_rpi_sao_edge_24_neon_10; ++#endif ++ c->sao_band_filter_c[0] = ff_hevc_rpi_sao_band_c_8_neon_10; ++ c->sao_band_filter_c[1] = ff_hevc_rpi_sao_band_c_16_neon_10; ++ c->sao_band_filter_c[2] = ff_hevc_rpi_sao_band_c_32_neon_10; ++ ++ c->sao_edge_filter_c[0] = ff_hevc_rpi_sao_edge_c_8_neon_10; ++ c->sao_edge_filter_c[1] = ff_hevc_rpi_sao_edge_c_16_neon_10; ++ c->sao_edge_filter_c[2] = ff_hevc_rpi_sao_edge_c_32_neon_10; ++ ++#if SAO_FILTER_N == 6 ++ c->sao_band_filter_c[5] = ff_hevc_rpi_sao_band_c_24_neon_10; ++ c->sao_edge_filter_c[5] = ff_hevc_rpi_sao_edge_c_24_neon_10; ++#endif ++ } ++ ++ assert(offsetof(HEVCRpiMvField, mv) == 0); ++ assert(offsetof(HEVCRpiMvField, ref_idx) == 8); ++ assert(offsetof(HEVCRpiMvField, pred_flag) == 10); ++ c->hevc_deblocking_boundary_strengths = ff_hevc_rpi_deblocking_boundary_strengths_neon; ++ c->cpy_blk = ff_hevc_rpi_cpy_blks8x4_neon; ++} +diff --git a/libavcodec/arm/rpi_hevcdsp_res16_neon.S b/libavcodec/arm/rpi_hevcdsp_res16_neon.S +new file mode 100644 +index 0000000000..93876d14c0 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_res16_neon.S +@@ -0,0 +1,620 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++ .arch_extension mp @ enable PLDW ++ ++#define BIT_DEPTH 10 ++ ++.macro clip16_4 Q0, Q1, Q2, Q3, Q_MIN, Q_MAX ++ vmax.s16 \Q0, \Q_MIN ++ vmax.s16 \Q1, \Q_MIN ++ vmax.s16 \Q2, \Q_MIN ++ vmax.s16 \Q3, \Q_MIN ++ vmin.s16 \Q0, \Q_MAX ++ vmin.s16 \Q1, \Q_MAX ++ vmin.s16 \Q2, \Q_MAX ++ vmin.s16 \Q3, \Q_MAX ++.endm ++ ++@ add_residual4x4( ++@ uint16_t *_dst, [r0] ++@ int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_neon_, BIT_DEPTH), export=1 ++ add ip, r0, r2 ++ vld1.16 {q10, q11}, [r1] ++ lsl r2, #1 ++ vld1.16 {d0}, [r0 :64], r2 ++ vld1.16 {d1}, [ip :64], r2 ++ vld1.16 {d2}, [r0 :64] ++ vld1.16 {d3}, [ip :64] ++ sub r0, r2 ++ vqadd.s16 q0, q10 ++ sub ip, r2 ++ vqadd.s16 q1, q11 ++ vmov.i16 q8, #0 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ vmax.s16 q0, q0, q8 ++ vmax.s16 q1, q1, q8 ++ vmin.s16 q0, q0, q9 ++ vmin.s16 q1, q1, q9 ++ vst1.16 {d0}, [r0 :64], r2 ++ vst1.16 {d1}, [ip :64], r2 ++ vst1.16 {d2}, [r0 :64] ++ vst1.16 {d3}, [ip :64] ++ bx lr ++ ++endfunc ++ ++@ add_residual4x4_dc( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_dc_neon_, BIT_DEPTH), export=1 ++ add ip, r0, r1 ++ vdup.16 q15, r2 ++ lsl r1, #1 ++ vld1.16 {d0}, [r0 :64], r1 ++ vld1.16 {d1}, [ip :64], r1 ++ vld1.16 {d2}, [r0 :64] ++ vld1.16 {d3}, [ip :64] ++ sub r0, r1 ++ vqadd.s16 q0, q15 ++ sub ip, r1 ++ vqadd.s16 q1, q15 ++ vmov.i16 q8, #0 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ vmax.s16 q0, q0, q8 ++ vmax.s16 q1, q1, q8 ++ vmin.s16 q0, q0, q9 ++ vmin.s16 q1, q1, q9 ++ vst1.16 {d0}, [r0 :64], r1 ++ vst1.16 {d1}, [ip :64], r1 ++ vst1.16 {d2}, [r0 :64] ++ vst1.16 {d3}, [ip :64] ++ bx lr ++ ++endfunc ++ ++ ++@ add_residual8x8( ++@ uint16_t *_dst, [r0] ++@ int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_neon_, BIT_DEPTH), export=1 ++ mov r3, #8 ++ vmov.i64 q8, #0 ++ add ip, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r2, #1 ++1: ++ vldm r1!, {q10-q13} ++ vld1.16 {q0}, [r0 :128], r2 ++ vld1.16 {q1}, [ip :128], r2 ++ vld1.16 {q2}, [r0 :128] ++ vld1.16 {q3}, [ip :128] ++ sub r0, r2 ++ vqadd.s16 q0, q10 ++ sub ip, r2 ++ vqadd.s16 q1, q11 ++ subs r3, #4 ++ vqadd.s16 q2, q12 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0}, [r0 :128], r2 ++ vst1.16 {q1}, [ip :128], r2 ++ vst1.16 {q2}, [r0 :128], r2 ++ vst1.16 {q3}, [ip :128], r2 ++ bne 1b ++ bx lr ++ ++endfunc ++ ++@ add_residual4x4_dc_c( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc_uv) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_dc_c_neon_, BIT_DEPTH), export=1 ++ mov r3, #4 ++ vdup.32 q15, r2 ++ b 9f ++endfunc ++ ++@ add_residual8x8_dc( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_dc_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r2 ++ mov r3, #8 ++9: ++ vmov.i16 q8, #0 ++ add ip, r0, r1 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r1, #1 ++1: ++ vld1.16 {q0}, [r0 :128], r1 ++ vld1.16 {q1}, [ip :128], r1 ++ vld1.16 {q2}, [r0 :128] ++ vld1.16 {q3}, [ip :128] ++ sub r0, r1 ++ vqadd.s16 q0, q15 ++ sub ip, r1 ++ vqadd.s16 q1, q15 ++ subs r3, #4 ++ vqadd.s16 q2, q15 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0}, [r0 :128], r1 ++ vst1.16 {q1}, [ip :128], r1 ++ vst1.16 {q2}, [r0 :128], r1 ++ vst1.16 {q3}, [ip :128], r1 ++ bne 1b ++ bx lr ++ ++endfunc ++ ++@ add_residual16x16( ++@ uint16_t *_dst, [r0] ++@ int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_neon_, BIT_DEPTH), export=1 ++ add ip, r0, r2 ++ vmov.i16 q8, #0 ++ lsl r2, #1 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ mov r3, #16 ++1: ++ vldm r1!, {q10-q13} ++ @ For RPI Sand we could guarantee :256 but not for general ++ @ non-RPI allocation. :128 is as good as we can claim ++ vld1.16 {q0, q1}, [r0 :128] ++ subs r3, #2 ++ vld1.16 {q2, q3}, [ip :128] ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q11 ++ vqadd.s16 q2, q12 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0, q1}, [r0 :128], r2 ++ vst1.16 {q2, q3}, [ip :128], r2 ++ bne 1b ++ bx lr ++endfunc ++ ++@ add_residual8x8_dc_c( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc_uv) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_dc_c_neon_, BIT_DEPTH), export=1 ++ mov r3, #8 ++ vdup.32 q15, r2 ++ b 9f ++endfunc ++ ++@ add_residual16x16_dc( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_dc_neon_, BIT_DEPTH), export=1 ++ vdup.i16 q15, r2 ++ mov r3, #16 ++9: ++ vmov.i16 q8, #0 ++ add ip, r0, r1 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r1, #1 ++1: ++ @ For RPI Sand we could guarantee :256 but not for general ++ @ non-RPI allocation. :128 is as good as we can claim ++ vld1.16 {q0, q1}, [r0 :128] ++ subs r3, #2 ++ vqadd.s16 q0, q15 ++ vqadd.s16 q1, q15 ++ vld1.16 {q2, q3}, [ip :128] ++ vqadd.s16 q2, q15 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0, q1}, [r0 :128], r1 ++ vst1.16 {q2, q3}, [ip :128], r1 ++ bne 1b ++ bx lr ++ ++endfunc ++ ++ ++@ add_residual32x32( ++@ uint16_t *_dst, [r0] ++@ int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_32x32_neon_, BIT_DEPTH), export=1 ++ push {lr} ++ mov r3, #32 ++ vmov.i16 q8, #0 ++ add lr, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ add ip, r0, #32 ++1: ++ vldm r1!, {q10-q13} ++ vldm r0, {q0-q3} ++ vqadd.s16 q0, q10 ++ pldw [lr] ++ vqadd.s16 q1, q11 ++ add lr, r2 ++ vqadd.s16 q2, q12 ++ subs r3, #1 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0-q1}, [r0], r2 ++ vst1.16 {q2-q3}, [ip], r2 ++ bne 1b ++ pop {pc} ++ ++endfunc ++ ++@ add_residual16x16_dc_c( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc_uv) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_dc_c_neon_, BIT_DEPTH), export=1 ++ mov r3, #16 ++ vdup.32 q15, r2 ++ b 9f ++endfunc ++ ++@ add_residual32x32_dc( ++@ uint16_t *_dst, [r0] ++@ ptrdiff_t stride, [r1] ++@ int dc) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_32x32_dc_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r2 ++ mov r3, #32 ++9: ++ vmov.i16 q8, #0 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ add ip, r0, #32 ++1: ++ vldm r0, {q0-q3} ++ vqadd.s16 q0, q15 ++ subs r3, #1 ++ vqadd.s16 q1, q15 ++ vqadd.s16 q2, q15 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst1.16 {q0-q1}, [r0], r1 ++ vst1.16 {q2-q3}, [ip], r1 ++ bne 1b ++ bx lr ++ ++endfunc ++ ++@ ============================================================================ ++@ U add ++ ++@ add_residual4x4_u( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_u_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ vld1.16 {q10, q11}, [r1 :256] ++ lsl r2, #1 ++ vld2.16 {d0, d2}, [r0 :128], r2 ++ vld2.16 {d1, d3}, [ip :128], r2 ++ vld2.16 {d4, d6}, [r0 :128] ++ vld2.16 {d5, d7}, [ip :128] ++ sub r0, r2 ++ vmov.i16 q8, #0 ++ sub ip, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q15 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ ++ vst2.16 {d0, d2}, [r0 :128], r2 ++ vst2.16 {d1, d3}, [ip :128], r2 ++ vst2.16 {d4, d6}, [r0 :128] ++ vst2.16 {d5, d7}, [ip :128] ++ bx lr ++endfunc ++ ++@ add_residual8x8_u( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_u_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r3 ++ mov r3, #8 ++ vmov.i16 q8, #0 ++ add ip, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r2, #1 ++1: ++ vld2.16 {q0, q1}, [r0 :256] ++ subs r3, #2 ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q10, q11}, [r1 :256]! ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q15 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ bx lr ++endfunc ++ ++@ add_residual16x16_u( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_u_neon_, BIT_DEPTH), export=1 ++ push {lr} ++ vdup.16 q15, r3 ++ mov r3, #16 ++ vmov.i16 q8, #0 ++ add lr, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ add ip, r0, #32 ++1: ++ vld2.16 {q0, q1}, [r0 :256] ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q10, q11}, [r1 :256]! ++ vqadd.s16 q0, q10 ++ pldw [lr] ++ vqadd.s16 q1, q15 ++ add lr, r2 ++ vqadd.s16 q2, q11 ++ subs r3, #1 ++ vqadd.s16 q3, q15 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ pop {pc} ++endfunc ++ ++@ ============================================================================ ++@ V add ++ ++@ add_residual4x4_v( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_v_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ vld1.16 {q10, q11}, [r1 :256] ++ lsl r2, #1 ++ vld2.16 {d0, d2}, [r0 :128], r2 ++ vld2.16 {d1, d3}, [ip :128], r2 ++ vld2.16 {d4, d6}, [r0 :128] ++ vld2.16 {d5, d7}, [ip :128] ++ sub r0, r2 ++ vmov.i16 q8, #0 ++ sub ip, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ ++ vqadd.s16 q0, q15 ++ vqadd.s16 q1, q10 ++ vqadd.s16 q2, q15 ++ vqadd.s16 q3, q11 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ ++ vst2.16 {d0, d2}, [r0 :128], r2 ++ vst2.16 {d1, d3}, [ip :128], r2 ++ vst2.16 {d4, d6}, [r0 :128] ++ vst2.16 {d5, d7}, [ip :128] ++ bx lr ++endfunc ++ ++@ add_residual8x8_v( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_v_neon_, BIT_DEPTH), export=1 ++ vdup.16 q15, r3 ++ mov r3, #8 ++ vmov.i16 q8, #0 ++ add ip, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r2, #1 ++1: ++ vld2.16 {q0, q1}, [r0 :256] ++ subs r3, #2 ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q10, q11}, [r1 :256]! ++ vqadd.s16 q0, q15 ++ vqadd.s16 q1, q10 ++ vqadd.s16 q2, q15 ++ vqadd.s16 q3, q11 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ bx lr ++endfunc ++ ++@ add_residual16x16_v( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc) [r3] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_v_neon_, BIT_DEPTH), export=1 ++ push {lr} ++ vdup.16 q15, r3 ++ mov r3, #16 ++ vmov.i16 q8, #0 ++ add lr, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ add ip, r0, #32 ++1: ++ vld2.16 {q0, q1}, [r0 :256] ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q10, q11}, [r1 :256]! ++ vqadd.s16 q0, q15 ++ pldw [lr] ++ vqadd.s16 q1, q10 ++ add lr, r2 ++ vqadd.s16 q2, q15 ++ subs r3, #1 ++ vqadd.s16 q3, q11 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ pop {pc} ++endfunc ++ ++@ ============================================================================ ++@ U & V add ++ ++@ add_residual4x4_c( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_4x4_c_neon_, BIT_DEPTH), export=1 ++ vmov.i16 q8, #0 ++ add ip, r0, r2 ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ lsl r2, #1 ++ vldm r1, {q10-q13} ++ vld2.16 {d0, d2}, [r0 :128], r2 ++ vld2.16 {d1, d3}, [ip :128], r2 ++ vld2.16 {d4, d6}, [r0 :128] ++ vld2.16 {d5, d7}, [ip :128] ++ ++ sub r0, r2 ++ vqadd.s16 q0, q10 ++ sub ip, r2 ++ vqadd.s16 q1, q12 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ ++ vst2.16 {d0, d2}, [r0 :128], r2 ++ vst2.16 {d1, d3}, [ip :128], r2 ++ vst2.16 {d4, d6}, [r0 :128] ++ vst2.16 {d5, d7}, [ip :128] ++ bx lr ++endfunc ++ ++@ add_residual8x8_c( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_8x8_c_neon_, BIT_DEPTH), export=1 ++ push {lr} ++ add ip, r0, r2 ++ lsl r2, #1 ++ vmov.i16 q8, #0 ++ add r3, r1, #(8*8*2) @ Offset to V ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ mov lr, #8 ++1: ++ vld1.16 {q10, q11}, [r1 :256]! ++ subs lr, #2 ++ vld2.16 {q0, q1}, [r0 :256] ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q12, q13}, [r3 :256]! ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q12 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ pop {pc} ++endfunc ++ ++@ add_residual16x16_c( ++@ uint16_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function JOIN(ff_hevc_rpi_add_residual_16x16_c_neon_, BIT_DEPTH), export=1 ++ push {r4, lr} ++ vmov.i16 q8, #0 ++ add r3, r1, #(16*16*2) @ Offset to V ++ vmov.i16 q9, #(1 << BIT_DEPTH) - 1 ++ add ip, r0, #32 ++ add r4, r0, r2 ++ mov lr, #16 ++1: ++ vld2.16 {q0, q1}, [r0 :256] ++ vld2.16 {q2, q3}, [ip :256] ++ vld1.16 {q10, q11}, [r1 :256]! ++ vld1.16 {q12, q13}, [r3 :256]! ++ vqadd.s16 q0, q10 ++ pldw [r4] ++ vqadd.s16 q1, q12 ++ add r4, r2 ++ vqadd.s16 q2, q11 ++ subs lr, #1 ++ vqadd.s16 q3, q13 ++ clip16_4 q0, q1, q2, q3, q8, q9 ++ vst2.16 {q0, q1}, [r0 :256], r2 ++ vst2.16 {q2, q3}, [ip :256], r2 ++ bne 1b ++ pop {r4,pc} ++endfunc ++ +diff --git a/libavcodec/arm/rpi_hevcdsp_res8_neon.S b/libavcodec/arm/rpi_hevcdsp_res8_neon.S +new file mode 100644 +index 0000000000..d9a1d7d98c +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_res8_neon.S +@@ -0,0 +1,741 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++ .arch_extension mp @ enable PLDW ++ ++@ General notes: ++@ ++@ Residual is generally only guaranteed to be clipped to 16 bits. ++@ This means that we do need to do vmovl, vqadd, vqmovun ++@ rather than vaddw, vqmovun (if we were clipped to 15 then we could get away ++@ with this). ++@ ++@ There is an exception for the DC case because its transform is guaranteed ++@ to be small enough that overflow cannot occur during the first add. ++ ++@ ============================================================================ ++@ Y add ++ ++function ff_hevc_rpi_add_residual_4x4_neon_8, export=1 ++ add ip, r0, r2 ++ vld1.16 {q0, q1}, [r1] ++ lsl r2, #1 ++ vld1.32 d4[0], [r0], r2 ++ rsb r3, r2, #0 ++ vld1.32 d4[1], [ip], r2 ++ vld1.32 d5[0], [r0], r3 ++ vld1.32 d5[1], [ip], r3 ++ vmovl.u8 q8, d4 ++ vmovl.u8 q9, d5 ++ vqadd.s16 q0, q8 ++ vqadd.s16 q1, q9 ++ vqmovun.s16 d0, q0 ++ vqmovun.s16 d1, q1 ++ vst1.32 d0[0], [r0], r2 ++ vst1.32 d0[1], [ip], r2 ++ vst1.32 d1[0], [r0] ++ vst1.32 d1[1], [ip] ++ bx lr ++endfunc ++ ++function ff_hevc_rpi_add_residual_8x8_neon_8, export=1 ++ push {r4, lr} ++ vld1.16 {q0, q1}, [r1]! ++ add ip, r0, r2 ++ vld1.8 {d6}, [r0] ++ add r4, r0, r2, lsl #1 ++ vld1.8 {d7}, [ip] ++ add lr, ip, r2, lsl #1 ++ lsl r2, #1 ++ mov r3, #8-2 ++ vmovl.u8 q2, d6 ++ vmovl.u8 q3, d7 ++ vqadd.s16 q2, q0 ++ vqadd.s16 q3, q1 ++1: ++ vld1.16 {q0, q1}, [r1]! ++ subs r3, #2 ++ vqmovun.s16 d4, q2 ++ vqmovun.s16 d5, q3 ++ vld1.8 {d6}, [r4], r2 ++ vld1.8 {d7}, [lr], r2 ++ vst1.8 {d4}, [r0], r2 ++ vst1.8 {d5}, [ip], r2 ++ vmovl.u8 q2, d6 ++ pldw [r4] ++ vmovl.u8 q3, d7 ++ vqadd.s16 q2, q0 ++ vqadd.s16 q3, q1 ++ bne 1b ++ ++ vqmovun.s16 d4, q2 ++ vqmovun.s16 d5, q3 ++ vst1.8 {d4}, [r0] ++ vst1.8 {d5}, [ip] ++ pop {r4, pc} ++endfunc ++ ++function ff_hevc_rpi_add_residual_16x16_neon_8, export=1 ++ vld1.16 {q0, q1}, [r1]! ++ add ip, r0, r2 ++ vld1.8 {q3}, [r0] ++ mov r3, #16-1 ++ vmovl.u8 q2, d6 ++ vmovl.u8 q3, d7 ++ vqadd.s16 q2, q0 ++ vqadd.s16 q3, q1 ++1: ++ vld1.16 {q0, q1}, [r1]! ++ subs r3, #1 ++ vqmovun.s16 d4, q2 ++ vqmovun.s16 d5, q3 ++ vld1.8 {q3}, [ip], r2 ++ vst1.8 {q2}, [r0], r2 ++ vmovl.u8 q2, d6 ++ pldw [ip] ++ vmovl.u8 q3, d7 ++ vqadd.s16 q2, q0 ++ vqadd.s16 q3, q1 ++ bne 1b ++ ++ vqmovun.s16 d4, q2 ++ vqmovun.s16 d5, q3 ++ vst1.8 {q2}, [r0] ++ bx lr ++endfunc ++ ++function ff_hevc_rpi_add_residual_32x32_neon_8, export=1 ++ vldm r1!, {q0-q3} ++ vld1.8 {q8, q9}, [r0] ++ add ip, r0, r2 ++ vmovl.u8 q10, d16 ++ mov r3, #32-1 ++ vmovl.u8 q11, d17 ++ vmovl.u8 q12, d18 ++ vmovl.u8 q13, d19 ++ vqadd.s16 q10, q0 ++ vqadd.s16 q11, q1 ++ vqadd.s16 q12, q2 ++ vqadd.s16 q13, q3 ++1: ++ vldm r1!, {q0-q3} ++ vqmovun.s16 d20, q10 ++ vqmovun.s16 d21, q11 ++ vqmovun.s16 d22, q12 ++ vqmovun.s16 d23, q13 ++ vld1.8 {q8, q9}, [ip], r2 ++ subs r3, #1 ++ vst1.8 {q10, q11}, [r0], r2 ++ vmovl.u8 q10, d16 ++ pldw [ip] ++ vmovl.u8 q11, d17 ++ vmovl.u8 q12, d18 ++ vmovl.u8 q13, d19 ++ vqadd.s16 q10, q0 ++ vqadd.s16 q11, q1 ++ vqadd.s16 q12, q2 ++ vqadd.s16 q13, q3 ++ bne 1b ++ ++ vqmovun.s16 d20, q10 ++ vqmovun.s16 d21, q11 ++ vqmovun.s16 d22, q12 ++ vqmovun.s16 d23, q13 ++ vst1.8 {q10, q11}, [r0] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_add_residual_4x4_dc_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_4x4_dc_neon_8, export=1 ++ add ip, r0, r1 ++ vdup.16 q15, r2 ++ lsl r1, #1 ++ vld1.32 d4[0], [r0], r1 ++ rsb r3, r1, #0 ++ vld1.32 d4[1], [ip], r1 ++ vld1.32 d5[0], [r0], r3 ++ vld1.32 d5[1], [ip], r3 ++ vaddw.u8 q0, q15, d4 ++ vaddw.u8 q1, q15, d5 ++ vqmovun.s16 d0, q0 ++ vqmovun.s16 d1, q1 ++ vst1.32 d0[0], [r0], r1 ++ vst1.32 d0[1], [ip], r1 ++ vst1.32 d1[0], [r0] ++ vst1.32 d1[1], [ip] ++ bx lr ++endfunc ++ ++@ ============================================================================ ++@ DC Y or C add ++ ++@ ff_hevc_rpi_add_residual_4x4_dc_c_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_4x4_dc_c_neon_8, export=1 ++ mov r3, #4-2 ++ vdup.32 q15, r2 ++ b 1f ++endfunc ++ ++@ ff_hevc_rpi_add_residual_8x8_dc_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_8x8_dc_neon_8, export=1 ++ vdup.16 q15, r2 ++ mov r3, #8-2 ++1: vld1.8 d16, [r0] ++ add ip, r0, r1 ++ push {r4, lr} ++ vld1.8 d17, [ip] ++ add r4, r0, r1, lsl #1 ++ vaddw.u8 q0, q15, d16 ++ lsl r1, #1 ++ vaddw.u8 q1, q15, d17 ++ add lr, ip, r1 ++1: ++ vld1.8 {d16}, [r4], r1 ++ vld1.8 {d17}, [lr], r1 ++ subs r3, #2 ++ vqmovun.s16 d4, q0 ++ vqmovun.s16 d5, q1 ++ vaddw.u8 q0, q15, d16 ++ vaddw.u8 q1, q15, d17 ++ vst1.8 {d4}, [r0], r1 ++ vst1.8 {d5}, [ip], r1 ++ bne 1b ++ ++ vqmovun.s16 d4, q0 ++ vqmovun.s16 d5, q1 ++ vst1.8 {d4}, [r0] ++ vst1.8 {d5}, [ip] ++ pop {r4, pc} ++endfunc ++ ++ ++@ ff_hevc_rpi_add_residual_8x8_dc_c_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_8x8_dc_c_neon_8, export=1 ++ mov r3, #8-1 ++ vdup.32 q15, r2 ++ b 1f ++endfunc ++ ++@ ff_hevc_rpi_add_residual_16x16_dc_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_16x16_dc_neon_8, export=1 ++ vdup.16 q15, r2 ++ mov r3, #16-1 ++1: vld1.8 {q8}, [r0] ++ add ip, r0, r1 ++ vaddw.u8 q0, q15, d16 ++ vaddw.u8 q1, q15, d17 ++1: ++ vld1.8 {q8}, [ip], r1 ++ subs r3, #1 ++ vqmovun.s16 d4, q0 ++ vqmovun.s16 d5, q1 ++ vaddw.u8 q0, q15, d16 ++ vaddw.u8 q1, q15, d17 ++ vst1.8 {q2}, [r0], r1 ++ bne 1b ++ ++ vqmovun.s16 d4, q0 ++ vqmovun.s16 d5, q1 ++ vst1.8 {q2}, [r0] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_add_residual_16x16_dc_c_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_16x16_dc_c_neon_8, export=1 ++ mov r3, #16-1 ++ vdup.32 q15, r2 ++ b 1f ++endfunc ++ ++@ ff_hevc_rpi_add_residual_32x32_dc_neon_8( ++@ uint8_t * dst, // [r0] ++@ unsigned int stride, // [r1] ++@ int dc) // [r2] ++ ++function ff_hevc_rpi_add_residual_32x32_dc_neon_8, export=1 ++ vdup.16 q15, r2 ++ mov r3, #32-1 ++1: vld1.8 {q8, q9}, [r0] ++ add ip, r0, r1 ++ vaddw.u8 q0, q15, d16 ++ vaddw.u8 q1, q15, d17 ++ vaddw.u8 q2, q15, d18 ++ vaddw.u8 q3, q15, d19 ++1: ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d22, q2 ++ vqmovun.s16 d23, q3 ++ vld1.8 {q8, q9}, [ip], r1 ++ subs r3, #1 ++ vaddw.u8 q0, q15, d16 ++ vaddw.u8 q1, q15, d17 ++ vaddw.u8 q2, q15, d18 ++ vaddw.u8 q3, q15, d19 ++ vst1.8 {q10, q11}, [r0], r1 ++ bne 1b ++ ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d22, q2 ++ vqmovun.s16 d23, q3 ++ vst1.8 {q10, q11}, [r0] ++ bx lr ++endfunc ++ ++@ ============================================================================ ++@ U add ++ ++@ add_residual4x4_c( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride, [r2] ++@ int dc_v) [r3] ++ ++function ff_hevc_rpi_add_residual_4x4_u_neon_8, export=1 ++ add ip, r0, r2 ++ vld1.16 {q0, q1}, [r1] ++ lsl r2, #1 ++ vld1.8 {d16}, [r0 :64], r2 ++ vld1.8 {d17}, [ip :64], r2 ++ vld1.8 {d18}, [r0 :64] ++ sub r0, r2 ++ vld1.8 {d19}, [ip :64] ++ sub ip, r2 ++ vdup.16 q2, r3 ++ vdup.16 q3, r3 ++ vmovl.u8 q10, d16 ++ vmovl.u8 q11, d17 ++ vmovl.u8 q12, d18 ++ vmovl.u8 q13, d19 ++ vzip.16 q0, q2 ++ vzip.16 q1, q3 ++ vqadd.s16 q0, q10 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q1, q12 ++ vqadd.s16 q3, q13 ++ vqmovun.s16 d0, q0 ++ vqmovun.s16 d1, q2 ++ vqmovun.s16 d2, q1 ++ vqmovun.s16 d3, q3 ++ vst1.8 {d0}, [r0 :64], r2 ++ vst1.8 {d1}, [ip :64], r2 ++ vst1.8 {d2}, [r0 :64] ++ vst1.8 {d3}, [ip :64] ++ bx lr ++endfunc ++ ++@ add_residual8x8_c( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++@ int dc_v) [r3] ++ ++function ff_hevc_rpi_add_residual_8x8_u_neon_8, export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ push {r4, lr} ++ vld2.8 {d16, d17}, [r0 :128] ++ lsl r2, #1 ++ vld2.8 {d18, d19}, [ip :128] ++ mov r3, #8-2 ++ vld1.16 {q0, q1}, [r1 :256]! ++ add r4, r0, r2 ++ vmovl.u8 q10, d16 ++ add lr, ip, r2 ++ vmovl.u8 q11, d18 ++ vqadd.s16 q0, q10 ++ vaddw.u8 q2, q15, d17 ++ vqadd.s16 q1, q11 ++ vaddw.u8 q3, q15, d19 ++1: ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d21, q2 ++ vld2.8 {d16, d17}, [r4 :128], r2 ++ subs r3, #2 ++ vqmovun.s16 d22, q1 ++ vqmovun.s16 d23, q3 ++ vst2.8 {d20, d21}, [r0 :128], r2 ++ vld2.8 {d18, d19}, [lr :128], r2 ++ vst2.8 {d22, d23}, [ip :128], r2 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vmovl.u8 q10, d16 ++ vmovl.u8 q11, d18 ++ vqadd.s16 q0, q10 ++ vaddw.u8 q2, q15, d17 ++ vqadd.s16 q1, q11 ++ vaddw.u8 q3, q15, d19 ++ bne 1b ++ ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d21, q2 ++ vqmovun.s16 d22, q1 ++ vqmovun.s16 d23, q3 ++ vst2.8 {d20, d21}, [r0 :128] ++ vst2.8 {d22, d23}, [ip :128] ++ pop {r4, pc} ++endfunc ++ ++@ add_residual16x16_u( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++@ int dc_v) [r3] ++ ++function ff_hevc_rpi_add_residual_16x16_u_neon_8, export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ vld2.8 {q8, q9}, [r0 :256] ++ mov r3, #16-1 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vmovl.u8 q11, d16 ++ vmovl.u8 q12, d17 ++ vqadd.s16 q0, q11 ++ vaddw.u8 q11, q15, d18 ++ vqadd.s16 q1, q12 ++ vaddw.u8 q12, q15, d19 ++1: ++ vld2.8 {q8, q9}, [ip :256], r2 ++ subs r3, #1 ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d22, q11 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d23, q12 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vst2.8 {q10, q11}, [r0 :256], r2 ++ vmovl.u8 q11, d16 ++ pldw [ip] ++ vmovl.u8 q12, d17 ++ vqadd.s16 q0, q11 ++ vaddw.u8 q11, q15, d18 ++ vqadd.s16 q1, q12 ++ vaddw.u8 q12, q15, d19 ++ bne 1b ++ ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d22, q11 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d23, q12 ++ vst2.8 {q10, q11}, [r0 :256] ++ bx lr ++endfunc ++ ++@ ============================================================================ ++@ V add ++ ++@ add_residual4x4_v( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_4x4_v_neon_8, export=1 ++ add ip, r0, r2 ++ vld1.16 {q2, q3}, [r1] ++ lsl r2, #1 ++ vld1.8 {d16}, [r0 :64], r2 ++ vld1.8 {d17}, [ip :64], r2 ++ vld1.8 {d18}, [r0 :64] ++ sub r0, r2 ++ vld1.8 {d19}, [ip :64] ++ sub ip, r2 ++ vdup.16 q0, r3 ++ vdup.16 q1, r3 ++ vmovl.u8 q10, d16 ++ vmovl.u8 q11, d17 ++ vmovl.u8 q12, d18 ++ vmovl.u8 q13, d19 ++ vzip.16 q0, q2 ++ vzip.16 q1, q3 ++ vqadd.s16 q0, q10 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q1, q12 ++ vqadd.s16 q3, q13 ++ vqmovun.s16 d0, q0 ++ vqmovun.s16 d1, q2 ++ vqmovun.s16 d2, q1 ++ vqmovun.s16 d3, q3 ++ vst1.8 {d0}, [r0 :64], r2 ++ vst1.8 {d1}, [ip :64], r2 ++ vst1.8 {d2}, [r0 :64] ++ vst1.8 {d3}, [ip :64] ++ bx lr ++endfunc ++ ++@ add_residual8x8_v( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_8x8_v_neon_8, export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ push {r4, lr} ++ vld2.8 {d16, d17}, [r0 :128] ++ lsl r2, #1 ++ vld2.8 {d18, d19}, [ip :128] ++ mov r3, #8-2 ++ vld1.16 {q0, q1}, [r1 :256]! ++ add r4, r0, r2 ++ vmovl.u8 q10, d17 ++ add lr, ip, r2 ++ vmovl.u8 q11, d19 ++ vqadd.s16 q0, q10 ++ vaddw.u8 q2, q15, d16 ++ vqadd.s16 q1, q11 ++ vaddw.u8 q3, q15, d18 ++1: ++ vqmovun.s16 d20, q2 ++ vqmovun.s16 d21, q0 ++ vld2.8 {d16, d17}, [r4 :128], r2 ++ subs r3, #2 ++ vqmovun.s16 d22, q3 ++ vqmovun.s16 d23, q1 ++ vst2.8 {d20, d21}, [r0 :128], r2 ++ vld2.8 {d18, d19}, [lr :128], r2 ++ vst2.8 {d22, d23}, [ip :128], r2 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vmovl.u8 q10, d17 ++ vmovl.u8 q11, d19 ++ vqadd.s16 q0, q10 ++ vaddw.u8 q2, q15, d16 ++ vqadd.s16 q1, q11 ++ vaddw.u8 q3, q15, d18 ++ bne 1b ++ ++ vqmovun.s16 d20, q2 ++ vqmovun.s16 d21, q0 ++ vqmovun.s16 d22, q3 ++ vqmovun.s16 d23, q1 ++ vst2.8 {d20, d21}, [r0 :128] ++ vst2.8 {d22, d23}, [ip :128] ++ pop {r4, pc} ++endfunc ++ ++@ add_residual16x16_v( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_16x16_v_neon_8, export=1 ++ vdup.16 q15, r3 ++ add ip, r0, r2 ++ vld2.8 {q8, q9}, [r0 :256] ++ mov r3, #16-1 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vmovl.u8 q11, d18 ++ vmovl.u8 q12, d19 ++ vqadd.s16 q0, q11 ++ vaddw.u8 q11, q15, d16 ++ vqadd.s16 q1, q12 ++ vaddw.u8 q12, q15, d17 ++1: ++ vld2.8 {q8, q9}, [ip :256], r2 ++ subs r3, #1 ++ vqmovun.s16 d20, q11 ++ vqmovun.s16 d22, q0 ++ vqmovun.s16 d21, q12 ++ vqmovun.s16 d23, q1 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vst2.8 {q10, q11}, [r0 :256], r2 ++ vmovl.u8 q11, d18 ++ pldw [ip] ++ vmovl.u8 q12, d19 ++ vqadd.s16 q0, q11 ++ vaddw.u8 q11, q15, d16 ++ vqadd.s16 q1, q12 ++ vaddw.u8 q12, q15, d17 ++ bne 1b ++ ++ vqmovun.s16 d20, q11 ++ vqmovun.s16 d22, q0 ++ vqmovun.s16 d21, q12 ++ vqmovun.s16 d23, q1 ++ vst2.8 {q10, q11}, [r0 :256] ++ bx lr ++endfunc ++ ++@ ============================================================================ ++@ U & V add ++ ++@ add_residual4x4_c( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_4x4_c_neon_8, export=1 ++ add ip, r0, r2 ++ vld1.16 {q0, q1}, [r1]! @ all of U ++ lsl r2, #1 ++ vld1.8 {d16}, [r0 :64], r2 ++ rsb r3, r2, #0 ++ vld1.8 {d17}, [ip :64], r2 ++ vld1.16 {q2, q3}, [r1] @ all of V ++ vld1.8 {d18}, [r0 :64], r3 ++ vld1.8 {d19}, [ip :64], r3 ++ vmovl.u8 q10, d16 ++ vmovl.u8 q11, d17 ++ vmovl.u8 q12, d18 ++ vmovl.u8 q13, d19 ++ vzip.16 q0, q2 ++ vzip.16 q1, q3 ++ vqadd.s16 q0, q10 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q1, q12 ++ vqadd.s16 q3, q13 ++ vqmovun.s16 d0, q0 ++ vqmovun.s16 d1, q2 ++ vqmovun.s16 d2, q1 ++ vqmovun.s16 d3, q3 ++ vst1.8 {d0}, [r0 :64], r2 ++ vst1.8 {d1}, [ip :64], r2 ++ vst1.8 {d2}, [r0 :64] ++ vst1.8 {d3}, [ip :64] ++ bx lr ++endfunc ++ ++@ add_residual8x8_c( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_8x8_c_neon_8, export=1 ++ vld2.8 {d16, d17}, [r0 :128] ++ add r3, r1, #(8*8*2) @ Offset to V ++ vld1.16 {q0}, [r1 :128]! ++ add ip, r0, r2 ++ vld1.16 {q1}, [r3 :128]! ++ vmovl.u8 q10, d16 ++ push {lr} ++ vmovl.u8 q8, d17 ++ mov lr, #8-1 ++ vqadd.s16 q10, q0 ++ vqadd.s16 q1, q8 ++1: ++ vld2.8 {d16, d17}, [ip :128], r2 ++ subs lr, #1 ++ vld1.16 {q0}, [r1 :128]! ++ vqmovun.s16 d20, q10 ++ vqmovun.s16 d21, q1 ++ vld1.16 {q1}, [r3 :128]! ++ vst2.8 {d20, d21}, [r0 :128], r2 ++ vmovl.u8 q10, d16 ++ pldw [ip] ++ vmovl.u8 q8, d17 ++ vqadd.s16 q10, q0 ++ vqadd.s16 q1, q8 ++ bne 1b ++ ++ vqmovun.s16 d20, q10 ++ vqmovun.s16 d21, q1 ++ vst2.8 {d20, d21}, [r0 :128] ++ pop {pc} ++endfunc ++ ++@ add_residual16x16_c( ++@ uint8_t *_dst, [r0] ++@ const int16_t *res, [r1] ++@ ptrdiff_t stride) [r2] ++ ++function ff_hevc_rpi_add_residual_16x16_c_neon_8, export=1 ++ vld2.8 {q8, q9}, [r0 :256] ++ add r3, r1, #(16*16*2) @ Offset to V ++ vld1.16 {q0, q1}, [r1 :256]! ++ add ip, r0, r2 ++ vld1.16 {q2, q3}, [r3 :256]! ++ vmovl.u8 q10, d16 ++ push {lr} ++ vmovl.u8 q8, d17 ++ mov lr, #16-1 ++ vmovl.u8 q11, d18 ++ vmovl.u8 q9, d19 ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q8 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q9 ++1: ++ vld2.8 {q8, q9}, [ip :256], r2 ++ subs lr, #1 ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d22, q2 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d23, q3 ++ vld1.16 {q0, q1}, [r1 :256]! ++ vst2.8 {d20-d23}, [r0 :256], r2 ++ vld1.16 {q2, q3}, [r3 :256]! ++ vmovl.u8 q10, d16 ++ pldw [ip] ++ vmovl.u8 q8, d17 ++ vmovl.u8 q11, d18 ++ vmovl.u8 q9, d19 ++ vqadd.s16 q0, q10 ++ vqadd.s16 q1, q8 ++ vqadd.s16 q2, q11 ++ vqadd.s16 q3, q9 ++ bne 1b ++ ++ vqmovun.s16 d20, q0 ++ vqmovun.s16 d22, q2 ++ vqmovun.s16 d21, q1 ++ vqmovun.s16 d23, q3 ++ vst2.8 {d20-d23}, [r0 :256] ++ pop {pc} ++endfunc ++ ++@ 32x32 chroma never occurs so NIF ++ ++@ ============================================================================ +diff --git a/libavcodec/arm/rpi_hevcdsp_sao_neon.S b/libavcodec/arm/rpi_hevcdsp_sao_neon.S +new file mode 100644 +index 0000000000..b56e0f9644 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcdsp_sao_neon.S +@@ -0,0 +1,2245 @@ ++/* ++ * Copyright (c) 2014 - 2015 Seppo Tomperi ++ * 2017 John Cox (for Raspberry Pi) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++.set EDGE_SRC_STRIDE, 160 ++ ++@ PIC jump tables are fractionally more expensive than absolute in our code ++.set jent_pic, CONFIG_PIC ++ ++ ++.macro sao_band_64b_8 XLAT0, XLAT1, Q_K128, I1, I2, I3, I4 ++ vshr.u8 q12, q8, #3 ++ \I1 ++ vadd.i8 q8, \Q_K128 ++ \I2 ++ vshr.u8 q13, q9, #3 ++ \I3 ++ vadd.i8 q9, \Q_K128 ++ \I4 ++ vtbl.8 d24, \XLAT0, d24 ++ vtbl.8 d25, \XLAT0, d25 ++ vtbl.8 d26, \XLAT1, d26 ++ vtbl.8 d27, \XLAT1, d27 ++ ++ vqadd.s8 q8, q12 ++ vshr.u8 q12, q10, #3 ++ vadd.i8 q10, \Q_K128 ++ vqadd.s8 q9, q13 ++ vshr.u8 q13, q11, #3 ++ vadd.i8 q11, \Q_K128 ++ ++ vtbl.8 d24, \XLAT0, d24 ++ vtbl.8 d25, \XLAT0, d25 ++ vtbl.8 d26, \XLAT1, d26 ++ vtbl.8 d27, \XLAT1, d27 ++ vqadd.s8 q10, q12 ++ vsub.i8 q8, \Q_K128 ++ vqadd.s8 q11, q13 ++ vsub.i8 q9, \Q_K128 ++ vsub.i8 q10, \Q_K128 ++ vsub.i8 q11, \Q_K128 ++.endm ++ ++.macro sao_band_16b_8 XLAT0, XLAT1, Q_K128, L1, L2, L3, L4, L5, S1, S2, S3, S4 ++ \L1 ++ \L2 ++ \L3 ++ \L4 ++ \L5 ++ vadd.i8 q12, q8, \Q_K128 ++ vshr.u8 q8, #3 ++ vtbl.8 d16, \XLAT0, d16 ++ vtbl.8 d17, \XLAT1, d17 ++ vqadd.s8 q12, q8 ++ bmi 2f ++1: \L1 ++ \L2 ++ \L3 ++ \L4 ++ \L5 ++ vsub.i8 q13, q12, \Q_K128 ++ vadd.i8 q12, q8, \Q_K128 ++ vshr.u8 q8, #3 ++ \S1 ++ \S2 ++ \S3 ++ \S4 ++ vtbl.8 d16, \XLAT0, d16 ++ vtbl.8 d17, \XLAT1, d17 ++ vqadd.s8 q12, q8 ++ bpl 1b ++2: vsub.i8 q13, q12, \Q_K128 ++ \S1 ++ \S2 ++ \S3 ++ \S4 ++.endm ++ ++ ++.macro clip16_4 Q0, Q1, Q2, Q3, Q_MIN, Q_MAX ++ vmax.s16 \Q0, \Q_MIN ++ vmax.s16 \Q1, \Q_MIN ++ vmax.s16 \Q2, \Q_MIN ++ vmax.s16 \Q3, \Q_MIN ++ vmin.s16 \Q0, \Q_MAX ++ vmin.s16 \Q1, \Q_MAX ++ vmin.s16 \Q2, \Q_MAX ++ vmin.s16 \Q3, \Q_MAX ++.endm ++ ++@ Clobbers q12, q13 ++.macro sao_band_64b_16 Q0, Q1, Q2, Q3, XLAT0, XLAT1, Q_MIN, Q_MAX, bit_depth, I1, I2 ++ vshrn.i16 d24, \Q0, #(\bit_depth - 5) ++ vshrn.i16 d25, \Q1, #(\bit_depth - 5) ++ vshrn.i16 d26, \Q2, #(\bit_depth - 5) ++ \I1 ++ vtbl.8 d24, \XLAT0, d24 ++ vshrn.i16 d27, \Q3, #(\bit_depth - 5) ++ vtbl.8 d25, \XLAT1, d25 ++ \I2 ++ vtbl.8 d26, \XLAT0, d26 ++ vtbl.8 d27, \XLAT1, d27 ++ vaddw.s8 \Q0, d24 ++ vaddw.s8 \Q1, d25 ++ vaddw.s8 \Q2, d26 ++ vaddw.s8 \Q3, d27 ++ clip16_4 \Q0, \Q1, \Q2, \Q3, \Q_MIN, \Q_MAX ++.endm ++ ++@ Clobbers q10, q11, q12 ++.macro sao_band_32b_16 Q0, Q1, XLAT0, XLAT1, Q_MIN, Q_MAX, bit_depth, L1, L2, L3, L4, L5, S1, S2, S3, S4 ++ \L1 ++ \L2 ++ \L3 ++ \L4 ++ \L5 ++ vshrn.i16 d24, \Q0, #\bit_depth - 5 ++ vshrn.i16 d25, \Q1, #\bit_depth - 5 ++ vtbl.8 d24, \XLAT0, d24 ++ vtbl.8 d25, \XLAT1, d25 ++ vaddw.s8 q10, \Q0, d24 ++ vaddw.s8 q11, \Q1, d25 ++ bmi 2f ++1: \L1 ++ \L2 ++ \L3 ++ \L4 ++ \L5 ++ vmax.s16 q10, \Q_MIN ++ vmax.s16 q11, \Q_MIN ++ vshrn.i16 d24, \Q0, #\bit_depth - 5 ++ vshrn.i16 d25, \Q1, #\bit_depth - 5 ++ vmin.s16 q10, \Q_MAX ++ vmin.s16 q11, \Q_MAX ++ \S1 ++ \S2 ++ \S3 ++ \S4 ++ vtbl.8 d24, \XLAT0, d24 ++ vtbl.8 d25, \XLAT1, d25 ++ vaddw.s8 q10, \Q0, d24 ++ vaddw.s8 q11, \Q1, d25 ++ bpl 1b ++2: vmax.s16 q10, \Q_MIN ++ vmax.s16 q11, \Q_MIN ++ vmin.s16 q10, \Q_MAX ++ vmin.s16 q11, \Q_MAX ++ \S1 ++ \S2 ++ \S3 ++ \S4 ++.endm ++ ++ ++@ Standard coding rules for sao_offset_abs limit it to 0-31 (Table 9-38) ++@ so we are quite safe stuffing it into a byte array ++@ There may be a subsequent shl by log2_sao_offset_scale_luma/chroma ++@ (7.4.3.3.2 && 7-70) but we should still be safe to at least 12 bits of ++@ precision ++ ++@ This, somewhat nasty, bit of code builds the {d0-d3} translation ++@ array via the stack ++@ Given that sao_left_class > 28 can cause wrap we can't just poke ++@ all 4 bytes in at once ++@ ++@ It also loads other common regs ++ ++@ Beware that the offset read here overrreads by 6 bytes so source must be sized appropriately ++function band_load_y ++ ldr ip, [sp, #16] @ &sao_offset_val[0] ++ ldr r4, [sp, #20] @ sao_left_class ++ vmov.i64 d4, #0 ++ vmov.i64 q0, #0 ++ pld [r1] ++ vld2.8 {q8}, [ip] ++ sub ip, sp, #8*5 ++ vmov.i64 q1, #0 ++ add r4, ip, r4 ++ vpush {d0-d4} @ Put zero array on stack ++ vshr.u64 d16, d16, #8 @ 1st interesting val is [1] ++ ldr ip, [ip, #8*5 + 28] @ height ++ vst1.32 {d16[0]}, [r4] ++ add r4, r1, r3 ++ vpop {d0-d4} @ Pop modified array ++ sub ip, ip, #1 ++ vorr d0, d0, d4 ++ bx lr ++endfunc ++ ++@ Beware that offset reads here overrread by 6 bytes so source must be sized appropriately ++function band_load_c ++ ldr ip, [sp, #16] @ &sao_offset_val1[0] ++ ldr r4, [sp, #20] @ sao_left_class1 ++ vmov.i64 d24, #0 ++ vmov.i64 q10, #0 ++ pld [r1] ++ vld2.8 {q8}, [ip] ++ sub ip, sp, #8*5 ++ vmov.i64 q11, #0 ++ add r4, ip, r4 ++ ldr ip, [sp, #24] @ &sao_offset_val2[0] ++ vpush {d20-d24} @ Put zero array on stack ++ vld2.8 {q9}, [ip] ++ vshr.u64 d16, d16, #8 @ 1st interesting val is [1] ++ ldr ip, [sp, #8*5 + 28] @ sao_left_class2 ++ vst1.32 {d16[0]}, [r4] ++ add ip, sp, ip ++ vshr.u64 d18, d18, #8 @ 1st interesting val is [1] ++ vldmia sp, {d0-d3} @ Load modified array ++ vldr d16, [sp, #8*4] ++ add r4, r1, r3 ++ vstmia sp, {d20-d24} @ Put zero array on stack (again) ++ vst1.32 {d18[0]}, [ip] ++ vorr d0, d0, d16 ++ vldmia sp, {d4-d7} @ Load modified array ++ vldr d18, [sp, #8*4] ++ ldr ip, [sp, #8*5 + 36] @ height ++ add sp, sp, #8*5 ++ vorr d4, d4, d18 ++ sub ip, ip, #1 ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_band_64_neon_8 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_band_64_neon_8, export=1 ++ push {r4-r6, lr} ++ vmov.u8 q15, #128 ++ bl band_load_y ++ ++1: vldmia r1, {q8-q11} ++ sao_band_64b_8 {d0-d3}, {d0-d3}, q15, \ ++ "pld [r4]", \ ++ "subs ip, #1", \ ++ "it ne; addne r4, r3", \ ++ "add r1, r3" ++ vstmia r0, {q8-q11} ++ add r0, r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_32_neon_8 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_band_32_neon_8, export=1 ++ push {r4-r6, lr} ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ vmov.u8 q15, #128 ++ bl band_load_y ++ ++1: vld1.8 { q8, q9 }, [r1, :128], r3 ++ subs ip, #2 ++ vld1.8 {q10, q11}, [r6, :128], r3 ++ ++ sao_band_64b_8 {d0-d3}, {d0-d3}, q15 ++ ++ vst1.8 { q8, q9 }, [r0, :128], r2 ++ vst1.8 {q10, q11}, [r5, :128], r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_16_neon_8 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_band_16_neon_8, export=1 ++ push {r4-r6, lr} ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ vmov.u8 q15, #128 ++ bl band_load_y ++ ++1: vld1.8 { q8}, [r1, :128], r3 ++ subs ip, #4 ++ vld1.8 { q9}, [r6, :128], r3 ++ vld1.8 {q10}, [r1, :128], r3 ++ vld1.8 {q11}, [r6, :128], r3 ++ ++ sao_band_64b_8 {d0-d3}, {d0-d3}, q15 ++ ++ vst1.8 { q8}, [r0, :128], r2 ++ vst1.8 { q9}, [r5, :128], r2 ++ vst1.8 {q10}, [r0, :128], r2 ++ vst1.8 {q11}, [r5, :128], r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_8_neon_8 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_band_8_neon_8, export=1 ++ ldr ip, [sp, #8] @ width ++ push {r4-r6, lr} ++ vmov.u8 q15, #128 ++ cmp ip, #8 ++ bl band_load_y ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ blt 4f ++ ++ sao_band_16b_8 {d0-d3}, {d0-d3}, q15, \ ++ "vld1.8 {d16}, [r1, :64], r3", \ ++ "subs ip, #2", \ ++ "vld1.8 {d17}, [r6, :64], r3", \ ++ "", \ ++ "", \ ++ "vst1.8 {d26}, [r0, :64], r2", \ ++ "vst1.8 {d27}, [r5, :64], r2" ++ pop {r4-r6, pc} ++4: ++ sao_band_16b_8 {d0-d3}, {d0-d3}, q15, \ ++ "vld1.32 {d16[0]}, [r1, :32], r3", \ ++ "subs ip, #4", \ ++ "vld1.32 {d16[1]}, [r6, :32], r3", \ ++ "vld1.32 {d17[0]}, [r1, :32], r3", \ ++ "vld1.32 {d17[1]}, [r6, :32], r3", \ ++ "vst1.32 {d26[0]}, [r0, :32], r2", \ ++ "vst1.32 {d26[1]}, [r5, :32], r2", \ ++ "vst1.32 {d27[0]}, [r0, :32], r2", \ ++ "vst1.32 {d27[1]}, [r5, :32], r2" ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_c_32_neon_8( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++function ff_hevc_rpi_sao_band_c_32_neon_8, export=1 ++ push {r4-r6, lr} ++ add r5, r0, #32 ++ add r6, r1, #32 ++ vmov.u8 q15, #128 ++ bl band_load_c ++ ++1: vld2.8 { q8, q9 }, [r1, :128], r3 ++ subs ip, #1 ++ vld2.8 {q10, q11}, [r6, :128], r3 ++ ++ sao_band_64b_8 {d0-d3}, {d4-d7}, q15, \ ++ "pld [r4]", \ ++ "it ne; addne r4, r3" ++ ++ vst2.8 { q8, q9 }, [r0, :128], r2 ++ vst2.8 {q10, q11}, [r5, :128], r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_c_16_neon_8( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++function ff_hevc_rpi_sao_band_c_16_neon_8, export=1 ++ push {r4-r6, lr} ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ vmov.u8 q15, #128 ++ bl band_load_c ++ ++1: vld2.8 { q8, q9 }, [r1, :128], r3 ++ subs ip, #2 ++ vld2.8 {q10, q11}, [r6, :128], r3 ++ ++ sao_band_64b_8 {d0-d3}, {d4-d7}, q15 ++ ++ vst2.8 { q8, q9 }, [r0, :128], r2 ++ vst2.8 {q10, q11}, [r5, :128], r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++endfunc ++ ++@ ff_hevc_rpi_sao_band_c_8_neon_8( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++function ff_hevc_rpi_sao_band_c_8_neon_8, export=1 ++ ldr ip, [sp, #16] @ width ++ push {r4-r6, lr} ++ vmov.u8 q15, #128 ++ cmp ip, #8 ++ bl band_load_c ++ blt 4f ++ ++ sao_band_16b_8 {d0-d3}, {d4-d7}, q15, \ ++ "vld2.8 {d16-d17}, [r1, :128], r3", \ ++ "subs ip, #1", \ ++ "", \ ++ "", \ ++ "", \ ++ "vst2.8 {d26-d27}, [r0, :128], r2" ++ pop {r4-r6, pc} ++4: ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ sao_band_16b_8 {d0-d3}, {d4-d7}, q15, \ ++ "vld1.8 {d16}, [r1, :64], r3", \ ++ "subs ip, #2", \ ++ "vld1.8 {d17}, [r6, :64], r3", \ ++ "vuzp.8 d16, d17", \ ++ "", \ ++ "vzip.8 d26, d27", \ ++ "vst1.8 {d26}, [r0, :64], r2", \ ++ "vst1.8 {d27}, [r5, :64], r2" ++ pop {r4-r6, pc} ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_band_64_neon_10 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++.macro band_64_16 bit_depth ++ push {r4-r6, lr} ++ vmov.i64 q2, #0 ++ vmov.i16 q3, #(1 << \bit_depth) - 1 ++ bl band_load_y ++ vpush {q4-q7} ++ ++1: vldm r1, {q4-q11} ++ sao_band_64b_16 q4, q5, q6, q7, {d0-d3}, {d0-d3}, q2, q3, \bit_depth, \ ++ "subs ip, #1", \ ++ "add r1, r3" ++ sao_band_64b_16 q8, q9, q10, q11, {d0-d3}, {d0-d3}, q2, q3, \bit_depth ++ vstm r0, {q4-q11} ++ add r0, r2 ++ bpl 1b ++ ++ vpop {q4-q7} ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_64_neon_10, export=1 ++ band_64_16 10 ++endfunc ++ ++@ ff_hevc_rpi_sao_band_32_neon_10 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++.macro band_32_16 bit_depth ++ push {r4-r6, lr} ++ vmov.i64 q2, #0 ++ vmov.i16 q3, #(1 << \bit_depth) - 1 ++ bl band_load_y ++ ++1: vldm r1, {q8-q11} ++ sao_band_64b_16 q8, q9, q10, q11, {d0-d3}, {d0-d3}, q2, q3, \bit_depth, \ ++ "subs ip, #1", \ ++ "add r1, r3" ++ vstm r0, {q8-q11} ++ add r0, r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_32_neon_10, export=1 ++ band_32_16 10 ++endfunc ++ ++@ ff_hevc_rpi_sao_band_16_neon_10 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++.macro band_16_16 bit_depth ++ push {r4-r6, lr} ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ vmov.i64 q14, #0 ++ vmov.i16 q15, #(1 << \bit_depth) - 1 ++ bl band_load_y ++ ++1: vld1.16 { q8, q9 }, [r1, :128], r3 ++ subs r12, #2 ++ vld1.16 {q10, q11}, [r6, :128], r3 ++ sao_band_64b_16 q8, q9, q10, q11, {d0-d3}, {d0-d3}, q14, q15, \bit_depth ++ vst1.16 { q8, q9 }, [r0, :128], r2 ++ vst1.16 {q10, q11}, [r5, :128], r2 ++ bpl 1b ++ ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_16_neon_10, export=1 ++ band_16_16 10 ++endfunc ++ ++@ ff_hevc_rpi_sao_band_8_neon_10 ( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ ptrdiff_t stride_src, [r3] ++@ int16_t *sao_offset_val, [sp, #0] ++@ int sao_left_class, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++.macro band_8_16 bit_depth ++ ldr ip, [sp, #8] @ width ++ push {r4-r6, lr} ++ vmov.i64 q14, #0 ++ cmp ip, #8 ++ vmov.i16 q15, #(1 << \bit_depth) - 1 ++ bl band_load_y ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ blt 4f ++ ++ sao_band_32b_16 q8, q9, {d0-d3}, {d0-d3}, q14, q15, \bit_depth, \ ++ "vld1.16 {q8}, [r1, :128], r3", \ ++ "subs ip, #2", \ ++ "vld1.16 {q9}, [r6, :128], r3", \ ++ "", \ ++ "", \ ++ "vst1.16 {q10}, [r0, :128], r2", \ ++ "vst1.16 {q11}, [r5, :128], r2" ++ pop {r4-r6, pc} ++4: ++ sao_band_32b_16 q8, q9, {d0-d3}, {d0-d3}, q14, q15, \bit_depth, \ ++ "vld1.16 {d16}, [r1, :64], r3", \ ++ "subs ip, #4", \ ++ "vld1.16 {d17}, [r6, :64], r3", \ ++ "vld1.16 {d18}, [r1, :64], r3", \ ++ "vld1.16 {d19}, [r6, :64], r3", \ ++ "vst1.16 {d20}, [r0, :64], r2", \ ++ "vst1.16 {d21}, [r5, :64], r2", \ ++ "vst1.16 {d22}, [r0, :64], r2", \ ++ "vst1.16 {d23}, [r5, :64], r2" ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_8_neon_10, export=1 ++ band_8_16 10 ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_band_c_32_neon_10( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++.macro band_c_32_16 bit_depth ++ push {r4-r6, lr} ++ add r5, r0, #32 ++ add r6, r1, #32 ++ sub r2, #64 ++ sub r3, #64 ++ vmov.i64 q14, #0 ++ vmov.i16 q15, #(1 << \bit_depth) - 1 ++ bl band_load_c ++ mov lr, #64 ++ vpush {q4-q7} ++ ++1: vld2.16 { q4, q5 }, [r1, :128], lr ++ subs ip, #1 ++ vld2.16 { q6, q7 }, [r6, :128], lr ++ vld2.16 { q8, q9 }, [r1, :128], r3 ++ vld2.16 {q10, q11}, [r6, :128], r3 ++ ++ sao_band_64b_16 q4, q5, q6, q7, {d0-d3}, {d4-d7}, q14, q15, \bit_depth, \ ++ "pld [r4]", \ ++ "it ne; addne r4, r3" ++ sao_band_64b_16 q8, q9, q10, q11, {d0-d3}, {d4-d7}, q14, q15, \bit_depth ++ ++ vst2.16 { q4, q5 }, [r0, :128], lr ++ vst2.16 { q6, q7 }, [r5, :128], lr ++ vst2.16 { q8, q9 }, [r0, :128], r2 ++ vst2.16 {q10, q11}, [r5, :128], r2 ++ ++ bpl 1b ++ ++ vpop {q4-q7} ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_c_32_neon_10, export=1 ++ band_c_32_16 10 ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_band_c_16_neon_10( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++.macro band_c_16_16 bit_depth ++ push {r4-r6, lr} ++ add r5, r0, #32 ++ add r6, r1, #32 ++ vmov.i64 q14, #0 ++ vmov.i16 q15, #(1 << \bit_depth) - 1 ++ bl band_load_c ++ ++1: vld2.16 { q8, q9 }, [r1, :128], r3 ++ subs ip, #1 ++ vld2.16 {q10, q11}, [r6, :128], r3 ++ ++ sao_band_64b_16 q4, q5, q6, q7, {d0-d3}, {d4-d7}, q14, q15, \bit_depth ++ sao_band_64b_16 q8, q9, q10, q11, {d0-d3}, {d4-d7}, q14, q15, \bit_depth ++ ++ vst2.16 { q8, q9 }, [r0, :128], r2 ++ vst2.16 {q10, q11}, [r5, :128], r2 ++ ++ bpl 1b ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_c_16_neon_10, export=1 ++ band_c_16_16 10 ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_band_c_8_neon_10( ++@ uint8_t * dst [r0] ++@ uint8_t * src [r1] ++@ uint32_t dst_stride [r2] ++@ uint32_t src_stride [r3] ++@ const int16_t * table1 sp[0] ++@ uint32_t offset1 sp[4] ++@ const int16_t * table2 sp[8] ++@ uint32_t offset2 sp[12] ++@ int width sp[16] ++@ int height sp[20] ++ ++.macro band_c_8_16 bit_depth ++ ldr ip, [sp, #16] @ width ++ push {r4-r6, lr} ++ vmov.i64 q14, #0 ++ cmp ip, #8 ++ vmov.i16 q15, #(1 << \bit_depth) - 1 ++ bl band_load_c ++ blt 4f ++ ++ sao_band_32b_16 q8, q9, {d0-d3}, {d4-d7}, q14, q15, \bit_depth, \ ++ "vld2.16 {q8,q9}, [r1, :128], r3", \ ++ "subs ip, #1", \ ++ "", \ ++ "", \ ++ "", \ ++ "vst2.16 {q10,q11}, [r0, :128], r2" ++ pop {r4-r6, pc} ++4: ++ add r5, r0, r2 ++ add r6, r1, r3 ++ lsl r2, #1 ++ lsl r3, #1 ++ sao_band_32b_16 q8, q9, {d0-d3}, {d4-d7}, q14, q15, \bit_depth, \ ++ "vld2.16 {d16,d18}, [r1, :128], r3", \ ++ "subs ip, #2", \ ++ "vld2.16 {d17,d19}, [r6, :128], r3", \ ++ "", \ ++ "", \ ++ "vst2.16 {d20,d22}, [r0, :128], r2", \ ++ "vst2.16 {d21,d23}, [r5, :128], r2" ++ pop {r4-r6, pc} ++.endm ++ ++function ff_hevc_rpi_sao_band_c_8_neon_10, export=1 ++ band_c_8_16 10 ++endfunc ++ ++ ++@ ============================================================================= ++@ SAO EDGE ++ ++@ r0 destination address ++@ r2 stride to post-increment r0 with ++@ [r5] translate values ++@ ++@ a <- c <- b ++@ a in q0 - q3 ++@ c in q4 - q7 ++@ b in q8 - q11 ++@ ++@ q12-15 used as temp ++@ ++@ Can be used for both Y & C as we unzip/zip the deltas and ++@ transform "u/v" separately via d26/d27. For Y d26=d27 ++ ++function edge_64b_body_8 ++ ++ vcgt.u8 q12, q4, q0 @ c > a -> -1 , otherwise 0 ++ vcgt.u8 q13, q5, q1 ++ vcgt.u8 q14, q6, q2 ++ vcgt.u8 q15, q7, q3 ++ ++ vcgt.u8 q0, q4 @ a > c -> -1 , otherwise 0 ++ vcgt.u8 q1, q5 ++ vcgt.u8 q2, q6 ++ vcgt.u8 q3, q7 ++ ++ vsub.s8 q0, q12 @ a = sign(c-a) ++ vsub.s8 q1, q13 ++ vsub.s8 q2, q14 ++ vsub.s8 q3, q15 ++ ++ vcgt.u8 q12, q4, q8 @ c > b -> -1 , otherwise 0 ++ vcgt.u8 q13, q5, q9 ++ vcgt.u8 q14, q6, q10 ++ vcgt.u8 q15, q7, q11 ++ ++ vsub.s8 q0, q12 ++ vsub.s8 q1, q13 ++ vsub.s8 q2, q14 ++ vsub.s8 q3, q15 ++ ++ vcgt.u8 q12, q8, q4 @ c < b -> -1 , otherwise 0 ++ vcgt.u8 q13, q9, q5 ++ vcgt.u8 q14, q10, q6 ++ vcgt.u8 q15, q11, q7 ++ ++ vadd.s8 q0, q12 @ a = sign(c-a) + sign(c-b) ++ vadd.s8 q1, q13 ++ vmov.u8 q12, #2 ++ vadd.s8 q2, q14 ++ vadd.s8 q3, q15 ++ ++ vadd.s8 q0, q12 ++ vadd.s8 q1, q12 ++ ++ vld1.8 {d26, d27}, [r5] ++ ++ vadd.s8 q2, q12 ++ vuzp.8 q0, q1 ++ vmov.u8 q15, #128 ++ vadd.s8 q3, q12 @ a = 2 + sign(c-a) + sign(c-b) ++ ++ vtbl.8 d0, {d26}, d0 ++ vadd.s8 q12, q4, q15 @ Add -128 so we can use saturating signed add ++ ++ vtbl.8 d1, {d26}, d1 ++ vadd.s8 q14, q5, q15 ++ ++ vtbl.8 d2, {d27}, d2 ++ vuzp.8 q2, q3 ++ ++ vtbl.8 d3, {d27}, d3 ++ ++ vtbl.8 d4, {d26}, d4 ++ vzip.8 q0, q1 ++ ++ vtbl.8 d5, {d26}, d5 ++ vqadd.s8 q0, q12 ++ vqadd.s8 q1, q14 ++ vadd.s8 q12, q6, q15 @ Add -128 so we can use saturating signed add ++ ++ vtbl.8 d6, {d27}, d6 ++ vtbl.8 d7, {d27}, d7 ++ vadd.s8 q14, q7, q15 @ Add -128 so we can use saturating signed add ++ vzip.8 q2, q3 ++ ++ vsub.s8 q0, q15 ++ vqadd.s8 q2, q12 ++ vqadd.s8 q3, q14 ++ vsub.s8 q1, q15 ++ vsub.s8 q2, q15 ++ vsub.s8 q3, q15 ++ ++ bx lr ++endfunc ++ ++@ r0 destination address ++@ r2 stride to post-increment r0 with ++@ r4 upper clip value ++@ [r5] translate values ++@ ++@ a <- c <- b ++@ a in q0 - q3 ++@ c in q4 - q7 ++@ b in q8 - q11 ++@ ++@ q12-15 used as temp ++@ ++@ Can be used for both Y & C as we unzip/zip the deltas and ++@ transform "u/v" separately via d26/d27. For Y d26=d27 ++ ++function edge_64b_body_16 ++ ++ vcgt.u16 q12, q4, q0 // c > a -> -1 , otherwise 0 ++ vcgt.u16 q13, q5, q1 ++ vcgt.u16 q14, q6, q2 ++ vcgt.u16 q15, q7, q3 ++ ++ vcgt.u16 q0, q0, q4 // a > c -> -1 , otherwise 0 ++ vcgt.u16 q1, q1, q5 ++ vcgt.u16 q2, q2, q6 ++ vcgt.u16 q3, q3, q7 ++ ++ vsub.s16 q0, q0, q12 // a = sign(c-a) ++ vsub.s16 q1, q1, q13 ++ vsub.s16 q2, q2, q14 ++ vsub.s16 q3, q3, q15 ++ ++ vcgt.u16 q12, q4, q8 // c > b -> -1 , otherwise 0 ++ vcgt.u16 q13, q5, q9 ++ vcgt.u16 q14, q6, q10 ++ vcgt.u16 q15, q7, q11 ++ ++ vsub.s16 q0, q0, q12 ++ vsub.s16 q1, q1, q13 ++ vsub.s16 q2, q2, q14 ++ vsub.s16 q3, q3, q15 ++ ++ vcgt.u16 q12, q8, q4 // c < b -> -1 , otherwise 0 ++ vcgt.u16 q13, q9, q5 ++ vcgt.u16 q14, q10, q6 ++ vcgt.u16 q15, q11, q7 ++ ++ vadd.s16 q0, q0, q12 // a = sign(c-a) + sign(c-b) ++ vadd.s16 q1, q1, q13 ++ vadd.s16 q2, q2, q14 ++ vadd.s16 q3, q3, q15 ++ ++ vmov.u8 q12, #2 ++ ++ vmovn.s16 d0, q0 ++ vmovn.s16 d1, q1 ++ vmovn.s16 d2, q2 ++ vmovn.s16 d3, q3 ++ ++ vldr d26, [r5] ++ ++ vuzp.8 q0, q1 ++ ++ vldr d27, [r5, #8] ++ ++ vadd.s8 q0, q0, q12 ++ vadd.s8 q1, q1, q12 ++ ++ vmov.i64 q12, #0 ++ ++ vtbl.8 d0, {d26}, d0 ++ vtbl.8 d1, {d26}, d1 ++ vtbl.8 d2, {d27}, d2 ++ vtbl.8 d3, {d27}, d3 ++ ++ vdup.i16 q13, r4 ++ ++ vzip.8 q0, q1 ++ ++ @ Avoid overwrite whilst widening ++ vaddw.s8 q2, q6, d2 ++ vaddw.s8 q3, q7, d3 ++ vaddw.s8 q1, q5, d1 ++ vaddw.s8 q0, q4, d0 ++ ++ @ now clip ++ clip16_4 q2, q3, q1, q0, q12, q13 ++ ++ bx lr ++endfunc ++ ++ ++@ a <- c <- b ++@ a in q0 ++@ c in q1 ++@ b in q2 ++@ Temp q3, q9, q10 ++@ ++@ d16, d17 (q8) xlat U, V ++@ q14.u8 #2 ++@ q15.u8 #128 ++ ++function edge_16b_body_8 ++ vcgt.u8 q9, q0, q1 @ a > c -> -1 , otherwise 0 ++ vadd.u8 q9, q14, q9 ++ vcgt.u8 q0, q1, q0 @ c > a -> -1 , otherwise 0 ++ vsub.u8 q9, q9, q0 ++ vcgt.u8 q0, q2, q1 @ c < b -> -1 , otherwise 0 ++ vadd.u8 q9, q9, q0 ++ vcgt.u8 q0, q1, q2 @ c > b -> -1 , otherwise 0 ++ vsub.u8 q0, q9, q0 ++ ++ vadd.s8 q3, q1, q15 @ Add -128 so we can use saturating signed add ++ ++ vuzp.8 d0, d1 ++ ++ vtbl.8 d0, {d16}, d0 ++ vtbl.8 d1, {d17}, d1 ++ ++ vzip.8 d0, d1 ++ vqadd.s8 q0, q3 ++ vsub.s8 q0, q15 ++ ++ bx lr ++endfunc ++ ++@ a <- c <- b ++@ a in q0 ++@ c in q1 ++@ b in q2 ++@ Temp q3 ++@ ++@ q12, #0 ++@ d16, d17 xlat U, V ++@ q14.u8 #2 ++@ q15.u16 max ++function edge_16b_body_16 ++ vcgt.u16 q9, q0, q1 @ a > c -> -1 , otherwise 0 ++ vadd.u16 q9, q14, q9 ++ vcgt.u16 q0, q1, q0 @ c > a -> -1 , otherwise 0 ++ vsub.u16 q9, q9, q0 ++ vcgt.u16 q0, q2, q1 @ c < b -> -1 , otherwise 0 ++ vadd.u16 q9, q9, q0 ++ vcgt.u16 q0, q1, q2 @ c > b -> -1 , otherwise 0 ++ vsub.u16 q0, q9, q0 ++ ++ vmovn.s16 d0, q0 ++ @ d1 will have random contents that we transform but ++ @ that doesn't matter as we then discard them ++ vuzp.8 d0, d1 ++ ++ vtbl.8 d0, {d16}, d0 ++ vtbl.8 d1, {d17}, d1 ++ ++ vzip.8 d0, d1 ++ ++ vaddw.s8 q0, q1, d0 ++ ++ @ now clip ++ vmax.s16 q0, q12 ++ vmin.s16 q0, q15 ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_edge_[c_]xx_neon( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] // Chroma only ++@ int eo, [sp, #sp_base + 0] ++@ int width, [sp, #sp_base + 4] ++@ int height) [sp, #sp_base + 8] ++ ++@ Jumps via jump_tab with ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ EDGE_SRC_STRIDE [r3] ++@ (1 << \bit_depth) - 1 [r4] ++@ * xlat_table [r5] // setup_64b only ++@ int height [r12] ++@ ++@ 0 [q12] // > 8 bit ++@ 2 [q14] ++@ 128 [q15] // = 8 bit ++@ r4 [q15] // > 8 bit ++ ++.macro edge_xxb_init, bit_depth, is_chroma, jump_tab, setup_64b = 0, setup_16b = 0, check_w4 = 0, do2 = 0, xjump = 0 ++ ++@ Build translate registers ++@ As translate values can only be 0-4 we don't care about junk in the rest ++@ of the register ++.if \is_chroma ++ ldr ip, [sp, #0] ++ push {r4-r6, lr} @ 16 bytes ++ vld1.8 {d16[2]}, [r3] ++ add r3, r3, #2 ++ vld1.8 {d17[2]}, [ip] ++ add ip, ip, #2 ++ vld1.8 {d16[0]}, [r3] ++ add r3, r3, #2 ++ vld1.8 {d17[0]}, [ip] ++ add ip, ip, #2 ++ vld1.8 {d16[1]}, [r3] ++ add r3, r3, #2 ++ vld1.8 {d17[1]}, [ip] ++ add ip, ip, #2 ++ vld1.8 {d16[3]}, [r3] ++ add r3, r3, #2 ++ vld1.8 {d17[3]}, [ip] ++ add ip, ip, #2 ++ vld1.8 {d16[4]}, [r3] ++ vld1.8 {d17[4]}, [ip] ++ movw r3, EDGE_SRC_STRIDE ++.set sp_base, 20 ++.else ++ add ip, r3, #4 ++ vld1.8 {d16[1]}, [r3] ++ add r3, r3, #2 ++ vld1.8 {d17[0]}, [ip] ++ add ip, ip, #2 ++ vld1.8 {d16[0]}, [r3] ++ add r3, r3, #6 ++ vld1.8 {d17[1]}, [ip] ++ vld1.8 {d16[2]}, [r3] ++ movw r3, EDGE_SRC_STRIDE ++ push {r4-r6, lr} @ 16 bytes ++ vzip.8 d16, d17 ++ vmov d17, d16 ++.set sp_base, 16 ++.endif ++ ++@ If setup_64b we need the xlat table on the stack ++.if \setup_64b ++ sub r5, sp, #16 ++.endif ++ ++@ Get jump address ++@ We have a special case for width 4 as the calling code doesn't detect it ++@ If we may have w4 then we add a 2nd jump table after the 1st ++.if \check_w4 ++ ldr r12, [sp, #sp_base + 4] @ width ++ adr r6, \jump_tab ++ ldr lr, [sp, #sp_base + 0] @ e0 ++ cmp r12, #8 ++ it lt ++ addlt r6, #16 ++.else ++ ldr lr, [sp, #sp_base + 0] @ e0 ++ adr r6, \jump_tab ++.endif ++ ++ ldr r12, [sp, #sp_base + 8] @ height ++ ++.if \bit_depth > 8 ++ movw r4, (1 << \bit_depth) - 1 ++.endif ++.if \setup_16b ++.if \bit_depth > 8 ++ vmov.i64 q12, #0 ++ vdup.16 q15, r4 ++ vmov.u16 q14, #2 ++.else ++ vmov.u8 q15, #128 ++ vmov.u8 q14, #2 ++.endif ++.endif ++ ++@ If setup_64b we need q4-q7 saved. ++.if \setup_64b ++ vpush {q4-q8} @ 80 bytes, q8 pushed first ++.set sp_base, sp_base + 80 ++.endif ++ ++ ldr r6, [r6, lr, lsl #2] ++ ++@ For 16 bit width 64 (or chroma 32) we need to do this in 2 passes ++.if \do2 ++ push {r0, r1, r6, r12} ++.if jent_pic ++ bl 98f ++.else ++ blx r6 ++.endif ++ pop {r0, r1, r6, r12} ++ ++ add r0, #64 ++ add r1, #64 ++.endif ++ ++.if jent_pic ++ bl 98f ++.else ++ blx r6 ++.endif ++ ++@ Tidy up & return ++.if \setup_64b ++ vpop {q4-q8} @ spurious but harmless load of q8 ++.endif ++ pop {r4-r6, pc} ++ ++.if jent_pic && !\xjump ++@ Magic label - used as 98b in jent macro ++98: ++ add pc, r6 ++.endif ++.endm ++ ++ ++.macro edge_16b_init, bit_depth, is_chroma, check_w4, jump_tab ++ edge_xxb_init \bit_depth, \is_chroma, \jump_tab, check_w4=\check_w4, setup_16b=1 ++.endm ++ ++.macro edge_64b_init, bit_depth, is_chroma, do2, jump_tab, xjump=0 ++ edge_xxb_init \bit_depth, \is_chroma, \jump_tab, do2=\do2, setup_64b=1, xjump=\xjump ++.endm ++ ++ ++.macro edge_64b_e0, body_fn, pb ++ sub r1, #8 ++ mov r6, lr ++1: vldm r1, {d7-d16} ++ // load a ++ vext.8 q0, q3, q4, #(16 - \pb) ++ add r1, r3 ++ vext.8 q1, q4, q5, #(16 - \pb) ++ subs r12, #1 ++ vext.8 q2, q5, q6, #(16 - \pb) ++ vext.8 q3, q6, q7, #(16 - \pb) ++ pld [r1] ++ // load b ++ vext.8 q11, q7, q8, #\pb @ Avoid overwrite ++ pld [r1, #64] ++ vext.8 q8, q4, q5, #\pb ++ vext.8 q9, q5, q6, #\pb ++ vext.8 q10, q6, q7, #\pb ++ bl \body_fn ++ vstm r0, {q0-q3} ++ add r0, r0, r2 ++ bgt 1b ++ bx r6 ++.endm ++ ++.macro edge_32bx2_e0, body_fn, pb ++ add r6, r1, r3 ++ push {r7,lr} ++ sub r1, #8 ++ add r7, r0, r2 ++ lsl r2, #1 ++1: vldmia r1, {d7-d12} ++ // load a ++ vext.8 q0, q3, q4, #16 - \pb ++ add r1, r1, r3, lsl #1 ++ vext.8 q1, q4, q5, #16 - \pb ++ subs r12, #2 ++ // load b ++ vext.8 q8, q4, q5, #\pb ++ vext.8 q9, q5, q6, #\pb ++ vldr d25, [r6, #-8] ++ vldmia r6, {d12-d15} ++ vldr d26, [r6, #32] ++ // load a ++ vext.8 q2, q12, q6, #16 - \pb ++ add r6, r6, r3, lsl #1 ++ vext.8 q3, q6, q7, #16 - \pb ++ // load b ++ vext.8 q10, q6, q7, #\pb ++ vext.8 q11, q7, q13, #\pb ++ bl \body_fn ++ vst1.8 {q0-q1}, [r0, :256], r2 ++ vst1.8 {q2-q3}, [r7, :256], r2 ++ bgt 1b ++ pop {r7,pc} ++.endm ++ ++.macro edge_16b_e0, body_fn, pb ++ sub r1, #8 ++ mov r6, lr ++1: vldmia r1, {d1-d4} ++ add r1, r3 ++ subs r12, #1 ++ vext.8 q0, q0, q1, #16 - \pb ++ vext.8 q2, q1, q2, #\pb ++ ++ bl \body_fn ++ vst1.8 {q0}, [r0, :128], r2 ++ bgt 1b ++ bx r6 ++.endm ++ ++.macro edge_8bx2_e0, body_fn, pb ++ add r6, r1, r3 ++ push {r7,lr} ++ sub r1, #8 ++ add r7, r0, r2 ++ lsl r2, #1 ++1: vldmia r1, {d1-d2} ++ vldmia r6, {d3-d4} ++ vldr d6, [r1, #16] ++ subs r12, #2 ++ vldr d7, [r6, #-8] ++ add r1, r1, r3, lsl #1 ++ vext.8 d0, d1, d2, #8 - \pb ++ add r6, r6, r3, lsl #1 ++ vext.8 d5, d3, d4, #\pb ++ vext.8 d4, d2, d6, #\pb ++ vext.8 d1, d7, d3, #8 - \pb ++ ++ bl \body_fn ++ vst1.8 {d0}, [r0, :64], r2 ++ vst1.8 {d1}, [r7, :64], r2 ++ bgt 1b ++ pop {r7,pc} ++.endm ++ ++.macro edge_4bx4_e0, body_fn, pb ++ add r6, r1, r3 ++ push {r7,lr} ++ add r7, r0, r2 ++ lsl r2, #1 ++ ++ tst r1, #4 ++ bne 2f ++1: // r1 (and assumed r6) are 64-bit aligned ++ vldr d2, [r1] ++ vldr d0, [r1, #-8] ++ add r1, r1, r3, lsl #1 ++ vldr d20, [r6] ++ subs r12, #4 ++ vldr d18, [r6, #-8] ++ add r6, r6, r3, lsl #1 ++ vldr d3, [r1] ++ vshr.u64 d4, d2, #\pb * 8 ++ vldr d1, [r1, #-8] ++ add r1, r1, r3, lsl #1 ++ vldr d21, [r6] ++ vext.8 d0, d0, d2, #8 - \pb ++ vldr d19, [r6,#-8] ++ add r6, r6, r3, lsl #1 ++ vshr.u64 d22, d20, #\pb * 8 ++ vext.8 d18, d18, d20, #8 - \pb ++ vshr.u64 d5, d3, #\pb * 8 ++ vext.8 d1, d1, d3, #8 - \pb ++ vshr.u64 d23, d21, #\pb * 8 ++ vext.8 d19, d19, d21, #8 - \pb ++ vsli.64 q1, q10, #32 ++ vsli.64 q2, q11, #32 ++ vsli.64 q0, q9, #32 ++ ++ bl \body_fn ++ vst1.32 {d0[0]}, [r0, :32], r2 ++ vst1.32 {d0[1]}, [r7, :32], r2 ++ vst1.32 {d1[0]}, [r0, :32], r2 ++ vst1.32 {d1[1]}, [r7, :32], r2 ++ bgt 1b ++ pop {r7,pc} ++ ++2: // r1 (and assumed r6) are 32-bit but not 64-bit aligned ++ vldr d20, [r1, #-4] ++ vldr d22, [r1, #4] ++ add r1, r1, r3, lsl #1 ++ vldr d2, [r6, #-4] ++ subs r12, #4 ++ vldr d4, [r6, #4] ++ add r6, r6, r3, lsl #1 ++ vldr d21, [r1, #-4] ++ vshl.i64 d18, d20, #\pb * 8 ++ vldr d23, [r1, #4] ++ add r1, r1, r3, lsl #1 ++ vldr d3, [r6, #-4] ++ vext.8 d22, d20, d22, #\pb ++ vldr d5, [r6, #4] ++ add r6, r6, r3, lsl #1 ++ vshl.i64 d0, d2, #\pb * 8 ++ vext.8 d4, d2, d4, #\pb ++ vshl.i64 d19, d21, #\pb * 8 ++ vext.8 d23, d21, d23, #\pb ++ vshl.i64 d1, d3, #\pb * 8 ++ vext.8 d5, d3, d5, #\pb ++ vsri.64 q1, q10, #32 ++ vsri.64 q0, q9, #32 ++ vsri.64 q2, q11, #32 ++ ++ bl \body_fn ++ vst1.32 {d0[0]}, [r0, :32], r2 ++ vst1.32 {d0[1]}, [r7, :32], r2 ++ vst1.32 {d1[0]}, [r0, :32], r2 ++ vst1.32 {d1[1]}, [r7, :32], r2 ++ bgt 2b ++ pop {r7,pc} ++.endm ++ ++ ++.macro edge_64b_e1, body_fn ++ sub r1, r3 ++ push {lr} ++ add r6, r1, #32 ++ // load a ++ vld1.8 {q0-q1}, [r1, :256], r3 ++ vld1.8 {q2-q3}, [r6, :256], r3 ++ // load c ++ vld1.8 {q4-q5}, [r1, :256], r3 ++ vld1.8 {q6-q7}, [r6, :256], r3 ++1: // load b ++ vld1.8 {q8-q9}, [r1, :256], r3 ++ subs r12, #1 ++ vld1.8 {q10-q11}, [r6, :256], r3 ++ bl \body_fn ++ vstm r0, {q0-q3} ++ // copy c to a ++ vmov.64 q0, q4 ++ pld [r1, r3] ++ vmov.64 q1, q5 ++ it le ++ pople {lr} ++ vmov.64 q2, q6 ++ it le ++ bxle lr ++ vmov.64 q3, q7 ++ add r0, r0, r2 ++ // copy b to c ++ vmov.64 q4, q8 ++ vmov.64 q5, q9 ++ vmov.64 q6, q10 ++ vmov.64 q7, q11 ++ b 1b ++.endm ++ ++.macro edge_32bx2_e1, body_fn ++ sub r6, r1, r3 ++ vld1.8 {q2-q3}, [r1, :256], r3 ++ vld1.8 {q0-q1}, [r6, :256] ++ mov r6, lr ++ ++1: @ Given the data duplication here we could obviously do better than ++ @ using the generic body_fn but it almost certainly isn't worth it ++ vld1.8 {q8-q9}, [r1, :256], r3 ++ subs r12, #2 ++ vmov q4, q2 ++ vmov q5, q3 ++ vld1.8 {q10-q11}, [r1, :256], r3 ++ vmov q6, q8 ++ vmov q7, q9 ++ ++ bl \body_fn ++ ++ vst1.8 {q0-q1}, [r0, :256], r2 ++ // copy b to a ++ vmov q0, q8 ++ vmov q1, q9 ++ vst1.8 {q2-q3}, [r0, :256], r2 ++ vmov q2, q10 ++ it le ++ bxle r6 ++ vmov q3, q11 ++ b 1b ++.endm ++ ++.macro edge_16b_e1, body_fn ++ sub r6, r1, r3 ++ // load c ++ vld1.8 {q1}, [r1, :128], r3 ++ // load a ++ vld1.8 {q0}, [r6, :128] ++ mov r6, lr ++1: // load b ++ vld1.8 {q2}, [r1, :128], r3 ++ bl \body_fn ++ vst1.8 {q0}, [r0, :128], r2 ++ subs r12, #1 ++ // copy c to a ++ vmov.64 q0, q1 ++ it le ++ bxle r6 ++ // copy b to c ++ vmov.64 q1, q2 ++ b 1b ++.endm ++ ++.macro edge_8bx2_e1, body_fn ++ sub r6, r1, r3 ++ lsl r3, #1 ++ push {r7, lr} ++ vld1.8 {d1}, [r1, :64], r3 ++ vld1.8 {d0}, [r6, :64], r3 ++ add r7, r0, r2 ++ lsl r2, #1 ++1: @ Given the data duplication here we could obviously do better than ++ @ using the generic body_fn but it almost certainly isn't worth it ++ vld1.8 {d4}, [r6, :64], r3 ++ vmov d2, d1 ++ vld1.8 {d5}, [r1, :64], r3 ++ subs r12, #2 ++ vmov d3, d4 ++ ++ bl \body_fn ++ ++ vst1.8 {d0}, [r0, :64], r2 ++ vst1.8 {d1}, [r7, :64], r2 ++ ++ // copy b to a ++ vmov q0, q2 ++ bgt 1b ++ pop {r7, pc} ++.endm ++ ++.macro edge_4bx4_e1, body_fn ++ sub r6, r1, r3 ++ lsl r3, #1 ++ push {r7, lr} ++ vld1.32 {d0[1]}, [r1, :32], r3 ++ add r7, r0, r2 ++ vld1.32 {d0[0]}, [r6, :32], r3 ++ lsl r2, #1 ++ vld1.32 {d4[1]}, [r1, :32], r3 ++ vld1.32 {d4[0]}, [r6, :32], r3 ++ vld1.32 {d5[1]}, [r1, :32], r3 ++ vld1.32 {d5[0]}, [r6, :32], r3 ++ vmov d1, d4 ++ vext.32 d2, d0, d4, #1 ++ subs r12, #4 ++ vmov d22, d5 ++ vext.32 d3, d4, d5, #1 ++ b 2f ++ ++1: vst1.32 {d0[0]}, [r0, :32], r2 ++ vext.32 d2, d22, d4, #1 ++ vst1.32 {d0[1]}, [r7, :32], r2 ++ vmov d0, d22 ++ vst1.32 {d1[0]}, [r0, :32], r2 ++ vext.32 d3, d4, d5, #1 ++ vst1.32 {d1[1]}, [r7, :32], r2 ++ vmov d1, d4 ++ vmov d22, d5 ++2: @ Given the data duplication here we could probably do better than ++ @ using the generic body_fn but it almost certainly isn't worth it ++ bl \body_fn ++ ble 3f ++ vld1.32 {d4[0]}, [r6, :32], r3 ++ subs r12, #4 ++ vld1.32 {d4[1]}, [r1, :32], r3 ++ vld1.32 {d5[0]}, [r6, :32], r3 ++ vld1.32 {d5[1]}, [r1, :32], r3 ++ b 1b ++ ++3: vst1.32 {d0[0]}, [r0, :32], r2 ++ vst1.32 {d0[1]}, [r7, :32], r2 ++ vst1.32 {d1[0]}, [r0, :32] ++ vst1.32 {d1[1]}, [r7, :32] ++ pop {r7, pc} ++.endm ++ ++.macro edge_64b_e2, body_fn, pb ++ push {lr} ++ sub r6, r1, r3 ++ // load c and a ++ vld1.8 {q4-q5}, [r1, :128] ++ vldr d25, [r6, #-8] ++ vldmia r6, {d16-d23} ++ vext.8 q0, q12, q8, #16 - \pb ++ add r6, r1, #32 ++ vext.8 q1, q8, q9, #16 - \pb ++ add r1, r1, r3 ++ vext.8 q2, q9, q10, #16 - \pb ++ vld1.8 {q6-q7}, [r6, :128] ++ sub r6, r1, r3 ++ vext.8 q3, q10, q11, #16 - \pb ++ ++1: // load b ++ vldmia r1, {d16-d24} ++ vext.8 q8, q8, q9, #\pb ++ pld [r1, r3] ++ vext.8 q9, q9, q10, #\pb ++ subs r12, #1 ++ vext.8 q10, q10, q11, #\pb ++ vext.8 q11, q11, q12, #\pb ++ bl \body_fn ++ // next a is mostly available in c ++ vldr d25, [r6, #-8] ++ vstmia r0, {q0-q3} ++ vext.8 q3, q6, q7, #16 - \pb ++ it le ++ pople {lr} ++ vext.8 q2, q5, q6, #16 - \pb ++ it le ++ bxle lr ++ vext.8 q1, q4, q5, #16 - \pb ++ add r6, r6, r3 ++ vext.8 q0, q12, q4, #16 - \pb ++ add r0, r0, r2 ++ // next c is mostly available in b ++ vldr d8, [r1] ++ vext.8 d9, d16, d17, #8 - \pb ++ vext.8 q5, q8, q9, #16 - \pb ++ add r1, r1, r3 ++ vext.8 q6, q9, q10, #16 - \pb ++ pld [r6, #-8] ++ vext.8 q7, q10, q11, #16 - \pb ++ b 1b ++.endm ++ ++.macro edge_32bx2_e2, body_fn, pb ++ sub r6, r1, r3 ++ push {r7, lr} ++ add r7, r0, r2 ++ lsl r2, #1 ++ // load a and first 32b of c ++ vld1.8 {q4-q5}, [r1, :256] ++ vldr d25, [r6, #-8] ++ vld1.8 {q13-q14}, [r6, :256] ++ vldr d31, [r1, #-8] ++ add r6, r6, r3, lsl #1 ++ vext.8 q0, q12, q13, #16 - \pb ++ add r1, r1, r3, lsl #1 ++ vext.8 q1, q13, q14, #16 - \pb ++ vext.8 q2, q15, q4, #16 - \pb ++ vext.8 q3, q4, q5, #16 - \pb ++1: ++ // load second 32b of c and second 32b of b ++ vldmia r6, {d12-d16} ++ vldmia r1, {d20-d24} ++ // first 32b of b is mostly available in second 32b of c ++ vext.8 q9, q7, q8, #\pb ++ subs r12, #2 ++ vext.8 q8, q6, q7, #\pb ++ vext.8 q10, q10, q11, #\pb ++ vext.8 q11, q11, q12, #\pb ++ ++ bl \body_fn ++ ++ vst1.8 {q0-q1}, [r0, :256], r2 ++ vst1.8 {q2-q3}, [r7, :256], r2 ++ ble 2f ++ ++ vldr d25, [r6, #-8] ++ add r6, r6, r3, lsl #1 ++ vldr d8, [r1] ++ vext.8 d9, d20, d21, #8 - \pb ++ vldr d31, [r1, #-8] ++ add r1, r1, r3, lsl #1 ++ // first 32b of a is mostly available in second 32b of c ++ vext.8 q1, q6, q7, #16 - \pb ++ vext.8 q0, q12, q6, #16 - \pb ++ // first 32b of c is mostly available in second 32b of b ++ vext.8 q5, q10, q11, #16 - \pb ++ // second 32b of a is mostly available in first 32b of c ++ vext.8 q2, q15, q4, #16 - \pb ++ vext.8 q3, q4, q5, #16 - \pb ++ b 1b ++ ++2: pop {r7, pc} ++.endm ++ ++.macro edge_16b_e2, body_fn, pb ++ push {lr} ++ sub r6, r1, r3 ++ vld1.8 {q1}, [r1, :128], r3 ++ vldr d19, [r6, #-8] ++ vld1.8 {q10}, [r6, :128], r3 ++ ++1: vldmia r1, {d4-d6} ++ vext.8 q0, q9, q10, #16 - \pb ++ subs r12, #1 ++ vext.8 q2, q2, q3, #\pb ++ bl \body_fn ++ vst1.8 {q0}, [r0, :128], r2 ++ ble 2f ++ vmov q10, q1 ++ vldr d2, [r1] ++ add r1, r1, r3 ++ vldr d19, [r6, #-8] ++ add r6, r6, r3 ++ vext.8 d3, d4, d5, #8 - \pb ++ b 1b ++ ++2: pop {pc} ++.endm ++ ++.macro edge_8bx2_e2, body_fn, pb ++ sub r6, r1, r3 ++ push {r7, lr} ++ add r7, r0, r2 ++ lsl r2, #1 ++ vldr d18, [r6, #-8] ++ vldr d19, [r6] ++ add r6, r6, r3, lsl #1 ++ vldr d20, [r1, #-8] ++ vldr d2, [r1] ++ add r1, r1, r3, lsl #1 ++ vldmia r6, {d3-d4} ++ vld1.8 {d21-d22}, [r1, :128] ++ ++1: vext.8 d0, d18, d19, #8 - \pb ++ vext.8 d4, d3, d4, #\pb ++ vext.8 d1, d20, d2, #8 - \pb ++ subs r12, #2 ++ vext.8 d5, d21, d22, #\pb ++ ++ bl \body_fn ++ ++ vst1.8 {d0}, [r0, :64], r2 ++ vst1.8 {d1}, [r7, :64], r2 ++ ble 2f ++ ++ vldr d18, [r6, #-8] ++ add r6, r6, r3, lsl #1 ++ vldr d20, [r1, #-8] ++ vmov d19, d3 ++ vldr d2, [r1] ++ add r1, r1, r3, lsl #1 ++ vldmia r6, {d3-d4} ++ vld1.8 {d21-d22}, [r1, :128] ++ b 1b ++ ++2: pop {r7, pc} ++.endm ++ ++.macro edge_4bx4_e2, body_fn, pb ++ sub r6, r1, r3 ++ push {r7-r9, lr} ++ add r8, r1, r3 ++ sub r6, r6, #\pb ++ add r8, r8, #\pb ++ add r7, r0, r2 ++ lsl r2, #1 ++ ++1: vld1.32 {d0[0]}, [r6], r3 ++ subs r12, #4 ++ vld1.32 {d2[0]}, [r1], r3 ++ vld1.32 {d4[0]}, [r8], r3 ++ vld1.32 {d0[1]}, [r6], r3 ++ vld1.32 {d2[1]}, [r1], r3 ++ vld1.32 {d4[1]}, [r8], r3 ++ vld1.32 {d1[0]}, [r6], r3 ++ vld1.32 {d3[0]}, [r1], r3 ++ vld1.32 {d5[0]}, [r8], r3 ++ vld1.32 {d1[1]}, [r6], r3 ++ vld1.32 {d3[1]}, [r1], r3 ++ vld1.32 {d5[1]}, [r8], r3 ++ ++ bl \body_fn ++ ++ vst1.32 {d0[0]}, [r0, :32], r2 ++ vst1.32 {d0[1]}, [r7, :32], r2 ++ vst1.32 {d1[0]}, [r0, :32], r2 ++ vst1.32 {d1[1]}, [r7, :32], r2 ++ bgt 1b ++ ++ pop {r7-r9,pc} ++.endm ++ ++.macro edge_64b_e3, body_fn, pb ++ push {lr} ++ sub r6, r1, r3 ++ // load c and a ++ vld1.8 {q4-q5}, [r1, :128] ++ vldmia r6, {d16-d24} ++ vext.8 q0, q8, q9, #\pb ++ add r6, r1, #32 ++ vext.8 q1, q9, q10, #\pb ++ add r1, r1, r3 ++ vext.8 q2, q10, q11, #\pb ++ vld1.8 {q6-q7}, [r6, :128] ++ sub r6, r1, r3 ++ vext.8 q3, q11, q12, #\pb ++ ++1: // load b ++ vldr d17, [r1, #-8] ++ vldmia r1, {d18-d25} ++ vext.8 q8, q8, q9, #16 - \pb ++ pld [r1, r3] ++ vext.8 q9, q9, q10, #16 - \pb ++ subs r12, #1 ++ vext.8 q10, q10, q11, #16 - \pb ++ vext.8 q11, q11, q12, #16 - \pb ++ bl \body_fn ++ // next a is mostly available in c ++ vldr d24, [r6, #64] ++ vstmia r0, {q0-q3} ++ vext.8 q0, q4, q5, #\pb ++ it le ++ pople {lr} ++ vext.8 q1, q5, q6, #\pb ++ it le ++ bxle lr ++ vext.8 q2, q6, q7, #\pb ++ add r6, r6, r3 ++ vext.8 q3, q7, q12, #\pb ++ add r0, r0, r2 ++ // next c is mostly available in b ++ vext.8 d14, d22, d23, #\pb ++ vldr d15, [r1, #56] ++ vext.8 q4, q8, q9, #\pb ++ add r1, r1, r3 ++ vext.8 q5, q9, q10, #\pb ++ vext.8 q6, q10, q11, #\pb ++ b 1b ++.endm ++ ++.macro edge_32bx2_e3, body_fn, pb ++ sub r6, r1, r3 ++ push {r7, lr} ++ add r7, r0, r2 ++ lsl r2, #1 ++ // load a and first 32b of c ++ vldmia r1, {d8-d12} ++ vldmia r6, {d24-d28} ++ vext.8 q2, q4, q5, #\pb ++ add r6, r6, r3, lsl #1 ++ vext.8 q3, q5, q6, #\pb ++ add r1, r1, r3, lsl #1 ++ vext.8 q0, q12, q13, #\pb ++ vext.8 q1, q13, q14, #\pb ++1: ++ // load second 32b of c and second 32b of b ++ vldr d25, [r6, #-8] ++ subs r12, #2 ++ vldmia r6, {d12-d15} ++ vldr d27, [r1, #-8] ++ vldmia r1, {d20-d23} ++ // first 32b of b is mostly available in second 32b of c ++ vext.8 q8, q12, q6, #16 - \pb ++ vext.8 q9, q6, q7, #16 - \pb ++ vext.8 q11, q10, q11, #16 - \pb ++ vext.8 q10, q13, q10, #16 - \pb ++ ++ bl \body_fn ++ ++ vst1.8 {q0-q1}, [r0, :256], r2 ++ vst1.8 {q2-q3}, [r7, :256], r2 ++ ble 2f ++ ++ vldr d24, [r6, #32] ++ add r6, r6, r3, lsl #1 ++ vldr d11, [r1, #24] ++ vext.8 d10, d22, d23, #\pb ++ vldr d30, [r1, #32] ++ add r1, r1, r3, lsl #1 ++ // first 32b of a is mostly available in second 32b of c ++ vext.8 q0, q6, q7, #\pb ++ vext.8 q1, q7, q12, #\pb ++ // first 32b of c is mostly available in second 32b of b ++ vext.8 q4, q10, q11, #\pb ++ // second 32b of a is mostly available in first 32b of c ++ vext.8 q3, q5, q15, #\pb ++ vext.8 q2, q4, q5, #\pb ++ b 1b ++ ++2: pop {r7, pc} ++.endm ++ ++.macro edge_16b_e3, body_fn, pb ++ push {lr} ++ sub r6, r1, r3 ++ vld1.8 {q1}, [r1, :128], r3 ++ vldmia r6, {d18-d20} ++ add r6, r6, r3 ++ ++1: vldr d5, [r1, #-8] ++ vld1.8 {q3}, [r1, :128] ++ subs r12, #1 ++ vext.8 q0, q9, q10, #\pb ++ vext.8 q2, q2, q3, #16 - \pb ++ bl \body_fn ++ vst1.8 {q0}, [r0, :128], r2 ++ ble 2f ++ vmov q9, q1 ++ vldr d3, [r1, #8] ++ add r1, r1, r3 ++ vldr d20, [r6, #16] ++ add r6, r6, r3 ++ vext.8 d2, d4, d5, #\pb ++ b 1b ++ ++2: pop {pc} ++.endm ++ ++.macro edge_8bx2_e3, body_fn, pb ++ sub r6, r1, r3 ++ push {r7, lr} ++ add r7, r0, r2 ++ lsl r2, #1 ++ vld1.8 {d18-d19}, [r6] ++ add r6, r6, r3, lsl #1 ++ vldr d20, [r1, #8] ++ vldr d2, [r1] ++ add r1, r1, r3, lsl #1 ++ vldr d4, [r6, #-8] ++ vldr d3, [r6] ++ vldr d21, [r1, #-8] ++ vldr d22, [r1] ++ ++1: vext.8 d0, d18, d19, #\pb ++ vext.8 d4, d4, d3, #8 - \pb ++ vext.8 d1, d2, d20, #\pb ++ subs r12, #2 ++ vext.8 d5, d21, d22, #8 - \pb ++ ++ bl \body_fn ++ ++ vst1.8 {d0}, [r0, :64], r2 ++ vst1.8 {d1}, [r7, :64], r2 ++ ble 2f ++ ++ vldr d19, [r6, #8] ++ add r6, r6, r3, lsl #1 ++ vldr d20, [r1, #8] ++ vmov d18, d3 ++ vldr d2, [r1] ++ add r1, r1, r3, lsl #1 ++ vldr d4, [r6, #-8] ++ vldr d3, [r6] ++ vldr d21, [r1, #-8] ++ vldr d22, [r1] ++ b 1b ++ ++2: pop {r7, pc} ++.endm ++ ++.macro edge_4bx4_e3, body_fn, pb ++ @ e3 is the same as e2 but with the X offset reversed ++ edge_4bx4_e2 \body_fn, (-\pb) ++.endm ++ ++@ Jump table entry - if in neon mode the bottom bit must be set ++@ ? There is probably a real asm instruction to do this but I haven't found it ++.macro jent lab ++.if jent_pic ++@ Could use .short here but due to A32 not supporting ldrh [lsl#1] it is ++@ simpler and clearer in the code to stick with .word ++T .word (0 + \lab) - (4 + 98b) ++A .word (0 + \lab) - (8 + 98b) ++.else ++T .word 1 + \lab ++A .word \lab ++.endif ++.endm ++ ++.macro edge_64b_bodies, body_fn, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ ++0: edge_64b_e0 \body_fn, \pb ++10: edge_64b_e1 \body_fn ++20: edge_64b_e2 \body_fn, \pb ++30: edge_64b_e3 \body_fn, \pb ++.endm ++ ++.macro edge_32bx2_bodies, body_fn, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ ++0: edge_32bx2_e0 \body_fn, \pb ++10: edge_32bx2_e1 \body_fn ++20: edge_32bx2_e2 \body_fn, \pb ++30: edge_32bx2_e3 \body_fn, \pb ++.endm ++ ++.macro edge_16b_bodies, body_fn, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ ++0: edge_16b_e0 \body_fn, \pb ++10: edge_16b_e1 \body_fn ++20: edge_16b_e2 \body_fn, \pb ++30: edge_16b_e3 \body_fn, \pb ++.endm ++ ++.macro edge_32bx2_16b_bodies, body_fn_64b, body_fn_16b, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ jent 5f ++ jent 15f ++ jent 25f ++ jent 35f ++ ++0: edge_32bx2_e0 \body_fn_64b, \pb ++10: edge_32bx2_e1 \body_fn_64b ++20: edge_32bx2_e2 \body_fn_64b, \pb ++30: edge_32bx2_e3 \body_fn_64b, \pb ++5: edge_16b_e0 \body_fn_16b, \pb ++15: edge_16b_e1 \body_fn_16b ++25: edge_16b_e2 \body_fn_16b, \pb ++35: edge_16b_e3 \body_fn_16b, \pb ++.endm ++ ++.macro edge_16b_8bx2_bodies, body_fn, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ jent 5f ++ jent 15f ++ jent 25f ++ jent 35f ++ ++0: edge_16b_e0 \body_fn, \pb ++10: edge_16b_e1 \body_fn ++20: edge_16b_e2 \body_fn, \pb ++30: edge_16b_e3 \body_fn, \pb ++5: edge_8bx2_e0 \body_fn, \pb ++15: edge_8bx2_e1 \body_fn ++25: edge_8bx2_e2 \body_fn, \pb ++35: edge_8bx2_e3 \body_fn, \pb ++.endm ++ ++.macro edge_8bx2_4bx4_bodies, body_fn, pb ++ jent 0f ++ jent 10f ++ jent 20f ++ jent 30f ++ jent 5f ++ jent 15f ++ jent 25f ++ jent 35f ++ ++0: edge_8bx2_e0 \body_fn, \pb ++10: edge_8bx2_e1 \body_fn ++20: edge_8bx2_e2 \body_fn, \pb ++30: edge_8bx2_e3 \body_fn, \pb ++5: edge_4bx4_e0 \body_fn, \pb ++15: edge_4bx4_e1 \body_fn ++25: edge_4bx4_e2 \body_fn, \pb ++35: edge_4bx4_e3 \body_fn, \pb ++.endm ++ ++@ void ff_hevc_rpi_sao_edge_8_neon_8( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_8_neon_8, export=1 ++ edge_16b_init 8, 0, 1, 99f ++99: ++ edge_8bx2_4bx4_bodies edge_16b_body_8, 1 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_16_neon_8( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_16_neon_8, export=1 ++ edge_16b_init 8, 0, 0, 99f ++99: ++ edge_16b_bodies edge_16b_body_8, 1 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_32_neon_8( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_32_neon_8, export=1 ++ edge_64b_init 8, 0, 0, 99f ++99: ++ edge_32bx2_bodies edge_64b_body_8, 1 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_64_neon_8( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_64_neon_8, export=1 ++ edge_64b_init 8, 0, 0, 99f ++99: ++ edge_64b_bodies edge_64b_body_8, 1 ++endfunc ++ ++@ ff_hevc_rpi_sao_edge_c_8_neon_8( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_8_neon_8, export=1 ++ edge_16b_init 8, 1, 1, 99f ++99: ++ edge_16b_8bx2_bodies edge_16b_body_8, 2 ++endfunc ++ ++@ ff_hevc_rpi_sao_edge_c_16_neon_8( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_16_neon_8, export=1 ++ edge_64b_init 8, 1, 0, 99f ++99: ++ edge_32bx2_bodies edge_64b_body_8, 2 ++endfunc ++ ++@ ff_hevc_rpi_sao_edge_c_32_neon_8( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_32_neon_8, export=1 ++ edge_64b_init 8, 1, 0, 99f ++99: ++ edge_64b_bodies edge_64b_body_8, 2 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_8_neon_10( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_8_neon_10, export=1 ++ edge_16b_init 10, 0, 1, 99f ++99: ++ edge_16b_8bx2_bodies edge_16b_body_16, 2 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_16_neon_10( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_16_neon_10, export=1 ++ edge_64b_init 10, 0, 0, 99f ++99: ++ edge_32bx2_bodies edge_64b_body_16, 2 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_64_neon_10( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++@ We simply split the 32 case into 2 vertical stripes ++@ and call the fns for w32 ++@ ++@ Calling code will always have src != dst so we don't have to worry ++@ about edge effects ++ ++function ff_hevc_rpi_sao_edge_64_neon_10, export=1 ++ edge_64b_init 10, 0, 1, 99f, xjump=1 ++endfunc ++ ++@ void ff_hevc_rpi_sao_edge_32_neon_10( ++@ uint8_t *_dst, [r0] ++@ uint8_t *_src, [r1] ++@ int stride_dst, [r2] ++@ int16_t *_sao_offset_val, [r3] ++@ int eo, [sp, #0] ++@ int width, [sp, #4] ++@ int height) [sp, #8] ++ ++function ff_hevc_rpi_sao_edge_32_neon_10, export=1 ++ edge_64b_init 10, 0, 0, 99f ++99: ++ edge_64b_bodies edge_64b_body_16, 2 ++endfunc ++ ++@ ff_hevc_rpi_sao_edge_c_8_neon_10( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_8_neon_10, export=1 ++ edge_xxb_init 10, 1, 99f, check_w4=1, setup_16b=1, setup_64b=1 ++99: ++ edge_32bx2_16b_bodies edge_64b_body_16, edge_16b_body_16, 4 ++endfunc ++ ++@ ff_hevc_rpi_sao_edge_c_32_neon_10( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_32_neon_10, export=1 ++ edge_64b_init 10, 1, 1, 99f, xjump=1 ++endfunc ++ ++ ++@ ff_hevc_rpi_sao_edge_c_16_neon_10( ++@ uint8_t *_dst, [r0] ++@ const uint8_t *_src, [r1] ++@ ptrdiff_t stride_dst, [r2] ++@ const int16_t *_sao_offset_val_u, [r3] ++@ const int16_t *_sao_offset_val_v, [sp, #0] ++@ int eo, [sp, #4] ++@ int width, [sp, #8] ++@ int height) [sp, #12] ++ ++function ff_hevc_rpi_sao_edge_c_16_neon_10, export=1 ++ edge_64b_init 10, 1, 0, 99f ++99: ++ edge_64b_bodies edge_64b_body_16, 4 ++endfunc ++ +diff --git a/libavcodec/arm/rpi_hevcpred_arm.h b/libavcodec/arm/rpi_hevcpred_arm.h +new file mode 100644 +index 0000000000..36a23a5bf9 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_arm.h +@@ -0,0 +1,28 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_ARM_HEVCPRED_ARM_H ++#define AVCODEC_ARM_HEVCPRED_ARM_H ++ ++#include "libavcodec/rpi_hevcpred.h" ++ ++void ff_hevc_rpi_pred_init_arm(HEVCRpiPredContext * const c, const int bit_depth); ++void ff_hevc_rpi_pred_init_neon(HEVCRpiPredContext * const c, const int bit_depth); ++ ++#endif /* AVCODEC_ARM_HEVCPRED_ARM_H */ ++ +diff --git a/libavcodec/arm/rpi_hevcpred_init_arm.c b/libavcodec/arm/rpi_hevcpred_init_arm.c +new file mode 100644 +index 0000000000..80724d4cf3 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_init_arm.c +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (c) 2018 John Cox (for Raspberry Pi) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/attributes.h" ++#include "libavutil/cpu.h" ++#include "libavutil/arm/cpu.h" ++ ++#include "libavcodec/rpi_hevcpred.h" ++#include "rpi_hevcpred_arm.h" ++ ++av_cold void ff_hevc_rpi_pred_init_arm(HEVCRpiPredContext * const c, const int bit_depth) ++{ ++ int cpu_flags = av_get_cpu_flags(); ++ ++ if (have_neon(cpu_flags)) ++ ff_hevc_rpi_pred_init_neon(c, bit_depth); ++} ++ +diff --git a/libavcodec/arm/rpi_hevcpred_init_neon.c b/libavcodec/arm/rpi_hevcpred_init_neon.c +new file mode 100644 +index 0000000000..21e7700174 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_init_neon.c +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2018 John Cox (for Raspberry Pi) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "rpi_hevcpred_arm.h" ++ ++intra_filter_fn_t ff_hevc_rpi_intra_filter_4_neon_8; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_8_neon_8; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_4_neon_16; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_8_neon_16; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_16_neon_16; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_4_neon_32; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_8_neon_32; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_16_neon_32; ++ ++void ff_hevc_rpi_pred_angular_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_32_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_32_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_angular_c_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++ ++void ff_hevc_rpi_pred_vertical_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_32_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_32_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_vertical_c_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++ ++void ff_hevc_rpi_pred_horizontal_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_32_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_32_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++void ff_hevc_rpi_pred_horizontal_c_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride, int mode); ++ ++void ff_hevc_rpi_pred_planar_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_32_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_32_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_planar_c_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++ ++void ff_hevc_rpi_pred_dc_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_32_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_4_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_8_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_16_neon_8(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_32_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_4_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_8_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++void ff_hevc_rpi_pred_dc_c_16_neon_10(uint8_t *src, const uint8_t *top, const uint8_t *left, ptrdiff_t stride); ++ ++void ff_hevc_rpi_pred_init_neon(HEVCRpiPredContext * const c, const int bit_depth) ++{ ++ switch (bit_depth) ++ { ++ case 8: ++ c->intra_filter[0] = ff_hevc_rpi_intra_filter_4_neon_8; ++ c->intra_filter[1] = ff_hevc_rpi_intra_filter_8_neon_8; ++ c->intra_filter_c[0] = ff_hevc_rpi_intra_filter_4_neon_16; // Equivalent to c_4_neon_8 ++ c->intra_filter_c[1] = ff_hevc_rpi_intra_filter_8_neon_16; ++ c->intra_filter_c[2] = ff_hevc_rpi_intra_filter_16_neon_16; ++ ++ c->pred_angular[0] = ff_hevc_rpi_pred_angular_4_neon_8; ++ c->pred_angular[1] = ff_hevc_rpi_pred_angular_8_neon_8; ++ c->pred_angular[2] = ff_hevc_rpi_pred_angular_16_neon_8; ++ c->pred_angular[3] = ff_hevc_rpi_pred_angular_32_neon_8; ++ c->pred_angular_c[0] = ff_hevc_rpi_pred_angular_c_4_neon_8; ++ c->pred_angular_c[1] = ff_hevc_rpi_pred_angular_c_8_neon_8; ++ c->pred_angular_c[2] = ff_hevc_rpi_pred_angular_c_16_neon_8; ++ ++ c->pred_horizontal[0] = ff_hevc_rpi_pred_horizontal_4_neon_8; ++ c->pred_horizontal[1] = ff_hevc_rpi_pred_horizontal_8_neon_8; ++ c->pred_horizontal[2] = ff_hevc_rpi_pred_horizontal_16_neon_8; ++ c->pred_horizontal[3] = ff_hevc_rpi_pred_horizontal_32_neon_8; ++ c->pred_horizontal_c[0] = ff_hevc_rpi_pred_horizontal_c_4_neon_8; ++ c->pred_horizontal_c[1] = ff_hevc_rpi_pred_horizontal_c_8_neon_8; ++ c->pred_horizontal_c[2] = ff_hevc_rpi_pred_horizontal_c_16_neon_8; ++ ++ c->pred_vertical[0] = ff_hevc_rpi_pred_vertical_4_neon_8; ++ c->pred_vertical[1] = ff_hevc_rpi_pred_vertical_8_neon_8; ++ c->pred_vertical[2] = ff_hevc_rpi_pred_vertical_16_neon_8; ++ c->pred_vertical[3] = ff_hevc_rpi_pred_vertical_32_neon_8; ++ c->pred_vertical_c[0] = ff_hevc_rpi_pred_vertical_c_4_neon_8; ++ c->pred_vertical_c[1] = ff_hevc_rpi_pred_vertical_c_8_neon_8; ++ c->pred_vertical_c[2] = ff_hevc_rpi_pred_vertical_c_16_neon_8; ++ ++ c->pred_planar[0] = ff_hevc_rpi_pred_planar_4_neon_8; ++ c->pred_planar[1] = ff_hevc_rpi_pred_planar_8_neon_8; ++ c->pred_planar[2] = ff_hevc_rpi_pred_planar_16_neon_8; ++ c->pred_planar[3] = ff_hevc_rpi_pred_planar_32_neon_8; ++ c->pred_planar_c[0] = ff_hevc_rpi_pred_planar_c_4_neon_8; ++ c->pred_planar_c[1] = ff_hevc_rpi_pred_planar_c_8_neon_8; ++ c->pred_planar_c[2] = ff_hevc_rpi_pred_planar_c_16_neon_8; ++ ++ c->pred_dc[0] = ff_hevc_rpi_pred_dc_4_neon_8; ++ c->pred_dc[1] = ff_hevc_rpi_pred_dc_8_neon_8; ++ c->pred_dc[2] = ff_hevc_rpi_pred_dc_16_neon_8; ++ c->pred_dc[3] = ff_hevc_rpi_pred_dc_32_neon_8; ++ c->pred_dc_c[0] = ff_hevc_rpi_pred_dc_c_4_neon_8; ++ c->pred_dc_c[1] = ff_hevc_rpi_pred_dc_c_8_neon_8; ++ c->pred_dc_c[2] = ff_hevc_rpi_pred_dc_c_16_neon_8; ++ break; ++ case 10: ++ c->intra_filter[0] = ff_hevc_rpi_intra_filter_4_neon_16; ++ c->intra_filter[1] = ff_hevc_rpi_intra_filter_8_neon_16; ++ c->intra_filter[2] = ff_hevc_rpi_intra_filter_16_neon_16; ++ c->intra_filter_c[0] = ff_hevc_rpi_intra_filter_4_neon_32; ++ c->intra_filter_c[1] = ff_hevc_rpi_intra_filter_8_neon_32; ++ c->intra_filter_c[2] = ff_hevc_rpi_intra_filter_16_neon_32; ++ ++ c->pred_angular[0] = ff_hevc_rpi_pred_angular_4_neon_10; ++ c->pred_angular[1] = ff_hevc_rpi_pred_angular_8_neon_10; ++ c->pred_angular[2] = ff_hevc_rpi_pred_angular_16_neon_10; ++ c->pred_angular[3] = ff_hevc_rpi_pred_angular_32_neon_10; ++ c->pred_angular_c[0] = ff_hevc_rpi_pred_angular_c_4_neon_10; ++ c->pred_angular_c[1] = ff_hevc_rpi_pred_angular_c_8_neon_10; ++ c->pred_angular_c[2] = ff_hevc_rpi_pred_angular_c_16_neon_10; ++ ++ c->pred_horizontal[0] = ff_hevc_rpi_pred_horizontal_4_neon_10; ++ c->pred_horizontal[1] = ff_hevc_rpi_pred_horizontal_8_neon_10; ++ c->pred_horizontal[2] = ff_hevc_rpi_pred_horizontal_16_neon_10; ++ c->pred_horizontal[3] = ff_hevc_rpi_pred_horizontal_32_neon_10; ++ c->pred_horizontal_c[0] = ff_hevc_rpi_pred_horizontal_c_4_neon_10; ++ c->pred_horizontal_c[1] = ff_hevc_rpi_pred_horizontal_c_8_neon_10; ++ c->pred_horizontal_c[2] = ff_hevc_rpi_pred_horizontal_c_16_neon_10; ++ ++ c->pred_vertical[0] = ff_hevc_rpi_pred_vertical_4_neon_10; ++ c->pred_vertical[1] = ff_hevc_rpi_pred_vertical_8_neon_10; ++ c->pred_vertical[2] = ff_hevc_rpi_pred_vertical_16_neon_10; ++ c->pred_vertical[3] = ff_hevc_rpi_pred_vertical_32_neon_10; ++ c->pred_vertical_c[0] = ff_hevc_rpi_pred_vertical_c_4_neon_10; ++ c->pred_vertical_c[1] = ff_hevc_rpi_pred_vertical_c_8_neon_10; ++ c->pred_vertical_c[2] = ff_hevc_rpi_pred_vertical_c_16_neon_10; ++ ++ c->pred_planar[0] = ff_hevc_rpi_pred_planar_4_neon_10; ++ c->pred_planar[1] = ff_hevc_rpi_pred_planar_8_neon_10; ++ c->pred_planar[2] = ff_hevc_rpi_pred_planar_16_neon_10; ++ c->pred_planar[3] = ff_hevc_rpi_pred_planar_32_neon_10; ++ c->pred_planar_c[0] = ff_hevc_rpi_pred_planar_c_4_neon_10; ++ c->pred_planar_c[1] = ff_hevc_rpi_pred_planar_c_8_neon_10; ++ c->pred_planar_c[2] = ff_hevc_rpi_pred_planar_c_16_neon_10; ++ ++ c->pred_dc[0] = ff_hevc_rpi_pred_dc_4_neon_10; ++ c->pred_dc[1] = ff_hevc_rpi_pred_dc_8_neon_10; ++ c->pred_dc[2] = ff_hevc_rpi_pred_dc_16_neon_10; ++ c->pred_dc[3] = ff_hevc_rpi_pred_dc_32_neon_10; ++ c->pred_dc_c[0] = ff_hevc_rpi_pred_dc_c_4_neon_10; ++ c->pred_dc_c[1] = ff_hevc_rpi_pred_dc_c_8_neon_10; ++ c->pred_dc_c[2] = ff_hevc_rpi_pred_dc_c_16_neon_10; ++ break; ++ default: ++ break; ++ } ++} ++ +diff --git a/libavcodec/arm/rpi_hevcpred_intra_angular_neon.S b/libavcodec/arm/rpi_hevcpred_intra_angular_neon.S +new file mode 100644 +index 0000000000..fa8f67cf03 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_intra_angular_neon.S +@@ -0,0 +1,2984 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++/* ++ * General angular pred ++ * ++ * Horizontal (10) & Vertical (26) cases have their own file ++ * and are not dealt with properly here (luma filtering is missing) ++ * ++ * The inv_angle calculations are annoying - if it wasn't for the +128 ++ * rounding step then the result would simply be the loop counter :-( ++ */ ++ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++.text ++ ++@ Horizontal Patch functions ++@ These need a transpose before store so exist as smaller patches ++@ Patches can be called repeatedly without any intermediate setup ++@ to generate a horizontal block ++@ ++@ It is almost certainly the case that larger patch fns can be built ++@ and they would be a little faster, but we would still need the small ++@ fns and code size (or at least instruction cache size) is an issue ++@ given how much code we already have here ++ ++@ Generate 8x8 luma 8 patch ++@ ++@ r3 Out stride ++@ r4 Angle add ++@ r7 Inv angle (_up only) ++@ ++@ In/Out (updated) ++@ r0 Out pointer - on exit point to start of next patch horizontally (i.e. r0 + patch width) ++@ r2 Left ptr - updated ++@ r10 Inv angle accumulator (_up only) ++@ r12 32 - angle frac (_down) or angle frac (_up) ++@ d0 Older reference samples ++@ d1=r8+r9 Newer reference samples ++@ d2 32 - angle frac ++@ d3 Angle frac ++@ q2 Partially computed next result (_up only) ++@ ++@ Temps ++@ r5 Loop counter ++@ r6 ++@ r7 (_down only) ++@ r11 (_up only) ++@ q2, q8-q11 ++ ++patch_h_down_8x8_8: ++ ldrd r8, r9, [r2] @ Left ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r6 ++ lsr r8, #8 ++ vdup.8 d2, r12 ++ orr r8, r8, r9, lsl #24 ++ ldr r9, [r2, #5]! ++ vmov d1, r8, r9 ++ // drop through... ++patch_h_down_8x8_8_continue: ++ mov r5, #8 ++1: ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ vext.8 q8, q8, q9, #8 ++ itt mi ++ lsrmi r7, r8, #8 ++ vmovmi d0, r8, r9 ++ vdup.8 d2, r12 ++ vext.8 q9, q9, q10, #8 ++ it mi ++ orrmi r8, r7, r9, lsl #24 ++ vext.8 q10, q10, q11, #8 ++ it mi ++ ldrmi r9, [r2, #1]! ++ vmov d22, d23 ++ vrshrn.u16 d23, q2, #5 ++ it mi ++ vmovmi d1, r8, r9 ++ subs r5, #1 ++ vdup.8 d3, r6 ++ bne 1b ++ // drop through... ++store_tran_8x8_8: ++ vzip.8 d16, d17 ++ add r6, r0, r3 ++ vzip.8 d18, d19 ++ lsl r3, #1 ++ vzip.8 d20, d21 ++ add r5, r0, r3 ++ vzip.8 d22, d23 ++ vzip.16 q8, q9 ++ vzip.16 q10, q11 ++ vzip.32 q8, q10 ++ vzip.32 q9, q11 ++ vst1.8 {d16}, [r0]! ++ vst1.8 {d17}, [r6], r3 ++ vst1.8 {d20}, [r5], r3 ++ vst1.8 {d21}, [r6], r3 ++ vst1.8 {d18}, [r5], r3 ++ vst1.8 {d19}, [r6], r3 ++ vst1.8 {d22}, [r5] ++ asr r3, #1 ++ vst1.8 {d23}, [r6] ++ ++ bx lr ++ ++patch_h_up_8x8_8: ++ ldrd r8, r9, [r2] ++ rsb r6, r4, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r4 ++ lsr r11, r8, #24 ++ vdup.8 d2, r6 ++ ldr r8, [r2, #-1]! ++ orr r9, r11, r9, lsl #8 ++ vmov d1, r8, r9 ++ mov r12, r4 ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++patch_h_up_8x8_8_continue: ++ mov r5, #8 ++1: ++ add r12, r4 ++ mov r11, #0 ++ cmp r12, #33 ++ it cs ++ addcs r10, r7 ++ vext.8 q8, q8, q9, #8 ++ itt cs ++ subcs r12, #32 ++ tstcs r10, #1<<31 ++ rsb r6, r12, #32 ++ it eq ++ asreq r11, r10, #8 ++ it cs ++ vmovcs d0, r8, r9 ++ vdup.8 d2, r6 ++ it cs ++ lsrcs r6, r8, #24 ++ vext.8 q9, q9, q10, #8 ++ itt cs ++ orrcs r9, r6, r9, lsl #8 ++ ldrbcs r11, [r1, r11] ++ vdup.8 d3, r12 ++ vext.8 q10, q10, q11, #8 ++ it hi ++ ldrbhi r11, [r2, #-1]! ++ vmov d22, d23 ++ vrshrn.u16 d23, q2, #5 ++ itt cs ++ orrcs r8, r11, r8, lsl #8 ++ vmovcs d1, r8, r9 ++ vmull.u8 q2, d0, d2 ++ subs r5, #1 ++ vmlal.u8 q2, d1, d3 ++ bne 1b ++ ++ b store_tran_8x8_8 ++ ++ ++.macro ADRT reg, val ++@ adr in T32 has enough range but not in A32 ++A adrl \reg, \val ++T adr \reg, \val ++.endm ++ ++@ ff_hevc_rpi_pred_angular_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_4_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r8, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ ldr lr, [r2], #1 @ Top ++ rsb r12, r6, #32 ++ vmov s0, lr ++ vdup.8 d3, r6 ++ ldr lr, [r2], #1 ++ vdup.8 d2, r12 ++ vmov s2, lr ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ itt mi ++ vmovmi s0, lr ++ ldrmi lr, [r2], #1 ++ vdup.8 d2, r12 ++ it mi ++ vmovmi s2, lr ++ vdup.8 d3, r6 ++ mov r5, #2 ++1: ++ vrshrn.u16 d20, q2, #5 ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ vext.64 q8, q8, q9, #1 ++ it mi ++ vmovmi s0, lr ++ vext.64 q9, q9, q10, #1 ++ it mi ++ ldrmi lr, [r2], #1 ++ vdup.8 d2, r12 ++ it mi ++ vmovmi s2, lr ++ subs r5, #1 ++ vdup.8 d3, r6 ++ bne 1b ++ ++ vrshrn.u16 d20, q2, #5 ++ vmull.u8 q2, d0, d2 ++ add r12, r0, r3 ++ vmlal.u8 q2, d1, d3 ++ lsl r3, #1 ++ vext.64 q8, q8, q9, #1 ++ vext.64 q9, q9, q10, #1 ++ vrshrn.u16 d20, q2, #5 ++ ++98: ++ vst4.8 {d17[0], d18[0], d19[0], d20[0]}, [r0], r3 ++ vst4.8 {d17[1], d18[1], d19[1], d20[1]}, [r12], r3 ++ vst4.8 {d17[2], d18[2], d19[2], d20[2]}, [r0] ++ vst4.8 {d17[3], d18[3], d19[3], d20[3]}, [r12] ++ pop {r4-r8, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ rsb r12, r6, #32 ++ ldr lr, [r2] @ Left ++ ldrb r2, [r2, #-1] @ Top-left ++ vmov s0, lr ++ vdup.8 d2, r12 ++ vdup.8 d3, r6 ++ orr lr, r2, lr, lsl #8 ++ vmov s2, lr ++ sub r8, r7, #128 ++ mov r5, #3 ++2: ++ vmull.u8 q2, d0, d2 ++ subs r12, r4 ++ vmlal.u8 q2, d1, d3 ++T it mi ++ addmi r12, #32 ++T asr r6, r8, #8 ++T it mi ++T ldrbmi r2, [r1, r6] ++A ldrbmi r2, [r1, r8, asr #8] ++ rsb r6, r12, #32 ++ vdup.8 d2, r12 ++ ittt mi ++ vmovmi s0, lr ++ orrmi lr, r2, lr, lsl #8 ++ vmovmi s2, lr ++ vrshrn.u16 d20, q2, #5 ++ vdup.8 d3, r6 ++ it mi ++ addmi r8, r7 ++ subs r5, #1 ++ vext.64 q8, q8, q9, #1 ++ vext.64 q9, q9, q10, #1 ++ bne 2b ++ ++ vmull.u8 q2, d0, d2 ++ add r12, r0, r3 ++ vmlal.u8 q2, d1, d3 ++ lsl r3, #1 ++ vrshrn.u16 d20, q2, #5 ++ b 98b ++ ++@ Left of vertical - works down left ++18: ++ ldrh r7, [r7] ++ rsb r12, r6, #32 ++ ldr lr, [r1] @ Top ++ ldrb r1, [r2, #-1] @ Top-left ++ vmov s0, lr ++ vdup.8 d2, r12 ++ vdup.8 d3, r6 ++ orr lr, r1, lr, lsl #8 ++ vmov s2, lr ++ sub r8, r7, #128 ++ mov r5, #3 ++2: ++ vmull.u8 q2, d0, d2 ++ subs r12, r4 ++ vmlal.u8 q2, d1, d3 ++T it mi ++ addmi r12, #32 ++T asr r6, r8, #8 ++T it mi ++T ldrbmi r1, [r2, r6] ++A ldrbmi r1, [r2, r8, asr #8] ++ rsb r6, r12, #32 ++ vdup.8 d2, r12 ++ ittt mi ++ vmovmi s0, lr ++ orrmi lr, r1, lr, lsl #8 ++ vmovmi s2, lr ++ vrshrn.u16 d4, q2, #5 ++ vdup.8 d3, r6 ++ it mi ++ addmi r8, r7 ++ subs r5, #1 ++ vst1.32 {d4[0]}, [r0], r3 ++ bne 2b ++ ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vrshrn.u16 d4, q2, #5 ++ vst1.32 {d4[0]}, [r0] ++ ++ pop {r4-r8, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ ldr lr, [r1], #1 @ Top ++ rsb r12, r6, #32 ++ vmov s0, lr ++ vdup.8 d3, r6 ++ ldr lr, [r1], #1 ++ vdup.8 d2, r12 ++ vmov s2, lr ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ itt mi ++ vmovmi s0, lr ++ ldrmi lr, [r1], #1 ++ vdup.8 d2, r12 ++ it mi ++ vmovmi s2, lr ++ vdup.8 d3, r6 ++ mov r5, #2 ++1: ++ vrshrn.u16 d6, q2, #5 ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ vst1.32 {d6[0]}, [r0], r3 ++ itt mi ++ vmovmi s0, lr ++ ldrmi lr, [r1], #1 ++ vdup.8 d2, r12 ++ it mi ++ vmovmi s2, lr ++ subs r5, #1 ++ vdup.8 d3, r6 ++ bne 1b ++ ++ vrshrn.u16 d6, q2, #5 ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vst1.32 {d6[0]}, [r0], r3 ++ vrshrn.u16 d6, q2, #5 ++ vst1.32 {d6[0]}, [r0] ++ ++ pop {r4-r8, pc} ++ ++endfunc ++ ++ ++ ++@ ff_hevc_rpi_pred_angular_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_8_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ bl patch_h_down_8x8_8 ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ bl patch_h_up_8x8_8 ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ ldrb lr, [r2, #-1] @ Top-left ++ ldrh r7, [r7] ++ vmov d0, r8, r9 ++ lsl r9, r9, #8 ++ vdup.8 d2, r12 ++ orr r9, r9, r8, lsr #24 ++ orr r8, lr, r8, lsl #8 ++ vmov d1, r8, r9 ++ sub r1, r7, #128 ++ mov r5, #7 ++1: ++ vdup.8 d3, r6 ++ vmull.u8 q2, d0, d2 ++ subs r12, r12, r4 ++ vmlal.u8 q2, d1, d3 ++ ittt mi ++ addmi lr, r2, r1, asr #8 ++ addmi r12, r12, #32 ++ vmovmi d0, r8, r9 ++ rsb r6, r12, #32 ++ itt mi ++ lslmi r9, r9, #8 ++ ldrbmi lr, [lr] ++ vdup.8 d2, r12 ++ vrshrn.u16 d4, q2, #5 ++ itttt mi ++ orrmi r9, r9, r8, lsr #24 ++ orrmi r8, lr, r8, lsl #8 ++ vmovmi d1, r8, r9 ++ addmi r1, r1, r7 ++ subs r5, r5, #1 ++ vst1.8 {d4}, [r0], r3 ++ bne 1b ++ ++ vdup.8 d3, r6 ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vrshrn.u16 d4, q2, #5 ++ vst1.8 {d4}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r6 ++ mov r5, #7 ++ lsr r8, #8 ++ vdup.8 d2, r12 ++ orr r8, r8, r9, lsl #24 ++ ldr r9, [r1, #5]! ++ vmov d1, r8, r9 ++1: ++ vmull.u8 q2, d0, d2 ++ subs r12, r4 ++ vmlal.u8 q2, d1, d3 ++ it mi ++ addmi r12, #32 ++ rsb r6, r12, #32 ++ itt mi ++ vmovmi d0, r8, r9 ++ lsrmi r8, #8 ++ vdup.8 d2, r12 ++ itt mi ++ orrmi r8, r8, r9, lsl #24 ++ ldrmi r9, [r1, #1]! ++ vrshrn.u16 d6, q2, #5 ++ it mi ++ vmovmi d1, r8, r9 ++ vdup.8 d3, r6 ++ subs r5, #1 ++ vst1.8 {d6}, [r0], r3 ++ bne 1b ++ ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vrshrn.u16 d6, q2, #5 ++ vst1.8 {d6}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_16_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r1, r2 @ save r2 - r1 unused by patch_down ++ ++ bl patch_h_down_8x8_8 ++ bl patch_h_down_8x8_8_continue ++ ++ add r2, r1, #8 @ restore r2, but 8 rows further down left ++ sub r0, #16 ++ mov r6, r4 ++ add r0, r0, r3, lsl #3 ++ ++ bl patch_h_down_8x8_8 ++ bl patch_h_down_8x8_8_continue ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ ++ push {r2} ++ bl patch_h_up_8x8_8 ++ bl patch_h_up_8x8_8_continue ++ pop {r2} ++ ++ sub r0, #16 ++ mov r10, #-128 ++ add r2, #8 ++ add r0, r0, r3, lsl #3 ++ sub r10, r10, r7, lsl #3 ++ ++ bl patch_h_up_8x8_8 ++ bl patch_h_up_8x8_8_continue ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.8 {q9}, [r1] ++ sub r1, r2, #1 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ vdup.8 d6, r6 ++ vext.8 q8, q9, q9, #15 ++ sub r8, r7, #128 ++ vld1.8 {d16[0]}, [r1] ++ vdup.8 d7, r12 ++ mov r5, #15 ++1: ++ vmull.u8 q0, d18, d7 ++ subs r12, r4 ++ vmlal.u8 q0, d16, d6 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d19, d7 ++ it cc ++ addcc r1, r2, r8, asr #8 ++ vmlal.u8 q1, d17, d6 ++ rsb r6, r12, #32 ++ vext.8 q10, q8, q8, #15 ++ sub r5, #1 ++ vld1.8 {d20[0]}, [r1] ++ it cc ++ addcc r8, r7 ++ vmov q11, q8 ++ teq r5, #0 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmull.u8 q0, d22, d7 ++ subs r12, r4 ++ vmlal.u8 q0, d20, d6 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d23, d7 ++ it cc ++ addcc r1, r2, r8, asr #8 ++ vmlal.u8 q1, d21, d6 ++ rsb r6, r12, #32 ++ vext.8 q8, q10, q10, #15 ++ sub r5, #1 ++ vld1.8 {d16[0]}, [r1] ++ it cc ++ addcc r8, r7 ++ vmov q9, q10 ++ teq r5, #0 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmull.u8 q0, d22, d7 ++ vmlal.u8 q0, d20, d6 ++ vmull.u8 q1, d23, d7 ++ vmlal.u8 q1, d21, d6 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmull.u8 q0, d18, d7 ++ vmlal.u8 q0, d16, d6 ++ vmull.u8 q1, d19, d7 ++ vmlal.u8 q1, d17, d6 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ vld1.8 {q9}, [r1]! ++ rsb r12, r6, #32 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vext.8 q8, q9, q9, #1 ++ vld1.8 {d17[7]}, [r1]! ++ mov r5, #15 ++1: ++ vmull.u8 q0, d16, d6 ++ subs r12, r4 ++ vmlal.u8 q0, d18, d7 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d17, d6 ++ rsb r6, r12, #32 ++ vmlal.u8 q1, d19, d7 ++ sub r5, #1 ++ vext.8 q10, q8, q8, #1 ++ teq r5, #0 ++ vld1.8 {d21[7]}, [r1] ++ it cc ++ addcc r1, #1 ++ vmov q11, q8 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmull.u8 q0, d20, d6 ++ subs r12, r4 ++ vmlal.u8 q0, d22, d7 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d21, d6 ++ rsb r6, r12, #32 ++ vmlal.u8 q1, d23, d7 ++ sub r5, #1 ++ vext.8 q8, q10, q10, #1 ++ teq r5, #0 ++ vld1.8 {d17[7]}, [r1] ++ it cc ++ addcc r1, #1 ++ vmov q9, q10 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmull.u8 q0, d20, d6 ++ vmlal.u8 q0, d22, d7 ++ vmull.u8 q1, d21, d6 ++ vmlal.u8 q1, d23, d7 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmull.u8 q0, d16, d6 ++ vmlal.u8 q0, d18, d7 ++ vmull.u8 q1, d17, d6 ++ vmlal.u8 q1, d19, d7 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_32_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_32_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r10, #4 ++ mov r1, r2 ++1: ++ bl patch_h_down_8x8_8 ++ bl patch_h_down_8x8_8_continue ++ bl patch_h_down_8x8_8_continue ++ bl patch_h_down_8x8_8_continue ++ ++ add r2, r1, #8 @ restore r2, but 8 rows further down left ++ add r1, r1, #8 ++ mov r6, r4 ++ sub r0, #32 ++ subs r10, #1 ++ add r0, r0, r3, lsl #3 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ vmov.i8 d6, #1<<2 ++1: ++ push {r2,r10} ++ bl patch_h_up_8x8_8 ++ bl patch_h_up_8x8_8_continue ++ bl patch_h_up_8x8_8_continue ++ bl patch_h_up_8x8_8_continue ++ pop {r2,r10} ++ ++ vmov r8, s12 ++ sub r0, #32 ++ add r2, #8 ++ add r0, r0, r3, lsl #3 ++ sub r10, r10, r7, lsl #3 ++ vshr.u8 d6, #1 ++ teq r8, #0 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.8 {q0-q1}, [r1] ++ sub r9, r2, #1 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ mov r5, #32 ++1: ++ vld1.8 {d17[7]}, [r9] ++ add r8, r7 ++ vmov q2, q0 ++ vmov q3, q1 ++ add r9, r2, r8, asr #8 ++ vext.8 q1, q0, q1, #15 ++ vext.8 q0, q8, q0, #15 ++2: ++ vmull.u8 q10, d4, d19 ++ subs r12, r4 ++ vmlal.u8 q10, d0, d18 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q11, d5, d19 ++ rsb r6, r12, #32 ++ vmlal.u8 q11, d1, d18 ++ sub r5, #1 ++ vmull.u8 q12, d6, d19 ++ teq r5, #0 ++ vmlal.u8 q12, d2, d18 ++ vmull.u8 q13, d7, d19 ++ vmlal.u8 q13, d3, d18 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ vrshrn.u16 d20, q10, #5 ++ vrshrn.u16 d21, q11, #5 ++ vrshrn.u16 d22, q12, #5 ++ vrshrn.u16 d23, q13, #5 ++ vst1.8 {q10-q11}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.8 {q0-q1}, [r1]! ++ rsb r12, r6, #32 ++ vld1.8 {d16[0]}, [r5] ++ mov r5, #32 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++1: ++ vmov q2, q0 ++ add r1, #1 ++ vmov q3, q1 ++ vext.8 q0, q0, q1, #1 ++ vext.8 q1, q1, q8, #1 ++2: ++ vmull.u8 q10, d0, d18 ++ subs r12, r4 ++ vmlal.u8 q10, d4, d19 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q11, d1, d18 ++ rsb r6, r12, #32 ++ vmlal.u8 q11, d5, d19 ++ sub r5, #1 ++ vmull.u8 q12, d2, d18 ++ teq r5, #0 ++ vmlal.u8 q12, d6, d19 ++ vmull.u8 q13, d3, d18 ++ vmlal.u8 q13, d7, d19 ++ vld1.8 {d16[0]}, [r1] ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ vrshrn.u16 d20, q10, #5 ++ vrshrn.u16 d21, q11, #5 ++ vrshrn.u16 d22, q12, #5 ++ vrshrn.u16 d23, q13, #5 ++ vst1.8 {q10-q11}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ Chroma 8 bit 4x4 patch fns ++ .text ++ ++patch_h_down_c_4x4_8: ++ ldrd r8, r9, [r2] @ Left ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r6 ++ lsr r8, #16 ++ vdup.8 d2, r12 ++ orr r8, r8, r9, lsl #16 ++ ldr r9, [r2, #6]! ++ vmov d1, r8, r9 ++ // drop through... ++patch_h_down_c_4x4_8_continue: ++ mov r5, #4 ++1: ++ subs r12, r4 ++ vmull.u8 q2, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmlal.u8 q2, d1, d3 ++ rsb r6, r12, #32 ++ vext.8 q8, q8, q9, #8 ++ it mi ++ lsrmi r7, r8, #16 ++ vmov d18, d19 ++ it mi ++ vmovmi d0, r8, r9 ++ vdup.8 d2, r12 ++ it mi ++ orrmi r8, r7, r9, lsl #16 ++ vrshrn.u16 d19, q2, #5 ++ itt mi ++ ldrmi r9, [r2, #2]! ++ vmovmi d1, r8, r9 ++ subs r5, #1 ++ vdup.8 d3, r6 ++ bne 1b ++ // drop through... ++store_tran_c_4x4_8: ++ vzip.16 d16, d17 ++ add r6, r0, r3 ++ vzip.16 d18, d19 ++ lsl r3, #1 ++ vzip.32 q8, q9 ++ add r5, r0, r3 ++ vst1.16 {d16}, [r0]! ++ vst1.16 {d17}, [r6], r3 ++ vst1.16 {d18}, [r5] ++ asr r3, #1 ++ vst1.16 {d19}, [r6] ++ ++ bx lr ++ ++patch_h_up_c_4x4_8: ++ ldrd r8, r9, [r2] ++ rsb r6, r4, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r4 ++ lsr r11, r8, #16 ++ vdup.8 d2, r6 ++ ldr r8, [r2, #-2]! ++ orr r9, r11, r9, lsl #16 ++ vmov d1, r8, r9 ++ mov r12, r4 ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++patch_h_up_c_4x4_8_continue: ++ mov r5, #4 ++1: ++ add r12, r4 ++ cmp r12, #33 ++ it cs ++ addcs r10, r7 ++ mov r11, #0 ++ itt cs ++ subcs r12, #32 ++ tstcs r10, #1<<31 ++ rsb r6, r12, #32 ++ it eq ++ asreq r11, r10, #7 ++ it cs ++ vmovcs d0, r8, r9 ++ it eq ++ biceq r11, #1 ++ vdup.8 d2, r6 ++ it cs ++ lsrcs r6, r8, #16 ++ vdup.8 d3, r12 ++ vext.8 q8, q8, q9, #8 ++ itt cs ++ orrcs r9, r6, r9, lsl #16 ++ ldrhcs r11, [r1, r11] ++ vmov d18, d19 ++ it hi ++ ldrhhi r11, [r2, #-2]! ++ vrshrn.u16 d19, q2, #5 ++ itt cs ++ orrcs r8, r11, r8, lsl #16 ++ vmovcs d1, r8, r9 ++ vmull.u8 q2, d0, d2 ++ subs r5, #1 ++ vmlal.u8 q2, d1, d3 ++ bne 1b ++ ++ b store_tran_c_4x4_8 ++ ++ ++@ ff_hevc_rpi_pred_angular_c_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_4_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ bl patch_h_down_c_4x4_8 ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ bl patch_h_up_c_4x4_8 ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ ldrh lr, [r2, #-2] @ Top-left ++ ldrh r7, [r7] ++ vmov d0, r8, r9 ++ lsl r9, r9, #16 ++ vdup.8 d2, r12 ++ orr r9, r9, r8, lsr #16 ++ orr r8, lr, r8, lsl #16 ++ vmov d1, r8, r9 ++ sub r1, r7, #128 ++ mov r5, #3 ++1: ++ vdup.8 d3, r6 ++ vmull.u8 q2, d0, d2 ++ subs r12, r12, r4 ++ vmlal.u8 q2, d1, d3 ++ itttt mi ++ addmi lr, r2, r1, asr #7 ++ bicmi lr, #1 ++ addmi r12, r12, #32 ++ vmovmi d0, r8, r9 ++ rsb r6, r12, #32 ++ itt mi ++ lslmi r9, r9, #16 ++ ldrhmi lr, [lr] ++ vdup.8 d2, r12 ++ vrshrn.u16 d4, q2, #5 ++ itttt mi ++ orrmi r9, r9, r8, lsr #16 ++ orrmi r8, lr, r8, lsl #16 ++ vmovmi d1, r8, r9 ++ addmi r1, r1, r7 ++ subs r5, r5, #1 ++ vst1.16 {d4}, [r0], r3 ++ bne 1b ++ ++ vdup.8 d3, r6 ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vrshrn.u16 d4, q2, #5 ++ vst1.16 {d4}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.8 d3, r6 ++ mov r5, #3 ++ lsr r8, #16 ++ vdup.8 d2, r12 ++ orr r8, r8, r9, lsl #16 ++ ldr r9, [r1, #6]! ++ vmov d1, r8, r9 ++1: ++ vmull.u8 q2, d0, d2 ++ subs r12, r4 ++ vmlal.u8 q2, d1, d3 ++ it mi ++ addmi r12, #32 ++ rsb r6, r12, #32 ++ itt mi ++ vmovmi d0, r8, r9 ++ lsrmi r8, #16 ++ vdup.8 d2, r12 ++ itt mi ++ orrmi r8, r8, r9, lsl #16 ++ ldrmi r9, [r1, #2]! ++ vrshrn.u16 d6, q2, #5 ++ it mi ++ vmovmi d1, r8, r9 ++ vdup.8 d3, r6 ++ subs r5, #1 ++ vst1.16 {d6}, [r0], r3 ++ bne 1b ++ ++ vmull.u8 q2, d0, d2 ++ vmlal.u8 q2, d1, d3 ++ vrshrn.u16 d6, q2, #5 ++ vst1.16 {d6}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_c_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_8_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r1, r2 @ save r2 - r1 unused by patch_down ++ ++ bl patch_h_down_c_4x4_8 ++ bl patch_h_down_c_4x4_8_continue ++ ++ add r2, r1, #4*2 @ restore r2, but 4 rows further down left ++ sub r0, #16 ++ mov r6, r4 ++ add r0, r0, r3, lsl #2 ++ ++ bl patch_h_down_c_4x4_8 ++ bl patch_h_down_c_4x4_8_continue ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ ++ push {r2} ++ bl patch_h_up_c_4x4_8 ++ bl patch_h_up_c_4x4_8_continue ++ pop {r2} ++ ++ sub r0, #16 ++ mov r10, #-128 ++ add r2, #8 ++ add r0, r0, r3, lsl #2 ++ sub r10, r10, r7, lsl #2 ++ ++ bl patch_h_up_c_4x4_8 ++ bl patch_h_up_c_4x4_8_continue ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.8 {q9}, [r1] ++ sub r1, r2, #2 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ vdup.8 d6, r6 ++ vext.8 q8, q9, q9, #14 ++ sub r8, r7, #128 ++ vld1.16 {d16[0]}, [r1] ++ vdup.8 d7, r12 ++ mov r5, #7 ++1: ++ subs r12, r4 ++ vmull.u8 q0, d18, d7 ++ it cc ++ asrcc r1, r8, #8 ++ vmlal.u8 q0, d16, d6 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d19, d7 ++ it cc ++ addcc r1, r2, r1, lsl #1 ++ vmlal.u8 q1, d17, d6 ++ rsb r6, r12, #32 ++ vext.8 q10, q8, q8, #14 ++ sub r5, #1 ++ vld1.16 {d20[0]}, [r1] ++ it cc ++ addcc r8, r7 ++ vmov q11, q8 ++ teq r5, #0 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ subs r12, r4 ++ vmull.u8 q0, d22, d7 ++ it cc ++ asrcc r1, r8, #8 ++ vmlal.u8 q0, d20, d6 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d23, d7 ++ it cc ++ addcc r1, r2, r1, lsl #1 ++ vmlal.u8 q1, d21, d6 ++ rsb r6, r12, #32 ++ vext.8 q8, q10, q10, #14 ++ sub r5, #1 ++ vld1.16 {d16[0]}, [r1] ++ it cc ++ addcc r8, r7 ++ vmov q9, q10 ++ teq r5, #0 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmull.u8 q0, d22, d7 ++ vmlal.u8 q0, d20, d6 ++ vmull.u8 q1, d23, d7 ++ vmlal.u8 q1, d21, d6 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmull.u8 q0, d18, d7 ++ vmlal.u8 q0, d16, d6 ++ vmull.u8 q1, d19, d7 ++ vmlal.u8 q1, d17, d6 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ vld1.8 {q9}, [r1]! ++ rsb r12, r6, #32 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vext.8 q8, q9, q9, #2 ++ vld1.16 {d17[3]}, [r1]! ++ mov r5, #7 ++1: ++ vmull.u8 q0, d16, d6 ++ subs r12, r4 ++ vmlal.u8 q0, d18, d7 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d17, d6 ++ rsb r6, r12, #32 ++ vmlal.u8 q1, d19, d7 ++ sub r5, #1 ++ vext.8 q10, q8, q8, #2 ++ teq r5, #0 ++ vld1.16 {d21[3]}, [r1] ++ it cc ++ addcc r1, #2 ++ vmov q11, q8 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmull.u8 q0, d20, d6 ++ subs r12, r4 ++ vmlal.u8 q0, d22, d7 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q1, d21, d6 ++ rsb r6, r12, #32 ++ vmlal.u8 q1, d23, d7 ++ sub r5, #1 ++ vext.8 q8, q10, q10, #2 ++ teq r5, #0 ++ vld1.16 {d17[3]}, [r1] ++ it cc ++ addcc r1, #2 ++ vmov q9, q10 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vdup.8 d6, r6 ++ vdup.8 d7, r12 ++ vst1.8 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmull.u8 q0, d20, d6 ++ vmlal.u8 q0, d22, d7 ++ vmull.u8 q1, d21, d6 ++ vmlal.u8 q1, d23, d7 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmull.u8 q0, d16, d6 ++ vmlal.u8 q0, d18, d7 ++ vmull.u8 q1, d17, d6 ++ vmlal.u8 q1, d19, d7 ++ vrshrn.u16 d0, q0, #5 ++ vrshrn.u16 d1, q1, #5 ++ vst1.8 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_c_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_16_neon_8, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r10, #4 ++ mov r1, r2 ++1: ++ bl patch_h_down_c_4x4_8 ++ bl patch_h_down_c_4x4_8_continue ++ bl patch_h_down_c_4x4_8_continue ++ bl patch_h_down_c_4x4_8_continue ++ ++ add r2, r1, #4*2 @ restore r2, but 4 rows further down left ++ add r1, r1, #4*2 ++ mov r6, r4 ++ sub r0, #32 ++ subs r10, #1 ++ add r0, r0, r3, lsl #2 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ vmov.i8 d6, #1<<2 ++1: ++ push {r2, r10} ++ bl patch_h_up_c_4x4_8 ++ bl patch_h_up_c_4x4_8_continue ++ bl patch_h_up_c_4x4_8_continue ++ bl patch_h_up_c_4x4_8_continue ++ pop {r2, r10} ++ ++ vmov r8, s12 ++ sub r0, #32 ++ add r2, #8 ++ add r0, r0, r3, lsl #2 ++ sub r10, r10, r7, lsl #2 ++ vshr.u8 d6, #1 ++ teq r8, #0 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.8 {q0-q1}, [r1] ++ sub r9, r2, #2 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ mov r5, #16 ++1: ++ vld1.16 {d17[3]}, [r9] ++ add r8, r7 ++ vmov q2, q0 ++ vmov q3, q1 ++ asr r9, r8, #8 ++ vext.8 q1, q0, q1, #14 ++ add r9, r2, r9, lsl #1 ++ vext.8 q0, q8, q0, #14 ++2: ++ vmull.u8 q10, d4, d19 ++ subs r12, r4 ++ vmlal.u8 q10, d0, d18 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q11, d5, d19 ++ rsb r6, r12, #32 ++ vmlal.u8 q11, d1, d18 ++ sub r5, #1 ++ vmull.u8 q12, d6, d19 ++ teq r5, #0 ++ vmlal.u8 q12, d2, d18 ++ vmull.u8 q13, d7, d19 ++ vmlal.u8 q13, d3, d18 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ vrshrn.u16 d20, q10, #5 ++ vrshrn.u16 d21, q11, #5 ++ vrshrn.u16 d22, q12, #5 ++ vrshrn.u16 d23, q13, #5 ++ vst1.8 {q10-q11}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.8 {q0-q1}, [r1]! ++ rsb r12, r6, #32 ++ vld1.16 {d16[0]}, [r5] ++ mov r5, #16 ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++1: ++ vmov q2, q0 ++ add r1, #2 ++ vmov q3, q1 ++ vext.8 q0, q0, q1, #2 ++ vext.8 q1, q1, q8, #2 ++2: ++ vmull.u8 q10, d0, d18 ++ subs r12, r4 ++ vmlal.u8 q10, d4, d19 ++ it cc ++ addcc r12, #32 ++ vmull.u8 q11, d1, d18 ++ rsb r6, r12, #32 ++ vmlal.u8 q11, d5, d19 ++ sub r5, #1 ++ vmull.u8 q12, d2, d18 ++ teq r5, #0 ++ vmlal.u8 q12, d6, d19 ++ vmull.u8 q13, d3, d18 ++ vmlal.u8 q13, d7, d19 ++ vld1.16 {d16[0]}, [r1] ++ vdup.8 d18, r6 ++ vdup.8 d19, r12 ++ vrshrn.u16 d20, q10, #5 ++ vrshrn.u16 d21, q11, #5 ++ vrshrn.u16 d22, q12, #5 ++ vrshrn.u16 d23, q13, #5 ++ vst1.8 {q10-q11}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++@------------------------------------------------------------------------------ ++@ Data ++ ++ .text ++ .balign 64 ++angle_2: ++ .byte 32 ++ .byte 26, 21, 17, 13, 9, 5, 2, 0 ++ @ Sign inverted from standards table ++ .byte 2, 5, 9, 13, 17, 21, 26, 32 ++ .byte 26, 21, 17, 13, 9, 5, 2, 0 ++ @ Standard sign ++ .byte 2, 5, 9, 13, 17, 21, 26, 32 ++ ++ .balign 2 ++ ++ @ Sign inverted from standards table ++inv_angle: ++ .short 4096, 1638, 910, 630, 482, 390, 315 ++ .short 256 ++ .short 315, 390, 482, 630, 910, 1638, 4096 ++ ++@------------------------------------------------------------------------------ ++@ ++@ 10 bit fns ++@ Should work for 9 & 11 bit as there is no actual bit-depth specific code ++@ but runs out of register width for 12+ bit ++ ++ .text ++ .balign 64 ++ ++patch_h_down_4x4_10: ++ ldrd r8, r9, [r2] @ Left ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.16 d3, r6 ++ lsr r8, #16 ++ vdup.16 d2, r12 ++ orr r8, r8, r9, lsl #16 ++ ldr r9, [r2, #6]! ++ vmov d1, r8, r9 ++ // drop through... ++patch_h_down_4x4_10_continue: ++ mov r5, #4 ++1: ++ subs r12, r4 ++ vmul.u16 d4, d0, d2 ++ it mi ++ addmi r12, #32 ++ vmla.u16 d4, d1, d3 ++ rsb r6, r12, #32 ++ vext.16 q8, q8, q9, #4 ++ it mi ++ lsrmi r7, r8, #16 ++ vmov d18, d19 ++ it mi ++ vmovmi d0, r8, r9 ++ vdup.16 d2, r12 ++ it mi ++ orrmi r8, r7, r9, lsl #16 ++ vrshr.u16 d19, d4, #5 ++ itt mi ++ ldrmi r9, [r2, #2]! ++ vmovmi d1, r8, r9 ++ subs r5, #1 ++ vdup.16 d3, r6 ++ bne 1b ++ // drop through... ++store_tran_4x4_10: ++ vzip.16 d16, d17 ++ add r6, r0, r3 ++ vzip.16 d18, d19 ++ lsl r3, #1 ++ vzip.32 q8, q9 ++ add r5, r0, r3 ++ vst1.16 {d16}, [r0]! ++ vst1.16 {d17}, [r6], r3 ++ vst1.16 {d18}, [r5] ++ asr r3, #1 ++ vst1.16 {d19}, [r6] ++ ++ bx lr ++ ++patch_h_up_4x4_10: ++ ldrd r8, r9, [r2] ++ rsb r6, r4, #32 ++ vmov d0, r8, r9 ++ vdup.16 d3, r4 ++ lsr r11, r8, #16 ++ vdup.16 d2, r6 ++ ldr r8, [r2, #-2]! ++ orr r9, r11, r9, lsl #16 ++ vmov d1, r8, r9 ++ mov r12, r4 ++ vmul.u16 d4, d0, d2 ++ vmla.u16 d4, d1, d3 ++patch_h_up_4x4_10_continue: ++ mov r5, #4 ++1: ++ add r12, r4 ++ cmp r12, #33 ++ it cs ++ addcs r10, r7 ++ mov r11, #0 ++ itt cs ++ subcs r12, #32 ++ tstcs r10, #1<<31 ++ rsb r6, r12, #32 ++ it eq ++ asreq r11, r10, #7 ++ it cs ++ vmovcs d0, r8, r9 ++ it eq ++ biceq r11, #1 ++ vdup.16 d2, r6 ++ it cs ++ lsrcs r6, r8, #16 ++ vdup.16 d3, r12 ++ vext.16 q8, q8, q9, #4 ++ itt cs ++ orrcs r9, r6, r9, lsl #16 ++ ldrhcs r11, [r1, r11] ++ vmov d18, d19 ++ it hi ++ ldrhhi r11, [r2, #-2]! ++ vrshr.u16 d19, d4, #5 ++ itt cs ++ orrcs r8, r11, r8, lsl #16 ++ vmovcs d1, r8, r9 ++ vmul.u16 d4, d0, d2 ++ subs r5, #1 ++ vmla.u16 d4, d1, d3 ++ bne 1b ++ ++ b store_tran_4x4_10 ++ ++ ++@ ff_hevc_rpi_pred_angular_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_4_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ bl patch_h_down_4x4_10 ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ bl patch_h_up_4x4_10 ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ ldrh lr, [r2, #-2] @ Top-left ++ ldrh r7, [r7] ++ vmov d0, r8, r9 ++ lsl r9, r9, #16 ++ vdup.16 d2, r12 ++ orr r9, r9, r8, lsr #16 ++ orr r8, lr, r8, lsl #16 ++ vmov d1, r8, r9 ++ sub r1, r7, #128 ++ mov r5, #3 ++1: ++ sel lr, lr, lr @ force pipeline 0 on Cortex-A53 ++ vdup.16 d3, r6 ++ vmul.u16 d4, d0, d2 ++ subs r12, r12, r4 ++ vmla.u16 d4, d1, d3 ++ itttt mi ++ addmi lr, r2, r1, asr #7 ++ bicmi lr, #1 ++ addmi r12, r12, #32 ++ vmovmi d0, r8, r9 ++ rsb r6, r12, #32 ++ itt mi ++ lslmi r9, r9, #16 ++ ldrhmi lr, [lr] ++ vdup.16 d2, r12 ++ vrshr.u16 d4, d4, #5 ++ itttt mi ++ orrmi r9, r9, r8, lsr #16 ++ orrmi r8, lr, r8, lsl #16 ++ vmovmi d1, r8, r9 ++ addmi r1, r1, r7 ++ subs r5, r5, #1 ++ vst1.16 {d4}, [r0], r3 ++ bne 1b ++ ++ vdup.16 d3, r6 ++ nop @ force next insn into pipeline 0 to enable ++ vmul.u16 d4, d0, d2 @ vmla to execute back-to-back on Cortex-A53 ++ vmla.u16 d4, d1, d3 ++ vrshr.u16 d4, d4, #5 ++ vst1.16 {d4}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ ldrd r8, r9, [r1] @ Top ++ rsb r12, r6, #32 ++ vmov d0, r8, r9 ++ vdup.16 d3, r6 ++ lsr r8, #16 ++ vdup.16 d2, r12 ++ orr r8, r8, r9, lsl #16 ++ ldr r9, [r1, #6]! ++ vmov d1, r8, r9 ++ mov r5, #3 ++1: ++ vmul.u16 d4, d0, d2 ++ subs r12, r4 ++ vmla.u16 d4, d1, d3 ++ it mi ++ addmi r12, #32 ++ rsb r6, r12, #32 ++ itt mi ++ vmovmi d0, r8, r9 ++ lsrmi r8, #16 ++ vdup.16 d2, r12 ++ itt mi ++ orrmi r8, r8, r9, lsl #16 ++ ldrmi r9, [r1, #2]! ++ vrshr.u16 d4, d4, #5 ++ it mi ++ vmovmi d1, r8, r9 ++ vdup.16 d3, r6 ++ subs r5, #1 ++ vst1.16 {d4}, [r0], r3 ++ bne 1b ++ ++ vmul.u16 d4, d0, d2 ++ vmla.u16 d4, d1, d3 ++ vrshr.u16 d4, d4, #5 ++ vst1.16 {d4}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_8_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r1, r2 @ save r2 - r1 unused by patch_down ++ ++ bl patch_h_down_4x4_10 ++ bl patch_h_down_4x4_10_continue ++ ++ add r2, r1, #4*2 @ restore r2, but 4 rows further down left ++ sub r0, #16 ++ mov r6, r4 ++ add r0, r0, r3, lsl #2 ++ ++ bl patch_h_down_4x4_10 ++ bl patch_h_down_4x4_10_continue ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ ++ push {r2} ++ bl patch_h_up_4x4_10 ++ bl patch_h_up_4x4_10_continue ++ pop {r2} ++ ++ sub r0, #16 ++ mov r10, #-128 ++ add r2, #8 ++ add r0, r0, r3, lsl #2 ++ sub r10, r10, r7, lsl #2 ++ ++ bl patch_h_up_4x4_10 ++ bl patch_h_up_4x4_10_continue ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.16 {q9}, [r1] ++ sub r1, r2, #2 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ vdup.16 q2, r6 ++ vext.16 q8, q9, q9, #7 ++ sub r8, r7, #128 ++ vld1.16 {d16[0]}, [r1] ++ vdup.16 q3, r12 ++ mov r5, #7 ++1: ++ vmul.u16 q0, q9, q3 ++ subs r12, r4 ++ vmla.u16 q0, q8, q2 ++ ittt cc ++ asrcc r1, r8, #8 ++ addcc r12, #32 ++ addcc r1, r2, r1, lsl #1 ++ vext.16 q10, q8, q8, #7 ++ rsb r6, r12, #32 ++ vmov q11, q8 ++ sub r5, #1 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r8, r7 ++ vld1.16 {d20[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmul.u16 q0, q11, q3 ++ subs r12, r4 ++ vmla.u16 q0, q10, q2 ++ ittt cc ++ asrcc r1, r8, #8 ++ addcc r12, #32 ++ addcc r1, r2, r1, lsl #1 ++ vext.16 q8, q10, q10, #7 ++ rsb r6, r12, #32 ++ vmov q9, q10 ++ sub r5, #1 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r8, r7 ++ vld1.16 {d16[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmul.u16 q0, q11, q3 ++ vmla.u16 q0, q10, q2 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmul.u16 q0, q9, q3 ++ vmla.u16 q0, q8, q2 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ vld1.16 {q9}, [r1]! ++ rsb r12, r6, #32 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vext.16 q8, q9, q9, #1 ++ vld1.16 {d17[3]}, [r1]! ++ mov r5, #7 ++1: ++ vmul.u16 q0, q8, q2 ++ subs r12, r4 ++ vmla.u16 q0, q9, q3 ++ it cc ++ addcc r12, #32 ++ vext.16 q10, q8, q8, #1 ++ rsb r6, r12, #32 ++ vld1.16 {d21[3]}, [r1] ++ sub r5, #1 ++ vmov q11, q8 ++ teq r5, #0 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r1, #2 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmul.u16 q0, q10, q2 ++ subs r12, r4 ++ vmla.u16 q0, q11, q3 ++ it cc ++ addcc r12, #32 ++ vext.16 q8, q10, q10, #1 ++ rsb r6, r12, #32 ++ vld1.16 {d17[3]}, [r1] ++ sub r5, #1 ++ vmov q9, q10 ++ teq r5, #0 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r1, #2 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmul.u16 q0, q10, q2 ++ vmla.u16 q0, q11, q3 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++4: ++ bcc 3b ++5: ++ vmul.u16 q0, q8, q2 ++ vmla.u16 q0, q9, q3 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_16_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r10, #4 ++ mov r1, r2 ++1: ++ bl patch_h_down_4x4_10 ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ ++ add r2, r1, #4*2 @ restore r2, but 4 rows further down left ++ add r1, r1, #4*2 ++ mov r6, r4 ++ sub r0, #32 ++ subs r10, #1 ++ add r0, r0, r3, lsl #2 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r10, #-128 ++ vmov.i8 d6, #1<<2 ++1: ++ push {r2, r10} ++ bl patch_h_up_4x4_10 ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ pop {r2, r10} ++ ++ vmov r8, s12 ++ sub r0, #32 ++ add r2, #8 ++ add r0, r0, r3, lsl #2 ++ sub r10, r10, r7, lsl #2 ++ vshr.u8 d6, #1 ++ teq r8, #0 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.16 {q0-q1}, [r1] ++ sub r9, r2, #2 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ mov r5, #16 ++1: ++ vld1.16 {d17[3]}, [r9] ++ add r8, r7 ++ vmov q2, q0 ++ vmov q3, q1 ++ asr r9, r8, #8 ++ vext.16 q1, q0, q1, #7 ++ add r9, r2, r9, lsl #1 ++ vext.16 q0, q8, q0, #7 ++2: ++ vmul.u16 q11, q2, q10 ++ subs r12, r4 ++ vmla.u16 q11, q0, q9 ++ it cc ++ addcc r12, #32 ++ vmul.u16 q12, q3, q10 ++ rsb r6, r12, #32 ++ vmla.u16 q12, q1, q9 ++ sub r5, #1 ++ teq r5, #0 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ vrshr.u16 q11, q11, #5 ++ vrshr.u16 q12, q12, #5 ++ vst1.16 {q11-q12}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.16 {q0-q1}, [r1]! ++ rsb r12, r6, #32 ++ vld1.16 {d16[0]}, [r5] ++ mov r5, #16 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++1: ++ vmov q2, q0 ++ add r1, #2 ++ vmov q3, q1 ++ vext.16 q0, q0, q1, #1 ++ vext.16 q1, q1, q8, #1 ++2: ++ vmul.u16 q11, q0, q9 ++ subs r12, r4 ++ vmla.u16 q11, q2, q10 ++ it cc ++ addcc r12, #32 ++ vmul.u16 q12, q1, q9 ++ rsb r6, r12, #32 ++ vmla.u16 q12, q3, q10 ++ sub r5, #1 ++ vld1.16 {d16[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ vrshr.u16 q11, q11, #5 ++ vrshr.u16 q12, q12, #5 ++ vst1.16 {q11-q12}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_32_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_32_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r11, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #1 ++ vpush {d8} ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ add sp, #8 ++ mov r10, #8 ++ mov r1, r2 ++1: ++ bl patch_h_down_4x4_10 ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ bl patch_h_down_4x4_10_continue ++ ++ add r2, r1, #4*2 @ restore r2, but 4 rows further down left ++ add r1, r1, #4*2 ++ mov r6, r4 ++ sub r0, #64 ++ subs r10, #1 ++ add r0, r0, r3, lsl #2 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ add sp, #8 ++ ldrh r7, [r7] ++ mov r10, #-128 ++ vmov.i8 d6, #1<<6 ++1: ++ push {r2, r10} ++ bl patch_h_up_4x4_10 ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ bl patch_h_up_4x4_10_continue ++ pop {r2, r10} ++ ++ vmov r8, s12 ++ sub r0, #64 ++ add r2, #8 ++ add r0, r0, r3, lsl #2 ++ sub r10, r10, r7, lsl #2 ++ vshr.u8 d6, #1 ++ teq r8, #0 ++ bne 1b ++ ++ pop {r4-r11, pc} ++ ++@ Left of vertical - works down left ++18: ++ add r5, r1, #32 ++ vld1.16 {q1-q2}, [r1] ++ rsb r12, r6, r6, lsl #16 ++ vld1.16 {q3-q4}, [r5] ++ sub r9, r2, #2 ++ rsb r4, r12, #0 ++ rsb r12, r12, #32 << 16 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vmov d0, d9 ++ vmov s2, r12 ++ add r10, r0, #32 ++ mov r5, #32 ++1: ++ vld1.16 {d1[3]}, [r9] ++ add r8, r7 ++ vmov q11, q4 ++ vmov q10, q3 ++ asr r9, r8, #8 ++ vmov q9, q2 ++ add r9, r2, r9, lsl #1 ++ vmov q8, q1 ++ vext.16 q4, q3, q4, #7 ++ vext.16 q3, q2, q3, #7 ++ vext.16 q2, q1, q2, #7 ++ vext.16 q1, q0, q1, #7 ++2: ++ vmul.u16 q12, q8, d1[1] ++ adds r12, r4 ++ vmla.u16 q12, q1, d1[0] ++ it cc ++ addcc r12, #32 << 16 ++ vmul.u16 q13, q9, d1[1] ++ it cc ++ subcc r12, #32 ++ vmla.u16 q13, q2, d1[0] ++ sub r5, #1 ++ vmul.u16 q14, q10, d1[1] ++ teq r5, #0 ++ vmla.u16 q14, q3, d1[0] ++ vmul.u16 q15, q11, d1[1] ++ vmla.u16 q15, q4, d1[0] ++ vmov s2, r12 ++ vrshr.u16 q12, q12, #5 ++ vrshr.u16 q13, q13, #5 ++ vrshr.u16 q14, q14, #5 ++ vrshr.u16 q15, q15, #5 ++ vst1.16 {q12-q13}, [r0], r3 ++ vst1.16 {q14-q15}, [r10], r3 ++ bhi 2b ++ bne 1b ++ ++ vpop {d8} ++ vmov d9, d0 ++ pop {r4-r11, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.16 {q1-q2}, [r1] ++ rsb r12, r6, r6, lsl #16 ++ vld1.16 {q3-q4}, [r5] ++ add r1, r1, #64 ++ rsb r4, r12, #0 ++ rsb r12, r12, #32 << 16 ++ vmov d1, d9 ++ vmov s1, r12 ++ add r10, r0, #32 ++ mov r5, #32 ++1: ++ vld1.16 {d0[0]}, [r1]! ++ vmov q8, q1 ++ vmov q9, q2 ++ vmov q10, q3 ++ vmov q11, q4 ++ vext.16 q1, q1, q2, #1 ++ vext.16 q2, q2, q3, #1 ++ vext.16 q3, q3, q4, #1 ++ vext.16 q4, q4, q0, #1 ++2: ++ vmul.u16 q12, q1, d0[2] ++ adds r12, r4 ++ vmla.u16 q12, q8, d0[3] ++ it cc ++ addcc r12, #32 << 16 ++ vmul.u16 q13, q2, d0[2] ++ it cc ++ subcc r12, #32 ++ vmla.u16 q13, q9, d0[3] ++ sub r5, #1 ++ vmul.u16 q14, q3, d0[2] ++ teq r5, #0 ++ vmla.u16 q14, q10, d0[3] ++ vmul.u16 q15, q4, d0[2] ++ vmla.u16 q15, q11, d0[3] ++ vmov s1, r12 ++ vrshr.u16 q12, q12, #5 ++ vrshr.u16 q13, q13, #5 ++ vrshr.u16 q14, q14, #5 ++ vrshr.u16 q15, q15, #5 ++ vst1.16 {q12-q13}, [r0], r3 ++ vst1.16 {q14-q15}, [r10], r3 ++ bhi 2b ++ bne 1b ++ ++ vpop {d8} ++ vmov d9, d1 ++ pop {r4-r11, pc} ++ ++endfunc ++ ++ ++ ++@ Generate 4x4 chroma patch ++@ ++@ In (const) ++@ r1 Up ptr (_up only) ++@ r3 Out stride ++@ r4 Angle add ++@ r7 Inv angle (_up only) ++@ ++@ In/Out (updated) ++@ r0 Out pointer - on exit point to start of next patch horizontally (i.e. r0 + patch width) ++@ r2 Left ptr - updated ++@ r6 Angle frac (init to r4 + 32) ++@ r8 Inv angle accumulator ++@ q2 Cur Line - load before 1st call for down - set by _up ++@ q8 Cur Line - load before 1st call for up - set by _down ++@ ++@ Temps ++@ r5 Loop counter ++@ r12 ++@ d0, q1, q12-q15 ++ ++patch_h_down_c_4x4_10: ++ vld1.16 {q12}, [r2]! ++ rsb r12, r6, #32 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ mov r5, #4 ++1: ++ vmov q13, q12 ++ vext.16 q12, q12, q12, #2 ++ vld1.32 {d25[1]}, [r2]! ++patch_h_down_c_4x4_10_continue: ++2: ++ vmov q8, q9 ++ subs r12, r4 ++ vmul.u16 q0, q13, q3 ++ it cc ++ addcc r12, #32 ++ vmla.u16 q0, q12, q2 ++ rsb r6, r12, #32 ++ vmov q9, q10 ++ sub r5, #1 ++ vmov q10, q11 ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vrshr.u16 q11, q0, #5 ++ bhi 2b ++ bne 1b ++ ++ bcs 3f ++ vmov q13, q12 ++ vext.16 q12, q12, q12, #2 ++ vld1.32 {d25[1]}, [r2]! ++3: ++ ++store_tran_c_4x4_10: ++T add r6, r0, r3 ++ vzip.32 q8, q10 ++A add r6, r0, r3 ++T lsl r3, #1 ++ vzip.32 q9, q11 ++A add r5, r0, r3, lsl #1 ++T add r5, r0, r3 ++ vst2.32 {d16,d18}, [r0]! ++A lsl r3, #1 ++ vst2.32 {d17,d19}, [r6], r3 ++ asr r3, #1 ++ vst2.32 {d20,d22}, [r5] ++ mov r5, #4 ++ vst2.32 {d21,d23}, [r6] ++ bx lr ++ ++patch_h_up_c_4x4_10: ++ vld1.16 {q1}, [r2] ++ rsb r12, r6, #32 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ mov r5, #4 ++1: ++ adds r8, r7 ++ vmov q12, q1 ++ it mi ++ ldrmi r6, [r2, #-4]! ++ vext.16 q1, q1, q1, #6 ++ itt pl ++ asrpl r6, r8, #8 ++ ldrpl r6, [r1, r6, lsl #2] ++ vmov s4, r6 ++patch_h_up_c_4x4_10_continue: ++2: ++ vmov q8, q9 ++ subs r12, r4 ++ vmul.u16 q0, q12, q3 ++ it cc ++ addcc r12, #32 ++ vmla.u16 q0, q1, q2 ++ rsb r6, r12, #32 ++ vmov q9, q10 ++ sub r5, #1 ++ vmov q10, q11 ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vrshr.u16 q11, q0, #5 ++ bhi 2b ++ bne 1b ++ ++ bcs store_tran_c_4x4_10 ++ adds r8, r7 ++ vmov q12, q1 ++ it mi ++ ldrmi r6, [r2, #-4]! ++ vext.16 q1, q1, q1, #6 ++ itt pl ++ asrpl r6, r8, #8 ++ ldrpl r6, [r1, r6, lsl #2] ++ vmov s4, r6 ++ b store_tran_c_4x4_10 ++ ++ ++@ ff_hevc_rpi_pred_angular_c_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_4_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r8, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #2 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ bl patch_h_down_c_4x4_10 ++ pop {r4-r8, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r8, #-128 ++ sub r8, r7 ++ bl patch_h_up_c_4x4_10 ++ pop {r4-r8, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.16 {q9}, [r1] ++ sub r1, r2, #4 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ vdup.16 q2, r6 ++ vext.16 q8, q9, q9, #6 ++ sub r8, r7, #128 ++ vld1.32 {d16[0]}, [r1] ++ vdup.16 q3, r12 ++ mov r5, #3 ++1: ++ vmul.u16 q0, q9, q3 ++ subs r12, r4 ++ vmla.u16 q0, q8, q2 ++ ittt cc ++ asrcc r1, r8, #8 ++ addcc r12, #32 ++ addcc r1, r2, r1, lsl #2 ++ vext.16 q10, q8, q8, #6 ++ rsb r6, r12, #32 ++ vmov q11, q8 ++ sub r5, #1 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r8, r7 ++ vld1.32 {d20[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmul.u16 q0, q11, q3 ++ subs r12, r4 ++ vmla.u16 q0, q10, q2 ++ ittt cc ++ asrcc r1, r8, #8 ++ addcc r12, #32 ++ addcc r1, r2, r1, lsl #2 ++ vext.16 q8, q10, q10, #6 ++ rsb r6, r12, #32 ++ vmov q9, q10 ++ sub r5, #1 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r8, r7 ++ vld1.32 {d16[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmul.u16 q0, q11, q3 ++ vmla.u16 q0, q10, q2 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r8, pc} ++4: ++ bcc 3b ++5: ++ vmul.u16 q0, q9, q3 ++ vmla.u16 q0, q8, q2 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r8, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ vld1.16 {q9}, [r1]! ++ rsb r12, r6, #32 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vext.16 q8, q9, q9, #2 ++ vld1.32 {d17[1]}, [r1]! ++ mov r5, #3 ++1: ++ vmul.u16 q0, q8, q2 ++ subs r12, r4 ++ vmla.u16 q0, q9, q3 ++ it cc ++ addcc r12, #32 ++ vext.16 q10, q8, q8, #2 ++ rsb r6, r12, #32 ++ vld1.32 {d21[1]}, [r1] ++ sub r5, #1 ++ vmov q11, q8 ++ teq r5, #0 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r1, #4 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 1b ++ beq 4f ++2: ++ vmul.u16 q0, q10, q2 ++ subs r12, r4 ++ vmla.u16 q0, q11, q3 ++ it cc ++ addcc r12, #32 ++ vext.16 q8, q10, q10, #2 ++ rsb r6, r12, #32 ++ vld1.32 {d17[1]}, [r1] ++ sub r5, #1 ++ vmov q9, q10 ++ teq r5, #0 ++ vrshr.u16 q0, q0, #5 ++ it cc ++ addcc r1, #4 ++ vdup.16 q2, r6 ++ vdup.16 q3, r12 ++ vst1.16 {q0}, [r0], r3 ++ bhi 2b ++ bne 1b ++ bcc 5f ++3: ++ vmul.u16 q0, q10, q2 ++ vmla.u16 q0, q11, q3 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r8, pc} ++4: ++ bcc 3b ++5: ++ vmul.u16 q0, q8, q2 ++ vmla.u16 q0, q9, q3 ++ vrshr.u16 q0, q0, #5 ++ vst1.16 {q0}, [r0] ++ ++ pop {r4-r8, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_c_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_8_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r8, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #2 ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ mov r1, r2 @ save r2 - r1 unused by patch_down ++ ++ bl patch_h_down_c_4x4_10 ++ bl patch_h_down_c_4x4_10_continue ++ ++ add r2, r1, #4*4 @ restore r2, but 4 rows further down left ++ sub r0, #32 ++ mov r6, r4 ++ add r0, r0, r3, lsl #2 ++ ++ bl patch_h_down_c_4x4_10 ++ bl patch_h_down_c_4x4_10_continue ++ ++ pop {r4-r8, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ ldrh r7, [r7] ++ mov r8, #-128 ++ sub r8, r7 ++ ++ push {r2, r8} ++ bl patch_h_up_c_4x4_10 ++ bl patch_h_up_c_4x4_10_continue ++ pop {r2, r8} ++ ++ sub r0, #32 ++ mov r6, r4 ++ add r2, #16 ++ sub r8, r8, r7, lsl #2 ++ add r0, r0, r3, lsl #2 ++ ++ bl patch_h_up_c_4x4_10 ++ bl patch_h_up_c_4x4_10_continue ++ ++ pop {r4-r8, pc} ++ ++@ Left of vertical - works down left ++18: ++ vld1.16 {q0-q1}, [r1] ++ sub r9, r2, #4 ++ rsb r12, r6, #32 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ mov r5, #8 ++1: ++ vld1.32 {d17[1]}, [r9] ++ add r8, r7 ++ vmov q2, q0 ++ vmov q3, q1 ++ asr r9, r8, #8 ++ vext.16 q1, q0, q1, #6 ++ add r9, r2, r9, lsl #2 ++ vext.16 q0, q8, q0, #6 ++2: ++ vmul.u16 q11, q2, q10 ++ subs r12, r4 ++ vmla.u16 q11, q0, q9 ++ it cc ++ addcc r12, #32 ++ vmul.u16 q12, q3, q10 ++ rsb r6, r12, #32 ++ vmla.u16 q12, q1, q9 ++ sub r5, #1 ++ teq r5, #0 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ vrshr.u16 q11, q11, #5 ++ vrshr.u16 q12, q12, #5 ++ vst1.16 {q11-q12}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r8, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.16 {q0-q1}, [r1]! ++ rsb r12, r6, #32 ++ vld1.32 {d16[0]}, [r5] ++ mov r5, #8 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++1: ++ vmov q2, q0 ++ add r1, #4 ++ vmov q3, q1 ++ vext.16 q0, q0, q1, #2 ++ vext.16 q1, q1, q8, #2 ++2: ++ vmul.u16 q11, q0, q9 ++ subs r12, r4 ++ vmla.u16 q11, q2, q10 ++ it cc ++ addcc r12, #32 ++ vmul.u16 q12, q1, q9 ++ rsb r6, r12, #32 ++ vmla.u16 q12, q3, q10 ++ sub r5, #1 ++ vld1.32 {d16[0]}, [r1] ++ teq r5, #0 ++ vdup.16 q9, r6 ++ vdup.16 q10, r12 ++ vrshr.u16 q11, q11, #5 ++ vrshr.u16 q12, q12, #5 ++ vst1.16 {q11-q12}, [r0], r3 ++ bhi 2b ++ bne 1b ++ ++ pop {r4-r8, pc} ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_angular_c_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride [r3] ++@ unsigned int mode [sp, #0] 2..34 ++ ++function ff_hevc_rpi_pred_angular_c_16_neon_10, export=1 ++ ldr r12, [sp] ++ push {r4-r10, lr} ++ ADRT r4, angle_2 - 2 ++ ADRT r7, inv_angle - 11*2 ++ add r7, r7, r12, lsl #1 ++ lsl r3, #2 ++ vpush {d8} ++ ldrsb r6, [r4, r12] ++ cmp r12, #26 ++ ldrsb r4, [r4, r12] ++ bge 26f ++ cmp r12, #18 ++ bge 18f ++ cmp r12, #10 ++ bge 10f ++ ++@ Down of Horizontal - works down left ++ add sp, #8 ++ mov r10, #4 ++ mov r1, r2 ++1: ++ bl patch_h_down_c_4x4_10 ++ bl patch_h_down_c_4x4_10_continue ++ bl patch_h_down_c_4x4_10_continue ++ bl patch_h_down_c_4x4_10_continue ++ ++ add r2, r1, #4*4 @ restore r2, but 4 rows further down left ++ add r1, r1, #4*4 ++ mov r6, r4 ++ sub r0, #64 ++ subs r10, #1 ++ add r0, r0, r3, lsl #2 ++ bne 1b ++ ++ pop {r4-r10, pc} ++ ++@ Up of Horizontal - works down up ++10: ++ add sp, #8 ++ mov r10, #4 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ sub r8, r7 ++2: ++ push {r2, r8} ++ bl patch_h_up_c_4x4_10 ++ bl patch_h_up_c_4x4_10_continue ++ bl patch_h_up_c_4x4_10_continue ++ bl patch_h_up_c_4x4_10_continue ++ pop {r2, r8} ++ ++ sub r0, #64 ++ mov r6, r4 ++ add r2, #16 ++ sub r8, r8, r7, lsl #2 ++ add r0, r0, r3, lsl #2 ++ subs r10, #1 ++ bne 2b ++ ++ pop {r4-r10, pc} ++ ++@ Left of vertical - works down left ++18: ++ add r5, r1, #32 ++ vld1.16 {q1-q2}, [r1] ++ rsb r12, r6, r6, lsl #16 ++ vld1.16 {q3-q4}, [r5] ++ sub r9, r2, #4 ++ rsb r4, r12, #0 ++ rsb r12, r12, #32 << 16 ++ ldrh r7, [r7] ++ mov r8, #-128 ++ vmov d0, d9 ++ vmov s2, r12 ++ add r10, r0, #32 ++ mov r5, #16 ++1: ++ vld1.32 {d1[1]}, [r9] ++ add r8, r7 ++ vmov q11, q4 ++ vmov q10, q3 ++ asr r9, r8, #8 ++ vmov q9, q2 ++ add r9, r2, r9, lsl #2 ++ vmov q8, q1 ++ vext.16 q4, q3, q4, #6 ++ vext.16 q3, q2, q3, #6 ++ vext.16 q2, q1, q2, #6 ++ vext.16 q1, q0, q1, #6 ++2: ++ vmul.u16 q12, q8, d1[1] ++ adds r12, r4 ++ vmla.u16 q12, q1, d1[0] ++ it cc ++ addcc r12, #32 << 16 ++ vmul.u16 q13, q9, d1[1] ++ it cc ++ subcc r12, #32 ++ vmla.u16 q13, q2, d1[0] ++ sub r5, #1 ++ vmul.u16 q14, q10, d1[1] ++ teq r5, #0 ++ vmla.u16 q14, q3, d1[0] ++ vmul.u16 q15, q11, d1[1] ++ vmla.u16 q15, q4, d1[0] ++ vmov s2, r12 ++ vrshr.u16 q12, q12, #5 ++ vrshr.u16 q13, q13, #5 ++ vrshr.u16 q14, q14, #5 ++ vrshr.u16 q15, q15, #5 ++ vst1.16 {q12-q13}, [r0], r3 ++ vst1.16 {q14-q15}, [r10], r3 ++ bhi 2b ++ bne 1b ++ ++ vpop {d8} ++ vmov d9, d0 ++ pop {r4-r10, pc} ++ ++@ Right of vertical - works along top - left unused ++26: ++ add r5, r1, #32 ++ vld1.16 {q1-q2}, [r1] ++ rsb r12, r6, r6, lsl #16 ++ vld1.16 {q3-q4}, [r5] ++ add r1, r1, #64 ++ rsb r4, r12, #0 ++ rsb r12, r12, #32 << 16 ++ vmov d1, d9 ++ vmov s1, r12 ++ add r10, r0, #32 ++ mov r5, #16 ++1: ++ vld1.32 {d0[0]}, [r1]! ++ vmov q8, q1 ++ vmov q9, q2 ++ vmov q10, q3 ++ vmov q11, q4 ++ vext.16 q1, q1, q2, #2 ++ vext.16 q2, q2, q3, #2 ++ vext.16 q3, q3, q4, #2 ++ vext.16 q4, q4, q0, #2 ++2: ++ vmul.u16 q12, q1, d0[2] ++ adds r12, r4 ++ vmla.u16 q12, q8, d0[3] ++ it cc ++ addcc r12, #32 << 16 ++ vmul.u16 q13, q2, d0[2] ++ it cc ++ subcc r12, #32 ++ vmla.u16 q13, q9, d0[3] ++ sub r5, #1 ++ vmul.u16 q14, q3, d0[2] ++ teq r5, #0 ++ vmla.u16 q14, q10, d0[3] ++ vmul.u16 q15, q4, d0[2] ++ vmla.u16 q15, q11, d0[3] ++ vmov s1, r12 ++ vrshr.u16 q12, q12, #5 ++ vrshr.u16 q13, q13, #5 ++ vrshr.u16 q14, q14, #5 ++ vrshr.u16 q15, q15, #5 ++ vst1.16 {q12-q13}, [r0], r3 ++ vst1.16 {q14-q15}, [r10], r3 ++ bhi 2b ++ bne 1b ++ ++ vpop {d8} ++ vmov d9, d1 ++ pop {r4-r10, pc} ++ ++endfunc +diff --git a/libavcodec/arm/rpi_hevcpred_intra_dc_neon.S b/libavcodec/arm/rpi_hevcpred_intra_dc_neon.S +new file mode 100644 +index 0000000000..df8c1c25b9 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_intra_dc_neon.S +@@ -0,0 +1,705 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++ ++@ ff_hevc_rpi_pred_dc_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_4_neon_8, export=1 ++ ++ @ Average the els of top & left ++ ldr r2, [r2] ++ vld1.32 {d0[0]}, [r1] ++ mov r1, #2 ++ vmov s1, r2 ++ vmov s2, r2 ++ vmov.i16 q2, #3 ++ add r2, r0, r3 ++ vaddl.u8 q1, d0, d1 @ d2[0] = top[0] + left[0] ++ lsl r3, #1 ++ vmovl.u8 q0, d0 ++ vmov.i64 d7, #0xffff ++ vmov.16 d4[0], r1 @ 2, 3, 3, 3... ++ vpadd.i16 d6, d2, d2 @ 2 (top & bottom of vector the same) ++ vbit d0, d2, d7 @ q0 = top[0]+left[0], top[1..3], left[0..3] ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ top_line[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vmov.i64 d7, #0xff ++ vpadd.i16 d6, d6 @ 1 (all the same) ++ vrshr.u16 d6, #3 ++ vmla.i16 q0, q2, d6[0] ++ vdup.8 d6, d6[0] ++ vrshrn.i16 d0, q0, #2 ++ ++ @ Store top line ++ vst1.32 {d0[0]}, [r0], r3 ++ ++ @ Store the rest ++ vshr.u64 d1, d0, #5*8 ++ vshr.u64 d2, d0, #6*8 ++ vshr.u64 d3, d0, #7*8 ++ vbif d1, d6, d7 ++ vbif d2, d6, d7 ++ vst1.32 {d1[0]}, [r2], r3 ++ vbif d3, d6, d7 ++ vst1.32 {d2[0]}, [r0] ++ vst1.32 {d3[0]}, [r2] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_c_4_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {d0}, [r1] ++ vld1.8 {d1}, [r2] ++A add r2, r0, r3, lsl #1 ++A lsl r3, #2 ++T lsl r3, #1 ++T add r2, r0, r3 ++T lsl r3, #1 ++ vaddl.u8 q0, d0, d1 ++ vadd.i16 d0, d1 @ d0 has 2 val pairs ++ vpadd.i32 d2, d0, d0 @ This adds U & V separately ++ vpadd.i32 d3, d0, d0 ++ vrshrn.u16 d0, q1, #3 ++ ++ @ Store ++ vst1.8 {d0}, [r0], r3 ++ vst1.8 {d0}, [r2], r3 ++ vst1.8 {d0}, [r0] ++ vst1.8 {d0}, [r2] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_8_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {d0}, [r1] ++ mov r1, #2 ++ vld1.8 {d16}, [r2] ++ vmov.i16 q2, #3 ++ vmov.i64 d7, #0xffff ++ vaddl.u8 q1, d0, d16 @ d2[0] = top[0] + left[0] ++ vmovl.u8 q0, d0 ++ vadd.i16 d6, d2, d3 @ d6 has 4 vals ++ vmov.16 d4[0], r1 @ 2, 3, 3, 3... ++ vbit d0, d2, d7 @ q0 = top[0]+left[0], top[1..7] ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ top_line[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vmov.i64 d7, #0xff ++ vmovl.u8 q1, d16 ++ vpadd.i16 d6, d6 @ 2 (top & bottom of vector the same) ++ vpadd.i16 d6, d6 @ 1 (all the same) ++ vrshr.u16 d6, #4 ++ vmla.i16 q1, q2, d6[0] ++ vmla.i16 q0, q2, d6[0] ++ vdup.8 d6, d6[0] ++ vrshrn.i16 d2, q1, #2 ++ vrshrn.i16 d0, q0, #2 ++ ++ @ Store top line ++ vst1.8 {d0}, [r0], r3 ++ ++ @ Store the rest ++ vshr.u64 d2, #8 ++ vbit d6, d2, d7 ++ vshr.u64 d2, #8 ++ vst1.8 {d6}, [r0], r3 ++ mov r1, #6 ++1: ++ vbit d6, d2, d7 ++ vshr.u64 d2, #8 ++ vst1.8 {d6}, [r0], r3 ++ subs r1, #2 ++ vbit d6, d2, d7 ++ vshr.u64 d2, #8 ++ vst1.8 {d6}, [r0], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_c_8_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {q0}, [r1] ++ mov r1, #8 ++ vld1.8 {q1}, [r2] ++T lsl r3, #1 ++ vaddl.u8 q0, d0, d1 ++A add r2, r0, r3, lsl #1 ++A lsl r3, #2 ++T add r2, r0, r3 ++T lsl r3, #1 ++ vaddl.u8 q1, d2, d3 ++ vadd.i16 q1, q0 ++ vadd.i16 d3, d2 @ d3 has 2 val pairs ++ vpadd.i32 d2, d3, d3 @ This add U & V separately ++ vpadd.i32 d3, d3, d3 ++ vrshrn.u16 d0, q1, #4 ++ vrshrn.u16 d1, q1, #4 ++ ++ @ Store ++1: ++ vst1.8 {q0}, [r0], r3 ++ subs r1, #4 ++ vst1.8 {q0}, [r2], r3 ++ vst1.8 {q0}, [r0], r3 ++ vst1.8 {q0}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_16_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {q8}, [r1] ++ mov r1, #2 ++ vld1.8 {q9}, [r2] ++ vaddl.u8 q10, d16, d17 ++ vaddl.u8 q11, d16, d18 ++ vaddl.u8 q0, d18, d19 ++ vmov.i16 q1, #3 ++ vadd.i16 q10, q0 ++ vmovl.u8 q0, d18 ++ vadd.i16 d20, d21 ++ vmov.i16 d2[0], r1 @ 2, 3, 3, 3... ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ top_line[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vmovl.u8 q2, d16 ++ vmovl.u8 q9, d19 ++ vpadd.i16 d20, d20 @ 2 (top & bottom of vector the same) ++ vmov.i64 d7, #0xffff ++ vmovl.u8 q8, d17 ++ vbit d4, d22, d7 @ q2 = top[0]+left[0], top[1..7] ++ vmov.i64 d7, #0xff ++ vpadd.i16 d20, d20 @ 1 (all the same) ++ vrshr.u16 d21, d20, #5 ++ vrshr.u16 d20, d20, #5 ++ vmla.i16 q0, q10, d2[1] ++ vmla.i16 q9, q10, d2[1] ++ vmla.i16 q2, q10, q1 ++ vmla.i16 q8, q10, d2[1] ++ vdup.8 q1, d20[0] ++ vrshrn.i16 d0, q0, #2 ++ vrshrn.i16 d1, q9, #2 ++ vrshrn.i16 d4, q2, #2 ++ vrshrn.i16 d5, q8, #2 ++ vext.8 q0, q0, q0, #1 ++ ++ @ Store top line ++ vst1.8 {q2}, [r0], r3 ++ ++ @ Store the rest ++ mov r1, #15 ++1: ++ vbit d2, d0, d7 ++ vext.8 q0, q0, q0, #1 ++ subs r1, #1 ++ vst1.8 {q1}, [r0], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_c_16_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {q0-q1}, [r1] ++ mov r1, #16 ++ vld1.8 {q2-q3}, [r2] ++T lsl r3, #1 ++ vaddl.u8 q0, d0, d1 ++A add r2, r0, r3, lsl #1 ++T add r2, r0, r3 ++ vaddl.u8 q1, d2, d3 ++A lsl r3, #2 ++T lsl r3, #1 ++ vaddl.u8 q2, d4, d5 ++ vaddl.u8 q3, d6, d7 ++ vadd.i16 q0, q1 ++ vadd.i16 q2, q3 ++ vadd.i16 q0, q2 ++ vadd.i16 d0, d1 @ d0 has 2 val pairs ++ vpadd.i32 d4, d0, d0 @ This adds U & V separately ++ vpadd.i32 d5, d0, d0 ++ vrshrn.u16 d0, q2, #5 ++ vrshrn.u16 d1, q2, #5 ++ vrshrn.u16 d2, q2, #5 ++ vrshrn.u16 d3, q2, #5 ++ ++ @ Store ++1: ++ vst1.8 {q0-q1}, [r0], r3 ++ subs r1, #2 ++ vst1.8 {q0-q1}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_32_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_32_neon_8, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {q0-q1}, [r1] ++ mov r1, #32 ++ vld1.8 {q2-q3}, [r2] ++ add r2, r0, r3 ++ vaddl.u8 q0, d0, d1 ++ lsl r3, #1 ++ vaddl.u8 q1, d2, d3 ++ vaddl.u8 q2, d4, d5 ++ vaddl.u8 q3, d6, d7 ++ vadd.i16 q0, q1 ++ vadd.i16 q2, q3 ++ vadd.i16 q0, q2 ++ vadd.i16 d0, d1 @ d0 has 4 vals ++ vpadd.i16 d0, d0 @ 2 (top & bottom the same) ++ vpadd.i16 d4, d0, d0 @ 1 (all the same) ++ vpadd.i16 d5, d0, d0 ++ vrshrn.u16 d0, q2, #6 ++ vrshrn.u16 d1, q2, #6 ++ vrshrn.u16 d2, q2, #6 ++ vrshrn.u16 d3, q2, #6 ++ ++ @ Store ++1: ++ vst1.8 {q0-q1}, [r0], r3 ++ subs r1, #2 ++ vst1.8 {q0-q1}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ----------------------------------------------------------------------------- ++@ ++@ 10 Bit versions ++@ ++@ There is no actual bit depth dependency in this code except that our ++@ intermediate results will overflow the 16 bits they are stored in ++@ All there functions are good to 10 bits - with the worst case being ++@ in dc_32 where we use all 16 bits. ++ ++ ++@ ff_hevc_rpi_pred_dc_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_4_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vld1.16 {d0}, [r1] ++ mov r1, #2 ++ vld1.16 {d1}, [r2] ++T lsl r3, #1 ++ vmov.i16 q2, #3 ++A add r2, r0, r3, lsl #1 ++T add r2, r0, r3 ++ vadd.u16 d2, d0, d1 @ d2[0] = top[0] + left[0] ++A lsl r3, #2 ++T lsl r3, #1 ++ vmov.16 d4[0], r1 @ 2, 3, 3, 3... ++ vmov.i64 d7, #0xffff ++ vbit d0, d2, d7 @ q0 = top[0]+left[0], top[1..3], left[0..3] ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ top_line[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vpadd.i16 d6, d2, d2 @ 2 (top & bottom of vector the same) ++ vpadd.i16 d6, d6 @ 1 (all the same) ++ vrshr.u16 d6, #3 ++ vmla.i16 q0, q2, d6[0] ++ vrshr.u16 q0, #2 ++ ++ @ Store top line ++ vst1.16 {d0}, [r0], r3 ++ ++ @ Store the rest ++ vshr.u64 d3, d1, #1*16 ++ vshr.u64 d4, d1, #2*16 ++ vshr.u64 d5, d1, #3*16 ++ vbif d3, d6, d7 ++ vbif d4, d6, d7 ++ vst1.16 {d3}, [r2], r3 ++ vbif d5, d6, d7 ++ vst1.16 {d4}, [r0] ++ vst1.16 {d5}, [r2] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] (In pels - needs * 4) ++ ++function ff_hevc_rpi_pred_dc_c_4_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vld1.8 {q0}, [r1] ++ vld1.8 {q1}, [r2] ++A add r2, r0, r3, lsl #2 ++A lsl r3, #3 ++T lsl r3, #2 ++T add r2, r0, r3 ++T lsl r3, #1 ++ vadd.i16 q0, q1 ++ vadd.i16 d0, d1 @ d0 has 2 val pairs ++ vpadd.i32 d2, d0, d0 @ This adds U & V separately ++ vpadd.i32 d3, d0, d0 ++ vrshr.u16 q0, q1, #3 ++ ++ vst1.16 {q0}, [r0], r3 ++ vst1.16 {q0}, [r2], r3 ++ vst1.16 {q0}, [r0] ++ vst1.16 {q0}, [r2] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_8_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vld1.16 {q0}, [r1] ++ mov r1, #2 ++ vld1.16 {q8}, [r2] ++T lsl r3, #1 ++ vmov.i16 q2, #3 ++A add r2, r0, r3, lsl #1 ++T add r2, r0, r3 ++ vadd.i16 q1, q0, q8 @ q1[0] = top[0] + left[0] ++A lsl r3, #2 ++T lsl r3, #1 ++ vmov.i64 d7, #0xffff ++ vmov.16 d4[0], r1 @ 2, 3, 3, 3... ++ vadd.i16 d6, d2, d3 @ d6 has 4 vals ++ vbit d0, d2, d7 @ q0 = top[0]+left[0], top[1..7] ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ top_line[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vpadd.i16 d6, d6 @ 2 (top & bottom of vector the same) ++ vpadd.i16 d6, d6 @ 1 (all the same) ++ vrshr.u16 d6, #4 ++ vmla.i16 q8, q2, d6[0] ++ vmla.i16 q0, q2, d6[0] ++ vdup.16 q2, d6[0] ++ vdup.16 q9, d6[0] ++ vrshr.u16 q8, q8, #2 ++ vrshr.u16 q0, q0, #2 ++ vext.16 q1, q8, q8, #1 ++ ++ @ Store top line ++ vst1.16 {q0}, [r0], r3 ++ ++ @ Store the rest ++ vbit d18, d2, d7 ++ vst1.16 {q9}, [r2], r3 ++ mov r1, #6 ++1: ++ vext.16 q8, q8, q8, #2 ++ subs r1, #2 ++ vext.16 q1, q1, q1, #2 ++ vbit d4, d16, d7 ++ vst1.16 {q2}, [r0], r3 ++ vbit d18, d2, d7 ++ vst1.16 {q9}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] (In pels - needs * 4) ++ ++function ff_hevc_rpi_pred_dc_c_8_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vld1.16 {q0-q1}, [r1] ++ mov r1, #8 ++ vld1.16 {q2-q3}, [r2] ++T lsl r3, #2 ++ vadd.i16 q1, q0 ++A add r2, r0, r3, lsl #2 ++A lsl r3, #3 ++T add r2, r0, r3 ++T lsl r3, #1 ++ vadd.i16 q2, q3 ++ vadd.i16 q1, q2 ++ vadd.i16 d3, d2 @ d3 has 2 val pairs ++ vpadd.i32 d2, d3, d3 @ This add U & V separately ++ vpadd.i32 d3, d3, d3 ++ vrshr.u16 q0, q1, #4 ++ vrshr.u16 q1, q1, #4 ++ ++ @ Store ++1: ++ vst1.8 {q0-q1}, [r0], r3 ++ subs r1, #2 ++ vst1.8 {q0-q1}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_dc_16_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vld1.16 {q8-q9}, [r1] ++ mov r1, #2 ++ vld1.16 {q10-q11}, [r2] ++ lsl r3, #1 @ stride given in pels ++ vadd.i16 q0, q8, q9 ++ vadd.i16 q1, q10, q11 ++ vmov.i16 q3, #3 ++ vadd.i16 q1, q0 ++ vadd.i16 d0, d16, d20 ++ vmov.i64 d31, #0xffff ++ vadd.i16 d3, d2 ++ vmov.16 d6[0], r1 @ 2, 3, 3, 3... ++ ++ @ top line gets some smoothing ++ @ (top[i] + 3*dc + 2) >> 2 ++ @ as does left ++ @ topline[0] is extra special ++ @ (top[0] + left[0] + 2*dc + 2) >> 2 ++ ++ vbit d16, d0, d31 @ q8 = top[0]+left[0], top[1..7] ++ vpadd.i16 d3, d3 @ 2 (top & bottom of vector the same) ++ vpadd.i16 d3, d3 @ 1 (all the same) ++ vrshr.u16 d2, d3, #5 ++ vrshr.u16 d3, d3, #5 ++ vmov q0, q1 ++ vmla.i16 q10, q1, d6[1] ++ vmla.i16 q11, q1, d6[1] ++ vmla.i16 q8, q1, q3 ++ vmla.i16 q9, q1, d6[1] ++ vrshr.u16 q2, q10, #2 ++ vrshr.u16 q3, q11, #2 ++ vrshr.u16 q8, #2 ++ vrshr.u16 q9, #2 ++ vext.16 q2, q2, q2, #1 ++ mov r1, #7<<29 ++ ++ @ Store top line ++ vst1.16 {q8-q9}, [r0], r3 ++ ++ @ Store the rest ++1: ++ vbit d0, d4, d31 ++ vext.16 q2, q2, q2, #1 ++ subs r1, #1<<29 ++ vst1.16 {q0-q1}, [r0], r3 ++ bne 1b ++1: ++ vbit d0, d6, d31 ++ vext.16 q3, q3, q3, #1 ++ subs r1, #1<<29 ++ vst1.16 {q0-q1}, [r0], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_c_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] (In pels - needs * 4) ++ ++function ff_hevc_rpi_pred_dc_c_16_neon_10, export=1 ++ ++ @ Average the els of top & left ++ vldm r1, {q0-q3} ++ vldm r2, {q8-q11} ++ vadd.i16 q0, q1 ++ mov r1, #16 ++ vadd.i16 q2, q3 ++ add r2, r0, #32 ++ vadd.i16 q8, q9 ++ lsl r3, #2 ++ vadd.i16 q10, q11 ++ vadd.u16 q0, q2 ++ vadd.u16 q8, q10 ++ vadd.i16 q0, q8 ++ vadd.i16 d0, d1 @ d0 has 2 val pairs ++ vpadd.i32 d4, d0, d0 @ This adds U & V separately ++ vpadd.i32 d5, d0, d0 ++ vrshr.u16 q0, q2, #5 ++ vrshr.u16 q1, q2, #5 ++ ++ @ Store ++1: ++ vst1.16 {q0-q1}, [r0], r3 ++ subs r1, #1 ++ vst1.16 {q0-q1}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_dc_32_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] (In pels) ++ ++function ff_hevc_rpi_pred_dc_32_neon_10, export=1 ++ ++ @ Average the els of top & left ++ @ With 10 bits we are (just) safe from overflow in i16 ++ vldm r1, {q0-q3} ++ vldm r2, {q8-q11} ++ vadd.i16 q0, q1 ++ mov r1, #32 ++ vadd.i16 q2, q3 ++ add r2, r0, #32 ++ vadd.i16 q8, q9 ++ lsl r3, #1 ++ vadd.i16 q10, q11 ++ vadd.u16 q0, q2 ++ vadd.u16 q8, q10 ++ vadd.i16 q0, q8 ++ vadd.i16 d0, d1 @ d0 has 4 vals ++ vpadd.i16 d0, d0 @ 2 (top & bottom the same) ++ vpadd.i16 d4, d0, d0 @ 1 (all the same) ++ vpadd.i16 d5, d0, d0 ++ vrshr.u16 q0, q2, #6 ++ vrshr.u16 q1, q2, #6 ++ ++ @ Store ++1: ++ vst1.16 {q0-q1}, [r0], r3 ++ subs r1, #1 ++ vst1.16 {q0-q1}, [r2], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ +diff --git a/libavcodec/arm/rpi_hevcpred_intra_filter_neon.S b/libavcodec/arm/rpi_hevcpred_intra_filter_neon.S +new file mode 100644 +index 0000000000..f6969d3591 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_intra_filter_neon.S +@@ -0,0 +1,881 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++@ All functions have the call ++@ ++@ int ff_hevc_rpi_intra_filter_N_neon_PW( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++@ ++@ Assumptions: ++@ (that wouldn't apply to all frame layoouts but do apply to sand, so beware ++@ if reuseing this code) ++@ ++@ Min ctb size is 8 so we don't need to worry about tr_size or dl_size for ++@ N==4, but do for chroma N>=8. As we share Y/C fns that means we can ignore ++@ N==8,PW=8 (chroma always PW>8) but have to cope for larger ++@ ++@ We always have at least 64 pixel H frame width rounding - this lets us ++@ load UR widthout having to worry about exactly how many pixels are actually ++@ within the frame. As partial loads will only occur very occasionally this ++@ should be a win in nearly all cases. ++@ ++@ 16 bit fns can be used as 8 bit chroma fns as chroma never filters ++@ so we do no maths on the contents ++@ ++@ No filtering in 32bit fns as they are chroma only ++ ++ ++.equ AVAIL_UR, 1 ++.equ AVAIL_U, 2 ++.equ AVAIL_UL, 4 ++.equ AVAIL_L, 8 ++.equ AVAIL_DL, 16 ++ ++.equ FILTER_LIGHT, 0x40 ++.equ FILTER_STRONG, 0x80 ++ ++.equ AVAIL_S_UR_N_U_C, 32 - 1 ++.equ AVAIL_S_U_N_UL_C, 32 - 2 ++.equ AVAIL_S_UL_N_L_C, 32 - 3 ++.equ AVAIL_S_L_N_DL_C, 32 - 4 ++ ++.equ AVAIL_S_U_DL_CPSR, 31 - 4 @ Shift for u..dl to go into flags via cpsr ++ ++@ On entry ++@ r2 req ++@ r3 avail ++@ [sp, #sp_offset...] args ++@ ++@ On Exit: ++@ ++@ Extend values: ++@ d_l scalar contains value for L & DL ++@ if DL avail then this is is DL[0] so we don't need to load that ++@ d_ul scalar containing value for UL ++@ d_u scalar containing value for U ++@ d_ur scalar containing value for UR ++@ If DL avail then d_l == b_dl elif L avail then d_l == a_l else... ++@ This means that L-light-filter works even if nreq DL (we never filter ++@ req-DL without req-L, but we do filter req-L without req-DL) ++@ If UR avail then d_ur == a_ur so U-filter good too ++@ ++@ Data load pointers (only load if req & avail): ++@ r4 DL + stride ++@ r10 L ++@ r6 U ++@ r5 UR ++@ ++@ Others: ++@ r2 req ++@ r7 req & avail ++@ r3 L + stride ++@ r8 DL + stride * 2 ++@ r9 stride * 2 ++@ cs Load U ++@ mi Load UR ++@ ++@ Clobbered: ++@ r12 ++ ++.macro load_pointers pw_s, log2_s, sp_offset, d_type, d_l, d_ul, d_u, d_ur ++ ++.equ src_l\@, \sp_offset + 0 ++.equ src_u\@, \sp_offset + 4 ++.equ src_ur\@, \sp_offset + 8 ++.equ stride\@, \sp_offset + 12 ++.equ pw\@, (1 << \pw_s) @ pel width in bytes ++.equ b_size\@, (1 << (\pw_s + \log2_s)) @ size in bytes ++ ++@ r9 stride ++@ r7 = ab_ul, r6 = a_u, r5 = a_ur ++@ r4 = b_dl, r10 = b_l, r8 = b_u ++ ++ ldr r5, [sp, #src_ur\@] ++ lsl r12, r3, #AVAIL_S_U_DL_CPSR ++ ldr r10, [sp, #src_l\@] ++ ldr r9, [sp, #stride\@] ++ ldr r6, [sp, #src_u\@] ++ ++ @ This is quite a slow instruction but it replaces ++ @ a decent number of tests that yield a max of 2 flags/op ++ @ It is annoying we can't branch on Q! ++ @ If L navail (ne) then DL must be navail (pl) ++ msr APSR_nzcvq, r12 @ n=dl, z=l, c=ul, v=u, q=ur ++ ++ mov r4, r5 ++ sub r7, r10, r9 ++ it vs ++ movvs r4, r6 ++ add r8, r6, #b_size\@ - pw\@ ++ it cs ++ movcs r4, r7 ++ ite ne ++ movne r10, r4 ++ addeq r4, r7, r9, lsl #\log2_s ++ it cc ++ movcc r7, r10 ++ it mi ++ addmi r4, r10, r9, lsl #\log2_s ++ vld1.\d_type {\d_ul}, [r7] ++ itt vc ++ movvc r8, r7 ++ movvc r6, r7 ++ vld1.\d_type {\d_l }, [r4], r9 ++ tst r3, #AVAIL_UR ++ vld1.\d_type {\d_u }, [r6] ++ it eq ++ moveq r5, r8 ++ and r7, r2, r3 ++ add r8, r4, r9 ++ vld1.\d_type {\d_ur}, [r5] ++ lsls r12, r7, #AVAIL_S_UR_N_U_C ++ add r3, r10, r9 ++ lsl r9, #1 ++.endm ++ ++ ++ ++@ int ff_hevc_rpi_intra_filter_4_neon_8( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set pw_s, 0 ++.set pw, (1 << pw_s) ++.set log2_s, 2 ++ ++function ff_hevc_rpi_intra_filter_4_neon_8, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 8, d0[], d31[7], d1[], d2[] ++ ++ it cs ++ vldrcs s2, [r6] ++ ite pl ++ vmovpl s3, s4 ++ vldrmi s3, [r5] ++ ++ lsls r7, #AVAIL_S_L_N_DL_C ++ add r12, r0, #-pw ++ bpl 1f ++ ++ vld1.8 {d0[0]}, [r10], r9 ++ vld1.8 {d0[1]}, [r3], r9 ++ vld1.8 {d0[2]}, [r10] ++ vld1.8 {d0[3]}, [r3] ++1: ++ bcc 1f ++ vld1.8 {d0[5]}, [r4], r9 ++ vld1.8 {d0[6]}, [r8] ++ vld1.8 {d0[7]}, [r4] ++1: ++ vstr d1, [r1] @ Up ++ vst1.8 {d31[7]}, [r12] ++ vstr d0, [r0] @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++ ++@ int ff_hevc_rpi_intra_filter_4_neon_16( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set pw_s, 1 ++.set pw, (1 << pw_s) ++.set log2_s, 2 ++ ++function ff_hevc_rpi_intra_filter_4_neon_16, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 16, "d0[],d1[]", d31[3], d2[], d3[] ++ ++ it cs ++ vldrcs d2, [r6] ++ it mi ++ vldrmi d3, [r5] ++ lsls r7, #AVAIL_S_L_N_DL_C ++ add r12, r0, #-pw ++ bpl 1f ++ vld1.16 {d0[0]}, [r10], r9 ++ vld1.16 {d0[1]}, [r3], r9 ++ vld1.16 {d0[2]}, [r10] ++ vld1.16 {d0[3]}, [r3] ++1: ++ bcc 1f ++ vld1.16 {d1[1]}, [r4], r9 ++ vld1.16 {d1[2]}, [r8] ++ vld1.16 {d1[3]}, [r4] ++1: ++ vst1.16 {q1}, [r1] @ Up ++ vst1.16 {d31[3]}, [r12] ++ vst1.16 {q0}, [r0] @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++ ++@ int ff_hevc_rpi_intra_filter_8_neon_8( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set pw_s, 0 ++.set pw, (1 << pw_s) ++.set log2_s, 3 ++ ++function ff_hevc_rpi_intra_filter_8_neon_8, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 8, "d0[],d1[]", d31[7], d4[], d5[] ++ ++ it cs ++ vldrcs d4, [r6] ++ it mi ++ vldrmi d5, [r5] ++ ++ lsls r7, #AVAIL_S_L_N_DL_C ++ bpl 1f ++ vld1.8 {d0[0]}, [r10], r9 ++ vld1.8 {d0[1]}, [r3], r9 ++ vld1.8 {d0[2]}, [r10], r9 ++ vld1.8 {d0[3]}, [r3], r9 ++ vld1.8 {d0[4]}, [r10], r9 ++ vld1.8 {d0[5]}, [r3], r9 ++ vld1.8 {d0[6]}, [r10] ++ vld1.8 {d0[7]}, [r3] ++1: ++ bcc 1f ++ vld1.8 {d1[1]}, [r4], r9 ++ vld1.8 {d1[2]}, [r8], r9 ++ vld1.8 {d1[3]}, [r4], r9 ++ vld1.8 {d1[4]}, [r8], r9 ++ vld1.8 {d1[5]}, [r4], r9 ++ vld1.8 {d1[6]}, [r8] ++ vld1.8 {d1[7]}, [r4] ++1: ++ tst r2, #FILTER_LIGHT ++ add r12, r0, #-pw ++ beq 10f ++ ++ @ Luma light filter ++ vext.8 q8, q15, q2, #15 ++ vext.8 q12, q15, q0, #15 ++ vaddl.u8 q9, d17, d5 ++ vaddl.u8 q8, d16, d4 ++ vaddl.u8 q13, d25, d1 ++ vaddl.u8 q12, d24, d0 ++ vmov.u8 r3, d5[7] @ Save final pel ++ vmov.u8 r2, d1[7] @ Save final pel ++ ++ vext.16 q2, q8, q9, #1 ++ vext.16 q3, q9, q9, #1 ++ vext.16 q0, q12, q13, #1 ++ vext.16 q1, q13, q13, #1 ++ vadd.u16 d30, d16, d24 @ d30[0] = l[0] + 2ul + u[0] ++ vadd.u16 q2, q8 ++ vadd.u16 q3, q9 ++ vadd.u16 q0, q12 ++ vadd.u16 q1, q13 ++ ++ vrshrn.u16 d4, q2, #2 ++ vrshrn.u16 d5, q3, #2 ++ vrshrn.u16 d0, q0, #2 ++ vrshrn.u16 d1, q1, #2 ++ vrshr.u16 d30, #2 ++ vmov.u8 d5[7], r3 @ Restore final pel ++ vmov.u8 d1[7], r2 @ Restore final pel ++ vdup.u8 d31, d30[0] @ d31[3] = d30[0] ++ ++10: ++ vst1.8 {q2 }, [r1] @ Up ++ vst1.8 {d31[7]}, [r12] @ Up-left ++ vst1.8 {q0 }, [r0] @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++ ++@ int ff_hevc_rpi_intra_filter_8_neon_16( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set ur_size, sp_base + 16 ++.set dl_size, sp_base + 20 ++.set pw_s, 1 ++.set pw, (1 << pw_s) ++.set log2_s, 3 ++.set p_size, (1 << log2_s) @ size in pels ++ ++function ff_hevc_rpi_intra_filter_8_neon_16, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 16, "d0[],d1[]", d31[3], "d4[],d5[]", "d6[],d7[]" ++ ++ it cs ++ vldmcs r6, {d4, d5} ++ ldr r12, [sp, #ur_size] ++ bpl 1f ++ cmp r12, #4 ++ vldm r5, {d6, d7} ++ bgt 1f ++ vdup.16 d7, d6[3] ++1: ++ lsls r12, r7, #AVAIL_S_L_N_DL_C ++ vdup.16 q1, d0[0] ++ bpl 1f ++ vld1.16 {d0[0]}, [r10], r9 ++ vld1.16 {d0[1]}, [r3], r9 ++ vld1.16 {d0[2]}, [r10], r9 ++ vld1.16 {d0[3]}, [r3], r9 ++ vld1.16 {d1[0]}, [r10], r9 ++ vld1.16 {d1[1]}, [r3], r9 ++ vld1.16 {d1[2]}, [r10] ++ vld1.16 {d1[3]}, [r3] ++1: ++ bcc 1f ++ ldr r12, [sp, #dl_size] ++ vld1.16 {d2[1]}, [r4], r9 ++ cmp r12, #p_size ++ vld1.16 {d2[2]}, [r8], r9 ++ vld1.16 {d2[3]}, [r4], r9 ++ blt 2f ++ vld1.16 {d3[0]}, [r8], r9 ++ vld1.16 {d3[1]}, [r4], r9 ++ vld1.16 {d3[2]}, [r8] ++ vld1.16 {d3[3]}, [r4] ++ b 1f ++2: ++ vdup.16 d3, d2[3] ++1: ++ tst r2, #FILTER_LIGHT ++ add r12, r0, #-pw ++ beq 10f ++ ++ @ Luma light filter ++ vext.16 q9, q2, q3, #7 ++ vext.16 q8, q15, q2, #7 ++ vext.16 q13, q0, q1, #7 ++ vext.16 q12, q15, q0, #7 ++ vadd.u16 q9, q3 ++ vadd.u16 q8, q2 ++ vadd.u16 q13, q1 ++ vadd.u16 q12, q0 ++ vmov.u16 r3, d7[3] @ Save final pel ++ vmov.u16 r2, d3[3] @ Save final pel ++ ++ vext.16 q2, q8, q9, #1 ++ vext.16 q3, q9, q9, #1 ++ vext.16 q0, q12, q13, #1 ++ vext.16 q1, q13, q13, #1 ++ vadd.u16 d30, d16, d24 @ d30[0] = l[0] + 2ul + u[0] ++ vadd.u16 q2, q8 ++ vadd.u16 q3, q9 ++ vadd.u16 q0, q12 ++ vadd.u16 q1, q13 ++ ++ vrshr.u16 q2, #2 ++ vrshr.u16 q3, #2 ++ vrshr.u16 q0, #2 ++ vrshr.u16 q1, #2 ++ vrshr.u16 d30, #2 ++ vmov.u16 d7[3], r3 @ Restore final pel ++ vmov.u16 d3[3], r2 @ Restore final pel ++ vdup.u16 d31, d30[0] @ d31[3] = d30[0] ++ ++10: ++ vst1.16 {q2, q3}, [r1] @ Up ++ vst1.16 {d31[3]}, [r12] @ Up-left ++ vst1.16 {q0, q1}, [r0] @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++@ int ff_hevc_rpi_intra_filter_16_neon_16( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set ur_size, sp_base + 16 ++.set dl_size, sp_base + 20 ++.set pw_s, 1 ++.set pw, (1 << pw_s) ++.set log2_s, 4 ++.set p_size, (1 << log2_s) @ size in pels ++ ++function ff_hevc_rpi_intra_filter_16_neon_16, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 16, "d0[],d1[]", d31[3], "d16[],d17[]", "d20[],d21[]" ++ ++ vdup.16 q9, d16[0] ++ vdup.16 q11, d20[0] ++ ++ it cs ++ vldmcs r6, {d16-d19} ++ ldr r12, [sp, #ur_size] ++ bpl 1f ++ cmp r12, #12 ++ @ Given chroma frame layout, if UR exists then it is always legit to ++ @ load all of it even if most of it is outside the frame. ++ vldm r5, {d20-d23} ++ bgt 1f ++ bge 4f ++ cmp r12, #8 ++ bge 3f ++ vdup.16 d21, d20[3] ++3: vdup.16 d22, d21[3] ++4: vdup.16 d23, d22[3] ++ ++1: ++ lsls r7, #AVAIL_S_L_N_DL_C ++ ldr r12, [sp, #dl_size] ++ vdup.16 q1, d0[0] ++ vdup.16 q2, d0[0] ++ vdup.16 q3, d0[0] ++ bpl 1f ++ vld1.16 {d0[0]}, [r10], r9 ++ vld1.16 {d0[1]}, [r3], r9 ++ vld1.16 {d0[2]}, [r10], r9 ++ vld1.16 {d0[3]}, [r3], r9 ++ vld1.16 {d1[0]}, [r10], r9 ++ vld1.16 {d1[1]}, [r3], r9 ++ vld1.16 {d1[2]}, [r10], r9 ++ vld1.16 {d1[3]}, [r3], r9 ++ vld1.16 {d2[0]}, [r10], r9 ++ vld1.16 {d2[1]}, [r3], r9 ++ vld1.16 {d2[2]}, [r10], r9 ++ vld1.16 {d2[3]}, [r3], r9 ++ vld1.16 {d3[0]}, [r10], r9 ++ vld1.16 {d3[1]}, [r3], r9 ++ vld1.16 {d3[2]}, [r10] ++ vld1.16 {d3[3]}, [r3] ++1: ++ bcc 1f ++ vld1.16 {d4[1]}, [r4], r9 ++ cmp r12, #4 ++ vld1.16 {d4[2]}, [r8], r9 ++ vld1.16 {d4[3]}, [r4], r9 ++ ble 2f ++ vld1.16 {d5[0]}, [r8], r9 ++ vld1.16 {d5[1]}, [r4], r9 ++ cmp r12, #12 ++ vld1.16 {d5[2]}, [r8], r9 ++ vld1.16 {d5[3]}, [r4], r9 ++ blt 3f ++ vld1.16 {d6[0]}, [r8], r9 ++ vld1.16 {d6[1]}, [r4], r9 ++ vld1.16 {d6[2]}, [r8], r9 ++ vld1.16 {d6[3]}, [r4], r9 ++ ble 4f ++ vld1.16 {d7[0]}, [r8], r9 ++ vld1.16 {d7[1]}, [r4], r9 ++ vld1.16 {d7[2]}, [r8] ++ vld1.16 {d7[3]}, [r4] ++ b 1f ++2: vdup.16 d5, d4[3] ++3: vdup.16 d6, d5[3] ++4: vdup.16 d7, d6[3] ++1: ++ tst r2, #FILTER_LIGHT ++ add r12, r0, #-pw ++ beq 10f ++ ++ vpush {q5} ++ @ Luma light filter ++ @ Left ++ vext.16 q5, q2, q3, #7 ++ vext.16 q14, q1, q2, #7 ++ vext.16 q13, q0, q1, #7 ++ vext.16 q12, q15, q0, #7 ++ ++ vadd.u16 q5, q3 ++ vadd.u16 q14, q2 ++ vadd.u16 q13, q1 ++ vadd.u16 q12, q0 ++ vmov.u16 r2, d7[3] @ Save final pel ++ ++ vext.16 q0, q12, q13, #1 ++ vext.16 q1, q13, q14, #1 ++ vext.16 q2, q14, q5, #1 ++ vext.16 q3, q5, q5, #1 ++ ++ vmov d30, d24 @ d30[0] = l[0] + ul ++ vadd.u16 q0, q12 ++ vadd.u16 q1, q13 ++ vadd.u16 q2, q14 ++ vadd.u16 q3, q5 ++ ++ vrshr.u16 q0, #2 ++ vrshr.u16 q1, #2 ++ vrshr.u16 q2, #2 ++ vrshr.u16 q3, #2 ++ ++ @ Up ++ vext.16 q5, q10, q11, #7 ++ vext.16 q14, q9, q10, #7 ++ vext.16 q13, q8, q9, #7 ++ vext.16 q12, q15, q8, #7 ++ ++ vadd.u16 q5, q11 ++ vadd.u16 q14, q10 ++ vadd.u16 q13, q9 ++ vadd.u16 q12, q8 ++ vmov.u16 r3, d23[3] @ Save final pel ++ ++ vext.16 q8, q12, q13, #1 ++ vext.16 q9, q13, q14, #1 ++ vext.16 q10, q14, q5, #1 ++ vext.16 q11, q5, q5, #1 ++ ++ vadd.u16 d30, d24 @ d30[0] = l[0] + 2ul + u[0] ++ vadd.u16 q8, q12 ++ vadd.u16 q9, q13 ++ vadd.u16 q10, q14 ++ vadd.u16 q11, q5 ++ ++ vrshr.u16 q8, #2 ++ vrshr.u16 q9, #2 ++ vrshr.u16 q10, #2 ++ vrshr.u16 q11, #2 ++ ++ @ Misc ++ vrshr.u16 d30, #2 ++ vmov.u16 d7[3], r2 @ Restore final pel ++ vmov.u16 d23[3], r3 @ Restore final pel ++ vdup.u16 d31, d30[0] @ d31[3] = d30[0] ++ vpop {q5} ++ ++10: ++ vstm r1, {d16-d23} @ Up ++ vst1.16 {d31[3]}, [r12] @ Up-left ++ vstm r0, { d0-d7 } @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++@ int ff_hevc_rpi_intra_filter_4_neon_32( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set pw_s, 2 ++.set pw, (1 << pw_s) ++.set log2_s, 2 ++ ++function ff_hevc_rpi_intra_filter_4_neon_32, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 32, "d0[],d1[]", d31[1], "d4[],d5[]", "d6[],d7[]" ++ ++ it cs ++ vldmcs r6, {d4, d5} ++ it mi ++ vldmmi r5, {d6, d7} ++ lsls r7, #AVAIL_S_L_N_DL_C ++ vdup.32 q1, d0[0] ++ add r12, r0, #-pw ++ bpl 1f ++ vld1.32 {d0[0]}, [r10], r9 ++ vld1.32 {d0[1]}, [r3], r9 ++ vld1.32 {d1[0]}, [r10] ++ vld1.32 {d1[1]}, [r3] ++1: ++ bcc 1f ++ vld1.32 {d2[1]}, [r4], r9 ++ vld1.32 {d3[0]}, [r8] ++ vld1.32 {d3[1]}, [r4] ++1: ++ vst1.32 {q2, q3 }, [r1] @ Up ++ vst1.32 {d31[1]}, [r12] ++ vst1.32 {q0, q1 }, [r0] @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++ ++@ int ff_hevc_rpi_intra_filter_8_neon_32( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set ur_size, sp_base + 16 ++.set dl_size, sp_base + 20 ++.set pw_s, 2 ++.set pw, (1 << pw_s) ++.set log2_s, 3 ++.set p_size, (1 << log2_s) @ size in pels ++ ++function ff_hevc_rpi_intra_filter_8_neon_32, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 32, "d0[],d1[]", d31[1], "d16[],d17[]", "d20[],d21[]" ++ ++ vdup.32 q9, d16[0] ++ vdup.32 q11, d20[0] ++ ++ it cs ++ vldmcs r6, {q8, q9 } ++ ldr r12, [sp, #ur_size] ++ bpl 1f ++ cmp r12, #p_size ++ vldm r5, {q10, q11} ++ bge 1f ++ vdup.32 q11, d21[1] ++1: ++ lsls r7, #AVAIL_S_L_N_DL_C ++ vdup.32 q1, d0[0] ++ vdup.32 q2, d0[0] ++ vdup.32 q3, d0[0] ++ bpl 1f ++ vld1.32 {d0[0]}, [r10], r9 ++ vld1.32 {d0[1]}, [r3], r9 ++ vld1.32 {d1[0]}, [r10], r9 ++ vld1.32 {d1[1]}, [r3], r9 ++ vld1.32 {d2[0]}, [r10], r9 ++ vld1.32 {d2[1]}, [r3], r9 ++ vld1.32 {d3[0]}, [r10] ++ vld1.32 {d3[1]}, [r3] ++1: ++ bcc 1f ++ ldr r12, [sp, #dl_size] ++ vld1.32 {d4[1]}, [r4], r9 ++ cmp r12, #p_size ++ vld1.32 {d5[0]}, [r8], r9 ++ vld1.32 {d5[1]}, [r4], r9 ++ blt 2f ++ vld1.32 {d6[0]}, [r8], r9 ++ vld1.32 {d6[1]}, [r4], r9 ++ vld1.32 {d7[0]}, [r8] ++ vld1.32 {d7[1]}, [r4] ++ b 1f ++2: ++ vdup.32 q3, d5[1] ++1: ++ add r12, r0, #-pw ++ vstm r1, { q8-q11} @ Up ++ vst1.32 {d31[1]}, [r12] ++ vstm r0, { q0-q3 } @ Left ++ pop {r4-r10, pc} ++endfunc ++ ++ ++@ int ff_hevc_rpi_intra_filter_16_neon_32( ++@ pixel * const left, [r0] ++@ pixel * const top, [r1] ++@ const unsigned int req, [r2] ++@ const unsigned int avail, [r3] ++@ const pixel * const src_l, [sp, #0] ++@ const pixel * const src_u, [sp, #4] ++@ const pixel * const src_ur, [sp, #8] ++@ const unsigned int stride, [sp, #12] (pels) ++@ const unsigned int top_right_size, [sp, #16] ++@ const unsigned int down_left_size) [sp, #20] ++ ++.set sp_base, 8*4 ++.set ur_size, sp_base + 16 ++.set dl_size, sp_base + 20 ++.set pw_s, 2 ++.set pw, (1 << pw_s) ++.set log2_s, 4 ++.set p_size, (1 << log2_s) @ size in pels ++ ++function ff_hevc_rpi_intra_filter_16_neon_32, export=1 ++ push {r4-r10, lr} ++ load_pointers pw_s, log2_s, sp_base, 32, d30[0], d30[1], d31[0], d31[1] ++ ++ @ Once we get this big we have run out of neon regs to store ++ @ everything at once so do in pieces ++ ++ @ Up (have) ++ it cs ++ vldmcs r6, { q0-q3 } ++ ldr r12, [sp, #ur_size] ++ it mi ++ vldmmi r5, { q8-q11} ++ it cs ++ vstmcs r1, { q0-q3 } ++ bpl 1f ++ cmp r12, #12 ++ add lr, r1, #(pw << log2_s) ++ bgt 2f ++ cmp r12, #8 ++ bge 3f ++ vdup.16 q9, d17[1] ++4: vdup.16 d10, d19[1] ++3: vdup.16 q11, d21[1] ++2: vstm lr, { q8-q11} ++1: ++ ++ @ Left (have) ++ add lr, r0, #-pw ++ lsls r12, r7, #AVAIL_S_L_N_DL_C ++ vst1.32 {d30[1]}, [lr] @ UL ++ bpl 1f ++ vld1.32 { d0[0]}, [r10], r9 ++ vld1.32 { d0[1]}, [r3], r9 ++ vld1.32 { d1[0]}, [r10], r9 ++ vld1.32 { d1[1]}, [r3], r9 ++ vld1.32 { d2[0]}, [r10], r9 ++ vld1.32 { d2[1]}, [r3], r9 ++ vld1.32 { d3[0]}, [r10], r9 ++ vld1.32 { d3[1]}, [r3], r9 ++ vld1.32 { d4[0]}, [r10], r9 ++ vld1.32 { d4[1]}, [r3], r9 ++ vld1.32 { d5[0]}, [r10], r9 ++ vld1.32 { d5[1]}, [r3], r9 ++ vld1.32 { d6[0]}, [r10], r9 ++ vld1.32 { d6[1]}, [r3], r9 ++ vld1.32 { d7[0]}, [r10] ++ vld1.32 { d7[1]}, [r3] ++ vstm r0, { q0-q3 } ++1: ++ bcc 1f ++ ldr r12, [sp, #dl_size] ++ vdup.32 d16, d30[0] @ d16[0] = d30[0] ++ add lr, r0, #(pw << log2_s) ++ vld1.32 {d16[1]}, [r4], r9 ++ cmp r12, #4 ++ vld1.32 {d17[0]}, [r8], r9 ++ vld1.32 {d17[1]}, [r4], r9 ++ ble 2f ++ vld1.32 {d18[0]}, [r8], r9 ++ vld1.32 {d18[1]}, [r4], r9 ++ cmp r12, #12 ++ vld1.32 {d19[0]}, [r8], r9 ++ vld1.32 {d19[1]}, [r4], r9 ++ blt 3f ++ vld1.32 {d20[0]}, [r8], r9 ++ vld1.32 {d20[1]}, [r4], r9 ++ vld1.32 {d21[0]}, [r8], r9 ++ vld1.32 {d21[1]}, [r4], r9 ++ ble 4f ++ vld1.32 {d22[0]}, [r8], r9 ++ vld1.32 {d22[1]}, [r4], r9 ++ vld1.32 {d23[0]}, [r8] ++ vld1.32 {d23[1]}, [r4] ++ b 5f ++2: vdup.32 q9, d17[1] ++3: vdup.32 q10, d19[1] ++4: vdup.32 q11, d21[1] ++5: vstm lr, { q8-q11} ++1: ++ eors r7, r2 ++ beq 99f ++ ++ lsls r12, r7, #AVAIL_S_UR_N_U_C ++ vdup.32 q0, d31[0] ++ vdup.32 q1, d31[0] ++ vdup.32 q2, d31[0] ++ vdup.32 q3, d31[0] ++ add lr, r1, #(pw << log2_s) ++ vdup.32 q8, d31[1] ++ vdup.32 q9, d31[1] ++ vdup.32 q10, d31[1] ++ vdup.32 q11, d31[1] ++ it cs ++ vstmcs r1, { q0-q3 } ++ it mi ++ vstmmi lr, { q8-q11} ++ ++ lsls r7, #AVAIL_S_L_N_DL_C ++ vdup.32 q0, d30[0] ++ vdup.32 q1, d30[0] ++ vdup.32 q2, d30[0] ++ vdup.32 q3, d30[0] ++ add lr, r0, #(pw << log2_s) ++ it mi ++ vstmmi r0, { q0-q3 } ++ it cs ++ vstmcs lr, { q0-q3 } ++ ++99: ++ pop {r4-r10, pc} ++endfunc ++ ++ ++ ++ +diff --git a/libavcodec/arm/rpi_hevcpred_intra_hv_neon.S b/libavcodec/arm/rpi_hevcpred_intra_hv_neon.S +new file mode 100644 +index 0000000000..56819ae439 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_intra_hv_neon.S +@@ -0,0 +1,920 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++/* ++ * Horizontal & Vertical special cases of angular intra pred ++ * ++ * Split out because: ++ * Vertical, at least, is relatively common ++ * Much simpler code than the general angular case ++ * Luma with size < 32 has extra filtering that doesn't happen anywhere else ++ * ++ * *** Currently luma filtering is mandatory where it occurs, but there are ++ * cases where it should be turned off (rdpcm & an extension sps flag). ++ * These don't occur in the standard conformance suite for Main Profile ++ */ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++@ ff_hevc_rpi_pred_vertical_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_4_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.32 {d0[0]}, [r2 :32] @ Left ++ add r2, r0, r3 ++ vld1.8 {d1[]}, [r1] ++ lsl r3, #1 ++ vdup.8 d4, ip ++ vmov.i8 d2, #128 ++ vhsub.u8 d4, d0, d4 ++ veor d1, d2 ++ vld1.32 {d0[0]}, [r1 :32] @ Top ++ vqadd.s8 d1, d4 ++ vmov.i64 d3, #0xff ++ vmov d4, d0 ++ veor d5, d1, d2 ++ veor d1, d1, d2 ++ vbit d0, d1, d3 ++ vshr.u64 d5, #8 ++ vst1.32 {d0[0]}, [r0], r3 ++ vshr.u64 d1, #16 ++ vbit d4, d5, d3 ++ vshr.u64 d5, #16 ++ vst1.32 {d4[0]}, [r2], r3 ++ vbit d0, d1, d3 ++ vst1.32 {d0[0]}, [r0] ++ vbit d4, d5, d3 ++ vst1.32 {d4[0]}, [r2] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_8_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.8 {d0}, [r2 :64] @ Left ++ vmov.i8 d1, #128 ++ vld1.8 {d2[]}, [r1] ++ vld1.8 {d3}, [r1 :64] @ Top ++ vdup.8 d4, ip ++ vhsub.u8 d4, d0, d4 ++ veor d2, d1 ++ vmov.i64 d0, #0xff ++ mov r1, #8 ++ vqadd.s8 d2, d4, d2 ++ veor d1, d2, d1 ++1: ++ vbit d3, d1, d0 ++ vshr.u64 d1, #8 ++ vst1.8 {d3}, [r0 :64], r3 ++ subs r1, #2 ++ vbit d3, d1, d0 ++ vshr.u64 d1, #8 ++ vst1.8 {d3}, [r0 :64], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_16_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.8 {q0}, [r2 :128] @ Left ++ vdup.8 q1, ip ++ vld1.8 {d4[],d5[]}, [r1] ++ vhsub.u8 q0, q1 ++ vmov.i8 q1, #128 ++ veor q2, q1 ++ vmov.i64 d16, #0xff ++ vqadd.s8 q0, q2 ++ vld1.8 {q3}, [r1 :128] @ Top ++ mov r1, #16 ++ veor q0, q1 ++ vmov q1, q3 ++ vext.8 q2, q0, q0, #1 ++1: ++ vbit d2, d0, d16 ++ vbit d6, d4, d16 ++ vext.8 q0, q0, q0, #2 ++ subs r1, #2 ++ vst1.8 {q1}, [r0 :128], r3 ++ vext.8 q2, q2, q2, #2 ++ vst1.8 {q3}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vert_32_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_32_neon_8, export=1 ++ vld1.8 {q0, q1 }, [r1 :128] @ Up ++ add r2, r0, r3 ++ lsl r3, #1 ++ mov r1, #16 ++1: ++ vst1.8 {q0, q1 }, [r0 :128], r3 ++ subs r1, #1 ++ vst1.8 {q0, q1 }, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_4_neon_8, export=1 ++ vld1.16 {d0 }, [r1 :64] @ Up ++ add r2, r0, r3, lsl #1 ++ lsl r3, #2 ++ ++ vst1.16 {d0 }, [r0 :64], r3 ++ vst1.16 {d0 }, [r2 :64], r3 ++ vst1.16 {d0 }, [r0 :64] ++ vst1.16 {d0 }, [r2 :64] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_8_neon_8, export=1 ++ vld1.16 {q0 }, [r1 :128] @ Up ++ add r2, r0, r3, lsl #1 ++ lsl r3, #2 ++ mov r1, #4 ++1: ++ vst1.16 {q0 }, [r0 :128], r3 ++ subs r1, #2 ++ vst1.16 {q0 }, [r2 :128], r3 ++ vst1.16 {q0 }, [r0 :128], r3 ++ vst1.16 {q0 }, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_16_neon_8, export=1 ++ vld1.16 {q0, q1 }, [r1 :128] @ Up ++ add r2, r0, r3, lsl #1 ++ lsl r3, #2 ++ mov r1, #8 ++1: ++ vst1.16 {q0, q1 }, [r0 :128], r3 ++ subs r1, #1 ++ vst1.16 {q0, q1 }, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontalal_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++@ ? Might be faster as simple arm ++ ++function ff_hevc_rpi_pred_horizontal_4_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.32 {d0[0]}, [r1 :32] @ Top ++ add r1, r2, #3 ++ vld1.8 {d1[]}, [r2]! ++ vdup.8 d2, ip ++ vmov.i8 d3, #128 ++ vhsub.u8 d0, d2 ++ veor d1, d3 ++ vld1.8 {d2[]}, [r2]! ++ add ip, r0, r3 ++ vqadd.s8 d0, d0, d1 ++ lsl r3, #1 ++ vld1.8 {d1[]}, [r2] ++ vld1.8 {d4[]}, [r1] ++ veor d0, d3 ++ vst1.32 {d0[0]}, [r0 :32], r3 ++ vst1.32 {d2[0]}, [ip :32], r3 ++ vst1.32 {d1[0]}, [r0 :32] ++ vst1.32 {d4[0]}, [ip :32] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_8_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.8 {d0}, [r1 :64] @ Top ++ vmov.i8 d1, #128 ++ vld1.8 {d2[]}, [r2]! ++ mov r1, #8-2 ++ vdup.8 d3, ip ++ vhsub.u8 d0, d3 ++ veor d2, d1 ++ vqadd.s8 d0, d2 ++ vld1.8 {d2[]}, [r2]! ++ veor d0, d1 ++ vst1.8 {d0}, [r0], r3 ++1: ++ vld1.8 {d0[]}, [r2]! ++ subs r1, #2 ++ vst1.8 {d2}, [r0 :64], r3 ++ vld1.8 {d2[]}, [r2]! ++ vst1.8 {d0}, [r0 :64], r3 ++ bne 1b ++ ++ vst1.8 {d2}, [r0 :64] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_16_neon_8, export=1 ++ ldrb ip, [r2, #-1] @ Top-left ++ vld1.8 {q0}, [r1 :64] @ Top ++ mov r1, #16-2 ++ vld1.8 {d4[],d5[]}, [r2]! ++ vdup.8 q3, ip ++ vhsub.u8 q0, q3 ++ vmov.i8 q1, #128 ++ veor q2, q1 ++ vqadd.s8 q0, q2 ++ vld1.8 {d4[],d5[]}, [r2]! ++ veor q0, q1 ++ vst1.8 {q0}, [r0], r3 ++1: ++ vld1.8 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.8 {q2}, [r0 :64], r3 ++ vld1.8 {d4[],d5[]}, [r2]! ++ vst1.8 {q0}, [r0 :64], r3 ++ bne 1b ++ ++ vst1.8 {q2}, [r0 :64] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_32_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_32_neon_8, export=1 ++ vld1.8 {d0[],d1[]}, [r2]! ++ add ip, r0, #16 ++ mov r1, #32-2 ++ vld1.8 {d2[],d3[]}, [r2]! ++ vst1.8 {q0}, [r0 :128], r3 ++ vst1.8 {q0}, [ip :128], r3 ++1: ++ vld1.8 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.8 {q1}, [r0 :128], r3 ++ vst1.8 {q1}, [ip :128], r3 ++ vld1.8 {d2[],d3[]}, [r2]! ++ vst1.8 {q0}, [r0 :128], r3 ++ vst1.8 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.8 {q1}, [r0 :128] ++ vst1.8 {q1}, [ip :128] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_4_neon_8, export=1 ++ add r1, r2, #2 ++ vld1.16 {d0[]}, [r2] ++ add r2, #4 ++ vld1.16 {d1[]}, [r1] ++ add r1, #4 ++ vld1.16 {d2[]}, [r2] ++A add r2, r0, r3, lsl #1 ++T lsl r3, #1 ++T add r2, r0, r3 ++ vld1.16 {d3[]}, [r1] ++A lsl r3, #2 ++T lsl r3, #1 ++ vst1.16 {d0}, [r0 :64], r3 ++ vst1.16 {d1}, [r2 :64], r3 ++ vst1.16 {d2}, [r0 :64] ++ vst1.16 {d3}, [r2 :64] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_8_neon_8, export=1 ++ vld1.16 {d0[],d1[]}, [r2]! ++ lsl r3, #1 ++ vld1.16 {d2[],d3[]}, [r2]! ++ mov r1, #8-2 ++ vst1.16 {q0}, [r0 :64], r3 ++1: ++ vld1.16 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.16 {q1}, [r0 :64], r3 ++ vld1.16 {d2[],d3[]}, [r2]! ++ vst1.16 {q0}, [r0 :64], r3 ++ bne 1b ++ ++ vst1.16 {q1}, [r0 :64] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_16_neon_8, export=1 ++ vld1.16 {d0[],d1[]}, [r2]! ++ lsl r3, #1 ++ add ip, r0, #16 ++ mov r1, #16-2 ++ vld1.16 {d2[],d3[]}, [r2]! ++ vst1.16 {q0}, [r0 :128], r3 ++ vst1.16 {q0}, [ip :128], r3 ++1: ++ vld1.16 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.16 {q1}, [r0 :128], r3 ++ vst1.16 {q1}, [ip :128], r3 ++ vld1.16 {d2[],d3[]}, [r2]! ++ vst1.16 {q0}, [r0 :128], r3 ++ vst1.16 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.16 {q1}, [r0 :128] ++ vst1.16 {q1}, [ip :128] ++ bx lr ++endfunc ++ ++ ++@------------------------------------------------------------------------------ ++@ ++@ 10 Bit ++@ Has clipping constants so 10-bit only but could easily be macroed up to ++@ 14-bit before we run out of bits ++ ++ ++@ ff_hevc_rpi_pred_vertical_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_4_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {d0}, [r2 :64] @ Left ++ vmov.i16 d2, #0 ++ vld1.16 {d1[]}, [r1] ++T lsl r3, #1 ++ vdup.16 d4, ip ++ vmov.i16 d3, #0x3ff ++ vld1.16 {d5}, [r1 :64] @ Top ++ vhsub.u16 d4, d0, d4 ++ vmov.i64 d0, #0xffff ++A add r2, r0, r3, lsl #1 ++T add r2, r0, r3 ++ vadd.i16 d1, d1, d4 ++ vmov d6, d5 ++ vmax.s16 d1, d1, d2 ++ vmin.s16 d2, d1, d3 ++ vmin.s16 d1, d1, d3 ++ vbit d5, d1, d0 ++A lsl r3, #2 ++T lsl r3, #1 ++ vshr.u64 d2, #16 ++ vshr.u64 d1, #32 ++ vbit d6, d2, d0 ++ vst1.16 {d5}, [r0], r3 ++ vshr.u64 d2, #32 ++ vst1.16 {d6}, [r2], r3 ++ vbit d5, d1, d0 ++ vst1.16 {d5}, [r0] ++ vbit d6, d2, d0 ++ vst1.16 {d6}, [r2] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_8_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {q0}, [r2 :128] @ Left ++ lsl r3, #1 ++ vdup.16 q1, ip ++ vld1.16 {d4[],d5[]}, [r1] ++ vhsub.u16 q0, q0, q1 ++ vmov.i16 q1, #0 ++ vadd.i16 q0, q2 ++ vmov.i16 q2, #0x3ff ++ vld1.16 {q3}, [r1 :128] @ Top ++ mov r1, #8 ++ vmax.s16 q0, q1 ++ vmov q1, q3 ++ vmin.s16 q0, q2 ++ vmov.i64 d16, #0xffff ++ vext.16 q2, q0, q0, #1 ++1: ++ vbit d2, d0, d16 ++ vbit d6, d4, d16 ++ vext.16 q0, q0, q0, #2 ++ subs r1, #2 ++ vst1.16 {q1}, [r0 :128], r3 ++ vext.16 q2, q2, q2, #2 ++ vst1.16 {q3}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_16_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {q0-q1}, [r2 :128] @ Left ++T lsl r3, #1 ++ vdup.16 q2, ip ++A add r2, r0, r3, lsl #1 ++T add r2, r0, r3 ++ vld1.16 {d6[],d7[]}, [r1] ++A lsl r3, #2 ++T lsl r3, #1 ++ vhsub.u16 q0, q2 ++ vhsub.u16 q1, q2 ++ vadd.i16 q0, q3 ++ vadd.i16 q1, q3 ++ vmov.i16 q2, #0 ++ vld1.16 {q8-q9}, [r1 :128] @ Top ++ mov r1, #0 ++ vmov.i16 q3, #0x3ff ++ vmax.s16 q0, q2 ++ vmax.s16 q1, q2 ++ vmin.s16 q0, q3 ++ vmin.s16 q1, q3 ++ vmov q10, q8 ++ vmov q11, q9 ++ vext.16 q2, q0, q1, #1 ++ vext.16 q3, q1, q1, #1 ++ vmov.i64 d24, #0xffff ++1: ++ vbit d16, d0, d24 ++ vbit d20, d4, d24 ++ vext.16 q0, q0, q0, #2 ++ subs r1, #1<<30 ++ vst1.16 {q8-q9}, [r0 :128], r3 ++ vext.16 q2, q2, q2, #2 ++ vst1.16 {q10-q11}, [r2 :128], r3 ++ bne 1b ++1: ++ vbit d16, d2, d24 ++ vbit d20, d6, d24 ++ vext.16 q1, q1, q1, #2 ++ subs r1, #1<<30 ++ vst1.16 {q8-q9}, [r0 :128], r3 ++ vext.16 q3, q3, q3, #2 ++ vst1.16 {q10-q11}, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_32_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_32_neon_10, export=1 ++ vldm r1, { q0-q3 } @ Up ++ lsl r3, #1 ++ mov r1, #32 ++ add r2, r0, #32 ++1: ++ vst1.16 {q0-q1}, [r0 :128], r3 ++ subs r1, #1 ++ vst1.16 {q2-q3}, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_4_neon_10, export=1 ++ vld1.16 {q0 }, [r1 :128] @ Up ++ add r2, r0, r3, lsl #2 ++ lsl r3, #3 ++ ++ vst1.16 {q0 }, [r0 :128], r3 ++ vst1.16 {q0 }, [r2 :128], r3 ++ vst1.16 {q0 }, [r0 :128] ++ vst1.16 {q0 }, [r2 :128] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_8_neon_10, export=1 ++ vld1.16 {q0, q1 }, [r1 :128] @ Up ++ add r2, r0, r3, lsl #2 ++ lsl r3, #3 ++ mov r1, #4 ++1: ++ vst1.16 {q0, q1 }, [r0 :128], r3 ++ subs r1, #1 ++ vst1.16 {q0, q1 }, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_vertical_c_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_vertical_c_16_neon_10, export=1 ++ vldm r1, { q0-q3 } @ Up ++ lsl r3, #2 ++ mov r1, #16 ++ add r2, r0, #32 ++1: ++ vst1.16 {q0-q1}, [r0 :128], r3 ++ subs r1, #1 ++ vst1.16 {q2-q3}, [r2 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++@ ff_hevc_rpi_pred_horizontal_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_4_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {d0}, [r1 :64] @ Top ++ vmov.i16 d1, #0 ++ vld1.16 {d2[]}, [r2]! ++T lsl r3, #1 ++ vdup.16 d3, ip ++ vmov.i16 d4, #0x3ff ++ vhsub.u16 d0, d3 ++A add ip, r0, r3, lsl #1 ++T add ip, r0, r3 ++ vld1.16 {d3[]}, [r2]! ++A lsl r3, #2 ++T lsl r3, #1 ++ vadd.i16 d0, d2 ++ vld1.16 {d2[]}, [r2]! ++ vmax.s16 d0, d1 ++ vld1.16 {d1[]}, [r2] ++ vmin.s16 d0, d4 ++ vst1.16 {d0}, [r0 :64], r3 ++ vst1.16 {d3}, [ip :64], r3 ++ vst1.16 {d2}, [r0 :64] ++ vst1.16 {d1}, [ip :64] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_8_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {q0}, [r1 :128] @ Top ++ lsl r3, #1 ++ vdup.16 q1, ip ++ mov r1, #8-2 ++ vhsub.u16 q0, q1 ++ vld1.16 {d2[],d3[]}, [r2]! ++ vmov.i16 q2, #0 ++ vadd.i16 q0, q1 ++ vmov.i16 q1, #0x3ff ++ vmax.s16 q0, q2 ++ vld1.16 {d4[],d5[]}, [r2]! ++ vmin.s16 q0, q1 ++ vst1.16 {q0}, [r0 :128], r3 ++1: ++ vld1.16 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.16 {q2}, [r0 :128], r3 ++ vld1.16 {d4[],d5[]}, [r2]! ++ vst1.16 {q0}, [r0 :128], r3 ++ bne 1b ++ ++ vst1.16 {q2}, [r0 :128] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontalal_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_16_neon_10, export=1 ++ ldrh ip, [r2, #-2] @ Top-left ++ vld1.16 {q0-q1}, [r1 :128] @ Top ++ lsl r3, #1 ++ vdup.16 q2, ip ++ add ip, r0, r3 ++ vhsub.u16 q0, q2 ++ add ip, #16 ++ vhsub.u16 q1, q2 ++ mov r1, #16-2 ++ vld1.16 {d4[],d5[]}, [r2]! ++ vmov.i16 q3, #0 ++ vadd.u16 q0, q2 ++ vadd.i16 q1, q2 ++ vmov.i16 q2, #0x3ff ++ vmax.s16 q0, q3 ++ vmax.s16 q1, q3 ++ vld1.16 {d6[],d7[]}, [r2]! ++ vmin.s16 q0, q2 ++ vmin.s16 q1, q2 ++ vst1.16 {q0-q1}, [r0 :128], r3 ++1: ++ vld1.16 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.16 {q3}, [r0 :128], r3 ++ vst1.16 {q3}, [ip :128], r3 ++ vld1.16 {d6[],d7[]}, [r2]! ++ vst1.16 {q0}, [r0 :128], r3 ++ vst1.16 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.16 {q3}, [r0 :128] ++ vst1.16 {q3}, [ip :128] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_32_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_32_neon_10, export=1 ++ vld1.16 {d0[],d1[]}, [r2]! ++ add ip, r0, #16 ++ push {lr} ++ mov lr, #32 ++ vld1.16 {d2[],d3[]}, [r2]! ++ lsl r3, #1 ++ vst1.16 {q0}, [r0 :128], lr ++ sub r3, #32 ++ vst1.16 {q0}, [ip :128], lr ++ mov r1, #32-2 ++ vst1.16 {q0}, [r0 :128], r3 ++ vst1.16 {q0}, [ip :128], r3 ++1: ++ vld1.16 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.16 {q1}, [r0 :128], lr ++ vst1.16 {q1}, [ip :128], lr ++ vst1.16 {q1}, [r0 :128], r3 ++ vst1.16 {q1}, [ip :128], r3 ++ vld1.16 {d2[],d3[]}, [r2]! ++ vst1.16 {q0}, [r0 :128], lr ++ vst1.16 {q0}, [ip :128], lr ++ vst1.16 {q0}, [r0 :128], r3 ++ vst1.16 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.16 {q1}, [r0 :128], lr ++ vst1.16 {q1}, [ip :128], lr ++ vst1.16 {q1}, [r0 :128] ++ vst1.16 {q1}, [ip :128] ++ pop {pc} ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_4_neon_10, export=1 ++ add r1, r2, #4 ++ vld1.32 {d0[],d1[]}, [r2] ++ add r2, #8 ++ vld1.32 {d2[],d3[]}, [r1] ++ add r1, #8 ++ vld1.32 {d4[],d5[]}, [r2] ++A add r2, r0, r3, lsl #2 ++T lsl r3, #2 ++T add r2, r0, r3 ++ vld1.32 {d6[],d7[]}, [r1] ++A lsl r3, #3 ++T lsl r3, #1 ++ vst1.32 {q0}, [r0 :128], r3 ++ vst1.32 {q1}, [r2 :128], r3 ++ vst1.32 {q2}, [r0 :128] ++ vst1.32 {q3}, [r2 :128] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_8_neon_10, export=1 ++ vld1.32 {d0[],d1[]}, [r2]! ++ lsl r3, #2 ++ add ip, r0, #16 ++ mov r1, #8-2 ++ vld1.32 {d2[],d3[]}, [r2]! ++ vst1.32 {q0}, [r0 :128], r3 ++ vst1.32 {q0}, [ip :128], r3 ++1: ++ vld1.32 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.32 {q1}, [r0 :128], r3 ++ vst1.32 {q1}, [ip :128], r3 ++ vld1.32 {d2[],d3[]}, [r2]! ++ vst1.32 {q0}, [r0 :128], r3 ++ vst1.32 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.32 {q1}, [r0 :128] ++ vst1.32 {q1}, [ip :128] ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_horizontal_c_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_horizontal_c_16_neon_10, export=1 ++ vld1.32 {d0[],d1[]}, [r2]! ++ add ip, r0, #16 ++ push {lr} ++ mov lr, #32 ++ vld1.32 {d2[],d3[]}, [r2]! ++ lsl r3, #2 ++ vst1.32 {q0}, [r0 :128], lr ++ sub r3, #32 ++ vst1.32 {q0}, [ip :128], lr ++ mov r1, #16-2 ++ vst1.32 {q0}, [r0 :128], r3 ++ vst1.32 {q0}, [ip :128], r3 ++1: ++ vld1.32 {d0[],d1[]}, [r2]! ++ subs r1, #2 ++ vst1.32 {q1}, [r0 :128], lr ++ vst1.32 {q1}, [ip :128], lr ++ vst1.32 {q1}, [r0 :128], r3 ++ vst1.32 {q1}, [ip :128], r3 ++ vld1.32 {d2[],d3[]}, [r2]! ++ vst1.32 {q0}, [r0 :128], lr ++ vst1.32 {q0}, [ip :128], lr ++ vst1.32 {q0}, [r0 :128], r3 ++ vst1.32 {q0}, [ip :128], r3 ++ bne 1b ++ ++ vst1.32 {q1}, [r0 :128], lr ++ vst1.32 {q1}, [ip :128], lr ++ vst1.32 {q1}, [r0 :128] ++ vst1.32 {q1}, [ip :128] ++ pop {pc} ++endfunc ++ ++ ++ +diff --git a/libavcodec/arm/rpi_hevcpred_intra_planar_neon.S b/libavcodec/arm/rpi_hevcpred_intra_planar_neon.S +new file mode 100644 +index 0000000000..af8c4c03f0 +--- /dev/null ++++ b/libavcodec/arm/rpi_hevcpred_intra_planar_neon.S +@@ -0,0 +1,1043 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#include "libavutil/arm/asm.S" ++#include "neon.S" ++ ++@ Planar intra pred (8.4.4.2.4) ++@ ++@ predSamples[ x ][ y ] = ++@ ( ( nTbS - 1 - x ) * p[ -1 ][ y ] + ++@ ( x + 1 ) * p[ nTbS ][ -1 ] + ++@ ( nTbS - 1 - y ) * p[ x ][ -1 ] + ++@ ( y + 1 ) * p[ -1 ][ nTbS ] + nTbS ) >> ( Log2( nTbS ) + 1 ) ++ ++@ All 10-bit functions would work with 9 ++ ++ ++@ ff_hevc_rpi_pred_planar_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_4_neon_8, export=1 ++ ++ vld1.8 {d0}, [r1] @ Top ++ adr ip, nb_3_0_1_4 ++ vld1.8 {d1}, [r2] @ Left ++ vmov.i64 d2, #0xffffffff ++ vldr d3, [ip, #8] @ {1,2,3,4,1,2,3,4} ++ add r1, r0, r3 ++ vdup.32 d4, d0[0] @ {t0,t1,t2,t3,t0,t1,t2,t3} ++ vdup.8 d0, d0[4] @ {t4,t4,t4,t4,t4,t4,t4,t4} ++ vdup.8 d5, d1[4] @ {l4,l4,l4,l4,l4,l4,l4,l4} ++ vdup.8 d6, d1[0] @ {l0,l0,l0,l0,l0,l0,l0,l0} ++ vshll.u8 q8, d4, #2 ++ lsl r3, #1 ++ vsubl.u8 q2, d5, d4 ++ vmlal.u8 q8, d0, d3 ++ vld1.8 {d0}, [ip] @ {3,2,1,0,3,2,1,0} ++ vdup.8 d7, d1[1] @ {l1,l1,l1,l1,l1,l1,l1,l1} ++ vshl.s16 q9, q2, #1 ++ vbif d6, d7, d2 @ {l0,l0,l0,l0,l1,l1,l1,l1} ++ vadd.i16 d16, d4 ++ vdup.8 d7, d1[2] @ {l2,l2,l2,l2,l2,l2,l2,l2} ++ vadd.i16 d17, d18 ++ vdup.8 d1, d1[3] @ {l3,l3,l3,l3,l3,l3,l3,l3} ++ vadd.i16 q2, q8, q9 ++ vmlal.u8 q8, d0, d6 ++ vbif d7, d1, d2 @ {l2,l2,l2,l2,l3,l3,l3,l3} ++ vmlal.u8 q2, d0, d7 ++ vrshrn.i16 d0, q8, #3 ++ vst1.32 d0[0], [r0 :32], r3 ++ vst1.32 d0[1], [r1 :32], r3 ++ vrshrn.i16 d0, q2, #3 ++ vst1.32 d0[0], [r0 :32] ++ vst1.32 d0[1], [r1 :32] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_4_neon_10, export=1 ++ @ Load from bytes & expand later - at the very least this uses less ++ @ memory than having a short table ++ vld1.16 {q0}, [r1 :64] @ Top ++ adr ip, nbh_3_0_1_4 ++ vldr d2, [r2, #8] @ Left (lower) ++ vldr d3, [ip, #8] @ {1,2,3,4} ++T lsl r3, #1 ++ vshl.s16 d4, d0, #2 ++ vdup.16 d1, d1[0] @ {t4,t4,t4,t4} ++ vldr d5, [r2] @ Left (upper) ++ vdup.16 d2, d2[0] @ {l4,l4,l4,l4} ++ vldr d6, [ip] @ {3,2,1,0} ++ vmla.i16 d4, d3, d1 @ Acc set up ++ vsub.i16 d0, d2, d0 @ Add set up ++ vmov d7, d6 ++ vdup.16 d2, d5[0] ++ vdup.16 d3, d5[1] ++ vdup.16 d16, d5[2] ++ vadd.i16 d18, d0, d4 ++ vshl.s16 d0, #1 @ x2 ++ vadd.i16 d19, d0, d4 ++ vdup.16 d17, d5[3] ++ vadd.i16 d4, d0, d18 ++A add r1, r0, r3, lsl #1 ++T add r1, r0, r3 ++ vadd.i16 d5, d0, d19 ++A lsl r3, #2 ++T lsl r3, #1 ++ vmla.i16 q9, q1, q3 ++ vmla.i16 q2, q8, q3 ++ vrshr.u16 q0, q9, #3 ++ vst1.16 {d0}, [r0], r3 ++ vrshr.u16 d2, d4, #3 ++ vst1.16 {d1}, [r1], r3 ++ vrshr.u16 d3, d5, #3 ++ vst1.16 {d2}, [r0] ++ vst1.16 {d3}, [r1] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_8_neon_8, export=1 ++ ++ vld1.8 {q0}, [r1] @ Top ++ adr ip, nb_7_0_1_8 ++ vldr d2, [r2, #8] @ Left (lower) ++ mov r1, #8 ++ vldr d3, [ip, #8] @ {1,2,3,4,5,6,7,8} ++ vshll.u8 q2, d0, #3 ++ vdup.8 d1, d1[0] @ {t8,t8,t8,t8,t8,t8,t8,t8} ++ vdup.8 d2, d2[0] @ {l8,l8,l8,l8,l8,l8,l8,l8} ++ vldr d6, [r2] @ Left (upper) ++ vmlal.u8 q2, d3, d1 ++ vsubl.u8 q0, d2, d0 ++ vldr d7, [ip] @ {7,6,5,4,3,2,1,0} ++ ++@ u8 7..0 [1] d7 ++@ u8 left[y] [1] d6 ++@ u16 acc [2] q2 (even rows) or q8 (odd rows) = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q0 = p[-1][nTbs] - p[x][-1] ++ ++ vdup.8 d2, d6[0] ++ vadd.i16 q2, q0 ++ vdup.8 d3, d6[1] ++ vadd.i16 q8, q2, q0 ++1: ++ vmlal.u8 q2, d7, d2 ++ subs r1, #2 ++ vadd.i16 q9, q8, q0 ++ vmlal.u8 q8, d7, d3 ++ vdup.8 d2, d6[2] ++ vdup.8 d3, d6[3] ++ vrshrn.i16 d20, q2, #4 ++ vshr.u64 d6, #16 ++ vmov q2, q9 ++ vst1.8 {d20}, [r0], r3 ++ vrshrn.i16 d20, q8, #4 ++ vadd.i16 q8, q2, q0 ++ vst1.8 {d20}, [r0], r3 ++ bne 1b ++ ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_8_neon_10, export=1 ++ ++ adr ip, nb_7_0_1_8 ++ vld1.16 {q0}, [r1 :128]! @ Top (left) ++ lsl r3, #1 ++ vld1.16 {q1}, [ip :128] @ {7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8} ++ add ip, r2, #16 ++ vld1.16 {d4[],d5[]}, [r1] @ Top (right) ++ mov r1, #8-2 ++ vshl.s16 q3, q0, #3 ++ vmovl.u8 q8, d3 @ {1,2,3,4,5,6,7,8} ++ vld1.16 {d18[],d19[]}, [ip] @ Left (lower) ++ vmla.i16 q3, q8, q2 @ Acc set up ++ vsub.i16 q0, q9, q0 @ Add set up ++ vmovl.u8 q1, d2 @ {7,6,5,4,3,2,1,0} ++ vadd.i16 q2, q3, q0 ++ ++@ u16 7..0 [1] q1 ++@ u32 left[y] [1] [r2] ++@ u16 acc [1] q3 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [1] q0 = p[-1][nTbs] - p[x][-1] ++ ++ vld1.16 {d6[],d7[]}, [r2]! ++ vadd.i16 q8, q2, q0 ++ vld1.16 {d18[],d19[]}, [r2]! ++ vmla.i16 q2, q1, q3 ++ vadd.i16 q3, q8, q0 ++ vmla.i16 q8, q1, q9 ++1: ++ vrshr.u16 q9, q2, #4 ++ subs r1, #2 ++ vmov q2, q3 ++ vrshr.u16 q10, q8, #4 ++ vld1.16 {d6[],d7[]}, [r2]! ++ vst1.16 {q9}, [r0 :128], r3 ++ vadd.i16 q8, q2, q0 ++ vld1.16 {d18[],d19[]}, [r2]! ++ vmla.i16 q2, q1, q3 ++ vadd.i16 q3, q8, q0 ++ vmla.i16 q8, q1, q9 ++ vst1.16 {q10}, [r0 :128], r3 ++ bne 1b ++ ++ vrshr.u16 q9, q2, #4 ++ add r3, r0 ++ vrshr.u16 q10, q8, #4 ++ vst1.16 {q9}, [r0 :128] ++ vst1.16 {q10}, [r3 :128] ++ ++ bx lr ++endfunc ++ ++ ++@------------------------------------------------------------------------------ ++@ ++@ Data - has to be in two lumps to ensure we can always reach using adr ++ ++ .balign 64 ++ ++nb_31_0_1_32: ++ .byte 31, 30, 29, 28, 27, 26, 25, 24 ++ .byte 23, 22, 21, 20, 19, 18, 17, 16 ++nb_15_0_1_16: ++ .byte 15, 14, 13, 12, 11, 10, 9, 8 ++ .byte 7, 6, 5, 4, 3, 2, 1, 0 ++ .byte 1, 2, 3, 4, 5, 6, 7, 8 ++ .byte 9, 10, 11, 12, 13, 14, 15, 16 ++ .byte 17, 18, 19, 20, 21, 22, 23, 24 ++ .byte 25, 26, 27, 28, 29, 30, 31, 32 ++ ++ @ should be back on a 64-byte boundary here ++ ++ @ These could be extracted from the above array, but separate out ++ @ out for better (16 byte) alignment ++nb_3_0_1_4: ++ .byte 3, 2, 1, 0, 3, 2, 1, 0 ++ .byte 1, 2, 3, 4, 1, 2, 3, 4 ++nb_7_0_1_8: ++ .byte 7, 6, 5, 4, 3, 2, 1, 0 ++ .byte 1, 2, 3, 4, 5, 6, 7, 8 ++nbh_3_0_1_4: ++ .short 3, 2, 1, 0, 1, 2, 3, 4 ++ ++@------------------------------------------------------------------------------ ++ ++ ++@ ff_hevc_rpi_pred_planar_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_16_neon_8, export=1 ++ ++ adr ip, nb_15_0_1_16 + 16 ++ vld1.8 {q0}, [r1 :128]! @ Top (left) ++ add r2, #16 ++ vld1.8 {q1}, [ip: 128] @ {1,2,3...16} ++ vld1.8 {d4[]}, [r1] @ Top (right) ++ sub ip, #16 ++ vshll.u8 q3, d0, #4 ++ mov r1, #16 ++ vshll.u8 q8, d1, #4 ++ vld1.8 {d5[]}, [r2] @ Left (lower) ++ sub r2, #16 ++ vmlal.u8 q3, d2, d4 ++ vmlal.u8 q8, d3, d4 @ Acc set up ++ vsubl.u8 q1, d5, d0 ++ vsubl.u8 q0, d5, d1 @ Add set up ++ vld1.8 {q2}, [ip :128] @ {15,14,13...0} ++ ++@ u8 15..0 [1] q2 ++@ u8 left[y] [1] [r2] ++@ u16 acc [2] q3,q8 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q1,q0 = p[-1][nTbs] - p[x][-1] ++ ++ vadd.i16 q3, q1 ++ vadd.i16 q8, q0 ++1: ++ vadd.i16 q10, q3, q1 ++ subs r1, #2 ++ vld1.8 {d18[]}, [r2]! ++ vadd.i16 q11, q8, q0 ++ vld1.8 {d19[]}, [r2]! ++ vmlal.u8 q3, d4, d18 ++ vmlal.u8 q8, d5, d18 ++ vadd.i16 q12, q10, q1 ++ vmlal.u8 q10, d4, d19 ++ vadd.i16 q13, q11, q0 ++ vmlal.u8 q11, d5, d19 ++ vrshrn.u16 d18, q3, #5 ++ vrshrn.u16 d19, q8, #5 ++ vmov q3, q12 ++ vst1.8 {q9}, [r0 :128], r3 ++ vrshrn.u16 d18, q10, #5 ++ vrshrn.u16 d19, q11, #5 ++ vmov q8, q13 ++ vst1.8 {q9}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_16_neon_10, export=1 ++ ++ @ Load from bytes & expand later - at the very least this uses less ++ @ memory than having a short table ++ adr ip, nb_15_0_1_16 + 16 ++ vld1.16 {q0-q1}, [r1 :128]! @ Top (left) ++ add r2, #32 ++ vld1.8 {q2}, [ip :128] @ {1,2,3...16} ++ lsl r3, #1 ++ vld1.16 {d6[],d7[]}, [r1] @ Top (right) ++ sub ip, #16 ++ vmovl.u8 q8, d4 ++ mov r1, #16 ++ vshl.i16 q9, q0, #4 ++ vmovl.u8 q2, d5 ++ vshl.i16 q10, q1, #4 ++ vld1.16 {d22[],d23[]}, [r2] @ Left (lower) ++ sub r2, #32 ++ vld1.8 {q12}, [ip] @ {15,14,13...0} ++ vmla.i16 q9, q8, q3 ++ vmla.i16 q10, q2, q3 @ Acc set up ++ vsub.i16 q0, q11, q0 ++ vsub.i16 q1, q11, q1 @ Add set up ++ vadd.i16 q2, q9, q0 ++ vadd.i16 q3, q10, q1 ++ vmovl.u8 q8, d24 ++ vmovl.u8 q9, d25 ++ ++@ u16 15..0 [2] q8,q9 ++@ u32 left[y] [2] [r2] ++@ u16 acc [2] q2,q3 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q0,q1 = p[-1][nTbs] - p[x][-1] ++ ++1: ++ vadd.i16 q10, q2, q0 ++ subs r1, #2 ++ vld1.16 {d24[],d25[]}, [r2]! ++ vadd.i16 q11, q3, q1 ++ vld1.16 {d28[],d29[]}, [r2]! ++ vmla.i16 q2, q8, q12 ++ vmla.i16 q3, q9, q12 ++ vadd.i16 q12, q10, q0 ++ vmla.i16 q10, q8, q14 ++ vadd.i16 q13, q11, q1 ++ vmla.i16 q11, q9, q14 ++ vrshr.u16 q14, q2, #5 ++ vrshr.u16 q15, q3, #5 ++ vmov q2, q12 ++ vst1.16 {q14-q15}, [r0 :128], r3 ++ vrshr.u16 q14, q10, #5 ++ vrshr.u16 q15, q11, #5 ++ vmov q3, q13 ++ vst1.16 {q14-q15}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_32_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_32_neon_8, export=1 ++ ++ vld1.8 {q0-q1}, [r1 :128]! @ Top (left) ++ adr ip, nb_31_0_1_32 + 32 ++ vpush {d8-d12} ++ vld1.8 {q2-q3}, [ip :128] @ {1,2,3...32} ++ add r2, #32 ++ vld1.8 {d8[]}, [r1] @ Top (right) ++ sub ip, #32 ++ vshll.u8 q8, d0, #5 ++ mov r1, #32 ++ vld1.8 {d9[]}, [r2] @ Left (lower) ++ sub r2, #32 ++ vshll.u8 q9, d1, #5 ++ vshll.u8 q10, d2, #5 ++ vshll.u8 q11, d3, #5 ++ vmlal.u8 q8, d4, d8 ++ vsubl.u8 q12, d9, d0 ++ vmlal.u8 q9, d5, d8 ++ vsubl.u8 q13, d9, d1 ++ vmlal.u8 q10, d6, d8 ++ vsubl.u8 q14, d9, d2 ++ vmlal.u8 q11, d7, d8 @ Acc set up ++ vsubl.u8 q15, d9, d3 @ Add set up ++ vadd.i16 q8, q12 ++ vadd.i16 q9, q13 ++ vadd.i16 q10, q14 ++ vadd.i16 q11, q15 ++ vld1.8 {q4-q5}, [ip :128] @ {31,30,29...0} ++ ++@ u8 31..0 [2] q4,q5 ++@ u8 left[y] [2] [r2] ++@ u16 acc [4] q8-q11 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [4] q12-q15 = p[-1][nTbs] - p[x][-1] ++ ++ vld1.8 {d12[]}, [r2]! ++ vadd.i16 q0, q8, q12 ++ b 2f ++1: ++ vld1.8 {d12[]}, [r2]! ++ vrshrn.u16 d3, q1, #6 ++ vrshrn.u16 d2, q0, #6 ++ vadd.i16 q0, q8, q12 ++ vrshrn.u16 d4, q2, #6 ++ vrshrn.u16 d5, q3, #6 ++ vst1.8 {q1-q2}, [r0 :128], r3 ++2: vadd.i16 q1, q9, q13 ++ subs r1, #2 ++ vadd.i16 q2, q10, q14 ++ vadd.i16 q3, q11, q15 ++ vmlal.u8 q8, d8, d12 ++ vmlal.u8 q9, d9, d12 ++ vmlal.u8 q10, d10, d12 ++ vmlal.u8 q11, d11, d12 ++ vld1.8 {d12[]}, [r2]! ++ vrshrn.u16 d19, q9, #6 ++ vrshrn.u16 d18, q8, #6 ++ vadd.i16 q8, q0, q12 ++ vrshrn.u16 d20, q10, #6 ++ vrshrn.u16 d21, q11, #6 ++ vst1.8 {q9-q10}, [r0 :128], r3 ++ vadd.i16 q9, q1, q13 ++ vadd.i16 q10, q2, q14 ++ vadd.i16 q11, q3, q15 ++ vmlal.u8 q0, d8, d12 ++ vmlal.u8 q1, d9, d12 ++ vmlal.u8 q2, d10, d12 ++ vmlal.u8 q3, d11, d12 ++ ++ bne 1b ++ ++ vpop {d8-d12} ++ ++ vrshrn.u16 d3, q1, #6 ++ vrshrn.u16 d2, q0, #6 ++ vrshrn.u16 d4, q2, #6 ++ vrshrn.u16 d5, q3, #6 ++ vst1.8 {q1-q2}, [r0 :128] ++ ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_32_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_32_neon_10, export=1 ++ ++ @ Load from bytes & expand later - at the very least this uses less ++ @ memory than having a short table ++ vld1.16 {q0-q1}, [r1 :128]! @ Top (left) ++ adr ip, nb_31_0_1_32 + 32 ++ vpush {q4-q7} ++ vld1.16 {q2-q3}, [r1 :128]! @ Top (centre) ++ add r2, #64 ++ vld1.8 {q14-q15}, [ip :128] @ {1,2,3...32} ++T lsl r3, #1 ++ vld1.16 {d8[],d9[]}, [r1] @ Top (right) ++ sub ip, #32 ++ vmovl.u8 q12, d28 ++ mov r1, #32 ++ vmovl.u8 q13, d29 ++ vld1.8 {q6-q7}, [ip :128] @ {31,30,29...0} ++ vmovl.u8 q14, d30 ++ vmovl.u8 q15, d31 ++ vld1.16 {d10[],d11[]}, [r2] @ Left (lower) ++ sub r2, #64 ++ vshl.i16 q8, q0, #5 ++ vshl.i16 q9, q1, #5 ++ vshl.i16 q10, q2, #5 ++ vshl.i16 q11, q3, #5 ++ vmla.i16 q8, q12, q4 ++ vsub.i16 q0, q5, q0 ++ vmla.i16 q9, q13, q4 ++ vsub.i16 q1, q5, q1 ++ vmla.i16 q10, q14, q4 ++ vmov.u16 ip, d0[0] ++ vsub.i16 q2, q5, q2 ++ vmla.i16 q11, q15, q4 @ Acc set up ++ vsub.i16 q3, q5, q3 @ Add set up ++ vadd.i16 q8, q0 ++ vadd.i16 q9, q1 ++ vadd.i16 q10, q2 ++ vadd.i16 q11, q3 ++ vmovl.u8 q4, d12 ++ vmovl.u8 q5, d13 ++ vmovl.u8 q6, d14 ++ vmovl.u8 q7, d15 ++ ++@ u16 31..0 [4] q4-q7 ++@ u16 left[y] [4] [r2] ++@ u16 acc [4] q8-q11 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [4] q0-q3 = p[-1][nTbs] - p[x][-1] ++ ++ vadd.i16 q12, q8, q0 ++A sub r0, r0, r3, lsl #1 ++T sub r0, r3 ++1: ++ vld1.16 {d0[0]}, [r2]! ++A add r0, r0, r3, lsl #1 ++T add r0, r3 ++ vadd.i16 q13, q9, q1 ++ subs r1, #2 ++ vadd.i16 q14, q10, q2 ++ vadd.i16 q15, q11, q3 ++ vmla.i16 q8, q4, d0[0] ++ vmla.i16 q9, q5, d0[0] ++ vmla.i16 q10, q6, d0[0] ++ vmla.i16 q11, q7, d0[0] ++ vmov.16 d0[0], ip ++ vrshr.u16 q8, #6 ++ vrshr.u16 q9, #6 ++ vrshr.u16 q10, #6 ++ vrshr.u16 q11, #6 ++ vstm r0, {q8-q11} ++ vadd.i16 q8, q12, q0 ++A add r0, r0, r3, lsl #1 ++T add r0, r3 ++ vld1.16 {d0[0]}, [r2]! ++ vadd.i16 q9, q13, q1 ++ vadd.i16 q10, q14, q2 ++ vadd.i16 q11, q15, q3 ++ vmla.i16 q12, q4, d0[0] ++ vmla.i16 q13, q5, d0[0] ++ vmla.i16 q14, q6, d0[0] ++ vmla.i16 q15, q7, d0[0] ++ vmov.16 d0[0], ip ++ vrshr.u16 q12, #6 ++ vrshr.u16 q13, #6 ++ vrshr.u16 q14, #6 ++ vrshr.u16 q15, #6 ++ vstm r0, {q12-q15} ++ vadd.i16 q12, q8, q0 ++ bne 1b ++ ++ vpop {q4-q7} ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_c_4_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_4_neon_8, export=1 ++ ++ vld1.8 {q0}, [r1] @ Top ++ adr ip, nbx2_3_0_1_4 ++ vldr d2, [r2, #8] @ Left (lower) ++ mov r1, #4 ++ vldr d3, [ip, #8] @ {1,1,2,2,3,3,4,4} ++ lsl r3, #1 ++ vshll.u8 q2, d0, #2 ++ vdup.16 d1, d1[0] @ {t4,t4,t4,t4,t4,t4,t4,t4} ++ vdup.16 d2, d2[0] @ {l4,l4,l4,l4,l4,l4,l4,l4} ++ vldr d6, [r2] @ Left (upper) ++ vmlal.u8 q2, d3, d1 ++ vsubl.u8 q0, d2, d0 ++ vldr d7, [ip] @ {3,3,2,2,1,1,0,0} ++ ++@ u8 3..0 [1] d7 ++@ u8 left[y] [1] d6 ++@ u16 acc [2] q2 (even rows) or q8 (odd rows) = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q0 = p[-1][nTbs] - p[x][-1] ++ ++ vdup.16 d2, d6[0] ++ vadd.i16 q2, q0 ++ vdup.16 d3, d6[1] ++ vadd.i16 q8, q2, q0 ++1: ++ vmlal.u8 q2, d7, d2 ++ subs r1, #2 ++ vadd.i16 q9, q8, q0 ++ vmlal.u8 q8, d7, d3 ++ vdup.16 d2, d6[2] ++ vdup.16 d3, d6[3] ++ vrshrn.i16 d20, q2, #3 ++ vmov q2, q9 ++ vst1.8 {d20}, [r0], r3 ++ vrshrn.i16 d20, q8, #3 ++ vadd.i16 q8, q2, q0 ++ vst1.8 {d20}, [r0], r3 ++ bne 1b ++ ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_c_4_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_4_neon_10, export=1 ++ ++ adr ip, nbx2_3_0_1_4 ++ vld1.16 {q0}, [r1 :128]! @ Top (left) ++ lsl r3, #2 ++ vld1.16 {q1}, [ip :128] @ {3,3,2,2,1,1,0,0,1,1,2,2,3,3,4,4} ++ add ip, r2, #16 ++ vld1.32 {d4[],d5[]}, [r1] @ Top (right) ++ vshl.s16 q3, q0, #2 ++ vmovl.u8 q8, d3 @ {1,1,2,2,3,3,4,4} ++ vld1.32 {d18[],d19[]}, [ip] @ Left (lower) ++ vmla.i16 q3, q8, q2 @ Acc set up ++ vsub.i16 q0, q9, q0 @ Add set up ++ vmovl.u8 q1, d2 @ {3,3,2,2,1,1,0,0} ++ vadd.i16 q2, q3, q0 ++ ++@ u16 3..0 [1] q1 ++@ u32 left[y] [1] [r2] ++@ u16 acc [1] q3 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [1] q0 = p[-1][nTbs] - p[x][-1] ++ ++ vld1.32 {d6[],d7[]}, [r2]! ++ vadd.i16 q8, q2, q0 ++ vld1.32 {d18[],d19[]}, [r2]! ++ vmla.i16 q2, q1, q3 ++ vadd.i16 q3, q8, q0 ++ vmla.i16 q8, q1, q9 ++ ++ vrshr.u16 q9, q2, #3 ++ vmov q2, q3 ++ vrshr.u16 q10, q8, #3 ++ vld1.32 {d6[],d7[]}, [r2]! ++ vst1.16 {q9}, [r0 :128], r3 ++ vadd.i16 q8, q2, q0 ++ vld1.32 {d18[],d19[]}, [r2]! ++ vmla.i16 q2, q1, q3 ++ vadd.i16 q3, q8, q0 ++ vmla.i16 q8, q1, q9 ++ vst1.16 {q10}, [r0 :128], r3 ++ ++ vrshr.u16 q9, q2, #3 ++ add r3, r0 ++ vrshr.u16 q10, q8, #3 ++ vst1.16 {q9}, [r0 :128] ++ vst1.16 {q10}, [r3 :128] ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_c_8_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_8_neon_8, export=1 ++ ++ adr ip, nbx2_7_0_1_8 + 16 ++ vld1.8 {q0}, [r1 :128]! @ Top (left) ++ add r2, #16 ++ vld1.8 {q1}, [ip: 128] @ {1,1,2,2,3,3...8,8} ++ lsl r3, #1 ++ vld1.16 {d4[]}, [r1] @ Top (right) ++ sub ip, #16 ++ vshll.u8 q3, d0, #3 ++ mov r1, #8 ++ vshll.u8 q8, d1, #3 ++ vld1.16 {d5[]}, [r2] @ Left (lower) ++ sub r2, #16 ++ vmlal.u8 q3, d2, d4 ++ vmlal.u8 q8, d3, d4 @ Acc set up ++ vsubl.u8 q1, d5, d0 ++ vsubl.u8 q0, d5, d1 @ Add set up ++ vld1.8 {q2}, [ip :128] @ {7,7,6,6,5,5...0,0} ++ ++@ u8 7..0 [1] q2 ++@ u8 left[y] [1] [r2] ++@ u16 acc [2] q3,q8 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q1,q0 = p[-1][nTbs] - p[x][-1] ++ ++ vadd.i16 q3, q1 ++ vadd.i16 q8, q0 ++1: ++ vadd.i16 q10, q3, q1 ++ subs r1, #2 ++ vld1.16 {d18[]}, [r2]! ++ vadd.i16 q11, q8, q0 ++ vld1.16 {d19[]}, [r2]! ++ vmlal.u8 q3, d4, d18 ++ vmlal.u8 q8, d5, d18 ++ vadd.i16 q12, q10, q1 ++ vmlal.u8 q10, d4, d19 ++ vadd.i16 q13, q11, q0 ++ vmlal.u8 q11, d5, d19 ++ vrshrn.u16 d18, q3, #4 ++ vrshrn.u16 d19, q8, #4 ++ vmov q3, q12 ++ vst1.8 {q9}, [r0 :128], r3 ++ vrshrn.u16 d18, q10, #4 ++ vrshrn.u16 d19, q11, #4 ++ vmov q8, q13 ++ vst1.8 {q9}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++ ++endfunc ++ ++ ++@------------------------------------------------------------------------------ ++@ ++@ Data - has to be in two lumps to ensure we can always reach using adr ++ ++ .balign 64 ++ ++nbx2_15_0_1_16: ++ .byte 15, 15, 14, 14, 13, 13, 12, 12 ++ .byte 11, 11, 10, 10, 9, 9, 8, 8 ++nbx2_7_0_1_8: ++ .byte 7, 7, 6, 6, 5, 5, 4, 4 ++ .byte 3, 3, 2, 2, 1, 1, 0, 0 ++ .byte 1, 1, 2, 2, 3, 3, 4, 4 ++ .byte 5, 5, 6, 6, 7, 7, 8, 8 ++ .byte 9, 9, 10, 10, 11, 11, 12, 12 ++ .byte 13, 13, 14, 14, 15, 15, 16, 16 ++ ++ @ should be back on a 64-byte boundary here ++ ++nbx2_3_0_1_4: ++ .byte 3, 3, 2, 2, 1, 1, 0, 0 ++ .byte 1, 1, 2, 2, 3, 3, 4, 4 ++ ++@------------------------------------------------------------------------------ ++ ++ ++@ ff_hevc_rpi_pred_planar_c_8_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_8_neon_10, export=1 ++ ++ @ Load from bytes & expand later - at the very least this uses less ++ @ memory than having a short table ++ adr ip, nbx2_7_0_1_8 + 16 ++ vld1.16 {q0-q1}, [r1 :128]! @ Top (left) ++ add r2, #32 ++ vld1.8 {q2}, [ip :128] @ {1,1,2,2,3,3...8,8} ++ lsl r3, #2 ++ vld1.32 {d6[],d7[]}, [r1] @ Top (right) ++ sub ip, #16 ++ vmovl.u8 q8, d4 ++ mov r1, #8 ++ vshl.i16 q9, q0, #3 ++ vmovl.u8 q2, d5 ++ vshl.i16 q10, q1, #3 ++ vld1.32 {d22[],d23[]}, [r2] @ Left (lower) ++ sub r2, #32 ++ vld1.8 {q12}, [ip] @ {7,7,6,6,5,5...0,0} ++ vmla.i16 q9, q8, q3 ++ vmla.i16 q10, q2, q3 @ Acc set up ++ vsub.i16 q0, q11, q0 ++ vsub.i16 q1, q11, q1 @ Add set up ++ vadd.i16 q2, q9, q0 ++ vadd.i16 q3, q10, q1 ++ vmovl.u8 q8, d24 ++ vmovl.u8 q9, d25 ++ ++@ u16 7..0 [2] q8,q9 ++@ u32 left[y] [2] [r2] ++@ u16 acc [2] q2,q3 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [2] q0,q1 = p[-1][nTbs] - p[x][-1] ++ ++1: ++ vadd.i16 q10, q2, q0 ++ subs r1, #2 ++ vld1.32 {d24[],d25[]}, [r2]! ++ vadd.i16 q11, q3, q1 ++ vld1.32 {d28[],d29[]}, [r2]! ++ vmla.i16 q2, q8, q12 ++ vmla.i16 q3, q9, q12 ++ vadd.i16 q12, q10, q0 ++ vmla.i16 q10, q8, q14 ++ vadd.i16 q13, q11, q1 ++ vmla.i16 q11, q9, q14 ++ vrshr.u16 q14, q2, #4 ++ vrshr.u16 q15, q3, #4 ++ vmov q2, q12 ++ vst1.16 {q14-q15}, [r0 :128], r3 ++ vrshr.u16 q14, q10, #4 ++ vrshr.u16 q15, q11, #4 ++ vmov q3, q13 ++ vst1.16 {q14-q15}, [r0 :128], r3 ++ bne 1b ++ ++ bx lr ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_c_16_neon_8 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_16_neon_8, export=1 ++ ++ vld1.8 {q0-q1}, [r1 :128]! @ Top (left) ++ adr ip, nbx2_15_0_1_16 + 32 ++ vpush {d8-d12} ++ vld1.8 {q2-q3}, [ip :128] @ {1,1,2,2,3,3...16,16} ++ add r2, #32 ++ vld1.16 {d8[]}, [r1] @ Top (right) ++ sub ip, #32 ++ vshll.u8 q8, d0, #4 ++ mov r1, #16 ++ vld1.16 {d9[]}, [r2] @ Left (lower) ++ sub r2, #32 ++ vshll.u8 q9, d1, #4 ++ lsl r3, #1 ++ vshll.u8 q10, d2, #4 ++ vshll.u8 q11, d3, #4 ++ vmlal.u8 q8, d4, d8 ++ vsubl.u8 q12, d9, d0 ++ vmlal.u8 q9, d5, d8 ++ vsubl.u8 q13, d9, d1 ++ vmlal.u8 q10, d6, d8 ++ vsubl.u8 q14, d9, d2 ++ vmlal.u8 q11, d7, d8 @ Acc set up ++ vsubl.u8 q15, d9, d3 @ Add set up ++ vadd.i16 q8, q12 ++ vadd.i16 q9, q13 ++ vadd.i16 q10, q14 ++ vadd.i16 q11, q15 ++ vld1.8 {q4-q5}, [ip :128] @ {15,15,14,14,13,13...0,0} ++ ++@ u8 15..0 [2] q4,q5 ++@ u8 left[y] [2] [r2] ++@ u16 acc [4] q8-q11 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [4] q12-q15 = p[-1][nTbs] - p[x][-1] ++ ++ vld1.16 {d12[]}, [r2]! ++ vadd.i16 q0, q8, q12 ++ b 2f ++1: ++ vld1.16 {d12[]}, [r2]! ++ vrshrn.u16 d3, q1, #5 ++ vrshrn.u16 d2, q0, #5 ++ vadd.i16 q0, q8, q12 ++ vrshrn.u16 d4, q2, #5 ++ vrshrn.u16 d5, q3, #5 ++ vst1.8 {q1-q2}, [r0 :128], r3 ++2: vadd.i16 q1, q9, q13 ++ subs r1, #2 ++ vadd.i16 q2, q10, q14 ++ vadd.i16 q3, q11, q15 ++ vmlal.u8 q8, d8, d12 ++ vmlal.u8 q9, d9, d12 ++ vmlal.u8 q10, d10, d12 ++ vmlal.u8 q11, d11, d12 ++ vld1.16 {d12[]}, [r2]! ++ vrshrn.u16 d19, q9, #5 ++ vrshrn.u16 d18, q8, #5 ++ vadd.i16 q8, q0, q12 ++ vrshrn.u16 d20, q10, #5 ++ vrshrn.u16 d21, q11, #5 ++ vst1.8 {q9-q10}, [r0 :128], r3 ++ vadd.i16 q9, q1, q13 ++ vadd.i16 q10, q2, q14 ++ vadd.i16 q11, q3, q15 ++ vmlal.u8 q0, d8, d12 ++ vmlal.u8 q1, d9, d12 ++ vmlal.u8 q2, d10, d12 ++ vmlal.u8 q3, d11, d12 ++ ++ bne 1b ++ ++ vpop {d8-d12} ++ ++ vrshrn.u16 d3, q1, #5 ++ vrshrn.u16 d2, q0, #5 ++ vrshrn.u16 d4, q2, #5 ++ vrshrn.u16 d5, q3, #5 ++ vst1.8 {q1-q2}, [r0 :128] ++ ++ bx lr ++ ++endfunc ++ ++ ++@ ff_hevc_rpi_pred_planar_c_16_neon_10 ++@ uint8_t *_src, [r0] ++@ const uint8_t *_top, [r1] ++@ const uint8_t *_left, [r2] ++@ ptrdiff_t stride) [r3] ++ ++function ff_hevc_rpi_pred_planar_c_16_neon_10, export=1 ++ ++ @ Load from bytes & expand later - at the very least this uses less ++ @ memory than having a short table ++ vld1.16 {q0-q1}, [r1 :128]! @ Top (left) ++ adr ip, nbx2_15_0_1_16 + 32 ++ vpush {q4-q7} ++ vld1.16 {q2-q3}, [r1 :128]! @ Top (centre) ++ add r2, #64 ++ vld1.8 {q14-q15}, [ip :128] @ {1,1,2,2,3,3...16,16} ++T lsl r3, #2 ++ vld1.32 {d8[],d9[]}, [r1] @ Top (right) ++ sub ip, #32 ++ vmovl.u8 q12, d28 ++ mov r1, #16 ++ vmovl.u8 q13, d29 ++ vld1.8 {q6-q7}, [ip :128] @ {15,15,14,14,13,13...0,0} ++ vmovl.u8 q14, d30 ++ vmovl.u8 q15, d31 ++ vld1.32 {d10[],d11[]}, [r2] @ Left (lower) ++ sub r2, #64 ++ vshl.i16 q8, q0, #4 ++ vshl.i16 q9, q1, #4 ++ vshl.i16 q10, q2, #4 ++ vshl.i16 q11, q3, #4 ++ vmla.i16 q8, q12, q4 ++ vsub.i16 q0, q5, q0 ++ vmla.i16 q9, q13, q4 ++ vpush {q0} ++ vsub.i16 q1, q5, q1 ++ vmla.i16 q10, q14, q4 ++ vsub.i16 q2, q5, q2 ++ vmla.i16 q11, q15, q4 @ Acc set up ++ vsub.i16 q3, q5, q3 @ Add set up ++ vadd.i16 q8, q0 ++ vadd.i16 q9, q1 ++ vadd.i16 q10, q2 ++ vadd.i16 q11, q3 ++ vmovl.u8 q4, d12 ++ vmovl.u8 q5, d13 ++ vmovl.u8 q6, d14 ++ vmovl.u8 q7, d15 ++ ++@ u16 31..0 [4] q4-q7 ++@ u16 left[y] [4] [r2] ++@ u16 acc [4] q8-q11 = (x+1)*p[nTbS][-1] + 32*p[x][-1] initially ++@ u16 add [4] q0-q3 = p[-1][nTbs] - p[x][-1] ++ ++ vadd.i16 q12, q8, q0 ++A sub r0, r0, r3, lsl #2 ++T sub r0, r3 ++1: ++ vld1.32 {d0[],d1[]}, [r2]! ++A add r0, r0, r3, lsl #2 ++T add r0, r3 ++ vadd.i16 q13, q9, q1 ++ subs r1, #2 ++ vadd.i16 q14, q10, q2 ++ vadd.i16 q15, q11, q3 ++ vmla.i16 q8, q4, q0 ++ vmla.i16 q9, q5, q0 ++ vmla.i16 q10, q6, q0 ++ vmla.i16 q11, q7, q0 ++ vld1.16 {q0}, [sp] ++ vrshr.u16 q8, #5 ++ vrshr.u16 q9, #5 ++ vrshr.u16 q10, #5 ++ vrshr.u16 q11, #5 ++ vstm r0, {q8-q11} ++ vadd.i16 q8, q12, q0 ++A add r0, r0, r3, lsl #2 ++T add r0, r3 ++ vld1.32 {d0[],d1[]}, [r2]! ++ vadd.i16 q9, q13, q1 ++ vadd.i16 q10, q14, q2 ++ vadd.i16 q11, q15, q3 ++ vmla.i16 q12, q4, q0 ++ vmla.i16 q13, q5, q0 ++ vmla.i16 q14, q6, q0 ++ vmla.i16 q15, q7, q0 ++ vld1.16 {q0}, [sp] ++ vrshr.u16 q12, #5 ++ vrshr.u16 q13, #5 ++ vrshr.u16 q14, #5 ++ vrshr.u16 q15, #5 ++ vstm r0, {q12-q15} ++ vadd.i16 q12, q8, q0 ++ bne 1b ++ ++ vpop {q3-q7} ++ bx lr ++ ++endfunc +diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h +index c91b2fd169..d6e019bbe1 100644 +--- a/libavcodec/avcodec.h ++++ b/libavcodec/avcodec.h +@@ -2236,8 +2236,7 @@ typedef struct AVCodecContext { + #define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1 + #endif + +- /** +- * Audio only. The amount of padding (in samples) appended by the encoder to ++ /* Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. +@@ -2567,6 +2566,17 @@ typedef struct AVHWAccel { + * that avctx->hwaccel_priv_data is invalid. + */ + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); ++ ++ /** ++ * Called if parsing fails ++ * ++ * An error has occured, end_frame will not be called ++ * start_frame & decode_slice may or may not have been called ++ * Optional ++ * ++ * @param avctx the codec context ++ */ ++ void (*abort_frame)(AVCodecContext *avctx); + } AVHWAccel; + + /** +diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h +index 1bf1c620d6..ccfa991f60 100644 +--- a/libavcodec/cabac.h ++++ b/libavcodec/cabac.h +@@ -43,7 +43,14 @@ extern const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; + typedef struct CABACContext{ + int low; + int range; +- int outstanding_count; ++ union ++ { ++ int outstanding_count; ++ struct { ++ uint16_t bits; ++ uint16_t range; ++ } by22; ++ }; + const uint8_t *bytestream_start; + const uint8_t *bytestream; + const uint8_t *bytestream_end; +diff --git a/libavcodec/codec.h b/libavcodec/codec.h +index 1fda619ee7..b4650f9ec9 100644 +--- a/libavcodec/codec.h ++++ b/libavcodec/codec.h +@@ -349,6 +349,17 @@ const AVCodec *av_codec_iterate(void **opaque); + */ + AVCodec *avcodec_find_decoder(enum AVCodecID id); + ++/** ++ * Find a registered decoder with a matching codec ID and pix_fmt. ++ * A decoder will pix_fmt set to NULL will match any fmt. ++ * A fmt of AV_PIX_FMT_NONE will only match a decoder will px_fmt NULL. ++ * ++ * @param id AVCodecID of the requested decoder ++ * @param fmt AVPixelForma that msut be supported by decoder ++ * @return A decoder if one was found, NULL otherwise. ++ */ ++AVCodec *avcodec_find_decoder_by_id_and_fmt(enum AVCodecID id, enum AVPixelFormat fmt); ++ + /** + * Find a registered decoder with the specified name. + * +diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h +new file mode 100644 +index 0000000000..ec47991544 +--- /dev/null ++++ b/libavcodec/h264-ctrls.h +@@ -0,0 +1,231 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the H.264 state controls for use with stateless H.264 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _H264_CTRLS_H_ ++#define _H264_CTRLS_H_ ++ ++#include ++ ++/* ++ * Maximum DPB size, as specified by section 'A.3.1 Level limits ++ * common to the Baseline, Main, and Extended profiles'. ++ */ ++#define V4L2_H264_NUM_DPB_ENTRIES 16 ++ ++#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) ++ ++/* Our pixel format isn't stable at the moment */ ++#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ ++ ++/* ++ * This is put insanely high to avoid conflicting with controls that ++ * would be added during the phase where those controls are not ++ * stable. It should be fixed eventually. ++ */ ++#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+1000) ++#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+1001) ++#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+1002) ++#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (V4L2_CID_MPEG_BASE+1003) ++#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004) ++#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005) ++#define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006) ++#define V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (V4L2_CID_MPEG_BASE+1007) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_H264_SPS 0x0110 ++#define V4L2_CTRL_TYPE_H264_PPS 0x0111 ++#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112 ++#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113 ++#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114 ++#define V4L2_CTRL_TYPE_H264_PRED_WEIGHTS 0x0115 ++ ++enum v4l2_mpeg_video_h264_decode_mode { ++ V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_h264_start_code { ++ V4L2_MPEG_VIDEO_H264_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, ++}; ++ ++#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01 ++#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02 ++#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04 ++#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08 ++#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10 ++#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20 ++ ++#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01 ++#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02 ++#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04 ++#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08 ++#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10 ++#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20 ++#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40 ++ ++struct v4l2_ctrl_h264_sps { ++ __u8 profile_idc; ++ __u8 constraint_set_flags; ++ __u8 level_idc; ++ __u8 seq_parameter_set_id; ++ __u8 chroma_format_idc; ++ __u8 bit_depth_luma_minus8; ++ __u8 bit_depth_chroma_minus8; ++ __u8 log2_max_frame_num_minus4; ++ __u8 pic_order_cnt_type; ++ __u8 log2_max_pic_order_cnt_lsb_minus4; ++ __u8 max_num_ref_frames; ++ __u8 num_ref_frames_in_pic_order_cnt_cycle; ++ __s32 offset_for_ref_frame[255]; ++ __s32 offset_for_non_ref_pic; ++ __s32 offset_for_top_to_bottom_field; ++ __u16 pic_width_in_mbs_minus1; ++ __u16 pic_height_in_map_units_minus1; ++ __u32 flags; ++}; ++ ++#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001 ++#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002 ++#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004 ++#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008 ++#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 ++#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 ++#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 ++#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080 ++ ++struct v4l2_ctrl_h264_pps { ++ __u8 pic_parameter_set_id; ++ __u8 seq_parameter_set_id; ++ __u8 num_slice_groups_minus1; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; ++ __u8 weighted_bipred_idc; ++ __s8 pic_init_qp_minus26; ++ __s8 pic_init_qs_minus26; ++ __s8 chroma_qp_index_offset; ++ __s8 second_chroma_qp_index_offset; ++ __u16 flags; ++}; ++ ++struct v4l2_ctrl_h264_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++}; ++ ++struct v4l2_h264_weight_factors { ++ __s16 luma_weight[32]; ++ __s16 luma_offset[32]; ++ __s16 chroma_weight[32][2]; ++ __s16 chroma_offset[32][2]; ++}; ++ ++#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \ ++ ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \ ++ ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \ ++ ((pps)->weighted_bipred_idc == 1 && \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ ++struct v4l2_ctrl_h264_pred_weights { ++ __u16 luma_log2_weight_denom; ++ __u16 chroma_log2_weight_denom; ++ struct v4l2_h264_weight_factors weight_factors[2]; ++}; ++ ++#define V4L2_H264_SLICE_TYPE_P 0 ++#define V4L2_H264_SLICE_TYPE_B 1 ++#define V4L2_H264_SLICE_TYPE_I 2 ++#define V4L2_H264_SLICE_TYPE_SP 3 ++#define V4L2_H264_SLICE_TYPE_SI 4 ++ ++#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 ++#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 ++ ++#define V4L2_H264_TOP_FIELD_REF 0x1 ++#define V4L2_H264_BOTTOM_FIELD_REF 0x2 ++#define V4L2_H264_FRAME_REF 0x3 ++ ++struct v4l2_h264_reference { ++ __u8 fields; ++ ++ /* Index into v4l2_ctrl_h264_decode_params.dpb[] */ ++ __u8 index; ++}; ++ ++struct v4l2_ctrl_h264_slice_params { ++ /* Offset in bits to slice_data() from the beginning of this slice. */ ++ __u32 header_bit_size; ++ ++ __u32 first_mb_in_slice; ++ ++ __u8 slice_type; ++ __u8 colour_plane_id; ++ __u8 redundant_pic_cnt; ++ __u8 cabac_init_idc; ++ __s8 slice_qp_delta; ++ __s8 slice_qs_delta; ++ __u8 disable_deblocking_filter_idc; ++ __s8 slice_alpha_c0_offset_div2; ++ __s8 slice_beta_offset_div2; ++ __u8 num_ref_idx_l0_active_minus1; ++ __u8 num_ref_idx_l1_active_minus1; ++ ++ __u8 reserved; ++ ++ struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; ++ struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; ++ ++ __u32 flags; ++}; ++ ++#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01 ++#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 ++#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 ++#define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 ++ ++struct v4l2_h264_dpb_entry { ++ __u64 reference_ts; ++ __u32 pic_num; ++ __u16 frame_num; ++ __u8 fields; ++ __u8 reserved[5]; ++ /* Note that field is indicated by v4l2_buffer.field */ ++ __s32 top_field_order_cnt; ++ __s32 bottom_field_order_cnt; ++ __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ ++}; ++ ++#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02 ++#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04 ++ ++struct v4l2_ctrl_h264_decode_params { ++ struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; ++ __u16 nal_ref_idc; ++ __u16 frame_num; ++ __s32 top_field_order_cnt; ++ __s32 bottom_field_order_cnt; ++ __u16 idr_pic_id; ++ __u16 pic_order_cnt_lsb; ++ __s32 delta_pic_order_cnt_bottom; ++ __s32 delta_pic_order_cnt0; ++ __s32 delta_pic_order_cnt1; ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ __u32 dec_ref_pic_marking_bit_size; ++ /* Size in bits of pic order count syntax. */ ++ __u32 pic_order_cnt_bit_size; ++ __u32 slice_group_change_cycle; ++ ++ __u32 reserved; ++ __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */ ++}; ++ ++#endif +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index db8363e4cc..39ae8fabfd 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -759,6 +759,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ + (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ + CONFIG_H264_NVDEC_HWACCEL + \ ++ CONFIG_H264_V4L2REQUEST_HWACCEL + \ + CONFIG_H264_VAAPI_HWACCEL + \ + CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_H264_VDPAU_HWACCEL) +@@ -784,10 +785,17 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + *fmt++ = AV_PIX_FMT_GBRP10; + } else + *fmt++ = AV_PIX_FMT_YUV444P10; +- } else if (CHROMA422(h)) ++ } else if (CHROMA422(h)) { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + *fmt++ = AV_PIX_FMT_YUV422P10; +- else ++ } else { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + *fmt++ = AV_PIX_FMT_YUV420P10; ++ } + break; + case 12: + if (CHROMA444(h)) { +@@ -826,6 +834,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + else + *fmt++ = AV_PIX_FMT_YUV444P; + } else if (CHROMA422(h)) { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + if (h->avctx->color_range == AVCOL_RANGE_JPEG) + *fmt++ = AV_PIX_FMT_YUVJ422P; + else +@@ -843,6 +854,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #endif + #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + if (h->avctx->codec->pix_fmts) + choices = h->avctx->codec->pix_fmts; +@@ -1736,7 +1750,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + unsigned int slice_type, tmp, i; + int field_pic_flag, bottom_field_flag; + int first_slice = sl == h->slice_ctx && !h->current_slice; +- int picture_structure; ++ int picture_structure, pos; + + if (first_slice) + av_assert0(!h->setup_finished); +@@ -1818,8 +1832,9 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + } + + if (nal->type == H264_NAL_IDR_SLICE) +- get_ue_golomb_long(&sl->gb); /* idr_pic_id */ ++ sl->idr_pic_id = get_ue_golomb_long(&sl->gb); + ++ pos = sl->gb.index; + if (sps->poc_type == 0) { + sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb); + +@@ -1833,6 +1848,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) + sl->delta_poc[1] = get_se_golomb(&sl->gb); + } ++ sl->pic_order_cnt_bit_size = sl->gb.index - pos; + + sl->redundant_pic_count = 0; + if (pps->redundant_pic_cnt_present) +@@ -1872,9 +1888,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + + sl->explicit_ref_marking = 0; + if (nal->ref_idc) { ++ int bit_pos = sl->gb.index; + ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, h->avctx); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; ++ sl->ref_pic_marking_size_in_bits = sl->gb.index - bit_pos; + } + + if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) { +diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c +index 5eedeb3c27..a504c89565 100644 +--- a/libavcodec/h264dec.c ++++ b/libavcodec/h264dec.c +@@ -1102,6 +1102,9 @@ AVCodec ff_h264_decoder = { + #endif + #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(h264), ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(h264), + #endif + NULL + }, +diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h +index a419615124..b3dcd6e7da 100644 +--- a/libavcodec/h264dec.h ++++ b/libavcodec/h264dec.h +@@ -190,6 +190,8 @@ typedef struct H264SliceContext { + int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) + int slice_type_fixed; + ++ int idr_pic_id; ++ + int qscale; + int chroma_qp[2]; // QPc + int qp_thresh; ///< QP threshold to skip loopfilter +@@ -328,11 +330,13 @@ typedef struct H264SliceContext { + MMCO mmco[MAX_MMCO_COUNT]; + int nb_mmco; + int explicit_ref_marking; ++ int ref_pic_marking_size_in_bits; + + int frame_num; + int poc_lsb; + int delta_poc_bottom; + int delta_poc[2]; ++ int pic_order_cnt_bit_size; + int curr_pic_num; + int max_pic_num; + } H264SliceContext; +diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h +new file mode 100644 +index 0000000000..13698d3f33 +--- /dev/null ++++ b/libavcodec/hevc-ctrls.h +@@ -0,0 +1,230 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the HEVC state controls for use with stateless HEVC ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _HEVC_CTRLS_H_ ++#define _HEVC_CTRLS_H_ ++ ++#include ++ ++/* The pixel format isn't stable at the moment and will likely be renamed. */ ++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ ++ ++#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) ++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 ++#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 ++#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 ++ ++enum v4l2_mpeg_video_hevc_decode_mode { ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_hevc_start_code { ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++}; ++ ++#define V4L2_HEVC_SLICE_TYPE_B 0 ++#define V4L2_HEVC_SLICE_TYPE_P 1 ++#define V4L2_HEVC_SLICE_TYPE_I 2 ++ ++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0) ++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1) ++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3) ++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4) ++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5) ++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6) ++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7) ++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8) ++ ++/* The controls are not stable at the moment and will likely be reworked. */ ++struct v4l2_ctrl_hevc_sps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ __u16 pic_width_in_luma_samples; ++ __u16 pic_height_in_luma_samples; ++ __u8 bit_depth_luma_minus8; ++ __u8 bit_depth_chroma_minus8; ++ __u8 log2_max_pic_order_cnt_lsb_minus4; ++ __u8 sps_max_dec_pic_buffering_minus1; ++ __u8 sps_max_num_reorder_pics; ++ __u8 sps_max_latency_increase_plus1; ++ __u8 log2_min_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_luma_coding_block_size; ++ __u8 log2_min_luma_transform_block_size_minus2; ++ __u8 log2_diff_max_min_luma_transform_block_size; ++ __u8 max_transform_hierarchy_depth_inter; ++ __u8 max_transform_hierarchy_depth_intra; ++ __u8 pcm_sample_bit_depth_luma_minus1; ++ __u8 pcm_sample_bit_depth_chroma_minus1; ++ __u8 log2_min_pcm_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_pcm_luma_coding_block_size; ++ __u8 num_short_term_ref_pic_sets; ++ __u8 num_long_term_ref_pics_sps; ++ __u8 chroma_format_idc; ++ ++ __u8 padding; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0) ++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) ++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) ++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) ++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4) ++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5) ++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6) ++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9) ++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10) ++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11) ++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12) ++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13) ++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15) ++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16) ++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17) ++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18) ++ ++struct v4l2_ctrl_hevc_pps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 num_extra_slice_header_bits; ++ __s8 init_qp_minus26; ++ __u8 diff_cu_qp_delta_depth; ++ __s8 pps_cb_qp_offset; ++ __s8 pps_cr_qp_offset; ++ __u8 num_tile_columns_minus1; ++ __u8 num_tile_rows_minus1; ++ __u8 column_width_minus1[20]; ++ __u8 row_height_minus1[22]; ++ __s8 pps_beta_offset_div2; ++ __s8 pps_tc_offset_div2; ++ __u8 log2_parallel_merge_level_minus2; ++ ++ __u8 padding[4]; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02 ++#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03 ++ ++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 ++ ++struct v4l2_hevc_dpb_entry { ++ __u64 timestamp; ++ __u8 rps; ++ __u8 field_pic; ++ __u16 pic_order_cnt[2]; ++ __u8 padding[2]; ++}; ++ ++struct v4l2_hevc_pred_weight_table { ++ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __u8 padding[6]; ++ ++ __u8 luma_log2_weight_denom; ++ __s8 delta_chroma_log2_weight_denom; ++}; ++ ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9) ++ ++struct v4l2_ctrl_hevc_slice_params { ++ __u32 bit_size; ++ __u32 data_bit_offset; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ ++ __u8 nal_unit_type; ++ __u8 nuh_temporal_id_plus1; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 slice_type; ++ __u8 colour_plane_id; ++ __u16 slice_pic_order_cnt; ++ __u8 num_ref_idx_l0_active_minus1; ++ __u8 num_ref_idx_l1_active_minus1; ++ __u8 collocated_ref_idx; ++ __u8 five_minus_max_num_merge_cand; ++ __s8 slice_qp_delta; ++ __s8 slice_cb_qp_offset; ++ __s8 slice_cr_qp_offset; ++ __s8 slice_act_y_qp_offset; ++ __s8 slice_act_cb_qp_offset; ++ __s8 slice_act_cr_qp_offset; ++ __s8 slice_beta_offset_div2; ++ __s8 slice_tc_offset_div2; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ ++ __u8 pic_struct; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 num_active_dpb_entries; ++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ __u8 num_rps_poc_st_curr_before; ++ __u8 num_rps_poc_st_curr_after; ++ __u8 num_rps_poc_lt_curr; ++ ++ __u8 padding; ++ ++ __u32 entry_point_offset_minus1[256]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; ++}; ++ ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ ++#endif +diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c +index 0772608a30..91a7536ee5 100644 +--- a/libavcodec/hevcdec.c ++++ b/libavcodec/hevcdec.c +@@ -372,14 +372,20 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \ + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ + CONFIG_HEVC_NVDEC_HWACCEL + \ ++ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \ + CONFIG_HEVC_VAAPI_HWACCEL + \ + CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ ++ CONFIG_HEVC_RPI4_8_HWACCEL + \ ++ CONFIG_HEVC_RPI4_10_HWACCEL + \ + CONFIG_HEVC_VDPAU_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; + + switch (sps->pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: ++#if CONFIG_HEVC_RPI4_8_HWACCEL ++ *fmt++ = AV_PIX_FMT_RPI4_8; ++#endif + #if CONFIG_HEVC_DXVA2_HWACCEL + *fmt++ = AV_PIX_FMT_DXVA2_VLD; + #endif +@@ -398,9 +404,15 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P10: ++#if CONFIG_HEVC_RPI4_10_HWACCEL ++ *fmt++ = AV_PIX_FMT_RPI4_10; ++#endif + #if CONFIG_HEVC_DXVA2_HWACCEL + *fmt++ = AV_PIX_FMT_DXVA2_VLD; + #endif +@@ -416,6 +428,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_NVDEC_HWACCEL + *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV444P: +@@ -3225,7 +3240,14 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, + s->ref = NULL; + ret = decode_nal_units(s, avpkt->data, avpkt->size); + if (ret < 0) ++ { ++ // Ensure that hwaccel knows this frame is over ++ if (s->avctx->hwaccel && s->avctx->hwaccel->abort_frame) { ++ s->avctx->hwaccel->abort_frame(s->avctx); ++ } ++ + return ret; ++ } + + if (avctx->hwaccel) { + if (s->ref && (ret = avctx->hwaccel->end_frame(avctx)) < 0) { +@@ -3588,6 +3610,15 @@ AVCodec ff_hevc_decoder = { + #endif + #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(hevc), ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(hevc), ++#endif ++#if CONFIG_HEVC_RPI4_8_HWACCEL ++ HWACCEL_RPI4_8(hevc), ++#endif ++#if CONFIG_HEVC_RPI4_10_HWACCEL ++ HWACCEL_RPI4_10(hevc), + #endif + NULL + }, +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 6109c89bd6..30927fda99 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -27,6 +27,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel; + extern const AVHWAccel ff_h264_d3d11va2_hwaccel; + extern const AVHWAccel ff_h264_dxva2_hwaccel; + extern const AVHWAccel ff_h264_nvdec_hwaccel; ++extern const AVHWAccel ff_h264_v4l2request_hwaccel; + extern const AVHWAccel ff_h264_vaapi_hwaccel; + extern const AVHWAccel ff_h264_vdpau_hwaccel; + extern const AVHWAccel ff_h264_videotoolbox_hwaccel; +@@ -34,6 +35,7 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel; + extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; + extern const AVHWAccel ff_hevc_dxva2_hwaccel; + extern const AVHWAccel ff_hevc_nvdec_hwaccel; ++extern const AVHWAccel ff_hevc_v4l2request_hwaccel; + extern const AVHWAccel ff_hevc_vaapi_hwaccel; + extern const AVHWAccel ff_hevc_vdpau_hwaccel; + extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +@@ -47,6 +49,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel; + extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel; + extern const AVHWAccel ff_mpeg2_nvdec_hwaccel; + extern const AVHWAccel ff_mpeg2_dxva2_hwaccel; ++extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel; + extern const AVHWAccel ff_mpeg2_vaapi_hwaccel; + extern const AVHWAccel ff_mpeg2_vdpau_hwaccel; + extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel; +@@ -62,11 +65,13 @@ extern const AVHWAccel ff_vc1_nvdec_hwaccel; + extern const AVHWAccel ff_vc1_vaapi_hwaccel; + extern const AVHWAccel ff_vc1_vdpau_hwaccel; + extern const AVHWAccel ff_vp8_nvdec_hwaccel; ++extern const AVHWAccel ff_vp8_v4l2request_hwaccel; + extern const AVHWAccel ff_vp8_vaapi_hwaccel; + extern const AVHWAccel ff_vp9_d3d11va_hwaccel; + extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; + extern const AVHWAccel ff_vp9_dxva2_hwaccel; + extern const AVHWAccel ff_vp9_nvdec_hwaccel; ++extern const AVHWAccel ff_vp9_v4l2request_hwaccel; + extern const AVHWAccel ff_vp9_vaapi_hwaccel; + extern const AVHWAccel ff_vp9_vdpau_hwaccel; + extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; +@@ -75,5 +80,7 @@ extern const AVHWAccel ff_wmv3_dxva2_hwaccel; + extern const AVHWAccel ff_wmv3_nvdec_hwaccel; + extern const AVHWAccel ff_wmv3_vaapi_hwaccel; + extern const AVHWAccel ff_wmv3_vdpau_hwaccel; ++extern const AVHWAccel ff_hevc_rpi4_8_hwaccel; ++extern const AVHWAccel ff_hevc_rpi4_10_hwaccel; + + #endif /* AVCODEC_HWACCELS_H */ +diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h +index f421dc909f..ed44e01de4 100644 +--- a/libavcodec/hwconfig.h ++++ b/libavcodec/hwconfig.h +@@ -24,6 +24,7 @@ + + + #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) ++#define HWACCEL_CAP_MT_SAFE (1 << 1) + + + typedef struct AVCodecHWConfigInternal { +@@ -80,6 +81,12 @@ typedef struct AVCodecHWConfigInternal { + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) + #define HWACCEL_XVMC(codec) \ + HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) ++#define HWACCEL_V4L2REQUEST(codec) \ ++ HW_CONFIG_HWACCEL(1, 0, 0, DRM_PRIME, DRM, ff_ ## codec ## _v4l2request_hwaccel) ++#define HWACCEL_RPI4_8(codec) \ ++ HW_CONFIG_HWACCEL(0, 0, 1, RPI4_8, NONE, ff_ ## codec ## _rpi4_8_hwaccel) ++#define HWACCEL_RPI4_10(codec) \ ++ HW_CONFIG_HWACCEL(0, 0, 1, RPI4_10, NONE, ff_ ## codec ## _rpi4_10_hwaccel) + + #define HW_CONFIG_ENCODER(device, frames, ad_hoc, format, device_type_) \ + &(const AVCodecHWConfigInternal) { \ +diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c +index 547bece576..bfd1083c16 100644 +--- a/libavcodec/mmaldec.c ++++ b/libavcodec/mmaldec.c +@@ -24,6 +24,9 @@ + * MMAL Video Decoder + */ + ++#pragma GCC diagnostic push ++// Many many redundant decls in the header files ++#pragma GCC diagnostic ignored "-Wredundant-decls" + #include + #include + #include +@@ -31,6 +34,7 @@ + #include + #include + #include ++#pragma GCC diagnostic pop + #include + + #include "avcodec.h" +diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c +index 99e56532a5..15aaf97a34 100644 +--- a/libavcodec/mpeg12dec.c ++++ b/libavcodec/mpeg12dec.c +@@ -1154,6 +1154,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { + #endif + #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL + AV_PIX_FMT_VIDEOTOOLBOX, ++#endif ++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL ++ AV_PIX_FMT_DRM_PRIME, + #endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +@@ -2952,6 +2955,9 @@ AVCodec ff_mpeg2video_decoder = { + #endif + #if CONFIG_MPEG2_XVMC_HWACCEL + HWACCEL_XVMC(mpeg2), ++#endif ++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(mpeg2), + #endif + NULL + }, +diff --git a/libavcodec/mpeg2-ctrls.h b/libavcodec/mpeg2-ctrls.h +new file mode 100644 +index 0000000000..6601455b3d +--- /dev/null ++++ b/libavcodec/mpeg2-ctrls.h +@@ -0,0 +1,82 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the MPEG2 state controls for use with stateless MPEG-2 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _MPEG2_CTRLS_H_ ++#define _MPEG2_CTRLS_H_ ++ ++#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS (V4L2_CID_MPEG_BASE+250) ++#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION (V4L2_CID_MPEG_BASE+251) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS 0x0103 ++#define V4L2_CTRL_TYPE_MPEG2_QUANTIZATION 0x0104 ++ ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_I 1 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_P 2 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_B 3 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_D 4 ++ ++struct v4l2_mpeg2_sequence { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */ ++ __u16 horizontal_size; ++ __u16 vertical_size; ++ __u32 vbv_buffer_size; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */ ++ __u16 profile_and_level_indication; ++ __u8 progressive_sequence; ++ __u8 chroma_format; ++}; ++ ++struct v4l2_mpeg2_picture { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */ ++ __u8 picture_coding_type; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */ ++ __u8 f_code[2][2]; ++ __u8 intra_dc_precision; ++ __u8 picture_structure; ++ __u8 top_field_first; ++ __u8 frame_pred_frame_dct; ++ __u8 concealment_motion_vectors; ++ __u8 q_scale_type; ++ __u8 intra_vlc_format; ++ __u8 alternate_scan; ++ __u8 repeat_first_field; ++ __u16 progressive_frame; ++}; ++ ++struct v4l2_ctrl_mpeg2_slice_params { ++ __u32 bit_size; ++ __u32 data_bit_offset; ++ __u64 backward_ref_ts; ++ __u64 forward_ref_ts; ++ ++ struct v4l2_mpeg2_sequence sequence; ++ struct v4l2_mpeg2_picture picture; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */ ++ __u32 quantiser_scale_code; ++}; ++ ++struct v4l2_ctrl_mpeg2_quantization { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */ ++ __u8 load_intra_quantiser_matrix; ++ __u8 load_non_intra_quantiser_matrix; ++ __u8 load_chroma_intra_quantiser_matrix; ++ __u8 load_chroma_non_intra_quantiser_matrix; ++ ++ __u8 intra_quantiser_matrix[64]; ++ __u8 non_intra_quantiser_matrix[64]; ++ __u8 chroma_intra_quantiser_matrix[64]; ++ __u8 chroma_non_intra_quantiser_matrix[64]; ++}; ++ ++#endif +diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c +index 601f170447..f890f99931 100644 +--- a/libavcodec/pthread_frame.c ++++ b/libavcodec/pthread_frame.c +@@ -191,7 +191,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) + + /* if the previous thread uses hwaccel then we take the lock to ensure + * the threads don't run concurrently */ +- if (avctx->hwaccel) { ++ if (avctx->hwaccel && ++ !(avctx->hwaccel->caps_internal & HWACCEL_CAP_MT_SAFE)) { + pthread_mutex_lock(&p->parent->hwaccel_mutex); + p->hwaccel_serializing = 1; + } +@@ -614,7 +615,9 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { + + if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; + +- if (avctx->hwaccel && !p->hwaccel_serializing) { ++ if (avctx->hwaccel && ++ !(avctx->hwaccel->caps_internal & HWACCEL_CAP_MT_SAFE) && ++ !p->hwaccel_serializing) { + pthread_mutex_lock(&p->parent->hwaccel_mutex); + p->hwaccel_serializing = 1; + } +diff --git a/libavcodec/raw.c b/libavcodec/raw.c +index b6fb91c1c6..7b2770e780 100644 +--- a/libavcodec/raw.c ++++ b/libavcodec/raw.c +@@ -289,10 +289,20 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { + { AV_PIX_FMT_YUV444P16LE, MKTAG('I', '4', 'F', 'L') }, + { AV_PIX_FMT_YUV444P16BE, MKTAG('I', '4', 'F', 'B') }, + ++ /* RPI (Might as well define for everything) */ ++ { AV_PIX_FMT_SAND128, MKTAG('S', 'A', 'N', 'D') }, ++ { AV_PIX_FMT_SAND64_10, MKTAG('S', 'N', 'D', 'A') }, ++ + /* special */ + { AV_PIX_FMT_RGB565LE,MKTAG( 3 , 0 , 0 , 0 ) }, /* flipped RGB565LE */ + { AV_PIX_FMT_YUV444P, MKTAG('Y', 'V', '2', '4') }, /* YUV444P, swapped UV */ + ++ /* RPI (Might as well define for everything) */ ++ { AV_PIX_FMT_SAND128, MKTAG('S', 'A', 'N', 'D') }, ++ { AV_PIX_FMT_RPI4_8, MKTAG('S', 'A', 'N', 'D') }, ++ { AV_PIX_FMT_SAND64_10, MKTAG('S', 'N', 'D', 'A') }, ++ { AV_PIX_FMT_RPI4_10, MKTAG('S', 'N', 'D', 'B') }, ++ + { AV_PIX_FMT_NONE, 0 }, + }; + +diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c +index d181b74570..3fe2ab445f 100644 +--- a/libavcodec/rawenc.c ++++ b/libavcodec/rawenc.c +@@ -24,6 +24,7 @@ + * Raw Video Encoder + */ + ++#include "config.h" + #include "avcodec.h" + #include "raw.h" + #include "internal.h" +@@ -31,6 +32,10 @@ + #include "libavutil/intreadwrite.h" + #include "libavutil/imgutils.h" + #include "libavutil/internal.h" ++#include "libavutil/avassert.h" ++#if CONFIG_SAND ++#include "libavutil/rpi_sand_fns.h" ++#endif + + static av_cold int raw_encode_init(AVCodecContext *avctx) + { +@@ -49,12 +54,95 @@ FF_ENABLE_DEPRECATION_WARNINGS + return 0; + } + ++#if CONFIG_SAND ++static int raw_sand8_as_yuv420(AVCodecContext *avctx, AVPacket *pkt, ++ const AVFrame *frame) ++{ ++ const int width = av_frame_cropped_width(frame); ++ const int height = av_frame_cropped_height(frame); ++ const int x0 = frame->crop_left; ++ const int y0 = frame->crop_top; ++ const int size = width * height * 3 / 2; ++ uint8_t * dst; ++ int ret; ++ ++ if ((ret = ff_alloc_packet2(avctx, pkt, size, size)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand_to_planar_y8(dst, width, frame->data[0], frame->linesize[0], frame->linesize[3], x0, y0, width, height); ++ dst += width * height; ++ av_rpi_sand_to_planar_c8(dst, width / 2, dst + width * height / 4, width / 2, ++ frame->data[1], frame->linesize[1], av_rpi_sand_frame_stride2(frame), x0 / 2, y0 / 2, width / 2, height / 2); ++ return 0; ++} ++ ++static int raw_sand16_as_yuv420(AVCodecContext *avctx, AVPacket *pkt, ++ const AVFrame *frame) ++{ ++ const int width = av_frame_cropped_width(frame); ++ const int height = av_frame_cropped_height(frame); ++ const int x0 = frame->crop_left; ++ const int y0 = frame->crop_top; ++ const int size = width * height * 3; ++ uint8_t * dst; ++ int ret; ++ ++ if ((ret = ff_alloc_packet2(avctx, pkt, size, size)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand_to_planar_y16(dst, width * 2, frame->data[0], frame->linesize[0], frame->linesize[3], x0 * 2, y0, width * 2, height); ++ dst += width * height * 2; ++ av_rpi_sand_to_planar_c16(dst, width, dst + width * height / 2, width, ++ frame->data[1], frame->linesize[1], av_rpi_sand_frame_stride2(frame), x0, y0 / 2, width, height / 2); ++ return 0; ++} ++ ++static int raw_sand30_as_yuv420(AVCodecContext *avctx, AVPacket *pkt, ++ const AVFrame *frame) ++{ ++ const int width = av_frame_cropped_width(frame); ++ const int height = av_frame_cropped_height(frame); ++ const int x0 = frame->crop_left; ++ const int y0 = frame->crop_top; ++ const int size = width * height * 3; ++ uint8_t * dst; ++ int ret; ++ ++ if ((ret = ff_alloc_packet2(avctx, pkt, size, size)) < 0) ++ return ret; ++ ++ dst = pkt->data; ++ ++ av_rpi_sand30_to_planar_y16(dst, width * 2, frame->data[0], frame->linesize[0], frame->linesize[3], x0, y0, width, height); ++ dst += width * height * 2; ++ av_rpi_sand30_to_planar_c16(dst, width, dst + width * height / 2, width, ++ frame->data[1], frame->linesize[1], av_rpi_sand_frame_stride2(frame), x0/2, y0 / 2, width/2, height / 2); ++ return 0; ++} ++#endif ++ ++ + static int raw_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) + { +- int ret = av_image_get_buffer_size(frame->format, +- frame->width, frame->height, 1); ++ int ret; ++ ++#if CONFIG_SAND ++ if (av_rpi_is_sand_frame(frame)) { ++ ret = av_rpi_is_sand8_frame(frame) ? raw_sand8_as_yuv420(avctx, pkt, frame) : ++ av_rpi_is_sand16_frame(frame) ? raw_sand16_as_yuv420(avctx, pkt, frame) : ++ av_rpi_is_sand30_frame(frame) ? raw_sand30_as_yuv420(avctx, pkt, frame) : -1; ++ *got_packet = (ret == 0); ++ return ret; ++ } ++#endif + ++ ret = av_image_get_buffer_size(frame->format, ++ frame->width, frame->height, 1); + if (ret < 0) + return ret; + +diff --git a/libavcodec/rpi_hevc_cabac.c b/libavcodec/rpi_hevc_cabac.c +new file mode 100644 +index 0000000000..58c094c5f8 +--- /dev/null ++++ b/libavcodec/rpi_hevc_cabac.c +@@ -0,0 +1,2257 @@ ++/* ++ * HEVC CABAC decoding ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2018 John Cox, Ben Avison, Peter de Rivaz for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#define UNCHECKED_BITSTREAM_READER 1 ++ ++#include "libavutil/attributes.h" ++#include "libavutil/common.h" ++ ++#include "cabac_functions.h" ++#include "rpi_hevc_data.h" ++#include "hevc.h" ++#include "rpi_hevcdec.h" ++#include "rpi_hevc_cabac_fns.h" ++ ++#include "libavutil/rpi_sand_fns.h" ++ ++// BY22 is probably faster than simple bypass if the processor has ++// either a fast 32-bit divide or a fast 32x32->64[63:32] instruction ++// x86 has fast int divide ++// Arm doesn't have divide or general fast 64 bit, but does have the multiply ++// * Beware: ARCH_xxx isn't set if configure --disable-asm is used ++#define USE_BY22 (HAVE_FAST_64BIT || ARCH_ARM || ARCH_X86) ++// Use native divide if we have a fast one - otherwise use mpy 1/x ++// x86 has a fast integer divide - arm doesn't - unsure about other ++// architectures ++#define USE_BY22_DIV ARCH_X86 ++ ++// Special case blocks with a single significant ceoff ++// Decreases the complexity of the code for a common case but increases the ++// code size. ++#define USE_N_END_1 1 ++ ++#if !USE_BY22_DIV ++// * 1/x @ 32 bits gets us 22 bits of accuracy ++#define CABAC_BY22_PEEK_BITS 22 ++#else ++// A real 32-bit divide gets us another bit ++// If we have a 64 bit int & a unit time divider then we should get a lot ++// of bits (55) but that is untested and it is unclear if it would give ++// us a large advantage ++#define CABAC_BY22_PEEK_BITS 23 ++#endif ++ ++#define CABAC_MAX_BIN 31 ++ ++ ++#if USE_BY22 && !USE_BY22_DIV ++#define I(x) (uint32_t)((0x10000000000ULL / (uint64_t)(x)) + 1ULL) ++ ++static const uint32_t cabac_by22_inv_range[256] = { ++ 0, I(257), I(258), I(259), ++ I(260), I(261), I(262), I(263), I(264), I(265), I(266), I(267), I(268), I(269), ++ I(270), I(271), I(272), I(273), I(274), I(275), I(276), I(277), I(278), I(279), ++ I(280), I(281), I(282), I(283), I(284), I(285), I(286), I(287), I(288), I(289), ++ I(290), I(291), I(292), I(293), I(294), I(295), I(296), I(297), I(298), I(299), ++ I(300), I(301), I(302), I(303), I(304), I(305), I(306), I(307), I(308), I(309), ++ I(310), I(311), I(312), I(313), I(314), I(315), I(316), I(317), I(318), I(319), ++ I(320), I(321), I(322), I(323), I(324), I(325), I(326), I(327), I(328), I(329), ++ I(330), I(331), I(332), I(333), I(334), I(335), I(336), I(337), I(338), I(339), ++ I(340), I(341), I(342), I(343), I(344), I(345), I(346), I(347), I(348), I(349), ++ I(350), I(351), I(352), I(353), I(354), I(355), I(356), I(357), I(358), I(359), ++ I(360), I(361), I(362), I(363), I(364), I(365), I(366), I(367), I(368), I(369), ++ I(370), I(371), I(372), I(373), I(374), I(375), I(376), I(377), I(378), I(379), ++ I(380), I(381), I(382), I(383), I(384), I(385), I(386), I(387), I(388), I(389), ++ I(390), I(391), I(392), I(393), I(394), I(395), I(396), I(397), I(398), I(399), ++ I(400), I(401), I(402), I(403), I(404), I(405), I(406), I(407), I(408), I(409), ++ I(410), I(411), I(412), I(413), I(414), I(415), I(416), I(417), I(418), I(419), ++ I(420), I(421), I(422), I(423), I(424), I(425), I(426), I(427), I(428), I(429), ++ I(430), I(431), I(432), I(433), I(434), I(435), I(436), I(437), I(438), I(439), ++ I(440), I(441), I(442), I(443), I(444), I(445), I(446), I(447), I(448), I(449), ++ I(450), I(451), I(452), I(453), I(454), I(455), I(456), I(457), I(458), I(459), ++ I(460), I(461), I(462), I(463), I(464), I(465), I(466), I(467), I(468), I(469), ++ I(470), I(471), I(472), I(473), I(474), I(475), I(476), I(477), I(478), I(479), ++ I(480), I(481), I(482), I(483), I(484), I(485), I(486), I(487), I(488), I(489), ++ I(490), I(491), I(492), I(493), I(494), I(495), I(496), I(497), I(498), I(499), ++ I(500), I(501), I(502), I(503), I(504), I(505), I(506), I(507), I(508), I(509), ++ I(510), I(511) ++}; ++#undef I ++#endif // USE_BY22 ++ ++#if ARCH_ARM ++#include "arm/rpi_hevc_cabac.h" ++#endif ++ ++/** ++ * number of bin by SyntaxElement. ++ */ ++static const int8_t num_bins_in_se[] = { ++ 1, // sao_merge_flag ++ 1, // sao_type_idx ++ 0, // sao_eo_class ++ 0, // sao_band_position ++ 0, // sao_offset_abs ++ 0, // sao_offset_sign ++ 0, // end_of_slice_flag ++ 3, // split_coding_unit_flag ++ 1, // cu_transquant_bypass_flag ++ 3, // skip_flag ++ 3, // cu_qp_delta ++ 1, // pred_mode ++ 4, // part_mode ++ 0, // pcm_flag ++ 1, // prev_intra_luma_pred_mode ++ 0, // mpm_idx ++ 0, // rem_intra_luma_pred_mode ++ 2, // intra_chroma_pred_mode ++ 1, // merge_flag ++ 1, // merge_idx ++ 5, // inter_pred_idc ++ 2, // ref_idx_l0 ++ 2, // ref_idx_l1 ++ 2, // abs_mvd_greater0_flag ++ 2, // abs_mvd_greater1_flag ++ 0, // abs_mvd_minus2 ++ 0, // mvd_sign_flag ++ 1, // mvp_lx_flag ++ 1, // no_residual_data_flag ++ 3, // split_transform_flag ++ 2, // cbf_luma ++ 4, // cbf_cb, cbf_cr ++ 2, // transform_skip_flag[][] ++ 2, // explicit_rdpcm_flag[][] ++ 2, // explicit_rdpcm_dir_flag[][] ++ 18, // last_significant_coeff_x_prefix ++ 18, // last_significant_coeff_y_prefix ++ 0, // last_significant_coeff_x_suffix ++ 0, // last_significant_coeff_y_suffix ++ 4, // significant_coeff_group_flag ++ 44, // significant_coeff_flag ++ 24, // coeff_abs_level_greater1_flag ++ 6, // coeff_abs_level_greater2_flag ++ 0, // coeff_abs_level_remaining ++ 0, // coeff_sign_flag ++ 8, // log2_res_scale_abs ++ 2, // res_scale_sign_flag ++ 1, // cu_chroma_qp_offset_flag ++ 1, // cu_chroma_qp_offset_idx ++}; ++ ++/** ++ * Offset to ctxIdx 0 in init_values and states, indexed by SyntaxElement. ++ */ ++static const int elem_offset[sizeof(num_bins_in_se)] = { ++ 0, // sao_merge_flag ++ 1, // sao_type_idx ++ 2, // sao_eo_class ++ 2, // sao_band_position ++ 2, // sao_offset_abs ++ 2, // sao_offset_sign ++ 2, // end_of_slice_flag ++ 2, // split_coding_unit_flag ++ 5, // cu_transquant_bypass_flag ++ 6, // skip_flag ++ 9, // cu_qp_delta ++ 12, // pred_mode ++ 13, // part_mode ++ 17, // pcm_flag ++ 17, // prev_intra_luma_pred_mode ++ 18, // mpm_idx ++ 18, // rem_intra_luma_pred_mode ++ 18, // intra_chroma_pred_mode ++ 20, // merge_flag ++ 21, // merge_idx ++ 22, // inter_pred_idc ++ 27, // ref_idx_l0 ++ 29, // ref_idx_l1 ++ 31, // abs_mvd_greater0_flag ++ 33, // abs_mvd_greater1_flag ++ 35, // abs_mvd_minus2 ++ 35, // mvd_sign_flag ++ 35, // mvp_lx_flag ++ 36, // no_residual_data_flag ++ 37, // split_transform_flag ++ 40, // cbf_luma ++ 42, // cbf_cb, cbf_cr ++ 46, // transform_skip_flag[][] ++ 48, // explicit_rdpcm_flag[][] ++ 50, // explicit_rdpcm_dir_flag[][] ++ 52, // last_significant_coeff_x_prefix ++ 70, // last_significant_coeff_y_prefix ++ 88, // last_significant_coeff_x_suffix ++ 88, // last_significant_coeff_y_suffix ++ 88, // significant_coeff_group_flag ++ 92, // significant_coeff_flag ++ 136, // coeff_abs_level_greater1_flag ++ 160, // coeff_abs_level_greater2_flag ++ 166, // coeff_abs_level_remaining ++ 166, // coeff_sign_flag ++ 166, // log2_res_scale_abs ++ 174, // res_scale_sign_flag ++ 176, // cu_chroma_qp_offset_flag ++ 177, // cu_chroma_qp_offset_idx ++}; ++ ++#define CNU 154 ++/** ++ * Indexed by init_type ++ */ ++static const uint8_t init_values[3][HEVC_CONTEXTS] = { ++ { // sao_merge_flag ++ 153, ++ // sao_type_idx ++ 200, ++ // split_coding_unit_flag ++ 139, 141, 157, ++ // cu_transquant_bypass_flag ++ 154, ++ // skip_flag ++ CNU, CNU, CNU, ++ // cu_qp_delta ++ 154, 154, 154, ++ // pred_mode ++ CNU, ++ // part_mode ++ 184, CNU, CNU, CNU, ++ // prev_intra_luma_pred_mode ++ 184, ++ // intra_chroma_pred_mode ++ 63, 139, ++ // merge_flag ++ CNU, ++ // merge_idx ++ CNU, ++ // inter_pred_idc ++ CNU, CNU, CNU, CNU, CNU, ++ // ref_idx_l0 ++ CNU, CNU, ++ // ref_idx_l1 ++ CNU, CNU, ++ // abs_mvd_greater1_flag ++ CNU, CNU, ++ // abs_mvd_greater1_flag ++ CNU, CNU, ++ // mvp_lx_flag ++ CNU, ++ // no_residual_data_flag ++ CNU, ++ // split_transform_flag ++ 153, 138, 138, ++ // cbf_luma ++ 111, 141, ++ // cbf_cb, cbf_cr ++ 94, 138, 182, 154, ++ // transform_skip_flag ++ 139, 139, ++ // explicit_rdpcm_flag ++ 139, 139, ++ // explicit_rdpcm_dir_flag ++ 139, 139, ++ // last_significant_coeff_x_prefix ++ 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, ++ 79, 108, 123, 63, ++ // last_significant_coeff_y_prefix ++ 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, ++ 79, 108, 123, 63, ++ // significant_coeff_group_flag ++ 91, 171, 134, 141, ++ // significant_coeff_flag ++ 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, ++ 125, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, ++ 139, 182, 182, 152, 136, 152, 136, 153, 136, 139, 111, 136, 139, 111, ++ 141, 111, ++ // coeff_abs_level_greater1_flag ++ 140, 92, 137, 138, 140, 152, 138, 139, 153, 74, 149, 92, 139, 107, ++ 122, 152, 140, 179, 166, 182, 140, 227, 122, 197, ++ // coeff_abs_level_greater2_flag ++ 138, 153, 136, 167, 152, 152, ++ // log2_res_scale_abs ++ 154, 154, 154, 154, 154, 154, 154, 154, ++ // res_scale_sign_flag ++ 154, 154, ++ // cu_chroma_qp_offset_flag ++ 154, ++ // cu_chroma_qp_offset_idx ++ 154, ++ }, ++ { // sao_merge_flag ++ 153, ++ // sao_type_idx ++ 185, ++ // split_coding_unit_flag ++ 107, 139, 126, ++ // cu_transquant_bypass_flag ++ 154, ++ // skip_flag ++ 197, 185, 201, ++ // cu_qp_delta ++ 154, 154, 154, ++ // pred_mode ++ 149, ++ // part_mode ++ 154, 139, 154, 154, ++ // prev_intra_luma_pred_mode ++ 154, ++ // intra_chroma_pred_mode ++ 152, 139, ++ // merge_flag ++ 110, ++ // merge_idx ++ 122, ++ // inter_pred_idc ++ 95, 79, 63, 31, 31, ++ // ref_idx_l0 ++ 153, 153, ++ // ref_idx_l1 ++ 153, 153, ++ // abs_mvd_greater1_flag ++ 140, 198, ++ // abs_mvd_greater1_flag ++ 140, 198, ++ // mvp_lx_flag ++ 168, ++ // no_residual_data_flag ++ 79, ++ // split_transform_flag ++ 124, 138, 94, ++ // cbf_luma ++ 153, 111, ++ // cbf_cb, cbf_cr ++ 149, 107, 167, 154, ++ // transform_skip_flag ++ 139, 139, ++ // explicit_rdpcm_flag ++ 139, 139, ++ // explicit_rdpcm_dir_flag ++ 139, 139, ++ // last_significant_coeff_x_prefix ++ 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, ++ 94, 108, 123, 108, ++ // last_significant_coeff_y_prefix ++ 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, ++ 94, 108, 123, 108, ++ // significant_coeff_group_flag ++ 121, 140, 61, 154, ++ // significant_coeff_flag ++ 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, ++ 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, ++ 153, 123, 123, 107, 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, ++ 140, 140, ++ // coeff_abs_level_greater1_flag ++ 154, 196, 196, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, ++ 136, 137, 169, 194, 166, 167, 154, 167, 137, 182, ++ // coeff_abs_level_greater2_flag ++ 107, 167, 91, 122, 107, 167, ++ // log2_res_scale_abs ++ 154, 154, 154, 154, 154, 154, 154, 154, ++ // res_scale_sign_flag ++ 154, 154, ++ // cu_chroma_qp_offset_flag ++ 154, ++ // cu_chroma_qp_offset_idx ++ 154, ++ }, ++ { // sao_merge_flag ++ 153, ++ // sao_type_idx ++ 160, ++ // split_coding_unit_flag ++ 107, 139, 126, ++ // cu_transquant_bypass_flag ++ 154, ++ // skip_flag ++ 197, 185, 201, ++ // cu_qp_delta ++ 154, 154, 154, ++ // pred_mode ++ 134, ++ // part_mode ++ 154, 139, 154, 154, ++ // prev_intra_luma_pred_mode ++ 183, ++ // intra_chroma_pred_mode ++ 152, 139, ++ // merge_flag ++ 154, ++ // merge_idx ++ 137, ++ // inter_pred_idc ++ 95, 79, 63, 31, 31, ++ // ref_idx_l0 ++ 153, 153, ++ // ref_idx_l1 ++ 153, 153, ++ // abs_mvd_greater1_flag ++ 169, 198, ++ // abs_mvd_greater1_flag ++ 169, 198, ++ // mvp_lx_flag ++ 168, ++ // no_residual_data_flag ++ 79, ++ // split_transform_flag ++ 224, 167, 122, ++ // cbf_luma ++ 153, 111, ++ // cbf_cb, cbf_cr ++ 149, 92, 167, 154, ++ // transform_skip_flag ++ 139, 139, ++ // explicit_rdpcm_flag ++ 139, 139, ++ // explicit_rdpcm_dir_flag ++ 139, 139, ++ // last_significant_coeff_x_prefix ++ 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, ++ 79, 108, 123, 93, ++ // last_significant_coeff_y_prefix ++ 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, ++ 79, 108, 123, 93, ++ // significant_coeff_group_flag ++ 121, 140, 61, 154, ++ // significant_coeff_flag ++ 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, ++ 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, ++ 153, 138, 138, 122, 121, 122, 121, 167, 151, 183, 140, 151, 183, 140, ++ 140, 140, ++ // coeff_abs_level_greater1_flag ++ 154, 196, 167, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, ++ 136, 122, 169, 208, 166, 167, 154, 152, 167, 182, ++ // coeff_abs_level_greater2_flag ++ 107, 167, 91, 107, 107, 167, ++ // log2_res_scale_abs ++ 154, 154, 154, 154, 154, 154, 154, 154, ++ // res_scale_sign_flag ++ 154, 154, ++ // cu_chroma_qp_offset_flag ++ 154, ++ // cu_chroma_qp_offset_idx ++ 154, ++ }, ++}; ++ ++static const uint8_t scan_1x1[1] = { ++ 0, ++}; ++ ++static const uint8_t horiz_scan2x2_x[4] = { ++ 0, 1, 0, 1, ++}; ++ ++static const uint8_t horiz_scan2x2_y[4] = { ++ 0, 0, 1, 1 ++}; ++ ++static const uint8_t horiz_scan4x4_x[16] = { ++ 0, 1, 2, 3, ++ 0, 1, 2, 3, ++ 0, 1, 2, 3, ++ 0, 1, 2, 3, ++}; ++ ++static const uint8_t horiz_scan4x4_y[16] = { ++ 0, 0, 0, 0, ++ 1, 1, 1, 1, ++ 2, 2, 2, 2, ++ 3, 3, 3, 3, ++}; ++ ++static const uint8_t horiz_scan8x8_inv[8][8] = { ++ { 0, 1, 2, 3, 16, 17, 18, 19, }, ++ { 4, 5, 6, 7, 20, 21, 22, 23, }, ++ { 8, 9, 10, 11, 24, 25, 26, 27, }, ++ { 12, 13, 14, 15, 28, 29, 30, 31, }, ++ { 32, 33, 34, 35, 48, 49, 50, 51, }, ++ { 36, 37, 38, 39, 52, 53, 54, 55, }, ++ { 40, 41, 42, 43, 56, 57, 58, 59, }, ++ { 44, 45, 46, 47, 60, 61, 62, 63, }, ++}; ++ ++static const uint8_t diag_scan2x2_x[4] = { ++ 0, 0, 1, 1, ++}; ++ ++static const uint8_t diag_scan2x2_y[4] = { ++ 0, 1, 0, 1, ++}; ++ ++static const uint8_t diag_scan2x2_inv[2][2] = { ++ { 0, 2, }, ++ { 1, 3, }, ++}; ++ ++static const uint8_t diag_scan4x4_inv[4][4] = { ++ { 0, 2, 5, 9, }, ++ { 1, 4, 8, 12, }, ++ { 3, 7, 11, 14, }, ++ { 6, 10, 13, 15, }, ++}; ++ ++static const uint8_t diag_scan8x8_inv[8][8] = { ++ { 0, 2, 5, 9, 14, 20, 27, 35, }, ++ { 1, 4, 8, 13, 19, 26, 34, 42, }, ++ { 3, 7, 12, 18, 25, 33, 41, 48, }, ++ { 6, 11, 17, 24, 32, 40, 47, 53, }, ++ { 10, 16, 23, 31, 39, 46, 52, 57, }, ++ { 15, 22, 30, 38, 45, 51, 56, 60, }, ++ { 21, 29, 37, 44, 50, 55, 59, 62, }, ++ { 28, 36, 43, 49, 54, 58, 61, 63, }, ++}; ++ ++ ++typedef struct ++{ ++ uint16_t coeff; ++ uint16_t scale; ++} xy_off_t; ++ ++#define XYT_C(x,y,t) ((x) + ((y) << (t))) ++#define SCALE_TRAFO(t) ((t) > 3 ? 3 : (t)) ++#define SCALE_SHR(t) ((t) - SCALE_TRAFO(t)) ++#define XYT_S(x,y,t) (((x) >> SCALE_SHR(t)) + (((y) >> SCALE_SHR(t)) << SCALE_TRAFO(t))) ++ ++#define XYT(x,y,t) {XYT_C(x,y,t), XYT_S(x,y,t)} ++ ++#define OFF_DIAG(t) {\ ++ XYT(0,0,t), XYT(0,1,t), XYT(1,0,t), XYT(0,2,t),\ ++ XYT(1,1,t), XYT(2,0,t), XYT(0,3,t), XYT(1,2,t),\ ++ XYT(2,1,t), XYT(3,0,t), XYT(1,3,t), XYT(2,2,t),\ ++ XYT(3,1,t), XYT(2,3,t), XYT(3,2,t), XYT(3,3,t)\ ++} ++ ++#define OFF_HORIZ(t) {\ ++ XYT(0,0,t), XYT(1,0,t), XYT(2,0,t), XYT(3,0,t),\ ++ XYT(0,1,t), XYT(1,1,t), XYT(2,1,t), XYT(3,1,t),\ ++ XYT(0,2,t), XYT(1,2,t), XYT(2,2,t), XYT(3,2,t),\ ++ XYT(0,3,t), XYT(1,3,t), XYT(2,3,t), XYT(3,3,t)\ ++} ++ ++#define OFF_VERT(t) {\ ++ XYT(0,0,t), XYT(0,1,t), XYT(0,2,t), XYT(0,3,t),\ ++ XYT(1,0,t), XYT(1,1,t), XYT(1,2,t), XYT(1,3,t),\ ++ XYT(2,0,t), XYT(2,1,t), XYT(2,2,t), XYT(2,3,t),\ ++ XYT(3,0,t), XYT(3,1,t), XYT(3,2,t), XYT(3,3,t)\ ++} ++ ++static const xy_off_t off_xys[3][4][16] = ++{ ++ {OFF_DIAG(2), OFF_DIAG(3), OFF_DIAG(4), OFF_DIAG(5)}, ++ {OFF_HORIZ(2), OFF_HORIZ(3), OFF_HORIZ(4), OFF_HORIZ(5)}, ++ {OFF_VERT(2), OFF_VERT(3), OFF_VERT(4), OFF_VERT(5)} ++}; ++ ++ ++// Helper fns ++#ifndef hevc_mem_bits32 ++static av_always_inline uint32_t hevc_mem_bits32(const void * buf, const unsigned int offset) ++{ ++ return AV_RB32((const uint8_t *)buf + (offset >> 3)) << (offset & 7); ++} ++#endif ++ ++#if AV_GCC_VERSION_AT_LEAST(3,4) && !defined(hevc_clz32) ++#define hevc_clz32 hevc_clz32_builtin ++static av_always_inline unsigned int hevc_clz32_builtin(const uint32_t x) ++{ ++ // __builtin_clz says it works on ints - so adjust if int is >32 bits long ++ return __builtin_clz(x) - (sizeof(int) * 8 - 32); ++} ++#endif ++ ++// It is unlikely that we will ever need this but include for completeness ++#ifndef hevc_clz32 ++static inline unsigned int hevc_clz32(unsigned int x) ++{ ++ unsigned int n = 1; ++ if ((x & 0xffff0000) == 0) { ++ n += 16; ++ x <<= 16; ++ } ++ if ((x & 0xff000000) == 0) { ++ n += 8; ++ x <<= 8; ++ } ++ if ((x & 0xf0000000) == 0) { ++ n += 4; ++ x <<= 4; ++ } ++ if ((x & 0xc0000000) == 0) { ++ n += 2; ++ x <<= 2; ++ } ++ return n - ((x >> 31) & 1); ++} ++#endif ++ ++static inline int cabac_overflow(const CABACContext * const cc) ++{ ++ av_assert0(cc->bytestream >= cc->bytestream_start); ++ return cc->bytestream >= cc->bytestream_end + 4; ++} ++ ++int ff_hevc_rpi_cabac_overflow(const HEVCRpiLocalContext * const lc) ++{ ++ return cabac_overflow(&lc->cc); ++} ++ ++#if !USE_BY22 ++// If no by22 then _by22 functions will revert to normal and so _peek/_flush ++// will no longer be called but the setup calls will still exist and we want ++// to null them out ++#define bypass_start(s) ++#define bypass_finish(s) ++#else ++// Use BY22 for residual bypass block ++ ++#define bypass_start(cc) get_cabac_by22_start(cc) ++#define bypass_finish(cc) get_cabac_by22_finish(cc) ++ ++// BY22 notes that bypass is simply a divide into the bitstream and so we ++// can peek out large quantities of bits at once and treat the result as if ++// it was VLC. In many cases this will lead to O(1) processing rather than ++// O(n) though the setup and teardown is sufficiently expensive that it is ++// only worth using if we expect to be dealing with more than a few bits ++// The definition of "a few bits" will vary from platform to platform but ++// tests on ARM show that it probably isn't worth it for a single coded ++// residual, but is for >1 - it also seems likely that if there are ++// more residuals then they are likely to be bigger and this will make the ++// O(1) nature of the code more worthwhile. ++ ++ ++// Bypass block start ++// Must be called before _by22_peek is used as it sets the CABAC environment ++// into the correct state. _by22_finish must be called to return to 'normal' ++// (i.e. non-bypass) cabac decoding ++#ifndef get_cabac_by22_start ++static inline void get_cabac_by22_start(CABACContext * const c) ++{ ++ const unsigned int bits = __builtin_ctz(c->low); ++ const uint32_t m = hevc_mem_bits32(c->bytestream, 0); ++ uint32_t x = (c->low << (22 - CABAC_BITS)) ^ ((m ^ 0x80000000U) >> (9 + CABAC_BITS - bits)); ++#if !USE_BY22_DIV ++ const uint32_t inv = cabac_by22_inv_range[c->range & 0xff]; ++#endif ++ ++ c->bytestream -= (CABAC_BITS / 8); ++ c->by22.bits = bits; ++#if !USE_BY22_DIV ++ c->by22.range = c->range; ++ c->range = inv; ++#endif ++ c->low = x; ++} ++#endif ++ ++// Bypass block finish ++// Must be called at the end of the bypass block to return to normal operation ++static inline void get_cabac_by22_finish(CABACContext * const c) ++{ ++ unsigned int used = c->by22.bits; ++ unsigned int bytes_used = (used / CABAC_BITS) * (CABAC_BITS / 8); ++ unsigned int bits_used = used & (CABAC_BITS == 16 ? 15 : 7); ++ ++ c->bytestream += bytes_used + (CABAC_BITS / 8); ++ c->low = (((uint32_t)c->low >> (22 - CABAC_BITS + bits_used)) | 1) << bits_used; ++#if !USE_BY22_DIV ++ c->range = c->by22.range; ++#endif ++} ++ ++// Peek bypass bits ++// _by22_start must be called before _by22_peek is called and _by22_flush ++// must be called afterwards to flush any used bits ++// The actual number of valid bits returned is ++// min(, CABAC_BY22_PEEK_BITS). CABAC_BY22_PEEK_BITS ++// will be at least 22 which should be long enough for any prefix or suffix ++// though probably not long enough for the worst case combination ++#ifndef get_cabac_by22_peek ++static inline uint32_t get_cabac_by22_peek(const CABACContext * const c) ++{ ++#if USE_BY22_DIV ++ return ((unsigned int)c->low / (unsigned int)c->range) << 9; ++#else ++ uint32_t x = c->low & ~1U; ++ const uint32_t inv = c->range; ++ ++ if (inv != 0) ++ x = (uint32_t)(((uint64_t)x * (uint64_t)inv) >> 32); ++ ++ return x << 1; ++#endif ++} ++#endif ++ ++// Flush bypass bits peeked by _by22_peek ++// Flush n bypass bits. n must be >= 1 to guarantee correct operation ++// val is an unmodified copy of whatever _by22_peek returned ++#ifndef get_cabac_by22_flush ++static inline void get_cabac_by22_flush(CABACContext * c, const unsigned int n, const uint32_t val) ++{ ++ // Subtract the bits used & reshift up to the top of the word ++#if USE_BY22_DIV ++ const uint32_t low = (((unsigned int)c->low << n) - (((val >> (32 - n)) * (unsigned int)c->range) << 23)); ++#else ++ const uint32_t low = (((uint32_t)c->low << n) - (((val >> (32 - n)) * c->by22.range) << 23)); ++#endif ++ ++ // and refill lower bits ++ // We will probably OR over some existing bits but that doesn't matter ++ c->by22.bits += n; ++ c->low = low | (hevc_mem_bits32(c->bytestream, c->by22.bits) >> 9); ++} ++#endif ++ ++#endif // USE_BY22 ++ ++ ++void ff_hevc_rpi_save_states(HEVCRpiContext *s, const HEVCRpiLocalContext * const lc) ++{ ++ memcpy(s->cabac_save->rice, lc->stat_coeff, 4); ++ memcpy(s->cabac_save->state, lc->cabac_state, HEVC_CONTEXTS); ++} ++ ++static void load_states(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ memcpy(lc->stat_coeff, s->cabac_save->rice, 4); ++ memcpy(lc->cabac_state, s->cabac_save->state, HEVC_CONTEXTS); ++} ++ ++int ff_hevc_rpi_cabac_init_decoder(HEVCRpiLocalContext * const lc) ++{ ++ GetBitContext * const gb = &lc->gb; ++ skip_bits(gb, 1); ++ align_get_bits(gb); ++ return ff_init_cabac_decoder(&lc->cc, ++ gb->buffer + get_bits_count(gb) / 8, ++ (get_bits_left(gb) + 7) / 8); ++} ++ ++static void cabac_init_state(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ int init_type = 2 - s->sh.slice_type; ++ int i; ++ ++ if (s->sh.cabac_init_flag && s->sh.slice_type != HEVC_SLICE_I) ++ init_type ^= 3; ++ ++ for (i = 0; i < HEVC_CONTEXTS; i++) { ++ int init_value = init_values[init_type][i]; ++ int m = (init_value >> 4) * 5 - 45; ++ int n = ((init_value & 15) << 3) - 16; ++ int pre = 2 * (((m * av_clip(s->sh.slice_qp, 0, 51)) >> 4) + n) - 127; ++ ++ pre ^= pre >> 31; ++ if (pre > 124) ++ pre = 124 + (pre & 1); ++ lc->cabac_state[i] = pre; ++ } ++ ++ for (i = 0; i < 4; i++) ++ lc->stat_coeff[i] = 0; ++} ++ ++void ff_hevc_rpi_cabac_init(const HEVCRpiContext * const s, HEVCRpiLocalContext *const lc, const unsigned int ctb_flags) ++{ ++ if (lc->cabac_init_req == 1 || (ctb_flags & CTB_TS_FLAGS_CIREQ) != 0) ++ { ++ lc->qPy_pred = s->sh.slice_qp; ++ cabac_init_state(s, lc); ++ } ++ else if ((ctb_flags & CTB_TS_FLAGS_CLOAD) != 0) ++ { ++ lc->qPy_pred = s->sh.slice_qp; ++ load_states(s, lc); ++ } ++ lc->cabac_init_req = 0; ++} ++ ++#define GET_CABAC_LC(ctx) get_cabac(&lc->cc, lc->cabac_state + (ctx)) ++ ++int ff_hevc_rpi_get_cabac(CABACContext * const c, uint8_t * const state) ++{ ++ return get_cabac_inline(c, state); ++} ++ ++int ff_hevc_rpi_get_cabac_terminate(CABACContext * const c) ++{ ++ return get_cabac_terminate(c); ++} ++ ++int ff_hevc_rpi_sao_type_idx_decode(HEVCRpiLocalContext * const lc) ++{ ++ if (!GET_CABAC_LC(elem_offset[SAO_TYPE_IDX])) ++ return 0; ++ ++ if (!get_cabac_bypass(&lc->cc)) ++ return SAO_BAND; ++ return SAO_EDGE; ++} ++ ++int ff_hevc_rpi_sao_band_position_decode(HEVCRpiLocalContext * const lc) ++{ ++ int i; ++ int value = get_cabac_bypass(&lc->cc); ++ ++ for (i = 0; i < 4; i++) ++ value = (value << 1) | get_cabac_bypass(&lc->cc); ++ return value; ++} ++ ++int ff_hevc_rpi_sao_offset_abs_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ int i = 0; ++ int length = (1 << (FFMIN(s->ps.sps->bit_depth, 10) - 5)) - 1; ++ ++ while (i < length && get_cabac_bypass(&lc->cc)) ++ i++; ++ return i; ++} ++ ++int ff_hevc_rpi_sao_offset_sign_decode(HEVCRpiLocalContext * const lc) ++{ ++ return get_cabac_bypass(&lc->cc); ++} ++ ++int ff_hevc_rpi_sao_eo_class_decode(HEVCRpiLocalContext * const lc) ++{ ++ int ret = get_cabac_bypass(&lc->cc) << 1; ++ ret |= get_cabac_bypass(&lc->cc); ++ return ret; ++} ++ ++int ff_hevc_rpi_cu_qp_delta(HEVCRpiLocalContext * const lc) ++{ ++ int val = 1; ++ ++ if (get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CU_QP_DELTA) == 0) ++ return 0; ++ ++ while (val < 5 && ++ get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CU_QP_DELTA + 1) != 0) ++ val++; ++ ++ if (val >= 5) { ++ unsigned int k = 0; ++ while (k < CABAC_MAX_BIN && get_cabac_bypass(&lc->cc)) { ++ val += 1 << k; ++ k++; ++ } ++// if (k == CABAC_MAX_BIN) ++// av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k); ++ ++ while (k--) ++ val += get_cabac_bypass(&lc->cc) << k; ++ } ++ return get_cabac_bypass(&lc->cc) ? -val : val; ++} ++ ++int ff_hevc_rpi_cu_chroma_qp_offset_idx(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ int c_max= FFMAX(5, s->ps.pps->chroma_qp_offset_list_len_minus1); ++ int i = 0; ++ ++ while (i < c_max && GET_CABAC_LC(elem_offset[CU_CHROMA_QP_OFFSET_IDX])) ++ i++; ++ ++ return i; ++} ++ ++int ff_hevc_rpi_part_mode_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const int log2_cb_size) ++{ ++ if (GET_CABAC_LC(elem_offset[PART_MODE])) // 1 ++ return PART_2Nx2N; ++ if (log2_cb_size == s->ps.sps->log2_min_cb_size) { ++ if (lc->cu.pred_mode == MODE_INTRA) // 0 ++ return PART_NxN; ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 1)) // 01 ++ return PART_2NxN; ++ if (log2_cb_size == 3) // 00 ++ return PART_Nx2N; ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 2)) // 001 ++ return PART_Nx2N; ++ return PART_NxN; // 000 ++ } ++ ++ if (!s->ps.sps->amp_enabled_flag) { ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 1)) // 01 ++ return PART_2NxN; ++ return PART_Nx2N; ++ } ++ ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 1)) { // 01X, 01XX ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 3)) // 011 ++ return PART_2NxN; ++ if (get_cabac_bypass(&lc->cc)) // 0101 ++ return PART_2NxnD; ++ return PART_2NxnU; // 0100 ++ } ++ ++ if (GET_CABAC_LC(elem_offset[PART_MODE] + 3)) // 001 ++ return PART_Nx2N; ++ if (get_cabac_bypass(&lc->cc)) // 0001 ++ return PART_nRx2N; ++ return PART_nLx2N; // 0000 ++} ++ ++int ff_hevc_rpi_mpm_idx_decode(HEVCRpiLocalContext * const lc) ++{ ++ int i = 0; ++ while (i < 2 && get_cabac_bypass(&lc->cc)) ++ i++; ++ return i; ++} ++ ++int ff_hevc_rpi_rem_intra_luma_pred_mode_decode(HEVCRpiLocalContext * const lc) ++{ ++ int i; ++ int value = get_cabac_bypass(&lc->cc); ++ ++ for (i = 0; i < 4; i++) ++ value = (value << 1) | get_cabac_bypass(&lc->cc); ++ return value; ++} ++ ++int ff_hevc_rpi_intra_chroma_pred_mode_decode(HEVCRpiLocalContext * const lc) ++{ ++ int ret; ++ if (!GET_CABAC_LC(elem_offset[INTRA_CHROMA_PRED_MODE])) ++ return 4; ++ ++ ret = get_cabac_bypass(&lc->cc) << 1; ++ ret |= get_cabac_bypass(&lc->cc); ++ return ret; ++} ++ ++int ff_hevc_rpi_merge_idx_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ int i = GET_CABAC_LC(elem_offset[MERGE_IDX]); ++ ++ if (i != 0) { ++ while (i < s->sh.max_num_merge_cand-1 && get_cabac_bypass(&lc->cc)) ++ i++; ++ } ++ return i; ++} ++ ++int ff_hevc_rpi_inter_pred_idc_decode(HEVCRpiLocalContext * const lc, int nPbW, int nPbH) ++{ ++ if (nPbW + nPbH == 12) ++ return GET_CABAC_LC(elem_offset[INTER_PRED_IDC] + 4); ++ if (GET_CABAC_LC(elem_offset[INTER_PRED_IDC] + lc->ct_depth)) ++ return PRED_BI; ++ ++ return GET_CABAC_LC(elem_offset[INTER_PRED_IDC] + 4); ++} ++ ++int ff_hevc_rpi_ref_idx_lx_decode(HEVCRpiLocalContext * const lc, const int num_ref_idx_lx) ++{ ++ int i = 0; ++ int max = num_ref_idx_lx - 1; ++ int max_ctx = FFMIN(max, 2); ++ ++ while (i < max_ctx && GET_CABAC_LC(elem_offset[REF_IDX_L0] + i)) ++ i++; ++ if (i == 2) { ++ while (i < max && get_cabac_bypass(&lc->cc)) ++ i++; ++ } ++ ++ return i; ++} ++ ++static av_always_inline int abs_mvd_greater0_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return GET_CABAC_LC(elem_offset[ABS_MVD_GREATER0_FLAG]); ++} ++ ++static av_always_inline int abs_mvd_greater1_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return GET_CABAC_LC(elem_offset[ABS_MVD_GREATER1_FLAG] + 1); ++} ++ ++#if !USE_BY22 ++static av_always_inline int mvd_decode(HEVCRpiLocalContext * const lc) ++{ ++ int ret = 2; ++ int k = 1; ++ ++ while (k < CABAC_MAX_BIN && get_cabac_bypass(&lc->cc)) { ++ ret += 1U << k; ++ k++; ++ } ++ if (k == CABAC_MAX_BIN) { ++ av_log(NULL, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k); ++ return 0; ++ } ++ ++ while (k--) ++ ret += get_cabac_bypass(&lc->cc) << k; ++ return get_cabac_bypass_sign(&lc->cc, -ret); ++} ++#endif ++ ++static av_always_inline int mvd_sign_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return get_cabac_bypass_sign(&lc->cc, -1); ++} ++ ++static int hevc_transform_skip_flag_decode(HEVCRpiLocalContext * const lc, int c_idx_nz) ++{ ++ return GET_CABAC_LC(elem_offset[TRANSFORM_SKIP_FLAG] + c_idx_nz); ++} ++ ++static int explicit_rdpcm_flag_decode(HEVCRpiLocalContext * const lc, int c_idx_nz) ++{ ++ return GET_CABAC_LC(elem_offset[EXPLICIT_RDPCM_FLAG] + c_idx_nz); ++} ++ ++static int explicit_rdpcm_dir_flag_decode(HEVCRpiLocalContext * const lc, int c_idx_nz) ++{ ++ return GET_CABAC_LC(elem_offset[EXPLICIT_RDPCM_DIR_FLAG] + c_idx_nz); ++} ++ ++ ++int ff_hevc_rpi_log2_res_scale_abs(HEVCRpiLocalContext * const lc, const int idx) { ++ int i =0; ++ ++ while (i < 4 && GET_CABAC_LC(elem_offset[LOG2_RES_SCALE_ABS] + 4 * idx + i)) ++ i++; ++ ++ return i; ++} ++ ++static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCRpiLocalContext * const lc, int c_idx_nz, ++ int log2_size, int *last_scx_prefix, int *last_scy_prefix) ++{ ++ int i = 0; ++ int max = (log2_size << 1) - 1; ++ int ctx_offset, ctx_shift; ++ ++ if (!c_idx_nz) { ++ ctx_offset = 3 * (log2_size - 2) + ((log2_size - 1) >> 2); ++ ctx_shift = (log2_size + 1) >> 2; ++ } else { ++ ctx_offset = 15; ++ ctx_shift = log2_size - 2; ++ } ++ while (i < max && ++ GET_CABAC_LC(elem_offset[LAST_SIGNIFICANT_COEFF_X_PREFIX] + (i >> ctx_shift) + ctx_offset)) ++ i++; ++ *last_scx_prefix = i; ++ ++ i = 0; ++ while (i < max && ++ GET_CABAC_LC(elem_offset[LAST_SIGNIFICANT_COEFF_Y_PREFIX] + (i >> ctx_shift) + ctx_offset)) ++ i++; ++ *last_scy_prefix = i; ++} ++ ++static av_always_inline int last_significant_coeff_suffix_decode(HEVCRpiLocalContext * const lc, ++ int last_significant_coeff_prefix) ++{ ++ int i; ++ int length = (last_significant_coeff_prefix >> 1) - 1; ++ int value = get_cabac_bypass(&lc->cc); ++ ++ for (i = 1; i < length; i++) ++ value = (value << 1) | get_cabac_bypass(&lc->cc); ++ return value; ++} ++ ++static av_always_inline int significant_coeff_group_flag_decode(HEVCRpiLocalContext * const lc, int c_idx_nz, int ctx_cg) ++{ ++ int inc; ++ ++ inc = (ctx_cg != 0) + (c_idx_nz << 1); ++ ++ return GET_CABAC_LC(elem_offset[SIGNIFICANT_COEFF_GROUP_FLAG] + inc); ++} ++ ++static av_always_inline int significant_coeff_flag_decode_0(HEVCRpiLocalContext * const lc, int offset) ++{ ++ return GET_CABAC_LC(elem_offset[SIGNIFICANT_COEFF_FLAG] + offset); ++} ++ ++#if !USE_BY22 ++#define coeff_abs_level_remaining_decode_bypass(s,r) coeff_abs_level_remaining_decode(s, r) ++#endif ++ ++ ++#ifndef coeff_abs_level_remaining_decode_bypass ++static int coeff_abs_level_remaining_decode_bypass(CABACContext * const c, const unsigned int rice_param) ++{ ++ uint32_t y; ++ unsigned int prefix; ++ unsigned int last_coeff_abs_level_remaining; ++ unsigned int n; ++ ++ y = get_cabac_by22_peek(c); ++ prefix = hevc_clz32(~y); ++ // y << prefix will always have top bit 0 ++ ++ if (prefix < 3) { ++ const unsigned int suffix = (y << prefix) >> (31 - rice_param); ++ last_coeff_abs_level_remaining = (prefix << rice_param) + suffix; ++ n = prefix + 1 + rice_param; ++ } ++ else if (prefix * 2 + rice_param <= CABAC_BY22_PEEK_BITS + 2) ++ { ++ const uint32_t suffix = ((y << prefix) | 0x80000000) >> (34 - (prefix + rice_param)); ++ ++ last_coeff_abs_level_remaining = (2 << rice_param) + suffix; ++ n = prefix * 2 + rice_param - 2; ++ } ++ else { ++ unsigned int suffix; ++ ++ get_cabac_by22_flush(c, prefix, y); ++ y = get_cabac_by22_peek(c); ++ ++ suffix = (y | 0x80000000) >> (34 - (prefix + rice_param)); ++ last_coeff_abs_level_remaining = (2 << rice_param) + suffix; ++ n = prefix + rice_param - 2; ++ } ++ ++ get_cabac_by22_flush(c, n, y); ++ ++ return last_coeff_abs_level_remaining; ++} ++#endif ++ ++static int coeff_abs_level_remaining_decode(CABACContext * const c, int rc_rice_param) ++{ ++ int prefix = 0; ++ int suffix = 0; ++ int last_coeff_abs_level_remaining; ++ int i; ++ ++ while (prefix < CABAC_MAX_BIN && get_cabac_bypass(c)) ++ prefix++; ++ if (prefix == CABAC_MAX_BIN) { ++// av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); ++ return 0; ++ } ++ ++ if (prefix < 3) { ++ for (i = 0; i < rc_rice_param; i++) ++ suffix = (suffix << 1) | get_cabac_bypass(c); ++ last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix; ++ } else { ++ int prefix_minus3 = prefix - 3; ++ for (i = 0; i < prefix_minus3 + rc_rice_param; i++) ++ suffix = (suffix << 1) | get_cabac_bypass(c); ++ last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1) ++ << rc_rice_param) + suffix; ++ } ++ ++ return last_coeff_abs_level_remaining; ++} ++ ++#if !USE_BY22 ++#define coeff_sign_flag_decode_bypass coeff_sign_flag_decode ++static inline uint32_t coeff_sign_flag_decode(CABACContext * const c, const unsigned int nb) ++{ ++ unsigned int i; ++ uint32_t ret = 0; ++ ++ for (i = 0; i < nb; i++) ++ ret = (ret << 1) | get_cabac_bypass(c); ++ ++ return ret << (32 - nb); ++} ++#endif ++ ++#ifndef coeff_sign_flag_decode_bypass ++static inline uint32_t coeff_sign_flag_decode_bypass(CABACContext * const c, const unsigned int nb) ++{ ++ uint32_t y; ++ y = get_cabac_by22_peek(c); ++ get_cabac_by22_flush(c, nb, y); ++ return y & ~(0xffffffffU >> nb); ++} ++#endif ++ ++ ++#ifndef get_cabac_greater1_bits ++static inline unsigned int get_cabac_greater1_bits(CABACContext * const c, const unsigned int n, ++ uint8_t * const state0) ++{ ++ unsigned int i; ++ unsigned int rv = 0; ++ for (i = 0; i != n; ++i) { ++ const unsigned int idx = rv != 0 ? 0 : i < 3 ? i + 1 : 3; ++ const unsigned int b = get_cabac(c, state0 + idx); ++ rv = (rv << 1) | b; ++ } ++ return rv; ++} ++#endif ++ ++ ++// N.B. levels returned are the values assuming coeff_abs_level_remaining ++// is uncoded, so 1 must be added if it is coded. sum_abs also reflects ++// this version of events. ++static inline uint32_t get_greaterx_bits(HEVCRpiLocalContext * const lc, const unsigned int n_end, int * const levels, ++ int * const pprev_subset_coded, int * const psum, ++ const unsigned int idx0_gt1, const unsigned int idx_gt2) ++{ ++ CABACContext * const c = &lc->cc; ++ uint8_t * const state0 = lc->cabac_state + idx0_gt1; ++ uint8_t * const state_gt2 = lc->cabac_state + idx_gt2; ++ unsigned int rv; ++ unsigned int i; ++ const unsigned int n = FFMIN(n_end, 8); ++ ++ // Really this is i != n but the simple unconditional loop is cheaper ++ // and faster ++ for (i = 0; i != 8; ++i) ++ levels[i] = 1; ++ ++ rv = get_cabac_greater1_bits(c, n, state0); ++ ++ *pprev_subset_coded = 0; ++ *psum = n; ++ ++ rv <<= (32 - n); ++ if (rv != 0) ++ { ++ *pprev_subset_coded = 1; ++ *psum = n + 1; ++ i = hevc_clz32(rv); ++ levels[i] = 2; ++ if (get_cabac(c, state_gt2) == 0) ++ { ++ // Unset first coded bit ++ rv &= ~(0x80000000U >> i); ++ } ++ } ++ ++ if (n_end > 8) { ++ const unsigned int g8 = n_end - 8; ++ rv |= ((1 << g8) - 1) << (24 - g8); ++ for (i = 0; i != g8; ++i) { ++ levels[i + 8] = 0; ++ } ++ } ++ ++ return rv; ++} ++ ++// extended_precision_processing_flag must be false given we are ++// putting the result into a 16-bit array ++// So trans_coeff_level must fit in 16 bits too (7.4.9.1 definition of coeff_abs_level_remaining) ++// scale_m is uint8_t ++// ++// scale is [40 - 72] << [0..12] based on qp- worst case is (45 << 12) ++// or it can be 2 (if we have transquant_bypass) ++// shift is set to one less than we really want but would normally be ++// s->ps.sps->bit_depth (max 16, min 8) + log2_trafo_size (max 5, min 2?) - 5 = max 16 min 5? ++// however the scale shift is substracted from shift to a min 0 so scale_m worst = 45 << 6 ++// This can still theoretically lead to overflow but the coding would have to be very odd (& inefficient) ++// to achieve it ++ ++#ifndef trans_scale_sat ++static inline int trans_scale_sat(const int level, const unsigned int scale, const unsigned int scale_m, const unsigned int shift) ++{ ++ return av_clip_int16((((level * (int)(scale * scale_m)) >> shift) + 1) >> 1); ++} ++#endif ++ ++ ++#ifndef update_rice ++static inline void update_rice(uint8_t * const stat_coeff, ++ const unsigned int last_coeff_abs_level_remaining, ++ const unsigned int c_rice_param) ++{ ++ const unsigned int x = (last_coeff_abs_level_remaining << 1) >> c_rice_param; ++ if (x >= 6) ++ (*stat_coeff)++; ++ else if (x == 0 && *stat_coeff > 0) ++ (*stat_coeff)--; ++} ++#endif ++ ++ ++// n must be > 0 on entry ++#ifndef get_cabac_sig_coeff_flag_idxs ++static inline uint8_t * get_cabac_sig_coeff_flag_idxs(CABACContext * const c, uint8_t * const state0, ++ unsigned int n, ++ const uint8_t const * ctx_map, ++ uint8_t * p) ++{ ++ do { ++ if (get_cabac(c, state0 + ctx_map[n])) ++ *p++ = n; ++ } while (--n != 0); ++ return p; ++} ++#endif ++ ++ ++static int get_sig_coeff_flag_idxs(CABACContext * const c, uint8_t * const state0, ++ unsigned int n, ++ const uint8_t * ctx_map, // const ptr here but not in asm ++ uint8_t * const flag_idx) ++{ ++ int rv; ++ ++ rv = get_cabac_sig_coeff_flag_idxs(c, state0, n, ctx_map, flag_idx) - flag_idx; ++ ++ return rv; ++} ++ ++#define H4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ ++ x0, x1, x2, x3,\ ++ x4, x5, x6, x7,\ ++ x8, x9, x10, x11,\ ++ x12, x13, x14, x15} ++ ++#define V4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ ++ x0, x4, x8, x12,\ ++ x1, x5, x9, x13,\ ++ x2, x6, x10, x14,\ ++ x3, x7, x11, x15} ++ ++#define D4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ ++ x0, x4, x1, x8,\ ++ x5, x2, x12, x9,\ ++ x6, x3, x13, x10,\ ++ x7, x14, x11, x15} ++ ++ ++static inline int next_subset(HEVCRpiLocalContext * const lc, int i, const int c_idx_nz, ++ uint8_t * const significant_coeff_group_flag, ++ const uint8_t * const scan_x_cg, const uint8_t * const scan_y_cg, ++ int * const pPrev_sig) ++{ ++ while (--i >= 0) { ++ uint8_t * const gf_y = scan_y_cg[i] + significant_coeff_group_flag; ++ const unsigned int x_cg = scan_x_cg[i]; ++ ++ // For the flag decode we only care about Z/NZ but ++ // we use the full Right * 2 + Down when calculating ++ // significant coeff flags so we obtain it here. ++ // ++ // The group flag array is one longer than it needs to ++ // be so we don't need to check for y_cg limits ++ const unsigned int prev_sig = ((gf_y[0] >> x_cg) & 2) | ((gf_y[1] >> x_cg) & 1); ++ ++ if (i == 0 || ++ significant_coeff_group_flag_decode(lc, c_idx_nz, prev_sig)) ++ { ++ gf_y[0] |= (1 << x_cg); ++ *pPrev_sig = prev_sig; ++ break; ++ } ++ } ++ ++ return i; ++} ++ ++static void rpi_add_residual(const HEVCRpiContext *const s, HEVCRpiJob * const jb, ++ const unsigned int log2_trafo_size, const unsigned int c_idx, ++ const unsigned int x0, const unsigned int y0, const int16_t * const coeffs) ++{ ++ const AVFrame * const frame = s->frame; ++ const unsigned int stride = frame_stride1(s->frame, c_idx); ++ const unsigned int x = x0 >> ctx_hshift(s, c_idx); ++ const unsigned int y = y0 >> ctx_vshift(s, c_idx); ++ const int is_sliced = 1; // av_rpi_is_sand_frame(frame); ++ uint8_t * const dst = !is_sliced ? ++ s->frame->data[c_idx] + y * stride + (x << s->ps.sps->pixel_shift) : ++ c_idx == 0 ? ++ av_rpi_sand_frame_pos_y(frame, x, y) : ++ av_rpi_sand_frame_pos_c(frame, x, y); ++ ++ const unsigned int i = jb->intra.n; ++ HEVCPredCmd *const pc = jb->intra.cmds + i - 1; ++ ++ if (i != 0 && c_idx == 2 && pc->type == RPI_PRED_ADD_RESIDUAL_U && ++ pc->ta.dst == dst) ++ { ++ av_assert1(pc->size == log2_trafo_size && ++ pc->c_idx == 1 && ++ pc->ta.stride == stride); ++ ++ pc->type = RPI_PRED_ADD_RESIDUAL_C; ++ } ++ else if (i != 0 && c_idx == 2 && pc->type == RPI_PRED_ADD_DC_U && ++ pc->dc.dst == dst) ++ { ++ const int16_t dc = (int16_t)pc->dc.dc; // Discard top bits ++ av_assert1(pc->size == log2_trafo_size && ++ pc->c_idx == 1 && ++ pc->dc.stride == stride); ++ ++ // Rewrite as add residual - must rewrite all fields as different union member ++ pc->type = RPI_PRED_ADD_RESIDUAL_V; ++ pc->ta.buf = coeffs; ++ pc->ta.dst = dst; ++ pc->ta.stride = stride; ++ pc->ta.dc = dc; ++ } ++ else ++ { ++ HEVCPredCmd * const cmd = pc + 1; ++ jb->intra.n = i + 1; ++ ++ cmd->type = RPI_PRED_ADD_RESIDUAL + (is_sliced ? c_idx : 0); ++ cmd->size = log2_trafo_size; ++ cmd->ta.buf = coeffs; ++ cmd->ta.dst = dst; ++ cmd->ta.stride = stride; ++ cmd->ta.dc = 0; ++ } ++} ++ ++ ++static void rpi_add_dc(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const unsigned int log2_trafo_size, const unsigned int c_idx, ++ const unsigned int x0, const unsigned int y0, const int16_t * const coeffs) ++{ ++ const AVFrame * const frame = s->frame; ++ const unsigned int stride = frame_stride1(s->frame, c_idx); ++ const unsigned int x = x0 >> ctx_hshift(s, c_idx); ++ const unsigned int y = y0 >> ctx_vshift(s, c_idx); ++ const int is_sliced = 1; ++ uint8_t * const dst = !is_sliced ? ++ s->frame->data[c_idx] + y * stride + (x << s->ps.sps->pixel_shift) : ++ c_idx == 0 ? ++ av_rpi_sand_frame_pos_y(frame, x, y) : ++ av_rpi_sand_frame_pos_c(frame, x, y); ++ ++ const unsigned int shift = FFMAX(14 - s->ps.sps->bit_depth, 0); ++ const int coeff = (coeffs[0] + (1 | (1 << shift))) >> (shift + 1); ++ ++ const unsigned int i = jb->intra.n; ++ HEVCPredCmd *const pc = jb->intra.cmds + i - 1; ++ ++ if (i != 0 && c_idx == 2 && pc->type == RPI_PRED_ADD_RESIDUAL_U && ++ pc->ta.dst == dst) ++ { ++ av_assert1(pc->size == log2_trafo_size && ++ pc->c_idx == 1 && ++ pc->ta.stride == stride); ++ ++ pc->ta.dc = (int16_t)coeff; ++ } ++ else if (i != 0 && c_idx == 2 && pc->type == RPI_PRED_ADD_DC_U && ++ pc->dc.dst == dst) ++ { ++ av_assert1(pc->size == log2_trafo_size && ++ pc->c_idx == 1 && ++ pc->dc.stride == stride && ++ (pc->dc.dc & ~0xffff) == 0); ++ ++ pc->dc.dc |= (coeff << 16); ++ } ++ else ++ { ++ HEVCPredCmd * const cmd = pc + 1; ++ jb->intra.n = i + 1; ++ ++ cmd->type = RPI_PRED_ADD_DC + c_idx; ++ cmd->size = log2_trafo_size; ++ cmd->dc.dst = dst; ++ cmd->dc.stride = stride; ++ cmd->dc.dc = c_idx == 0 ? coeff : c_idx == 2 ? coeff << 16 : coeff & 0xffff; ++ } ++} ++ ++ ++void ff_hevc_rpi_hls_residual_coding(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const int x0, const int y0, ++ const int log2_trafo_size, const enum ScanType scan_idx, ++ const int c_idx) ++{ ++ int trans_skip_or_bypass = lc->cu.cu_transquant_bypass_flag; ++ ++ int last_significant_coeff_x, last_significant_coeff_y; ++ int num_coeff = 0; ++ int prev_subset_coded = 0; ++ ++ int num_last_subset; ++ int x_cg_last_sig, y_cg_last_sig; ++ ++ const uint8_t *scan_x_cg, *scan_y_cg; ++ const xy_off_t * const scan_xy_off = off_xys[scan_idx][log2_trafo_size - 2]; ++ ++ int use_vpu; ++#if RPI_COMPRESS_COEFFS ++ int num_nonzero = 0; ++ int use_compress = 0; ++ int *coeffs32; ++#endif ++ int use_dc = 0; ++ int16_t *coeffs; ++ uint8_t significant_coeff_group_flag[9] = {0}; // Allow 1 final byte that is always zero ++ int explicit_rdpcm_flag = 0; ++ int explicit_rdpcm_dir_flag; ++ ++ int i; ++ int shift,scale; ++ const uint8_t *scale_matrix = NULL; ++ uint8_t dc_scale; ++ const int c_idx_nz = (c_idx != 0); ++ const int pred_mode_intra = c_idx_nz ? lc->tu.intra_pred_mode_c : lc->tu.intra_pred_mode; ++ int prev_sig = 0; ++ int may_hide_sign; ++ ++ int16_t dummy_coeffs[16]; ++ ++ // Derive QP for dequant ++ if (!lc->cu.cu_transquant_bypass_flag) { ++ may_hide_sign = s->ps.pps->sign_data_hiding_flag; ++ ++ if (s->ps.pps->transform_skip_enabled_flag && ++ log2_trafo_size <= s->ps.pps->log2_max_transform_skip_block_size) { ++ int transform_skip_flag = hevc_transform_skip_flag_decode(lc, c_idx_nz); ++ if (transform_skip_flag) { ++ trans_skip_or_bypass = 1; ++ if (lc->cu.pred_mode == MODE_INTRA && ++ s->ps.sps->implicit_rdpcm_enabled_flag && ++ (pred_mode_intra == 10 || pred_mode_intra == 26)) { ++ may_hide_sign = 0; ++ } ++ } ++ } ++ ++ { ++ static const uint8_t level_scale[8] = { ++ 40, 45, 51, 57, 64, 72, 0, 0 // Pad to 8 ++ }; ++ const int qp6 = (int8_t)lc->tu.qp_divmod6[c_idx][lc->qp_y]; ++ ++ // Shift is set to one less than will actually occur as the scale ++ // and saturate step adds 1 and then shifts right again ++ scale = level_scale[qp6 & 7]; ++// shift = s->ps.sps->bit_depth + log2_trafo_size - (int)(qp6 >> 3); ++ shift = log2_trafo_size - (qp6 >> 3); ++ ++ if (shift < 0) { ++ scale <<= -shift; ++ shift = 0; ++ } ++ } ++ ++ if (s->ps.sps->scaling_list_enable_flag && !(trans_skip_or_bypass && log2_trafo_size > 2)) { ++ const ScalingList * const sl = s->ps.pps->scaling_list_data_present_flag ? ++ &s->ps.pps->scaling_list : &s->ps.sps->scaling_list; ++ const unsigned int matrix_id = ++ lc->cu.pred_mode != MODE_INTRA ? 3 + c_idx : c_idx; ++ ++ scale_matrix = sl->sl[log2_trafo_size - 2][matrix_id]; ++ dc_scale = scale_matrix[0]; ++ if (log2_trafo_size >= 4) ++ dc_scale = sl->sl_dc[log2_trafo_size - 4][matrix_id]; ++ } ++ else ++ { ++ static const uint8_t sixteen_scale[64] = { ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16, ++ 16, 16, 16, 16, 16, 16, 16, 16 ++ }; ++ scale_matrix = sixteen_scale; ++ dc_scale = 16; ++ } ++ } else { ++ static const uint8_t unit_scale[64] = { ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, ++ }; ++ scale_matrix = unit_scale; ++ shift = 0; ++ scale = 2; // We will shift right to kill this ++ dc_scale = 1; ++ ++ may_hide_sign = 0; ++ } ++ ++ ++ ++ ++ if (lc->cu.pred_mode == MODE_INTER && s->ps.sps->explicit_rdpcm_enabled_flag && ++ trans_skip_or_bypass) { ++ explicit_rdpcm_flag = explicit_rdpcm_flag_decode(lc, c_idx_nz); ++ if (explicit_rdpcm_flag) { ++ may_hide_sign = 0; ++ explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(lc, c_idx_nz); ++ } ++ } ++ ++ last_significant_coeff_xy_prefix_decode(lc, c_idx_nz, log2_trafo_size, ++ &last_significant_coeff_x, &last_significant_coeff_y); ++ ++ if (last_significant_coeff_x > 3) { ++ int suffix = last_significant_coeff_suffix_decode(lc, last_significant_coeff_x); ++ last_significant_coeff_x = (1 << ((last_significant_coeff_x >> 1) - 1)) * ++ (2 + (last_significant_coeff_x & 1)) + ++ suffix; ++ } ++ ++ if (last_significant_coeff_y > 3) { ++ int suffix = last_significant_coeff_suffix_decode(lc, last_significant_coeff_y); ++ last_significant_coeff_y = (1 << ((last_significant_coeff_y >> 1) - 1)) * ++ (2 + (last_significant_coeff_y & 1)) + ++ suffix; ++ } ++ ++ if (scan_idx == SCAN_VERT) ++ FFSWAP(int, last_significant_coeff_x, last_significant_coeff_y); ++ ++ x_cg_last_sig = last_significant_coeff_x >> 2; ++ y_cg_last_sig = last_significant_coeff_y >> 2; ++ ++ switch (scan_idx) { ++ case SCAN_DIAG: { ++ int last_x_c = last_significant_coeff_x & 3; ++ int last_y_c = last_significant_coeff_y & 3; ++ ++ num_coeff = diag_scan4x4_inv[last_y_c][last_x_c]; ++ ++ switch (log2_trafo_size) { ++ case 2: ++ scan_x_cg = scan_1x1; ++ scan_y_cg = scan_1x1; ++ break; ++ case 3: ++ num_coeff += diag_scan2x2_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = diag_scan2x2_x; ++ scan_y_cg = diag_scan2x2_y; ++ break; ++ case 4: ++ num_coeff += diag_scan4x4_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = ff_hevc_rpi_diag_scan4x4_x; ++ scan_y_cg = ff_hevc_rpi_diag_scan4x4_y; ++ break; ++ case 5: ++ default: ++ num_coeff += diag_scan8x8_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = ff_hevc_rpi_diag_scan8x8_x; ++ scan_y_cg = ff_hevc_rpi_diag_scan8x8_y; ++ break; ++ } ++ break; ++ } ++ case SCAN_HORIZ: ++ scan_x_cg = horiz_scan2x2_x; ++ scan_y_cg = horiz_scan2x2_y; ++ num_coeff = horiz_scan8x8_inv[last_significant_coeff_y][last_significant_coeff_x]; ++ break; ++ default: //SCAN_VERT ++ scan_x_cg = horiz_scan2x2_y; ++ scan_y_cg = horiz_scan2x2_x; ++ num_coeff = horiz_scan8x8_inv[last_significant_coeff_x][last_significant_coeff_y]; ++ break; ++ } ++ num_coeff++; ++ num_last_subset = (num_coeff - 1) >> 4; ++ ++ significant_coeff_group_flag[y_cg_last_sig] = 1 << x_cg_last_sig; // 1st subset always significant ++ ++ { ++ const unsigned int ccount = 1 << (log2_trafo_size * 2); ++ const int special = trans_skip_or_bypass /* || lc->tu.cross_pf */; // These need special processing ++ use_vpu = 0; ++ use_dc = (num_coeff == 1) && !special && ++ !(lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2); ++ ++ if (use_dc) { ++ // Just need a little empty space ++ coeffs = dummy_coeffs; ++ // No need to clear ++ } ++ else ++ { ++ use_vpu = !special && log2_trafo_size >= 4; ++#if RPI_COMPRESS_COEFFS ++ use_compress = use_vpu && lc->jb0->coeffs.s[log2_trafo_size - 2].packed; ++#endif ++ coeffs = rpi_alloc_coeff_buf(lc->jb0, !use_vpu ? 0 : log2_trafo_size - 2, ccount); ++#if RPI_COMPRESS_COEFFS ++ coeffs32 = (int*)coeffs; ++ if (!use_compress) ++#endif ++#if HAVE_NEON ++ rpi_zap_coeff_vals_neon(coeffs, log2_trafo_size - 2); ++#else ++ memset(coeffs, 0, ccount * sizeof(int16_t)); ++#endif ++ } ++ } ++ ++ i = num_last_subset; ++ do { ++ int implicit_non_zero_coeff = 0; ++ int n_end; ++ ++ uint8_t significant_coeff_flag_idx[16]; ++ unsigned int nb_significant_coeff_flag = 0; ++ ++ if (i == num_last_subset) { ++ // First time through ++ int last_scan_pos = num_coeff - (i << 4) - 1; ++ n_end = last_scan_pos - 1; ++ significant_coeff_flag_idx[0] = last_scan_pos; ++ nb_significant_coeff_flag = 1; ++ } else { ++ n_end = 15; ++ implicit_non_zero_coeff = (i != 0); ++ } ++ ++ if (n_end >= 0) { ++ static const uint8_t ctx_idx_maps_ts2[3][16] = { ++ D4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8), // log2_trafo_size == 2 ++ H4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8), // log2_trafo_size == 2 ++ V4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8) // log2_trafo_size == 2 ++ }; ++ // N.B. prev_sig = Right * 2 + Down ++ static const uint8_t ctx_idx_maps[3][4][16] = { ++ { ++ D4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 ++ D4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 1 ++ D4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 2 ++ D4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default ++ }, ++ { ++ H4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 ++ H4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 1 ++ H4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 2 ++ H4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default ++ }, ++ { ++ V4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 ++ V4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 1 ++ V4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 2 ++ V4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default ++ } ++ }; ++ const uint8_t *ctx_idx_map_p; ++ int scf_offset = 0; ++ ++ if (s->ps.sps->transform_skip_context_enabled_flag && trans_skip_or_bypass) { ++ ctx_idx_map_p = ctx_idx_maps[0][3]; ++ scf_offset = 40 + c_idx_nz; ++ } else { ++ if (c_idx_nz != 0) ++ scf_offset = 27; ++ ++ if (log2_trafo_size == 2) { ++ ctx_idx_map_p = ctx_idx_maps_ts2[scan_idx]; ++ } else { ++ ctx_idx_map_p = ctx_idx_maps[scan_idx][prev_sig]; ++ if (!c_idx_nz) { ++ if (i != 0) ++ scf_offset += 3; ++ ++ if (log2_trafo_size == 3) { ++ scf_offset += (scan_idx == SCAN_DIAG) ? 9 : 15; ++ } else { ++ scf_offset += 21; ++ } ++ } else { ++ if (log2_trafo_size == 3) ++ scf_offset += 9; ++ else ++ scf_offset += 12; ++ } ++ } ++ } ++ ++ if (n_end > 0) { ++ int cnt = get_sig_coeff_flag_idxs(&lc->cc, ++ lc->cabac_state + elem_offset[SIGNIFICANT_COEFF_FLAG] + scf_offset, ++ n_end, ctx_idx_map_p, ++ significant_coeff_flag_idx + nb_significant_coeff_flag); ++ ++ nb_significant_coeff_flag += cnt; ++ if (cnt != 0) { ++ implicit_non_zero_coeff = 0; ++ } ++ } ++ ++ if (implicit_non_zero_coeff == 0) { ++ if (s->ps.sps->transform_skip_context_enabled_flag && trans_skip_or_bypass) { ++ scf_offset = 42 + c_idx_nz; ++ } else { ++ if (i == 0) { ++ scf_offset = c_idx_nz ? 27 : 0; ++ } else { ++ scf_offset = 2 + scf_offset; ++ } ++ } ++ if (significant_coeff_flag_decode_0(lc, scf_offset) == 1) { ++ significant_coeff_flag_idx[nb_significant_coeff_flag] = 0; ++ nb_significant_coeff_flag++; ++ } ++ } else { ++ significant_coeff_flag_idx[nb_significant_coeff_flag] = 0; ++ nb_significant_coeff_flag++; ++ } ++ } ++#if RPI_COMPRESS_COEFFS ++ if (use_compress && (nb_significant_coeff_flag + num_nonzero + 1 >= (1<<(2*log2_trafo_size-1)))) { // Overflow when half-full! ++ int16_t temp[32*32]; ++ const unsigned int ccount = 1 << (log2_trafo_size * 2); ++ lc->jb0->coeffs.s[log2_trafo_size - 2].packed = 0; ++ lc->jb0->coeffs.s[log2_trafo_size - 2].packed_n = lc->jb0->coeffs.s[log2_trafo_size - 2].n - ccount; // Don't want to unpack the last buffer ++ memcpy(temp, coeffs, sizeof(int)*num_nonzero); ++ coeffs32 = (int *)temp; ++ memset(coeffs, 0, ccount * sizeof(int16_t)); ++ num_nonzero--; ++ while (num_nonzero >= 0) { ++ const unsigned int res = coeffs32[num_nonzero]; ++ const unsigned int offset = res & 0xffff; ++ coeffs[ offset ] = res >> 16; ++ num_nonzero--; ++ } ++ use_compress = 0; ++ } ++#endif ++ ++ if (nb_significant_coeff_flag != 0) { ++ const unsigned int gt1_idx_delta = (c_idx_nz << 2) | ++ ((i != 0 && !c_idx_nz) ? 2 : 0) | ++ prev_subset_coded; ++ const unsigned int idx0_gt1 = elem_offset[COEFF_ABS_LEVEL_GREATER1_FLAG] + ++ (gt1_idx_delta << 2); ++ const unsigned int idx_gt2 = elem_offset[COEFF_ABS_LEVEL_GREATER2_FLAG] + ++ gt1_idx_delta; ++ ++ const unsigned int x_cg = scan_x_cg[i]; ++ const unsigned int y_cg = scan_y_cg[i]; ++ int16_t * const blk_coeffs = coeffs + ++ ((x_cg + (y_cg << log2_trafo_size)) << 2); ++ // This calculation is 'wrong' for log2_traffo_size == 2 ++ // but that doesn't matter as in this case x_cg & y_cg ++ // are always 0 so result is correct (0) anyway ++ const uint8_t * const blk_scale = scale_matrix + ++ (((x_cg + (y_cg << 3)) << (5 - log2_trafo_size))); ++ ++ // * The following code block doesn't deal with these flags: ++ // (nor did the one it replaces) ++ // ++ // cabac_bypass_alignment_enabled_flag ++ // This should be easy but I can't find a test case ++ // extended_precision_processing_flag ++ // This can extend the required precision past 16bits ++ // so is probably tricky - also no example found yet ++ ++#if USE_N_END_1 ++ if (nb_significant_coeff_flag == 1) { ++ // There is a small gain to be had from special casing the single ++ // transform coefficient case. The reduction in complexity ++ // makes up for the code duplicatioon. ++ ++ int trans_coeff_level = 1; ++ int coeff_sign_flag; ++ int coded_val = 0; ++ ++ // initialize first elem of coeff_bas_level_greater1_flag ++ prev_subset_coded = 0; ++ ++ if (get_cabac(&lc->cc, lc->cabac_state + idx0_gt1 + 1)) { ++ trans_coeff_level = 2; ++ prev_subset_coded = 1; ++ coded_val = get_cabac(&lc->cc, lc->cabac_state + idx_gt2); ++ } ++ ++ // Probably not worth the overhead of starting by22 for just one value ++ coeff_sign_flag = get_cabac_bypass(&lc->cc); ++ ++ if (coded_val) ++ { ++ if (!s->ps.sps->persistent_rice_adaptation_enabled_flag) { ++ trans_coeff_level = 3 + coeff_abs_level_remaining_decode(&lc->cc, 0); ++ } else { ++ uint8_t * const stat_coeff = ++ lc->stat_coeff + trans_skip_or_bypass + 2 - ((c_idx_nz) << 1); ++ const unsigned int c_rice_param = *stat_coeff >> 2; ++ const int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(&lc->cc, c_rice_param); ++ ++ trans_coeff_level = 3 + last_coeff_abs_level_remaining; ++ update_rice(stat_coeff, last_coeff_abs_level_remaining, c_rice_param); ++ } ++ } ++ ++ { ++ const xy_off_t * const xy_off = scan_xy_off + significant_coeff_flag_idx[0]; ++ const int k = (int32_t)(coeff_sign_flag << 31) >> 31; ++ const unsigned int scale_m = blk_scale[xy_off->scale]; ++ const int res = trans_scale_sat( ++ (trans_coeff_level ^ k) - k, // Apply sign ++ scale, ++ i == 0 && xy_off->coeff == 0 ? dc_scale : scale_m, ++ shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) ++ coeffs32[num_nonzero++] = (res<<16) + (&blk_coeffs[xy_off->coeff] - coeffs); ++ else ++#endif ++ blk_coeffs[xy_off->coeff] = res; ++ } ++ } ++ else ++#endif ++ { ++ int sign_hidden = may_hide_sign; ++ int levels[16]; // Should be able to get away with int16_t but that fails some tests ++ uint32_t coeff_sign_flags; ++ uint32_t coded_vals = 0; ++ // Sum(abs(level[])) ++ // In fact we only need the bottom bit and in some future ++ // version that may be all we calculate ++ unsigned int sum_abs; ++ ++ coded_vals = get_greaterx_bits(lc, nb_significant_coeff_flag, levels, ++ &prev_subset_coded, &sum_abs, idx0_gt1, idx_gt2); ++ ++ if (significant_coeff_flag_idx[0] - significant_coeff_flag_idx[nb_significant_coeff_flag - 1] <= 3) ++ sign_hidden = 0; ++ ++ // -- Start bypass block ++ ++ bypass_start(&lc->cc); ++ ++ coeff_sign_flags = coeff_sign_flag_decode_bypass(&lc->cc, nb_significant_coeff_flag - sign_hidden); ++ ++ if (coded_vals != 0) ++ { ++ const int rice_adaptation_enabled = s->ps.sps->persistent_rice_adaptation_enabled_flag; ++ uint8_t * stat_coeff = !rice_adaptation_enabled ? NULL : ++ lc->stat_coeff + trans_skip_or_bypass + 2 - ((c_idx_nz) << 1); ++ int c_rice_param = !rice_adaptation_enabled ? 0 : *stat_coeff >> 2; ++ int * level = levels - 1; ++ ++ do { ++ { ++ const unsigned int z = hevc_clz32(coded_vals) + 1; ++ level += z; ++ coded_vals <<= z; ++ } ++ ++ { ++ const int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode_bypass(&lc->cc, c_rice_param); ++ const int trans_coeff_level = *level + last_coeff_abs_level_remaining + 1; ++ ++ sum_abs += last_coeff_abs_level_remaining + 1; ++ *level = trans_coeff_level; ++ ++ if (stat_coeff != NULL) ++ update_rice(stat_coeff, last_coeff_abs_level_remaining, c_rice_param); ++ stat_coeff = NULL; ++ ++ if (trans_coeff_level > (3 << c_rice_param) && ++ (c_rice_param < 4 || rice_adaptation_enabled)) ++ ++c_rice_param; ++ } ++ } while (coded_vals != 0); ++ } ++ ++ // sign_hidden = 0 or 1 so we can combine the tests ++ if ((sign_hidden & sum_abs) != 0) { ++ levels[nb_significant_coeff_flag - 1] = -levels[nb_significant_coeff_flag - 1]; ++ } ++ ++ bypass_finish(&lc->cc); ++ ++ // -- Finish bypass block ++ ++ // Scale loop ++ { ++ int m = nb_significant_coeff_flag - 1; ++ ++ // Deal with DC component (if any) first ++ if (i == 0 && significant_coeff_flag_idx[m] == 0) ++ { ++ const int k = (int32_t)(coeff_sign_flags << m) >> 31; ++ const int res = trans_scale_sat( ++ (levels[m] ^ k) - k, scale, dc_scale, shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) ++ { ++ coeffs32[num_nonzero++] = (res<<16) + (blk_coeffs - coeffs); ++ } ++ else ++#endif ++ { ++ blk_coeffs[0] = res; ++ } ++ --m; ++ } ++ ++#if !USE_N_END_1 ++ // If N_END_1 set then m was at least 1 initially ++ if (m >= 0) ++#endif ++ { ++ do { ++ const xy_off_t * const xy_off = scan_xy_off + ++ significant_coeff_flag_idx[m]; ++ const int k = (int32_t)(coeff_sign_flags << m) >> 31; ++ const int res = trans_scale_sat( ++ (levels[m] ^ k) - k, ++ scale, ++ blk_scale[xy_off->scale], ++ shift); ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) { ++ coeffs32[num_nonzero++] = (res<<16) + (&blk_coeffs[xy_off->coeff] - coeffs); ++ } else ++#endif ++ blk_coeffs[xy_off->coeff] = res; ++ } while (--m >= 0); ++ } ++ } ++ ++ } ++ } ++ } while ((i = next_subset(lc, i, c_idx_nz, ++ significant_coeff_group_flag, scan_x_cg, scan_y_cg, &prev_sig)) >= 0 && ++ !cabac_overflow(&lc->cc)); ++ ++ if (lc->cu.cu_transquant_bypass_flag) { ++ if (explicit_rdpcm_flag || (s->ps.sps->implicit_rdpcm_enabled_flag && ++ (pred_mode_intra == 10 || pred_mode_intra == 26))) { ++ int mode = s->ps.sps->implicit_rdpcm_enabled_flag ? (pred_mode_intra == 26) : explicit_rdpcm_dir_flag; ++ ++ s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); ++ } ++ } else { ++ if (trans_skip_or_bypass) { // Must be trans_skip as we've already dealt with bypass ++ int rot = s->ps.sps->transform_skip_rotation_enabled_flag && ++ log2_trafo_size == 2 && ++ lc->cu.pred_mode == MODE_INTRA; ++ if (rot) { ++ for (i = 0; i < 8; i++) ++ FFSWAP(int16_t, coeffs[i], coeffs[16 - i - 1]); ++ } ++ ++ s->hevcdsp.dequant(coeffs, log2_trafo_size); ++ ++ if (explicit_rdpcm_flag || (s->ps.sps->implicit_rdpcm_enabled_flag && ++ lc->cu.pred_mode == MODE_INTRA && ++ (pred_mode_intra == 10 || pred_mode_intra == 26))) { ++ int mode = explicit_rdpcm_flag ? explicit_rdpcm_dir_flag : (pred_mode_intra == 26); ++ ++ s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); ++ } ++ } else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) { ++ s->hevcdsp.transform_4x4_luma(coeffs); ++ } ++ else if (!use_vpu) ++ { ++ int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y); ++ if (max_xy == 0) ++ { ++ if (use_dc) ++ rpi_add_dc(s, lc->jb0, log2_trafo_size, c_idx, x0, y0, coeffs); ++ else ++ s->hevcdsp.idct_dc[log2_trafo_size - 2](coeffs); ++ } ++ else { ++ int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4; ++ if (max_xy < 4) ++ col_limit = FFMIN(4, col_limit); ++ else if (max_xy < 8) ++ col_limit = FFMIN(8, col_limit); ++ else if (max_xy < 12) ++ col_limit = FFMIN(24, col_limit); ++ s->hevcdsp.idct[log2_trafo_size - 2](coeffs, col_limit); ++ } ++ } ++ } ++ ++#if 0 ++ // Mildly rotted - we support no mode where cross is valid ++ if (lc->tu.cross_pf) { ++ int16_t * const coeffs_y = (int16_t*)lc->edge_emu_buffer; ++ const int ccount = 1 << (log2_trafo_size * 2); ++ ++ for (i = 0; i < ccount; i++) { ++ coeffs[i] = coeffs[i] + ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++ } ++#endif ++ ++ if (!use_dc) { ++#if RPI_COMPRESS_COEFFS ++ if (use_compress) { ++ coeffs32[num_nonzero] = 0; ++ } ++#endif ++ rpi_add_residual(s, lc->jb0, log2_trafo_size, c_idx, x0, y0, coeffs); ++ } ++} ++ ++#if !USE_BY22 ++// Stores results to lc ++MvXY ff_hevc_rpi_hls_mvd_coding(HEVCRpiLocalContext * const lc) ++{ ++ int x = abs_mvd_greater0_flag_decode(lc); ++ int y = abs_mvd_greater0_flag_decode(lc); ++ ++ if (x) ++ x += abs_mvd_greater1_flag_decode(lc); ++ if (y) ++ y += abs_mvd_greater1_flag_decode(lc); ++ ++ switch (x) { ++ case 2: x = mvd_decode(lc); break; ++ case 1: x = mvd_sign_flag_decode(lc); break; ++ case 0: x = 0; break; ++ } ++ ++ switch (y) { ++ case 2: y = mvd_decode(lc); break; ++ case 1: y = mvd_sign_flag_decode(lc); break; ++ case 0: y = 0; break; ++ } ++ return MV_XY(x,y); ++} ++#else ++MvXY ff_hevc_rpi_hls_mvd_coding(HEVCRpiLocalContext * const lc) ++{ ++ int x = abs_mvd_greater0_flag_decode(lc); ++ int y = abs_mvd_greater0_flag_decode(lc); ++ ++ if ((x | y) == 0) ++ return 0; ++ ++ if (x != 0) ++ x += abs_mvd_greater1_flag_decode(lc); ++ if (y != 0) ++ y += abs_mvd_greater1_flag_decode(lc); ++ ++ if ((x | y) == 1) ++ { ++ // Not worth starting BY22 ++ if (x != 0) ++ x = mvd_sign_flag_decode(lc); ++ if (y != 0) ++ y = mvd_sign_flag_decode(lc); ++ } ++ else ++ { ++ CABACContext * const cc = &lc->cc; ++ uint32_t val; ++ uint32_t b; ++ unsigned int n = 0; ++ ++ bypass_start(cc); ++ b = val = get_cabac_by22_peek(cc); ++ ++ if (x == 1) { ++ x = ((int32_t)b >> 31) | 1; ++ n = 1; ++ b <<= 1; ++ } ++ else if (x == 2) { ++ // EG1 so we have (leading one bits + 1) of suffix ++ // This makes prefix & suffix lengths the same ++ const unsigned int k = hevc_clz32(~b) + 1; ++ int s; ++ ++ av_assert2(k <= 15); ++ ++ b <<= k; ++ n = 2 * k + 1; // Includes suffix & sign ++ ++ // We need to have k*2 + 2 (prefix, suffix, sign, y-sign) bits peeked ++ // if we are going to do this without a flush ++ if (k > CABAC_BY22_PEEK_BITS / 2 - 1) ++ { ++ // Need too many bits - flush ++ // n = k ++ get_cabac_by22_flush(cc, k, val); ++ b = val = get_cabac_by22_peek(cc); ++ n = k + 1; ++ } ++ ++ x = (b >> (32 - k)) + (1 << k); ++ b <<= k; ++ s = (int32_t)b >> 31; ++ x = (x ^ s) - s; ++ b <<= 1; ++ ++ // Max abs value of an mv is 2^15 - 1 (i.e. a prefix len of 15 bits) ++ if (y > 1 && n > CABAC_BY22_PEEK_BITS - 15) ++ { ++ get_cabac_by22_flush(cc, n, val); ++ b = val = get_cabac_by22_peek(cc); ++ n = 0; ++ } ++ } ++ ++ if (y == 1) { ++ y = ((int32_t)b >> 31) | 1; ++ ++n; ++ // don't care about b anymore ++ } ++ else if (y == 2) { ++ const unsigned int k = hevc_clz32(~b) + 1; ++ int s; ++ ++ av_assert2(k <= 15); ++ ++ // We need to have k*2 + 1 (prefix, suffix, sign) bits peeked ++ // if we are going to do this without a flush ++ b <<= k; ++ n += 2 * k + 1; ++ ++ if (n > CABAC_BY22_PEEK_BITS) ++ { ++ // Need too many bits - flush ++ get_cabac_by22_flush(cc, n - (k + 1), val); ++ b = val = get_cabac_by22_peek(cc); ++ n = k + 1; ++ } ++ ++ y = (b >> (32 - k)) + (1 << k); ++ s = (int32_t)(b << k) >> 31; ++ y = (y ^ s) - s; ++ // don't care about b anymore ++ } ++ ++ get_cabac_by22_flush(cc, n, val); ++ bypass_finish(cc); ++ } ++ ++ return MV_XY(x, y); ++} ++#endif +diff --git a/libavcodec/rpi_hevc_cabac_fns.h b/libavcodec/rpi_hevc_cabac_fns.h +new file mode 100644 +index 0000000000..ca191f00d9 +--- /dev/null ++++ b/libavcodec/rpi_hevc_cabac_fns.h +@@ -0,0 +1,217 @@ ++/* ++ * HEVC CABAC decoding ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2018 John Cox ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++#ifndef AVCODEC_RPI_HEVC_CABAC_FNS_H ++#define AVCODEC_RPI_HEVC_CABAC_FNS_H ++ ++#include "config.h" ++#include "rpi_hevcdec.h" ++ ++void ff_hevc_rpi_save_states(HEVCRpiContext *s, const HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_cabac_init_decoder(HEVCRpiLocalContext * const lc); ++void ff_hevc_rpi_cabac_init(const HEVCRpiContext * const s, HEVCRpiLocalContext *const lc, const unsigned int ctb_flags); ++int ff_hevc_rpi_sao_type_idx_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_sao_band_position_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_sao_offset_abs_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_sao_offset_sign_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_sao_eo_class_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_part_mode_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const int log2_cb_size); ++int ff_hevc_rpi_mpm_idx_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_rem_intra_luma_pred_mode_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_intra_chroma_pred_mode_decode(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_merge_idx_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_inter_pred_idc_decode(HEVCRpiLocalContext * const lc, int nPbW, int nPbH); ++int ff_hevc_rpi_ref_idx_lx_decode(HEVCRpiLocalContext * const lc, const int num_ref_idx_lx); ++int ff_hevc_rpi_log2_res_scale_abs(HEVCRpiLocalContext * const lc, const int idx); ++ ++//int ff_hevc_rpi_cu_qp_delta_sign_flag(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_cu_qp_delta(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_cu_chroma_qp_offset_idx(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc); ++void ff_hevc_rpi_hls_residual_coding(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const int x0, const int y0, ++ const int log2_trafo_size, const enum ScanType scan_idx, ++ const int c_idx); ++ ++MvXY ff_hevc_rpi_hls_mvd_coding(HEVCRpiLocalContext * const lc); ++int ff_hevc_rpi_cabac_overflow(const HEVCRpiLocalContext * const lc); ++ ++#define HEVC_BIN_SAO_MERGE_FLAG 0 ++#define HEVC_BIN_SAO_TYPE_IDX 1 ++#define HEVC_BIN_SAO_EO_CLASS 2 ++#define HEVC_BIN_SAO_BAND_POSITION 2 ++#define HEVC_BIN_SAO_OFFSET_ABS 2 ++#define HEVC_BIN_SAO_OFFSET_SIGN 2 ++#define HEVC_BIN_END_OF_SLICE_FLAG 2 ++#define HEVC_BIN_SPLIT_CODING_UNIT_FLAG 2 ++#define HEVC_BIN_CU_TRANSQUANT_BYPASS_FLAG 5 ++#define HEVC_BIN_SKIP_FLAG 6 ++#define HEVC_BIN_CU_QP_DELTA 9 ++#define HEVC_BIN_PRED_MODE 12 ++#define HEVC_BIN_PART_MODE 13 ++#define HEVC_BIN_PCM_FLAG 17 ++#define HEVC_BIN_PREV_INTRA_LUMA_PRED_MODE 17 ++#define HEVC_BIN_MPM_IDX 18 ++#define HEVC_BIN_REM_INTRA_LUMA_PRED_MODE 18 ++#define HEVC_BIN_INTRA_CHROMA_PRED_MODE 18 ++#define HEVC_BIN_MERGE_FLAG 20 ++#define HEVC_BIN_MERGE_IDX 21 ++#define HEVC_BIN_INTER_PRED_IDC 22 ++#define HEVC_BIN_REF_IDX_L0 27 ++#define HEVC_BIN_REF_IDX_L1 29 ++#define HEVC_BIN_ABS_MVD_GREATER0_FLAG 31 ++#define HEVC_BIN_ABS_MVD_GREATER1_FLAG 33 ++#define HEVC_BIN_ABS_MVD_MINUS2 35 ++#define HEVC_BIN_MVD_SIGN_FLAG 35 ++#define HEVC_BIN_MVP_LX_FLAG 35 ++#define HEVC_BIN_NO_RESIDUAL_DATA_FLAG 36 ++#define HEVC_BIN_SPLIT_TRANSFORM_FLAG 37 ++#define HEVC_BIN_CBF_LUMA 40 ++#define HEVC_BIN_CBF_CB_CR 42 ++#define HEVC_BIN_TRANSFORM_SKIP_FLAG 46 ++#define HEVC_BIN_EXPLICIT_RDPCM_FLAG 48 ++#define HEVC_BIN_EXPLICIT_RDPCM_DIR_FLAG 50 ++#define HEVC_BIN_LAST_SIGNIFICANT_COEFF_X_PREFIX 52 ++#define HEVC_BIN_LAST_SIGNIFICANT_COEFF_Y_PREFIX 70 ++#define HEVC_BIN_LAST_SIGNIFICANT_COEFF_X_SUFFIX 88 ++#define HEVC_BIN_LAST_SIGNIFICANT_COEFF_Y_SUFFIX 88 ++#define HEVC_BIN_SIGNIFICANT_COEFF_GROUP_FLAG 88 ++#define HEVC_BIN_SIGNIFICANT_COEFF_FLAG 92 ++#define HEVC_BIN_COEFF_ABS_LEVEL_GREATER1_FLAG 136 ++#define HEVC_BIN_COEFF_ABS_LEVEL_GREATER2_FLAG 160 ++#define HEVC_BIN_COEFF_ABS_LEVEL_REMAINING 166 ++#define HEVC_BIN_COEFF_SIGN_FLAG 166 ++#define HEVC_BIN_LOG2_RES_SCALE_ABS 166 ++#define HEVC_BIN_RES_SCALE_SIGN_FLAG 174 ++#define HEVC_BIN_CU_CHROMA_QP_OFFSET_FLAG 176 ++#define HEVC_BIN_CU_CHROMA_QP_OFFSET_IDX 177 ++ ++ ++int ff_hevc_rpi_get_cabac(CABACContext * const c, uint8_t * const state); ++int ff_hevc_rpi_get_cabac_terminate(CABACContext * const c); ++ ++static inline const uint8_t* ff_hevc_rpi_cabac_skip_bytes(CABACContext * const c, int n) { ++ const uint8_t *ptr = c->bytestream; ++ ++ if (c->low & 0x1) ++ ptr--; ++#if CABAC_BITS == 16 ++ if (c->low & 0x1FF) ++ ptr--; ++#endif ++ if ((int) (c->bytestream_end - ptr) < n) ++ return NULL; ++ if (ff_init_cabac_decoder(c, ptr + n, c->bytestream_end - ptr - n) < 0) ++ return NULL; ++ ++ return ptr; ++} ++ ++static inline int ff_hevc_rpi_sao_merge_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_SAO_MERGE_FLAG); ++} ++ ++static inline int ff_hevc_rpi_cu_transquant_bypass_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CU_TRANSQUANT_BYPASS_FLAG); ++} ++ ++static inline int ff_hevc_rpi_cu_chroma_qp_offset_flag(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CU_CHROMA_QP_OFFSET_FLAG); ++} ++ ++static inline int ff_hevc_rpi_split_coding_unit_flag_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int ct_depth, ++ const unsigned int x0, const unsigned int y0) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_SPLIT_CODING_UNIT_FLAG + ++ ((s->cabac_stash_left[y0 >> 3] >> 1) > ct_depth) + ++ ((s->cabac_stash_up[x0 >> 3] >> 1) > ct_depth)); ++} ++ ++static inline int ff_hevc_rpi_skip_flag_decode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const int x0, const int y0, const int x_cb, const int y_cb) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_SKIP_FLAG + ++ (s->cabac_stash_left[y0 >> 3] & 1) + ++ (s->cabac_stash_up[x0 >> 3] & 1)); ++} ++ ++static inline int ff_hevc_rpi_pred_mode_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_PRED_MODE); ++} ++ ++static inline int ff_hevc_rpi_pcm_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac_terminate(&lc->cc); ++} ++ ++static inline int ff_hevc_rpi_prev_intra_luma_pred_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_PREV_INTRA_LUMA_PRED_MODE); ++} ++ ++static inline int ff_hevc_rpi_merge_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_MERGE_FLAG); ++} ++ ++static inline int ff_hevc_rpi_mvp_lx_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_MVP_LX_FLAG); ++} ++ ++static inline int ff_hevc_rpi_no_residual_syntax_flag_decode(HEVCRpiLocalContext * const lc) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_NO_RESIDUAL_DATA_FLAG); ++} ++ ++static inline int ff_hevc_rpi_cbf_cb_cr_decode(HEVCRpiLocalContext * const lc, const int trafo_depth) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CBF_CB_CR + trafo_depth); ++} ++ ++static inline int ff_hevc_rpi_cbf_luma_decode(HEVCRpiLocalContext * const lc, const int trafo_depth) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_CBF_LUMA + !trafo_depth); ++} ++ ++static inline int ff_hevc_rpi_split_transform_flag_decode(HEVCRpiLocalContext * const lc, const int log2_trafo_size) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_SPLIT_TRANSFORM_FLAG + 5 - log2_trafo_size); ++} ++ ++static inline int ff_hevc_rpi_res_scale_sign_flag(HEVCRpiLocalContext *const lc, const int idx) ++{ ++ return ff_hevc_rpi_get_cabac(&lc->cc, lc->cabac_state + HEVC_BIN_RES_SCALE_SIGN_FLAG + idx); ++} ++ ++ ++ ++#endif ++ +diff --git a/libavcodec/rpi_hevc_data.c b/libavcodec/rpi_hevc_data.c +new file mode 100644 +index 0000000000..341bb77d9d +--- /dev/null ++++ b/libavcodec/rpi_hevc_data.c +@@ -0,0 +1,75 @@ ++/* ++ * HEVC shared tables ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++ ++#include "rpi_hevc_data.h" ++ ++const uint8_t ff_hevc_rpi_diag_scan4x4_x[16] = { ++ 0, 0, 1, 0, ++ 1, 2, 0, 1, ++ 2, 3, 1, 2, ++ 3, 2, 3, 3, ++}; ++ ++const uint8_t ff_hevc_rpi_diag_scan4x4_y[16] = { ++ 0, 1, 0, 2, ++ 1, 0, 3, 2, ++ 1, 0, 3, 2, ++ 1, 3, 2, 3, ++}; ++ ++const uint8_t ff_hevc_rpi_diag_scan8x8_x[64] = { ++ 0, 0, 1, 0, ++ 1, 2, 0, 1, ++ 2, 3, 0, 1, ++ 2, 3, 4, 0, ++ 1, 2, 3, 4, ++ 5, 0, 1, 2, ++ 3, 4, 5, 6, ++ 0, 1, 2, 3, ++ 4, 5, 6, 7, ++ 1, 2, 3, 4, ++ 5, 6, 7, 2, ++ 3, 4, 5, 6, ++ 7, 3, 4, 5, ++ 6, 7, 4, 5, ++ 6, 7, 5, 6, ++ 7, 6, 7, 7, ++}; ++ ++const uint8_t ff_hevc_rpi_diag_scan8x8_y[64] = { ++ 0, 1, 0, 2, ++ 1, 0, 3, 2, ++ 1, 0, 4, 3, ++ 2, 1, 0, 5, ++ 4, 3, 2, 1, ++ 0, 6, 5, 4, ++ 3, 2, 1, 0, ++ 7, 6, 5, 4, ++ 3, 2, 1, 0, ++ 7, 6, 5, 4, ++ 3, 2, 1, 7, ++ 6, 5, 4, 3, ++ 2, 7, 6, 5, ++ 4, 3, 7, 6, ++ 5, 4, 7, 6, ++ 5, 7, 6, 7, ++}; +diff --git a/libavcodec/rpi_hevc_data.h b/libavcodec/rpi_hevc_data.h +new file mode 100644 +index 0000000000..0aee673d8b +--- /dev/null ++++ b/libavcodec/rpi_hevc_data.h +@@ -0,0 +1,31 @@ ++/* ++ * HEVC shared data tables ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVC_DATA_H ++#define AVCODEC_RPI_HEVC_DATA_H ++ ++#include ++ ++extern const uint8_t ff_hevc_rpi_diag_scan4x4_x[16]; ++extern const uint8_t ff_hevc_rpi_diag_scan4x4_y[16]; ++extern const uint8_t ff_hevc_rpi_diag_scan8x8_x[64]; ++extern const uint8_t ff_hevc_rpi_diag_scan8x8_y[64]; ++ ++#endif /* AVCODEC_RPI_HEVC_DATA_H */ +diff --git a/libavcodec/rpi_hevc_filter.c b/libavcodec/rpi_hevc_filter.c +new file mode 100644 +index 0000000000..5125d1eb6b +--- /dev/null ++++ b/libavcodec/rpi_hevc_filter.c +@@ -0,0 +1,1210 @@ ++/* ++ * HEVC video decoder ++ * ++ * Originally by: ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2013 Seppo Tomperi ++ * Copyright (C) 2013 Wassim Hamidouche ++ * ++ * Substantially rewritten: ++ * Copyright (C) 2018 John Cox, Ben Avison for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++//#define DISABLE_SAO ++//#define DISABLE_DEBLOCK ++//#define DISABLE_STRENGTHS ++// define DISABLE_DEBLOCK_NONREF for a 6% speed boost (by skipping deblocking on unimportant frames) ++//#define DISABLE_DEBLOCK_NONREF ++ ++#include "libavutil/common.h" ++#include "libavutil/internal.h" ++ ++#include "rpi_hevcdec.h" ++ ++#include "bit_depth_template.c" ++ ++#include "rpi_qpu.h" ++#include "rpi_zc.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++#define LUMA 0 ++#define CB 1 ++#define CR 2 ++ ++// tcoffset: -12,12; qp: 0,51; (bs-1)*2: 0,2 ++// so -12,75 overall ++static const uint8_t tctablex[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -ve quant padding ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -12..-1 ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // QP 0...18 ++ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, // QP 19...37 ++ 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 24, // QP 38...53 ++ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 // 54..75 ++}; ++#define tctable (tctablex + 12 + 6*8) ++ ++static const uint8_t betatablex[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -ve quant padding ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -12..-1 ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, // QP 0...18 ++ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, // QP 19...37 ++ 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, // QP 38...51 ++ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 // 52..73 ++}; ++#define betatable (betatablex + 12 + 6*8) ++ ++static inline int chroma_tc(const HEVCRpiContext * const s, const int qp_y, ++ const int c_idx, const int tc_offset) ++{ ++ return tctable[(int)s->ps.pps->qp_dblk_x[c_idx][qp_y] + tc_offset + 2]; ++} ++ ++static inline int get_qPy_pred(const HEVCRpiContext * const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int xBase, const unsigned int yBase) ++{ ++ const unsigned int ctb_size_mask = (1 << s->ps.sps->log2_ctb_size) - 1; ++ const unsigned int MinCuQpDeltaSizeMask = ~0U << s->ps.pps->log2_min_cu_qp_delta_size; ++ const unsigned int xQgBase = xBase & MinCuQpDeltaSizeMask; ++ const unsigned int yQgBase = yBase & MinCuQpDeltaSizeMask; ++ const unsigned int min_cb_width = s->ps.sps->min_cb_width; ++ const unsigned int x_cb = xQgBase >> s->ps.sps->log2_min_cb_size; ++ const unsigned int y_cb = yQgBase >> s->ps.sps->log2_min_cb_size; ++ const int qPy_pred = lc->qPy_pred; ++ ++ return (((xQgBase & ctb_size_mask) == 0 ? qPy_pred : ++ s->qp_y_tab[(x_cb - 1) + y_cb * min_cb_width]) + ++ ((yQgBase & ctb_size_mask) == 0 ? qPy_pred : ++ s->qp_y_tab[x_cb + (y_cb - 1) * min_cb_width]) + 1) >> 1; ++} ++ ++// * Only called from bitstream decode in foreground ++// so should be safe ++void ff_hevc_rpi_set_qPy(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, int xBase, int yBase) ++{ ++ const int qp_y = get_qPy_pred(s, lc, xBase, yBase); ++ ++ if (lc->tu.cu_qp_delta != 0) { ++ // ?? I suspect that the -bd_offset here leads to us adding it elsewhere ++ int off = s->ps.sps->qp_bd_offset; ++ lc->qp_y = FFUMOD(qp_y + lc->tu.cu_qp_delta + 52 + 2 * off, ++ 52 + off) - off; ++ } else ++ lc->qp_y = qp_y; ++} ++ ++static inline unsigned int pixel_shift(const HEVCRpiContext * const s, const unsigned int c_idx) ++{ ++ return c_idx != 0 ? 1 + s->ps.sps->pixel_shift : s->ps.sps->pixel_shift; ++} ++ ++// "DSP" these? ++static void copy_pixel(uint8_t *dst, const uint8_t *src, int pixel_shift) ++{ ++ switch (pixel_shift) ++ { ++ case 2: ++ *(uint32_t *)dst = *(uint32_t *)src; ++ break; ++ case 1: ++ *(uint16_t *)dst = *(uint16_t *)src; ++ break; ++ default: ++ *dst = *src; ++ break; ++ } ++} ++ ++static void copy_CTB_to_hv(const HEVCRpiContext * const s, const uint8_t * const src, ++ ptrdiff_t stride_src, int x, int y, int width, int height, ++ int c_idx, int x_ctb, int y_ctb) ++{ ++ const unsigned int sh = pixel_shift(s, c_idx); ++ const unsigned int w = s->ps.sps->width >> ctx_hshift(s, c_idx); ++ const unsigned int h = s->ps.sps->height >> ctx_vshift(s, c_idx); ++ ++ /* copy horizontal edges */ ++ memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << sh), ++ src, width << sh); ++ memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << sh), ++ src + stride_src * (height - 1), width << sh); ++ ++ /* copy vertical edges */ ++ ff_hevc_rpi_copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << sh), src, sh, height, 1 << sh, stride_src); ++ ++ ff_hevc_rpi_copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src); ++} ++ ++// N.B. Src & dst are swapped as this is a restore! ++// x0 & y0 are in luma coords ++// Width & height are in Y/C pels as appropriate ++// * Clear scope for optimsation here but not used enough to be worth it ++static void restore_tqb_pixels(const HEVCRpiContext * const s, ++ uint8_t *src1, const uint8_t *dst1, ++ const ptrdiff_t stride_src, const ptrdiff_t stride_dst, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int width, const int height, ++ const int c_idx) ++{ ++ if (s->ps.pps->transquant_bypass_enable_flag || ++ s->ps.sps->pcm.loop_filter_disable_flag) ++ { ++ const uint8_t *pcm = s->is_pcm + (x0 >> 6) + (y0 >> 3) * s->ps.sps->pcm_width; ++ int blks_y = height >> (c_idx == 0 ? 3 : 2); ++ const unsigned int bwidth = 8 << s->ps.sps->pixel_shift; // Y & C have the same width in sand ++ const unsigned int bheight = (c_idx == 0) ? 8 : 4; ++ const unsigned int sh = ((x0 >> 3) & 7); ++ const unsigned int mask = (1 << (width >> (c_idx == 0 ? 3 : 2))) - 1; ++ ++ do { ++ unsigned int m = (*pcm >> sh) & mask; ++ uint8_t * bd = src1; ++ const uint8_t * bs = dst1; ++ while (m != 0) { ++ if ((m & 1) != 0) { ++ s->hevcdsp.cpy_blk(bd, stride_src, bs, stride_dst, bwidth, bheight); ++ } ++ m >>= 1; ++ bs += bwidth; ++ bd += bwidth; ++ } ++ src1 += stride_src * bheight; ++ dst1 += stride_dst * bheight; ++ pcm += s->ps.sps->pcm_width; ++ } while (--blks_y > 0); ++ } ++} ++ ++#define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)]) ++ ++static void sao_filter_CTB(const HEVCRpiContext * const s, const int x, const int y) ++{ ++#if SAO_FILTER_N == 5 ++ static const uint8_t sao_tab[8] = { 0 /* 8 */, 1 /* 16 */, 2 /* 24 */, 2 /* 32 */, 3, 3 /* 48 */, 4, 4 /* 64 */}; ++#elif SAO_FILTER_N == 6 ++ static const uint8_t sao_tab[8] = { 0 /* 8 */, 1 /* 16 */, 5 /* 24 */, 2 /* 32 */, 3, 3 /* 48 */, 4, 4 /* 64 */}; ++#else ++#error Confused by size of sao fn array ++#endif ++ int c_idx; ++ int edges[4]; // 0 left 1 top 2 right 3 bottom ++ int x_ctb = x >> s->ps.sps->log2_ctb_size; ++ int y_ctb = y >> s->ps.sps->log2_ctb_size; ++ int ctb_addr_rs = y_ctb * s->ps.sps->ctb_width + x_ctb; ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs]; ++ RpiSAOParams *sao = &CTB(s->sao, x_ctb, y_ctb); ++ // flags indicating unfilterable edges ++ uint8_t vert_edge[] = { 0, 0 }; ++ uint8_t horiz_edge[] = { 0, 0 }; ++ uint8_t diag_edge[] = { 0, 0, 0, 0 }; ++ uint8_t lfase = CTB(s->filter_slice_edges, x_ctb, y_ctb); ++ uint8_t no_tile_filter = s->ps.pps->tiles_enabled_flag && ++ !s->ps.pps->loop_filter_across_tiles_enabled_flag; ++ uint8_t restore = no_tile_filter || !lfase; ++ uint8_t left_tile_edge = 0; ++ uint8_t right_tile_edge = 0; ++ uint8_t up_tile_edge = 0; ++ uint8_t bottom_tile_edge = 0; ++ const int sliced = 1; ++ const int plane_count = sliced ? 2 : (ctx_cfmt(s) != 0 ? 3 : 1); ++ ++ edges[0] = x_ctb == 0; ++ edges[1] = y_ctb == 0; ++ edges[2] = x_ctb == s->ps.sps->ctb_width - 1; ++ edges[3] = y_ctb == s->ps.sps->ctb_height - 1; ++ ++#ifdef DISABLE_SAO ++ return; ++#endif ++ ++ if (restore) { ++ if (!edges[0]) { ++ left_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1]]; ++ vert_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb)) || left_tile_edge; ++ } ++ if (!edges[2]) { ++ right_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs+1]]; ++ vert_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb)) || right_tile_edge; ++ } ++ if (!edges[1]) { ++ up_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]]; ++ horiz_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) || up_tile_edge; ++ } ++ if (!edges[3]) { ++ bottom_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs + s->ps.sps->ctb_width]]; ++ horiz_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb + 1)) || bottom_tile_edge; ++ } ++ if (!edges[0] && !edges[1]) { ++ diag_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge || up_tile_edge; ++ } ++ if (!edges[1] && !edges[2]) { ++ diag_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb - 1)) || right_tile_edge || up_tile_edge; ++ } ++ if (!edges[2] && !edges[3]) { ++ diag_edge[2] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb + 1)) || right_tile_edge || bottom_tile_edge; ++ } ++ if (!edges[0] && !edges[3]) { ++ diag_edge[3] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb + 1)) || left_tile_edge || bottom_tile_edge; ++ } ++ } ++ ++ for (c_idx = 0; c_idx < plane_count; c_idx++) { ++ const unsigned int vshift = ctx_vshift(s, c_idx); ++ const unsigned int hshift = ctx_hshift(s, c_idx); ++ const int x0 = x >> hshift; ++ const int y0 = y >> vshift; ++ const ptrdiff_t stride_src = frame_stride1(s->frame, c_idx); ++ const int ctb_size_h = (1 << (s->ps.sps->log2_ctb_size)) >> hshift; ++ const int ctb_size_v = (1 << (s->ps.sps->log2_ctb_size)) >> vshift; ++ const int width = FFMIN(ctb_size_h, (s->ps.sps->width >> hshift) - x0); ++ const int height = FFMIN(ctb_size_v, (s->ps.sps->height >> vshift) - y0); ++ int tab = sao_tab[(FFALIGN(width, 8) >> 3) - 1]; ++ ptrdiff_t stride_dst; ++ uint8_t *dst; ++ ++ const unsigned int sh = s->ps.sps->pixel_shift + (sliced && c_idx != 0); ++ const int wants_lr = sao->type_idx[c_idx] == SAO_EDGE && sao->eo_class[c_idx] != 1 /* Vertical */; ++ uint8_t * const src = !sliced ? ++ &s->frame->data[c_idx][y0 * stride_src + (x0 << sh)] : ++ c_idx == 0 ? ++ av_rpi_sand_frame_pos_y(s->frame, x0, y0) : ++ av_rpi_sand_frame_pos_c(s->frame, x0, y0); ++ const uint8_t * const src_l = edges[0] || !wants_lr ? NULL : ++ !sliced ? src - (1 << sh) : ++ c_idx == 0 ? ++ av_rpi_sand_frame_pos_y(s->frame, x0 - 1, y0) : ++ av_rpi_sand_frame_pos_c(s->frame, x0 - 1, y0); ++ const uint8_t * const src_r = edges[2] || !wants_lr ? NULL : ++ !sliced ? src + (width << sh) : ++ c_idx == 0 ? ++ av_rpi_sand_frame_pos_y(s->frame, x0 + width, y0) : ++ av_rpi_sand_frame_pos_c(s->frame, x0 + width, y0); ++ ++ if (sliced && c_idx > 1) { ++ break; ++ } ++ ++// if (c_idx == 1) ++// printf("%d: %dx%d %d,%d: lr=%d\n", c_idx, width, height, x0, y0, wants_lr); ++ ++ switch (sao->type_idx[c_idx]) { ++ case SAO_BAND: ++ copy_CTB_to_hv(s, src, stride_src, x0, y0, width, height, c_idx, ++ x_ctb, y_ctb); ++ if (s->ps.pps->transquant_bypass_enable_flag || ++ s->ps.sps->pcm.loop_filter_disable_flag) ++ { ++ // Can't use the edge buffer here as it may be in use by the foreground ++ DECLARE_ALIGNED(64, uint8_t, dstbuf) ++ [2*MAX_PB_SIZE*MAX_PB_SIZE]; ++ dst = dstbuf; ++ stride_dst = 2*MAX_PB_SIZE; ++ s->hevcdsp.cpy_blk(dst, stride_dst, src, stride_src, width << sh, height); ++ if (sliced && c_idx != 0) ++ { ++ s->hevcdsp.sao_band_filter_c[tab](src, dst, stride_src, stride_dst, ++ sao->offset_val[1], sao->band_position[1], ++ sao->offset_val[2], sao->band_position[2], ++ width, height); ++ } ++ else ++ { ++ s->hevcdsp.sao_band_filter[tab](src, dst, stride_src, stride_dst, ++ sao->offset_val[c_idx], sao->band_position[c_idx], ++ width, height); ++ } ++ restore_tqb_pixels(s, src, dst, stride_src, stride_dst, ++ x, y, width, height, c_idx); ++ } else { ++ if (sliced && c_idx != 0) ++ { ++ s->hevcdsp.sao_band_filter_c[tab](src, src, stride_src, stride_src, ++ sao->offset_val[1], sao->band_position[1], ++ sao->offset_val[2], sao->band_position[2], ++ width, height); ++ } ++ else ++ { ++ s->hevcdsp.sao_band_filter[tab](src, src, stride_src, stride_src, ++ sao->offset_val[c_idx], sao->band_position[c_idx], ++ width, height); ++ } ++ } ++ sao->type_idx[c_idx] = SAO_APPLIED; ++ break; ++ case SAO_EDGE: ++ { ++ const int w = s->ps.sps->width >> hshift; ++ const int h = s->ps.sps->height >> vshift; ++ int top_edge = edges[1]; ++ int bottom_edge = edges[3]; ++ // Can't use the edge buffer here as it may be in use by the foreground ++ DECLARE_ALIGNED(64, uint8_t, dstbuf) ++ [RPI_HEVC_SAO_BUF_STRIDE * (MAX_PB_SIZE + 2) + 64]; ++ ++ stride_dst = RPI_HEVC_SAO_BUF_STRIDE; ++ dst = dstbuf + stride_dst + 32; ++ ++ if (!top_edge) { ++ uint8_t *dst1; ++ int src_idx; ++ const uint8_t * const src_spb = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w + x0) << sh); ++ ++ dst1 = dst - stride_dst; ++ ++ if (src_l != NULL) { ++ src_idx = (CTB(s->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] == ++ SAO_APPLIED); ++ copy_pixel(dst1 - (1 << sh), src_idx ? src_spb - (1 << sh) : src_l - stride_src, sh); ++ } ++ ++ src_idx = (CTB(s->sao, x_ctb, y_ctb-1).type_idx[c_idx] == ++ SAO_APPLIED); ++ memcpy(dst1, src_idx ? src_spb : src - stride_src, width << sh); ++ ++ if (src_r != NULL) { ++ src_idx = (CTB(s->sao, x_ctb+1, y_ctb-1).type_idx[c_idx] == ++ SAO_APPLIED); ++ copy_pixel(dst1 + (width << sh), src_idx ? src_spb + (width << sh) : src_r - stride_src, sh); ++ } ++ } ++ if (!bottom_edge) { ++ uint8_t * const dst1 = dst + height * stride_dst; ++ int src_idx; ++ const uint8_t * const src_spb = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w + x0) << sh); ++ const unsigned int hoff = height * stride_src; ++ ++ if (src_l != NULL) { ++ src_idx = (CTB(s->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] == ++ SAO_APPLIED); ++ copy_pixel(dst1 - (1 << sh), src_idx ? src_spb - (1 << sh) : src_l + hoff, sh); ++ } ++ ++ src_idx = (CTB(s->sao, x_ctb, y_ctb+1).type_idx[c_idx] == ++ SAO_APPLIED); ++ memcpy(dst1, src_idx ? src_spb : src + hoff, width << sh); ++ ++ if (src_r != NULL) { ++ src_idx = (CTB(s->sao, x_ctb+1, y_ctb+1).type_idx[c_idx] == ++ SAO_APPLIED); ++ copy_pixel(dst1 + (width << sh), src_idx ? src_spb + (width << sh) : src_r + hoff, sh); ++ } ++ } ++ if (src_l != NULL) { ++ if (CTB(s->sao, x_ctb-1, y_ctb).type_idx[c_idx] == SAO_APPLIED) { ++ ff_hevc_rpi_copy_vert(dst - (1 << sh), ++ s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) * h + y0) << sh), ++ sh, height, stride_dst, 1 << sh); ++ } else { ++ ff_hevc_rpi_copy_vert(dst - (1 << sh), ++ src_l, ++ sh, height, stride_dst, stride_src); ++ } ++ } ++ if (src_r != NULL) { ++ if (CTB(s->sao, x_ctb+1, y_ctb).type_idx[c_idx] == SAO_APPLIED) { ++ ff_hevc_rpi_copy_vert(dst + (width << sh), ++ s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) * h + y0) << sh), ++ sh, height, stride_dst, 1 << sh); ++ } else { ++ ff_hevc_rpi_copy_vert(dst + (width << sh), ++ src_r, ++ sh, height, stride_dst, stride_src); ++ } ++ } ++ ++ s->hevcdsp.cpy_blk(dst, stride_dst, src, stride_src, width << sh, height); ++ ++ copy_CTB_to_hv(s, src, stride_src, x0, y0, width, height, c_idx, ++ x_ctb, y_ctb); ++ if (sliced && c_idx != 0) ++ { ++ // Class always the same for both U & V (which is just as well :-)) ++ s->hevcdsp.sao_edge_filter_c[tab](src, dst, stride_src, ++ sao->offset_val[1], sao->offset_val[2], sao->eo_class[1], ++ width, height); ++ s->hevcdsp.sao_edge_restore_c[restore](src, dst, ++ stride_src, stride_dst, ++ sao, ++ edges, width, ++ height, c_idx, ++ vert_edge, ++ horiz_edge, ++ diag_edge); ++ } ++ else ++ { ++ s->hevcdsp.sao_edge_filter[tab](src, dst, stride_src, sao->offset_val[c_idx], ++ sao->eo_class[c_idx], width, height); ++ s->hevcdsp.sao_edge_restore[restore](src, dst, ++ stride_src, stride_dst, ++ sao, ++ edges, width, ++ height, c_idx, ++ vert_edge, ++ horiz_edge, ++ diag_edge); ++ } ++ restore_tqb_pixels(s, src, dst, stride_src, stride_dst, ++ x, y, width, height, c_idx); ++ sao->type_idx[c_idx] = SAO_APPLIED; ++ break; ++ } ++ } ++ } ++ ++#if RPI_ZC_SAND_8_IN_10_BUF ++ if (s->frame->format == AV_PIX_FMT_SAND64_10 && s->frame->buf[RPI_ZC_SAND_8_IN_10_BUF] != NULL && ++ (((x + (1 << (s->ps.sps->log2_ctb_size))) & 255) == 0 || edges[2])) ++ { ++ const unsigned int stride1 = frame_stride1(s->frame, 1); ++ const unsigned int stride2 = av_rpi_sand_frame_stride2(s->frame); ++ const unsigned int xoff = (x >> 8) * stride2 * stride1; ++ const unsigned int ctb_size = (1 << s->ps.sps->log2_ctb_size); ++ const uint8_t * const sy = s->frame->data[0] + xoff * 4 + y * stride1; ++ uint8_t * const dy = s->frame->buf[4]->data + xoff * 2 + y * stride1; ++ const uint8_t * const sc = s->frame->data[1] + xoff * 4 + (y >> 1) * stride1; ++ uint8_t * const dc = s->frame->buf[4]->data + (s->frame->data[1] - s->frame->data[0]) + xoff * 2 + (y >> 1) * stride1; ++ const unsigned int wy = !edges[2] ? 256 : s->ps.sps->width - (x & ~255); ++ const unsigned int hy = !edges[3] ? ctb_size : s->ps.sps->height - y; ++ ++// printf("dy=%p/%p, stride1=%d, stride2=%d, sy=%p/%p, wy=%d, hy=%d, x=%d, y=%d, cs=%d\n", dy, dc, stride1, stride2, sy, sc, wy, hy, x, y, ctb_size); ++ av_rpi_sand16_to_sand8(dy, stride1, stride2, sy, stride1, stride2, wy, hy, 3); ++ av_rpi_sand16_to_sand8(dc, stride1, stride2, sc, stride1, stride2, wy, hy >> 1, 3); ++ } ++#endif ++} ++ ++// When bits are delivered to deblock we want them ++//#define TL 1 ++//#define TR 2 ++//#define BL 4 ++//#define BR 8 ++ ++// pcm4 returns them as b0 = tl, b1 = tr, b16 = bl, b17 = br ++// so we need to rearrange before passing on ++ ++static inline uint32_t pcm4(const HEVCRpiContext * const s, const unsigned int x, const unsigned int y) ++{ ++ const uint8_t * const pcm = s->is_pcm + (x >> 6) + (y >> 3) * s->ps.sps->pcm_width; ++ return (pcm[0] | ++ (pcm[1] << 8) | ++ (pcm[s->ps.sps->pcm_width] << 16) | ++ (pcm[s->ps.sps->pcm_width + 1] << 24)) >> ((x >> 3) & 7); ++} ++ ++static inline uint32_t pcm2(const HEVCRpiContext * const s, const unsigned int x, const unsigned int y) ++{ ++ const uint8_t * const pcm = s->is_pcm + (x >> 6) + (y >> 3) * s->ps.sps->pcm_width; ++ return (pcm[0] | (pcm[1] << 8)) >> ((x >> 3) & 7); ++} ++ ++// We cast away const here as we want this to work for both get and set ++static inline uint32_t * bs_ptr32(const uint8_t * bs, const unsigned int stride2, const unsigned int x, const unsigned int y) ++{ ++ return (uint32_t *)(bs + ++#if (~3U & (HEVC_RPI_BS_STRIDE1_PEL_MASK >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT)) != 0 ++#warning Unexpected masks ++ // As it happens we end up with stride1 = sizeof(uint32_t) so this expr vanishes ++ ((x >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT) & ++ (~3 & (HEVC_RPI_BS_STRIDE1_PEL_MASK >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT))) + ++#elif HEVC_RPI_BS_STRIDE1_BYTES < 4 ++#error Stride1 < return size ++#endif ++ ((y >> HEVC_RPI_BS_Y_SHR) << HEVC_RPI_BS_STRIDE1_BYTE_SHIFT) + ++ (x >> HEVC_RPI_BS_STRIDE1_PEL_SHIFT) * stride2); ++} ++ ++static inline uint8_t * bs_ptr8(const uint8_t * bs, const unsigned int stride2, const unsigned int x, const unsigned int y) ++{ ++ return (uint8_t *)(bs + ++ ((x >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT) & ++ (HEVC_RPI_BS_STRIDE1_PEL_MASK >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT)) + ++ ((y >> HEVC_RPI_BS_Y_SHR) << HEVC_RPI_BS_STRIDE1_BYTE_SHIFT) + ++ (x >> HEVC_RPI_BS_STRIDE1_PEL_SHIFT) * stride2); ++} ++ ++ ++// Get block strength ++// Given how we call we will always get within the 32bit boundries ++static inline uint32_t bs_get32(const uint8_t * bs, unsigned int stride2, ++ unsigned int xl, unsigned int xr, const unsigned int y) ++{ ++ if (xr <= xl) { ++ return 0; ++ } ++ else ++ { ++#if HAVE_ARMV6T2_INLINE ++#if (~3U & (HEVC_RPI_BS_STRIDE1_PEL_MASK >> HEVC_RPI_BS_PELS_PER_BYTE_SHIFT)) != 0 ++#error This case not yet handled in bs_get32 ++#elif HEVC_RPI_BS_STRIDE1_BYTES < 4 ++#error Stride1 < return size ++#endif ++ uint32_t tmp; ++ __asm__ ( ++ "lsr %[tmp], %[xl], %[xl_shift] \n\t" ++ "rsb %[xr], %[xl], %[xr] \n\t" ++ "mla %[stride2], %[stride2], %[tmp], %[bs] \n\t" ++ "add %[xr], %[xr], #7 \n\t" ++ "lsr %[bs], %[y], %[y_shift1] \n\t" ++ "bic %[xr], %[xr], #7 \n\t" ++ "ubfx %[xl], %[xl], #1, #5 \n\t" ++ "lsr %[xr], %[xr], #1 \n\t" ++ "cmp %[xr], #32 \n\t" ++ "mvn %[tmp], #0 \n\t" ++ "ldr %[bs], [%[stride2], %[bs], lsl %[y_shift2]] \n\t" ++ "lsl %[tmp], %[tmp], %[xr] \n\t" ++ "lsr %[xl], %[bs], %[xl] \n\t" ++ "it ne \n\t" ++ "bicne %[bs], %[xl], %[tmp] \n\t" ++ : // Outputs ++ [bs]"+r"(bs), ++ [stride2]"+r"(stride2), ++ [xl]"+r"(xl), ++ [xr]"+r"(xr), ++ [tmp]"=&r"(tmp) ++ : // Inputs ++ [y]"r"(y), ++ [xl_shift]"M"(HEVC_RPI_BS_STRIDE1_PEL_SHIFT), ++ [y_shift1]"M"(HEVC_RPI_BS_Y_SHR), ++ [y_shift2]"M"(HEVC_RPI_BS_STRIDE1_BYTE_SHIFT) ++ : // Clobbers ++ "cc" ++ ); ++ return (uint32_t) bs; ++#else ++ const uint32_t a = *bs_ptr32(bs, stride2, xl, y); ++ const unsigned int n = ((xr - xl + 7) & ~7) >> 1; ++ ++ return n == 32 ? a : ++ (a >> ((xl >> 1) & 31)) & ~(~0U << n); ++#endif ++ } ++} ++ ++static inline uint32_t hbs_get32(const HEVCRpiContext * const s, const unsigned int xl, const unsigned int xr, const unsigned int y) ++{ ++ av_assert2(((xl ^ (xr - 1)) >> s->ps.sps->log2_ctb_size) == 0); ++ return bs_get32(s->bs_horizontal, s->bs_stride2, xl, xr, y); ++} ++ ++static inline uint32_t vbs_get32(const HEVCRpiContext * const s, const unsigned int xl, const unsigned int xr, const unsigned int y) ++{ ++ av_assert2(((xl ^ (xr - 1)) >> s->ps.sps->log2_ctb_size) == 0); ++ return bs_get32(s->bs_vertical, s->bs_stride2, xl, xr, y); ++} ++ ++ ++static void deblock_y_blk(const HEVCRpiContext * const s, const RpiBlk bounds, const int end_x, const int end_y) ++{ ++ const unsigned int log2_ctb_size = s->ps.sps->log2_ctb_size; ++ const unsigned int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ const unsigned int ctb_size = (1 << log2_ctb_size); ++ const unsigned int cb_r = bounds.x + bounds.w - (end_x ? 0 : 1); ++ const unsigned int ctb_n = (bounds.x + bounds.y * s->ps.sps->ctb_width) >> log2_ctb_size; ++ const DBParams * cb_dbp = s->deblock + ctb_n; ++ const unsigned int b_b = bounds.y + bounds.h - (end_y ? 0 : 8); ++ ++ unsigned int cb_x; ++ ++ // Do in CTB-shaped blocks ++ for (cb_x = bounds.x; cb_x < cb_r; cb_x += ctb_size, ++cb_dbp) ++ { ++ const unsigned int bv_r = FFMIN(cb_x + ctb_size, cb_r); ++ const unsigned int bv_l = FFMAX(cb_x, 8); ++ const unsigned int bh_r = cb_x + ctb_size >= cb_r ? cb_r - 8 : cb_x + ctb_size - 9; ++ const unsigned int bh_l = bv_l - 8; ++ unsigned int y; ++ ++ // Main body ++ for (y = (bounds.y == 0 ? 0 : bounds.y - 8); y < b_b; y += 8) ++ { ++ uint32_t vbs = vbs_get32(s, bv_l, bv_r, y); ++ ++ const DBParams * const dbp = y < bounds.y ? cb_dbp - s->ps.sps->ctb_width : cb_dbp; ++ const int8_t * const qta = s->qp_y_tab + ((y - 1) >> log2_min_cb_size) * s->ps.sps->min_cb_width; ++ const int8_t * const qtb = s->qp_y_tab + (y >> log2_min_cb_size) * s->ps.sps->min_cb_width; ++ ++ if (vbs != 0) ++ { ++ const uint8_t * const tcv = tctable + dbp->tc_offset; ++ const uint8_t * const betav = betatable + dbp->beta_offset; ++ unsigned int pcmfa = pcm2(s, bv_l - 1, y); ++ unsigned int x; ++ ++ for (x = bv_l; vbs != 0; x += 8, vbs >>= 4, pcmfa >>= 1) ++ { ++ if ((vbs & 0xf) != 0 && (pcmfa & 3) != 3) ++ { ++ const int qp = (qtb[(x - 1) >> log2_min_cb_size] + qtb[x >> log2_min_cb_size] + 1) >> 1; ++ s->hevcdsp.hevc_v_loop_filter_luma2(av_rpi_sand_frame_pos_y(s->frame, x, y), ++ frame_stride1(s->frame, LUMA), ++ betav[qp], ++ ((vbs & 3) == 0 ? 0 : tcv[qp + (int)(vbs & 2)]) | ++ (((vbs & 0xc) == 0 ? 0 : tcv[qp + (int)((vbs >> 2) & 2)]) << 16), ++ pcmfa & 3, ++ av_rpi_sand_frame_pos_y(s->frame, x - 4, y)); ++ } ++ } ++ } ++ ++ if (y != 0) ++ { ++ uint32_t hbs; ++ ++ // H left - mostly separated out so we only need a uint32_t hbs ++ if ((hbs = hbs_get32(s, bh_l, cb_x, y)) != 0) ++ { ++ const unsigned int x = bh_l; ++ const unsigned int pcmfa = pcm4(s, bh_l, y - 1); ++ const int qp = (qta[x >> log2_min_cb_size] + qtb[x >> log2_min_cb_size] + 1) >> 1; ++ const DBParams * const dbph = dbp - 1; ++ const uint8_t * const tc = tctable + dbph->tc_offset + qp; ++ ++ av_assert2(cb_x - bh_l == 8); ++ ++ s->hevcdsp.hevc_h_loop_filter_luma2(av_rpi_sand_frame_pos_y(s->frame, x, y), ++ frame_stride1(s->frame, LUMA), ++ betatable[qp + dbph->beta_offset], ++ ((hbs & 3) == 0 ? 0 : tc[hbs & 2]) | ++ (((hbs & 0xc) == 0 ? 0 : tc[(hbs >> 2) & 2]) << 16), ++ (pcmfa & 1) | ((pcmfa & 0x10000) >> 15)); ++ } ++ ++ // H ++ if ((hbs = hbs_get32(s, cb_x, bh_r + 1, y)) != 0) // Will give (x <= bh_r) in for loop ++ { ++ unsigned int x; ++ unsigned int pcmfa = pcm4(s, cb_x, y - 1); ++ ++ for (x = cb_x; hbs != 0; x += 8, hbs >>= 4, pcmfa >>= 1) ++ { ++ if ((hbs & 0xf) != 0 && (~pcmfa & 0x10001) != 0) ++ { ++ const int qp = (qta[x >> log2_min_cb_size] + qtb[x >> log2_min_cb_size] + 1) >> 1; ++ const uint8_t * const tc = tctable + dbp->tc_offset + qp; ++ s->hevcdsp.hevc_h_loop_filter_luma2(av_rpi_sand_frame_pos_y(s->frame, x, y), ++ frame_stride1(s->frame, LUMA), ++ betatable[qp + dbp->beta_offset], ++ ((hbs & 3) == 0 ? 0 : tc[hbs & 2]) | ++ (((hbs & 0xc) == 0 ? 0 : tc[(hbs >> 2) & 2]) << 16), ++ (pcmfa & 1) | ((pcmfa & 0x10000) >> 15)); ++ } ++ } ++ } ++ } ++ ++ } ++ } ++} ++ ++static av_always_inline int q2h(const HEVCRpiContext * const s, const unsigned int x, const unsigned int y) ++{ ++ const unsigned int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ const int8_t * const qt = s->qp_y_tab + (y >> log2_min_cb_size) * s->ps.sps->min_cb_width; ++ return (qt[(x - 1) >> log2_min_cb_size] + qt[x >> log2_min_cb_size] + 1) >> 1; ++} ++ ++static void deblock_uv_blk(const HEVCRpiContext * const s, const RpiBlk bounds, const int end_x, const int end_y) ++{ ++ const unsigned int log2_ctb_size = s->ps.sps->log2_ctb_size; ++ const unsigned int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ const unsigned int ctb_size = (1 << log2_ctb_size); ++ const unsigned int cb_r = bounds.x + bounds.w - (end_x ? 0 : 8); ++ const unsigned int ctb_n = (bounds.x + bounds.y * s->ps.sps->ctb_width) >> log2_ctb_size; ++ const DBParams * dbp = s->deblock + ctb_n; ++ const unsigned int b_b = bounds.y + bounds.h - (end_y ? 0 : 8); ++ const uint8_t * const tcq_u = s->ps.pps->qp_dblk_x[1]; ++ const uint8_t * const tcq_v = s->ps.pps->qp_dblk_x[2]; ++ ++ unsigned int cb_x; ++ ++ av_assert1((bounds.x & (ctb_size - 1)) == 0); ++ av_assert1((bounds.y & (ctb_size - 1)) == 0); ++ av_assert1(bounds.h <= ctb_size); ++ ++ // Do in CTB-shaped blocks ++ for (cb_x = bounds.x; cb_x < cb_r; cb_x += ctb_size, ++dbp) { ++ const unsigned int bv_r = FFMIN(cb_x + ctb_size, cb_r); ++ const unsigned int bv_l = FFMAX(cb_x, 16); ++ unsigned int y; ++ ++ // V above ++ if (bounds.y != 0) { ++ // Deblock V up 8 ++ // CTB above current ++ // Top-half only (tc4 & ~0xffff == 0) is special cased in asm ++ const unsigned int y = bounds.y - 8; ++ uint32_t vbs = vbs_get32(s, bv_l, bv_r, y) & 0x02020202U; ++ ++ if (vbs != 0) ++ { ++ unsigned int pcmfa = pcm2(s, bv_l - 1, y); ++ const uint8_t * const tc = tctable + 2 + (dbp - s->ps.sps->ctb_width)->tc_offset; ++ unsigned int x; ++ ++ for (x = bv_l; vbs != 0; x += 16, vbs >>= 8, pcmfa >>= 2) ++ { ++ if ((vbs & 2) != 0 && (~pcmfa & 3) != 0) ++ { ++ const int qp0 = q2h(s, x, y); ++ s->hevcdsp.hevc_v_loop_filter_uv2(av_rpi_sand_frame_pos_c(s->frame, x >> 1, y >> 1), ++ frame_stride1(s->frame, 1), ++ tc[tcq_u[qp0]] | (tc[tcq_v[qp0]] << 8), ++ av_rpi_sand_frame_pos_c(s->frame, (x >> 1) - 2, y >> 1), ++ pcmfa & 3); ++ } ++ } ++ } ++ } ++ ++ for (y = bounds.y; y < b_b; y += 16) ++ { ++ uint32_t vbs = (vbs_get32(s, bv_l, bv_r, y) & 0x02020202U) | ++ (y + 16 > b_b ? 0 : (vbs_get32(s, bv_l, bv_r, y + 8) & 0x02020202U) << 4); ++ ++ // V ++ if (vbs != 0) ++ { ++ unsigned int x; ++ unsigned int pcmfa = ++ (y + 16 > b_b ? ++ pcm2(s, bv_l - 1, y) | 0xffff0000 : ++ pcm4(s, bv_l - 1, y)); ++ const uint8_t * const tc = tctable + 2 + dbp->tc_offset; ++ ++ for (x = bv_l; vbs != 0; x += 16, vbs >>= 8, pcmfa >>= 2) ++ { ++ if ((vbs & 0xff) != 0 && (~pcmfa & 0x30003) != 0) ++ { ++ const int qp0 = q2h(s, x, y); ++ const int qp1 = q2h(s, x, y + 8); ++ s->hevcdsp.hevc_v_loop_filter_uv2(av_rpi_sand_frame_pos_c(s->frame, x >> 1, y >> 1), ++ frame_stride1(s->frame, 1), ++ ((vbs & 2) == 0 ? 0 : (tc[tcq_u[qp0]] << 0) | (tc[tcq_v[qp0]] << 8)) | ++ ((vbs & 0x20) == 0 ? 0 : (tc[tcq_u[qp1]] << 16) | (tc[tcq_v[qp1]] << 24)), ++ av_rpi_sand_frame_pos_c(s->frame, (x >> 1) - 2, y >> 1), ++ (pcmfa & 3) | ((pcmfa >> 14) & 0xc)); ++ } ++ } ++ } ++ ++ // H ++ if (y != 0) ++ { ++ uint32_t hbs; ++ const unsigned int bh_l = bv_l - 16; ++ const unsigned int bh_r = cb_x + ctb_size >= cb_r ? cb_r : cb_x + ctb_size - 16; ++ const int8_t * const qta = s->qp_y_tab + ((y - 1) >> log2_min_cb_size) * s->ps.sps->min_cb_width; ++ const int8_t * const qtb = s->qp_y_tab + (y >> log2_min_cb_size) * s->ps.sps->min_cb_width; ++ ++ // H left - mostly separated out so we only need a uint32_t hbs ++ // Stub is width 8 to the left of bounds, but width 16 internally ++ if ((hbs = hbs_get32(s, bh_l, cb_x, y) & 0x22U) != 0) ++ { ++ unsigned int pcmfa = pcm4(s, bh_l, y - 1); ++ ++ // Chop off bits we don't want... ++ if (bh_l < bounds.x) { ++ pcmfa |= 0x10001; // TL|BL pre rearrangement ++ hbs &= ~3; // Make BS 0 ++ } ++ ++ // Double check we still want this ++ if (hbs != 0 && (~pcmfa & 0x30003) != 0) ++ { ++ const unsigned int x = bh_l; ++ const int qp0 = (qta[x >> log2_min_cb_size] + qtb[x >> log2_min_cb_size] + 1) >> 1; ++ const int qp1 = (qta[(x + 8) >> log2_min_cb_size] + qtb[(x + 8) >> log2_min_cb_size] + 1) >> 1; ++ const uint8_t * const tc = tctable + 2 + (dbp - 1)->tc_offset; ++ ++ s->hevcdsp.hevc_h_loop_filter_uv(av_rpi_sand_frame_pos_c(s->frame, x >> 1, y >> 1), ++ frame_stride1(s->frame, 1), ++ ((hbs & 2) == 0 ? 0 : (tc[tcq_u[qp0]] << 0) | (tc[tcq_v[qp0]] << 8)) | ++ ((hbs & 0x20) == 0 ? 0 : (tc[tcq_u[qp1]] << 16) | (tc[tcq_v[qp1]] << 24)), ++ (pcmfa & 3) | ((pcmfa >> 14) & 0xc)); ++ } ++ } ++ ++ // H main ++ if ((hbs = (hbs_get32(s, cb_x, bh_r, y) & 0x22222222U)) != 0) ++ { ++ unsigned int x; ++ unsigned int pcmfa = pcm4(s, cb_x, y - 1); // Might like to mask out far right writes but probably not worth it ++ ++ for (x = cb_x; hbs != 0; x += 16, hbs >>= 8, pcmfa >>= 2) ++ { ++ if ((hbs & 0xff) != 0 && (~pcmfa & 0x30003) != 0) ++ { ++ const int qp0 = (qta[x >> log2_min_cb_size] + qtb[x >> log2_min_cb_size] + 1) >> 1; ++ const int qp1 = (qta[(x + 8) >> log2_min_cb_size] + qtb[(x + 8) >> log2_min_cb_size] + 1) >> 1; ++ const uint8_t * const tc = tctable + 2 + dbp->tc_offset; ++ ++ s->hevcdsp.hevc_h_loop_filter_uv(av_rpi_sand_frame_pos_c(s->frame, x >> 1, y >> 1), ++ frame_stride1(s->frame, 1), ++ ((hbs & 2) == 0 ? 0 : (tc[tcq_u[qp0]] << 0) | (tc[tcq_v[qp0]] << 8)) | ++ ((hbs & 0x20) == 0 ? 0 : (tc[tcq_u[qp1]] << 16) | (tc[tcq_v[qp1]] << 24)), ++ (pcmfa & 3) | ((pcmfa >> 14) & 0xc)); ++ } ++ } ++ } ++ } ++ } ++ } ++} ++ ++static inline unsigned int off_boundary(const unsigned int x, const unsigned int log2_n) ++{ ++ return x & ~(~0U << log2_n); ++} ++ ++static inline void hbs_set(const HEVCRpiContext * const s, const unsigned int x, const unsigned int y, const uint32_t mask, uint32_t bsf) ++{ ++ av_assert2((y & 7) == 0); ++ ++ // This doesn't have the same simultainious update issues that bsf_stash ++ // does (other threads will have a different y) so we can do it the easy way ++ if ((bsf &= mask) != 0) ++ *bs_ptr32(s->bs_horizontal, s->bs_stride2, x, y) |= bsf << ((x >> 1) & 31); ++} ++ ++ ++static void vbs_set(const HEVCRpiContext * const s, const unsigned int x, const unsigned int y, const uint32_t mask, uint32_t bsf) ++{ ++ // We arrange this in a slightly odd fashion but it lines up with ++ // how we are going to use it in the actual deblock code & it is easier ++ // to do the contortions here than there ++ // ++ // Arrange (LE) {x0y0, x0y4, x8y0, x8,y4}, {x16y0, x16y4, x24y0, x24y4},... ++ ++ av_assert2((x & 7) == 0); ++ ++ if ((bsf &= mask) != 0) ++ { ++ uint8_t *p = bs_ptr8(s->bs_vertical, s->bs_stride2, x, y); ++ const unsigned int sh = ((x & 8) | (y & 4)) >> 1; ++ ++ if (mask <= 0xf) ++ { ++ *p |= (bsf << sh); ++ } ++ else ++ { ++ do { ++ *p |= (bsf & 0xf) << sh; ++ p += HEVC_RPI_BS_STRIDE1_BYTES; ++ } while ((bsf >>= 4) != 0); ++ } ++ } ++} ++ ++static inline uint32_t bsf_mv(const HEVCRpiContext * const s, ++ const unsigned int rep, const unsigned int dup, ++ const unsigned int mvf_stride0, ++ const unsigned int mvf_stride1, ++ const RefPicList * const rpl_p, const RefPicList * const rpl_q, ++ const HEVCRpiMvField * const mvf_p, const HEVCRpiMvField * const mvf_q) ++{ ++ return s->hevcdsp.hevc_deblocking_boundary_strengths(rep, dup, ++ mvf_p, mvf_q, ++ rpl_p[0].list, rpl_p[1].list, rpl_q[0].list, rpl_q[1].list, ++ sizeof(HEVCRpiMvField) * mvf_stride0, sizeof(HEVCRpiMvField) * mvf_stride1); ++} ++ ++ ++void ff_hevc_rpi_deblocking_boundary_strengths(const HEVCRpiContext * const s, ++ const HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_trafo_size, ++ const int is_coded_block) ++{ ++ const HEVCRpiMvField * const mvf_curr = mvf_stash_ptr(s, lc, x0, y0); ++ const unsigned int log2_min_pu_size = LOG2_MIN_PU_SIZE; ++ const RefPicList * const rpl = s->refPicList; ++ // Rep count for bsf_mv when running with min_pu chuncks ++ const unsigned int log2_rep_min_pu = log2_trafo_size <= log2_min_pu_size ? 0 : log2_trafo_size - log2_min_pu_size; ++ const unsigned int boundary_flags = s->sh.no_dblk_boundary_flags & lc->boundary_flags; ++ const unsigned int trafo_size = (1U << log2_trafo_size); ++ const uint32_t bsf_mask = log2_trafo_size > 5 ? ~0U : (1U << (trafo_size >> 1)) - 1; ++ const uint32_t bsf_cbf = (bsf_mask & 0x55555555); ++ ++ // Do we cover a pred split line? ++ const int has_x_split = x0 < lc->cu.x_split && x0 + trafo_size > lc->cu.x_split; ++ const int has_y_split = y0 < lc->cu.y_split && y0 + trafo_size > lc->cu.y_split; ++ ++ uint32_t bsf_h; ++ uint32_t bsf_v; ++ ++#ifdef DISABLE_STRENGTHS ++ return; ++#endif ++ ++ // We are always on a size boundary ++ av_assert2((x0 & (trafo_size - 1)) == 0); ++ av_assert2((y0 & (trafo_size - 1)) == 0); ++ // log2_trafo_size not really a transform size; we can have to deal ++ // with size 2^6 blocks ++ av_assert2(log2_trafo_size >= 2 && log2_trafo_size <= 6); ++ ++ // Retrieve and update coded (b0), intra (b1) bs flags ++ // ++ // Store on min width (rather than uint32_t) to avoid possible issues ++ // with another thread on another core running wpp using the same ++ // memory (min CTB = 16 pels = 4 bsf els = 8 bits) ++ // ++ // In bsf BS=2 is represented by 3 as it is much easier to test & set ++ // and the actual deblock code tests for 0 and b1 set/not-set so 2 and ++ // 3 will work the same ++ { ++ // Given where we are called from is_cbf_luma & is_intra will be constant over the block ++ const uint32_t bsf0 = (lc->cu.pred_mode == MODE_INTRA) ? bsf_mask : is_coded_block ? bsf_cbf : 0; ++ uint8_t *const p = s->bsf_stash_up + (x0 >> 4); ++ uint8_t *const q = s->bsf_stash_left + (y0 >> 4); ++ ++ switch (log2_trafo_size) ++ { ++ case 2: ++ case 3: ++ { ++ const unsigned int sh_h = (x0 >> 1) & 7; ++ const unsigned int sh_v = (y0 >> 1) & 7; ++ bsf_h = *p; ++ bsf_v = *q; ++ *p = (bsf_h & ~(bsf_mask << sh_h)) | (bsf0 << sh_h); ++ *q = (bsf_v & ~(bsf_mask << sh_v)) | (bsf0 << sh_v); ++ bsf_h >>= sh_h; ++ bsf_v >>= sh_v; ++ break; ++ } ++ case 4: ++ bsf_h = *p; ++ bsf_v = *q; ++ *p = bsf0; ++ *q = bsf0; ++ break; ++ case 5: ++ bsf_h = *(uint16_t *)p; ++ bsf_v = *(uint16_t *)q; ++ *(uint16_t *)p = bsf0; ++ *(uint16_t *)q = bsf0; ++ break; ++ case 6: ++ default: ++ bsf_h = *(uint32_t *)p; ++ bsf_v = *(uint32_t *)q; ++ *(uint32_t *)p = bsf0; ++ *(uint32_t *)q = bsf0; ++ break; ++ } ++ ++ bsf_h |= bsf0; ++ bsf_v |= bsf0; ++ } ++ ++ // Do Horizontal ++ if ((y0 & 7) == 0) ++ { ++ // Boundary upper ++ if (y0 != 0 && ++ (off_boundary(y0, s->ps.sps->log2_ctb_size) || ++ (boundary_flags & (BOUNDARY_UPPER_SLICE | BOUNDARY_UPPER_TILE)) == 0)) ++ { ++ // Look at MVs (BS=1) if we don't already has a full set of bs bits ++ if ((~bsf_h & bsf_cbf) != 0 && (y0 == lc->cu.y || y0 == lc->cu.y_split)) ++ { ++ // If we aren't on the top boundary we must be in the middle ++ // and in that case we know where mvf can change ++ const unsigned int log2_rep = (y0 == lc->cu.y) ? log2_rep_min_pu : has_x_split ? 1 : 0; ++ const RefPicList *const rpl_top = !off_boundary(y0, s->ps.sps->log2_ctb_size) ? ++ s->rpl_up[x0 >> s->ps.sps->log2_ctb_size] : ++ rpl; ++ ++ bsf_h |= bsf_mv(s, 1 << log2_rep, trafo_size >> (2 + log2_rep), ++ trafo_size >> (log2_min_pu_size + log2_rep), ++ trafo_size >> (log2_min_pu_size + log2_rep), ++ rpl, rpl_top, ++ mvf_curr, mvf_ptr(s, lc, x0, y0, x0, y0 - 1)); ++ } ++ ++ // Finally put the results into bs ++ hbs_set(s, x0, y0, bsf_mask, bsf_h); ++ } ++ ++ // Max of 1 pu internal split - ignore if not on 8pel boundary ++ if (has_y_split && !off_boundary(lc->cu.y_split, 3)) ++ { ++ const HEVCRpiMvField * const mvf = mvf_stash_ptr(s, lc, x0, lc->cu.y_split); ++ // If we have the x split as well then it must be in the middle ++ const unsigned int log2_rep = has_x_split ? 1 : 0; ++ ++ hbs_set(s, x0, lc->cu.y_split, bsf_mask, ++ bsf_mv(s, 1 << log2_rep, trafo_size >> (2 + log2_rep), ++ trafo_size >> (log2_min_pu_size + log2_rep), ++ trafo_size >> (log2_min_pu_size + log2_rep), ++ rpl, rpl, ++ mvf, mvf - MVF_STASH_WIDTH_PU)); ++ } ++ } ++ ++ // And again for vertical - same logic as horizontal just in the other direction ++ if ((x0 & 7) == 0) ++ { ++ // Boundary left ++ if (x0 != 0 && ++ (off_boundary(x0, s->ps.sps->log2_ctb_size) || ++ (boundary_flags & (BOUNDARY_LEFT_SLICE | BOUNDARY_LEFT_TILE)) == 0)) ++ { ++ if ((~bsf_v & bsf_cbf) != 0 && (x0 == lc->cu.x || x0 == lc->cu.x_split)) ++ { ++ const unsigned int log2_rep = (x0 == lc->cu.x) ? log2_rep_min_pu : has_y_split ? 1 : 0; ++ const RefPicList *const rpl_left = !off_boundary(x0, s->ps.sps->log2_ctb_size) ? ++ s->rpl_left[y0 >> s->ps.sps->log2_ctb_size] : ++ rpl; ++ ++ bsf_v |= bsf_mv(s, 1 << log2_rep, trafo_size >> (2 + log2_rep), ++ (MVF_STASH_WIDTH_PU << log2_trafo_size) >> (log2_min_pu_size + log2_rep), ++ (mvf_left_stride(s, x0, x0 - 1) << log2_trafo_size) >> (log2_min_pu_size + log2_rep), ++ rpl, rpl_left, ++ mvf_curr, mvf_ptr(s, lc, x0, y0, x0 - 1, y0)); ++ } ++ ++ vbs_set(s, x0, y0, bsf_mask, bsf_v); ++ } ++ ++ if (has_x_split && !off_boundary(lc->cu.x_split, 3)) ++ { ++ const HEVCRpiMvField *const mvf = mvf_stash_ptr(s, lc, lc->cu.x_split, y0); ++ const unsigned int log2_rep = has_y_split ? 1 : 0; ++ ++ vbs_set(s, lc->cu.x_split, y0, bsf_mask, ++ bsf_mv(s, 1 << log2_rep, trafo_size >> (2 + log2_rep), ++ (MVF_STASH_WIDTH_PU << log2_trafo_size) >> (log2_min_pu_size + log2_rep), ++ (MVF_STASH_WIDTH_PU << log2_trafo_size) >> (log2_min_pu_size + log2_rep), ++ rpl, rpl, ++ mvf, mvf - 1)); ++ } ++ } ++} ++ ++#undef LUMA ++#undef CB ++#undef CR ++ ++static inline unsigned int ussub(const unsigned int a, const unsigned int b) ++{ ++ return a < b ? 0 : a - b; ++} ++ ++static inline int cache_boundry(const AVFrame * const frame, const unsigned int x) ++{ ++ return ((x >> av_rpi_sand_frame_xshl(frame)) & ~63) == 0; ++} ++ ++int ff_hevc_rpi_hls_filter_blk(const HEVCRpiContext * const s, const RpiBlk bounds, const int eot) ++{ ++ const int ctb_size = (1 << s->ps.sps->log2_ctb_size); ++ int x, y; ++ ++ const unsigned int br = bounds.x + bounds.w; ++ const unsigned int bb = bounds.y + bounds.h; ++ ++ const int x_end = (br >= s->ps.sps->width); ++ const int y_end = (bb >= s->ps.sps->height); ++ ++ // Deblock may not touch the edges of the bound as they are still needed ++ // for Intra pred ++ // ++ // Deblock is disabled with a per-slice flag ++ // Given that bounds may cover multiple slices & we dblock outside bounds ++ // anyway we can't avoid deblock using that flag - about the only thing we ++ // could do is have a "no deblock seen yet" flag but it doesn't really ++ // seem worth the effort ++ ++ deblock_y_blk(s, bounds, x_end, y_end); ++ deblock_uv_blk(s, bounds, x_end, y_end); ++ ++ // SAO needs ++ // (a) CTB alignment ++ // (b) Valid pixels all the way around the CTB in particular it needs the DR pixel ++ { ++ const unsigned int xo = bounds.x - ((bounds.x - 16) & ~(ctb_size - 1)); ++ const unsigned int yo = bounds.y - ((bounds.y - 16) & ~(ctb_size - 1)); ++ const unsigned int yt = ussub(bounds.y, yo); ++ const unsigned int yb = y_end ? bb : ussub(bb, yo); ++ const unsigned int xl = ussub(bounds.x, xo); ++ const unsigned int xr = x_end ? br : ussub(br, xo); ++ ++ if (s->ps.sps->sao_enabled) ++ { ++ for (y = yt; y < yb; y += ctb_size) { ++ for (x = xl; x < xr; x += ctb_size) { ++ sao_filter_CTB(s, x, y); ++ } ++ } ++ } ++ ++ // Cache invalidate ++ y = 0; ++ if (xr != 0 && yb != 0) ++ { ++ const unsigned int llen = ++ (av_rpi_sand_frame_stride1(s->frame) >> av_rpi_sand_frame_xshl(s->frame)); ++ const unsigned int mask = ~(llen - 1); ++ const unsigned int il = (xl == 0) ? 0 : (xl - 1) & mask; ++ const unsigned int ir = x_end || !cache_boundry(s->frame, br) ? br : (xr - 1) & mask; ++ const unsigned int it = ussub(yt, 1); ++ const unsigned int ib = y_end ? bb : yb - 1; ++ ++ if (il < ir) { ++ rpi_cache_buf_t cbuf; ++ rpi_cache_flush_env_t * const rfe = rpi_cache_flush_init(&cbuf); ++ rpi_cache_flush_add_frame_block(rfe, s->frame, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE, ++ il, it, ir - il, ib - it, ++ ctx_vshift(s, 1), 1, 1); ++ ++ // If we have to commit the right hand tile boundry due to ++ // cache boundry considerations then at EoTile we must commit ++ // that boundry to bottom of tile (bounds) ++ if (ib != bb && ir == br && eot) { ++ rpi_cache_flush_add_frame_block(rfe, s->frame, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE, ++ br - 1, ib, 1, bb - ib, ++ ctx_vshift(s, 1), 1, 1); ++ } ++ ++ rpi_cache_flush_finish(rfe); ++ ++ if (x_end) ++ y = y_end ? INT_MAX : ib; ++ ++// printf("Flush: %4d,%4d -> %4d,%4d: signal: %d\n", il, it, ir, ib, y - 1); ++ } ++ } ++ } ++ ++ return y; ++} ++ +diff --git a/libavcodec/rpi_hevc_mv.h b/libavcodec/rpi_hevc_mv.h +new file mode 100644 +index 0000000000..6b36f5e737 +--- /dev/null ++++ b/libavcodec/rpi_hevc_mv.h +@@ -0,0 +1,71 @@ ++#ifndef AVCODEC_RPI_HEVC_MV_H ++#define AVCODEC_RPI_HEVC_MV_H ++ ++#include "config.h" ++ ++typedef int32_t MvXY; ++ ++typedef struct HEVCRpiMvField { ++ MvXY xy[2]; ++ int8_t ref_idx[2]; ++ int8_t pred_flag; ++ int8_t dummy; // To 12 bytes ++} HEVCRpiMvField; ++ ++ ++#define MV_X(xy) (((xy) << 16) >> 16) ++#define MV_Y(xy) ((xy) >> 16) ++#define MV_XY(x, y) ((x & 0xffff) | ((y) << 16)) ++ ++#if ARCH_ARM ++#include "arm/rpi_hevc_mv_arm.h" ++#endif ++ ++#ifndef mvxy_add ++static inline MvXY mvxy_add(const MvXY a, const MvXY b) ++{ ++ return MV_XY(MV_X(a) + MV_X(b), MV_Y(a) + MV_Y(b)); ++} ++#endif ++ ++ ++#ifndef mv_scale_xy ++static inline MvXY mv_scale_xy(const MvXY const src, int td, int tb) ++{ ++ int tx, scale_factor; ++ ++ td = td == 0 ? 1 : av_clip_int8(td); ++ tb = av_clip_int8(tb); ++ tx = (0x4000 + (abs(td) >> 1)) / td; ++ scale_factor = av_clip_intp2((tb * tx + 32) >> 6, 12); ++ return MV_XY( ++ av_clip_int16((scale_factor * MV_X(src) + 127 + ++ (scale_factor * MV_X(src) < 0)) >> 8), ++ av_clip_int16((scale_factor * MV_Y(src) + 127 + ++ (scale_factor * MV_Y(src) < 0)) >> 8)); ++} ++#endif ++ ++// 8.3.1 states that the bitstream may not contain poc diffs that do not ++// fit in 16 bits, so given that we don't care about the high bits we only ++// store the low 16 + LT & Inter flags ++ ++#define COL_POC_INTRA 0 ++#define COL_POC_INTER (1 << 16) ++#define COL_POC_LT (1 << 17) ++#define COL_POC_DIFF(x,y) ((int16_t)((x) - (y))) ++#define COL_POC_MAKE_INTER(lt,poc) (COL_POC_INTER | ((lt) ? COL_POC_LT : 0) | ((poc) & 0xffff)) ++#define COL_POC_IS_LT(x) (((x) & COL_POC_LT) != 0) ++ ++typedef struct ColMv_s { ++ int32_t poc; ++ int32_t xy; ++} ColMv; ++ ++typedef struct ColMvField_s { ++ ColMv L[2]; ++} ColMvField; ++ ++ ++ ++#endif // AVCODEC_RPI_HEVC_MV_H +diff --git a/libavcodec/rpi_hevc_mvs.c b/libavcodec/rpi_hevc_mvs.c +new file mode 100644 +index 0000000000..27a9f69525 +--- /dev/null ++++ b/libavcodec/rpi_hevc_mvs.c +@@ -0,0 +1,487 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2013 Anand Meher Kotra ++ * Copyright (C) 2018 John Cox for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hevc.h" ++#include "rpi_hevcdec.h" ++ ++static av_always_inline int ++is_eq_mer(const unsigned int plevel, ++ const unsigned int xN, const unsigned int yN, ++ const unsigned int xP, const unsigned int yP) ++{ ++ return (((xN ^ xP) | (yN ^ yP)) >> plevel) == 0; ++} ++ ++// check if the mv's and refidx are the same between A and B ++static av_always_inline int compare_mv_ref_idx(const HEVCRpiMvField * const a, const HEVCRpiMvField * const b) ++{ ++ return a->pred_flag == b->pred_flag && ++ ((a->pred_flag & PF_L0) == 0 || (a->ref_idx[0] == b->ref_idx[0] && a->xy[0] == b->xy[0])) && ++ ((a->pred_flag & PF_L1) == 0 || (a->ref_idx[1] == b->ref_idx[1] && a->xy[1] == b->xy[1])); ++ return 0; ++} ++ ++/* ++ * 8.5.3.1.7 temporal luma motion vector prediction ++ */ ++static int temporal_luma_motion_vector(const HEVCRpiContext * const s, ++ const HEVCRpiLocalContext * const lc, const int x0, const int y0, ++ const int nPbW, const int nPbH, const int refIdxLx, ++ MvXY * const mvLXCol, const int X) ++{ ++ int x, y; ++ const ColMv * cmv = NULL; ++ ++ HEVCRpiFrame * const col_ref = s->ref->collocated_ref; ++ const RefPicList * const refPicList = s->refPicList + X; ++ const int cur_lt = refPicList->isLongTerm[refIdxLx]; ++ ++ *mvLXCol = 0; ++ // Unlikely but we might have a col_ref IDR frame! ++ if (col_ref->col_mvf == NULL) ++ return 0; ++ ++ ff_hevc_rpi_progress_wait_mv(s, lc->jb0, col_ref, y0 + nPbH); ++ ++ //bottom right collocated motion vector ++ x = x0 + nPbW; ++ y = y0 + nPbH; ++ ++ if ((y0 >> s->ps.sps->log2_ctb_size) == (y >> s->ps.sps->log2_ctb_size) && ++ y < s->ps.sps->height && ++ x < s->ps.sps->width) ++ { ++ const ColMvField * const col = col_ref->col_mvf + (x >> 4) + ++ (y >> 4) * s->col_mvf_stride; ++ ++ if (col->L[0].poc != COL_POC_INTRA && ++ (col->L[1].poc == COL_POC_INTRA || ++ (s->no_backward_pred_flag ? s->sh.collocated_list == L1 : X == 0))) ++ { ++ cmv = col->L + 0; ++ } ++ else if (col->L[1].poc != COL_POC_INTRA) ++ { ++ cmv = col->L + 1; ++ } ++ } ++ ++ // derive center collocated motion vector ++ if (cmv == NULL || COL_POC_IS_LT(cmv->poc) != cur_lt) ++ { ++ cmv = NULL; ++ x = x0 + (nPbW >> 1); ++ y = y0 + (nPbH >> 1); ++ ++ { ++ const ColMvField * const col = col_ref->col_mvf + (x >> 4) + ++ (y >> 4) * s->col_mvf_stride; ++ ++ if (col->L[0].poc != COL_POC_INTRA && ++ (col->L[1].poc == COL_POC_INTRA || ++ (s->no_backward_pred_flag ? s->sh.collocated_list == L1 : X == 0))) ++ { ++ cmv = col->L + 0; ++ } ++ else if (col->L[1].poc != COL_POC_INTRA) ++ { ++ cmv = col->L + 1; ++ } ++ } ++ } ++ ++ if (cmv == NULL || cur_lt != COL_POC_IS_LT(cmv->poc)) ++ return 0; ++ ++ { ++ const int col_poc = col_ref->poc; ++ const int ref_poc = refPicList->list[refIdxLx]; ++ ++ *mvLXCol = (cur_lt || ++ cmv->poc == col_poc || ++ COL_POC_DIFF(col_poc, cmv->poc) == s->poc - ref_poc) ? ++ cmv->xy : ++ mv_scale_xy(cmv->xy, COL_POC_DIFF(col_poc, cmv->poc), s->poc - ref_poc); ++ } ++ ++ return cmv != NULL; ++} ++ ++static inline int mvf_eq(const HEVCRpiMvField * const a, const HEVCRpiMvField * const b) ++{ ++ return b != NULL && compare_mv_ref_idx(a, b); ++} ++ ++ ++ ++/* ++ * 8.5.3.1.2 Derivation process for spatial merging candidates ++ */ ++static inline const HEVCRpiMvField * ++derive_spatial_merge_candidates( ++ const HEVCRpiContext * const s, ++ const HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int nPbW, const unsigned int nPbH, ++ const unsigned int avail, ++ const unsigned int part_idx, ++ const unsigned int merge_idx, ++ HEVCRpiMvField * const mvf_t) ++{ ++ const unsigned int parts_a1 = (1 << PART_Nx2N) | (1 << PART_nLx2N) | (1 << PART_nRx2N); ++ const unsigned int parts_b1 = (1 << PART_2NxN) | (1<< PART_2NxnU) | (1 << PART_2NxnD); ++ ++ const HEVCRpiMvField * mvf_a1 = mvf_ptr(s, lc, x0, y0, x0 - 1, y0 + nPbH - 1); ++ const HEVCRpiMvField * mvf_a0 = mvf_a1 + mvf_left_stride(s, x0, x0 - 1); ++ const HEVCRpiMvField * mvf_b1 = mvf_ptr(s, lc, x0, y0, x0 + nPbW - 1, y0 - 1); ++ const HEVCRpiMvField * mvf_b0 = mvf_b1 + 1; ++ const unsigned int plevel = s->ps.pps->log2_parallel_merge_level; ++ const unsigned int part_mode = lc->cu.part_mode; ++ ++ const HEVCRpiMvField * perm[4]; ++ unsigned int nb_merge_cand = 0; ++ ++ // singleMCLFlag => part_idx == 0 so no need to test for it ++ if ((avail & AVAIL_L) == 0 || ++ (part_idx == 1 && ++ ((parts_a1 >> part_mode) & 1) != 0 || ++ is_eq_mer(plevel, x0 - 1, y0 + nPbH - 1, x0, y0)) || ++ mvf_a1->pred_flag == PF_INTRA) ++ { ++ mvf_a1 = NULL; ++ } ++ else ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_a1; ++ perm[nb_merge_cand++] = mvf_a1; ++ } ++ ++ if ((avail & AVAIL_U) == 0 || ++ (part_idx == 1 && ++ ((parts_b1 >> part_mode) & 1) != 0 || ++ is_eq_mer(plevel, x0 + nPbW - 1, y0 - 1, x0, y0)) || ++ mvf_b1->pred_flag == PF_INTRA) ++ { ++ mvf_b1 = NULL; ++ } ++ else if (!mvf_eq(mvf_b1, mvf_a1)) ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_b1; ++ perm[nb_merge_cand++] = mvf_b1; ++ } ++ ++ // above right spatial merge candidate ++ // Never need mvf_b0 again so don't bother zeroing if navail ++ if ((avail & AVAIL_UR) != 0 && ++ !is_eq_mer(plevel, x0 + nPbW, y0 - 1, x0, y0) && ++ mvf_b0->pred_flag != PF_INTRA && ++ !mvf_eq(mvf_b0, mvf_b1)) ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_b0; ++ perm[nb_merge_cand++] = mvf_b0; ++ } ++ ++ // left bottom spatial merge candidate ++ // Never need mvf_a0 again so don't bother zeroing if navail ++ if ((avail & AVAIL_DL) != 0 && ++ !is_eq_mer(plevel, x0 - 1, y0 + nPbH, x0, y0) && ++ mvf_a0->pred_flag != PF_INTRA && ++ !mvf_eq(mvf_a0, mvf_a1)) ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_a0; ++ perm[nb_merge_cand++] = mvf_a0; ++ } ++ ++ // above left spatial merge candidate ++ if (nb_merge_cand != 4 && ++ (avail & AVAIL_UL) != 0 && ++ !is_eq_mer(plevel, x0 - 1, y0 - 1, x0, y0)) ++ { ++ const HEVCRpiMvField * mvf_b2 = mvf_ptr(s, lc, x0, y0, x0 - 1, y0 - 1); // UL ++ ++ if (mvf_b2->pred_flag != PF_INTRA && ++ !mvf_eq(mvf_b2, mvf_a1) && ++ !mvf_eq(mvf_b2, mvf_b1)) ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_b2; ++ perm[nb_merge_cand++] = mvf_b2; ++ } ++ } ++ ++ // temporal motion vector candidate ++ if (s->sh.slice_temporal_mvp_enabled_flag) ++ { ++ static const HEVCRpiMvField mvf_z = {{0}}; ++ ++ *mvf_t = mvf_z; ++ ++ if (temporal_luma_motion_vector(s, lc, x0, y0, nPbW, nPbH, ++ 0, mvf_t->xy + 0, 0)) ++ mvf_t->pred_flag = PF_L0; ++ ++ if (s->sh.slice_type == HEVC_SLICE_B && ++ temporal_luma_motion_vector(s, lc, x0, y0, nPbW, nPbH, ++ 0, mvf_t->xy + 1, 1)) ++ mvf_t->pred_flag |= PF_L1; ++ ++ if (mvf_t->pred_flag != 0) ++ { ++ if (merge_idx == nb_merge_cand) ++ return mvf_t; ++ perm[nb_merge_cand++] = mvf_t; ++ } ++ } ++ ++ // combined bi-predictive merge candidates (applies for B slices) ++ if (s->sh.slice_type == HEVC_SLICE_B && nb_merge_cand > 1) ++ { ++ unsigned int comb_idx = 0; ++ const unsigned int cand_count = nb_merge_cand * (nb_merge_cand - 1); ++ const RefPicList * const refPicList = s->refPicList; ++ ++ for (comb_idx = 0; comb_idx < cand_count; comb_idx++) ++ { ++ static const uint8_t l0_l1_cand_idx[12][2] = { ++ { 0, 1, }, ++ { 1, 0, }, ++ { 0, 2, }, ++ { 2, 0, }, ++ { 1, 2, }, ++ { 2, 1, }, ++ { 0, 3, }, ++ { 3, 0, }, ++ { 1, 3, }, ++ { 3, 1, }, ++ { 2, 3, }, ++ { 3, 2, }, ++ }; ++ ++ const unsigned int l0_cand_idx = l0_l1_cand_idx[comb_idx][0]; ++ const unsigned int l1_cand_idx = l0_l1_cand_idx[comb_idx][1]; ++ const HEVCRpiMvField * const mvf_c0 = perm[l0_cand_idx]; ++ const HEVCRpiMvField * const mvf_c1 = perm[l1_cand_idx]; ++ ++ if ((mvf_c0->pred_flag & PF_L0) != 0 && ++ (mvf_c1->pred_flag & PF_L1) != 0 && ++ (refPicList[0].list[mvf_c0->ref_idx[0]] != refPicList[1].list[mvf_c1->ref_idx[1]] || ++ mvf_c0->xy[0] != mvf_c1->xy[1])) ++ { ++ if (merge_idx == nb_merge_cand++) ++ { ++ // Need to be a bit careful as we will construct mvf_t and we ++ // may already be using that as one of our condidates ++ // so build & copy rather than build in place ++ const HEVCRpiMvField mvf_m = { ++ .xy = { ++ mvf_c0->xy[0], ++ mvf_c1->xy[1]}, ++ .ref_idx = { ++ mvf_c0->ref_idx[0], ++ mvf_c1->ref_idx[1]}, ++ .pred_flag = PF_BI ++ }; ++ *mvf_t = mvf_m; ++ return mvf_t; ++ } ++ } ++ } ++ } ++ ++ // "append" Zero motion vector candidates ++ { ++ const unsigned int nb_refs = (s->sh.slice_type == HEVC_SLICE_B) ? ++ FFMIN(s->sh.nb_refs[0], s->sh.nb_refs[1]) : s->sh.nb_refs[0]; ++ const unsigned int zero_idx = merge_idx - nb_merge_cand; ++ ++ const HEVCRpiMvField mvf_m = { ++ .xy = {0, 0}, ++ .ref_idx = { ++ zero_idx < nb_refs ? zero_idx : 0, ++ (s->sh.slice_type == HEVC_SLICE_B && zero_idx < nb_refs) ? zero_idx : 0}, ++ .pred_flag = (s->sh.slice_type == HEVC_SLICE_B) ? PF_BI : PF_L0 ++ }; ++ ++ *mvf_t = mvf_m; ++ return mvf_t; ++ } ++} ++ ++ ++// 8.5.3.1.1 Derivation process of luma Mvs for merge mode ++void ff_hevc_rpi_luma_mv_merge_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, int x0, int y0, int nPbW, ++ int nPbH, int log2_cb_size, int part_idx, ++ int merge_idx, HEVCRpiMvField * const mv) ++{ ++ const HEVCRpiMvField * mvf_m = (s->ps.pps->log2_parallel_merge_level > 2 && log2_cb_size == 3) ? ++ derive_spatial_merge_candidates(s, lc, lc->cu.x, lc->cu.y, 8, 8, ++ ff_hevc_rpi_tb_avail_flags(s, lc, lc->cu.x, lc->cu.y, 8, 8), ++ 0, merge_idx, mv) : ++ derive_spatial_merge_candidates(s, lc, x0, y0, nPbW, nPbH, ++ ff_hevc_rpi_tb_avail_flags(s, lc, x0, y0, nPbW, nPbH), ++ part_idx, merge_idx, mv); ++ ++ if (mvf_m != mv) ++ *mv = *mvf_m; ++ ++ if (mv->pred_flag == PF_BI && (nPbW + nPbH) == 12) ++ mv->pred_flag = PF_L0; ++} ++ ++ ++static av_always_inline const MvXY * ++mvf_same_poc(const RefPicList * const rpl, const unsigned int pfi0, const unsigned int pfi1, const int poc0, const HEVCRpiMvField * const mvf) ++{ ++ if (mvf != NULL) ++ { ++ if (((mvf->pred_flag >> pfi0) & 1) != 0 && rpl[pfi0].list[mvf->ref_idx[pfi0]] == poc0) ++ return mvf->xy + pfi0; ++ if (((mvf->pred_flag >> pfi1) & 1) != 0 && rpl[pfi1].list[mvf->ref_idx[pfi1]] == poc0) ++ return mvf->xy + pfi1; ++ } ++ return NULL; ++} ++ ++static av_always_inline const MvXY * ++mvf_other_poc(const RefPicList * const rpl, const unsigned int pfi0, const unsigned int pfi1, ++ const int islt0, const int poc0, const int poc_cur, ++ MvXY * const mv_t, const HEVCRpiMvField * const mvf) ++{ ++ if (mvf != NULL) ++ { ++ if (((mvf->pred_flag >> pfi0) & 1) != 0 && rpl[pfi0].isLongTerm[mvf->ref_idx[pfi0]] == islt0) ++ { ++ const int poc1 = rpl[pfi0].list[mvf->ref_idx[pfi0]]; ++ if (islt0 || poc1 == poc0) { ++ return mvf->xy + pfi0; ++ } ++ *mv_t = mv_scale_xy(mvf->xy[pfi0], poc_cur - poc1, poc_cur - poc0); ++ return mv_t; ++ } ++ if (((mvf->pred_flag >> pfi1) & 1) != 0 && rpl[pfi1].isLongTerm[mvf->ref_idx[pfi1]] == islt0) ++ { ++ const int poc1 = rpl[pfi1].list[mvf->ref_idx[pfi1]]; ++ if (islt0 || poc1 == poc0) { ++ return mvf->xy + pfi1; ++ } ++ *mv_t = mv_scale_xy(mvf->xy[pfi1], poc_cur - poc1, poc_cur - poc0); ++ return mv_t; ++ } ++ } ++ return NULL; ++} ++ ++void ff_hevc_rpi_luma_mv_mvp_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int nPbW, const unsigned int nPbH, ++ const unsigned int avail, ++ HEVCRpiMvField * const mv, ++ const unsigned int mvp_lx_flag, const unsigned int LX) ++{ ++ const unsigned int pfi0 = LX; ++ const unsigned int pfi1 = LX == 0 ? 1 : 0; ++ const RefPicList * const rpl = s->refPicList; ++ const int poc0 = rpl[LX].list[mv->ref_idx[LX]]; ++ const int poc_cur = s->poc; ++ const int islt0 = rpl[LX].isLongTerm[mv->ref_idx[LX]]; ++ ++ const HEVCRpiMvField * mvf_a1 = mvf_ptr(s, lc, x0, y0, x0 - 1, y0 + nPbH - 1); ++ const HEVCRpiMvField * mvf_a0 = mvf_a1 + mvf_left_stride(s, x0, x0 - 1); ++ const HEVCRpiMvField * mvf_b2 = mvf_ptr(s, lc, x0, y0, x0 - 1, y0 - 1); // UL ++ const HEVCRpiMvField * mvf_b1 = mvf_ptr(s, lc, x0, y0, x0 + nPbW - 1, y0 - 1); ++ const HEVCRpiMvField * mvf_b0 = mvf_b1 + 1; ++ const MvXY * mva = NULL; ++ const MvXY * mvb; ++ MvXY * const mv_rv = mv->xy + LX; ++ MvXY mvt_a, mvt_b; ++ ++ *mv_rv = 0; ++ ++ if ((avail & AVAIL_DL) == 0 || mvf_a0->pred_flag == PF_INTRA) ++ mvf_a0 = NULL; ++ else if ((mva = mvf_same_poc(rpl, pfi0, pfi1, poc0, mvf_a0)) != NULL && mvp_lx_flag == 0) ++ goto use_mva; ++ ++ if ((avail & AVAIL_L) == 0 || mvf_a1->pred_flag == PF_INTRA) ++ mvf_a1 = NULL; ++ ++ if (mva == NULL && ++ (mva = mvf_same_poc(rpl, pfi0, pfi1, poc0, mvf_a1)) == NULL && ++ (mva = mvf_other_poc(rpl, pfi0, pfi1, islt0, poc0, poc_cur, &mvt_a, mvf_a0)) == NULL) ++ mva = mvf_other_poc(rpl, pfi0, pfi1, islt0, poc0, poc_cur, &mvt_a, mvf_a1); ++ ++ if (mvp_lx_flag == 0 && mva != NULL) ++ goto use_mva; ++ ++ if ((avail & AVAIL_UR) == 0 || mvf_b0->pred_flag == PF_INTRA) ++ mvf_b0 = NULL; ++ if ((avail & AVAIL_U) == 0 || mvf_b1->pred_flag == PF_INTRA) ++ mvf_b1 = NULL; ++ if ((avail & AVAIL_UL) == 0 || mvf_b2->pred_flag == PF_INTRA) ++ mvf_b2 = NULL; ++ ++ if ((mvb = mvf_same_poc(rpl, pfi0, pfi1, poc0, mvf_b0)) == NULL && ++ (mvb = mvf_same_poc(rpl, pfi0, pfi1, poc0, mvf_b1)) == NULL) ++ mvb = mvf_same_poc(rpl, pfi0, pfi1, poc0, mvf_b2); ++ ++ if (mvf_a0 == NULL && mvf_a1 == NULL) { ++ mva = mvb; ++ if (mvp_lx_flag == 0 && mva != NULL) ++ goto use_mva; ++ ++ if ((mvb = mvf_other_poc(rpl, pfi0, pfi1, islt0, poc0, poc_cur, &mvt_b, mvf_b0)) == NULL && ++ (mvb = mvf_other_poc(rpl, pfi0, pfi1, islt0, poc0, poc_cur, &mvt_b, mvf_b1)) == NULL) ++ mvb = mvf_other_poc(rpl, pfi0, pfi1, islt0, poc0, poc_cur, &mvt_b, mvf_b2); ++ } ++ ++ if (mva == NULL) { ++ mva = mvb; ++ mvb = NULL; ++ } ++ ++ if (mvb != NULL && *mva == *mvb) // If A == B then ignore B ++ mvb = NULL; ++ ++ if (mvp_lx_flag == 0 && mva != NULL) { ++ goto use_mva; ++ } ++ else if (mvp_lx_flag != 0 && mvb != NULL) { ++ *mv_rv = *mvb; ++ } ++ else if (s->sh.slice_temporal_mvp_enabled_flag && ((mvp_lx_flag == 0 && mva == NULL) || (mvp_lx_flag != 0 && mva != NULL))) { ++ temporal_luma_motion_vector(s, lc, x0, y0, nPbW, ++ nPbH, mv->ref_idx[LX], ++ mv_rv, LX); ++ } ++ return; ++ ++use_mva: ++ *mv_rv = *mva; ++ return; ++} ++ +diff --git a/libavcodec/rpi_hevc_parse.c b/libavcodec/rpi_hevc_parse.c +new file mode 100644 +index 0000000000..e58a59ce5e +--- /dev/null ++++ b/libavcodec/rpi_hevc_parse.c +@@ -0,0 +1,143 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "bytestream.h" ++#include "h2645_parse.h" ++#include "hevc.h" ++#include "rpi_hevc_parse.h" ++ ++static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCRpiParamSets *ps, ++ HEVCSEIContext *sei, int is_nalff, int nal_length_size, ++ int err_recognition, int apply_defdispwin, void *logctx) ++{ ++ int i; ++ int ret = 0; ++ H2645Packet pkt = { 0 }; ++ ++ ret = ff_h2645_packet_split(&pkt, buf, buf_size, logctx, is_nalff, ++ nal_length_size, AV_CODEC_ID_HEVC, 1, 0); ++ if (ret < 0) { ++ goto done; ++ } ++ ++ for (i = 0; i < pkt.nb_nals; i++) { ++ H2645NAL *nal = &pkt.nals[i]; ++ ++ /* ignore everything except parameter sets and VCL NALUs */ ++ switch (nal->type) { ++ case HEVC_NAL_VPS: ++ ret = ff_hevc_rpi_decode_nal_vps(&nal->gb, logctx, ps); ++ if (ret < 0) ++ goto done; ++ break; ++ case HEVC_NAL_SPS: ++ ret = ff_hevc_rpi_decode_nal_sps(&nal->gb, logctx, ps, apply_defdispwin); ++ if (ret < 0) ++ goto done; ++ break; ++ case HEVC_NAL_PPS: ++ ret = ff_hevc_rpi_decode_nal_pps(&nal->gb, logctx, ps); ++ if (ret < 0) ++ goto done; ++ break; ++ case HEVC_NAL_SEI_PREFIX: ++ case HEVC_NAL_SEI_SUFFIX: ++ ret = ff_hevc_rpi_decode_nal_sei(&nal->gb, logctx, sei, ps, nal->type); ++ if (ret < 0) ++ goto done; ++ break; ++ default: ++ av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n", nal->type); ++ break; ++ } ++ } ++ ++done: ++ ff_h2645_packet_uninit(&pkt); ++ if (err_recognition & AV_EF_EXPLODE) ++ return ret; ++ ++ return 0; ++} ++ ++int ff_hevc_rpi_decode_extradata(const uint8_t *data, int size, HEVCRpiParamSets *ps, ++ HEVCSEIContext *sei, int *is_nalff, int *nal_length_size, ++ int err_recognition, int apply_defdispwin, void *logctx) ++{ ++ int ret = 0; ++ GetByteContext gb; ++ ++ bytestream2_init(&gb, data, size); ++ ++ if (size > 3 && (data[0] || data[1] || data[2] > 1)) { ++ /* It seems the extradata is encoded as hvcC format. ++ * Temporarily, we support configurationVersion==0 until 14496-15 3rd ++ * is finalized. When finalized, configurationVersion will be 1 and we ++ * can recognize hvcC by checking if avctx->extradata[0]==1 or not. */ ++ int i, j, num_arrays, nal_len_size; ++ ++ *is_nalff = 1; ++ ++ bytestream2_skip(&gb, 21); ++ nal_len_size = (bytestream2_get_byte(&gb) & 3) + 1; ++ num_arrays = bytestream2_get_byte(&gb); ++ ++ /* nal units in the hvcC always have length coded with 2 bytes, ++ * so put a fake nal_length_size = 2 while parsing them */ ++ *nal_length_size = 2; ++ ++ /* Decode nal units from hvcC. */ ++ for (i = 0; i < num_arrays; i++) { ++ int type = bytestream2_get_byte(&gb) & 0x3f; ++ int cnt = bytestream2_get_be16(&gb); ++ ++ for (j = 0; j < cnt; j++) { ++ // +2 for the nal size field ++ int nalsize = bytestream2_peek_be16(&gb) + 2; ++ if (bytestream2_get_bytes_left(&gb) < nalsize) { ++ av_log(logctx, AV_LOG_ERROR, ++ "Invalid NAL unit size in extradata.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ ret = hevc_decode_nal_units(gb.buffer, nalsize, ps, sei, *is_nalff, ++ *nal_length_size, err_recognition, apply_defdispwin, ++ logctx); ++ if (ret < 0) { ++ av_log(logctx, AV_LOG_ERROR, ++ "Decoding nal unit %d %d from hvcC failed\n", ++ type, i); ++ return ret; ++ } ++ bytestream2_skip(&gb, nalsize); ++ } ++ } ++ ++ /* Now store right nal length size, that will be used to parse ++ * all other nals */ ++ *nal_length_size = nal_len_size; ++ } else { ++ *is_nalff = 0; ++ ret = hevc_decode_nal_units(data, size, ps, sei, *is_nalff, *nal_length_size, ++ err_recognition, apply_defdispwin, logctx); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return ret; ++} +diff --git a/libavcodec/rpi_hevc_parse.h b/libavcodec/rpi_hevc_parse.h +new file mode 100644 +index 0000000000..4b4d032a16 +--- /dev/null ++++ b/libavcodec/rpi_hevc_parse.h +@@ -0,0 +1,36 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/** ++ * @file ++ * H.265 parser code ++ */ ++ ++#ifndef AVCODEC_RPI_HEVC_PARSE_H ++#define AVCODEC_RPI_HEVC_PARSE_H ++ ++#include ++ ++#include "rpi_hevc_ps.h" ++#include "rpi_hevc_sei.h" ++ ++int ff_hevc_rpi_decode_extradata(const uint8_t *data, int size, HEVCRpiParamSets *ps, ++ HEVCSEIContext *sei, int *is_nalff, int *nal_length_size, ++ int err_recognition, int apply_defdispwin, void *logctx); ++ ++#endif /* AVCODEC_RPI_HEVC_PARSE_H */ +diff --git a/libavcodec/rpi_hevc_ps.c b/libavcodec/rpi_hevc_ps.c +new file mode 100644 +index 0000000000..f4e31f7d1d +--- /dev/null ++++ b/libavcodec/rpi_hevc_ps.c +@@ -0,0 +1,1938 @@ ++/* ++ * HEVC Parameter Set decoding ++ * ++ * Copyright (C) 2012 - 2103 Guillaume Martres ++ * Copyright (C) 2012 - 2103 Mickael Raulet ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2013 Vittorio Giovara ++ * Copyright (C) 2018 John Cox for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/imgutils.h" ++#include "golomb.h" ++#include "rpi_hevc_data.h" ++#include "rpi_hevc_ps.h" ++#include "rpi_hevcdec.h" ++ ++static const uint8_t default_scaling_list_intra[] = { ++ 16, 16, 16, 16, 17, 18, 21, 24, ++ 16, 16, 16, 16, 17, 19, 22, 25, ++ 16, 16, 17, 18, 20, 22, 25, 29, ++ 16, 16, 18, 21, 24, 27, 31, 36, ++ 17, 17, 20, 24, 30, 35, 41, 47, ++ 18, 19, 22, 27, 35, 44, 54, 65, ++ 21, 22, 25, 31, 41, 54, 70, 88, ++ 24, 25, 29, 36, 47, 65, 88, 115 ++}; ++ ++static const uint8_t default_scaling_list_inter[] = { ++ 16, 16, 16, 16, 17, 18, 20, 24, ++ 16, 16, 16, 17, 18, 20, 24, 25, ++ 16, 16, 17, 18, 20, 24, 25, 28, ++ 16, 17, 18, 20, 24, 25, 28, 33, ++ 17, 18, 20, 24, 25, 28, 33, 41, ++ 18, 20, 24, 25, 28, 33, 41, 54, ++ 20, 24, 25, 28, 33, 41, 54, 71, ++ 24, 25, 28, 33, 41, 54, 71, 91 ++}; ++ ++static const AVRational vui_sar[] = { ++ { 0, 1 }, ++ { 1, 1 }, ++ { 12, 11 }, ++ { 10, 11 }, ++ { 16, 11 }, ++ { 40, 33 }, ++ { 24, 11 }, ++ { 20, 11 }, ++ { 32, 11 }, ++ { 80, 33 }, ++ { 18, 11 }, ++ { 15, 11 }, ++ { 64, 33 }, ++ { 160, 99 }, ++ { 4, 3 }, ++ { 3, 2 }, ++ { 2, 1 }, ++}; ++ ++ ++// pps_cb_qp_offset: -12,+12 ++// slice_cb_qp_offset: -12,+12 also ++// "The value of pps_cb_qp_offset + slice_cb_qp_offset shall be in the range of -12 to +12, inclusive." ++// cr_qp_offset_list[n]: -12,+12 ++// So worst case total offset: -24,+24 ++ ++#define T(n) ((((48+(n))/6-10)<<3) | (48+(n))%6) ++#define C(B,n) T(B*6+(n) < 0 ? -B*6 : (n) > 51 ? 51 : (n)) ++#define M(B,n) C(B,(-n)) ++ ++// Sizeof the QP_START_BLOCK ++#define QP_OFFSET_0 (8*6 + 12*2) ++#define QP_START(B) \ ++ M(B,48), M(B,48), M(B,48), M(B,48), M(B,48), M(B,48),\ ++ M(B,48), M(B,48), M(B,48), M(B,48), M(B,48), M(B,48),\ ++ M(B,48), M(B,48), M(B,48), M(B,48), M(B,48), M(B,48),\ ++ M(B,48), M(B,48), M(B,48), M(B,48), M(B,48), M(B,48),\ ++\ ++ M(B,48), M(B,47), M(B,46), M(B,45), M(B,44), M(B,43),\ ++ M(B,42), M(B,41), M(B,40), M(B,39), M(B,38), M(B,37),\ ++ M(B,36), M(B,35), M(B,34), M(B,33), M(B,32), M(B,31),\ ++ M(B,30), M(B,29), M(B,28), M(B,27), M(B,26), M(B,25),\ ++ M(B,24), M(B,23), M(B,22), M(B,21), M(B,20), M(B,19),\ ++ M(B,18), M(B,17), M(B,16), M(B,15), M(B,14), M(B,13),\ ++ M(B,12), M(B,11), M(B,10), M(B, 9), M(B, 8), M(B, 7),\ ++ M(B, 6), M(B, 5), M(B, 4), M(B, 3), M(B, 2), M(B, 1) ++#define QP_END(B) \ ++ C(B,51), C(B,51), C(B,51), C(B,51), C(B,51), C(B,51),\ ++ C(B,51), C(B,51), C(B,51), C(B,51), C(B,51), C(B,51),\ ++ C(B,51), C(B,51), C(B,51), C(B,51), C(B,51), C(B,51) ++ ++#define T1(B)\ ++{\ ++ QP_START(B),\ ++ C(B, 0), C(B, 1), C(B, 2), C(B, 3), C(B, 4), C(B, 5), C(B, 6), C(B, 7), C(B, 8), C(B, 9),\ ++ C(B,10), C(B,11), C(B,12), C(B,13), C(B,14), C(B,15), C(B,16), C(B,17), C(B,18), C(B,19),\ ++ C(B,20), C(B,21), C(B,22), C(B,23), C(B,24), C(B,25), C(B,26), C(B,27), C(B,28), C(B,29),\ ++ C(B,29), C(B,30), C(B,31), C(B,32), C(B,33), C(B,33), C(B,34), C(B,34), C(B,35), C(B,35),\ ++ C(B,36), C(B,36), C(B,37), C(B,37), C(B,38), C(B,39), C(B,40), C(B,41), C(B,42), C(B,43),\ ++ C(B,44), C(B,45),\ ++ C(B,46), C(B,47), C(B,48), C(B,49), C(B,50), C(B,51),\ ++ QP_END(B)\ ++} ++#define T0(B)\ ++{\ ++ QP_START(B),\ ++ C(B, 0), C(B, 1), C(B, 2), C(B, 3), C(B, 4), C(B, 5), C(B, 6), C(B, 7), C(B, 8), C(B, 9),\ ++ C(B,10), C(B,11), C(B,12), C(B,13), C(B,14), C(B,15), C(B,16), C(B,17), C(B,18), C(B,19),\ ++ C(B,20), C(B,21), C(B,22), C(B,23), C(B,24), C(B,25), C(B,26), C(B,27), C(B,28), C(B,29),\ ++ C(B,30), C(B,31), C(B,32), C(B,33), C(B,34), C(B,35), C(B,36), C(B,37), C(B,38), C(B,39),\ ++ C(B,40), C(B,41), C(B,42), C(B,43), C(B,44), C(B,45), C(B,46), C(B,47), C(B,48), C(B,49),\ ++ C(B,50), C(B,51),\ ++ C(B,51), C(B,51), C(B,51), C(B,51), C(B,51), C(B,51),\ ++ QP_END(B)\ ++} ++ ++#define QP_TABLE_SIZE (QP_OFFSET_0 + 52 + 12*2) ++ ++static const int8_t qp_c_bd_0[8][QP_TABLE_SIZE] = {T0(0),T0(1),T0(2),T0(3),T0(4),T0(5),T0(6),T0(7)}; ++static const int8_t qp_c_bd_1[8][QP_TABLE_SIZE] = {T1(0),T1(1),T1(2),T1(3),T1(4),T1(5),T1(6),T1(7)}; ++ ++#undef T ++#undef C ++#undef QP_END ++ ++#define C(B,n) ((n)<0?0:(n)>51?51:(n)) ++// We do need a lot of -ve padding to cope with high bit depths that give -ve qps ++#define QP_DBLK_OFFSET_0 QP_OFFSET_0 ++#define QP_END(B)\ ++ 51, 51, 51, 51, 51, 51 ++ ++// These don't need all the padding we have here (12 top/bottom would be enough) ++static const uint8_t qp_c_dblk_0[] = T0(0); ++static const uint8_t qp_c_dblk_1[] = T1(0); ++ ++#undef T ++#undef M ++#undef C ++#undef QP_END ++#undef QP_START ++ ++ ++static void remove_pps(HEVCRpiParamSets * const s, const int id) ++{ ++ if (s->pps_list[id] && s->pps == (const HEVCRpiPPS*)s->pps_list[id]->data) ++ s->pps = NULL; ++ av_buffer_unref(&s->pps_list[id]); ++} ++ ++static void remove_sps(HEVCRpiParamSets * const s, const int id) ++{ ++ int i; ++ if (s->sps_list[id]) { ++ if (s->sps == (const HEVCRpiSPS*)s->sps_list[id]->data) ++ s->sps = NULL; ++ ++ /* drop all PPS that depend on this SPS */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++) ++ if (s->pps_list[i] && ((HEVCRpiPPS*)s->pps_list[i]->data)->sps_id == id) ++ remove_pps(s, i); ++ ++ av_assert0(!(s->sps_list[id] && s->sps == (HEVCRpiSPS*)s->sps_list[id]->data)); ++ } ++ av_buffer_unref(&s->sps_list[id]); ++} ++ ++static void remove_vps(HEVCRpiParamSets * const s, const int id) ++{ ++ int i; ++ if (s->vps_list[id]) { ++ if (s->vps == (const HEVCRpiVPS*)s->vps_list[id]->data) ++ s->vps = NULL; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->sps_list); i++) ++ if (s->sps_list[i] && ((HEVCRpiSPS*)s->sps_list[i]->data)->vps_id == id) ++ remove_sps(s, i); ++ } ++ av_buffer_unref(&s->vps_list[id]); ++} ++ ++int ff_hevc_rpi_decode_short_term_rps(GetBitContext * const gb, AVCodecContext * const avctx, ++ ShortTermRPS * const rps, const HEVCRpiSPS * const sps, const int is_slice_header) ++{ ++ uint8_t rps_predict = 0; ++ int delta_poc; ++ int k0 = 0; ++ int k1 = 0; ++ int k = 0; ++ int i; ++ ++ if (rps != sps->st_rps && sps->nb_st_rps) ++ rps_predict = get_bits1(gb); ++ ++ if (rps_predict) { ++ const ShortTermRPS *rps_ridx; ++ int delta_rps; ++ unsigned abs_delta_rps; ++ uint8_t use_delta_flag = 0; ++ uint8_t delta_rps_sign; ++ ++ if (is_slice_header) { ++ unsigned int delta_idx = get_ue_golomb_long(gb) + 1; ++ if (delta_idx > sps->nb_st_rps) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid value of delta_idx in slice header RPS: %d > %d.\n", ++ delta_idx, sps->nb_st_rps); ++ return AVERROR_INVALIDDATA; ++ } ++ rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; ++ rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; ++ } else ++ rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; ++ ++ delta_rps_sign = get_bits1(gb); ++ abs_delta_rps = get_ue_golomb_long(gb) + 1; ++ if (abs_delta_rps < 1 || abs_delta_rps > 32768) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid value of abs_delta_rps: %d\n", ++ abs_delta_rps); ++ return AVERROR_INVALIDDATA; ++ } ++ delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps; ++ for (i = 0; i <= rps_ridx->num_delta_pocs; i++) { ++ int used = rps->used[k] = get_bits1(gb); ++ ++ if (!used) ++ use_delta_flag = get_bits1(gb); ++ ++ if (used || use_delta_flag) { ++ if (i < rps_ridx->num_delta_pocs) ++ delta_poc = delta_rps + rps_ridx->delta_poc[i]; ++ else ++ delta_poc = delta_rps; ++ rps->delta_poc[k] = delta_poc; ++ if (delta_poc < 0) ++ k0++; ++ else ++ k1++; ++ k++; ++ } ++ } ++ ++ if (k >= FF_ARRAY_ELEMS(rps->used)) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid num_delta_pocs: %d\n", k); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ rps->num_delta_pocs = k; ++ rps->num_negative_pics = k0; ++ // sort in increasing order (smallest first) ++ if (rps->num_delta_pocs != 0) { ++ int used, tmp; ++ for (i = 1; i < rps->num_delta_pocs; i++) { ++ delta_poc = rps->delta_poc[i]; ++ used = rps->used[i]; ++ for (k = i - 1; k >= 0; k--) { ++ tmp = rps->delta_poc[k]; ++ if (delta_poc < tmp) { ++ rps->delta_poc[k + 1] = tmp; ++ rps->used[k + 1] = rps->used[k]; ++ rps->delta_poc[k] = delta_poc; ++ rps->used[k] = used; ++ } ++ } ++ } ++ } ++ if ((rps->num_negative_pics >> 1) != 0) { ++ int used; ++ k = rps->num_negative_pics - 1; ++ // flip the negative values to largest first ++ for (i = 0; i < rps->num_negative_pics >> 1; i++) { ++ delta_poc = rps->delta_poc[i]; ++ used = rps->used[i]; ++ rps->delta_poc[i] = rps->delta_poc[k]; ++ rps->used[i] = rps->used[k]; ++ rps->delta_poc[k] = delta_poc; ++ rps->used[k] = used; ++ k--; ++ } ++ } ++ } else { ++ unsigned int prev, nb_positive_pics; ++ rps->num_negative_pics = get_ue_golomb_long(gb); ++ nb_positive_pics = get_ue_golomb_long(gb); ++ ++ if (rps->num_negative_pics >= HEVC_MAX_REFS || ++ nb_positive_pics >= HEVC_MAX_REFS) { ++ av_log(avctx, AV_LOG_ERROR, "Too many refs in a short term RPS.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ rps->num_delta_pocs = rps->num_negative_pics + nb_positive_pics; ++ if (rps->num_delta_pocs) { ++ prev = 0; ++ for (i = 0; i < rps->num_negative_pics; i++) { ++ delta_poc = get_ue_golomb_long(gb) + 1; ++ if (delta_poc < 1 || delta_poc > 32768) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid value of delta_poc: %d\n", ++ delta_poc); ++ return AVERROR_INVALIDDATA; ++ } ++ prev -= delta_poc; ++ rps->delta_poc[i] = prev; ++ rps->used[i] = get_bits1(gb); ++ } ++ prev = 0; ++ for (i = 0; i < nb_positive_pics; i++) { ++ delta_poc = get_ue_golomb_long(gb) + 1; ++ if (delta_poc < 1 || delta_poc > 32768) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid value of delta_poc: %d\n", ++ delta_poc); ++ return AVERROR_INVALIDDATA; ++ } ++ prev += delta_poc; ++ rps->delta_poc[rps->num_negative_pics + i] = prev; ++ rps->used[rps->num_negative_pics + i] = get_bits1(gb); ++ } ++ } ++ } ++ return 0; ++} ++ ++ ++static int decode_profile_tier_level(GetBitContext * const gb, AVCodecContext * const avctx, ++ PTLCommon * const ptl) ++{ ++ int i; ++ ++ if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 16 + 16 + 12) ++ return -1; ++ ++ ptl->profile_space = get_bits(gb, 2); ++ ptl->tier_flag = get_bits1(gb); ++ ptl->profile_idc = get_bits(gb, 5); ++ if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN) ++ av_log(avctx, AV_LOG_DEBUG, "Main profile bitstream\n"); ++ else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_10) ++ av_log(avctx, AV_LOG_DEBUG, "Main 10 profile bitstream\n"); ++ else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_STILL_PICTURE) ++ av_log(avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n"); ++ else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT) ++ av_log(avctx, AV_LOG_DEBUG, "Range Extension profile bitstream\n"); ++ else ++ av_log(avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); ++ ++ for (i = 0; i < 32; i++) { ++ ptl->profile_compatibility_flag[i] = get_bits1(gb); ++ ++ if (ptl->profile_idc == 0 && i > 0 && ptl->profile_compatibility_flag[i]) ++ ptl->profile_idc = i; ++ } ++ ptl->progressive_source_flag = get_bits1(gb); ++ ptl->interlaced_source_flag = get_bits1(gb); ++ ptl->non_packed_constraint_flag = get_bits1(gb); ++ ptl->frame_only_constraint_flag = get_bits1(gb); ++ ++ skip_bits(gb, 16); // XXX_reserved_zero_44bits[0..15] ++ skip_bits(gb, 16); // XXX_reserved_zero_44bits[16..31] ++ skip_bits(gb, 12); // XXX_reserved_zero_44bits[32..43] ++ ++ return 0; ++} ++ ++static int parse_ptl(GetBitContext * const gb, AVCodecContext * const avctx, ++ PTL * const ptl, const int max_num_sub_layers) ++{ ++ int i; ++ if (decode_profile_tier_level(gb, avctx, &ptl->general_ptl) < 0 || ++ get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 0))) { ++ av_log(avctx, AV_LOG_ERROR, "PTL information too short\n"); ++ return -1; ++ } ++ ++ ptl->general_ptl.level_idc = get_bits(gb, 8); ++ ++ for (i = 0; i < max_num_sub_layers - 1; i++) { ++ ptl->sub_layer_profile_present_flag[i] = get_bits1(gb); ++ ptl->sub_layer_level_present_flag[i] = get_bits1(gb); ++ } ++ ++ if (max_num_sub_layers - 1> 0) ++ for (i = max_num_sub_layers - 1; i < 8; i++) ++ skip_bits(gb, 2); // reserved_zero_2bits[i] ++ for (i = 0; i < max_num_sub_layers - 1; i++) { ++ if (ptl->sub_layer_profile_present_flag[i] && ++ decode_profile_tier_level(gb, avctx, &ptl->sub_layer_ptl[i]) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "PTL information for sublayer %i too short\n", i); ++ return -1; ++ } ++ if (ptl->sub_layer_level_present_flag[i]) { ++ if (get_bits_left(gb) < 8) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Not enough data for sublayer %i level_idc\n", i); ++ return -1; ++ } else ++ ptl->sub_layer_ptl[i].level_idc = get_bits(gb, 8); ++ } ++ } ++ ++ return 0; ++} ++ ++static void decode_sublayer_hrd(GetBitContext * const gb, const unsigned int nb_cpb, ++ const int subpic_params_present) ++{ ++ int i; ++ ++ for (i = 0; i < nb_cpb; i++) { ++ get_ue_golomb_long(gb); // bit_rate_value_minus1 ++ get_ue_golomb_long(gb); // cpb_size_value_minus1 ++ ++ if (subpic_params_present) { ++ get_ue_golomb_long(gb); // cpb_size_du_value_minus1 ++ get_ue_golomb_long(gb); // bit_rate_du_value_minus1 ++ } ++ skip_bits1(gb); // cbr_flag ++ } ++} ++ ++static int decode_hrd(GetBitContext * const gb, const int common_inf_present, ++ const int max_sublayers) ++{ ++ int nal_params_present = 0, vcl_params_present = 0; ++ int subpic_params_present = 0; ++ int i; ++ ++ if (common_inf_present) { ++ nal_params_present = get_bits1(gb); ++ vcl_params_present = get_bits1(gb); ++ ++ if (nal_params_present || vcl_params_present) { ++ subpic_params_present = get_bits1(gb); ++ ++ if (subpic_params_present) { ++ skip_bits(gb, 8); // tick_divisor_minus2 ++ skip_bits(gb, 5); // du_cpb_removal_delay_increment_length_minus1 ++ skip_bits(gb, 1); // sub_pic_cpb_params_in_pic_timing_sei_flag ++ skip_bits(gb, 5); // dpb_output_delay_du_length_minus1 ++ } ++ ++ skip_bits(gb, 4); // bit_rate_scale ++ skip_bits(gb, 4); // cpb_size_scale ++ ++ if (subpic_params_present) ++ skip_bits(gb, 4); // cpb_size_du_scale ++ ++ skip_bits(gb, 5); // initial_cpb_removal_delay_length_minus1 ++ skip_bits(gb, 5); // au_cpb_removal_delay_length_minus1 ++ skip_bits(gb, 5); // dpb_output_delay_length_minus1 ++ } ++ } ++ ++ for (i = 0; i < max_sublayers; i++) { ++ int low_delay = 0; ++ unsigned int nb_cpb = 1; ++ int fixed_rate = get_bits1(gb); ++ ++ if (!fixed_rate) ++ fixed_rate = get_bits1(gb); ++ ++ if (fixed_rate) ++ get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1 ++ else ++ low_delay = get_bits1(gb); ++ ++ if (!low_delay) { ++ nb_cpb = get_ue_golomb_long(gb) + 1; ++ if (nb_cpb < 1 || nb_cpb > 32) { ++ av_log(NULL, AV_LOG_ERROR, "nb_cpb %d invalid\n", nb_cpb); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ if (nal_params_present) ++ decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); ++ if (vcl_params_present) ++ decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); ++ } ++ return 0; ++} ++ ++int ff_hevc_rpi_decode_nal_vps(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiParamSets * const ps) ++{ ++ int i,j; ++ int vps_id = 0; ++ ptrdiff_t nal_size; ++ HEVCRpiVPS *vps; ++ AVBufferRef *vps_buf = av_buffer_allocz(sizeof(*vps)); ++ ++ if (!vps_buf) ++ return AVERROR(ENOMEM); ++ vps = (HEVCRpiVPS*)vps_buf->data; ++ ++ av_log(avctx, AV_LOG_DEBUG, "Decoding VPS\n"); ++ ++ nal_size = gb->buffer_end - gb->buffer; ++ if (nal_size > sizeof(vps->data)) { ++ av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized VPS " ++ "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n", ++ nal_size, sizeof(vps->data)); ++ vps->data_size = sizeof(vps->data); ++ } else { ++ vps->data_size = nal_size; ++ } ++ memcpy(vps->data, gb->buffer, vps->data_size); ++ ++ vps_id = get_bits(gb, 4); ++ if (vps_id >= HEVC_MAX_VPS_COUNT) { ++ av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", vps_id); ++ goto err; ++ } ++ ++ if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits ++ av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); ++ goto err; ++ } ++ ++ vps->vps_max_layers = get_bits(gb, 6) + 1; ++ vps->vps_max_sub_layers = get_bits(gb, 3) + 1; ++ vps->vps_temporal_id_nesting_flag = get_bits1(gb); ++ ++ if (get_bits(gb, 16) != 0xffff) { // vps_reserved_ffff_16bits ++ av_log(avctx, AV_LOG_ERROR, "vps_reserved_ffff_16bits is not 0xffff\n"); ++ goto err; ++ } ++ ++ if (vps->vps_max_sub_layers > HEVC_MAX_SUB_LAYERS) { ++ av_log(avctx, AV_LOG_ERROR, "vps_max_sub_layers out of range: %d\n", ++ vps->vps_max_sub_layers); ++ goto err; ++ } ++ ++ if (parse_ptl(gb, avctx, &vps->ptl, vps->vps_max_sub_layers) < 0) ++ goto err; ++ ++ vps->vps_sub_layer_ordering_info_present_flag = get_bits1(gb); ++ ++ i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_sub_layers - 1; ++ for (; i < vps->vps_max_sub_layers; i++) { ++ vps->vps_max_dec_pic_buffering[i] = get_ue_golomb_long(gb) + 1; ++ vps->vps_num_reorder_pics[i] = get_ue_golomb_long(gb); ++ vps->vps_max_latency_increase[i] = get_ue_golomb_long(gb) - 1; ++ ++ if (vps->vps_max_dec_pic_buffering[i] > HEVC_MAX_DPB_SIZE || !vps->vps_max_dec_pic_buffering[i]) { ++ av_log(avctx, AV_LOG_ERROR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n", ++ vps->vps_max_dec_pic_buffering[i] - 1); ++ goto err; ++ } ++ if (vps->vps_num_reorder_pics[i] > vps->vps_max_dec_pic_buffering[i] - 1) { ++ av_log(avctx, AV_LOG_WARNING, "vps_max_num_reorder_pics out of range: %d\n", ++ vps->vps_num_reorder_pics[i]); ++ if (avctx->err_recognition & AV_EF_EXPLODE) ++ goto err; ++ } ++ } ++ ++ vps->vps_max_layer_id = get_bits(gb, 6); ++ vps->vps_num_layer_sets = get_ue_golomb_long(gb) + 1; ++ if (vps->vps_num_layer_sets < 1 || vps->vps_num_layer_sets > 1024 || ++ (vps->vps_num_layer_sets - 1LL) * (vps->vps_max_layer_id + 1LL) > get_bits_left(gb)) { ++ av_log(avctx, AV_LOG_ERROR, "too many layer_id_included_flags\n"); ++ goto err; ++ } ++ ++ for (i = 1; i < vps->vps_num_layer_sets; i++) ++ for (j = 0; j <= vps->vps_max_layer_id; j++) ++ skip_bits(gb, 1); // layer_id_included_flag[i][j] ++ ++ vps->vps_timing_info_present_flag = get_bits1(gb); ++ if (vps->vps_timing_info_present_flag) { ++ vps->vps_num_units_in_tick = get_bits_long(gb, 32); ++ vps->vps_time_scale = get_bits_long(gb, 32); ++ vps->vps_poc_proportional_to_timing_flag = get_bits1(gb); ++ if (vps->vps_poc_proportional_to_timing_flag) ++ vps->vps_num_ticks_poc_diff_one = get_ue_golomb_long(gb) + 1; ++ vps->vps_num_hrd_parameters = get_ue_golomb_long(gb); ++ if (vps->vps_num_hrd_parameters > (unsigned)vps->vps_num_layer_sets) { ++ av_log(avctx, AV_LOG_ERROR, ++ "vps_num_hrd_parameters %d is invalid\n", vps->vps_num_hrd_parameters); ++ goto err; ++ } ++ for (i = 0; i < vps->vps_num_hrd_parameters; i++) { ++ int common_inf_present = 1; ++ ++ get_ue_golomb_long(gb); // hrd_layer_set_idx ++ if (i) ++ common_inf_present = get_bits1(gb); ++ decode_hrd(gb, common_inf_present, vps->vps_max_sub_layers); ++ } ++ } ++ get_bits1(gb); /* vps_extension_flag */ ++ ++ if (get_bits_left(gb) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Overread VPS by %d bits\n", -get_bits_left(gb)); ++ if (ps->vps_list[vps_id]) ++ goto err; ++ } ++ ++ if (ps->vps_list[vps_id] && ++ !memcmp(ps->vps_list[vps_id]->data, vps_buf->data, vps_buf->size)) { ++ av_buffer_unref(&vps_buf); ++ } else { ++ remove_vps(ps, vps_id); ++ ps->vps_list[vps_id] = vps_buf; ++ } ++ ++ return 0; ++ ++err: ++ av_buffer_unref(&vps_buf); ++ return AVERROR_INVALIDDATA; ++} ++ ++static void decode_vui(GetBitContext * const gb, AVCodecContext * const avctx, ++ const int apply_defdispwin, HEVCRpiSPS * const sps) ++{ ++ VUI backup_vui, * const vui = &sps->vui; ++ GetBitContext backup; ++ int sar_present, alt = 0; ++ ++ av_log(avctx, AV_LOG_DEBUG, "Decoding VUI\n"); ++ ++ sar_present = get_bits1(gb); ++ if (sar_present) { ++ uint8_t sar_idx = get_bits(gb, 8); ++ if (sar_idx < FF_ARRAY_ELEMS(vui_sar)) ++ vui->sar = vui_sar[sar_idx]; ++ else if (sar_idx == 255) { ++ vui->sar.num = get_bits(gb, 16); ++ vui->sar.den = get_bits(gb, 16); ++ } else ++ av_log(avctx, AV_LOG_WARNING, ++ "Unknown SAR index: %u.\n", sar_idx); ++ } ++ ++ vui->overscan_info_present_flag = get_bits1(gb); ++ if (vui->overscan_info_present_flag) ++ vui->overscan_appropriate_flag = get_bits1(gb); ++ ++ vui->video_signal_type_present_flag = get_bits1(gb); ++ if (vui->video_signal_type_present_flag) { ++ vui->video_format = get_bits(gb, 3); ++ vui->video_full_range_flag = get_bits1(gb); ++ vui->colour_description_present_flag = get_bits1(gb); ++ if (vui->video_full_range_flag && sps->pix_fmt == AV_PIX_FMT_YUV420P) ++ sps->pix_fmt = AV_PIX_FMT_YUVJ420P; ++ if (vui->colour_description_present_flag) { ++ vui->colour_primaries = get_bits(gb, 8); ++ vui->transfer_characteristic = get_bits(gb, 8); ++ vui->matrix_coeffs = get_bits(gb, 8); ++ ++ // Set invalid values to "unspecified" ++ if (!av_color_primaries_name(vui->colour_primaries)) ++ vui->colour_primaries = AVCOL_PRI_UNSPECIFIED; ++ if (!av_color_transfer_name(vui->transfer_characteristic)) ++ vui->transfer_characteristic = AVCOL_TRC_UNSPECIFIED; ++ if (!av_color_space_name(vui->matrix_coeffs)) ++ vui->matrix_coeffs = AVCOL_SPC_UNSPECIFIED; ++ if (vui->matrix_coeffs == AVCOL_SPC_RGB) { ++ switch (sps->pix_fmt) { ++ case AV_PIX_FMT_YUV444P: ++ sps->pix_fmt = AV_PIX_FMT_GBRP; ++ break; ++ case AV_PIX_FMT_YUV444P10: ++ sps->pix_fmt = AV_PIX_FMT_GBRP10; ++ break; ++ case AV_PIX_FMT_YUV444P12: ++ sps->pix_fmt = AV_PIX_FMT_GBRP12; ++ break; ++ } ++ } ++ } ++ } ++ ++ vui->chroma_loc_info_present_flag = get_bits1(gb); ++ if (vui->chroma_loc_info_present_flag) { ++ vui->chroma_sample_loc_type_top_field = get_ue_golomb_long(gb); ++ vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_long(gb); ++ } ++ ++ vui->neutra_chroma_indication_flag = get_bits1(gb); ++ vui->field_seq_flag = get_bits1(gb); ++ vui->frame_field_info_present_flag = get_bits1(gb); ++ ++ // Backup context in case an alternate header is detected ++ memcpy(&backup, gb, sizeof(backup)); ++ memcpy(&backup_vui, vui, sizeof(backup_vui)); ++ if (get_bits_left(gb) >= 68 && show_bits_long(gb, 21) == 0x100000) { ++ vui->default_display_window_flag = 0; ++ av_log(avctx, AV_LOG_WARNING, "Invalid default display window\n"); ++ } else ++ vui->default_display_window_flag = get_bits1(gb); ++ ++ if (vui->default_display_window_flag) { ++ int vert_mult = 1 + (sps->chroma_format_idc < 2); ++ int horiz_mult = 1 + (sps->chroma_format_idc < 3); ++ vui->def_disp_win.left_offset = get_ue_golomb_long(gb) * horiz_mult; ++ vui->def_disp_win.right_offset = get_ue_golomb_long(gb) * horiz_mult; ++ vui->def_disp_win.top_offset = get_ue_golomb_long(gb) * vert_mult; ++ vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) * vert_mult; ++ ++ if (apply_defdispwin && ++ avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { ++ av_log(avctx, AV_LOG_DEBUG, ++ "discarding vui default display window, " ++ "original values are l:%u r:%u t:%u b:%u\n", ++ vui->def_disp_win.left_offset, ++ vui->def_disp_win.right_offset, ++ vui->def_disp_win.top_offset, ++ vui->def_disp_win.bottom_offset); ++ ++ vui->def_disp_win.left_offset = ++ vui->def_disp_win.right_offset = ++ vui->def_disp_win.top_offset = ++ vui->def_disp_win.bottom_offset = 0; ++ } ++ } ++ ++timing_info: ++ vui->vui_timing_info_present_flag = get_bits1(gb); ++ ++ if (vui->vui_timing_info_present_flag) { ++ if( get_bits_left(gb) < 66 && !alt) { ++ // The alternate syntax seem to have timing info located ++ // at where def_disp_win is normally located ++ av_log(avctx, AV_LOG_WARNING, ++ "Strange VUI timing information, retrying...\n"); ++ memcpy(vui, &backup_vui, sizeof(backup_vui)); ++ memcpy(gb, &backup, sizeof(backup)); ++ alt = 1; ++ goto timing_info; ++ } ++ vui->vui_num_units_in_tick = get_bits_long(gb, 32); ++ vui->vui_time_scale = get_bits_long(gb, 32); ++ if (alt) { ++ av_log(avctx, AV_LOG_INFO, "Retry got %"PRIu32"/%"PRIu32" fps\n", ++ vui->vui_time_scale, vui->vui_num_units_in_tick); ++ } ++ vui->vui_poc_proportional_to_timing_flag = get_bits1(gb); ++ if (vui->vui_poc_proportional_to_timing_flag) ++ vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); ++ vui->vui_hrd_parameters_present_flag = get_bits1(gb); ++ if (vui->vui_hrd_parameters_present_flag) ++ decode_hrd(gb, 1, sps->max_sub_layers); ++ } ++ ++ vui->bitstream_restriction_flag = get_bits1(gb); ++ if (vui->bitstream_restriction_flag) { ++ if (get_bits_left(gb) < 8 && !alt) { ++ av_log(avctx, AV_LOG_WARNING, ++ "Strange VUI bitstream restriction information, retrying" ++ " from timing information...\n"); ++ memcpy(vui, &backup_vui, sizeof(backup_vui)); ++ memcpy(gb, &backup, sizeof(backup)); ++ alt = 1; ++ goto timing_info; ++ } ++ vui->tiles_fixed_structure_flag = get_bits1(gb); ++ vui->motion_vectors_over_pic_boundaries_flag = get_bits1(gb); ++ vui->restricted_ref_pic_lists_flag = get_bits1(gb); ++ vui->min_spatial_segmentation_idc = get_ue_golomb_long(gb); ++ vui->max_bytes_per_pic_denom = get_ue_golomb_long(gb); ++ vui->max_bits_per_min_cu_denom = get_ue_golomb_long(gb); ++ vui->log2_max_mv_length_horizontal = get_ue_golomb_long(gb); ++ vui->log2_max_mv_length_vertical = get_ue_golomb_long(gb); ++ } ++ ++ if (get_bits_left(gb) < 1 && !alt) { ++ // XXX: Alternate syntax when sps_range_extension_flag != 0? ++ av_log(avctx, AV_LOG_WARNING, ++ "Overread in VUI, retrying from timing information...\n"); ++ memcpy(vui, &backup_vui, sizeof(backup_vui)); ++ memcpy(gb, &backup, sizeof(backup)); ++ alt = 1; ++ goto timing_info; ++ } ++} ++ ++static void set_default_scaling_list_data(ScalingList * const sl) ++{ ++ int matrixId; ++ ++ for (matrixId = 0; matrixId < 6; matrixId++) { ++ // 4x4 default is 16 ++ memset(sl->sl[0][matrixId], 16, 16); ++ sl->sl_dc[0][matrixId] = 16; // default for 16x16 ++ sl->sl_dc[1][matrixId] = 16; // default for 32x32 ++ } ++ ++ memcpy(sl->sl[1][0], default_scaling_list_intra, 64); ++ memcpy(sl->sl[1][1], default_scaling_list_intra, 64); ++ memcpy(sl->sl[1][2], default_scaling_list_intra, 64); ++ ++ memcpy(sl->sl[1][3], default_scaling_list_inter, 64); ++ memcpy(sl->sl[1][4], default_scaling_list_inter, 64); ++ memcpy(sl->sl[1][5], default_scaling_list_inter, 64); ++ ++ memcpy(sl->sl[2][0], default_scaling_list_intra, 64); ++ memcpy(sl->sl[2][1], default_scaling_list_intra, 64); ++ memcpy(sl->sl[2][2], default_scaling_list_intra, 64); ++ ++ memcpy(sl->sl[2][3], default_scaling_list_inter, 64); ++ memcpy(sl->sl[2][4], default_scaling_list_inter, 64); ++ memcpy(sl->sl[2][5], default_scaling_list_inter, 64); ++ ++ memcpy(sl->sl[3][0], default_scaling_list_intra, 64); ++ memcpy(sl->sl[3][1], default_scaling_list_intra, 64); ++ memcpy(sl->sl[3][2], default_scaling_list_intra, 64); ++ ++ memcpy(sl->sl[3][3], default_scaling_list_inter, 64); ++ memcpy(sl->sl[3][4], default_scaling_list_inter, 64); ++ memcpy(sl->sl[3][5], default_scaling_list_inter, 64); ++} ++ ++static int scaling_list_data(GetBitContext * const gb, AVCodecContext * const avctx, ScalingList * const sl, ++ const HEVCRpiSPS * const sps) ++{ ++ uint8_t scaling_list_pred_mode_flag; ++ int32_t scaling_list_dc_coef[2][6]; ++ int size_id, matrix_id, pos; ++ int i; ++ ++ for (size_id = 0; size_id < 4; size_id++) ++ for (matrix_id = 0; matrix_id < 6; matrix_id += ((size_id == 3) ? 3 : 1)) { ++ scaling_list_pred_mode_flag = get_bits1(gb); ++ if (!scaling_list_pred_mode_flag) { ++ unsigned int delta = get_ue_golomb_long(gb); ++ /* Only need to handle non-zero delta. Zero means default, ++ * which should already be in the arrays. */ ++ if (delta) { ++ // Copy from previous array. ++ delta *= (size_id == 3) ? 3 : 1; ++ if (matrix_id < delta) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Invalid delta in scaling list data: %d.\n", delta); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ memcpy(sl->sl[size_id][matrix_id], ++ sl->sl[size_id][matrix_id - delta], ++ size_id > 0 ? 64 : 16); ++ if (size_id > 1) ++ sl->sl_dc[size_id - 2][matrix_id] = sl->sl_dc[size_id - 2][matrix_id - delta]; ++ } ++ } else { ++ int next_coef, coef_num; ++ int32_t scaling_list_delta_coef; ++ ++ next_coef = 8; ++ coef_num = FFMIN(64, 1 << (4 + (size_id << 1))); ++ if (size_id > 1) { ++ scaling_list_dc_coef[size_id - 2][matrix_id] = get_se_golomb(gb) + 8; ++ next_coef = scaling_list_dc_coef[size_id - 2][matrix_id]; ++ sl->sl_dc[size_id - 2][matrix_id] = next_coef; ++ } ++ for (i = 0; i < coef_num; i++) { ++ if (size_id == 0) ++ pos = 4 * ff_hevc_rpi_diag_scan4x4_y[i] + ++ ff_hevc_rpi_diag_scan4x4_x[i]; ++ else ++ pos = 8 * ff_hevc_rpi_diag_scan8x8_y[i] + ++ ff_hevc_rpi_diag_scan8x8_x[i]; ++ ++ scaling_list_delta_coef = get_se_golomb(gb); ++ next_coef = (next_coef + 256U + scaling_list_delta_coef) % 256; ++ sl->sl[size_id][matrix_id][pos] = next_coef; ++ } ++ } ++ } ++ ++ if (sps->chroma_format_idc == 3) { ++ for (i = 0; i < 64; i++) { ++ sl->sl[3][1][i] = sl->sl[2][1][i]; ++ sl->sl[3][2][i] = sl->sl[2][2][i]; ++ sl->sl[3][4][i] = sl->sl[2][4][i]; ++ sl->sl[3][5][i] = sl->sl[2][5][i]; ++ } ++ sl->sl_dc[1][1] = sl->sl_dc[0][1]; ++ sl->sl_dc[1][2] = sl->sl_dc[0][2]; ++ sl->sl_dc[1][4] = sl->sl_dc[0][4]; ++ sl->sl_dc[1][5] = sl->sl_dc[0][5]; ++ } ++ ++ ++ return 0; ++} ++ ++static int map_pixel_format(HEVCRpiSPS * const sps) ++{ ++ const int cfmt = sps->chroma_format_idc; ++ ++ sps->pix_fmt = AV_PIX_FMT_NONE; ++ switch (sps->bit_depth) { ++ case 8: ++ if (cfmt == 1) ++ sps->pix_fmt = AV_PIX_FMT_SAND128; ++ break; ++ case 10: ++ if (cfmt == 1) ++ sps->pix_fmt = AV_PIX_FMT_SAND64_10; ++ break; ++ default: ++ break; ++ } ++ ++ sps->hshift[0] = sps->vshift[0] = 0; ++ sps->hshift[2] = sps->hshift[1] = cfmt > 2 ? 0 : 1; // 1 unless 4:4:4 ++ sps->vshift[2] = sps->vshift[1] = cfmt > 1 ? 0 : 1; // 1 unless 4:4:4 or 4:2:2 ++ ++ sps->pixel_shift = sps->bit_depth > 8 ? 1 : 0; ++ ++ return 0; ++} ++ ++static int ff_hevc_rpi_parse_sps(HEVCRpiSPS * const sps, GetBitContext * const gb, unsigned int * const sps_id, ++ const int apply_defdispwin, AVBufferRef * const * const vps_list, AVCodecContext * const avctx) ++{ ++ HEVCRpiWindow *ow; ++ int ret = 0; ++ int log2_diff_max_min_transform_block_size; ++ int bit_depth_chroma, start, vui_present, sublayer_ordering_info; ++ int i; ++ ++ // Coded parameters ++ ++ sps->vps_id = get_bits(gb, 4); ++ if (sps->vps_id >= HEVC_MAX_VPS_COUNT) { ++ av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", sps->vps_id); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (vps_list && !vps_list[sps->vps_id]) { ++ av_log(avctx, AV_LOG_ERROR, "VPS %d does not exist\n", ++ sps->vps_id); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sps->max_sub_layers = get_bits(gb, 3) + 1; ++ if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) { ++ av_log(avctx, AV_LOG_ERROR, "sps_max_sub_layers out of range: %d\n", ++ sps->max_sub_layers); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sps->temporal_id_nesting_flag = get_bits(gb, 1); ++ ++ if ((ret = parse_ptl(gb, avctx, &sps->ptl, sps->max_sub_layers)) < 0) ++ return ret; ++ ++ *sps_id = get_ue_golomb_long(gb); ++ if (*sps_id >= HEVC_MAX_SPS_COUNT) { ++ av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", *sps_id); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sps->chroma_format_idc = get_ue_golomb_long(gb); ++ if (sps->chroma_format_idc > 3U) { ++ av_log(avctx, AV_LOG_ERROR, "chroma_format_idc %d is invalid\n", sps->chroma_format_idc); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (sps->chroma_format_idc == 3) ++ sps->separate_colour_plane_flag = get_bits1(gb); ++ ++ if (sps->separate_colour_plane_flag) ++ sps->chroma_format_idc = 0; ++ ++ sps->width = get_ue_golomb_long(gb); ++ sps->height = get_ue_golomb_long(gb); ++ if ((ret = av_image_check_size(sps->width, ++ sps->height, 0, avctx)) < 0) ++ return ret; ++ ++ if (get_bits1(gb)) { // pic_conformance_flag ++ int vert_mult = 1 + (sps->chroma_format_idc < 2); ++ int horiz_mult = 1 + (sps->chroma_format_idc < 3); ++ sps->pic_conf_win.left_offset = get_ue_golomb_long(gb) * horiz_mult; ++ sps->pic_conf_win.right_offset = get_ue_golomb_long(gb) * horiz_mult; ++ sps->pic_conf_win.top_offset = get_ue_golomb_long(gb) * vert_mult; ++ sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) * vert_mult; ++ ++ if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { ++ av_log(avctx, AV_LOG_DEBUG, ++ "discarding sps conformance window, " ++ "original values are l:%u r:%u t:%u b:%u\n", ++ sps->pic_conf_win.left_offset, ++ sps->pic_conf_win.right_offset, ++ sps->pic_conf_win.top_offset, ++ sps->pic_conf_win.bottom_offset); ++ ++ sps->pic_conf_win.left_offset = ++ sps->pic_conf_win.right_offset = ++ sps->pic_conf_win.top_offset = ++ sps->pic_conf_win.bottom_offset = 0; ++ } ++ sps->output_window = sps->pic_conf_win; ++ } ++ ++ sps->bit_depth = get_ue_golomb_long(gb) + 8; ++ bit_depth_chroma = get_ue_golomb_long(gb) + 8; ++ if (sps->chroma_format_idc && bit_depth_chroma != sps->bit_depth) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Luma bit depth (%d) is different from chroma bit depth (%d), " ++ "this is unsupported.\n", ++ sps->bit_depth, bit_depth_chroma); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ ret = map_pixel_format(sps); ++ if (ret < 0) ++ return ret; ++ ++ sps->log2_max_poc_lsb = get_ue_golomb_long(gb) + 4; ++ if (sps->log2_max_poc_lsb > 16) { ++ av_log(avctx, AV_LOG_ERROR, "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", ++ sps->log2_max_poc_lsb - 4); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sublayer_ordering_info = get_bits1(gb); ++ start = sublayer_ordering_info ? 0 : sps->max_sub_layers - 1; ++ for (i = start; i < sps->max_sub_layers; i++) { ++ sps->temporal_layer[i].max_dec_pic_buffering = get_ue_golomb_long(gb) + 1; ++ sps->temporal_layer[i].num_reorder_pics = get_ue_golomb_long(gb); ++ sps->temporal_layer[i].max_latency_increase = get_ue_golomb_long(gb) - 1; ++ if (sps->temporal_layer[i].max_dec_pic_buffering > (unsigned)HEVC_MAX_DPB_SIZE) { ++ av_log(avctx, AV_LOG_ERROR, "sps_max_dec_pic_buffering_minus1 out of range: %d\n", ++ sps->temporal_layer[i].max_dec_pic_buffering - 1U); ++ return AVERROR_INVALIDDATA; ++ } ++ if (sps->temporal_layer[i].num_reorder_pics > sps->temporal_layer[i].max_dec_pic_buffering - 1) { ++ av_log(avctx, AV_LOG_WARNING, "sps_max_num_reorder_pics out of range: %d\n", ++ sps->temporal_layer[i].num_reorder_pics); ++ if (avctx->err_recognition & AV_EF_EXPLODE || ++ sps->temporal_layer[i].num_reorder_pics > HEVC_MAX_DPB_SIZE - 1) { ++ return AVERROR_INVALIDDATA; ++ } ++ sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[i].num_reorder_pics + 1; ++ } ++ } ++ ++ if (!sublayer_ordering_info) { ++ for (i = 0; i < start; i++) { ++ sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[start].max_dec_pic_buffering; ++ sps->temporal_layer[i].num_reorder_pics = sps->temporal_layer[start].num_reorder_pics; ++ sps->temporal_layer[i].max_latency_increase = sps->temporal_layer[start].max_latency_increase; ++ } ++ } ++ ++ sps->log2_min_cb_size = get_ue_golomb_long(gb) + 3; ++ sps->log2_diff_max_min_coding_block_size = get_ue_golomb_long(gb); ++ sps->log2_min_tb_size = get_ue_golomb_long(gb) + 2; ++ log2_diff_max_min_transform_block_size = get_ue_golomb_long(gb); ++ sps->log2_max_trafo_size = log2_diff_max_min_transform_block_size + ++ sps->log2_min_tb_size; ++ ++ if (sps->log2_min_cb_size < 3 || sps->log2_min_cb_size > 30) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_min_cb_size", sps->log2_min_cb_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (sps->log2_diff_max_min_coding_block_size > 30) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_diff_max_min_coding_block_size", sps->log2_diff_max_min_coding_block_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (sps->log2_min_tb_size >= sps->log2_min_cb_size || sps->log2_min_tb_size < 2) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value for log2_min_tb_size"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (log2_diff_max_min_transform_block_size < 0 || log2_diff_max_min_transform_block_size > 30) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value %d for log2_diff_max_min_transform_block_size", log2_diff_max_min_transform_block_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ { ++ const unsigned int CtbLog2SizeY = sps->log2_min_cb_size + sps->log2_diff_max_min_coding_block_size; ++ // Not a bitstream limitation, but all profiles ++ if (CtbLog2SizeY < 4 || CtbLog2SizeY > HEVC_MAX_LOG2_CTB_SIZE) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value %d for CtbLog2SizeY", CtbLog2SizeY); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (sps->log2_max_trafo_size > FFMIN(5, CtbLog2SizeY)) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid value %d for MaxTbLog2SizeY", sps->log2_max_trafo_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ // Inferred parameters ++ sps->log2_ctb_size = CtbLog2SizeY; ++// sps->log2_min_pu_size = sps->log2_min_cb_size - 1; ++ } ++ ++ sps->max_transform_hierarchy_depth_inter = get_ue_golomb_long(gb); ++ sps->max_transform_hierarchy_depth_intra = get_ue_golomb_long(gb); ++ ++ sps->scaling_list_enable_flag = get_bits1(gb); ++ if (sps->scaling_list_enable_flag) { ++ set_default_scaling_list_data(&sps->scaling_list); ++ ++ if (get_bits1(gb)) { ++ ret = scaling_list_data(gb, avctx, &sps->scaling_list, sps); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ ++ sps->amp_enabled_flag = get_bits1(gb); ++ sps->sao_enabled = get_bits1(gb); ++ ++ // Set pcm defaults (0) so we don't have to test _enabled when we ++ // want to use them ++ memset(&sps->pcm, 0, sizeof(sps->pcm)); ++ ++ if (get_bits1(gb)) // pcm_enabled_flag ++ { ++ const unsigned int limit_max_pcm = FFMIN(5, ++ sps->log2_min_cb_size + sps->log2_diff_max_min_coding_block_size); ++ sps->pcm.bit_depth = get_bits(gb, 4) + 1; ++ sps->pcm.bit_depth_chroma = get_bits(gb, 4) + 1; ++ sps->pcm.log2_min_pcm_cb_size = get_ue_golomb_long(gb) + 3; ++ sps->pcm.log2_max_pcm_cb_size = sps->pcm.log2_min_pcm_cb_size + ++ get_ue_golomb_long(gb); ++ if (FFMAX(sps->pcm.bit_depth, sps->pcm.bit_depth_chroma) > sps->bit_depth) { ++ av_log(avctx, AV_LOG_ERROR, ++ "PCM bit depth (%d, %d) is greater than normal bit depth (%d)\n", ++ sps->pcm.bit_depth, sps->pcm.bit_depth_chroma, sps->bit_depth); ++ return AVERROR_INVALIDDATA; ++ } ++ if (sps->pcm.log2_min_pcm_cb_size < sps->log2_min_cb_size || ++ sps->pcm.log2_max_pcm_cb_size > limit_max_pcm) { ++ av_log(avctx, AV_LOG_ERROR, "Bad PCM CB min/max size (%d->%d)", ++ sps->pcm.log2_min_pcm_cb_size, sps->pcm.log2_max_pcm_cb_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sps->pcm.loop_filter_disable_flag = get_bits1(gb); ++ } ++ ++ // Could be based on min_pcm_cb_size but much easier logic if we just stick ++ // with 8 (and costs us little) ++ sps->pcm_width = (sps->width + 63) >> 6; // 8 for min size, 8 bits per byte - round up ++ sps->pcm_height = (sps->height + 7) >> 3; ++ ++ sps->nb_st_rps = get_ue_golomb_long(gb); ++ if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) { ++ av_log(avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n", ++ sps->nb_st_rps); ++ return AVERROR_INVALIDDATA; ++ } ++ for (i = 0; i < sps->nb_st_rps; i++) { ++ if ((ret = ff_hevc_rpi_decode_short_term_rps(gb, avctx, &sps->st_rps[i], ++ sps, 0)) < 0) ++ return ret; ++ } ++ ++ sps->long_term_ref_pics_present_flag = get_bits1(gb); ++ if (sps->long_term_ref_pics_present_flag) { ++ sps->num_long_term_ref_pics_sps = get_ue_golomb_long(gb); ++ if (sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PICS) { ++ av_log(avctx, AV_LOG_ERROR, "num_long_term_ref_pics_sps %d is out of range.\n", ++ sps->num_long_term_ref_pics_sps); ++ return AVERROR_INVALIDDATA; ++ } ++ for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) { ++ sps->lt_ref_pic_poc_lsb_sps[i] = get_bits(gb, sps->log2_max_poc_lsb); ++ sps->used_by_curr_pic_lt_sps_flag[i] = get_bits1(gb); ++ } ++ } ++ ++ sps->sps_temporal_mvp_enabled_flag = get_bits1(gb); ++ sps->intra_filters_disable = get_bits1(gb) ? 0 : FILTER_STRONG; // sps->sps_strong_intra_smoothing_enable_flag ++ sps->vui.sar = (AVRational){0, 1}; ++ vui_present = get_bits1(gb); ++ if (vui_present) ++ decode_vui(gb, avctx, apply_defdispwin, sps); ++ ++ if (get_bits1(gb)) { // sps_extension_flag ++ int sps_extension_flag[1]; ++ for (i = 0; i < 1; i++) ++ sps_extension_flag[i] = get_bits1(gb); ++ skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); ++ if (sps_extension_flag[0]) { ++ int extended_precision_processing_flag; ++ int cabac_bypass_alignment_enabled_flag; ++ ++ sps->transform_skip_rotation_enabled_flag = get_bits1(gb); ++ sps->transform_skip_context_enabled_flag = get_bits1(gb); ++ sps->implicit_rdpcm_enabled_flag = get_bits1(gb); ++ ++ sps->explicit_rdpcm_enabled_flag = get_bits1(gb); ++ ++ extended_precision_processing_flag = get_bits1(gb); ++ if (extended_precision_processing_flag) ++ av_log(avctx, AV_LOG_WARNING, ++ "extended_precision_processing_flag not yet implemented\n"); ++ ++ if (get_bits1(gb)) // sps->intra_smoothing_disabled_flag ++ sps->intra_filters_disable |= FILTER_EITHER; ++ sps->high_precision_offsets_enabled_flag = get_bits1(gb); ++ sps->persistent_rice_adaptation_enabled_flag = get_bits1(gb); ++ ++ cabac_bypass_alignment_enabled_flag = get_bits1(gb); ++ if (cabac_bypass_alignment_enabled_flag) ++ av_log(avctx, AV_LOG_WARNING, ++ "cabac_bypass_alignment_enabled_flag not yet implemented\n"); ++ } ++ } ++ if (apply_defdispwin) { ++ sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; ++ sps->output_window.right_offset += sps->vui.def_disp_win.right_offset; ++ sps->output_window.top_offset += sps->vui.def_disp_win.top_offset; ++ sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset; ++ } ++ ++ ow = &sps->output_window; ++ if (ow->left_offset >= INT_MAX - ow->right_offset || ++ ow->top_offset >= INT_MAX - ow->bottom_offset || ++ ow->left_offset + ow->right_offset >= sps->width || ++ ow->top_offset + ow->bottom_offset >= sps->height) { ++ av_log(avctx, AV_LOG_WARNING, "Invalid cropping offsets: %u/%u/%u/%u\n", ++ ow->left_offset, ow->right_offset, ow->top_offset, ow->bottom_offset); ++ if (avctx->err_recognition & AV_EF_EXPLODE) { ++ return AVERROR_INVALIDDATA; ++ } ++ av_log(avctx, AV_LOG_WARNING, ++ "Displaying the whole video surface.\n"); ++ memset(ow, 0, sizeof(*ow)); ++ memset(&sps->pic_conf_win, 0, sizeof(sps->pic_conf_win)); ++ } ++ ++ // Inferred parameters ++ ++ sps->ctb_width = (sps->width + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; ++ sps->ctb_height = (sps->height + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; ++ sps->ctb_size = sps->ctb_width * sps->ctb_height; ++ ++ sps->min_cb_width = sps->width >> sps->log2_min_cb_size; ++ sps->min_cb_height = sps->height >> sps->log2_min_cb_size; ++ sps->min_tb_width = sps->width >> sps->log2_min_tb_size; ++ sps->min_tb_height = sps->height >> sps->log2_min_tb_size; ++ sps->min_pu_width = sps->width >> LOG2_MIN_PU_SIZE; ++ sps->min_pu_height = sps->height >> LOG2_MIN_PU_SIZE; ++ sps->tb_mask = (1 << (sps->log2_ctb_size - sps->log2_min_tb_size)) - 1; ++ ++ sps->qp_bd_offset = 6 * (sps->bit_depth - 8); ++ sps->wp_offset_half_range = (1U << (sps->high_precision_offsets_enabled_flag ? sps->bit_depth - 1 : 7)); ++ ++ if (av_mod_uintp2(sps->width, sps->log2_min_cb_size) || ++ av_mod_uintp2(sps->height, sps->log2_min_cb_size)) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid coded frame dimensions.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (sps->max_transform_hierarchy_depth_inter > sps->log2_ctb_size - sps->log2_min_tb_size) { ++ av_log(avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_inter out of range: %d\n", ++ sps->max_transform_hierarchy_depth_inter); ++ return AVERROR_INVALIDDATA; ++ } ++ if (sps->max_transform_hierarchy_depth_intra > sps->log2_ctb_size - sps->log2_min_tb_size) { ++ av_log(avctx, AV_LOG_ERROR, "max_transform_hierarchy_depth_intra out of range: %d\n", ++ sps->max_transform_hierarchy_depth_intra); ++ return AVERROR_INVALIDDATA; ++ } ++ if (sps->log2_max_trafo_size > FFMIN(sps->log2_ctb_size, 5)) { ++ av_log(avctx, AV_LOG_ERROR, ++ "max transform block size out of range: %d\n", ++ sps->log2_max_trafo_size); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (get_bits_left(gb) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Overread SPS by %d bits\n", -get_bits_left(gb)); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ return 0; ++} ++ ++int ff_hevc_rpi_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, ++ HEVCRpiParamSets *ps, int apply_defdispwin) ++{ ++ HEVCRpiSPS *sps; ++ AVBufferRef *sps_buf = av_buffer_allocz(sizeof(*sps)); ++ unsigned int sps_id; ++ int ret; ++ ptrdiff_t nal_size; ++ ++ if (!sps_buf) ++ return AVERROR(ENOMEM); ++ sps = (HEVCRpiSPS*)sps_buf->data; ++ ++ av_log(avctx, AV_LOG_DEBUG, "Decoding SPS\n"); ++ ++ nal_size = gb->buffer_end - gb->buffer; ++ if (nal_size > sizeof(sps->data)) { ++ av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized SPS " ++ "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n", ++ nal_size, sizeof(sps->data)); ++ sps->data_size = sizeof(sps->data); ++ } else { ++ sps->data_size = nal_size; ++ } ++ memcpy(sps->data, gb->buffer, sps->data_size); ++ ++ ret = ff_hevc_rpi_parse_sps(sps, gb, &sps_id, ++ apply_defdispwin, ++ ps->vps_list, avctx); ++ if (ret < 0) { ++ av_buffer_unref(&sps_buf); ++ return ret; ++ } ++ ++ if (avctx->debug & FF_DEBUG_BITSTREAM) { ++ av_log(avctx, AV_LOG_DEBUG, ++ "Parsed SPS: id %d; coded wxh: %dx%d; " ++ "cropped wxh: %dx%d; pix_fmt: %s.\n", ++ sps_id, sps->width, sps->height, ++ sps->width - (sps->output_window.left_offset + sps->output_window.right_offset), ++ sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset), ++ av_get_pix_fmt_name(sps->pix_fmt)); ++ } ++ ++ /* check if this is a repeat of an already parsed SPS, then keep the ++ * original one. ++ * otherwise drop all PPSes that depend on it */ ++ if (ps->sps_list[sps_id] && ++ !memcmp(ps->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) { ++ av_buffer_unref(&sps_buf); ++ } else { ++ remove_sps(ps, sps_id); ++ ps->sps_list[sps_id] = sps_buf; ++ } ++ ++ return 0; ++} ++ ++static void hevc_pps_free(void *opaque, uint8_t *data) ++{ ++ HEVCRpiPPS *pps = (HEVCRpiPPS*)data; ++ ++ av_freep(&pps->column_width); ++ av_freep(&pps->row_height); ++ av_freep(&pps->col_bd); ++ av_freep(&pps->row_bd); ++ av_freep(&pps->col_idxX); ++ av_freep(&pps->ctb_addr_rs_to_ts); ++ av_freep(&pps->ctb_addr_ts_to_rs); ++ av_freep(&pps->tile_pos_ts); ++ av_freep(&pps->tile_size); ++ av_freep(&pps->tile_id); ++ av_freep(&pps->ctb_ts_flags); ++ ++ av_freep(&pps); ++} ++ ++static int get_offset_list(GetBitContext * const gb, AVCodecContext * const avctx, unsigned int n_minus_1, int8_t * offsets) ++{ ++ do ++ { ++ const int offset = get_se_golomb_long(gb); ++ if (offset < -12 || offset > 12) { ++ av_log(avctx, AV_LOG_ERROR, "qp_offset_list[]: %d out of range\n", offset); ++ return AVERROR_INVALIDDATA; ++ } ++ *offsets++ = offset; ++ } while (n_minus_1-- != 0); ++ return 0; ++} ++ ++static int pps_range_extensions(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiPPS * const pps, const HEVCRpiSPS * const sps) ++{ ++ if (pps->transform_skip_enabled_flag) { ++ pps->log2_max_transform_skip_block_size = get_ue_golomb_long(gb) + 2; ++ } ++ pps->cross_component_prediction_enabled_flag = get_bits1(gb); ++ if (pps->cross_component_prediction_enabled_flag && ++ (sps->chroma_format_idc != 3 || sps->separate_colour_plane_flag)) ++ { ++ av_log(avctx, AV_LOG_ERROR, "cross_component_prediction_enabled but chroma_format_idc != 3\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ pps->chroma_qp_offset_list_enabled_flag = get_bits1(gb); ++ if (pps->chroma_qp_offset_list_enabled_flag) { ++ int err; ++ ++ pps->diff_cu_chroma_qp_offset_depth = get_ue_golomb_long(gb); ++ pps->chroma_qp_offset_list_len_minus1 = get_ue_golomb_long(gb); ++ if (pps->chroma_qp_offset_list_len_minus1 > 5) { ++ av_log(avctx, AV_LOG_ERROR, ++ "chroma_qp_offset_list_len_minus1 shall be in the range [0, 5].\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ av_log(avctx, AV_LOG_WARNING, "cb_qp_offset_list not tested yet.\n"); ++ ++ if ((err = get_offset_list(gb, avctx, pps->chroma_qp_offset_list_len_minus1, pps->cb_qp_offset_list)) != 0 || ++ (err = get_offset_list(gb, avctx, pps->chroma_qp_offset_list_len_minus1, pps->cr_qp_offset_list)) != 0) ++ return err; ++ } ++ ++ { ++ const unsigned int max_offset = sps->bit_depth > 10 ? sps->bit_depth - 10 : 0; ++ ++ pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); ++ if (pps->log2_sao_offset_scale_luma > max_offset) { ++ av_log(avctx, AV_LOG_ERROR, "log2_sao_offset_scale_luma invalid"); ++ return AVERROR_INVALIDDATA; ++ } ++ pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); ++ if (pps->log2_sao_offset_scale_chroma > max_offset) { ++ av_log(avctx, AV_LOG_ERROR, "log2_sao_offset_scale_chroma invalid"); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ return(0); ++} ++ ++static inline int setup_pps(AVCodecContext * const avctx, ++ HEVCRpiPPS * const pps, const HEVCRpiSPS * const sps) ++{ ++ int pic_area_in_ctbs; ++ int i, j, x, y, ctb_addr_rs, tile_id; ++ ++ // Inferred parameters ++ ++ // qp_y -> qp_u/qp_v tables ++ // The tables have at least -24,+24 overrun after adding offset here ++ // which should allow for clipless offseting ++ ++ pps->qp_dblk_x[0] = qp_c_dblk_0 + QP_DBLK_OFFSET_0; // No offset for luma, but may be useful for general code ++ pps->qp_bd_x[0] = qp_c_bd_0[sps->bit_depth - 8] + QP_OFFSET_0; ++ ++ if (sps->chroma_format_idc == 1) { ++ pps->qp_dblk_x[1] = qp_c_dblk_1 + pps->cb_qp_offset + QP_DBLK_OFFSET_0; ++ pps->qp_bd_x[1] = qp_c_bd_1[sps->bit_depth - 8] + pps->cb_qp_offset + QP_OFFSET_0; ++ pps->qp_dblk_x[2] = qp_c_dblk_1 + pps->cr_qp_offset + QP_DBLK_OFFSET_0; ++ pps->qp_bd_x[2] = qp_c_bd_1[sps->bit_depth - 8] + pps->cr_qp_offset + QP_OFFSET_0; ++ } ++ else ++ { ++ pps->qp_dblk_x[1] = qp_c_dblk_0 + pps->cb_qp_offset + QP_DBLK_OFFSET_0; ++ pps->qp_bd_x[1] = qp_c_bd_0[sps->bit_depth - 8] + pps->cb_qp_offset + QP_OFFSET_0; ++ pps->qp_dblk_x[2] = qp_c_dblk_0 + pps->cr_qp_offset + QP_DBLK_OFFSET_0; ++ pps->qp_bd_x[2] = qp_c_bd_0[sps->bit_depth - 8] + pps->cr_qp_offset + QP_OFFSET_0; ++ } ++ ++ pps->col_bd = av_malloc_array(pps->num_tile_columns + 1, sizeof(*pps->col_bd)); ++ pps->row_bd = av_malloc_array(pps->num_tile_rows + 1, sizeof(*pps->row_bd)); ++ pps->col_idxX = av_malloc_array(sps->ctb_width, sizeof(*pps->col_idxX)); ++ if (!pps->col_bd || !pps->row_bd || !pps->col_idxX) ++ return AVERROR(ENOMEM); ++ ++ if (pps->uniform_spacing_flag) { ++ if (!pps->column_width) { ++ pps->column_width = av_malloc_array(pps->num_tile_columns, sizeof(*pps->column_width)); ++ pps->row_height = av_malloc_array(pps->num_tile_rows, sizeof(*pps->row_height)); ++ } ++ if (!pps->column_width || !pps->row_height) ++ return AVERROR(ENOMEM); ++ ++ for (i = 0; i < pps->num_tile_columns; i++) { ++ pps->column_width[i] = ((i + 1) * sps->ctb_width) / pps->num_tile_columns - ++ (i * sps->ctb_width) / pps->num_tile_columns; ++ } ++ ++ for (i = 0; i < pps->num_tile_rows; i++) { ++ pps->row_height[i] = ((i + 1) * sps->ctb_height) / pps->num_tile_rows - ++ (i * sps->ctb_height) / pps->num_tile_rows; ++ } ++ } ++ ++ { ++ const unsigned int td_mask = 63 >> (sps->log2_ctb_size + sps->pixel_shift); ++ pps->col_bd[0] = 0; ++ pps->tile_wpp_inter_disable = 0; ++ for (i = 0; i < pps->num_tile_columns; i++) ++ { ++ pps->col_bd[i + 1] = pps->col_bd[i] + pps->column_width[i]; ++ ++ // Avoid trying tile parallel if the columns don't fall on cache boundries ++ // (this causes too much pain syncing flushes with the QPU) ++ // Ignore the final (RHS of pic) tile boundry ++ if ((pps->col_bd[i] & td_mask) != 0) { ++ pps->tile_wpp_inter_disable = 1; ++ } ++ } ++ ++ // If we can start the next row before finishing the first line of ++ // this one then we must wait at the end of the tile ++ // * if this happens a lot then there are better but more complicated ++ // conditions that we could apply ++ if (pps->tile_wpp_inter_disable) { ++ for (i = 0; i < pps->num_tile_rows; i++) ++ { ++ if (pps->row_height[i] <= RPI_MAX_JOBS) { ++ pps->tile_wpp_inter_disable = 2; ++ break; ++ } ++ } ++ } ++ } ++ ++ pps->row_bd[0] = 0; ++ for (i = 0; i < pps->num_tile_rows; i++) ++ pps->row_bd[i + 1] = pps->row_bd[i] + pps->row_height[i]; ++ ++ for (i = 0, j = 0; i < sps->ctb_width; i++) { ++ if (i >= pps->col_bd[j + 1]) ++ j++; ++ pps->col_idxX[i] = j; ++ } ++ ++ /** ++ * 6.5 ++ */ ++ pic_area_in_ctbs = sps->ctb_size; ++ ++ pps->ctb_addr_rs_to_ts = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_rs_to_ts)); ++ pps->ctb_addr_ts_to_rs = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_addr_ts_to_rs)); ++ pps->tile_id = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->tile_id)); ++ pps->tile_size = av_malloc_array(pps->num_tile_columns * pps->num_tile_rows, sizeof(*pps->tile_size)); ++ pps->tile_pos_ts = av_malloc_array(pps->num_tile_columns * pps->num_tile_rows, sizeof(*pps->tile_pos_ts)); ++ pps->ctb_ts_flags = av_malloc_array(pic_area_in_ctbs, sizeof(*pps->ctb_ts_flags)); ++ if (!pps->ctb_addr_rs_to_ts || !pps->ctb_addr_ts_to_rs || ++ !pps->tile_id || pps->tile_pos_ts == NULL || pps->tile_size == NULL) { ++ return AVERROR(ENOMEM); ++ } ++ ++ memset(pps->ctb_ts_flags, 0, pic_area_in_ctbs * sizeof(*pps->ctb_ts_flags)); ++ ++ for (ctb_addr_rs = 0; ctb_addr_rs < pic_area_in_ctbs; ctb_addr_rs++) { ++ int tb_x = ctb_addr_rs % sps->ctb_width; ++ int tb_y = ctb_addr_rs / sps->ctb_width; ++ int tile_x = 0; ++ int tile_y = 0; ++ int val = 0; ++ ++ for (i = 0; i < pps->num_tile_columns; i++) { ++ if (tb_x < pps->col_bd[i + 1]) { ++ tile_x = i; ++ break; ++ } ++ } ++ ++ for (i = 0; i < pps->num_tile_rows; i++) { ++ if (tb_y < pps->row_bd[i + 1]) { ++ tile_y = i; ++ break; ++ } ++ } ++ ++ for (i = 0; i < tile_x; i++) ++ val += pps->row_height[tile_y] * pps->column_width[i]; ++ for (i = 0; i < tile_y; i++) ++ val += sps->ctb_width * pps->row_height[i]; ++ ++ val += (tb_y - pps->row_bd[tile_y]) * pps->column_width[tile_x] + ++ tb_x - pps->col_bd[tile_x]; ++ ++ pps->ctb_addr_rs_to_ts[ctb_addr_rs] = val; ++ pps->ctb_addr_ts_to_rs[val] = ctb_addr_rs; ++ } ++ ++ { ++ uint8_t * pflags = pps->ctb_ts_flags; ++ uint16_t * ptid = pps->tile_id; ++ ++ for (j = 0, tile_id = 0; j < pps->num_tile_rows; j++) ++ { ++ for (i = 0; i < pps->num_tile_columns; i++, tile_id++) ++ { ++ const unsigned int tile_w = pps->column_width[i]; ++ ++ pflags[0] |= CTB_TS_FLAGS_CIREQ; ++ ++ for (x = 0; x != tile_w; ++x) { ++ pflags[x] |= CTB_TS_FLAGS_TOT; ++ } ++ ++ for (y = pps->row_bd[j]; y < pps->row_bd[j + 1]; y++) ++ { ++ pflags[0] |= CTB_TS_FLAGS_SOTL; ++ ++ if (pps->entropy_coding_sync_enabled_flag) ++ { ++ if (pps->column_width[i] != 1) ++ pflags[1] |= CTB_TS_FLAGS_CSAVE; ++ else ++ pflags[0] |= CTB_TS_FLAGS_CIREQ; ++ ++ if ((pflags[0] & CTB_TS_FLAGS_CIREQ) == 0) ++ pflags[0] |= CTB_TS_FLAGS_CLOAD; ++ } ++ ++ for (x = 0; x != tile_w; ++x) ++ *ptid++ = tile_id; ++ ++ pflags += tile_w; ++ pflags[-1] |= CTB_TS_FLAGS_EOTL; ++ if (i + 1 == pps->num_tile_columns) ++ pflags[-1] |= CTB_TS_FLAGS_EOL; ++ } ++ ++ pflags[-1] |= CTB_TS_FLAGS_EOT; ++ } ++ } ++ } ++ ++ { ++ unsigned int ts = 0; ++ for (j = 0; j < pps->num_tile_rows; j++) ++ for (i = 0; i < pps->num_tile_columns; i++) ++ { ++ const unsigned int size = pps->column_width[i] * pps->row_height[j]; ++ pps->tile_size[j * pps->num_tile_columns + i] = size; ++ pps->tile_pos_ts[j * pps->num_tile_columns + i] = ts; ++ ts += size; ++ } ++ } ++ ++ return 0; ++} ++ ++int ff_hevc_rpi_decode_nal_pps(GetBitContext * const gb, AVCodecContext * const avctx, ++ HEVCRpiParamSets * const ps) ++{ ++ const HEVCRpiSPS *sps = NULL; ++ int i, ret = 0; ++ unsigned int pps_id = 0; ++ ptrdiff_t nal_size; ++ unsigned log2_parallel_merge_level_minus2; ++ ++ AVBufferRef *pps_buf; ++ HEVCRpiPPS *pps = av_mallocz(sizeof(*pps)); ++ ++ if (!pps) ++ return AVERROR(ENOMEM); ++ ++ pps_buf = av_buffer_create((uint8_t *)pps, sizeof(*pps), ++ hevc_pps_free, NULL, 0); ++ if (!pps_buf) { ++ av_freep(&pps); ++ return AVERROR(ENOMEM); ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "Decoding PPS\n"); ++ ++ nal_size = gb->buffer_end - gb->buffer; ++ if (nal_size > sizeof(pps->data)) { ++ av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized PPS " ++ "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n", ++ nal_size, sizeof(pps->data)); ++ pps->data_size = sizeof(pps->data); ++ } else { ++ pps->data_size = nal_size; ++ } ++ memcpy(pps->data, gb->buffer, pps->data_size); ++ ++ // Default values ++ pps->loop_filter_across_tiles_enabled_flag = 1; ++ pps->num_tile_columns = 1; ++ pps->num_tile_rows = 1; ++ pps->uniform_spacing_flag = 1; ++ pps->disable_dbf = 0; ++ pps->beta_offset = 0; ++ pps->tc_offset = 0; ++ pps->log2_max_transform_skip_block_size = 2; ++ ++ // Coded parameters ++ pps_id = get_ue_golomb_long(gb); ++ if (pps_id >= HEVC_MAX_PPS_COUNT) { ++ av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->sps_id = get_ue_golomb_long(gb); ++ if (pps->sps_id >= HEVC_MAX_SPS_COUNT) { ++ av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", pps->sps_id); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ if (!ps->sps_list[pps->sps_id]) { ++ av_log(avctx, AV_LOG_ERROR, "SPS %u does not exist.\n", pps->sps_id); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ sps = (HEVCRpiSPS *)ps->sps_list[pps->sps_id]->data; ++ ++ pps->dependent_slice_segments_enabled_flag = get_bits1(gb); ++ pps->output_flag_present_flag = get_bits1(gb); ++ pps->num_extra_slice_header_bits = get_bits(gb, 3); ++ ++ pps->sign_data_hiding_flag = get_bits1(gb); ++ ++ pps->cabac_init_present_flag = get_bits1(gb); ++ ++ pps->num_ref_idx_l0_default_active = get_ue_golomb_long(gb) + 1; ++ if (pps->num_ref_idx_l0_default_active < 1 || pps->num_ref_idx_l0_default_active > 15) { ++ av_log(avctx, AV_LOG_ERROR, "pps->num_ref_idx_l0_default_active invalid\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->num_ref_idx_l1_default_active = get_ue_golomb_long(gb) + 1; ++ if (pps->num_ref_idx_l1_default_active < 1 || pps->num_ref_idx_l1_default_active > 15) { ++ av_log(avctx, AV_LOG_ERROR, "pps->num_ref_idx_l1_default_active invalid\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ ++ pps->pic_init_qp_minus26 = get_se_golomb(gb); ++ if (pps->pic_init_qp_minus26 > 25 || pps->pic_init_qp_minus26 < -(26 + sps->qp_bd_offset)) { ++ av_log(avctx, AV_LOG_ERROR, ++ "init_qp_minus26 %d is outside the valid range " ++ "[%d, %d].\n", ++ pps->pic_init_qp_minus26, ++ -(26 + sps->qp_bd_offset), 25); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ ++ pps->constrained_intra_pred_flag = get_bits1(gb); ++ pps->transform_skip_enabled_flag = get_bits1(gb); ++ ++ pps->cu_qp_delta_enabled_flag = get_bits1(gb); ++ pps->log2_min_cu_qp_delta_size = sps->log2_ctb_size; ++ if (pps->cu_qp_delta_enabled_flag) ++ { ++ const unsigned int diff_cu_qp_delta_depth = get_ue_golomb_long(gb); ++ ++ if (diff_cu_qp_delta_depth > sps->log2_diff_max_min_coding_block_size) { ++ av_log(avctx, AV_LOG_ERROR, "diff_cu_qp_delta_depth %d is invalid\n", ++ diff_cu_qp_delta_depth); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ ++ pps->log2_min_cu_qp_delta_size = sps->log2_ctb_size - diff_cu_qp_delta_depth; ++ } ++ ++ pps->cb_qp_offset = get_se_golomb(gb); ++ if (pps->cb_qp_offset < -12 || pps->cb_qp_offset > 12) { ++ av_log(avctx, AV_LOG_ERROR, "pps_cb_qp_offset out of range: %d\n", ++ pps->cb_qp_offset); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->cr_qp_offset = get_se_golomb(gb); ++ if (pps->cr_qp_offset < -12 || pps->cr_qp_offset > 12) { ++ av_log(avctx, AV_LOG_ERROR, "pps_cr_qp_offset out of range: %d\n", ++ pps->cr_qp_offset); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->pic_slice_level_chroma_qp_offsets_present_flag = get_bits1(gb); ++ ++ pps->weighted_pred_flag = get_bits1(gb); ++ pps->weighted_bipred_flag = get_bits1(gb); ++ ++ pps->transquant_bypass_enable_flag = get_bits1(gb); ++ pps->tiles_enabled_flag = get_bits1(gb); ++ pps->entropy_coding_sync_enabled_flag = get_bits1(gb); ++ ++ if (pps->tiles_enabled_flag) { ++ pps->num_tile_columns = get_ue_golomb_long(gb) + 1; ++ pps->num_tile_rows = get_ue_golomb_long(gb) + 1; ++ if (pps->num_tile_columns <= 0 || ++ pps->num_tile_columns >= sps->width) { ++ av_log(avctx, AV_LOG_ERROR, "num_tile_columns_minus1 out of range: %d\n", ++ pps->num_tile_columns - 1); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ if (pps->num_tile_rows <= 0 || ++ pps->num_tile_rows >= sps->height) { ++ av_log(avctx, AV_LOG_ERROR, "num_tile_rows_minus1 out of range: %d\n", ++ pps->num_tile_rows - 1); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ ++ pps->column_width = av_malloc_array(pps->num_tile_columns, sizeof(*pps->column_width)); ++ pps->row_height = av_malloc_array(pps->num_tile_rows, sizeof(*pps->row_height)); ++ if (!pps->column_width || !pps->row_height) { ++ ret = AVERROR(ENOMEM); ++ goto err; ++ } ++ ++ pps->uniform_spacing_flag = get_bits1(gb); ++ if (!pps->uniform_spacing_flag) { ++ uint64_t sum = 0; ++ for (i = 0; i < pps->num_tile_columns - 1; i++) { ++ pps->column_width[i] = get_ue_golomb_long(gb) + 1; ++ sum += pps->column_width[i]; ++ } ++ if (sum >= sps->ctb_width) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid tile widths.\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->column_width[pps->num_tile_columns - 1] = sps->ctb_width - sum; ++ ++ sum = 0; ++ for (i = 0; i < pps->num_tile_rows - 1; i++) { ++ pps->row_height[i] = get_ue_golomb_long(gb) + 1; ++ sum += pps->row_height[i]; ++ } ++ if (sum >= sps->ctb_height) { ++ av_log(avctx, AV_LOG_ERROR, "Invalid tile heights.\n"); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->row_height[pps->num_tile_rows - 1] = sps->ctb_height - sum; ++ } ++ pps->loop_filter_across_tiles_enabled_flag = get_bits1(gb); ++ } ++ ++ pps->seq_loop_filter_across_slices_enabled_flag = get_bits1(gb); ++ ++ pps->deblocking_filter_control_present_flag = get_bits1(gb); ++ if (pps->deblocking_filter_control_present_flag) { ++ pps->deblocking_filter_override_enabled_flag = get_bits1(gb); ++ pps->disable_dbf = get_bits1(gb); ++ if (!pps->disable_dbf) { ++ int beta_offset_div2 = get_se_golomb(gb); ++ int tc_offset_div2 = get_se_golomb(gb) ; ++ if (beta_offset_div2 < -6 || beta_offset_div2 > 6) { ++ av_log(avctx, AV_LOG_ERROR, "pps_beta_offset_div2 out of range: %d\n", ++ beta_offset_div2); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ if (tc_offset_div2 < -6 || tc_offset_div2 > 6) { ++ av_log(avctx, AV_LOG_ERROR, "pps_tc_offset_div2 out of range: %d\n", ++ tc_offset_div2); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->beta_offset = 2 * beta_offset_div2; ++ pps->tc_offset = 2 * tc_offset_div2; ++ } ++ } ++ ++ pps->scaling_list_data_present_flag = get_bits1(gb); ++ if (pps->scaling_list_data_present_flag) { ++ set_default_scaling_list_data(&pps->scaling_list); ++ ret = scaling_list_data(gb, avctx, &pps->scaling_list, sps); ++ if (ret < 0) ++ goto err; ++ } ++ pps->lists_modification_present_flag = get_bits1(gb); ++ log2_parallel_merge_level_minus2 = get_ue_golomb_long(gb); ++ if (log2_parallel_merge_level_minus2 > sps->log2_ctb_size) { ++ av_log(avctx, AV_LOG_ERROR, "log2_parallel_merge_level_minus2 out of range: %d\n", ++ log2_parallel_merge_level_minus2); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ pps->log2_parallel_merge_level = log2_parallel_merge_level_minus2 + 2; ++ ++ pps->slice_header_extension_present_flag = get_bits1(gb); ++ ++ if (get_bits1(gb)) { // pps_extension_present_flag ++ int pps_range_extensions_flag = get_bits1(gb); ++ skip_bits(gb, 7); // pps_extension_7bits ++ if (sps->ptl.general_ptl.profile_idc == FF_PROFILE_HEVC_REXT && pps_range_extensions_flag) { ++ if ((ret = pps_range_extensions(gb, avctx, pps, sps)) < 0) ++ goto err; ++ } ++ } ++ ++ ret = setup_pps(avctx, pps, sps); ++ if (ret < 0) ++ goto err; ++ ++ if (get_bits_left(gb) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Overread PPS by %d bits\n", -get_bits_left(gb)); ++ ret = AVERROR_INVALIDDATA; ++ goto err; ++ } ++ ++ remove_pps(ps, pps_id); ++ ps->pps_list[pps_id] = pps_buf; ++ ++ return 0; ++ ++err: ++ av_buffer_unref(&pps_buf); ++ return ret; ++} ++ ++int ff_hevc_rpi_compute_poc(const HEVCRpiSPS *sps, int pocTid0, int poc_lsb, int nal_unit_type) ++{ ++ int max_poc_lsb = 1 << sps->log2_max_poc_lsb; ++ int prev_poc_lsb = pocTid0 % max_poc_lsb; ++ int prev_poc_msb = pocTid0 - prev_poc_lsb; ++ int poc_msb; ++ ++ if (poc_lsb < prev_poc_lsb && prev_poc_lsb - poc_lsb >= max_poc_lsb / 2) ++ poc_msb = prev_poc_msb + max_poc_lsb; ++ else if (poc_lsb > prev_poc_lsb && poc_lsb - prev_poc_lsb > max_poc_lsb / 2) ++ poc_msb = prev_poc_msb - max_poc_lsb; ++ else ++ poc_msb = prev_poc_msb; ++ ++ // For BLA picture types, POCmsb is set to 0. ++ if (nal_unit_type == HEVC_NAL_BLA_W_LP || ++ nal_unit_type == HEVC_NAL_BLA_W_RADL || ++ nal_unit_type == HEVC_NAL_BLA_N_LP) ++ poc_msb = 0; ++ ++ return poc_msb + poc_lsb; ++} +diff --git a/libavcodec/rpi_hevc_ps.h b/libavcodec/rpi_hevc_ps.h +new file mode 100644 +index 0000000000..c725ebb9ca +--- /dev/null ++++ b/libavcodec/rpi_hevc_ps.h +@@ -0,0 +1,449 @@ ++/* ++ * HEVC parameter set parsing ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVC_PS_H ++#define AVCODEC_RPI_HEVC_PS_H ++ ++#include ++ ++#include "libavutil/buffer.h" ++#include "libavutil/pixfmt.h" ++#include "libavutil/rational.h" ++ ++#include "avcodec.h" ++#include "get_bits.h" ++#include "hevc.h" ++ ++typedef struct ShortTermRPS { ++ unsigned int num_negative_pics; ++ int num_delta_pocs; ++ int rps_idx_num_delta_pocs; ++ int32_t delta_poc[32]; ++ uint8_t used[32]; ++} ShortTermRPS; ++ ++typedef struct LongTermRPS { ++ int poc[32]; ++ uint8_t used[32]; ++ uint8_t nb_refs; ++} LongTermRPS; ++ ++typedef struct RpiSliceHeader { ++ unsigned int pps_id; ++ ++ ///< address (in raster order) of the first block in the current slice segment ++ unsigned int slice_segment_addr; ++ ///< address (in raster order) of the first block in the current slice ++ unsigned int slice_addr; ++ ++ enum HEVCSliceType slice_type; ++ ++ int pic_order_cnt_lsb; ++ ++ uint8_t first_slice_in_pic_flag; ++ uint8_t dependent_slice_segment_flag; ++ uint8_t pic_output_flag; ++ uint8_t colour_plane_id; ++ ++ ///< RPS coded in the slice header itself is stored here ++ int short_term_ref_pic_set_sps_flag; ++ int short_term_ref_pic_set_size; ++ ShortTermRPS slice_rps; ++ const ShortTermRPS *short_term_rps; ++ int long_term_ref_pic_set_size; ++ LongTermRPS long_term_rps; ++ unsigned int list_entry_lx[2][32]; ++ ++ uint8_t rpl_modification_flag[2]; ++ uint8_t no_output_of_prior_pics_flag; ++ uint8_t slice_temporal_mvp_enabled_flag; ++ ++ unsigned int nb_refs[2]; ++ ++ uint8_t slice_sample_adaptive_offset_flag[3]; ++ uint8_t mvd_l1_zero_flag; ++ ++ uint8_t cabac_init_flag; ++ uint8_t disable_deblocking_filter_flag; ///< slice_header_disable_deblocking_filter_flag ++ uint8_t slice_loop_filter_across_slices_enabled_flag; ++ uint8_t collocated_list; ++ ++ uint8_t no_dblk_boundary_flags; ++ ++ unsigned int collocated_ref_idx; ++ ++ int slice_qp_delta; ++ int slice_cb_qp_offset; // -12, +12 ++ int slice_cr_qp_offset; // -12, +12 ++ ++ uint8_t cu_chroma_qp_offset_enabled_flag; ++ ++ int beta_offset; ///< beta_offset_div2 * 2 ++ int tc_offset; ///< tc_offset_div2 * 2 ++ ++ unsigned int max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand ++ ++ unsigned *entry_point_offset; ++ int * offset; ++ int * size; ++ int num_entry_point_offsets; ++ int offsets_allocated; ++ ++ uint8_t offload_wpp; ++ uint8_t offload_tiles; ++ ++ int8_t slice_qp; ++ ++ uint8_t luma_log2_weight_denom; ++ uint8_t chroma_log2_weight_denom; ++ ++ int16_t luma_weight_l0[16]; // -128, +255 ++ int16_t luma_offset_l0[16]; ++ int16_t chroma_weight_l0[16][2]; ++ int16_t chroma_offset_l0[16][2]; ++ ++ int16_t luma_weight_l1[16]; ++ int16_t luma_offset_l1[16]; ++ int16_t chroma_weight_l1[16][2]; ++ int16_t chroma_offset_l1[16][2]; ++ ++} RpiSliceHeader; ++ ++typedef struct HEVCRpiWindow { ++ uint16_t left_offset; ++ uint16_t right_offset; ++ uint16_t top_offset; ++ uint16_t bottom_offset; ++} HEVCRpiWindow; ++ ++typedef struct VUI { ++ AVRational sar; ++ ++ int overscan_info_present_flag; ++ int overscan_appropriate_flag; ++ ++ int video_signal_type_present_flag; ++ int video_format; ++ int video_full_range_flag; ++ int colour_description_present_flag; ++ uint8_t colour_primaries; ++ uint8_t transfer_characteristic; ++ uint8_t matrix_coeffs; ++ ++ int chroma_loc_info_present_flag; ++ int chroma_sample_loc_type_top_field; ++ int chroma_sample_loc_type_bottom_field; ++ int neutra_chroma_indication_flag; ++ ++ int field_seq_flag; ++ int frame_field_info_present_flag; ++ ++ int default_display_window_flag; ++ HEVCRpiWindow def_disp_win; ++ ++ int vui_timing_info_present_flag; ++ uint32_t vui_num_units_in_tick; ++ uint32_t vui_time_scale; ++ int vui_poc_proportional_to_timing_flag; ++ int vui_num_ticks_poc_diff_one_minus1; ++ int vui_hrd_parameters_present_flag; ++ ++ int bitstream_restriction_flag; ++ int tiles_fixed_structure_flag; ++ int motion_vectors_over_pic_boundaries_flag; ++ int restricted_ref_pic_lists_flag; ++ int min_spatial_segmentation_idc; ++ int max_bytes_per_pic_denom; ++ int max_bits_per_min_cu_denom; ++ int log2_max_mv_length_horizontal; ++ int log2_max_mv_length_vertical; ++} VUI; ++ ++typedef struct PTLCommon { ++ uint8_t profile_space; ++ uint8_t tier_flag; ++ uint8_t profile_idc; ++ uint8_t profile_compatibility_flag[32]; ++ uint8_t level_idc; ++ uint8_t progressive_source_flag; ++ uint8_t interlaced_source_flag; ++ uint8_t non_packed_constraint_flag; ++ uint8_t frame_only_constraint_flag; ++} PTLCommon; ++ ++typedef struct PTL { ++ PTLCommon general_ptl; ++ PTLCommon sub_layer_ptl[HEVC_MAX_SUB_LAYERS]; ++ ++ uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; ++ uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; ++} PTL; ++ ++typedef struct HEVCRpiVPS { ++ uint8_t vps_temporal_id_nesting_flag; ++ int vps_max_layers; ++ int vps_max_sub_layers; ///< vps_max_temporal_layers_minus1 + 1 ++ ++ PTL ptl; ++ int vps_sub_layer_ordering_info_present_flag; ++ unsigned int vps_max_dec_pic_buffering[HEVC_MAX_SUB_LAYERS]; ++ unsigned int vps_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; ++ unsigned int vps_max_latency_increase[HEVC_MAX_SUB_LAYERS]; ++ int vps_max_layer_id; ++ int vps_num_layer_sets; ///< vps_num_layer_sets_minus1 + 1 ++ uint8_t vps_timing_info_present_flag; ++ uint32_t vps_num_units_in_tick; ++ uint32_t vps_time_scale; ++ uint8_t vps_poc_proportional_to_timing_flag; ++ int vps_num_ticks_poc_diff_one; ///< vps_num_ticks_poc_diff_one_minus1 + 1 ++ int vps_num_hrd_parameters; ++ ++ uint8_t data[4096]; ++ int data_size; ++} HEVCRpiVPS; ++ ++typedef struct ScalingList { ++ /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, ++ * and size ID 3 only has 2 arrays, not 6. */ ++ uint8_t sl[4][6][64]; ++ uint8_t sl_dc[2][6]; ++} ScalingList; ++ ++typedef struct HEVCRpiSPS { ++ unsigned vps_id; ++ uint8_t chroma_format_idc; ++ uint8_t separate_colour_plane_flag; ++ ++ HEVCRpiWindow output_window; ++ ++ HEVCRpiWindow pic_conf_win; ++ ++ uint16_t wp_offset_half_range; // WpOffsetHalfRange ++ ++ uint8_t bit_depth; ++ ++// int bit_depth_chroma; // We only support lum_bit_depth = chroma_bit_depth ++ uint8_t pixel_shift; ++ enum AVPixelFormat pix_fmt; ++ ++ unsigned int log2_max_poc_lsb; ++ ++ int max_sub_layers; ++ struct { ++ int max_dec_pic_buffering; ++ int num_reorder_pics; ++ int max_latency_increase; ++ } temporal_layer[HEVC_MAX_SUB_LAYERS]; ++ uint8_t temporal_id_nesting_flag; ++ ++ uint8_t scaling_list_enable_flag; ++ ScalingList scaling_list; ++ ++ unsigned int nb_st_rps; ++ ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; ++ ++ uint8_t amp_enabled_flag; ++ uint8_t sao_enabled; ++ ++ uint8_t long_term_ref_pics_present_flag; ++ uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; ++ uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; ++ uint8_t num_long_term_ref_pics_sps; ++ ++ struct { ++ uint8_t bit_depth; ++ uint8_t bit_depth_chroma; ++ uint8_t log2_min_pcm_cb_size; ++ uint8_t log2_max_pcm_cb_size; ++ uint8_t loop_filter_disable_flag; ++ } pcm; ++ char sps_temporal_mvp_enabled_flag; ++// char sps_strong_intra_smoothing_enable_flag; -> intra_filtes_disable ++ ++ uint8_t log2_min_cb_size; // 3..6 ++ uint8_t log2_diff_max_min_coding_block_size; ++ uint8_t log2_min_tb_size; // 2..5 ++ uint8_t log2_max_trafo_size; ++ uint8_t log2_ctb_size; // 4..6 ++// unsigned int log2_min_pu_size; // 2..5 (min_cb_size - 1) ++#define LOG2_MIN_PU_SIZE 2 ++#define LOG2_MIN_CU_SIZE 3 ++ ++ uint8_t max_transform_hierarchy_depth_inter; ++ uint8_t max_transform_hierarchy_depth_intra; ++ ++ char transform_skip_rotation_enabled_flag; ++ char transform_skip_context_enabled_flag; ++ char implicit_rdpcm_enabled_flag; ++ char explicit_rdpcm_enabled_flag; ++// char intra_smoothing_disabled_flag; -> intra_filtes_disable ++ char high_precision_offsets_enabled_flag; ++ char persistent_rice_adaptation_enabled_flag; ++ ++ uint8_t intra_filters_disable; ++ ++ ///< coded frame dimension in various units ++ int width; ++ int height; ++ int ctb_width; ++ int ctb_height; ++ int ctb_size; // Pic size in CTBs not size of a CTB ++ int min_cb_width; ++ int min_cb_height; ++ int min_tb_width; ++ int min_tb_height; ++ int min_pu_width; ++ int min_pu_height; ++ int pcm_width; ++ int pcm_height; ++ int tb_mask; ++ ++ int hshift[3]; ++ int vshift[3]; ++ ++ int qp_bd_offset; ++ ++ uint8_t data[4096]; ++ int data_size; ++ ++ VUI vui; ++ PTL ptl; ++} HEVCRpiSPS; ++ ++#define CTB_TS_FLAGS_SOTL (1U << 0) // X start of tile line ++#define CTB_TS_FLAGS_EOTL (1U << 1) // Last CTB of a tile line ++#define CTB_TS_FLAGS_EOL (1U << 2) // Last CTB of a complete line ++#define CTB_TS_FLAGS_EOT (1U << 3) // Last CTB of a tile ++#define CTB_TS_FLAGS_CSAVE (1U << 4) ++#define CTB_TS_FLAGS_CIREQ (1U << 5) // Cabac init request ++#define CTB_TS_FLAGS_TOT (1U << 6) // CTB on top row of a tile ++#define CTB_TS_FLAGS_CLOAD (1U << 7) ++ ++typedef struct HEVCRpiPPS { ++ unsigned int sps_id; ///< seq_parameter_set_id ++ ++ uint8_t sign_data_hiding_flag; ++ ++ uint8_t cabac_init_present_flag; ++ ++ int num_ref_idx_l0_default_active; ///< num_ref_idx_l0_default_active_minus1 + 1 ++ int num_ref_idx_l1_default_active; ///< num_ref_idx_l1_default_active_minus1 + 1 ++ int pic_init_qp_minus26; ++ ++ uint8_t constrained_intra_pred_flag; ++ uint8_t transform_skip_enabled_flag; ++ ++ uint8_t cu_qp_delta_enabled_flag; ++ uint8_t log2_min_cu_qp_delta_size; ++ int cb_qp_offset; // -12..12 ++ int cr_qp_offset; // -12..12 ++ const uint8_t * qp_dblk_x[3]; ++ const int8_t * qp_bd_x[3]; ++ ++ uint8_t pic_slice_level_chroma_qp_offsets_present_flag; ++ uint8_t weighted_pred_flag; ++ uint8_t weighted_bipred_flag; ++ uint8_t output_flag_present_flag; ++ uint8_t transquant_bypass_enable_flag; ++ ++ uint8_t dependent_slice_segments_enabled_flag; ++ uint8_t tiles_enabled_flag; ++ uint8_t entropy_coding_sync_enabled_flag; ++ ++ uint8_t tile_wpp_inter_disable; ++ int num_tile_columns; ///< num_tile_columns_minus1 + 1 ++ int num_tile_rows; ///< num_tile_rows_minus1 + 1 ++ uint8_t uniform_spacing_flag; ++ uint8_t loop_filter_across_tiles_enabled_flag; ++ ++ uint8_t seq_loop_filter_across_slices_enabled_flag; ++ ++ uint8_t deblocking_filter_control_present_flag; ++ uint8_t deblocking_filter_override_enabled_flag; ++ uint8_t disable_dbf; ++ int beta_offset; ///< beta_offset_div2 * 2 ++ int tc_offset; ///< tc_offset_div2 * 2 ++ ++ uint8_t scaling_list_data_present_flag; ++ ScalingList scaling_list; ++ ++ uint8_t lists_modification_present_flag; ++ int log2_parallel_merge_level; ///< log2_parallel_merge_level_minus2 + 2 ++ int num_extra_slice_header_bits; ++ uint8_t slice_header_extension_present_flag; ++ uint8_t log2_max_transform_skip_block_size; ++ uint8_t cross_component_prediction_enabled_flag; ++ uint8_t chroma_qp_offset_list_enabled_flag; ++ uint8_t diff_cu_chroma_qp_offset_depth; ++ uint8_t chroma_qp_offset_list_len_minus1; ++ int8_t cb_qp_offset_list[6]; ++ int8_t cr_qp_offset_list[6]; ++ uint8_t log2_sao_offset_scale_luma; ++ uint8_t log2_sao_offset_scale_chroma; ++ ++ // Inferred parameters ++ uint16_t *column_width; ///< ColumnWidth ++ uint16_t *row_height; ///< RowHeight ++ uint16_t *col_bd; ///< ColBd ++ uint16_t *row_bd; ///< RowBd ++ uint16_t *col_idxX; ++ ++ // We can limit these to uint16_t given our other size limits ++ uint16_t *ctb_addr_rs_to_ts; ///< CtbAddrRSToTS ++ uint16_t *ctb_addr_ts_to_rs; ///< CtbAddrTSToRS ++ uint16_t *tile_id; ///< TileId ++ uint16_t *tile_pos_ts; ///< TilePosRS ++ uint16_t *tile_size; ///< TileSize ++ uint8_t * ctb_ts_flags; ++ ++ uint8_t data[4096]; ++ int data_size; ++} HEVCRpiPPS; ++ ++typedef struct HEVCRpiParamSets { ++ /* currently active parameter sets */ ++ const HEVCRpiVPS *vps; ++ const HEVCRpiSPS *sps; ++ const HEVCRpiPPS *pps; ++ ++ AVBufferRef *vps_list[HEVC_MAX_VPS_COUNT]; ++ AVBufferRef *sps_list[HEVC_MAX_SPS_COUNT]; ++ AVBufferRef *pps_list[HEVC_MAX_PPS_COUNT]; ++} HEVCRpiParamSets; ++ ++int ff_hevc_rpi_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, ++ HEVCRpiParamSets *ps); ++int ff_hevc_rpi_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, ++ HEVCRpiParamSets *ps, int apply_defdispwin); ++int ff_hevc_rpi_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, ++ HEVCRpiParamSets *ps); ++ ++int ff_hevc_rpi_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, ++ ShortTermRPS *rps, const HEVCRpiSPS *sps, int is_slice_header); ++ ++int ff_hevc_rpi_encode_nal_vps(HEVCRpiVPS *vps, unsigned int id, ++ uint8_t *buf, int buf_size); ++ ++/** ++ * Compute POC of the current frame and return it. ++ */ ++int ff_hevc_rpi_compute_poc(const HEVCRpiSPS *sps, int pocTid0, int poc_lsb, int nal_unit_type); ++ ++#endif /* AVCODEC_RPI_HEVC_PS_H */ +diff --git a/libavcodec/rpi_hevc_refs.c b/libavcodec/rpi_hevc_refs.c +new file mode 100644 +index 0000000000..8cc5796cf0 +--- /dev/null ++++ b/libavcodec/rpi_hevc_refs.c +@@ -0,0 +1,485 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/avassert.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/rpi_sand_fns.h" ++#include "internal.h" ++#include "thread.h" ++#include "hevc.h" ++#include "rpi_hevcdec.h" ++ ++void ff_hevc_rpi_unref_frame(HEVCRpiContext *s, HEVCRpiFrame *frame, int flags) ++{ ++ /* frame->frame can be NULL if context init failed */ ++ if (!frame->frame || !frame->frame->buf[0]) ++ return; ++ ++ frame->flags &= ~flags; ++ if (!frame->flags) { ++ ff_thread_release_buffer(s->avctx, &frame->tf); ++ ++ av_buffer_unref(&frame->col_mvf_buf); // OK if already NULL ++ frame->col_mvf = NULL; ++ ++ frame->collocated_ref = NULL; ++ } ++} ++ ++void ff_hevc_rpi_clear_refs(HEVCRpiContext *s) ++{ ++ int i; ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) ++ ff_hevc_rpi_unref_frame(s, &s->DPB[i], ++ HEVC_FRAME_FLAG_SHORT_REF | ++ HEVC_FRAME_FLAG_LONG_REF); ++} ++ ++void ff_hevc_rpi_flush_dpb(HEVCRpiContext *s) ++{ ++ int i; ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) ++ ff_hevc_rpi_unref_frame(s, &s->DPB[i], ~0); ++} ++ ++static HEVCRpiFrame *alloc_frame(HEVCRpiContext * const s) ++{ ++ int i, ret; ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame * const frame = &s->DPB[i]; ++ if (frame->frame->buf[0]) ++ continue; ++ ++ ret = ff_thread_get_buffer(s->avctx, &frame->tf, ++ AV_GET_BUFFER_FLAG_REF); ++ if (ret < 0) ++ return NULL; ++ ++ frame->col_mvf = NULL; ++ frame->col_mvf_buf = NULL; ++ if (s->used_for_ref && !s->is_irap) ++ { ++ frame->col_mvf_buf = av_buffer_pool_get(s->col_mvf_pool); ++ if (!frame->col_mvf_buf) ++ goto fail; ++ frame->col_mvf = (ColMvField *)frame->col_mvf_buf->data; ++ } ++ ++ frame->frame->top_field_first = s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD; ++ frame->frame->interlaced_frame = (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) || (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD); ++ ++ return frame; ++ ++fail: ++ ff_hevc_rpi_unref_frame(s, frame, ~0); ++ return NULL; ++ } ++ av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n"); ++ return NULL; ++} ++ ++int ff_hevc_rpi_set_new_ref(HEVCRpiContext *s, AVFrame **frame, int poc) ++{ ++ HEVCRpiFrame *ref; ++ int i; ++ ++ /* check that this POC doesn't already exist */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ ++ if (frame->frame->buf[0] && frame->sequence == s->seq_decode && ++ frame->poc == poc) { ++ av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", ++ poc); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ ref = alloc_frame(s); ++ if (!ref) ++ return AVERROR(ENOMEM); ++ ++ *frame = ref->frame; ++ s->ref = ref; ++ ++ if (s->sh.pic_output_flag) ++ ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF; ++ else ++ ref->flags = HEVC_FRAME_FLAG_SHORT_REF; ++ ++ ref->poc = poc; ++ ref->sequence = s->seq_decode; ++ ref->frame->crop_left = s->ps.sps->output_window.left_offset; ++ ref->frame->crop_right = s->ps.sps->output_window.right_offset; ++ ref->frame->crop_top = s->ps.sps->output_window.top_offset; ++ ref->frame->crop_bottom = s->ps.sps->output_window.bottom_offset; ++ ++ return 0; ++} ++ ++int ff_hevc_rpi_output_frame(HEVCRpiContext *s, AVFrame *out, int flush) ++{ ++ do { ++ int nb_output = 0; ++ int min_poc = INT_MAX; ++ int i, min_idx, ret; ++ ++ if (s->sh.no_output_of_prior_pics_flag == 1 && s->no_rasl_output_flag == 1) { ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ if (!(frame->flags & HEVC_FRAME_FLAG_BUMPING) && frame->poc != s->poc && ++ frame->sequence == s->seq_output) { ++ ff_hevc_rpi_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); ++ } ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) && ++ frame->sequence == s->seq_output) { ++ nb_output++; ++ if (frame->poc < min_poc || nb_output == 1) { ++ min_poc = frame->poc; ++ min_idx = i; ++ } ++ } ++ } ++ ++ /* wait for more frames before output */ ++ if (!flush && s->seq_output == s->seq_decode && s->ps.sps && ++ nb_output <= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].num_reorder_pics) ++ return 0; ++ ++ if (nb_output) { ++ HEVCRpiFrame *frame = &s->DPB[min_idx]; ++ if (frame->frame->format == AV_PIX_FMT_VIDEOTOOLBOX && frame->frame->buf[0]->size == 1) ++ return 0; ++ ++ ret = av_frame_ref(out, frame->frame); ++ if (frame->flags & HEVC_FRAME_FLAG_BUMPING) ++ ff_hevc_rpi_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING); ++ else ++ ff_hevc_rpi_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT); ++ if (ret < 0) ++ return ret; ++ av_log(s->avctx, AV_LOG_DEBUG, ++ "Output frame with POC %d.\n", frame->poc); ++ return 1; ++ } ++ ++ if (s->seq_output != s->seq_decode) ++ s->seq_output = (s->seq_output + 1) & 0xff; ++ else ++ break; ++ } while (1); ++ ++ return 0; ++} ++ ++void ff_hevc_rpi_bump_frame(HEVCRpiContext *s) ++{ ++ int dpb = 0; ++ int min_poc = INT_MAX; ++ int i; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ if ((frame->flags) && ++ frame->sequence == s->seq_output && ++ frame->poc != s->poc) { ++ dpb++; ++ } ++ } ++ ++ if (s->ps.sps && dpb >= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].max_dec_pic_buffering) { ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ if ((frame->flags) && ++ frame->sequence == s->seq_output && ++ frame->poc != s->poc) { ++ if (frame->flags == HEVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) { ++ min_poc = frame->poc; ++ } ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ if (frame->flags & HEVC_FRAME_FLAG_OUTPUT && ++ frame->sequence == s->seq_output && ++ frame->poc <= min_poc) { ++ frame->flags |= HEVC_FRAME_FLAG_BUMPING; ++ } ++ } ++ ++ dpb--; ++ } ++} ++ ++static int init_slice_rpl(HEVCRpiContext *s) ++{ ++ if (s->slice_idx >= s->rpl_tab_size) ++ return AVERROR_INVALIDDATA; ++ ++ s->refPicList = s->rpl_tab[s->slice_idx].refPicList + 0; ++ return 0; ++} ++ ++int ff_hevc_rpi_slice_rpl(HEVCRpiContext *s) ++{ ++ RpiSliceHeader *sh = &s->sh; ++ ++ uint8_t nb_list = sh->slice_type == HEVC_SLICE_B ? 2 : 1; ++ uint8_t list_idx; ++ int i, j, ret; ++ ++ ret = init_slice_rpl(s); ++ if (ret < 0) ++ return ret; ++ ++ if (!(s->rps[ST_CURR_BEF].nb_refs + s->rps[ST_CURR_AFT].nb_refs + ++ s->rps[LT_CURR].nb_refs)) { ++ av_log(s->avctx, AV_LOG_ERROR, "Zero refs in the frame RPS.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ for (list_idx = 0; list_idx < nb_list; list_idx++) { ++ RefPicList rpl_tmp = { { 0 } }; ++ RefPicList *rpl = &s->refPicList[list_idx]; ++ ++ /* The order of the elements is ++ * ST_CURR_BEF - ST_CURR_AFT - LT_CURR for the L0 and ++ * ST_CURR_AFT - ST_CURR_BEF - LT_CURR for the L1 */ ++ int cand_lists[3] = { list_idx ? ST_CURR_AFT : ST_CURR_BEF, ++ list_idx ? ST_CURR_BEF : ST_CURR_AFT, ++ LT_CURR }; ++ ++ /* concatenate the candidate lists for the current frame */ ++ while (rpl_tmp.nb_refs < sh->nb_refs[list_idx]) { ++ for (i = 0; i < FF_ARRAY_ELEMS(cand_lists); i++) { ++ RefPicList *rps = &s->rps[cand_lists[i]]; ++ for (j = 0; j < rps->nb_refs && rpl_tmp.nb_refs < HEVC_MAX_REFS; j++) { ++ rpl_tmp.list[rpl_tmp.nb_refs] = rps->list[j]; ++ rpl_tmp.ref[rpl_tmp.nb_refs] = rps->ref[j]; ++ rpl_tmp.isLongTerm[rpl_tmp.nb_refs] = i == 2; ++ rpl_tmp.nb_refs++; ++ } ++ } ++ } ++ ++ /* reorder the references if necessary */ ++ if (sh->rpl_modification_flag[list_idx]) { ++ for (i = 0; i < sh->nb_refs[list_idx]; i++) { ++ int idx = sh->list_entry_lx[list_idx][i]; ++ ++ if (idx >= rpl_tmp.nb_refs) { ++ av_log(s->avctx, AV_LOG_ERROR, "Invalid reference index.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ rpl->list[i] = rpl_tmp.list[idx]; ++ rpl->ref[i] = rpl_tmp.ref[idx]; ++ rpl->isLongTerm[i] = rpl_tmp.isLongTerm[idx]; ++ rpl->nb_refs++; ++ } ++ } else { ++ memcpy(rpl, &rpl_tmp, sizeof(*rpl)); ++ rpl->nb_refs = FFMIN(rpl->nb_refs, sh->nb_refs[list_idx]); ++ } ++ ++ if (sh->collocated_list == list_idx && ++ sh->collocated_ref_idx < rpl->nb_refs) ++ s->ref->collocated_ref = rpl->ref[sh->collocated_ref_idx]; ++ } ++ ++ return 0; ++} ++ ++static HEVCRpiFrame *find_ref_idx(HEVCRpiContext *s, int poc) ++{ ++ int i; ++ int LtMask = (1 << s->ps.sps->log2_max_poc_lsb) - 1; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *ref = &s->DPB[i]; ++ if (ref->frame->buf[0] && (ref->sequence == s->seq_decode)) { ++ if ((ref->poc & LtMask) == poc) ++ return ref; ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *ref = &s->DPB[i]; ++ if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { ++ if (ref->poc == poc || (ref->poc & LtMask) == poc) ++ return ref; ++ } ++ } ++ ++ if (s->nal_unit_type != HEVC_NAL_CRA_NUT && !IS_BLA(s)) ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Could not find ref with POC %d\n", poc); ++ return NULL; ++} ++ ++static void mark_ref(HEVCRpiFrame *frame, int flag) ++{ ++ frame->flags &= ~(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF); ++ frame->flags |= flag; ++} ++ ++static HEVCRpiFrame *generate_missing_ref(HEVCRpiContext *s, int poc) ++{ ++ HEVCRpiFrame *frame; ++ int i, x, y; ++ ++ frame = alloc_frame(s); ++ if (!frame) ++ return NULL; ++ ++ if (!s->ps.sps->pixel_shift) { ++ for (i = 0; frame->frame->buf[i]; i++) ++ memset(frame->frame->buf[i]->data, 1 << (s->ps.sps->bit_depth - 1), ++ frame->frame->buf[i]->size); ++ } else { ++ for (i = 0; frame->frame->data[i]; i++) ++ for (y = 0; y < (s->ps.sps->height >> s->ps.sps->vshift[i]); y++) ++ for (x = 0; x < (s->ps.sps->width >> s->ps.sps->hshift[i]); x++) { ++ AV_WN16(frame->frame->data[i] + y * frame_stride1(frame->frame, 1) + 2 * x, ++ 1 << (s->ps.sps->bit_depth - 1)); ++ } ++ } ++ ++ frame->poc = poc; ++ frame->sequence = s->seq_decode; ++ frame->flags = 0; ++ ++ ff_hevc_rpi_progress_set_all_done(frame); ++ ++ return frame; ++} ++ ++/* add a reference with the given poc to the list and mark it as used in DPB */ ++static int add_candidate_ref(HEVCRpiContext *s, RefPicList *list, ++ int poc, int ref_flag) ++{ ++ HEVCRpiFrame *ref = find_ref_idx(s, poc); ++ ++ if (ref == s->ref || list->nb_refs >= HEVC_MAX_REFS) ++ return AVERROR_INVALIDDATA; ++ ++ if (!ref) { ++ ref = generate_missing_ref(s, poc); ++ if (!ref) ++ return AVERROR(ENOMEM); ++ } ++ ++ list->list[list->nb_refs] = ref->poc; ++ list->ref[list->nb_refs] = ref; ++ list->nb_refs++; ++ ++ mark_ref(ref, ref_flag); ++ return 0; ++} ++ ++int ff_hevc_rpi_frame_rps(HEVCRpiContext *s) ++{ ++ const ShortTermRPS *short_rps = s->sh.short_term_rps; ++ const LongTermRPS *long_rps = &s->sh.long_term_rps; ++ RefPicList *rps = s->rps; ++ int i, ret = 0; ++ ++ if (!short_rps) { ++ rps[0].nb_refs = rps[1].nb_refs = 0; ++ return 0; ++ } ++ ++ /* clear the reference flags on all frames except the current one */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ HEVCRpiFrame *frame = &s->DPB[i]; ++ ++ if (frame == s->ref) ++ continue; ++ ++ mark_ref(frame, 0); ++ } ++ ++ for (i = 0; i < NB_RPS_TYPE; i++) ++ rps[i].nb_refs = 0; ++ ++ /* add the short refs */ ++ for (i = 0; i < short_rps->num_delta_pocs; i++) { ++ int poc = s->poc + short_rps->delta_poc[i]; ++ int list; ++ ++ if (!short_rps->used[i]) ++ list = ST_FOLL; ++ else if (i < short_rps->num_negative_pics) ++ list = ST_CURR_BEF; ++ else ++ list = ST_CURR_AFT; ++ ++ ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF); ++ if (ret < 0) ++ goto fail; ++ } ++ ++ /* add the long refs */ ++ for (i = 0; i < long_rps->nb_refs; i++) { ++ int poc = long_rps->poc[i]; ++ int list = long_rps->used[i] ? LT_CURR : LT_FOLL; ++ ++ ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF); ++ if (ret < 0) ++ goto fail; ++ } ++ ++fail: ++ /* release any frames that are now unused */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) ++ ff_hevc_rpi_unref_frame(s, &s->DPB[i], 0); ++ ++ return ret; ++} ++ ++int ff_hevc_rpi_frame_nb_refs(HEVCRpiContext *s) ++{ ++ int ret = 0; ++ int i; ++ const ShortTermRPS *rps = s->sh.short_term_rps; ++ LongTermRPS *long_rps = &s->sh.long_term_rps; ++ ++ if (rps) { ++ for (i = 0; i < rps->num_negative_pics; i++) ++ ret += !!rps->used[i]; ++ for (; i < rps->num_delta_pocs; i++) ++ ret += !!rps->used[i]; ++ } ++ ++ if (long_rps) { ++ for (i = 0; i < long_rps->nb_refs; i++) ++ ret += !!long_rps->used[i]; ++ } ++ return ret; ++} +diff --git a/libavcodec/rpi_hevc_sei.c b/libavcodec/rpi_hevc_sei.c +new file mode 100644 +index 0000000000..cd8149d58e +--- /dev/null ++++ b/libavcodec/rpi_hevc_sei.c +@@ -0,0 +1,368 @@ ++/* ++ * HEVC Supplementary Enhancement Information messages ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2013 Vittorio Giovara ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "golomb.h" ++#include "rpi_hevc_ps.h" ++#include "rpi_hevc_sei.h" ++ ++static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, GetBitContext *gb) ++{ ++ int cIdx, i; ++ uint8_t hash_type; ++ //uint16_t picture_crc; ++ //uint32_t picture_checksum; ++ hash_type = get_bits(gb, 8); ++ ++ for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) { ++ if (hash_type == 0) { ++ s->is_md5 = 1; ++ for (i = 0; i < 16; i++) ++ s->md5[cIdx][i] = get_bits(gb, 8); ++ } else if (hash_type == 1) { ++ // picture_crc = get_bits(gb, 16); ++ skip_bits(gb, 16); ++ } else if (hash_type == 2) { ++ // picture_checksum = get_bits_long(gb, 32); ++ skip_bits(gb, 32); ++ } ++ } ++ return 0; ++} ++ ++static int decode_nal_sei_mastering_display_info(HEVCSEIMasteringDisplay *s, GetBitContext *gb) ++{ ++ int i; ++ // Mastering primaries ++ for (i = 0; i < 3; i++) { ++ s->display_primaries[i][0] = get_bits(gb, 16); ++ s->display_primaries[i][1] = get_bits(gb, 16); ++ } ++ // White point (x, y) ++ s->white_point[0] = get_bits(gb, 16); ++ s->white_point[1] = get_bits(gb, 16); ++ ++ // Max and min luminance of mastering display ++ s->max_luminance = get_bits_long(gb, 32); ++ s->min_luminance = get_bits_long(gb, 32); ++ ++ // As this SEI message comes before the first frame that references it, ++ // initialize the flag to 2 and decrement on IRAP access unit so it ++ // persists for the coded video sequence (e.g., between two IRAPs) ++ s->present = 2; ++ return 0; ++} ++ ++static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, GetBitContext *gb) ++{ ++ // Max and average light levels ++ s->max_content_light_level = get_bits_long(gb, 16); ++ s->max_pic_average_light_level = get_bits_long(gb, 16); ++ // As this SEI message comes before the first frame that references it, ++ // initialize the flag to 2 and decrement on IRAP access unit so it ++ // persists for the coded video sequence (e.g., between two IRAPs) ++ s->present = 2; ++ return 0; ++} ++ ++static int decode_nal_sei_frame_packing_arrangement(HEVCSEIFramePacking *s, GetBitContext *gb) ++{ ++ get_ue_golomb_long(gb); // frame_packing_arrangement_id ++ s->present = !get_bits1(gb); ++ ++ if (s->present) { ++ s->arrangement_type = get_bits(gb, 7); ++ s->quincunx_subsampling = get_bits1(gb); ++ s->content_interpretation_type = get_bits(gb, 6); ++ ++ // spatial_flipping_flag, frame0_flipped_flag, field_views_flag ++ skip_bits(gb, 3); ++ s->current_frame_is_frame0_flag = get_bits1(gb); ++ // frame0_self_contained_flag, frame1_self_contained_flag ++ skip_bits(gb, 2); ++ ++ if (!s->quincunx_subsampling && s->arrangement_type != 5) ++ skip_bits(gb, 16); // frame[01]_grid_position_[xy] ++ skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte ++ skip_bits1(gb); // frame_packing_arrangement_persistence_flag ++ } ++ skip_bits1(gb); // upsampled_aspect_ratio_flag ++ return 0; ++} ++ ++static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetBitContext *gb) ++{ ++ s->present = !get_bits1(gb); ++ ++ if (s->present) { ++ s->hflip = get_bits1(gb); // hor_flip ++ s->vflip = get_bits1(gb); // ver_flip ++ ++ s->anticlockwise_rotation = get_bits(gb, 16); ++ skip_bits1(gb); // display_orientation_persistence_flag ++ } ++ ++ return 0; ++} ++ ++static int decode_nal_sei_pic_timing(HEVCSEIContext *s, GetBitContext *gb, const HEVCRpiParamSets *ps, ++ void *logctx, int size) ++{ ++ HEVCSEIPictureTiming *h = &s->picture_timing; ++ HEVCRpiSPS *sps; ++ ++ if (!ps->sps_list[s->active_seq_parameter_set_id]) ++ return(AVERROR(ENOMEM)); ++ sps = (HEVCRpiSPS*)ps->sps_list[s->active_seq_parameter_set_id]->data; ++ ++ if (sps->vui.frame_field_info_present_flag) { ++ int pic_struct = get_bits(gb, 4); ++ h->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN; ++ if (pic_struct == 2 || pic_struct == 10 || pic_struct == 12) { ++ av_log(logctx, AV_LOG_DEBUG, "BOTTOM Field\n"); ++ h->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; ++ } else if (pic_struct == 1 || pic_struct == 9 || pic_struct == 11) { ++ av_log(logctx, AV_LOG_DEBUG, "TOP Field\n"); ++ h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD; ++ } ++ get_bits(gb, 2); // source_scan_type ++ get_bits(gb, 1); // duplicate_flag ++ skip_bits1(gb); ++ size--; ++ } ++ skip_bits_long(gb, 8 * size); ++ ++ return 0; ++} ++ ++static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetBitContext *gb, ++ int size) ++{ ++ int flag; ++ int user_data_type_code; ++ int cc_count; ++ ++ if (size < 3) ++ return AVERROR(EINVAL); ++ ++ user_data_type_code = get_bits(gb, 8); ++ if (user_data_type_code == 0x3) { ++ skip_bits(gb, 1); // reserved ++ ++ flag = get_bits(gb, 1); // process_cc_data_flag ++ if (flag) { ++ skip_bits(gb, 1); ++ cc_count = get_bits(gb, 5); ++ skip_bits(gb, 8); // reserved ++ size -= 2; ++ ++ if (cc_count && size >= cc_count * 3) { ++ const uint64_t new_size = (s->a53_caption_size + cc_count ++ * UINT64_C(3)); ++ int i, ret; ++ ++ if (new_size > INT_MAX) ++ return AVERROR(EINVAL); ++ ++ /* Allow merging of the cc data from two fields. */ ++ ret = av_reallocp(&s->a53_caption, new_size); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < cc_count; i++) { ++ s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); ++ s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); ++ s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); ++ } ++ skip_bits(gb, 8); // marker_bits ++ } ++ } ++ } else { ++ int i; ++ for (i = 0; i < size - 1; i++) ++ skip_bits(gb, 8); ++ } ++ ++ return 0; ++} ++ ++static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEIContext *s, GetBitContext *gb, ++ int size) ++{ ++ uint32_t country_code; ++ uint32_t user_identifier; ++ ++ if (size < 7) ++ return AVERROR(EINVAL); ++ size -= 7; ++ ++ country_code = get_bits(gb, 8); ++ if (country_code == 0xFF) { ++ skip_bits(gb, 8); ++ size--; ++ } ++ ++ skip_bits(gb, 8); ++ skip_bits(gb, 8); ++ ++ user_identifier = get_bits_long(gb, 32); ++ ++ switch (user_identifier) { ++ case MKBETAG('G', 'A', '9', '4'): ++ return decode_registered_user_data_closed_caption(&s->a53_caption, gb, size); ++ default: ++ skip_bits_long(gb, size * 8); ++ break; ++ } ++ return 0; ++} ++ ++static int decode_nal_sei_active_parameter_sets(HEVCSEIContext *s, GetBitContext *gb, void *logctx) ++{ ++ int num_sps_ids_minus1; ++ int i; ++ unsigned active_seq_parameter_set_id; ++ ++ get_bits(gb, 4); // active_video_parameter_set_id ++ get_bits(gb, 1); // self_contained_cvs_flag ++ get_bits(gb, 1); // num_sps_ids_minus1 ++ num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1 ++ ++ if (num_sps_ids_minus1 < 0 || num_sps_ids_minus1 > 15) { ++ av_log(logctx, AV_LOG_ERROR, "num_sps_ids_minus1 %d invalid\n", num_sps_ids_minus1); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ active_seq_parameter_set_id = get_ue_golomb_long(gb); ++ if (active_seq_parameter_set_id >= HEVC_MAX_SPS_COUNT) { ++ av_log(logctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id); ++ return AVERROR_INVALIDDATA; ++ } ++ s->active_seq_parameter_set_id = active_seq_parameter_set_id; ++ ++ for (i = 1; i <= num_sps_ids_minus1; i++) ++ get_ue_golomb_long(gb); // active_seq_parameter_set_id[i] ++ ++ return 0; ++} ++ ++static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, GetBitContext *gb) ++{ ++ s->present = 1; ++ s->preferred_transfer_characteristics = get_bits(gb, 8); ++ return 0; ++} ++ ++static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEIContext *s, const HEVCRpiParamSets *ps, ++ int type, int size) ++{ ++ switch (type) { ++ case 256: // Mismatched value from HM 8.1 ++ return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); ++ case HEVC_SEI_TYPE_FRAME_PACKING: ++ return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); ++ case HEVC_SEI_TYPE_DISPLAY_ORIENTATION: ++ return decode_nal_sei_display_orientation(&s->display_orientation, gb); ++ case HEVC_SEI_TYPE_PICTURE_TIMING: ++ return decode_nal_sei_pic_timing(s, gb, ps, logctx, size); ++ case HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO: ++ return decode_nal_sei_mastering_display_info(&s->mastering_display, gb); ++ case HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: ++ return decode_nal_sei_content_light_info(&s->content_light, gb); ++ case HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS: ++ return decode_nal_sei_active_parameter_sets(s, gb, logctx); ++ case HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: ++ return decode_nal_sei_user_data_registered_itu_t_t35(s, gb, size); ++ case HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: ++ return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gb); ++ default: ++ av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); ++ skip_bits_long(gb, 8 * size); ++ return 0; ++ } ++} ++ ++static int decode_nal_sei_suffix(GetBitContext *gb, void *logctx, HEVCSEIContext *s, ++ int type, int size) ++{ ++ switch (type) { ++ case HEVC_SEI_TYPE_DECODED_PICTURE_HASH: ++ return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); ++ default: ++ av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); ++ skip_bits_long(gb, 8 * size); ++ return 0; ++ } ++} ++ ++static int decode_nal_sei_message(GetBitContext * const gb, void * const logctx, HEVCSEIContext * const s, ++ const HEVCRpiParamSets * const ps, const int nal_unit_type) ++{ ++ int payload_type = 0; ++ int payload_size = 0; ++ int byte = 0xFF; ++ av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n"); ++ ++ while (byte == 0xFF) { ++ if (get_bits_left(gb) < 16 || payload_type > INT_MAX - 255) ++ return AVERROR_INVALIDDATA; ++ byte = get_bits(gb, 8); ++ payload_type += byte; ++ } ++ byte = 0xFF; ++ while (byte == 0xFF) { ++ if (get_bits_left(gb) < 8 + 8LL*payload_size) ++ return AVERROR_INVALIDDATA; ++ byte = get_bits(gb, 8); ++ payload_size += byte; ++ } ++ if (nal_unit_type == HEVC_NAL_SEI_PREFIX) { ++ return decode_nal_sei_prefix(gb, logctx, s, ps, payload_type, payload_size); ++ } else { /* nal_unit_type == NAL_SEI_SUFFIX */ ++ return decode_nal_sei_suffix(gb, logctx, s, payload_type, payload_size); ++ } ++} ++ ++static int more_rbsp_data(GetBitContext *gb) ++{ ++ return get_bits_left(gb) > 0 && show_bits(gb, 8) != 0x80; ++} ++ ++int ff_hevc_rpi_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, ++ const HEVCRpiParamSets *ps, int type) ++{ ++ int ret; ++ ++ do { ++ ret = decode_nal_sei_message(gb, logctx, s, ps, type); ++ if (ret < 0) ++ return ret; ++ } while (more_rbsp_data(gb)); ++ return 1; ++} ++ ++void ff_hevc_rpi_reset_sei(HEVCSEIContext *s) ++{ ++ s->a53_caption.a53_caption_size = 0; ++ av_freep(&s->a53_caption.a53_caption); ++} +diff --git a/libavcodec/rpi_hevc_sei.h b/libavcodec/rpi_hevc_sei.h +new file mode 100644 +index 0000000000..d4ac348df9 +--- /dev/null ++++ b/libavcodec/rpi_hevc_sei.h +@@ -0,0 +1,135 @@ ++/* ++ * HEVC Supplementary Enhancement Information messages ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVC_SEI_H ++#define AVCODEC_RPI_HEVC_SEI_H ++ ++#include ++ ++#include "libavutil/md5.h" ++ ++#include "get_bits.h" ++ ++/** ++ * SEI message types ++ */ ++typedef enum { ++ HEVC_SEI_TYPE_BUFFERING_PERIOD = 0, ++ HEVC_SEI_TYPE_PICTURE_TIMING = 1, ++ HEVC_SEI_TYPE_PAN_SCAN_RECT = 2, ++ HEVC_SEI_TYPE_FILLER_PAYLOAD = 3, ++ HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, ++ HEVC_SEI_TYPE_USER_DATA_UNREGISTERED = 5, ++ HEVC_SEI_TYPE_RECOVERY_POINT = 6, ++ HEVC_SEI_TYPE_SCENE_INFO = 9, ++ HEVC_SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, ++ HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, ++ HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, ++ HEVC_SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, ++ HEVC_SEI_TYPE_POST_FILTER_HINT = 22, ++ HEVC_SEI_TYPE_TONE_MAPPING_INFO = 23, ++ HEVC_SEI_TYPE_FRAME_PACKING = 45, ++ HEVC_SEI_TYPE_DISPLAY_ORIENTATION = 47, ++ HEVC_SEI_TYPE_SOP_DESCRIPTION = 128, ++ HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, ++ HEVC_SEI_TYPE_DECODING_UNIT_INFO = 130, ++ HEVC_SEI_TYPE_TEMPORAL_LEVEL0_INDEX = 131, ++ HEVC_SEI_TYPE_DECODED_PICTURE_HASH = 132, ++ HEVC_SEI_TYPE_SCALABLE_NESTING = 133, ++ HEVC_SEI_TYPE_REGION_REFRESH_INFO = 134, ++ HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO = 137, ++ HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, ++ HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, ++} HEVC_SEI_Type; ++ ++typedef struct HEVCSEIPictureHash { ++ uint8_t md5[3][16]; ++ uint8_t is_md5; ++} HEVCSEIPictureHash; ++ ++typedef struct HEVCSEIFramePacking { ++ int present; ++ int arrangement_type; ++ int content_interpretation_type; ++ int quincunx_subsampling; ++ int current_frame_is_frame0_flag; ++} HEVCSEIFramePacking; ++ ++typedef struct HEVCSEIDisplayOrientation { ++ int present; ++ int anticlockwise_rotation; ++ int hflip, vflip; ++} HEVCSEIDisplayOrientation; ++ ++typedef struct HEVCSEIPictureTiming { ++ int picture_struct; ++} HEVCSEIPictureTiming; ++ ++typedef struct HEVCSEIA53Caption { ++ int a53_caption_size; ++ uint8_t *a53_caption; ++} HEVCSEIA53Caption; ++ ++typedef struct HEVCSEIMasteringDisplay { ++ int present; ++ uint16_t display_primaries[3][2]; ++ uint16_t white_point[2]; ++ uint32_t max_luminance; ++ uint32_t min_luminance; ++} HEVCSEIMasteringDisplay; ++ ++typedef struct HEVCSEIContentLight { ++ int present; ++ uint16_t max_content_light_level; ++ uint16_t max_pic_average_light_level; ++} HEVCSEIContentLight; ++ ++typedef struct HEVCSEIAlternativeTransfer { ++ int present; ++ int preferred_transfer_characteristics; ++} HEVCSEIAlternativeTransfer; ++ ++typedef struct HEVCSEIContext { ++ HEVCSEIPictureHash picture_hash; ++ HEVCSEIFramePacking frame_packing; ++ HEVCSEIDisplayOrientation display_orientation; ++ HEVCSEIPictureTiming picture_timing; ++ HEVCSEIA53Caption a53_caption; ++ HEVCSEIMasteringDisplay mastering_display; ++ HEVCSEIContentLight content_light; ++ int active_seq_parameter_set_id; ++ HEVCSEIAlternativeTransfer alternative_transfer; ++} HEVCSEIContext; ++ ++struct HEVCRpiParamSets; ++ ++int ff_hevc_rpi_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, ++ const struct HEVCRpiParamSets *ps, int type); ++ ++/** ++ * Reset SEI values that are stored on the Context. ++ * e.g. Caption data that was extracted during NAL ++ * parsing. ++ * ++ * @param s HEVCRpiContext. ++ */ ++void ff_hevc_rpi_reset_sei(HEVCSEIContext *s); ++ ++#endif /* AVCODEC_RPI_HEVC_SEI_H */ +diff --git a/libavcodec/rpi_hevc_shader.c b/libavcodec/rpi_hevc_shader.c +new file mode 100644 +index 0000000000..23b49a99ae +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader.c +@@ -0,0 +1,1537 @@ ++#include "rpi_hevc_shader.h" ++ ++#ifdef _MSC_VER ++ #include ++ /* cast through uintptr_t to avoid warnings */ ++ #define POINTER_TO_UINT(X) ((unsigned int)(uintptr_t)(X)) ++#else ++ #define POINTER_TO_UINT(X) ((unsigned int)(X)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { /* the types are probably wrong... */ ++#endif ++#ifdef __cplusplus ++} ++#endif ++ ++#ifdef _MSC_VER ++__declspec(align(8)) ++#elif defined(__GNUC__) ++__attribute__((aligned(8))) ++#endif ++unsigned int ff_hevc_rpi_shader[] = { ++// ::mc_setup_c_q0 ++// ::mc_start ++/* [0x00000000] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_setup_c_qn ++/* [0x00000008] */ 0x95801ff6, 0xd0025900, // mov tmurs, 1 ; mov ra0, unif ++/* [0x00000010] */ 0xaaaaff00, 0xe6020827, // mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++/* [0x00000018] */ 0x9181e1f6, 0xd00250d8, // shl rb_ef, r0, i_shift30 ; mov ra_base, unif ++/* [0x00000020] */ 0x0d801dc0, 0xd0020827, // sub r0, unif, 1 ++/* [0x00000028] */ 0x119c11c0, 0xd00216a7, // shl rb_max_x, r0, v_x_shift ++/* [0x00000030] */ 0x0d801dc0, 0xd00217a7, // sub rb_max_y, unif, 1 ++/* [0x00000038] */ 0xff800100, 0xe0020527, // mov ra_kff800100, 0xff800100 ++/* [0x00000040] */ 0x000000ff, 0xe0021627, // mov rb_pmask, v_pmask ++/* [0x00000048] */ 0x001000ff, 0xe00205e7, // mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++/* [0x00000050] */ 0x00004000, 0xe00217e7, // mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++/* [0x00000058] */ 0x4000000e, 0xe0020667, // mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++/* [0x00000060] */ 0x95803ff6, 0x10024754, // mov ra_ef, rb_ef ; mov rb_xpitch, unif ++/* [0x00000068] */ 0x15827d80, 0x10021427, // mov rb_pitch, unif ++/* [0x00000070] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++/* [0x00000078] */ 0x0c9d03c0, 0x10021667, // add rb_dma1_base, r1, rb_pitch ++/* [0x00000080] */ 0x14981f80, 0xd0020827, // and r0, 1, elem_num ++/* [0x00000088] */ 0x409c5007, 0xd00049e0, // nop ; mul24 r0, r0, 5 ++/* [0x00000090] */ 0x0c9a7180, 0x100210a7, // add rb_elem_x, r0, elem_num ++/* [0x00000098] */ 0x11001dc0, 0xd4020827, // shl r0, ra0.16b, v_x_shift ++/* [0x000000a0] */ 0x0c9c21c0, 0x10020827, // add r0, r0, rb_elem_x ++/* [0x000000a8] */ 0x930001f6, 0xd2225811, // max r0, r0, 0 ; mov ra_y, ra0.16a ++/* [0x000000b0] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x000000b8] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x000000c0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x000000c8] */ 0x0d510dc0, 0x18020867, // sub r1, ra_k0, rb_pitch ++/* [0x000000d0] */ 0x149e7040, 0x10020867, // and r1, r0, r1 ++/* [0x000000d8] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x000000e0] */ 0x8c827076, 0x10025800, // add r0, r0, r1 ; mov ra0, unif ++/* [0x000000e8] */ 0x0c627c00, 0x10020627, // add ra_base, ra_base, r0 ++/* [0x000000f0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++/* [0x000000f8] */ 0x0f9c25c0, 0xd0020867, // asr r1, r2, 2 ++/* [0x00000100] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++/* [0x00000108] */ 0x149c35c0, 0xd0020827, // and r0, r2, 3 ++/* [0x00000110] */ 0x159e7040, 0x10020827, // or r0, r0, r1 ++/* [0x00000118] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++/* [0x00000120] */ 0x0c9e7040, 0x10021727, // add r_vpm, r0, r1 ++/* [0x00000128] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++/* [0x00000130] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++/* [0x00000138] */ 0x0c9e7040, 0x100216e7, // add r_dma, r0, r1 ++/* [0x00000140] */ 0x11001dc0, 0xd4020827, // shl r0, ra0.16b, v_x_shift ++/* [0x00000148] */ 0x8c0021f6, 0x12125811, // add r0, r0, rb_elem_x ; mov ra_y2, ra0.16a ++/* [0x00000150] */ 0x938001f6, 0xd002480f, // max r0, r0, 0 ; mov rb_base2, unif ++/* [0x00000158] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00000160] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x00000168] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00000170] */ 0x0d510dc0, 0x18020867, // sub r1, ra_k0, rb_pitch ++/* [0x00000178] */ 0x949c307f, 0xd0024863, // and r1, r0, r1 ; mov r3, PREREAD ++/* [0x00000180] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000188] */ 0x8c467076, 0x12024822, // add r0, r0, r1 ; mov r2, ra_y2 ++/* [0x00000190] */ 0x8c44fe36, 0x140253e0, // add rb_base2, rb_base2, r0 ; mov r0, ra_y ++// :1 ++/* [0x00000198] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x000001a0] */ 0x139c01c0, 0xd0020867, // max r1, r0, 0 ++/* [0x000001a8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x000001b0] */ 0x4c51018f, 0x1a024821, // add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x000001b8] */ 0x8c627c40, 0x10225e11, // add t0s, ra_base, r1 ; mov ra_y, r0 ++/* [0x000001c0] */ 0x139c05c0, 0xd0020867, // max r1, r2, 0 ++/* [0x000001c8] */ 0xffffffb0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x000001d0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x000001d8] */ 0x4c51058f, 0x1a0248a1, // add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x000001e0] */ 0x8c9cfe52, 0x10125f11, // add t1s, rb_base2, r1 ; mov ra_y2, r2 ++/* [0x000001e8] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x000001f0] */ 0x00000000, 0xe0024104, // mov ra4, 0 ; mov rb4, 0 ++/* [0x000001f8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000200] */ 0x00000000, 0xe0024145, // mov ra5, 0 ; mov rb5, 0 ++/* [0x00000208] */ 0x00000000, 0xe0024186, // mov ra6, 0 ; mov rb6, 0 ++/* [0x00000210] */ 0x00000000, 0xe00241c7, // mov ra7, 0 ; mov rb7, 0 ++// ::mc_filter_c_p ++/* [0x00000218] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00000220] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00000228] */ 0xf1081dc0, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r0, r0 ++/* [0x00000230] */ 0x8c8021f6, 0x10025810, // add r0, r0, rb_elem_x ; mov ra_width_height, unif ++/* [0x00000238] */ 0x8d810bf6, 0x10025840, // sub r1, r5, rb_pitch ; mov ra0, unif ++/* [0x00000240] */ 0x93567176, 0x14024800, // max r0, r0, r5 ; mov vrx_xshift, vrx_xshift_next ++/* [0x00000248] */ 0x9209a1f6, 0x12225813, // min r0, r0, rb_max_x ; mov vra_y_next, ra2.16a ++/* [0x00000250] */ 0x119c31c0, 0xd0220567, // shl vrx_xshift_next, r0, 3 ++/* [0x00000258] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00000260] */ 0x54402077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x00000268] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000270] */ 0x8c827076, 0x10025803, // add r0, r0, r1 ; mov ra3, unif ++/* [0x00000278] */ 0x8c427636, 0x120246a1, // add vrx_base_next, r3, r0 ; mov r1, ra_height ++/* [0x00000280] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x00000288] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x00000290] */ 0x8c81f3f6, 0xd0039496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_off_mul_l0, unif ++/* [0x00000298] */ 0x918073f6, 0xd002581c, // shl r0, r1, v_dma_h_shift ; mov ra_dest, unif ++/* [0x000002a0] */ 0x8c6670b6, 0x14024822, // add r0, r0, r2 ; mov r2, ra_fir_off_val ++/* [0x000002a8] */ 0x910d01f6, 0xdc02480a, // shl r0, r0, v_dma_wh_shift ; mov rb10, ra3.8c ++/* [0x000002b0] */ 0x8c59b1f6, 0x140246e1, // add ra_dma0, r0, rb_dma0_base ; mov r1, ra_wt_off_l0 ++/* [0x000002b8] */ 0x5158c3d6, 0xd2024860, // shl r1, r1, i_wt_den_p5 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x000002c0] */ 0x8d667236, 0x14025320, // sub rb_wt_off, r1, r0 ; mov r0, ra_kmul_add ++/* [0x000002c8] */ 0x8c59cc3f, 0xd21245a5, // add ra_wt_mul_l0, ra_wt_mul_l0, r0 ; mov r5rep, -4 ++/* [0x000002d0] */ 0x950e0dbf, 0x1e0252de, // mov rb11, ra3.8d ; mov ra_link, unif ++// :1 ++/* [0x000002d8] */ 0x8d151bf6, 0xa00269c4, // sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu0 ++/* [0x000002e0] */ 0x8e4c09f6, 0x140288a3, // shr r2, r4, vrx_xshift ; mov.ifz r3, vra_y_next ++/* [0x000002e8] */ 0x8e4485f6, 0xd402c863, // shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++/* [0x000002f0] */ 0x8c683ff6, 0x1002b9d8, // add.setf -, rb_ef, rb_ef ; mov.ifz vra_base, vrx_base_next ++/* [0x000002f8] */ 0x8c531789, 0xda224460, // add vra_y, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x00000300] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x00000308] */ 0x929de7d2, 0x1003c8e0, // min r3, r3, rb_max_y ; mov.ifnc r0, r2 ++/* [0x00000310] */ 0x545d039f, 0x12024863, // and r1, r1, ra_pmax ; mul24 r3, r3, rb_pitch ++/* [0x00000318] */ 0x8c618cc7, 0x10024e20, // add vr_txs, vra_base, r3 ; v8min r0, r0, rb_pmask ++/* [0x00000320] */ 0x4c001bf0, 0xd8025963, // add r5rep, r5, 1 ; mul24 r3, ra0.8a, r0 ++/* [0x00000328] */ 0x4d01fef1, 0x1e0248a3, // sub r2, rb_fir_off_h, r3 ; mul24 r3, ra0.8d, r1 ++/* [0x00000330] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00000338] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00000340] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00000348] */ 0x4c032b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00000350] */ 0xffffff68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00000358] */ 0x4c1ca4f7, 0x100248a0, // add r2, r2, r3 ; mul24 r0, ra7, rb10 ++/* [0x00000360] */ 0x550c6ffe, 0x1a024161, // mov ra5, rb6 ; mul24 r1, rb6, ra3.8b ++/* [0x00000368] */ 0x8f1c05f6, 0xd00241c6, // asr ra7, r2, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x00000370] */ 0x4c0c423e, 0x18024860, // add r1, r1, r0 ; mul24 r0, rb4, ra3.8a ++/* [0x00000378] */ 0x4d1cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra7, rb11 ++/* [0x00000380] */ 0x0d9e7200, 0x10020867, // sub r1, r1, r0 ++/* [0x00000388] */ 0x8f5c63f6, 0xdc024863, // asr r1, r1, 6 ; mov r3, ra_blk_height ++/* [0x00000390] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00000398] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x000003a0] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x000003a8] */ 0xffffff10, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000003b0] */ 0x0f9cd3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x000003b8] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x000003c0] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x000003c8] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000003d0] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x000003d8] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000003e0] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000003e8] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000003f0] */ 0xfffffec8, 0xf0f809e7, // brr -, r:1b ++/* [0x000003f8] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00000400] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00000408] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_c_p_l1 ++/* [0x00000410] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00000418] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00000420] */ 0xf1081dc0, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r0, r0 ++/* [0x00000428] */ 0x8c8021f6, 0x10025810, // add r0, r0, rb_elem_x ; mov ra_width_height, unif ++/* [0x00000430] */ 0x8d810bf6, 0x10025840, // sub r1, r5, rb_pitch ; mov ra0, unif ++/* [0x00000438] */ 0x939c117f, 0x10125815, // max r0, r0, r5 ; mov vrx_xshift, vrx_xshift_next ++/* [0x00000440] */ 0x9209a1f6, 0x12125813, // min r0, r0, rb_max_x ; mov vra_y_next, ra2.16a ++/* [0x00000448] */ 0x119c31c0, 0xd0021067, // shl vrx_xshift_next, r0, 3 ++/* [0x00000450] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00000458] */ 0x54402077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x00000460] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000468] */ 0x8c827076, 0x10025803, // add r0, r0, r1 ; mov ra3, unif ++/* [0x00000470] */ 0x8c427636, 0x120254e1, // add vrx_base_next, r3, r0 ; mov r1, ra_height ++/* [0x00000478] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x00000480] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x00000488] */ 0x8c81f3f6, 0xd0039496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_off_mul_l0, unif ++/* [0x00000490] */ 0x918073f6, 0xd002581c, // shl r0, r1, v_dma_h_shift ; mov ra_dest, unif ++/* [0x00000498] */ 0x8c6670b6, 0x14024822, // add r0, r0, r2 ; mov r2, ra_fir_off_val ++/* [0x000004a0] */ 0x910d01f6, 0xdc02480a, // shl r0, r0, v_dma_wh_shift ; mov rb10, ra3.8c ++/* [0x000004a8] */ 0x8c59b1f6, 0x140246e1, // add ra_dma0, r0, rb_dma0_base ; mov r1, ra_wt_off_l0 ++/* [0x000004b0] */ 0x5158c3d6, 0xd2024860, // shl r1, r1, i_wt_den_p5 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x000004b8] */ 0x8d667236, 0x14025320, // sub rb_wt_off, r1, r0 ; mov r0, ra_kmul_add ++/* [0x000004c0] */ 0x8c59cc3f, 0xd21245a5, // add ra_wt_mul_l0, ra_wt_mul_l0, r0 ; mov r5rep, -4 ++/* [0x000004c8] */ 0x950e0dbf, 0x1e0252de, // mov rb11, ra3.8d ; mov ra_link, unif ++// :1 ++/* [0x000004d0] */ 0x8d151bf6, 0xb00269c4, // sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu1 ++/* [0x000004d8] */ 0x8e5539bf, 0x1202888f, // shr r2, r4, vrx_xshift ; mov.ifz vra_base, vrx_base_next ++/* [0x000004e0] */ 0x8e4485f6, 0xd202c863, // shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++/* [0x000004e8] */ 0x8c4c3ff6, 0x1202a9e3, // add.setf -, rb_ef, rb_ef ; mov.ifz r3, vra_y_next ++/* [0x000004f0] */ 0x8c531789, 0xda124460, // add vra_y, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x000004f8] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x00000500] */ 0x929de7d2, 0x1003c8e0, // min r3, r3, rb_max_y ; mov.ifnc r0, r2 ++/* [0x00000508] */ 0x545d039f, 0x12024863, // and r1, r1, ra_pmax ; mul24 r3, r3, rb_pitch ++/* [0x00000510] */ 0x8c5cfec6, 0x12024f20, // add vr_txs, vra_base, r3 ; v8min r0, r0, ra_pmax ++/* [0x00000518] */ 0x4c001bf0, 0xd8025963, // add r5rep, r5, 1 ; mul24 r3, ra0.8a, r0 ++/* [0x00000520] */ 0x4d01fef1, 0x1e0248a3, // sub r2, rb_fir_off_h, r3 ; mul24 r3, ra0.8d, r1 ++/* [0x00000528] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00000530] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00000538] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00000540] */ 0x4c032b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00000548] */ 0xffffff68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00000550] */ 0x4c1ca4f7, 0x100248a0, // add r2, r2, r3 ; mul24 r0, ra7, rb10 ++/* [0x00000558] */ 0x550c6ffe, 0x1a024161, // mov ra5, rb6 ; mul24 r1, rb6, ra3.8b ++/* [0x00000560] */ 0x8f1c05f6, 0xd00241c6, // asr ra7, r2, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x00000568] */ 0x4c0c423e, 0x18024860, // add r1, r1, r0 ; mul24 r0, rb4, ra3.8a ++/* [0x00000570] */ 0x4d1cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra7, rb11 ++/* [0x00000578] */ 0x0d9e7200, 0x10020867, // sub r1, r1, r0 ++/* [0x00000580] */ 0x8f5c63f6, 0xdc024863, // asr r1, r1, 6 ; mov r3, ra_blk_height ++/* [0x00000588] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00000590] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x00000598] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x000005a0] */ 0xffffff10, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000005a8] */ 0x0f9cd3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x000005b0] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x000005b8] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x000005c0] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000005c8] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x000005d0] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000005d8] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000005e0] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000005e8] */ 0xfffffec8, 0xf0f809e7, // brr -, r:1b ++/* [0x000005f0] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x000005f8] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00000600] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_c_b ++/* [0x00000608] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00000610] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00000618] */ 0xf1081dc9, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r1, r1 ++/* [0x00000620] */ 0x8c0821f6, 0x12225813, // add r0, r0, rb_elem_x ; mov ra_y_next, ra2.16a ++/* [0x00000628] */ 0x8d810bf6, 0x10025850, // sub r1, r5, rb_pitch ; mov ra_width_height, unif ++/* [0x00000630] */ 0x93567176, 0x14125815, // max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++/* [0x00000638] */ 0x9281a1f6, 0x10025800, // min r0, r0, rb_max_x ; mov ra0, unif ++/* [0x00000640] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00000648] */ 0x9481c1f6, 0xd0025802, // and r0, r0, -4 ; mov ra2, unif ++/* [0x00000650] */ 0x54402077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x00000658] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000660] */ 0x8c427076, 0x12024821, // add r0, r0, r1 ; mov r1, ra_height ++/* [0x00000668] */ 0x8c9c163f, 0x10024680, // add ra_base_next, r3, r0 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00000670] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x00000678] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x00000680] */ 0x8c59f3f6, 0xd4139496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_mul_l0, ra_wt_off_l0 ++/* [0x00000688] */ 0x918073f6, 0xd0025803, // shl r0, r1, v_dma_h_shift ; mov ra3, unif ++/* [0x00000690] */ 0x8c8270b6, 0x10024823, // add r0, r0, r2 ; mov r3, unif ++/* [0x00000698] */ 0x910d01f6, 0xd2125813, // shl r0, r0, v_dma_wh_shift ; mov ra_y2_next, ra3.16a ++/* [0x000006a0] */ 0x8c0db1f6, 0x140246e0, // add ra_dma0, r0, rb_dma0_base ; mov r0, ra3.16b ++/* [0x000006a8] */ 0x918011f6, 0xd0025801, // shl r0, r0, v_x_shift ; mov ra1, unif ++/* [0x000006b0] */ 0x8c8021f6, 0x10025803, // add r0, r0, rb_elem_x ; mov ra3, unif ++/* [0x000006b8] */ 0x8d810bf6, 0x10025852, // sub r1, r5, rb_pitch ; mov ra_wt_off_mul_l1, unif ++/* [0x000006c0] */ 0x939de17f, 0x10025809, // max r0, r0, r5 ; mov ra9, rb_max_y ++/* [0x000006c8] */ 0x9265a1f6, 0x14024822, // min r0, r0, rb_max_x ; mov r2, ra_kmul_add ++/* [0x000006d0] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x000006d8] */ 0x9481c1f6, 0xd0039812, // and r0, r0, -4 ; mov.ifc ra_wt_off_mul_l1, unif ++/* [0x000006e0] */ 0x949dc07f, 0xd0024865, // and r1, r0, r1 ; mov r5rep, -4 ++/* [0x000006e8] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x000006f0] */ 0x8c827076, 0x1002581c, // add r0, r0, r1 ; mov ra_dest, unif ++/* [0x000006f8] */ 0x8c667636, 0x140254e0, // add rb_base2_next, r3, r0 ; mov r0, ra_fir_off_val ++/* [0x00000700] */ 0x4c5a7c86, 0x121245a1, // add ra_wt_mul_l0, ra_wt_mul_l0, r2 ; mul24 r1, r0, ra_wt_mul_l0 ++/* [0x00000708] */ 0x4c4a7c86, 0x121244a0, // add ra_wt_mul_l1, ra_wt_mul_l1, r2 ; mul24 r0, r0, ra_wt_mul_l1 ++/* [0x00000710] */ 0x8c4a7076, 0x14024821, // add r0, r0, r1 ; mov r1, ra_wt_off_l1 ++/* [0x00000718] */ 0x910cd3f6, 0xde02484b, // shl r1, r1, i_wt_den_p6 ; mov rb11, ra3.8d ++/* [0x00000720] */ 0x8d827236, 0x1002531e, // sub rb_wt_off, r1, r0 ; mov ra_link, unif ++/* [0x00000728] */ 0x95080ff6, 0x1e024287, // mov ra10, rb_xshift2 ; mov rb7, ra2.8d ++// :1 ++/* [0x00000730] */ 0x0d9d1bc0, 0xa00229e7, // sub.setf -, r5, rb_i_tmu ; nop ; ldtmu0 ++/* [0x00000738] */ 0x8e5539bf, 0x1202888f, // shr r2, r4, ra_xshift ; mov.ifz rb_base2, rb_base2_next ++/* [0x00000740] */ 0x8e4c85f6, 0xd0029851, // shr r1, r2, v_v_shift ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00000748] */ 0x8c683ff6, 0x1002b9d8, // add.setf -, rb_ef, rb_ef ; mov.ifz ra_base, ra_base_next ++/* [0x00000750] */ 0x8c441fb6, 0xd4224463, // add ra_y, 1, ra_y ; mov r3, ra_y ++/* [0x00000758] */ 0x93531789, 0xd80248e0, // max r3, r3, ra_k0 ; mov r0, r1 << 15 ++/* [0x00000760] */ 0x9227f792, 0xd003c8e1, // min r3, r3, ra9 ; mov.ifnc r1, r2 << 1 ++/* [0x00000768] */ 0x559d049f, 0x100e4823, // mov.ifnc r0, r2 ; mul24 r3, r3, rb_pitch ++/* [0x00000770] */ 0x8c618cc7, 0x10024e20, // add t0s, ra_base, r3 ; v8min r0, r0, rb_pmask ++/* [0x00000778] */ 0x540183f0, 0x18024862, // and r1, r1, rb_pmask ; mul24 r2, ra0.8a, r0 ++/* [0x00000780] */ 0x4d01feb1, 0x1e0248a3, // sub r2, rb_fir_off_h, r2 ; mul24 r3, ra0.8d, r1 ++/* [0x00000788] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00000790] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00000798] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x000007a0] */ 0x40032031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x000007a8] */ 0x4c0854fe, 0xb8025804, // add r0, r2, r3 ; mul24 ra4, rb5, ra2.8a ; ldtmu1 ++/* [0x000007b0] */ 0x8e2869bf, 0x10024885, // shr r2, r4, ra10 ; mov rb5, rb6 ++/* [0x000007b8] */ 0x8e4485f6, 0xd2024863, // shr r1, r2, v_v_shift ; mov r3, ra_y2 ++/* [0x000007c0] */ 0x8e1c01f6, 0xd00241c6, // shr ra7, r0, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x000007c8] */ 0x8c531789, 0xda124460, // add ra_y2, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x000007d0] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x000007d8] */ 0x925de7ce, 0x120248e1, // min r3, r3, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x000007e0] */ 0x559d049f, 0x100e4823, // mov.ifnc r0, r2 ; mul24 r3, r3, rb_pitch ++/* [0x000007e8] */ 0x8c5cfec6, 0x12024f20, // add t1s, rb_base2, r3 ; v8min r0, r0, ra_pmax ++/* [0x000007f0] */ 0x4c041bf0, 0xd8025962, // add r5rep, r5, 1 ; mul24 r2, ra1.8a, r0 ++/* [0x000007f8] */ 0x4d05feb1, 0x1e0248a3, // sub r2, rb_fir_off_h, r2 ; mul24 r3, ra1.8d, r1 ++/* [0x00000800] */ 0x4d07e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00000808] */ 0x40074031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00000810] */ 0x4c07c6b0, 0xdc0248a3, // add r2, r3, r2 ; mul24 r3, ra1.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00000818] */ 0x4c072b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00000820] */ 0xfffffef0, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00000828] */ 0x4c0c94fe, 0x180248a0, // add r2, r2, r3 ; mul24 r0, rb9, ra3.8a ++/* [0x00000830] */ 0x550caffe, 0x1a025261, // mov rb9, rb10 ; mul24 r1, rb10, ra3.8b ++/* [0x00000838] */ 0x8e2c05f6, 0xd00242ca, // shr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00000840] */ 0x4d08523e, 0x1a0248a1, // sub r2, r1, r0 ; mul24 r1, rb5, ra2.8b ++/* [0x00000848] */ 0x8d112bf6, 0x100269e0, // sub.setf -, r5, rb_lcount ; mov r0, ra4 ++/* [0x00000850] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00000858] */ 0x4c1c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra7, rb7 ++/* [0x00000860] */ 0x4d0ca23e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00000868] */ 0x4c2cb437, 0x100248a0, // add r2, r2, r0 ; mul24 r0, ra11, rb11 ++/* [0x00000870] */ 0x0d9e7400, 0x100208a7, // sub r2, r2, r0 ++/* [0x00000878] */ 0x0e9c63c0, 0xd0020867, // shr r1, r1, 6 ++/* [0x00000880] */ 0x4e5865ce, 0xd20248a0, // shr r2, r2, 6 ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00000888] */ 0x4c4a7456, 0x120248a1, // add r2, r2, r1 ; mul24 r1, r2, ra_wt_mul_l1 ++/* [0x00000890] */ 0x4c667216, 0x14024862, // add r1, r1, r0 ; mul24 r2, r2, ra_kmul_add ++/* [0x00000898] */ 0x8d5e72b6, 0x1c024863, // sub r1, r1, r2 ; mov r3, ra_blk_height ++/* [0x000008a0] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x000008a8] */ 0xfffffe68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000008b0] */ 0x0f667380, 0x18020867, // asr r1, r1, ra_wt_den_p7 ++/* [0x000008b8] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x000008c0] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x000008c8] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000008d0] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x000008d8] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000008e0] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000008e8] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000008f0] */ 0xfffffe20, 0xf0f809e7, // brr -, r:1b ++/* [0x000008f8] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00000900] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00000908] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_sync_q0 ++/* [0x00000910] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000918] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000920] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000928] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000930] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000938] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000940] */ 0x0000001c, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000948] */ 0x00000001, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000950] */ 0x0000000d, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q1 ++/* [0x00000958] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000960] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000968] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000970] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000978] */ 0x00000011, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000980] */ 0x00000002, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q2 ++/* [0x00000988] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000990] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000998] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x000009a0] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x000009a8] */ 0x00000012, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000009b0] */ 0x00000003, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q3 ++/* [0x000009b8] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x000009c0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x000009c8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x000009d0] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x000009d8] */ 0x00000013, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000009e0] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_sync_q4 ++/* [0x000009e8] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x000009f0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x000009f8] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a00] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a08] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a10] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000a18] */ 0x0000001d, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a20] */ 0x00000005, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000a28] */ 0x0000000e, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q5 ++/* [0x00000a30] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000a38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000a40] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000a48] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000a50] */ 0x00000015, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a58] */ 0x00000006, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q6 ++/* [0x00000a60] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000a68] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000a70] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000a78] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000a80] */ 0x00000016, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000a88] */ 0x00000007, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q7 ++/* [0x00000a90] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000a98] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000aa0] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000aa8] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000ab0] */ 0x00000017, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_sync_q8 ++/* [0x00000ac0] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000ac8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000ad0] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000ad8] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000ae0] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000ae8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000af0] */ 0x0000001e, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000af8] */ 0x00000009, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000b00] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q9 ++/* [0x00000b08] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000b10] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000b18] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000b20] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000b28] */ 0x00000019, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000b30] */ 0x0000000a, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q10 ++/* [0x00000b38] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000b40] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000b48] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000b50] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000b58] */ 0x0000001a, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000b60] */ 0x0000000b, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync_q11 ++/* [0x00000b68] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000b70] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000b78] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000b80] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x00000b88] */ 0x0000001b, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000b90] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_exit_c_qn ++// ::mc_exit_y_qn ++/* [0x00000b98] */ 0x00000002, 0xe00228e7, // mov.setf r3, PREREAD - 1 ++// :1 ++/* [0x00000ba0] */ 0xffffffe0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x00000ba8] */ 0x009e7000, 0xa00009e7, // nop ; nop ; ldtmu0 ++/* [0x00000bb0] */ 0x009e7000, 0xb00009e7, // nop ; nop ; ldtmu1 ++/* [0x00000bb8] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x00000bc0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000bc8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++/* [0x00000bd0] */ 0x009e7000, 0x100009e7, // nop ++/* [0x00000bd8] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_exit_c_q0 ++// ::mc_exit_y_q0 ++/* [0x00000be0] */ 0x00000002, 0xe00228e7, // mov.setf r3, PREREAD - 1 ++// :1 ++/* [0x00000be8] */ 0xffffffe0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x00000bf0] */ 0x009e7000, 0xa00009e7, // nop ; nop ; ldtmu0 ++/* [0x00000bf8] */ 0x009e7000, 0xb00009e7, // nop ; nop ; ldtmu1 ++/* [0x00000c00] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x00000c08] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00000c10] */ 0x0000001c, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00000c18] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++/* [0x00000c20] */ 0x00000001, 0xe00209a7, // mov interrupt, 1 ++/* [0x00000c28] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_setup_y_q0 ++/* [0x00000c30] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_setup_y_qn ++/* [0x00000c38] */ 0x95801ff6, 0xd0025900, // mov tmurs, 1 ; mov ra0, unif ++/* [0x00000c40] */ 0x15827d80, 0x10020267, // mov ra9, unif ++/* [0x00000c48] */ 0x15827d80, 0x10020067, // mov ra1, unif ++/* [0x00000c50] */ 0xaaaaff00, 0xe6020827, // mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++/* [0x00000c58] */ 0x9181e1f6, 0xd00250cb, // shl rb_ef, r0, i_shift30 ; mov ra11, unif ++/* [0x00000c60] */ 0xff800100, 0xe0020527, // mov ra_kff800100, 0xff800100 ++/* [0x00000c68] */ 0x000000ff, 0xe0021627, // mov rb_pmask, v_pmask ++/* [0x00000c70] */ 0x001000ff, 0xe00205e7, // mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++/* [0x00000c78] */ 0x00004000, 0xe00217e7, // mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++/* [0x00000c80] */ 0x4000000e, 0xe0020667, // mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++/* [0x00000c88] */ 0x050b0a00, 0xe0021567, // mov rb_y_coeffs_2, 0x050b0a00 ++/* [0x00000c90] */ 0x11283a40, 0xe00215a7, // mov rb_y_coeffs_3, 0x11283a40 ++/* [0x00000c98] */ 0x0a0b0500, 0xe00215e7, // mov rb_y_coeffs_5, 0x0a0b0500 ++/* [0x00000ca0] */ 0x15827d80, 0x100200e7, // mov ra3, unif ++/* [0x00000ca8] */ 0x95803ff6, 0x10024754, // mov ra_ef, rb_ef ; mov rb_xpitch, unif ++/* [0x00000cb0] */ 0x0d0c1dc0, 0xd40216a7, // sub rb_max_x, ra3.16b, 1 ++/* [0x00000cb8] */ 0x0d0c1dc0, 0xd20217a7, // sub rb_max_y, ra3.16a, 1 ++/* [0x00000cc0] */ 0x959a0dbf, 0x100248d0, // mov r3, elem_num ; mov rb_pitch, unif ++/* [0x00000cc8] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++/* [0x00000cd0] */ 0x159d03c0, 0x10021667, // or rb_dma1_base, r1, rb_pitch ++/* [0x00000cd8] */ 0x0c027cc0, 0x14020827, // add r0, ra0.16b, r3 ++/* [0x00000ce0] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 ++/* [0x00000ce8] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00000cf0] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00000cf8] */ 0xf49dc1d2, 0xd0024822, // and r0, r0, -4 ; v8subs r2, r2, r2 ++/* [0x00000d00] */ 0x0d9d05c0, 0x100208a7, // sub r2, r2, rb_pitch ++/* [0x00000d08] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00000d10] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000d18] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00000d20] */ 0x0c267c00, 0x10020627, // add ra_base, ra9, r0 ++/* [0x00000d28] */ 0x0c067cc0, 0x14020827, // add r0, ra1.16b, r3 ++/* [0x00000d30] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 ++/* [0x00000d38] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00000d40] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x00000d48] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00000d50] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00000d58] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000d60] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00000d68] */ 0x0c2e7c00, 0x100213e7, // add rb_base2, ra11, r0 ++/* [0x00000d70] */ 0x80027036, 0x120049e0, // nop ; mov r0, ra0.16a ++/* [0x00000d78] */ 0x95043ff6, 0xd20248e2, // mov r3, PREREAD ; mov r2, ra1.16a ++// :1 ++/* [0x00000d80] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x00000d88] */ 0x139c01c0, 0xd0020867, // max r1, r0, 0 ++/* [0x00000d90] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x00000d98] */ 0x4c51018f, 0x1a024821, // add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x00000da0] */ 0x8c627c40, 0x10225e11, // add t0s, ra_base, r1 ; mov ra_y, r0 ++/* [0x00000da8] */ 0x139c05c0, 0xd0020867, // max r1, r2, 0 ++/* [0x00000db0] */ 0xffffffb0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x00000db8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x00000dc0] */ 0x4c51058f, 0x1a0248a1, // add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x00000dc8] */ 0x8c9cfe52, 0x10125f11, // add t1s, rb_base2, r1 ; mov ra_y2, r2 ++/* [0x00000dd0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++/* [0x00000dd8] */ 0x0f9c25c0, 0xd0020867, // asr r1, r2, 2 ++/* [0x00000de0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++/* [0x00000de8] */ 0x149c35c0, 0xd0020827, // and r0, r2, 3 ++/* [0x00000df0] */ 0x159e7040, 0x10020827, // or r0, r0, r1 ++/* [0x00000df8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++/* [0x00000e00] */ 0x0c9e7040, 0x10021727, // add r_vpm, r0, r1 ++/* [0x00000e08] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++/* [0x00000e10] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++/* [0x00000e18] */ 0x0c9e7040, 0x100216e7, // add r_dma, r0, r1 ++/* [0x00000e20] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00000e28] */ 0x00000000, 0xe0024208, // mov ra8, 0 ; mov rb8, 0 ++/* [0x00000e30] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000e38] */ 0x00000000, 0xe0024249, // mov ra9, 0 ; mov rb9, 0 ++/* [0x00000e40] */ 0x00000000, 0xe002428a, // mov ra10, 0 ; mov rb10, 0 ++/* [0x00000e48] */ 0x00000000, 0xe00242cb, // mov ra11, 0 ; mov rb11, 0 ++// :per_block_setup_8 ++/* [0x00000e50] */ 0x93567176, 0x14125815, // max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++/* [0x00000e58] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00000e60] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00000e68] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00000e70] */ 0x8d810bf6, 0x1002589a, // sub r2, r5, rb_pitch ; mov ra_base_next, unif ++/* [0x00000e78] */ 0x940270b6, 0x12225853, // and r1, r0, r2 ; mov ra_y_next, ra0.16a ++/* [0x00000e80] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000e88] */ 0x8c827076, 0x10025801, // add r0, r0, r1 ; mov ra1, unif ++/* [0x00000e90] */ 0x0c6a7c00, 0x100206a7, // add ra_base_next, ra_base_next, r0 ++/* [0x00000e98] */ 0x0c067cc0, 0x14020827, // add r0, ra1.16b, r3 ++/* [0x00000ea0] */ 0x93067176, 0x12125813, // max r0, r0, r5 ; mov ra_y2_next, ra1.16a ++/* [0x00000ea8] */ 0x9281a1f6, 0x10024813, // min r0, r0, rb_max_x ; mov rb_base2_next, unif ++/* [0x00000eb0] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x00000eb8] */ 0x9481c1f6, 0xd0025810, // and r0, r0, -4 ; mov ra_width_height, unif ++/* [0x00000ec0] */ 0x949dc0bf, 0x10024871, // and r1, r0, r2 ; mov vw_setup, rb_vpm_init ++/* [0x00000ec8] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00000ed0] */ 0x4c401077, 0xd4024821, // add r0, r0, r1 ; mul24 r1, ra_width, v_x_mul ++/* [0x00000ed8] */ 0x0c9d3e00, 0x100214e7, // add rb_base2_next, rb_base2_next, r0 ++/* [0x00000ee0] */ 0x8d419e76, 0x12025760, // sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height ++/* [0x00000ee8] */ 0x8c5dc1c6, 0xdc025460, // add rb_i_tmu, r0, (7-8) - PREREAD ; v8min r0, r0, ra_blk_height ++/* [0x00000ef0] */ 0x0c9df1c0, 0xd00214a7, // add rb_lcount, r0, (7-8) ++/* [0x00000ef8] */ 0x916471f6, 0xd4024823, // shl r0, r0, v_dma_h_shift ; mov r3, ra_kmul_add ++/* [0x00000f00] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00000f08] */ 0x916501f6, 0xd4024822, // shl r0, r0, v_dma_wh_shift ; mov r2, ra_fir_off_val ++/* [0x00000f10] */ 0x8c81b1f6, 0x100246e0, // add ra_dma0, r0, rb_dma0_base ; mov r0, unif ++/* [0x00000f18] */ 0x918101f6, 0xd00a5816, // shl.ifnn r0, r0, i_shift16 ; mov ra_wt_off_mul_l0, unif ++/* [0x00000f20] */ 0x915031f6, 0xde024205, // shl ra8, r0, 3 ; mov rb5, ra_k255 ++/* [0x00000f28] */ 0x01040400, 0xe0020867, // mov r1, 0x01040400 ++/* [0x00000f30] */ 0x10227380, 0x1e5200a7, // ror ra2.8b, r1, ra8.8d ++/* [0x00000f38] */ 0x10227380, 0x1c520027, // ror ra0.8b, r1, ra8.8c ++/* [0x00000f40] */ 0x10215f80, 0x1e6200a7, // ror ra2.8c, rb_y_coeffs_2, ra8.8d ++/* [0x00000f48] */ 0x10215f80, 0x1c620027, // ror ra0.8c, rb_y_coeffs_2, ra8.8c ++/* [0x00000f50] */ 0x00010100, 0xe0020867, // mov r1,0x00010100 ++/* [0x00000f58] */ 0x902203bf, 0x1e025812, // ror r0, r1, ra8.8d ; mov ra_wt_off_mul_l1, unif ++/* [0x00000f60] */ 0x90205387, 0x1c424004, // ror ra0.8a, r1, ra8.8c ; v8min rb4, r0, rb5 ++/* [0x00000f68] */ 0x914883f6, 0xd0031856, // shl r1, r1, 8 ; mov.ifn ra_wt_off_mul_l0, ra_wt_off_mul_l1 ++/* [0x00000f70] */ 0x902203bf, 0x1e02581c, // ror r0, r1, ra8.8d ; mov ra_dest, unif ++/* [0x00000f78] */ 0x90205387, 0x1c72404b, // ror ra1.8d, r1, ra8.8c ; v8min rb11, r0, rb5 ++/* [0x00000f80] */ 0x10216f80, 0x1e7200a7, // ror ra2.8d, rb_y_coeffs_3, ra8.8d ++/* [0x00000f88] */ 0x10216f80, 0x1c720027, // ror ra0.8d, rb_y_coeffs_3, ra8.8c ++/* [0x00000f90] */ 0x10217f80, 0x1e5200e7, // ror ra3.8b, rb_y_coeffs_5, ra8.8d ++/* [0x00000f98] */ 0x10217f80, 0x1c520067, // ror ra1.8b, rb_y_coeffs_5, ra8.8c ++/* [0x00000fa0] */ 0x04040100, 0xe0020867, // mov r1,0x04040100 ++/* [0x00000fa8] */ 0x10227380, 0x1e6200e7, // ror ra3.8c, r1, ra8.8d ++/* [0x00000fb0] */ 0x902183bf, 0xdc624065, // ror ra1.8c, r1, ra8.8c ; mov r5rep, -8 ++/* [0x00000fb8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00000fc0] */ 0x3a281100, 0xe0020867, // mov r1,0x3a281100 ++/* [0x00000fc8] */ 0x902203bf, 0x1e02581e, // ror r0, r1, ra8.8d ; mov ra_link, unif ++/* [0x00000fd0] */ 0x90205387, 0x1c424048, // ror ra1.8a, r1, ra8.8c ; v8min rb8, r0, rb5 ++// ::mc_filter_y_pxx ++/* [0x00000fd8] */ 0xfffffe58, 0xf0f807a7, // brr ra_link, r:per_block_setup_8 ++/* [0x00000fe0] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x00000fe8] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x00000ff0] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00000ff8] */ 0x1158cdc0, 0xd4020867, // shl r1, ra_wt_off_l0, i_wt_den_p5 ++/* [0x00001000] */ 0x4c5a7cd6, 0x121245a0, // add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x00001008] */ 0x8d9c423f, 0x1042531d, // sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++// :1 ++/* [0x00001010] */ 0x4c745dbe, 0x100279c4, // add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++/* [0x00001018] */ 0x93440dff, 0xd40248a1, // max r2, ra_y, 0 ; mov r1, 0 ++/* [0x00001020] */ 0x9251e5f6, 0x1a0248a3, // min r2, r2, rb_max_y ; mov r3, ra_k1 ++/* [0x00001028] */ 0x4c450cd7, 0xa4224462, // add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++/* [0x00001030] */ 0x8c606cbf, 0x10024e05, // add t0s, ra_base, r2 ; mov rb5, rb6 ++/* [0x00001038] */ 0x8e5479bf, 0x12024806, // shr r0, r4, ra_xshift ; mov rb6, rb7 ++/* [0x00001040] */ 0x93458c47, 0xb20248a0, // max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 ++/* [0x00001048] */ 0x8e2009f6, 0x10024847, // shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++/* [0x00001050] */ 0x925de5ce, 0x120248a1, // min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x00001058] */ 0x4c450cd7, 0x12124462, // add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++/* [0x00001060] */ 0x8c24feb6, 0x10025f08, // add t1s, rb_base2, r2 ; mov ra8, ra9 ++/* [0x00001068] */ 0x4c038af1, 0xd8025962, // add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++/* [0x00001070] */ 0x5501fff0, 0x180348e2, // mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++/* [0x00001078] */ 0x4d03f6b0, 0xda0248a3, // sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++/* [0x00001080] */ 0x40037031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++/* [0x00001088] */ 0x4c03e4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001090] */ 0x40036031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++/* [0x00001098] */ 0x4d03d4f0, 0xde0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++/* [0x000010a0] */ 0x40035031, 0xde0109e3, // nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++/* [0x000010a8] */ 0x4c07c4f0, 0xd80248a3, // add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++/* [0x000010b0] */ 0x40074031, 0xd80109e3, // nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++/* [0x000010b8] */ 0x4c07b4f0, 0xda0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++/* [0x000010c0] */ 0x40073031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++/* [0x000010c8] */ 0x4d07a4f0, 0xdc0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++/* [0x000010d0] */ 0x40072031, 0xdc0109e3, // nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x000010d8] */ 0x4c0794f0, 0xde0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++/* [0x000010e0] */ 0x4c071b71, 0xde0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++/* [0x000010e8] */ 0xffffff08, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000010f0] */ 0x4d0854fe, 0x1a0248a1, // sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++/* [0x000010f8] */ 0x550caffe, 0x1a024260, // mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++/* [0x00001100] */ 0x8f2c05f6, 0xd00242ca, // asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00001108] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00001110] */ 0x4d08723e, 0x1e024860, // sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++/* [0x00001118] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++/* [0x00001120] */ 0x4c0ca23e, 0x1c024860, // add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00001128] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++/* [0x00001130] */ 0x8d5d1bf6, 0x1c0269e3, // sub.setf -, r5, rb_i_tmu ; mov r3, ra_blk_height ++/* [0x00001138] */ 0x8d1133bf, 0x1002884f, // sub r1, r1, ra4 ; mov.ifz rb_base2, rb_base2_next ++/* [0x00001140] */ 0x8d6a7236, 0x10029858, // sub r1, r1, r0 ; mov.ifz ra_base, ra_base_next ++/* [0x00001148] */ 0x8f4c63f6, 0xd0029851, // asr r1, r1, 6 ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00001150] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00001158] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x00001160] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x00001168] */ 0xfffffe88, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001170] */ 0x0f9cd3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x00001178] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001180] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00001188] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00001190] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001198] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000011a0] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000011a8] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000011b0] */ 0xfffffe40, 0xf0f809e7, // brr -, r:1b ++/* [0x000011b8] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x000011c0] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x000011c8] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y_bxx ++/* [0x000011d0] */ 0xfffffc60, 0xf0f807a7, // brr ra_link, r:per_block_setup_8 ++/* [0x000011d8] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x000011e0] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x000011e8] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x000011f0] */ 0x1158ddc0, 0xd4020867, // shl r1, ra_wt_off_l0, i_wt_den_p6 ++/* [0x000011f8] */ 0x4c5a7cd6, 0x121245a0, // add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x00001200] */ 0x4d4a7216, 0x12024860, // sub r1, r1, r0 ; mul24 r0, r2, ra_wt_mul_l1 ++/* [0x00001208] */ 0x8d9c423f, 0x1042531d, // sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++// :1 ++/* [0x00001210] */ 0x4c745dbe, 0x100279c4, // add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++/* [0x00001218] */ 0x93440dff, 0xd40248a1, // max r2, ra_y, 0 ; mov r1, 0 ++/* [0x00001220] */ 0x9251e5f6, 0x1a0248a3, // min r2, r2, rb_max_y ; mov r3, ra_k1 ++/* [0x00001228] */ 0x4c450cd7, 0xa4224462, // add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++/* [0x00001230] */ 0x8c606cbf, 0x10024e05, // add t0s, ra_base, r2 ; mov rb5, rb6 ++/* [0x00001238] */ 0x8e5479bf, 0x12024806, // shr r0, r4, ra_xshift ; mov rb6, rb7 ++/* [0x00001240] */ 0x93458c47, 0xb20248a0, // max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 ++/* [0x00001248] */ 0x8e2009f6, 0x10024847, // shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++/* [0x00001250] */ 0x925de5ce, 0x120248a1, // min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x00001258] */ 0x4c450cd7, 0x12124462, // add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++/* [0x00001260] */ 0x8c24feb6, 0x10025f08, // add t1s, rb_base2, r2 ; mov ra8, ra9 ++/* [0x00001268] */ 0x4c038af1, 0xd8025962, // add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++/* [0x00001270] */ 0x5501fff0, 0x180348e2, // mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++/* [0x00001278] */ 0x4d03f6b0, 0xda0248a3, // sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++/* [0x00001280] */ 0x40037031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++/* [0x00001288] */ 0x4c03e4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001290] */ 0x40036031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++/* [0x00001298] */ 0x4d03d4f0, 0xde0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++/* [0x000012a0] */ 0x40035031, 0xde0109e3, // nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++/* [0x000012a8] */ 0x4c07c4f0, 0xd80248a3, // add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++/* [0x000012b0] */ 0x40074031, 0xd80109e3, // nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++/* [0x000012b8] */ 0x4c07b4f0, 0xda0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++/* [0x000012c0] */ 0x40073031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++/* [0x000012c8] */ 0x4d07a4f0, 0xdc0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++/* [0x000012d0] */ 0x40072031, 0xdc0109e3, // nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x000012d8] */ 0x4c0794f0, 0xde0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++/* [0x000012e0] */ 0x4c071b71, 0xde0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++/* [0x000012e8] */ 0xffffff08, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000012f0] */ 0x4d0854fe, 0x1a0248a1, // sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++/* [0x000012f8] */ 0x550caffe, 0x1a024260, // mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++/* [0x00001300] */ 0x8f2c05f6, 0xd00242ca, // asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00001308] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00001310] */ 0x4d08723e, 0x1e024860, // sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++/* [0x00001318] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++/* [0x00001320] */ 0x4c0ca23e, 0x1c024860, // add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00001328] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++/* [0x00001330] */ 0x0d127380, 0x10020867, // sub r1, r1, ra4 ++/* [0x00001338] */ 0x8d9cc23f, 0x10024862, // sub r1, r1, r0 ; mov r2, rb_wt_off ++/* [0x00001340] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++/* [0x00001348] */ 0x4d591bce, 0x120269e0, // sub.setf -, r5, rb_i_tmu ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00001350] */ 0x55653fce, 0x140453e1, // mov.ifz rb_base2, rb_base2_next ; mul24 r1, r1, ra_kmul_add ++/* [0x00001358] */ 0x8d4e7076, 0x10029851, // sub r1, r0, r1 ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00001360] */ 0x8d692bf6, 0x1002b9d8, // sub.setf -, r5, rb_lcount ; mov.ifz ra_base, ra_base_next ++/* [0x00001368] */ 0x8c9f8289, 0xd0024860, // add r1, r1, r2 ; mov r0, r1 << 8 ++/* [0x00001370] */ 0x8c5e7236, 0x1c024863, // add r1, r1, r0 ; mov r3, ra_blk_height ++/* [0x00001378] */ 0xfffffe78, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001380] */ 0x4f65039f, 0x18024862, // asr r1, r1, ra_wt_den_p7 ; mul24 r2, r3, rb_pitch ++/* [0x00001388] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001390] */ 0xf34003f3, 0xd2024c20, // max vpm, r1, 0 ; v8subs r0, ra_height, r3 ++/* [0x00001398] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000013a0] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x000013a8] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000013b0] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000013b8] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000013c0] */ 0xfffffe30, 0xf0f809e7, // brr -, r:1b ++/* [0x000013c8] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x000013d0] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x000013d8] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y_p00 ++/* [0x000013e0] */ 0x959a0ff6, 0x10024020, // mov ra0, unif ; mov r0, elem_num ++/* [0x000013e8] */ 0xf5567dad, 0x14124565, // mov ra_xshift, ra_xshift_next ; v8subs r5rep, r5, r5 ++/* [0x000013f0] */ 0x8c020c3f, 0x1402581a, // add r0, ra0.16b, r0 ; mov ra_base_next, unif ++/* [0x000013f8] */ 0x93027176, 0x12225813, // max r0, r0, r5 ; mov ra_y_next, ra0.16a ++/* [0x00001400] */ 0x9281a1f6, 0x10025810, // min r0, r0, rb_max_x ; mov ra_width_height, unif ++/* [0x00001408] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00001410] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00001418] */ 0x8d810bf6, 0x10025896, // sub r2, r5, rb_pitch ; mov ra_wt_off_mul_l0, unif ++/* [0x00001420] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00001428] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00001430] */ 0x8c827076, 0x1002581c, // add r0, r0, r1 ; mov ra_dest, unif ++/* [0x00001438] */ 0x8c69cc3f, 0x100246b1, // add ra_base_next, ra_base_next, r0 ; mov vw_setup, rb_vpm_init ++/* [0x00001440] */ 0x11400dc0, 0xd4020867, // shl r1, ra_width, v_x_shift ++/* [0x00001448] */ 0x8d419e76, 0x12025760, // sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height ++/* [0x00001450] */ 0x8d5c31c6, 0xdc025460, // sub rb_i_tmu, r0, PREREAD ; v8min r0, r0, ra_blk_height ++/* [0x00001458] */ 0x919c71c0, 0xd0024812, // shl r0, r0, v_dma_h_shift ; mov rb_lcount, r0 ++/* [0x00001460] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00001468] */ 0x1158edc0, 0xd4021327, // shl rb_wt_off, ra_wt_off_l0, DENOM + 7 ++/* [0x00001470] */ 0x918101f6, 0xd002581e, // shl r0, r0, v_dma_wh_shift ; mov ra_link, unif ++/* [0x00001478] */ 0x0c9db1c0, 0x100206e7, // add ra_dma0, r0, rb_dma0_base ++// :1 ++/* [0x00001480] */ 0xcd511bee, 0x1a0269e5, // sub.setf -, r5, rb_i_tmu ; v8adds r5rep, r5, ra_k1 ++/* [0x00001488] */ 0x804e7036, 0xa42099d1, // nop ; mov.ifz ra_y, ra_y_next ; ldtmu0 ++/* [0x00001490] */ 0x8e5509bf, 0x12024823, // shr r0, r4, ra_xshift ; mov r3, rb_pitch ++/* [0x00001498] */ 0x13440dc0, 0xd40208a7, // max r2, ra_y, 0 ++/* [0x000014a0] */ 0x9269e5f6, 0x10029898, // min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++/* [0x000014a8] */ 0x4c441dd3, 0xd4224462, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++/* [0x000014b0] */ 0x8c618c87, 0x10024e20, // add t0s, ra_base, r2 ; v8min r0, r0, rb_pmask ++/* [0x000014b8] */ 0x4d592bc6, 0x120269e1, // sub.setf -, r5, rb_lcount ; mul24 r1, r0, ra_wt_mul_l0 ++/* [0x000014c0] */ 0x915c83f6, 0xdc024863, // shl r1, r1, 8 ; mov r3, ra_blk_height ++/* [0x000014c8] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x000014d0] */ 0xffffff90, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000014d8] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, DENOM + 8 ++/* [0x000014e0] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x000014e8] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x000014f0] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000014f8] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001500] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00001508] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00001510] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00001518] */ 0xffffff48, 0xf0f809e7, // brr -, r:1b ++/* [0x00001520] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00001528] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00001530] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y_b00 ++/* [0x00001538] */ 0xfffff8f8, 0xf0f807a7, // brr ra_link, r:per_block_setup_8 ++/* [0x00001540] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x00001548] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x00001550] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00001558] */ 0x00000001, 0xe00208a7, // mov r2, 1 ++/* [0x00001560] */ 0x8c591eb6, 0x10025461, // add rb_i_tmu, rb_i_tmu, r2 ; mov r1, ra_wt_off_mul_l0 ++/* [0x00001568] */ 0xf158fded, 0xd4025325, // shl rb_wt_off, ra_wt_off_l0, DENOM + 8 ; v8subs r5quad, r5, r5 ++/* [0x00001570] */ 0x809f8009, 0xd000d9d6, // nop ; mov.ifnz ra_wt_off_mul_l0, r1 << 8 ++// :1 ++/* [0x00001578] */ 0x0d9d1bc0, 0xb00229e7, // sub.setf -, r5, rb_i_tmu ; nop ; ldtmu1 ++/* [0x00001580] */ 0x8e4c09f6, 0xa0029851, // shr r1, r4, rb_xshift2 ; mov.ifz ra_y_y2, ra_y_y2_next ; ldtmu0 ++/* [0x00001588] */ 0x8e5509bf, 0x12024823, // shr r0, r4, ra_xshift ; mov r3, rb_pitch ++/* [0x00001590] */ 0x13440dc0, 0xd40208a7, // max r2, ra_y, 0 ++/* [0x00001598] */ 0x9269e5f6, 0x10029898, // min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++/* [0x000015a0] */ 0x4c441dd3, 0xd4224462, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++/* [0x000015a8] */ 0x8c613cbf, 0x10028e0f, // add t0s, ra_base, r2 ; mov.ifz rb_base2, rb_base2_next ++/* [0x000015b0] */ 0x13440dc0, 0xd20208a7, // max r2, ra_y2, 0 ++/* [0x000015b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_max_y ++/* [0x000015c0] */ 0x4c441dd3, 0xd2124462, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++/* [0x000015c8] */ 0x8c5cfe86, 0x12024f20, // add t1s, rb_base2, r2 ; v8min r0, r0, ra_pmax ++/* [0x000015d0] */ 0x545983c6, 0x12024860, // and r1, r1, rb_pmask ; mul24 r0, r0, ra_wt_mul_l0 ++/* [0x000015d8] */ 0x4d492bce, 0x120269e1, // sub.setf -, r5, rb_lcount ; mul24 r1, r1, ra_wt_mul_l1 ++/* [0x000015e0] */ 0xcc52706e, 0x1a024865, // add r1, r0, r1 ; v8adds r5rep, r5, ra_k1 ++/* [0x000015e8] */ 0x915c83f6, 0xdc024863, // shl r1, r1, 8 ; mov r3, ra_blk_height ++/* [0x000015f0] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x000015f8] */ 0xffffff60, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001600] */ 0x0f9d03c0, 0xd0020867, // asr r1, r1, (DENOM + 9) - 32 ++/* [0x00001608] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001610] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00001618] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00001620] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001628] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00001630] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00001638] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00001640] */ 0xffffff18, 0xf0f809e7, // brr -, r:1b ++/* [0x00001648] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00001650] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00001658] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_setup_c10_q0 ++/* [0x00001660] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_setup_c10_qn ++/* [0x00001668] */ 0x95801ff6, 0xd0025900, // mov tmurs, 1 ; mov ra0, unif ++/* [0x00001670] */ 0xaaaaff00, 0xe6020827, // mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++/* [0x00001678] */ 0x9181e1f6, 0xd00250d8, // shl rb_ef, r0, i_shift30 ; mov ra_base, unif ++/* [0x00001680] */ 0x0d801dc0, 0xd0020827, // sub r0, unif, 1 ++/* [0x00001688] */ 0x119c21c0, 0xd00216a7, // shl rb_max_x, r0, v_x_shift ++/* [0x00001690] */ 0x0d801dc0, 0xd00217a7, // sub rb_max_y, unif, 1 ++/* [0x00001698] */ 0xff800100, 0xe0020527, // mov ra_kff800100, 0xff800100 ++/* [0x000016a0] */ 0x0000ffff, 0xe0021627, // mov rb_pmask, v_pmask ++/* [0x000016a8] */ 0x000803ff, 0xe00205e7, // mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++/* [0x000016b0] */ 0x00010000, 0xe00217e7, // mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++/* [0x000016b8] */ 0x4000000c, 0xe0020667, // mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++/* [0x000016c0] */ 0x95803ff6, 0x10024754, // mov ra_ef, rb_ef ; mov rb_xpitch, unif ++/* [0x000016c8] */ 0x15827d80, 0x10021427, // mov rb_pitch, unif ++/* [0x000016d0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++/* [0x000016d8] */ 0x0c9d03c0, 0x10021667, // add rb_dma1_base, r1, rb_pitch ++/* [0x000016e0] */ 0x14981f80, 0xd0020827, // and r0, 1, elem_num ++/* [0x000016e8] */ 0x409c5007, 0xd00049e0, // nop ; mul24 r0, r0, 5 ++/* [0x000016f0] */ 0x0c9a7180, 0x10020827, // add r0, r0, elem_num ++/* [0x000016f8] */ 0x0c9e7000, 0x100210a7, // add rb_elem_x, r0, r0 ++/* [0x00001700] */ 0x11002dc0, 0xd4020827, // shl r0, ra0.16b, v_x_shift ++/* [0x00001708] */ 0x0c9c21c0, 0x10020827, // add r0, r0, rb_elem_x ++/* [0x00001710] */ 0x930001f6, 0xd2225811, // max r0, r0, 0 ; mov ra_y, ra0.16a ++/* [0x00001718] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00001720] */ 0x00000000, 0xe0224541, // mov ra_xshift_next, 0 ; mov rb_xshift2_next, 0 ++/* [0x00001728] */ 0x0d510dc0, 0x18020867, // sub r1, ra_k0, rb_pitch ++/* [0x00001730] */ 0x149e7040, 0x10020867, // and r1, r0, r1 ++/* [0x00001738] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00001740] */ 0x8c827076, 0x10025800, // add r0, r0, r1 ; mov ra0, unif ++/* [0x00001748] */ 0x0c627c00, 0x10020627, // add ra_base, ra_base, r0 ++/* [0x00001750] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++/* [0x00001758] */ 0x0f9c15c0, 0xd0020867, // asr r1, r2, 1 ++/* [0x00001760] */ 0x119c43c0, 0xd0020867, // shl r1, r1, 4 ++/* [0x00001768] */ 0x149c15c0, 0xd0020827, // and r0, r2, 1 ++/* [0x00001770] */ 0x159e7040, 0x10020827, // or r0, r0, r1 ++/* [0x00001778] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++/* [0x00001780] */ 0x0c9e7040, 0x10021727, // add r_vpm, r0, r1 ++/* [0x00001788] */ 0x80004002, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h16p(0,0,0)) ++/* [0x00001790] */ 0x119c61c0, 0xd0020827, // shl r0, r0, 6 ++/* [0x00001798] */ 0x0c9e7040, 0x100216e7, // add r_dma, r0, r1 ++/* [0x000017a0] */ 0x11002dc0, 0xd4020827, // shl r0, ra0.16b, v_x_shift ++/* [0x000017a8] */ 0x8c0021f6, 0x12125811, // add r0, r0, rb_elem_x ; mov ra_y2, ra0.16a ++/* [0x000017b0] */ 0x938001f6, 0xd002480f, // max r0, r0, 0 ; mov rb_base2, unif ++/* [0x000017b8] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x000017c0] */ 0x0d510dc0, 0x18020867, // sub r1, ra_k0, rb_pitch ++/* [0x000017c8] */ 0x949c307f, 0xd0024863, // and r1, r0, r1 ; mov r3, PREREAD ++/* [0x000017d0] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x000017d8] */ 0x8c467076, 0x12024822, // add r0, r0, r1 ; mov r2, ra_y2 ++/* [0x000017e0] */ 0x8c44fe36, 0x140253e0, // add rb_base2, rb_base2, r0 ; mov r0, ra_y ++// :1 ++/* [0x000017e8] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x000017f0] */ 0x139c01c0, 0xd0020867, // max r1, r0, 0 ++/* [0x000017f8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x00001800] */ 0x4c51018f, 0x1a024821, // add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x00001808] */ 0x8c627c40, 0x10225e11, // add t0s, ra_base, r1 ; mov ra_y, r0 ++/* [0x00001810] */ 0x139c05c0, 0xd0020867, // max r1, r2, 0 ++/* [0x00001818] */ 0xffffffb0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x00001820] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x00001828] */ 0x4c51058f, 0x1a0248a1, // add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x00001830] */ 0x8c9cfe52, 0x10125f11, // add t1s, rb_base2, r1 ; mov ra_y2, r2 ++/* [0x00001838] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00001840] */ 0x00000000, 0xe0024104, // mov ra4, 0 ; mov rb4, 0 ++/* [0x00001848] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00001850] */ 0x00000000, 0xe0024145, // mov ra5, 0 ; mov rb5, 0 ++/* [0x00001858] */ 0x00000000, 0xe0024186, // mov ra6, 0 ; mov rb6, 0 ++/* [0x00001860] */ 0x00000000, 0xe00241c7, // mov ra7, 0 ; mov rb7, 0 ++// ::mc_filter_c10_p ++/* [0x00001868] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00001870] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00001878] */ 0xf1082dc0, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r0, r0 ++/* [0x00001880] */ 0x8c8021f6, 0x10025810, // add r0, r0, rb_elem_x ; mov ra_width_height, unif ++/* [0x00001888] */ 0x8d810bf6, 0x10025840, // sub r1, r5, rb_pitch ; mov ra0, unif ++/* [0x00001890] */ 0x93567176, 0x14024800, // max r0, r0, r5 ; mov vrx_xshift, vrx_xshift_next ++/* [0x00001898] */ 0x9209a1f6, 0x12225813, // min r0, r0, rb_max_x ; mov vra_y_next, ra2.16a ++/* [0x000018a0] */ 0x54404077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x000018a8] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x000018b0] */ 0x8c827076, 0x10025803, // add r0, r0, r1 ; mov ra3, unif ++/* [0x000018b8] */ 0x8c427636, 0x120246a1, // add vrx_base_next, r3, r0 ; mov r1, ra_height ++/* [0x000018c0] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x000018c8] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x000018d0] */ 0x8c81f3f6, 0xd0039496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_off_mul_l0, unif ++/* [0x000018d8] */ 0x918083f6, 0xd002581c, // shl r0, r1, v_dma_h_shift ; mov ra_dest, unif ++/* [0x000018e0] */ 0x8c6670b6, 0x14024822, // add r0, r0, r2 ; mov r2, ra_fir_off_val ++/* [0x000018e8] */ 0x910cf1f6, 0xdc02480a, // shl r0, r0, v_dma_wh_shift ; mov rb10, ra3.8c ++/* [0x000018f0] */ 0x8c59b1f6, 0x140246e1, // add ra_dma0, r0, rb_dma0_base ; mov r1, ra_wt_off_l0 ++/* [0x000018f8] */ 0x5158a3d6, 0xd2024860, // shl r1, r1, i_wt_den_p5 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x00001900] */ 0x8d667236, 0x14025320, // sub rb_wt_off, r1, r0 ; mov r0, ra_kmul_add ++/* [0x00001908] */ 0x8c59cc3f, 0xd21245a5, // add ra_wt_mul_l0, ra_wt_mul_l0, r0 ; mov r5rep, -4 ++/* [0x00001910] */ 0x950e0dbf, 0x1e0252de, // mov rb11, ra3.8d ; mov ra_link, unif ++// :1 ++/* [0x00001918] */ 0x8d151bf6, 0xa00269c4, // sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu0 ++/* [0x00001920] */ 0x8e4c09f6, 0x140288a3, // shr r2, r4, vrx_xshift ; mov.ifz r3, vra_y_next ++/* [0x00001928] */ 0x8e4505f6, 0xd402c863, // shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++/* [0x00001930] */ 0x8c683ff6, 0x1002b9d8, // add.setf -, rb_ef, rb_ef ; mov.ifz vra_base, vrx_base_next ++/* [0x00001938] */ 0x8c531789, 0xda224460, // add vra_y, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x00001940] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x00001948] */ 0x929de7d2, 0x1003c8e0, // min r3, r3, rb_max_y ; mov.ifnc r0, r2 ++/* [0x00001950] */ 0x545d039f, 0x12024863, // and r1, r1, ra_pmax ; mul24 r3, r3, rb_pitch ++/* [0x00001958] */ 0x8c618cc7, 0x10024e20, // add vr_txs, vra_base, r3 ; v8min r0, r0, rb_pmask ++/* [0x00001960] */ 0x4c001bf0, 0xd8025963, // add r5rep, r5, 1 ; mul24 r3, ra0.8a, r0 ++/* [0x00001968] */ 0x4d01fef1, 0x1e0248a3, // sub r2, rb_fir_off_h, r3 ; mul24 r3, ra0.8d, r1 ++/* [0x00001970] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001978] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00001980] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00001988] */ 0x4c032b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00001990] */ 0xffffff68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001998] */ 0x4c1ca4f7, 0x100248a0, // add r2, r2, r3 ; mul24 r0, ra7, rb10 ++/* [0x000019a0] */ 0x550c6ffe, 0x1a024161, // mov ra5, rb6 ; mul24 r1, rb6, ra3.8b ++/* [0x000019a8] */ 0x8f1c25f6, 0xd00241c6, // asr ra7, r2, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x000019b0] */ 0x4c0c423e, 0x18024860, // add r1, r1, r0 ; mul24 r0, rb4, ra3.8a ++/* [0x000019b8] */ 0x4d1cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra7, rb11 ++/* [0x000019c0] */ 0x0d9e7200, 0x10020867, // sub r1, r1, r0 ++/* [0x000019c8] */ 0x8f5c63f6, 0xdc024863, // asr r1, r1, 6 ; mov r3, ra_blk_height ++/* [0x000019d0] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x000019d8] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x000019e0] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x000019e8] */ 0xffffff10, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000019f0] */ 0x0f9cb3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x000019f8] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001a00] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00001a08] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00001a10] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001a18] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00001a20] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00001a28] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00001a30] */ 0xfffffec8, 0xf0f809e7, // brr -, r:1b ++/* [0x00001a38] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00001a40] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00001a48] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_c10_p_l1 ++/* [0x00001a50] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00001a58] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00001a60] */ 0xf1082dc0, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r0, r0 ++/* [0x00001a68] */ 0x8c8021f6, 0x10025810, // add r0, r0, rb_elem_x ; mov ra_width_height, unif ++/* [0x00001a70] */ 0x8d810bf6, 0x10025840, // sub r1, r5, rb_pitch ; mov ra0, unif ++/* [0x00001a78] */ 0x939c117f, 0x10125815, // max r0, r0, r5 ; mov vrx_xshift, vrx_xshift_next ++/* [0x00001a80] */ 0x9209a1f6, 0x12125813, // min r0, r0, rb_max_x ; mov vra_y_next, ra2.16a ++/* [0x00001a88] */ 0x54404077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x00001a90] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00001a98] */ 0x8c827076, 0x10025803, // add r0, r0, r1 ; mov ra3, unif ++/* [0x00001aa0] */ 0x8c427636, 0x120254e1, // add vrx_base_next, r3, r0 ; mov r1, ra_height ++/* [0x00001aa8] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x00001ab0] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x00001ab8] */ 0x8c81f3f6, 0xd0039496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_off_mul_l0, unif ++/* [0x00001ac0] */ 0x918083f6, 0xd002581c, // shl r0, r1, v_dma_h_shift ; mov ra_dest, unif ++/* [0x00001ac8] */ 0x8c6670b6, 0x14024822, // add r0, r0, r2 ; mov r2, ra_fir_off_val ++/* [0x00001ad0] */ 0x910cf1f6, 0xdc02480a, // shl r0, r0, v_dma_wh_shift ; mov rb10, ra3.8c ++/* [0x00001ad8] */ 0x8c59b1f6, 0x140246e1, // add ra_dma0, r0, rb_dma0_base ; mov r1, ra_wt_off_l0 ++/* [0x00001ae0] */ 0x5158a3d6, 0xd2024860, // shl r1, r1, i_wt_den_p5 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x00001ae8] */ 0x8d667236, 0x14025320, // sub rb_wt_off, r1, r0 ; mov r0, ra_kmul_add ++/* [0x00001af0] */ 0x8c59cc3f, 0xd21245a5, // add ra_wt_mul_l0, ra_wt_mul_l0, r0 ; mov r5rep, -4 ++/* [0x00001af8] */ 0x950e0dbf, 0x1e0252de, // mov rb11, ra3.8d ; mov ra_link, unif ++// :1 ++/* [0x00001b00] */ 0x8d151bf6, 0xb00269c4, // sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu1 ++/* [0x00001b08] */ 0x8e5539bf, 0x1202888f, // shr r2, r4, vrx_xshift ; mov.ifz vra_base, vrx_base_next ++/* [0x00001b10] */ 0x8e4505f6, 0xd202c863, // shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++/* [0x00001b18] */ 0x8c4c3ff6, 0x1202a9e3, // add.setf -, rb_ef, rb_ef ; mov.ifz r3, vra_y_next ++/* [0x00001b20] */ 0x8c531789, 0xda124460, // add vra_y, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x00001b28] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x00001b30] */ 0x929de7d2, 0x1003c8e0, // min r3, r3, rb_max_y ; mov.ifnc r0, r2 ++/* [0x00001b38] */ 0x545d039f, 0x12024863, // and r1, r1, ra_pmax ; mul24 r3, r3, rb_pitch ++/* [0x00001b40] */ 0x8c5cfec6, 0x12024f20, // add vr_txs, vra_base, r3 ; v8min r0, r0, ra_pmax ++/* [0x00001b48] */ 0x4c001bf0, 0xd8025963, // add r5rep, r5, 1 ; mul24 r3, ra0.8a, r0 ++/* [0x00001b50] */ 0x4d01fef1, 0x1e0248a3, // sub r2, rb_fir_off_h, r3 ; mul24 r3, ra0.8d, r1 ++/* [0x00001b58] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001b60] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00001b68] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00001b70] */ 0x4c032b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00001b78] */ 0xffffff68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001b80] */ 0x4c1ca4f7, 0x100248a0, // add r2, r2, r3 ; mul24 r0, ra7, rb10 ++/* [0x00001b88] */ 0x550c6ffe, 0x1a024161, // mov ra5, rb6 ; mul24 r1, rb6, ra3.8b ++/* [0x00001b90] */ 0x8f1c25f6, 0xd00241c6, // asr ra7, r2, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x00001b98] */ 0x4c0c423e, 0x18024860, // add r1, r1, r0 ; mul24 r0, rb4, ra3.8a ++/* [0x00001ba0] */ 0x4d1cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra7, rb11 ++/* [0x00001ba8] */ 0x0d9e7200, 0x10020867, // sub r1, r1, r0 ++/* [0x00001bb0] */ 0x8f5c63f6, 0xdc024863, // asr r1, r1, 6 ; mov r3, ra_blk_height ++/* [0x00001bb8] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00001bc0] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x00001bc8] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x00001bd0] */ 0xffffff10, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001bd8] */ 0x0f9cb3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x00001be0] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001be8] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00001bf0] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00001bf8] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001c00] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00001c08] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00001c10] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00001c18] */ 0xfffffec8, 0xf0f809e7, // brr -, r:1b ++/* [0x00001c20] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00001c28] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00001c30] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_c10_b ++/* [0x00001c38] */ 0x9581cff6, 0x10025c42, // mov vw_setup, rb_vpm_init ; mov ra2, unif ++/* [0x00001c40] */ 0x8c803ff6, 0x100269e3, // add.setf -, rb_ef, rb_ef ; mov r3, unif ++/* [0x00001c48] */ 0xf1082dc9, 0xd4024825, // shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r1, r1 ++/* [0x00001c50] */ 0x8c0821f6, 0x12225813, // add r0, r0, rb_elem_x ; mov ra_y_next, ra2.16a ++/* [0x00001c58] */ 0x8d810bf6, 0x10025850, // sub r1, r5, rb_pitch ; mov ra_width_height, unif ++/* [0x00001c60] */ 0x93567176, 0x14125815, // max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++/* [0x00001c68] */ 0x9281a1f6, 0x10025800, // min r0, r0, rb_max_x ; mov ra0, unif ++/* [0x00001c70] */ 0x9481c1f6, 0xd0025802, // and r0, r0, -4 ; mov ra2, unif ++/* [0x00001c78] */ 0x54404077, 0xd4024862, // and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul ++/* [0x00001c80] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00001c88] */ 0x8c427076, 0x12024821, // add r0, r0, r1 ; mov r1, ra_height ++/* [0x00001c90] */ 0x8c9c163f, 0x10024680, // add ra_base_next, r3, r0 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00001c98] */ 0x8d819eb6, 0x10025756, // sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif ++/* [0x00001ca0] */ 0x8c5dc3ce, 0xdc025461, // add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++/* [0x00001ca8] */ 0x8c59f3f6, 0xd4139496, // add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_mul_l0, ra_wt_off_l0 ++/* [0x00001cb0] */ 0x918083f6, 0xd0025803, // shl r0, r1, v_dma_h_shift ; mov ra3, unif ++/* [0x00001cb8] */ 0x8c8270b6, 0x10024823, // add r0, r0, r2 ; mov r3, unif ++/* [0x00001cc0] */ 0x910cf1f6, 0xd2125813, // shl r0, r0, v_dma_wh_shift ; mov ra_y2_next, ra3.16a ++/* [0x00001cc8] */ 0x8c0db1f6, 0x140246e0, // add ra_dma0, r0, rb_dma0_base ; mov r0, ra3.16b ++/* [0x00001cd0] */ 0x918021f6, 0xd0025801, // shl r0, r0, v_x_shift ; mov ra1, unif ++/* [0x00001cd8] */ 0x8c8021f6, 0x10025803, // add r0, r0, rb_elem_x ; mov ra3, unif ++/* [0x00001ce0] */ 0x8d810bf6, 0x10025852, // sub r1, r5, rb_pitch ; mov ra_wt_off_mul_l1, unif ++/* [0x00001ce8] */ 0x939de17f, 0x10025809, // max r0, r0, r5 ; mov ra9, rb_max_y ++/* [0x00001cf0] */ 0x9265a1f6, 0x14024822, // min r0, r0, rb_max_x ; mov r2, ra_kmul_add ++/* [0x00001cf8] */ 0x9481c1f6, 0xd0039812, // and r0, r0, -4 ; mov.ifc ra_wt_off_mul_l1, unif ++/* [0x00001d00] */ 0x949dc07f, 0xd0024865, // and r1, r0, r1 ; mov r5rep, -4 ++/* [0x00001d08] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00001d10] */ 0x8c827076, 0x1002581c, // add r0, r0, r1 ; mov ra_dest, unif ++/* [0x00001d18] */ 0x8c667636, 0x140254e0, // add rb_base2_next, r3, r0 ; mov r0, ra_fir_off_val ++/* [0x00001d20] */ 0x4c5a7c86, 0x121245a1, // add ra_wt_mul_l0, ra_wt_mul_l0, r2 ; mul24 r1, r0, ra_wt_mul_l0 ++/* [0x00001d28] */ 0x4c4a7c86, 0x121244a0, // add ra_wt_mul_l1, ra_wt_mul_l1, r2 ; mul24 r0, r0, ra_wt_mul_l1 ++/* [0x00001d30] */ 0x8c4a7076, 0x14024821, // add r0, r0, r1 ; mov r1, ra_wt_off_l1 ++/* [0x00001d38] */ 0x910cb3f6, 0xde02484b, // shl r1, r1, i_wt_den_p6 ; mov rb11, ra3.8d ++/* [0x00001d40] */ 0x8d827236, 0x1002531e, // sub rb_wt_off, r1, r0 ; mov ra_link, unif ++/* [0x00001d48] */ 0x95080ff6, 0x1e024287, // mov ra10, rb_xshift2 ; mov rb7, ra2.8d ++// :1 ++/* [0x00001d50] */ 0x0d9d1bc0, 0xa00229e7, // sub.setf -, r5, rb_i_tmu ; nop ; ldtmu0 ++/* [0x00001d58] */ 0x8e5539bf, 0x1202888f, // shr r2, r4, ra_xshift ; mov.ifz rb_base2, rb_base2_next ++/* [0x00001d60] */ 0x8e4d05f6, 0xd0029851, // shr r1, r2, v_v_shift ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00001d68] */ 0x8c683ff6, 0x1002b9d8, // add.setf -, rb_ef, rb_ef ; mov.ifz ra_base, ra_base_next ++/* [0x00001d70] */ 0x8c441fb6, 0xd4224463, // add ra_y, 1, ra_y ; mov r3, ra_y ++/* [0x00001d78] */ 0x93531789, 0xd80248e0, // max r3, r3, ra_k0 ; mov r0, r1 << 15 ++/* [0x00001d80] */ 0x9227f792, 0xd003c8e1, // min r3, r3, ra9 ; mov.ifnc r1, r2 << 1 ++/* [0x00001d88] */ 0x559d049f, 0x100e4823, // mov.ifnc r0, r2 ; mul24 r3, r3, rb_pitch ++/* [0x00001d90] */ 0x8c618cc7, 0x10024e20, // add t0s, ra_base, r3 ; v8min r0, r0, rb_pmask ++/* [0x00001d98] */ 0x540183f0, 0x18024862, // and r1, r1, rb_pmask ; mul24 r2, ra0.8a, r0 ++/* [0x00001da0] */ 0x4d01feb1, 0x1e0248a3, // sub r2, rb_fir_off_h, r2 ; mul24 r3, ra0.8d, r1 ++/* [0x00001da8] */ 0x4d03e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001db0] */ 0x40034031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00001db8] */ 0x4c03c4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00001dc0] */ 0x40032031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00001dc8] */ 0x4c0854fe, 0xb8025804, // add r0, r2, r3 ; mul24 ra4, rb5, ra2.8a ; ldtmu1 ++/* [0x00001dd0] */ 0x8e2869bf, 0x10024885, // shr r2, r4, ra10 ; mov rb5, rb6 ++/* [0x00001dd8] */ 0x8e4505f6, 0xd2024863, // shr r1, r2, v_v_shift ; mov r3, ra_y2 ++/* [0x00001de0] */ 0x8e1c21f6, 0xd00241c6, // shr ra7, r0, v_bit_depth - 8 ; mov rb6, ra7 ++/* [0x00001de8] */ 0x8c531789, 0xda124460, // add ra_y2, r3, ra_k1 ; mov r0, r1 << 15 ++/* [0x00001df0] */ 0x9353f792, 0xd803c8e1, // max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++/* [0x00001df8] */ 0x925de7ce, 0x120248e1, // min r3, r3, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x00001e00] */ 0x559d049f, 0x100e4823, // mov.ifnc r0, r2 ; mul24 r3, r3, rb_pitch ++/* [0x00001e08] */ 0x8c5cfec6, 0x12024f20, // add t1s, rb_base2, r3 ; v8min r0, r0, ra_pmax ++/* [0x00001e10] */ 0x4c041bf0, 0xd8025962, // add r5rep, r5, 1 ; mul24 r2, ra1.8a, r0 ++/* [0x00001e18] */ 0x4d05feb1, 0x1e0248a3, // sub r2, rb_fir_off_h, r2 ; mul24 r3, ra1.8d, r1 ++/* [0x00001e20] */ 0x4d07e4f0, 0xda0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8b << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00001e28] */ 0x40074031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00001e30] */ 0x4c07c6b0, 0xdc0248a3, // add r2, r3, r2 ; mul24 r3, ra1.8c << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00001e38] */ 0x4c072b71, 0xdc0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00001e40] */ 0xfffffef0, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001e48] */ 0x4c0c94fe, 0x180248a0, // add r2, r2, r3 ; mul24 r0, rb9, ra3.8a ++/* [0x00001e50] */ 0x550caffe, 0x1a025261, // mov rb9, rb10 ; mul24 r1, rb10, ra3.8b ++/* [0x00001e58] */ 0x8e2c25f6, 0xd00242ca, // shr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00001e60] */ 0x4d08523e, 0x1a0248a1, // sub r2, r1, r0 ; mul24 r1, rb5, ra2.8b ++/* [0x00001e68] */ 0x8d112bf6, 0x100269e0, // sub.setf -, r5, rb_lcount ; mov r0, ra4 ++/* [0x00001e70] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00001e78] */ 0x4c1c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra7, rb7 ++/* [0x00001e80] */ 0x4d0ca23e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00001e88] */ 0x4c2cb437, 0x100248a0, // add r2, r2, r0 ; mul24 r0, ra11, rb11 ++/* [0x00001e90] */ 0x0d9e7400, 0x100208a7, // sub r2, r2, r0 ++/* [0x00001e98] */ 0x0e9c63c0, 0xd0020867, // shr r1, r1, 6 ++/* [0x00001ea0] */ 0x4e5865ce, 0xd20248a0, // shr r2, r2, 6 ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00001ea8] */ 0x4c4a7456, 0x120248a1, // add r2, r2, r1 ; mul24 r1, r2, ra_wt_mul_l1 ++/* [0x00001eb0] */ 0x4c667216, 0x14024862, // add r1, r1, r0 ; mul24 r2, r2, ra_kmul_add ++/* [0x00001eb8] */ 0x8d5e72b6, 0x1c024863, // sub r1, r1, r2 ; mov r3, ra_blk_height ++/* [0x00001ec0] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x00001ec8] */ 0xfffffe68, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00001ed0] */ 0x0f667380, 0x18020867, // asr r1, r1, ra_wt_den_p7 ++/* [0x00001ed8] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00001ee0] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00001ee8] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00001ef0] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00001ef8] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00001f00] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00001f08] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00001f10] */ 0xfffffe20, 0xf0f809e7, // brr -, r:1b ++/* [0x00001f18] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00001f20] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00001f28] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_sync10_q0 ++/* [0x00001f30] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00001f38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00001f40] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001f48] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001f50] */ 0x00000010, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001f58] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00001f60] */ 0x0000001c, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001f68] */ 0x00000001, 0xe80009e7, // mov dst, srel(i) ++/* [0x00001f70] */ 0x0000000d, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q1 ++/* [0x00001f78] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00001f80] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00001f88] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00001f90] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x00001f98] */ 0x00000011, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001fa0] */ 0x00000002, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q2 ++/* [0x00001fa8] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00001fb0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00001fb8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00001fc0] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x00001fc8] */ 0x00000012, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00001fd0] */ 0x00000003, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q3 ++/* [0x00001fd8] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00001fe0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00001fe8] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00001ff0] */ 0x00000000, 0xe80009e7, // mov dst, srel(i) ++/* [0x00001ff8] */ 0x00000013, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002000] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_sync10_q4 ++/* [0x00002008] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002010] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002018] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002020] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002028] */ 0x00000014, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002030] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002038] */ 0x0000001d, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002040] */ 0x00000005, 0xe80009e7, // mov dst, srel(i) ++/* [0x00002048] */ 0x0000000e, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q5 ++/* [0x00002050] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002058] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002060] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002068] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x00002070] */ 0x00000015, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002078] */ 0x00000006, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q6 ++/* [0x00002080] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002088] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002090] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002098] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x000020a0] */ 0x00000016, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000020a8] */ 0x00000007, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q7 ++/* [0x000020b0] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x000020b8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x000020c0] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x000020c8] */ 0x00000004, 0xe80009e7, // mov dst, srel(i) ++/* [0x000020d0] */ 0x00000017, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000020d8] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_sync10_q8 ++/* [0x000020e0] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x000020e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x000020f0] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000020f8] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002100] */ 0x00000018, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002108] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002110] */ 0x0000001e, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002118] */ 0x00000009, 0xe80009e7, // mov dst, srel(i) ++/* [0x00002120] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q9 ++/* [0x00002128] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002130] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002138] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002140] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x00002148] */ 0x00000019, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002150] */ 0x0000000a, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q10 ++/* [0x00002158] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002160] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002168] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002170] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x00002178] */ 0x0000001a, 0xe80009e7, // mov dst, sacq(i) ++/* [0x00002180] */ 0x0000000b, 0xe80009e7, // mov dst, srel(i) ++// ::mc_sync10_q11 ++/* [0x00002188] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002190] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002198] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x000021a0] */ 0x00000008, 0xe80009e7, // mov dst, srel(i) ++/* [0x000021a8] */ 0x0000001b, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000021b0] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_exit_c10_q0 ++// ::mc_exit_y10_q0 ++/* [0x000021b8] */ 0x00000002, 0xe00228e7, // mov.setf r3, PREREAD - 1 ++// :1 ++/* [0x000021c0] */ 0xffffffe0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x000021c8] */ 0x009e7000, 0xa00009e7, // nop ; nop ; ldtmu0 ++/* [0x000021d0] */ 0x009e7000, 0xb00009e7, // nop ; nop ; ldtmu1 ++/* [0x000021d8] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x000021e0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x000021e8] */ 0x0000001c, 0xe80009e7, // mov dst, sacq(i) ++/* [0x000021f0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++/* [0x000021f8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1 ++/* [0x00002200] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_exit_c10_qn ++// ::mc_exit_y10_qn ++/* [0x00002208] */ 0x00000002, 0xe00228e7, // mov.setf r3, PREREAD - 1 ++// :1 ++/* [0x00002210] */ 0xffffffe0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x00002218] */ 0x009e7000, 0xa00009e7, // nop ; nop ; ldtmu0 ++/* [0x00002220] */ 0x009e7000, 0xb00009e7, // nop ; nop ; ldtmu1 ++/* [0x00002228] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x00002230] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++/* [0x00002238] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++/* [0x00002240] */ 0x009e7000, 0x100009e7, // nop ++/* [0x00002248] */ 0x009e7000, 0x100009e7, // nop ++// ::mc_setup_y10_q0 ++/* [0x00002250] */ 0x0000000c, 0xe80009e7, // mov dst, srel(i) ++// ::mc_setup_y10_qn ++/* [0x00002258] */ 0x95801ff6, 0xd0025900, // mov tmurs, 1 ; mov ra0, unif ++/* [0x00002260] */ 0x15827d80, 0x10020267, // mov ra9, unif ++/* [0x00002268] */ 0x15827d80, 0x10020067, // mov ra1, unif ++/* [0x00002270] */ 0xaaaaff00, 0xe6020827, // mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++/* [0x00002278] */ 0x9181e1f6, 0xd00250cb, // shl rb_ef, r0, i_shift30 ; mov ra11, unif ++/* [0x00002280] */ 0xff800100, 0xe0020527, // mov ra_kff800100, 0xff800100 ++/* [0x00002288] */ 0x0000ffff, 0xe0021627, // mov rb_pmask, v_pmask ++/* [0x00002290] */ 0x000803ff, 0xe00205e7, // mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++/* [0x00002298] */ 0x00010000, 0xe00217e7, // mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++/* [0x000022a0] */ 0x4000000c, 0xe0020667, // mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++/* [0x000022a8] */ 0x050b0a00, 0xe0021567, // mov rb_y_coeffs_2, 0x050b0a00 ++/* [0x000022b0] */ 0x11283a40, 0xe00215a7, // mov rb_y_coeffs_3, 0x11283a40 ++/* [0x000022b8] */ 0x0a0b0500, 0xe00215e7, // mov rb_y_coeffs_5, 0x0a0b0500 ++/* [0x000022c0] */ 0x15827d80, 0x100200e7, // mov ra3, unif ++/* [0x000022c8] */ 0x95803ff6, 0x10024754, // mov ra_ef, rb_ef ; mov rb_xpitch, unif ++/* [0x000022d0] */ 0x0d0c1dc0, 0xd4020827, // sub r0, ra3.16b, 1 ++/* [0x000022d8] */ 0x119c11c0, 0xd00216a7, // shl rb_max_x, r0, v_x_shift ++/* [0x000022e0] */ 0x0d0c1dc0, 0xd20217a7, // sub rb_max_y, ra3.16a, 1 ++/* [0x000022e8] */ 0x959a0dbf, 0x100248d0, // mov r3, elem_num ; mov rb_pitch, unif ++/* [0x000022f0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++/* [0x000022f8] */ 0x159d03c0, 0x10021667, // or rb_dma1_base, r1, rb_pitch ++/* [0x00002300] */ 0x0c027cc0, 0x14020827, // add r0, ra0.16b, r3 ++/* [0x00002308] */ 0x119c11c0, 0xd0020827, // shl r0, r0, v_x_shift ++/* [0x00002310] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 ++/* [0x00002318] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00002320] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00002328] */ 0xf49dc1d2, 0xd0024822, // and r0, r0, -4 ; v8subs r2, r2, r2 ++/* [0x00002330] */ 0x0d9d05c0, 0x100208a7, // sub r2, r2, rb_pitch ++/* [0x00002338] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00002340] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00002348] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00002350] */ 0x0c267c00, 0x10020627, // add ra_base, ra9, r0 ++/* [0x00002358] */ 0x0c067cc0, 0x14020827, // add r0, ra1.16b, r3 ++/* [0x00002360] */ 0x119c11c0, 0xd0020827, // shl r0, r0, v_x_shift ++/* [0x00002368] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 ++/* [0x00002370] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x00002378] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x00002380] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00002388] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00002390] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00002398] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x000023a0] */ 0x0c2e7c00, 0x100213e7, // add rb_base2, ra11, r0 ++/* [0x000023a8] */ 0x80027036, 0x120049e0, // nop ; mov r0, ra0.16a ++/* [0x000023b0] */ 0x95043ff6, 0xd20248e2, // mov r3, PREREAD ; mov r2, ra1.16a ++// :1 ++/* [0x000023b8] */ 0x0d9c17c0, 0xd00228e7, // sub.setf r3, r3, 1 ++/* [0x000023c0] */ 0x139c01c0, 0xd0020867, // max r1, r0, 0 ++/* [0x000023c8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x000023d0] */ 0x4c51018f, 0x1a024821, // add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x000023d8] */ 0x8c627c40, 0x10225e11, // add t0s, ra_base, r1 ; mov ra_y, r0 ++/* [0x000023e0] */ 0x139c05c0, 0xd0020867, // max r1, r2, 0 ++/* [0x000023e8] */ 0xffffffb0, 0xf03809e7, // brr.anynz -, r:1b ++/* [0x000023f0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_max_y ++/* [0x000023f8] */ 0x4c51058f, 0x1a0248a1, // add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++/* [0x00002400] */ 0x8c9cfe52, 0x10125f11, // add t1s, rb_base2, r1 ; mov ra_y2, r2 ++/* [0x00002408] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++/* [0x00002410] */ 0x0f9c15c0, 0xd0020867, // asr r1, r2, 1 ++/* [0x00002418] */ 0x119c43c0, 0xd0020867, // shl r1, r1, 4 ++/* [0x00002420] */ 0x149c15c0, 0xd0020827, // and r0, r2, 1 ++/* [0x00002428] */ 0x159e7040, 0x10020827, // or r0, r0, r1 ++/* [0x00002430] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++/* [0x00002438] */ 0x0c9e7040, 0x10021727, // add r_vpm, r0, r1 ++/* [0x00002440] */ 0x80004002, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h16p(0,0,0)) ++/* [0x00002448] */ 0x119c61c0, 0xd0020827, // shl r0, r0, 6 ++/* [0x00002450] */ 0x0c9e7040, 0x100216e7, // add r_dma, r0, r1 ++/* [0x00002458] */ 0x15827d80, 0x100207a7, // mov ra_link, unif ++/* [0x00002460] */ 0x00000000, 0xe0024208, // mov ra8, 0 ; mov rb8, 0 ++/* [0x00002468] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002470] */ 0x00000000, 0xe0024249, // mov ra9, 0 ; mov rb9, 0 ++/* [0x00002478] */ 0x00000000, 0xe002428a, // mov ra10, 0 ; mov rb10, 0 ++/* [0x00002480] */ 0x00000000, 0xe00242cb, // mov ra11, 0 ; mov rb11, 0 ++// :per_block_setup_10 ++/* [0x00002488] */ 0x119c11c0, 0xd0020827, // shl r0, r0, v_x_shift ++/* [0x00002490] */ 0x93567176, 0x14125815, // max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++/* [0x00002498] */ 0x129da1c0, 0x10020827, // min r0, r0, rb_max_x ++/* [0x000024a0] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x000024a8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x000024b0] */ 0x8d810bf6, 0x1002589a, // sub r2, r5, rb_pitch ; mov ra_base_next, unif ++/* [0x000024b8] */ 0x940270b6, 0x12225853, // and r1, r0, r2 ; mov ra_y_next, ra0.16a ++/* [0x000024c0] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x000024c8] */ 0x8c827076, 0x10025801, // add r0, r0, r1 ; mov ra1, unif ++/* [0x000024d0] */ 0x0c6a7c00, 0x100206a7, // add ra_base_next, ra_base_next, r0 ++/* [0x000024d8] */ 0x0c067cc0, 0x14020827, // add r0, ra1.16b, r3 ++/* [0x000024e0] */ 0x119c11c0, 0xd0020827, // shl r0, r0, v_x_shift ++/* [0x000024e8] */ 0x93067176, 0x12125813, // max r0, r0, r5 ; mov ra_y2_next, ra1.16a ++/* [0x000024f0] */ 0x9281a1f6, 0x10024813, // min r0, r0, rb_max_x ; mov rb_base2_next, unif ++/* [0x000024f8] */ 0x119c31c0, 0xd0021067, // shl rb_xshift2_next, r0, 3 ++/* [0x00002500] */ 0x9481c1f6, 0xd0025810, // and r0, r0, -4 ; mov ra_width_height, unif ++/* [0x00002508] */ 0x949dc0bf, 0x10024871, // and r1, r0, r2 ; mov vw_setup, rb_vpm_init ++/* [0x00002510] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00002518] */ 0x4c402077, 0xd4024821, // add r0, r0, r1 ; mul24 r1, ra_width, v_x_mul ++/* [0x00002520] */ 0x0c9d3e00, 0x100214e7, // add rb_base2_next, rb_base2_next, r0 ++/* [0x00002528] */ 0x8d419e76, 0x12025760, // sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height ++/* [0x00002530] */ 0x8c5dc1c6, 0xdc025460, // add rb_i_tmu, r0, (7-8) - PREREAD ; v8min r0, r0, ra_blk_height ++/* [0x00002538] */ 0x0c9df1c0, 0xd00214a7, // add rb_lcount, r0, (7-8) ++/* [0x00002540] */ 0x916481f6, 0xd4024823, // shl r0, r0, v_dma_h_shift ; mov r3, ra_kmul_add ++/* [0x00002548] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x00002550] */ 0x9164f1f6, 0xd4024822, // shl r0, r0, v_dma_wh_shift ; mov r2, ra_fir_off_val ++/* [0x00002558] */ 0x8c81b1f6, 0x100246e0, // add ra_dma0, r0, rb_dma0_base ; mov r0, unif ++/* [0x00002560] */ 0x918101f6, 0xd00a5816, // shl.ifnn r0, r0, i_shift16 ; mov ra_wt_off_mul_l0, unif ++/* [0x00002568] */ 0x915031f6, 0xde024205, // shl ra8, r0, 3 ; mov rb5, ra_k255 ++/* [0x00002570] */ 0x01040400, 0xe0020867, // mov r1, 0x01040400 ++/* [0x00002578] */ 0x10227380, 0x1e5200a7, // ror ra2.8b, r1, ra8.8d ++/* [0x00002580] */ 0x10227380, 0x1c520027, // ror ra0.8b, r1, ra8.8c ++/* [0x00002588] */ 0x10215f80, 0x1e6200a7, // ror ra2.8c, rb_y_coeffs_2, ra8.8d ++/* [0x00002590] */ 0x10215f80, 0x1c620027, // ror ra0.8c, rb_y_coeffs_2, ra8.8c ++/* [0x00002598] */ 0x00010100, 0xe0020867, // mov r1,0x00010100 ++/* [0x000025a0] */ 0x902203bf, 0x1e025812, // ror r0, r1, ra8.8d ; mov ra_wt_off_mul_l1, unif ++/* [0x000025a8] */ 0x90205387, 0x1c424004, // ror ra0.8a, r1, ra8.8c ; v8min rb4, r0, rb5 ++/* [0x000025b0] */ 0x914883f6, 0xd0031856, // shl r1, r1, 8 ; mov.ifn ra_wt_off_mul_l0, ra_wt_off_mul_l1 ++/* [0x000025b8] */ 0x902203bf, 0x1e02581c, // ror r0, r1, ra8.8d ; mov ra_dest, unif ++/* [0x000025c0] */ 0x90205387, 0x1c72404b, // ror ra1.8d, r1, ra8.8c ; v8min rb11, r0, rb5 ++/* [0x000025c8] */ 0x10216f80, 0x1e7200a7, // ror ra2.8d, rb_y_coeffs_3, ra8.8d ++/* [0x000025d0] */ 0x10216f80, 0x1c720027, // ror ra0.8d, rb_y_coeffs_3, ra8.8c ++/* [0x000025d8] */ 0x10217f80, 0x1e5200e7, // ror ra3.8b, rb_y_coeffs_5, ra8.8d ++/* [0x000025e0] */ 0x10217f80, 0x1c520067, // ror ra1.8b, rb_y_coeffs_5, ra8.8c ++/* [0x000025e8] */ 0x04040100, 0xe0020867, // mov r1,0x04040100 ++/* [0x000025f0] */ 0x10227380, 0x1e6200e7, // ror ra3.8c, r1, ra8.8d ++/* [0x000025f8] */ 0x902183bf, 0xdc624065, // ror ra1.8c, r1, ra8.8c ; mov r5rep, -8 ++/* [0x00002600] */ 0x00000000, 0xf0f7c9e7, // bra -, ra_link ++/* [0x00002608] */ 0x3a281100, 0xe0020867, // mov r1,0x3a281100 ++/* [0x00002610] */ 0x902203bf, 0x1e02581e, // ror r0, r1, ra8.8d ; mov ra_link, unif ++/* [0x00002618] */ 0x90205387, 0x1c424048, // ror ra1.8a, r1, ra8.8c ; v8min rb8, r0, rb5 ++// ::mc_filter_y10_pxx ++/* [0x00002620] */ 0xfffffe48, 0xf0f807a7, // brr ra_link, r:per_block_setup_10 ++/* [0x00002628] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x00002630] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x00002638] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00002640] */ 0x1158adc0, 0xd4020867, // shl r1, ra_wt_off_l0, i_wt_den_p5 ++/* [0x00002648] */ 0x4c5a7cd6, 0x121245a0, // add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x00002650] */ 0x8d9c423f, 0x1042531d, // sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++// :1 ++/* [0x00002658] */ 0x4c745dbe, 0x100279c4, // add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++/* [0x00002660] */ 0x93440dff, 0xd40248a1, // max r2, ra_y, 0 ; mov r1, 0 ++/* [0x00002668] */ 0x9251e5f6, 0x1a0248a3, // min r2, r2, rb_max_y ; mov r3, ra_k1 ++/* [0x00002670] */ 0x4c450cd7, 0xa4224462, // add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++/* [0x00002678] */ 0x8c606cbf, 0x10024e05, // add t0s, ra_base, r2 ; mov rb5, rb6 ++/* [0x00002680] */ 0x8e5479bf, 0x12024806, // shr r0, r4, ra_xshift ; mov rb6, rb7 ++/* [0x00002688] */ 0x93458c47, 0xb20248a0, // max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 ++/* [0x00002690] */ 0x8e2009f6, 0x10024847, // shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++/* [0x00002698] */ 0x925de5ce, 0x120248a1, // min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x000026a0] */ 0x4c450cd7, 0x12124462, // add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++/* [0x000026a8] */ 0x8c24feb6, 0x10025f08, // add t1s, rb_base2, r2 ; mov ra8, ra9 ++/* [0x000026b0] */ 0x4c038af1, 0xd8025962, // add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++/* [0x000026b8] */ 0x5501fff0, 0x180348e2, // mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++/* [0x000026c0] */ 0x4d03f6b0, 0xda0248a3, // sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++/* [0x000026c8] */ 0x40037031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++/* [0x000026d0] */ 0x4c03e4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++/* [0x000026d8] */ 0x40036031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++/* [0x000026e0] */ 0x4d03d4f0, 0xde0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++/* [0x000026e8] */ 0x40035031, 0xde0109e3, // nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++/* [0x000026f0] */ 0x4c07c4f0, 0xd80248a3, // add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++/* [0x000026f8] */ 0x40074031, 0xd80109e3, // nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00002700] */ 0x4c07b4f0, 0xda0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++/* [0x00002708] */ 0x40073031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++/* [0x00002710] */ 0x4d07a4f0, 0xdc0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++/* [0x00002718] */ 0x40072031, 0xdc0109e3, // nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00002720] */ 0x4c0794f0, 0xde0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++/* [0x00002728] */ 0x4c071b71, 0xde0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++/* [0x00002730] */ 0xffffff08, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00002738] */ 0x4d0854fe, 0x1a0248a1, // sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++/* [0x00002740] */ 0x550caffe, 0x1a024260, // mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++/* [0x00002748] */ 0x8f2c25f6, 0xd00242ca, // asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00002750] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00002758] */ 0x4d08723e, 0x1e024860, // sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++/* [0x00002760] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++/* [0x00002768] */ 0x4c0ca23e, 0x1c024860, // add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00002770] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++/* [0x00002778] */ 0x8d5d1bf6, 0x1c0269e3, // sub.setf -, r5, rb_i_tmu ; mov r3, ra_blk_height ++/* [0x00002780] */ 0x8d1133bf, 0x1002884f, // sub r1, r1, ra4 ; mov.ifz rb_base2, rb_base2_next ++/* [0x00002788] */ 0x8d6a7236, 0x10029858, // sub r1, r1, r0 ; mov.ifz ra_base, ra_base_next ++/* [0x00002790] */ 0x8f4c63f6, 0xd0029851, // asr r1, r1, 6 ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00002798] */ 0x4d592bce, 0x120269e0, // sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x000027a0] */ 0x4c64c1ce, 0x14024821, // add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++/* [0x000027a8] */ 0xed427073, 0x12024860, // sub r1, r0, r1 ; v8subs r0, ra_height, r3 ++/* [0x000027b0] */ 0xfffffe88, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x000027b8] */ 0x0f9cb3c0, 0xd0020867, // asr r1, r1, i_wt_den_p6 ++/* [0x000027c0] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x000027c8] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x000027d0] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x000027d8] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x000027e0] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x000027e8] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x000027f0] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x000027f8] */ 0xfffffe40, 0xf0f809e7, // brr -, r:1b ++/* [0x00002800] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00002808] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00002810] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y10_p00 ++/* [0x00002818] */ 0x959a0ff6, 0x10024020, // mov ra0, unif ; mov r0, elem_num ++/* [0x00002820] */ 0xf5567dad, 0x14124565, // mov ra_xshift, ra_xshift_next ; v8subs r5rep, r5, r5 ++/* [0x00002828] */ 0x8c020c3f, 0x1402581a, // add r0, ra0.16b, r0 ; mov ra_base_next, unif ++/* [0x00002830] */ 0x119c11c0, 0xd0020827, // shl r0, r0, v_x_shift ++/* [0x00002838] */ 0x93027176, 0x12225813, // max r0, r0, r5 ; mov ra_y_next, ra0.16a ++/* [0x00002840] */ 0x9281a1f6, 0x10025810, // min r0, r0, rb_max_x ; mov ra_width_height, unif ++/* [0x00002848] */ 0x119c31c0, 0xd0220567, // shl ra_xshift_next, r0, 3 ++/* [0x00002850] */ 0x149dc1c0, 0xd0020827, // and r0, r0, -4 ++/* [0x00002858] */ 0x8d810bf6, 0x10025896, // sub r2, r5, rb_pitch ; mov ra_wt_off_mul_l0, unif ++/* [0x00002860] */ 0x149e7080, 0x10020867, // and r1, r0, r2 ++/* [0x00002868] */ 0x569d404f, 0x10024821, // xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++/* [0x00002870] */ 0x8c827076, 0x1002581c, // add r0, r0, r1 ; mov ra_dest, unif ++/* [0x00002878] */ 0x8c69cc3f, 0x100246b1, // add ra_base_next, ra_base_next, r0 ; mov vw_setup, rb_vpm_init ++/* [0x00002880] */ 0x11401dc0, 0xd4020867, // shl r1, ra_width, v_x_shift ++/* [0x00002888] */ 0x8d419e76, 0x12025760, // sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height ++/* [0x00002890] */ 0x8d5c31c6, 0xdc025460, // sub rb_i_tmu, r0, PREREAD ; v8min r0, r0, ra_blk_height ++/* [0x00002898] */ 0x919c81c0, 0xd0024812, // shl r0, r0, v_dma_h_shift ; mov rb_lcount, r0 ++/* [0x000028a0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++/* [0x000028a8] */ 0x1158edc0, 0xd4021327, // shl rb_wt_off, ra_wt_off_l0, DENOM + 7 ++/* [0x000028b0] */ 0x9180f1f6, 0xd002581e, // shl r0, r0, v_dma_wh_shift ; mov ra_link, unif ++/* [0x000028b8] */ 0x0c9db1c0, 0x100206e7, // add ra_dma0, r0, rb_dma0_base ++// :1 ++/* [0x000028c0] */ 0xcd511bee, 0x1a0269e5, // sub.setf -, r5, rb_i_tmu ; v8adds r5rep, r5, ra_k1 ++/* [0x000028c8] */ 0x804e7036, 0xa42099d1, // nop ; mov.ifz ra_y, ra_y_next ; ldtmu0 ++/* [0x000028d0] */ 0x8e5509bf, 0x12024823, // shr r0, r4, ra_xshift ; mov r3, rb_pitch ++/* [0x000028d8] */ 0x13440dc0, 0xd40208a7, // max r2, ra_y, 0 ++/* [0x000028e0] */ 0x9269e5f6, 0x10029898, // min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++/* [0x000028e8] */ 0x4c441dd3, 0xd4224462, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++/* [0x000028f0] */ 0x8c618c87, 0x10024e20, // add t0s, ra_base, r2 ; v8min r0, r0, rb_pmask ++/* [0x000028f8] */ 0x4d592bc6, 0x120269e1, // sub.setf -, r5, rb_lcount ; mul24 r1, r0, ra_wt_mul_l0 ++/* [0x00002900] */ 0x915c83f6, 0xdc024863, // shl r1, r1, 8 ; mov r3, ra_blk_height ++/* [0x00002908] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x00002910] */ 0xffffff90, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00002918] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, DENOM + 8 ++/* [0x00002920] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00002928] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00002930] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00002938] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00002940] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00002948] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00002950] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00002958] */ 0xffffff48, 0xf0f809e7, // brr -, r:1b ++/* [0x00002960] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00002968] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00002970] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y10_bxx ++/* [0x00002978] */ 0xfffffaf0, 0xf0f807a7, // brr ra_link, r:per_block_setup_10 ++/* [0x00002980] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x00002988] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x00002990] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00002998] */ 0x1158bdc0, 0xd4020867, // shl r1, ra_wt_off_l0, i_wt_den_p6 ++/* [0x000029a0] */ 0x4c5a7cd6, 0x121245a0, // add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 ++/* [0x000029a8] */ 0x4d4a7216, 0x12024860, // sub r1, r1, r0 ; mul24 r0, r2, ra_wt_mul_l1 ++/* [0x000029b0] */ 0x8d9c423f, 0x1042531d, // sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++// :1 ++/* [0x000029b8] */ 0x4c745dbe, 0x100279c4, // add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++/* [0x000029c0] */ 0x93440dff, 0xd40248a1, // max r2, ra_y, 0 ; mov r1, 0 ++/* [0x000029c8] */ 0x9251e5f6, 0x1a0248a3, // min r2, r2, rb_max_y ; mov r3, ra_k1 ++/* [0x000029d0] */ 0x4c450cd7, 0xa4224462, // add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++/* [0x000029d8] */ 0x8c606cbf, 0x10024e05, // add t0s, ra_base, r2 ; mov rb5, rb6 ++/* [0x000029e0] */ 0x8e5479bf, 0x12024806, // shr r0, r4, ra_xshift ; mov rb6, rb7 ++/* [0x000029e8] */ 0x93458c47, 0xb20248a0, // max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 ++/* [0x000029f0] */ 0x8e2009f6, 0x10024847, // shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++/* [0x000029f8] */ 0x925de5ce, 0x120248a1, // min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++/* [0x00002a00] */ 0x4c450cd7, 0x12124462, // add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++/* [0x00002a08] */ 0x8c24feb6, 0x10025f08, // add t1s, rb_base2, r2 ; mov ra8, ra9 ++/* [0x00002a10] */ 0x4c038af1, 0xd8025962, // add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++/* [0x00002a18] */ 0x5501fff0, 0x180348e2, // mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++/* [0x00002a20] */ 0x4d03f6b0, 0xda0248a3, // sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++/* [0x00002a28] */ 0x40037031, 0xda0109e3, // nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++/* [0x00002a30] */ 0x4c03e4f0, 0xdc0248a3, // add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++/* [0x00002a38] */ 0x40036031, 0xdc0109e3, // nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++/* [0x00002a40] */ 0x4d03d4f0, 0xde0248a3, // sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++/* [0x00002a48] */ 0x40035031, 0xde0109e3, // nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++/* [0x00002a50] */ 0x4c07c4f0, 0xd80248a3, // add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++/* [0x00002a58] */ 0x40074031, 0xd80109e3, // nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++/* [0x00002a60] */ 0x4c07b4f0, 0xda0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++/* [0x00002a68] */ 0x40073031, 0xda0109e3, // nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++/* [0x00002a70] */ 0x4d07a4f0, 0xdc0248a3, // sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++/* [0x00002a78] */ 0x40072031, 0xdc0109e3, // nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++/* [0x00002a80] */ 0x4c0794f0, 0xde0248a3, // add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++/* [0x00002a88] */ 0x4c071b71, 0xde0329e3, // add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++/* [0x00002a90] */ 0xffffff08, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00002a98] */ 0x4d0854fe, 0x1a0248a1, // sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++/* [0x00002aa0] */ 0x550caffe, 0x1a024260, // mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++/* [0x00002aa8] */ 0x8f2c25f6, 0xd00242ca, // asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++/* [0x00002ab0] */ 0x4d08623e, 0x1c024860, // sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++/* [0x00002ab8] */ 0x4d08723e, 0x1e024860, // sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++/* [0x00002ac0] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++/* [0x00002ac8] */ 0x4c0ca23e, 0x1c024860, // add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++/* [0x00002ad0] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++/* [0x00002ad8] */ 0x0d127380, 0x10020867, // sub r1, r1, ra4 ++/* [0x00002ae0] */ 0x8d9cc23f, 0x10024862, // sub r1, r1, r0 ; mov r2, rb_wt_off ++/* [0x00002ae8] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++/* [0x00002af0] */ 0x4d591bce, 0x120269e0, // sub.setf -, r5, rb_i_tmu ; mul24 r0, r1, ra_wt_mul_l0 ++/* [0x00002af8] */ 0x55653fce, 0x140453e1, // mov.ifz rb_base2, rb_base2_next ; mul24 r1, r1, ra_kmul_add ++/* [0x00002b00] */ 0x8d4e7076, 0x10029851, // sub r1, r0, r1 ; mov.ifz ra_y_y2, ra_y_y2_next ++/* [0x00002b08] */ 0x8d692bf6, 0x1002b9d8, // sub.setf -, r5, rb_lcount ; mov.ifz ra_base, ra_base_next ++/* [0x00002b10] */ 0x8c9f8289, 0xd0024860, // add r1, r1, r2 ; mov r0, r1 << 8 ++/* [0x00002b18] */ 0x8c5e7236, 0x1c024863, // add r1, r1, r0 ; mov r3, ra_blk_height ++/* [0x00002b20] */ 0xfffffe78, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00002b28] */ 0x4f65039f, 0x18024862, // asr r1, r1, ra_wt_den_p7 ; mul24 r2, r3, rb_pitch ++/* [0x00002b30] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00002b38] */ 0xf34003f3, 0xd2024c20, // max vpm, r1, 0 ; v8subs r0, ra_height, r3 ++/* [0x00002b40] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00002b48] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00002b50] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00002b58] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00002b60] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00002b68] */ 0xfffffe30, 0xf0f809e7, // brr -, r:1b ++/* [0x00002b70] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00002b78] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00002b80] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_filter_y10_b00 ++/* [0x00002b88] */ 0xfffff8e0, 0xf0f807a7, // brr ra_link, r:per_block_setup_10 ++/* [0x00002b90] */ 0x959a0ff6, 0x10024023, // mov ra0, unif ; mov r3, elem_num ++/* [0x00002b98] */ 0xec9c3fd2, 0x100269e5, // add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 ++/* [0x00002ba0] */ 0x8c001cff, 0x14024800, // add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++/* [0x00002ba8] */ 0x00000001, 0xe00208a7, // mov r2, 1 ++/* [0x00002bb0] */ 0x8c591eb6, 0x10025461, // add rb_i_tmu, rb_i_tmu, r2 ; mov r1, ra_wt_off_mul_l0 ++/* [0x00002bb8] */ 0xf158fded, 0xd4025325, // shl rb_wt_off, ra_wt_off_l0, DENOM + 8 ; v8subs r5quad, r5, r5 ++/* [0x00002bc0] */ 0x809f8009, 0xd000d9d6, // nop ; mov.ifnz ra_wt_off_mul_l0, r1 << 8 ++// :1 ++/* [0x00002bc8] */ 0x0d9d1bc0, 0xb00229e7, // sub.setf -, r5, rb_i_tmu ; nop ; ldtmu1 ++/* [0x00002bd0] */ 0x8e4c09f6, 0xa0029851, // shr r1, r4, rb_xshift2 ; mov.ifz ra_y_y2, ra_y_y2_next ; ldtmu0 ++/* [0x00002bd8] */ 0x8e5509bf, 0x12024823, // shr r0, r4, ra_xshift ; mov r3, rb_pitch ++/* [0x00002be0] */ 0x13440dc0, 0xd40208a7, // max r2, ra_y, 0 ++/* [0x00002be8] */ 0x9269e5f6, 0x10029898, // min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++/* [0x00002bf0] */ 0x4c441dd3, 0xd4224462, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++/* [0x00002bf8] */ 0x8c613cbf, 0x10028e0f, // add t0s, ra_base, r2 ; mov.ifz rb_base2, rb_base2_next ++/* [0x00002c00] */ 0x13440dc0, 0xd20208a7, // max r2, ra_y2, 0 ++/* [0x00002c08] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_max_y ++/* [0x00002c10] */ 0x4c441dd3, 0xd2124462, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++/* [0x00002c18] */ 0x8c5cfe86, 0x12024f20, // add t1s, rb_base2, r2 ; v8min r0, r0, ra_pmax ++/* [0x00002c20] */ 0x545983c6, 0x12024860, // and r1, r1, rb_pmask ; mul24 r0, r0, ra_wt_mul_l0 ++/* [0x00002c28] */ 0x4d492bce, 0x120269e1, // sub.setf -, r5, rb_lcount ; mul24 r1, r1, ra_wt_mul_l1 ++/* [0x00002c30] */ 0xcc52706e, 0x1a024865, // add r1, r0, r1 ; v8adds r5rep, r5, ra_k1 ++/* [0x00002c38] */ 0x915c83f6, 0xdc024863, // shl r1, r1, 8 ; mov r3, ra_blk_height ++/* [0x00002c40] */ 0xec40c3f3, 0x12024860, // add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++/* [0x00002c48] */ 0xffffff60, 0xf06809e7, // brr.anyn -, r:1b ++/* [0x00002c50] */ 0x0f9d03c0, 0xd0020867, // asr r1, r1, (DENOM + 9) - 32 ++/* [0x00002c58] */ 0x925f23bf, 0x12020867, // min r1, r1, ra_pmax ; mov -, vw_wait ++/* [0x00002c60] */ 0x5351039f, 0x18024c22, // max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++/* [0x00002c68] */ 0x956e7036, 0x10126431, // mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 ++/* [0x00002c70] */ 0x00000000, 0xf027c9e7, // bra.anyz -, ra_link ++/* [0x00002c78] */ 0x929dd0ff, 0x10024831, // min r0, r0, r3 ; mov vw_setup, rb_dma1 ++/* [0x00002c80] */ 0x8d7270f6, 0x10024872, // sub r1, r0, r3 ; mov vw_addr, ra_dest ++/* [0x00002c88] */ 0x119d73c0, 0xd0020867, // shl r1, r1, i_shift23 ++/* [0x00002c90] */ 0xffffff18, 0xf0f809e7, // brr -, r:1b ++/* [0x00002c98] */ 0x0c9d2e00, 0x100214a7, // add rb_lcount, rb_lcount, r0 ++/* [0x00002ca0] */ 0x0c6e7c40, 0x100206e7, // add ra_dma0, ra_dma0, r1 ++/* [0x00002ca8] */ 0x8c71ccbf, 0x10024731, // add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init ++// ::mc_end ++}; ++#ifdef __HIGHC__ ++#pragma Align_to(8, ff_hevc_rpi_shader) ++#endif +diff --git a/libavcodec/rpi_hevc_shader.h b/libavcodec/rpi_hevc_shader.h +new file mode 100644 +index 0000000000..79651c9b6c +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader.h +@@ -0,0 +1,63 @@ ++#ifndef rpi_hevc_shader_H ++#define rpi_hevc_shader_H ++ ++extern unsigned int ff_hevc_rpi_shader[]; ++ ++#define mc_setup_c_q0 (ff_hevc_rpi_shader + 0) ++#define mc_start (ff_hevc_rpi_shader + 0) ++#define mc_setup_c_qn (ff_hevc_rpi_shader + 2) ++#define mc_filter_c_p (ff_hevc_rpi_shader + 134) ++#define mc_filter_c_p_l1 (ff_hevc_rpi_shader + 260) ++#define mc_filter_c_b (ff_hevc_rpi_shader + 386) ++#define mc_sync_q0 (ff_hevc_rpi_shader + 580) ++#define mc_sync_q1 (ff_hevc_rpi_shader + 598) ++#define mc_sync_q2 (ff_hevc_rpi_shader + 610) ++#define mc_sync_q3 (ff_hevc_rpi_shader + 622) ++#define mc_sync_q4 (ff_hevc_rpi_shader + 634) ++#define mc_sync_q5 (ff_hevc_rpi_shader + 652) ++#define mc_sync_q6 (ff_hevc_rpi_shader + 664) ++#define mc_sync_q7 (ff_hevc_rpi_shader + 676) ++#define mc_sync_q8 (ff_hevc_rpi_shader + 688) ++#define mc_sync_q9 (ff_hevc_rpi_shader + 706) ++#define mc_sync_q10 (ff_hevc_rpi_shader + 718) ++#define mc_sync_q11 (ff_hevc_rpi_shader + 730) ++#define mc_exit_c_qn (ff_hevc_rpi_shader + 742) ++#define mc_exit_y_qn (ff_hevc_rpi_shader + 742) ++#define mc_exit_c_q0 (ff_hevc_rpi_shader + 760) ++#define mc_exit_y_q0 (ff_hevc_rpi_shader + 760) ++#define mc_setup_y_q0 (ff_hevc_rpi_shader + 780) ++#define mc_setup_y_qn (ff_hevc_rpi_shader + 782) ++#define mc_filter_y_pxx (ff_hevc_rpi_shader + 1014) ++#define mc_filter_y_bxx (ff_hevc_rpi_shader + 1140) ++#define mc_filter_y_p00 (ff_hevc_rpi_shader + 1272) ++#define mc_filter_y_b00 (ff_hevc_rpi_shader + 1358) ++#define mc_setup_c10_q0 (ff_hevc_rpi_shader + 1432) ++#define mc_setup_c10_qn (ff_hevc_rpi_shader + 1434) ++#define mc_filter_c10_p (ff_hevc_rpi_shader + 1562) ++#define mc_filter_c10_p_l1 (ff_hevc_rpi_shader + 1684) ++#define mc_filter_c10_b (ff_hevc_rpi_shader + 1806) ++#define mc_sync10_q0 (ff_hevc_rpi_shader + 1996) ++#define mc_sync10_q1 (ff_hevc_rpi_shader + 2014) ++#define mc_sync10_q2 (ff_hevc_rpi_shader + 2026) ++#define mc_sync10_q3 (ff_hevc_rpi_shader + 2038) ++#define mc_sync10_q4 (ff_hevc_rpi_shader + 2050) ++#define mc_sync10_q5 (ff_hevc_rpi_shader + 2068) ++#define mc_sync10_q6 (ff_hevc_rpi_shader + 2080) ++#define mc_sync10_q7 (ff_hevc_rpi_shader + 2092) ++#define mc_sync10_q8 (ff_hevc_rpi_shader + 2104) ++#define mc_sync10_q9 (ff_hevc_rpi_shader + 2122) ++#define mc_sync10_q10 (ff_hevc_rpi_shader + 2134) ++#define mc_sync10_q11 (ff_hevc_rpi_shader + 2146) ++#define mc_exit_c10_q0 (ff_hevc_rpi_shader + 2158) ++#define mc_exit_y10_q0 (ff_hevc_rpi_shader + 2158) ++#define mc_exit_c10_qn (ff_hevc_rpi_shader + 2178) ++#define mc_exit_y10_qn (ff_hevc_rpi_shader + 2178) ++#define mc_setup_y10_q0 (ff_hevc_rpi_shader + 2196) ++#define mc_setup_y10_qn (ff_hevc_rpi_shader + 2198) ++#define mc_filter_y10_pxx (ff_hevc_rpi_shader + 2440) ++#define mc_filter_y10_p00 (ff_hevc_rpi_shader + 2566) ++#define mc_filter_y10_bxx (ff_hevc_rpi_shader + 2654) ++#define mc_filter_y10_b00 (ff_hevc_rpi_shader + 2786) ++#define mc_end (ff_hevc_rpi_shader + 2860) ++ ++#endif +diff --git a/libavcodec/rpi_hevc_shader.qasm b/libavcodec/rpi_hevc_shader.qasm +new file mode 100644 +index 0000000000..af5b59e181 +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader.qasm +@@ -0,0 +1,1850 @@ ++# Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++# All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions are met: ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# * Neither the name of the copyright holder nor the ++# names of its contributors may be used to endorse or promote products ++# derived from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++# Written by Peter de Rivaz, John Cox ++ ++ ++ ++# Inter pred asm ++# ++# Logic here should be good to 14 bits without modification ++# but only 8 & 10 are currently instantiated & tested ++# 15 & 16 bits have different shift1, shift2 calc & I also suspect overflow ++# in _p00 & _b00 ++ ++# The @ "mul_used", 0 annotations that occur by various mul blocks suppress ++# the warning that we are using rotation & ra/rb registers. r0..3 can be ++# rotated through all 16 elems ra regs can only be rotated through their ++# local 4. As it happens this is what is wanted here as we do not want the ++# constants from the other half of the calc. ++ ++# Number limits in P/B calculation ++# ++# In order to avoid issues with mul24 being an unsigned 24->32 bit multiplier ++# we offset our intermediates s.t. they always end up +ve before the next ++# multiply (may be -ve whilst summing but that doesn't matter). ++# ++# Range calc for up to 14 bits (Y-B pred): ++# ++# denom: [0, 7] ++# bmax = (1 << bits) - 1 ++# off: [-(1 << (bits-1)), (1 << (bits-1)) - 1] ++# ++# wt_mul: [-128, 255] ++# wt_off = off * 2 + 1: [-bmax, bmax] ++# ++# pel: [0, bmax] ++# H-filter: [(-22*pel + 88*pel) >> (bits-8) + 0x4000] = [0x2a00, 0x97ff] ++# V-filter: [(-22*hf + 88*hf) >> 6] = [0x580, 0xc28e] ++# mul_t = (V_L0 + V_l1) * (wt_mul + 128): [0, 0x24624e6] ++# mul_t - (V_l0 + V_l1)* 128: [-0xc28e00, 0x18396e4] ++# adj_wt_off = (wt_off << ((denom + 6) - (bits - 8))) - 0x4000 * (wt_mul * 2): ++# [wt_off << (21 - bits)] - [wt_mul << 15] = [-0x1fffff, 0x1fffff] - [-0x400000, 0x7f8000] ++# ++# This all looks good and is mostly bit depth independant - and as we manage ++# to do unsigned multiplies everywhere (now) this should be good for any bit ++# depth up to 14 (we could probably do 16 - but that requires a few tweaks ++# to the shifts we don't currently have logic for) ++ ++# PREREAD is the number of requests that we have sitting in the TMU request ++# queue. ++# ++# There are 8 slots availible in the TMU request Q for tm0s requests, but ++# only 4 output FIFO entries and overflow is bad (corruption or crash) ++# (If threaded then only 2 out FIFO entries, but we aren't.) ++# In s/w we are effectively limited to the min vertical read which is >= 4 ++# so output FIFO is the limit. ++# ++# As the test for read-next is is the main part of the Luma loop (rather than ++# the preload FIFO part) we are limited to min_luma_height - 1 ++# Min_luma_height is 4 so we can only have a preload of 3 ++# Beware that min_chroma_height (and_width) is 2 so we can't do the same trick ++# in chroma without abandoning preload pretty much entirely (which would be bad) ++# ++# Timing tests vs preload of 4 suggests this doesn't hurt us much ++# Could have preread 4 for Chroma but when tested it didn't help ++ ++.set PREREAD, 3 ++ ++# Offset added (effectively) at the exit of the H FIR filter ++# This is enough to force the result +ve ++# Is good if it is a power of 2 as that allows for >> without loss ++# ++# Worst case for a single Y FIR is *-22 so we need an offset of 256*22 ++# But we need twice offset to survive both H & V = 256*22*2 = 0x2c00 ++# Round up to next power of 2 ++ ++.set FIR_OFFSET, 0x4000 ++ ++# Block heights - 8 & 16 are the only numbers we currently support ++ ++.set C_BLK_HEIGHT_8, 16 ++.set C_BLK_HEIGHT_16, 8 ++.set Y_BLK_HEIGHT_8, 16 ++.set Y_BLK_HEIGHT_16, 8 ++ ++# QPU counts - depend on block size ++# If we have a 2-byte format & block_size > 8 then can only afford ++# 8 QPUs ++# These numbers must match the numbers in ff_hevc_rpi_shader_cmd.h ++ ++.set N_QPU_8, 12 ++.set N_QPU_16, 12 ++ ++# Value to add to the weight multiplier to convert it into an unsigned value ++# Should be power of two for convienience ++ ++.set LOG2_MUL_ADD, 14 ++.set MUL_ADD, (1 << LOG2_MUL_ADD) ++ ++# Fixed denom (max that it can be set to) ++.set DENOM, 7 ++ ++# register allocation ++# ++ ++# ra0-3 ++# Used as temp and may be loop filter coeffs (split into .8s) ++# or temp in loop. Check usage on an individual basis. ++ ++# ra4-11 ++# V FIFO / temp / free ++ ++# -- free -- ra12 ++ ++# -- free -- ra13 ++ ++# -- free -- ra14 ++ ++# -- free -- ra15 ++ ++# uniform: width:height ++.set ra_width_height, ra16 ++.set ra_width, ra16.16b ++.set ra_height, ra16.16a ++ ++# y:y2 same layout as y_y2_next so we can update both together ++.set ra_y_y2, ra17 ++.set ra_y2, ra17.16a ++.set ra_y, ra17.16b ++ ++# uniform: L1 weight (U on left, V on right) ++# Only used in Y B ++.set ra_wt_off_mul_l1, ra18 ++.set ra_wt_off_l1, ra18.16b ++.set ra_wt_mul_l1, ra18.16a ++ ++# y_next:y2_next same layout as y_y2 so we can update both together ++.set ra_y_y2_next, ra19 ++.set ra_y_next, ra19.16b ++.set ra_y2_next, ra19.16a ++ ++# Setup: consts - subdivide a single register ++.set ra_kff800100, ra20 ++.set ra_k256, ra20.16a ++.set ra_k0, ra20.8a ++.set ra_k1, ra20.8b ++.set ra_k128, ra20.8c ++.set ra_k255, ra20.8d ++ ++# Loop: xshifts ++.set ra_xshift, ra21.16a ++.set ra_xshift_next, ra21.16b ++ ++# Loop var: L0 weight (U on left, V on right) ++# _off_ is not used in loop as we want to modify it before use ++.set ra_wt_off_mul_l0, ra22 ++.set ra_wt_mul_l0, ra22.16a ++.set ra_wt_off_l0, ra22.16b ++ ++# Max pel value (for 8 bit we can get away with sat ops but not 9+) ++# * Could merge with rb_pmask. For 10 bit Logically pmask needs 0xff in the ++# 2nd byte but as the source should never be > 3 there 0x3ff should do ++.set ra_blk_height_pmax, ra23 ++.set ra_pmax, ra23.16a ++.set ra_blk_height, ra23.8c ++# --free -- ra23.8d ++ ++# Loop: src frame base (L0) ++.set ra_base, ra24 ++ ++# Misc offsets ++.set ra_fir_off_val_wt_den_p7, ra25 ++.set ra_wt_den_p7, ra25.8a ++# -- free -- ra25.8b ++.set ra_fir_off_val, ra25.16b ++ ++# As it happens these constants are the same ++.if FIR_OFFSET == MUL_ADD ++# Weight multiplier unsigned add ++.set ra_kmul_add, ra_fir_off_val ++.else ++.error "FIR_OFFSET != MUL_ADD: Need new register & init" ++.endif ++ ++# Loop: next src frame base (L0) ++.set ra_base_next, ra26 ++ ++# Loop: height<<23 + width<<16 + vdw_setup_0 ++.set ra_dma0, ra27 ++ ++# Loop: destination address ++.set ra_dest, ra28 ++ ++# Setup: Dup of rb_ef ++# Lo bits are used as Y coeff 0 as that lefts us combine test & coeff mul ++# (top bits are ignored by mul24) ++.set ra_ef, ra29 ++ ++# Use an even numbered register as a link register to avoid corrupting flags ++.set ra_link, ra30 ++ ++# -- free -- ra31 ++ ++.set rb_xshift2, rb0 ++.set rb_xshift2_next, rb1 ++ ++# C: (elem & 1) == 0 ? elem * 2 : (elem + 4) * 2 ++.set rb_elem_x, rb2 ++ ++# El Flags ++# After adding to self we to have el even/odd on nc/c and lo/hi on nn/n ++# Duped into ra_ef as sometimes that is easier to use ++.set rb_ef, rb3 ++ ++# rb4-11 ++# Loop: V filter FIFO or V filter coeff ++ ++# Loop var: offset to add before shift (round + weighting offsets) ++# Exact value varies by loop ++.set rb_wt_off, rb12 ++ ++# -- free -- rb13 ++ ++# -- free -- rb14 ++ ++# Loop: src frame base (L1) ++.set rb_base2, rb15 ++ ++# Line pitch (128 for sand128) ++.set rb_pitch, rb16 ++ ++# Loop count - 2 (set up TMU for next xfer) ++.set rb_i_tmu, rb17 ++ ++# Loop count for min(height, 16) ++# Y will reset & loop again if height > 16 ++.set rb_lcount, rb18 ++ ++# frame_base2_next ++.set rb_base2_next, rb19 ++ ++# Setup: Height of Y+C in sand, (x&mask)*xpitch will give ++# offset to the slice ++.set rb_xpitch, rb20 ++ ++# These 3 consts each save 1 instruction in Y loop setup ++# so whilst they are worthwhile they should be the 1st to die if we need ++# another b reg ++.set rb_y_coeffs_2, rb21 # 0x050b0a00 ++.set rb_y_coeffs_3, rb22 # 0x11283a40 ++.set rb_y_coeffs_5, rb23 # 0x0a0b0500 ++ ++# Setup: 0xff (8-bit) / 0xffff (9+ bit) ++.set rb_pmask, rb24 ++ ++# vdw_setup_1(dst_pitch) ++.set rb_dma1_base, rb25 ++ ++# Setup: pic width - 1 ++# In bytes so 8 bit luma is (width - 1)*1, 16 bit chroma is (width -1)*4 etc. ++.set rb_max_x, rb26 ++ ++# vdw_setup_0 (depends on QPU number) ++.set rb_dma0_base, rb27 ++ ++# Setup: vw_setup value to reset VPM write pointer ++.set rb_vpm_init, rb28 ++ ++# Loop: vdw_setup_1(dst_pitch-width) = stride ++.set rb_dma1, rb29 ++ ++# Setup: pic_height - 1 ++.set rb_max_y, rb30 ++ ++# Setup: FIR H offset ++.set rb_fir_off_h, rb31 ++ ++ ++# With shifts only the bottom 5 bits are considered so -16=16, -15=17 etc. ++.set i_shift16, -16 ++.set i_shift21, -11 ++.set i_shift23, -9 ++.set i_shift30, -2 ++ ++# Much of the setup code is common between Y & C ++# Macros that express this - obviously these can't be overlapped ++# so are probably unsuitable for loop code ++ ++.macro m_calc_dma_regs, v_bit_depth, v_blk_height, r_vpm, r_dma ++ mov r2, qpu_num ++.if v_bit_depth <= 8 ++ # 8 bit version ++ asr r1, r2, 2 ++ shl r1, r1, 6 ++ and r0, r2, 3 ++ or r0, r0, r1 ++ ++ mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit ++ add r_vpm, r0, r1 # VPM 8bit storage ++ ++ mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later ++ shl r0, r0, 5 ++ ++.else ++ # 16 bit version ++ # Limited to 8 QPUs if blk height > 8 ++ asr r1, r2, 1 ++.if v_blk_height <= 8 ++ shl r1, r1, 4 ++.else ++ shl r1, r1, 5 ++.endif ++ and r0, r2, 1 ++ or r0, r0, r1 ++ ++ mov r1, vpm_setup(0, 2, h16p(0, 0)) # 2 is stride - stride acts on ADDR ++ add r_vpm, r0, r1 ++ ++ # X = H * 8 so the YH from VPMVCD_WR_SETUP[ADDR] drops into ++ # XY VPMVCD_WR_SETUP[VPMBASE] if shifted left 3 (+ 3 for pos of field in reg) ++ mov r1, vdw_setup_0(0, 0, dma_h16p(0,0,0)) # height,width added later ++ shl r0, r0, 6 ++.endif ++ add r_dma, r0, r1 # DMA out ++.endm ++ ++ ++.macro m_setup_q0 ++ srel -, 12 ++.endm ++ ++# Code start label ++::mc_start ++ ++################################################################################ ++# mc_setup_c ++# ++# typedef struct qpu_mc_pred_c_s_s { ++# int16_t y; ++# int16_t x; ++# uint32_t base; ++# uint32_t pic_cw; // C Width (== Y width / 2) ++# uint32_t pic_ch; // C Height (== Y Height / 2) ++# uint32_t stride2; ++# uint32_t stride1; ++# uint32_t wdenom; ++# int16_t y2; ++# int16_t x2; ++# uint32_t base2; ++# uint32_t next_fn; ++# } qpu_mc_pred_c_s_t; ++ ++.macro m_setup_c, v_bit_depth ++ ++# Cannot use mul24 on x as x might be -ve, so must use shift ++.if v_bit_depth <= 8 ++.set v_x_shift, 1 ++.set v_pmask, 0xff ++.set v_blk_height, C_BLK_HEIGHT_8 ++.else ++.set v_x_shift, 2 ++.set v_pmask, 0xffff ++.set v_blk_height, C_BLK_HEIGHT_16 ++.endif ++ ++ mov tmurs, 1 ; mov ra0, unif # No TMU swap ; x_y ++ ++ mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++ shl rb_ef, r0, i_shift30 ; mov ra_base, unif # ; ref_c_base ++ ++# Read image dimensions ++ sub r0, unif, 1 # pic c width ++ shl rb_max_x, r0, v_x_shift # rb_max_x in bytes ++ sub rb_max_y, unif, 1 # pic c height ++ ++# load constants ++ mov ra_kff800100, 0xff800100 ++ mov rb_pmask, v_pmask ++ mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++ mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++ mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++ ++# get source pitch ++ mov ra_ef, rb_ef ; mov rb_xpitch, unif # ; stride2 ++ mov rb_pitch, unif # stride1 ++ mov r1, vdw_setup_1(0) # [rb_pitch delay] Merged with dst_stride shortly ++ add rb_dma1_base, r1, rb_pitch # vdw_setup_1 ++ ++ and r0, 1, elem_num ++ nop ; mul24 r0, r0, 5 ++.if v_bit_depth <= 8 ++ add rb_elem_x, r0, elem_num ++.else ++ add r0, r0, elem_num ++ add rb_elem_x, r0, r0 ++.endif ++ ++# Compute base address for first and second access ++# ra_base ends up with t0s base ++# ra_base2 ends up with t1s base ++ ++ shl r0, ra0.16b, v_x_shift # [rb_elem_x delay] ++ add r0, r0, rb_elem_x # Add elem no to x to get X for this slice ++ max r0, r0, 0 ; mov ra_y, ra0.16a # ; stash Y ++ min r0, r0, rb_max_x ++ ++# Get shift ++# Shift will always calculate as 0 for 9+ bit ++# Ideally we can optimize the shift out of the code in these cases but for now ++# it is tidier to leave it in ++.if v_bit_depth <= 8 ++ shl ra_xshift_next, r0, 3 ++.else ++ mov ra_xshift_next, 0 ; mov rb_xshift2_next, 0 ++.endif ++ ++# In a single 32 bit word we get 1 or 2 UV pairs so mask bottom bits of xs if we need to ++ ++.if v_bit_depth <= 8 ++ and r0, r0, -4 ++.endif ++ sub r1, ra_k0, rb_pitch ++ and r1, r0, r1 ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov ra0, unif # ; next_x2_y2 ++ add ra_base, ra_base, r0 ++ ++# Compute part of VPM to use for DMA output ++# * We only get 8 QPUs if 16 bit - maybe reduce height and auto-loop? ++ m_calc_dma_regs v_bit_depth, v_blk_height, rb_vpm_init, rb_dma0_base ++ ++# And again for L1, but only worrying about frame2 stuff ++ ++# Compute base address for first and second access ++# ra_base ends up with t0s base ++# rb_base2 ends up with t1s base ++ ++ shl r0, ra0.16b, v_x_shift ++ add r0, r0, rb_elem_x ; mov ra_y2, ra0.16a # Add QPU slice offset ++ max r0, r0, 0 ; mov rb_base2, unif # ref_c_base2 ++ min r0, r0, rb_max_x ++ ++# Get shift (already zero if 9+ bit so ignore) ++.if v_bit_depth <= 8 ++ shl rb_xshift2_next, r0, 3 ++.endif ++ ++# In a single 32 bit word we get 2 UV pairs so mask bottom bit of xs ++ ++.if v_bit_depth <= 8 ++ and r0, r0, -4 ++.endif ++ sub r1, ra_k0, rb_pitch ++ and r1, r0, r1 ; mov r3, PREREAD ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov r2, ra_y2 ++ add rb_base2, rb_base2, r0 ; mov r0, ra_y ++ ++# Do preloads ++# r0 = ra_y, r2 = ra_y2, r3 = PREREAD ++ ++:1 ++ sub.setf r3, r3, 1 ++ max r1, r0, 0 ++ min r1, r1, rb_max_y ++ add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++ add t0s, ra_base, r1 ; mov ra_y, r0 ++ ++ max r1, r2, 0 ++ brr.anynz -, r:1b ++ min r1, r1, rb_max_y ++ add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++ add t1s, rb_base2, r1 ; mov ra_y2, r2 ++# >>> .anynz 1b ++ ++ mov ra_link, unif # link ++# touch registers to keep simulator happy (and fills in delay slots) ++ mov ra4, 0 ; mov rb4, 0 ++ bra -, ra_link ++ mov ra5, 0 ; mov rb5, 0 ++ mov ra6, 0 ; mov rb6, 0 ++ mov ra7, 0 ; mov rb7, 0 ++# >>> ra_link ++.endm ++ ++::mc_setup_c_q0 ++ m_setup_q0 ++::mc_setup_c_qn ++ m_setup_c 8 ++ ++################################################################################ ++# ++# mc_filter_c_p ++# ++# typedef struct qpu_mc_pred_c_p_s { ++# int16_t y; ++# int16_t x; ++# uint32_t base; ++# uint16_t h; ++# uint16_t w; ++# uint32_t coeffs_x; ++# uint32_t coeffs_y; ++# uint32_t wo_u; ++# uint32_t wo_v; ++# uint32_t dst_addr_c; ++# uint32_t next_fn; ++# } qpu_mc_pred_c_p_t; ++ ++.macro m_filter_c_p, v_tmu, v_bit_depth ++ ++.if v_bit_depth <= 8 ++.set v_x_shift, 1 ++.set v_x_mul, 2 ++.set v_v_shift, 8 ++# Shifts to get width & height in the right place in rb_dma0 ++.set v_dma_h_shift, 7 ++.set v_dma_wh_shift, i_shift16 ++.else ++.set v_x_shift, 2 ++.set v_x_mul, 4 ++.set v_v_shift, i_shift16 ++# Shifts to get width & height in the right place in rb_dma0 ++.set v_dma_h_shift, 8 ++.set v_dma_wh_shift, 15 ++.endif ++ ++.if v_tmu == 0 ++.set vrx_xshift, rb_xshift2 # b side more convienient ++.set vrx_xshift_next, ra_xshift_next ++.set vra_y_next, ra_y_next ++.set vrx_base_next, ra_base_next ++.set vra_y, ra_y ++.set vra_base, ra_base ++.set vr_txs, t0s ++.else ++.set vrx_xshift, ra_xshift # a side more convienient ++.set vrx_xshift_next, rb_xshift2_next ++.set vra_y_next, ra_y2_next ++.set vrx_base_next, rb_base2_next ++.set vra_y, ra_y2 ++.set vra_base, rb_base2 ++.set vr_txs, t1s ++.endif ++ ++# denom shift values ++.set i_wt_den_p5, (DENOM + 13 - v_bit_depth) ++.set i_wt_den_p6, (DENOM + 14 - v_bit_depth) ++ ++# per-channel shifts were calculated on the *previous* invocation ++# get base addresses and per-channel shifts for *next* invocation ++ mov vw_setup, rb_vpm_init ; mov ra2, unif # ; x_y ++ ++ add.setf -, rb_ef, rb_ef ; mov r3, unif # [ra2 delay] ; base ++ ++ shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r0, r0 # r5 = 0 ++ add r0, r0, rb_elem_x ; mov ra_width_height, unif # r1=pitch2 mask ; width_height ++ sub r1, r5, rb_pitch ; mov ra0, unif # ; H filter coeffs ++ max r0, r0, r5 ; mov vrx_xshift, vrx_xshift_next ++ min r0, r0, rb_max_x ; mov vra_y_next, ra2.16a ++ ++.if v_bit_depth <= 8 ++ shl vrx_xshift_next, r0, 3 ++ and r0, r0, -4 ++.endif ++ and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul # r2=w*2 (we are working in pel pairs) ** x*2 already calced! ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov ra3, unif # ; V filter coeffs ++ add vrx_base_next, r3, r0 ; mov r1, ra_height ++ ++# set up VPM write ++ sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif # Compute vdw_setup1(dst_pitch-width) ; U offset/weight ++ add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++ add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_off_mul_l0, unif # ; V offset/weight ++ ++# Misc final setup... ++ ++ shl r0, r1, v_dma_h_shift ; mov ra_dest, unif # ; dst_addr ++ add r0, r0, r2 ; mov r2, ra_fir_off_val # Combine width and height of destination area (r0=h<<8, r2=w*2) ++ shl r0, r0, v_dma_wh_shift ; mov rb10, ra3.8c # Shift into bits 16 upwards of the vdw_setup0 register ++ add ra_dma0, r0, rb_dma0_base ; mov r1, ra_wt_off_l0 # ; r1=weight ++ shl r1, r1, i_wt_den_p5 ; mul24 r0, r2, ra_wt_mul_l0 ++ sub rb_wt_off, r1, r0 ; mov r0, ra_kmul_add ++ add ra_wt_mul_l0, ra_wt_mul_l0, r0 ; mov r5rep, -4 # ; loop counter (V FIFO fill = 4) ++ mov rb11, ra3.8d ; mov ra_link, unif # ; Link ++ ++# r5 = -4 (loop counter) ++# ra_wt_mul_l0 = weight L0 + 128 (now unsigned) ++# rb_wt_off = (offset * 2 + 1) << (wt_den + 5) ++# rb31 = FIR value offset ++ ++# FIFO: rb4, ra5, rb6, ra7 ++# Coeffs in ra3.8a, ra3.8b, rb10, rb11 ++ ++# We want (r0r1) ++# U0U3 : V0V3 : U1U4 : V1V4 : U2U5 : V2U5 : ... ++# We fetch (after shift) ++# C0 : C3 : C1 : C4 : C2 : C5 : ... ++ ++:1 ++# retrieve texture results and pick out bytes ++# then submit two more texture requests ++ ++.if v_tmu == 0 ++ sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu0 ++ shr r2, r4, vrx_xshift ; mov.ifz r3, vra_y_next ++ shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++ add.setf -, rb_ef, rb_ef ; mov.ifz vra_base, vrx_base_next ++.else ++ sub.setf -, r5, rb_i_tmu ; mov rb4, ra5 ; ldtmu1 ++ shr r2, r4, vrx_xshift ; mov.ifz vra_base, vrx_base_next ++ shr r1, r2, v_v_shift ; mov.ifnz r3, vra_y ++ add.setf -, rb_ef, rb_ef ; mov.ifz r3, vra_y_next # [r1 << delay] ++.endif ++ ++ add vra_y, r3, ra_k1 ; mov r0, r1 << 15 ++ max r3, r3, ra_k0 ; mov.ifnc r1, r2 << 1 ++ min r3, r3, rb_max_y ; mov.ifnc r0, r2 ++ ++ and r1, r1, ra_pmax ; mul24 r3, r3, rb_pitch ++.if v_tmu == 0 ++ add vr_txs, vra_base, r3 ; v8min r0, r0, rb_pmask # ; mask bytes ++.else ++ add vr_txs, vra_base, r3 ; v8min r0, r0, ra_pmax # ; mask bytes ++.endif ++ ++# apply horizontal filter ++# The filter coeffs for the two halves of this are the same (unlike in the ++# Y case) so it doesn't matter which ra0 we get them from ++# Also as the two halves are locked together we don't need to separate the 1st ++# r0 mul or the last r1 mul as they are valid for all QPUs ++ ++ add r5rep, r5, 1 ; mul24 r3, ra0.8a, r0 ++ sub r2, rb_fir_off_h, r3 ; mul24 r3, ra0.8d, r1 ++ sub r2, r2, r3 ; mul24 r3, ra0.8b << 2, r0 << 2 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8b << 12, r1 << 12 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra0.8c << 4, r0 << 4 @ "mul_used", 0 ++ add.setf -, r5, r5 ; mul24.ifn r3, ra0.8c << 14, r1 << 14 @ "mul_used", 0 ++ ++# V filter = - r4 * a + r5 * b + r6 * c - r7 * d (post FIFO shift) ++# We would like to save the r5->r4 shift but we need a delay slot ++# for both r7 & r6 which we can't find anything to put in if we have ++# already multiplied r4 & r5! ++ brr.anyn -, r:1b ++ add r2, r2, r3 ; mul24 r0, ra7, rb10 # r6 post ++ mov ra5, rb6 ; mul24 r1, rb6, ra3.8b # r5 post ++ asr ra7, r2, v_bit_depth - 8 ; mov rb6, ra7 ++# >>> .anyn 1b ++ ++ add r1, r1, r0 ; mul24 r0, rb4, ra3.8a # [ra7 delay] ++ sub r1, r1, r0 ; mul24 r0, ra7, rb11 ++ sub r1, r1, r0 ++ ++ asr r1, r1, 6 ; mov r3, ra_blk_height # ; NxtLoop ++ sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++ add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++ sub r1, r0, r1 ; v8subs r0, ra_height, r3 # ; NxtLoop ++ brr.anyn -, r:1b ++ asr r1, r1, i_wt_den_p6 ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch # ; NxtLoop ++# >>> .anyn 1b ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed 16 height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link ++ ++# Here r1 = cur_blk_height - 16 so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_c_p ++ m_filter_c_p 0, 8 ++ ++::mc_filter_c_p_l1 ++ m_filter_c_p 1, 8 ++ ++################################################################################ ++# ++# mc_filter_c_b ++# ++# typedef struct qpu_mc_pred_c_b_s { ++# int16_t y; ++# int16_t x; ++# uint32_t base; ++# uint16_t h; ++# uint16_t w; ++# uint32_t coeffs_x1; ++# uint32_t coeffs_y1; ++# int16_t weight_u1; ++# int16_t weight_v1; ++# int16_t y2; ++# int16_t x2; ++# uint32_t base2; ++# uint32_t coeffs_x2; ++# uint32_t coeffs_y2; ++# uint32_t wo_u2; ++# uint32_t wo_v2; ++# uint32_t dst_addr_c; ++# uint32_t next_fn; ++# } qpu_mc_pred_c_b_t; ++ ++.macro m_filter_c_b, v_bit_depth ++ ++.if v_bit_depth <= 8 ++.set v_x_shift, 1 ++.set v_v_shift, 8 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 7 ++.set v_dma_wh_shift, i_shift16 ++.else ++.set v_x_shift, 2 ++.set v_v_shift, i_shift16 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 8 ++.set v_dma_wh_shift, 15 ++.endif ++.set v_x_mul, (1 << v_x_shift) ++ ++# denom shift values ++.set i_wt_den_p5, (DENOM + 13 - v_bit_depth) ++.set i_wt_den_p6, (DENOM + 14 - v_bit_depth) ++ ++# per-channel shifts were calculated on the *previous* invocation ++ ++# get base addresses and per-channel shifts for *next* invocation ++ mov vw_setup, rb_vpm_init ; mov ra2, unif # ; x_y ++ ++ add.setf -, rb_ef, rb_ef ; mov r3, unif # [ra2 delay] ; r3=base ++ ++ shl r0, ra2.16b, v_x_shift ; v8subs r5rep, r1, r1 # x ; r5=0 ++ add r0, r0, rb_elem_x ; mov ra_y_next, ra2.16a ++ sub r1, r5, rb_pitch ; mov ra_width_height, unif # r1=pitch2 mask ; width_height ++ max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++ min r0, r0, rb_max_x ; mov ra0, unif # ; L0 H filter coeffs ++ ++.if v_bit_depth <= 8 ++ shl ra_xshift_next, r0, 3 ++.endif ++ ++ and r0, r0, -4 ; mov ra2, unif # ; L0 V filter coeffs ++ and r1, r0, r1 ; mul24 r2, ra_width, v_x_mul # r2=x*2 (we are working in pel pairs) ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov r1, ra_height # Add stripe offsets ; r1=height ++ add ra_base_next, r3, r0 ; mov rb_xshift2, rb_xshift2_next # ; xshift2 used because B ++ ++# set up VPM write ++ ++ sub rb_dma1, rb_dma1_base, r2 ; mov ra_wt_off_mul_l0, unif # Compute vdw_setup1(dst_pitch-width) ; U weight ++ add rb_i_tmu, r1, (3-4) - PREREAD ; v8min r1, r1, ra_blk_height ++ add rb_lcount, r1, (3-4) ; mov.ifc ra_wt_mul_l0, ra_wt_off_l0 # ; V weight ++ ++ shl r0, r1, v_dma_h_shift ; mov ra3, unif # ; x2_y2 ++ add r0, r0, r2 ; mov r3, unif # [ra3 delay] ; base ++ shl r0, r0, v_dma_wh_shift ; mov ra_y2_next, ra3.16a # Shift into bits 16 upwards of the vdw_setup0 register ++ add ra_dma0, r0, rb_dma0_base ; mov r0, ra3.16b # r0=x ++ ++# L1 - uniform layout could possibly be optimized ++ ++ shl r0, r0, v_x_shift ; mov ra1, unif # r0=x<>> .anyn 1b ++ ++ sub r2, r1, r0 ; mul24 r1, rb5, ra2.8b # L1 ; L0 ++ sub.setf -, r5, rb_lcount ; mov r0, ra4 ++ sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++ add r1, r1, r0 ; mul24 r0, ra7, rb7 ++ ++ sub r1, r1, r0 ; mul24 r0, rb10, ra3.8c # L1 ++ add r2, r2, r0 ; mul24 r0, ra11, rb11 # L1 ++ sub r2, r2, r0 ++ ++ shr r1, r1, 6 ++ shr r2, r2, 6 ; mul24 r0, r1, ra_wt_mul_l0 ++ add r2, r2, r1 ; mul24 r1, r2, ra_wt_mul_l1 ++ add r1, r1, r0 ; mul24 r2, r2, ra_kmul_add ++ sub r1, r1, r2 ; mov r3, ra_blk_height # ; NxtLoop ++ add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 # ; NxtLoop ++ ++ brr.anyn -, r:1b ++ asr r1, r1, ra_wt_den_p7 ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch # ; NxtLoop ++# >>> .anyn 1b ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed 16 height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # ; VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # ; Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # ; start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link ++ ++# Here r1 = cur_blk_height - 16 so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_c_b ++ m_filter_c_b 8 ++ ++################################################################################ ++# Exit code used by both Luma & Chroma so place between them to avoid I-cache ++# conflicts ++ ++.macro m_exit_drain ++.if PREREAD == 2 ++# Special case 2 as loop is wasteful ++ nop ; nop ; ldtmu0 ++ nop ; nop ; ldtmu1 ++ nop ; nop ; ldtmu0 ++ mov -, vw_wait ; nop ; ldtmu1 ++.else ++ mov.setf r3, PREREAD - 1 ++:1 ++ brr.anynz -, r:1b ++ nop ; nop ; ldtmu0 ++ nop ; nop ; ldtmu1 ++ sub.setf r3, r3, 1 ++ # >>> ++ mov -, vw_wait ++.endif ++.endm ++ ++# This sync layout groups QPUs 0-3, 4-7, 8-11 (i.e. 1 group per TMU pair) ++# All qpus start at the beginning and after that (group - 1) must have finished ++# before (group) can start ++# ++# Requires setup code for QPU 0 to srel sem 12 (m_setup_q0) to start the chain ++# Exit code will sacq sem 12 so everything is @ 0 on exit (this is important - ++# lockup otherwise) ++# ++# There is some, currently ill defined, potential lockup if we have the VDM active ++# whilst doing sem stuff so we wait first. ?? QPU stall from sem stalls VDM pipe too ?? ++# ++# The code stalled when I had many waiters on a single sem so we have a ++# "ripple" of srels to restart. Unsure why, may have been bug, but this works ++# and we currently have both the memory & sems to support it. ++.macro m_sync_q, n_qpu, n_quads ++# Do not generate code for qpu >= quads * 4 - fns should never be called ++.if n_qpu < n_quads * 4 ++ mov ra_link, unif # Can only branch to an a reg (not r0) ++ mov -, vw_wait # [ra_link delay] ++ ++.set n_sem_sync, n_qpu - (n_qpu % 4) ++.set n_sem_in, n_qpu ++.set n_sem_out, n_qpu + 1 ++ ++.if n_qpu % 4 == 0 ++ ++.set n_sem_quad_in, 12 + n_qpu / 4 ++.set n_sem_quad_out, 12 + (((n_qpu / 4) + 1) % n_quads) ++ ++ sacq -, n_sem_sync ++ sacq -, n_sem_sync ++ sacq -, n_sem_sync ++ bra -, ra_link ++ sacq -, n_sem_quad_in ++ srel -, n_sem_out ++ srel -, n_sem_quad_out ++ ++.else ++ bra -, ra_link ++ srel -, n_sem_sync ++ sacq -, n_sem_in ++.if n_sem_out % 4 != 0 ++ srel -, n_sem_out ++.else ++ nop ++.endif ++.endif ++.endif ++.endm ++ ++.set v_quads8, N_QPU_8 / 4 ++ ++::mc_sync_q0 ++ m_sync_q 0, v_quads8 ++::mc_sync_q1 ++ m_sync_q 1, v_quads8 ++::mc_sync_q2 ++ m_sync_q 2, v_quads8 ++::mc_sync_q3 ++ m_sync_q 3, v_quads8 ++::mc_sync_q4 ++ m_sync_q 4, v_quads8 ++::mc_sync_q5 ++ m_sync_q 5, v_quads8 ++::mc_sync_q6 ++ m_sync_q 6, v_quads8 ++::mc_sync_q7 ++ m_sync_q 7, v_quads8 ++::mc_sync_q8 ++ m_sync_q 8, v_quads8 ++::mc_sync_q9 ++ m_sync_q 9, v_quads8 ++::mc_sync_q10 ++ m_sync_q 10, v_quads8 ++::mc_sync_q11 ++ m_sync_q 11, v_quads8 ++ ++# mc_exit() ++# Chroma & Luma the same now ++ ++.macro m_exit_qn ++ m_exit_drain ++ nop ; nop ; thrend ++ nop ++ nop ++# >>> thrend <<< ++.endm ++ ++::mc_exit_c_qn ++::mc_exit_y_qn ++ m_exit_qn ++ ++ ++ ++# mc_interrupt_exit12() ++ ++.macro m_exit_q0 ++ m_exit_drain ++ sacq -, 12 ++ nop ; nop ; thrend ++ mov interrupt, 1 ++ nop ++# >>> thrend <<< ++.endm ++ ++::mc_exit_c_q0 ++::mc_exit_y_q0 ++ m_exit_q0 ++ ++# LUMA CODE ++ ++# The idea is to form B predictions by doing 8 pixels from ref0 in parallel with 8 pixels from ref1. ++# For P frames we make the second x,y coordinates offset by +8 ++ ++ ++################################################################################ ++# mc_setup ++# ++# typedef struct qpu_mc_pred_y_s_s { ++# qpu_mc_src_t next_src1; ++# qpu_mc_src_t next_src2; ++# uint16_t pic_h; ++# uint16_t pic_w; ++# uint32_t stride2; ++# uint32_t stride1; ++# uint32_t wdenom; ++# uint32_t next_fn; ++# } qpu_mc_pred_y_s_t; ++ ++.macro m_setup_y, v_bit_depth ++ ++# Cannot use mul24 on x as x might be -ve, so must use shift ++.if v_bit_depth <= 8 ++.set v_x_shift, 0 ++.set v_pmask, 0xff ++.set v_blk_height, Y_BLK_HEIGHT_8 ++.else ++.set v_x_shift, 1 ++.set v_pmask, 0xffff ++.set v_blk_height, Y_BLK_HEIGHT_16 ++.endif ++ ++ ++ # Need to save these because we need to know the frame dimensions before computing texture coordinates ++ mov tmurs, 1 ; mov ra0, unif # No TMU swap ; x_y ++ mov ra9, unif # ref_y_base ++ mov ra1, unif # x2_y2 ++ ++ ++# load constants ++ mov r0, [0,2,0,2,0,2,0,2,1,3,1,3,1,3,1,3] ++ shl rb_ef, r0, i_shift30 ; mov ra11, unif # ; ref_y2_base ++ ++ mov ra_kff800100, 0xff800100 ++ mov rb_pmask, v_pmask ++ mov ra_blk_height_pmax, ((1 << v_bit_depth) - 1) | (v_blk_height << 16) ++ mov rb_fir_off_h, (FIR_OFFSET << (v_bit_depth - 8)) ++ mov ra_fir_off_val_wt_den_p7, (FIR_OFFSET << 16) | (DENOM + 15 - v_bit_depth) ++ mov rb_y_coeffs_2, 0x050b0a00 ++ mov rb_y_coeffs_3, 0x11283a40 ++ mov rb_y_coeffs_5, 0x0a0b0500 ++ ++# Compute part of VPM to use ++ ++# Read image dimensions ++ mov ra3, unif # width_height ++ mov ra_ef, rb_ef ; mov rb_xpitch, unif # [ra3 delay] ; stride2 ++.if v_x_shift == 0 ++ sub rb_max_x, ra3.16b, 1 ++.else ++ sub r0, ra3.16b, 1 ++ shl rb_max_x, r0, v_x_shift ++.endif ++ sub rb_max_y, ra3.16a, 1 ++ mov r3, elem_num ; mov rb_pitch, unif # stride1 ++ ++# get destination pitch ++ mov r1, vdw_setup_1(0) # [rb_pitch delay] ++ or rb_dma1_base, r1, rb_pitch ++ ++# Compute base address for first and second access ++ add r0, ra0.16b, r3 # Load x + elem_num ++.if v_x_shift != 0 ++ shl r0, r0, v_x_shift ++.endif ++ max r0, r0, 0 ++ min r0, r0, rb_max_x ++ shl ra_xshift_next, r0, 3 # Compute shifts ++ ++# X is byte offset - we can only load words - mask ++ ++ and r0, r0, -4 ; v8subs r2, r2, r2 ++ sub r2, r2, rb_pitch ++ and r1, r0, r2 ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 # Add stripe offsets ++ add ra_base, ra9, r0 ++ ++ # r3 still contains elem_num ++ add r0, ra1.16b, r3 # Load x ++.if v_x_shift != 0 ++ shl r0, r0, v_x_shift ++.endif ++ max r0, r0, 0 ++ min r0, r0, rb_max_x ++ shl rb_xshift2_next, r0, 3 # Compute shifts ++ ++ # r2 still contains mask ++ and r0, r0, -4 ++ and r1, r0, r2 ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 # Add stripe offsets ++ add rb_base2, ra11, r0 ++ ++# Do preloads ++ nop ; mov r0, ra0.16a # ; r0 = y ++ mov r3, PREREAD ; mov r2, ra1.16a # ; r2 = y2 ++ ++:1 ++ sub.setf r3, r3, 1 ++ max r1, r0, 0 ++ min r1, r1, rb_max_y ++ add r0, r0, ra_k1 ; mul24 r1, r1, rb_pitch ++ add t0s, ra_base, r1 ; mov ra_y, r0 ++ ++ max r1, r2, 0 ++ brr.anynz -, r:1b ++ min r1, r1, rb_max_y ++ add r2, r2, ra_k1 ; mul24 r1, r1, rb_pitch ++ add t1s, rb_base2, r1 ; mov ra_y2, r2 ++# >>> .anynz 1b ++ ++ m_calc_dma_regs v_bit_depth, v_blk_height, rb_vpm_init, rb_dma0_base ++ ++ mov ra_link, unif # Next fn ++ ++# touch vertical context to keep simulator happy ++ mov ra8, 0 ; mov rb8, 0 # [ra_link delay] ++ bra -, ra_link ++ mov ra9, 0 ; mov rb9, 0 ++ mov ra10, 0 ; mov rb10, 0 ++ mov ra11, 0 ; mov rb11, 0 ++# >>> ra_link ++.endm ++ ++::mc_setup_y_q0 ++ m_setup_q0 ++::mc_setup_y_qn ++ m_setup_y 8 ++ ++################################################################################ ++# ++# Start of per-block setup code ++# P and B blocks share the same setup code to save on Icache space ++ ++# get base addresses and per-channel shifts for *next* invocation ++# per-channel shifts were calculated on the *previous* invocation ++ ++# 1st 3 instructions of per_block-setup in branch delay ++# ++# typedef struct qpu_mc_pred_y_p_s { ++# qpu_mc_src_t next_src1; ++# qpu_mc_src_t next_src2; ++# uint16_t h; ++# uint16_t w; ++# uint32_t mymx21; ++# uint32_t wo1; ++# uint32_t wo2; ++# uint32_t dst_addr; ++# uint32_t next_fn; ++# } qpu_mc_pred_y_p_t; ++# ++ ++.macro m_luma_setup, v_bit_depth ++# Hack - QASM may well have have label pasting but I have no idea how... ++.if v_bit_depth == 8 ++ brr ra_link, r:per_block_setup_8 ++.elif v_bit_depth == 10 ++ brr ra_link, r:per_block_setup_10 ++.endif ++ mov ra0, unif ; mov r3, elem_num # y_x ; elem_num has implicit unpack?? ++ add.setf -, rb_ef, rb_ef ; v8subs r5rep, r2, r2 # [ra0 delay] ; r5 = 0 ++ add r0, ra0.16b, r3 ; mov rb_xshift2, rb_xshift2_next ++.endm ++ ++.macro m_per_block_setup, v_bit_depth ++ ++.if v_bit_depth <= 8 ++.set v_x_shift, 0 ++.set v_x_mul, 1 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 7 ++.set v_dma_wh_shift, i_shift16 ++.else ++.set v_x_shift, 1 ++.set v_x_mul, 2 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 8 ++.set v_dma_wh_shift, 15 ++.endif ++ ++.if v_x_shift != 0 ++ shl r0, r0, v_x_shift ++.endif ++ max r0, r0, r5 ; mov ra_xshift, ra_xshift_next ++ min r0, r0, rb_max_x ++ ++ shl ra_xshift_next, r0, 3 # Compute shifts ++ and r0, r0, -4 ++ sub r2, r5, rb_pitch ; mov ra_base_next, unif # ; src1.base ++ and r1, r0, r2 ; mov ra_y_next, ra0.16a ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov ra1, unif # Add stripe offsets ; src2.x_y ++ add ra_base_next, ra_base_next, r0 # [ra1 delay] ++ ++ add r0, ra1.16b, r3 # Load x2 ++.if v_x_shift != 0 ++ shl r0, r0, v_x_shift ++.endif ++ max r0, r0, r5 ; mov ra_y2_next, ra1.16a ++ min r0, r0, rb_max_x ; mov rb_base2_next, unif # ; src2.base ++ shl rb_xshift2_next, r0, 3 # Compute shifts ++ and r0, r0, -4 ; mov ra_width_height, unif # ; width_height ++ and r1, r0, r2 ; mov vw_setup, rb_vpm_init # ; set up VPM write ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mul24 r1, ra_width, v_x_mul # Add stripe offsets ; r1 = x in bytes ++ add rb_base2_next, rb_base2_next, r0 ++ ++# get width,height of block (unif load above), r1 = width * pel_size ++ sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height # Compute vdw_setup1(dst_pitch-width) ++ add rb_i_tmu, r0, (7-8) - PREREAD ; v8min r0, r0, ra_blk_height ++ add rb_lcount, r0, (7-8) ++ shl r0, r0, v_dma_h_shift ; mov r3, ra_kmul_add # ; r3 return val ++ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, v_dma_wh_shift ; mov r2, ra_fir_off_val # Shift into bits 16 upwards of the vdw_setup0 register ; r2 return val ++ add ra_dma0, r0, rb_dma0_base ; mov r0, unif # ; Packed filter offsets ++ ++# get filter coefficients and discard unused B frame values ++ shl.ifnn r0, r0, i_shift16 ; mov ra_wt_off_mul_l0, unif # Pick half to use ; L0 offset/weight ++ shl ra8, r0, 3 ; mov rb5, ra_k255 ++ ++# Coeffs are all abs values here as that means mul24 works (no sign extend from .8) ++ ++# 2nd half coeffs same as first if we can swap 8<->24 in the rotate val ++# but I can't see a way of doing that that is cheap enough to be worth it ++ ++# Picked out in a slightly random order to space out uniform loads ++ ++ # 1 ++ mov r1, 0x01040400 # [ra8 delay] ++ ror ra2.8b, r1, ra8.8d ++ ror ra0.8b, r1, ra8.8c ++ # 2 ++ ror ra2.8c, rb_y_coeffs_2, ra8.8d ++ ror ra0.8c, rb_y_coeffs_2, ra8.8c ++ # 0 ++ mov r1,0x00010100 # -ve [ra8 delay] ++ ror r0, r1, ra8.8d ; mov ra_wt_off_mul_l1, unif # ; L1 Wt/Offset ++ ror ra0.8a, r1, ra8.8c ; v8min rb4, r0, rb5 ++ # 7 ++ shl r1, r1, 8 ; mov.ifn ra_wt_off_mul_l0, ra_wt_off_mul_l1 # r1 = 0x01010000 ++ ror r0, r1, ra8.8d ; mov ra_dest, unif # ; Destination address ++ ror ra1.8d, r1, ra8.8c ; v8min rb11, r0, rb5 ++ # 3 ++ ror ra2.8d, rb_y_coeffs_3, ra8.8d ++ ror ra0.8d, rb_y_coeffs_3, ra8.8c ++ # 5 ++ ror ra3.8b, rb_y_coeffs_5, ra8.8d ++ ror ra1.8b, rb_y_coeffs_5, ra8.8c ++ # 6 ++ mov r1,0x04040100 ++ ror ra3.8c, r1, ra8.8d ++ ror ra1.8c, r1, ra8.8c ; mov r5rep, -8 # ; r5 return val ++ ++ bra -, ra_link ++ # 4 ++ mov r1,0x3a281100 ++ ror r0, r1, ra8.8d ; mov ra_link, unif # ; link - load after we've used its previous val ++ ror ra1.8a, r1, ra8.8c ; v8min rb8, r0, rb5 ++# >>> branch ra_link ++ ++# r5 = -8 ++# r2 = fir_off_val ++# r3 = 128 ++.endm ++ ++:per_block_setup_8 ++ m_per_block_setup 8 ++ ++ ++ ++################################################################################ ++# ++# mc_filter_y_pxx ++# ++# Setup (& therefore uniform struct) shared with _bxx ++# Struct in m_luma_setup ++# ++# We can have 2 separate P reqs here as long as they mate to generate a ++# rectangular output block (i.e. h0 = h1, w0 = 8) ++# ++# At this point we have already issued PREREAD pairs of texture requests for the current block ++ ++.macro m_filter_y_pxx, v_bit_depth ++ ++# denom shift values ++.set i_wt_den_p5, (DENOM + 13 - v_bit_depth) ++.set i_wt_den_p6, (DENOM + 14 - v_bit_depth) ++ ++ m_luma_setup v_bit_depth ++ ++ shl r1, ra_wt_off_l0, i_wt_den_p5 ++ add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 # r2 = 0x4000 so mul24 safe even with -ve wt_mul ++ sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++ ++# retrieve texture results and pick out bytes ++# then submit two more texture requests ++ ++# This loop is identical to the B loop from here ---> ++:1 ++ add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++ ++ max r2, ra_y, 0 ; mov r1, 0 ++ min r2, r2, rb_max_y ; mov r3, ra_k1 ++ add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++ add t0s, ra_base, r2 ; mov rb5, rb6 ++ shr r0, r4, ra_xshift ; mov rb6, rb7 ++ ++ max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 # ; masks out all but wanted bytes ++ shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++ min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++ add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++ add t1s, rb_base2, r2 ; mov ra8, ra9 ++ ++# apply horizontal filter ++ add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++ mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++ sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++ sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++ sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++ add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++ ++ brr.anyn -, r:1b ++ sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++ mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++ asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++ # >>> .anyn 1b (r5 + r5) ++ ++ # apply vertical filter and write to VPM ++ # - r4* + r5 - r6 + r7 + r8 - r9 + r10 - r11 ++ ++ sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++ sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++ add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++ add r1, r1, r0 ; mul24 r0, ra11, rb11 ++# <--- to here ++ sub.setf -, r5, rb_i_tmu ; mov r3, ra_blk_height # ; NxtLoop: r3 = block height ++ sub r1, r1, ra4 ; mov.ifz rb_base2, rb_base2_next ++ sub r1, r1, r0 ; mov.ifz ra_base, ra_base_next ++ ++ asr r1, r1, 6 ; mov.ifz ra_y_y2, ra_y_y2_next ++ sub.setf -, r5, rb_lcount ; mul24 r0, r1, ra_wt_mul_l0 ++ add r0, r0, rb_wt_off ; mul24 r1, r1, ra_kmul_add ++ sub r1, r0, r1 ; v8subs r0, ra_height, r3 # ; NxtLoop: r0 = remaining height (0 saturate) ++ ++ brr.anyn -, r:1b ++ asr r1, r1, i_wt_den_p6 ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch # ; NxtLoop ++# >>> branch.anyn 1b (r5 - rb_lcount) ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed 16 height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link ++ ++# Here r1 = cur_blk_height - 16 so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_y_pxx ++ m_filter_y_pxx 8 ++ ++ ++################################################################################ ++ ++# mc_filter_b(y_x, base, y2_x2, base2, width_height, my2_mx2_my_mx, offsetweight0, this_dst, next_kernel) ++# ++# Setup (& therefore uniform struct) shared with _pxx ++# Struct in m_luma_setup ++# ++# l0 calc in els 0-7, L1 in 8-15 ++# Only els 0-7 write data that is stored back to ram (els 8-15 may write tosh) ++# ++# At this point we have already issued PREREAD pairs of texture requests for the current block ++ ++.macro m_filter_y_bxx, v_bit_depth ++ ++# denom shift values ++.set i_wt_den_p5, (DENOM + 13 - v_bit_depth) ++.set i_wt_den_p6, (DENOM + 14 - v_bit_depth) ++ ++ m_luma_setup v_bit_depth ++ ++ shl r1, ra_wt_off_l0, i_wt_den_p6 ++ add ra_wt_mul_l0, ra_wt_mul_l0, r3 ; mul24 r0, r2, ra_wt_mul_l0 ++ sub r1, r1, r0 ; mul24 r0, r2, ra_wt_mul_l1 ++ sub rb_wt_off, r1, r0 ; mov ra_ef.8a, rb4 ++ ++# This loop is identical to the P loop from here ---> ++:1 ++ add.setf -, ra_ef, ra_ef ; mul24 ra4, rb5, ra_ef ++ ++ max r2, ra_y, 0 ; mov r1, 0 ++ min r2, r2, rb_max_y ; mov r3, ra_k1 ++ add ra_y, ra_y, r3 ; mul24 r2, r2, rb_pitch ; ldtmu0 ++ add t0s, ra_base, r2 ; mov rb5, rb6 ++ shr r0, r4, ra_xshift ; mov rb6, rb7 ++ ++ max r2, ra_y2, r1 ; v8min r0, r0, rb_pmask ; ldtmu1 # ; masks out all but wanted bytes ++ shr r1, r4, rb_xshift2 ; mov rb7, ra8 ++ min r2, r2, rb_max_y ; v8min r1, r1, ra_pmax ++ add ra_y2, ra_y2, r3 ; mul24 r2, r2, rb_pitch ++ add t1s, rb_base2, r2 ; mov ra8, ra9 ++ ++# apply horizontal filter ++ add r5rep, r5, r3 ; mul24 r2, ra0.8a << 8, r1 << 8 @ "mul_used", 0 ++ mov r3, rb_fir_off_h ; mul24.ifnn r2, ra0.8a, r0 ++ sub r2, r3, r2 ; mul24 r3, ra0.8b << 1, r0 << 1 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8b << 9, r1 << 9 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra0.8c << 2, r0 << 2 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8c << 10, r1 << 10 @ "mul_used", 0 ++ sub r2, r2, r3 ; mul24 r3, ra0.8d << 3, r0 << 3 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra0.8d << 11, r1 << 11 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8a << 4, r0 << 4 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8a << 12, r1 << 12 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8b << 5, r0 << 5 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8b << 13, r1 << 13 @ "mul_used", 0 ++ sub r2, r2, r3 ; mul24 r3, ra1.8c << 6, r0 << 6 @ "mul_used", 0 ++ nop ; mul24.ifn r3, ra1.8c << 14, r1 << 14 @ "mul_used", 0 ++ add r2, r2, r3 ; mul24 r3, ra1.8d << 7, r0 << 7 @ "mul_used", 0 ++ add.setf -, r5, r5 ; mul24.ifn r3, ra1.8d << 15, r1 << 15 @ "mul_used", 0 ++ ++ brr.anyn -, r:1b ++ sub r2, r2, r3 ; mul24 r1, rb5, ra2.8b ++ mov ra9, rb10 ; mul24 r0, rb10, ra3.8b ++ asr ra11, r2, v_bit_depth - 8 ; mov rb10, ra11 ++ # >>> .anyn 1b (r5 + r5) ++ ++ # apply vertical filter and write to VPM ++ # - r4* + r5 - r6 + r7 + r8 - r9 + r10 - r11 ++ ++ sub r1, r1, r0 ; mul24 r0, rb6, ra2.8c ++ sub r1, r1, r0 ; mul24 r0, rb7, ra2.8d ++ add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ add r1, r1, r0 ; mul24 r0, rb10, ra3.8c ++ add r1, r1, r0 ; mul24 r0, ra11, rb11 ++# <--- to here ++ sub r1, r1, ra4 ++ sub r1, r1, r0 ; mov r2, rb_wt_off ++ ++ asr r1, r1, 6 ++ sub.setf -, r5, rb_i_tmu ; mul24 r0, r1, ra_wt_mul_l0 ++ mov.ifz rb_base2, rb_base2_next ; mul24 r1, r1, ra_kmul_add ++ sub r1, r0, r1 ; mov.ifz ra_y_y2, ra_y_y2_next ++ sub.setf -, r5, rb_lcount ; mov.ifz ra_base, ra_base_next ++ add r1, r1, r2 ; mov r0, r1 << 8 ++ add r1, r1, r0 ; mov r3, ra_blk_height # ; NxtLoop: r3 = block height ++ ++ brr.anyn -, r:1b ++ asr r1, r1, ra_wt_den_p7 ; mul24 r2, r3, rb_pitch # ; NxtLoop ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, 0 ; v8subs r0, ra_height, r3 # ; NxtLoop: r0 = remaining height (0 saturate) ++# >>> branch.anyn 1b (r5 - rb_lcount) ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed block_height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link (ra_height - remaining height) ++ ++# Here r1 = cur_blk_height - blk_height so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_y_bxx ++ m_filter_y_bxx 8 ++ ++################################################################################ ++# ++# typedef struct qpu_mc_pred_y_p00_s { ++# qpu_mc_src_t next_src1; ++# uint16_t h; ++# uint16_t w; ++# uint32_t wo1; ++# uint32_t dst_addr; ++# uint32_t next_fn; ++# } qpu_mc_pred_y_p00_t; ++ ++.macro m_filter_y_p00, v_bit_depth ++ ++.if v_bit_depth <= 8 ++.set v_x_shift, 0 ++.set v_x_mul, 1 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 7 ++.set v_dma_wh_shift, i_shift16 ++.else ++.set v_x_shift, 1 ++.set v_x_mul, 2 ++# Shifts to get width & height in the right place in ra_dma0 ++.set v_dma_h_shift, 8 ++.set v_dma_wh_shift, 15 ++.endif ++ ++ mov ra0, unif ; mov r0, elem_num # y_x ++ mov ra_xshift, ra_xshift_next ; v8subs r5rep, r5, r5 # [ra0 delay] ; r5 = 0 ++ add r0, ra0.16b, r0 ; mov ra_base_next, unif # ; src1.base ++.if v_x_shift != 0 ++ shl r0, r0, v_x_shift ++.endif ++ ++ max r0, r0, r5 ; mov ra_y_next, ra0.16a # ; width_height ++ min r0, r0, rb_max_x ; mov ra_width_height, unif ++ ++ shl ra_xshift_next, r0, 3 # Compute shifts ++ and r0, r0, -4 ++ sub r2, r5, rb_pitch ; mov ra_wt_off_mul_l0, unif # ; weight_offset ++ and r1, r0, r2 ++ xor r0, r0, r1 ; mul24 r1, r1, rb_xpitch ++ add r0, r0, r1 ; mov ra_dest, unif # Add stripe offsets ; dest addr ++ add ra_base_next, ra_base_next, r0 ; mov vw_setup, rb_vpm_init # [ra_width delay] ; set up VPM write ++ ++# get width,height of block (unif load above) ++# Compute vdw_setup1(dst_pitch-width) ++ shl r1, ra_width, v_x_shift ++ sub rb_dma1, rb_dma1_base, r1 ; mov r0, ra_height ++ sub rb_i_tmu, r0, PREREAD ; v8min r0, r0, ra_blk_height ++ shl r0, r0, v_dma_h_shift ; mov rb_lcount, r0 ++ add r0, r0, r1 # Combine width and height of destination area ++ shl rb_wt_off, ra_wt_off_l0, DENOM + 7 ++ shl r0, r0, v_dma_wh_shift ; mov ra_link, unif # Shift into bits 16 upwards of the vdw_setup0 register ; link ++ add ra_dma0, r0, rb_dma0_base ++ ++:1 ++ sub.setf -, r5, rb_i_tmu ; v8adds r5rep, r5, ra_k1 ++ nop ; mov.ifz ra_y, ra_y_next ; ldtmu0 ++ shr r0, r4, ra_xshift ; mov r3, rb_pitch ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++ add t0s, ra_base, r2 ; v8min r0, r0, rb_pmask ++ ++ sub.setf -, r5, rb_lcount ; mul24 r1, r0, ra_wt_mul_l0 ++ shl r1, r1, 8 ; mov r3, ra_blk_height ++ add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++ ++ brr.anyn -, r:1b ++ asr r1, r1, DENOM + 8 ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++# >>> branch.anyn 1b ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed 16 height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link ++ ++# Here r1 = cur_blk_height - 16 so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_y_p00 ++ m_filter_y_p00 8 ++ ++################################################################################ ++ ++.macro m_filter_y_b00, v_bit_depth ++# luma setup does a fair bit more than we need calculating filter coeffs ++# that we will never use but it saves I-cache to use it (also simple!) ++ m_luma_setup v_bit_depth ++ ++# Fix up vals that were expecting a filter (somewhat icky) ++ mov r2, 1 ++ add rb_i_tmu, rb_i_tmu, r2 ; mov r1, ra_wt_off_mul_l0 # Need in rX rather than raX for <<8 to do what we want ++ shl rb_wt_off, ra_wt_off_l0, DENOM + 8 ; v8subs r5quad, r5, r5 # [r1 << delay] ; r5quad OK for zero ++ nop ; mov.ifnz ra_wt_off_mul_l0, r1 << 8 ++ ++:1 ++ sub.setf -, r5, rb_i_tmu ; nop ; ldtmu1 ++ shr r1, r4, rb_xshift2 ; mov.ifz ra_y_y2, ra_y_y2_next ; ldtmu0 ++ shr r0, r4, ra_xshift ; mov r3, rb_pitch ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_max_y ; mov.ifz ra_base, ra_base_next ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++ add t0s, ra_base, r2 ; mov.ifz rb_base2, rb_base2_next ++ ++ max r2, ra_y2, 0 ++ min r2, r2, rb_max_y ++ add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++ add t1s, rb_base2, r2 ; v8min r0, r0, ra_pmax # v8subs masks out all but bottom byte ++ and r1, r1, rb_pmask ; mul24 r0, r0, ra_wt_mul_l0 ++ ++ sub.setf -, r5, rb_lcount ; mul24 r1, r1, ra_wt_mul_l1 ++ add r1, r0, r1 ; v8adds r5rep, r5, ra_k1 ++ ++ shl r1, r1, 8 ; mov r3, ra_blk_height ++ add r1, r1, rb_wt_off ; v8subs r0, ra_height, r3 ++ ++ brr.anyn -, r:1b ++ asr r1, r1, (DENOM + 9) - 32 # -32 to get valid shift immediate ++ min r1, r1, ra_pmax ; mov -, vw_wait ++ max vpm, r1, ra_k0 ; mul24 r2, r3, rb_pitch ++# >>> branch.anyn 1b ++ ++# r0 = remaining height (min 0) ++# r2 = r3 * rb_pitch ++# r3 = block_height ++ ++# If looping again then we consumed 16 height last loop ++# rb_dma1 (stride) remains constant ++# rb_i_tmu remains const (based on total height) ++# recalc ra_dma0, rb_lcount based on new segment height ++ ++ mov.setf ra_height, r0 ; mov vw_setup, ra_dma0 # ; VDW setup 0 ++ ++# DMA out ++ bra.anyz -, ra_link ++ min r0, r0, r3 ; mov vw_setup, rb_dma1 # ; Stride ++ sub r1, r0, r3 ; mov vw_addr, ra_dest # ; start the VDW ++ shl r1, r1, i_shift23 ++# >>> .anyz ra_link ++ ++# Here r1 = cur_blk_height - 16 so it will be 0 or -ve ++# We add to dma0 to reduce the number of output lines in the final block ++ brr -, r:1b ++ add rb_lcount, rb_lcount, r0 ++ add ra_dma0, ra_dma0, r1 ++ add ra_dest, ra_dest, r2 ; mov vw_setup, rb_vpm_init # ; Reset our VDM write pointer ++# >>> 1b ++.endm ++ ++::mc_filter_y_b00 ++ m_filter_y_b00 8 ++ ++################################################################################ ++################################################################################ ++# 10 BIT ++ ++::mc_setup_c10_q0 ++ m_setup_q0 ++::mc_setup_c10_qn ++ m_setup_c 10 ++ ++::mc_filter_c10_p ++ m_filter_c_p 0, 10 ++ ++::mc_filter_c10_p_l1 ++ m_filter_c_p 1, 10 ++ ++ ++::mc_filter_c10_b ++ m_filter_c_b 10 ++ ++# Even if these fns are the same as for other bit depths we want our own copy ++# to keep the code we are using in a single lump to avoid (direct map) cache ++# thrashing ++.set v_quads10, N_QPU_16 / 4 ++ ++::mc_sync10_q0 ++ m_sync_q 0, v_quads10 ++::mc_sync10_q1 ++ m_sync_q 1, v_quads10 ++::mc_sync10_q2 ++ m_sync_q 2, v_quads10 ++::mc_sync10_q3 ++ m_sync_q 3, v_quads10 ++::mc_sync10_q4 ++ m_sync_q 4, v_quads10 ++::mc_sync10_q5 ++ m_sync_q 5, v_quads10 ++::mc_sync10_q6 ++ m_sync_q 6, v_quads10 ++::mc_sync10_q7 ++ m_sync_q 7, v_quads10 ++::mc_sync10_q8 ++ m_sync_q 8, v_quads10 ++::mc_sync10_q9 ++ m_sync_q 9, v_quads10 ++::mc_sync10_q10 ++ m_sync_q 10, v_quads10 ++::mc_sync10_q11 ++ m_sync_q 11, v_quads10 ++ ++::mc_exit_y10_q0 ++::mc_exit_c10_q0 ++ m_exit_q0 ++ ++::mc_exit_y10_qn ++::mc_exit_c10_qn ++ m_exit_qn ++ ++::mc_setup_y10_q0 ++ m_setup_q0 ++::mc_setup_y10_qn ++ m_setup_y 10 ++ ++:per_block_setup_10 ++ m_per_block_setup 10 ++ ++::mc_filter_y10_pxx ++ m_filter_y_pxx 10 ++ ++::mc_filter_y10_p00 ++ m_filter_y_p00 10 ++ ++::mc_filter_y10_bxx ++ m_filter_y_bxx 10 ++ ++::mc_filter_y10_b00 ++ m_filter_y_b00 10 ++ ++ ++ ++::mc_end ++# Do not add code here because mc_end must appear after all other code. +diff --git a/libavcodec/rpi_hevc_shader_cmd.h b/libavcodec/rpi_hevc_shader_cmd.h +new file mode 100644 +index 0000000000..89711d776b +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader_cmd.h +@@ -0,0 +1,165 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#ifndef RPI_SHADER_CMD_H ++#define RPI_SHADER_CMD_H ++ ++#pragma pack(push, 4) ++ ++#if RPI_QPU_EMU_C && RPI_QPU_EMU_Y ++// If mixed then we are just confused and get a lot of warnings.... ++typedef const uint8_t * qpu_mc_src_addr_t; ++typedef uint8_t * qpu_mc_dst_addr_t; ++#else ++typedef uint32_t qpu_mc_src_addr_t; ++typedef uint32_t qpu_mc_dst_addr_t; ++#endif ++ ++typedef struct qpu_mc_src_s ++{ ++ int16_t y; ++ int16_t x; ++ qpu_mc_src_addr_t base; ++} qpu_mc_src_t; ++ ++ ++typedef struct qpu_mc_pred_c_p_s { ++ qpu_mc_src_t next_src; ++ uint16_t h; ++ uint16_t w; ++ uint32_t coeffs_x; ++ uint32_t coeffs_y; ++ uint32_t wo_u; ++ uint32_t wo_v; ++ qpu_mc_dst_addr_t dst_addr_c; ++ uint32_t next_fn; ++} qpu_mc_pred_c_p_t; ++ ++typedef struct qpu_mc_pred_c_b_s { ++ qpu_mc_src_t next_src1; ++ uint16_t h; ++ uint16_t w; ++ uint32_t coeffs_x1; ++ uint32_t coeffs_y1; ++ int16_t weight_u1; ++ int16_t weight_v1; ++ qpu_mc_src_t next_src2; ++ uint32_t coeffs_x2; ++ uint32_t coeffs_y2; ++ uint32_t wo_u2; ++ uint32_t wo_v2; ++ qpu_mc_dst_addr_t dst_addr_c; ++ uint32_t next_fn; ++} qpu_mc_pred_c_b_t; ++ ++typedef struct qpu_mc_pred_c_s_s { ++ qpu_mc_src_t next_src1; ++ uint32_t pic_cw; // C Width (== Y width / 2) ++ uint32_t pic_ch; // C Height (== Y Height / 2) ++ uint32_t stride2; ++ uint32_t stride1; ++ qpu_mc_src_t next_src2; ++ uint32_t next_fn; ++} qpu_mc_pred_c_s_t; ++ ++typedef struct qpu_mc_pred_c_s { ++ union { ++ qpu_mc_pred_c_p_t p; ++ qpu_mc_pred_c_b_t b; ++ qpu_mc_pred_c_s_t s; ++ }; ++} qpu_mc_pred_c_t; ++ ++ ++typedef struct qpu_mc_pred_y_p_s { ++ qpu_mc_src_t next_src1; ++ qpu_mc_src_t next_src2; ++ uint16_t h; ++ uint16_t w; ++ uint32_t mymx21; ++ uint32_t wo1; ++ uint32_t wo2; ++ qpu_mc_dst_addr_t dst_addr; ++ uint32_t next_fn; ++} qpu_mc_pred_y_p_t; ++ ++typedef struct qpu_mc_pred_y_p00_s { ++ qpu_mc_src_t next_src1; ++ uint16_t h; ++ uint16_t w; ++ uint32_t wo1; ++ qpu_mc_dst_addr_t dst_addr; ++ uint32_t next_fn; ++} qpu_mc_pred_y_p00_t; ++ ++typedef struct qpu_mc_pred_y_s_s { ++ qpu_mc_src_t next_src1; ++ qpu_mc_src_t next_src2; ++ uint16_t pic_h; ++ uint16_t pic_w; ++ uint32_t stride2; ++ uint32_t stride1; ++ uint32_t next_fn; ++} qpu_mc_pred_y_s_t; ++ ++typedef struct qpu_mc_pred_sync_s { ++ uint32_t next_fn; ++} qpu_mc_pred_sync_t; ++ ++// Only a useful structure in that it allows us to return something other than a void * ++typedef struct qpu_mc_pred_y_s { ++ union { ++ qpu_mc_pred_y_p_t p; ++ qpu_mc_pred_y_p00_t p00; ++ qpu_mc_pred_y_s_t s; ++ }; ++} qpu_mc_pred_y_t; ++ ++typedef union qpu_mc_pred_cmd_u { ++ qpu_mc_pred_y_t y; ++ qpu_mc_pred_c_t c; ++ qpu_mc_pred_sync_t sync; ++} qpu_mc_pred_cmd_t; ++ ++static void inline qpu_mc_link_set(qpu_mc_pred_cmd_t * const cmd, const uint32_t fn) ++{ ++ // Link is last el of previous cmd ++ ((uint32_t *)cmd)[-1] = fn; ++} ++ ++#define QPU_MC_PRED_N_Y8 12 ++#define QPU_MC_PRED_N_C8 12 ++ ++#define QPU_MC_PRED_N_Y10 12 ++#define QPU_MC_PRED_N_C10 12 ++ ++#define QPU_MC_DENOM 7 ++ ++#pragma pack(pop) ++ ++#endif ++ +diff --git a/libavcodec/rpi_hevc_shader_template.c b/libavcodec/rpi_hevc_shader_template.c +new file mode 100644 +index 0000000000..77d8366eb8 +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader_template.c +@@ -0,0 +1,88 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#include "hevc.h" ++#include "rpi_hevcdec.h" ++#include "libavutil/rpi_sand_fns.h" ++#include "rpi_hevc_shader_cmd.h" ++#include "rpi_hevc_shader_template.h" ++ ++typedef struct shader_track_s ++{ ++ const union qpu_mc_pred_cmd_u *qpu_mc_curr; ++ const struct qpu_mc_src_s *last_l0; ++ const struct qpu_mc_src_s *last_l1; ++ uint32_t width; // pic_width * PW ++ uint32_t height; ++ uint32_t stride2; ++ uint32_t stride1; ++} shader_track_t; ++ ++static int wtoidx(const unsigned int w) ++{ ++ static const uint8_t pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ return pel_weight[w]; ++} ++ ++static const int fctom(uint32_t x) ++{ ++ int rv; ++ // As it happens we can take the 2nd filter term & divide it by 8 ++ // (dropping fractions) to get the fractional move ++ rv = 8 - ((x >> 11) & 0xf); ++ av_assert2(rv >= 0 && rv <= 7); ++ return rv; ++} ++ ++static inline int32_t ext(int32_t x, unsigned int shl, unsigned int shr) ++{ ++ return (x << shl) >> shr; ++} ++ ++static inline int woff_p(HEVCRpiContext *const s, int32_t x) ++{ ++ return ext(x, 0, 17 + s->ps.sps->bit_depth - 8); ++} ++ ++static inline int woff_b(HEVCRpiContext *const s, int32_t x) ++{ ++ return ext(x - 0x10000, 0, 16 + s->ps.sps->bit_depth - 8); ++} ++ ++static inline int wweight(int32_t x) ++{ ++ return ext(x, 16, 16); ++} ++ ++ ++#define PW 1 ++#include "rpi_hevc_shader_template_fn.h" ++ ++#undef PW ++#define PW 2 ++#include "rpi_hevc_shader_template_fn.h" ++ +diff --git a/libavcodec/rpi_hevc_shader_template.h b/libavcodec/rpi_hevc_shader_template.h +new file mode 100644 +index 0000000000..0fc5a45e9f +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader_template.h +@@ -0,0 +1,49 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#ifndef LIBAVCODEC_RPI_SHADER_TEMPLATE_H ++#define LIBAVCODEC_RPI_SHADER_TEMPLATE_H ++ ++struct HEVCRpiContext; ++struct HEVCRpiInterPredEnv; ++ ++void ff_hevc_rpi_shader_c8(struct HEVCRpiContext *const s, ++ const struct HEVCRpiInterPredEnv *const ipe_y, ++ const struct HEVCRpiInterPredEnv *const ipe_c); ++ ++void ff_hevc_rpi_shader_c16(struct HEVCRpiContext *const s, ++ const struct HEVCRpiInterPredEnv *const ipe_y, ++ const struct HEVCRpiInterPredEnv *const ipe_c); ++ ++void rpi_sand_dump8(const char * const name, ++ const uint8_t * const base, const int stride1, const int stride2, int x, int y, int w, int h, const int is_c); ++ ++void rpi_sand_dump16(const char * const name, ++ const uint8_t * const base, const int stride1, const int stride2, int x, int y, int w, int h, const int is_c); ++ ++#endif ++ +diff --git a/libavcodec/rpi_hevc_shader_template_fn.h b/libavcodec/rpi_hevc_shader_template_fn.h +new file mode 100644 +index 0000000000..10c163a4b9 +--- /dev/null ++++ b/libavcodec/rpi_hevc_shader_template_fn.h +@@ -0,0 +1,502 @@ ++/* ++Copyright (c) 2017 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#define STRCAT(x,y) x##y ++ ++#if PW == 1 ++#define pixel uint8_t ++#define FUNC(f) STRCAT(f, 8) ++#elif PW == 2 ++#define pixel uint16_t ++#define FUNC(f) STRCAT(f, 16) ++#else ++#error Unexpected PW ++#endif ++ ++#define PATCH_STRIDE (16 * PW) ++ ++static void FUNC(dup_lr)(uint8_t * dst, const uint8_t * src, unsigned int w, unsigned int h, unsigned int stride) ++{ ++ for (unsigned int i = 0; i != h; ++i, dst += stride, src += stride) { ++ const pixel s = *(const pixel *)src; ++ pixel * d = (pixel *)dst; ++ for (unsigned int j = 0; j < w; j += PW) { ++ *d++ = s; ++ } ++ } ++} ++ ++static void FUNC(dup_tb)(uint8_t * dst, const uint8_t * src, unsigned int w, unsigned int h, unsigned int stride) ++{ ++ for (unsigned int i = 0; i != h; ++i, dst += stride) { ++ memcpy(dst, src, w); ++ } ++} ++ ++static void FUNC(get_patch_y)(const shader_track_t * const st, ++ uint8_t * dst, const unsigned int dst_stride, ++ const qpu_mc_src_t *src, ++ unsigned int _w, unsigned int _h) ++{ ++ int x = src->x * PW; ++ int y = src->y; ++ int w = _w * PW; ++ int h = _h; ++ int dl = 0; ++ int dr = 0; ++ int dt = 0; ++ int db = 0; ++ ++ if (x < 0) { ++ if (-x >= w) ++ x = PW - w; ++ dl = -x; ++ w += x; ++ x = 0; ++ } ++ if (x + w > st->width) { ++ if (x >= st->width) ++ x = st->width - PW; ++ dr = (x + w) - st->width; ++ w = st->width - x; ++ } ++ ++ // Y ++ if (y < 0) { ++ if (-y >= h) ++ y = 1 - h; ++ dt = -y; ++ h += y; ++ y = 0; ++ } ++ if (y + h > st->height) { ++ if (y >= st->height) ++ y = st->height - 1; ++ db = (y + h) - st->height; ++ h = st->height - y; ++ } ++ ++ dst += dl + dt * dst_stride; ++ FUNC(av_rpi_sand_to_planar_y)(dst, dst_stride, (const uint8_t *)src->base, st->stride1, st->stride2, x, y, w, h); ++ ++ // Edge dup ++ if (dl != 0) ++ FUNC(dup_lr)(dst - dl, dst, dl, h, dst_stride); ++ if (dr != 0) ++ FUNC(dup_lr)(dst + w, dst + w - PW, dr, h, dst_stride); ++ w += dl + dr; ++ dst -= dl; ++ ++ if (dt != 0) ++ FUNC(dup_tb)(dst - dt * dst_stride, dst, w, dt, dst_stride); ++ if (db != 0) ++ FUNC(dup_tb)(dst + h * dst_stride, dst + (h - 1) * dst_stride, w, db, dst_stride); ++} ++ ++ ++ ++static void FUNC(get_patch_c)(const shader_track_t * const st, ++ uint8_t * dst_u, uint8_t * dst_v, const unsigned int dst_stride, ++ const qpu_mc_src_t *src, ++ unsigned int _w, unsigned int _h) ++{ ++ int x = src->x * PW; ++ int y = src->y; ++ int w = _w * PW; ++ int h = _h; ++ int dl = 0; ++ int dr = 0; ++ int dt = 0; ++ int db = 0; ++ const int width = st->width; ++ const int height = st->height; ++ ++ if (x < 0) { ++ if (-x >= w) ++ x = PW - w; ++ dl = -x; ++ w += x; ++ x = 0; ++ } ++ if (x + w > width) { ++ if (x >= width) ++ x = width - PW; ++ dr = (x + w) - width; ++ w = width - x; ++ } ++ ++ // Y ++ if (y < 0) { ++ if (-y >= h) ++ y = 1 - h; ++ dt = -y; ++ h += y; ++ y = 0; ++ } ++ if (y + h > height) { ++ if (y >= height) ++ y = height - 1; ++ db = (y + h) - height; ++ h = height - y; ++ } ++ ++ dst_u += dl + dt * dst_stride; ++ dst_v += dl + dt * dst_stride; ++ FUNC(av_rpi_sand_to_planar_c)(dst_u, dst_stride, dst_v, dst_stride, (const uint8_t *)src->base, st->stride1, st->stride2, x, y, w, h); ++ ++ // Edge dup ++ if (dl != 0) ++ { ++ FUNC(dup_lr)(dst_u - dl, dst_u, dl, h, dst_stride); ++ FUNC(dup_lr)(dst_v - dl, dst_v, dl, h, dst_stride); ++ } ++ if (dr != 0) ++ { ++ FUNC(dup_lr)(dst_u + w, dst_u + w - PW, dr, h, dst_stride); ++ FUNC(dup_lr)(dst_v + w, dst_v + w - PW, dr, h, dst_stride); ++ } ++ w += dl + dr; ++ dst_u -= dl; ++ dst_v -= dl; ++ ++ if (dt != 0) ++ { ++ FUNC(dup_tb)(dst_u - dt * dst_stride, dst_u, w, dt, dst_stride); ++ FUNC(dup_tb)(dst_v - dt * dst_stride, dst_v, w, dt, dst_stride); ++ } ++ if (db != 0) ++ { ++ FUNC(dup_tb)(dst_u + h * dst_stride, dst_u + (h - 1) * dst_stride, w, db, dst_stride); ++ FUNC(dup_tb)(dst_v + h * dst_stride, dst_v + (h - 1) * dst_stride, w, db, dst_stride); ++ } ++} ++ ++// w, y, w, h in pixels ++// stride1, stride2 in bytes ++void FUNC(rpi_sand_dump)(const char * const name, ++ const uint8_t * const base, const int stride1, const int stride2, int x, int y, int w, int h, const int is_c) ++{ ++ const int mask = stride2 == 0 ? ~0 : stride1 - 1; ++ ++ printf("%s (%d,%d) %dx%d\n", name, x, y, w, h); ++ ++ if (is_c) { ++ x *= 2; ++ w *= 2; ++ } ++ ++ for (int i = y; i != y + h; ++i) { ++ for (int j = x; j != x + w; ++j) { ++ const uint8_t * p = base + ((j*PW) & mask) + i * stride1 + ((j*PW) & ~mask) * stride2; ++ char sep = is_c && (j & 1) == 0 ? ':' : ' '; ++#if PW == 1 ++ if (j < 0 || i < 0) ++ printf("..%c", sep); ++ else ++ printf("%02x%c", *(const pixel*)p, sep); ++#else ++ if (j < 0 || i < 0) ++ printf("...%c", sep); ++ else ++ printf("%03x%c", *(const pixel*)p, sep); ++#endif ++ } ++ printf("\n"); ++ } ++} ++ ++ ++void FUNC(ff_hevc_rpi_shader_c)(HEVCRpiContext *const s, ++ const HEVCRpiInterPredEnv *const ipe_y, ++ const HEVCRpiInterPredEnv *const ipe_c) ++{ ++ for (int c_idx = 0; c_idx < 2; ++c_idx) ++ { ++ const HEVCRpiInterPredEnv *const ipe = c_idx == 0 ? ipe_y : ipe_c; ++ shader_track_t tracka[QPU_N_MAX] = {{NULL}}; ++ unsigned int exit_n = 0; ++ ++ if (ipe == NULL || !ipe->used) { ++ continue; ++ } ++ ++ do { ++ for (unsigned int i = 0; i != ipe->n; ++i) { ++ const HEVCRpiInterPredQ * const q = ipe->q + i; ++ shader_track_t * const st = tracka + i; ++ const qpu_mc_pred_cmd_t * cmd = st->qpu_mc_curr == NULL ? q->qpu_mc_base : st->qpu_mc_curr; ++ ++ for (;;) { ++ const uint32_t link = (cmd == q->qpu_mc_base) ? q->code_setup : ((uint32_t *)cmd)[-1]; ++ ++ if (link == q->code_setup) { ++ if (c_idx == 0) { ++ // Luma ++ const qpu_mc_pred_y_s_t *const c = &cmd->y.s; ++ ++ st->height = c->pic_h; ++ st->width = c->pic_w * PW; ++ st->stride1 = c->stride1; ++ st->stride2 = c->stride2; ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else { ++ // Chroma ++ const qpu_mc_pred_c_s_t *const c = &cmd->c.s; ++ ++ st->height = c->pic_ch; ++ st->width = c->pic_cw * PW; ++ st->stride1 = c->stride1; ++ st->stride2 = c->stride2; ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ } ++ else if (link == s->qpu.y_pxx) { ++ const qpu_mc_pred_y_p_t *const c = &cmd->y.p; ++ const int w1 = FFMIN(c->w, 8); ++ const int w2 = c->w - w1; ++ ++ uint8_t patch_y1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_y2[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ ++ FUNC(get_patch_y)(st, ++ patch_y1, PATCH_STRIDE, ++ st->last_l0, ++ 16, c->h + 7); ++ if (w2 > 0) { ++ FUNC(get_patch_y)(st, ++ patch_y2, PATCH_STRIDE, ++ st->last_l1, ++ 16, c->h + 7); ++ } ++ ++ // wo[offset] = offset*2+1 ++ s->hevcdsp.put_hevc_qpel_uni_w[wtoidx(w1)][(c->mymx21 & 0xff00) != 0][(c->mymx21 & 0xff) != 0]( ++ (uint8_t *)c->dst_addr, st->stride1, patch_y1 + 3 * (PATCH_STRIDE + PW), PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo1), woff_p(s, c->wo1), (c->mymx21 & 0xff), ((c->mymx21 >> 8) & 0xff), w1); ++ if (w2 > 0) { ++ s->hevcdsp.put_hevc_qpel_uni_w[wtoidx(w2)][(c->mymx21 & 0xff000000) != 0][(c->mymx21 & 0xff0000) != 0]( ++ (uint8_t *)c->dst_addr + 8 * PW, st->stride1, patch_y2 + 3 * (PATCH_STRIDE + PW), PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo2), woff_p(s, c->wo2), ((c->mymx21 >> 16) & 0xff), ((c->mymx21 >> 24) & 0xff), w2); ++ } ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.y_bxx) { ++ const qpu_mc_pred_y_p_t *const c = &cmd->y.p; ++ ++ uint8_t patch_y1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_y2[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ int16_t patch_y3[MAX_PB_SIZE * MAX_PB_SIZE]; ++ ++ FUNC(get_patch_y)(st, ++ patch_y1, PATCH_STRIDE, ++ st->last_l0, ++ 16, c->h + 7); ++ FUNC(get_patch_y)(st, ++ patch_y2, PATCH_STRIDE, ++ st->last_l1, ++ 16, c->h + 7); ++ ++ s->hevcdsp.put_hevc_qpel[wtoidx(c->w)][(c->mymx21 & 0xff00) != 0][(c->mymx21 & 0xff) != 0]( ++ patch_y3, patch_y1+ 3 * (PATCH_STRIDE + PW), PATCH_STRIDE, ++ c->h, (c->mymx21 & 0xff), ((c->mymx21 >> 8) & 0xff), c->w); ++ ++ s->hevcdsp.put_hevc_qpel_bi_w[wtoidx(c->w)][(c->mymx21 & 0xff000000) != 0][(c->mymx21 & 0xff0000) != 0]( ++ (uint8_t *)c->dst_addr, st->stride1, patch_y2 + 3 * (PATCH_STRIDE + PW), PATCH_STRIDE, patch_y3, ++ c->h, QPU_MC_DENOM, wweight(c->wo1), wweight(c->wo2), ++ 0, woff_b(s, c->wo2), ((c->mymx21 >> 16) & 0xff), ((c->mymx21 >> 24) & 0xff), c->w); ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.y_p00) { ++ const qpu_mc_pred_y_p00_t *const c = &cmd->y.p00; ++ ++ uint8_t patch_y1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ ++ FUNC(get_patch_y)(st, ++ patch_y1, PATCH_STRIDE, ++ st->last_l0, ++ 16, c->h + 7); ++ ++ // wo[offset] = offset*2+1 ++ s->hevcdsp.put_hevc_qpel_uni_w[wtoidx(c->w)][0][0]( ++ (uint8_t *)c->dst_addr, st->stride1, patch_y1, PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo1), woff_p(s, c->wo1), 0, 0, c->w); ++ ++ st->last_l0 = &c->next_src1; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.y_b00) { ++ const qpu_mc_pred_y_p_t *const c = &cmd->y.p; ++ ++ uint8_t patch_y1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_y2[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ int16_t patch_y3[MAX_PB_SIZE * MAX_PB_SIZE]; ++ ++ av_assert0(c->w <= 16 && c->h <= 64); ++ ++ FUNC(get_patch_y)(st, ++ patch_y1, PATCH_STRIDE, ++ st->last_l0, ++ 16, c->h); ++ FUNC(get_patch_y)(st, ++ patch_y2, PATCH_STRIDE, ++ st->last_l1, ++ 16, c->h); ++ ++ s->hevcdsp.put_hevc_qpel[wtoidx(c->w)][0][0]( ++ patch_y3, patch_y1, PATCH_STRIDE, ++ c->h, 0, 0, c->w); ++ ++ s->hevcdsp.put_hevc_qpel_bi_w[wtoidx(c->w)][0][0]( ++ (uint8_t *)c->dst_addr, st->stride1, patch_y2, PATCH_STRIDE, patch_y3, ++ c->h, QPU_MC_DENOM, wweight(c->wo1), wweight(c->wo2), ++ 0, woff_b(s, c->wo2), 0, 0, c->w); ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.c_pxx) { ++ const qpu_mc_pred_c_p_t *const c = &cmd->c.p; ++ const int mx = fctom(c->coeffs_x); ++ const int my = fctom(c->coeffs_y); ++ ++ uint8_t patch_u1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_v1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_u3[8 * 16 * PW]; ++ uint8_t patch_v3[8 * 16 * PW]; ++ ++ FUNC(get_patch_c)(st, patch_u1, patch_v1, PATCH_STRIDE, st->last_l0, 8+3, c->h + 3); ++ ++ s->hevcdsp.put_hevc_epel_uni_w[wtoidx(c->w)][my != 0][mx != 0]( ++ patch_u3, 8 * PW, patch_u1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo_u), woff_p(s, c->wo_u), mx, my, c->w); ++ s->hevcdsp.put_hevc_epel_uni_w[wtoidx(c->w)][my != 0][mx != 0]( ++ patch_v3, 8 * PW, patch_v1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo_v), woff_p(s, c->wo_v), mx, my, c->w); ++ ++ FUNC(av_rpi_planar_to_sand_c)((uint8_t *)c->dst_addr_c, st->stride1, st->stride2, patch_u3, 8 * PW, patch_v3, 8 * PW, 0, 0, c->w * PW, c->h); ++ ++ st->last_l0 = &c->next_src; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.c_pxx_l1) { ++ const qpu_mc_pred_c_p_t *const c = &cmd->c.p; ++ const int mx = fctom(c->coeffs_x); ++ const int my = fctom(c->coeffs_y); ++ ++ uint8_t patch_u1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_v1[PATCH_STRIDE * 72]; // (Max width + 8) * (max height + 8) ++ uint8_t patch_u3[8 * 16 * PW]; ++ uint8_t patch_v3[8 * 16 * PW]; ++ ++ FUNC(get_patch_c)(st, patch_u1, patch_v1, PATCH_STRIDE, st->last_l1, 8+3, c->h + 3); ++ ++ s->hevcdsp.put_hevc_epel_uni_w[wtoidx(c->w)][my != 0][mx != 0]( ++ patch_u3, 8 * PW, patch_u1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo_u), woff_p(s, c->wo_u), mx, my, c->w); ++ s->hevcdsp.put_hevc_epel_uni_w[wtoidx(c->w)][my != 0][mx != 0]( ++ patch_v3, 8 * PW, patch_v1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, QPU_MC_DENOM, wweight(c->wo_v), woff_p(s, c->wo_v), mx, my, c->w); ++ ++ FUNC(av_rpi_planar_to_sand_c)((uint8_t *)c->dst_addr_c, st->stride1, st->stride2, patch_u3, 8 * PW, patch_v3, 8 * PW, 0, 0, c->w * PW, c->h); ++ ++ st->last_l1 = &c->next_src; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == s->qpu.c_bxx) { ++ const qpu_mc_pred_c_b_t *const c = &cmd->c.b; ++ const int mx1 = fctom(c->coeffs_x1); ++ const int my1 = fctom(c->coeffs_y1); ++ const int mx2 = fctom(c->coeffs_x2); ++ const int my2 = fctom(c->coeffs_y2); ++ ++ uint8_t patch_u1[PATCH_STRIDE * 72]; ++ uint8_t patch_v1[PATCH_STRIDE * 72]; ++ uint8_t patch_u2[PATCH_STRIDE * 72]; ++ uint8_t patch_v2[PATCH_STRIDE * 72]; ++ uint8_t patch_u3[8 * 16 * PW]; ++ uint8_t patch_v3[8 * 16 * PW]; ++ uint16_t patch_u4[MAX_PB_SIZE * MAX_PB_SIZE]; ++ uint16_t patch_v4[MAX_PB_SIZE * MAX_PB_SIZE]; ++ ++ FUNC(get_patch_c)(st, patch_u1, patch_v1, PATCH_STRIDE, st->last_l0, 8+3, c->h + 3); ++ FUNC(get_patch_c)(st, patch_u2, patch_v2, PATCH_STRIDE, st->last_l1, 8+3, c->h + 3); ++ ++ s->hevcdsp.put_hevc_epel[wtoidx(c->w)][my1 != 0][mx1 != 0]( ++ patch_u4, patch_u1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, mx1, my1, c->w); ++ s->hevcdsp.put_hevc_epel[wtoidx(c->w)][my1 != 0][mx1 != 0]( ++ patch_v4, patch_v1 + PATCH_STRIDE + PW, PATCH_STRIDE, ++ c->h, mx1, my1, c->w); ++ ++ s->hevcdsp.put_hevc_epel_bi_w[wtoidx(c->w)][my2 != 0][mx2 != 0]( ++ patch_u3, 8 * PW, patch_u2 + PATCH_STRIDE + PW, PATCH_STRIDE, patch_u4, ++ c->h, QPU_MC_DENOM, c->weight_u1, wweight(c->wo_u2), ++ 0, woff_b(s, c->wo_u2), mx2, my2, c->w); ++ s->hevcdsp.put_hevc_epel_bi_w[wtoidx(c->w)][my2 != 0][mx2 != 0]( ++ patch_v3, 8 * PW, patch_v2 + PATCH_STRIDE + PW, PATCH_STRIDE, patch_v4, ++ c->h, QPU_MC_DENOM, c->weight_v1, wweight(c->wo_v2), ++ 0, woff_b(s, c->wo_v2), mx2, my2, c->w); ++ ++ FUNC(av_rpi_planar_to_sand_c)((uint8_t *)c->dst_addr_c, st->stride1, st->stride2, patch_u3, 8 * PW, patch_v3, 8 * PW, 0, 0, c->w * PW, c->h); ++ ++ st->last_l0 = &c->next_src1; ++ st->last_l1 = &c->next_src2; ++ cmd = (const qpu_mc_pred_cmd_t *)(c + 1); ++ } ++ else if (link == q->code_sync) { ++ cmd = (const qpu_mc_pred_cmd_t *)((uint32_t *)cmd + 1); ++ break; ++ } ++ else if (link == q->code_exit) { ++ // We expect exit to occur without other sync ++ av_assert0(i == exit_n); ++ ++exit_n; ++ break; ++ } ++ else { ++ av_assert0(0); ++ } ++ } ++ ++ st->qpu_mc_curr = cmd; ++ } ++ } while (exit_n == 0); ++ } ++} ++ ++#undef FUNC ++#undef pixel ++ +diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s +new file mode 100644 +index 0000000000..3caef20137 +--- /dev/null ++++ b/libavcodec/rpi_hevc_transform.s +@@ -0,0 +1,444 @@ ++# ****************************************************************************** ++# Argon Design Ltd. ++# (c) Copyright 2015 Argon Design Ltd. All rights reserved. ++# ++# Module : HEVC ++# Author : Peter de Rivaz ++# ****************************************************************************** ++ ++# USE_STACK = 1 means temporary data stored on the stack (requires build with larger stack) ++# USE_STACK = 0 means temporary data stored in fixed per-VPU data buffers (requires modifications to vasm to handle instruction encoding for PC relative instructions) ++.set USE_STACK, 0 ++ ++# Lines that fail to assemble start with #: ++# The script insert_magic_opcodes.sh inserts the machine code directly for these. ++# HEVC VPU Transform ++# ++# Transform matrix can be thought of as ++# output row vector = input row vector * transMatrix2 ++# ++# The even rows of the matrix are symmetric ++# The odd rows of the matrix are antisymmetric ++# ++# So only need to compute the first half of the results, then can compute the remainder with a butterfly ++# ++# EXAMPLE ++# (a b c d) (1 2 2 1) ++# (3 4 -4 -3) ++# (5 6 6 5) ++# (7 8 -8 -7) ++# ++# x=(a c)(1 2) = 1a+5c 2a+6c ++# (5 6) ++# ++# y=(b d)(3 4) = 3b+7d 4b+8d ++# (7 8) ++# ++# u=x+y = 1a+5c+3b+7d 2a+4b+6c+8d ++# v=x-y = 1a+5c-3b-7d 2a+6c-4b-8d ++# ++# Final results are (u , v[::-1]) ++# ++# ++# For 32x1 input, load even rows into HX(0++,0), odd rows into HX(16++,0) ++# Apply the even matrix first and stop before rounding ++# Then apply the odd matrix in a full manner: ++# ++# First step is to compute partial products with the first input (16 cycles) ++# 1a 3b 5c 7d 16x1 input coefficients produce 16x16 output ++# 2a 4b 6c 8d ++# 2a -4b 6c -8d ++# 1a -3b 5c -7d ++# ++# Second step is to sum partial products into final position (8 cycles) ++# 1a+3b+5c+7d ++# 2a+4b+6c+8d ++# 2a-4b+6c-8d ++# 1a-3b+5c-7d ++# ++# Then can apply butterfly to combine even results and odd results + rounding to produce 16 rows of output at a time (need to save in transposed format) ++# ++# For 16x16 no butterfly is required and can store final results in original location (Could do 2 16x16s in parallel to make use of the trick - saves on the adds) ++# ++# For 8x8 we could compute two in parallel. ++# ++# ++ ++# Columns are transformed first ++# ++# Store top left half of transMatrix2 in ++# Store bottom left half of transMatrix2 in HX(32,32) ++# ++# For 16x16 ++# HX(0:15,0) contains input data before transform ++# HY(0:15,0) contains 32bit output data after transform ++# HX(32,0) contains even rows of left half of transMatrix2 ++# HX(32,32) contains odd rows of left half of transMatrix2 ++# HY(48,0) contains partial products ready for summing ++# ++ ++ ++# hevc_trans_16x16(short *transMatrix2, short *coeffs, int num) # TODO add size so we can branch to correct implementation (or perhaps have coeffs32 and num32 as secondary inputs!) ++# transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) ++# coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) ++# num: number of 16x16 transforms to be done ++# coeffs32 ++# num32: number of 32x32 transforms ++# command 0 for transform, 1 for memclear16(int16_t *dst,num16) ++# ++ ++.equ TRANS_SHIFT, 20 - BIT_DEPTH ++.equ TRANS_RND2, 1 << (TRANS_SHIFT - 1) ++.equ TRANS_ASL2, 16 - TRANS_SHIFT ++ ++ ++hevc_trans_16x16: ++ push r6-r15, lr # TODO cut down number of used registers ++ mov r14,r3 # coeffs32 ++ mov r15,r4 # num32 ++ mov r3, 16*2 # Stride of transMatrix2 in bytes ++ vldh HX(32++,0),(r0 += r3) REP 16 # This is the 16x16 matrix, a transform is equivalent to multiplying input row vector * matrix ++ ++ add r0, 16*16*2 # For 32x32 transforms we also need this matrix ++ vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix ++ ++ # Now use r0 to describe which matrix we are working on. ++ # Allows us to prefetch the next block of coefficients for efficiency. ++ mov r0,0 # This describes the location where we read our coefficients from ++ mov r3,16*2 # Stride of coefficients in bytes (TODO remove) ++ mov r7,16*16*2 # Total block size ++ mov r8,64*16 # Value used to swap from current to next VRF location ++ mov r4,64 # Constant used for rounding first pass ++ mov r5,TRANS_RND2 # Constant used for rounding second pass ++ ++ sub sp,sp,64+16*16*2 # Move on stack pointer in case interrupt occurs and uses stack ++ ++ add r11,sp,64 # Space for 32 bytes before, and rounding ++ lsr r11,5 ++ lsl r11,5 # Make sure r11 is rounded to multiple of 2**5==32 ++ ++ lsr r10, r2, 16 # Number of compressed blocks stored in top short ++ extu r2,16 ++ # At start of block r0,r1 point to the current block (that has already been loaded) ++ # r0 VRF location of current block ++ # r1 address of current block ++ # r2 number of 16*16 transforms to do ++ # r3 Stride of coefficients (==32) ++ # r4 TRANS_RND1 (64) ++ # r5 TRANS_RND2 ++ # r6 temporary used inside col_trans16 ++ # r7 16*16*2 total bytes in block ++ # r8 64*16 VRF switch locations ++ # r9 temporary in unpack_coeff for index ++ # r10 number of 16x16 transforms using compression ++ # r11 unpacked data buffer (16*16 shorts) (preceded by 16 shorts of packed data buffer) ++ # r12 temporary counter in unpack_coeff ++ # r13 ++ # r14 Save information for 32 bit transform (coeffs location) ++ # r15 Save information for 32 bit transform (number of transforms) ++ cmp r2,0 ++ beq done16x16s ++block_loop: ++ # With compressed coefficients, we don't use prefetch as we don't want to issue unnecessary memory requests ++ cmp r10,0 ++ mov r6, r1 ++ beq not_compressed ++ sub r10, 1 ++ bl unpack16x16 ++not_compressed: ++ #mov r6,r1 # DEBUG without compress ++ vldh HX(0++,0)+r0,(r6 += r3) REP 16 ++ #eor r0,r8 ++ #add r1,r7 ++ # Prefetch the next block ++ #bl unpack16x16 ++ #vldh HX(0++,0)+r0,(r6 += r3) REP 16 ++ #vmov HX(0++,0)+r0,0 REP 16 # DEBUG ++ #eor r0,r8 ++ #sub r1,r7 ++ ++ # Transform the current block ++ bl col_trans_16 ++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r4 REP 16 # Now add on rounding, shift down by 7, and saturate ++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # 9+7=16 so this ends up with the output saturated and in the top half of the word. ++ vasl HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # This should be saturating, but the instruction above does not assemble? ++ vmov VX(0,0++)+r0, HX(0++,32)+r0 REP 16 # For simplicity transpose this back to the original position ++ ++ bl col_trans_16 ++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r5 REP 16 # Now add on rounding, shift down by 7, and saturate ++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,4 REP 16 # 4+12=16 so this ends up with the output saturated and in the top half of the word. ++ vasl HY(0++,0)+r0,HY(0++,0)+r0,TRANS_ASL2 REP 16 # This should be saturating, but the instruction above does not assemble? (Probably because it ends with ls which is interpreted as a condition flag) ++ ++ # Save results - note there has been a transposition during the processing so we save columns ++ vsth VX(0,32++)+r0, (r1 += r3) REP 16 ++ ++ # Move onto next block ++ eor r0,r8 ++ add r1,r7 ++ ++ addcmpbgt r2,-1,0,block_loop ++done16x16s: ++ ++ add sp,sp,64+16*16*2 # Move on stack pointer in case interrupt occurs and uses stack ++ # Now go and do any 32x32 transforms ++ b hevc_trans_32x32 ++ ++ pop r6-r15, pc ++# This returns a value in r6 that says where to load the data from. ++# We load data 16 shorts at a time from memory (uncached), and store to stack space to allow us to process it. ++unpack16x16: ++# Clear out destination ++ vmov HX(0,0)+r0,0 ++ mov r6, r11 ++ vsth HX(0,0)+r0,(r6 += r3) REP 16 ++ mov r5, r1 # Moving pointer to input coefficients ++unpack_outer_loop: ++ # Loop until we find the end ++ vldh HX(0,0)+r0,(r5) # TODO would prefetch help here while unpacking previous? ++ sub r6,r11,32 ++ #add r6,pc,packed_data-$ # Packed data ++ vsth HX(0,0)+r0,(r6) # Store into packed data ++ mov r12,0 ++unpack_loop: ++ ld r4,(r6) ++ add r6,r6,4 ++ lsr r9,r4,16 # r9 is destination value ++ cmp r4,0 # {value,index} ++ extu r4,8 ++ beq done_unpack ++ sth r9,(r11, r4) ++ addcmpblt r12,1,8,unpack_loop ++# # Read next 16 ++ add r5,32 ++ b unpack_outer_loop ++done_unpack: ++# # Set new load location ++ mov r6, r11 ++ #add r6,pc,unpacked_data-$ ++# # Restore constants ++ mov r4,64 ++ mov r5,TRANS_RND2 ++# pop r6-r15, pc ++ b lr ++ ++# r1,r2,r3 r7,r8 should be preserved ++# HX(0++,0)+r0 is the block to be transformed ++# HX(32++,0)+r6 is the 16x16 matrix of transform coefficients ++# Use HY(48,0) for intermediate results ++# r0 can be used, but should be returned to its original value at the end ++col_trans_16: ++ add r6,r0,16 # Final value for this loop ++col_trans_16_loop: ++ # First compute partial products for a single column ++ vmul32s HY(48++,0), VX(0,0)+r0, VX(32,0++) REP 16 ++ # Then sum up the results and place back ++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC ++ addcmpblt r0,1,r6,col_trans_16_loop ++ sub r0,16 # put r0 back to its original value ++ b lr ++ ++col_trans_odd_16: ++ add r6,r0,16 # Final value for this loop ++col_trans_odd_16_loop: ++ # First compute partial products for a single column ++ vmul32s HY(48++,0), VX(0,0)+r0, VX(32,32++) REP 16 ++ # Then sum up the results and place back ++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC ++ addcmpblt r0,1,r6,col_trans_odd_16_loop ++ sub r0,16 # put r0 back to its original value ++ b lr ++ ++# r1/r10 input pointer ++# r0,r4,r5,r6 free ++# r8/r9 output storage ++# ++# Store packed coefficients at r9-32 ++# Store unpacked at r9+32*32 (because transform works on even/odd rows on input, but writes all rows) ++unpack32x32: ++# Clear out destination ++ vmov HX(0,0),0 ++ add r0, r9, 32*32*2 # Unpacked buffer ++ mov r4, 32 ++ vsth HX(0,0),(r0 += r4) REP 64 ++unpack_outer_loop32: ++ # Loop until we find the end ++ vldh HX(0,0),(r1) # TODO would prefetch help here while unpacking previous? ++ sub r6,r9,32 ++ #add r6,pc,packed_data-$ # Packed data ++ vsth HX(0,0),(r6) # Store into packed data ++ mov r8,0 ++unpack_loop32: ++ ld r4,(r6) ++ add r6,r6,4 ++ lsr r5,r4,16 # r5 is destination value ++ cmp r4,0 # {value,index} ++ extu r4,10 ++ beq done_unpack ++ sth r5,(r0, r4) ++ addcmpblt r8,1,8,unpack_loop32 ++# # Read next 16 ++ add r1,32 ++ b unpack_outer_loop32 ++done_unpack32: ++ b lr ++# hevc_trans_32x32(short *transMatrix2, short *coeffs, int num) ++# transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) Even followed by odd ++# coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) ++# num: number of 16x16 transforms to be done in low 16, number of packed in high 16 ++# ++# Note that the 32x32 transforms are stored in reverse order, this means that the unpacked ones appear first! ++hevc_trans_32x32: ++ mov r1,r14 # coeffs ++ mov r2,r15 # num ++ lsr r15,r15,16 # Number that are packed ++ extu r2,16 # Total number ++ ++ # Fetch odd transform matrix ++ #mov r3, 16*2 # Stride of transMatrix2 in bytes (and of coefficients) ++ #vldh HX(32++,0),(r0 += r3) REP 16 # This is the even 16x16 matrix ++ #add r0, 16*16*2 ++ #vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix ++ ++ mov r3, 32*2*2 # Stride used to fetch alternate rows of our input coefficient buffer ++ mov r7, 16*16*2 # Total block size ++ ++.if USE_STACK ++ # Stack base allocation ++ sub sp,sp,32*32*4+64 # Allocate some space on the stack for us to store 32*32 shorts as temporary results (needs to be aligned) and another 32*32 for unpacking ++ # set r8 to 32byte aligned stack pointer with 32 bytes of space before it ++ add r8,sp,63 ++ lsr r8,5 ++ lsl r8,5 ++.else ++#:version r8 ++ .half 0x00e8 #AUTOINSERTED ++ btst r8,16 ++#:add r8,pc,intermediate_results-$ ++ .half 0xbfe8 ++ .half intermediate_results-($-2) ++ beq on_vpu1 ++ add r8,r8,32*32*2*2+16*2 # Move to secondary storage ++on_vpu1: ++.endif ++ mov r9,r8 # Backup of the temporary storage ++ mov r10,r1 # Backup of the coefficient buffer ++ ++ cmp r2,0 ++ beq done32x32s ++block_loop32: ++ ++ # Transform the first 16 columns ++ mov r1,r10 # Input Coefficient buffer ++ mov r8,r9 # Output temporary storage ++ # Unpacked are first, so need to only do unpacking when r2(=num left) <= r15 (=num packed) ++ cmp r2,r15 ++ bgt not_compressed_32 ++ bl unpack32x32 ++ add r1,r9,32*32*2 # Uncompressed into temporary storage ++ mov r8,r9 # Transform into here ++not_compressed_32: ++ # COLUMN TRANSFORM ++ mov r4, 64 # Constant used for rounding first pass ++ mov r5, 9 # left shift used for rounding first pass ++ ++ bl trans32 ++ # Transform the second 16 columns ++ add r8,32*16*2 ++ add r1,32 ++ bl trans32 ++ ++ # ROW TRANSFORM ++ mov r4, TRANS_RND2 # Constant used for rounding second pass ++ mov r5, TRANS_ASL2 # left shift used for rounding second pass ++ ++ mov r1,r9 # Input temporary storage ++ mov r8,r10 # Output Coefficient buffer ++ bl trans32 ++ # Transform the second 16 columns ++ add r8,32*16*2 ++ add r1,32 ++ bl trans32 ++ ++ add r10, 32*32*2 # move onto next block of coefficients ++ addcmpbgt r2,-1,0,block_loop32 ++done32x32s: ++ ++.if USE_STACK ++ add sp,sp,32*32*4+64# Restore stack ++.endif ++ ++ pop r6-r15, pc ++ ++trans32: ++ push lr ++ # We can no longer afford the VRF space to do prefetching when doing 32x32 ++ # Fetch the even rows ++ vldh HX(0++,0),(r1 += r3) REP 16 ++ # Fetch the odd rows ++ vldh HX(16++,0),64(r1 += r3) REP 16 # First odd row is 32 shorts ahead of r1 ++ ++ # Transform the even rows using even matrix ++ mov r0, 0 # Even rows ++ bl col_trans_16 ++ ++ # Now transform the odd rows using odd matrix ++ mov r0, 64*16 # Odd rows ++ bl col_trans_odd_16 ++ ++ # Now apply butterfly to compute the first 16 results ++ vadd HY(48++,0),HY(0++,0),HY(16++,0) REP 16 ++ vadd HY(48++,0),HY(48++,0),r4 REP 16 # add on rounding, ++ vasl HY(48++,0),HY(48++,0),r5 REP 16 # shift down by 7, and saturate ++ # 16bit results now in HX(48,32) ++ mov r0,r8 ++ mov r6,32*2 ++ vsth VX(48,32++),(r0+=r6) REP 16 ++ ++ # Now apply butterfly to compute the second 16 results (in reverse order) ++ vsub HY(63,0),HY(0 ,0),HY(16,0) ++ vsub HY(62,0),HY(1 ,0),HY(17,0) ++ vsub HY(61,0),HY(2 ,0),HY(18,0) ++ vsub HY(60,0),HY(3 ,0),HY(19,0) ++ vsub HY(59,0),HY(4 ,0),HY(20,0) ++ vsub HY(58,0),HY(5 ,0),HY(21,0) ++ vsub HY(57,0),HY(6 ,0),HY(22,0) ++ vsub HY(56,0),HY(7 ,0),HY(23,0) ++ vsub HY(55,0),HY(8 ,0),HY(24,0) ++ vsub HY(54,0),HY(9 ,0),HY(25,0) ++ vsub HY(53,0),HY(10,0),HY(26,0) ++ vsub HY(52,0),HY(11,0),HY(27,0) ++ vsub HY(51,0),HY(12,0),HY(28,0) ++ vsub HY(50,0),HY(13,0),HY(29,0) ++ vsub HY(49,0),HY(14,0),HY(30,0) ++ vsub HY(48,0),HY(15,0),HY(31,0) ++ vadd HY(48++,0),HY(48++,0),r4 REP 16 # add on rounding, ++ vasl HY(48++,0),HY(48++,0),r5 REP 16 # shift down by 7, and saturate ++ add r0,r8,32 ++ vsth VX(48,32++),(r0+=r6) REP 16 ++ pop pc ++ ++.if USE_STACK == 0 ++ .balign 32 ++ ++# .space directives generate 0's in the bin so avoid unnecessary padding by ++# just setting to appropriate value ++.equ intermediate_results, $+16*2 ++ ++# Layout goes: ++# ++#packed_buffer: ++# .space 16*2 ++#intermediate_results: ++# .space 32*32*2 ++#unpacked_buffer: ++# .space 32*32*2 ++# ++#packed_buffer2: ++# .space 16*2 ++#intermediate_results2: ++# .space 32*32*2 ++#unpacked_buffer2: ++# .space 32*32*2 ++.endif ++ ++ +diff --git a/libavcodec/rpi_hevc_transform10.h b/libavcodec/rpi_hevc_transform10.h +new file mode 100644 +index 0000000000..1c364492d0 +--- /dev/null ++++ b/libavcodec/rpi_hevc_transform10.h +@@ -0,0 +1,94 @@ ++static const unsigned char rpi_hevc_transform10 [] = { ++0xa9, 0x03, 0x3e, 0x40, 0x4f, 0x40, 0x03, 0xb0, // 0000 ++0x20, 0x00, 0x0c, 0xf8, 0x38, 0x88, 0x80, 0x03, // 0008 ++0xc0, 0xf8, 0x00, 0x00, 0x40, 0xb0, 0x00, 0x02, // 0010 ++0x0c, 0xf8, 0x38, 0xa8, 0x80, 0x03, 0xc0, 0xf8, // 0018 ++0x00, 0x00, 0x00, 0x60, 0x03, 0xb0, 0x20, 0x00, // 0020 ++0x07, 0xb0, 0x00, 0x02, 0x08, 0xb0, 0x00, 0x04, // 0028 ++0x04, 0xb0, 0x40, 0x00, 0x05, 0xb0, 0x00, 0x02, // 0030 ++0x59, 0xb0, 0xc0, 0xfd, 0x0b, 0x12, 0x5b, 0x7a, // 0038 ++0x5b, 0x7c, 0x4a, 0xc3, 0x50, 0x17, 0x02, 0x6f, // 0040 ++0x02, 0x6a, 0x32, 0x18, 0x0a, 0x6a, 0x16, 0x40, // 0048 ++0x04, 0x18, 0x1a, 0x66, 0x80, 0x90, 0x32, 0x00, // 0050 ++0x0c, 0xf8, 0x38, 0x80, 0x80, 0x03, 0xc0, 0x08, // 0058 ++0x18, 0x00, 0x80, 0x90, 0x51, 0x00, 0x04, 0xff, // 0060 ++0x30, 0xc0, 0x80, 0x03, 0x20, 0x08, 0x10, 0x00, // 0068 ++0x4c, 0xfe, 0x30, 0xc0, 0x09, 0x04, 0x20, 0x08, // 0070 ++0x00, 0x00, 0x04, 0xfc, 0x38, 0x90, 0x80, 0x02, // 0078 ++0xc0, 0x0b, 0x02, 0x00, 0x80, 0x90, 0x40, 0x00, // 0080 ++0x04, 0xff, 0x30, 0xc0, 0x80, 0x03, 0x20, 0x08, // 0088 ++0x14, 0x00, 0x4c, 0xfe, 0x30, 0xc0, 0x06, 0x04, // 0090 ++0x20, 0x08, 0x00, 0x00, 0x8c, 0xf8, 0x2c, 0xe0, // 0098 ++0x80, 0x03, 0x20, 0x30, 0x04, 0x00, 0x80, 0x45, // 00a0 ++0x71, 0x42, 0xf2, 0x8c, 0xd1, 0xc0, 0x59, 0xb0, // 00a8 ++0x40, 0x02, 0x00, 0x9e, 0x6d, 0x00, 0x29, 0x03, // 00b0 ++0x00, 0xf4, 0x38, 0x80, 0x00, 0x0c, 0xb6, 0x40, // 00b8 ++0x8c, 0xf8, 0x20, 0xe0, 0x80, 0x03, 0x00, 0x30, // 00c0 ++0x18, 0x00, 0x15, 0x40, 0x08, 0xf0, 0x38, 0x80, // 00c8 ++0x85, 0x0b, 0x66, 0xb5, 0xe0, 0xff, 0x88, 0xf0, // 00d0 ++0x24, 0xe0, 0x86, 0x03, 0x0c, 0x60, 0x64, 0x08, // 00d8 ++0x46, 0x62, 0x49, 0xc3, 0x50, 0x27, 0x04, 0x6a, // 00e0 ++0x84, 0x6e, 0x07, 0x18, 0x69, 0xa0, 0x04, 0x5f, // 00e8 ++0x1c, 0x8b, 0xf7, 0xc8, 0x45, 0x76, 0x6b, 0x1f, // 00f0 ++0xb6, 0x40, 0x04, 0xb0, 0x40, 0x00, 0x05, 0xb0, // 00f8 ++0x00, 0x02, 0x5a, 0x00, 0x06, 0xb4, 0x10, 0x00, // 0100 ++0xa4, 0xff, 0x24, 0xcc, 0x60, 0x02, 0x00, 0xf8, // 0108 ++0x3e, 0x00, 0x03, 0xff, 0x37, 0xd0, 0x78, 0x03, // 0110 ++0xe0, 0x03, 0xbe, 0x0b, 0x10, 0x8b, 0xf6, 0x5b, // 0118 ++0x00, 0x67, 0x5a, 0x00, 0x06, 0xb4, 0x10, 0x00, // 0120 ++0xa4, 0xff, 0x24, 0xcc, 0xe0, 0x02, 0x00, 0xf8, // 0128 ++0x3e, 0x00, 0x03, 0xff, 0x37, 0xd0, 0x78, 0x03, // 0130 ++0xe0, 0x03, 0xbe, 0x0b, 0x10, 0x8b, 0xf6, 0x5b, // 0138 ++0x00, 0x67, 0x5a, 0x00, 0x00, 0xf4, 0x38, 0x80, // 0140 ++0x00, 0x04, 0x20, 0xb5, 0x00, 0x08, 0x04, 0xb0, // 0148 ++0x20, 0x00, 0x8e, 0xf8, 0x20, 0xe0, 0x80, 0x03, // 0150 ++0xc0, 0x43, 0x00, 0x00, 0x08, 0xf0, 0x38, 0x80, // 0158 ++0x81, 0x03, 0x26, 0xb5, 0xe0, 0xff, 0x88, 0xf0, // 0160 ++0x20, 0xe0, 0x86, 0x03, 0x08, 0x60, 0x64, 0x08, // 0168 ++0x46, 0x62, 0x45, 0xc3, 0x50, 0x27, 0x04, 0x6a, // 0170 ++0xa4, 0x6e, 0x7f, 0x90, 0xbf, 0xff, 0x65, 0xa0, // 0178 ++0x04, 0x07, 0x18, 0x8b, 0xf6, 0xc8, 0x41, 0x76, // 0180 ++0x6a, 0x1f, 0x5a, 0x00, 0xe1, 0x40, 0xf2, 0x40, // 0188 ++0x0f, 0x7b, 0x02, 0x6f, 0x03, 0xb0, 0x80, 0x00, // 0190 ++0x07, 0xb0, 0x00, 0x02, 0xe8, 0x00, 0x08, 0x6d, // 0198 ++0xe8, 0xbf, 0x60, 0x01, 0x03, 0x18, 0x48, 0xb0, // 01a0 ++0x20, 0x10, 0x89, 0x40, 0x1a, 0x40, 0x02, 0x6a, // 01a8 ++0x24, 0x18, 0xa1, 0x40, 0x98, 0x40, 0xf2, 0x4a, // 01b0 ++0x06, 0x1e, 0xff, 0x9f, 0xc5, 0xff, 0x21, 0xb5, // 01b8 ++0x00, 0x08, 0x98, 0x40, 0x04, 0xb0, 0x40, 0x00, // 01c0 ++0x95, 0x60, 0x80, 0x90, 0x18, 0x00, 0x48, 0xb0, // 01c8 ++0x00, 0x04, 0x41, 0x76, 0x80, 0x90, 0x13, 0x00, // 01d0 ++0x04, 0xb0, 0x00, 0x02, 0x65, 0x60, 0x91, 0x40, // 01d8 ++0xa8, 0x40, 0x80, 0x90, 0x0c, 0x00, 0x48, 0xb0, // 01e0 ++0x00, 0x04, 0x41, 0x76, 0x80, 0x90, 0x07, 0x00, // 01e8 ++0x4a, 0xb0, 0x00, 0x08, 0xf2, 0x8c, 0xdf, 0xc0, // 01f0 ++0x29, 0x03, 0xef, 0x03, 0x0c, 0xf8, 0x38, 0x80, // 01f8 ++0x80, 0x03, 0xc0, 0xf8, 0x04, 0x00, 0x0c, 0xf8, // 0200 ++0x38, 0x84, 0xc0, 0x03, 0xc0, 0xf8, 0x04, 0x00, // 0208 ++0x00, 0x60, 0xff, 0x9f, 0x79, 0xff, 0x00, 0xb0, // 0210 ++0x00, 0x04, 0xff, 0x9f, 0x85, 0xff, 0x04, 0xff, // 0218 ++0x30, 0xcc, 0x10, 0x03, 0xe0, 0xfb, 0x3e, 0x00, // 0220 ++0x04, 0xff, 0x33, 0xcc, 0x80, 0x03, 0xe0, 0xfb, // 0228 ++0x10, 0x00, 0x4c, 0xfe, 0x33, 0xcc, 0x80, 0x03, // 0230 ++0xe0, 0xfb, 0x14, 0x00, 0x80, 0x40, 0x06, 0xb0, // 0238 ++0x40, 0x00, 0x8c, 0xf8, 0x2f, 0xe0, 0x80, 0x03, // 0240 ++0xe0, 0x63, 0x00, 0x00, 0x20, 0xf7, 0xf0, 0xcf, // 0248 ++0x10, 0x03, 0x20, 0xf7, 0xb0, 0xcf, 0x11, 0x13, // 0250 ++0x20, 0xf7, 0x70, 0xcf, 0x12, 0x23, 0x20, 0xf7, // 0258 ++0x30, 0xcf, 0x13, 0x33, 0x20, 0xf7, 0xf0, 0xce, // 0260 ++0x14, 0x43, 0x20, 0xf7, 0xb0, 0xce, 0x15, 0x53, // 0268 ++0x20, 0xf7, 0x70, 0xce, 0x16, 0x63, 0x20, 0xf7, // 0270 ++0x30, 0xce, 0x17, 0x73, 0x20, 0xf7, 0xf0, 0xcd, // 0278 ++0x18, 0x83, 0x20, 0xf7, 0xb0, 0xcd, 0x19, 0x93, // 0280 ++0x20, 0xf7, 0x70, 0xcd, 0x1a, 0xa3, 0x20, 0xf7, // 0288 ++0x30, 0xcd, 0x1b, 0xb3, 0x20, 0xf7, 0xf0, 0xcc, // 0290 ++0x1c, 0xc3, 0x20, 0xf7, 0xb0, 0xcc, 0x1d, 0xd3, // 0298 ++0x20, 0xf7, 0x70, 0xcc, 0x1e, 0xe3, 0x20, 0xf7, // 02a0 ++0x30, 0xcc, 0x1f, 0xf3, 0x04, 0xff, 0x33, 0xcc, // 02a8 ++0x80, 0x03, 0xe0, 0xfb, 0x10, 0x00, 0x4c, 0xfe, // 02b0 ++0x33, 0xcc, 0x80, 0x03, 0xe0, 0xfb, 0x14, 0x00, // 02b8 ++0x00, 0xb5, 0x20, 0x00, 0x8c, 0xf8, 0x2f, 0xe0, // 02c0 ++0x80, 0x03, 0xe0, 0x63, 0x00, 0x00, 0x6f, 0x03, // 02c8 ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 02d0 ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 02d8 ++}; +diff --git a/libavcodec/rpi_hevc_transform8.h b/libavcodec/rpi_hevc_transform8.h +new file mode 100644 +index 0000000000..1128a2c054 +--- /dev/null ++++ b/libavcodec/rpi_hevc_transform8.h +@@ -0,0 +1,94 @@ ++static const unsigned char rpi_hevc_transform8 [] = { ++0xa9, 0x03, 0x3e, 0x40, 0x4f, 0x40, 0x03, 0xb0, // 0000 ++0x20, 0x00, 0x0c, 0xf8, 0x38, 0x88, 0x80, 0x03, // 0008 ++0xc0, 0xf8, 0x00, 0x00, 0x40, 0xb0, 0x00, 0x02, // 0010 ++0x0c, 0xf8, 0x38, 0xa8, 0x80, 0x03, 0xc0, 0xf8, // 0018 ++0x00, 0x00, 0x00, 0x60, 0x03, 0xb0, 0x20, 0x00, // 0020 ++0x07, 0xb0, 0x00, 0x02, 0x08, 0xb0, 0x00, 0x04, // 0028 ++0x04, 0xb0, 0x40, 0x00, 0x05, 0xb0, 0x00, 0x08, // 0030 ++0x59, 0xb0, 0xc0, 0xfd, 0x0b, 0x12, 0x5b, 0x7a, // 0038 ++0x5b, 0x7c, 0x4a, 0xc3, 0x50, 0x17, 0x02, 0x6f, // 0040 ++0x02, 0x6a, 0x32, 0x18, 0x0a, 0x6a, 0x16, 0x40, // 0048 ++0x04, 0x18, 0x1a, 0x66, 0x80, 0x90, 0x32, 0x00, // 0050 ++0x0c, 0xf8, 0x38, 0x80, 0x80, 0x03, 0xc0, 0x08, // 0058 ++0x18, 0x00, 0x80, 0x90, 0x51, 0x00, 0x04, 0xff, // 0060 ++0x30, 0xc0, 0x80, 0x03, 0x20, 0x08, 0x10, 0x00, // 0068 ++0x4c, 0xfe, 0x30, 0xc0, 0x09, 0x04, 0x20, 0x08, // 0070 ++0x00, 0x00, 0x04, 0xfc, 0x38, 0x90, 0x80, 0x02, // 0078 ++0xc0, 0x0b, 0x02, 0x00, 0x80, 0x90, 0x40, 0x00, // 0080 ++0x04, 0xff, 0x30, 0xc0, 0x80, 0x03, 0x20, 0x08, // 0088 ++0x14, 0x00, 0x4c, 0xfe, 0x30, 0xc0, 0x04, 0x04, // 0090 ++0x20, 0x08, 0x00, 0x00, 0x8c, 0xf8, 0x2c, 0xe0, // 0098 ++0x80, 0x03, 0x20, 0x30, 0x04, 0x00, 0x80, 0x45, // 00a0 ++0x71, 0x42, 0xf2, 0x8c, 0xd1, 0xc0, 0x59, 0xb0, // 00a8 ++0x40, 0x02, 0x00, 0x9e, 0x6d, 0x00, 0x29, 0x03, // 00b0 ++0x00, 0xf4, 0x38, 0x80, 0x00, 0x0c, 0xb6, 0x40, // 00b8 ++0x8c, 0xf8, 0x20, 0xe0, 0x80, 0x03, 0x00, 0x30, // 00c0 ++0x18, 0x00, 0x15, 0x40, 0x08, 0xf0, 0x38, 0x80, // 00c8 ++0x85, 0x0b, 0x66, 0xb5, 0xe0, 0xff, 0x88, 0xf0, // 00d0 ++0x24, 0xe0, 0x86, 0x03, 0x0c, 0x60, 0x64, 0x08, // 00d8 ++0x46, 0x62, 0x49, 0xc3, 0x50, 0x27, 0x04, 0x6a, // 00e0 ++0x84, 0x6e, 0x07, 0x18, 0x69, 0xa0, 0x04, 0x5f, // 00e8 ++0x1c, 0x8b, 0xf7, 0xc8, 0x45, 0x76, 0x6b, 0x1f, // 00f0 ++0xb6, 0x40, 0x04, 0xb0, 0x40, 0x00, 0x05, 0xb0, // 00f8 ++0x00, 0x08, 0x5a, 0x00, 0x06, 0xb4, 0x10, 0x00, // 0100 ++0xa4, 0xff, 0x24, 0xcc, 0x60, 0x02, 0x00, 0xf8, // 0108 ++0x3e, 0x00, 0x03, 0xff, 0x37, 0xd0, 0x78, 0x03, // 0110 ++0xe0, 0x03, 0xbe, 0x0b, 0x10, 0x8b, 0xf6, 0x5b, // 0118 ++0x00, 0x67, 0x5a, 0x00, 0x06, 0xb4, 0x10, 0x00, // 0120 ++0xa4, 0xff, 0x24, 0xcc, 0xe0, 0x02, 0x00, 0xf8, // 0128 ++0x3e, 0x00, 0x03, 0xff, 0x37, 0xd0, 0x78, 0x03, // 0130 ++0xe0, 0x03, 0xbe, 0x0b, 0x10, 0x8b, 0xf6, 0x5b, // 0138 ++0x00, 0x67, 0x5a, 0x00, 0x00, 0xf4, 0x38, 0x80, // 0140 ++0x00, 0x04, 0x20, 0xb5, 0x00, 0x08, 0x04, 0xb0, // 0148 ++0x20, 0x00, 0x8e, 0xf8, 0x20, 0xe0, 0x80, 0x03, // 0150 ++0xc0, 0x43, 0x00, 0x00, 0x08, 0xf0, 0x38, 0x80, // 0158 ++0x81, 0x03, 0x26, 0xb5, 0xe0, 0xff, 0x88, 0xf0, // 0160 ++0x20, 0xe0, 0x86, 0x03, 0x08, 0x60, 0x64, 0x08, // 0168 ++0x46, 0x62, 0x45, 0xc3, 0x50, 0x27, 0x04, 0x6a, // 0170 ++0xa4, 0x6e, 0x7f, 0x90, 0xbf, 0xff, 0x65, 0xa0, // 0178 ++0x04, 0x07, 0x18, 0x8b, 0xf6, 0xc8, 0x41, 0x76, // 0180 ++0x6a, 0x1f, 0x5a, 0x00, 0xe1, 0x40, 0xf2, 0x40, // 0188 ++0x0f, 0x7b, 0x02, 0x6f, 0x03, 0xb0, 0x80, 0x00, // 0190 ++0x07, 0xb0, 0x00, 0x02, 0xe8, 0x00, 0x08, 0x6d, // 0198 ++0xe8, 0xbf, 0x60, 0x01, 0x03, 0x18, 0x48, 0xb0, // 01a0 ++0x20, 0x10, 0x89, 0x40, 0x1a, 0x40, 0x02, 0x6a, // 01a8 ++0x24, 0x18, 0xa1, 0x40, 0x98, 0x40, 0xf2, 0x4a, // 01b0 ++0x06, 0x1e, 0xff, 0x9f, 0xc5, 0xff, 0x21, 0xb5, // 01b8 ++0x00, 0x08, 0x98, 0x40, 0x04, 0xb0, 0x40, 0x00, // 01c0 ++0x95, 0x60, 0x80, 0x90, 0x18, 0x00, 0x48, 0xb0, // 01c8 ++0x00, 0x04, 0x41, 0x76, 0x80, 0x90, 0x13, 0x00, // 01d0 ++0x04, 0xb0, 0x00, 0x08, 0x45, 0x60, 0x91, 0x40, // 01d8 ++0xa8, 0x40, 0x80, 0x90, 0x0c, 0x00, 0x48, 0xb0, // 01e0 ++0x00, 0x04, 0x41, 0x76, 0x80, 0x90, 0x07, 0x00, // 01e8 ++0x4a, 0xb0, 0x00, 0x08, 0xf2, 0x8c, 0xdf, 0xc0, // 01f0 ++0x29, 0x03, 0xef, 0x03, 0x0c, 0xf8, 0x38, 0x80, // 01f8 ++0x80, 0x03, 0xc0, 0xf8, 0x04, 0x00, 0x0c, 0xf8, // 0200 ++0x38, 0x84, 0xc0, 0x03, 0xc0, 0xf8, 0x04, 0x00, // 0208 ++0x00, 0x60, 0xff, 0x9f, 0x79, 0xff, 0x00, 0xb0, // 0210 ++0x00, 0x04, 0xff, 0x9f, 0x85, 0xff, 0x04, 0xff, // 0218 ++0x30, 0xcc, 0x10, 0x03, 0xe0, 0xfb, 0x3e, 0x00, // 0220 ++0x04, 0xff, 0x33, 0xcc, 0x80, 0x03, 0xe0, 0xfb, // 0228 ++0x10, 0x00, 0x4c, 0xfe, 0x33, 0xcc, 0x80, 0x03, // 0230 ++0xe0, 0xfb, 0x14, 0x00, 0x80, 0x40, 0x06, 0xb0, // 0238 ++0x40, 0x00, 0x8c, 0xf8, 0x2f, 0xe0, 0x80, 0x03, // 0240 ++0xe0, 0x63, 0x00, 0x00, 0x20, 0xf7, 0xf0, 0xcf, // 0248 ++0x10, 0x03, 0x20, 0xf7, 0xb0, 0xcf, 0x11, 0x13, // 0250 ++0x20, 0xf7, 0x70, 0xcf, 0x12, 0x23, 0x20, 0xf7, // 0258 ++0x30, 0xcf, 0x13, 0x33, 0x20, 0xf7, 0xf0, 0xce, // 0260 ++0x14, 0x43, 0x20, 0xf7, 0xb0, 0xce, 0x15, 0x53, // 0268 ++0x20, 0xf7, 0x70, 0xce, 0x16, 0x63, 0x20, 0xf7, // 0270 ++0x30, 0xce, 0x17, 0x73, 0x20, 0xf7, 0xf0, 0xcd, // 0278 ++0x18, 0x83, 0x20, 0xf7, 0xb0, 0xcd, 0x19, 0x93, // 0280 ++0x20, 0xf7, 0x70, 0xcd, 0x1a, 0xa3, 0x20, 0xf7, // 0288 ++0x30, 0xcd, 0x1b, 0xb3, 0x20, 0xf7, 0xf0, 0xcc, // 0290 ++0x1c, 0xc3, 0x20, 0xf7, 0xb0, 0xcc, 0x1d, 0xd3, // 0298 ++0x20, 0xf7, 0x70, 0xcc, 0x1e, 0xe3, 0x20, 0xf7, // 02a0 ++0x30, 0xcc, 0x1f, 0xf3, 0x04, 0xff, 0x33, 0xcc, // 02a8 ++0x80, 0x03, 0xe0, 0xfb, 0x10, 0x00, 0x4c, 0xfe, // 02b0 ++0x33, 0xcc, 0x80, 0x03, 0xe0, 0xfb, 0x14, 0x00, // 02b8 ++0x00, 0xb5, 0x20, 0x00, 0x8c, 0xf8, 0x2f, 0xe0, // 02c0 ++0x80, 0x03, 0xe0, 0x63, 0x00, 0x00, 0x6f, 0x03, // 02c8 ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 02d0 ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 02d8 ++}; +diff --git a/libavcodec/rpi_hevcdec.c b/libavcodec/rpi_hevcdec.c +new file mode 100644 +index 0000000000..e651e5c565 +--- /dev/null ++++ b/libavcodec/rpi_hevcdec.c +@@ -0,0 +1,6134 @@ ++/* ++ * HEVC video Decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Mickael Raulet ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2012 - 2013 Wassim Hamidouche ++ * Copyright (C) 2018 John Cox, Ben Avison, Peter de Rivaz for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/attributes.h" ++#include "libavutil/common.h" ++#include "libavutil/display.h" ++#include "libavutil/internal.h" ++#include "libavutil/mastering_display_metadata.h" ++#include "libavutil/md5.h" ++#include "libavutil/opt.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/stereo3d.h" ++ ++#include "decode.h" ++#include "bswapdsp.h" ++#include "bytestream.h" ++#include "golomb.h" ++#include "hevc.h" ++#include "rpi_hevc_data.h" ++#include "rpi_hevc_parse.h" ++#include "rpi_hevcdec.h" ++#include "rpi_hevc_cabac_fns.h" ++#include "profiles.h" ++#include "hwconfig.h" ++ ++#include "rpi_zc_frames.h" ++#include "rpi_qpu.h" ++#include "rpi_hevc_shader.h" ++#include "rpi_hevc_shader_cmd.h" ++#include "rpi_hevc_shader_template.h" ++#include "rpi_zc.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++#include "pthread.h" ++#include ++ ++#define DEBUG_DECODE_N 0 // 0 = do all, n = frames idr onwards ++ ++#define PACK2(hi,lo) (((hi) << 16) | ((lo) & 0xffff)) ++ ++#ifndef av_mod_uintp2 ++static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p) ++{ ++ return a & ((1 << p) - 1); ++} ++# define av_mod_uintp2 av_mod_uintp2_c ++#endif ++ ++const uint8_t ff_hevc_rpi_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++static void rpi_begin(const HEVCRpiContext * const s, HEVCRpiJob * const jb, const unsigned int ctu_ts_first); ++ ++#define MC_DUMMY_X (-32) ++#define MC_DUMMY_Y (-32) ++ ++// UV & Y both have min 4x4 pred (no 2x2 chroma) ++// Allow for even spread +1 for setup, +1 for rounding ++// As we have load sharing this can (in theory) be exceeded so we have to ++// check after each CTU, but it is a good base size ++ ++// Worst case (all 4x4) commands per CTU ++#define QPU_Y_CMD_PER_CTU_MAX (16 * 16) ++#define QPU_C_CMD_PER_CTU_MAX (8 * 8) ++ ++#define QPU_MAX_CTU_PER_LINE ((HEVC_RPI_MAX_WIDTH + 63) / 64) ++ ++#define QPU_GRPS (QPU_N_MAX / QPU_N_GRP) ++#define QPU_CTU_PER_GRP ((QPU_MAX_CTU_PER_LINE + QPU_GRPS - 1) / QPU_GRPS) ++ ++#define QPU_Y_CMD_SLACK_PER_Q (QPU_Y_CMD_PER_CTU_MAX / 2) ++#define QPU_C_CMD_SLACK_PER_Q (QPU_C_CMD_PER_CTU_MAX / 2) ++ ++// Total cmds to allocate - allow for slack & setup ++#define QPU_Y_COMMANDS (QPU_CTU_PER_GRP * QPU_GRPS * QPU_Y_CMD_PER_CTU_MAX + (1 + QPU_Y_CMD_SLACK_PER_Q) * QPU_N_MAX) ++#define QPU_C_COMMANDS (QPU_CTU_PER_GRP * QPU_GRPS * QPU_C_CMD_PER_CTU_MAX + (1 + QPU_C_CMD_SLACK_PER_Q) * QPU_N_MAX) ++ ++#define QPU_Y_SYNCS (QPU_N_MAX * (16 + 2)) ++#define QPU_C_SYNCS (QPU_N_MAX * (8 + 2)) ++ ++// The QPU code for UV blocks only works up to a block width of 8 ++#define RPI_CHROMA_BLOCK_WIDTH 8 ++ ++#define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++ ++// Actual filter goes -ve, +ve, +ve, -ve using these values ++static const uint32_t rpi_filter_coefs[8] = { ++ ENCODE_COEFFS( 0, 64, 0, 0), ++ ENCODE_COEFFS( 2, 58, 10, 2), ++ ENCODE_COEFFS( 4, 54, 16, 2), ++ ENCODE_COEFFS( 6, 46, 28, 4), ++ ENCODE_COEFFS( 4, 36, 36, 4), ++ ENCODE_COEFFS( 4, 28, 46, 6), ++ ENCODE_COEFFS( 2, 16, 54, 4), ++ ENCODE_COEFFS( 2, 10, 58, 2) ++}; ++ ++// Function arrays by QPU ++ ++static const int * const inter_pred_setup_c_qpu[12] = { ++ mc_setup_c_q0, mc_setup_c_qn, mc_setup_c_qn, mc_setup_c_qn, ++ mc_setup_c_qn, mc_setup_c_qn, mc_setup_c_qn, mc_setup_c_qn, ++ mc_setup_c_qn, mc_setup_c_qn, mc_setup_c_qn, mc_setup_c_qn ++}; ++ ++static const int * const inter_pred_setup_c10_qpu[12] = { ++ mc_setup_c10_q0, mc_setup_c10_qn, mc_setup_c10_qn, mc_setup_c10_qn, ++ mc_setup_c10_qn, mc_setup_c10_qn, mc_setup_c10_qn, mc_setup_c10_qn, ++ mc_setup_c10_qn, mc_setup_c10_qn, mc_setup_c10_qn, mc_setup_c10_qn ++}; ++ ++static const int * const inter_pred_setup_y_qpu[12] = { ++ mc_setup_y_q0, mc_setup_y_qn, mc_setup_y_qn, mc_setup_y_qn, ++ mc_setup_y_qn, mc_setup_y_qn, mc_setup_y_qn, mc_setup_y_qn, ++ mc_setup_y_qn, mc_setup_y_qn, mc_setup_y_qn, mc_setup_y_qn ++}; ++ ++static const int * const inter_pred_setup_y10_qpu[12] = { ++ mc_setup_y10_q0, mc_setup_y10_qn, mc_setup_y10_qn, mc_setup_y10_qn, ++ mc_setup_y10_qn, mc_setup_y10_qn, mc_setup_y10_qn, mc_setup_y10_qn, ++ mc_setup_y10_qn, mc_setup_y10_qn, mc_setup_y10_qn, mc_setup_y10_qn ++}; ++ ++static const int * const inter_pred_sync_qpu[12] = { ++ mc_sync_q0, mc_sync_q1, mc_sync_q2, mc_sync_q3, ++ mc_sync_q4, mc_sync_q5, mc_sync_q6, mc_sync_q7, ++ mc_sync_q8, mc_sync_q9, mc_sync_q10, mc_sync_q11 ++}; ++ ++static const int * const inter_pred_sync10_qpu[12] = { ++ mc_sync10_q0, mc_sync10_q1, mc_sync10_q2, mc_sync10_q3, ++ mc_sync10_q4, mc_sync10_q5, mc_sync10_q6, mc_sync10_q7, ++ mc_sync10_q8, mc_sync10_q9, mc_sync10_q10, mc_sync10_q11 ++}; ++ ++static const int * const inter_pred_exit_c_qpu[12] = { ++ mc_exit_c_q0, mc_exit_c_qn, mc_exit_c_qn, mc_exit_c_qn, ++ mc_exit_c_qn, mc_exit_c_qn, mc_exit_c_qn, mc_exit_c_qn, ++ mc_exit_c_qn, mc_exit_c_qn, mc_exit_c_qn, mc_exit_c_qn ++}; ++ ++static const int * const inter_pred_exit_c10_qpu[12] = { ++ mc_exit_c10_q0, mc_exit_c10_qn, mc_exit_c10_qn, mc_exit_c10_qn, ++ mc_exit_c10_qn, mc_exit_c10_qn, mc_exit_c10_qn, mc_exit_c10_qn, ++ mc_exit_c10_qn, mc_exit_c10_qn, mc_exit_c10_qn, mc_exit_c10_qn ++}; ++ ++static const int * const inter_pred_exit_y_qpu[12] = { ++ mc_exit_y_q0, mc_exit_y_qn, mc_exit_y_qn, mc_exit_y_qn, ++ mc_exit_y_qn, mc_exit_y_qn, mc_exit_y_qn, mc_exit_y_qn, ++ mc_exit_y_qn, mc_exit_y_qn, mc_exit_y_qn, mc_exit_y_qn ++}; ++ ++static const int * const inter_pred_exit_y10_qpu[12] = { ++ mc_exit_y10_q0, mc_exit_y10_qn, mc_exit_y10_qn, mc_exit_y10_qn, ++ mc_exit_y10_qn, mc_exit_y10_qn, mc_exit_y10_qn, mc_exit_y10_qn, ++ mc_exit_y10_qn, mc_exit_y10_qn, mc_exit_y10_qn, mc_exit_y10_qn ++}; ++ ++typedef struct ipe_chan_info_s ++{ ++ const uint8_t bit_depth; ++ const uint8_t n; ++ const int * const * setup_fns; ++ const int * const * sync_fns; ++ const int * const * exit_fns; ++} ipe_chan_info_t; ++ ++typedef struct ipe_init_info_s ++{ ++ ipe_chan_info_t luma; ++ ipe_chan_info_t chroma; ++} ipe_init_info_t; ++ ++static void set_bytes(uint8_t * b, const unsigned int stride, const int ln, unsigned int a) ++{ ++ switch (ln) ++ { ++ default: // normally 0 ++ *b = a; ++ break; ++ case 1: ++ a |= a << 8; ++ *(uint16_t *)b = a; ++ b += stride; ++ *(uint16_t *)b = a; ++ break; ++ case 2: ++ a |= a << 8; ++ a |= a << 16; ++ *(uint32_t *)b = a; ++ b += stride; ++ *(uint32_t *)b = a; ++ b += stride; ++ *(uint32_t *)b = a; ++ b += stride; ++ *(uint32_t *)b = a; ++ break; ++ case 3: ++ { ++ unsigned int i; ++ uint64_t d; ++ a |= a << 8; ++ a |= a << 16; ++ d = ((uint64_t)a << 32) | a; ++ for (i = 0; i != 8; ++i, b += stride) ++ *(uint64_t *)b = d; ++ break; ++ } ++ case 4: ++ { ++ unsigned int i; ++ uint64_t d; ++ a |= a << 8; ++ a |= a << 16; ++ d = ((uint64_t)a << 32) | a; ++ for (i = 0; i != 16; ++i, b += stride) ++ { ++ *(uint64_t *)b = d; ++ *(uint64_t *)(b + 8) = d; ++ } ++ break; ++ } ++ } ++} ++ ++// We expect this to be called with ln = (log2_cb_size - 3) so range = -1..3 ++// (4 not required) ++static void set_stash2(uint8_t * b_u, uint8_t * b_l, const int ln, unsigned int a) ++{ ++ switch (ln) ++ { ++ default: // 0 or -1 ++ *b_u = a; ++ *b_l = a; ++ break; ++ case 1: ++ a |= a << 8; ++ *(uint16_t *)b_u = a; ++ *(uint16_t *)b_l = a; ++ break; ++ case 2: ++ a |= a << 8; ++ a |= a << 16; ++ *(uint32_t *)b_u = a; ++ *(uint32_t *)b_l = a; ++ break; ++ case 3: ++ a |= a << 8; ++ a |= a << 16; ++ *(uint32_t *)b_u = a; ++ *(uint32_t *)(b_u + 4) = a; ++ *(uint32_t *)b_l = a; ++ *(uint32_t *)(b_l + 4) = a; ++ break; ++ case 4: ++ a |= a << 8; ++ a |= a << 16; ++ *(uint32_t *)b_u = a; ++ *(uint32_t *)(b_u + 4) = a; ++ *(uint32_t *)(b_u + 8) = a; ++ *(uint32_t *)(b_u + 12) = a; ++ *(uint32_t *)b_l = a; ++ *(uint32_t *)(b_l + 4) = a; ++ *(uint32_t *)(b_l + 8) = a; ++ *(uint32_t *)(b_l + 12) = a; ++ break; ++ } ++} ++ ++static void zap_cabac_stash(uint8_t * b, const int ln) ++{ ++ switch (ln) ++ { ++ default: // 0 ++ *b = 0; ++ break; ++ case 1: ++ *(uint16_t *)b = 0; ++ break; ++ case 2: ++ *(uint32_t *)b = 0; ++ break; ++ case 3: ++ *(uint32_t *)b = 0; ++ *(uint32_t *)(b + 4) = 0; ++ break; ++ } ++} ++ ++ ++ ++// Set a small square block of bits in a bitmap ++// Bits must be aligned on their size boundry (which will be true of all split CBs) ++static void set_bits(uint8_t * f, const unsigned int x, const unsigned int stride, const unsigned int ln) ++{ ++ unsigned int n; ++ const unsigned int sh = (x & 7); ++ ++ f += (x >> 3); ++ ++ av_assert2(ln <= 3); ++ av_assert2((x & ((1 << ln) - 1)) == 0); ++ ++ switch (ln) ++ { ++ default: // 1 ++ f[0] |= 1 << sh; ++ break; ++ case 1: // 3 * 2 ++ n = 3 << sh; ++ f[0] |= n; ++ f[stride] |= n; ++ break; ++ case 2: // 0xf * 4 ++ n = 0xf << sh; ++ f[0] |= n; ++ f[stride] |= n; ++ f[stride * 2] |= n; ++ f[stride * 3] |= n; ++ break; ++ case 3: // 0xff * 8 ++ for (n = 0; n != 8; ++n, f += stride) ++ *f = 0xff; ++ break; ++ } ++} ++ ++static const ipe_init_info_t ipe_init_infos[9] = { // Alloc for bit depths of 8-16 ++ { // 8 ++ .luma = {8, QPU_MC_PRED_N_Y8, inter_pred_setup_y_qpu, inter_pred_sync_qpu, inter_pred_exit_y_qpu}, ++ .chroma = {8, QPU_MC_PRED_N_C8, inter_pred_setup_c_qpu, inter_pred_sync_qpu, inter_pred_exit_c_qpu} ++ }, ++ { // 9 ++ .luma = {0}, ++ .chroma = {0} ++ }, ++ { // 10 ++ .luma = {10, QPU_MC_PRED_N_Y10, inter_pred_setup_y10_qpu, inter_pred_sync10_qpu, inter_pred_exit_y10_qpu}, ++ .chroma = {10, QPU_MC_PRED_N_C10, inter_pred_setup_c10_qpu, inter_pred_sync10_qpu, inter_pred_exit_c10_qpu} ++ } ++ ++}; ++ ++static void set_ipe_from_ici(HEVCRpiInterPredEnv * const ipe, const ipe_chan_info_t * const ici) ++{ ++ const unsigned int n = ici->n; ++ const unsigned int q1_size = (ipe->gptr.numbytes / n) & ~3; // Round down to word ++ ++ ipe->n = n; ++ ipe->max_fill = q1_size - ipe->min_gap; ++ for(unsigned int i = 0; i < n; i++) { ++ HEVCRpiInterPredQ * const q = ipe->q + i; ++ q->qpu_mc_curr = q->qpu_mc_base = ++ (qpu_mc_pred_cmd_t *)(ipe->gptr.arm + i * q1_size); ++ q->code_setup = qpu_fn(ici->setup_fns[i]); ++ q->code_sync = qpu_fn(ici->sync_fns[i]); ++ q->code_exit = qpu_fn(ici->exit_fns[i]); ++ } ++} ++ ++static void rpi_hevc_qpu_set_fns(HEVCRpiContext * const s, const unsigned int bit_depth) ++{ ++ av_assert0(bit_depth >= 8 && bit_depth <= 16); ++ ++ rpi_hevc_qpu_init_fn(&s->qpu, bit_depth); ++} ++ ++// Unsigned Trivial MOD ++static inline unsigned int utmod(const unsigned int x, const unsigned int n) ++{ ++ return x >= n ? x - n : x; ++} ++ ++// returns pq->job_n++ ++static inline unsigned int pass_queue_inc_job_n(HEVCRpiPassQueue * const pq) ++{ ++ unsigned int const x2 = pq->job_n; ++ pq->job_n = utmod(x2 + 1, RPI_MAX_JOBS); ++ return x2; ++} ++ ++static void pass_queue_init(HEVCRpiPassQueue * const pq, HEVCRpiContext * const s, HEVCRpiWorkerFn * const worker, sem_t * const psem_out, const int n) ++{ ++ pq->terminate = 0; ++ pq->job_n = 0; ++ pq->context = s; ++ pq->worker = worker; ++ pq->psem_out = psem_out; ++ pq->pass_n = n; ++ pq->started = 0; ++ sem_init(&pq->sem_in, 0, 0); ++} ++ ++static void pass_queue_kill(HEVCRpiPassQueue * const pq) ++{ ++ sem_destroy(&pq->sem_in); ++} ++ ++static inline void rpi_sem_wait(sem_t * const sem) ++{ ++ while (sem_wait(sem) != 0) { ++ av_assert0(errno == EINTR); ++ } ++} ++ ++static void pass_queue_submit_job(HEVCRpiPassQueue * const pq) ++{ ++ sem_post(&pq->sem_in); ++} ++ ++static inline void pass_queue_do_all(HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ // Do the various passes - common with the worker code ++ for (unsigned int i = 0; i != RPI_PASSES; ++i) { ++ s->passq[i].worker(s, jb); ++ } ++} ++ ++ ++#if 0 ++static void dump_jbc(const HEVCRpiJobCtl *const jbc, const char * const func) ++{ ++ int x; ++ sem_getvalue((sem_t *)&jbc->sem_out, &x); ++ printf("%s: jbc: in=%d, out=%d, sum=%d\n", func, jbc->offload_in, jbc->offload_out, x); ++} ++#endif ++ ++ ++static HEVCRpiJob * job_alloc(HEVCRpiJobCtl * const jbc, HEVCRpiLocalContext * const lc) ++{ ++ HEVCRpiJob * jb; ++ HEVCRpiJobGlobal * const jbg = jbc->jbg; ++ ++ pthread_mutex_lock(&jbg->lock); ++ // Check local 1st ++ if ((jb = jbc->jb1) != NULL) ++ { ++ // Only 1 - very easy :-) ++ jbc->jb1 = NULL; ++ } ++ else ++ { ++ // Now look for global free chain ++ if ((jb = jbg->free1) != NULL) ++ { ++ // Found one - unlink it ++ jbg->free1 = jb->next; ++ jb->next = NULL; ++ } ++ else ++ { ++ // Out of places to look - wait for one to become free - add to Qs ++ ++ // Global ++ // If "good" lc then add after the last "good" el in the chain ++ // otherwise add to the tail ++ if (jbg->wait_tail == NULL || jbg->wait_tail->last_progress_good || !lc->last_progress_good) ++ { ++ // Add to end as we had to wait last time or wait Q empty ++ if ((lc->jw_prev = jbg->wait_tail) == NULL) ++ jbg->wait_head = lc; ++ else ++ lc->jw_prev->jw_next = lc; ++ lc->jw_next = NULL; ++ jbg->wait_tail = lc; ++ } ++ else ++ { ++ // This is a "good" lc that we need to poke into the middle ++ // of the Q ++ // We know that the Q isn't empty and there is at least one ++ // !last_progess_good el in it from the previous test ++ ++ HEVCRpiLocalContext * const p = jbg->wait_good; // Insert after ++ ++ if (p == NULL) ++ { ++ // No current good els - add to head ++ lc->jw_next = jbg->wait_head; ++ jbg->wait_head = lc; ++ } ++ else ++ { ++ lc->jw_next = p->jw_next; ++ p->jw_next = lc; ++ } ++ ++ lc->jw_next->jw_prev = lc; ++ lc->jw_prev = p; ++ } ++ ++ // If "good" then we are now the last good waiting el ++ if (lc->last_progress_good) ++ jbg->wait_good = lc; ++ ++ // Local ++ if ((lc->ljw_prev = jbc->lcw_tail) == NULL) ++ jbc->lcw_head = lc; ++ else ++ lc->ljw_prev->ljw_next = lc; ++ lc->ljw_next = NULL; ++ jbc->lcw_tail = lc; ++ } ++ } ++ ++ pthread_mutex_unlock(&jbg->lock); ++ ++ if (jb == NULL) // Need to wait ++ { ++ rpi_sem_wait(&lc->jw_sem); ++ jb = lc->jw_job; // Set by free code ++ } ++ ++ return jb; ++} ++ ++ ++static void job_free(HEVCRpiJobCtl * const jbc0, HEVCRpiJob * const jb) ++{ ++ HEVCRpiJobGlobal * const jbg = jbc0->jbg; // This jbc only used to find jbg so we can get the lock ++ HEVCRpiJobCtl * jbc = jb->jbc_local; ++ HEVCRpiLocalContext * lc = NULL; ++ ++ pthread_mutex_lock(&jbg->lock); ++ ++ if (jbc != NULL) ++ { ++ av_assert1(jbc->jb1 == NULL); ++ ++ // Release to Local if nothing waiting there ++ if ((lc = jbc->lcw_head) == NULL) ++ jbc->jb1 = jb; ++ } ++ else ++ { ++ // Release to global if nothing waiting there ++ if ((lc = jbg->wait_head) == NULL) ++ { ++ jb->next = jbg->free1; ++ jbg->free1 = jb; ++ } ++ else ++ { ++ // ? seems somehow mildy ugly... ++ jbc = lc->context->jbc; ++ } ++ } ++ ++ if (lc != NULL) ++ { ++ // Something was waiting ++ ++ // Unlink ++ // Global ++ if (lc->jw_next == NULL) ++ jbg->wait_tail = lc->jw_prev; ++ else ++ lc->jw_next->jw_prev = lc->jw_prev; ++ ++ if (lc->jw_prev == NULL) ++ jbg->wait_head = lc->jw_next; ++ else ++ lc->jw_prev->jw_next = lc->jw_next; ++ ++ // Local ++ if (lc->ljw_next == NULL) ++ jbc->lcw_tail = lc->ljw_prev; ++ else ++ lc->ljw_next->ljw_prev = lc->ljw_prev; ++ ++ if (lc->ljw_prev == NULL) ++ jbc->lcw_head = lc->ljw_next; ++ else ++ lc->ljw_prev->ljw_next = lc->ljw_next; ++ ++ // Update good if required ++ if (jbg->wait_good == lc) ++ jbg->wait_good = lc->jw_prev; ++ ++ // Prod ++ lc->jw_job = jb; ++ sem_post(&lc->jw_sem); ++ } ++ ++ pthread_mutex_unlock(&jbg->lock); ++} ++ ++static void job_lc_kill(HEVCRpiLocalContext * const lc) ++{ ++ sem_destroy(&lc->jw_sem); ++} ++ ++static void job_lc_init(HEVCRpiLocalContext * const lc) ++{ ++ lc->jw_next = NULL; ++ lc->jw_prev = NULL; ++ lc->ljw_next = NULL; ++ lc->ljw_prev = NULL; ++ lc->jw_job = NULL; ++ sem_init(&lc->jw_sem, 0, 0); ++} ++ ++// Returns: ++// 0 if we have waited for MV or expect to wait for recon ++// 1 if we haven't waited for MV & do not need to wait for recon ++static int progress_good(const HEVCRpiContext *const s, const HEVCRpiJob * const jb) ++{ ++ if (jb->waited) // reset by rpi_begin ++ return 0; ++ for (unsigned int i = 0; i != FF_ARRAY_ELEMS(jb->progress_req); ++i) ++ { ++ if (jb->progress_req[i] >= 0 && s->DPB[i].tf.progress != NULL && ++ ((volatile int *)(s->DPB[i].tf.progress->data))[0] < jb->progress_req[i]) ++ return 0; ++ } ++ return 1; ++} ++ ++// Submit job if it is full (indicated by having ctu_ts_last set >= 0) ++static inline void worker_submit_job(HEVCRpiContext *const s, HEVCRpiLocalContext * const lc) ++{ ++ HEVCRpiJobCtl *const jbc = s->jbc; ++ HEVCRpiJob * const jb = lc->jb0; ++ ++ av_assert1(jb != NULL); ++ ++ if (jb->ctu_ts_last < 0) { ++ return; ++ } ++ ++ lc->last_progress_good = progress_good(s, jb); ++ jb->waited = !lc->last_progress_good; ++ lc->jb0 = NULL; ++ ++ if (s->offload_recon) ++ { ++ pthread_mutex_lock(&jbc->in_lock); ++ jbc->offloadq[jbc->offload_in] = jb; ++ jbc->offload_in = utmod(jbc->offload_in + 1, RPI_MAX_JOBS); ++ pthread_mutex_unlock(&jbc->in_lock); ++ ++ pass_queue_submit_job(s->passq + 0); // Consumes job eventually ++ } ++ else ++ { ++ pass_queue_do_all(s, jb); // Consumes job before return ++ } ++} ++ ++ ++// Call worker_pass0_ready to wait until the s->pass0_job slot becomes ++// available to receive the next job. ++// ++// Now safe against multiple callers - needed for tiles ++// "normal" and WPP will only call here one at a time ++static inline void worker_pass0_ready(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ HEVCRpiJobCtl * const jbc = s->jbc; ++ ++ // It is legit for us to already have a job allocated - do nothing in this case ++ if (lc->jb0 != NULL) ++ return; ++ ++ if (s->offload_recon) ++ rpi_sem_wait(&jbc->sem_out); // This sem will stop this frame grabbing too much ++ ++ lc->jb0 = job_alloc(jbc, lc); ++ ++ rpi_begin(s, lc->jb0, lc->ts); ++} ++ ++// Free up a job without submission ++static void worker_free(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ HEVCRpiJobCtl * const jbc = s->jbc; ++ HEVCRpiJob * const jb = lc->jb0; ++ ++ if (jb == NULL) { ++ return; ++ } ++ ++ lc->jb0 = NULL; ++ ++ job_free(jbc, jb); ++ ++ // If offload then poke sem_out too ++ if (s->offload_recon) { ++ sem_post(&jbc->sem_out); ++ } ++} ++ ++ ++// Call this to wait for all jobs to have completed at the end of a frame ++// Slightly icky as there is no clean way to wait for a sem to count up ++// Not reentrant - call on main thread only ++static void worker_wait(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc) ++{ ++ HEVCRpiJobCtl * const jbc = s->jbc; ++ int i = 0; ++ ++ // We shouldn't reach here with an unsubmitted job ++ av_assert1(lc->jb0 == NULL); ++ ++ // If no offload then there can't be anything to wait for ++ if (!s->offload_recon) { ++ return; ++ } ++ ++ if (sem_getvalue(&jbc->sem_out, &i) == 0 && i < RPI_MAX_JOBS) ++ { ++ for (i = 0; i != RPI_MAX_JOBS; ++i) { ++ rpi_sem_wait(&jbc->sem_out); ++ } ++ for (i = 0; i != RPI_MAX_JOBS; ++i) { ++ sem_post(&jbc->sem_out); ++ } ++ } ++} ++ ++static void * pass_worker(void *arg) ++{ ++ HEVCRpiPassQueue *const pq = (HEVCRpiPassQueue *)arg; ++ HEVCRpiContext *const s = pq->context; ++ ++ for (;;) ++ { ++ rpi_sem_wait(&pq->sem_in); ++ ++ if (pq->terminate) ++ break; ++ ++ pq->worker(s, s->jbc->offloadq[pass_queue_inc_job_n(pq)]); ++ // * should really set jb->passes_done here ++ ++ sem_post(pq->psem_out); ++ } ++ return NULL; ++} ++ ++static void pass_queues_start_all(HEVCRpiContext *const s) ++{ ++ unsigned int i; ++ HEVCRpiPassQueue * const pqs = s->passq; ++ ++ for (i = 0; i != RPI_PASSES; ++i) ++ { ++ av_assert0(pthread_create(&pqs[i].thread, NULL, pass_worker, pqs + i) == 0); ++ pqs[i].started = 1; ++ } ++} ++ ++static void pass_queues_term_all(HEVCRpiContext *const s) ++{ ++ unsigned int i; ++ HEVCRpiPassQueue * const pqs = s->passq; ++ ++ for (i = 0; i != RPI_PASSES; ++i) ++ pqs[i].terminate = 1; ++ for (i = 0; i != RPI_PASSES; ++i) ++ { ++ if (pqs[i].started) ++ sem_post(&pqs[i].sem_in); ++ } ++ for (i = 0; i != RPI_PASSES; ++i) ++ { ++ if (pqs[i].started) { ++ pthread_join(pqs[i].thread, NULL); ++ pqs[i].started = 0; ++ } ++ } ++} ++ ++static void pass_queues_kill_all(HEVCRpiContext *const s) ++{ ++ unsigned int i; ++ HEVCRpiPassQueue * const pqs = s->passq; ++ ++ for (i = 0; i != RPI_PASSES; ++i) ++ pass_queue_kill(pqs + i); ++} ++ ++ ++static void worker_pic_free_one(HEVCRpiJob * const jb) ++{ ++ // Free coeff stuff - allocation not the same for all buffers ++ HEVCRpiCoeffsEnv * const cf = &jb->coeffs; ++ ++ if (cf->s[0].buf != NULL) ++ av_freep(&cf->mptr); ++ if (cf->s[2].buf != NULL) ++ gpu_free(&cf->gptr); ++ memset(cf, 0, sizeof(*cf)); ++} ++ ++static int worker_pic_alloc_one(HEVCRpiJob * const jb, const unsigned int coeff_count) ++{ ++ HEVCRpiCoeffsEnv * const cf = &jb->coeffs; ++ ++ if (gpu_malloc_cached((coeff_count + 32*32) * sizeof(cf->s[2].buf[0]), &cf->gptr) != 0) ++ goto fail; ++ cf->s[2].buf = (int16_t *)cf->gptr.arm; ++ cf->s[3].buf = cf->s[2].buf + coeff_count; ++ ++ // Must be 64 byte aligned for our zero zapping code so over-allocate & ++ // round ++ if ((cf->mptr = av_malloc(coeff_count * sizeof(cf->s[0].buf[0]) + 63)) == NULL) ++ goto fail; ++ cf->s[0].buf = (void *)(((intptr_t)cf->mptr + 63) & ~63); ++ return 0; ++ ++fail: ++ av_log(NULL, AV_LOG_ERROR, "%s: Allocation failed\n", __func__); ++ worker_pic_free_one(jb); ++ return -1; ++} ++ ++static void worker_pic_reset(HEVCRpiCoeffsEnv * const cf) ++{ ++ unsigned int i; ++ for (i = 0; i != 4; ++i) { ++ cf->s[i].n = 0; ++#if RPI_COMPRESS_COEFFS ++ cf->s[i].packed = 1; ++ cf->s[i].packed_n = 0; ++#endif ++ } ++} ++ ++int16_t * rpi_alloc_coeff_buf(HEVCRpiJob * const jb, const int buf_no, const int n) ++{ ++ HEVCRpiCoeffEnv *const cfe = jb->coeffs.s + buf_no; ++ int16_t * const coeffs = (buf_no != 3) ? cfe->buf + cfe->n : cfe->buf - (cfe->n + n); ++ cfe->n += n; ++ return coeffs; ++} ++ ++void ff_hevc_rpi_progress_wait_field(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const HEVCRpiFrame * const ref, const int val, const int field) ++{ ++ if (ref->tf.progress != NULL && ((int *)ref->tf.progress->data)[field] < val) { ++ HEVCRpiContext *const fs = ref->tf.owner[field]->priv_data; ++ HEVCRpiFrameProgressState * const pstate = fs->progress_states + field; ++ sem_t * sem = NULL; ++ ++ av_assert0(pthread_mutex_lock(&pstate->lock) == 0); ++ if (((volatile int *)ref->tf.progress->data)[field] < val) { ++ HEVCRpiFrameProgressWait * const pwait = &jb->progress_wait; ++ ++ av_assert1(pwait->req == -1 && pwait->next == NULL); ++ jb->waited = 1; // Remember that we had to wait for later scheduling ++ ++ pwait->req = val; ++ pwait->next = NULL; ++ if (pstate->first == NULL) ++ pstate->first = pwait; ++ else ++ pstate->last->next = pwait; ++ pstate->last = pwait; ++ sem = &pwait->sem; ++ } ++ pthread_mutex_unlock(&pstate->lock); ++ ++ if (sem != NULL) { ++ rpi_sem_wait(sem); ++ } ++ } ++} ++ ++void ff_hevc_rpi_progress_signal_field(HEVCRpiContext * const s, const int val, const int field) ++{ ++ HEVCRpiFrameProgressState *const pstate = s->progress_states + field; ++ ++ ((int *)s->ref->tf.progress->data)[field] = val; ++ ++ av_assert0(pthread_mutex_lock(&pstate->lock) == 0); ++ { ++ HEVCRpiFrameProgressWait ** ppwait = &pstate->first; ++ HEVCRpiFrameProgressWait * pwait; ++ ++ while ((pwait = *ppwait) != NULL) { ++ if (pwait->req > val) ++ { ++ ppwait = &pwait->next; ++ pstate->last = pwait; ++ } ++ else ++ { ++ *ppwait = pwait->next; ++ pwait->req = -1; ++ pwait->next = NULL; ++ sem_post(&pwait->sem); ++ } ++ } ++ } ++ pthread_mutex_unlock(&pstate->lock); ++} ++ ++static void ff_hevc_rpi_progress_init_state(HEVCRpiFrameProgressState * const pstate) ++{ ++ pstate->first = NULL; ++ pstate->last = NULL; ++ pthread_mutex_init(&pstate->lock, NULL); ++} ++ ++static void ff_hevc_rpi_progress_init_wait(HEVCRpiFrameProgressWait * const pwait) ++{ ++ pwait->req = -1; ++ pwait->next = NULL; ++ sem_init(&pwait->sem, 0, 0); ++} ++ ++static void ff_hevc_rpi_progress_kill_state(HEVCRpiFrameProgressState * const pstate) ++{ ++ av_assert1(pstate->first == NULL); ++ pthread_mutex_destroy(&pstate->lock); ++} ++ ++static void ff_hevc_rpi_progress_kill_wait(HEVCRpiFrameProgressWait * const pwait) ++{ ++ sem_destroy(&pwait->sem); ++} ++ ++ ++/** ++ * NOTE: Each function hls_foo correspond to the function foo in the ++ * specification (HLS stands for High Level Syntax). ++ */ ++ ++/** ++ * Section 5.7 ++ */ ++ ++// Realloc the entry point arrays ++static int alloc_entry_points(RpiSliceHeader * const sh, const int n) ++{ ++ if (sh->entry_point_offset == NULL || n > sh->offsets_allocated || n == 0) ++ { ++ // Round up alloc to multiple of 32 ++ int a = (n + 31) & ~31; ++ ++ // We don't care about the previous contents so probably fastest to simply discard ++ av_freep(&sh->entry_point_offset); ++ av_freep(&sh->offset); ++ av_freep(&sh->size); ++ ++ if (a != 0) ++ { ++ sh->entry_point_offset = av_malloc_array(a, sizeof(unsigned)); ++ sh->offset = av_malloc_array(a, sizeof(int)); ++ sh->size = av_malloc_array(a, sizeof(int)); ++ ++ if (!sh->entry_point_offset || !sh->offset || !sh->size) { ++ sh->num_entry_point_offsets = 0; ++ sh->offsets_allocated = 0; ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ sh->offsets_allocated = a; ++ } ++ ++ return 0; ++} ++ ++/* free everything allocated by pic_arrays_init() */ ++static void pic_arrays_free(HEVCRpiContext *s) ++{ ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++ ++ av_freep(&s->cabac_stash_up); ++ s->cabac_stash_left = NULL; // freed with _up ++ ++ av_freep(&s->mvf_up); ++ av_freep(&s->mvf_left); ++ ++ av_freep(&s->is_pcm); ++ av_freep(&s->is_intra_store); ++ s->is_intra = NULL; ++ av_freep(&s->rpl_tab); ++ s->rpl_tab_size = 0; ++ ++ av_freep(&s->qp_y_tab); ++ av_freep(&s->tab_slice_address); ++ av_freep(&s->filter_slice_edges); ++ ++ av_freep(&s->bs_horizontal); ++ s->bs_vertical = NULL; // freed with H ++ av_freep(&s->bsf_stash_left); ++ av_freep(&s->bsf_stash_up); ++ ++ av_freep(&s->rpl_up); ++ av_freep(&s->rpl_left); ++ ++ alloc_entry_points(&s->sh, 0); ++ ++ av_buffer_pool_uninit(&s->col_mvf_pool); ++} ++ ++/* allocate arrays that depend on frame dimensions */ ++static int pic_arrays_init(HEVCRpiContext * const s, const HEVCRpiSPS * const sps) ++{ ++ const unsigned int log2_min_cb_size = sps->log2_min_cb_size; ++ const unsigned int width = sps->width; ++ const unsigned int height = sps->height; ++ const unsigned int pic_size_in_cb = ((width >> log2_min_cb_size) + 1) * ++ ((height >> log2_min_cb_size) + 1); ++ const unsigned int ctb_count = sps->ctb_size; ++ ++ { ++ unsigned int w = ((width + HEVC_RPI_BS_STRIDE1_PEL_MASK) & ~HEVC_RPI_BS_STRIDE1_PEL_MASK); ++ unsigned int h = ((height + 15) & ~15); ++ ++ s->bs_stride2 = h >> HEVC_RPI_BS_COL_BYTES_SHR; // Column size ++ s->bs_size = s->bs_stride2 * (w >> HEVC_RPI_BS_STRIDE1_PEL_SHIFT); // col size * cols ++ } ++ ++ s->sao = av_mallocz(ctb_count * sizeof(*s->sao) + 8); // Our sao code overreads this array slightly ++ s->deblock = av_mallocz_array(ctb_count, sizeof(*s->deblock)); ++ if (!s->sao || !s->deblock) ++ goto fail; ++ ++ s->cabac_stash_up = av_malloc((((width + 63) & ~63) >> 3) + (((height + 63) & ~63) >> 3)); ++ s->cabac_stash_left = s->cabac_stash_up + (((width + 63) & ~63) >> 3); ++ if (s->cabac_stash_up == NULL) ++ goto fail; ++ ++ // Round width up to max ctb size ++ s->mvf_up = av_malloc((((width + 63) & ~63) >> LOG2_MIN_PU_SIZE) * sizeof(*s->mvf_up)); ++ // * Only needed if we have H tiles ++ s->mvf_left = av_malloc((((height + 63) & ~63) >> LOG2_MIN_PU_SIZE) * sizeof(*s->mvf_up)); ++ ++ // We can overread by 1 line & one byte in deblock so alloc & zero ++ // We don't need to zero the extra @ start of frame as it will never be ++ // written ++ s->is_pcm = av_mallocz(sps->pcm_width * (sps->pcm_height + 1) + 1); ++ s->is_intra_store = av_mallocz(sps->pcm_width * (sps->pcm_height + 1) + 1); ++ if (s->is_pcm == NULL || s->is_intra_store == NULL) ++ goto fail; ++ ++ s->filter_slice_edges = av_mallocz(ctb_count); ++ s->tab_slice_address = av_malloc_array(ctb_count, ++ sizeof(*s->tab_slice_address)); ++ s->qp_y_tab = av_malloc_array(pic_size_in_cb, ++ sizeof(*s->qp_y_tab)); ++ if (!s->qp_y_tab || !s->filter_slice_edges || !s->tab_slice_address) ++ goto fail; ++ ++ s->bs_horizontal = av_mallocz(s->bs_size * 2); ++ s->bs_vertical = s->bs_horizontal + s->bs_size; ++ if (s->bs_horizontal == NULL) ++ goto fail; ++ ++ s->rpl_up = av_mallocz(sps->ctb_width * sizeof(*s->rpl_up)); ++ s->rpl_left = av_mallocz(sps->ctb_height * sizeof(*s->rpl_left)); ++ if (s->rpl_left == NULL || s->rpl_up == NULL) ++ goto fail; ++ ++ if ((s->bsf_stash_left = av_mallocz(((height + 63) & ~63) >> 4)) == NULL || ++ (s->bsf_stash_up = av_mallocz(((width + 63) & ~63) >> 4)) == NULL) ++ goto fail; ++ ++ s->col_mvf_stride = (width + 15) >> 4; ++ s->col_mvf_pool = av_buffer_pool_init(((height + 15) >> 4) * s->col_mvf_stride * sizeof(ColMvField), ++ av_buffer_allocz); ++ if (s->col_mvf_pool == NULL) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ pic_arrays_free(s); ++ return AVERROR(ENOMEM); ++} ++ ++static void default_pred_weight_table(HEVCRpiContext * const s) ++{ ++ unsigned int i; ++ const unsigned int wt = 1 << QPU_MC_DENOM; ++ s->sh.luma_log2_weight_denom = 0; ++ s->sh.chroma_log2_weight_denom = 0; ++ for (i = 0; i < s->sh.nb_refs[L0]; i++) { ++ s->sh.luma_weight_l0[i] = wt; ++ s->sh.luma_offset_l0[i] = 0; ++ s->sh.chroma_weight_l0[i][0] = wt; ++ s->sh.chroma_weight_l0[i][1] = wt; ++ s->sh.chroma_offset_l0[i][0] = 0; ++ s->sh.chroma_offset_l0[i][1] = 0; ++ } ++ for (i = 0; i < s->sh.nb_refs[L1]; i++) { ++ s->sh.luma_weight_l1[i] = wt; ++ s->sh.luma_offset_l1[i] = 0; ++ s->sh.chroma_weight_l1[i][0] = wt; ++ s->sh.chroma_weight_l1[i][1] = wt; ++ s->sh.chroma_offset_l1[i][0] = 0; ++ s->sh.chroma_offset_l1[i][1] = 0; ++ } ++} ++ ++static int get_weights(HEVCRpiContext * const s, GetBitContext * const gb, ++ const unsigned int refs, ++ int16_t * luma_weight, int16_t * luma_offset, ++ int16_t * chroma_weight, int16_t * chroma_offset) ++{ ++ unsigned int luma_flags; ++ unsigned int chroma_flags; ++ unsigned int i; ++ const unsigned int wp_offset_bd_shift = s->ps.sps->high_precision_offsets_enabled_flag ? 0 : (s->ps.sps->bit_depth - 8); ++ const int wp_offset_half_range = s->ps.sps->wp_offset_half_range; ++ const unsigned int luma_weight_base = 1 << QPU_MC_DENOM; ++ const unsigned int chroma_weight_base = 1 << QPU_MC_DENOM; ++ const unsigned int luma_weight_shift = (QPU_MC_DENOM - s->sh.luma_log2_weight_denom); ++ const unsigned int chroma_weight_shift = (QPU_MC_DENOM - s->sh.chroma_log2_weight_denom); ++ ++ if (refs == 0) ++ return 0; ++ ++ luma_flags = get_bits(gb, refs); ++ chroma_flags = ctx_cfmt(s) == 0 ? 0 : get_bits(gb, refs); ++ i = 1 << (refs - 1); ++ ++ do ++ { ++ if ((luma_flags & i) != 0) ++ { ++ const int delta_weight = get_se_golomb(gb); ++ const int offset = get_se_golomb(gb); ++ if (delta_weight < -128 || delta_weight > 127 || ++ offset < -wp_offset_half_range || offset >= wp_offset_half_range) ++ { ++ return AVERROR_INVALIDDATA; ++ } ++ *luma_weight++ = luma_weight_base + (delta_weight << luma_weight_shift); ++ *luma_offset++ = offset << wp_offset_bd_shift; ++ } ++ else ++ { ++ *luma_weight++ = luma_weight_base; ++ *luma_offset++ = 0; ++ } ++ ++ if ((chroma_flags & i) != 0) ++ { ++ unsigned int j; ++ for (j = 0; j != 2; ++j) ++ { ++ const int delta_weight = get_se_golomb(gb); ++ const int delta_offset = get_se_golomb(gb); ++ ++ if (delta_weight < -128 || delta_weight > 127 || ++ delta_offset < -4 * wp_offset_half_range || delta_offset >= 4 * wp_offset_half_range) ++ { ++ return AVERROR_INVALIDDATA; ++ } ++ ++ *chroma_weight++ = chroma_weight_base + (delta_weight << chroma_weight_shift); ++ *chroma_offset++ = av_clip( ++ wp_offset_half_range + delta_offset - ++ ((wp_offset_half_range * ((1 << s->sh.chroma_log2_weight_denom) + delta_weight)) >> s->sh.chroma_log2_weight_denom), ++ -wp_offset_half_range, wp_offset_half_range - 1) << wp_offset_bd_shift; ++ } ++ } ++ else ++ { ++ *chroma_weight++ = chroma_weight_base; ++ *chroma_weight++ = chroma_weight_base; ++ *chroma_offset++ = 0; ++ *chroma_offset++ = 0; ++ } ++ } while ((i >>= 1) != 0); ++ ++ return 0; ++} ++ ++static int pred_weight_table(HEVCRpiContext *s, GetBitContext *gb) ++{ ++ int err; ++ const unsigned int luma_log2_weight_denom = get_ue_golomb_long(gb); ++ const unsigned int chroma_log2_weight_denom = (ctx_cfmt(s) == 0) ? 0 : luma_log2_weight_denom + get_se_golomb(gb); ++ ++ if (luma_log2_weight_denom > 7 || ++ chroma_log2_weight_denom > 7) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Invalid prediction weight denom: luma=%d, chroma=%d\n", ++ luma_log2_weight_denom, chroma_log2_weight_denom); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ s->sh.luma_log2_weight_denom = luma_log2_weight_denom; ++ s->sh.chroma_log2_weight_denom = chroma_log2_weight_denom; ++ ++ if ((err = get_weights(s, gb, s->sh.nb_refs[L0], ++ s->sh.luma_weight_l0, s->sh.luma_offset_l0, ++ s->sh.chroma_weight_l0[0], s->sh.chroma_offset_l0[0])) != 0 || ++ (err = get_weights(s, gb, s->sh.nb_refs[L1], ++ s->sh.luma_weight_l1, s->sh.luma_offset_l1, ++ s->sh.chroma_weight_l1[0], s->sh.chroma_offset_l1[0])) != 0) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Invalid prediction weight or offset\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int decode_lt_rps(HEVCRpiContext *s, LongTermRPS *rps, GetBitContext *gb) ++{ ++ const HEVCRpiSPS *sps = s->ps.sps; ++ int max_poc_lsb = 1 << sps->log2_max_poc_lsb; ++ int prev_delta_msb = 0; ++ unsigned int nb_sps = 0, nb_sh; ++ int i; ++ ++ rps->nb_refs = 0; ++ if (!sps->long_term_ref_pics_present_flag) ++ return 0; ++ ++ if (sps->num_long_term_ref_pics_sps > 0) ++ nb_sps = get_ue_golomb_long(gb); ++ nb_sh = get_ue_golomb_long(gb); ++ ++ if (nb_sps > sps->num_long_term_ref_pics_sps) ++ return AVERROR_INVALIDDATA; ++ if (nb_sh + (uint64_t)nb_sps > FF_ARRAY_ELEMS(rps->poc)) ++ return AVERROR_INVALIDDATA; ++ ++ rps->nb_refs = nb_sh + nb_sps; ++ ++ for (i = 0; i < rps->nb_refs; i++) { ++ uint8_t delta_poc_msb_present; ++ ++ if (i < nb_sps) { ++ uint8_t lt_idx_sps = 0; ++ ++ if (sps->num_long_term_ref_pics_sps > 1) ++ lt_idx_sps = get_bits(gb, av_ceil_log2(sps->num_long_term_ref_pics_sps)); ++ ++ rps->poc[i] = sps->lt_ref_pic_poc_lsb_sps[lt_idx_sps]; ++ rps->used[i] = sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps]; ++ } else { ++ rps->poc[i] = get_bits(gb, sps->log2_max_poc_lsb); ++ rps->used[i] = get_bits1(gb); ++ } ++ ++ delta_poc_msb_present = get_bits1(gb); ++ if (delta_poc_msb_present) { ++ int64_t delta = get_ue_golomb_long(gb); ++ int64_t poc; ++ ++ if (i && i != nb_sps) ++ delta += prev_delta_msb; ++ ++ poc = rps->poc[i] + s->poc - delta * max_poc_lsb - s->sh.pic_order_cnt_lsb; ++ if (poc != (int32_t)poc) ++ return AVERROR_INVALIDDATA; ++ rps->poc[i] = poc; ++ prev_delta_msb = delta; ++ } ++ } ++ ++ return 0; ++} ++ ++static void export_stream_params(AVCodecContext *avctx, const HEVCRpiParamSets *ps, ++ const HEVCRpiSPS *sps) ++{ ++ const HEVCRpiVPS *vps = (const HEVCRpiVPS*)ps->vps_list[sps->vps_id]->data; ++ const HEVCRpiWindow *ow = &sps->output_window; ++ unsigned int num = 0, den = 0; ++ ++ avctx->pix_fmt = sps->pix_fmt; ++ avctx->coded_width = sps->width; ++ avctx->coded_height = sps->height; ++ avctx->width = sps->width - ow->left_offset - ow->right_offset; ++ avctx->height = sps->height - ow->top_offset - ow->bottom_offset; ++ avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; ++ avctx->profile = sps->ptl.general_ptl.profile_idc; ++ avctx->level = sps->ptl.general_ptl.level_idc; ++ ++ ff_set_sar(avctx, sps->vui.sar); ++ ++ if (sps->vui.video_signal_type_present_flag) ++ avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG ++ : AVCOL_RANGE_MPEG; ++ else ++ avctx->color_range = AVCOL_RANGE_MPEG; ++ ++ if (sps->vui.colour_description_present_flag) { ++ avctx->color_primaries = sps->vui.colour_primaries; ++ avctx->color_trc = sps->vui.transfer_characteristic; ++ avctx->colorspace = sps->vui.matrix_coeffs; ++ } else { ++ avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; ++ avctx->color_trc = AVCOL_TRC_UNSPECIFIED; ++ avctx->colorspace = AVCOL_SPC_UNSPECIFIED; ++ } ++ ++ if (vps->vps_timing_info_present_flag) { ++ num = vps->vps_num_units_in_tick; ++ den = vps->vps_time_scale; ++ } else if (sps->vui.vui_timing_info_present_flag) { ++ num = sps->vui.vui_num_units_in_tick; ++ den = sps->vui.vui_time_scale; ++ } ++ ++ if (num != 0 && den != 0) ++ av_reduce(&avctx->framerate.den, &avctx->framerate.num, ++ num, den, 1 << 30); ++} ++ ++static enum AVPixelFormat get_format(HEVCRpiContext *s, const HEVCRpiSPS *sps) ++{ ++ enum AVPixelFormat pix_fmts[4], *fmt = pix_fmts; ++ ++ // Admit to no h/w formats ++ ++ *fmt++ = sps->pix_fmt; ++ *fmt = AV_PIX_FMT_NONE; ++ ++ return pix_fmts[0] == AV_PIX_FMT_NONE ? AV_PIX_FMT_NONE: ff_thread_get_format(s->avctx, pix_fmts); ++} ++ ++static int is_sps_supported(const HEVCRpiSPS * const sps) ++{ ++ return av_rpi_is_sand_format(sps->pix_fmt) && ++ sps->width <= HEVC_RPI_MAX_WIDTH && ++ sps->height <= HEVC_RPI_MAX_HEIGHT; ++} ++ ++static int set_sps(HEVCRpiContext * const s, const HEVCRpiSPS * const sps, ++ const enum AVPixelFormat pix_fmt) ++{ ++ int ret; ++ ++ pic_arrays_free(s); ++ s->ps.sps = NULL; ++ s->ps.vps = NULL; ++ ++ if (sps == NULL) ++ return 0; ++ ++ if (!is_sps_supported(sps)) ++ return AVERROR_DECODER_NOT_FOUND; ++ ++ ret = pic_arrays_init(s, sps); ++ if (ret < 0) ++ goto fail; ++ ++ export_stream_params(s->avctx, &s->ps, sps); ++ ++ s->avctx->pix_fmt = pix_fmt; ++ ++ ff_hevc_rpi_pred_init(&s->hpc, sps->bit_depth); ++ ff_hevc_rpi_dsp_init (&s->hevcdsp, sps->bit_depth); ++ ++ // * We don't support cross_component_prediction_enabled_flag but as that ++ // must be 0 unless we have 4:4:4 there is no point testing for it as we ++ // only deal with sand which is never 4:4:4 ++ // [support wouldn't be hard] ++ ++ rpi_hevc_qpu_set_fns(s, sps->bit_depth); ++ ++ av_freep(&s->sao_pixel_buffer_h[0]); ++ av_freep(&s->sao_pixel_buffer_v[0]); ++ ++ if (sps->sao_enabled) ++ { ++ const unsigned int c_count = (ctx_cfmt(s) != 0) ? 3 : 1; ++ unsigned int c_idx; ++ size_t vsize[3] = {0}; ++ size_t hsize[3] = {0}; ++ ++ for(c_idx = 0; c_idx < c_count; c_idx++) { ++ int w = sps->width >> ctx_hshift(s, c_idx); ++ int h = sps->height >> ctx_vshift(s, c_idx); ++ // ctb height & width are a min of 8 so this must a multiple of 16 ++ // so no point rounding up! ++ hsize[c_idx] = (w * 2 * sps->ctb_height) << sps->pixel_shift; ++ vsize[c_idx] = (h * 2 * sps->ctb_width) << sps->pixel_shift; ++ } ++ ++ // Allocate as a single lump so we can extend h[1] & v[1] into h[2] & v[2] ++ // when we have plaited chroma ++ s->sao_pixel_buffer_h[0] = av_malloc(hsize[0] + hsize[1] + hsize[2]); ++ s->sao_pixel_buffer_v[0] = av_malloc(vsize[0] + vsize[1] + vsize[2]); ++ s->sao_pixel_buffer_h[1] = s->sao_pixel_buffer_h[0] + hsize[0]; ++ s->sao_pixel_buffer_h[2] = s->sao_pixel_buffer_h[1] + hsize[1]; ++ s->sao_pixel_buffer_v[1] = s->sao_pixel_buffer_v[0] + vsize[0]; ++ s->sao_pixel_buffer_v[2] = s->sao_pixel_buffer_v[1] + vsize[1]; ++ } ++ ++ s->ps.sps = sps; ++ s->ps.vps = (HEVCRpiVPS*) s->ps.vps_list[s->ps.sps->vps_id]->data; ++ ++ return 0; ++ ++fail: ++ pic_arrays_free(s); ++ s->ps.sps = NULL; ++ return ret; ++} ++ ++static inline int qp_offset_valid(const int qp_offset) ++{ ++ return qp_offset >= -12 && qp_offset <= 12; ++} ++ ++static int hls_slice_header(HEVCRpiContext * const s) ++{ ++ GetBitContext * const gb = &s->HEVClc->gb; ++ RpiSliceHeader * const sh = &s->sh; ++ int i, ret; ++ ++ // Coded parameters ++ sh->first_slice_in_pic_flag = get_bits1(gb); ++ if ((IS_IDR(s) || IS_BLA(s)) && sh->first_slice_in_pic_flag) { ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ if (IS_IDR(s)) ++ ff_hevc_rpi_clear_refs(s); ++ } ++ sh->no_output_of_prior_pics_flag = 0; ++ if (IS_IRAP(s)) ++ sh->no_output_of_prior_pics_flag = get_bits1(gb); ++ ++ sh->pps_id = get_ue_golomb_long(gb); ++ if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { ++ av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id); ++ return AVERROR_INVALIDDATA; ++ } ++ if (!sh->first_slice_in_pic_flag && ++ s->ps.pps != (HEVCRpiPPS*)s->ps.pps_list[sh->pps_id]->data) { ++ av_log(s->avctx, AV_LOG_ERROR, "PPS changed between slices.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ s->ps.pps = (HEVCRpiPPS*)s->ps.pps_list[sh->pps_id]->data; ++ if (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos == 1) ++ sh->no_output_of_prior_pics_flag = 1; ++ ++ if (s->ps.sps != (HEVCRpiSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data) { ++ const HEVCRpiSPS *sps = (HEVCRpiSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data; ++ const HEVCRpiSPS *last_sps = s->ps.sps; ++ enum AVPixelFormat pix_fmt; ++ ++ if (last_sps && IS_IRAP(s) && s->nal_unit_type != HEVC_NAL_CRA_NUT) { ++ if (sps->width != last_sps->width || sps->height != last_sps->height || ++ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering != ++ last_sps->temporal_layer[last_sps->max_sub_layers - 1].max_dec_pic_buffering) ++ sh->no_output_of_prior_pics_flag = 0; ++ } ++ ff_hevc_rpi_clear_refs(s); ++ ++ ret = set_sps(s, sps, sps->pix_fmt); ++ if (ret < 0) ++ return ret; ++ ++ pix_fmt = get_format(s, sps); ++ if (pix_fmt < 0) ++ return pix_fmt; ++ ++// ret = set_sps(s, sps, pix_fmt); ++// if (ret < 0) ++// return ret; ++ ++ s->avctx->pix_fmt = pix_fmt; ++ ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ } ++ ++ sh->dependent_slice_segment_flag = 0; ++ if (!sh->first_slice_in_pic_flag) { ++ int slice_address_length; ++ ++ if (s->ps.pps->dependent_slice_segments_enabled_flag) ++ sh->dependent_slice_segment_flag = get_bits1(gb); ++ ++ slice_address_length = av_ceil_log2(s->ps.sps->ctb_size); ++ sh->slice_segment_addr = get_bitsz(gb, slice_address_length); ++ if (sh->slice_segment_addr >= s->ps.sps->ctb_size) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid slice segment address: %u.\n", ++ sh->slice_segment_addr); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (!sh->dependent_slice_segment_flag) { ++ sh->slice_addr = sh->slice_segment_addr; ++ s->slice_idx++; ++ } ++ } else { ++ sh->slice_segment_addr = sh->slice_addr = 0; ++ s->slice_idx = 0; ++ s->slice_initialized = 0; ++ } ++ ++ if (!sh->dependent_slice_segment_flag) { ++ s->slice_initialized = 0; ++ ++ for (i = 0; i < s->ps.pps->num_extra_slice_header_bits; i++) ++ skip_bits(gb, 1); // slice_reserved_undetermined_flag[] ++ ++ sh->slice_type = get_ue_golomb_long(gb); ++ if (!(sh->slice_type == HEVC_SLICE_I || ++ sh->slice_type == HEVC_SLICE_P || ++ sh->slice_type == HEVC_SLICE_B)) { ++ av_log(s->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n", ++ sh->slice_type); ++ return AVERROR_INVALIDDATA; ++ } ++ if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I) { ++ av_log(s->avctx, AV_LOG_ERROR, "Inter slices in an IRAP frame.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ // when flag is not present, picture is inferred to be output ++ sh->pic_output_flag = 1; ++ if (s->ps.pps->output_flag_present_flag) ++ sh->pic_output_flag = get_bits1(gb); ++ ++ if (s->ps.sps->separate_colour_plane_flag) ++ sh->colour_plane_id = get_bits(gb, 2); ++ ++ if (!IS_IDR(s)) { ++ int poc, pos; ++ ++ sh->pic_order_cnt_lsb = get_bits(gb, s->ps.sps->log2_max_poc_lsb); ++ poc = ff_hevc_rpi_compute_poc(s->ps.sps, s->pocTid0, sh->pic_order_cnt_lsb, s->nal_unit_type); ++ if (!sh->first_slice_in_pic_flag && poc != s->poc) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Ignoring POC change between slices: %d -> %d\n", s->poc, poc); ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return AVERROR_INVALIDDATA; ++ poc = s->poc; ++ } ++ s->poc = poc; ++ ++ sh->short_term_ref_pic_set_sps_flag = get_bits1(gb); ++ pos = get_bits_left(gb); ++ if (!sh->short_term_ref_pic_set_sps_flag) { ++ ret = ff_hevc_rpi_decode_short_term_rps(gb, s->avctx, &sh->slice_rps, s->ps.sps, 1); ++ if (ret < 0) ++ return ret; ++ ++ sh->short_term_rps = &sh->slice_rps; ++ } else { ++ int numbits, rps_idx; ++ ++ if (!s->ps.sps->nb_st_rps) { ++ av_log(s->avctx, AV_LOG_ERROR, "No ref lists in the SPS.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ numbits = av_ceil_log2(s->ps.sps->nb_st_rps); ++ rps_idx = numbits > 0 ? get_bits(gb, numbits) : 0; ++ sh->short_term_rps = &s->ps.sps->st_rps[rps_idx]; ++ } ++ sh->short_term_ref_pic_set_size = pos - get_bits_left(gb); ++ ++ pos = get_bits_left(gb); ++ ret = decode_lt_rps(s, &sh->long_term_rps, gb); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, "Invalid long term RPS.\n"); ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return AVERROR_INVALIDDATA; ++ } ++ sh->long_term_ref_pic_set_size = pos - get_bits_left(gb); ++ ++ if (s->ps.sps->sps_temporal_mvp_enabled_flag) ++ sh->slice_temporal_mvp_enabled_flag = get_bits1(gb); ++ else ++ sh->slice_temporal_mvp_enabled_flag = 0; ++ } else { ++ s->sh.short_term_rps = NULL; ++ s->poc = 0; ++ } ++ ++ /* 8.3.1 */ ++ if (sh->first_slice_in_pic_flag && s->temporal_id == 0 && ++ s->nal_unit_type != HEVC_NAL_TRAIL_N && ++ s->nal_unit_type != HEVC_NAL_TSA_N && ++ s->nal_unit_type != HEVC_NAL_STSA_N && ++ s->nal_unit_type != HEVC_NAL_RADL_N && ++ s->nal_unit_type != HEVC_NAL_RADL_R && ++ s->nal_unit_type != HEVC_NAL_RASL_N && ++ s->nal_unit_type != HEVC_NAL_RASL_R) ++ s->pocTid0 = s->poc; ++ ++ if (s->ps.sps->sao_enabled) { ++ sh->slice_sample_adaptive_offset_flag[0] = get_bits1(gb); ++ if (ctx_cfmt(s) != 0) { ++ sh->slice_sample_adaptive_offset_flag[1] = ++ sh->slice_sample_adaptive_offset_flag[2] = get_bits1(gb); ++ } ++ } else { ++ sh->slice_sample_adaptive_offset_flag[0] = 0; ++ sh->slice_sample_adaptive_offset_flag[1] = 0; ++ sh->slice_sample_adaptive_offset_flag[2] = 0; ++ } ++ ++ sh->nb_refs[L0] = sh->nb_refs[L1] = 0; ++ if (sh->slice_type == HEVC_SLICE_P || sh->slice_type == HEVC_SLICE_B) { ++ int nb_refs; ++ ++ sh->nb_refs[L0] = s->ps.pps->num_ref_idx_l0_default_active; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->nb_refs[L1] = s->ps.pps->num_ref_idx_l1_default_active; ++ ++ if (get_bits1(gb)) { // num_ref_idx_active_override_flag ++ sh->nb_refs[L0] = get_ue_golomb_long(gb) + 1; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->nb_refs[L1] = get_ue_golomb_long(gb) + 1; ++ } ++ if (sh->nb_refs[L0] > HEVC_MAX_REFS || sh->nb_refs[L1] > HEVC_MAX_REFS) { ++ av_log(s->avctx, AV_LOG_ERROR, "Too many refs: %d/%d.\n", ++ sh->nb_refs[L0], sh->nb_refs[L1]); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->rpl_modification_flag[0] = 0; ++ sh->rpl_modification_flag[1] = 0; ++ nb_refs = ff_hevc_rpi_frame_nb_refs(s); ++ if (!nb_refs) { ++ av_log(s->avctx, AV_LOG_ERROR, "Zero refs for a frame with P or B slices.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (s->ps.pps->lists_modification_present_flag && nb_refs > 1) { ++ sh->rpl_modification_flag[0] = get_bits1(gb); ++ if (sh->rpl_modification_flag[0]) { ++ for (i = 0; i < sh->nb_refs[L0]; i++) ++ sh->list_entry_lx[0][i] = get_bits(gb, av_ceil_log2(nb_refs)); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ sh->rpl_modification_flag[1] = get_bits1(gb); ++ if (sh->rpl_modification_flag[1] == 1) ++ for (i = 0; i < sh->nb_refs[L1]; i++) ++ sh->list_entry_lx[1][i] = get_bits(gb, av_ceil_log2(nb_refs)); ++ } ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->mvd_l1_zero_flag = get_bits1(gb); ++ ++ if (s->ps.pps->cabac_init_present_flag) ++ sh->cabac_init_flag = get_bits1(gb); ++ else ++ sh->cabac_init_flag = 0; ++ ++ sh->collocated_ref_idx = 0; ++ if (sh->slice_temporal_mvp_enabled_flag) { ++ sh->collocated_list = L0; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->collocated_list = !get_bits1(gb); ++ ++ if (sh->nb_refs[sh->collocated_list] > 1) { ++ sh->collocated_ref_idx = get_ue_golomb_long(gb); ++ if (sh->collocated_ref_idx >= sh->nb_refs[sh->collocated_list]) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid collocated_ref_idx: %d.\n", ++ sh->collocated_ref_idx); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ } ++ ++ if ((s->ps.pps->weighted_pred_flag && sh->slice_type == HEVC_SLICE_P) || ++ (s->ps.pps->weighted_bipred_flag && sh->slice_type == HEVC_SLICE_B)) ++ { ++ if ((ret = pred_weight_table(s, gb)) != 0) ++ return ret; ++ } ++ else ++ { ++ // Give us unit weights ++ default_pred_weight_table(s); ++ } ++ ++ sh->max_num_merge_cand = 5 - get_ue_golomb_long(gb); ++ if (sh->max_num_merge_cand < 1 || sh->max_num_merge_cand > 5) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid number of merging MVP candidates: %d.\n", ++ sh->max_num_merge_cand); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ sh->slice_qp_delta = get_se_golomb(gb); ++ ++ if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) { ++ sh->slice_cb_qp_offset = get_se_golomb(gb); ++ sh->slice_cr_qp_offset = get_se_golomb(gb); ++ if (!qp_offset_valid(sh->slice_cb_qp_offset) || ++ !qp_offset_valid(s->ps.pps->cb_qp_offset + sh->slice_cb_qp_offset) || ++ !qp_offset_valid(sh->slice_cr_qp_offset) || ++ !qp_offset_valid(s->ps.pps->cr_qp_offset + sh->slice_cr_qp_offset)) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Bad chroma offset (pps:%d/%d; slice=%d/%d\n", ++ sh->slice_cr_qp_offset, sh->slice_cr_qp_offset, ++ s->ps.pps->cb_qp_offset, s->ps.pps->cr_qp_offset); ++ return AVERROR_INVALIDDATA; ++ } ++ } else ++ { ++ sh->slice_cb_qp_offset = 0; ++ sh->slice_cr_qp_offset = 0; ++ } ++ ++ if (s->ps.pps->chroma_qp_offset_list_enabled_flag) ++ sh->cu_chroma_qp_offset_enabled_flag = get_bits1(gb); ++ else ++ sh->cu_chroma_qp_offset_enabled_flag = 0; ++ ++ if (s->ps.pps->deblocking_filter_control_present_flag) { ++ int deblocking_filter_override_flag = 0; ++ ++ if (s->ps.pps->deblocking_filter_override_enabled_flag) ++ deblocking_filter_override_flag = get_bits1(gb); ++ ++ if (deblocking_filter_override_flag) { ++ sh->disable_deblocking_filter_flag = get_bits1(gb); ++ if (!sh->disable_deblocking_filter_flag) { ++ int beta_offset_div2 = get_se_golomb(gb); ++ int tc_offset_div2 = get_se_golomb(gb) ; ++ if (beta_offset_div2 < -6 || beta_offset_div2 > 6 || ++ tc_offset_div2 < -6 || tc_offset_div2 > 6) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid deblock filter offsets: %d, %d\n", ++ beta_offset_div2, tc_offset_div2); ++ return AVERROR_INVALIDDATA; ++ } ++ sh->beta_offset = beta_offset_div2 * 2; ++ sh->tc_offset = tc_offset_div2 * 2; ++ } ++ } else { ++ sh->disable_deblocking_filter_flag = s->ps.pps->disable_dbf; ++ sh->beta_offset = s->ps.pps->beta_offset; ++ sh->tc_offset = s->ps.pps->tc_offset; ++ } ++ } else { ++ sh->disable_deblocking_filter_flag = 0; ++ sh->beta_offset = 0; ++ sh->tc_offset = 0; ++ } ++ ++ if (s->ps.pps->seq_loop_filter_across_slices_enabled_flag && ++ (sh->slice_sample_adaptive_offset_flag[0] || ++ sh->slice_sample_adaptive_offset_flag[1] || ++ !sh->disable_deblocking_filter_flag)) { ++ sh->slice_loop_filter_across_slices_enabled_flag = get_bits1(gb); ++ } else { ++ sh->slice_loop_filter_across_slices_enabled_flag = s->ps.pps->seq_loop_filter_across_slices_enabled_flag; ++ } ++ sh->no_dblk_boundary_flags = ++ (sh->slice_loop_filter_across_slices_enabled_flag ? 0 : ++ BOUNDARY_UPPER_SLICE | BOUNDARY_LEFT_SLICE) | ++ (s->ps.pps->loop_filter_across_tiles_enabled_flag ? 0 : ++ BOUNDARY_UPPER_TILE | BOUNDARY_LEFT_TILE); ++ ++ ++ } else if (!s->slice_initialized) { ++ av_log(s->avctx, AV_LOG_ERROR, "Independent slice segment missing.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->num_entry_point_offsets = 0; ++ sh->offload_wpp = 0; ++ sh->offload_tiles = 0; ++ ++ if (s->ps.pps->tiles_enabled_flag || s->ps.pps->entropy_coding_sync_enabled_flag) { ++ unsigned num_entry_point_offsets = get_ue_golomb_long(gb); ++ // It would be possible to bound this tighter but this here is simpler ++ if (num_entry_point_offsets > get_bits_left(gb)) { ++ av_log(s->avctx, AV_LOG_ERROR, "num_entry_point_offsets %d is invalid\n", num_entry_point_offsets); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->num_entry_point_offsets = num_entry_point_offsets; ++ if (sh->num_entry_point_offsets > 0) { ++ int offset_len = get_ue_golomb_long(gb) + 1; ++ ++ if (offset_len < 1 || offset_len > 32) { ++ sh->num_entry_point_offsets = 0; ++ av_log(s->avctx, AV_LOG_ERROR, "offset_len %d is invalid\n", offset_len); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if ((ret = alloc_entry_points(sh, sh->num_entry_point_offsets)) < 0) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate memory\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < sh->num_entry_point_offsets; i++) { ++ uint32_t val_minus1 = get_bits_long(gb, offset_len); ++ if (val_minus1 > (1 << 28)) ++ { ++ // We can declare offsets of > 2^28 bad without loss of generality ++ // Will check actual bounds wrt NAL later, but this keeps ++ // the values within bounds we can deal with easily ++ av_log(s->avctx, AV_LOG_ERROR, "entry_point_offset_minus1 %d invalid\n", val_minus1); ++ return AVERROR_INVALIDDATA; ++ } ++ sh->entry_point_offset[i] = val_minus1 + 1; // +1 to get the size ++ } ++ ++ // Do we want to offload this ++ if (s->threads_type != 0) ++ { ++ sh->offload_tiles = (!s->ps.pps->tile_wpp_inter_disable || sh->slice_type == HEVC_SLICE_I) && ++ s->ps.pps->num_tile_columns > 1; ++ // * We only cope with WPP in a single column ++ // Probably want to deal with that case as tiles rather than WPP anyway ++ // ?? Not actually sure that the main code deals with WPP + multi-col correctly ++ sh->offload_wpp = s->ps.pps->entropy_coding_sync_enabled_flag && ++ s->ps.pps->num_tile_columns == 1; ++ } ++ } ++ } ++ ++ if (s->ps.pps->slice_header_extension_present_flag) { ++ unsigned int length = get_ue_golomb_long(gb); ++ if (length*8LL > get_bits_left(gb)) { ++ av_log(s->avctx, AV_LOG_ERROR, "too many slice_header_extension_data_bytes\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ for (i = 0; i < length; i++) ++ skip_bits(gb, 8); // slice_header_extension_data_byte ++ } ++ ++ // Inferred parameters ++ sh->slice_qp = 26U + s->ps.pps->pic_init_qp_minus26 + sh->slice_qp_delta; ++ if (sh->slice_qp > 51 || ++ sh->slice_qp < -s->ps.sps->qp_bd_offset) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "The slice_qp %d is outside the valid range " ++ "[%d, 51].\n", ++ sh->slice_qp, ++ -s->ps.sps->qp_bd_offset); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (get_bits_left(gb) < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Overread slice header by %d bits\n", -get_bits_left(gb)); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ s->slice_initialized = 1; ++ return 0; ++} ++ ++static void hls_sao_param(const HEVCRpiContext *s, HEVCRpiLocalContext * const lc, const int rx, const int ry) ++{ ++ RpiSAOParams * const sao = s->sao + rx + ry * s->ps.sps->ctb_width; ++ int c_idx, i; ++ ++ if (s->sh.slice_sample_adaptive_offset_flag[0] || ++ s->sh.slice_sample_adaptive_offset_flag[1]) { ++ if ((lc->ctb_avail & AVAIL_L) != 0) ++ { ++ const int sao_merge_left_flag = ff_hevc_rpi_sao_merge_flag_decode(lc); ++ if (sao_merge_left_flag) { ++ *sao = sao[-1]; ++ return; ++ } ++ } ++ if ((lc->ctb_avail & AVAIL_U) != 0) ++ { ++ const int sao_merge_up_flag = ff_hevc_rpi_sao_merge_flag_decode(lc); ++ if (sao_merge_up_flag) { ++ *sao = sao[-(int)s->ps.sps->ctb_width]; ++ return; ++ } ++ } ++ } ++ ++ for (c_idx = 0; c_idx < (ctx_cfmt(s) != 0 ? 3 : 1); c_idx++) { ++ const unsigned int log2_sao_offset_scale = c_idx == 0 ? s->ps.pps->log2_sao_offset_scale_luma : ++ s->ps.pps->log2_sao_offset_scale_chroma; ++ int offset_abs[4]; ++ char offset_sign[4] = {0}; ++ ++ if (!s->sh.slice_sample_adaptive_offset_flag[c_idx]) { ++ sao->type_idx[c_idx] = SAO_NOT_APPLIED; ++ continue; ++ } ++ ++ if (c_idx == 2) { ++ sao->type_idx[2] = sao->type_idx[1]; ++ sao->eo_class[2] = sao->eo_class[1]; ++ } else { ++ sao->type_idx[c_idx] = ff_hevc_rpi_sao_type_idx_decode(lc); ++ } ++ ++ // ** Could use BY22 here quite plausibly - this is all bypass stuff ++ // though only per CTB so not very timing critical ++ ++ if (sao->type_idx[c_idx] == SAO_NOT_APPLIED) ++ continue; ++ ++ for (i = 0; i < 4; i++) ++ offset_abs[i] = ff_hevc_rpi_sao_offset_abs_decode(s, lc); ++ ++ if (sao->type_idx[c_idx] == SAO_BAND) { ++ for (i = 0; i < 4; i++) { ++ if (offset_abs[i] != 0) ++ offset_sign[i] = ff_hevc_rpi_sao_offset_sign_decode(lc); ++ } ++ sao->band_position[c_idx] = ff_hevc_rpi_sao_band_position_decode(lc); ++ } else if (c_idx != 2) { ++ sao->eo_class[c_idx] = ff_hevc_rpi_sao_eo_class_decode(lc); ++ } ++ ++ // Inferred parameters ++ sao->offset_val[c_idx][0] = 0; ++ for (i = 0; i < 4; i++) { ++ sao->offset_val[c_idx][i + 1] = offset_abs[i] << log2_sao_offset_scale; ++ if (sao->type_idx[c_idx] == SAO_EDGE) { ++ if (i > 1) ++ sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; ++ } else if (offset_sign[i]) { ++ sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; ++ } ++ } ++ } ++} ++ ++#if 0 ++static int hls_cross_component_pred(HEVCRpiLocalContext * const lc, const int idx) { ++ int log2_res_scale_abs_plus1 = ff_hevc_rpi_log2_res_scale_abs(lc, idx); // 0..4 ++ ++ if (log2_res_scale_abs_plus1 != 0) { ++ int res_scale_sign_flag = ff_hevc_rpi_res_scale_sign_flag(lc, idx); ++ lc->tu.res_scale_val = (1 << (log2_res_scale_abs_plus1 - 1)) * ++ (1 - 2 * res_scale_sign_flag); ++ } else { ++ lc->tu.res_scale_val = 0; ++ } ++ ++ ++ return 0; ++} ++#endif ++ ++static inline HEVCPredCmd * rpi_new_intra_cmd(HEVCRpiJob * const jb) ++{ ++ return jb->intra.cmds + jb->intra.n++; ++} ++ ++#define A0(x, y, U, L, UL, UR, DL) \ ++ [(x)+(y)*16] = (((U) ? AVAIL_U : 0) | ((L) ? AVAIL_L : 0) | ((UL) ? AVAIL_UL : 0) | ((UR) ? AVAIL_UR : 0) | ((DL) ? AVAIL_DL : 0)) ++ ++#define A1(x, y, U, L, UL, UR, DL) \ ++ A0((x) + 0, (y) + 0, (U), (L), (UL), (U), (L) ), A0((x) + 1, (y) + 0, (U), 1, (U), (UR), 0 ),\ ++ A0((x) + 0, (y) + 1, 1, (L), (L), 1, (DL)), A0((x) + 1, (y) + 1, 1, 1, 1, 0, 0 ) ++ ++#define A2(x, y, U, L, UL, UR, DL) \ ++ A1((x) + 0, (y) + 0, (U), (L), (UL), (U), (L) ), A1((x) + 2, (y) + 0, (U), 1, (U), (UR), 0 ),\ ++ A1((x) + 0, (y) + 2, 1, (L), (L), 1, (DL)), A1((x) + 2, (y) + 2, 1, 1, 1, 0, 0 ) ++ ++#define A3(x, y, U, L, UL, UR, DL) \ ++ A2((x) + 0, (y) + 0, (U), (L), (UL), (U), (L) ), A2((x) + 4, (y) + 0, (U), 1, (U), (UR), 0 ),\ ++ A2((x) + 0, (y) + 4, 1, (L), (L), 1, (DL)), A2((x) + 4, (y) + 4, 1, 1, 1, 0, 0 ) ++ ++#define A4(x, y, U, L, UL, UR, DL) \ ++ A3((x) + 0, (y) + 0, (U), (L), (UL), (U), (L) ), A3((x) + 8, (y) + 0, (U), 1, (U), (UR), 0 ),\ ++ A3((x) + 0, (y) + 8, 1, (L), (L), 1, (DL)), A3((x) + 8, (y) + 8, 1, 1, 1, 0, 0 ) ++ ++static const uint8_t tb_flags[16 * 16] = {A4(0, 0, 0, 0, 0, 0, 0)}; ++ ++unsigned int ff_hevc_rpi_tb_avail_flags( ++ const HEVCRpiContext * const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x, const unsigned int y, const unsigned int w, const unsigned int h) ++{ ++ const unsigned int ctb_mask = ~0U << s->ps.sps->log2_ctb_size; ++ const unsigned int tb_x = x & ~ctb_mask; ++ const unsigned int tb_y = y & ~ctb_mask; ++ const unsigned int ctb_avail = lc->ctb_avail; ++ ++ const uint8_t * const tb_f = tb_flags + (tb_x >> 2) + (tb_y >> 2) * 16; ++ ++ unsigned int f = (ctb_avail | tb_f[0]) & (AVAIL_L | AVAIL_U | AVAIL_UL); ++ ++ // This deals with both the U & L edges ++ if ((tb_x | tb_y) != 0 && (~f & (AVAIL_L | AVAIL_U)) == 0) ++ f |= AVAIL_UL; ++ ++ if (x + w < lc->end_of_ctb_x) ++ f |= (tb_y == 0 ? ctb_avail >> (AVAIL_S_U - AVAIL_S_UR) : tb_f[(w - 1) >> 2]) & AVAIL_UR; ++ else if (tb_y == 0) ++ f |= (ctb_avail & AVAIL_UR); ++#if AVAIL_S_U - AVAIL_S_UR < 0 ++#error Shift problem ++#endif ++ ++ // Never any D if Y beyond eoctb ++ if (y + h < lc->end_of_ctb_y) ++ f |= (tb_x == 0 ? ctb_avail << (AVAIL_S_DL - AVAIL_S_L) : tb_f[((h - 1) >> 2) * 16]) & AVAIL_DL; ++#if AVAIL_S_DL - AVAIL_S_L < 0 ++#error Shift problem ++#endif ++ ++// printf("(%#x, %#x): %dx%d ca=%02x, ful=%02x, ftr=%02x, fdl=%02x, eox=%#x, eoy=%#x\n", x, y, w, h, ++// lc->ctb_avail, tb_f[0], tb_f[(w - 1) >> 2], tb_f[((h - 1) >> 2) * 16], ++// lc->end_of_ctb_x, lc->end_of_ctb_y); ++ ++ return f; ++} ++ ++#undef A0 ++#undef A1 ++#undef A2 ++#undef A3 ++#undef A4 ++ ++static void do_intra_pred(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, int log2_trafo_size, int x0, int y0, int c_idx, ++ unsigned int avail) ++{ ++ // If rpi_enabled then sand - U & V done on U call ++ if (c_idx <= 1) ++ { ++ HEVCPredCmd *const cmd = rpi_new_intra_cmd(lc->jb0); ++ cmd->type = RPI_PRED_INTRA + c_idx; ++ cmd->size = log2_trafo_size; ++ cmd->avail = avail; ++ cmd->i_pred.x = x0; ++ cmd->i_pred.y = y0; ++ cmd->i_pred.mode = c_idx ? lc->tu.intra_pred_mode_c : lc->tu.intra_pred_mode; ++ ++// printf("(%#x, %#x) c_idx=%d, s=%d, a=%#x\n", x0, y0, c_idx, 1 << log2_trafo_size, avail); ++ } ++} ++ ++#define CBF_CB0_S 0 ++#define CBF_CB1_S 1 // CB1 must be CB0 + 1 ++#define CBF_CR0_S 2 ++#define CBF_CR1_S 3 ++ ++#define CBF_CB0 (1 << CBF_CB0_S) ++#define CBF_CR0 (1 << CBF_CR0_S) ++#define CBF_CB1 (1 << CBF_CB1_S) ++#define CBF_CR1 (1 << CBF_CR1_S) ++ ++// * Only good for chroma_idx == 1 ++static int hls_transform_unit(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_cb_size, const unsigned int log2_trafo_size, ++ const unsigned int blk_idx, const int cbf_luma, ++ const unsigned int cbf_chroma) ++{ ++ const unsigned int log2_trafo_size_c = FFMAX(2, log2_trafo_size - 1); ++ const unsigned int x0_c = x0 & ~7; ++ const unsigned int y0_c = y0 & ~7; ++ ++ enum ScanType scan_idx = SCAN_DIAG; ++ enum ScanType scan_idx_c = SCAN_DIAG; ++ ++ if (lc->cu.pred_mode == MODE_INTRA) ++ { ++ const unsigned int trafo_size = 1 << log2_trafo_size; ++ const unsigned int avail = ff_hevc_rpi_tb_avail_flags(s, lc, x0, y0, trafo_size, trafo_size); ++ ++ do_intra_pred(s, lc, log2_trafo_size, x0, y0, 0, avail); ++ ++ if (log2_trafo_size > 2) ++ do_intra_pred(s, lc, log2_trafo_size_c, x0_c, y0_c, 1, avail); ++ else if (blk_idx == 3) ++ do_intra_pred(s, lc, log2_trafo_size_c, x0_c, y0_c, 1, ++ ff_hevc_rpi_tb_avail_flags(s, lc, x0_c, y0_c, 8, 8)); ++ ++ if (log2_trafo_size < 4) { ++ if (lc->tu.intra_pred_mode >= 6 && ++ lc->tu.intra_pred_mode <= 14) { ++ scan_idx = SCAN_VERT; ++ } else if (lc->tu.intra_pred_mode >= 22 && ++ lc->tu.intra_pred_mode <= 30) { ++ scan_idx = SCAN_HORIZ; ++ } ++ ++ if (lc->tu.intra_pred_mode_c >= 6 && ++ lc->tu.intra_pred_mode_c <= 14) { ++ scan_idx_c = SCAN_VERT; ++ } else if (lc->tu.intra_pred_mode_c >= 22 && ++ lc->tu.intra_pred_mode_c <= 30) { ++ scan_idx_c = SCAN_HORIZ; ++ } ++ } ++ } ++ ++ if (!cbf_luma && cbf_chroma == 0) ++ return 0; ++ ++ if (lc->tu.is_cu_qp_delta_wanted) ++ { ++ const int qp_delta = ff_hevc_rpi_cu_qp_delta(lc); ++ const unsigned int cb_mask = ~0U << log2_cb_size; ++ ++ if (qp_delta < -(26 + (s->ps.sps->qp_bd_offset >> 1)) || ++ qp_delta > (25 + (s->ps.sps->qp_bd_offset >> 1))) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "The cu_qp_delta %d is outside the valid range " ++ "[%d, %d].\n", ++ qp_delta, ++ -(26 + (s->ps.sps->qp_bd_offset >> 1)), ++ (25 + (s->ps.sps->qp_bd_offset >> 1))); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ lc->tu.is_cu_qp_delta_wanted = 0; ++ lc->tu.cu_qp_delta = qp_delta; ++ ff_hevc_rpi_set_qPy(s, lc, x0 & cb_mask, y0 & cb_mask); ++ } ++ ++ // * Not main profile & untested due to no conform streams ++ if (lc->tu.cu_chroma_qp_offset_wanted && cbf_chroma && ++ !lc->cu.cu_transquant_bypass_flag) { ++ int cu_chroma_qp_offset_flag = ff_hevc_rpi_cu_chroma_qp_offset_flag(lc); ++ if (cu_chroma_qp_offset_flag) { ++ int cu_chroma_qp_offset_idx = 0; ++ if (s->ps.pps->chroma_qp_offset_list_len_minus1 > 0) { ++ cu_chroma_qp_offset_idx = ff_hevc_rpi_cu_chroma_qp_offset_idx(s, lc); ++ } ++ lc->tu.qp_divmod6[1] += s->ps.pps->cb_qp_offset_list[cu_chroma_qp_offset_idx]; ++ lc->tu.qp_divmod6[2] += s->ps.pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; ++ } ++ lc->tu.cu_chroma_qp_offset_wanted = 0; ++ } ++ ++ if (cbf_luma) ++ ff_hevc_rpi_hls_residual_coding(s, lc, x0, y0, log2_trafo_size, scan_idx, 0); ++ ++ if (log2_trafo_size > 2 || blk_idx == 3) ++ { ++ if ((cbf_chroma & CBF_CB0) != 0) ++ ff_hevc_rpi_hls_residual_coding(s, lc, x0_c, y0_c, ++ log2_trafo_size_c, scan_idx_c, 1); ++ if ((cbf_chroma & CBF_CR0) != 0) ++ ff_hevc_rpi_hls_residual_coding(s, lc, x0_c, y0_c, ++ log2_trafo_size_c, scan_idx_c, 2); ++ } ++ ++ return 0; ++} ++ ++static inline void set_deblocking_bypass(const HEVCRpiContext * const s, const int x0, const int y0, const int log2_cb_size) ++{ ++ set_bits(s->is_pcm + (y0 >> 3) * s->ps.sps->pcm_width, x0 >> 3, s->ps.sps->pcm_width, log2_cb_size - 3); ++} ++ ++ ++static int hls_transform_tree(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_trafo_size, ++ const unsigned int trafo_depth, const unsigned int blk_idx, ++ const unsigned int cbf_c0) ++{ ++ // When trafo_size == 2 hls_transform_unit uses c0 so put in c1 ++ unsigned int cbf_c1 = cbf_c0; ++ int split_transform_flag; ++ int ret; ++ ++ if (lc->cu.intra_split_flag) { ++ if (trafo_depth == 1) { ++ lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; ++ if (ctx_cfmt(s) == 3) { ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[blk_idx]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[blk_idx]; ++ } else { ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; ++ } ++ } ++ } else { ++ lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[0]; ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; ++ } ++ ++ if (log2_trafo_size <= s->ps.sps->log2_max_trafo_size && ++ log2_trafo_size > s->ps.sps->log2_min_tb_size && ++ trafo_depth < lc->cu.max_trafo_depth && ++ !(lc->cu.intra_split_flag && trafo_depth == 0)) ++ { ++ split_transform_flag = ff_hevc_rpi_split_transform_flag_decode(lc, log2_trafo_size); ++ } else { ++ int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 && ++ lc->cu.pred_mode == MODE_INTER && ++ lc->cu.part_mode != PART_2Nx2N && ++ trafo_depth == 0; ++ ++ split_transform_flag = log2_trafo_size > s->ps.sps->log2_max_trafo_size || ++ (lc->cu.intra_split_flag && trafo_depth == 0) || ++ inter_split; ++ } ++ ++ if (log2_trafo_size > 2 || ctx_cfmt(s) == 3) ++ { ++ const int wants_c1 = ctx_cfmt(s) == 2 && (!split_transform_flag || log2_trafo_size == 3); ++ cbf_c1 = 0; ++ ++ if ((cbf_c0 & CBF_CB0) != 0) ++ { ++ cbf_c1 = ff_hevc_rpi_cbf_cb_cr_decode(lc, trafo_depth) << CBF_CB0_S; ++ if (wants_c1) ++ cbf_c1 |= ff_hevc_rpi_cbf_cb_cr_decode(lc, trafo_depth) << CBF_CB1_S; ++ } ++ ++ if ((cbf_c0 & CBF_CR0) != 0) ++ { ++ cbf_c1 |= ff_hevc_rpi_cbf_cb_cr_decode(lc, trafo_depth) << CBF_CR0_S; ++ if (wants_c1) ++ cbf_c1 |= ff_hevc_rpi_cbf_cb_cr_decode(lc, trafo_depth) << CBF_CR1_S; ++ } ++ } ++ ++ if (split_transform_flag) { ++ const int trafo_size_split = 1 << (log2_trafo_size - 1); ++ const int x1 = x0 + trafo_size_split; ++ const int y1 = y0 + trafo_size_split; ++ ++#define SUBDIVIDE(x, y, idx) \ ++do { \ ++ ret = hls_transform_tree(s, lc, x, y, \ ++ log2_trafo_size - 1, trafo_depth + 1, idx, \ ++ cbf_c1); \ ++ if (ret < 0) \ ++ return ret; \ ++} while (0) ++ ++ SUBDIVIDE(x0, y0, 0); ++ SUBDIVIDE(x1, y0, 1); ++ SUBDIVIDE(x0, y1, 2); ++ SUBDIVIDE(x1, y1, 3); ++ ++#undef SUBDIVIDE ++ } else { ++ // If trafo_size == 2 then we should have cbf_c == 0 here but as we can't have ++ // trafo_size == 2 with depth == 0 the issue is moot ++ const int cbf_luma = ((lc->cu.pred_mode != MODE_INTRA && trafo_depth == 0 && cbf_c1 == 0) || ++ ff_hevc_rpi_cbf_luma_decode(lc, trafo_depth)); ++ ++ ret = hls_transform_unit(s, lc, x0, y0, ++ log2_trafo_size + trafo_depth, log2_trafo_size, ++ blk_idx, cbf_luma, cbf_c1); ++ if (ret < 0) ++ return ret; ++ ++ if (!s->sh.disable_deblocking_filter_flag) { ++ ff_hevc_rpi_deblocking_boundary_strengths(s, lc, x0, y0, log2_trafo_size, cbf_luma); ++ } ++ } ++ return 0; ++} ++ ++ ++static int pcm_extract(const HEVCRpiContext * const s, const uint8_t * pcm, const int length, const int x0, const int y0, const int cb_size) ++{ ++ GetBitContext gb; ++ int ret; ++ ++ ret = init_get_bits(&gb, pcm, length); ++ if (ret < 0) ++ return ret; ++ ++ s->hevcdsp.put_pcm(av_rpi_sand_frame_pos_y(s->frame, x0, y0), ++ frame_stride1(s->frame, 0), ++ cb_size, cb_size, &gb, s->ps.sps->pcm.bit_depth); ++ ++ s->hevcdsp.put_pcm_c(av_rpi_sand_frame_pos_c(s->frame, x0 >> ctx_hshift(s, 1), y0 >> ctx_vshift(s, 1)), ++ s->frame->linesize[1], ++ cb_size >> ctx_hshift(s, 1), ++ cb_size >> ctx_vshift(s, 1), ++ &gb, s->ps.sps->pcm.bit_depth_chroma); ++ ++ return 0; ++} ++ ++ ++// x * 2^(y*2) ++static inline unsigned int xyexp2(const unsigned int x, const unsigned int y) ++{ ++ return x << (y * 2); ++} ++ ++static int hls_pcm_sample(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const int x0, const int y0, unsigned int log2_cb_size) ++{ ++ // Length in bits ++ const unsigned int length = xyexp2(s->ps.sps->pcm.bit_depth, log2_cb_size) + ++ xyexp2(s->ps.sps->pcm.bit_depth_chroma, log2_cb_size - ctx_vshift(s, 1)) + ++ xyexp2(s->ps.sps->pcm.bit_depth_chroma, log2_cb_size - ctx_vshift(s, 2)); ++ ++ const uint8_t * const pcm = ff_hevc_rpi_cabac_skip_bytes(&lc->cc, (length + 7) >> 3); ++ ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_rpi_deblocking_boundary_strengths(s, lc, x0, y0, log2_cb_size, 0); ++ ++ // Copy coeffs ++ { ++ const int blen = (length + 7) >> 3; ++ // Round allocated bytes up to nearest 32 to avoid alignment confusion ++ // Allocation is in int16_t s ++ // As we are only using 1 byte per sample and the coeff buffer allows 2 per ++ // sample this rounding doesn't affect the total size we need to allocate for ++ // the coeff buffer ++ int16_t * const coeffs = rpi_alloc_coeff_buf(lc->jb0, 0, ((blen + 31) & ~31) >> 1); ++ memcpy(coeffs, pcm, blen); ++ ++ // Our coeff stash assumes that any partially allocated 64byte lump ++ // is zeroed so make that true. ++ { ++ uint8_t * const eopcm = (uint8_t *)coeffs + blen; ++ if ((-(intptr_t)eopcm & 63) != 0) ++ memset(eopcm, 0, -(intptr_t)eopcm & 63); ++ } ++ ++ // Add command ++ { ++ HEVCPredCmd *const cmd = rpi_new_intra_cmd(lc->jb0); ++ cmd->type = RPI_PRED_I_PCM; ++ cmd->size = log2_cb_size; ++ cmd->i_pcm.src = coeffs; ++ cmd->i_pcm.x = x0; ++ cmd->i_pcm.y = y0; ++ cmd->i_pcm.src_len = length; ++ } ++ return 0; ++ } ++} ++ ++ ++static void hevc_await_progress(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const HEVCRpiFrame * const ref, ++ const MvXY xy, const int y0, const int height) ++{ ++ if (s->threads_type != 0) { ++ const int y = FFMAX(0, (MV_Y(xy) >> 2) + y0 + height + 9); ++ ++ // Progress has to be attached to current job as the actual wait ++ // is in worker_core which can't use lc ++ int16_t *const pr = lc->jb0->progress_req + ref->dpb_no; ++ if (*pr < y) { ++ *pr = y; ++ } ++ } ++} ++ ++static void hevc_luma_mv_mvp_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const int x0, const int y0, const int nPbW, ++ const int nPbH, ++ HEVCRpiMvField * const mv) ++{ ++ enum InterPredIdc inter_pred_idc = PRED_L0; ++ int mvp_flag; ++ const unsigned int avail = ff_hevc_rpi_tb_avail_flags(s, lc, x0, y0, nPbW, nPbH); ++ ++ mv->pred_flag = 0; ++ if (s->sh.slice_type == HEVC_SLICE_B) ++ inter_pred_idc = ff_hevc_rpi_inter_pred_idc_decode(lc, nPbW, nPbH); ++ ++ if (inter_pred_idc != PRED_L1) { ++ MvXY mvd; ++ ++ if (s->sh.nb_refs[L0]) ++ mv->ref_idx[0]= ff_hevc_rpi_ref_idx_lx_decode(lc, s->sh.nb_refs[L0]); ++ ++ mv->pred_flag = PF_L0; ++ mvd = ff_hevc_rpi_hls_mvd_coding(lc); ++ mvp_flag = ff_hevc_rpi_mvp_lx_flag_decode(lc); ++ ff_hevc_rpi_luma_mv_mvp_mode(s, lc, x0, y0, nPbW, nPbH, avail, ++ mv, mvp_flag, 0); ++ mv->xy[0] = mvxy_add(mv->xy[0], mvd); ++ } ++ ++ if (inter_pred_idc != PRED_L0) { ++ MvXY mvd = 0; ++ ++ if (s->sh.nb_refs[L1]) ++ mv->ref_idx[1] = ff_hevc_rpi_ref_idx_lx_decode(lc, s->sh.nb_refs[L1]); ++ ++ if (s->sh.mvd_l1_zero_flag != 1 || inter_pred_idc != PRED_BI) ++ mvd = ff_hevc_rpi_hls_mvd_coding(lc); ++ ++ mv->pred_flag += PF_L1; ++ mvp_flag = ff_hevc_rpi_mvp_lx_flag_decode(lc); ++ ff_hevc_rpi_luma_mv_mvp_mode(s, lc, x0, y0, nPbW, nPbH, avail, ++ mv, mvp_flag, 1); ++ mv->xy[1] = mvxy_add(mv->xy[1], mvd); ++ } ++} ++ ++ ++static HEVCRpiInterPredQ * ++rpi_nxt_pred(HEVCRpiInterPredEnv * const ipe, const unsigned int load_val, const uint32_t fn) ++{ ++ HEVCRpiInterPredQ * yp = NULL; ++ HEVCRpiInterPredQ * ypt = ipe->q + ipe->curr; ++ const unsigned int max_fill = ipe->max_fill; ++ unsigned int load = UINT_MAX; ++ ++ for (unsigned int i = 0; i != ipe->n_grp; ++i, ++ypt) { ++ // We will always have enough room between the Qs but if we are ++ // running critically low due to poor scheduling then use fill size ++ // rather than load to determine QPU. This has obvious dire ++ // performance implications but (a) it is better than crashing ++ // and (b) it should (almost) never happen ++ const unsigned int tfill = (char *)ypt->qpu_mc_curr - (char *)ypt->qpu_mc_base; ++ const unsigned int tload = tfill > max_fill ? tfill + 0x1000000 : ypt->load; ++ ++ if (tload < load) ++ { ++ yp = ypt; ++ load = tload; ++ } ++ } ++ ++ yp->load += load_val; ++ ipe->used_grp = 1; ++ qpu_mc_link_set(yp->qpu_mc_curr, fn); ++ ++ return yp; ++} ++ ++ ++static void rpi_inter_pred_sync(HEVCRpiInterPredEnv * const ipe) ++{ ++ for (unsigned int i = 0; i != ipe->n; ++i) { ++ HEVCRpiInterPredQ * const q = ipe->q + i; ++ const unsigned int qfill = (char *)q->qpu_mc_curr - (char *)q->qpu_mc_base; ++ ++ qpu_mc_link_set(q->qpu_mc_curr, q->code_sync); ++ q->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(&q->qpu_mc_curr->sync + 1); ++ q->load = (qfill >> 7); // Have a mild preference for emptier Qs to balance memory usage ++ } ++} ++ ++// Returns 0 on success ++// We no longer check for Q fullness as wew have emergncy code in ctu alloc ++// * However it might be an idea to have some means of spotting that we've used it ++static int rpi_inter_pred_next_ctu(HEVCRpiInterPredEnv * const ipe) ++{ ++ if (!ipe->used_grp) ++ return 0; ++ ++ if ((ipe->curr += ipe->n_grp) >= ipe->n) ++ { ++ ipe->curr = 0; ++ rpi_inter_pred_sync(ipe); ++ } ++ ipe->used = 1; ++ ipe->used_grp = 0; ++ ++ return 0; ++} ++ ++static void rpi_inter_pred_reset(HEVCRpiInterPredEnv * const ipe) ++{ ++ unsigned int i; ++ ++ ipe->curr = 0; ++ ipe->used = 0; ++ ipe->used_grp = 0; ++ for (i = 0; i != ipe->n; ++i) { ++ HEVCRpiInterPredQ * const q = ipe->q + i; ++ q->qpu_mc_curr = q->qpu_mc_base; ++ q->load = 0; ++ q->last_l0 = NULL; ++ q->last_l1 = NULL; ++ } ++} ++ ++static int rpi_inter_pred_alloc(HEVCRpiInterPredEnv * const ipe, ++ const unsigned int n_max, const unsigned int n_grp, ++ const unsigned int total_size, const unsigned int min_gap) ++{ ++ int rv; ++ ++ memset(ipe, 0, sizeof(*ipe)); ++ if ((ipe->q = av_mallocz(n_max * sizeof(*ipe->q))) == NULL) ++ return AVERROR(ENOMEM); ++ ++ ipe->n_grp = n_grp; ++ ipe->min_gap = min_gap; ++ ++ if ((rv = gpu_malloc_cached(total_size, &ipe->gptr)) != 0) ++ av_freep(&ipe->q); ++ return rv; ++} ++ ++ ++#if RPI_QPU_EMU_Y ++#define get_mc_address_y(f) ((f)->data[0]) ++#else ++#define get_mc_address_y(f) get_vc_address_y(f) ++#endif ++#if RPI_QPU_EMU_C ++#define get_mc_address_u(f) ((f)->data[1]) ++#else ++#define get_mc_address_u(f) get_vc_address_u(f) ++#endif ++ ++static inline uint32_t pack_wo_p(const int off, const int mul) ++{ ++ return PACK2(off * 2 + 1, mul); ++} ++ ++static inline uint32_t pack_wo_b(const int off0, const int off1, const int mul) ++{ ++ return PACK2(off0 + off1 + 1, mul); ++} ++ ++ ++static void ++rpi_pred_y(const HEVCRpiContext *const s, HEVCRpiJob * const jb, ++ const int x0, const int y0, ++ const int nPbW, const int nPbH, ++ const MvXY mv_xy, ++ const int weight_mul, ++ const int weight_offset, ++ AVFrame *const src_frame) ++{ ++ const unsigned int y_off = av_rpi_sand_frame_off_y(s->frame, x0, y0); ++ const unsigned int mx = MV_X(mv_xy) & 3; ++ const unsigned int my = MV_Y(mv_xy) & 3; ++ const unsigned int my_mx = (my << 8) | mx; ++ const uint32_t my2_mx2_my_mx = (my_mx << 16) | my_mx; ++ const qpu_mc_src_addr_t src_vc_address_y = get_mc_address_y(src_frame); ++ qpu_mc_dst_addr_t dst_addr = get_mc_address_y(s->frame) + y_off; ++ const uint32_t wo = pack_wo_p(weight_offset, weight_mul); ++ HEVCRpiInterPredEnv * const ipe = &jb->luma_ip; ++ const unsigned int xshl = av_rpi_sand_frame_xshl(s->frame); ++ ++ if (my_mx == 0) ++ { ++ const int x1 = x0 + (MV_X(mv_xy) >> 2); ++ const int y1 = y0 + (MV_Y(mv_xy) >> 2); ++ const int bh = nPbH; ++ ++ for (int start_x = 0; start_x < nPbW; start_x += 16) ++ { ++ const int bw = FFMIN(nPbW - start_x, 16); ++ HEVCRpiInterPredQ *const yp = rpi_nxt_pred(ipe, bh, s->qpu.y_p00); ++ qpu_mc_src_t *const src1 = yp->last_l0; ++ qpu_mc_pred_y_p00_t *const cmd_y = &yp->qpu_mc_curr->y.p00; ++ ++#if RPI_TSTATS ++ { ++ HEVCRpiStats *const ts = (HEVCRpiStats *)&s->tstats; ++ ++ts->y_pred1_x0y0; ++ ++ if (nPbW > 8) ++ ++ts->y_pred1_wgt8; ++ else ++ ++ts->y_pred1_wle8; ++ ++ if (nPbH > 16) ++ ++ts->y_pred1_hgt16; ++ else ++ ++ts->y_pred1_hle16; ++ } ++#endif ++ ++ src1->x = x1 + start_x; ++ src1->y = y1; ++ src1->base = src_vc_address_y; ++ cmd_y->w = bw; ++ cmd_y->h = bh; ++ cmd_y->wo1 = wo; ++ cmd_y->dst_addr = dst_addr + (start_x << xshl); ++ yp->last_l0 = &cmd_y->next_src1; ++ yp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(cmd_y + 1); ++ } ++ } ++ else ++ { ++ const int x1_m3 = x0 + (MV_X(mv_xy) >> 2) - 3; ++ const int y1_m3 = y0 + (MV_Y(mv_xy) >> 2) - 3; ++ const unsigned int bh = nPbH; ++ int start_x = 0; ++ ++#if 1 ++ // As Y-pred operates on two independant 8-wide src blocks we can merge ++ // this pred with the previous one if it the previous one is 8 pel wide, ++ // the same height as the current block, immediately to the left of our ++ // current dest block and mono-pred. ++ ++ qpu_mc_pred_y_p_t *const last_y8_p = jb->last_y8_p; ++ if (last_y8_p != NULL && last_y8_p->h == bh && last_y8_p->dst_addr + (8 << xshl) == dst_addr) ++ { ++ const int bw = FFMIN(nPbW, 8); ++ qpu_mc_src_t *const last_y8_src2 = jb->last_y8_l1; ++ ++ last_y8_src2->x = x1_m3; ++ last_y8_src2->y = y1_m3; ++ last_y8_src2->base = src_vc_address_y; ++ last_y8_p->w += bw; ++ last_y8_p->mymx21 = PACK2(my2_mx2_my_mx, last_y8_p->mymx21); ++ last_y8_p->wo2 = wo; ++ ++ jb->last_y8_p = NULL; ++ jb->last_y8_l1 = NULL; ++ start_x = bw; ++#if RPI_TSTATS ++ ++((HEVCRpiStats *)&s->tstats)->y_pred1_y8_merge; ++#endif ++ } ++#endif ++ ++ for (; start_x < nPbW; start_x += 16) ++ { ++ const int bw = FFMIN(nPbW - start_x, 16); ++ HEVCRpiInterPredQ *const yp = rpi_nxt_pred(ipe, bh + 7, s->qpu.y_pxx); ++ qpu_mc_src_t *const src1 = yp->last_l0; ++ qpu_mc_src_t *const src2 = yp->last_l1; ++ qpu_mc_pred_y_p_t *const cmd_y = &yp->qpu_mc_curr->y.p; ++#if RPI_TSTATS ++ { ++ HEVCRpiStats *const ts = (HEVCRpiStats *)&s->tstats; ++ if (mx == 0 && my == 0) ++ ++ts->y_pred1_x0y0; ++ else if (mx == 0) ++ ++ts->y_pred1_x0; ++ else if (my == 0) ++ ++ts->y_pred1_y0; ++ else ++ ++ts->y_pred1_xy; ++ ++ if (nPbW > 8) ++ ++ts->y_pred1_wgt8; ++ else ++ ++ts->y_pred1_wle8; ++ ++ if (nPbH > 16) ++ ++ts->y_pred1_hgt16; ++ else ++ ++ts->y_pred1_hle16; ++ } ++#endif ++ src1->x = x1_m3 + start_x; ++ src1->y = y1_m3; ++ src1->base = src_vc_address_y; ++ if (bw <= 8) ++ { ++ src2->x = MC_DUMMY_X; ++ src2->y = MC_DUMMY_Y; ++#if RPI_QPU_EMU_Y ++ src2->base = s->qpu_dummy_frame_emu; ++#else ++ src2->base = s->qpu_dummy_frame_qpu; ++#endif ++ } ++ else ++ { ++ src2->x = x1_m3 + start_x + 8; ++ src2->y = y1_m3; ++ src2->base = src_vc_address_y; ++ } ++ cmd_y->w = bw; ++ cmd_y->h = bh; ++ cmd_y->mymx21 = my2_mx2_my_mx; ++ cmd_y->wo1 = wo; ++ cmd_y->wo2 = wo; ++ cmd_y->dst_addr = dst_addr + (start_x << xshl); ++ yp->last_l0 = &cmd_y->next_src1; ++ yp->last_l1 = &cmd_y->next_src2; ++ yp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(cmd_y + 1); ++ ++ if (bw == 8) { ++ jb->last_y8_l1 = src2; ++ jb->last_y8_p = cmd_y; ++ } ++ } ++ } ++} ++ ++static void ++rpi_pred_y_b(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const int x0, const int y0, ++ const int nPbW, const int nPbH, ++ const struct HEVCRpiMvField *const mv_field, ++ const AVFrame *const src_frame, ++ const AVFrame *const src_frame2) ++{ ++ const unsigned int y_off = av_rpi_sand_frame_off_y(s->frame, x0, y0); ++ const MvXY mv = mv_field->xy[0]; ++ const MvXY mv2 = mv_field->xy[1]; ++ ++ const unsigned int mx = MV_X(mv) & 3; ++ const unsigned int my = MV_Y(mv) & 3; ++ const unsigned int my_mx = (my<<8) | mx; ++ const unsigned int mx2 = MV_X(mv2) & 3; ++ const unsigned int my2 = MV_Y(mv2) & 3; ++ const unsigned int my2_mx2 = (my2<<8) | mx2; ++ const uint32_t my2_mx2_my_mx = (my2_mx2 << 16) | my_mx; ++ const unsigned int ref_idx0 = mv_field->ref_idx[0]; ++ const unsigned int ref_idx1 = mv_field->ref_idx[1]; ++ const uint32_t wo1 = pack_wo_b(s->sh.luma_offset_l0[ref_idx0], s->sh.luma_offset_l1[ref_idx1], s->sh.luma_weight_l0[ref_idx0]); ++ const uint32_t wo2 = pack_wo_b(s->sh.luma_offset_l0[ref_idx0], s->sh.luma_offset_l1[ref_idx1], s->sh.luma_weight_l1[ref_idx1]); ++ ++ const unsigned int xshl = av_rpi_sand_frame_xshl(s->frame); ++ qpu_mc_dst_addr_t dst = get_mc_address_y(s->frame) + y_off; ++ const qpu_mc_src_addr_t src1_base = get_mc_address_y(src_frame); ++ const qpu_mc_src_addr_t src2_base = get_mc_address_y(src_frame2); ++ HEVCRpiInterPredEnv * const ipe = &jb->luma_ip; ++ ++ if (my2_mx2_my_mx == 0) ++ { ++ const int x1 = x0 + (MV_X(mv) >> 2); ++ const int y1 = y0 + (MV_Y(mv) >> 2); ++ const int x2 = x0 + (MV_X(mv2) >> 2); ++ const int y2 = y0 + (MV_Y(mv2) >> 2); ++ const int bh = nPbH; ++ ++ // Can do chunks a full 16 wide if we don't want the H filter ++ for (int start_x=0; start_x < nPbW; start_x += 16) ++ { ++ HEVCRpiInterPredQ *const yp = rpi_nxt_pred(ipe, bh, s->qpu.y_b00); ++ qpu_mc_src_t *const src1 = yp->last_l0; ++ qpu_mc_src_t *const src2 = yp->last_l1; ++ qpu_mc_pred_y_p_t *const cmd_y = &yp->qpu_mc_curr->y.p; ++#if RPI_TSTATS ++ { ++ HEVCRpiStats *const ts = (HEVCRpiStats *)&s->tstats; ++ ++ts->y_pred2_x0y0; ++ ++ if (nPbH > 16) ++ ++ts->y_pred2_hgt16; ++ else ++ ++ts->y_pred2_hle16; ++ } ++#endif ++ src1->x = x1 + start_x; ++ src1->y = y1; ++ src1->base = src1_base; ++ src2->x = x2 + start_x; ++ src2->y = y2; ++ src2->base = src2_base; ++ cmd_y->w = FFMIN(nPbW - start_x, 16); ++ cmd_y->h = bh; ++ cmd_y->mymx21 = 0; ++ cmd_y->wo1 = wo1; ++ cmd_y->wo2 = wo2; ++ cmd_y->dst_addr = dst + (start_x << xshl); ++ yp->last_l0 = &cmd_y->next_src1; ++ yp->last_l1 = &cmd_y->next_src2; ++ yp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(cmd_y + 1); ++ } ++ } ++ else ++ { ++ // Filter requires a run-up of 3 ++ const int x1 = x0 + (MV_X(mv) >> 2) - 3; ++ const int y1 = y0 + (MV_Y(mv) >> 2) - 3; ++ const int x2 = x0 + (MV_X(mv2) >> 2) - 3; ++ const int y2 = y0 + (MV_Y(mv2) >> 2) - 3; ++ const int bh = nPbH; ++ ++ for (int start_x=0; start_x < nPbW; start_x += 8) ++ { // B blocks work 8 at a time ++ // B weights aren't doubled as the QPU code does the same ++ // amount of work as it does for P ++ HEVCRpiInterPredQ *const yp = rpi_nxt_pred(ipe, bh + 7, s->qpu.y_bxx); ++ qpu_mc_src_t *const src1 = yp->last_l0; ++ qpu_mc_src_t *const src2 = yp->last_l1; ++ qpu_mc_pred_y_p_t *const cmd_y = &yp->qpu_mc_curr->y.p; ++#if RPI_TSTATS ++ { ++ HEVCRpiStats *const ts = (HEVCRpiStats *)&s->tstats; ++ const unsigned int mmx = mx | mx2; ++ const unsigned int mmy = my | my2; ++ if (mmx == 0 && mmy == 0) ++ ++ts->y_pred2_x0y0; ++ else if (mmx == 0) ++ ++ts->y_pred2_x0; ++ else if (mmy == 0) ++ ++ts->y_pred2_y0; ++ else ++ ++ts->y_pred2_xy; ++ ++ if (nPbH > 16) ++ ++ts->y_pred2_hgt16; ++ else ++ ++ts->y_pred2_hle16; ++ } ++#endif ++ src1->x = x1 + start_x; ++ src1->y = y1; ++ src1->base = src1_base; ++ src2->x = x2 + start_x; ++ src2->y = y2; ++ src2->base = src2_base; ++ cmd_y->w = FFMIN(nPbW - start_x, 8); ++ cmd_y->h = bh; ++ cmd_y->mymx21 = my2_mx2_my_mx; ++ cmd_y->wo1 = wo1; ++ cmd_y->wo2 = wo2; ++ cmd_y->dst_addr = dst + (start_x << xshl); ++ yp->last_l0 = &cmd_y->next_src1; ++ yp->last_l1 = &cmd_y->next_src2; ++ yp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(cmd_y + 1); ++ } ++ } ++} ++ ++// h/v shifts fixed at one as that is all the qasm copes with ++static void ++rpi_pred_c(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const unsigned int lx, const int x0_c, const int y0_c, ++ const int nPbW_c, const int nPbH_c, ++ const MvXY mv, ++ const int16_t * const c_weights, ++ const int16_t * const c_offsets, ++ AVFrame * const src_frame) ++{ ++ const unsigned int c_off = av_rpi_sand_frame_off_c(s->frame, x0_c, y0_c); ++ const int hshift = 1; // = s->ps.sps->hshift[1]; ++ const int vshift = 1; // = s->ps.sps->vshift[1]; ++ ++ const int x1_c = x0_c + (MV_X(mv) >> (2 + hshift)) - 1; ++ const int y1_c = y0_c + (MV_Y(mv) >> (2 + hshift)) - 1; ++ const qpu_mc_src_addr_t src_base_u = get_mc_address_u(src_frame); ++ const uint32_t x_coeffs = rpi_filter_coefs[av_mod_uintp2(MV_X(mv), 2 + hshift) << (1 - hshift)]; ++ const uint32_t y_coeffs = rpi_filter_coefs[av_mod_uintp2(MV_Y(mv), 2 + vshift) << (1 - vshift)]; ++ const uint32_t wo_u = pack_wo_p(c_offsets[0], c_weights[0]); ++ const uint32_t wo_v = pack_wo_p(c_offsets[1], c_weights[1]); ++ qpu_mc_dst_addr_t dst_base_u = get_mc_address_u(s->frame) + c_off; ++ HEVCRpiInterPredEnv * const ipe = &jb->chroma_ip; ++ const unsigned int xshl = av_rpi_sand_frame_xshl(s->frame) + 1; ++ const unsigned int bh = nPbH_c; ++ const uint32_t qfn = lx == 0 ? s->qpu.c_pxx : s->qpu.c_pxx_l1; ++ ++ for(int start_x=0; start_x < nPbW_c; start_x+=RPI_CHROMA_BLOCK_WIDTH) ++ { ++ HEVCRpiInterPredQ * const cp = rpi_nxt_pred(ipe, bh + 3, qfn); ++ qpu_mc_pred_c_p_t * const cmd_c = &cp->qpu_mc_curr->c.p; ++ qpu_mc_src_t ** const plast_lx = (lx == 0) ? &cp->last_l0 : &cp->last_l1; ++ qpu_mc_src_t * const last_lx = *plast_lx; ++ const int bw = FFMIN(nPbW_c-start_x, RPI_CHROMA_BLOCK_WIDTH); ++ ++ last_lx->x = x1_c + start_x; ++ last_lx->y = y1_c; ++ last_lx->base = src_base_u; ++ cmd_c->h = bh; ++ cmd_c->w = bw; ++ cmd_c->coeffs_x = x_coeffs; ++ cmd_c->coeffs_y = y_coeffs; ++ cmd_c->wo_u = wo_u; ++ cmd_c->wo_v = wo_v; ++ cmd_c->dst_addr_c = dst_base_u + (start_x << xshl); ++ *plast_lx = &cmd_c->next_src; ++ cp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(cmd_c + 1); ++ } ++ return; ++} ++ ++// h/v shifts fixed at one as that is all the qasm copes with ++static void ++rpi_pred_c_b(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const int x0_c, const int y0_c, ++ const int nPbW_c, const int nPbH_c, ++ const struct HEVCRpiMvField * const mv_field, ++ const int16_t * const c_weights, ++ const int16_t * const c_offsets, ++ const int16_t * const c_weights2, ++ const int16_t * const c_offsets2, ++ AVFrame * const src_frame, ++ AVFrame * const src_frame2) ++{ ++ const unsigned int c_off = av_rpi_sand_frame_off_c(s->frame, x0_c, y0_c); ++ const int hshift = 1; // s->ps.sps->hshift[1]; ++ const int vshift = 1; // s->ps.sps->vshift[1]; ++ const MvXY mv = mv_field->xy[0]; ++ const MvXY mv2 = mv_field->xy[1]; ++ ++ const unsigned int mx = av_mod_uintp2(MV_X(mv), 2 + hshift); ++ const unsigned int my = av_mod_uintp2(MV_Y(mv), 2 + vshift); ++ const uint32_t coefs0_x = rpi_filter_coefs[mx << (1 - hshift)]; ++ const uint32_t coefs0_y = rpi_filter_coefs[my << (1 - vshift)]; // Fractional part of motion vector ++ const int x1_c = x0_c + (MV_X(mv) >> (2 + hshift)) - 1; ++ const int y1_c = y0_c + (MV_Y(mv) >> (2 + hshift)) - 1; ++ ++ const unsigned int mx2 = av_mod_uintp2(MV_X(mv2), 2 + hshift); ++ const unsigned int my2 = av_mod_uintp2(MV_Y(mv2), 2 + vshift); ++ const uint32_t coefs1_x = rpi_filter_coefs[mx2 << (1 - hshift)]; ++ const uint32_t coefs1_y = rpi_filter_coefs[my2 << (1 - vshift)]; // Fractional part of motion vector ++ ++ const int x2_c = x0_c + (MV_X(mv2) >> (2 + hshift)) - 1; ++ const int y2_c = y0_c + (MV_Y(mv2) >> (2 + hshift)) - 1; ++ ++ const uint32_t wo_u2 = pack_wo_b(c_offsets[0], c_offsets2[0], c_weights2[0]); ++ const uint32_t wo_v2 = pack_wo_b(c_offsets[1], c_offsets2[1], c_weights2[1]); ++ ++ const qpu_mc_dst_addr_t dst_base_u = get_mc_address_u(s->frame) + c_off; ++ const qpu_mc_src_addr_t src1_base = get_mc_address_u(src_frame); ++ const qpu_mc_src_addr_t src2_base = get_mc_address_u(src_frame2); ++ HEVCRpiInterPredEnv * const ipe = &jb->chroma_ip; ++ const unsigned int xshl = av_rpi_sand_frame_xshl(s->frame) + 1; ++ const unsigned int bh = nPbH_c; ++ ++ for (int start_x=0; start_x < nPbW_c; start_x += RPI_CHROMA_BLOCK_WIDTH) ++ { ++ const unsigned int bw = FFMIN(nPbW_c-start_x, RPI_CHROMA_BLOCK_WIDTH); ++ ++ HEVCRpiInterPredQ * const cp = rpi_nxt_pred(ipe, bh * 2 + 3, s->qpu.c_bxx); ++ qpu_mc_pred_c_b_t * const u = &cp->qpu_mc_curr->c.b; ++ qpu_mc_src_t * const src_l0 = cp->last_l0; ++ qpu_mc_src_t * const src_l1 = cp->last_l1; ++ ++ src_l0->x = x1_c + start_x; ++ src_l0->y = y1_c; ++ src_l0->base = src1_base; ++ src_l1->x = x2_c + start_x; ++ src_l1->y = y2_c; ++ src_l1->base = src2_base; ++ ++ u[0].h = bh; ++ u[0].w = bw; ++ u[0].coeffs_x1 = coefs0_x; ++ u[0].coeffs_y1 = coefs0_y; ++ u[0].weight_u1 = c_weights[0]; // Weight L0 U ++ u[0].weight_v1 = c_weights[1]; // Weight L0 V ++ u[0].coeffs_x2 = coefs1_x; ++ u[0].coeffs_y2 = coefs1_y; ++ u[0].wo_u2 = wo_u2; ++ u[0].wo_v2 = wo_v2; ++ u[0].dst_addr_c = dst_base_u + (start_x << xshl); ++ ++ cp->last_l0 = &u[0].next_src1; ++ cp->last_l1 = &u[0].next_src2; ++ cp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(u + 1); ++ } ++} ++ ++ ++static inline void ++col_stash(const HEVCRpiContext * const s, ++ const unsigned int x0, const unsigned int y0, const unsigned int w0, const unsigned int h0, ++ const HEVCRpiMvField * const mvf) ++{ ++ ColMvField * const col_mvf = s->ref->col_mvf; ++ const unsigned int x = (x0 + 15) >> 4; ++ const unsigned int y = (y0 + 15) >> 4; ++ const unsigned int w = ((x0 + 15 + w0) >> 4) - x; ++ const unsigned int h = ((y0 + 15 + h0) >> 4) - y; ++ ++ if (col_mvf != NULL && w != 0 && h != 0) ++ { ++ // Only record MV from the top left of the 16x16 block ++ ++ const RefPicList * const rpl = s->refPicList; ++ const ColMvField cmv = { ++ .L = { ++ { ++ .poc = (mvf->pred_flag & PF_L0) == 0 ? ++ COL_POC_INTRA : ++ COL_POC_MAKE_INTER(rpl[0].isLongTerm[mvf->ref_idx[0]], rpl[0].list[mvf->ref_idx[0]]), ++ .xy = mvf->xy[0] ++ }, ++ { ++ .poc = (mvf->pred_flag & PF_L1) == 0 ? ++ COL_POC_INTRA : ++ COL_POC_MAKE_INTER(rpl[1].isLongTerm[mvf->ref_idx[1]], rpl[1].list[mvf->ref_idx[1]]), ++ .xy = mvf->xy[1] ++ } ++ } ++ }; ++ ++ ColMvField * p = col_mvf + y * s->col_mvf_stride + x; ++ const unsigned int stride = s->col_mvf_stride - w; ++ unsigned int j = h; ++ ++ do ++ { ++ unsigned int k = w; ++ do ++ { ++ *p++ = cmv; ++ } while (--k != 0); ++ p += stride; ++ } while (--j != 0); ++ } ++} ++ ++static void hls_prediction_unit(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int nPbW, const unsigned int nPbH, ++ const unsigned int log2_cb_size, const unsigned int partIdx, const unsigned int idx) ++{ ++ HEVCRpiJob * const jb = lc->jb0; ++ ++ struct HEVCRpiMvField current_mv = {{0}}; ++ const RefPicList *const refPicList = s->refPicList; ++ const HEVCRpiFrame *ref0 = NULL, *ref1 = NULL; ++ ++ if (lc->cu.pred_mode != MODE_SKIP) ++ lc->pu.merge_flag = ff_hevc_rpi_merge_flag_decode(lc); ++ ++ if (lc->cu.pred_mode == MODE_SKIP || lc->pu.merge_flag) { ++ const unsigned int merge_idx = s->sh.max_num_merge_cand <= 1 ? 0 : ++ ff_hevc_rpi_merge_idx_decode(s, lc); ++ ++ ff_hevc_rpi_luma_mv_merge_mode(s, lc, x0, y0, nPbW, nPbH, log2_cb_size, ++ partIdx, merge_idx, ¤t_mv); ++ } else { ++ hevc_luma_mv_mvp_mode(s, lc, x0, y0, nPbW, nPbH, ¤t_mv); ++ } ++ ++ { ++ HEVCRpiMvField * p = mvf_stash_ptr(s, lc, x0, y0); ++ unsigned int i, j; ++ ++ for (j = 0; j < nPbH >> LOG2_MIN_PU_SIZE; j++) ++ { ++ for (i = 0; i < nPbW >> LOG2_MIN_PU_SIZE; i++) ++ p[i] = current_mv; ++ p += MVF_STASH_WIDTH_PU; ++ } ++ } ++ ++ col_stash(s, x0, y0, nPbW, nPbH, ¤t_mv); ++ ++ if (current_mv.pred_flag & PF_L0) { ++ ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; ++ if (!ref0) ++ return; ++ hevc_await_progress(s, lc, ref0, current_mv.xy[0], y0, nPbH); ++ } ++ if (current_mv.pred_flag & PF_L1) { ++ ref1 = refPicList[1].ref[current_mv.ref_idx[1]]; ++ if (!ref1) ++ return; ++ hevc_await_progress(s, lc, ref1, current_mv.xy[1], y0, nPbH); ++ } ++ ++ if (current_mv.pred_flag == PF_L0) { ++ const int x0_c = x0 >> ctx_hshift(s, 1); ++ const int y0_c = y0 >> ctx_vshift(s, 1); ++ const int nPbW_c = nPbW >> ctx_hshift(s, 1); ++ const int nPbH_c = nPbH >> ctx_vshift(s, 1); ++ ++ rpi_pred_y(s, jb, x0, y0, nPbW, nPbH, current_mv.xy[0], ++ s->sh.luma_weight_l0[current_mv.ref_idx[0]], s->sh.luma_offset_l0[current_mv.ref_idx[0]], ++ ref0->frame); ++ ++ if (ctx_cfmt(s) != 0) { ++ rpi_pred_c(s, jb, 0, x0_c, y0_c, nPbW_c, nPbH_c, current_mv.xy[0], ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]], s->sh.chroma_offset_l0[current_mv.ref_idx[0]], ++ ref0->frame); ++ return; ++ } ++ } else if (current_mv.pred_flag == PF_L1) { ++ const int x0_c = x0 >> ctx_hshift(s, 1); ++ const int y0_c = y0 >> ctx_vshift(s, 1); ++ const int nPbW_c = nPbW >> ctx_hshift(s, 1); ++ const int nPbH_c = nPbH >> ctx_vshift(s, 1); ++ ++ rpi_pred_y(s, jb, x0, y0, nPbW, nPbH, current_mv.xy[1], ++ s->sh.luma_weight_l1[current_mv.ref_idx[1]], s->sh.luma_offset_l1[current_mv.ref_idx[1]], ++ ref1->frame); ++ ++ if (ctx_cfmt(s) != 0) { ++ rpi_pred_c(s, jb, 1, x0_c, y0_c, nPbW_c, nPbH_c, current_mv.xy[1], ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]], s->sh.chroma_offset_l1[current_mv.ref_idx[1]], ++ ref1->frame); ++ return; ++ } ++ } else if (current_mv.pred_flag == PF_BI) { ++ const int x0_c = x0 >> ctx_hshift(s, 1); ++ const int y0_c = y0 >> ctx_vshift(s, 1); ++ const int nPbW_c = nPbW >> ctx_hshift(s, 1); ++ const int nPbH_c = nPbH >> ctx_vshift(s, 1); ++ ++ rpi_pred_y_b(s, jb, x0, y0, nPbW, nPbH, ¤t_mv, ref0->frame, ref1->frame); ++ ++ if (ctx_cfmt(s) != 0) { ++ rpi_pred_c_b(s, jb, x0_c, y0_c, nPbW_c, nPbH_c, ++ ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]], ++ s->sh.chroma_offset_l0[current_mv.ref_idx[0]], ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]], ++ s->sh.chroma_offset_l1[current_mv.ref_idx[1]], ++ ref0->frame, ++ ref1->frame); ++ return; ++ } ++ } ++} ++ ++static void set_ipm(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_cb_size, ++ const unsigned int ipm) ++{ ++ const unsigned int x_pu = x0 >> LOG2_MIN_PU_SIZE; ++ const unsigned int y_pu = y0 >> LOG2_MIN_PU_SIZE; ++ ++ { ++ const unsigned int ctb_mask = ~(~0U << (s->ps.sps->log2_ctb_size - LOG2_MIN_PU_SIZE)); ++ set_stash2(lc->ipm_left + (y_pu & ctb_mask), lc->ipm_up + (x_pu & ctb_mask), log2_cb_size - LOG2_MIN_PU_SIZE, ipm); ++ } ++ ++ // If IRAP then everything is Intra & we avoid ever looking at these ++ // stashes so don't bother setting them ++ if (!s->is_irap && lc->cu.pred_mode == MODE_INTRA) ++ { ++ if (s->is_intra != NULL) ++ { ++ set_bits(s->is_intra + (y0 >> LOG2_MIN_CU_SIZE) * s->ps.sps->pcm_width, x0 >> LOG2_MIN_CU_SIZE, s->ps.sps->pcm_width, log2_cb_size - LOG2_MIN_CU_SIZE); ++ } ++ ++ { ++ HEVCRpiMvField * p = mvf_stash_ptr(s, lc, x0, y0); ++ const unsigned int size_in_pus = (1 << log2_cb_size) >> LOG2_MIN_PU_SIZE; // min_pu <= log2_cb so >= 1 ++ unsigned int n = size_in_pus; ++ ++ do ++ { ++ memset(p, 0, size_in_pus * sizeof(*p)); ++ p += MVF_STASH_WIDTH_PU; ++ } while (--n != 0); ++ } ++ ++ ++ if (s->ref->col_mvf != NULL && ((x0 | y0) & 0xf) == 0) ++ { ++ // Only record top left stuff ++ // Blocks should always be alinged on size boundries ++ // so cannot have overflow from a small block ++ ++ ColMvField * p = s->ref->col_mvf + (y0 >> 4) * s->col_mvf_stride + (x0 >> 4); ++ const unsigned int size_in_col = log2_cb_size < 4 ? 1 : (1 << (log2_cb_size - 4)); ++ const unsigned int stride = s->col_mvf_stride - size_in_col; ++ unsigned int j = size_in_col; ++ ++ do ++ { ++ unsigned int k = size_in_col; ++ do ++ { ++ p->L[0].poc = COL_POC_INTRA; ++ p->L[0].xy = 0; ++ p->L[1].poc = COL_POC_INTRA; ++ p->L[1].xy = 0; ++ ++p; ++ } while (--k != 0); ++ p += stride; ++ } while (--j != 0); ++ } ++ } ++} ++ ++static inline void intra_prediction_unit_default_value(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_cb_size) ++{ ++ set_ipm(s, lc, x0, y0, log2_cb_size, INTRA_DC); ++} ++ ++ ++/** ++ * 8.4.1 ++ */ ++static int luma_intra_pred_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ int x0, int y0, int log2_pu_size, ++ int prev_intra_luma_pred_flag, ++ const unsigned int idx) ++{ ++ const unsigned int ctb_mask = ~(~0U << s->ps.sps->log2_ctb_size); ++ const unsigned int xb_pu = (x0 & ctb_mask) >> LOG2_MIN_PU_SIZE; ++ const unsigned int yb_pu = (y0 & ctb_mask) >> LOG2_MIN_PU_SIZE; ++ ++ // Up does not cross boundries so as we always scan 1 slice-tile-line in an ++ // lc we can just keep 1 CTB lR stashes ++ // Left is reset to DC @ Start of Line/Tile/Slice in fill_job ++ const unsigned int cand_up = yb_pu == 0 ? INTRA_DC : lc->ipm_up[xb_pu]; ++ const unsigned int cand_left = lc->ipm_left[yb_pu]; ++ ++ unsigned int intra_pred_mode; ++ unsigned int a, b, c; ++ ++ if (cand_left == cand_up) { ++ if (cand_left < 2) { ++ a = INTRA_PLANAR; ++ b = INTRA_DC; ++ c = INTRA_ANGULAR_26; ++ } else { ++ a = cand_left; ++ b = 2 + ((cand_left - 2 - 1 + 32) & 31); ++ c = 2 + ((cand_left - 2 + 1) & 31); ++ } ++ } else { ++ a = cand_left; ++ b = cand_up; ++ c = (cand_left != INTRA_PLANAR && cand_up != INTRA_PLANAR) ? ++ INTRA_PLANAR : ++ (cand_left != INTRA_DC && cand_up != INTRA_DC) ? ++ INTRA_DC : ++ INTRA_ANGULAR_26; ++ } ++ ++ if (prev_intra_luma_pred_flag) { ++ intra_pred_mode = idx == 0 ? a : idx == 1 ? b : c; ++ } else { ++ // Sort lowest 1st ++ if (a > b) ++ FFSWAP(int, a, b); ++ if (a > c) ++ FFSWAP(int, a, c); ++ if (b > c) ++ FFSWAP(int, b, c); ++ ++ intra_pred_mode = idx; ++ if (intra_pred_mode >= a) ++ intra_pred_mode++; ++ if (intra_pred_mode >= b) ++ intra_pred_mode++; ++ if (intra_pred_mode >= c) ++ intra_pred_mode++; ++ } ++ ++ /* write the intra prediction units into the mv array */ ++ set_ipm(s, lc, x0, y0, log2_pu_size, intra_pred_mode); ++ return intra_pred_mode; ++} ++ ++static const uint8_t tab_mode_idx[] = { ++ 0, 1, 2, 2, 2, 2, 3, 5, 7, 8, 10, 12, 13, 15, 17, 18, 19, 20, ++ 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31}; ++ ++static void intra_prediction_unit(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_cb_size) ++{ ++ static const uint8_t intra_chroma_table[4] = { 0, 26, 10, 1 }; ++ uint8_t prev_intra_luma_pred_flag[4]; ++ int split = lc->cu.part_mode == PART_NxN; ++ const unsigned int split_size = (1 << (log2_cb_size - 1)); ++ int chroma_mode; ++ const unsigned int n = split ? 4 : 1; ++ unsigned int i; ++ ++ for (i = 0; i != n; i++) ++ prev_intra_luma_pred_flag[i] = ff_hevc_rpi_prev_intra_luma_pred_flag_decode(lc); ++ ++ for (i = 0; i < n; i++) { ++ // depending on mode idx is mpm or luma_pred_mode ++ const unsigned int idx = prev_intra_luma_pred_flag[i] ? ++ ff_hevc_rpi_mpm_idx_decode(lc) : ++ ff_hevc_rpi_rem_intra_luma_pred_mode_decode(lc); ++ ++ lc->pu.intra_pred_mode[i] = ++ luma_intra_pred_mode(s, lc, ++ x0 + ((i & 1) == 0 ? 0 : split_size), ++ y0 + ((i & 2) == 0 ? 0 : split_size), ++ log2_cb_size - split, ++ prev_intra_luma_pred_flag[i], idx); ++ } ++ ++ if (ctx_cfmt(s) == 3) { ++ for (i = 0; i < n; i++) { ++ lc->pu.chroma_mode_c[i] = chroma_mode = ff_hevc_rpi_intra_chroma_pred_mode_decode(lc); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[i] == intra_chroma_table[chroma_mode]) ++ lc->pu.intra_pred_mode_c[i] = 34; ++ else ++ lc->pu.intra_pred_mode_c[i] = intra_chroma_table[chroma_mode]; ++ } else { ++ lc->pu.intra_pred_mode_c[i] = lc->pu.intra_pred_mode[i]; ++ } ++ } ++ } else if (ctx_cfmt(s) == 2) { ++ int mode_idx; ++ lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_rpi_intra_chroma_pred_mode_decode(lc); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) ++ mode_idx = 34; ++ else ++ mode_idx = intra_chroma_table[chroma_mode]; ++ } else { ++ mode_idx = lc->pu.intra_pred_mode[0]; ++ } ++ lc->pu.intra_pred_mode_c[0] = tab_mode_idx[mode_idx]; ++ } else if (ctx_cfmt(s) != 0) { ++ chroma_mode = ff_hevc_rpi_intra_chroma_pred_mode_decode(lc); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) ++ lc->pu.intra_pred_mode_c[0] = 34; ++ else ++ lc->pu.intra_pred_mode_c[0] = intra_chroma_table[chroma_mode]; ++ } else { ++ lc->pu.intra_pred_mode_c[0] = lc->pu.intra_pred_mode[0]; ++ } ++ } ++} ++ ++static int hls_coding_unit(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, const unsigned int log2_cb_size) ++{ ++ const unsigned int cb_size = 1 << log2_cb_size; ++ const unsigned int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ const unsigned int min_cb_width = s->ps.sps->min_cb_width; ++ const unsigned int x_cb = x0 >> log2_min_cb_size; ++ const unsigned int y_cb = y0 >> log2_min_cb_size; ++ const unsigned int idx = log2_cb_size - 2; ++ const unsigned int qp_block_mask = (1 << s->ps.pps->log2_min_cu_qp_delta_size) - 1; ++ int skip_flag = 0; ++ ++ lc->cu.x = x0; ++ lc->cu.y = y0; ++ lc->cu.x_split = x0; ++ lc->cu.y_split = y0; ++ ++ lc->cu.pred_mode = MODE_INTRA; ++ lc->cu.part_mode = PART_2Nx2N; ++ lc->cu.intra_split_flag = 0; ++ lc->cu.cu_transquant_bypass_flag = 0; ++ lc->pu.intra_pred_mode[0] = 1; ++ lc->pu.intra_pred_mode[1] = 1; ++ lc->pu.intra_pred_mode[2] = 1; ++ lc->pu.intra_pred_mode[3] = 1; ++ ++ if (s->ps.pps->transquant_bypass_enable_flag) { ++ lc->cu.cu_transquant_bypass_flag = ff_hevc_rpi_cu_transquant_bypass_flag_decode(lc); ++ if (lc->cu.cu_transquant_bypass_flag) ++ set_deblocking_bypass(s, x0, y0, log2_cb_size); ++ } ++ ++ if (s->sh.slice_type != HEVC_SLICE_I) { ++ lc->cu.pred_mode = MODE_INTER; ++ skip_flag = ff_hevc_rpi_skip_flag_decode(s, lc, x0, y0, x_cb, y_cb); ++ } ++ ++ if (skip_flag) { ++ lc->cu.pred_mode = MODE_SKIP; ++ ++ hls_prediction_unit(s, lc, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); ++ intra_prediction_unit_default_value(s, lc, x0, y0, log2_cb_size); ++ ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_rpi_deblocking_boundary_strengths(s, lc, x0, y0, log2_cb_size, 0); ++ } else { ++ int pcm_flag = 0; ++ ++ if (s->sh.slice_type != HEVC_SLICE_I) ++ lc->cu.pred_mode = ff_hevc_rpi_pred_mode_decode(lc); ++ if (lc->cu.pred_mode != MODE_INTRA || ++ log2_cb_size == s->ps.sps->log2_min_cb_size) { ++ lc->cu.part_mode = ff_hevc_rpi_part_mode_decode(s, lc, log2_cb_size); ++ lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN && ++ lc->cu.pred_mode == MODE_INTRA; ++ } ++ ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ if (lc->cu.part_mode == PART_2Nx2N && ++ log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size && // 0 if not enabled ++ log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size && ++ ff_hevc_rpi_pcm_flag_decode(lc) != 0) ++ { ++ int ret; ++ pcm_flag = 1; ++ intra_prediction_unit_default_value(s, lc, x0, y0, log2_cb_size); ++ if ((ret = hls_pcm_sample(s, lc, x0, y0, log2_cb_size)) < 0) ++ return ret; ++ ++ if (s->ps.sps->pcm.loop_filter_disable_flag) ++ set_deblocking_bypass(s, x0, y0, log2_cb_size); ++ } else { ++ intra_prediction_unit(s, lc, x0, y0, log2_cb_size); ++ } ++ } else { ++ intra_prediction_unit_default_value(s, lc, x0, y0, log2_cb_size); ++ switch (lc->cu.part_mode) { ++ case PART_2Nx2N: ++ hls_prediction_unit(s, lc, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); ++ break; ++ case PART_2NxN: ++ hls_prediction_unit(s, lc, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0, idx); ++ lc->cu.y_split = y0 + cb_size / 2; ++ hls_prediction_unit(s, lc, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx); ++ break; ++ case PART_Nx2N: ++ hls_prediction_unit(s, lc, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1); ++ lc->cu.x_split = x0 + cb_size / 2; ++ hls_prediction_unit(s, lc, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1); ++ break; ++ case PART_2NxnU: ++ hls_prediction_unit(s, lc, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0, idx); ++ lc->cu.y_split = y0 + cb_size / 4; ++ hls_prediction_unit(s, lc, x0, y0 + cb_size / 4, cb_size, cb_size / 4 * 3, log2_cb_size, 1, idx); ++ break; ++ case PART_2NxnD: ++ hls_prediction_unit(s, lc, x0, y0, cb_size, cb_size / 4 * 3, log2_cb_size, 0, idx); ++ lc->cu.y_split = y0 + cb_size / 4 * 3; ++ hls_prediction_unit(s, lc, x0, y0 + cb_size / 4 * 3, cb_size, cb_size / 4, log2_cb_size, 1, idx); ++ break; ++ case PART_nLx2N: ++ hls_prediction_unit(s, lc, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0, idx - 2); ++ lc->cu.x_split = x0 + cb_size / 4; ++ hls_prediction_unit(s, lc, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2); ++ break; ++ case PART_nRx2N: ++ hls_prediction_unit(s, lc, x0, y0, cb_size / 4 * 3, cb_size, log2_cb_size, 0, idx - 2); ++ lc->cu.x_split = x0 + cb_size / 4 * 3; ++ hls_prediction_unit(s, lc, x0 + cb_size / 4 * 3, y0, cb_size / 4, cb_size, log2_cb_size, 1, idx - 2); ++ break; ++ case PART_NxN: ++ hls_prediction_unit(s, lc, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1); ++ lc->cu.x_split = x0 + cb_size / 2; ++ hls_prediction_unit(s, lc, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1); ++ lc->cu.y_split = y0 + cb_size / 2; ++ hls_prediction_unit(s, lc, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1); ++ hls_prediction_unit(s, lc, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1); ++ break; ++ } ++ } ++ ++ if (!pcm_flag) { ++ int rqt_root_cbf = 1; ++ ++ if (lc->cu.pred_mode != MODE_INTRA && ++ !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) { ++ rqt_root_cbf = ff_hevc_rpi_no_residual_syntax_flag_decode(lc); ++ } ++ if (rqt_root_cbf) { ++ const unsigned int cbf_c = ctx_cfmt(s) == 0 ? 0 : (CBF_CR0 | CBF_CB0); ++ int ret; ++ ++ lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ? ++ s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag : ++ s->ps.sps->max_transform_hierarchy_depth_inter; ++ // transform_tree does deblock_boundary_strengths ++ ret = hls_transform_tree(s, lc, x0, y0, ++ log2_cb_size, 0, 0, cbf_c); ++ if (ret < 0) ++ return ret; ++ } else { ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_rpi_deblocking_boundary_strengths(s, lc, x0, y0, log2_cb_size, 0); ++ } ++ } ++ } ++ ++ // If the delta is still wanted then we haven't read the delta & therefore need to set qp here ++ if (lc->tu.is_cu_qp_delta_wanted) ++ ff_hevc_rpi_set_qPy(s, lc, x0, y0); ++ ++ if(((x0 + (1<qPy_pred = lc->qp_y; ++ } ++ ++ set_bytes(s->qp_y_tab + y_cb * min_cb_width + x_cb, min_cb_width, log2_cb_size - log2_min_cb_size, lc->qp_y & 0xff); ++ ++ set_stash2(s->cabac_stash_up + (x0 >> 3), s->cabac_stash_left + (y0 >> 3), log2_cb_size - 3, (lc->ct_depth << 1) | skip_flag); ++ ++ return 0; ++} ++ ++// Returns: ++// < 0 Error ++// 0 More data wanted ++// 1 EoSlice / EoPicture ++static int hls_coding_quadtree(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const int x0, const int y0, ++ const int log2_cb_size, const unsigned int cb_depth) ++{ ++ const int cb_size = 1 << log2_cb_size; ++ int ret; ++ int split_cu; ++ ++ lc->ct_depth = cb_depth; ++ split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size); ++ if (x0 + cb_size <= s->ps.sps->width && ++ y0 + cb_size <= s->ps.sps->height && ++ split_cu) ++ { ++ split_cu = ff_hevc_rpi_split_coding_unit_flag_decode(s, lc, cb_depth, x0, y0); ++ } ++ ++ // Qp delta (and offset) need to remain wanted if cb_size < min until ++ // a coded block is found so we still initial state at depth 0 (outside ++ // this fn) and only reset here ++ if (s->ps.pps->cu_qp_delta_enabled_flag && ++ log2_cb_size >= s->ps.pps->log2_min_cu_qp_delta_size) ++ { ++ lc->tu.is_cu_qp_delta_wanted = 1; ++ lc->tu.cu_qp_delta = 0; ++ } ++ if (s->sh.cu_chroma_qp_offset_enabled_flag && ++ log2_cb_size >= s->ps.pps->log2_min_cu_qp_delta_size) ++ { ++ lc->tu.cu_chroma_qp_offset_wanted = 1; ++ } ++ ++ lc->tu.qp_divmod6[0] = s->ps.pps->qp_bd_x[0]; ++ lc->tu.qp_divmod6[1] = s->ps.pps->qp_bd_x[1] + s->sh.slice_cb_qp_offset; ++ lc->tu.qp_divmod6[2] = s->ps.pps->qp_bd_x[2] + s->sh.slice_cr_qp_offset; ++ ++ if (split_cu) { ++ int qp_block_mask = (1 << s->ps.pps->log2_min_cu_qp_delta_size) - 1; ++ const int cb_size_split = cb_size >> 1; ++ const int x1 = x0 + cb_size_split; ++ const int y1 = y0 + cb_size_split; ++ ++ int more_data = 0; ++ ++ more_data = hls_coding_quadtree(s, lc, x0, y0, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ ++ if (more_data && x1 < s->ps.sps->width) { ++ more_data = hls_coding_quadtree(s, lc, x1, y0, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ if (more_data && y1 < s->ps.sps->height) { ++ more_data = hls_coding_quadtree(s, lc, x0, y1, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ if (more_data && x1 < s->ps.sps->width && ++ y1 < s->ps.sps->height) { ++ more_data = hls_coding_quadtree(s, lc, x1, y1, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ ++ if(((x0 + (1<qPy_pred = lc->qp_y; ++ ++ if (more_data) ++ return ((x1 + cb_size_split) < s->ps.sps->width || ++ (y1 + cb_size_split) < s->ps.sps->height); ++ else ++ return 0; ++ } else { ++ ret = hls_coding_unit(s, lc, x0, y0, log2_cb_size); ++ if (ret < 0) ++ return ret; ++ if ((!((x0 + cb_size) % ++ (1 << (s->ps.sps->log2_ctb_size))) || ++ (x0 + cb_size >= s->ps.sps->width)) && ++ (!((y0 + cb_size) % ++ (1 << (s->ps.sps->log2_ctb_size))) || ++ (y0 + cb_size >= s->ps.sps->height))) { ++ int end_of_slice_flag = ff_hevc_rpi_get_cabac_terminate(&lc->cc); ++ return !end_of_slice_flag; ++ } else { ++ return 1; ++ } ++ } ++ ++ return 0; // NEVER ++} ++ ++static void hls_decode_neighbour(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const int x_ctb, const int y_ctb, const int ctb_addr_ts) ++{ ++ const unsigned int ctb_size = 1 << s->ps.sps->log2_ctb_size; ++ const unsigned int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ const unsigned int ctb_addr_rs_in_slice = ctb_addr_rs - s->sh.slice_addr; // slice_addr = RS addr of start of slice ++ const unsigned int ctb_flags = s->ps.pps->ctb_ts_flags[ctb_addr_ts]; ++ const unsigned int line_w = s->ps.sps->ctb_width; ++ ++ s->tab_slice_address[ctb_addr_rs] = s->sh.slice_addr; ++ ++ lc->end_of_ctb_x = FFMIN(x_ctb + ctb_size, s->ps.sps->width); ++ lc->end_of_ctb_y = FFMIN(y_ctb + ctb_size, s->ps.sps->height); ++ ++ lc->boundary_flags = 0; ++ ++ if ((ctb_flags & CTB_TS_FLAGS_SOTL) != 0) ++ lc->boundary_flags |= BOUNDARY_LEFT_TILE; ++ if (x_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - 1]) ++ lc->boundary_flags |= BOUNDARY_LEFT_SLICE; ++ if ((ctb_flags & CTB_TS_FLAGS_TOT) != 0) ++ lc->boundary_flags |= BOUNDARY_UPPER_TILE; ++ if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - line_w]) ++ lc->boundary_flags |= BOUNDARY_UPPER_SLICE; ++ ++ // Use line width rather than tile width for addr_in_slice test as ++ // addr_in_slice is in raster units ++ ++ lc->ctb_avail = ++ ((lc->boundary_flags & (BOUNDARY_LEFT_SLICE | BOUNDARY_LEFT_TILE)) == 0 ? AVAIL_L : 0) | ++ ((lc->boundary_flags & (BOUNDARY_UPPER_SLICE | BOUNDARY_UPPER_TILE)) == 0 ? AVAIL_U : 0) | ++ ((lc->boundary_flags & (BOUNDARY_LEFT_TILE | BOUNDARY_UPPER_TILE)) == 0 && ++ (ctb_addr_rs_in_slice > line_w) ? AVAIL_UL : 0) | ++ ((ctb_flags & (CTB_TS_FLAGS_EOTL | CTB_TS_FLAGS_TOT)) == 0 && ++ (ctb_addr_rs_in_slice + 1 >= line_w) ? AVAIL_UR : 0); ++ // Down-left never avail at CTB level ++} ++ ++ ++static void rpi_execute_dblk_cmds(const HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ int y = ff_hevc_rpi_hls_filter_blk(s, jb->bounds, ++ (s->ps.pps->ctb_ts_flags[jb->ctu_ts_last] & CTB_TS_FLAGS_EOT) != 0); ++ ++ // Signal ++ if (y > 0) { ++ // Cast away const as progress is held in s, but this really shouldn't confuse anything ++ ff_hevc_rpi_progress_signal_recon((HEVCRpiContext *)s, y - 1); ++ } ++ ++ // Job done now ++ // ? Move outside this fn ++ job_free(s->jbc, jb); ++} ++ ++// I-pred, transform_and_add for all blocks types done here ++// All ARM ++static void rpi_execute_pred_cmds(const HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ unsigned int i; ++ HEVCRpiIntraPredEnv * const iap = &jb->intra; ++ const HEVCPredCmd *cmd = iap->cmds; ++ ++#if !RPI_WORKER_WAIT_PASS_0 ++ rpi_sem_wait(&jb->sem); ++ rpi_cache_flush_execute(jb->rfe); // Invalidate data set up in pass1 ++#endif ++ ++ for (i = iap->n; i > 0; i--, cmd++) ++ { ++ switch (cmd->type) ++ { ++ case RPI_PRED_INTRA: ++ s->hpc.intra_pred(s, cmd->i_pred.mode, cmd->i_pred.x, cmd->i_pred.y, cmd->avail, cmd->size); ++ break; ++ case RPI_PRED_INTRA_C: ++ s->hpc.intra_pred_c(s, cmd->i_pred.mode, cmd->i_pred.x, cmd->i_pred.y, cmd->avail, cmd->size); ++ break; ++ case RPI_PRED_ADD_RESIDUAL: ++ s->hevcdsp.add_residual[cmd->size - 2](cmd->ta.dst, (int16_t *)cmd->ta.buf, cmd->ta.stride); ++ break; ++ case RPI_PRED_ADD_DC: ++ s->hevcdsp.add_residual_dc[cmd->size - 2](cmd->dc.dst, cmd->dc.stride, cmd->dc.dc); ++ break; ++ case RPI_PRED_ADD_RESIDUAL_U: ++ s->hevcdsp.add_residual_u[cmd->size - 2](cmd->ta.dst, (int16_t *)cmd->ta.buf, cmd->ta.stride, cmd->ta.dc); ++ break; ++ case RPI_PRED_ADD_RESIDUAL_V: ++ s->hevcdsp.add_residual_v[cmd->size - 2](cmd->ta.dst, (int16_t *)cmd->ta.buf, cmd->ta.stride, cmd->ta.dc); ++ break; ++ case RPI_PRED_ADD_RESIDUAL_C: ++ s->hevcdsp.add_residual_c[cmd->size - 2](cmd->ta.dst, (int16_t *)cmd->ta.buf, cmd->ta.stride); ++ break; ++ case RPI_PRED_ADD_DC_U: ++ case RPI_PRED_ADD_DC_V: ++ s->hevcdsp.add_residual_dc_c[cmd->size - 2](cmd->dc.dst, cmd->dc.stride, cmd->dc.dc); ++ break; ++ ++ case RPI_PRED_I_PCM: ++ pcm_extract(s, cmd->i_pcm.src, cmd->i_pcm.src_len, cmd->i_pcm.x, cmd->i_pcm.y, 1 << cmd->size); ++ break; ++ ++ default: ++ av_log(s->avctx, AV_LOG_PANIC, "Bad command %d in worker pred Q\n", cmd->type); ++ abort(); ++ } ++ } ++ ++ // Mark done ++ iap->n = 0; ++} ++ ++ ++// Set initial uniform job values & zero ctu_count ++static void rpi_begin(const HEVCRpiContext * const s, HEVCRpiJob * const jb, const unsigned int ctu_ts_first) ++{ ++ unsigned int i; ++ HEVCRpiInterPredEnv *const cipe = &jb->chroma_ip; ++ HEVCRpiInterPredEnv *const yipe = &jb->luma_ip; ++ const HEVCRpiSPS * const sps = s->ps.sps; ++ ++ const uint16_t pic_width_y = sps->width; ++ const uint16_t pic_height_y = sps->height; ++ ++ const uint16_t pic_width_c = sps->width >> ctx_hshift(s, 1); ++ const uint16_t pic_height_c = sps->height >> ctx_vshift(s, 1); ++ ++ // We expect the pointer to change if we use another sps ++ if (sps != jb->sps) ++ { ++ worker_pic_free_one(jb); ++ ++ set_ipe_from_ici(cipe, &ipe_init_infos[s->ps.sps->bit_depth - 8].chroma); ++ set_ipe_from_ici(yipe, &ipe_init_infos[s->ps.sps->bit_depth - 8].luma); ++ ++ { ++ const int coefs_per_luma = HEVC_MAX_CTB_SIZE * HEVC_RPI_MAX_WIDTH; ++ const int coefs_per_chroma = (coefs_per_luma * 2) >> (ctx_vshift(s, 1) + ctx_hshift(s, 1)); ++ worker_pic_alloc_one(jb, coefs_per_luma + coefs_per_chroma); ++ } ++ ++ jb->sps = sps; ++ } ++ ++ jb->waited = 0; ++ jb->ctu_ts_first = ctu_ts_first; ++ jb->ctu_ts_last = -1; ++ ++ rpi_inter_pred_reset(cipe); ++ for (i = 0; i < cipe->n; i++) { ++ HEVCRpiInterPredQ * const cp = cipe->q + i; ++ qpu_mc_pred_c_s_t * const u = &cp->qpu_mc_base->c.s; ++ ++ u->next_src1.x = 0; ++ u->next_src1.y = 0; ++ u->next_src1.base = 0; ++ u->pic_cw = pic_width_c; ++ u->pic_ch = pic_height_c; ++ u->stride2 = av_rpi_sand_frame_stride2(s->frame); ++ u->stride1 = av_rpi_sand_frame_stride1(s->frame); ++ cp->last_l0 = &u->next_src1; ++ ++ u->next_fn = 0; ++ u->next_src2.x = 0; ++ u->next_src2.y = 0; ++ u->next_src2.base = 0; ++ cp->last_l1 = &u->next_src2; ++ ++ cp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(u + 1); ++ } ++ ++ rpi_inter_pred_reset(yipe); ++ for (i = 0; i < yipe->n; i++) { ++ HEVCRpiInterPredQ * const yp = yipe->q + i; ++ qpu_mc_pred_y_s_t * const y = &yp->qpu_mc_base->y.s; ++ ++ y->next_src1.x = 0; ++ y->next_src1.y = 0; ++ y->next_src1.base = 0; ++ y->next_src2.x = 0; ++ y->next_src2.y = 0; ++ y->next_src2.base = 0; ++ y->pic_h = pic_height_y; ++ y->pic_w = pic_width_y; ++ y->stride2 = av_rpi_sand_frame_stride2(s->frame); ++ y->stride1 = av_rpi_sand_frame_stride1(s->frame); ++ y->next_fn = 0; ++ yp->last_l0 = &y->next_src1; ++ yp->last_l1 = &y->next_src2; ++ ++ yp->qpu_mc_curr = (qpu_mc_pred_cmd_t *)(y + 1); ++ } ++ ++ jb->last_y8_p = NULL; ++ jb->last_y8_l1 = NULL; ++ ++ for (i = 0; i != FF_ARRAY_ELEMS(jb->progress_req); ++i) { ++ jb->progress_req[i] = -1; ++ } ++ ++ worker_pic_reset(&jb->coeffs); ++} ++ ++ ++#if !RPI_QPU_EMU_Y || !RPI_QPU_EMU_C ++static unsigned int mc_terminate_add_qpu(const HEVCRpiContext * const s, ++ const vpu_qpu_job_h vqj, ++ rpi_cache_flush_env_t * const rfe, ++ HEVCRpiInterPredEnv * const ipe) ++{ ++ unsigned int i; ++ uint32_t mail[QPU_N_MAX][QPU_MAIL_EL_VALS]; ++ unsigned int max_block = 0; ++ ++ if (!ipe->used) { ++ return 0; ++ } ++ ++ if (ipe->curr != 0) { ++ rpi_inter_pred_sync(ipe); ++ } ++ ++ // Add final commands to Q ++ for(i = 0; i != ipe->n; ++i) { ++ HEVCRpiInterPredQ * const yp = ipe->q + i; ++ qpu_mc_src_t *const p0 = yp->last_l0; ++ qpu_mc_src_t *const p1 = yp->last_l1; ++ const unsigned int block_size = (char *)yp->qpu_mc_curr - (char *)yp->qpu_mc_base; ++ ++ if (block_size > max_block) ++ max_block = block_size; ++ ++ qpu_mc_link_set(yp->qpu_mc_curr, yp->code_exit); ++ ++ // Need to set the srcs for L0 & L1 to something that can be (pointlessly) prefetched ++ p0->x = MC_DUMMY_X; ++ p0->y = MC_DUMMY_Y; ++ p0->base = s->qpu_dummy_frame_qpu; ++ p1->x = MC_DUMMY_X; ++ p1->y = MC_DUMMY_Y; ++ p1->base = s->qpu_dummy_frame_qpu; ++ ++ yp->last_l0 = NULL; ++ yp->last_l1 = NULL; ++ ++ // Add to mailbox list ++ mail[i][0] = ipe->gptr.vc + ((uint8_t *)yp->qpu_mc_base - ipe->gptr.arm); ++ mail[i][1] = yp->code_setup; ++ } ++ ++ // We don't need invalidate here as the uniforms aren't changed by the QPU ++ // and leaving them in ARM cache avoids (pointless) pre-reads when writing ++ // new values which seems to give us a small performance advantage ++ // ++ // In most cases we will not have a completely packed set of uniforms and as ++ // we have a 2d invalidate we writeback all uniform Qs to the depth of the ++ // fullest ++ rpi_cache_flush_add_gm_blocks(rfe, &ipe->gptr, RPI_CACHE_FLUSH_MODE_WRITEBACK, ++ (uint8_t *)ipe->q[0].qpu_mc_base - ipe->gptr.arm, max_block, ++ ipe->n, ipe->max_fill + ipe->min_gap); ++ vpu_qpu_job_add_qpu(vqj, ipe->n, (uint32_t *)mail); ++ ++ return 1; ++} ++#endif ++ ++#if RPI_QPU_EMU_Y || RPI_QPU_EMU_C ++static unsigned int mc_terminate_add_emu(const HEVCRpiContext * const s, ++ const vpu_qpu_job_h vqj, ++ rpi_cache_flush_env_t * const rfe, ++ HEVCRpiInterPredEnv * const ipe) ++{ ++ unsigned int i; ++ if (!ipe->used) { ++ return 0; ++ } ++ ++ if (ipe->curr != 0) { ++ rpi_inter_pred_sync(ipe); ++ } ++ ++ // Add final commands to Q ++ for(i = 0; i != ipe->n; ++i) { ++ HEVCRpiInterPredQ * const yp = ipe->q + i; ++ qpu_mc_src_t *const p0 = yp->last_l0; ++ qpu_mc_src_t *const p1 = yp->last_l1; ++ ++ yp->qpu_mc_curr->data[-1] = yp->code_exit; ++ ++ // Need to set the srcs for L0 & L1 to something that can be (pointlessly) prefetched ++ p0->x = MC_DUMMY_X; ++ p0->y = MC_DUMMY_Y; ++ p0->base = s->qpu_dummy_frame_emu; ++ p1->x = MC_DUMMY_X; ++ p1->y = MC_DUMMY_Y; ++ p1->base = s->qpu_dummy_frame_emu; ++ ++ yp->last_l0 = NULL; ++ yp->last_l1 = NULL; ++ } ++ ++ return 1; ++} ++#endif ++ ++ ++#if RPI_QPU_EMU_Y ++#define mc_terminate_add_y mc_terminate_add_emu ++#else ++#define mc_terminate_add_y mc_terminate_add_qpu ++#endif ++#if RPI_QPU_EMU_C ++#define mc_terminate_add_c mc_terminate_add_emu ++#else ++#define mc_terminate_add_c mc_terminate_add_qpu ++#endif ++ ++ ++static void flush_frame(HEVCRpiContext *s,AVFrame *frame) ++{ ++ rpi_cache_buf_t cbuf; ++ rpi_cache_flush_env_t * rfe = rpi_cache_flush_init(&cbuf); ++ rpi_cache_flush_add_frame(rfe, frame, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE); ++ rpi_cache_flush_finish(rfe); ++} ++ ++static void job_gen_bounds(const HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ const unsigned int rs0 = s->ps.pps->ctb_addr_ts_to_rs[jb->ctu_ts_first]; ++ const unsigned int rs1 = s->ps.pps->ctb_addr_ts_to_rs[jb->ctu_ts_last]; ++ const unsigned int ctb_width = s->ps.sps->ctb_width; ++ RpiBlk *const bounds = &jb->bounds; ++ av_assert1(jb->ctu_ts_first <= jb->ctu_ts_last); ++ bounds->x = (rs0 % ctb_width) << s->ps.sps->log2_ctb_size; ++ bounds->y = (rs0 / ctb_width) << s->ps.sps->log2_ctb_size; ++ bounds->w = ((rs1 - rs0) % ctb_width + 1) << s->ps.sps->log2_ctb_size; ++ bounds->h = ((rs1 - rs0) / ctb_width + 1) << s->ps.sps->log2_ctb_size; ++ ++ bounds->w = FFMIN(bounds->w, s->ps.sps->width - bounds->x); ++ bounds->h = FFMIN(bounds->h, s->ps.sps->height - bounds->y); ++} ++ ++#if RPI_PASSES == 2 ++static void worker_core2(HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ // Perform intra prediction and residual reconstruction ++ rpi_execute_pred_cmds(s, jb); ++ ++ // Perform deblocking for CTBs in this row ++ rpi_execute_dblk_cmds(s, jb); ++} ++#endif ++ ++// Core execution tasks ++static void worker_core(const HEVCRpiContext * const s, HEVCRpiJob * const jb) ++{ ++ int pred_y, pred_c; ++ vpu_qpu_job_env_t qvbuf; ++ const vpu_qpu_job_h vqj = vpu_qpu_job_init(&qvbuf); ++#if RPI_WORKER_WAIT_PASS_0 ++ int do_wait; ++#endif ++ ++ { ++ const HEVCRpiCoeffsEnv * const cf = &jb->coeffs; ++ if (cf->s[3].n + cf->s[2].n != 0) ++ { ++ const unsigned int csize = sizeof(cf->s[3].buf[0]); ++ const unsigned int offset32 = ((cf->s[3].buf - cf->s[2].buf) - cf->s[3].n) * csize; ++ unsigned int n16 = (cf->s[2].n >> 8); ++ unsigned int n32 = (cf->s[3].n >> 10); ++#if RPI_COMPRESS_COEFFS ++ if (cf->s[2].packed) { ++ n16 = n16 | (n16<<16); ++ } else { ++ const unsigned int npack16 = (cf->s[2].packed_n>>8); ++ n16 = n16 | (npack16<<16); ++ } ++ if (cf->s[3].packed) { ++ n32 = n32 | (n32<<16); ++ } else { ++ const unsigned int npack32 = (cf->s[3].packed_n>>10); ++ n32 = n32 | (npack32<<16); ++ } ++#endif ++ vpu_qpu_job_add_vpu(vqj, ++ vpu_get_fn(s->ps.sps->bit_depth), ++ vpu_get_constants(), ++ cf->gptr.vc, ++ n16, ++ cf->gptr.vc + offset32, ++ n32, ++ 0); ++ ++ rpi_cache_flush_add_gm_range(jb->rfe, &cf->gptr, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE, 0, cf->s[2].n * csize); ++ rpi_cache_flush_add_gm_range(jb->rfe, &cf->gptr, RPI_CACHE_FLUSH_MODE_WB_INVALIDATE, offset32, cf->s[3].n * csize); ++ } ++ } ++ ++ pred_c = mc_terminate_add_c(s, vqj, jb->rfe, &jb->chroma_ip); ++ ++// We could take a sync here and try to locally overlap QPU processing with ARM ++// but testing showed a slightly negative benefit with noticable extra complexity ++ ++ pred_y = mc_terminate_add_y(s, vqj, jb->rfe, &jb->luma_ip); ++ ++ // Returns 0 if nothing to do, 1 if sync added ++#if RPI_WORKER_WAIT_PASS_0 ++ do_wait = vpu_qpu_job_add_sync_sem(vqj, &jb->sem); ++#else ++ if (vpu_qpu_job_add_sync_sem(vqj, &jb->sem) == 0) ++ sem_post(&jb->sem); ++#endif ++ ++ rpi_cache_flush_execute(jb->rfe); ++ ++ // Await progress as required ++ // jb->waited will only be clear if we have already tested the progress values ++ // (in worker_submit_job) and found we don't have to wait ++ if (jb->waited) ++ { ++ unsigned int i; ++ for (i = 0; i != FF_ARRAY_ELEMS(jb->progress_req); ++i) { ++ if (jb->progress_req[i] >= 0) { ++ ff_hevc_rpi_progress_wait_recon(s, jb, s->DPB + i, jb->progress_req[i]); ++ } ++ } ++ } ++ ++ vpu_qpu_job_finish(vqj); ++ ++ // We always work on a rectangular block ++ if (pred_y || pred_c) ++ { ++ rpi_cache_flush_add_frame_block(jb->rfe, s->frame, RPI_CACHE_FLUSH_MODE_INVALIDATE, ++ jb->bounds.x, jb->bounds.y, jb->bounds.w, jb->bounds.h, ++ ctx_vshift(s, 1), pred_y, pred_c); ++ } ++ ++ // If we have emulated VPU ops - do it here ++#if RPI_QPU_EMU_Y || RPI_QPU_EMU_C ++ if (av_rpi_is_sand8_frame(s->frame)) ++ { ++#if RPI_QPU_EMU_Y && RPI_QPU_EMU_C ++ ff_hevc_rpi_shader_c8(s, &jb->luma_ip, &jb->chroma_ip); ++#elif RPI_QPU_EMU_Y ++ ff_hevc_rpi_shader_c8(s, &jb->luma_ip, NULL); ++#else ++ ff_hevc_rpi_shader_c8(s, NULL, &jb->chroma_ip); ++#endif ++ } ++ else ++ { ++#if RPI_QPU_EMU_Y && RPI_QPU_EMU_C ++ ff_hevc_rpi_shader_c16(s, &jb->luma_ip, &jb->chroma_ip); ++#elif RPI_QPU_EMU_Y ++ ff_hevc_rpi_shader_c16(s, &jb->luma_ip, NULL); ++#else ++ ff_hevc_rpi_shader_c16(s, NULL, &jb->chroma_ip); ++#endif ++ } ++#endif ++ ++#if RPI_WORKER_WAIT_PASS_0 ++ if (do_wait) ++ rpi_sem_wait(&jb->sem); ++ rpi_cache_flush_execute(jb->rfe); ++#endif ++} ++ ++ ++static void rpi_free_inter_pred(HEVCRpiInterPredEnv * const ipe) ++{ ++ av_freep(&ipe->q); ++ gpu_free(&ipe->gptr); ++} ++ ++static HEVCRpiJob * job_new(void) ++{ ++ HEVCRpiJob * const jb = av_mallocz(sizeof(HEVCRpiJob)); ++ ++ if (jb == NULL) ++ return NULL; ++ ++ sem_init(&jb->sem, 0, 0); ++ jb->rfe = rpi_cache_flush_init(&jb->flush_buf); ++ ff_hevc_rpi_progress_init_wait(&jb->progress_wait); ++ ++ jb->intra.n = 0; ++ if ((jb->intra.cmds = av_mallocz(sizeof(HEVCPredCmd) * RPI_MAX_PRED_CMDS)) == NULL) ++ goto fail1; ++ ++ // * Sizeof the union structure might be overkill but at the moment it ++ // is correct (it certainly isn't going to be too small) ++ // Set max fill to slack/2 from the end of the Q ++ // If we exceed this in any Q then we will schedule by size (which should ++ // mean that we never use that Q again part from syncs) ++ // * Given how agressive the overflow resonse is we could maybe put the ++ // threshold even nearer the end, but I don't expect us to ever hit ++ // it on any real stream anyway. ++ ++ if (rpi_inter_pred_alloc(&jb->chroma_ip, ++ QPU_N_MAX, QPU_N_GRP, ++ QPU_C_COMMANDS * sizeof(qpu_mc_pred_c_t) + QPU_C_SYNCS * sizeof(uint32_t), ++ QPU_C_CMD_SLACK_PER_Q * sizeof(qpu_mc_pred_c_t) / 2) != 0) ++ goto fail2; ++ if (rpi_inter_pred_alloc(&jb->luma_ip, ++ QPU_N_MAX, QPU_N_GRP, ++ QPU_Y_COMMANDS * sizeof(qpu_mc_pred_y_t) + QPU_Y_SYNCS * sizeof(uint32_t), ++ QPU_Y_CMD_SLACK_PER_Q * sizeof(qpu_mc_pred_y_t) / 2) != 0) ++ goto fail3; ++ ++ return jb; ++ ++fail3: ++ rpi_free_inter_pred(&jb->luma_ip); ++fail2: ++ av_freep(&jb->intra.cmds); ++fail1: ++ ff_hevc_rpi_progress_kill_wait(&jb->progress_wait); ++ rpi_cache_flush_finish(jb->rfe); ++ sem_destroy(&jb->sem); ++ return NULL; ++} ++ ++static void job_delete(HEVCRpiJob * const jb) ++{ ++ worker_pic_free_one(jb); ++ ff_hevc_rpi_progress_kill_wait(&jb->progress_wait); ++ rpi_free_inter_pred(&jb->chroma_ip); ++ rpi_free_inter_pred(&jb->luma_ip); ++ av_freep(&jb->intra.cmds); ++ rpi_cache_flush_finish(jb->rfe); // Not really needed - should do nothing ++ sem_destroy(&jb->sem); ++ av_free(jb); ++} ++ ++static void jbg_delete(HEVCRpiJobGlobal * const jbg) ++{ ++ HEVCRpiJob * jb; ++ ++ if (jbg == NULL) ++ return; ++ ++ jb = jbg->free1; ++ while (jb != NULL) ++ { ++ HEVCRpiJob * const jb2 = jb; ++ jb = jb2->next; ++ job_delete(jb2); ++ } ++ ++ pthread_mutex_destroy(&jbg->lock); ++ av_free(jbg); ++} ++ ++static HEVCRpiJobGlobal * jbg_new(unsigned int job_count) ++{ ++ HEVCRpiJobGlobal * const jbg = av_mallocz(sizeof(HEVCRpiJobGlobal)); ++ if (jbg == NULL) ++ return NULL; ++ ++ pthread_mutex_init(&jbg->lock, NULL); ++ ++ while (job_count-- != 0) ++ { ++ HEVCRpiJob * const jb = job_new(); ++ if (jb == NULL) ++ goto fail; ++ ++ jb->next = jbg->free1; ++ jbg->free1 = jb; ++ } ++ ++ return jbg; ++ ++fail: ++ jbg_delete(jbg); ++ return NULL; ++} ++ ++static void rpi_job_ctl_delete(HEVCRpiJobCtl * const jbc) ++{ ++ HEVCRpiJobGlobal * jbg; ++ ++ if (jbc == NULL) ++ return; ++ ++ jbg = jbc->jbg; ++ ++ if (jbc->jb1 != NULL) ++ job_delete(jbc->jb1); ++ ++ pthread_mutex_destroy(&jbc->in_lock); ++ sem_destroy(&jbc->sem_out); ++ av_free(jbc); ++ ++ // Deref the global job context ++ if (jbg != NULL && atomic_fetch_add(&jbg->ref_count, -1) == 1) ++ jbg_delete(jbg); ++} ++ ++static HEVCRpiJobCtl * rpi_job_ctl_new(HEVCRpiJobGlobal *const jbg) ++{ ++ HEVCRpiJobCtl * const jbc = av_mallocz(sizeof(HEVCRpiJobCtl)); ++ ++ if (jbc == NULL) ++ return NULL; ++ ++ jbc->jbg = jbg; ++ atomic_fetch_add(&jbg->ref_count, 1); ++ ++ sem_init(&jbc->sem_out, 0, RPI_MAX_JOBS); ++ pthread_mutex_init(&jbc->in_lock, NULL); ++ ++ if ((jbc->jb1 = job_new()) == NULL) ++ goto fail; ++ jbc->jb1->jbc_local = jbc; ++ ++ return jbc; ++ ++fail: ++ rpi_job_ctl_delete(jbc); ++ return NULL; ++} ++ ++ ++ ++static av_cold void hevc_init_worker(HEVCRpiContext * const s) ++{ ++#if RPI_PASSES == 2 ++ pass_queue_init(s->passq + 1, s, worker_core2, &s->jbc->sem_out, 1); ++#elif RPI_PASSES == 3 ++ pass_queue_init(s->passq + 2, s, rpi_execute_dblk_cmds, &s->jbc->sem_out, 2); ++ pass_queue_init(s->passq + 1, s, rpi_execute_pred_cmds, &s->passq[2].sem_in, 1); ++#else ++#error Passes confused ++#endif ++ pass_queue_init(s->passq + 0, s, worker_core, &s->passq[1].sem_in, 0); ++ ++ pass_queues_start_all(s); ++} ++ ++static av_cold void hevc_exit_worker(HEVCRpiContext *s) ++{ ++ pass_queues_term_all(s); ++ ++ pass_queues_kill_all(s); ++ ++ rpi_job_ctl_delete(s->jbc); ++ s->jbc = NULL; ++} ++ ++ ++static int slice_start(const HEVCRpiContext * const s, HEVCRpiLocalContext *const lc) ++{ ++ const int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; ++ const int tiles = s->ps.pps->num_tile_rows * s->ps.pps->num_tile_columns; ++ const unsigned int tile_id = s->ps.pps->tile_id[ctb_addr_ts]; ++ ++ // Check for obvious disasters ++ if (ctb_addr_ts == 0 && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ // If dependant then ctb_addr_ts != 0 from previous check ++ if (s->sh.dependent_slice_segment_flag) { ++ int prev_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts - 1]; ++ if (s->tab_slice_address[prev_rs] != s->sh.slice_addr) { ++ av_log(s->avctx, AV_LOG_ERROR, "Previous slice segment missing\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ if (!s->ps.pps->entropy_coding_sync_enabled_flag && ++ tile_id + s->sh.num_entry_point_offsets >= tiles) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Entry points exceed tiles\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ // Tiled stuff must start at start of tile if it has multiple entry points ++ if (!s->ps.pps->entropy_coding_sync_enabled_flag && ++ s->sh.num_entry_point_offsets != 0 && ++ ctb_addr_ts != s->ps.pps->tile_pos_ts[tile_id]) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Multiple tiles in slice; slice start != tile start\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ ff_hevc_rpi_cabac_init_decoder(lc); ++ ++ // Setup any required decode vars ++ lc->cabac_init_req = !s->sh.dependent_slice_segment_flag; ++ ++// printf("SS: req=%d, sol=%d, sot=%d\n", lc->cabac_init_req, sol, sot); ++ lc->qp_y = s->sh.slice_qp; ++ ++ // General setup ++ lc->bt_line_no = 0; ++ lc->ts = ctb_addr_ts; ++ return 0; ++} ++ ++static int gen_entry_points(HEVCRpiContext * const s, const H2645NAL * const nal) ++{ ++ const GetBitContext * const gb = &s->HEVClc->gb; ++ RpiSliceHeader * const sh = &s->sh; ++ int i, j; ++ ++ const unsigned int length = nal->size; ++ unsigned int offset = ((gb->index) >> 3) + 1; // We have a bit & align still to come = +1 byte ++ unsigned int cmpt; ++ unsigned int startheader; ++ ++ if (sh->num_entry_point_offsets == 0) { ++ s->data = NULL; ++ return 0; ++ } ++ ++ // offset in slice header includes emulation prevention bytes. ++ // Unfortunately those have been removed by the time we get here so we ++ // have to compensate. The nal layer keeps a track of where they were. ++ for (j = 0, cmpt = 0, startheader = offset + sh->entry_point_offset[0]; j < nal->skipped_bytes; j++) { ++ if (nal->skipped_bytes_pos[j] >= offset && nal->skipped_bytes_pos[j] < startheader) { ++ startheader--; ++ cmpt++; ++ } ++ } ++ ++ for (i = 1; i < sh->num_entry_point_offsets; i++) { ++ offset += (sh->entry_point_offset[i - 1] - cmpt); ++ for (j = 0, cmpt = 0, startheader = offset + sh->entry_point_offset[i]; j < nal->skipped_bytes; j++) { ++ if (nal->skipped_bytes_pos[j] >= offset && nal->skipped_bytes_pos[j] < startheader) { ++ startheader--; ++ cmpt++; ++ } ++ } ++ if (sh->entry_point_offset[i] <= cmpt) { ++ av_log(s->avctx, AV_LOG_ERROR, "entry point offset <= skipped bytes\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ sh->size[i - 1] = sh->entry_point_offset[i] - cmpt; ++ sh->offset[i - 1] = offset; ++ } ++ ++ offset += sh->entry_point_offset[sh->num_entry_point_offsets - 1] - cmpt; ++ if (length < offset) { ++ av_log(s->avctx, AV_LOG_ERROR, "entry_point_offset table is corrupted\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ sh->size[sh->num_entry_point_offsets - 1] = length - offset; ++ sh->offset[sh->num_entry_point_offsets - 1] = offset; ++ ++ // Remember data start pointer as we won't have nal later ++ s->data = nal->data; ++ return 0; ++} ++ ++ ++// Return ++// < 0 Error ++// 0 OK ++// ++// jb->ctu_ts_last < 0 Job still filling ++// jb->ctu_ts_last >= 0 Job ready ++ ++static int fill_job(HEVCRpiContext * const s, HEVCRpiLocalContext *const lc, unsigned int max_blocks) ++{ ++ const unsigned int log2_ctb_size = s->ps.sps->log2_ctb_size; ++ const unsigned int ctb_size = (1 << log2_ctb_size); ++ HEVCRpiJob * const jb = lc->jb0; ++ int more_data = 1; ++ unsigned int ctb_addr_ts = lc->ts; ++ unsigned int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ unsigned int x_ctb = (ctb_addr_rs % s->ps.sps->ctb_width) << log2_ctb_size; ++ const unsigned int y_ctb = (ctb_addr_rs / s->ps.sps->ctb_width) << log2_ctb_size; ++ ++ lc->unit_done = 0; ++ ++ while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) ++ { ++ int q_full; ++ const unsigned int ctb_flags = s->ps.pps->ctb_ts_flags[ctb_addr_ts]; ++ ++ hls_decode_neighbour(s, lc, x_ctb, y_ctb, ctb_addr_ts); ++ ++ ff_hevc_rpi_cabac_init(s, lc, ctb_flags); ++ ++ hls_sao_param(s, lc, x_ctb >> log2_ctb_size, y_ctb >> log2_ctb_size); ++ ++ s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset; ++ s->deblock[ctb_addr_rs].tc_offset = s->sh.tc_offset; ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ ++ // Zap stashes if navail ++ if ((lc->ctb_avail & AVAIL_U) == 0) ++ zap_cabac_stash(s->cabac_stash_up + (x_ctb >> 3), log2_ctb_size - 3); ++ if ((lc->ctb_avail & AVAIL_L) == 0) ++ { ++ memset(lc->ipm_left, INTRA_DC, IPM_TAB_SIZE); ++ zap_cabac_stash(s->cabac_stash_left + (y_ctb >> 3), log2_ctb_size - 3); ++ } ++#if MVF_STASH_WIDTH > 64 ++ // Restore left mvf stash at start of tile if not at start of line ++ if ((ctb_flags & CTB_TS_FLAGS_SOTL) != 0 && x_ctb != 0 && !s->is_irap) ++ { ++ unsigned int i; ++ HEVCRpiMvField * dst = mvf_stash_ptr(s, lc, x_ctb - 1, 0); ++ const HEVCRpiMvField * src = s->mvf_left + (y_ctb >> LOG2_MIN_PU_SIZE); ++ for (i = 0; i != ctb_size >> LOG2_MIN_PU_SIZE; ++i) ++ { ++ *dst = *src++; ++ dst += MVF_STASH_WIDTH_PU; ++ } ++ } ++#endif ++ ++ // Set initial tu states ++ lc->tu.cu_qp_delta = 0; ++ lc->tu.is_cu_qp_delta_wanted = 0; ++ lc->tu.cu_chroma_qp_offset_wanted = 0; ++ ++ // Decode ++ more_data = hls_coding_quadtree(s, lc, x_ctb, y_ctb, log2_ctb_size, 0); ++ ++ if (ff_hevc_rpi_cabac_overflow(lc)) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Quadtree bitstream overread\n "); ++ more_data = AVERROR_INVALIDDATA; ++ } ++ ++ if (more_data < 0) { ++ s->tab_slice_address[ctb_addr_rs] = TAB_SLICE_ADDR_BROKEN; // Mark slice as broken ++ return more_data; ++ } ++ ++ if (more_data && ((ctb_flags & CTB_TS_FLAGS_EOT) != 0 || ++ (s->ps.pps->entropy_coding_sync_enabled_flag && (ctb_flags & CTB_TS_FLAGS_EOTL) != 0))) ++ { ++ if (ff_hevc_rpi_get_cabac_terminate(&lc->cc) < 0 || ++ ff_hevc_rpi_cabac_skip_bytes(&lc->cc, 0) == NULL) ++ { ++ av_log(s->avctx, AV_LOG_ERROR, "Error reading terminate el\n "); ++ return -1; ++ } ++ } ++ ++ // --- Post CTB processing ++ ++ // Stash rpl top/left for deblock that needs to remember such things cross-slice ++ s->rpl_up[x_ctb >> log2_ctb_size] = s->refPicList; ++ s->rpl_left[y_ctb >> log2_ctb_size] = s->refPicList; ++ ++ if (!s->is_irap) ++ { ++ // Copy MVF up to up-left & stash to up ++ { ++ const HEVCRpiMvField * src = mvf_stash_ptr(s, lc, x_ctb, ctb_size - 1); ++ HEVCRpiMvField * dst = s->mvf_up + (x_ctb >> LOG2_MIN_PU_SIZE); ++ ++ // printf("Stash: %d,%d, ctb_size=%d, %p->%p\n", x_ctb, y_ctb, ctb_size, src, dst); ++ ++ lc->mvf_ul[0] = dst[(ctb_size - 1) >> LOG2_MIN_PU_SIZE]; ++ memcpy(dst, src, (sizeof(*src)*ctb_size) >> LOG2_MIN_PU_SIZE); ++ } ++ // Stash sideways if end of tile line but not end of line (no point) ++ // ** Could/should do this @ end of fn ++#if MVF_STASH_WIDTH > 64 ++ if ((ctb_flags & (CTB_TS_FLAGS_EOTL | CTB_TS_FLAGS_EOL)) == CTB_TS_FLAGS_EOTL) ++#endif ++ { ++ unsigned int i; ++ const HEVCRpiMvField * src = mvf_stash_ptr(s, lc, x_ctb + ctb_size - 1, 0); ++ HEVCRpiMvField * dst = s->mvf_left + (y_ctb >> LOG2_MIN_PU_SIZE); ++ for (i = 0; i != ctb_size >> LOG2_MIN_PU_SIZE; ++i) ++ { ++ *dst++ = *src; ++ src += MVF_STASH_WIDTH_PU; ++ } ++ } ++ } ++ ++ if ((ctb_flags & CTB_TS_FLAGS_CSAVE) != 0) ++ ff_hevc_rpi_save_states(s, lc); ++ ++ // Report progress so we can use our MVs in other frames ++ if ((ctb_flags & CTB_TS_FLAGS_EOL) != 0) ++ ff_hevc_rpi_progress_signal_mv(s, y_ctb + ctb_size - 1); ++ ++ // End of line || End of tile line || End of tile ++ // (EoL covers end of frame for our purposes here) ++ q_full = ((ctb_flags & CTB_TS_FLAGS_EOTL) != 0); ++ ++ // Allocate QPU chunks on fixed size 64 pel boundries rather than ++ // whatever ctb_size is today. ++ // * We might quite like to continue to 64 pel vertical too but that ++ // currently confuses WPP ++ if (((x_ctb + ctb_size) & 63) == 0 || q_full) ++ { ++ int overflow = 0; ++ if (rpi_inter_pred_next_ctu(&jb->luma_ip) != 0) ++ overflow = 1; ++ if (rpi_inter_pred_next_ctu(&jb->chroma_ip) != 0) ++ overflow = 1; ++ if (overflow) ++ { ++ // * This is very annoying (and slow) to cope with in WPP so ++ // we treat it as an error there (no known stream triggers this ++ // with the current buffer sizes). Non-wpp should cope fine. ++ av_log(s->avctx, AV_LOG_WARNING, "%s: Q full before EoL\n", __func__); ++ q_full = 1; ++ } ++ } ++ ++ // Inc TS to next. ++ ctb_addr_ts++; ++ ctb_addr_rs++; ++ x_ctb += ctb_size; ++ ++ if (q_full) ++ { ++ // Do job ++ // Prep for submission ++ jb->ctu_ts_last = ctb_addr_ts - 1; // Was pre-inced ++ job_gen_bounds(s, jb); ++ break; ++ } ++ ++ // If max_blocks started as 0 then this will never be true ++ if (--max_blocks == 0) ++ break; ++ } ++ ++ lc->unit_done = (more_data <= 0); ++ lc->ts = ctb_addr_ts; ++ return 0; ++} ++ ++static void bt_lc_init(HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, const unsigned int n) ++{ ++ lc->context = s; ++ lc->jb0 = NULL; ++ lc->lc_n = n; ++ lc->bt_terminate = 0; ++ lc->bt_psem_out = NULL; ++ sem_init(&lc->bt_sem_in, 0, 0); ++} ++ ++#define TRACE_WPP 0 ++#if RPI_EXTRA_BIT_THREADS > 0 ++static inline unsigned int line_ts_width(const HEVCRpiContext * const s, unsigned int ts) ++{ ++ unsigned int rs = s->ps.pps->ctb_addr_ts_to_rs[ts]; ++ return s->ps.pps->column_width[s->ps.pps->col_idxX[rs % s->ps.sps->ctb_width]]; ++} ++ ++// Move local context parameters from an aux bit thread back to the main ++// thread at the end of a slice as processing is going to continue there. ++static void movlc(HEVCRpiLocalContext *const dst_lc, HEVCRpiLocalContext *const src_lc, const int is_dep) ++{ ++ if (src_lc == dst_lc) { ++ return; ++ } ++ ++ // Move the job ++ // We will still have an active job if the final line terminates early ++ // Dest should always be null by now ++ av_assert1(dst_lc->jb0 == NULL); ++ dst_lc->jb0 = src_lc->jb0; ++ src_lc->jb0 = NULL; ++ ++ // Always need to store where we are in the bitstream ++ dst_lc->ts = src_lc->ts; ++ dst_lc->gb = src_lc->gb; ++ // Cabac init request will be built at start of next slice ++ ++ // Need to store context if we might have a dependent seg ++ if (is_dep) ++ { ++ dst_lc->qPy_pred = src_lc->qPy_pred; ++ memcpy(dst_lc->ipm_left, src_lc->ipm_left, sizeof(src_lc->ipm_left)); ++ memcpy(dst_lc->cabac_state, src_lc->cabac_state, sizeof(src_lc->cabac_state)); ++ memcpy(dst_lc->stat_coeff, src_lc->stat_coeff, sizeof(src_lc->stat_coeff)); ++ } ++} ++ ++static inline int wait_bt_sem_in(HEVCRpiLocalContext * const lc) ++{ ++ rpi_sem_wait(&lc->bt_sem_in); ++ return lc->bt_terminate; ++} ++ ++// Do one WPP line ++// Will not work correctly over horizontal tile boundries - vertical should be OK ++static int rpi_run_one_line(HEVCRpiContext *const s, HEVCRpiLocalContext * const lc, const int is_first) ++{ ++ const int is_tile = lc->bt_is_tile; ++ const unsigned int tile_id = s->ps.pps->tile_id[lc->ts]; ++ const unsigned int line = lc->bt_line_no; ++ const unsigned int line_inc = lc->bt_line_inc; ++ const int is_last = (line >= lc->bt_last_line); ++ ++ const unsigned int ts_eol = lc->ts + (is_tile ? s->ps.pps->tile_size[tile_id] : lc->bt_line_width); ++ const unsigned int ts_next = ++ line + line_inc > (unsigned int)s->sh.num_entry_point_offsets ? ++ INT_MAX : ++ is_tile ? ++ s->ps.pps->tile_pos_ts[tile_id + line_inc] : ++ lc->ts + lc->bt_line_width * line_inc; ++ // Tile wants line, WPP a few CTUs (must be >= 2 for cabac context to work) ++ const unsigned int partial_size = is_tile ? line_ts_width(s, lc->ts) : 2; ++ unsigned int ts_prev; ++ int loop_n = 0; ++ int err = 0; ++ ++ av_assert1(line <= s->sh.num_entry_point_offsets); ++ ++#if TRACE_WPP ++ printf("%s[%d]: Start %s: tile=%d, line=%d/%d/%d, ts=%d/%d/%d, width=%d, jb=%p\n", __func__, ++ lc->lc_n, is_tile ? "Tile" : "WPP", tile_id, ++ line, lc->bt_last_line, s->sh.num_entry_point_offsets, ++ lc->ts, ts_eol, ts_next, partial_size, lc->jb0); ++#endif ++ if (line != 0) ++ { ++ const uint8_t * const data = s->data + s->sh.offset[line - 1]; ++ const unsigned int len = s->sh.size[line - 1]; ++ if ((err = init_get_bits8(&lc->gb, data, len)) < 0) ++ return err; ++ ++ ff_init_cabac_decoder(&lc->cc, data, len); ++ } ++ ++ // We should never be processing a dependent slice here so reset is good ++ // ?? These probably shouldn't be needed (as they should be set by later ++ // logic) but do seem to be required ++ lc->qp_y = s->sh.slice_qp; ++ ++ do ++ { ++ if (!is_last && loop_n > 1) { ++#if TRACE_WPP ++ printf("%s[%d]: %sPoke %p\n", __func__, lc->lc_n, err == 0 ? "" : "ERR: ", lc->bt_psem_out); ++#endif ++ sem_post(lc->bt_psem_out); ++ } ++ // The wait for loop_n == 0 has been done in bit_thread ++ if (!is_first && loop_n != 0) ++ { ++#if TRACE_WPP ++ printf("%s[%d]: %sWait %p\n", __func__, lc->lc_n, err == 0 ? "" : "ERR: ", &lc->bt_sem_in); ++#endif ++ if (wait_bt_sem_in(lc) != 0) ++ return AVERROR_EXIT; ++ } ++ ++#if TRACE_WPP ++ { ++ int n; ++ sem_getvalue(&lc->bt_sem_in, &n); ++ printf("%s[%d]: ts=%d, sem=%d %p\n", __func__, lc->lc_n, lc->ts, n, &lc->bt_sem_in); ++ } ++#endif ++ ++ ts_prev = lc->ts; ++ ++ // If we have had an error - do no further decode but do continue ++ // moving signals around so the other threads continue to operate ++ // correctly (or at least as correctly as they can with this line missing) ++ // ++ // Errors in WPP/Tile are less fatal than normal as we have a good idea ++ // of how to restart on the next line so there is no need to give up totally ++ if (err != 0) ++ { ++ lc->unit_done = 0; ++ lc->ts += partial_size; ++ } ++ else ++ { ++ worker_pass0_ready(s, lc); ++ ++ if ((err = fill_job(s, lc, partial_size)) < 0 || ++ (lc->ts < ts_eol && !is_last && (lc->ts != ts_prev + partial_size || lc->unit_done))) ++ { ++ if (err == 0) { ++ av_log(s->avctx, AV_LOG_ERROR, "Unexpected end of tile/wpp section\n"); ++ err = AVERROR_INVALIDDATA; ++ } ++ worker_free(s, lc); ++ lc->ts = ts_prev + partial_size; // Pretend we did all that ++ lc->unit_done = 0; ++ } ++ else if (is_tile) ++ { ++ worker_submit_job(s, lc); ++ } ++ } ++ ++ ++loop_n; ++ } while (lc->ts < ts_eol && !lc->unit_done); ++ ++ // If we are on the last line & we didn't get a whole line we must wait for ++ // and sink the sem_posts from the line above / tile to the left. ++ while ((ts_prev += partial_size) < ts_eol) ++ { ++#if TRACE_WPP ++ printf("%s[%d]: EOL Wait: ts=%d %p\n", __func__, lc->lc_n, ts_prev, &lc->bt_sem_in); ++#endif ++ if (wait_bt_sem_in(lc) != 0) ++ return AVERROR_EXIT; ++ } ++ ++ lc->bt_line_no += line_inc; ++ ++ if (!is_tile && err == 0) ++ worker_submit_job(s, lc); ++ ++ if (!is_last) { ++ lc->ts = ts_next; ++ ++#if TRACE_WPP ++ printf("%s[%d]: Poke post submit %p\n", __func__, lc->lc_n, lc->bt_psem_out); ++#endif ++ sem_post(lc->bt_psem_out); ++ if (loop_n > 1) { ++#if TRACE_WPP ++ printf("%s[%d]: Poke post submit2 %p\n", __func__, lc->lc_n, lc->bt_psem_out); ++#endif ++ sem_post(lc->bt_psem_out); ++ } ++ } ++ else ++ { ++ movlc(s->HEVClcList[0], lc, s->ps.pps->dependent_slice_segments_enabled_flag); // * & not EoT ++#if MVF_STASH_WIDTH > 64 ++ // Horrid calculations to work out what we want but luckily this should almost never execute ++ // **** Move to movlc ++ if (!s->is_irap) ++ { ++ const unsigned int ctb_flags = s->ps.pps->ctb_ts_flags[lc->ts]; ++ if ((ctb_flags & CTB_TS_FLAGS_EOTL) == 0) // If EOTL then we have already stashed mvf ++ { ++ const unsigned int x_ctb = ((s->ps.pps->ctb_addr_ts_to_rs[lc->ts] % s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size) - 1; ++ unsigned int i; ++ const HEVCRpiMvField *s_mvf = lc->mvf_stash + ((x_ctb >> LOG2_MIN_PU_SIZE) & (MVF_STASH_WIDTH_PU - 1)); ++ HEVCRpiMvField *d_mvf = s->HEVClcList[0]->mvf_stash + ((x_ctb >> LOG2_MIN_PU_SIZE) & (MVF_STASH_WIDTH_PU - 1)); ++ ++ for (i = 0; i != MVF_STASH_HEIGHT_PU; ++i) ++ { ++ *d_mvf = *s_mvf; ++ d_mvf += MVF_STASH_WIDTH_PU; ++ s_mvf += MVF_STASH_WIDTH_PU; ++ } ++ ++ } ++ } ++#endif ++ // When all done poke the thread 0 sem_in one final time ++#if TRACE_WPP ++ printf("%s[%d]: Poke final %p\n", __func__, lc->lc_n, &s->HEVClcList[0]->bt_sem_in); ++#endif ++ sem_post(&s->HEVClcList[0]->bt_sem_in); ++ } ++ ++#if TRACE_WPP ++ printf("%s[%d]: End. dep=%d\n", __func__, lc->lc_n, s->ps.pps->dependent_slice_segments_enabled_flag); ++#endif ++ return err; ++} ++ ++static void wpp_setup_lcs(HEVCRpiContext * const s) ++{ ++ unsigned int ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; ++ const unsigned int line_width = line_ts_width(s, ts); ++ ++ for (int i = 0; i <= s->sh.num_entry_point_offsets && i < RPI_BIT_THREADS; ++i) ++ { ++ HEVCRpiLocalContext * const lc = s->HEVClcList[i]; ++ lc->ts = ts; ++ lc->bt_is_tile = 0; ++ lc->bt_line_no = i; ++ lc->bt_line_width = line_width; ++ lc->bt_last_line = s->sh.num_entry_point_offsets; ++ lc->bt_line_inc = RPI_BIT_THREADS; ++ ts += line_width; ++ } ++} ++ ++ ++// Can only process tile single row at once ++static void tile_one_row_setup_lcs(HEVCRpiContext * const s, unsigned int slice_row) ++{ ++ const HEVCRpiPPS * const pps = s->ps.pps; ++ const unsigned int ts0 = pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr]; ++ const unsigned int tile0 = pps->tile_id[ts0]; ++ const unsigned int col0 = tile0 % pps->num_tile_columns; ++ ++ const unsigned int col = (slice_row == 0) ? col0 : 0; ++ unsigned int line = slice_row * pps->num_tile_columns - col0 + col; ++ const unsigned int last_line = FFMIN( ++ line + pps->num_tile_columns - 1 - col, s->sh.num_entry_point_offsets); ++ ++ const unsigned int par = ++ FFMIN(RPI_BIT_THREADS, last_line + 1 - line); ++#if TRACE_WPP ++ printf("ts0=%d, ents=%d, row=%d, tiles=%dx%d, col=%d, par=%d, line=%d/%d\n", ts0, s->sh.num_entry_point_offsets, slice_row, ++ pps->num_tile_columns, pps->num_tile_rows, col, par, line, last_line); ++#endif ++ for (unsigned int i = 0; i != par; ++i, ++line) ++ { ++ HEVCRpiLocalContext * const lc = s->HEVClcList[i]; ++ const unsigned int tile = tile0 + line; ++ ++ lc->ts = pps->tile_pos_ts[tile]; ++ lc->bt_line_no = line; ++ lc->bt_is_tile = 1; ++ lc->bt_line_width = line_ts_width(s, lc->ts); ++ lc->bt_last_line = last_line; ++ lc->bt_line_inc = par; ++ } ++} ++ ++ ++static void * bit_thread(void * v) ++{ ++ HEVCRpiLocalContext * const lc = v; ++ HEVCRpiContext *const s = lc->context; ++ ++ while (wait_bt_sem_in(lc) == 0) ++ { ++ int err; ++ ++ if ((err = rpi_run_one_line(s, lc, 0)) < 0) { // Never first tile/wpp ++ if (lc->bt_terminate) { ++ av_log(s->avctx, AV_LOG_ERROR, "%s: Unexpected termination\n", __func__); ++ break; ++ } ++ av_log(s->avctx, AV_LOG_WARNING, "%s: Decode failure: %d\n", __func__, err); ++ } ++ } ++ ++ return NULL; ++} ++ ++static int bit_threads_start(HEVCRpiContext * const s) ++{ ++ if (s->bt_started) ++ return 0; ++ ++ for (int i = 1; i < RPI_BIT_THREADS; ++i) ++ { ++ // lc[0] belongs to the main thread - this sets up lc[1..RPI_BIT_THREADS] ++ if (s->HEVClcList[i] == NULL) { ++ if ((s->HEVClcList[i] = av_mallocz(sizeof(*s->HEVClcList[0]))) == NULL) ++ return -1; ++ } ++ ++ bt_lc_init(s, s->HEVClcList[i], i); ++ job_lc_init(s->HEVClcList[i]); ++ } ++ ++ // Link the sems in a circle ++ for (int i = 0; i < RPI_BIT_THREADS - 1; ++i) ++ s->HEVClcList[i]->bt_psem_out = &s->HEVClcList[i + 1]->bt_sem_in; ++ s->HEVClcList[RPI_BIT_THREADS - 1]->bt_psem_out = &s->HEVClcList[0]->bt_sem_in; ++ ++ // Init all lc before starting any threads ++ for (int i = 0; i < RPI_EXTRA_BIT_THREADS; ++i) ++ { ++ if (pthread_create(s->bit_threads + i, NULL, bit_thread, s->HEVClcList[i + 1]) < 0) ++ return -1; ++ } ++ ++ s->bt_started = 1; ++ return 0; ++} ++ ++static int bit_threads_kill(HEVCRpiContext * const s) ++{ ++ if (!s->bt_started) ++ return 0; ++ s->bt_started = 0; ++ ++ for (int i = 0; i < RPI_EXTRA_BIT_THREADS; ++i) ++ { ++ HEVCRpiLocalContext *const lc = s->HEVClcList[i + 1]; ++ if (lc == NULL) ++ break; ++ ++ lc->bt_terminate = 1; ++ sem_post(&lc->bt_sem_in); ++ pthread_join(s->bit_threads[i], NULL); ++ ++ sem_destroy(&lc->bt_sem_in); ++ job_lc_kill(lc); ++ } ++ return 0; ++} ++#endif ++ ++ ++// If we are at EoT and the row is shorter than the number of jobs ++// we can Q we have to wait for it finish otherwise we risk cache/QPU ++// disasters ++static inline int tile_needs_wait(const HEVCRpiContext * const s, const int n) ++{ ++ return ++ s->ps.pps->tile_wpp_inter_disable >= 2 && ++ s->sh.slice_type != HEVC_SLICE_I && ++ n >= 0 && ++ (s->ps.pps->ctb_ts_flags[n] & (CTB_TS_FLAGS_EOT | CTB_TS_FLAGS_EOL)) == CTB_TS_FLAGS_EOT; ++} ++ ++static int rpi_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++{ ++ HEVCRpiContext * const s = avctxt->priv_data; ++ HEVCRpiLocalContext * const lc = s->HEVClc; ++ int err; ++ ++ // Start of slice ++ if ((err = slice_start(s, lc)) != 0) ++ return err; ++ ++#if RPI_EXTRA_BIT_THREADS > 0 ++ ++ if (s->sh.offload_tiles) ++ { ++ unsigned int slice_row = 0; ++ ++#if TRACE_WPP ++ printf("%s: Do Tiles\n", __func__); ++#endif ++ // Generate & start extra bit threads if they aren't already running ++ bit_threads_start(s); ++ ++ do ++ { ++ // Reset lc lines etc. ++ tile_one_row_setup_lcs(s, slice_row); ++ ++#if TRACE_WPP ++ printf("%s: Row %d: Do 1st: line=%d/%d/%d\n", ++ __func__, slice_row, lc->bt_line_no, lc->bt_last_line, s->sh.num_entry_point_offsets); ++#endif ++ ++ rpi_run_one_line(s, lc, 1); // Kicks off the other threads ++#if TRACE_WPP ++ printf("%s: Row %d: Done 1st: line=%d/%d/%d\n", ++ __func__, slice_row, lc->bt_line_no, lc->bt_last_line, s->sh.num_entry_point_offsets); ++#endif ++ ++ while (lc->bt_line_no <= lc->bt_last_line) { ++ rpi_sem_wait(&lc->bt_sem_in); ++ rpi_run_one_line(s, lc, 0); ++ } ++#if TRACE_WPP ++ printf("%s: Done body\n", __func__); ++#endif ++ ++ // Wait for everything else to finish ++ rpi_sem_wait(&lc->bt_sem_in); ++ ++ ++slice_row; ++ } while (lc->bt_last_line < s->sh.num_entry_point_offsets); ++ ++ ++#if TRACE_WPP ++ printf("%s: Done wait: ts=%d\n", __func__, lc->ts); ++#endif ++ } ++ else if (s->sh.offload_wpp) ++ { ++#if TRACE_WPP ++ printf("%s: Do WPP\n", __func__); ++#endif ++ // Generate & start extra bit threads if they aren't already running ++ bit_threads_start(s); ++ ++ // Reset lc lines etc. ++ wpp_setup_lcs(s); ++ ++ rpi_run_one_line(s, lc, 1); // Kicks off the other threads ++#if TRACE_WPP ++ printf("%s: Done 1st\n", __func__); ++#endif ++ ++ while (lc->bt_line_no <= s->sh.num_entry_point_offsets) { ++ rpi_sem_wait(&lc->bt_sem_in); ++ rpi_run_one_line(s, lc, 0); ++ } ++#if TRACE_WPP ++ printf("%s: Done body\n", __func__); ++#endif ++ ++ // Wait for everything else to finish ++ rpi_sem_wait(&lc->bt_sem_in); ++ ++#if TRACE_WPP ++ printf("%s: Done wait: ts=%d\n", __func__, lc->ts); ++#endif ++ } ++ else ++#endif ++ { ++#if TRACE_WPP ++ printf("%s: Single start: ts=%d\n", __func__, lc->ts); ++#endif ++ // Single bit thread ++ do { ++ // Make sure we have space to prepare the next job ++ worker_pass0_ready(s, lc); ++ ++ if ((err = fill_job(s, lc, 0)) < 0) ++ goto fail; ++ ++ worker_submit_job(s, lc); ++ ++ if (tile_needs_wait(s, lc->ts - 1)) ++ worker_wait(s, lc); ++ ++ } while (!lc->unit_done); ++ ++#if TRACE_WPP ++ printf("%s: Single end: ts=%d\n", __func__, lc->ts); ++#endif ++ } ++ ++ // If we have reached the end of the frame or ++ // then wait for the worker to finish all its jobs ++ if (lc->ts >= s->ps.sps->ctb_size) ++ worker_wait(s, lc); ++ ++#if RPI_TSTATS ++ { ++ HEVCRpiStats *const ts = &s->tstats; ++ ++ printf("=== P: xy00:%5d/%5d/%5d/%5d h16gl:%5d/%5d w8gl:%5d/%5d y8m:%d\n B: xy00:%5d/%5d/%5d/%5d h16gl:%5d/%5d\n", ++ ts->y_pred1_xy, ts->y_pred1_x0, ts->y_pred1_y0, ts->y_pred1_x0y0, ++ ts->y_pred1_hgt16, ts->y_pred1_hle16, ts->y_pred1_wgt8, ts->y_pred1_wle8, ts->y_pred1_y8_merge, ++ ts->y_pred2_xy, ts->y_pred2_x0, ts->y_pred2_y0, ts->y_pred2_x0y0, ++ ts->y_pred2_hgt16, ts->y_pred2_hle16); ++ memset(ts, 0, sizeof(*ts)); ++ } ++#endif ++ ++ return lc->ts; ++ ++fail: ++ // Cleanup ++ av_log(s->avctx, AV_LOG_ERROR, "%s failed: err=%d\n", __func__, err); ++ // Free our job & wait for temination ++ worker_free(s, lc); ++ worker_wait(s, lc); ++ return err; ++} ++ ++ ++static void set_no_backward_pred(HEVCRpiContext * const s) ++{ ++ int i, j; ++ const RefPicList *const refPicList = s->refPicList; ++ ++ s->no_backward_pred_flag = 0; ++ if (s->sh.slice_type != HEVC_SLICE_B || !s->sh.slice_temporal_mvp_enabled_flag) ++ return; ++ ++ for (j = 0; j < 2; j++) { ++ for (i = 0; i < refPicList[j].nb_refs; i++) { ++ if (refPicList[j].list[i] > s->poc) { ++ s->no_backward_pred_flag = 1; ++ return; ++ } ++ } ++ } ++} ++ ++static int hls_slice_data(HEVCRpiContext * const s, const H2645NAL * const nal) ++{ ++ int err; ++ if ((err = gen_entry_points(s, nal)) < 0) ++ return err; ++ ++ set_no_backward_pred(s); ++ ++ return rpi_decode_entry(s->avctx, NULL); ++} ++ ++static int set_side_data(HEVCRpiContext *s) ++{ ++ AVFrame *out = s->ref->frame; ++ ++ if (s->sei.frame_packing.present && ++ s->sei.frame_packing.arrangement_type >= 3 && ++ s->sei.frame_packing.arrangement_type <= 5 && ++ s->sei.frame_packing.content_interpretation_type > 0 && ++ s->sei.frame_packing.content_interpretation_type < 3) { ++ AVStereo3D *stereo = av_stereo3d_create_side_data(out); ++ if (!stereo) ++ return AVERROR(ENOMEM); ++ ++ switch (s->sei.frame_packing.arrangement_type) { ++ case 3: ++ if (s->sei.frame_packing.quincunx_subsampling) ++ stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; ++ else ++ stereo->type = AV_STEREO3D_SIDEBYSIDE; ++ break; ++ case 4: ++ stereo->type = AV_STEREO3D_TOPBOTTOM; ++ break; ++ case 5: ++ stereo->type = AV_STEREO3D_FRAMESEQUENCE; ++ break; ++ } ++ ++ if (s->sei.frame_packing.content_interpretation_type == 2) ++ stereo->flags = AV_STEREO3D_FLAG_INVERT; ++ ++ if (s->sei.frame_packing.arrangement_type == 5) { ++ if (s->sei.frame_packing.current_frame_is_frame0_flag) ++ stereo->view = AV_STEREO3D_VIEW_LEFT; ++ else ++ stereo->view = AV_STEREO3D_VIEW_RIGHT; ++ } ++ } ++ ++ if (s->sei.display_orientation.present && ++ (s->sei.display_orientation.anticlockwise_rotation || ++ s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) { ++ double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); ++ AVFrameSideData *rotation = av_frame_new_side_data(out, ++ AV_FRAME_DATA_DISPLAYMATRIX, ++ sizeof(int32_t) * 9); ++ if (!rotation) ++ return AVERROR(ENOMEM); ++ ++ av_display_rotation_set((int32_t *)rotation->data, angle); ++ av_display_matrix_flip((int32_t *)rotation->data, ++ s->sei.display_orientation.hflip, ++ s->sei.display_orientation.vflip); ++ } ++ ++ // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 ++ // so the side data persists for the entire coded video sequence. ++ if (s->sei.mastering_display.present > 0 && ++ IS_IRAP(s) && s->no_rasl_output_flag) { ++ s->sei.mastering_display.present--; ++ } ++ if (s->sei.mastering_display.present) { ++ // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b ++ const int mapping[3] = {2, 0, 1}; ++ const int chroma_den = 50000; ++ const int luma_den = 10000; ++ int i; ++ AVMasteringDisplayMetadata *metadata = ++ av_mastering_display_metadata_create_side_data(out); ++ if (!metadata) ++ return AVERROR(ENOMEM); ++ ++ for (i = 0; i < 3; i++) { ++ const int j = mapping[i]; ++ metadata->display_primaries[i][0].num = s->sei.mastering_display.display_primaries[j][0]; ++ metadata->display_primaries[i][0].den = chroma_den; ++ metadata->display_primaries[i][1].num = s->sei.mastering_display.display_primaries[j][1]; ++ metadata->display_primaries[i][1].den = chroma_den; ++ } ++ metadata->white_point[0].num = s->sei.mastering_display.white_point[0]; ++ metadata->white_point[0].den = chroma_den; ++ metadata->white_point[1].num = s->sei.mastering_display.white_point[1]; ++ metadata->white_point[1].den = chroma_den; ++ ++ metadata->max_luminance.num = s->sei.mastering_display.max_luminance; ++ metadata->max_luminance.den = luma_den; ++ metadata->min_luminance.num = s->sei.mastering_display.min_luminance; ++ metadata->min_luminance.den = luma_den; ++ metadata->has_luminance = 1; ++ metadata->has_primaries = 1; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); ++ av_log(s->avctx, AV_LOG_DEBUG, ++ "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", ++ av_q2d(metadata->display_primaries[0][0]), ++ av_q2d(metadata->display_primaries[0][1]), ++ av_q2d(metadata->display_primaries[1][0]), ++ av_q2d(metadata->display_primaries[1][1]), ++ av_q2d(metadata->display_primaries[2][0]), ++ av_q2d(metadata->display_primaries[2][1]), ++ av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); ++ av_log(s->avctx, AV_LOG_DEBUG, ++ "min_luminance=%f, max_luminance=%f\n", ++ av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); ++ } ++ // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 ++ // so the side data persists for the entire coded video sequence. ++ if (s->sei.content_light.present > 0 && ++ IS_IRAP(s) && s->no_rasl_output_flag) { ++ s->sei.content_light.present--; ++ } ++ if (s->sei.content_light.present) { ++ AVContentLightMetadata *metadata = ++ av_content_light_metadata_create_side_data(out); ++ if (!metadata) ++ return AVERROR(ENOMEM); ++ metadata->MaxCLL = s->sei.content_light.max_content_light_level; ++ metadata->MaxFALL = s->sei.content_light.max_pic_average_light_level; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); ++ av_log(s->avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", ++ metadata->MaxCLL, metadata->MaxFALL); ++ } ++ ++ if (s->sei.a53_caption.a53_caption) { ++ AVFrameSideData* sd = av_frame_new_side_data(out, ++ AV_FRAME_DATA_A53_CC, ++ s->sei.a53_caption.a53_caption_size); ++ if (sd) ++ memcpy(sd->data, s->sei.a53_caption.a53_caption, s->sei.a53_caption.a53_caption_size); ++ av_freep(&s->sei.a53_caption.a53_caption); ++ s->sei.a53_caption.a53_caption_size = 0; ++ s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; ++ } ++ ++ if (s->sei.alternative_transfer.present && ++ av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && ++ s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { ++ s->avctx->color_trc = out->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; ++ } ++ ++ return 0; ++} ++ ++static int hevc_frame_start(HEVCRpiContext * const s) ++{ ++ int ret; ++ ++ memset(s->bs_horizontal, 0, s->bs_size * 2); // Does V too ++ memset(s->is_pcm, 0, s->ps.sps->pcm_width * s->ps.sps->pcm_height); ++ memset(s->tab_slice_address, -1, s->ps.sps->ctb_size * sizeof(*s->tab_slice_address)); ++ ++ // Only need to remember intra for CIP ++ if (!s->ps.pps->constrained_intra_pred_flag || s->is_irap) ++ s->is_intra = NULL; ++ else ++ { ++ s->is_intra = s->is_intra_store; ++ memset(s->is_intra, 0, s->ps.sps->pcm_width * s->ps.sps->pcm_height); ++ } ++ ++ s->is_decoded = 0; ++ s->first_nal_type = s->nal_unit_type; ++ ++ s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos); ++ ++ if (s->pkt.nb_nals > s->rpl_tab_size) ++ { ++ // In most cases it will be faster to free & realloc as that doesn't ++ // require (an unwanted) copy ++ av_freep(&s->rpl_tab); ++ s->rpl_tab_size = 0; ++ if ((s->rpl_tab = av_malloc(s->pkt.nb_nals * sizeof(*s->rpl_tab))) == NULL) ++ goto fail; ++ s->rpl_tab_size = s->pkt.nb_nals; ++ } ++ memset(s->rpl_tab, 0, s->pkt.nb_nals * sizeof(*s->rpl_tab)); ++ ++ ret = ff_hevc_rpi_set_new_ref(s, &s->frame, s->poc); ++ if (ret < 0) ++ goto fail; ++ ++ // Resize rpl_tab to max that we might want ++ ret = ff_hevc_rpi_frame_rps(s); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n"); ++ goto fail; ++ } ++ ++ s->ref->frame->key_frame = IS_IRAP(s); ++ ++ ret = set_side_data(s); ++ if (ret < 0) ++ goto fail; ++ ++ s->frame->pict_type = 3 - s->sh.slice_type; ++ ++ if (!IS_IRAP(s)) ++ ff_hevc_rpi_bump_frame(s); ++ ++ av_frame_unref(s->output_frame); ++ ret = ff_hevc_rpi_output_frame(s, s->output_frame, 0); ++ if (ret < 0) ++ goto fail; ++ ++ ff_thread_finish_setup(s->avctx); ++ ++ return 0; ++ ++fail: ++ if (s->ref) ++ ff_hevc_rpi_unref_frame(s, s->ref, ~0); ++ s->ref = NULL; ++ return ret; ++} ++ ++static inline int is_non_ref_unit_type(const unsigned int nal_unit_type) ++{ ++ // From Table 7-1 ++ return (nal_unit_type & ~0xe) == 0; // True for 0, 2, 4, 6, 8, 10, 12, 14 ++} ++ ++static int decode_nal_unit(HEVCRpiContext *s, const H2645NAL *nal) ++{ ++ GetBitContext * const gb = &s->HEVClc->gb; ++ int ctb_addr_ts, ret; ++ ++ *gb = nal->gb; ++ s->nal_unit_type = nal->type; ++ s->temporal_id = nal->temporal_id; ++ ++ switch (s->nal_unit_type) { ++ case HEVC_NAL_VPS: ++ ret = ff_hevc_rpi_decode_nal_vps(gb, s->avctx, &s->ps); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_SPS: ++ ret = ff_hevc_rpi_decode_nal_sps(gb, s->avctx, &s->ps, ++ s->apply_defdispwin); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_PPS: ++ ret = ff_hevc_rpi_decode_nal_pps(gb, s->avctx, &s->ps); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_SEI_PREFIX: ++ case HEVC_NAL_SEI_SUFFIX: ++ ret = ff_hevc_rpi_decode_nal_sei(gb, s->avctx, &s->sei, &s->ps, s->nal_unit_type); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_TRAIL_R: ++ case HEVC_NAL_TRAIL_N: ++ case HEVC_NAL_TSA_N: ++ case HEVC_NAL_TSA_R: ++ case HEVC_NAL_STSA_N: ++ case HEVC_NAL_STSA_R: ++ case HEVC_NAL_BLA_W_LP: ++ case HEVC_NAL_BLA_W_RADL: ++ case HEVC_NAL_BLA_N_LP: ++ case HEVC_NAL_IDR_W_RADL: ++ case HEVC_NAL_IDR_N_LP: ++ case HEVC_NAL_CRA_NUT: ++ case HEVC_NAL_RADL_N: ++ case HEVC_NAL_RADL_R: ++ case HEVC_NAL_RASL_N: ++ case HEVC_NAL_RASL_R: ++ ret = hls_slice_header(s); ++ if (ret < 0) ++ return ret; ++ ++ // The definition of _N unit types is "non-reference for other frames ++ // with the same temporal_id" so they may/will be ref frames for pics ++ // with a higher temporal_id. ++ s->used_for_ref = s->ps.sps->max_sub_layers > s->temporal_id + 1 || ++ !is_non_ref_unit_type(s->nal_unit_type); ++ s->offload_recon = s->threads_type != 0 && s->used_for_ref; ++ s->is_irap = IS_IRAP(s); ++ ++#if DEBUG_DECODE_N ++ { ++ static int z = 0; ++ if (IS_IDR(s)) { ++ z = 1; ++ } ++ if (z != 0 && z++ > DEBUG_DECODE_N) { ++ s->is_decoded = 0; ++ break; ++ } ++ } ++#endif ++ if ( ++ (s->avctx->skip_frame >= AVDISCARD_NONREF && !s->used_for_ref) || ++ (s->avctx->skip_frame >= AVDISCARD_BIDIR && s->sh.slice_type == HEVC_SLICE_B) || ++ (s->avctx->skip_frame >= AVDISCARD_NONINTRA && s->sh.slice_type != HEVC_SLICE_I) || ++ (s->avctx->skip_frame >= AVDISCARD_NONKEY && !IS_IRAP(s))) ++ { ++ s->is_decoded = 0; ++ break; ++ } ++ ++ if (s->sh.first_slice_in_pic_flag) { ++ if (s->max_ra == INT_MAX) { ++ if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { ++ s->max_ra = s->poc; ++ } else { ++ if (IS_IDR(s)) ++ s->max_ra = INT_MIN; ++ } ++ } ++ ++ if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) && ++ s->poc <= s->max_ra) { ++ s->is_decoded = 0; ++ break; ++ } else { ++ if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra) ++ s->max_ra = INT_MIN; ++ } ++ ++ ret = hevc_frame_start(s); ++ if (ret < 0) ++ return ret; ++ } else if (!s->ref) { ++ av_log(s->avctx, AV_LOG_ERROR, "First slice in a frame missing.\n"); ++ goto fail; ++ } ++ ++ if (s->nal_unit_type != s->first_nal_type) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Non-matching NAL types of the VCL NALUs: %d %d\n", ++ s->first_nal_type, s->nal_unit_type); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (!s->sh.dependent_slice_segment_flag && ++ s->sh.slice_type != HEVC_SLICE_I) { ++ ret = ff_hevc_rpi_slice_rpl(s); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Error constructing the reference lists for the current slice.\n"); ++ goto fail; ++ } ++ } ++ ++ ctb_addr_ts = hls_slice_data(s, nal); ++ if (ctb_addr_ts >= s->ps.sps->ctb_size) { ++ s->is_decoded = 1; ++ } ++ ++ if (ctb_addr_ts < 0) { ++ ret = ctb_addr_ts; ++ goto fail; ++ } ++ break; ++ case HEVC_NAL_EOS_NUT: ++ case HEVC_NAL_EOB_NUT: ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ break; ++ case HEVC_NAL_AUD: ++ case HEVC_NAL_FD_NUT: ++ break; ++ default: ++ av_log(s->avctx, AV_LOG_INFO, ++ "Skipping NAL unit %d\n", s->nal_unit_type); ++ } ++ ++ return 0; ++fail: ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return ret; ++ return 0; ++} ++ ++static int decode_nal_units(HEVCRpiContext *s, const uint8_t *buf, int length) ++{ ++ int i, ret = 0; ++ int eos_at_start = 1; ++ ++ s->ref = NULL; ++ s->last_eos = s->eos; ++ s->eos = 0; ++ ++ /* split the input packet into NAL units, so we know the upper bound on the ++ * number of slices in the frame */ ++ ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff, ++ s->nal_length_size, s->avctx->codec_id, 0, 0); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Error splitting the input into NAL units.\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < s->pkt.nb_nals; i++) { ++ if (s->pkt.nals[i].type == HEVC_NAL_EOB_NUT || ++ s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) { ++ if (eos_at_start) { ++ s->last_eos = 1; ++ } else { ++ s->eos = 1; ++ } ++ } else { ++ eos_at_start = 0; ++ } ++ } ++ ++ /* decode the NAL units */ ++ for (i = 0; i < s->pkt.nb_nals; i++) { ++ ret = decode_nal_unit(s, &s->pkt.nals[i]); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Error parsing NAL unit #%d.\n", i); ++ goto fail; ++ } ++ } ++ ++fail: // Also success path ++ if (s->ref != NULL) { ++ if (s->used_for_ref && s->threads_type != 0) { ++ ff_hevc_rpi_progress_signal_all_done(s); ++ } ++ else { ++ // Flush frame to real memory as we expect to be able to pass ++ // it straight on to mmal ++ flush_frame(s, s->frame); ++ } ++ } ++ return ret; ++} ++ ++static void print_md5(void *log_ctx, int level, uint8_t md5[16]) ++{ ++ int i; ++ for (i = 0; i < 16; i++) ++ av_log(log_ctx, level, "%02"PRIx8, md5[i]); ++} ++ ++static int verify_md5(HEVCRpiContext *s, AVFrame *frame) ++{ ++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); ++ int pixel_shift; ++ int i, j; ++ ++ if (!desc) ++ return AVERROR(EINVAL); ++ ++ pixel_shift = desc->comp[0].depth > 8; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Verifying checksum for frame with POC %d: ", ++ s->poc); ++ ++ /* the checksums are LE, so we have to byteswap for >8bpp formats ++ * on BE arches */ ++#if HAVE_BIGENDIAN ++ if (pixel_shift && !s->checksum_buf) { ++ av_fast_malloc(&s->checksum_buf, &s->checksum_buf_size, ++ FFMAX3(frame->linesize[0], frame->linesize[1], ++ frame->linesize[2])); ++ if (!s->checksum_buf) ++ return AVERROR(ENOMEM); ++ } ++#endif ++ ++ for (i = 0; frame->data[i]; i++) { ++ int width = s->avctx->coded_width; ++ int height = s->avctx->coded_height; ++ int w = (i == 1 || i == 2) ? (width >> desc->log2_chroma_w) : width; ++ int h = (i == 1 || i == 2) ? (height >> desc->log2_chroma_h) : height; ++ uint8_t md5[16]; ++ ++ av_md5_init(s->md5_ctx); ++ for (j = 0; j < h; j++) { ++ const uint8_t *src = frame->data[i] + j * frame_stride1(frame, 1); ++#if HAVE_BIGENDIAN ++ if (pixel_shift) { ++ s->bdsp.bswap16_buf((uint16_t *) s->checksum_buf, ++ (const uint16_t *) src, w); ++ src = s->checksum_buf; ++ } ++#endif ++ av_md5_update(s->md5_ctx, src, w << pixel_shift); ++ } ++ av_md5_final(s->md5_ctx, md5); ++ ++ if (!memcmp(md5, s->sei.picture_hash.md5[i], 16)) { ++ av_log (s->avctx, AV_LOG_DEBUG, "plane %d - correct ", i); ++ print_md5(s->avctx, AV_LOG_DEBUG, md5); ++ av_log (s->avctx, AV_LOG_DEBUG, "; "); ++ } else { ++ av_log (s->avctx, AV_LOG_ERROR, "mismatching checksum of plane %d - ", i); ++ print_md5(s->avctx, AV_LOG_ERROR, md5); ++ av_log (s->avctx, AV_LOG_ERROR, " != "); ++ print_md5(s->avctx, AV_LOG_ERROR, s->sei.picture_hash.md5[i]); ++ av_log (s->avctx, AV_LOG_ERROR, "\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "\n"); ++ ++ return 0; ++} ++ ++static int all_sps_supported(const HEVCRpiContext * const s) ++{ ++ for (unsigned int i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { ++ if (s->ps.sps_list[i] != NULL) ++ { ++ const HEVCRpiSPS * const sps = (const HEVCRpiSPS*)s->ps.sps_list[i]->data; ++ if (!is_sps_supported(sps)) ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static int hevc_rpi_decode_extradata(HEVCRpiContext *s, uint8_t *buf, int length, int first) ++{ ++ int ret, i; ++ ++ ret = ff_hevc_rpi_decode_extradata(buf, length, &s->ps, &s->sei, &s->is_nalff, ++ &s->nal_length_size, s->avctx->err_recognition, ++ s->apply_defdispwin, s->avctx); ++ if (ret < 0) ++ return ret; ++ ++ /* export stream parameters from the first SPS */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { ++ if (first && s->ps.sps_list[i]) { ++ const HEVCRpiSPS *sps = (const HEVCRpiSPS*)s->ps.sps_list[i]->data; ++ export_stream_params(s->avctx, &s->ps, sps); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int hevc_rpi_decode_frame(AVCodecContext *avctx, void *data, int *got_output, ++ AVPacket *avpkt) ++{ ++ int ret; ++ int new_extradata_size; ++ uint8_t *new_extradata; ++ HEVCRpiContext *s = avctx->priv_data; ++ ++ if (!avpkt->size) { ++ ret = ff_hevc_rpi_output_frame(s, data, 1); ++ if (ret < 0) ++ return ret; ++ ++ *got_output = ret; ++ return 0; ++ } ++ ++ new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, ++ &new_extradata_size); ++ if (new_extradata && new_extradata_size > 0) { ++ ret = hevc_rpi_decode_extradata(s, new_extradata, new_extradata_size, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ s->ref = NULL; ++ ret = decode_nal_units(s, avpkt->data, avpkt->size); ++ if (ret < 0) ++ return ret; ++ ++ /* verify the SEI checksum */ ++ if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && ++ s->sei.picture_hash.is_md5) { ++ ret = verify_md5(s, s->ref->frame); ++ if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { ++ ff_hevc_rpi_unref_frame(s, s->ref, ~0); ++ return ret; ++ } ++ } ++ s->sei.picture_hash.is_md5 = 0; ++ ++ if (s->is_decoded) { ++ av_log(avctx, AV_LOG_DEBUG, "Decoded frame with POC %d.\n", s->poc); ++ s->is_decoded = 0; ++ } ++ ++ if (s->output_frame->buf[0]) { ++ av_frame_move_ref(data, s->output_frame); ++ *got_output = 1; ++ } ++ ++ return avpkt->size; ++} ++ ++static int hevc_ref_frame(HEVCRpiContext *s, HEVCRpiFrame *dst, HEVCRpiFrame *src) ++{ ++ int ret; ++ ++ ret = ff_thread_ref_frame(&dst->tf, &src->tf); ++ if (ret < 0) ++ return ret; ++ ++ if (src->col_mvf_buf != NULL) ++ { ++ dst->col_mvf_buf = av_buffer_ref(src->col_mvf_buf); ++ if (!dst->col_mvf_buf) ++ goto fail; ++ } ++ dst->col_mvf = src->col_mvf; ++ ++ dst->poc = src->poc; ++ dst->flags = src->flags; ++ dst->sequence = src->sequence; ++ return 0; ++ ++fail: ++ ff_hevc_rpi_unref_frame(s, dst, ~0); ++ return AVERROR(ENOMEM); ++} ++ ++ ++static av_cold int hevc_decode_free(AVCodecContext *avctx) ++{ ++ HEVCRpiContext * const s = avctx->priv_data; ++ int i; ++ ++ pic_arrays_free(s); ++ ++ av_freep(&s->md5_ctx); ++ ++ av_freep(&s->cabac_save); ++ ++#if RPI_EXTRA_BIT_THREADS ++ bit_threads_kill(s); ++#endif ++ ++ hevc_exit_worker(s); ++ for (i = 0; i != 2; ++i) { ++ ff_hevc_rpi_progress_kill_state(s->progress_states + i); ++ } ++ job_lc_kill(s->HEVClc); ++ ++ av_freep(&s->sao_pixel_buffer_h[0]); // [1] & [2] allocated with [0] ++ av_freep(&s->sao_pixel_buffer_v[0]); ++ av_frame_free(&s->output_frame); ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ ff_hevc_rpi_unref_frame(s, &s->DPB[i], ~0); ++ av_frame_free(&s->DPB[i].frame); ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) ++ av_buffer_unref(&s->ps.vps_list[i]); ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) ++ av_buffer_unref(&s->ps.sps_list[i]); ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) ++ av_buffer_unref(&s->ps.pps_list[i]); ++ s->ps.sps = NULL; ++ s->ps.pps = NULL; ++ s->ps.vps = NULL; ++ ++ // Free separately from sLists as used that way by RPI WPP ++ for (i = 0; i < MAX_NB_THREADS && s->HEVClcList[i] != NULL; ++i) { ++ av_freep(s->HEVClcList + i); ++ } ++ s->HEVClc = NULL; // Allocated as part of HEVClcList ++ ++ ff_h2645_packet_uninit(&s->pkt); ++ ++ if (s->qpu_init_ok) ++ vpu_qpu_term(); ++ s->qpu_init_ok = 0; ++ ++ return 0; ++} ++ ++ ++static av_cold int hevc_init_context(AVCodecContext *avctx) ++{ ++ HEVCRpiContext *s = avctx->priv_data; ++ int i; ++ ++ s->avctx = avctx; ++ ++ s->HEVClc = av_mallocz(sizeof(HEVCRpiLocalContext)); ++ if (!s->HEVClc) ++ goto fail; ++ s->HEVClcList[0] = s->HEVClc; ++ ++ if (vpu_qpu_init() != 0) ++ goto fail; ++ s->qpu_init_ok = 1; ++ ++#if RPI_QPU_EMU_Y || RPI_QPU_EMU_C ++ { ++ static const uint32_t dframe[1] = {0x80808080}; ++ s->qpu_dummy_frame_emu = (const uint8_t *)dframe; ++ } ++#endif ++#if !RPI_QPU_EMU_Y || !RPI_QPU_EMU_C ++ s->qpu_dummy_frame_qpu = qpu_dummy(); ++#endif ++ ++ bt_lc_init(s, s->HEVClc, 0); ++ job_lc_init(s->HEVClc); ++ ++ for (i = 0; i != 2; ++i) { ++ ff_hevc_rpi_progress_init_state(s->progress_states + i); ++ } ++ ++ if ((s->cabac_save = av_malloc(sizeof(*s->cabac_save))) == NULL) ++ goto fail; ++ ++ if ((s->output_frame = av_frame_alloc()) == NULL) ++ goto fail; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ s->DPB[i].frame = av_frame_alloc(); ++ if (!s->DPB[i].frame) ++ goto fail; ++ s->DPB[i].tf.f = s->DPB[i].frame; ++ s->DPB[i].dpb_no = i; ++ } ++ ++ s->max_ra = INT_MAX; ++ ++ if ((s->md5_ctx = av_md5_alloc()) == NULL) ++ goto fail; ++ ++ s->context_initialized = 1; ++ s->eos = 0; ++ ++ ff_hevc_rpi_reset_sei(&s->sei); ++ ++ return 0; ++ ++fail: ++ av_log(s->avctx, AV_LOG_ERROR, "%s: Failed\n", __func__); ++ hevc_decode_free(avctx); ++ return AVERROR(ENOMEM); ++} ++ ++#if HAVE_THREADS ++static int hevc_update_thread_context(AVCodecContext *dst, ++ const AVCodecContext *src) ++{ ++ HEVCRpiContext *s = dst->priv_data; ++ HEVCRpiContext *s0 = src->priv_data; ++ int i, ret; ++ ++ av_assert0(s->context_initialized); ++ ++ // dst == src can happen according to the comments and in that case ++ // there is nothing to do here ++ if (dst == src) ++ return 0; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ ff_hevc_rpi_unref_frame(s, &s->DPB[i], ~0); ++ if (s0->DPB[i].frame->buf[0]) { ++ ret = hevc_ref_frame(s, &s->DPB[i], &s0->DPB[i]); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ ++ if (s->ps.sps != s0->ps.sps) ++ s->ps.sps = NULL; ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) { ++ av_buffer_unref(&s->ps.vps_list[i]); ++ if (s0->ps.vps_list[i]) { ++ s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]); ++ if (!s->ps.vps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { ++ av_buffer_unref(&s->ps.sps_list[i]); ++ if (s0->ps.sps_list[i]) { ++ s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]); ++ if (!s->ps.sps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) { ++ av_buffer_unref(&s->ps.pps_list[i]); ++ if (s0->ps.pps_list[i]) { ++ s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]); ++ if (!s->ps.pps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ if (s->ps.sps != s0->ps.sps) ++ if ((ret = set_sps(s, s0->ps.sps, src->pix_fmt)) < 0) ++ return ret; ++ ++ s->seq_decode = s0->seq_decode; ++ s->seq_output = s0->seq_output; ++ s->pocTid0 = s0->pocTid0; ++ s->max_ra = s0->max_ra; ++ s->eos = s0->eos; ++ s->no_rasl_output_flag = s0->no_rasl_output_flag; ++ ++ s->is_nalff = s0->is_nalff; ++ s->nal_length_size = s0->nal_length_size; ++ ++ s->threads_type = s0->threads_type; ++ ++ if (s0->eos) { ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ } ++ ++ s->sei.frame_packing = s0->sei.frame_packing; ++ s->sei.display_orientation = s0->sei.display_orientation; ++ s->sei.mastering_display = s0->sei.mastering_display; ++ s->sei.content_light = s0->sei.content_light; ++ s->sei.alternative_transfer = s0->sei.alternative_transfer; ++ ++ // * We do this here as it allows us to easily locate our parents ++ // global job pool, but there really should be a less nasty way ++ if (s->jbc == NULL) ++ { ++ av_assert0((s->jbc = rpi_job_ctl_new(s0->jbc->jbg)) != NULL); ++ hevc_init_worker(s); ++ } ++ ++ return 0; ++} ++#endif ++ ++#include ++static int qpu_ok(void) ++{ ++ static int is_pi3 = -1; ++ if (is_pi3 == -1) ++ { ++ struct stat sb; ++ is_pi3 = (stat("/dev/rpivid-intcmem", &sb) != 0); ++ } ++ return is_pi3; ++} ++ ++static av_cold int hevc_decode_init(AVCodecContext *avctx) ++{ ++ HEVCRpiContext *s = avctx->priv_data; ++ int ret; ++ ++ if (!qpu_ok()) ++ return AVERROR_DECODER_NOT_FOUND; ++ ++ if ((ret = hevc_init_context(avctx)) < 0) ++ return ret; ++ ++ // If we are a child context then stop now ++ // Everything after this point is either 1st decode setup or global alloc ++ // that must not be repeated ++ // Global info will be copied into children in update_thread_context (we ++ // can't do it here as we have no way of finding the parent context) ++ if (avctx->internal->is_copy) ++ return 0; ++ ++ // Job allocation requires VCSM alloc to work so ensure that we have it ++ // initialised by this point ++ { ++ HEVCRpiJobGlobal * const jbg = jbg_new(FFMAX(avctx->thread_count * 3, 5)); ++ if (jbg == NULL) { ++ av_log(s->avctx, AV_LOG_ERROR, "%s: Job global init failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ if ((s->jbc = rpi_job_ctl_new(jbg)) == NULL) { ++ av_log(s->avctx, AV_LOG_ERROR, "%s: Job ctl init failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ } ++ ++ hevc_init_worker(s); ++ ++ s->eos = 1; ++ ++ if (avctx->extradata_size > 0 && avctx->extradata) { ++ if ((ret = hevc_rpi_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1)) < 0) ++ goto fail; ++ ++ if (!all_sps_supported(s)) { ++ ret = AVERROR_DECODER_NOT_FOUND; ++ goto fail; ++ } ++ } ++ ++ if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1) ++ s->threads_type = FF_THREAD_FRAME; ++ else ++ s->threads_type = 0; ++ ++ return 0; ++ ++fail: ++ hevc_decode_free(avctx); ++ return ret; ++} ++ ++static void hevc_decode_flush(AVCodecContext *avctx) ++{ ++ HEVCRpiContext *s = avctx->priv_data; ++ ff_hevc_rpi_flush_dpb(s); ++ s->max_ra = INT_MAX; ++ s->eos = 1; ++} ++ ++typedef struct hwaccel_rpi3_qpu_env_s { ++ const AVClass *av_class; ++ AVZcEnvPtr zc; ++} hwaccel_rpi3_qpu_env_t; ++ ++static int hwaccel_alloc_frame(AVCodecContext *s, AVFrame *frame) ++{ ++ hwaccel_rpi3_qpu_env_t * const r3 = s->internal->hwaccel_priv_data; ++ int rv; ++ ++ if (av_rpi_zc_in_use(s)) ++ { ++ rv = s->get_buffer2(s, frame, 0); ++ } ++ else ++ { ++ rv = av_rpi_zc_get_buffer(r3->zc, frame); ++ if (rv == 0) ++ rv = av_rpi_zc_resolve_frame(frame, ZC_RESOLVE_ALLOC_VALID); // actually do the alloc ++ } ++ ++ if (rv == 0 && ++ (rv = ff_attach_decode_data(frame)) < 0) ++ { ++ av_frame_unref(frame); ++ } ++ ++ return rv; ++} ++ ++static int hwaccel_rpi3_qpu_free(AVCodecContext *avctx) ++{ ++ hwaccel_rpi3_qpu_env_t * const r3 = avctx->internal->hwaccel_priv_data; ++ av_rpi_zc_int_env_freep(&r3->zc); ++ return 0; ++} ++ ++static int hwaccel_rpi3_qpu_init(AVCodecContext *avctx) ++{ ++ hwaccel_rpi3_qpu_env_t * const r3 = avctx->internal->hwaccel_priv_data; ++ ++ if ((r3->zc = av_rpi_zc_int_env_alloc(avctx)) == NULL) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ av_log(avctx, AV_LOG_ERROR, "Rpi3 QPU init failed\n"); ++ hwaccel_rpi3_qpu_free(avctx); ++ return AVERROR(ENOMEM); ++} ++ ++ ++#define OFFSET(x) offsetof(HEVCRpiContext, x) ++#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) ++ ++ ++static const AVOption options[] = { ++ { "apply_defdispwin", "Apply default display window from VUI", OFFSET(apply_defdispwin), ++ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, PAR }, ++ { "strict-displaywin", "stricly apply default display window size", OFFSET(apply_defdispwin), ++ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, PAR }, ++ { NULL }, ++}; ++ ++static const AVClass hevc_rpi_decoder_class = { ++ .class_name = "HEVC RPI decoder", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++static const enum AVPixelFormat hevc_rpi_pix_fmts[] = { ++ AV_PIX_FMT_SAND128, ++ AV_PIX_FMT_SAND64_10, ++ AV_PIX_FMT_NONE ++}; ++ ++ ++static const AVHWAccel hwaccel_rpi3_qpu = { ++ .name = "Pi3 QPU Hwaccel", ++ .alloc_frame = hwaccel_alloc_frame, ++ .init = hwaccel_rpi3_qpu_init, ++ .uninit = hwaccel_rpi3_qpu_free, ++ .priv_data_size = sizeof(hwaccel_rpi3_qpu_env_t), ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_MT_SAFE, ++}; ++ ++static const AVCodecHWConfigInternal hevc_rpi_hw_config_sand128 = ++{ ++ .public = { ++ .pix_fmt = AV_PIX_FMT_SAND128, ++ .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, ++ .device_type = AV_HWDEVICE_TYPE_NONE, ++ }, ++ .hwaccel = &hwaccel_rpi3_qpu ++}; ++static const AVCodecHWConfigInternal hevc_rpi_hw_config_sand64_10 = ++{ ++ .public = { ++ .pix_fmt = AV_PIX_FMT_SAND64_10, ++ .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, ++ .device_type = AV_HWDEVICE_TYPE_NONE, ++ }, ++ .hwaccel = &hwaccel_rpi3_qpu ++}; ++ ++ ++static const AVCodecHWConfigInternal *hevc_rpi_hw_configs[] = { ++ &hevc_rpi_hw_config_sand128, ++ &hevc_rpi_hw_config_sand64_10, ++ NULL ++}; ++ ++ ++AVCodec ff_hevc_rpi_decoder = { ++ .name = "hevc_rpi", ++ .long_name = NULL_IF_CONFIG_SMALL("HEVC (rpi)"), ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .priv_data_size = sizeof(HEVCRpiContext), ++ .priv_class = &hevc_rpi_decoder_class, ++ .init = hevc_decode_init, ++ .close = hevc_decode_free, ++ .decode = hevc_rpi_decode_frame, ++ .flush = hevc_decode_flush, ++ .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context), ++ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | ++ AV_CODEC_CAP_HARDWARE | ++ AV_CODEC_CAP_AVOID_PROBING | ++#if 0 ++ // Debugging is often easier without threads getting in the way ++ 0, ++#warning H265 threading turned off ++#else ++ // We only have decent optimisation for frame - so only admit to that ++ AV_CODEC_CAP_FRAME_THREADS, ++#endif ++ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | ++ FF_CODEC_CAP_EXPORTS_CROPPING | ++ FF_CODEC_CAP_ALLOCATE_PROGRESS, ++ .pix_fmts = hevc_rpi_pix_fmts, ++ .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), ++ .hw_configs = hevc_rpi_hw_configs, ++// .wrapper_name = "hevc_rpi", ++}; ++ +diff --git a/libavcodec/rpi_hevcdec.h b/libavcodec/rpi_hevcdec.h +new file mode 100644 +index 0000000000..1f94d18673 +--- /dev/null ++++ b/libavcodec/rpi_hevcdec.h +@@ -0,0 +1,1091 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVCDEC_H ++#define AVCODEC_RPI_HEVCDEC_H ++ ++#include "config.h" ++ ++#include ++ ++#include "libavutil/buffer.h" ++ ++#include "avcodec.h" ++#include "bswapdsp.h" ++#include "cabac.h" ++#include "get_bits.h" ++#include "rpi_hevcpred.h" ++#include "h2645_parse.h" ++#include "hevc.h" ++#include "rpi_hevc_mv.h" ++#include "rpi_hevc_ps.h" ++#include "rpi_hevc_sei.h" ++#include "rpi_hevcdsp.h" ++#include "internal.h" ++#include "thread.h" ++#include "videodsp.h" ++ ++#if ARCH_ARM ++#include "arm/rpi_hevc_misc_neon.h" ++#endif ++ ++#define MAX_NB_THREADS 16 ++#define SHIFT_CTB_WPP 2 ++ ++//TODO: check if this is really the maximum ++#define MAX_TRANSFORM_DEPTH 5 ++ ++#define MAX_TB_SIZE 32 ++#define MAX_QP 51 ++#define DEFAULT_INTRA_TC_OFFSET 2 ++ ++#define HEVC_CONTEXTS 199 ++ ++#define MRG_MAX_NUM_CANDS 5 ++ ++#define HEVC_MAX_CTB_SIZE (1 << HEVC_MAX_LOG2_CTB_SIZE) // 64 ++ ++// Size of DPB array ++#define HEVC_DPB_ELS 32 ++ ++#define L0 0 ++#define L1 1 ++ ++#define EPEL_EXTRA_BEFORE 1 ++#define EPEL_EXTRA_AFTER 2 ++#define EPEL_EXTRA 3 ++#define QPEL_EXTRA_BEFORE 3 ++#define QPEL_EXTRA_AFTER 4 ++#define QPEL_EXTRA 7 ++ ++#define EDGE_EMU_BUFFER_STRIDE 80 ++ ++#include ++#include "rpi_qpu.h" ++ ++// Max jobs per frame thread. Actual usage will be limited by the size ++// of the global job pool ++// ?? Limits ++#define RPI_MAX_JOBS 8 ++ ++// This is the number of _extra_ bit threads - we will have ++// RPI_EXTRA_BIT_THREADS+1 threads actually doing the processing ++// ++// 0 is legitimate and will disable our WPP processing ++//#define RPI_EXTRA_BIT_THREADS 0 ++#define RPI_EXTRA_BIT_THREADS 2 ++ ++// Number of separate threads/passes in worker ++// 2 and 3 are the currently valid numbers ++// At the moment 3 seems fractionally faster ++//#define RPI_PASSES 2 ++#define RPI_PASSES 3 ++ ++// Print out various usage stats ++#define RPI_TSTATS 0 ++ ++// Define RPI_COMPRESS_COEFFS to 1 to send coefficients in compressed form ++#define RPI_COMPRESS_COEFFS 1 ++ ++// Wait for VPU/QPU to finish in worker pass 0 ++// If 0 then the wait is in pass 1 ++// ++// One might expect the better place to wait would be in pass 1 however ++// testing shows that pass 0 produces overall faster decode. ++// Interestingly it is QPU/VPU limited streams that seem to suffer ++// from pass 1 waits, CPU limited ones tend to show a very mild gain. ++// This define exists so it is easy to test this. ++#define RPI_WORKER_WAIT_PASS_0 1 ++ ++// Use ARM emulation of QPU pred ++// These are for debug only as the emulation makes only limited ++// effort to be fast ++#define RPI_QPU_EMU_Y 0 ++#define RPI_QPU_EMU_C 0 ++ ++// Max width & height we are prepared to consider ++// Sand frame shape calc becomes confused with large frames ++// Some buffer alloc also depends on this ++#define HEVC_RPI_MAX_WIDTH 2048 ++#define HEVC_RPI_MAX_HEIGHT 1088 ++ ++ ++// Min CTB size is 16 ++#define HEVC_RPI_MAX_CTBS ((HEVC_RPI_MAX_WIDTH + 15) / 16) * ((HEVC_RPI_MAX_HEIGHT + 15) / 16) ++ ++/** ++ * Value of the luma sample at position (x, y) in the 2D array tab. ++ */ ++#define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)]) ++#define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)]) ++ ++#define IS_IDR(s) ((s)->nal_unit_type == HEVC_NAL_IDR_W_RADL || (s)->nal_unit_type == HEVC_NAL_IDR_N_LP) ++#define IS_BLA(s) ((s)->nal_unit_type == HEVC_NAL_BLA_W_RADL || (s)->nal_unit_type == HEVC_NAL_BLA_W_LP || \ ++ (s)->nal_unit_type == HEVC_NAL_BLA_N_LP) ++#define IS_IRAP(s) ((s)->nal_unit_type >= 16 && (s)->nal_unit_type <= 23) ++ ++enum RPSType { ++ ST_CURR_BEF = 0, ++ ST_CURR_AFT, ++ ST_FOLL, ++ LT_CURR, ++ LT_FOLL, ++ NB_RPS_TYPE, ++}; ++ ++enum SyntaxElement { ++ SAO_MERGE_FLAG = 0, ++ SAO_TYPE_IDX, ++ SAO_EO_CLASS, ++ SAO_BAND_POSITION, ++ SAO_OFFSET_ABS, ++ SAO_OFFSET_SIGN, ++ END_OF_SLICE_FLAG, ++ SPLIT_CODING_UNIT_FLAG, ++ CU_TRANSQUANT_BYPASS_FLAG, ++ SKIP_FLAG, ++ CU_QP_DELTA, ++ PRED_MODE_FLAG, ++ PART_MODE, ++ PCM_FLAG, ++ PREV_INTRA_LUMA_PRED_FLAG, ++ MPM_IDX, ++ REM_INTRA_LUMA_PRED_MODE, ++ INTRA_CHROMA_PRED_MODE, ++ MERGE_FLAG, ++ MERGE_IDX, ++ INTER_PRED_IDC, ++ REF_IDX_L0, ++ REF_IDX_L1, ++ ABS_MVD_GREATER0_FLAG, ++ ABS_MVD_GREATER1_FLAG, ++ ABS_MVD_MINUS2, ++ MVD_SIGN_FLAG, ++ MVP_LX_FLAG, ++ NO_RESIDUAL_DATA_FLAG, ++ SPLIT_TRANSFORM_FLAG, ++ CBF_LUMA, ++ CBF_CB_CR, ++ TRANSFORM_SKIP_FLAG, ++ EXPLICIT_RDPCM_FLAG, ++ EXPLICIT_RDPCM_DIR_FLAG, ++ LAST_SIGNIFICANT_COEFF_X_PREFIX, ++ LAST_SIGNIFICANT_COEFF_Y_PREFIX, ++ LAST_SIGNIFICANT_COEFF_X_SUFFIX, ++ LAST_SIGNIFICANT_COEFF_Y_SUFFIX, ++ SIGNIFICANT_COEFF_GROUP_FLAG, ++ SIGNIFICANT_COEFF_FLAG, ++ COEFF_ABS_LEVEL_GREATER1_FLAG, ++ COEFF_ABS_LEVEL_GREATER2_FLAG, ++ COEFF_ABS_LEVEL_REMAINING, ++ COEFF_SIGN_FLAG, ++ LOG2_RES_SCALE_ABS, ++ RES_SCALE_SIGN_FLAG, ++ CU_CHROMA_QP_OFFSET_FLAG, ++ CU_CHROMA_QP_OFFSET_IDX, ++}; ++ ++enum PartMode { ++ PART_2Nx2N = 0, ++ PART_2NxN = 1, ++ PART_Nx2N = 2, ++ PART_NxN = 3, ++ PART_2NxnU = 4, ++ PART_2NxnD = 5, ++ PART_nLx2N = 6, ++ PART_nRx2N = 7, ++}; ++ ++enum PredMode { ++ MODE_INTER = 0, ++ MODE_INTRA, ++ MODE_SKIP, ++}; ++ ++enum InterPredIdc { ++ PRED_L0 = 0, ++ PRED_L1, ++ PRED_BI, ++}; ++ ++enum PredFlag { ++ PF_INTRA = 0, ++ PF_L0, ++ PF_L1, ++ PF_BI, ++}; ++ ++enum SAOType { ++ SAO_NOT_APPLIED = 0, ++ SAO_BAND, ++ SAO_EDGE, ++ SAO_APPLIED ++}; ++ ++enum SAOEOClass { ++ SAO_EO_HORIZ = 0, ++ SAO_EO_VERT, ++ SAO_EO_135D, ++ SAO_EO_45D, ++}; ++ ++enum ScanType { ++ SCAN_DIAG = 0, ++ SCAN_HORIZ, ++ SCAN_VERT, ++}; ++ ++typedef struct RefPicList { ++ struct HEVCRpiFrame *ref[HEVC_MAX_REFS]; ++ int list[HEVC_MAX_REFS]; ++ uint8_t isLongTerm[HEVC_MAX_REFS]; ++ int nb_refs; ++} RefPicList; ++ ++typedef struct RefPicListTab { ++ RefPicList refPicList[2]; ++} RefPicListTab; ++ ++typedef struct RpiCodingUnit { ++ unsigned int x; // Passed to deblock ++ unsigned int y; ++ unsigned int x_split; ++ unsigned int y_split; ++ ++ enum PredMode pred_mode; ///< PredMode ++ enum PartMode part_mode; ///< PartMode ++ ++ // Inferred parameters ++ uint8_t intra_split_flag; ///< IntraSplitFlag ++ uint8_t max_trafo_depth; ///< MaxTrafoDepth ++ uint8_t cu_transquant_bypass_flag; ++} RpiCodingUnit; ++ ++typedef struct RpiPredictionUnit { ++ uint8_t intra_pred_mode[4]; ++ uint8_t intra_pred_mode_c[4]; ++ uint8_t chroma_mode_c[4]; ++ uint8_t merge_flag; ++} RpiPredictionUnit; ++ ++typedef struct HEVCRpiTransformUnit { ++ int8_t cu_qp_delta; ++ ++ // Inferred parameters; ++ uint8_t intra_pred_mode; ++ uint8_t intra_pred_mode_c; ++ uint8_t chroma_mode_c; ++ uint8_t is_cu_qp_delta_wanted; ++ uint8_t cu_chroma_qp_offset_wanted; ++ const int8_t * qp_divmod6[3]; ++} HEVCRpiTransformUnit; ++ ++typedef struct DBParams { ++ int8_t beta_offset; // -12 to +12 ++ int8_t tc_offset; // -12 to +12 ++} DBParams; ++ ++#define HEVC_FRAME_FLAG_OUTPUT (1 << 0) ++#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1) ++#define HEVC_FRAME_FLAG_LONG_REF (1 << 2) ++#define HEVC_FRAME_FLAG_BUMPING (1 << 3) ++ ++struct HEVCRpiJob; ++ ++typedef struct HEVCRpiFrame { ++ AVFrame *frame; ++ ThreadFrame tf; ++ ColMvField *col_mvf; ++ int poc; ++ struct HEVCRpiFrame *collocated_ref; ++ ++ AVBufferRef *col_mvf_buf; ++ ++ /** ++ * A sequence counter, so that old frames are output first ++ * after a POC reset ++ */ ++ uint16_t sequence; ++ ++ /** ++ * A combination of HEVC_FRAME_FLAG_* ++ */ ++ uint8_t flags; ++ ++ // Entry no in DPB - can be used as a small unique ++ // frame identifier (within the current thread) ++ uint8_t dpb_no; ++} HEVCRpiFrame; ++ ++typedef struct HEVCRpiLocalContext { ++ HEVCRpiTransformUnit tu; ++ ++ CABACContext cc; ++ ++ // Vars that allow us to locate everything from just an lc ++ struct HEVCRpiContext * context; // ??? make const ??? ++ unsigned int lc_n; // lc list el no ++ ++ // Job wait links ++ struct HEVCRpiLocalContext * jw_next; ++ struct HEVCRpiLocalContext * jw_prev; ++ struct HEVCRpiLocalContext * ljw_next; ++ struct HEVCRpiLocalContext * ljw_prev; ++ struct HEVCRpiJob * volatile jw_job; ++ sem_t jw_sem; ++ ++ // ?? Wrap in structure ?? ++ sem_t bt_sem_in; ++ sem_t * bt_psem_out; ++ volatile int bt_terminate; ++ unsigned int ts; ++ unsigned int bt_last_line; // Last line in this bit_thread chunk ++ unsigned int bt_line_no; ++ unsigned int bt_line_width; ++ unsigned int bt_line_inc; ++ ++ struct HEVCRpiJob * jb0; ++ char unit_done; // Set once we have dealt with this slice ++ char bt_is_tile; ++ char last_progress_good; ++ char cabac_init_req; ++ ++ uint8_t cabac_state[HEVC_CONTEXTS]; ++ uint8_t stat_coeff[4]; ++ GetBitContext gb; ++ ++ uint8_t ct_depth; ++ int8_t qp_y; ++ int8_t curr_qp_y; ++ int8_t qPy_pred; ++ ++// N.B. Used by asm (neon) - do not change ++#define AVAIL_S_UR 0 ++#define AVAIL_S_U 1 ++#define AVAIL_S_UL 2 ++#define AVAIL_S_L 3 ++#define AVAIL_S_DL 4 ++ ++#define AVAIL_U (1 << AVAIL_S_U) ++#define AVAIL_L (1 << AVAIL_S_L) ++#define AVAIL_UL (1 << AVAIL_S_UL) ++#define AVAIL_UR (1 << AVAIL_S_UR) ++#define AVAIL_DL (1 << AVAIL_S_DL) ++ ++// Intra filters - same number space as avail ++#define FILTER_LIGHT 0x40 ++#define FILTER_STRONG 0x80 ++#define FILTER_EITHER (FILTER_LIGHT | FILTER_STRONG) ++ ++ uint8_t ctb_avail; ++ int end_of_ctb_x; ++ int end_of_ctb_y; ++ ++ RpiCodingUnit cu; ++ RpiPredictionUnit pu; ++ ++#define BOUNDARY_LEFT_SLICE (1 << 0) ++#define BOUNDARY_LEFT_TILE (1 << 1) ++#define BOUNDARY_UPPER_SLICE (1 << 2) ++#define BOUNDARY_UPPER_TILE (1 << 3) ++ /* properties of the boundary of the current CTB for the purposes ++ * of the deblocking filter */ ++ unsigned int boundary_flags; ++ ++#define IPM_TAB_SIZE (HEVC_MAX_CTB_SIZE >> LOG2_MIN_PU_SIZE) ++ uint8_t ipm_left[IPM_TAB_SIZE]; ++ uint8_t ipm_up[IPM_TAB_SIZE]; ++ ++//#define MVF_STASH_WIDTH 128 ++#define MVF_STASH_WIDTH 64 ++#define MVF_STASH_HEIGHT 64 ++#define MVF_STASH_WIDTH_PU (MVF_STASH_WIDTH >> LOG2_MIN_PU_SIZE) ++#define MVF_STASH_HEIGHT_PU (MVF_STASH_HEIGHT >> LOG2_MIN_PU_SIZE) ++ HEVCRpiMvField mvf_ul[1]; ++ HEVCRpiMvField mvf_stash[MVF_STASH_WIDTH_PU * MVF_STASH_HEIGHT_PU]; ++ ++ /* +7 is for subpixel interpolation, *2 for high bit depths */ ++// DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; ++ /* The extended size between the new edge emu buffer is abused by SAO */ ++// DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer2)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; ++// DECLARE_ALIGNED(32, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); ++ ++} HEVCRpiLocalContext; ++ ++// Each block can have an intra prediction and an add_residual command ++// noof-cmds(2) * max-ctu height(64) / min-transform(4) * planes(3) * MAX_WIDTH ++ ++// Sand only has 2 planes (Y/C) ++#define RPI_MAX_PRED_CMDS (2*(HEVC_MAX_CTB_SIZE/4)*2*(HEVC_RPI_MAX_WIDTH/4)) ++ ++// Command for intra prediction and transform_add of predictions to coefficients ++enum rpi_pred_cmd_e ++{ ++ RPI_PRED_ADD_RESIDUAL, ++ RPI_PRED_ADD_RESIDUAL_U, // = RPI_PRED_TRANSFORM_ADD + c_idx ++ RPI_PRED_ADD_RESIDUAL_V, // = RPI_PRED_TRANSFORM_ADD + c_idx ++ RPI_PRED_ADD_RESIDUAL_C, // Merged U+V ++ RPI_PRED_ADD_DC, ++ RPI_PRED_ADD_DC_U, // Both U & V are effectively C ++ RPI_PRED_ADD_DC_V, ++ RPI_PRED_INTRA, ++ RPI_PRED_INTRA_C, ++ RPI_PRED_I_PCM, ++ RPI_PRED_CMD_MAX ++}; ++ ++typedef struct HEVCPredCmd { ++ uint8_t type; ++ uint8_t size; // log2 "size" used by all variants ++ uint8_t avail; // i_pred - but left here as they pack well ++ uint8_t dummy; ++ union { ++ struct { // TRANSFORM_ADD ++ uint8_t * dst; ++ const int16_t * buf; ++ uint16_t stride; // Should be good enough for all pic fmts we use ++ int16_t dc; ++ } ta; ++ struct { ++ uint8_t * dst; ++ uint32_t stride; ++ int dc; ++ } dc; ++ struct { // INTRA ++ uint16_t x; ++ uint16_t y; ++ enum IntraPredMode mode; ++ } i_pred; ++ struct { // I_PCM ++ uint16_t x; ++ uint16_t y; ++ const void * src; ++ uint32_t src_len; ++ } i_pcm; ++ }; ++} HEVCPredCmd; ++ ++union qpu_mc_pred_cmd_s; ++struct qpu_mc_pred_y_p_s; ++struct qpu_mc_src_s; ++ ++typedef struct HEVCRpiInterPredQ ++{ ++ union qpu_mc_pred_cmd_u *qpu_mc_base; ++ union qpu_mc_pred_cmd_u *qpu_mc_curr; ++ struct qpu_mc_src_s *last_l0; ++ struct qpu_mc_src_s *last_l1; ++ unsigned int load; ++ uint32_t code_setup; ++ uint32_t code_sync; ++ uint32_t code_exit; ++} HEVCRpiInterPredQ; ++ ++typedef struct HEVCRpiInterPredEnv ++{ ++ HEVCRpiInterPredQ * q; ++ uint8_t n; // Number of Qs ++ uint8_t n_grp; // Number of Q in a group ++ uint8_t curr; // Current Q number (0..n-1) ++ uint8_t used; // 0 if nothing in any Q, 1 otherwise ++ uint8_t used_grp; // 0 if nothing in any Q in the current group ++ unsigned int max_fill; ++ unsigned int min_gap; ++ GPU_MEM_PTR_T gptr; ++} HEVCRpiInterPredEnv; ++ ++typedef struct HEVCRpiIntraPredEnv { ++ unsigned int n; // Number of commands ++ HEVCPredCmd * cmds; ++} HEVCRpiIntraPredEnv; ++ ++typedef struct HEVCRpiCoeffEnv { ++ unsigned int n; ++#if RPI_COMPRESS_COEFFS ++ unsigned int packed; // Equal to 1 if coefficients should be being packed ++ unsigned int packed_n; // Value of n when packed was set equal to 0 (i.e. the amount that is sent compressed). Only valid if packed==0 ++#endif ++ int16_t * buf; ++} HEVCRpiCoeffEnv; ++ ++typedef struct HEVCRpiCoeffsEnv { ++ HEVCRpiCoeffEnv s[4]; ++ GPU_MEM_PTR_T gptr; ++ void * mptr; ++} HEVCRpiCoeffsEnv; ++ ++typedef struct HEVCRpiFrameProgressWait { ++ int req; ++ struct HEVCRpiFrameProgressWait * next; ++ sem_t sem; ++} HEVCRpiFrameProgressWait; ++ ++typedef struct HEVCRpiFrameProgressState { ++ struct HEVCRpiFrameProgressWait * first; ++ struct HEVCRpiFrameProgressWait * last; ++ pthread_mutex_t lock; ++} HEVCRpiFrameProgressState; ++ ++typedef struct RpiBlk ++{ ++ unsigned int x; ++ unsigned int y; ++ unsigned int w; ++ unsigned int h; ++} RpiBlk; ++ ++typedef struct HEVCRpiJob { ++ struct HEVCRpiJob * next; // Free chain ++ struct HEVCRpiJobCtl * jbc_local; ++ const HEVCRpiSPS * sps; // sps used to set up this job ++ ++ int waited; ++ int ctu_ts_first; ++ int ctu_ts_last; ++ RpiBlk bounds; // Bounding box of job ++ ++ struct qpu_mc_pred_y_p_s * last_y8_p; ++ struct qpu_mc_src_s * last_y8_l1; ++ rpi_cache_flush_env_t * rfe; ++ ++ HEVCRpiInterPredEnv chroma_ip; ++ HEVCRpiInterPredEnv luma_ip; ++ int16_t progress_req[HEVC_DPB_ELS]; // index by dpb_no ++ HEVCRpiIntraPredEnv intra; ++ HEVCRpiCoeffsEnv coeffs; ++ HEVCRpiFrameProgressWait progress_wait; ++ sem_t sem; ++ rpi_cache_buf_t flush_buf; ++} HEVCRpiJob; ++ ++struct HEVCRpiContext; ++ ++typedef void HEVCRpiWorkerFn(const struct HEVCRpiContext * const s, HEVCRpiJob * const jb); ++ ++typedef struct HEVCRpiPassQueue ++{ ++// int pending; ++ volatile int terminate; ++ sem_t sem_in; ++ sem_t * psem_out; ++ unsigned int job_n; ++ struct HEVCRpiContext * context; // Context pointer as we get to pass a single "void * this" to the thread ++ HEVCRpiWorkerFn * worker; ++ pthread_t thread; ++ uint8_t pass_n; // Pass number - debug ++ uint8_t started; ++} HEVCRpiPassQueue; ++ ++ ++struct HEVCRpiJobGlobal; ++ ++typedef struct HEVCRpiJobCtl ++{ ++ sem_t sem_out; ++ ++ HEVCRpiJob * volatile jb1; // The job associated with this frame if unallocated - NULL if allocated ++ struct HEVCRpiJobGlobal * jbg; ++ ++ HEVCRpiLocalContext * lcw_head; ++ HEVCRpiLocalContext * lcw_tail; ++ ++ pthread_mutex_t in_lock; ++ int offload_in; ++ ++ HEVCRpiJob *offloadq[RPI_MAX_JOBS]; ++} HEVCRpiJobCtl; ++ ++ ++typedef struct HEVCRpiJobGlobal ++{ ++ intptr_t ref_count; ++ pthread_mutex_t lock; ++ HEVCRpiJob * free1; // Singly linked list of free jobs ++ HEVCRpiLocalContext * wait_head; // Double linked list of lcs waiting for a job ++ HEVCRpiLocalContext * wait_good; // Last good tail ++ HEVCRpiLocalContext * wait_tail; ++ ++} HEVCRpiJobGlobal; ++ ++#define RPI_BIT_THREADS (RPI_EXTRA_BIT_THREADS + 1) ++ ++#if RPI_TSTATS ++typedef struct HEVCRpiStats { ++ int y_pred1_y8_merge; ++ int y_pred1_xy; ++ int y_pred1_x0; ++ int y_pred1_y0; ++ int y_pred1_x0y0; ++ int y_pred1_wle8; ++ int y_pred1_wgt8; ++ int y_pred1_hle16; ++ int y_pred1_hgt16; ++ int y_pred2_xy; ++ int y_pred2_x0; ++ int y_pred2_y0; ++ int y_pred2_x0y0; ++ int y_pred2_hle16; ++ int y_pred2_hgt16; ++} HEVCRpiStats; ++#endif ++ ++typedef struct HEVCRpiCabacState ++{ ++ uint8_t rice[4]; ++ uint8_t state[HEVC_CONTEXTS]; ++} HEVCRpiCabacState; ++ ++#define HEVC_RPI_BS_STRIDE1_PEL_SHIFT 6 // 64 pels ++#define HEVC_RPI_BS_STRIDE1_PELS (1U << HEVC_RPI_BS_STRIDE1_PEL_SHIFT) ++#define HEVC_RPI_BS_STRIDE1_PEL_MASK (HEVC_RPI_BS_STRIDE1_PELS - 1) ++#define HEVC_RPI_BS_ELS_PER_BYTE_SHIFT 2 // 4 els per byte ++#define HEVC_RPI_BS_PELS_PER_EL_SHIFT 2 // 4 pels per el ++#define HEVC_RPI_BS_PELS_PER_BYTE_SHIFT (HEVC_RPI_BS_PELS_PER_EL_SHIFT + HEVC_RPI_BS_ELS_PER_BYTE_SHIFT) ++#define HEVC_RPI_BS_STRIDE1_BYTE_SHIFT (HEVC_RPI_BS_STRIDE1_PEL_SHIFT - HEVC_RPI_BS_PELS_PER_BYTE_SHIFT) ++#define HEVC_RPI_BS_STRIDE1_BYTES (1U << HEVC_RPI_BS_STRIDE1_BYTE_SHIFT) ++#define HEVC_RPI_BS_Y_SHR 3 // 8 vertical pels per row ++#define HEVC_RPI_BS_COL_BYTES_SHR (HEVC_RPI_BS_Y_SHR - HEVC_RPI_BS_STRIDE1_BYTE_SHIFT) ++ ++typedef struct HEVCRpiContext { ++ const AVClass *c; // needed by private avoptions ++ AVCodecContext *avctx; ++ ++ uint8_t threads_type; ++ char qpu_init_ok; ++ ++ /** 1 if the independent slice segment header was successfully parsed */ ++ uint8_t slice_initialized; ++ char used_for_ref; // rpi ++ char is_irap; ++ char offload_recon; ++ uint8_t eos; ///< current packet contains an EOS/EOB NAL ++ uint8_t last_eos; ///< last packet contains an EOS/EOB NAL ++ uint8_t no_backward_pred_flag; ++ uint8_t is_decoded; ++ uint8_t no_rasl_output_flag; ++ ++ ++ /** ++ * Sequence counters for decoded and output frames, so that old ++ * frames are output first after a POC reset ++ */ ++ uint16_t seq_decode; ++ uint16_t seq_output; ++ ++ int width; ++ int height; ++ ++ HEVCRpiJobCtl * jbc; ++ // cabac stash ++ // b0 skip flag ++ // b1+ ct_depth ++ uint8_t * cabac_stash_left; ++ uint8_t * cabac_stash_up; ++ ++ // Function pointers ++#if RPI_QPU_EMU_Y || RPI_QPU_EMU_C ++ const uint8_t * qpu_dummy_frame_emu; ++#endif ++#if !RPI_QPU_EMU_Y || !RPI_QPU_EMU_C ++ uint32_t qpu_dummy_frame_qpu; // Not a frame - just a bit of memory ++#endif ++ HEVCRpiQpu qpu; ++ ++ HEVCRpiFrameProgressState progress_states[2]; ++ ++ HEVCRpiCabacState *cabac_save; ++ ++ AVFrame *frame; ++ AVFrame *output_frame; ++ uint8_t *sao_pixel_buffer_h[3]; ++ uint8_t *sao_pixel_buffer_v[3]; ++ ++ unsigned int col_mvf_stride; ++ AVBufferPool *col_mvf_pool; ++ ++ RpiSAOParams *sao; ++ DBParams *deblock; ++ enum HEVCNALUnitType nal_unit_type; ++ int temporal_id; ///< temporal_id_plus1 - 1 ++ HEVCRpiFrame *ref; ++ int poc; ++ int pocTid0; ++ int slice_idx; ///< number of the slice being currently decoded ++ int max_ra; ++ ++ int8_t *qp_y_tab; ++ ++ // Deblocking block strength bitmaps ++ unsigned int bs_stride2; ++ unsigned int bs_size; ++ uint8_t *bs_horizontal; ++ uint8_t *bs_vertical; ++ uint8_t *bsf_stash_up; ++ uint8_t *bsf_stash_left; ++ ++#if HEVC_RPI_MAX_CTBS >= 0xffff ++#define TAB_SLICE_ADDR_BROKEN ~(uint32_t)0 ++ uint32_t *tab_slice_address; ++#else ++#define TAB_SLICE_ADDR_BROKEN ~(uint16_t)0 ++ uint16_t *tab_slice_address; ++#endif ++ ++ // Bitfield 1 bit per 8 pels (min pcm size) ++ uint8_t *is_pcm; ++ // Bitfield 1 bit per 8 pels (min cb size) ++ // Only needed for CIP as CIP processing is async to the main thread ++ uint8_t *is_intra; ++ ++ // PU ++ HEVCRpiMvField *mvf_up; ++ HEVCRpiMvField *mvf_left; ++ ++ const RefPicList **rpl_up; ++ const RefPicList **rpl_left; ++ RefPicList * refPicList; ++ ++ // CTB-level flags affecting loop filter operation ++ uint8_t *filter_slice_edges; ++ ++ /** used on BE to byteswap the lines for checksumming */ ++ uint8_t *checksum_buf; ++ int checksum_buf_size; ++ ++ const uint8_t *data; ++ ++ H2645Packet pkt; ++ // type of the first VCL NAL of the current frame ++ enum HEVCNALUnitType first_nal_type; ++ ++ uint8_t context_initialized; ++ int is_nalff; ///< this flag is != 0 if bitstream is encapsulated ++ ///< as a format defined in 14496-15 ++ int apply_defdispwin; ++ ++ int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) ++ int nuh_layer_id; ++ ++ struct AVMD5 *md5_ctx; ++ ++ RefPicListTab * rpl_tab; ++ unsigned int rpl_tab_size; ++ ++ uint8_t *is_intra_store; ++ ++ RpiSliceHeader sh; ++ ++ HEVCRpiParamSets ps; ++ ++ HEVCRpiLocalContext *HEVClc; ++ HEVCRpiLocalContext *HEVClcList[MAX_NB_THREADS]; ++ ++ HEVCRpiFrame DPB[HEVC_DPB_ELS]; ++ ++ ///< candidate references for the current frame ++ RefPicList rps[5]; ++ ++ HEVCRpiPredContext hpc; ++ HEVCDSPContext hevcdsp; ++ ++ HEVCSEIContext sei; ++ ++ // Put structures that allocate non-trivial storage at the end ++ // These are mostly used indirectly so position in the structure doesn't matter ++ HEVCRpiPassQueue passq[RPI_PASSES]; ++#if RPI_EXTRA_BIT_THREADS > 0 ++ int bt_started; ++ // This simply contains thread descriptors - task setup is held elsewhere ++ pthread_t bit_threads[RPI_EXTRA_BIT_THREADS]; ++#endif ++#if RPI_TSTATS ++ HEVCRpiStats tstats; ++#endif ++} HEVCRpiContext; ++ ++/** ++ * Mark all frames in DPB as unused for reference. ++ */ ++void ff_hevc_rpi_clear_refs(HEVCRpiContext *s); ++ ++/** ++ * Drop all frames currently in DPB. ++ */ ++void ff_hevc_rpi_flush_dpb(HEVCRpiContext *s); ++ ++/** ++ * Construct the reference picture sets for the current frame. ++ */ ++int ff_hevc_rpi_frame_rps(HEVCRpiContext *s); ++ ++/** ++ * Construct the reference picture list(s) for the current slice. ++ */ ++int ff_hevc_rpi_slice_rpl(HEVCRpiContext *s); ++ ++ ++/** ++ * Get the number of candidate references for the current frame. ++ */ ++int ff_hevc_rpi_frame_nb_refs(HEVCRpiContext *s); ++ ++int ff_hevc_rpi_set_new_ref(HEVCRpiContext *s, AVFrame **frame, int poc); ++ ++/** ++ * Find next frame in output order and put a reference to it in frame. ++ * @return 1 if a frame was output, 0 otherwise ++ */ ++int ff_hevc_rpi_output_frame(HEVCRpiContext *s, AVFrame *frame, int flush); ++ ++void ff_hevc_rpi_bump_frame(HEVCRpiContext *s); ++ ++void ff_hevc_rpi_unref_frame(HEVCRpiContext *s, HEVCRpiFrame *frame, int flags); ++ ++unsigned int ff_hevc_rpi_tb_avail_flags( ++ const HEVCRpiContext * const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x, const unsigned int y, const unsigned int w, const unsigned int h); ++ ++void ff_hevc_rpi_luma_mv_merge_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, int x0, int y0, int nPbW, ++ int nPbH, int log2_cb_size, int part_idx, ++ int merge_idx, HEVCRpiMvField * const mv); ++void ff_hevc_rpi_luma_mv_mvp_mode(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int nPbW, const unsigned int nPbH, ++ const unsigned int avail, ++ HEVCRpiMvField * const mv, ++ const unsigned int mvp_lx_flag, const unsigned int LX); ++void ff_hevc_rpi_set_qPy(const HEVCRpiContext * const s, HEVCRpiLocalContext * const lc, int xBase, int yBase); ++void ff_hevc_rpi_deblocking_boundary_strengths(const HEVCRpiContext * const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int log2_trafo_size, const int is_coded_block); ++int ff_hevc_rpi_hls_filter_blk(const HEVCRpiContext * const s, const RpiBlk bounds, const int eot); ++ ++extern const uint8_t ff_hevc_rpi_qpel_extra_before[4]; ++extern const uint8_t ff_hevc_rpi_qpel_extra_after[4]; ++extern const uint8_t ff_hevc_rpi_qpel_extra[4]; ++ ++int16_t * rpi_alloc_coeff_buf(HEVCRpiJob * const jb, const int buf_no, const int n); ++ ++// arm/hevc_misc_neon.S ++// Neon coeff zap fn ++#if HAVE_NEON ++extern void rpi_zap_coeff_vals_neon(int16_t * dst, unsigned int l2ts_m2); ++#endif ++ ++void ff_hevc_rpi_progress_wait_field(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const HEVCRpiFrame * const ref, const int val, const int field); ++ ++void ff_hevc_rpi_progress_signal_field(HEVCRpiContext * const s, const int val, const int field); ++ ++// All of these expect that s->threads_type == FF_THREAD_FRAME ++ ++static inline void ff_hevc_rpi_progress_wait_mv(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const HEVCRpiFrame * const ref, const int y) ++{ ++ if (s->threads_type != 0) ++ ff_hevc_rpi_progress_wait_field(s, jb, ref, y, 1); ++} ++ ++static inline void ff_hevc_rpi_progress_signal_mv(HEVCRpiContext * const s, const int y) ++{ ++ if (s->used_for_ref && s->threads_type != 0) ++ ff_hevc_rpi_progress_signal_field(s, y, 1); ++} ++ ++static inline void ff_hevc_rpi_progress_wait_recon(const HEVCRpiContext * const s, HEVCRpiJob * const jb, ++ const HEVCRpiFrame * const ref, const int y) ++{ ++ ff_hevc_rpi_progress_wait_field(s, jb, ref, y, 0); ++} ++ ++static inline void ff_hevc_rpi_progress_signal_recon(HEVCRpiContext * const s, const int y) ++{ ++ if (s->used_for_ref && s->threads_type != 0) ++ { ++ ff_hevc_rpi_progress_signal_field(s, y, 0); ++ } ++} ++ ++static inline void ff_hevc_rpi_progress_signal_all_done(HEVCRpiContext * const s) ++{ ++ ff_hevc_rpi_progress_signal_field(s, INT_MAX, 0); ++ ff_hevc_rpi_progress_signal_field(s, INT_MAX, 1); ++} ++ ++ ++// Set all done - signal nothing (used in missing refs) ++// Works for both rpi & non-rpi ++static inline void ff_hevc_rpi_progress_set_all_done(HEVCRpiFrame * const ref) ++{ ++ if (ref->tf.progress != NULL) ++ { ++ int * const p = (int *)ref->tf.progress->data; ++ p[0] = INT_MAX; ++ p[1] = INT_MAX; ++ } ++} ++ ++#define HEVC_RPI_420_ONLY 1 ++#define HEVC_RPI_SAND128_ONLY 1 ++ ++static inline unsigned int ctx_hshift(const HEVCRpiContext * const s, const int cidx) ++{ ++#if HEVC_RPI_420_ONLY ++ return cidx == 0 ? 0 : 1; ++#else ++ return s->ps.sps->hshift[cidx]; ++#endif ++} ++ ++static inline unsigned int ctx_vshift(const HEVCRpiContext * const s, const int cidx) ++{ ++#if HEVC_RPI_420_ONLY ++ return cidx == 0 ? 0 : 1; ++#else ++ return s->ps.sps->vshift[cidx]; ++#endif ++} ++ ++static inline int ctx_cfmt(const HEVCRpiContext * const s) ++{ ++#if HEVC_RPI_420_ONLY ++ return 1; ++#else ++ return s->ps.sps->chroma_format_idc; ++#endif ++} ++ ++static inline int frame_stride1(const AVFrame * const frame, const int c_idx) ++{ ++#if HEVC_RPI_SAND128_ONLY ++ return 128; ++#else ++ return frame->linesize[c_idx]; ++#endif ++} ++ ++#if HEVC_RPI_SAND128_ONLY ++// Propagate this decision to later zc includes ++#define RPI_ZC_SAND128_ONLY 1 ++#endif ++ ++#ifndef ff_hevc_rpi_copy_vert ++static inline void ff_hevc_rpi_copy_vert(uint8_t *dst, const uint8_t *src, ++ int pixel_shift, int height, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src) ++{ ++ int i; ++ switch (pixel_shift) ++ { ++ case 2: ++ for (i = 0; i < height; i++) { ++ *(uint32_t *)dst = *(uint32_t *)src; ++ dst += stride_dst; ++ src += stride_src; ++ } ++ break; ++ case 1: ++ for (i = 0; i < height; i++) { ++ *(uint16_t *)dst = *(uint16_t *)src; ++ dst += stride_dst; ++ src += stride_src; ++ } ++ break; ++ default: ++ for (i = 0; i < height; i++) { ++ *dst = *src; ++ dst += stride_dst; ++ src += stride_src; ++ } ++ break; ++ } ++} ++#endif ++ ++ ++#if MVF_STASH_WIDTH == 64 ++static inline HEVCRpiMvField* mvf_stash_ptr(const HEVCRpiContext *const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x, const unsigned int y) ++{ ++ const unsigned int mask_cs_hi = (~0U << s->ps.sps->log2_ctb_size); ++ return (HEVCRpiMvField*)(lc->mvf_stash + ((y & ~mask_cs_hi) >> LOG2_MIN_PU_SIZE) * MVF_STASH_WIDTH_PU + ((x & ~mask_cs_hi) >> LOG2_MIN_PU_SIZE)); ++} ++ ++static inline HEVCRpiMvField* mvf_ptr(const HEVCRpiContext *const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int x, const unsigned int y) ++{ ++ const unsigned int mask_cs_hi = (~0U << s->ps.sps->log2_ctb_size); ++ const unsigned int x0_ctb = x0 & mask_cs_hi; ++ const unsigned int y0_ctb = y0 & mask_cs_hi; ++ ++ return (HEVCRpiMvField *)((y < y0_ctb) ? ++ (x < x0_ctb ? lc->mvf_ul : s->mvf_up + (x >> LOG2_MIN_PU_SIZE)) : ++ (x < x0_ctb ? s->mvf_left + (y >> LOG2_MIN_PU_SIZE) : ++ lc->mvf_stash + ++ ((y & ~mask_cs_hi) >> LOG2_MIN_PU_SIZE) * MVF_STASH_WIDTH_PU + ++ ((x & ~mask_cs_hi) >> LOG2_MIN_PU_SIZE))); ++} ++ ++static inline unsigned int mvf_left_stride(const HEVCRpiContext *const s, ++ const unsigned int x0, ++ const unsigned int x) ++{ ++ const unsigned int mask_cs_hi = (~0U << s->ps.sps->log2_ctb_size); ++ const unsigned int x0_ctb = x0 & mask_cs_hi; ++ return x < x0_ctb ? 1 : MVF_STASH_WIDTH_PU; ++} ++ ++#else ++static inline HEVCRpiMvField* mvf_stash_ptr(const HEVCRpiContext *const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x, const unsigned int y) ++{ ++ const unsigned int mask_cs_hi = (~0U << s->ps.sps->log2_ctb_size); ++ return (HEVCRpiMvField*)(lc->mvf_stash + ((y & ~mask_cs_hi) >> LOG2_MIN_PU_SIZE) * MVF_STASH_WIDTH_PU + ((x >> LOG2_MIN_PU_SIZE) & (MVF_STASH_WIDTH_PU - 1))); ++} ++ ++static inline HEVCRpiMvField* mvf_ptr(const HEVCRpiContext *const s, const HEVCRpiLocalContext * const lc, ++ const unsigned int x0, const unsigned int y0, ++ const unsigned int x, const unsigned int y) ++{ ++ const unsigned int mask_cs_hi = (~0U << s->ps.sps->log2_ctb_size); ++ ++ const unsigned int x0_ctb = x0 & mask_cs_hi; ++ const unsigned int y0_ctb = y0 & mask_cs_hi; ++ ++ // If not in the same CTB for Y assume up ++ if (y < y0_ctb) { ++ // If not in the same CTB for X too assume up-left ++ return (HEVCRpiMvField *)(x < x0_ctb ? lc->mvf_ul : s->mvf_up + (x >> LOG2_MIN_PU_SIZE)); ++ } ++ return mvf_stash_ptr(s, lc, x, y); ++} ++ ++static inline unsigned int mvf_left_stride(const HEVCRpiContext *const s, ++ const unsigned int x0, ++ const unsigned int x) ++{ ++ return MVF_STASH_WIDTH_PU; ++} ++#endif ++ ++#endif /* AVCODEC_RPI_HEVCDEC_H */ +diff --git a/libavcodec/rpi_hevcdsp.c b/libavcodec/rpi_hevcdsp.c +new file mode 100644 +index 0000000000..87f3cc9d14 +--- /dev/null ++++ b/libavcodec/rpi_hevcdsp.c +@@ -0,0 +1,450 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2013 - 2014 Pierre-Edouard Lepere ++ * Copyright (C) 2018 John Cox, Ben Avison for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "rpi_hevcdsp.h" ++#include "rpi_hevc_mv.h" ++ ++static const int8_t transform[32][32] = { ++ { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, ++ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }, ++ { 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, ++ -4, -13, -22, -31, -38, -46, -54, -61, -67, -73, -78, -82, -85, -88, -90, -90 }, ++ { 90, 87, 80, 70, 57, 43, 25, 9, -9, -25, -43, -57, -70, -80, -87, -90, ++ -90, -87, -80, -70, -57, -43, -25, -9, 9, 25, 43, 57, 70, 80, 87, 90 }, ++ { 90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13, ++ 13, 38, 61, 78, 88, 90, 85, 73, 54, 31, 4, -22, -46, -67, -82, -90 }, ++ { 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89, ++ 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89 }, ++ { 88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22, ++ -22, -61, -85, -90, -73, -38, 4, 46, 78, 90, 82, 54, 13, -31, -67, -88 }, ++ { 87, 57, 9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87, ++ -87, -57, -9, 43, 80, 90, 70, 25, -25, -70, -90, -80, -43, 9, 57, 87 }, ++ { 85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31, ++ 31, 78, 90, 61, 4, -54, -88, -82, -38, 22, 73, 90, 67, 13, -46, -85 }, ++ { 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83, ++ 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83 }, ++ { 82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67, 4, 73, 88, 38, ++ -38, -88, -73, -4, 67, 90, 46, -31, -85, -78, -13, 61, 90, 54, -22, -82 }, ++ { 80, 9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80, ++ -80, -9, 70, 87, 25, -57, -90, -43, 43, 90, 57, -25, -87, -70, 9, 80 }, ++ { 78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46, ++ 46, 90, 38, -54, -90, -31, 61, 88, 22, -67, -85, -13, 73, 82, 4, -78 }, ++ { 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75, ++ 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75 }, ++ { 73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54, ++ -54, -85, 4, 88, 46, -61, -82, 13, 90, 38, -67, -78, 22, 90, 31, -73 }, ++ { 70, -43, -87, 9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70, ++ -70, 43, 87, -9, -90, -25, 80, 57, -57, -80, 25, 90, 9, -87, -43, 70 }, ++ { 67, -54, -78, 38, 85, -22, -90, 4, 90, 13, -88, -31, 82, 46, -73, -61, ++ 61, 73, -46, -82, 31, 88, -13, -90, -4, 90, 22, -85, -38, 78, 54, -67 }, ++ { 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, ++ 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64 }, ++ { 61, -73, -46, 82, 31, -88, -13, 90, -4, -90, 22, 85, -38, -78, 54, 67, ++ -67, -54, 78, 38, -85, -22, 90, 4, -90, 13, 88, -31, -82, 46, 73, -61 }, ++ { 57, -80, -25, 90, -9, -87, 43, 70, -70, -43, 87, 9, -90, 25, 80, -57, ++ -57, 80, 25, -90, 9, 87, -43, -70, 70, 43, -87, -9, 90, -25, -80, 57 }, ++ { 54, -85, -4, 88, -46, -61, 82, 13, -90, 38, 67, -78, -22, 90, -31, -73, ++ 73, 31, -90, 22, 78, -67, -38, 90, -13, -82, 61, 46, -88, 4, 85, -54 }, ++ { 50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50, ++ 50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50 }, ++ { 46, -90, 38, 54, -90, 31, 61, -88, 22, 67, -85, 13, 73, -82, 4, 78, ++ -78, -4, 82, -73, -13, 85, -67, -22, 88, -61, -31, 90, -54, -38, 90, -46 }, ++ { 43, -90, 57, 25, -87, 70, 9, -80, 80, -9, -70, 87, -25, -57, 90, -43, ++ -43, 90, -57, -25, 87, -70, -9, 80, -80, 9, 70, -87, 25, 57, -90, 43 }, ++ { 38, -88, 73, -4, -67, 90, -46, -31, 85, -78, 13, 61, -90, 54, 22, -82, ++ 82, -22, -54, 90, -61, -13, 78, -85, 31, 46, -90, 67, 4, -73, 88, -38 }, ++ { 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36, ++ 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36 }, ++ { 31, -78, 90, -61, 4, 54, -88, 82, -38, -22, 73, -90, 67, -13, -46, 85, ++ -85, 46, 13, -67, 90, -73, 22, 38, -82, 88, -54, -4, 61, -90, 78, -31 }, ++ { 25, -70, 90, -80, 43, 9, -57, 87, -87, 57, -9, -43, 80, -90, 70, -25, ++ -25, 70, -90, 80, -43, -9, 57, -87, 87, -57, 9, 43, -80, 90, -70, 25 }, ++ { 22, -61, 85, -90, 73, -38, -4, 46, -78, 90, -82, 54, -13, -31, 67, -88, ++ 88, -67, 31, 13, -54, 82, -90, 78, -46, 4, 38, -73, 90, -85, 61, -22 }, ++ { 18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18, ++ 18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18 }, ++ { 13, -38, 61, -78, 88, -90, 85, -73, 54, -31, 4, 22, -46, 67, -82, 90, ++ -90, 82, -67, 46, -22, -4, 31, -54, 73, -85, 90, -88, 78, -61, 38, -13 }, ++ { 9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9, ++ -9, 25, -43, 57, -70, 80, -87, 90, -90, 87, -80, 70, -57, 43, -25, 9 }, ++ { 4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90, ++ 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4 }, ++}; ++ ++DECLARE_ALIGNED(16, const int8_t, ff_hevc_rpi_epel_filters[7][4]) = { ++ { -2, 58, 10, -2}, ++ { -4, 54, 16, -2}, ++ { -6, 46, 28, -4}, ++ { -4, 36, 36, -4}, ++ { -4, 28, 46, -6}, ++ { -2, 16, 54, -4}, ++ { -2, 10, 58, -2}, ++}; ++ ++DECLARE_ALIGNED(16, const int8_t, ff_hevc_rpi_qpel_filters[3][16]) = { ++ { -1, 4,-10, 58, 17, -5, 1, 0, -1, 4,-10, 58, 17, -5, 1, 0}, ++ { -1, 4,-11, 40, 40,-11, 4, -1, -1, 4,-11, 40, 40,-11, 4, -1}, ++ { 0, 1, -5, 17, 58,-10, 4, -1, 0, 1, -5, 17, 58,-10, 4, -1} ++}; ++ ++#define BIT_DEPTH 8 ++#include "rpi_hevcdsp_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 9 ++#include "rpi_hevcdsp_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 10 ++#include "rpi_hevcdsp_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 12 ++#include "rpi_hevcdsp_template.c" ++#undef BIT_DEPTH ++ ++static uint32_t hevc_deblocking_boundary_strengths(int pus, int dup, const HEVCRpiMvField *curr, const HEVCRpiMvField *neigh, ++ const int *curr_rpl0, const int *curr_rpl1, const int *neigh_rpl0, const int *neigh_rpl1, ++ int in_inc0, int in_inc1) ++{ ++ int shift = 32; ++ uint32_t bs = 0; ++ for (; pus > 0; pus--) { ++ int strength, out; ++ int curr_refL0 = curr_rpl0[curr->ref_idx[0]]; ++ int curr_refL1 = curr_rpl1[curr->ref_idx[1]]; ++ int nr_idx0 = neigh->ref_idx[0]; ++ int nr_idx1 = neigh->ref_idx[1]; ++ int neigh_refL0 = neigh_rpl0[nr_idx0]; ++ int neigh_refL1 = neigh_rpl1[nr_idx1]; ++ ++ av_assert0(nr_idx0 >= 0 && nr_idx0 <=31); ++ av_assert0(nr_idx1 >= 0 && nr_idx1 <=31); ++ ++#if 1 // This more directly matches the original implementation ++ if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) { ++ // same L0 and L1 ++ if (curr_refL0 == neigh_refL0 && ++ curr_refL0 == curr_refL1 && ++ neigh_refL0 == neigh_refL1) { ++ if ((FFABS(MV_X(neigh->xy[0]) - MV_X(curr->xy[0])) >= 4 || FFABS(MV_Y(neigh->xy[0]) - MV_Y(curr->xy[0])) >= 4 || ++ FFABS(MV_X(neigh->xy[1]) - MV_X(curr->xy[1])) >= 4 || FFABS(MV_Y(neigh->xy[1]) - MV_Y(curr->xy[1])) >= 4) && ++ (FFABS(MV_X(neigh->xy[1]) - MV_X(curr->xy[0])) >= 4 || FFABS(MV_Y(neigh->xy[1]) - MV_Y(curr->xy[0])) >= 4 || ++ FFABS(MV_X(neigh->xy[0]) - MV_X(curr->xy[1])) >= 4 || FFABS(MV_Y(neigh->xy[0]) - MV_Y(curr->xy[1])) >= 4)) ++ strength = 1; ++ else ++ strength = 0; ++ } else if (neigh_refL0 == curr_refL0 && ++ neigh_refL1 == curr_refL1) { ++ if (FFABS(MV_X(neigh->xy[0]) - MV_X(curr->xy[0])) >= 4 || FFABS(MV_Y(neigh->xy[0]) - MV_Y(curr->xy[0])) >= 4 || ++ FFABS(MV_X(neigh->xy[1]) - MV_X(curr->xy[1])) >= 4 || FFABS(MV_Y(neigh->xy[1]) - MV_Y(curr->xy[1])) >= 4) ++ strength = 1; ++ else ++ strength = 0; ++ } else if (neigh_refL1 == curr_refL0 && ++ neigh_refL0 == curr_refL1) { ++ if (FFABS(MV_X(neigh->xy[1]) - MV_X(curr->xy[0])) >= 4 || FFABS(MV_Y(neigh->xy[1]) - MV_Y(curr->xy[0])) >= 4 || ++ FFABS(MV_X(neigh->xy[0]) - MV_X(curr->xy[1])) >= 4 || FFABS(MV_Y(neigh->xy[0]) - MV_Y(curr->xy[1])) >= 4) ++ strength = 1; ++ else ++ strength = 0; ++ } else { ++ strength = 1; ++ } ++ } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV ++ MvXY curr_mv0, neigh_mv0; ++ ++ if (curr->pred_flag & 1) { ++ curr_mv0 = curr->xy[0]; ++ } else { ++ curr_mv0 = curr->xy[1]; ++ curr_refL0 = curr_refL1; ++ } ++ ++ if (neigh->pred_flag & 1) { ++ neigh_mv0 = neigh->xy[0]; ++ } else { ++ neigh_mv0 = neigh->xy[1]; ++ neigh_refL0 = neigh_refL1; ++ } ++ ++ if (curr_refL0 == neigh_refL0) { ++ if (FFABS(MV_X(curr_mv0) - MV_X(neigh_mv0)) >= 4 || FFABS(MV_Y(curr_mv0) - MV_Y(neigh_mv0)) >= 4) ++ strength = 1; ++ else ++ strength = 0; ++ } else ++ strength = 1; ++ } else ++ strength = 1; ++#else // This has exactly the same effect, but is more suitable for vectorisation ++ MvXY curr_mv[2]; ++ MvXY neigh_mv[2]; ++ memcpy(curr_mv, curr->xy, sizeof curr_mv); ++ memcpy(neigh_mv, neigh->xy, sizeof neigh_mv); ++ ++ if (!(curr->pred_flag & 2)) { ++ curr_mv[1] = curr_mv[0]; ++ curr_refL1 = curr_refL0; ++ } ++ if (!(neigh->pred_flag & 2)) { ++ neigh_mv[1] = neigh_mv[0]; ++ neigh_refL1 = neigh_refL0; ++ } ++ if (!(curr->pred_flag & 1)) { ++ curr_mv[0] = curr_mv[1]; ++ curr_refL0 = curr_refL1; ++ } ++ if (!(neigh->pred_flag & 1)) { ++ neigh_mv[0] = neigh_mv[1]; ++ neigh_refL0 = neigh_refL1; ++ } ++ ++ strength = 1; ++ ++ strength &= (neigh_refL0 != curr_refL0) | (neigh_refL1 != curr_refL1) | ++ (FFABS(MV_X(neigh_mv[0]) - MV_X(curr_mv[0])) >= 4) | (FFABS(MV_Y(neigh_mv[0]) - MV_Y(curr_mv[0])) >= 4) | ++ (FFABS(MV_X(neigh_mv[1]) - MV_X(curr_mv[1])) >= 4) | (FFABS(MV_Y(neigh_mv[1]) - MV_Y(curr_mv[1])) >= 4); ++ ++ strength &= (neigh_refL1 != curr_refL0) | (neigh_refL0 != curr_refL1) | ++ (FFABS(MV_X(neigh_mv[1]) - MV_X(curr_mv[0])) >= 4) | (FFABS(MV_Y(neigh_mv[1]) - MV_Y(curr_mv[0])) >= 4) | ++ (FFABS(MV_X(neigh_mv[0]) - MV_X(curr_mv[1])) >= 4) | (FFABS(MV_Y(neigh_mv[0]) - MV_Y(curr_mv[1])) >= 4); ++ ++ strength |= (((curr->pred_flag + 1) ^ (neigh->pred_flag + 1)) >> 2); ++#endif ++ ++ curr += in_inc0 / sizeof (HEVCRpiMvField); ++ neigh += in_inc1 / sizeof (HEVCRpiMvField); ++ ++ for (out = dup; out > 0; out--) ++ { ++ bs = (bs >> 2) | (strength << 30); ++ shift -= 2; ++ } ++ } ++ return bs >> shift; ++} ++ ++ ++static void cpy_blk(uint8_t *dst, unsigned int stride_dst, const uint8_t *src, unsigned stride_src, unsigned int width, unsigned int height) ++{ ++ unsigned int i, j; ++ ++ if (((intptr_t)dst | (intptr_t)src | stride_dst | stride_src) & 15) { ++ for (i = 0; i < height; i++) { ++ for (j = 0; j < width; j+=8) ++ AV_COPY64U(dst+j, src+j); ++ dst += stride_dst; ++ src += stride_src; ++ } ++ } else { ++ for (i = 0; i < height; i++) { ++ for (j = 0; j < width; j+=16) ++ AV_COPY128(dst+j, src+j); ++ dst += stride_dst; ++ src += stride_src; ++ } ++ } ++} ++ ++ ++ ++void ff_hevc_rpi_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) ++{ ++#undef FUNC ++#define FUNC(a, depth) a ## _ ## depth ++ ++#undef PEL_FUNC ++#define PEL_FUNC(dst1, idx1, idx2, a, depth) \ ++ for(i = 0 ; i < 10 ; i++) \ ++{ \ ++ hevcdsp->dst1[i][idx1][idx2] = a ## _ ## depth; \ ++} ++ ++#undef EPEL_FUNCS ++#define EPEL_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_epel, 0, 0, put_hevc_pel_pixels, depth); \ ++ PEL_FUNC(put_hevc_epel, 0, 1, put_hevc_epel_h, depth); \ ++ PEL_FUNC(put_hevc_epel, 1, 0, put_hevc_epel_v, depth); \ ++ PEL_FUNC(put_hevc_epel, 1, 1, put_hevc_epel_hv, depth) ++ ++#undef EPEL_UNI_FUNCS ++#define EPEL_UNI_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_epel_uni, 0, 0, put_hevc_pel_uni_pixels, depth); \ ++ PEL_FUNC(put_hevc_epel_uni, 0, 1, put_hevc_epel_uni_h, depth); \ ++ PEL_FUNC(put_hevc_epel_uni, 1, 0, put_hevc_epel_uni_v, depth); \ ++ PEL_FUNC(put_hevc_epel_uni, 1, 1, put_hevc_epel_uni_hv, depth); \ ++ PEL_FUNC(put_hevc_epel_uni_w, 0, 0, put_hevc_pel_uni_w_pixels, depth); \ ++ PEL_FUNC(put_hevc_epel_uni_w, 0, 1, put_hevc_epel_uni_w_h, depth); \ ++ PEL_FUNC(put_hevc_epel_uni_w, 1, 0, put_hevc_epel_uni_w_v, depth); \ ++ PEL_FUNC(put_hevc_epel_uni_w, 1, 1, put_hevc_epel_uni_w_hv, depth) ++ ++#undef EPEL_BI_FUNCS ++#define EPEL_BI_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_epel_bi, 0, 0, put_hevc_pel_bi_pixels, depth); \ ++ PEL_FUNC(put_hevc_epel_bi, 0, 1, put_hevc_epel_bi_h, depth); \ ++ PEL_FUNC(put_hevc_epel_bi, 1, 0, put_hevc_epel_bi_v, depth); \ ++ PEL_FUNC(put_hevc_epel_bi, 1, 1, put_hevc_epel_bi_hv, depth); \ ++ PEL_FUNC(put_hevc_epel_bi_w, 0, 0, put_hevc_pel_bi_w_pixels, depth); \ ++ PEL_FUNC(put_hevc_epel_bi_w, 0, 1, put_hevc_epel_bi_w_h, depth); \ ++ PEL_FUNC(put_hevc_epel_bi_w, 1, 0, put_hevc_epel_bi_w_v, depth); \ ++ PEL_FUNC(put_hevc_epel_bi_w, 1, 1, put_hevc_epel_bi_w_hv, depth) ++ ++#undef QPEL_FUNCS ++#define QPEL_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_qpel, 0, 0, put_hevc_pel_pixels, depth); \ ++ PEL_FUNC(put_hevc_qpel, 0, 1, put_hevc_qpel_h, depth); \ ++ PEL_FUNC(put_hevc_qpel, 1, 0, put_hevc_qpel_v, depth); \ ++ PEL_FUNC(put_hevc_qpel, 1, 1, put_hevc_qpel_hv, depth) ++ ++#undef QPEL_UNI_FUNCS ++#define QPEL_UNI_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_qpel_uni, 0, 0, put_hevc_pel_uni_pixels, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni, 0, 1, put_hevc_qpel_uni_h, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni, 1, 0, put_hevc_qpel_uni_v, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni, 1, 1, put_hevc_qpel_uni_hv, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni_w, 0, 0, put_hevc_pel_uni_w_pixels, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni_w, 0, 1, put_hevc_qpel_uni_w_h, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni_w, 1, 0, put_hevc_qpel_uni_w_v, depth); \ ++ PEL_FUNC(put_hevc_qpel_uni_w, 1, 1, put_hevc_qpel_uni_w_hv, depth) ++ ++#undef QPEL_BI_FUNCS ++#define QPEL_BI_FUNCS(depth) \ ++ PEL_FUNC(put_hevc_qpel_bi, 0, 0, put_hevc_pel_bi_pixels, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi, 0, 1, put_hevc_qpel_bi_h, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi, 1, 0, put_hevc_qpel_bi_v, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi, 1, 1, put_hevc_qpel_bi_hv, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi_w, 0, 0, put_hevc_pel_bi_w_pixels, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi_w, 0, 1, put_hevc_qpel_bi_w_h, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi_w, 1, 0, put_hevc_qpel_bi_w_v, depth); \ ++ PEL_FUNC(put_hevc_qpel_bi_w, 1, 1, put_hevc_qpel_bi_w_hv, depth) ++ ++#define SLICED_ADD_RESIDUAL(depth)\ ++ hevcdsp->add_residual_u[0] = FUNC(add_residual4x4_u, depth); \ ++ hevcdsp->add_residual_u[1] = FUNC(add_residual8x8_u, depth); \ ++ hevcdsp->add_residual_u[2] = FUNC(add_residual16x16_u, depth); \ ++ hevcdsp->add_residual_u[3] = FUNC(add_residual32x32_u, depth); \ ++ hevcdsp->add_residual_v[0] = FUNC(add_residual4x4_v, depth); \ ++ hevcdsp->add_residual_v[1] = FUNC(add_residual8x8_v, depth); \ ++ hevcdsp->add_residual_v[2] = FUNC(add_residual16x16_v, depth); \ ++ hevcdsp->add_residual_v[3] = FUNC(add_residual32x32_v, depth); \ ++ hevcdsp->add_residual_c[0] = FUNC(add_residual4x4_c, depth); \ ++ hevcdsp->add_residual_c[1] = FUNC(add_residual8x8_c, depth); \ ++ hevcdsp->add_residual_c[2] = FUNC(add_residual16x16_c, depth); \ ++ hevcdsp->add_residual_c[3] = FUNC(add_residual32x32_c, depth); \ ++ hevcdsp->add_residual_dc_c[0] = FUNC(add_residual4x4_dc_c, depth); \ ++ hevcdsp->add_residual_dc_c[1] = FUNC(add_residual8x8_dc_c, depth); \ ++ hevcdsp->add_residual_dc_c[2] = FUNC(add_residual16x16_dc_c, depth); \ ++ hevcdsp->add_residual_dc_c[3] = FUNC(add_residual32x32_dc_c, depth); \ ++ hevcdsp->put_pcm_c = FUNC(put_pcm_c, depth) ++#define SLICED_LOOP_FILTERS(depth)\ ++ hevcdsp->hevc_h_loop_filter_luma2 = FUNC(hevc_h_loop_filter_luma2, depth); \ ++ hevcdsp->hevc_v_loop_filter_luma2 = FUNC(hevc_v_loop_filter_luma2, depth); \ ++ hevcdsp->hevc_h_loop_filter_uv = FUNC(hevc_h_loop_filter_uv, depth); \ ++ hevcdsp->hevc_v_loop_filter_uv2 = FUNC(hevc_v_loop_filter_uv2, depth) ++#define SLICED_SAO(depth)\ ++ for (i = 0; i != SAO_FILTER_N; ++i) { \ ++ hevcdsp->sao_band_filter_c[i] = FUNC(sao_band_filter_c, depth); \ ++ hevcdsp->sao_edge_filter_c[i] = FUNC(sao_edge_filter_c, depth); \ ++ } \ ++ hevcdsp->sao_edge_restore_c[0] = FUNC(sao_edge_restore_c_0, depth); \ ++ hevcdsp->sao_edge_restore_c[1] = FUNC(sao_edge_restore_c_1, depth) ++ ++#define HEVC_DSP(depth) \ ++ hevcdsp->put_pcm = FUNC(put_pcm, depth); \ ++ hevcdsp->add_residual[0] = FUNC(add_residual4x4, depth); \ ++ hevcdsp->add_residual[1] = FUNC(add_residual8x8, depth); \ ++ hevcdsp->add_residual[2] = FUNC(add_residual16x16, depth); \ ++ hevcdsp->add_residual[3] = FUNC(add_residual32x32, depth); \ ++ hevcdsp->add_residual_dc[0] = FUNC(add_residual4x4_dc, depth); \ ++ hevcdsp->add_residual_dc[1] = FUNC(add_residual8x8_dc, depth); \ ++ hevcdsp->add_residual_dc[2] = FUNC(add_residual16x16_dc, depth); \ ++ hevcdsp->add_residual_dc[3] = FUNC(add_residual32x32_dc, depth); \ ++ SLICED_ADD_RESIDUAL(depth); \ ++ hevcdsp->dequant = FUNC(dequant, depth); \ ++ hevcdsp->transform_rdpcm = FUNC(transform_rdpcm, depth); \ ++ hevcdsp->transform_4x4_luma = FUNC(transform_4x4_luma, depth); \ ++ hevcdsp->idct[0] = FUNC(idct_4x4, depth); \ ++ hevcdsp->idct[1] = FUNC(idct_8x8, depth); \ ++ hevcdsp->idct[2] = FUNC(idct_16x16, depth); \ ++ hevcdsp->idct[3] = FUNC(idct_32x32, depth); \ ++ \ ++ hevcdsp->idct_dc[0] = FUNC(idct_4x4_dc, depth); \ ++ hevcdsp->idct_dc[1] = FUNC(idct_8x8_dc, depth); \ ++ hevcdsp->idct_dc[2] = FUNC(idct_16x16_dc, depth); \ ++ hevcdsp->idct_dc[3] = FUNC(idct_32x32_dc, depth); \ ++ \ ++ for (i = 0; i != SAO_FILTER_N; ++i) { \ ++ hevcdsp->sao_band_filter[i] = FUNC(sao_band_filter, depth); \ ++ hevcdsp->sao_edge_filter[i] = FUNC(sao_edge_filter, depth); \ ++ } \ ++ hevcdsp->sao_edge_restore[0] = FUNC(sao_edge_restore_0, depth); \ ++ hevcdsp->sao_edge_restore[1] = FUNC(sao_edge_restore_1, depth); \ ++ SLICED_SAO(depth); \ ++ \ ++ QPEL_FUNCS(depth); \ ++ QPEL_UNI_FUNCS(depth); \ ++ QPEL_BI_FUNCS(depth); \ ++ EPEL_FUNCS(depth); \ ++ EPEL_UNI_FUNCS(depth); \ ++ EPEL_BI_FUNCS(depth); \ ++ \ ++ SLICED_LOOP_FILTERS(depth); \ ++ hevcdsp->hevc_h_loop_filter_luma = FUNC(hevc_h_loop_filter_luma, depth); \ ++ hevcdsp->hevc_v_loop_filter_luma = FUNC(hevc_v_loop_filter_luma, depth); \ ++ hevcdsp->hevc_h_loop_filter_chroma = FUNC(hevc_h_loop_filter_chroma, depth); \ ++ hevcdsp->hevc_v_loop_filter_chroma = FUNC(hevc_v_loop_filter_chroma, depth); \ ++ hevcdsp->hevc_h_loop_filter_luma_c = FUNC(hevc_h_loop_filter_luma, depth); \ ++ hevcdsp->hevc_v_loop_filter_luma_c = FUNC(hevc_v_loop_filter_luma, depth); \ ++ hevcdsp->hevc_h_loop_filter_chroma_c = FUNC(hevc_h_loop_filter_chroma, depth); \ ++ hevcdsp->hevc_v_loop_filter_chroma_c = FUNC(hevc_v_loop_filter_chroma, depth) ++int i = 0; ++ ++ switch (bit_depth) { ++ case 9: ++ HEVC_DSP(9); ++ break; ++ case 10: ++ HEVC_DSP(10); ++ break; ++ case 12: ++ HEVC_DSP(12); ++ break; ++ default: ++ HEVC_DSP(8); ++ break; ++ } ++ ++ hevcdsp->hevc_deblocking_boundary_strengths = hevc_deblocking_boundary_strengths; ++ hevcdsp->cpy_blk = cpy_blk; ++ ++ if (ARCH_PPC) ++ ff_hevc_rpi_dsp_init_ppc(hevcdsp, bit_depth); ++ if (ARCH_X86) ++ ff_hevc_rpi_dsp_init_x86(hevcdsp, bit_depth); ++ if (ARCH_ARM) ++ ff_hevcdsp_rpi_init_arm(hevcdsp, bit_depth); ++ if (ARCH_MIPS) ++ ff_hevc_rpi_dsp_init_mips(hevcdsp, bit_depth); ++} +diff --git a/libavcodec/rpi_hevcdsp.h b/libavcodec/rpi_hevcdsp.h +new file mode 100644 +index 0000000000..5a7cdeeb66 +--- /dev/null ++++ b/libavcodec/rpi_hevcdsp.h +@@ -0,0 +1,177 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2013 - 2014 Pierre-Edouard Lepere ++ * ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVCDSP_H ++#define AVCODEC_RPI_HEVCDSP_H ++ ++#include "hevc.h" ++#include "get_bits.h" ++ ++struct HEVCRpiMvField; ++ ++#define MAX_PB_SIZE 64 ++ ++#define RPI_HEVC_SAO_BUF_STRIDE 160 ++ ++ ++typedef struct RpiSAOParams { ++ uint8_t band_position[3]; ///< sao_band_position (Y,U,V) ++ uint8_t eo_class[3]; ///< sao_eo_class (Y,U=V) ++ uint8_t type_idx[3]; ///< sao_type_idx (Y,U=V) ++ ++ int16_t offset_val[3][5]; ///> 16; ++ const int dc_u = (dc << 16) >> 16; ++ ++ stride /= sizeof(pixel); ++ ++ for (y = 0; y < size; y++) { ++ for (x = 0; x < size * 2; x += 2) { ++ dst[x] = av_clip_pixel(dst[x] + dc_u); ++ dst[x + 1] = av_clip_pixel(dst[x + 1] + dc_v); ++ } ++ dst += stride; ++ } ++} ++ ++ ++static void FUNC(add_residual4x4)(uint8_t *_dst, int16_t *res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual)(_dst, res, stride, 4); ++} ++ ++static void FUNC(add_residual8x8)(uint8_t *_dst, int16_t *res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual)(_dst, res, stride, 8); ++} ++ ++static void FUNC(add_residual16x16)(uint8_t *_dst, int16_t *res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual)(_dst, res, stride, 16); ++} ++ ++static void FUNC(add_residual32x32)(uint8_t *_dst, int16_t *res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual)(_dst, res, stride, 32); ++} ++ ++static void FUNC(add_residual4x4_dc)(uint8_t *_dst, ptrdiff_t stride, int dc) ++{ ++ FUNC(add_residual_dc)(_dst, stride, dc, 4); ++} ++ ++static void FUNC(add_residual8x8_dc)(uint8_t *_dst, ptrdiff_t stride, int dc) ++{ ++ FUNC(add_residual_dc)(_dst, stride, dc, 8); ++} ++ ++static void FUNC(add_residual16x16_dc)(uint8_t *_dst, ptrdiff_t stride, int dc) ++{ ++ FUNC(add_residual_dc)(_dst, stride, dc, 16); ++} ++ ++static void FUNC(add_residual32x32_dc)(uint8_t *_dst, ptrdiff_t stride, int dc) ++{ ++ FUNC(add_residual_dc)(_dst, stride, dc, 32); ++} ++ ++// -- U -- (plaited) ++ ++static void FUNC(add_residual4x4_u)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_u) ++{ ++ FUNC(add_residual_u)(_dst, res, stride, dc_u, 4); ++} ++ ++static void FUNC(add_residual8x8_u)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_u) ++{ ++ FUNC(add_residual_u)(_dst, res, stride, dc_u, 8); ++} ++ ++static void FUNC(add_residual16x16_u)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_u) ++{ ++ FUNC(add_residual_u)(_dst, res, stride, dc_u, 16); ++} ++ ++static void FUNC(add_residual32x32_u)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_u) ++{ ++ // Should never occur for 420, which is all that sand supports ++ av_assert0(0); ++} ++ ++// -- V -- (plaited) ++ ++static void FUNC(add_residual4x4_v)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_v) ++{ ++ FUNC(add_residual_v)(_dst, res, stride, dc_v, 4); ++} ++ ++static void FUNC(add_residual8x8_v)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_v) ++{ ++ FUNC(add_residual_v)(_dst, res, stride, dc_v, 8); ++} ++ ++static void FUNC(add_residual16x16_v)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_v) ++{ ++ FUNC(add_residual_v)(_dst, res, stride, dc_v, 16); ++} ++ ++static void FUNC(add_residual32x32_v)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride, int dc_v) ++{ ++ // Should never occur for 420, which is all that sand supports ++ av_assert0(0); ++} ++ ++// -- C -- (plaited - both U & V) ++ ++static void FUNC(add_residual4x4_c)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual_c)(_dst, res, stride, 4); ++} ++ ++static void FUNC(add_residual8x8_c)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual_c)(_dst, res, stride, 8); ++} ++ ++static void FUNC(add_residual16x16_c)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride) ++{ ++ FUNC(add_residual_c)(_dst, res, stride, 16); ++} ++ ++static void FUNC(add_residual32x32_c)(uint8_t *_dst, const int16_t * res, ++ ptrdiff_t stride) ++{ ++ // Should never occur for 420, which is all that sand supports ++ av_assert0(0); ++} ++ ++static void FUNC(add_residual4x4_dc_c)(uint8_t *_dst, ptrdiff_t stride, int32_t dc) ++{ ++ FUNC(add_residual_dc_c)(_dst, stride, dc, 4); ++} ++ ++static void FUNC(add_residual8x8_dc_c)(uint8_t *_dst, ptrdiff_t stride, int32_t dc) ++{ ++ FUNC(add_residual_dc_c)(_dst, stride, dc, 8); ++} ++ ++static void FUNC(add_residual16x16_dc_c)(uint8_t *_dst, ptrdiff_t stride, int32_t dc) ++{ ++ FUNC(add_residual_dc_c)(_dst, stride, dc, 16); ++} ++ ++static void FUNC(add_residual32x32_dc_c)(uint8_t *_dst, ptrdiff_t stride, int32_t dc) ++{ ++ // Should never occur for 420, which is all that sand supports ++ av_assert0(0); ++} ++ ++ ++static void FUNC(transform_rdpcm)(int16_t *_coeffs, int16_t log2_size, int mode) ++{ ++ int16_t *coeffs = (int16_t *) _coeffs; ++ int x, y; ++ int size = 1 << log2_size; ++ ++ if (mode) { ++ coeffs += size; ++ for (y = 0; y < size - 1; y++) { ++ for (x = 0; x < size; x++) ++ coeffs[x] += coeffs[x - size]; ++ coeffs += size; ++ } ++ } else { ++ for (y = 0; y < size; y++) { ++ for (x = 1; x < size; x++) ++ coeffs[x] += coeffs[x - 1]; ++ coeffs += size; ++ } ++ } ++} ++ ++static void FUNC(dequant)(int16_t *coeffs, int16_t log2_size) ++{ ++ int shift = 15 - BIT_DEPTH - log2_size; ++ int x, y; ++ int size = 1 << log2_size; ++ ++ if (shift > 0) { ++ int offset = 1 << (shift - 1); ++ for (y = 0; y < size; y++) { ++ for (x = 0; x < size; x++) { ++ *coeffs = (*coeffs + offset) >> shift; ++ coeffs++; ++ } ++ } ++ } else { ++ for (y = 0; y < size; y++) { ++ for (x = 0; x < size; x++) { ++ *coeffs = *coeffs << -shift; ++ coeffs++; ++ } ++ } ++ } ++} ++ ++#define SET(dst, x) (dst) = (x) ++#define SCALE(dst, x) (dst) = av_clip_int16(((x) + add) >> shift) ++ ++#define TR_4x4_LUMA(dst, src, step, assign) \ ++ do { \ ++ int c0 = src[0 * step] + src[2 * step]; \ ++ int c1 = src[2 * step] + src[3 * step]; \ ++ int c2 = src[0 * step] - src[3 * step]; \ ++ int c3 = 74 * src[1 * step]; \ ++ \ ++ assign(dst[2 * step], 74 * (src[0 * step] - \ ++ src[2 * step] + \ ++ src[3 * step])); \ ++ assign(dst[0 * step], 29 * c0 + 55 * c1 + c3); \ ++ assign(dst[1 * step], 55 * c2 - 29 * c1 + c3); \ ++ assign(dst[3 * step], 55 * c0 + 29 * c2 - c3); \ ++ } while (0) ++ ++static void FUNC(transform_4x4_luma)(int16_t *coeffs) ++{ ++ int i; ++ int shift = 7; ++ int add = 1 << (shift - 1); ++ int16_t *src = coeffs; ++ ++ for (i = 0; i < 4; i++) { ++ TR_4x4_LUMA(src, src, 4, SCALE); ++ src++; ++ } ++ ++ shift = 20 - BIT_DEPTH; ++ add = 1 << (shift - 1); ++ for (i = 0; i < 4; i++) { ++ TR_4x4_LUMA(coeffs, coeffs, 1, SCALE); ++ coeffs += 4; ++ } ++} ++ ++#undef TR_4x4_LUMA ++ ++#define TR_4(dst, src, dstep, sstep, assign, end) \ ++ do { \ ++ const int e0 = 64 * src[0 * sstep] + 64 * src[2 * sstep]; \ ++ const int e1 = 64 * src[0 * sstep] - 64 * src[2 * sstep]; \ ++ const int o0 = 83 * src[1 * sstep] + 36 * src[3 * sstep]; \ ++ const int o1 = 36 * src[1 * sstep] - 83 * src[3 * sstep]; \ ++ \ ++ assign(dst[0 * dstep], e0 + o0); \ ++ assign(dst[1 * dstep], e1 + o1); \ ++ assign(dst[2 * dstep], e1 - o1); \ ++ assign(dst[3 * dstep], e0 - o0); \ ++ } while (0) ++ ++#define TR_8(dst, src, dstep, sstep, assign, end) \ ++ do { \ ++ int i, j; \ ++ int e_8[4]; \ ++ int o_8[4] = { 0 }; \ ++ for (i = 0; i < 4; i++) \ ++ for (j = 1; j < end; j += 2) \ ++ o_8[i] += transform[4 * j][i] * src[j * sstep]; \ ++ TR_4(e_8, src, 1, 2 * sstep, SET, 4); \ ++ \ ++ for (i = 0; i < 4; i++) { \ ++ assign(dst[i * dstep], e_8[i] + o_8[i]); \ ++ assign(dst[(7 - i) * dstep], e_8[i] - o_8[i]); \ ++ } \ ++ } while (0) ++ ++#define TR_16(dst, src, dstep, sstep, assign, end) \ ++ do { \ ++ int i, j; \ ++ int e_16[8]; \ ++ int o_16[8] = { 0 }; \ ++ for (i = 0; i < 8; i++) \ ++ for (j = 1; j < end; j += 2) \ ++ o_16[i] += transform[2 * j][i] * src[j * sstep]; \ ++ TR_8(e_16, src, 1, 2 * sstep, SET, 8); \ ++ \ ++ for (i = 0; i < 8; i++) { \ ++ assign(dst[i * dstep], e_16[i] + o_16[i]); \ ++ assign(dst[(15 - i) * dstep], e_16[i] - o_16[i]); \ ++ } \ ++ } while (0) ++ ++#define TR_32(dst, src, dstep, sstep, assign, end) \ ++ do { \ ++ int i, j; \ ++ int e_32[16]; \ ++ int o_32[16] = { 0 }; \ ++ for (i = 0; i < 16; i++) \ ++ for (j = 1; j < end; j += 2) \ ++ o_32[i] += transform[j][i] * src[j * sstep]; \ ++ TR_16(e_32, src, 1, 2 * sstep, SET, end / 2); \ ++ \ ++ for (i = 0; i < 16; i++) { \ ++ assign(dst[i * dstep], e_32[i] + o_32[i]); \ ++ assign(dst[(31 - i) * dstep], e_32[i] - o_32[i]); \ ++ } \ ++ } while (0) ++ ++#define IDCT_VAR4(H) \ ++ int limit2 = FFMIN(col_limit + 4, H) ++#define IDCT_VAR8(H) \ ++ int limit = FFMIN(col_limit, H); \ ++ int limit2 = FFMIN(col_limit + 4, H) ++#define IDCT_VAR16(H) IDCT_VAR8(H) ++#define IDCT_VAR32(H) IDCT_VAR8(H) ++ ++#define IDCT(H) \ ++static void FUNC(idct_ ## H ## x ## H )(int16_t *coeffs, \ ++ int col_limit) \ ++{ \ ++ int i; \ ++ int shift = 7; \ ++ int add = 1 << (shift - 1); \ ++ int16_t *src = coeffs; \ ++ IDCT_VAR ## H(H); \ ++ \ ++ for (i = 0; i < H; i++) { \ ++ TR_ ## H(src, src, H, H, SCALE, limit2); \ ++ if (limit2 < H && i%4 == 0 && !!i) \ ++ limit2 -= 4; \ ++ src++; \ ++ } \ ++ \ ++ shift = 20 - BIT_DEPTH; \ ++ add = 1 << (shift - 1); \ ++ for (i = 0; i < H; i++) { \ ++ TR_ ## H(coeffs, coeffs, 1, 1, SCALE, limit); \ ++ coeffs += H; \ ++ } \ ++} ++ ++#define IDCT_DC(H) \ ++static void FUNC(idct_ ## H ## x ## H ## _dc)(int16_t *coeffs) \ ++{ \ ++ int i, j; \ ++ int shift = 14 - BIT_DEPTH; \ ++ int add = 1 << (shift - 1); \ ++ int coeff = (((coeffs[0] + 1) >> 1) + add) >> shift; \ ++ \ ++ for (j = 0; j < H; j++) { \ ++ for (i = 0; i < H; i++) { \ ++ coeffs[i + j * H] = coeff; \ ++ } \ ++ } \ ++} ++ ++IDCT( 4) ++IDCT( 8) ++IDCT(16) ++IDCT(32) ++ ++IDCT_DC( 4) ++IDCT_DC( 8) ++IDCT_DC(16) ++IDCT_DC(32) ++ ++#undef TR_4 ++#undef TR_8 ++#undef TR_16 ++#undef TR_32 ++ ++#undef SET ++#undef SCALE ++ ++static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ int16_t *sao_offset_val, int sao_left_class, ++ int width, int height) ++{ ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int offset_table[32] = { 0 }; ++ int k, y, x; ++ int shift = BIT_DEPTH - 5; ++ ++ stride_dst /= sizeof(pixel); ++ stride_src /= sizeof(pixel); ++ ++ for (k = 0; k < 4; k++) ++ offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); ++ dst += stride_dst; ++ src += stride_src; ++ } ++} ++ ++#define CMP(a, b) (((a) > (b)) - ((a) < (b))) ++ ++static void FUNC(sao_edge_filter)(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *sao_offset_val, ++ int eo, int width, int height) { ++ ++ static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; ++ static const int8_t pos[4][2][2] = { ++ { { -1, 0 }, { 1, 0 } }, // horizontal ++ { { 0, -1 }, { 0, 1 } }, // vertical ++ { { -1, -1 }, { 1, 1 } }, // 45 degree ++ { { 1, -1 }, { -1, 1 } }, // 135 degree ++ }; ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int a_stride, b_stride; ++ int x, y; ++ const ptrdiff_t stride_src = RPI_HEVC_SAO_BUF_STRIDE / sizeof(pixel); ++ stride_dst /= sizeof(pixel); ++ ++ a_stride = pos[eo][0][0] + pos[eo][0][1] * stride_src; ++ b_stride = pos[eo][1][0] + pos[eo][1][1] * stride_src; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) { ++ int diff0 = CMP(src[x], src[x + a_stride]); ++ int diff1 = CMP(src[x], src[x + b_stride]); ++ int offset_val = edge_idx[2 + diff0 + diff1]; ++ dst[x] = av_clip_pixel(src[x] + sao_offset_val[offset_val]); ++ } ++ src += stride_src; ++ dst += stride_dst; ++ } ++} ++ ++ ++#if BIT_DEPTH == 10 ++// We need a 32 bit variation for the _c restores so hijack bit depth 10 ++#undef pixel ++#undef BIT_DEPTH ++#define pixel uint32_t ++#define BIT_DEPTH 32 ++// All 16 bit variations are the same ++#define sao_edge_restore_0_10 sao_edge_restore_0_9 ++#define sao_edge_restore_1_10 sao_edge_restore_1_9 ++#define sao_edge_restore_0_11 sao_edge_restore_0_9 ++#define sao_edge_restore_1_11 sao_edge_restore_1_9 ++#define sao_edge_restore_0_12 sao_edge_restore_0_9 ++#define sao_edge_restore_1_12 sao_edge_restore_1_9 ++#define sao_edge_restore_0_13 sao_edge_restore_0_9 ++#define sao_edge_restore_1_13 sao_edge_restore_1_9 ++#define sao_edge_restore_0_14 sao_edge_restore_0_9 ++#define sao_edge_restore_1_14 sao_edge_restore_1_9 ++#define sao_edge_restore_0_15 sao_edge_restore_0_9 ++#define sao_edge_restore_1_15 sao_edge_restore_1_9 ++#define sao_edge_restore_0_16 sao_edge_restore_0_9 ++#define sao_edge_restore_1_16 sao_edge_restore_1_9 ++#endif ++#if BIT_DEPTH <= 9 || BIT_DEPTH == 32 ++static void FUNC(sao_edge_restore_0)(uint8_t *_dst, uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, RpiSAOParams *sao, ++ int *borders, int _width, int _height, ++ int c_idx, uint8_t *vert_edge, ++ uint8_t *horiz_edge, uint8_t *diag_edge) ++{ ++ int x, y; ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int sao_eo_class = sao->eo_class[c_idx]; ++ int init_x = 0, width = _width, height = _height; ++ ++ stride_dst /= sizeof(pixel); ++ stride_src /= sizeof(pixel); ++ ++ if (sao_eo_class != SAO_EO_VERT) { ++ if (borders[0]) { ++ for (y = 0; y < height; y++) { ++ dst[y * stride_dst] = src[y * stride_src]; ++ } ++ init_x = 1; ++ } ++ if (borders[2]) { ++ int offset = width - 1; ++ for (x = 0; x < height; x++) { ++ dst[x * stride_dst + offset] = src[x * stride_src + offset]; ++ } ++ width--; ++ } ++ } ++ if (sao_eo_class != SAO_EO_HORIZ) { ++ if (borders[1]) { ++ for (x = init_x; x < width; x++) ++ dst[x] = src[x]; ++ } ++ if (borders[3]) { ++ ptrdiff_t y_stride_dst = stride_dst * (height - 1); ++ ptrdiff_t y_stride_src = stride_src * (height - 1); ++ for (x = init_x; x < width; x++) ++ dst[x + y_stride_dst] = src[x + y_stride_src]; ++ height--; ++ } ++ } ++} ++ ++static void FUNC(sao_edge_restore_1)(uint8_t *_dst, uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, RpiSAOParams *sao, ++ int *borders, int _width, int _height, ++ int c_idx, uint8_t *vert_edge, ++ uint8_t *horiz_edge, uint8_t *diag_edge) ++{ ++ int x, y; ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int sao_eo_class = sao->eo_class[c_idx]; ++ int init_x = 0, init_y = 0, width = _width, height = _height; ++ ++ stride_dst /= sizeof(pixel); ++ stride_src /= sizeof(pixel); ++ ++ if (sao_eo_class != SAO_EO_VERT) { ++ if (borders[0]) { ++ for (y = 0; y < height; y++) { ++ dst[y * stride_dst] = src[y * stride_src]; ++ } ++ init_x = 1; ++ } ++ if (borders[2]) { ++ int offset = width - 1; ++ for (x = 0; x < height; x++) { ++ dst[x * stride_dst + offset] = src[x * stride_src + offset]; ++ } ++ width--; ++ } ++ } ++ if (sao_eo_class != SAO_EO_HORIZ) { ++ if (borders[1]) { ++ for (x = init_x; x < width; x++) ++ dst[x] = src[x]; ++ init_y = 1; ++ } ++ if (borders[3]) { ++ ptrdiff_t y_stride_dst = stride_dst * (height - 1); ++ ptrdiff_t y_stride_src = stride_src * (height - 1); ++ for (x = init_x; x < width; x++) ++ dst[x + y_stride_dst] = src[x + y_stride_src]; ++ height--; ++ } ++ } ++ ++ { ++ int save_upper_left = !diag_edge[0] && sao_eo_class == SAO_EO_135D && !borders[0] && !borders[1]; ++ int save_upper_right = !diag_edge[1] && sao_eo_class == SAO_EO_45D && !borders[1] && !borders[2]; ++ int save_lower_right = !diag_edge[2] && sao_eo_class == SAO_EO_135D && !borders[2] && !borders[3]; ++ int save_lower_left = !diag_edge[3] && sao_eo_class == SAO_EO_45D && !borders[0] && !borders[3]; ++ ++ // Restore pixels that can't be modified ++ if(vert_edge[0] && sao_eo_class != SAO_EO_VERT) { ++ for(y = init_y+save_upper_left; y< height-save_lower_left; y++) ++ dst[y*stride_dst] = src[y*stride_src]; ++ } ++ if(vert_edge[1] && sao_eo_class != SAO_EO_VERT) { ++ for(y = init_y+save_upper_right; y< height-save_lower_right; y++) ++ dst[y*stride_dst+width-1] = src[y*stride_src+width-1]; ++ } ++ ++ if(horiz_edge[0] && sao_eo_class != SAO_EO_HORIZ) { ++ for(x = init_x+save_upper_left; x < width-save_upper_right; x++) ++ dst[x] = src[x]; ++ } ++ if(horiz_edge[1] && sao_eo_class != SAO_EO_HORIZ) { ++ for(x = init_x+save_lower_left; x < width-save_lower_right; x++) ++ dst[(height-1)*stride_dst+x] = src[(height-1)*stride_src+x]; ++ } ++ if(diag_edge[0] && sao_eo_class == SAO_EO_135D) ++ dst[0] = src[0]; ++ if(diag_edge[1] && sao_eo_class == SAO_EO_45D) ++ dst[width-1] = src[width-1]; ++ if(diag_edge[2] && sao_eo_class == SAO_EO_135D) ++ dst[stride_dst*(height-1)+width-1] = src[stride_src*(height-1)+width-1]; ++ if(diag_edge[3] && sao_eo_class == SAO_EO_45D) ++ dst[stride_dst*(height-1)] = src[stride_src*(height-1)]; ++ ++ } ++} ++#endif ++#if BIT_DEPTH == 32 ++#undef BIT_DEPTH ++#undef pixel ++#define BIT_DEPTH 10 ++#define pixel uint16_t ++#endif ++ ++// --- Plaited chroma versions ++ ++static void FUNC(sao_band_filter_c)(uint8_t *_dst, const uint8_t *_src, ++ ptrdiff_t stride_dst, ptrdiff_t stride_src, ++ const int16_t *sao_offset_val_u, int sao_left_class_u, ++ const int16_t *sao_offset_val_v, int sao_left_class_v, ++ int width, int height) ++{ ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int offset_table_u[32] = { 0 }; ++ int offset_table_v[32] = { 0 }; ++ int k, y, x; ++ int shift = BIT_DEPTH - 5; ++ ++ stride_dst /= sizeof(pixel); ++ stride_src /= sizeof(pixel); ++ width *= 2; ++ ++ for (k = 0; k < 4; k++) ++ { ++ offset_table_u[(k + sao_left_class_u) & 31] = sao_offset_val_u[k + 1]; ++ offset_table_v[(k + sao_left_class_v) & 31] = sao_offset_val_v[k + 1]; ++ } ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x += 2) ++ { ++// printf("dst=%p, src=%p, x=%d, shift=%d\n", dst, src, x, shift); ++// printf("offsets=%x,%x\n", src[x + 0], src[x + 1]); ++ // *** & 31 shouldn't be wanted but just now we generate broken input that ++ // crashes us in 10-bit world ++ dst[x + 0] = av_clip_pixel(src[x + 0] + offset_table_u[(src[x + 0] >> shift) & 31]); ++ dst[x + 1] = av_clip_pixel(src[x + 1] + offset_table_v[(src[x + 1] >> shift) & 31]); ++ } ++ dst += stride_dst; ++ src += stride_src; ++ } ++} ++ ++static void FUNC(sao_edge_filter_c)(uint8_t *_dst, const uint8_t *_src, ptrdiff_t stride_dst, ++ const int16_t *sao_offset_val_u, const int16_t *sao_offset_val_v, ++ int eo, int width, int height) { ++ ++ static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; ++ static const int8_t pos[4][2][2] = { ++ { { -1, 0 }, { 1, 0 } }, // horizontal ++ { { 0, -1 }, { 0, 1 } }, // vertical ++ { { -1, -1 }, { 1, 1 } }, // 45 degree ++ { { 1, -1 }, { -1, 1 } }, // 135 degree ++ }; ++ pixel *dst = (pixel *)_dst; ++ pixel *src = (pixel *)_src; ++ int a_stride, b_stride; ++ int x, y; ++ const ptrdiff_t stride_src = RPI_HEVC_SAO_BUF_STRIDE / sizeof(pixel); ++ ++ stride_dst /= sizeof(pixel); ++ width *= 2; ++ ++ av_assert0(width <= 64); ++ ++ a_stride = pos[eo][0][0] * 2 + pos[eo][0][1] * stride_src; ++ b_stride = pos[eo][1][0] * 2 + pos[eo][1][1] * stride_src; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x += 2) { ++ int diff0u = CMP(src[x], src[x + a_stride]); ++ int diff1u = CMP(src[x], src[x + b_stride]); ++ int offset_valu = edge_idx[2 + diff0u + diff1u]; ++ int diff0v = CMP(src[x+1], src[x+1 + a_stride]); ++ int diff1v = CMP(src[x+1], src[x+1 + b_stride]); ++ int offset_valv = edge_idx[2 + diff0v + diff1v]; ++ dst[x] = av_clip_pixel(src[x] + sao_offset_val_u[offset_valu]); ++ dst[x+1] = av_clip_pixel(src[x+1] + sao_offset_val_v[offset_valv]); ++ } ++ src += stride_src; ++ dst += stride_dst; ++ } ++} ++ ++// Do once ++#if BIT_DEPTH == 8 ++// Any old 2 byte 'normal' restore will work for these ++#define sao_edge_restore_c_0_8 sao_edge_restore_0_16 ++#define sao_edge_restore_c_1_8 sao_edge_restore_1_16 ++// We need 32 bit for 9 bit+ ++#define sao_edge_restore_c_0_9 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_9 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_10 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_10 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_11 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_11 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_12 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_12 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_13 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_13 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_14 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_14 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_15 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_15 sao_edge_restore_1_32 ++#define sao_edge_restore_c_0_16 sao_edge_restore_0_32 ++#define sao_edge_restore_c_1_16 sao_edge_restore_1_32 ++#endif ++ ++#undef CMP ++ ++//////////////////////////////////////////////////////////////////////////////// ++// ++//////////////////////////////////////////////////////////////////////////////// ++static void FUNC(put_hevc_pel_pixels)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = src[x] << (14 - BIT_DEPTH); ++ src += srcstride; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_pel_uni_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ for (y = 0; y < height; y++) { ++ memcpy(dst, src, width * sizeof(pixel)); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((src[x] << (14 - BIT_DEPTH)) + src2[x] + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel((((src[x] << (14 - BIT_DEPTH)) * wx + offset) >> shift) + ox); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) { ++ dst[x] = av_clip_pixel(( (src[x] << (14 - BIT_DEPTH)) * wx1 + src2[x] * wx0 + (ox0 + ox1 + 1) * (1 << log2Wd)) >> (log2Wd + 1)); ++ } ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// ++//////////////////////////////////////////////////////////////////////////////// ++#define QPEL_FILTER(src, stride) \ ++ (filter[0] * src[x - 3 * stride] + \ ++ filter[1] * src[x - 2 * stride] + \ ++ filter[2] * src[x - stride] + \ ++ filter[3] * src[x ] + \ ++ filter[4] * src[x + stride] + \ ++ filter[5] * src[x + 2 * stride] + \ ++ filter[6] * src[x + 3 * stride] + \ ++ filter[7] * src[x + 4 * stride]) ++ ++static void FUNC(put_hevc_qpel_h)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_v)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_hv)(int16_t *dst, ++ uint8_t *_src, ++ ptrdiff_t _srcstride, ++ int height, intptr_t mx, ++ intptr_t my, int width) ++{ ++ int x, y; ++ const int8_t *filter; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ ++ src -= QPEL_EXTRA_BEFORE * srcstride; ++ filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height + QPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6; ++ tmp += MAX_PB_SIZE; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ int shift = 14 - BIT_DEPTH; ++ ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ int shift = 14 - BIT_DEPTH; ++ ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++ ++static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ const int8_t *filter; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 - BIT_DEPTH; ++ ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= QPEL_EXTRA_BEFORE * srcstride; ++ filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height + QPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ const int8_t *filter; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= QPEL_EXTRA_BEFORE * srcstride; ++ filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height + QPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, ++ intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel((((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, ++ intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel((((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ ++ const int8_t *filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, ++ intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ const int8_t *filter; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= QPEL_EXTRA_BEFORE * srcstride; ++ filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height + QPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel((((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ const int8_t *filter; ++ pixel *src = (pixel*)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ src -= QPEL_EXTRA_BEFORE * srcstride; ++ filter = ff_hevc_rpi_qpel_filters[mx - 1]; ++ for (y = 0; y < height + QPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_qpel_filters[my - 1]; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// ++//////////////////////////////////////////////////////////////////////////////// ++#define EPEL_FILTER(src, stride) \ ++ (filter[0] * src[x - stride] + \ ++ filter[1] * src[x] + \ ++ filter[2] * src[x + stride] + \ ++ filter[3] * src[x + 2 * stride]) ++ ++static void FUNC(put_hevc_epel_h)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_v)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_hv)(int16_t *dst, ++ uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ ++ src -= EPEL_EXTRA_BEFORE * srcstride; ++ ++ for (y = 0; y < height + EPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6; ++ tmp += MAX_PB_SIZE; ++ dst += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int shift = 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) { ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); ++ } ++ dst += dststride; ++ src += srcstride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[my - 1]; ++ int shift = 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift); ++ src += srcstride; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[my - 1]; ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift); ++ dst += dststride; ++ src += srcstride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= EPEL_EXTRA_BEFORE * srcstride; ++ ++ for (y = 0; y < height + EPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 + 1 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= EPEL_EXTRA_BEFORE * srcstride; ++ ++ for (y = 0; y < height + EPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) { ++ dst[x] = av_clip_pixel((((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); ++ } ++ dst += dststride; ++ src += srcstride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[my - 1]; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) { ++ dst[x] = av_clip_pixel((((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox); ++ } ++ dst += dststride; ++ src += srcstride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[my - 1]; ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); ++ src += srcstride; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = denom + 14 - BIT_DEPTH; ++#if BIT_DEPTH < 14 ++ int offset = 1 << (shift - 1); ++#else ++ int offset = 0; ++#endif ++ ++ src -= EPEL_EXTRA_BEFORE * srcstride; ++ ++ for (y = 0; y < height + EPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ ox = ox * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel((((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ } ++} ++ ++static void FUNC(put_hevc_epel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, ++ int16_t *src2, ++ int height, int denom, int wx0, int wx1, ++ int ox0, int ox1, intptr_t mx, intptr_t my, int width) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ ptrdiff_t srcstride = _srcstride / sizeof(pixel); ++ pixel *dst = (pixel *)_dst; ++ ptrdiff_t dststride = _dststride / sizeof(pixel); ++ const int8_t *filter = ff_hevc_rpi_epel_filters[mx - 1]; ++ int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE]; ++ int16_t *tmp = tmp_array; ++ int shift = 14 + 1 - BIT_DEPTH; ++ int log2Wd = denom + shift - 1; ++ ++ src -= EPEL_EXTRA_BEFORE * srcstride; ++ ++ for (y = 0; y < height + EPEL_EXTRA; y++) { ++ for (x = 0; x < width; x++) ++ tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8); ++ src += srcstride; ++ tmp += MAX_PB_SIZE; ++ } ++ ++ tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE; ++ filter = ff_hevc_rpi_epel_filters[my - 1]; ++ ++ ox0 = ox0 * (1 << (BIT_DEPTH - 8)); ++ ox1 = ox1 * (1 << (BIT_DEPTH - 8)); ++ for (y = 0; y < height; y++) { ++ for (x = 0; x < width; x++) ++ dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 + ++ ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); ++ tmp += MAX_PB_SIZE; ++ dst += dststride; ++ src2 += MAX_PB_SIZE; ++ } ++} ++ ++// line zero ++#define P3 pix[-4 * xstride] ++#define P2 pix[-3 * xstride] ++#define P1 pix[-2 * xstride] ++#define P0 pix[-1 * xstride] ++#define Q0 pix[0 * xstride] ++#define Q1 pix[1 * xstride] ++#define Q2 pix[2 * xstride] ++#define Q3 pix[3 * xstride] ++ ++// line three. used only for deblocking decision ++#define TP3 pix[-4 * xstride + 3 * ystride] ++#define TP2 pix[-3 * xstride + 3 * ystride] ++#define TP1 pix[-2 * xstride + 3 * ystride] ++#define TP0 pix[-1 * xstride + 3 * ystride] ++#define TQ0 pix[0 * xstride + 3 * ystride] ++#define TQ1 pix[1 * xstride + 3 * ystride] ++#define TQ2 pix[2 * xstride + 3 * ystride] ++#define TQ3 pix[3 * xstride + 3 * ystride] ++ ++static void FUNC(hevc_loop_filter_luma)(uint8_t *_pix, ++ ptrdiff_t _xstride, ptrdiff_t _ystride, ++ int beta, int *_tc, ++ uint8_t *_no_p, uint8_t *_no_q) ++{ ++ int d, j; ++ pixel *pix = (pixel *)_pix; ++ ptrdiff_t xstride = _xstride / sizeof(pixel); ++ ptrdiff_t ystride = _ystride / sizeof(pixel); ++ ++ beta <<= BIT_DEPTH - 8; ++ ++ for (j = 0; j < 2; j++) { ++ const int dp0 = abs(P2 - 2 * P1 + P0); ++ const int dq0 = abs(Q2 - 2 * Q1 + Q0); ++ const int dp3 = abs(TP2 - 2 * TP1 + TP0); ++ const int dq3 = abs(TQ2 - 2 * TQ1 + TQ0); ++ const int d0 = dp0 + dq0; ++ const int d3 = dp3 + dq3; ++ const int tc = _tc[j] << (BIT_DEPTH - 8); ++ const int no_p = _no_p[j]; ++ const int no_q = _no_q[j]; ++ ++ if (d0 + d3 >= beta) { ++ pix += 4 * ystride; ++ continue; ++ } else { ++ const int beta_3 = beta >> 3; ++ const int beta_2 = beta >> 2; ++ const int tc25 = ((tc * 5 + 1) >> 1); ++ ++ if (abs(P3 - P0) + abs(Q3 - Q0) < beta_3 && abs(P0 - Q0) < tc25 && ++ abs(TP3 - TP0) + abs(TQ3 - TQ0) < beta_3 && abs(TP0 - TQ0) < tc25 && ++ (d0 << 1) < beta_2 && (d3 << 1) < beta_2) { ++ // strong filtering ++ const int tc2 = tc << 1; ++ for (d = 0; d < 4; d++) { ++ const int p3 = P3; ++ const int p2 = P2; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ const int q2 = Q2; ++ const int q3 = Q3; ++ if (!no_p) { ++ P0 = p0 + av_clip(((p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4) >> 3) - p0, -tc2, tc2); ++ P1 = p1 + av_clip(((p2 + p1 + p0 + q0 + 2) >> 2) - p1, -tc2, tc2); ++ P2 = p2 + av_clip(((2 * p3 + 3 * p2 + p1 + p0 + q0 + 4) >> 3) - p2, -tc2, tc2); ++ } ++ if (!no_q) { ++ Q0 = q0 + av_clip(((p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 + 4) >> 3) - q0, -tc2, tc2); ++ Q1 = q1 + av_clip(((p0 + q0 + q1 + q2 + 2) >> 2) - q1, -tc2, tc2); ++ Q2 = q2 + av_clip(((2 * q3 + 3 * q2 + q1 + q0 + p0 + 4) >> 3) - q2, -tc2, tc2); ++ } ++ pix += ystride; ++ } ++ } else { // normal filtering ++ int nd_p = 1; ++ int nd_q = 1; ++ const int tc_2 = tc >> 1; ++ if (dp0 + dp3 < ((beta + (beta >> 1)) >> 3)) ++ nd_p = 2; ++ if (dq0 + dq3 < ((beta + (beta >> 1)) >> 3)) ++ nd_q = 2; ++ ++ for (d = 0; d < 4; d++) { ++ const int p2 = P2; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ const int q2 = Q2; ++ int delta0 = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4; ++ if (abs(delta0) < 10 * tc) { ++ delta0 = av_clip(delta0, -tc, tc); ++ if (!no_p) ++ P0 = av_clip_pixel(p0 + delta0); ++ if (!no_q) ++ Q0 = av_clip_pixel(q0 - delta0); ++ if (!no_p && nd_p > 1) { ++ const int deltap1 = av_clip((((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1, -tc_2, tc_2); ++ P1 = av_clip_pixel(p1 + deltap1); ++ } ++ if (!no_q && nd_q > 1) { ++ const int deltaq1 = av_clip((((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1, -tc_2, tc_2); ++ Q1 = av_clip_pixel(q1 + deltaq1); ++ } ++ } ++ pix += ystride; ++ } ++ } ++ } ++ } ++} ++ ++static void FUNC(hevc_loop_filter_chroma)(uint8_t *_pix, ptrdiff_t _xstride, ++ ptrdiff_t _ystride, int *_tc, ++ uint8_t *_no_p, uint8_t *_no_q) ++{ ++ int d, j, no_p, no_q; ++ pixel *pix = (pixel *)_pix; ++ ptrdiff_t xstride = _xstride / sizeof(pixel); ++ ptrdiff_t ystride = _ystride / sizeof(pixel); ++ ++ for (j = 0; j < 2; j++) { ++ const int tc = _tc[j] << (BIT_DEPTH - 8); ++ if (tc <= 0) { ++ pix += 4 * ystride; ++ continue; ++ } ++ no_p = _no_p[j]; ++ no_q = _no_q[j]; ++ ++ for (d = 0; d < 4; d++) { ++ int delta0; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ delta0 = av_clip((((q0 - p0) * 4) + p1 - q1 + 4) >> 3, -tc, tc); ++ if (!no_p) ++ P0 = av_clip_pixel(p0 + delta0); ++ if (!no_q) ++ Q0 = av_clip_pixel(q0 - delta0); ++ pix += ystride; ++ } ++ } ++} ++ ++static void FUNC(hevc_h_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride, ++ int32_t *tc, uint8_t *no_p, ++ uint8_t *no_q) ++{ ++ FUNC(hevc_loop_filter_chroma)(pix, stride, sizeof(pixel), tc, no_p, no_q); ++} ++ ++static void FUNC(hevc_v_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride, ++ int32_t *tc, uint8_t *no_p, ++ uint8_t *no_q) ++{ ++ FUNC(hevc_loop_filter_chroma)(pix, sizeof(pixel), stride, tc, no_p, no_q); ++} ++ ++static void FUNC(hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride, ++ int beta, int32_t *tc, uint8_t *no_p, ++ uint8_t *no_q) ++{ ++ FUNC(hevc_loop_filter_luma)(pix, stride, sizeof(pixel), ++ beta, tc, no_p, no_q); ++} ++ ++static void FUNC(hevc_v_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride, ++ int beta, int32_t *tc, uint8_t *no_p, ++ uint8_t *no_q) ++{ ++ FUNC(hevc_loop_filter_luma)(pix, sizeof(pixel), stride, ++ beta, tc, no_p, no_q); ++} ++ ++#undef P3 ++#undef P2 ++#undef P1 ++#undef P0 ++#undef Q0 ++#undef Q1 ++#undef Q2 ++#undef Q3 ++ ++#undef TP3 ++#undef TP2 ++#undef TP1 ++#undef TP0 ++#undef TQ0 ++#undef TQ1 ++#undef TQ2 ++#undef TQ3 ++ ++// line zero ++#define P3 pix_l[0 * xstride] ++#define P2 pix_l[1 * xstride] ++#define P1 pix_l[2 * xstride] ++#define P0 pix_l[3 * xstride] ++#define Q0 pix_r[0 * xstride] ++#define Q1 pix_r[1 * xstride] ++#define Q2 pix_r[2 * xstride] ++#define Q3 pix_r[3 * xstride] ++ ++// line three. used only for deblocking decision ++#define TP3 pix_l[0 * xstride + 3 * ystride] ++#define TP2 pix_l[1 * xstride + 3 * ystride] ++#define TP1 pix_l[2 * xstride + 3 * ystride] ++#define TP0 pix_l[3 * xstride + 3 * ystride] ++#define TQ0 pix_r[0 * xstride + 3 * ystride] ++#define TQ1 pix_r[1 * xstride + 3 * ystride] ++#define TQ2 pix_r[2 * xstride + 3 * ystride] ++#define TQ3 pix_r[3 * xstride + 3 * ystride] ++ ++// This is identical to hevc_loop_filter_luma except that the P/Q ++// components are on separate pointers ++static void FUNC(hevc_v_loop_filter_luma2)(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f, ++ uint8_t * _pix_l) ++{ ++ int d, j; ++ pixel *pix_l = (pixel *)_pix_l; ++ pixel *pix_r = (pixel *)_pix_r; ++ const ptrdiff_t xstride = 1; ++ const ptrdiff_t ystride = _stride / sizeof(pixel); ++ ++ beta <<= BIT_DEPTH - 8; ++ ++ for (j = 0; j < 2; j++) { ++ const int dp0 = abs(P2 - 2 * P1 + P0); ++ const int dq0 = abs(Q2 - 2 * Q1 + Q0); ++ const int dp3 = abs(TP2 - 2 * TP1 + TP0); ++ const int dq3 = abs(TQ2 - 2 * TQ1 + TQ0); ++ const int d0 = dp0 + dq0; ++ const int d3 = dp3 + dq3; ++ const int tc = ((tc2 >> (j << 4)) & 0xffff) << (BIT_DEPTH - 8); ++ const int no_p = no_f & 1; ++ const int no_q = no_f & 2; ++ ++ if (d0 + d3 >= beta) { ++ pix_l += 4 * ystride; ++ pix_r += 4 * ystride; ++ continue; ++ } else { ++ const int beta_3 = beta >> 3; ++ const int beta_2 = beta >> 2; ++ const int tc25 = ((tc * 5 + 1) >> 1); ++ ++ if (abs(P3 - P0) + abs(Q3 - Q0) < beta_3 && abs(P0 - Q0) < tc25 && ++ abs(TP3 - TP0) + abs(TQ3 - TQ0) < beta_3 && abs(TP0 - TQ0) < tc25 && ++ (d0 << 1) < beta_2 && (d3 << 1) < beta_2) { ++ // strong filtering ++ const int tc2 = tc << 1; ++ for (d = 0; d < 4; d++) { ++ const int p3 = P3; ++ const int p2 = P2; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ const int q2 = Q2; ++ const int q3 = Q3; ++ if (!no_p) { ++ P0 = p0 + av_clip(((p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4) >> 3) - p0, -tc2, tc2); ++ P1 = p1 + av_clip(((p2 + p1 + p0 + q0 + 2) >> 2) - p1, -tc2, tc2); ++ P2 = p2 + av_clip(((2 * p3 + 3 * p2 + p1 + p0 + q0 + 4) >> 3) - p2, -tc2, tc2); ++ } ++ if (!no_q) { ++ Q0 = q0 + av_clip(((p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 + 4) >> 3) - q0, -tc2, tc2); ++ Q1 = q1 + av_clip(((p0 + q0 + q1 + q2 + 2) >> 2) - q1, -tc2, tc2); ++ Q2 = q2 + av_clip(((2 * q3 + 3 * q2 + q1 + q0 + p0 + 4) >> 3) - q2, -tc2, tc2); ++ } ++ pix_l += ystride; ++ pix_r += ystride; ++ } ++ } else { // normal filtering ++ int nd_p = 1; ++ int nd_q = 1; ++ const int tc_2 = tc >> 1; ++ if (dp0 + dp3 < ((beta + (beta >> 1)) >> 3)) ++ nd_p = 2; ++ if (dq0 + dq3 < ((beta + (beta >> 1)) >> 3)) ++ nd_q = 2; ++ ++ for (d = 0; d < 4; d++) { ++ const int p2 = P2; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ const int q2 = Q2; ++ int delta0 = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4; ++ if (abs(delta0) < 10 * tc) { ++ delta0 = av_clip(delta0, -tc, tc); ++ if (!no_p) ++ P0 = av_clip_pixel(p0 + delta0); ++ if (!no_q) ++ Q0 = av_clip_pixel(q0 - delta0); ++ if (!no_p && nd_p > 1) { ++ const int deltap1 = av_clip((((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1, -tc_2, tc_2); ++ P1 = av_clip_pixel(p1 + deltap1); ++ } ++ if (!no_q && nd_q > 1) { ++ const int deltaq1 = av_clip((((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1, -tc_2, tc_2); ++ Q1 = av_clip_pixel(q1 + deltaq1); ++ } ++ } ++ pix_l += ystride; ++ pix_r += ystride; ++ } ++ } ++ } ++ } ++} ++ ++static void FUNC(hevc_h_loop_filter_luma2)(uint8_t * _pix_r, ++ unsigned int _stride, unsigned int beta, unsigned int tc2, unsigned int no_f) ++{ ++ // Just call the non-2 function having massaged the parameters ++ int32_t tc[2] = {tc2 & 0xffff, tc2 >> 16}; ++ uint8_t no_p[2] = {no_f & 1, no_f & 1}; ++ uint8_t no_q[2] = {no_f & 2, no_f & 2}; ++ FUNC(hevc_h_loop_filter_luma)(_pix_r, _stride, beta, tc, no_p, no_q); ++} ++ ++#undef TP3 ++#undef TP2 ++#undef TP1 ++#undef TP0 ++#undef TQ0 ++#undef TQ1 ++#undef TQ2 ++#undef TQ3 ++ ++#undef P3 ++#undef P2 ++#undef P1 ++#undef P0 ++#undef Q0 ++#undef Q1 ++#undef Q2 ++#undef Q3 ++ ++#define P1 pix_l[0 * xstride] ++#define P0 pix_l[1 * xstride] ++#define Q0 pix_r[0 * xstride] ++#define Q1 pix_r[1 * xstride] ++ ++static void FUNC(hevc_loop_filter_uv2)(uint8_t *_pix_l, ptrdiff_t _xstride, ++ ptrdiff_t _ystride, const int32_t *_tc, ++ const uint8_t *_no_p, const uint8_t *_no_q, uint8_t *_pix_r) ++{ ++ int d, j, no_p, no_q; ++ pixel *pix_l = (pixel *)_pix_l; ++ pixel *pix_r = (pixel *)_pix_r; ++ ptrdiff_t xstride = _xstride / sizeof(pixel); ++ ptrdiff_t ystride = _ystride / sizeof(pixel); ++ ++ for (j = 0; j < 2; j++) { ++ const int tc = _tc[j] << (BIT_DEPTH - 8); ++ if (tc <= 0) { ++ pix_l += 4 * ystride; ++ pix_r += 4 * ystride; ++ continue; ++ } ++ no_p = _no_p[j]; ++ no_q = _no_q[j]; ++ ++ for (d = 0; d < 4; d++) { ++ int delta0; ++ const int p1 = P1; ++ const int p0 = P0; ++ const int q0 = Q0; ++ const int q1 = Q1; ++ delta0 = av_clip((((q0 - p0) * 4) + p1 - q1 + 4) >> 3, -tc, tc); ++ if (!no_p) ++ P0 = av_clip_pixel(p0 + delta0); ++ if (!no_q) ++ Q0 = av_clip_pixel(q0 - delta0); ++ pix_l += ystride; ++ pix_r += ystride; ++ } ++ } ++} ++ ++static void FUNC(hevc_h_loop_filter_uv)(uint8_t * pix, unsigned int stride, uint32_t tc4, ++ unsigned int no_f) ++{ ++ uint8_t no_p[2] = {no_f & 1, no_f & 2}; ++ uint8_t no_q[2] = {no_f & 4, no_f & 8}; ++ int32_t tc[4] = {tc4 & 0xff, (tc4 >> 8) & 0xff, (tc4 >> 16) & 0xff, tc4 >> 24}; ++ FUNC(hevc_loop_filter_chroma)(pix, stride, sizeof(pixel) * 2, tc, no_p, no_q); ++ FUNC(hevc_loop_filter_chroma)(pix + sizeof(pixel), stride, sizeof(pixel) * 2, tc + 2, no_p, no_q); ++} ++ ++static void FUNC(hevc_v_loop_filter_uv2)(uint8_t * src_r, unsigned int stride, uint32_t tc4, ++ uint8_t * src_l, ++ unsigned int no_f) ++{ ++ uint8_t no_p[2] = {no_f & 1, no_f & 2}; ++ uint8_t no_q[2] = {no_f & 4, no_f & 8}; ++ int32_t tc[4] = {tc4 & 0xff, (tc4 >> 8) & 0xff, (tc4 >> 16) & 0xff, tc4 >> 24}; ++ FUNC(hevc_loop_filter_uv2)(src_l, sizeof(pixel) * 2, stride, tc, no_p, no_q, src_r); ++ FUNC(hevc_loop_filter_uv2)(src_l + sizeof(pixel), sizeof(pixel) * 2, stride, tc + 2, no_p, no_q, src_r + sizeof(pixel)); ++} ++ ++#undef P1 ++#undef P0 ++#undef Q0 ++#undef Q1 ++ +diff --git a/libavcodec/rpi_hevcpred.c b/libavcodec/rpi_hevcpred.c +new file mode 100644 +index 0000000000..0aa8809a4b +--- /dev/null ++++ b/libavcodec/rpi_hevcpred.c +@@ -0,0 +1,161 @@ ++/* ++ * HEVC video Decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2018 John Cox for Raspberry Pi (Trading) ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "rpi_hevcdec.h" ++ ++#include "rpi_hevcpred.h" ++#if (ARCH_ARM) ++#include "arm/rpi_hevcpred_arm.h" ++#endif ++ ++#define PRED_C 0 ++#define BIT_DEPTH 8 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 9 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 10 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 12 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++#undef PRED_C ++ ++#define PRED_C 1 ++#define BIT_DEPTH 8 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 9 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 10 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++ ++#define BIT_DEPTH 12 ++#include "rpi_hevcpred_template.c" ++#undef BIT_DEPTH ++#undef PRED_C ++ ++void ff_hevc_rpi_pred_init(HEVCRpiPredContext *hpc, int bit_depth) ++{ ++#undef FUNC ++#define FUNC(a, depth) a ## _ ## depth ++ ++#undef FUNCC ++#define FUNCC(a, depth) a ## _ ## depth ## _c ++ ++#define HEVC_PRED_Y(depth) \ ++ hpc->intra_pred = FUNC(intra_pred, depth); \ ++ hpc->intra_filter[0] = FUNC(intra_filter_2, depth); \ ++ hpc->intra_filter[1] = FUNC(intra_filter_3, depth); \ ++ hpc->intra_filter[2] = FUNC(intra_filter_4, depth); \ ++ hpc->intra_filter[3] = FUNC(intra_filter_5, depth); \ ++ hpc->pred_planar[0] = FUNC(pred_planar_0, depth); \ ++ hpc->pred_planar[1] = FUNC(pred_planar_1, depth); \ ++ hpc->pred_planar[2] = FUNC(pred_planar_2, depth); \ ++ hpc->pred_planar[3] = FUNC(pred_planar_3, depth); \ ++ hpc->pred_dc[0] = FUNC(pred_dc_0, depth); \ ++ hpc->pred_dc[1] = FUNC(pred_dc_1, depth); \ ++ hpc->pred_dc[2] = FUNC(pred_dc_2, depth); \ ++ hpc->pred_dc[3] = FUNC(pred_dc_3, depth); \ ++ hpc->pred_vertical[0] = FUNC(pred_angular_0, depth); \ ++ hpc->pred_vertical[1] = FUNC(pred_angular_1, depth); \ ++ hpc->pred_vertical[2] = FUNC(pred_angular_2, depth); \ ++ hpc->pred_vertical[3] = FUNC(pred_angular_3, depth); \ ++ hpc->pred_horizontal[0] = FUNC(pred_angular_0, depth); \ ++ hpc->pred_horizontal[1] = FUNC(pred_angular_1, depth); \ ++ hpc->pred_horizontal[2] = FUNC(pred_angular_2, depth); \ ++ hpc->pred_horizontal[3] = FUNC(pred_angular_3, depth); \ ++ hpc->pred_angular[0] = FUNC(pred_angular_0, depth); \ ++ hpc->pred_angular[1] = FUNC(pred_angular_1, depth); \ ++ hpc->pred_angular[2] = FUNC(pred_angular_2, depth); \ ++ hpc->pred_angular[3] = FUNC(pred_angular_3, depth); \ ++ hpc->pred_dc0[0] = FUNC(pred_dc0_0, depth); \ ++ hpc->pred_dc0[1] = FUNC(pred_dc0_1, depth); \ ++ hpc->pred_dc0[2] = FUNC(pred_dc0_2, depth); \ ++ hpc->pred_dc0[3] = FUNC(pred_dc0_3, depth); ++ ++#define HEVC_PRED_C(depth) \ ++ hpc->intra_pred_c = FUNCC(intra_pred, depth); \ ++ hpc->intra_filter_c[0] = FUNCC(intra_filter_2, depth); \ ++ hpc->intra_filter_c[1] = FUNCC(intra_filter_3, depth); \ ++ hpc->intra_filter_c[2] = FUNCC(intra_filter_4, depth); \ ++ hpc->intra_filter_c[3] = FUNCC(intra_filter_5, depth); \ ++ hpc->pred_planar_c[0] = FUNCC(pred_planar_0, depth); \ ++ hpc->pred_planar_c[1] = FUNCC(pred_planar_1, depth); \ ++ hpc->pred_planar_c[2] = FUNCC(pred_planar_2, depth); \ ++ hpc->pred_planar_c[3] = FUNCC(pred_planar_3, depth); \ ++ hpc->pred_dc_c[0] = FUNCC(pred_dc_0, depth); \ ++ hpc->pred_dc_c[1] = FUNCC(pred_dc_1, depth); \ ++ hpc->pred_dc_c[2] = FUNCC(pred_dc_2, depth); \ ++ hpc->pred_dc_c[3] = FUNCC(pred_dc_3, depth); \ ++ hpc->pred_vertical_c[0] = FUNCC(pred_angular_0, depth); \ ++ hpc->pred_vertical_c[1] = FUNCC(pred_angular_1, depth); \ ++ hpc->pred_vertical_c[2] = FUNCC(pred_angular_2, depth); \ ++ hpc->pred_vertical_c[3] = FUNCC(pred_angular_3, depth); \ ++ hpc->pred_horizontal_c[0] = FUNCC(pred_angular_0, depth); \ ++ hpc->pred_horizontal_c[1] = FUNCC(pred_angular_1, depth); \ ++ hpc->pred_horizontal_c[2] = FUNCC(pred_angular_2, depth); \ ++ hpc->pred_horizontal_c[3] = FUNCC(pred_angular_3, depth); \ ++ hpc->pred_angular_c[0] = FUNCC(pred_angular_0, depth); \ ++ hpc->pred_angular_c[1] = FUNCC(pred_angular_1, depth); \ ++ hpc->pred_angular_c[2] = FUNCC(pred_angular_2, depth); \ ++ hpc->pred_angular_c[3] = FUNCC(pred_angular_3, depth); \ ++ hpc->pred_dc0_c[0] = FUNCC(pred_dc0_0, depth); \ ++ hpc->pred_dc0_c[1] = FUNCC(pred_dc0_1, depth); \ ++ hpc->pred_dc0_c[2] = FUNCC(pred_dc0_2, depth); \ ++ hpc->pred_dc0_c[3] = FUNCC(pred_dc0_3, depth); ++ ++#define HEVC_PRED(depth) \ ++ HEVC_PRED_Y(depth); \ ++ HEVC_PRED_C(depth); ++ ++ switch (bit_depth) { ++ case 9: ++ HEVC_PRED(9); ++ break; ++ case 10: ++ HEVC_PRED(10); ++ break; ++ case 12: ++ HEVC_PRED(12); ++ break; ++ default: ++ HEVC_PRED(8); ++ break; ++ } ++ ++#if (ARCH_ARM) ++ ff_hevc_rpi_pred_init_arm(hpc, bit_depth); ++#elif (ARCH_MIPS) ++ ff_hevc_rpi_pred_init_mips(hpc, bit_depth); ++#endif ++} +diff --git a/libavcodec/rpi_hevcpred.h b/libavcodec/rpi_hevcpred.h +new file mode 100644 +index 0000000000..9f0edb8798 +--- /dev/null ++++ b/libavcodec/rpi_hevcpred.h +@@ -0,0 +1,123 @@ ++/* ++ * HEVC video Decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_RPI_HEVCPRED_H ++#define AVCODEC_RPI_HEVCPRED_H ++ ++#include ++#include ++#include "config.h" ++ ++struct HEVCRpiContext; ++struct HEVCRpiLocalContext; ++ ++enum IntraPredMode { ++ INTRA_PLANAR = 0, ++ INTRA_DC, ++ INTRA_ANGULAR_2, ++ INTRA_ANGULAR_3, ++ INTRA_ANGULAR_4, ++ INTRA_ANGULAR_5, ++ INTRA_ANGULAR_6, ++ INTRA_ANGULAR_7, ++ INTRA_ANGULAR_8, ++ INTRA_ANGULAR_9, ++ INTRA_ANGULAR_10, ++ INTRA_ANGULAR_11, ++ INTRA_ANGULAR_12, ++ INTRA_ANGULAR_13, ++ INTRA_ANGULAR_14, ++ INTRA_ANGULAR_15, ++ INTRA_ANGULAR_16, ++ INTRA_ANGULAR_17, ++ INTRA_ANGULAR_18, ++ INTRA_ANGULAR_19, ++ INTRA_ANGULAR_20, ++ INTRA_ANGULAR_21, ++ INTRA_ANGULAR_22, ++ INTRA_ANGULAR_23, ++ INTRA_ANGULAR_24, ++ INTRA_ANGULAR_25, ++ INTRA_ANGULAR_26, ++ INTRA_ANGULAR_27, ++ INTRA_ANGULAR_28, ++ INTRA_ANGULAR_29, ++ INTRA_ANGULAR_30, ++ INTRA_ANGULAR_31, ++ INTRA_ANGULAR_32, ++ INTRA_ANGULAR_33, ++ INTRA_ANGULAR_34, ++}; ++#define INTRA_ANGULAR_HORIZONTAL INTRA_ANGULAR_10 ++#define INTRA_ANGULAR_VERTICAL INTRA_ANGULAR_26 ++ ++typedef void intra_filter_fn_t( ++ uint8_t * const left, uint8_t * const top, ++ const unsigned int req, const unsigned int avail, ++ const uint8_t * const src_l, const uint8_t * const src_u, const uint8_t * const src_ur, ++ const unsigned int stride, ++ const unsigned int top_right_size, const unsigned int down_left_size); ++ ++typedef struct HEVCRpiPredContext { ++ void (*intra_pred)(const struct HEVCRpiContext * const s, ++ const enum IntraPredMode mode, const unsigned int x0, const unsigned int y0, ++ const unsigned int avail, const unsigned int log2_size); ++ ++ intra_filter_fn_t *intra_filter[4]; ++ void (*pred_planar[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride); ++ void (*pred_dc[4])(uint8_t *src, const uint8_t *top, const uint8_t *left, ++ ptrdiff_t stride); ++ void (*pred_angular[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_vertical[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_horizontal[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_dc0[4])(uint8_t *src, ptrdiff_t stride); ++ ++ void (*intra_pred_c)(const struct HEVCRpiContext * const s, ++ const enum IntraPredMode mode, const unsigned int x0, const unsigned int y0, ++ const unsigned int avail, const unsigned int log2_size); ++ intra_filter_fn_t *intra_filter_c[4]; ++ void (*pred_planar_c[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride); ++ void (*pred_dc_c[4])(uint8_t *src, const uint8_t *top, const uint8_t *left, ++ ptrdiff_t stride); ++ void (*pred_angular_c[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_vertical_c[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_horizontal_c[4])(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ptrdiff_t stride, ++ int mode); ++ void (*pred_dc0_c[4])(uint8_t *src, ptrdiff_t stride); ++} HEVCRpiPredContext; ++ ++void ff_hevc_rpi_pred_init(HEVCRpiPredContext *hpc, int bit_depth); ++ ++#endif /* AVCODEC_RPI_HEVCPRED_H */ +diff --git a/libavcodec/rpi_hevcpred_template.c b/libavcodec/rpi_hevcpred_template.c +new file mode 100644 +index 0000000000..f2ebcad332 +--- /dev/null ++++ b/libavcodec/rpi_hevcpred_template.c +@@ -0,0 +1,1407 @@ ++/* ++ * HEVC video decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "config.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/rpi_sand_fns.h" ++#include "bit_depth_template.c" ++ ++#include "rpi_hevcdec.h" ++#include "rpi_hevcpred.h" ++ ++#define DUMP_PRED 0 ++ ++#define POS(x, y) src[(x) + stride * (y)] ++ ++// INCLUDED_ONCE defined at EOF ++#ifndef INCLUDED_ONCE ++typedef uint8_t (* c8_dst_ptr_t)[2]; ++typedef const uint8_t (* c8_src_ptr_t)[2]; ++typedef uint16_t (* c16_dst_ptr_t)[2]; ++typedef const uint16_t (* c16_src_ptr_t)[2]; ++ ++// *** On ARM make these NEON registers ++typedef struct pixel4_16 { ++ uint16_t x[4]; ++} pixel4_16; ++typedef struct pixel4_32 { ++ uint32_t x[4]; ++} pixel4_32; ++static inline pixel4_16 PIXEL_SPLAT_X4_16(const uint16_t x) ++{ ++ pixel4_16 t = {{x, x, x, x}}; ++ return t; ++} ++static inline pixel4_32 PIXEL_SPLAT_X4_32(const uint32_t x) ++{ ++ pixel4_32 t = {{x, x, x, x}}; ++ return t; ++} ++#endif ++ ++#if PRED_C ++// For chroma we double pixel size so we copy pairs ++#undef pixel ++#undef pixel2 ++#undef pixel4 ++#undef dctcoef ++#undef INIT_CLIP ++#undef no_rnd_avg_pixel4 ++#undef rnd_avg_pixel4 ++#undef AV_RN2P ++#undef AV_RN4P ++#undef AV_RN4PA ++#undef AV_WN2P ++#undef AV_WN4P ++#undef AV_WN4PA ++#undef CLIP ++#undef FUNC ++#undef FUNCC ++#undef av_clip_pixel ++#undef PIXEL_SPLAT_X4 ++ ++#if BIT_DEPTH == 8 ++#define pixel uint16_t ++#define pixel4 pixel4_16 ++#define PIXEL_SPLAT_X4 PIXEL_SPLAT_X4_16 ++#define cpel uint8_t ++#define c_src_ptr_t c8_src_ptr_t ++#define c_dst_ptr_t c8_dst_ptr_t ++#else ++#define pixel uint32_t ++#define pixel4 pixel4_32 ++#define PIXEL_SPLAT_X4 PIXEL_SPLAT_X4_32 ++#define cpel uint16_t ++#define c_src_ptr_t c16_dst_ptr_t ++#define c_dst_ptr_t c16_dst_ptr_t ++#endif ++#define AV_RN4P(p) (*(pixel4*)(p)) ++#define AV_WN4P(p,x) (*(pixel4*)(p) = (x)) ++#define FUNC(a) FUNC2(a, BIT_DEPTH, _c) ++#endif ++ ++ ++// Get PW prior to horrid PRED_C trickery ++#if BIT_DEPTH == 8 ++#define PW 1 ++#else ++#define PW 2 ++#endif ++ ++ ++#if DUMP_PRED && !defined(INCLUDED_ONCE) ++static void dump_pred_uv(const uint8_t * data, const unsigned int stride, const unsigned int size) ++{ ++ for (unsigned int y = 0; y != size; y++, data += stride * 2) { ++ for (unsigned int x = 0; x != size; x++) { ++ printf("%4d", data[x * 2]); ++ } ++ printf("\n"); ++ } ++ printf("\n"); ++} ++#endif ++ ++#ifndef INCLUDED_ONCE ++static inline void extend_8(void * ptr, const unsigned int v, unsigned int n) ++{ ++ if ((n >>= 2) != 0) { ++ uint32_t v4 = v | (v << 8); ++ uint32_t * p = (uint32_t *)ptr; ++ v4 = v4 | (v4 << 16); ++ do { ++ *p++ = v4; ++ } while (--n != 0); ++ } ++} ++ ++static inline void extend_16(void * ptr, const unsigned int v, unsigned int n) ++{ ++ if ((n >>= 2) != 0) { ++ uint32_t v2 = v | (v << 16); ++ uint32_t * p = (uint32_t *)ptr; ++ do { ++ *p++ = v2; ++ *p++ = v2; ++ } while (--n != 0); ++ } ++} ++ ++static inline void extend_32(void * ptr, const unsigned int v, unsigned int n) ++{ ++ if ((n >>= 2) != 0) { ++ uint32_t * p = (uint32_t *)ptr; ++ do { ++ *p++ = v; ++ *p++ = v; ++ *p++ = v; ++ *p++ = v; ++ } while (--n != 0); ++ } ++} ++ ++// Beware that this inverts the avail ordering ++// For CIP it seems easier this way round ++static unsigned int cip_avail_l(const uint8_t * is_intra, const int i_stride, const unsigned int i_mask, ++ const unsigned int log2_intra_bits, const unsigned int avail, unsigned int size, ++ unsigned int s0, unsigned int odd_s) ++{ ++ const unsigned int n = 1 << log2_intra_bits; ++ unsigned int fa = 0; ++ unsigned int i; ++ ++ size >>= 2; // Now in 4-pel units ++ s0 >>= 2; ++ ++ if ((avail & AVAIL_DL) != 0) ++ fa |= ((1 << s0) - 1) << (size - s0); ++ if ((avail & AVAIL_L) != 0) ++ fa |= ((1 << size) - 1) << size; ++ if ((avail & AVAIL_UL) != 0) ++ fa |= 1 << (size << 1); ++ ++ if (odd_s) { ++ if ((fa & 1) != 0 && (*is_intra & i_mask) == 0) ++ fa &= ~1; ++ is_intra += i_stride; ++ } ++ ++ for (i = odd_s; (fa >> i) != 0; i += n, is_intra += i_stride) { ++ const unsigned int m = ((1 << n) - 1) << i; ++ if ((fa & m) != 0 && (*is_intra & i_mask) == 0) ++ fa &= ~m; ++ } ++ ++ return fa; ++} ++ ++static unsigned int cip_avail_u(const uint8_t * is_intra, unsigned int i_shift, ++ const unsigned int log2_intra_bits, const unsigned int avail, unsigned int size, ++ unsigned int s1, unsigned int odd_s) ++{ ++ if ((avail & (AVAIL_U | AVAIL_UR)) == 0) ++ { ++ return 0; ++ } ++ else ++ { ++ const unsigned int n = 1 << log2_intra_bits; ++ unsigned int fa = 0; ++ unsigned int i; ++ unsigned int im = ((is_intra[1] << 8) | (is_intra[0])) >> i_shift; ++ ++ size >>= 2; // Now in 4-pel units ++ s1 >>= 2; ++ ++ if ((avail & AVAIL_U) != 0) ++ fa |= ((1 << size) - 1); ++ if ((avail & AVAIL_UR) != 0) ++ fa |= ((1 << s1) - 1) << size; ++ ++ if (odd_s) { ++ fa &= im | ~1; ++ im >>= 1; ++ } ++ ++ for (i = odd_s; (fa >> i) != 0; i += n, im >>= 1) { ++ const unsigned int m = ((1 << n) - 1) << i; ++ if ((im & 1) == 0) ++ fa &= ~m; ++ } ++ return fa; ++ } ++} ++ ++ ++ ++static inline unsigned int rmbd(unsigned int x) ++{ ++#if 1 ++ return __builtin_ctz(x); ++#else ++ unsigned int n = 0; ++ if ((x & 0xffff) == 0) { ++ x >>= 16; ++ n += 16; ++ } ++ if ((x & 0xff) == 0) { ++ x >>= 8; ++ n += 8; ++ } ++ if ((x & 0xf) == 0) { ++ x >>= 4; ++ n += 4; ++ } ++ if ((x & 0x3) == 0) { ++ x >>= 2; ++ n += 2; ++ } ++ ++ return (x & 1) == 0 ? n + 1 : n; ++#endif ++} ++#endif ++ ++ ++static void FUNC(cip_fill)(pixel * const left, pixel * const top, ++ const unsigned int avail_l, const unsigned int avail_u, ++ const pixel * const src_l, const pixel * const src_u, const pixel * const src_ur, ++ const unsigned int stride, ++ const unsigned int size) ++{ ++ pixel a; ++ unsigned int i; ++ ++ // 1st find DL value ++ if ((avail_l & 1) == 0) { ++ if (avail_l != 0) ++ a = src_l[((int)size * 2 - 1 - (int)rmbd(avail_l)*4) * (int)stride]; ++ else ++ { ++ // (avail_l | avail_u) != 0 so this must be good ++ const unsigned int n = rmbd(avail_u)*4; ++ a = (n >= size) ? src_ur[n - size] : src_u[n]; ++ } ++ } ++ ++ // L ++ { ++ pixel * d = left + size * 2 - 1; ++ const pixel * s = src_l + (size * 2 - 1) * stride; ++ unsigned int x = avail_l; ++ for (i = 0; i < size * 2; i += 4, x >>= 1) ++ { ++ if ((x & 1) != 0) { ++ // Avail ++ *d-- = *s; ++ s -= stride; ++ *d-- = *s; ++ s -= stride; ++ *d-- = *s; ++ s -= stride; ++ *d-- = a = *s; ++ s -= stride; ++ } ++ else ++ { ++ *d-- = a; ++ *d-- = a; ++ *d-- = a; ++ *d-- = a; ++ s -= stride * 4; ++ } ++ } ++ // UL ++ *d = a = (x & 1) != 0 ? *s : a; ++ } ++ ++ // U ++ { ++ pixel * d = top; ++ const pixel * s = src_u; ++ unsigned int x = avail_u; ++ ++ for (i = 0; i < size; i += 4, x >>= 1) ++ { ++ if ((x & 1) != 0) { ++ // Avail ++ *d++ = *s++; ++ *d++ = *s++; ++ *d++ = *s++; ++ *d++ = a = *s++; ++ } ++ else ++ { ++ *d++ = a; ++ *d++ = a; ++ *d++ = a; ++ *d++ = a; ++ s += 4; ++ } ++ } ++ ++ // UR ++ s = src_ur; ++ for (i = 0; i < size; i += 4, x >>= 1) ++ { ++ if ((x & 1) != 0) { ++ // Avail ++ *d++ = *s++; ++ *d++ = *s++; ++ *d++ = *s++; ++ *d++ = a = *s++; ++ } ++ else ++ { ++ *d++ = a; ++ *d++ = a; ++ *d++ = a; ++ *d++ = a; ++ s += 4; ++ } ++ } ++ } ++} ++ ++ ++#if !PRED_C && PW == 1 ++#define EXTEND(ptr, val, len) extend_8(ptr, val, len) ++#elif (!PRED_C && PW == 2) || (PRED_C && PW == 1) ++#define EXTEND(ptr, val, len) extend_16(ptr, val, len) ++#else ++#define EXTEND(ptr, val, len) extend_32(ptr, val, len) ++#endif ++ ++// Reqs: ++// ++// Planar: DL[0], L, ul, U, UR[0] ++// DC: dl, L, ul, U, ur ++// A2-9: DL, L, ul, u, ur ++// A10: dl, L, ul, u, ur ++// A11-17 dl, L, UL, U, ur ++// A18-25 dl, L, Ul, U, ur ++// A26 dl, l, ul, U, ur ++// A27-34 dl, l, ul, U, UR ++ ++#ifndef INCLUDED_ONCE ++ ++intra_filter_fn_t ff_hevc_rpi_intra_filter_8_neon_8; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_4_neon_16; ++intra_filter_fn_t ff_hevc_rpi_intra_filter_8_neon_16; ++ ++static const uint8_t req_avail_c[35] = ++{ ++ AVAIL_DL | AVAIL_L | 0 | AVAIL_U | AVAIL_UR, // Planar (DL[0] & UR[0] only needed) ++ AVAIL_L | 0 | AVAIL_U, // DC ++ AVAIL_DL | AVAIL_L, // 2 ++ AVAIL_DL | AVAIL_L, // 3 ++ AVAIL_DL | AVAIL_L, // 4 ++ AVAIL_DL | AVAIL_L, // 5 ++ AVAIL_DL | AVAIL_L, // 6 ++ AVAIL_DL | AVAIL_L, // 7 ++ AVAIL_DL | AVAIL_L, // 8 ++ AVAIL_DL | AVAIL_L, // 9 ++ AVAIL_L, // 10 (H) ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 11 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 12 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 13 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 14 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 15 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 16 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 17 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 18 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 19 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 20 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 21 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 22 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 23 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 24 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 25 ++ AVAIL_U, // 26 (V) ++ AVAIL_U | AVAIL_UR, // 27 ++ AVAIL_U | AVAIL_UR, // 28 ++ AVAIL_U | AVAIL_UR, // 29 ++ AVAIL_U | AVAIL_UR, // 30 ++ AVAIL_U | AVAIL_UR, // 31 ++ AVAIL_U | AVAIL_UR, // 32 ++ AVAIL_U | AVAIL_UR, // 33 ++ AVAIL_U | AVAIL_UR // 34 ++}; ++ ++static const uint8_t req_avail[4][35] = { ++{ ++ AVAIL_DL | AVAIL_L | 0 | AVAIL_U | AVAIL_UR, // Planar (DL[0] & UR[0] only needed) ++ AVAIL_L | 0 | AVAIL_U, // DC ++ AVAIL_DL | AVAIL_L, // 2 ++ AVAIL_DL | AVAIL_L, // 3 ++ AVAIL_DL | AVAIL_L, // 4 ++ AVAIL_DL | AVAIL_L, // 5 ++ AVAIL_DL | AVAIL_L, // 6 ++ AVAIL_DL | AVAIL_L, // 7 ++ AVAIL_DL | AVAIL_L, // 8 ++ AVAIL_DL | AVAIL_L, // 9 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 10 (H) ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 11 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 12 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 13 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 14 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 15 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 16 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 17 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 18 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 19 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 20 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 21 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 22 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 23 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 24 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 25 ++ AVAIL_L | AVAIL_UL | AVAIL_U, // 26 (V) ++ AVAIL_U | AVAIL_UR, // 27 ++ AVAIL_U | AVAIL_UR, // 28 ++ AVAIL_U | AVAIL_UR, // 29 ++ AVAIL_U | AVAIL_UR, // 30 ++ AVAIL_U | AVAIL_UR, // 31 ++ AVAIL_U | AVAIL_UR, // 32 ++ AVAIL_U | AVAIL_UR, // 33 ++ AVAIL_U | AVAIL_UR // 34 ++}, ++{ // 3 ++ AVAIL_DL | AVAIL_L | 0 | AVAIL_U | AVAIL_UR | FILTER_LIGHT, // Planar (DL[0] & UR[0] only needed) ++ AVAIL_L | 0 | AVAIL_U, // DC ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 2 ++ AVAIL_DL | AVAIL_L | 0, // 3 ++ AVAIL_DL | AVAIL_L | 0, // 4 ++ AVAIL_DL | AVAIL_L | 0, // 5 ++ AVAIL_DL | AVAIL_L | 0, // 6 ++ AVAIL_DL | AVAIL_L | 0, // 7 ++ AVAIL_DL | AVAIL_L | 0, // 8 ++ AVAIL_DL | AVAIL_L | 0, // 9 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 10 (H) ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 11 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 12 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 13 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 14 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 15 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 16 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 17 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 18 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 19 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 20 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 21 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 22 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 23 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 24 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 25 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 26 (V) ++ AVAIL_U | AVAIL_UR | 0, // 27 ++ AVAIL_U | AVAIL_UR | 0, // 28 ++ AVAIL_U | AVAIL_UR | 0, // 29 ++ AVAIL_U | AVAIL_UR | 0, // 30 ++ AVAIL_U | AVAIL_UR | 0, // 31 ++ AVAIL_U | AVAIL_UR | 0, // 32 ++ AVAIL_U | AVAIL_UR | 0, // 33 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT // 34 ++}, ++{ // 4 ++ AVAIL_DL | AVAIL_L | 0 | AVAIL_U | AVAIL_UR | FILTER_LIGHT, // Planar (DL[0] & UR[0] only needed) ++ AVAIL_L | 0 | AVAIL_U, // DC ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 2 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 3 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 4 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 5 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 6 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 7 ++ AVAIL_DL | AVAIL_L | FILTER_LIGHT, // 8 ++ AVAIL_DL | AVAIL_L | 0, // 9 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 10 (H) ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 11 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 12 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 13 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 14 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 15 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 16 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 17 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 18 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 19 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 20 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 21 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 22 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 23 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_LIGHT, // 24 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 25 ++ AVAIL_L | AVAIL_UL | AVAIL_U | 0, // 26 (V) ++ AVAIL_U | AVAIL_UR | 0, // 27 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 28 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 29 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 30 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 31 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 32 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT, // 33 ++ AVAIL_U | AVAIL_UR | FILTER_LIGHT // 34 ++}, ++{ // 5 ++ AVAIL_DL | AVAIL_L | 0 | AVAIL_U | AVAIL_UR | FILTER_EITHER, // Planar (DL[0] & UR[0] only needed) ++ AVAIL_L | 0 | AVAIL_U, // DC ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 2 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 3 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 4 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 5 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 6 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 7 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 8 ++ AVAIL_DL | AVAIL_L | FILTER_EITHER, // 9 ++ AVAIL_L | 0, // 10 (H) ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 11 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 12 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 13 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 14 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 15 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 16 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 17 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 18 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 19 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 20 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 21 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 22 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 23 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 24 ++ AVAIL_L | AVAIL_UL | AVAIL_U | FILTER_EITHER, // 25 ++ AVAIL_U | 0, // 26 (V) ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 27 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 28 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 29 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 30 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 31 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 32 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER, // 33 ++ AVAIL_U | AVAIL_UR | FILTER_EITHER // 34 ++} ++}; ++ ++ ++#endif ++ ++#define filter_light1 FUNC(filter_light1) ++static inline pixel filter_light1(pixel a, pixel b, pixel c) ++{ ++ return (a + b*2 + c + 2) >> 2; ++} ++ ++#define filter_light FUNC(filter_light) ++static inline void filter_light(pixel * dst, pixel p1, const pixel * src, const pixel pn, const int sstride, const unsigned int n) ++{ ++ pixel p0; ++ pixel p2 = *src; ++ // Allow for final pel - it is just clearer to to have the call take the actual number of output pels ++ unsigned int n_minus_1 = n - 1; ++ ++ do ++ { ++ src += sstride; ++ p0 = p1; ++ p1 = p2; ++ p2 = *src; ++ *dst++ = filter_light1(p0, p1, p2); ++ } while (--n_minus_1 != 0); ++ *dst = filter_light1(p1, p2, pn); ++} ++ ++#define filter_strong FUNC(filter_strong) ++static inline void filter_strong(pixel * dst, const unsigned int p0, const unsigned int p1, unsigned int n) ++{ ++ unsigned int a = 64 * p0 + 32; ++ const int v = p1 - p0; ++ ++ do ++ { ++ *dst++ = (a += v) >> 6; ++ } while (--n != 0); ++} ++ ++#define intra_filter FUNC(intra_filter) ++static av_always_inline void intra_filter( ++ pixel * const left, pixel * const top, ++ const unsigned int req, const unsigned int avail, ++ const pixel * const src_l, const pixel * const src_u, const pixel * const src_ur, ++ const unsigned int stride, ++ const unsigned int top_right_size, const unsigned int down_left_size, ++ const unsigned int log2_size) ++{ ++ const unsigned int strong_threshold = 1 << (BIT_DEPTH - 5); ++ const unsigned int size = 1 << log2_size; ++ ++ // a_ is the first pel in a section working round dl -> ur ++ // b_ is the last ++ // Beware that top & left work out from UL so usage of a_ & b_ may ++ // swap between them. It is a bad naming scheme but I have found no ++ // better ++ const pixel * a_dl = src_l + (down_left_size + size - 1) * stride; ++ const pixel * b_dl = src_l + size * stride; ++ const pixel * a_l = src_l + (size - 1) * stride; ++ const pixel * b_l = src_l; ++ const pixel * ab_ul = src_l - stride; ++ const pixel * a_u = src_u; ++ const pixel * b_u = src_u + size - 1; ++ const pixel * a_ur = src_ur; ++ const pixel * b_ur = src_ur + top_right_size - 1; ++ ++ const unsigned int want = req & ~avail; ++ const unsigned int have = req & avail; ++ unsigned int i; ++ ++ if ((avail & AVAIL_DL) == 0) ++ { ++ a_dl = a_ur; ++ if ((avail & AVAIL_U) != 0) ++ a_dl = a_u; ++ if ((avail & AVAIL_UL) != 0) ++ a_dl = ab_ul; ++ if ((avail & AVAIL_L) != 0) ++ a_dl = a_l; ++ b_dl = a_dl; ++ } ++ ++ if ((avail & AVAIL_L) == 0) ++ { ++ a_l = b_dl; ++ b_l = b_dl; ++ } ++ if ((avail & AVAIL_UL) == 0) ++ { ++ ab_ul = b_l; ++ } ++ if ((avail & AVAIL_U) == 0) ++ { ++ a_u = ab_ul; ++ b_u = ab_ul; ++ } ++ if ((avail & AVAIL_UR) == 0) ++ { ++ a_ur = b_u; ++ b_ur = b_u; ++ } ++ ++ if ((req & FILTER_LIGHT) == 0 || PRED_C || log2_size == 2) // PRED_C, log2_size compiler opt hints ++ { ++ if ((req & AVAIL_UL) != 0) ++ left[-1] = *ab_ul; ++ ++ if ((want & AVAIL_L) != 0) ++ EXTEND(left, *a_l, size); ++ if ((want & AVAIL_DL) != 0) ++ EXTEND(left + size, *a_dl, size); ++ if ((want & AVAIL_U) != 0) ++ EXTEND(top, *a_u, size); ++ if ((want & AVAIL_UR) != 0) ++ EXTEND(top + size, *a_ur, size); ++ ++ if ((have & AVAIL_U) != 0) ++ // Always good - even with sand ++ memcpy(top, a_u, size * sizeof(pixel)); ++ if ((have & AVAIL_UR) != 0) ++ { ++ memcpy(top + size, a_ur, top_right_size * sizeof(pixel)); ++ EXTEND(top + size + top_right_size, *b_ur, ++ size - top_right_size); ++ } ++ if ((have & AVAIL_L) != 0) ++ { ++ for (i = 0; i < size; i++) ++ left[i] = b_l[stride * i]; ++ } ++ if ((have & AVAIL_DL) != 0) ++ { ++ for (i = 0; i < down_left_size; i++) ++ left[i + size] = b_dl[stride * i]; ++ EXTEND(left + size + down_left_size, *a_dl, ++ size - down_left_size); ++ } ++ } ++ else if ((req & FILTER_STRONG) != 0 && log2_size == 5 && // log2_size compiler opt hint ++ FFABS((int)(*a_dl - *a_l * 2 + *ab_ul)) < strong_threshold && ++ FFABS((int)(*ab_ul - *b_u * 2 + *b_ur)) < strong_threshold) ++ { ++ if ((req & (AVAIL_U | AVAIL_UR)) != 0) ++ filter_strong(top, *ab_ul, *b_ur, size * 2); ++ left[-1] = *ab_ul; ++ if ((req & (AVAIL_L | AVAIL_DL)) != 0) ++ filter_strong(left, *ab_ul, *a_dl, size*2); ++ } ++ else ++ { ++ // Same code for both have & want for UL ++ if ((req & AVAIL_UL) != 0) ++ { ++ left[-1] = filter_light1(*b_l, *ab_ul, *a_u); ++ } ++ ++ if ((want & AVAIL_L) != 0) ++ { ++ EXTEND(left, *a_l, size); ++ left[0] = (*a_l * 3 + *ab_ul + 2) >> 2; ++ } ++ if ((want & AVAIL_DL) != 0) ++ { ++ // If we want DL then it cannot be avail so a_dl = a_l so no edge rounding ++ EXTEND(left + size, *a_l, size); ++ } ++ if ((want & AVAIL_U) != 0) ++ { ++ EXTEND(top, *a_u, size); ++ top[size - 1] = (*a_u * 3 + *a_ur + 2) >> 2; ++ } ++ if ((want & AVAIL_UR) != 0) ++ { ++ // If we want UR then it cannot be avail so a_ur = b_u so no edge rounding ++ EXTEND(top + size, *a_ur, size); ++ } ++ ++ if ((have & AVAIL_U) != 0) ++ { ++ filter_light(top, *ab_ul, a_u, *a_ur, 1, size); ++ } ++ if ((have & AVAIL_UR) != 0) { ++ filter_light(top + size, *b_u, a_ur, *b_ur, 1, top_right_size); ++ top[size*2 - 1] = *b_ur; ++ EXTEND(top + size + top_right_size, *b_ur, size - top_right_size); ++ } ++ if ((have & AVAIL_L) != 0) ++ { ++ filter_light(left, *ab_ul, b_l, *b_dl, stride, size); ++ } ++ if ((have & AVAIL_DL) != 0) ++ { ++ filter_light(left + size, *a_l, b_dl, *a_dl, stride, down_left_size); ++ left[size*2 - 1] = *a_dl; ++ EXTEND(left + size + down_left_size, *a_dl, size - down_left_size); ++ } ++ } ++} ++ ++#define INTRA_FILTER(log2_size) \ ++static void FUNC(intra_filter_ ## log2_size)( \ ++ uint8_t * const left, uint8_t * const top, \ ++ const unsigned int req, const unsigned int avail, \ ++ const uint8_t * const src_l, const uint8_t * const src_u, const uint8_t * const src_ur, \ ++ const unsigned int stride, \ ++ const unsigned int top_right_size, const unsigned int down_left_size) \ ++{ \ ++ intra_filter((pixel *)left, (pixel *)top, req, avail, \ ++ (const pixel *)src_l, (const pixel *)src_u, (const pixel *)src_ur, stride / sizeof(pixel), top_right_size, down_left_size, log2_size); \ ++} ++ ++INTRA_FILTER(2) ++INTRA_FILTER(3) ++INTRA_FILTER(4) ++INTRA_FILTER(5) ++ ++#undef intra_filter ++#undef INTRA_FILTER ++ ++static void FUNC(intra_pred)(const HEVCRpiContext * const s, ++ const enum IntraPredMode mode, const unsigned int x0, const unsigned int y0, const unsigned int avail, ++ const unsigned int log2_size) ++{ ++ // c_idx will alaways be 1 for _c versions and 0 for y ++ const unsigned int c_idx = PRED_C; ++ const unsigned int hshift = ctx_hshift(s, c_idx); ++ const unsigned int vshift = ctx_vshift(s, c_idx); ++ const unsigned int size = (1 << log2_size); ++ const unsigned int x = x0 >> hshift; ++ const unsigned int y = y0 >> vshift; ++ ++ const ptrdiff_t stride = frame_stride1(s->frame, c_idx) / sizeof(pixel); ++ pixel *const src = c_idx == 0 ? ++ (pixel *)av_rpi_sand_frame_pos_y(s->frame, x, y) : ++ (pixel *)av_rpi_sand_frame_pos_c(s->frame, x, y); ++ ++ // Align so we can do multiple loads in the asm ++ // Padded to 16 byte boundary so as not to confuse anything ++ DECLARE_ALIGNED(16, pixel, top[2 * MAX_TB_SIZE]); ++ DECLARE_ALIGNED(16, pixel, left_array[2 * MAX_TB_SIZE + 16 / sizeof(pixel)]); ++ ++ pixel * const left = left_array + 16 / sizeof(pixel); ++ const pixel * top_pred = top; ++ ++ const pixel * src_l = src - 1; ++ const pixel * src_u = src - stride; ++ const pixel * src_ur = src_u + size; ++#if !PRED_C ++ const unsigned int req = req_avail[log2_size - 2][mode] & ~s->ps.sps->intra_filters_disable; ++#else ++ const unsigned int req = req_avail_c[mode]; ++#endif ++ ++ // If we have nothing to pred from then fill with grey ++ // This isn't a common case but dealing with it here means we don't have to ++ // test for it later ++ if (avail == 0) ++ { ++dc_only: ++#if !PRED_C ++ s->hpc.pred_dc0[log2_size - 2]((uint8_t *)src, stride); ++#else ++ s->hpc.pred_dc0_c[log2_size - 2]((uint8_t *)src, stride); ++#endif ++ return; ++ } ++ ++ { ++ // N.B. stride is in pixels (not bytes) or in the case of chroma pixel-pairs ++ const AVFrame * const frame = s->frame; ++ const unsigned int mask = stride - 1; // For chroma pixel=uint16 so stride_c is stride_y / 2 ++ const unsigned int stripe_adj = (av_rpi_sand_frame_stride2(frame) - 1) * stride; ++ if ((x & mask) == 0) ++ src_l -= stripe_adj; ++ if (((x + size) & mask) == 0) ++ src_ur += stripe_adj; ++ } ++ ++ // Can deal with I-slices in 'normal' code even if CIP ++ // This also means that we don't need to generate (elsewhere) is_intra ++ // for IRAP frames ++ if (s->ps.pps->constrained_intra_pred_flag == 1 && ++ s->sh.slice_type != HEVC_SLICE_I) ++ { ++ // * If we ever actually care about CIP performance then we should ++ // special case out size 4 stuff (can be done by 'normal') and ++ // have 8-pel avail masks ++ unsigned int avail_l = cip_avail_l(s->is_intra + ((y + size * 2 - 1) >> (3 - vshift)) * s->ps.sps->pcm_width + ((x - 1) >> (6 - hshift)), ++ -(int)(s->ps.sps->pcm_width), ++ 1 << (((x - 1) >> (3 - hshift)) & 7), ++ 1 - hshift, ++ avail, ++ size, ++ FFMIN(size, ((s->ps.sps->height - y0) >> vshift) - size), ++ vshift != 0 ? 0 : (y >> 2) & 1); ++ ++ unsigned int avail_u = cip_avail_u(s->is_intra + ((y - 1) >> (3 - vshift)) * s->ps.sps->pcm_width + (x >> (6 - hshift)), ++ (x >> (3 - hshift)) & 7, ++ 1 - hshift, ++ avail, ++ size, ++ FFMIN(size, ((s->ps.sps->width - x0) >> hshift) - size), ++ hshift != 0 ? 0 : (x >> 2) & 1); ++ ++ // Anything left? ++ if ((avail_l | avail_u) == 0) ++ goto dc_only; ++ ++ FUNC(cip_fill)(left, top, avail_l, avail_u, src_l, src_u, src_ur, stride, size); ++ ++#if !PRED_C ++ if ((req & FILTER_LIGHT) != 0) ++ { ++ const unsigned threshold = 1 << (BIT_DEPTH - 5); ++ if ((req & FILTER_STRONG) != 0 && ++ (int)(FFABS(left[-1] + top[63] - 2 * top[31])) < threshold && ++ (int)(FFABS(left[-1] + left[63] - 2 * left[31])) < threshold) ++ { ++ filter_strong(top, left[-1], top[63], 64); ++ filter_strong(left, left[-1], left[63], 64); ++ } else ++ { ++ // LHS writes UL too so copy for top ++ const pixel p_ul = left[-1]; ++ filter_light(left - 1, top[0], left - 1, left[2*size - 1], 1, 2*size); ++ filter_light(top, p_ul, top, top[2*size - 1], 1, 2*size - 1); ++ } ++ } ++#endif ++ } ++ else ++ { ++ const unsigned int ur_size = FFMIN(size, ((s->ps.sps->width - x0) >> hshift) - size); ++ if ((req & ~((AVAIL_UR | AVAIL_U) & avail)) == 0 && ++ ((req & AVAIL_UR) == 0 || src_u + 2*size == src_ur + ur_size)) ++ { ++ top_pred = src_u; ++ } ++ else ++ { ++#if !PRED_C ++ s->hpc.intra_filter[log2_size - 2] ++#else ++ s->hpc.intra_filter_c[log2_size - 2] ++#endif ++ ((uint8_t *)left, (uint8_t *)top, req, avail, ++ (const uint8_t *)src_l, (const uint8_t *)src_u, (const uint8_t *)src_ur, stride * sizeof(pixel), ++ ur_size, ++ FFMIN(size, ((s->ps.sps->height - y0) >> vshift) - size)); ++ } ++ } ++ ++ ++#if !PRED_C ++ switch (mode) { ++ case INTRA_PLANAR: ++ s->hpc.pred_planar[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride); ++ break; ++ case INTRA_DC: ++ s->hpc.pred_dc[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride); ++ break; ++ case INTRA_ANGULAR_HORIZONTAL: ++ s->hpc.pred_horizontal[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ case INTRA_ANGULAR_VERTICAL: ++ s->hpc.pred_vertical[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ default: ++ s->hpc.pred_angular[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ } ++#else ++ switch (mode) { ++ case INTRA_PLANAR: ++ s->hpc.pred_planar_c[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride); ++ break; ++ case INTRA_DC: ++ s->hpc.pred_dc_c[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride); ++ break; ++ case INTRA_ANGULAR_HORIZONTAL: ++ s->hpc.pred_horizontal_c[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ case INTRA_ANGULAR_VERTICAL: ++ s->hpc.pred_vertical_c[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ default: ++ s->hpc.pred_angular_c[log2_size - 2]((uint8_t *)src, (uint8_t *)top_pred, ++ (uint8_t *)left, stride, ++ mode); ++ break; ++ } ++ ++#if DUMP_PRED ++ printf("U pred @ %d, %d: mode=%d\n", x, y, mode); ++ dump_pred_uv((uint8_t *)src, stride, 1 << log2_size); ++ printf("V pred @ %d, %d: mode=%d\n", x, y, mode); ++ dump_pred_uv((uint8_t *)src + 1, stride, 1 << log2_size); ++#endif ++#endif ++} ++ ++#if !PRED_C ++static av_always_inline void FUNC(pred_planar)(uint8_t *_src, const uint8_t *_top, ++ const uint8_t *_left, ptrdiff_t stride, ++ int trafo_size) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ const pixel *top = (const pixel *)_top; ++ const pixel *left = (const pixel *)_left; ++ int size = 1 << trafo_size; ++ for (y = 0; y < size; y++) ++ for (x = 0; x < size; x++) ++ POS(x, y) = ((size - 1 - x) * left[y] + (x + 1) * top[size] + ++ (size - 1 - y) * top[x] + (y + 1) * left[size] + size) >> (trafo_size + 1); ++} ++#else ++static av_always_inline void FUNC(pred_planar)(uint8_t * _src, const uint8_t * _top, ++ const uint8_t * _left, ptrdiff_t stride, ++ int trafo_size) ++{ ++ int x, y; ++ int size = 1 << trafo_size; ++ c_dst_ptr_t src = (c_dst_ptr_t)_src; ++ const c_src_ptr_t top = (c_src_ptr_t)_top; ++ const c_src_ptr_t left = (c_src_ptr_t)_left; ++ ++ for (y = 0; y < size; y++, src += stride) ++ { ++ for (x = 0; x < size; x++) ++ { ++ src[x][0] = ((size - 1 - x) * left[y][0] + (x + 1) * top[size][0] + ++ (size - 1 - y) * top[x][0] + (y + 1) * left[size][0] + size) >> (trafo_size + 1); ++ src[x][1] = ((size - 1 - x) * left[y][1] + (x + 1) * top[size][1] + ++ (size - 1 - y) * top[x][1] + (y + 1) * left[size][1] + size) >> (trafo_size + 1); ++ } ++ } ++} ++#endif ++ ++#define PRED_PLANAR(size)\ ++static void FUNC(pred_planar_ ## size)(uint8_t *src, const uint8_t *top, \ ++ const uint8_t *left, ptrdiff_t stride) \ ++{ \ ++ FUNC(pred_planar)(src, top, left, stride, size + 2); \ ++} ++ ++PRED_PLANAR(0) ++PRED_PLANAR(1) ++PRED_PLANAR(2) ++PRED_PLANAR(3) ++ ++#undef PRED_PLANAR ++ ++#if !PRED_C ++static void FUNC(pred_dc)(uint8_t *_src, const uint8_t *_top, ++ const uint8_t *_left, ++ ptrdiff_t stride, int log2_size) ++{ ++ int i, j, x, y; ++ int size = (1 << log2_size); ++ pixel *src = (pixel *)_src; ++ const pixel *top = (const pixel *)_top; ++ const pixel *left = (const pixel *)_left; ++ int dc = size; ++ pixel4 a; ++ for (i = 0; i < size; i++) ++ dc += left[i] + top[i]; ++ ++ dc >>= log2_size + 1; ++ ++ a = PIXEL_SPLAT_X4(dc); ++ ++ for (i = 0; i < size; i++) ++ for (j = 0; j < size; j+=4) ++ AV_WN4P(&POS(j, i), a); ++ ++// if (c_idx == 0 && size < 32) ++// As we now have separate fns for y & c - no need to test that ++ if (size < 32) ++ { ++ POS(0, 0) = (left[0] + 2 * dc + top[0] + 2) >> 2; ++ for (x = 1; x < size; x++) ++ POS(x, 0) = (top[x] + 3 * dc + 2) >> 2; ++ for (y = 1; y < size; y++) ++ POS(0, y) = (left[y] + 3 * dc + 2) >> 2; ++ } ++} ++#else ++static void FUNC(pred_dc)(uint8_t *_src, const uint8_t *_top, ++ const uint8_t *_left, ++ ptrdiff_t stride, int log2_size) ++{ ++ unsigned int i, j; ++ const unsigned int size = (1 << log2_size); ++ c_dst_ptr_t src = (c_dst_ptr_t)_src; ++ const c_src_ptr_t top = (c_src_ptr_t)_top; ++ const c_src_ptr_t left = (c_src_ptr_t)_left; ++ unsigned int dc0 = size; ++ unsigned int dc1 = size; ++ ++ for (i = 0; i < size; i++) ++ { ++ dc0 += left[i][0] + top[i][0]; ++ dc1 += left[i][1] + top[i][1]; ++ } ++ ++ dc0 >>= log2_size + 1; ++ dc1 >>= log2_size + 1; ++ ++ for (i = 0; i < size; i++, src += stride) ++ { ++ for (j = 0; j < size; ++j) ++ { ++ src[j][0] = dc0; ++ src[j][1] = dc1; ++ ++ } ++ } ++} ++#endif ++ ++#define PRED_DC(size)\ ++static void FUNC(pred_dc_ ## size)(uint8_t *src, const uint8_t *top, \ ++ const uint8_t *left, ptrdiff_t stride) \ ++{ \ ++ FUNC(pred_dc)(src, top, left, stride, size + 2); \ ++} ++ ++PRED_DC(0) ++PRED_DC(1) ++PRED_DC(2) ++PRED_DC(3) ++ ++#undef PRED_DC ++ ++ ++ ++ ++#if !PRED_C ++static void FUNC(pred_dc0)(uint8_t *_src, ptrdiff_t stride, int log2_size) ++{ ++ int i, j; ++ int size = (1 << log2_size); ++ pixel *src = (pixel *)_src; ++ pixel4 a = PIXEL_SPLAT_X4(1 << (BIT_DEPTH - 1)); ++ ++ for (i = 0; i < size; i++) ++ for (j = 0; j < size; j+=4) ++ AV_WN4P(&POS(j, i), a); ++} ++#else ++static void FUNC(pred_dc0)(uint8_t *_src, ptrdiff_t stride, int log2_size) ++{ ++ unsigned int i, j; ++ const unsigned int size = (1 << log2_size); ++ c_dst_ptr_t src = (c_dst_ptr_t)_src; ++ const pixel a = (1 << (BIT_DEPTH - 1)); ++ ++ for (i = 0; i < size; i++, src += stride) ++ { ++ for (j = 0; j < size; ++j) ++ { ++ src[j][0] = a; ++ src[j][1] = a; ++ } ++ } ++} ++#endif ++ ++#define PRED_DC0(size)\ ++static void FUNC(pred_dc0_ ## size)(uint8_t *src, ptrdiff_t stride) \ ++{ \ ++ FUNC(pred_dc0)(src, stride, size + 2); \ ++} ++ ++PRED_DC0(0) ++PRED_DC0(1) ++PRED_DC0(2) ++PRED_DC0(3) ++ ++#undef PRED_DC0 ++ ++ ++ ++ ++#ifndef ANGLE_CONSTS ++#define ANGLE_CONSTS ++static const int intra_pred_angle[] = { ++ 32, 26, 21, 17, 13, 9, 5, 2, 0, -2, -5, -9, -13, -17, -21, -26, -32, ++ -26, -21, -17, -13, -9, -5, -2, 0, 2, 5, 9, 13, 17, 21, 26, 32 ++}; ++static const int inv_angle[] = { ++ -4096, -1638, -910, -630, -482, -390, -315, -256, -315, -390, -482, ++ -630, -910, -1638, -4096 ++}; ++#endif ++ ++#if !PRED_C ++static av_always_inline void FUNC(pred_angular)(uint8_t *_src, ++ const uint8_t *_top, ++ const uint8_t *_left, ++ ptrdiff_t stride, ++ int mode, int size) ++{ ++ int x, y; ++ pixel *src = (pixel *)_src; ++ const pixel *top = (const pixel *)_top; ++ const pixel *left = (const pixel *)_left; ++ ++ int angle = intra_pred_angle[mode - 2]; ++ pixel ref_array[3 * MAX_TB_SIZE + 4]; ++ pixel *ref_tmp = ref_array + size; ++ const pixel *ref; ++ int last = (size * angle) >> 5; ++ ++ if (mode >= 18) { ++ ref = top - 1; ++ ++ if (angle < 0) ++ { ++ memcpy(ref_tmp + 1, top, size * PW); ++ ref_tmp[0] = left[-1]; ++ ++ for (x = last; x <= -1; x++) ++ ref_tmp[x] = left[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)]; ++ ref = ref_tmp; ++ } ++ ++ for (y = 0; y < size; y++) { ++ int idx = ((y + 1) * angle) >> 5; ++ int fact = ((y + 1) * angle) & 31; ++ if (fact) { ++ for (x = 0; x < size; x += 4) { ++ POS(x , y) = ((32 - fact) * ref[x + idx + 1] + ++ fact * ref[x + idx + 2] + 16) >> 5; ++ POS(x + 1, y) = ((32 - fact) * ref[x + 1 + idx + 1] + ++ fact * ref[x + 1 + idx + 2] + 16) >> 5; ++ POS(x + 2, y) = ((32 - fact) * ref[x + 2 + idx + 1] + ++ fact * ref[x + 2 + idx + 2] + 16) >> 5; ++ POS(x + 3, y) = ((32 - fact) * ref[x + 3 + idx + 1] + ++ fact * ref[x + 3 + idx + 2] + 16) >> 5; ++ } ++ } else { ++ for (x = 0; x < size; x += 4) ++ AV_WN4P(&POS(x, y), AV_RN4P(&ref[x + idx + 1])); ++ } ++ } ++ if (mode == 26 && size < 32) { ++ for (y = 0; y < size; y++) ++ POS(0, y) = av_clip_pixel(top[0] + ((left[y] - left[-1]) >> 1)); ++ } ++ ++ } else { ++ ref = left - 1; ++ if (angle < 0 && last < -1) { ++ for (x = 0; x <= size; x += 4) ++ AV_WN4P(&ref_tmp[x], AV_RN4P(&left[x - 1])); ++ // Inv angle <= -256 so top offset >= 0 ++ for (x = last; x <= -1; x++) ++ ref_tmp[x] = top[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)]; ++ ref = ref_tmp; ++ } ++ ++ for (x = 0; x < size; x++) { ++ int idx = ((x + 1) * angle) >> 5; ++ int fact = ((x + 1) * angle) & 31; ++ if (fact) { ++ for (y = 0; y < size; y++) { ++ POS(x, y) = ((32 - fact) * ref[y + idx + 1] + ++ fact * ref[y + idx + 2] + 16) >> 5; ++ } ++ } else { ++ for (y = 0; y < size; y++) ++ POS(x, y) = ref[y + idx + 1]; ++ } ++ } ++ if (mode == 10 && size < 32) { ++ for (x = 0; x < size; x += 4) { ++ POS(x, 0) = av_clip_pixel(left[0] + ((top[x ] - left[-1]) >> 1)); ++ POS(x + 1, 0) = av_clip_pixel(left[0] + ((top[x + 1] - left[-1]) >> 1)); ++ POS(x + 2, 0) = av_clip_pixel(left[0] + ((top[x + 2] - left[-1]) >> 1)); ++ POS(x + 3, 0) = av_clip_pixel(left[0] + ((top[x + 3] - left[-1]) >> 1)); ++ } ++ } ++ } ++} ++#else ++static av_always_inline void FUNC(pred_angular)(uint8_t *_src, ++ const uint8_t *_top, ++ const uint8_t *_left, ++ ptrdiff_t stride, ++ int mode, int size) ++{ ++ int x, y; ++ c_dst_ptr_t src = (c_dst_ptr_t)_src; ++ c_src_ptr_t top = (c_src_ptr_t)_top; ++ c_src_ptr_t left = (c_src_ptr_t)_left; ++ ++ const int angle = intra_pred_angle[mode - 2]; ++ cpel ref_array[3 * MAX_TB_SIZE + 4][2]; ++ c_dst_ptr_t ref_tmp = ref_array + size; ++ c_src_ptr_t ref; ++ const int last = (size * angle) >> 5; ++ ++ if (mode >= 18) { ++ ref = top - 1; ++ if (angle < 0) { ++ memcpy(ref_tmp + 1, top, size * 2 * PW); ++ ref_tmp[0][0] = left[-1][0]; ++ ref_tmp[0][1] = left[-1][1]; ++ for (x = last; x <= -1; x++) ++ { ++ ref_tmp[x][0] = left[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)][0]; ++ ref_tmp[x][1] = left[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)][1]; ++ } ++ ref = (c_src_ptr_t)ref_tmp; ++ } ++ ++ for (y = 0; y < size; y++, src += stride) { ++ const int idx = ((y + 1) * angle) >> 5; ++ const int fact = ((y + 1) * angle) & 31; ++ if (fact) { ++ for (x = 0; x < size; ++x) { ++ src[x][0] = ((32 - fact) * ref[x + idx + 1][0] + ++ fact * ref[x + idx + 2][0] + 16) >> 5; ++ src[x][1] = ((32 - fact) * ref[x + idx + 1][1] + ++ fact * ref[x + idx + 2][1] + 16) >> 5; ++ } ++ } else { ++ memcpy(src, ref + idx + 1, size * 2 * PW); ++ } ++ } ++ } else { ++ ref = left - 1; ++ if (angle < 0 && last < -1) { ++ memcpy(ref_tmp, left - 1, (size + 1) * 2 * PW); ++ for (x = last; x <= -1; x++) ++ { ++ ref_tmp[x][0] = top[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)][0]; ++ ref_tmp[x][1] = top[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)][1]; ++ } ++ ref = (c_src_ptr_t)ref_tmp; ++ } ++ ++ for (x = 0; x < size; x++, src++) { ++ const int idx = ((x + 1) * angle) >> 5; ++ const int fact = ((x + 1) * angle) & 31; ++ if (fact) { ++ for (y = 0; y < size; y++) { ++ src[y * stride][0] = ((32 - fact) * ref[y + idx + 1][0] + ++ fact * ref[y + idx + 2][0] + 16) >> 5; ++ src[y * stride][1] = ((32 - fact) * ref[y + idx + 1][1] + ++ fact * ref[y + idx + 2][1] + 16) >> 5; ++ } ++ } else { ++ for (y = 0; y < size; y++) ++ { ++ src[y * stride][0] = ref[y + idx + 1][0]; ++ src[y * stride][1] = ref[y + idx + 1][1]; ++ } ++ } ++ } ++ } ++} ++#endif ++ ++static void FUNC(pred_angular_0)(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ++ ptrdiff_t stride, int mode) ++{ ++ FUNC(pred_angular)(src, top, left, stride, mode, 1 << 2); ++} ++ ++static void FUNC(pred_angular_1)(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ++ ptrdiff_t stride, int mode) ++{ ++ FUNC(pred_angular)(src, top, left, stride, mode, 1 << 3); ++} ++ ++static void FUNC(pred_angular_2)(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ++ ptrdiff_t stride, int mode) ++{ ++ FUNC(pred_angular)(src, top, left, stride, mode, 1 << 4); ++} ++ ++static void FUNC(pred_angular_3)(uint8_t *src, const uint8_t *top, ++ const uint8_t *left, ++ ptrdiff_t stride, int mode) ++{ ++ FUNC(pred_angular)(src, top, left, stride, mode, 1 << 5); ++} ++ ++#undef cpel ++#undef c_src_ptr_t ++#undef c_dst_ptr_t ++ ++#undef EXTEND ++#undef POS ++#undef PW ++ ++#undef filter_light1 ++#undef filter_light ++#undef filter_strong ++#undef ref_gen ++ ++#ifndef INCLUDED_ONCE ++#define INCLUDED_ONCE ++#endif ++ +diff --git a/libavcodec/rpi_mailbox.c b/libavcodec/rpi_mailbox.c +new file mode 100644 +index 0000000000..98a0b104b7 +--- /dev/null ++++ b/libavcodec/rpi_mailbox.c +@@ -0,0 +1,155 @@ ++/* ++Copyright (c) 2012, Broadcom Europe Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define MAJOR_NUM 100 ++#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) ++#define DEVICE_FILE_NAME "/dev/vcio" ++ ++#include "rpi_mailbox.h" ++//#include ++ ++/* ++ * use ioctl to send mbox property message ++ */ ++ ++static int mbox_property(int file_desc, void *buf) ++{ ++ int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); ++ ++ if (ret_val < 0) { ++ printf("ioctl_set_msg failed:%d\n", ret_val); ++ } ++ ++#ifdef DEBUG ++ unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; ++ for (i=0; i ++#include ++#include ++#include ++ ++#include "config.h" ++ ++#include "libavutil/avassert.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++#pragma GCC diagnostic push ++// Many many redundant decls in the header files ++#pragma GCC diagnostic ignored "-Wredundant-decls" ++#include ++#include ++#include ++#pragma GCC diagnostic pop ++ ++#include "rpi_mem.h" ++#include "rpi_zc_frames.h" ++ ++ ++#define OPT_PREFER_CMA 0 ++ ++struct rpi_cache_flush_env_s { ++ struct vcsm_user_clean_invalid2_s v; ++}; ++ ++ ++// GPU memory alloc fns (internal) ++ ++static void gpu_free_internal(GPU_MEM_PTR_T * const p) ++{ ++ if (p->arm != NULL) ++ vcsm_unlock_ptr(p->arm); ++ if (p->vcsm_handle != 0) ++ vcsm_free(p->vcsm_handle); ++ memset(p, 0, sizeof(*p)); // Ensure we crash hard if we try and use this again ++} ++ ++ ++static int gpu_malloc_internal(GPU_MEM_PTR_T * const p, ++ const int numbytes, const unsigned int cache_type, const char * const name) ++{ ++ memset(p, 0, sizeof(*p)); ++ p->numbytes = (numbytes + 255) & ~255; // Round up ++ ++ if ((p->vcsm_handle = vcsm_malloc_cache(p->numbytes, cache_type | 0x80, (char *)name)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "Unable to alloc %d bytes from VCSM for %s\n", p->numbytes, name); ++ goto fail; ++ } ++ if ((p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "Unable to VC handle from VCSM for %s\n", name); ++ goto fail; ++ } ++ if ((p->arm = vcsm_lock(p->vcsm_handle)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "Unable to lock handle from VCSM for %s\n", name); ++ goto fail; ++ } ++ if ((p->vc = vcsm_vc_addr_from_hdl(p->vcsm_handle)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "Unable to get VC addr from VCSM for %s\n", name); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ gpu_free_internal(p); ++ return AVERROR(ENOMEM); ++} ++ ++// Public gpu fns ++ ++// Allocate memory on GPU ++// Fills in structure

      containing ARM pointer, videocore handle, videocore memory address, numbytes ++// Returns 0 on success. ++// This allocates memory that will not be cached in ARM's data cache. ++// Therefore safe to use without data cache flushing. ++int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) ++{ ++ return gpu_malloc_internal(p, numbytes, VCSM_CACHE_TYPE_NONE, "ffmpeg uncached"); ++} ++ ++// This allocates data that will be ++// Cached in ARM L2 ++// Uncached in VPU L2 ++int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p) ++{ ++ return gpu_malloc_internal(p, numbytes, VCSM_CACHE_TYPE_HOST, "ffmpeg cached"); ++} ++ ++void gpu_free(GPU_MEM_PTR_T * const p) { ++ gpu_free_internal(p); ++} ++ ++void rpi_mem_gpu_uninit(void) ++{ ++ vcsm_exit(); ++ bcm_host_deinit(); ++} ++ ++int rpi_mem_gpu_init(const unsigned int flags) ++{ ++ const int wants_cma = bcm_host_is_fkms_active(); ++ int use_cma; ++ ++ (void)flags; ++ ++ if (vcsm_init_ex(wants_cma ? 1 : 0, -1) == 0) ++ use_cma = 1; ++ else if (vcsm_init_ex(wants_cma ? 0 : 1, -1) == 0) ++ use_cma = 0; ++ else ++ return AVERROR(EINVAL); ++ ++ bcm_host_init(); ++ ++ return use_cma + 1; ++} ++ ++// ---------------------------------------------------------------------------- ++// ++// Cache flush functions ++ ++#define CACHE_EL_MAX ((sizeof(rpi_cache_buf_t) - sizeof (struct vcsm_user_clean_invalid2_s)) / sizeof (struct vcsm_user_clean_invalid2_block_s)) ++ ++rpi_cache_flush_env_t * rpi_cache_flush_init(rpi_cache_buf_t * const buf) ++{ ++ rpi_cache_flush_env_t * const rfe = (rpi_cache_flush_env_t *)buf; ++ *rfe = (rpi_cache_flush_env_t){.v={.op_count = 0}}; ++ return rfe; ++} ++ ++void rpi_cache_flush_abort(rpi_cache_flush_env_t * const rfe) ++{ ++ // Nothing needed ++} ++ ++int rpi_cache_flush_execute(rpi_cache_flush_env_t * const rfe) ++{ ++ int rc = 0; ++ if (rfe->v.op_count != 0) { ++ if (vcsm_clean_invalid2(&rfe->v) != 0) ++ { ++ const int err = errno; ++ av_log(NULL, AV_LOG_ERROR, "vcsm_clean_invalid2 failed: errno=%d\n", err); ++ rc = AVERROR(err); ++ } ++ rfe->v.op_count = 0; ++ } ++ return rc; ++} ++ ++int rpi_cache_flush_finish(rpi_cache_flush_env_t * const rfe) ++{ ++ int rc = rpi_cache_flush_execute(rfe);; ++ ++ return rc; ++} ++ ++inline void rpi_cache_flush_add_gm_blocks(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const unsigned int mode, ++ const unsigned int offset0, const unsigned int block_size, const unsigned int blocks, const unsigned int block_stride) ++{ ++ struct vcsm_user_clean_invalid2_block_s * const b = rfe->v.s + rfe->v.op_count++; ++ ++ av_assert1(rfe->v.op_count <= CACHE_EL_MAX); ++ ++ b->invalidate_mode = mode; ++ b->block_count = blocks; ++ b->start_address = gm->arm + offset0; ++ b->block_size = block_size; ++ b->inter_block_stride = block_stride; ++} ++ ++void rpi_cache_flush_add_gm_range(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const unsigned int mode, ++ const unsigned int offset, const unsigned int size) ++{ ++ // Deal with empty pointer trivially ++ if (gm == NULL || size == 0) ++ return; ++ ++ av_assert1(offset <= gm->numbytes); ++ av_assert1(size <= gm->numbytes); ++ av_assert1(offset + size <= gm->numbytes); ++ ++ rpi_cache_flush_add_gm_blocks(rfe, gm, mode, offset, size, 1, 0); ++} ++ ++void rpi_cache_flush_add_gm_ptr(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const unsigned int mode) ++{ ++ rpi_cache_flush_add_gm_blocks(rfe, gm, mode, 0, gm->numbytes, 1, 0); ++} ++ ++ ++void rpi_cache_flush_add_frame(rpi_cache_flush_env_t * const rfe, const AVFrame * const frame, const unsigned int mode) ++{ ++#if !RPI_ONE_BUF ++#error Fixme! (NIF) ++#endif ++ if (gpu_is_buf1(frame)) { ++ rpi_cache_flush_add_gm_ptr(rfe, gpu_buf1_gmem(frame), mode); ++ } ++ else ++ { ++ rpi_cache_flush_add_gm_ptr(rfe, gpu_buf3_gmem(frame, 0), mode); ++ rpi_cache_flush_add_gm_ptr(rfe, gpu_buf3_gmem(frame, 1), mode); ++ rpi_cache_flush_add_gm_ptr(rfe, gpu_buf3_gmem(frame, 2), mode); ++ } ++} ++ ++// Flush an area of a frame ++// Width, height, x0, y0 in luma pels ++void rpi_cache_flush_add_frame_block(rpi_cache_flush_env_t * const rfe, const AVFrame * const frame, const unsigned int mode, ++ const unsigned int x0, const unsigned int y0, const unsigned int width, const unsigned int height, ++ const unsigned int uv_shift, const int do_luma, const int do_chroma) ++{ ++ const unsigned int y_offset = frame->linesize[0] * y0; ++ const unsigned int y_size = frame->linesize[0] * height; ++ // Round UV up/down to get everything ++ const unsigned int uv_rnd = (1U << uv_shift) >> 1; ++ const unsigned int uv_offset = frame->linesize[1] * (y0 >> uv_shift); ++ const unsigned int uv_size = frame->linesize[1] * ((y0 + height + uv_rnd) >> uv_shift) - uv_offset; ++ ++#if 0 ++ // *** frame->height is cropped height so not good ++ // As all unsigned they will also reject -ve ++ // Test individually as well as added to reject overflow ++ av_assert0(start_line <= (unsigned int)frame->height); // ***** frame height cropped ++ av_assert0(n <= (unsigned int)frame->height); ++ av_assert0(start_line + n <= (unsigned int)frame->height); ++#endif ++ ++ if (!gpu_is_buf1(frame)) ++ { ++ if (do_luma) { ++ rpi_cache_flush_add_gm_range(rfe, gpu_buf3_gmem(frame, 0), mode, y_offset, y_size); ++ } ++ if (do_chroma) { ++ rpi_cache_flush_add_gm_range(rfe, gpu_buf3_gmem(frame, 1), mode, uv_offset, uv_size); ++ rpi_cache_flush_add_gm_range(rfe, gpu_buf3_gmem(frame, 2), mode, uv_offset, uv_size); ++ } ++ } ++ else if (!av_rpi_is_sand_frame(frame)) ++ { ++ const GPU_MEM_PTR_T * const gm = gpu_buf1_gmem(frame); ++ if (do_luma) { ++ rpi_cache_flush_add_gm_range(rfe, gm, mode, (frame->data[0] - gm->arm) + y_offset, y_size); ++ } ++ if (do_chroma) { ++ rpi_cache_flush_add_gm_range(rfe, gm, mode, (frame->data[1] - gm->arm) + uv_offset, uv_size); ++ rpi_cache_flush_add_gm_range(rfe, gm, mode, (frame->data[2] - gm->arm) + uv_offset, uv_size); ++ } ++ } ++ else ++ { ++ const unsigned int stride1 = av_rpi_sand_frame_stride1(frame); ++ const unsigned int stride2 = av_rpi_sand_frame_stride2(frame); ++ const unsigned int xshl = av_rpi_sand_frame_xshl(frame); ++ const unsigned int xleft = x0 & ~((stride1 >> xshl) - 1); ++ const unsigned int block_count = (((x0 + width - xleft) << xshl) + stride1 - 1) / stride1; // Same for Y & C ++ av_assert1(rfe->v.op_count + do_chroma + do_luma < CACHE_EL_MAX); ++ ++ if (do_chroma) ++ { ++ struct vcsm_user_clean_invalid2_block_s * const b = rfe->v.s + rfe->v.op_count++; ++ b->invalidate_mode = mode; ++ b->block_count = block_count; ++ b->start_address = av_rpi_sand_frame_pos_c(frame, xleft >> 1, y0 >> 1); ++ b->block_size = uv_size; ++ b->inter_block_stride = stride1 * stride2; ++ } ++ if (do_luma) ++ { ++ struct vcsm_user_clean_invalid2_block_s * const b = rfe->v.s + rfe->v.op_count++; ++ b->invalidate_mode = mode; ++ b->block_count = block_count; ++ b->start_address = av_rpi_sand_frame_pos_y(frame, xleft, y0); ++ b->block_size = y_size; ++ b->inter_block_stride = stride1 * stride2; ++ } ++ } ++} ++ ++// Call this to clean and invalidate a region of memory ++void rpi_cache_flush_one_gm_ptr(const GPU_MEM_PTR_T *const p, const rpi_cache_flush_mode_t mode) ++{ ++ rpi_cache_buf_t cbuf; ++ rpi_cache_flush_env_t * rfe = rpi_cache_flush_init(&cbuf); ++ rpi_cache_flush_add_gm_ptr(rfe, p, mode); ++ rpi_cache_flush_finish(rfe); ++} ++ +diff --git a/libavcodec/rpi_mem.h b/libavcodec/rpi_mem.h +new file mode 100644 +index 0000000000..a451079806 +--- /dev/null ++++ b/libavcodec/rpi_mem.h +@@ -0,0 +1,88 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#ifndef RPI_MEM_H ++#define RPI_MEM_H ++ ++typedef struct gpu_mem_ptr_s { ++ unsigned char *arm; // Pointer to memory mapped on ARM side ++ int vc_handle; // Videocore handle of relocatable memory ++ int vcsm_handle; // Handle for use by VCSM ++ int vc; // Address for use in GPU code ++ int numbytes; // Size of memory block ++} GPU_MEM_PTR_T; ++ ++// General GPU functions ++ ++#define GPU_INIT_GPU 1 ++#define GPU_INIT_CMA 2 ++ ++extern int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p); ++extern int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p); ++extern void gpu_free(GPU_MEM_PTR_T * const p); ++int rpi_mem_gpu_init(const unsigned int flags); ++void rpi_mem_gpu_uninit(void); ++ ++// Cache flush stuff ++ ++struct rpi_cache_flush_env_s; ++typedef struct rpi_cache_flush_env_s rpi_cache_flush_env_t; ++ ++typedef struct {uint32_t t[33];} rpi_cache_buf_t; ++ ++rpi_cache_flush_env_t * rpi_cache_flush_init(rpi_cache_buf_t * const buf); ++// Free env without flushing ++void rpi_cache_flush_abort(rpi_cache_flush_env_t * const rfe); ++// Do the accumulated flush & clear but do not free the env ++int rpi_cache_flush_execute(rpi_cache_flush_env_t * const rfe); ++// Do the accumulated flush & free the env ++int rpi_cache_flush_finish(rpi_cache_flush_env_t * const rfe); ++ ++typedef enum ++{ ++ RPI_CACHE_FLUSH_MODE_INVALIDATE = 1, ++ RPI_CACHE_FLUSH_MODE_WRITEBACK = 2, ++ RPI_CACHE_FLUSH_MODE_WB_INVALIDATE = 3 ++} rpi_cache_flush_mode_t; ++ ++struct AVFrame; ++void rpi_cache_flush_add_gm_ptr(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const rpi_cache_flush_mode_t mode); ++void rpi_cache_flush_add_gm_range(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const rpi_cache_flush_mode_t mode, ++ const unsigned int offset, const unsigned int size); ++void rpi_cache_flush_add_gm_blocks(rpi_cache_flush_env_t * const rfe, const GPU_MEM_PTR_T * const gm, const unsigned int mode, ++ const unsigned int offset0, const unsigned int block_size, const unsigned int blocks, const unsigned int block_stride); ++void rpi_cache_flush_add_frame(rpi_cache_flush_env_t * const rfe, const struct AVFrame * const frame, const rpi_cache_flush_mode_t mode); ++void rpi_cache_flush_add_frame_block(rpi_cache_flush_env_t * const rfe, const struct AVFrame * const frame, const rpi_cache_flush_mode_t mode, ++ const unsigned int x0, const unsigned int y0, const unsigned int width, const unsigned int height, ++ const unsigned int uv_shift, const int do_luma, const int do_chroma); ++ ++// init, add, finish for one gm ptr ++void rpi_cache_flush_one_gm_ptr(const GPU_MEM_PTR_T * const p, const rpi_cache_flush_mode_t mode); ++ ++#endif +diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c +new file mode 100644 +index 0000000000..cb7b96119e +--- /dev/null ++++ b/libavcodec/rpi_qpu.c +@@ -0,0 +1,776 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include "libavutil/avassert.h" ++ ++#include "config.h" ++ ++#include ++#include ++ ++#include ++ ++#include "rpi_mailbox.h" ++#include "rpi_mem.h" ++#include "rpi_qpu.h" ++#include "rpi_hevc_shader.h" ++#include "rpi_hevc_transform8.h" ++#include "rpi_hevc_transform10.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++// Trace time spent waiting for GPU (VPU/QPU) (1=Yes, 0=No) ++#define RPI_TRACE_TIME_VPU_QPU_WAIT 0 ++ ++// Add profile flags to all QPU requests - generates output in "vcdbg log msg" ++// Beware this is expensive and will probably throw off all other timing by >10% ++#define RPI_TRACE_QPU_PROFILE_ALL 0 ++ ++// QPU "noflush" flags ++// a mixture of flushing & profiling ++ ++#define QPU_FLAGS_NO_FLUSH_VPU 1 // If unset VPU cache will be flushed ++#define QPU_FLAGS_PROF_CLEAR_AND_ENABLE 2 // Clear & Enable detailed QPU profiling registers ++#define QPU_FLAGS_PROF_OUTPUT_COUNTS 4 // Print the results ++#define QPU_FLAGS_OUTPUT_QPU_TIMES 8 // Print QPU times - independant of the profiling ++#define QPU_FLAGS_NO_FLUSH_QPU 16 // If unset flush QPU caches & TMUs (uniforms always flushed) ++ ++#define vcos_verify_ge0(x) ((x)>=0) ++ ++// Size in 32bit words ++#define QPU_CODE_SIZE 4098 ++#define VPU_CODE_SIZE 16384 ++ ++static const short rpi_transMatrix2even[32][16] = { // Even rows first ++{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, ++{90, 87, 80, 70, 57, 43, 25, 9, -9, -25, -43, -57, -70, -80, -87, -90}, ++{89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89}, ++{87, 57, 9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87}, ++{83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83}, ++{80, 9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80}, ++{75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75}, ++{70, -43, -87, 9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70}, ++{64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64}, ++{57, -80, -25, 90, -9, -87, 43, 70, -70, -43, 87, 9, -90, 25, 80, -57}, ++{50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50}, ++{43, -90, 57, 25, -87, 70, 9, -80, 80, -9, -70, 87, -25, -57, 90, -43}, ++{36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36}, ++{25, -70, 90, -80, 43, 9, -57, 87, -87, 57, -9, -43, 80, -90, 70, -25}, ++{18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18}, ++{ 9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9}, ++// Odd rows ++{90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4}, ++{90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13}, ++{88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22}, ++{85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31}, ++{82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67, 4, 73, 88, 38}, ++{78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46}, ++{73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54}, ++{67, -54, -78, 38, 85, -22, -90, 4, 90, 13, -88, -31, 82, 46, -73, -61}, ++{61, -73, -46, 82, 31, -88, -13, 90, -4, -90, 22, 85, -38, -78, 54, 67}, ++{54, -85, -4, 88, -46, -61, 82, 13, -90, 38, 67, -78, -22, 90, -31, -73}, ++{46, -90, 38, 54, -90, 31, 61, -88, 22, 67, -85, 13, 73, -82, 4, 78}, ++{38, -88, 73, -4, -67, 90, -46, -31, 85, -78, 13, 61, -90, 54, 22, -82}, ++{31, -78, 90, -61, 4, 54, -88, 82, -38, -22, 73, -90, 67, -13, -46, 85}, ++{22, -61, 85, -90, 73, -38, -4, 46, -78, 90, -82, 54, -13, -31, 67, -88}, ++{13, -38, 61, -78, 88, -90, 85, -73, 54, -31, 4, 22, -46, 67, -82, 90}, ++{ 4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90} ++}; ++ ++// Code/constants on GPU ++struct GPU ++{ ++// unsigned int qpu_code[QPU_CODE_SIZE]; ++ unsigned int vpu_code8[VPU_CODE_SIZE]; ++ unsigned int vpu_code10[VPU_CODE_SIZE]; ++ short transMatrix2even[16*16*2]; ++}; ++ ++#define WAIT_COUNT_MAX 16 ++ ++typedef struct trace_time_one_s ++{ ++ int count; ++ int64_t start[WAIT_COUNT_MAX]; ++ int64_t total[WAIT_COUNT_MAX]; ++} trace_time_one_t; ++ ++typedef struct trace_time_wait_s ++{ ++ unsigned int jcount; ++ int64_t start0; ++ int64_t last_update; ++ trace_time_one_t active; ++ trace_time_one_t wait; ++} trace_time_wait_t; ++ ++typedef struct vq_wait_s ++{ ++ sem_t sem; ++ struct vq_wait_s * next; ++} vq_wait_t; ++ ++#define VQ_WAIT_POOL_SIZE 16 ++typedef struct vq_wait_pool_s ++{ ++ vq_wait_t * head; ++ vq_wait_t pool[VQ_WAIT_POOL_SIZE]; ++} vq_wait_pool_t; ++ ++static void vq_wait_pool_init(vq_wait_pool_t * const pool); ++static void vq_wait_pool_deinit(vq_wait_pool_t * const pool); ++ ++typedef struct gpu_env_s ++{ ++ int open_count; ++ int init_count; ++ int vpu_i_cache_flushed; ++ GPU_MEM_PTR_T qpu_code_gm_ptr; ++ GPU_MEM_PTR_T code_gm_ptr; ++ GPU_MEM_PTR_T dummy_gm_ptr; ++ vq_wait_pool_t wait_pool; ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ trace_time_wait_t ttw; ++#endif ++} gpu_env_t; ++ ++// Stop more than one thread trying to allocate memory or use the processing resources at once ++static pthread_mutex_t gpu_mutex = PTHREAD_MUTEX_INITIALIZER; ++static gpu_env_t * gpu = NULL; ++ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ ++static int64_t ns_time(void) ++{ ++ struct timespec ts; ++ clock_gettime(CLOCK_MONOTONIC, &ts); ++ return (int64_t)ts.tv_sec * (int64_t)1000000000 + ts.tv_nsec; ++} ++ ++ ++#define WAIT_TIME_PRINT_PERIOD (int64_t)2000000000 ++ ++#define T_MS(t) ((unsigned int)((t)/(int64_t)1000000) % 1000U) ++#define T_SEC(t) (unsigned int)((t)/(int64_t)1000000000) ++#define T_ARG(t) T_SEC(t), T_MS(t) ++#define T_FMT "%u.%03u" ++ ++static void tto_print(trace_time_one_t * tto, const int64_t now, const int64_t start0, const char * const prefix) ++{ ++ // Update totals for levels that are still pending ++ for (int i = 0; i < tto->count; ++i) { ++ tto->total[i] += now - tto->start[i]; ++ tto->start[i] = now; ++ } ++ ++ printf("%s: Idle:" T_FMT ", 1:" T_FMT ", 2:" T_FMT ", 3:" T_FMT ", 4:" T_FMT "\n", ++ prefix, ++ T_ARG(now - start0 - tto->total[0]), ++ T_ARG(tto->total[0]), ++ T_ARG(tto->total[1]), ++ T_ARG(tto->total[2]), ++ T_ARG(tto->total[3])); ++} ++ ++ ++static void tto_start(trace_time_one_t * const tto, const int64_t now) ++{ ++ av_assert0(tto->count < WAIT_COUNT_MAX); ++ tto->start[tto->count++] = now; ++} ++ ++static void tto_end(trace_time_one_t * const tto, const int64_t now) ++{ ++ const int n = --tto->count; ++ av_assert0(n >= 0); ++ tto->total[n] += now - tto->start[n]; ++} ++ ++static void ttw_print(trace_time_wait_t * const ttw, const int64_t now) ++{ ++ printf("Jobs:%d, Total time=" T_FMT "\n", ttw->jcount, T_ARG(now - ttw->start0)); ++ tto_print(&ttw->active, now, ttw->start0, "Active"); ++ tto_print(&ttw->wait, now, ttw->start0, " Wait"); ++} ++ ++#endif ++ ++// GPU memory alloc fns (internal) ++ ++static void gpu_free_internal(GPU_MEM_PTR_T * const p) ++{ ++ if (p->arm != NULL) ++ vcsm_unlock_ptr(p->arm); ++ if (p->vcsm_handle != 0) ++ vcsm_free(p->vcsm_handle); ++ memset(p, 0, sizeof(*p)); // Ensure we crash hard if we try and use this again ++} ++ ++ ++static int gpu_malloc_internal(GPU_MEM_PTR_T * const p, ++ const int numbytes, const unsigned int cache_type, const char * const name) ++{ ++ memset(p, 0, sizeof(*p)); ++ p->numbytes = (numbytes + 255) & ~255; // Round up ++ ++ if ((p->vcsm_handle = vcsm_malloc_cache(p->numbytes, cache_type | 0x80, (char *)name)) == 0 || ++ (p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle)) == 0 || ++ (p->arm = vcsm_lock(p->vcsm_handle)) == NULL || ++ (p->vc = vcsm_vc_addr_from_hdl(p->vcsm_handle)) == 0) ++ { ++ gpu_free_internal(p); ++ return AVERROR(ENOMEM); ++ } ++ return 0; ++} ++ ++ ++// GPU init, free, lock, unlock ++ ++static void gpu_term(void) ++{ ++ gpu_env_t * const ge = gpu; ++ ++ // We have to hope that eveything has terminated... ++ gpu = NULL; ++ ++ vc_gpuserv_deinit(); ++ ++ gpu_free_internal(&ge->code_gm_ptr); ++ gpu_free_internal(&ge->qpu_code_gm_ptr); ++ gpu_free_internal(&ge->dummy_gm_ptr); ++ ++ vcsm_exit(); ++ ++ vq_wait_pool_deinit(&ge->wait_pool); ++ ++ free(ge); ++} ++ ++ ++// Connect to QPU, returns 0 on success. ++static int gpu_init(gpu_env_t ** const gpu) { ++ volatile struct GPU* ptr; ++ gpu_env_t * const ge = calloc(1, sizeof(gpu_env_t)); ++ int rv; ++ *gpu = NULL; ++ ++ if (ge == NULL) ++ return -1; ++ ++ vq_wait_pool_init(&ge->wait_pool); ++ ++ vcsm_init(); ++ ++ // Now copy over the QPU code into GPU memory ++ if ((rv = gpu_malloc_internal(&ge->qpu_code_gm_ptr, QPU_CODE_SIZE * 4, VCSM_CACHE_TYPE_NONE, "ffmpeg qpu code")) != 0) ++ return rv; ++ ++ { ++ int num_bytes = (char *)mc_end - (char *)ff_hevc_rpi_shader; ++ av_assert0(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy(ge->qpu_code_gm_ptr.arm, ff_hevc_rpi_shader, num_bytes); ++ memset(ge->qpu_code_gm_ptr.arm + num_bytes, 0, QPU_CODE_SIZE*4 - num_bytes); ++ } ++ ++ // And the VPU code ++ if ((rv = gpu_malloc_internal(&ge->code_gm_ptr, sizeof(struct GPU), VCSM_CACHE_TYPE_VC, "ffmpeg vpu code")) != 0) ++ return rv; ++ ptr = (volatile struct GPU*)ge->code_gm_ptr.arm; ++ ++ // Zero everything so we have zeros between the code bits ++ memset((void *)ptr, 0, sizeof(*ptr)); ++ { ++ int num_bytes = sizeof(rpi_hevc_transform8); ++ av_assert0(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->vpu_code8, rpi_hevc_transform8, num_bytes); ++ } ++ { ++ int num_bytes = sizeof(rpi_hevc_transform10); ++ av_assert0(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->vpu_code10, rpi_hevc_transform10, num_bytes); ++ } ++ // And the transform coefficients ++ memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, sizeof(rpi_transMatrix2even)); ++ ++ // Generate a dummy "frame" & fill with 0x80 ++ // * Could reset to 1 <dummy_gm_ptr, 0x4000, VCSM_CACHE_TYPE_NONE, "ffmpeg dummy frame")) != 0) ++ return rv; ++ memset(ge->dummy_gm_ptr.arm, 0x80, 0x4000); ++ ++ *gpu = ge; ++ return 0; ++} ++ ++ ++ ++static void gpu_unlock(void) { ++ pthread_mutex_unlock(&gpu_mutex); ++} ++ ++// Make sure we have exclusive access to the mailbox, and enable qpu if necessary. ++static gpu_env_t * gpu_lock(void) { ++ pthread_mutex_lock(&gpu_mutex); ++ ++ av_assert1(gpu != NULL); ++ return gpu; ++} ++ ++static gpu_env_t * gpu_lock_ref(void) ++{ ++ pthread_mutex_lock(&gpu_mutex); ++ ++ if (gpu == NULL) { ++ int rv = gpu_init(&gpu); ++ if (rv != 0) { ++ gpu_unlock(); ++ return NULL; ++ } ++ } ++ ++ ++gpu->open_count; ++ return gpu; ++} ++ ++static void gpu_unlock_unref(gpu_env_t * const ge) ++{ ++ if (--ge->open_count == 0) ++ gpu_term(); ++ ++ gpu_unlock(); ++} ++ ++static inline gpu_env_t * gpu_ptr(void) ++{ ++ av_assert1(gpu != NULL); ++ return gpu; ++} ++ ++unsigned int vpu_get_fn(const unsigned int bit_depth) { ++ uint32_t a = 0; ++ ++ // Make sure that the gpu is initialized ++ av_assert1(gpu != NULL); ++ switch (bit_depth){ ++ case 8: ++ a = gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code8); ++ break; ++ case 10: ++ a = gpu->code_gm_ptr.vc + offsetof(struct GPU, vpu_code10); ++ break; ++ default: ++ av_assert0(0); ++ } ++ return a; ++} ++ ++unsigned int vpu_get_constants(void) { ++ av_assert1(gpu != NULL); ++ return (gpu->code_gm_ptr.vc + offsetof(struct GPU,transMatrix2even)); ++} ++ ++void gpu_ref(void) ++{ ++ gpu_lock_ref(); ++ gpu_unlock(); ++} ++ ++void gpu_unref(void) ++{ ++ gpu_env_t * const ge = gpu_lock(); ++ gpu_unlock_unref(ge); ++} ++ ++// ---------------------------------------------------------------------------- ++ ++ ++// Wait abstractions - mostly so we can easily add profile code ++static void vq_wait_pool_init(vq_wait_pool_t * const wp) ++{ ++ unsigned int i; ++ for (i = 0; i != VQ_WAIT_POOL_SIZE; ++i) { ++ sem_init(&wp->pool[i].sem, 0, 0); ++ wp->pool[i].next = wp->pool + i + 1; ++ } ++ wp->head = wp->pool + 0; ++ wp->pool[VQ_WAIT_POOL_SIZE - 1].next = NULL; ++} ++ ++static void vq_wait_pool_deinit(vq_wait_pool_t * const wp) ++{ ++ unsigned int i; ++ wp->head = NULL; ++ for (i = 0; i != VQ_WAIT_POOL_SIZE; ++i) { ++ sem_destroy(&wp->pool[i].sem); ++ wp->pool[i].next = NULL; ++ } ++} ++ ++ ++// If sem_init actually takes time then maybe we want a pool... ++static vq_wait_t * vq_wait_new(void) ++{ ++ gpu_env_t * const ge = gpu_lock_ref(); ++ vq_wait_t * const wait = ge->wait_pool.head; ++ ge->wait_pool.head = wait->next; ++ wait->next = NULL; ++ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ tto_start(&ge->ttw.active, ns_time()); ++#endif ++ ++ gpu_unlock(); ++ return wait; ++} ++ ++static void vq_wait_delete(vq_wait_t * const wait) ++{ ++ gpu_env_t * const ge = gpu_lock(); ++ wait->next = ge->wait_pool.head; ++ ge->wait_pool.head = wait; ++ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ { ++ trace_time_wait_t * const ttw = &ge->ttw; ++ const int64_t now = ns_time(); ++ ++ttw->jcount; ++ tto_end(&ttw->wait, now); ++ ++ if (ttw->start0 == 0) ++ { ++ ttw->start0 = ttw->active.start[0]; ++ ttw->last_update = ttw->start0; ++ } ++ if (now - ttw->last_update > WAIT_TIME_PRINT_PERIOD) ++ { ++ ttw->last_update += WAIT_TIME_PRINT_PERIOD; ++ ttw_print(ttw, now); ++ } ++ } ++#endif ++ gpu_unlock_unref(ge); ++} ++ ++static void vq_wait_wait(vq_wait_t * const wait) ++{ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ { ++ const int64_t now = ns_time(); ++ gpu_env_t * const ge = gpu_lock(); ++ tto_start(&ge->ttw.wait, now); ++ gpu_unlock(); ++ } ++#endif ++ ++ while (sem_wait(&wait->sem) == -1 && errno == EINTR) ++ /* loop */; ++} ++ ++static void vq_wait_post(vq_wait_t * const wait) ++{ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ { ++ gpu_env_t *const ge = gpu_lock(); ++ tto_end(&ge->ttw.active, ns_time()); ++ gpu_unlock(); ++ } ++#endif ++ ++ sem_post(&wait->sem); ++} ++ ++ ++ ++// Header comments were wrong for these two ++#define VPU_QPU_MASK_QPU 1 ++#define VPU_QPU_MASK_VPU 2 ++ ++typedef struct vpu_qpu_job_env_s vpu_qpu_job_env_t; ++ ++vpu_qpu_job_env_t * vpu_qpu_job_init(vpu_qpu_job_env_t * const buf) ++{ ++// vpu_qpu_job_env_t * vqj = calloc(1, sizeof(vpu_qpu_job_env_t)); ++ vpu_qpu_job_env_t * vqj = buf; ++// memset(vqj, 0, sizeof(*vqj)); ++ vqj->n = 0; ++ vqj->mask = 0; ++ return vqj; ++} ++ ++void vpu_qpu_job_delete(vpu_qpu_job_env_t * const vqj) ++{ ++// memset(vqj, 0, sizeof(*vqj)); ++// free(vqj); ++} ++ ++static inline struct gpu_job_s * new_job(vpu_qpu_job_env_t * const vqj) ++{ ++ struct gpu_job_s * const j = vqj->j + vqj->n++; ++ av_assert1(vqj->n <= VPU_QPU_JOB_MAX); ++ return j; ++} ++ ++void vpu_qpu_job_add_vpu(vpu_qpu_job_env_t * const vqj, const uint32_t vpu_code, ++ const unsigned r0, const unsigned r1, const unsigned r2, const unsigned r3, const unsigned r4, const unsigned r5) ++{ ++ if (vpu_code != 0) { ++ struct gpu_job_s *const j = new_job(vqj); ++ vqj->mask |= VPU_QPU_MASK_VPU; ++ ++ j->command = EXECUTE_VPU; ++ j->callback.func = 0; ++ j->callback.cookie = NULL; ++ // The bottom two bits of the execute address contain no-flush flags ++ // b0 will flush the VPU I-cache if unset so we nearly always want that set ++ // as we never reload code ++ j->u.v.q[0] = vpu_code | gpu->vpu_i_cache_flushed; ++ j->u.v.q[1] = r0; ++ j->u.v.q[2] = r1; ++ j->u.v.q[3] = r2; ++ j->u.v.q[4] = r3; ++ j->u.v.q[5] = r4; ++ j->u.v.q[6] = r5; ++ gpu->vpu_i_cache_flushed = 1; ++ } ++} ++ ++// flags are QPU_FLAGS_xxx ++void vpu_qpu_job_add_qpu(vpu_qpu_job_env_t * const vqj, const unsigned int n, const uint32_t * const mail) ++{ ++ if (n != 0) { ++ struct gpu_job_s *const j = new_job(vqj); ++ vqj->mask |= VPU_QPU_MASK_QPU; ++ ++ j->command = EXECUTE_QPU; ++ j->callback.func = 0; ++ j->callback.cookie = NULL; ++ ++ j->u.q.jobs = n; ++#if RPI_TRACE_QPU_PROFILE_ALL ++ j->u.q.noflush = QPU_FLAGS_NO_FLUSH_VPU | QPU_FLAGS_PROF_CLEAR_AND_ENABLE | QPU_FLAGS_PROF_OUTPUT_COUNTS; ++#else ++ j->u.q.noflush = QPU_FLAGS_NO_FLUSH_VPU; ++#endif ++ j->u.q.timeout = 5000; ++ memcpy(j->u.q.control, mail, n * QPU_MAIL_EL_VALS * sizeof(uint32_t)); ++ } ++} ++ ++// Convert callback to sem post ++static void vpu_qpu_job_callback_wait(void * v) ++{ ++ vq_wait_post(v); ++} ++ ++// Poke a user-supplied sem ++static void vpu_qpu_job_callback_sem(void * v) ++{ ++ sem_post((sem_t *)v); ++} ++ ++void vpu_qpu_job_add_sync_this(vpu_qpu_job_env_t * const vqj, vpu_qpu_wait_h * const wait_h) ++{ ++ vq_wait_t * wait; ++ ++ if (vqj->mask == 0) { ++ *wait_h = NULL; ++ return; ++ } ++ ++ // We are going to want a sync object ++ wait = vq_wait_new(); ++ ++ // There are 2 VPU Qs & 1 QPU Q so we can collapse sync ++ // If we only posted one thing or only QPU jobs ++ if (vqj->n == 1 || vqj->mask == VPU_QPU_MASK_QPU) ++ { ++ struct gpu_job_s * const j = vqj->j + (vqj->n - 1); ++ av_assert1(j->callback.func == 0); ++ ++ j->callback.func = vpu_qpu_job_callback_wait; ++ j->callback.cookie = wait; ++ } ++ else ++ { ++ struct gpu_job_s *const j = new_job(vqj); ++ ++ j->command = EXECUTE_SYNC; ++ j->u.s.mask = vqj->mask; ++ j->callback.func = vpu_qpu_job_callback_wait; ++ j->callback.cookie = wait; ++ } ++ ++ vqj->mask = 0; ++ *wait_h = wait; ++} ++ ++// Returns 0 if no sync added ('cos Q empty), 1 if sync added ++int vpu_qpu_job_add_sync_sem(vpu_qpu_job_env_t * const vqj, sem_t * const sem) ++{ ++ // If nothing on q then just return ++ if (vqj->mask == 0) ++ return 0; ++ ++ // There are 2 VPU Qs & 1 QPU Q so we can collapse sync ++ // If we only posted one thing or only QPU jobs ++ if (vqj->n == 1 || vqj->mask == VPU_QPU_MASK_QPU) ++ { ++ struct gpu_job_s * const j = vqj->j + (vqj->n - 1); ++ av_assert1(j->callback.func == 0); ++ ++ j->callback.func = vpu_qpu_job_callback_sem; ++ j->callback.cookie = sem; ++ } ++ else ++ { ++ struct gpu_job_s *const j = new_job(vqj); ++ ++ j->command = EXECUTE_SYNC; ++ j->u.s.mask = vqj->mask; ++ j->callback.func = vpu_qpu_job_callback_sem; ++ j->callback.cookie = sem; ++ } ++ ++ vqj->mask = 0; ++ return 1; ++} ++ ++ ++int vpu_qpu_job_start(vpu_qpu_job_env_t * const vqj) ++{ ++ if (vqj->n == 0) ++ return 0; ++ ++ return vc_gpuserv_execute_code(vqj->n, vqj->j); ++} ++ ++// Simple wrapper of start + delete ++int vpu_qpu_job_finish(vpu_qpu_job_env_t * const vqj) ++{ ++ int rv; ++ rv = vpu_qpu_job_start(vqj); ++ vpu_qpu_job_delete(vqj); ++ return rv; ++} ++ ++void vpu_qpu_wait(vpu_qpu_wait_h * const wait_h) ++{ ++ if (wait_h != NULL) ++ { ++ vq_wait_t * const wait = *wait_h; ++ if (wait != NULL) { ++ *wait_h = NULL; ++ vq_wait_wait(wait); ++ vq_wait_delete(wait); ++ } ++ } ++} ++ ++int vpu_qpu_init() ++{ ++ gpu_env_t * const ge = gpu_lock_ref(); ++ if (ge == NULL) ++ return -1; ++ ++ if (ge->init_count++ == 0) ++ { ++ vc_gpuserv_init(); ++ } ++ ++ gpu_unlock(); ++ return 0; ++} ++ ++void vpu_qpu_term() ++{ ++ gpu_env_t * const ge = gpu_lock(); ++ ++ if (--ge->init_count == 0) { ++ vc_gpuserv_deinit(); ++ ++#if RPI_TRACE_TIME_VPU_QPU_WAIT ++ ttw_print(&ge->ttw, ns_time()); ++#endif ++ } ++ ++ gpu_unlock_unref(ge); ++} ++ ++uint32_t qpu_fn(const int * const mc_fn) ++{ ++ return gpu->qpu_code_gm_ptr.vc + ((const char *)mc_fn - (const char *)ff_hevc_rpi_shader); ++} ++ ++uint32_t qpu_dummy(void) ++{ ++ return gpu->dummy_gm_ptr.vc; ++} ++ ++int rpi_hevc_qpu_init_fn(HEVCRpiQpu * const qf, const unsigned int bit_depth) ++{ ++ // Dummy values we can catch with emulation ++ qf->y_pxx = ~1U; ++ qf->y_bxx = ~2U; ++ qf->y_p00 = ~3U; ++ qf->y_b00 = ~4U; ++ qf->c_pxx = ~5U; ++ qf->c_bxx = ~6U; ++ ++ switch (bit_depth) { ++ case 8: ++ qf->y_pxx = qpu_fn(mc_filter_y_pxx); ++ qf->y_pxx = qpu_fn(mc_filter_y_pxx); ++ qf->y_bxx = qpu_fn(mc_filter_y_bxx); ++ qf->y_p00 = qpu_fn(mc_filter_y_p00); ++ qf->y_b00 = qpu_fn(mc_filter_y_b00); ++ qf->c_pxx = qpu_fn(mc_filter_c_p); ++ qf->c_pxx_l1 = qpu_fn(mc_filter_c_p_l1); ++ qf->c_bxx = qpu_fn(mc_filter_c_b); ++ break; ++ case 10: ++ qf->c_pxx = qpu_fn(mc_filter_c10_p); ++ qf->c_pxx_l1 = qpu_fn(mc_filter_c10_p_l1); ++ qf->c_bxx = qpu_fn(mc_filter_c10_b); ++ qf->y_pxx = qpu_fn(mc_filter_y10_pxx); ++ qf->y_bxx = qpu_fn(mc_filter_y10_bxx); ++ qf->y_p00 = qpu_fn(mc_filter_y10_p00); ++ qf->y_b00 = qpu_fn(mc_filter_y10_b00); ++ break; ++ default: ++ return -1; ++ } ++ return 0; ++} ++ +diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h +new file mode 100644 +index 0000000000..8777687021 +--- /dev/null ++++ b/libavcodec/rpi_qpu.h +@@ -0,0 +1,103 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#ifndef RPI_QPU_H ++#define RPI_QPU_H ++ ++#include "rpi_mem.h" ++#include "rpi_zc_frames.h" ++ ++#pragma GCC diagnostic push ++// Many many redundant decls in the header files ++#pragma GCC diagnostic ignored "-Wredundant-decls" ++#pragma GCC diagnostic ignored "-Wstrict-prototypes" ++#include "interface/vmcs_host/vc_vchi_gpuserv.h" // for gpu_job_s ++#pragma GCC diagnostic pop ++ ++// QPU specific functions ++ ++typedef struct HEVCRpiQpu { ++ uint32_t c_pxx; ++ uint32_t c_pxx_l1; ++ uint32_t c_bxx; ++ uint32_t y_pxx; ++ uint32_t y_bxx; ++ uint32_t y_p00; ++ uint32_t y_b00; ++} HEVCRpiQpu; ++ ++int rpi_hevc_qpu_init_fn(HEVCRpiQpu * const qf, const unsigned int bit_depth); ++ ++uint32_t qpu_fn(const int * const mc_fn); ++uint32_t qpu_dummy(void); ++ ++#define QPU_N_GRP 4 ++#define QPU_N_MAX 12 ++ ++#define QPU_MAIL_EL_VALS 2 ++ ++struct vpu_qpu_wait_s; ++typedef struct vq_wait_s * vpu_qpu_wait_h; ++ ++// VPU specific functions ++ ++struct vpu_qpu_job_env_s; ++typedef struct vpu_qpu_job_env_s * vpu_qpu_job_h; ++ ++#define VPU_QPU_JOB_MAX 4 ++struct vpu_qpu_job_env_s ++{ ++ unsigned int n; ++ unsigned int mask; ++ struct gpu_job_s j[VPU_QPU_JOB_MAX]; ++}; ++typedef struct vpu_qpu_job_env_s vpu_qpu_job_env_t; ++ ++vpu_qpu_job_h vpu_qpu_job_init(vpu_qpu_job_env_t * const buf); ++void vpu_qpu_job_delete(const vpu_qpu_job_h vqj); ++void vpu_qpu_job_add_vpu(const vpu_qpu_job_h vqj, const uint32_t vpu_code, ++ const unsigned r0, const unsigned r1, const unsigned r2, const unsigned r3, const unsigned r4, const unsigned r5); ++void vpu_qpu_job_add_qpu(const vpu_qpu_job_h vqj, const unsigned int n, const uint32_t * const mail); ++void vpu_qpu_job_add_sync_this(const vpu_qpu_job_h vqj, vpu_qpu_wait_h * const wait_h); ++int vpu_qpu_job_add_sync_sem(vpu_qpu_job_env_t * const vqj, sem_t * const sem); ++int vpu_qpu_job_start(const vpu_qpu_job_h vqj); ++int vpu_qpu_job_finish(const vpu_qpu_job_h vqj); ++ ++extern unsigned int vpu_get_fn(const unsigned int bit_depth); ++extern unsigned int vpu_get_constants(void); ++ ++// Waits for previous post_codee to complete and Will null out *wait_h after use ++void vpu_qpu_wait(vpu_qpu_wait_h * const wait_h); ++int vpu_qpu_init(void); ++void vpu_qpu_term(void); ++ ++void gpu_ref(void); ++void gpu_unref(void); ++ ++#endif +diff --git a/libavcodec/rpi_zc.c b/libavcodec/rpi_zc.c +new file mode 100644 +index 0000000000..37be9a0f49 +--- /dev/null ++++ b/libavcodec/rpi_zc.c +@@ -0,0 +1,1227 @@ ++#include "config.h" ++ ++#include "libavcodec/avcodec.h" ++#include "rpi_mem.h" ++#include "rpi_mailbox.h" ++#include "rpi_zc.h" ++#include "libavutil/avassert.h" ++#include ++ ++#include "libavutil/buffer_internal.h" ++ ++#pragma GCC diagnostic push ++// Many many redundant decls in the header files ++#pragma GCC diagnostic ignored "-Wredundant-decls" ++#include ++#include ++#pragma GCC diagnostic pop ++ ++#define TRACE_ALLOC 0 ++#define DEBUG_ALWAYS_KEEP_LOCKED 0 ++ ++struct ZcPoolEnt; ++ ++typedef struct ZcPool ++{ ++ size_t numbytes; ++ struct ZcPoolEnt * head; ++ pthread_mutex_t lock; ++} ZcPool; ++ ++typedef struct ZcPoolEnt ++{ ++ size_t numbytes; ++ ++ unsigned int vcsm_handle; ++ unsigned int vc_handle; ++ void * map_arm; ++ unsigned int map_vc; ++ ++ struct ZcPoolEnt * next; ++ struct ZcPool * pool; ++} ZcPoolEnt; ++ ++typedef struct ZcOldCtxVals ++{ ++ int thread_safe_callbacks; ++ int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); ++ void * opaque; ++} ZcOldCtxVals; ++ ++typedef struct AVZcEnv ++{ ++ unsigned int refcount; ++ ZcOldCtxVals old; ++ ++ void * pool_env; ++ av_rpi_zc_alloc_buf_fn_t * alloc_buf; ++ av_rpi_zc_free_pool_fn_t * free_pool; ++ ++ unsigned int pool_size; ++} ZcEnv; ++ ++typedef struct ZcUserBufEnv { ++ void * v; ++ const av_rpi_zc_buf_fn_tab_t * fn; ++ size_t numbytes; ++ int offset; ++} ZcUserBufEnv; ++ ++#define ZC_BUF_INVALID 0 ++#define ZC_BUF_VALID 1 ++#define ZC_BUF_NEVER 2 ++ ++typedef struct ZcBufEnv { ++ GPU_MEM_PTR_T gmem; ++ AVZcEnvPtr zc; ++ int is_valid; ++ AVBufferRef * user; ++ AVRpiZcFrameGeometry geo; ++ size_t size_y; ++ size_t size_c; ++ size_t size_pic; ++ ssize_t offset; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++} ZcBufEnv; ++ ++ ++ ++ ++ ++ ++#define ALLOC_PAD 0 ++#define ALLOC_ROUND 0x1000 ++#define STRIDE_ROUND 64 ++#define STRIDE_OR 0 ++ ++#define DEBUG_ZAP0_BUFFERS 0 ++ ++static inline int av_rpi_is_sand_format(const int format) ++{ ++ return (format >= AV_PIX_FMT_SAND128 && format <= AV_PIX_FMT_SAND64_16) || ++ (format == AV_PIX_FMT_RPI4_8 || format == AV_PIX_FMT_RPI4_10); ++} ++ ++static inline int av_rpi_is_sand_frame(const AVFrame * const frame) ++{ ++ return av_rpi_is_sand_format(frame->format); ++} ++ ++//---------------------------------------------------------------------------- ++// ++// Internal pool stuff ++ ++// Pool entry functions ++ ++static ZcPoolEnt * zc_pool_ent_alloc(ZcPool * const pool, const size_t req_size) ++{ ++ ZcPoolEnt * const zp = av_mallocz(sizeof(ZcPoolEnt)); ++ ++ // Round up to 4k & add 4k ++ const unsigned int alloc_size = (req_size + ALLOC_PAD + ALLOC_ROUND - 1) & ~(ALLOC_ROUND - 1); ++ ++ if (zp == NULL) { ++ av_log(NULL, AV_LOG_ERROR, "av_malloc(ZcPoolEnt) failed\n"); ++ goto fail0; ++ } ++ ++ // The 0x80 here maps all pages here rather than waiting for lazy mapping ++ // BEWARE that in GPU land a later unlock/lock pair will put us back into ++ // lazy mode - which will also break cache invalidate calls. ++ if ((zp->vcsm_handle = vcsm_malloc_cache(alloc_size, VCSM_CACHE_TYPE_HOST | 0x80, "ffmpeg_rpi_zc")) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "av_gpu_malloc_cached(%d) failed\n", alloc_size); ++ goto fail1; ++ } ++ ++#if TRACE_ALLOC ++ printf("%s: Alloc %#x bytes @ h=%d\n", __func__, alloc_size, zp->vcsm_handle); ++#endif ++ ++ zp->numbytes = alloc_size; ++ zp->pool = pool; ++ return zp; ++ ++fail1: ++ av_free(zp); ++fail0: ++ return NULL; ++} ++ ++static void zc_pool_ent_free(ZcPoolEnt * const zp) ++{ ++#if TRACE_ALLOC ++ printf("%s: Free %#x bytes @ h=%d\n", __func__, zp->numbytes, zp->vcsm_handle); ++#endif ++ ++ if (zp->vcsm_handle != 0) ++ { ++ // VC addr & handle need no dealloc ++ if (zp->map_arm != NULL) ++ vcsm_unlock_hdl(zp->vcsm_handle); ++ vcsm_free(zp->vcsm_handle); ++ } ++ av_free(zp); ++} ++ ++//---------------------------------------------------------------------------- ++// ++// Pool functions ++ ++static void zc_pool_free_ent_list(ZcPoolEnt * p) ++{ ++ while (p != NULL) ++ { ++ ZcPoolEnt * const zp = p; ++ p = p->next; ++ zc_pool_ent_free(zp); ++ } ++} ++ ++static void zc_pool_flush(ZcPool * const pool) ++{ ++ ZcPoolEnt * p = pool->head; ++ pool->head = NULL; ++ pool->numbytes = ~0U; ++ zc_pool_free_ent_list(p); ++} ++ ++static ZcPoolEnt * zc_pool_get_ent(ZcPool * const pool, const size_t req_bytes) ++{ ++ ZcPoolEnt * zp = NULL; ++ ZcPoolEnt * flush_list = NULL; ++ size_t numbytes; ++ ++ pthread_mutex_lock(&pool->lock); ++ ++ numbytes = pool->numbytes; ++ ++ // If size isn't close then dump the pool ++ // Close in this context means within 128k ++ if (req_bytes > numbytes || req_bytes + 0x20000 < numbytes) ++ { ++ flush_list = pool->head; ++ pool->head = NULL; ++ pool->numbytes = numbytes = req_bytes; ++ } ++ else if (pool->head != NULL) ++ { ++ zp = pool->head; ++ pool->head = zp->next; ++ } ++ ++ pthread_mutex_unlock(&pool->lock); ++ ++ zc_pool_free_ent_list(flush_list); ++ ++ if (zp == NULL) ++ zp = zc_pool_ent_alloc(pool, numbytes); ++ ++ return zp; ++} ++ ++static void zc_pool_put_ent(ZcPoolEnt * const zp) ++{ ++ ZcPool * const pool = zp == NULL ? NULL : zp->pool; ++ if (zp != NULL) ++ { ++ pthread_mutex_lock(&pool->lock); ++#if TRACE_ALLOC ++ printf("%s: Recycle %#x, %#x\n", __func__, pool->numbytes, zp->numbytes); ++#endif ++ ++ if (pool->numbytes == zp->numbytes) ++ { ++ zp->next = pool->head; ++ pool->head = zp; ++ pthread_mutex_unlock(&pool->lock); ++ } ++ else ++ { ++ pthread_mutex_unlock(&pool->lock); ++ zc_pool_ent_free(zp); ++ } ++ } ++} ++ ++static ZcPool * ++zc_pool_new(void) ++{ ++ ZcPool * const pool = av_mallocz(sizeof(*pool)); ++ if (pool == NULL) ++ return NULL; ++ ++ pool->numbytes = -1; ++ pool->head = NULL; ++ pthread_mutex_init(&pool->lock, NULL); ++ return pool; ++} ++ ++static void ++zc_pool_delete(ZcPool * const pool) ++{ ++ if (pool != NULL) ++ { ++ pool->numbytes = -1; ++ zc_pool_flush(pool); ++ pthread_mutex_destroy(&pool->lock); ++ av_free(pool); ++ } ++} ++ ++//============================================================================ ++// ++// ZC implementation using above pool implementation ++// ++// Fn table fns... ++ ++static void zc_pool_free_v(void * v) ++{ ++ zc_pool_put_ent(v); ++} ++ ++static unsigned int zc_pool_ent_vcsm_handle_v(void * v) ++{ ++ ZcPoolEnt * zp = v; ++ return zp->vcsm_handle; ++} ++ ++static unsigned int zc_pool_ent_vc_handle_v(void * v) ++{ ++ ZcPoolEnt * zp = v; ++ if (zp->vc_handle == 0) ++ { ++ if ((zp->vc_handle = vcsm_vc_hdl_from_hdl(zp->vcsm_handle)) == 0) ++ av_log(NULL, AV_LOG_ERROR, "%s: Failed to map VCSM handle %d to VC handle\n", ++ __func__, zp->vcsm_handle); ++ } ++ return zp->vc_handle; ++} ++ ++static void * zc_pool_ent_map_arm_v(void * v) ++{ ++ ZcPoolEnt * zp = v; ++ if (zp->map_arm == NULL) ++ { ++ if ((zp->map_arm = vcsm_lock(zp->vcsm_handle)) == NULL) ++ av_log(NULL, AV_LOG_ERROR, "%s: Failed to map VCSM handle %d to ARM address\n", ++ __func__, zp->vcsm_handle); ++ } ++ return zp->map_arm; ++} ++ ++static unsigned int zc_pool_ent_map_vc_v(void * v) ++{ ++ ZcPoolEnt * zp = v; ++ if (zp->map_vc == 0) ++ { ++ if ((zp->map_vc = vcsm_vc_addr_from_hdl(zp->vcsm_handle)) == 0) ++ av_log(NULL, AV_LOG_ERROR, "%s: Failed to map VCSM handle %d to VC address\n", ++ __func__, zp->vcsm_handle); ++ } ++ return zp->map_vc; ++} ++ ++static const av_rpi_zc_buf_fn_tab_t zc_pool_buf_fns = { ++ .free = zc_pool_free_v, ++ .vcsm_handle = zc_pool_ent_vcsm_handle_v, ++ .vc_handle = zc_pool_ent_vc_handle_v, ++ .map_arm = zc_pool_ent_map_arm_v, ++ .map_vc = zc_pool_ent_map_vc_v, ++}; ++ ++// ZC Env fns ++ ++// Delete pool ++// All buffers guaranteed freed by now ++static void ++zc_pool_delete_v(void * v) ++{ ++ zc_pool_delete((ZcPool *)v); ++ rpi_mem_gpu_uninit(); ++} ++ ++// Allocate a new ZC buffer ++static AVBufferRef * ++zc_pool_buf_alloc(void * v, size_t size, const AVRpiZcFrameGeometry * geo) ++{ ++ ZcPool * const pool = v; ++ ZcPoolEnt *const zp = zc_pool_get_ent(pool, size); ++ AVBufferRef * buf; ++ ++ (void)geo; // geo ignored here ++ ++ if (zp == NULL) { ++ av_log(NULL, AV_LOG_ERROR, "zc_pool_alloc(%d) failed\n", size); ++ goto fail0; ++ } ++ ++ if ((buf = av_rpi_zc_buf(size, 0, zp, &zc_pool_buf_fns)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "av_rpi_zc_buf() failed\n"); ++ goto fail2; ++ } ++ ++ return buf; ++ ++fail2: ++ zc_pool_put_ent(zp); ++fail0: ++ return NULL; ++} ++ ++// Init wrappers - the public fns ++ ++AVZcEnvPtr ++av_rpi_zc_int_env_alloc(void * logctx) ++{ ++ ZcEnv * zc; ++ ZcPool * pool_env; ++ ++ if (rpi_mem_gpu_init(0) < 0) ++ return NULL; ++ ++ if ((pool_env = zc_pool_new()) == NULL) ++ goto fail1; ++ ++ if ((zc = av_rpi_zc_env_alloc(logctx, pool_env, zc_pool_buf_alloc, zc_pool_delete_v)) == NULL) ++ goto fail2; ++ ++ return zc; ++ ++fail2: ++ zc_pool_delete(pool_env); ++fail1: ++ rpi_mem_gpu_uninit(); ++ return NULL; ++} ++ ++void ++av_rpi_zc_int_env_freep(AVZcEnvPtr * zcp) ++{ ++ const AVZcEnvPtr zc = *zcp; ++ *zcp = NULL; ++ if (zc != NULL) ++ av_rpi_zc_env_release(zc); ++} ++ ++//============================================================================ ++// ++// Geometry ++// ++// This is a separate chunck to the rest ++ ++// Get mailbox fd - should be in a lock when called ++// Rely on process close to close it ++static int mbox_fd(void) ++{ ++ static int fd = -1; ++ if (fd != -1) ++ return fd; ++ return (fd = mbox_open()); ++} ++ ++AVRpiZcFrameGeometry av_rpi_zc_frame_geometry( ++ const int format, const unsigned int video_width, const unsigned int video_height) ++{ ++ static pthread_mutex_t sand_lock = PTHREAD_MUTEX_INITIALIZER; ++ ++ AVRpiZcFrameGeometry geo = { ++ .format = format, ++ .video_width = video_width, ++ .video_height = video_height ++ }; ++ ++ switch (format) ++ { ++ case AV_PIX_FMT_YUV420P: ++ geo.stride_y = ((video_width + 32 + STRIDE_ROUND - 1) & ~(STRIDE_ROUND - 1)) | STRIDE_OR; ++ geo.stride_c = geo.stride_y / 2; ++ geo.height_y = (video_height + 32 + 31) & ~31; ++ geo.height_c = geo.height_y / 2; ++ geo.planes_c = 2; ++ geo.stripes = 1; ++ geo.bytes_per_pel = 1; ++ geo.stripe_is_yc = 1; ++ break; ++ ++ case AV_PIX_FMT_YUV420P10: ++ geo.stride_y = ((video_width * 2 + 64 + STRIDE_ROUND - 1) & ~(STRIDE_ROUND - 1)) | STRIDE_OR; ++ geo.stride_c = geo.stride_y / 2; ++ geo.height_y = (video_height + 32 + 31) & ~31; ++ geo.height_c = geo.height_y / 2; ++ geo.planes_c = 2; ++ geo.stripes = 1; ++ geo.bytes_per_pel = 2; ++ geo.stripe_is_yc = 1; ++ break; ++ ++ case AV_PIX_FMT_SAND128: ++ case AV_PIX_FMT_RPI4_8: ++ { ++ const unsigned int stripe_w = 128; ++ ++ static VC_IMAGE_T img = {0}; ++ ++ // Given the overhead of calling the mailbox keep a stashed ++ // copy as we will almost certainly just want the same numbers again ++ // but that means we need a lock ++ pthread_mutex_lock(&sand_lock); ++ ++ if (img.width != video_width || img.height != video_height) ++ { ++ VC_IMAGE_T new_img = { ++ .type = VC_IMAGE_YUV_UV, ++ .width = video_width, ++ .height = video_height ++ }; ++ ++ mbox_get_image_params(mbox_fd(), &new_img); ++ img = new_img; ++ } ++ ++ geo.stride_y = stripe_w; ++ geo.stride_c = stripe_w; ++ geo.height_y = ((intptr_t)img.extra.uv.u - (intptr_t)img.image_data) / stripe_w; ++ geo.height_c = img.pitch / stripe_w - geo.height_y; ++ geo.stripe_is_yc = 1; ++ if (geo.height_y * stripe_w > img.pitch) ++ { ++ // "tall" sand - all C blocks now follow Y ++ geo.height_y = img.pitch / stripe_w; ++ geo.height_c = geo.height_y; ++ geo.stripe_is_yc = 0; ++ } ++ geo.planes_c = 1; ++ geo.stripes = (video_width + stripe_w - 1) / stripe_w; ++ geo.bytes_per_pel = 1; ++ ++ pthread_mutex_unlock(&sand_lock); ++#if 0 ++ printf("Req: %dx%d: stride=%d/%d, height=%d/%d, stripes=%d, img.pitch=%d\n", ++ video_width, video_height, ++ geo.stride_y, geo.stride_c, ++ geo.height_y, geo.height_c, ++ geo.stripes, img.pitch); ++#endif ++ av_assert0((int)geo.height_y > 0 && (int)geo.height_c > 0); ++ av_assert0(geo.height_y >= video_height && geo.height_c >= video_height / 2); ++ break; ++ } ++ ++ case AV_PIX_FMT_RPI4_10: ++ { ++ const unsigned int stripe_w = 128; // bytes ++ ++ static pthread_mutex_t sand_lock = PTHREAD_MUTEX_INITIALIZER; ++ static VC_IMAGE_T img = {0}; ++ ++ // Given the overhead of calling the mailbox keep a stashed ++ // copy as we will almost certainly just want the same numbers again ++ // but that means we need a lock ++ pthread_mutex_lock(&sand_lock); ++ ++ if (img.width != video_width || img.height != video_height) ++ { ++ VC_IMAGE_T new_img = { ++ .type = VC_IMAGE_YUV10COL, ++ .width = video_width, ++ .height = video_height ++ }; ++ ++ mbox_get_image_params(mbox_fd(), &new_img); ++ img = new_img; ++ } ++ ++ geo.stride_y = stripe_w; ++ geo.stride_c = stripe_w; ++ geo.height_y = ((intptr_t)img.extra.uv.u - (intptr_t)img.image_data) / stripe_w; ++ geo.height_c = img.pitch / stripe_w - geo.height_y; ++ geo.planes_c = 1; ++ geo.stripes = ((video_width * 4 + 2) / 3 + stripe_w - 1) / stripe_w; ++ geo.bytes_per_pel = 1; ++ geo.stripe_is_yc = 1; ++ ++ pthread_mutex_unlock(&sand_lock); ++ ++#if 0 ++ printf("Req: %dx%d: stride=%d/%d, height=%d/%d, stripes=%d, img.pitch=%d\n", ++ video_width, video_height, ++ geo.stride_y, geo.stride_c, ++ geo.height_y, geo.height_c, ++ geo.stripes, img.pitch); ++#endif ++ av_assert0((int)geo.height_y > 0 && (int)geo.height_c > 0); ++ av_assert0(geo.height_y >= video_height && geo.height_c >= video_height / 2); ++ break; ++ } ++ ++ case AV_PIX_FMT_SAND64_16: ++ case AV_PIX_FMT_SAND64_10: ++ { ++ const unsigned int stripe_w = 128; // bytes ++ ++ static pthread_mutex_t sand_lock = PTHREAD_MUTEX_INITIALIZER; ++ static VC_IMAGE_T img = {0}; ++ ++ // Given the overhead of calling the mailbox keep a stashed ++ // copy as we will almost certainly just want the same numbers again ++ // but that means we need a lock ++ pthread_mutex_lock(&sand_lock); ++ ++ if (img.width != video_width || img.height != video_height) ++ { ++ VC_IMAGE_T new_img = { ++ .type = VC_IMAGE_YUV_UV_16, ++ .width = video_width, ++ .height = video_height ++ }; ++ ++ mbox_get_image_params(mbox_fd(), &new_img); ++ img = new_img; ++ } ++ ++ geo.stride_y = stripe_w; ++ geo.stride_c = stripe_w; ++ geo.height_y = ((intptr_t)img.extra.uv.u - (intptr_t)img.image_data) / stripe_w; ++ geo.height_c = img.pitch / stripe_w - geo.height_y; ++ geo.planes_c = 1; ++ geo.stripes = (video_width * 2 + stripe_w - 1) / stripe_w; ++ geo.bytes_per_pel = 2; ++ geo.stripe_is_yc = 1; ++ ++ pthread_mutex_unlock(&sand_lock); ++ break; ++ } ++ ++ default: ++ break; ++ } ++ return geo; ++} ++ ++//============================================================================ ++// ++// ZC Env fns ++// ++// Frame copy fns ++ ++static AVBufferRef * zc_copy(const AVZcEnvPtr zc, ++ const AVFrame * const src) ++{ ++ AVFrame dest_frame; ++ AVFrame * const dest = &dest_frame; ++ unsigned int i; ++ uint8_t * psrc, * pdest; ++ ++ dest->format = src->format; ++ dest->width = src->width; ++ dest->height = src->height; ++ ++ if (av_rpi_zc_get_buffer(zc, dest) != 0 || ++ av_rpi_zc_resolve_frame(dest, ZC_RESOLVE_ALLOC_VALID) != 0) ++ { ++ return NULL; ++ } ++ ++ for (i = 0, psrc = src->data[0], pdest = dest->data[0]; ++ i != dest->height; ++ ++i, psrc += src->linesize[0], pdest += dest->linesize[0]) ++ { ++ memcpy(pdest, psrc, dest->width); ++ } ++ for (i = 0, psrc = src->data[1], pdest = dest->data[1]; ++ i != dest->height / 2; ++ ++i, psrc += src->linesize[1], pdest += dest->linesize[1]) ++ { ++ memcpy(pdest, psrc, dest->width / 2); ++ } ++ for (i = 0, psrc = src->data[2], pdest = dest->data[2]; ++ i != dest->height / 2; ++ ++i, psrc += src->linesize[2], pdest += dest->linesize[2]) ++ { ++ memcpy(pdest, psrc, dest->width / 2); ++ } ++ ++ return dest->buf[0]; ++} ++ ++ ++static AVBufferRef * zc_420p10_to_sand128(const AVZcEnvPtr zc, ++ const AVFrame * const src) ++{ ++ assert(0); ++ return NULL; ++} ++ ++ ++static AVBufferRef * zc_sand64_16_to_sand128(const AVZcEnvPtr zc, ++ const AVFrame * const src, const unsigned int src_bits) ++{ ++ assert(0); ++ return NULL; ++} ++ ++//---------------------------------------------------------------------------- ++// ++// Public info extraction calls ++ ++static void zc_buf_env_free_cb(void * opaque, uint8_t * data); ++ ++static inline ZcBufEnv * pic_zbe_ptr(AVBufferRef *const buf) ++{ ++ // Kludge where we check the free fn to check this is really ++ // one of our buffers - can't think of a better way ++ return buf == NULL || buf->buffer->free != zc_buf_env_free_cb ? NULL : ++ av_buffer_get_opaque(buf); ++} ++ ++static inline GPU_MEM_PTR_T * pic_gm_ptr(AVBufferRef * const buf) ++{ ++ // As gmem is the first el NULL should be preserved ++ return &pic_zbe_ptr(buf)->gmem; ++} ++ ++unsigned int av_rpi_zc_vcsm_handle(const AVRpiZcRefPtr fr_ref) ++{ ++ const GPU_MEM_PTR_T * const p = pic_gm_ptr(fr_ref); ++ return p == NULL ? 0 : p->vcsm_handle; ++} ++ ++int av_rpi_zc_vc_handle(const AVRpiZcRefPtr fr_ref) ++{ ++ const GPU_MEM_PTR_T * const p = pic_gm_ptr(fr_ref); ++ return p == NULL ? -1 : p->vc_handle; ++} ++ ++int av_rpi_zc_offset(const AVRpiZcRefPtr fr_ref) ++{ ++ const ZcBufEnv * const zbe = pic_zbe_ptr(fr_ref); ++ return zbe == NULL ? 0 : zbe->offset; ++} ++ ++int av_rpi_zc_length(const AVRpiZcRefPtr fr_ref) ++{ ++ const ZcBufEnv * const zbe = pic_zbe_ptr(fr_ref); ++ return zbe == NULL ? 0 : zbe->size_pic; ++} ++ ++int av_rpi_zc_numbytes(const AVRpiZcRefPtr fr_ref) ++{ ++ const GPU_MEM_PTR_T * const p = pic_gm_ptr(fr_ref); ++ return p == NULL ? 0 : p->numbytes; ++} ++ ++const AVRpiZcFrameGeometry * av_rpi_zc_geometry(const AVRpiZcRefPtr fr_ref) ++{ ++ const ZcBufEnv * const zbe = pic_zbe_ptr(fr_ref); ++ return zbe == NULL ? NULL : &zbe->geo; ++} ++ ++AVRpiZcRefPtr av_rpi_zc_ref(void * const logctx, const AVZcEnvPtr zc, ++ const AVFrame * const frame, const enum AVPixelFormat expected_format, const int maycopy) ++{ ++ av_assert0(!maycopy || zc != NULL); ++ ++ if (frame->format != AV_PIX_FMT_YUV420P && ++ frame->format != AV_PIX_FMT_YUV420P10 && ++ !av_rpi_is_sand_frame(frame)) ++ { ++ av_log(logctx, AV_LOG_WARNING, "%s: *** Format not SAND/YUV420P: %d\n", __func__, frame->format); ++ return NULL; ++ } ++ ++ if (frame->buf[1] != NULL || frame->format != expected_format) ++ { ++#if RPI_ZC_SAND_8_IN_10_BUF ++ if (frame->format == AV_PIX_FMT_SAND64_10 && expected_format == AV_PIX_FMT_SAND128 && frame->buf[RPI_ZC_SAND_8_IN_10_BUF] != NULL) ++ { ++// av_log(s, AV_LOG_INFO, "%s: --- found buf[4]\n", __func__); ++ return av_buffer_ref(frame->buf[RPI_ZC_SAND_8_IN_10_BUF]); ++ } ++#endif ++ ++ if (maycopy) ++ { ++ if (frame->buf[1] != NULL) ++ av_log(logctx, AV_LOG_INFO, "%s: *** Not a single buf frame: copying\n", __func__); ++ else ++ av_log(logctx, AV_LOG_INFO, "%s: *** Unexpected frame format %d: copying to %d\n", __func__, frame->format, expected_format); ++ ++ switch (frame->format) ++ { ++ case AV_PIX_FMT_YUV420P10: ++ return zc_420p10_to_sand128(zc, frame); ++ ++ case AV_PIX_FMT_SAND64_10: ++ return zc_sand64_16_to_sand128(zc, frame, 10); ++ ++ default: ++ return zc_copy(zc, frame); ++ } ++ } ++ else ++ { ++ if (frame->buf[1] != NULL) ++ av_log(logctx, AV_LOG_WARNING, "%s: *** Not a single buf frame: buf[1] != NULL\n", __func__); ++ else ++ av_log(logctx, AV_LOG_INFO, "%s: *** Unexpected frame format: %d != %d\n", __func__, frame->format, expected_format); ++ return NULL; ++ } ++ } ++ ++ if (pic_gm_ptr(frame->buf[0]) == NULL) ++ { ++ if (maycopy) ++ { ++ av_log(logctx, AV_LOG_INFO, "%s: *** Not one of our buffers: copying\n", __func__); ++ return zc_copy(zc, frame); ++ } ++ else ++ { ++ av_log(logctx, AV_LOG_WARNING, "%s: *** Not one of our buffers: NULL\n", __func__); ++ return NULL; ++ } ++ } ++ ++ return av_buffer_ref(frame->buf[0]); ++} ++ ++void av_rpi_zc_unref(AVRpiZcRefPtr fr_ref) ++{ ++ if (fr_ref != NULL) ++ { ++ av_buffer_unref(&fr_ref); ++ } ++} ++ ++//---------------------------------------------------------------------------- ++ ++// Extract user environment from an AVBufferRef ++void * av_rpi_zc_buf_v(AVBufferRef * const buf) ++{ ++ ZcBufEnv * const zbe = pic_zbe_ptr(buf); ++ if (zbe != NULL && zbe->user != NULL) ++ { ++ const ZcUserBufEnv * const zub = (const ZcUserBufEnv *)zbe->user->data; ++ return zub == NULL ? NULL : zub->v; ++ } ++ return NULL; ++} ++ ++// AV buffer pre-free callback ++static void zc_user_buf_free_cb(void * opaque, uint8_t * data) ++{ ++ if (opaque != NULL) ++ { ++ ZcUserBufEnv * const zub = opaque; ++ ++ if (zub->fn->free) ++ zub->fn->free(zub->v); ++ ++ av_free(zub); ++ } ++} ++ ++static void zc_buf_env_free_cb(void * opaque, uint8_t * data) ++{ ++ if (opaque != NULL) ++ { ++ ZcBufEnv * const zbe = opaque; ++ ++ av_buffer_unref(&zbe->user); ++ ++ if (zbe->zc != NULL) ++ av_rpi_zc_env_release(zbe->zc); ++ ++ pthread_cond_destroy(&zbe->cond); ++ pthread_mutex_destroy(&zbe->lock); ++ av_free(zbe); ++ } ++} ++ ++ ++// Wrap the various ZC bits in an AV Buffer and resolve those things we want ++// resolved now. ++// Currently we resolve everything, but in future we might not ++AVBufferRef * av_rpi_zc_buf(size_t numbytes, int addr_offset, void * v, const av_rpi_zc_buf_fn_tab_t * fn_tab) ++{ ++ AVBufferRef *buf; ++ ZcUserBufEnv * zub; ++ ++ if ((zub = av_malloc(sizeof(ZcUserBufEnv))) == NULL) ++ return NULL; ++ ++ zub->fn = fn_tab; ++ zub->v = v; ++ zub->numbytes = numbytes; ++ zub->offset = addr_offset; ++ ++ if ((buf = av_buffer_create((uint8_t*)zub, sizeof(*zub), zc_user_buf_free_cb, zub, 0)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "ZC: Failed av_buffer_create\n"); ++ av_free(zub); ++ return NULL; ++ } ++ ++ return buf; ++} ++ ++int av_rpi_zc_resolve_buffer(AVBufferRef * const buf, const int alloc_mode) ++{ ++ ZcBufEnv * const zbe = pic_zbe_ptr(buf); ++ ++ if (zbe == NULL) ++ return AVERROR(EINVAL); ++ ++ if (alloc_mode == ZC_RESOLVE_FAIL && !zbe->is_valid) ++ return AVERROR(EAGAIN); ++ ++ if (alloc_mode == ZC_RESOLVE_WAIT_VALID && !zbe->is_valid) ++ { ++ pthread_mutex_lock(&zbe->lock); ++ while (!zbe->is_valid) ++ pthread_cond_wait(&zbe->cond, &zbe->lock); ++ pthread_mutex_unlock(&zbe->lock); ++ } ++ ++ if (zbe->is_valid == ZC_BUF_NEVER) ++ return AVERROR(EINVAL); ++ ++ // Do alloc if we need it ++ if (zbe->user == NULL) ++ { ++ ZcEnv * const zc = zbe->zc; ++ const ZcUserBufEnv * zub; ++ ++ av_assert0(alloc_mode == ZC_RESOLVE_ALLOC || alloc_mode == ZC_RESOLVE_ALLOC_VALID); ++ ++ if ((zbe->user = zc->alloc_buf(zc->pool_env, zbe->size_pic, &zbe->geo)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "rpi_get_display_buffer: Failed to get buffer from pool\n"); ++ goto fail; ++ } ++ zub = (const ZcUserBufEnv *)zbe->user->data; ++ ++ // Track ++ ++ zbe->offset = zub->offset; ++ zbe->gmem.numbytes = zub->numbytes; ++ if ((zbe->gmem.arm = zub->fn->map_arm(zub->v)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "ZC: Failed to lock vcsm_handle %u\n", zbe->gmem.vcsm_handle); ++ goto fail; ++ } ++ ++ if ((zbe->gmem.vcsm_handle = zub->fn->vcsm_handle(zub->v)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "ZC: Failed to get vcsm_handle\n"); ++ goto fail; ++ } ++ ++ if ((zbe->gmem.vc_handle = zub->fn->vc_handle(zub->v)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "ZC: Failed to get vc handle from vcsm_handle %u\n", zbe->gmem.vcsm_handle); ++ goto fail; ++ } ++ if ((zbe->gmem.vc = zub->fn->map_vc(zub->v)) == 0) ++ { ++ av_log(NULL, AV_LOG_ERROR, "ZC: Failed to get vc addr from vcsm_handle %u\n", zbe->gmem.vcsm_handle); ++ goto fail; ++ } ++ ++ buf->buffer->data = zbe->gmem.arm + zbe->offset; ++ buf->buffer->size = zbe->size_pic; ++ ++ // In this mode we shouldn't have anyone waiting for us ++ // so no need to signal ++ if (alloc_mode == ZC_RESOLVE_ALLOC_VALID) ++ zbe->is_valid = 1; ++ } ++ ++ // Just overwrite - no point in testing ++ buf->data = zbe->gmem.arm + zbe->offset; ++ buf->size = zbe->size_pic; ++ return 0; ++ ++fail: ++ av_buffer_unref(&zbe->user); ++ return AVERROR(ENOMEM); ++} ++ ++int av_rpi_zc_resolve_frame(AVFrame * const frame, const int may_alloc) ++{ ++ int rv; ++ ++ // Do alloc if we need it ++ if ((rv = av_rpi_zc_resolve_buffer(frame->buf[0], may_alloc)) != 0) ++ return rv; ++ ++ // If we are a framebuf copy then the alloc can be done but we haven't ++ // imported its results yet ++ if (frame->data[0] == NULL) ++ { ++ const ZcBufEnv * const zbe = pic_zbe_ptr(frame->buf[0]); ++ ++ frame->linesize[0] = zbe->geo.stride_y; ++ frame->linesize[1] = zbe->geo.stride_c; ++ frame->linesize[2] = zbe->geo.stride_c; ++ // abuse: linesize[3] = "stripe stride" ++ // stripe_stride is NOT the stride between slices it is (that / geo.stride_y). ++ // In a general case this makes the calculation an xor and multiply rather ++ // than a divide and multiply ++ if (zbe->geo.stripes > 1) ++ frame->linesize[3] = zbe->geo.stripe_is_yc ? zbe->geo.height_y + zbe->geo.height_c : zbe->geo.height_y; ++ ++ frame->data[0] = frame->buf[0]->data; ++ frame->data[1] = frame->data[0] + (zbe->geo.stripe_is_yc ? zbe->size_y : zbe->size_y * zbe->geo.stripes); ++ if (zbe->geo.planes_c > 1) ++ frame->data[2] = frame->data[1] + zbe->size_c; ++ ++ frame->extended_data = frame->data; ++ // Leave extended buf alone ++ } ++ ++ return 0; ++} ++ ++int av_rpi_zc_set_valid_frame(AVFrame * const frame) ++{ ++ ZcBufEnv * const zbe = pic_zbe_ptr(frame->buf[0]); ++ ++ if (zbe == NULL) ++ return AVERROR(EINVAL); ++ ++ zbe->is_valid = ZC_BUF_VALID; ++ pthread_cond_broadcast(&zbe->cond); ++ ++ return 0; ++} ++ ++int av_rpi_zc_set_broken_frame(AVFrame * const frame) ++{ ++ ZcBufEnv * const zbe = pic_zbe_ptr(frame->buf[0]); ++ ++ if (zbe == NULL) ++ return AVERROR(EINVAL); ++ ++ zbe->is_valid = ZC_BUF_NEVER; ++ pthread_cond_broadcast(&zbe->cond); ++ ++ return 0; ++} ++ ++void av_rpi_zc_set_decoder_pool_size(ZcEnv *const zc, const unsigned int pool_size) ++{ ++ zc->pool_size = pool_size; ++} ++ ++unsigned int av_rpi_zc_get_decoder_pool_size(ZcEnv *const zc) ++{ ++ return zc->pool_size; ++} ++ ++int av_rpi_zc_get_buffer(ZcEnv *const zc, AVFrame * const frame) ++{ ++#if 1 ++ ZcBufEnv * zbe = av_mallocz(sizeof(*zbe)); ++ ++ for (unsigned int i = 0; i < AV_NUM_DATA_POINTERS; i++) { ++ frame->buf[i] = NULL; ++ frame->data[i] = NULL; ++ frame->linesize[i] = 0; ++ } ++ ++ if (zbe == NULL) ++ return AVERROR(ENOMEM); ++ ++ if ((frame->buf[0] = av_buffer_create((uint8_t *)zbe, sizeof(*zbe), zc_buf_env_free_cb, zbe, 0)) == NULL) ++ { ++ av_free(zbe); ++ return AVERROR(ENOMEM); ++ } ++ ++ pthread_mutex_init(&zbe->lock, NULL); ++ pthread_cond_init(&zbe->cond, NULL); ++ zbe->zc = zc; ++ atomic_fetch_add(&zc->refcount, 1); ++ ++ zbe->geo = av_rpi_zc_frame_geometry(frame->format, frame->width, frame->height); // Note geometry for later use ++ zbe->size_y = zbe->geo.stride_y * zbe->geo.height_y; ++ zbe->size_c = zbe->geo.stride_c * zbe->geo.height_c; ++ zbe->size_pic = (zbe->size_y + zbe->size_c * zbe->geo.planes_c) * zbe->geo.stripes; ++ ++#else ++ const AVRpiZcFrameGeometry geo = av_rpi_zc_frame_geometry(frame->format, frame->width, frame->height); ++ const unsigned int size_y = geo.stride_y * geo.height_y; ++ const unsigned int size_c = geo.stride_c * geo.height_c; ++ const unsigned int size_pic = (size_y + size_c * geo.planes_c) * geo.stripes; ++ AVBufferRef * buf; ++ unsigned int i; ++ ++// printf("Do local alloc: format=%#x, %dx%d: %u\n", frame->format, frame->width, frame->height, size_pic); ++ ++ if ((buf = zc->alloc_buf(zc->pool_env, size_pic, &geo)) == NULL) ++ { ++ av_log(NULL, AV_LOG_ERROR, "rpi_get_display_buffer: Failed to get buffer from pool\n"); ++ return AVERROR(ENOMEM); ++ } ++ ++ // Track ++ atomic_fetch_add(&zc->refcount, 1); ++ pic_zbe_ptr(buf)->zc = zc; ++ ++ for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { ++ frame->buf[i] = NULL; ++ frame->data[i] = NULL; ++ frame->linesize[i] = 0; ++ } ++ ++ frame->buf[0] = buf; ++ ++ frame->linesize[0] = geo.stride_y; ++ frame->linesize[1] = geo.stride_c; ++ frame->linesize[2] = geo.stride_c; ++ // abuse: linesize[3] = "stripe stride" ++ // stripe_stride is NOT the stride between slices it is (that / geo.stride_y). ++ // In a general case this makes the calculation an xor and multiply rather ++ // than a divide and multiply ++ if (geo.stripes > 1) ++ frame->linesize[3] = geo.stripe_is_yc ? geo.height_y + geo.height_c : geo.height_y; ++ ++ frame->data[0] = buf->data; ++ frame->data[1] = frame->data[0] + (geo.stripe_is_yc ? size_y : size_y * geo.stripes); ++ if (geo.planes_c > 1) ++ frame->data[2] = frame->data[1] + size_c; ++ ++ frame->extended_data = frame->data; ++ // Leave extended buf alone ++ ++#if RPI_ZC_SAND_8_IN_10_BUF != 0 ++ // *** If we intend to use this for real we will want a 2nd buffer pool ++ frame->buf[RPI_ZC_SAND_8_IN_10_BUF] = zc_pool_buf_alloc(&zc->pool, size_pic); // *** 2 * wanted size - kludge ++#endif ++#endif ++ ++ return 0; ++} ++ ++void av_rpi_zc_env_release(const AVZcEnvPtr zc) ++{ ++ const int n = atomic_fetch_add(&zc->refcount, -1); ++ if (n == 1) // was 1, now 0 ++ { ++ zc->free_pool(zc->pool_env); ++ av_free(zc); ++ } ++} ++ ++AVZcEnvPtr av_rpi_zc_env_alloc(void * logctx, ++ void * pool_env, ++ av_rpi_zc_alloc_buf_fn_t * alloc_buf_fn, ++ av_rpi_zc_free_pool_fn_t * free_pool_fn) ++{ ++ ZcEnv * zc; ++ ++ if ((zc = av_mallocz(sizeof(ZcEnv))) == NULL) ++ { ++ av_log(logctx, AV_LOG_ERROR, "av_rpi_zc_env_alloc: Context allocation failed\n"); ++ return NULL; ++ } ++ ++ *zc = (ZcEnv){ ++ .refcount = ATOMIC_VAR_INIT(1), ++ .pool_env = pool_env, ++ .alloc_buf = alloc_buf_fn, ++ .free_pool = free_pool_fn, ++ .pool_size = 0 ++ }; ++ ++ return zc; ++} ++ ++//============================================================================ ++// ++// External ZC initialisation ++ ++#define RPI_GET_BUFFER2 1 ++ ++ ++static int zc_get_buffer2(struct AVCodecContext *s, AVFrame *frame, int flags) ++{ ++#if !RPI_GET_BUFFER2 ++ return avcodec_default_get_buffer2(s, frame, flags); ++#else ++ int rv; ++ ++ if ((s->codec->capabilities & AV_CODEC_CAP_DR1) == 0) ++ { ++// printf("Do default alloc: format=%#x\n", frame->format); ++ rv = avcodec_default_get_buffer2(s, frame, flags); ++ } ++ else if (frame->format == AV_PIX_FMT_YUV420P || ++ av_rpi_is_sand_frame(frame)) ++ { ++ if ((rv = av_rpi_zc_get_buffer(s->opaque, frame)) == 0) ++ rv = av_rpi_zc_resolve_frame(frame, ZC_RESOLVE_ALLOC_VALID); ++ } ++ else ++ { ++ rv = avcodec_default_get_buffer2(s, frame, flags); ++ } ++ ++#if 0 ++ printf("%s: fmt:%d, %dx%d lsize=%d/%d/%d/%d data=%p/%p/%p bref=%p/%p/%p opaque[0]=%p\n", __func__, ++ frame->format, frame->width, frame->height, ++ frame->linesize[0], frame->linesize[1], frame->linesize[2], frame->linesize[3], ++ frame->data[0], frame->data[1], frame->data[2], ++ frame->buf[0], frame->buf[1], frame->buf[2], ++ av_buffer_get_opaque(frame->buf[0])); ++#endif ++ return rv; ++#endif ++} ++ ++int av_rpi_zc_in_use(const struct AVCodecContext * const s) ++{ ++ return s->get_buffer2 == zc_get_buffer2; ++} ++ ++int av_rpi_zc_init2(struct AVCodecContext * const s, ++ void * pool_env, ++ av_rpi_zc_alloc_buf_fn_t * alloc_buf_fn, ++ av_rpi_zc_free_pool_fn_t * free_pool_fn) ++{ ++ ZcEnv * zc; ++ ++ av_assert0(!av_rpi_zc_in_use(s)); ++ ++ if ((zc = av_rpi_zc_env_alloc(s, pool_env, alloc_buf_fn, free_pool_fn)) == NULL) ++ return AVERROR(ENOMEM); ++ ++ zc->old = (ZcOldCtxVals){ ++ .opaque = s->opaque, ++ .get_buffer2 = s->get_buffer2, ++ .thread_safe_callbacks = s->thread_safe_callbacks ++ }; ++ ++ s->opaque = zc; ++ s->get_buffer2 = zc_get_buffer2; ++ s->thread_safe_callbacks = 1; ++ return 0; ++} ++ ++void av_rpi_zc_uninit2(struct AVCodecContext * const s) ++{ ++ ZcEnv * const zc = s->opaque; ++ ++ av_assert0(av_rpi_zc_in_use(s)); ++ ++ s->get_buffer2 = zc->old.get_buffer2; ++ s->opaque = zc->old.opaque; ++ s->thread_safe_callbacks = zc->old.thread_safe_callbacks; ++ ++ av_rpi_zc_env_release(zc); ++} ++ +diff --git a/libavcodec/rpi_zc.h b/libavcodec/rpi_zc.h +new file mode 100644 +index 0000000000..f00a7c962c +--- /dev/null ++++ b/libavcodec/rpi_zc.h +@@ -0,0 +1,228 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++#ifndef LIBAVCODEC_RPI_ZC_H ++#define LIBAVCODEC_RPI_ZC_H ++ ++// Zero-Copy frame code for RPi ++// RPi needs Y/U/V planes to be contiguous for display. By default ++// ffmpeg will allocate separated planes so a memcpy is needed before ++// display. This code provides a method a making ffmpeg allocate a single ++// bit of memory for the frame when can then be reference counted until ++// display has finished with it. ++ ++// Frame buffer number in which to stuff an 8-bit copy of a 16-bit frame ++// 0 disables ++// *** This option still in development ++// Only works if SAO active ++// Allocates buffers that are twice the required size ++#define RPI_ZC_SAND_8_IN_10_BUF 0 ++ ++struct AVBufferRef; ++struct AVFrame; ++struct AVCodecContext; ++enum AVPixelFormat; ++ ++// "Opaque" pointer to whatever we are using as a buffer reference ++typedef struct AVBufferRef * AVRpiZcRefPtr; ++ ++struct AVZcEnv; ++typedef struct AVZcEnv * AVZcEnvPtr; ++ ++typedef struct AVRpiZcFrameGeometry ++{ ++ unsigned int stride_y; // Luma stride (bytes) ++ unsigned int height_y; // Luma height (lines) ++ unsigned int stride_c; // Chroma stride (bytes) ++ unsigned int height_c; // Chroma stride (lines) ++ unsigned int planes_c; // Chroma plane count (U, V = 2, interleaved = 1) ++ unsigned int stripes; // Number of stripes (sand) ++ unsigned int bytes_per_pel; ++ int stripe_is_yc; // A single stripe is Y then C (false for tall sand) ++ ++ int format; // Requested format ++ unsigned int video_width; // Requested width ++ unsigned int video_height; // Requested height ++} AVRpiZcFrameGeometry; ++ ++// Get expected MMAL geometry for a given format, width & height ++AVRpiZcFrameGeometry av_rpi_zc_frame_geometry( ++ const int format, ++ const unsigned int video_width, const unsigned int video_height); ++ ++//---------------------------------------------------------------------------- ++// ++// Calls that extract info from a ZC frame whether internally or externally ++// allocated ++ ++// Generate a ZC reference to the buffer(s) in this frame ++// If the buffer doesn't appear to be one allocated by ZC ++// then the behaviour depends on maycopy: ++// If maycopy=0 then return NULL ++// If maycopy=1 && the src frame is in a form where we can easily copy ++// the data, then allocate a new buffer and copy the data into it ++// Otherwise return NULL ++// If maycopy == 0 then ZC may be NULL ++AVRpiZcRefPtr av_rpi_zc_ref(void * const logging_context, const AVZcEnvPtr zc, ++ const struct AVFrame * const frame, const enum AVPixelFormat expected_format, const int maycopy); ++ ++// Unreference the buffer refed/allocated by _zc_ref ++// If fr_ref is NULL then this will NOP ++void av_rpi_zc_unref(AVRpiZcRefPtr fr_ref); ++ ++// Get the vc_handle from the frame ref ++// Returns -1 if ref doesn't look valid ++int av_rpi_zc_vc_handle(const AVRpiZcRefPtr fr_ref); ++// Get the vcsm_handle from the frame ref ++// Returns 0 if ref doesn't look valid ++unsigned int av_rpi_zc_vcsm_handle(const AVRpiZcRefPtr fr_ref); ++// Get offset from the start of the memory referenced ++// by the vc_handle to valid data ++int av_rpi_zc_offset(const AVRpiZcRefPtr fr_ref); ++// Length of buffer data ++int av_rpi_zc_length(const AVRpiZcRefPtr fr_ref); ++// Get the number of bytes allocated from the frame ref ++// Returns 0 if ref doesn't look valid ++int av_rpi_zc_numbytes(const AVRpiZcRefPtr fr_ref); ++// Geometry this frame was allocated with ++const AVRpiZcFrameGeometry * av_rpi_zc_geometry(const AVRpiZcRefPtr fr_ref); ++ ++//---------------------------------------------------------------------------- ++// ++// Calls for external frame allocation ++ ++// Callbacks registered in av_rpi_zc_init2 ++ ++// Callback to allocate a buf for a frame ++// The frame itself is generated in the calling code ++// ++// Parameters: ++// pool_env value passed to av-rpi_zc_init2 ++// size size wanted ++// geo geometry of the frame to be allocated ++// Returns: ++// NULL Alloc failed ++// ptr AVBufferBuf* of allocated buffer ++// In most cases av_rpi_zc_buf will be called by this function ++// and this will be the buf returned by that. ++typedef AVBufferRef * av_rpi_zc_alloc_buf_fn_t(void * pool_env, size_t size, ++ const AVRpiZcFrameGeometry * geo); ++ ++// Callback once ffmpeg is completely done with this pool ++// Called once all allocated buffers have been derefed and ffmpegs ref to this ++// pool has been dropped ++typedef void av_rpi_zc_free_pool_fn_t(void * pool_env); ++ ++// Init ZC into a context ++// Sets opaque, get_buffer2, thread_safe_callbacks ++// Use if you want to allocate your own pools and/or create ZC buffers for ++// all decoders ++// RPI HEVC decoders will allocate appropriate VCSM buffers which can be taken ++// apart by av_rpi_zc_xxx calls without this ++int av_rpi_zc_init2(struct AVCodecContext * const s, ++ void * pool_env, av_rpi_zc_alloc_buf_fn_t * alloc_buf_fn, ++ av_rpi_zc_free_pool_fn_t * free_pool_fn); ++ ++// Free ZC from a context ++void av_rpi_zc_uninit2(struct AVCodecContext * const s); ++ ++// Get minimum pool size in frames - valid by the time the first alloc request ++// occurs. Takes into account thread requests and DPB sizes derived from SPS ++// rather than just adding a worst case DPB size. ++unsigned int av_rpi_zc_get_decoder_pool_size(const AVZcEnvPtr zc); ++ ++typedef struct av_rpi_zc_buf_fn_tab_s { ++ // This AVBuffer is being freed by ffmpeg - return memory ++ // to external pool. Memory may be, but need not be, unmapped. ++ // v is the ptr passed in av_rpi_zc_buf ++ void (* free)(void * v); ++ ++ // Return appropriate handles / mappings ++ // v is the ptr passed in av_rpi_zc_buf ++ unsigned int (* vcsm_handle)(void * v); ++ unsigned int (* vc_handle)(void * v); ++ void * (* map_arm)(void * v); ++ unsigned int (* map_vc)(void * v); ++} av_rpi_zc_buf_fn_tab_t; ++ ++// Allocate a ZC AVBufferRef and set its callback table ++// Doesn't take a buffer address directly - relies on callbacks to return ++// addresses as they are required. Mappings need not be generated until ++// the map callbacks are called but they should persist from then until ++// the buffer is freed. ++// ++// Parameters: ++// numbytes Size of the buffer ++// addr_offset Offset to first usable byte of buffer (for alignment) ++// normally 0 ++// v Pointer passed to callbacks ++// fn_tab Function table ++AVBufferRef * av_rpi_zc_buf(size_t numbytes, int addr_offset, void * v, const av_rpi_zc_buf_fn_tab_t * fn_tab); ++ ++// Get v ptr set in in av_rpi_zc_buf ++void * av_rpi_zc_buf_v(AVBufferRef * const buf); ++ ++//---------------------------------------------------------------------------- ++// ++// Mostly internal calls but might possibly be wanted by outside code ++ ++void av_rpi_zc_int_env_freep(AVZcEnvPtr * zc); ++AVZcEnvPtr av_rpi_zc_int_env_alloc(void * const logctx); ++void av_rpi_zc_set_decoder_pool_size(const AVZcEnvPtr zc, const unsigned int pool_size); ++ ++// Test to see if the context is using zc (checks get_buffer2) ++int av_rpi_zc_in_use(const struct AVCodecContext * const s); ++ ++// Get buffer generates placeholders for later alloc ++int av_rpi_zc_get_buffer(const AVZcEnvPtr zc, AVFrame * const frame); ++// Resolve actually does the alloc (noop if already alloced) ++// Set data pointers on a buffer/frame that was copied before the alloc ++// accured ++#define ZC_RESOLVE_FAIL 0 // return error on invalid ++#define ZC_RESOLVE_ALLOC 1 // alloc as invalid ++#define ZC_RESOLVE_WAIT_VALID 2 // wait for valid ++#define ZC_RESOLVE_ALLOC_VALID 3 // alloc as valid ++int av_rpi_zc_resolve_buffer(AVBufferRef * const buf, const int may_alloc); ++int av_rpi_zc_resolve_frame(AVFrame * const frame, const int may_alloc); ++ ++int av_rpi_zc_set_valid_frame(AVFrame * const frame); ++int av_rpi_zc_set_broken_frame(AVFrame * const frame); ++ ++ ++ ++ ++AVZcEnvPtr av_rpi_zc_env_alloc(void * logctx, ++ void * pool_env, ++ av_rpi_zc_alloc_buf_fn_t * alloc_buf_fn, ++ av_rpi_zc_free_pool_fn_t * free_pool_fn); ++void av_rpi_zc_env_release(const AVZcEnvPtr zc); ++ ++ ++#endif ++ +diff --git a/libavcodec/rpi_zc_frames.h b/libavcodec/rpi_zc_frames.h +new file mode 100644 +index 0000000000..9b7b6536a4 +--- /dev/null ++++ b/libavcodec/rpi_zc_frames.h +@@ -0,0 +1,142 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox, Ben Avison ++*/ ++ ++#ifndef RPI_ZC_FRAMES_H ++#define RPI_ZC_FRAMES_H ++ ++#define RPI_ONE_BUF 1 ++ ++#include "rpi_mem.h" // for GPU_MEM_PTR_T ++#include "libavutil/frame.h" ++ ++#if !RPI_ONE_BUF ++static inline uint32_t get_vc_address_y(const AVFrame * const frame) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_buffer_get_opaque(frame->buf[0]); ++ return p->vc; ++} ++ ++static inline uint32_t get_vc_address_u(const AVFrame * const frame) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_buffer_get_opaque(frame->buf[1]); ++ return p->vc; ++} ++ ++static inline uint32_t get_vc_address_v(const AVFrame * const frame) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_buffer_get_opaque(frame->buf[2]); ++ return p->vc; ++} ++ ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_y(const AVFrame * const frame) { ++ return *(GPU_MEM_PTR_T *)av_buffer_pool_buffer_get_opaque(frame->buf[0]); ++} ++ ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_u(const AVFrame * const frame) { ++ return *(GPU_MEM_PTR_T *)av_buffer_pool_buffer_get_opaque(frame->buf[1]); ++} ++ ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_v(const AVFrame * const frame) { ++ return *(GPU_MEM_PTR_T *)av_buffer_pool_buffer_get_opaque(frame->buf[2]); ++} ++ ++#else ++ ++static inline int gpu_is_buf1(const AVFrame * const frame) ++{ ++ return frame->buf[1] == NULL; ++} ++ ++static inline GPU_MEM_PTR_T * gpu_buf1_gmem(const AVFrame * const frame) ++{ ++ return av_buffer_get_opaque(frame->buf[0]); ++} ++ ++static inline GPU_MEM_PTR_T * gpu_buf3_gmem(const AVFrame * const frame, const unsigned int n) ++{ ++ return av_buffer_pool_buffer_get_opaque(frame->buf[n]); ++} ++ ++static inline uint32_t get_vc_address3(const AVFrame * const frame, const unsigned int n) ++{ ++ const GPU_MEM_PTR_T * const gm = gpu_is_buf1(frame) ? gpu_buf1_gmem(frame) : gpu_buf3_gmem(frame, n); ++ return gm->vc + (frame->data[n] - gm->arm); ++} ++ ++ ++static inline uint32_t get_vc_address_y(const AVFrame * const frame) { ++ return get_vc_address3(frame, 0); ++} ++ ++static inline uint32_t get_vc_address_u(const AVFrame * const frame) { ++ return get_vc_address3(frame, 1); ++} ++ ++static inline uint32_t get_vc_address_v(const AVFrame * const frame) { ++ return get_vc_address3(frame, 2); ++} ++ ++#if 0 ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_y(const AVFrame * const frame) { ++ if (gpu_is_buf1(frame)) ++ { ++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); ++ g.numbytes = frame->data[1] - frame->data[0]; ++ return g; ++ } ++ else ++ return *gpu_buf3_gmem(frame, 0); ++} ++ ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_u(const AVFrame * const frame) { ++ if (gpu_is_buf1(frame)) ++ { ++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); ++ g.arm += frame->data[1] - frame->data[0]; ++ g.vc += frame->data[1] - frame->data[0]; ++ g.numbytes = frame->data[2] - frame->data[1]; // chroma size ++ return g; ++ } ++ else ++ return *gpu_buf3_gmem(frame, 1); ++} ++ ++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_v(const AVFrame * const frame) { ++ if (gpu_is_buf1(frame)) ++ { ++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); ++ g.arm += frame->data[2] - frame->data[0]; ++ g.vc += frame->data[2] - frame->data[0]; ++ g.numbytes = frame->data[2] - frame->data[1]; // chroma size ++ return g; ++ } ++ else ++ return *gpu_buf3_gmem(frame, 2); ++} ++#endif ++#endif ++ ++#endif +diff --git a/libavcodec/rpivid_hevc.c b/libavcodec/rpivid_hevc.c +new file mode 100644 +index 0000000000..a6b5e8a189 +--- /dev/null ++++ b/libavcodec/rpivid_hevc.c +@@ -0,0 +1,2033 @@ ++// FFMPEG HEVC decoder hardware accelerator ++// Andrew Holme, Argon Design Ltd ++// Copyright (c) June 2017 Raspberry Pi Ltd ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "fftools/ffmpeg.h" ++#include "libavutil/avassert.h" ++#include "libavutil/imgutils.h" ++#include "avcodec.h" ++#include "hwconfig.h" ++#include "decode.h" ++ ++#include "hevc.h" ++#include "hevcdec.h" ++#include "rpi_zc.h" ++#include "rpi_mem.h" ++#include "rpi_zc_frames.h" ++#include "rpi_mailbox.h" ++ ++ ++#define OPT_PHASE_TIMING 0 // Generate stats for phase usage ++ ++#define NUM_SCALING_FACTORS 4064 ++ ++#define AXI_BASE64 0 ++ ++#define PROB_BACKUP ((20<<12) + (20<<6) + (0<<0)) ++#define PROB_RELOAD ((20<<12) + (20<<0) + (0<<6)) ++ ++#define RPIVID_COL_PICS 17 // 16 ref & current ++ ++#define RPIVID_BITBUFS 2 // Bit + Cmd bufs (phase 0 & 1) ++#define RPIVID_BITBUF_SIZE (4 << 20) // Bit + Cmd buf size ++ ++#define RPIVID_COEFFBUFS 3 // PU + Coeff bufs (phase 1 & 2) ++#define RPIVID_COEFFBUF_SIZE (16 << 20) // PU + Coeff buf size ++ ++////////////////////////////////////////////////////////////////////////////// ++// ++// Register offsets ++ ++#define RPI_SPS0 0 ++#define RPI_SPS1 4 ++#define RPI_PPS 8 ++#define RPI_SLICE 12 ++#define RPI_TILESTART 16 ++#define RPI_TILEEND 20 ++#define RPI_SLICESTART 24 ++#define RPI_MODE 28 ++#define RPI_LEFT0 32 ++#define RPI_LEFT1 36 ++#define RPI_LEFT2 40 ++#define RPI_LEFT3 44 ++#define RPI_QP 48 ++#define RPI_CONTROL 52 ++#define RPI_STATUS 56 ++#define RPI_VERSION 60 ++#define RPI_BFBASE 64 ++#define RPI_BFNUM 68 ++#define RPI_BFCONTROL 72 ++#define RPI_BFSTATUS 76 ++#define RPI_PUWBASE 80 ++#define RPI_PUWSTRIDE 84 ++#define RPI_COEFFWBASE 88 ++#define RPI_COEFFWSTRIDE 92 ++#define RPI_SLICECMDS 96 ++#define RPI_BEGINTILEEND 100 ++#define RPI_TRANSFER 104 ++#define RPI_CFBASE 108 ++#define RPI_CFNUM 112 ++#define RPI_CFSTATUS 116 ++ ++#define RPI_PURBASE 0x8000 ++#define RPI_PURSTRIDE 0x8004 ++#define RPI_COEFFRBASE 0x8008 ++#define RPI_COEFFRSTRIDE 0x800C ++#define RPI_NUMROWS 0x8010 ++#define RPI_CONFIG2 0x8014 ++#define RPI_OUTYBASE 0x8018 ++#define RPI_OUTYSTRIDE 0x801C ++#define RPI_OUTCBASE 0x8020 ++#define RPI_OUTCSTRIDE 0x8024 ++#define RPI_STATUS2 0x8028 ++#define RPI_FRAMESIZE 0x802C ++#define RPI_MVBASE 0x8030 ++#define RPI_MVSTRIDE 0x8034 ++#define RPI_COLBASE 0x8038 ++#define RPI_COLSTRIDE 0x803C ++#define RPI_CURRPOC 0x8040 ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++// Unused but left here to illustrate the diffrences between FFmpegs prob ++// structure and the rpivid one ++ ++struct FFM_PROB { ++ uint8_t sao_merge_flag [ 1]; ++ uint8_t sao_type_idx [ 1]; ++ uint8_t split_coding_unit_flag [ 3]; ++ uint8_t cu_transquant_bypass_flag [ 1]; ++ uint8_t skip_flag [ 3]; ++ uint8_t cu_qp_delta [ 3]; ++ uint8_t pred_mode_flag [ 1]; ++ uint8_t part_mode [ 4]; ++ uint8_t prev_intra_luma_pred_flag [ 1]; ++ uint8_t intra_chroma_pred_mode [ 2]; ++ uint8_t merge_flag [ 1]; ++ uint8_t merge_idx [ 1]; ++ uint8_t inter_pred_idc [ 5]; ++ uint8_t ref_idx_l0 [ 2]; ++ uint8_t ref_idx_l1 [ 2]; ++ uint8_t abs_mvd_greater0_flag [ 2]; ++ uint8_t abs_mvd_greater1_flag [ 2]; ++ uint8_t mvp_lx_flag [ 1]; ++ uint8_t no_residual_data_flag [ 1]; ++ uint8_t split_transform_flag [ 3]; ++ uint8_t cbf_luma [ 2]; ++ uint8_t cbf_cb_cr [ 4]; ++ uint8_t transform_skip_flag/*[][]*/ [ 2]; ++ uint8_t explicit_rdpcm_flag/*[][]*/ [ 2]; ++ uint8_t explicit_rdpcm_dir_flag/*[][]*/ [ 2]; ++ uint8_t last_significant_coeff_x_prefix [18]; ++ uint8_t last_significant_coeff_y_prefix [18]; ++ uint8_t significant_coeff_group_flag [ 4]; ++ uint8_t significant_coeff_flag [44]; ++ uint8_t coeff_abs_level_greater1_flag [24]; ++ uint8_t coeff_abs_level_greater2_flag [ 6]; ++ uint8_t log2_res_scale_abs [ 8]; ++ uint8_t res_scale_sign_flag [ 2]; ++ uint8_t cu_chroma_qp_offset_flag [ 1]; ++ uint8_t cu_chroma_qp_offset_idx [ 1]; ++} __attribute__((packed)); ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++struct RPI_PROB { ++ uint8_t SAO_MERGE_FLAG [ 1]; ++ uint8_t SAO_TYPE_IDX [ 1]; ++ uint8_t SPLIT_FLAG [ 3]; ++ uint8_t CU_SKIP_FLAG [ 3]; ++ uint8_t CU_TRANSQUANT_BYPASS_FLAG [ 1]; ++ uint8_t PRED_MODE [ 1]; ++ uint8_t PART_SIZE [ 4]; ++ uint8_t INTRA_PRED_MODE [ 1]; ++ uint8_t CHROMA_PRED_MODE [ 1]; ++ uint8_t MERGE_FLAG_EXT [ 1]; ++ uint8_t MERGE_IDX_EXT [ 1]; ++ uint8_t INTER_DIR [ 5]; ++ uint8_t REF_PIC [ 2]; ++ uint8_t MVP_IDX [ 1]; ++ uint8_t MVD [ 2]; ++ uint8_t QT_ROOT_CBF [ 1]; ++ uint8_t TRANS_SUBDIV_FLAG [ 3]; ++ uint8_t QT_CBF [ 6]; ++ uint8_t DQP [ 2]; ++ uint8_t ONE_FLAG [24]; ++ uint8_t LASTX [18]; ++ uint8_t LASTY [18]; ++ uint8_t SIG_CG_FLAG [ 4]; ++ uint8_t ABS_FLAG [ 6]; ++ uint8_t TRANSFORMSKIP_FLAG [ 2]; ++ uint8_t SIG_FLAG [42]; ++ uint8_t SIG_FLAG_unused [ 2]; ++} __attribute__((packed)); ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++struct RPI_CMD { ++ uint32_t addr; ++ uint32_t data; ++} __attribute__((packed)); ++ ++struct RPI_BIT { ++ int cmd; ++ const void *ptr; ++ int len; ++}; ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++struct RPI_T; ++ ++// Actual addressability is 38bits but we can only alloc in the bottom 32 ++// currently - when passed to rpivid h/w the address is always >> 6 so will ++// fit in 32 bit there ++// At some point we may weant to make this uint64_t ++typedef uint32_t vid_vc_addr_t; ++ ++typedef enum rpivid_decode_state_e { ++ RPIVID_DECODE_NEW = 0, ++ RPIVID_DECODE_START, ++ RPIVID_DECODE_SLICE, ++ RPIVID_DECODE_END, ++} rpivid_decode_state_t; ++ ++#define RPI_PROB_VALS 154U ++#define RPI_PROB_ARRAY_SIZE ((154 + 3) & ~3) ++ ++typedef struct dec_env_s { ++ const AVCodecContext * avctx; ++ ++ rpivid_decode_state_t state; ++ unsigned int decode_order; ++ ++ int phase_no; // Current phase (i.e. the last one we waited for) ++ struct dec_env_s * phase_wait_q_next; ++ sem_t phase_wait; ++ ++ struct RPI_BIT *bit_fifo; ++ struct RPI_CMD *cmd_fifo; ++ unsigned int bit_len, bit_max; ++ unsigned int cmd_len, cmd_max; ++ unsigned int num_slice_msgs; ++ unsigned int PicWidthInCtbsY; ++ unsigned int PicHeightInCtbsY; ++ unsigned int dpbno_col; ++ uint32_t reg_slicestart; ++ unsigned int wpp_entry_x; ++ unsigned int wpp_entry_y; ++ uint16_t slice_msgs[2*HEVC_MAX_REFS*8+3]; ++ uint8_t scaling_factors[NUM_SCALING_FACTORS]; ++// unsigned int RefPicList[2][HEVC_MAX_REFS]; ++} dec_env_t; ++ ++#define RPIVID_PHASES 3 ++#define RPIVID_PHASE_NEW (RPIVID_PHASES) // Phase before we have inced decode order ++#define RPIVID_PHASE_START (-1) // Phase after we have inced decode_order ++ ++#if OPT_PHASE_TIMING ++static const unsigned int time_thresholds[8] = { ++ 10, 15, 20, 30, 45, 60, 75, 90 ++}; ++#endif ++ ++typedef struct phase_wait_env_s { ++ unsigned int last_order; ++ dec_env_t * q; ++#if OPT_PHASE_TIMING ++ uint64_t phase_time; ++ uint64_t max_phase_time; ++ uint64_t time_in_phase; ++ uint64_t time_out_phase; ++ unsigned int max_time_decode_order; ++ unsigned int time_bins[9]; ++ unsigned int time_bins3[9]; ++ unsigned int time_bins5[9]; ++ uint64_t time_stash[16]; ++ unsigned int i3; ++#endif ++} phase_wait_env_t; // Single linked list of threads waiting for this phase ++ ++typedef struct RPI_T { ++ atomic_int ref_count; ++ sem_t ref_zero; ++ ++ dec_env_t ** dec_envs; ++ AVZcEnvPtr zc; ++ ++ pthread_mutex_t phase_lock; ++ phase_wait_env_t phase_reqs[RPIVID_PHASES]; ++ ++ volatile uint32_t * regs; ++ volatile uint32_t * ints; ++ ++ GPU_MEM_PTR_T gcolbuf; ++ unsigned int col_stride; ++ size_t col_picsize; ++ ++ unsigned int bitbuf_no; ++ sem_t bitbuf_sem; ++ GPU_MEM_PTR_T gbitbufs[RPIVID_BITBUFS]; ++ ++ unsigned int max_pu_msgs; ++ unsigned int coeffbuf_no; ++ sem_t coeffbuf_sem; ++ GPU_MEM_PTR_T gcoeffbufs[RPIVID_COEFFBUFS]; ++ ++ unsigned int decode_order; ++ int mbox_fd; ++ int gpu_init_type; ++} RPI_T; ++ ++#if OPT_PHASE_TIMING ++static uint64_t tus64(void) ++{ ++ struct timespec ts; ++ clock_gettime(CLOCK_MONOTONIC, &ts); ++ return (uint64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; ++} ++#endif ++ ++static inline unsigned int rnd64(unsigned int x) ++{ ++ return (x + 63) & ~63; ++} ++ ++static inline int rpi_sem_wait(sem_t * const sem) ++{ ++ int rv; ++ while ((rv = sem_wait(sem)) != 0 && errno == EINTR) ++ /* Loop */; ++ return rv; ++} ++ ++//============================================================================ ++ ++#define TRACE_DEV 0 ++#define TRACE_ENTRY 0 ++ ++#define REGS_NAME "/dev/rpivid-hevcmem" ++#define REGS_SIZE 0x10000 ++#define INTS_NAME "/dev/rpivid-intcmem" ++#define INTS_SIZE 0x10000 // 4 is probably enough but we are going to alloc a page anyway ++ ++static volatile uint32_t * map_dev(AVCodecContext * const avctx, const char * const dev_name, size_t size) ++{ ++ void *gpio_map; ++ int mem_fd; ++ ++ /* open /dev/mem */ ++ if ((mem_fd = open(dev_name, O_RDWR|O_SYNC) ) < 0) { ++ av_log(avctx, AV_LOG_WARNING, "can't open %s\n", dev_name); ++ return NULL; ++ } ++ ++ // Now map it ++ gpio_map = mmap( ++ NULL, ++ size, ++ PROT_READ|PROT_WRITE, ++ MAP_SHARED, ++ mem_fd, ++ 0 ++ ); ++ ++ close(mem_fd); // No longer need the FD ++ ++ if (gpio_map == MAP_FAILED) { ++ av_log(avctx, AV_LOG_WARNING, "GPIO mapping failed"); ++ return NULL; ++ } ++ ++ return (volatile uint32_t *)gpio_map; ++} ++ ++static void unmap_devp(volatile uint32_t ** const p_gpio_map, size_t size) ++{ ++ volatile uint32_t * const gpio_map = *p_gpio_map; ++ if (gpio_map != NULL) { ++ *p_gpio_map = NULL; ++ munmap((void *)gpio_map, size); ++ } ++} ++ ++#define MANGLE(x) ((x) &~0xc0000000) // ** If x is ever a 64 bit thing this will need fixing! ++#define MANGLE64(x) (uint32_t)(MANGLE(x)>>6) ++ ++static inline void apb_write_vc_addr(const RPI_T *const rpi, const uint32_t addr, const vid_vc_addr_t data) ++{ ++ rpi->regs[addr >> 2] = MANGLE64(data); ++} ++ ++static inline void apb_write_vc_len(const RPI_T *const rpi, const uint32_t addr, const unsigned int data) ++{ ++ rpi->regs[addr >> 2] = data >> 6; // ?? rnd64 - but not currently needed ++} ++ ++static inline void apb_write(const RPI_T * const rpi, const uint32_t addr, const uint32_t data) ++{ ++#if TRACE_DEV ++ printf("W %x %08x\n", addr, data); ++#endif ++ ++ rpi->regs[addr >> 2] = data; ++} ++ ++static inline uint32_t apb_read(const RPI_T * const rpi, const uint32_t addr) ++{ ++ const uint32_t v = rpi->regs[addr >> 2]; ++#if TRACE_DEV ++ printf("R %x (=%x)\n", addr, v); ++#endif ++ return v; ++} ++ ++#define ARG_IC_ICTRL_ACTIVE1_INT_SET 0x00000001 ++#define ARG_IC_ICTRL_ACTIVE1_EDGE_SET 0x00000002 ++#define ARG_IC_ICTRL_ACTIVE1_EN_SET 0x00000004 ++#define ARG_IC_ICTRL_ACTIVE1_STATUS_SET 0x00000008 ++#define ARG_IC_ICTRL_ACTIVE2_INT_SET 0x00000010 ++#define ARG_IC_ICTRL_ACTIVE2_EDGE_SET 0x00000020 ++#define ARG_IC_ICTRL_ACTIVE2_EN_SET 0x00000040 ++#define ARG_IC_ICTRL_ACTIVE2_STATUS_SET 0x00000080 ++ ++static inline void int_wait(const RPI_T * const rpi, const unsigned int phase) ++{ ++ const uint32_t mask_reset = phase == 1 ? ~ARG_IC_ICTRL_ACTIVE2_INT_SET : ~ARG_IC_ICTRL_ACTIVE1_INT_SET; ++ const uint32_t mask_done = phase == 1 ? ARG_IC_ICTRL_ACTIVE1_INT_SET : ARG_IC_ICTRL_ACTIVE2_INT_SET; ++ uint32_t ival; ++ while (((ival = rpi->ints[0]) & mask_done) == 0) { ++ usleep(1000); ++ } ++ rpi->ints[0] = ival & mask_reset; ++} ++ ++#if TRACE_DEV ++static void apb_dump_regs(const RPI_T * const rpi, uint16_t addr, int num) { ++ int i; ++ ++ for (i=0; iregs[(addr>>2)+i]); ++ ++ if ((i%4)==3 || i+1 == num) ++ printf("\n"); ++ else ++ printf(" "); ++ } ++} ++ ++static void axi_dump(const dec_env_t * const de, uint64_t addr, uint32_t size) { ++ int i; ++ ++ for (i=0; i>2; i++) ++ { ++ if ((i%4)==0) ++ printf("%08x: ", MANGLE(de->gbuf.vc) + (uint32_t)addr + 4*i); ++ ++ printf("%08x", ((uint32_t*)de->gbuf.arm)[(addr>>2)+i]); ++ ++ if ((i%4)==3 || i+1 == size>>2) ++ printf("\n"); ++ else ++ printf(" "); ++ } ++} ++#endif ++ ++ ++////////////////////////////////////////////////////////////////////////////// ++// Scaling factors ++ ++static void expand_scaling_list( ++ const unsigned int sizeID, ++ const unsigned int matrixID, ++ uint8_t * const dst0, ++ const uint8_t * const src0, ++ uint8_t dc) ++{ ++ switch (sizeID) { ++ case 0: ++ memcpy(dst0, src0, 16); ++ break; ++ case 1: ++ memcpy(dst0, src0, 64); ++ break; ++ case 2: ++ { ++ uint8_t * d = dst0; ++ for (unsigned int y=0; y != 16; y++) { ++ const uint8_t * s = src0 + (y >> 1) * 8; ++ for (unsigned int x = 0; x != 8; ++x) { ++ *d++ = *s; ++ *d++ = *s++; ++ } ++ } ++ dst0[0] = dc; ++ break; ++ } ++ default: ++ { ++ uint8_t * d = dst0; ++ for (unsigned int y=0; y != 32; y++) { ++ const uint8_t * s = src0 + (y >> 2) * 8; ++ for (unsigned int x = 0; x != 8; ++x) { ++ *d++ = *s; ++ *d++ = *s; ++ *d++ = *s; ++ *d++ = *s++; ++ } ++ } ++ dst0[0] = dc; ++ break; ++ } ++ } ++} ++ ++static void populate_scaling_factors(dec_env_t * const de, const HEVCContext * const s) { ++ // Array of constants for scaling factors ++ static const uint32_t scaling_factor_offsets[4][6] = { ++ // MID0 MID1 MID2 MID3 MID4 MID5 ++ {0x0000, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050}, // SID0 (4x4) ++ {0x0060, 0x00A0, 0x00E0, 0x0120, 0x0160, 0x01A0}, // SID1 (8x8) ++ {0x01E0, 0x02E0, 0x03E0, 0x04E0, 0x05E0, 0x06E0}, // SID2 (16x16) ++ {0x07E0, 0, 0, 0x0BE0, 0, 0}}; // SID3 (32x32) ++ ++ // ffmpeg places SID3,MID1 where matrixID 3 normally is ++ const ScalingList * const sl = ++ s->ps.pps->scaling_list_data_present_flag ? &s->ps.pps->scaling_list ++ : &s->ps.sps->scaling_list; ++ unsigned int mid; ++ ++ for (mid=0; mid<6; mid++) ++ expand_scaling_list(0, mid, ++ de->scaling_factors + scaling_factor_offsets[0][mid], ++ sl->sl[0][mid], 0); ++ for (mid=0; mid<6; mid++) ++ expand_scaling_list(1, mid, ++ de->scaling_factors + scaling_factor_offsets[1][mid], ++ sl->sl[1][mid], 0); ++ for (mid=0; mid<6; mid++) ++ expand_scaling_list(2, mid, ++ de->scaling_factors + scaling_factor_offsets[2][mid], ++ sl->sl[2][mid], ++ sl->sl_dc[0][mid]); ++ // second scaling matrix for 32x32 is at matrixID 3 not 1 in ffmpeg ++ for (mid=0; mid<6; mid += 3) ++ expand_scaling_list(3, mid, ++ de->scaling_factors + scaling_factor_offsets[3][mid], ++ sl->sl[3][mid], ++ sl->sl_dc[1][mid]); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Probabilities ++ ++static const uint8_t prob_init[3][156] = { ++ { ++ 153, 200, 139, 141, 157, 154, 154, 154, ++ 154, 154, 184, 154, 154, 154, 184, 63, ++ 154, 154, 154, 154, 154, 154, 154, 154, ++ 154, 154, 154, 154, 154, 153, 138, 138, ++ 111, 141, 94, 138, 182, 154, 154, 154, ++ 140, 92, 137, 138, 140, 152, 138, 139, ++ 153, 74, 149, 92, 139, 107, 122, 152, ++ 140, 179, 166, 182, 140, 227, 122, 197, ++ 110, 110, 124, 125, 140, 153, 125, 127, ++ 140, 109, 111, 143, 127, 111, 79, 108, ++ 123, 63, 110, 110, 124, 125, 140, 153, ++ 125, 127, 140, 109, 111, 143, 127, 111, ++ 79, 108, 123, 63, 91, 171, 134, 141, ++ 138, 153, 136, 167, 152, 152, 139, 139, ++ 111, 111, 125, 110, 110, 94, 124, 108, ++ 124, 107, 125, 141, 179, 153, 125, 107, ++ 125, 141, 179, 153, 125, 107, 125, 141, ++ 179, 153, 125, 140, 139, 182, 182, 152, ++ 136, 152, 136, 153, 136, 139, 111, 136, ++ 139, 111, 0, 0, }, ++ { ++ 153, 185, 107, 139, 126, 197, 185, 201, ++ 154, 149, 154, 139, 154, 154, 154, 152, ++ 110, 122, 95, 79, 63, 31, 31, 153, ++ 153, 168, 140, 198, 79, 124, 138, 94, ++ 153, 111, 149, 107, 167, 154, 154, 154, ++ 154, 196, 196, 167, 154, 152, 167, 182, ++ 182, 134, 149, 136, 153, 121, 136, 137, ++ 169, 194, 166, 167, 154, 167, 137, 182, ++ 125, 110, 94, 110, 95, 79, 125, 111, ++ 110, 78, 110, 111, 111, 95, 94, 108, ++ 123, 108, 125, 110, 94, 110, 95, 79, ++ 125, 111, 110, 78, 110, 111, 111, 95, ++ 94, 108, 123, 108, 121, 140, 61, 154, ++ 107, 167, 91, 122, 107, 167, 139, 139, ++ 155, 154, 139, 153, 139, 123, 123, 63, ++ 153, 166, 183, 140, 136, 153, 154, 166, ++ 183, 140, 136, 153, 154, 166, 183, 140, ++ 136, 153, 154, 170, 153, 123, 123, 107, ++ 121, 107, 121, 167, 151, 183, 140, 151, ++ 183, 140, 0, 0, }, ++ { ++ 153, 160, 107, 139, 126, 197, 185, 201, ++ 154, 134, 154, 139, 154, 154, 183, 152, ++ 154, 137, 95, 79, 63, 31, 31, 153, ++ 153, 168, 169, 198, 79, 224, 167, 122, ++ 153, 111, 149, 92, 167, 154, 154, 154, ++ 154, 196, 167, 167, 154, 152, 167, 182, ++ 182, 134, 149, 136, 153, 121, 136, 122, ++ 169, 208, 166, 167, 154, 152, 167, 182, ++ 125, 110, 124, 110, 95, 94, 125, 111, ++ 111, 79, 125, 126, 111, 111, 79, 108, ++ 123, 93, 125, 110, 124, 110, 95, 94, ++ 125, 111, 111, 79, 125, 126, 111, 111, ++ 79, 108, 123, 93, 121, 140, 61, 154, ++ 107, 167, 91, 107, 107, 167, 139, 139, ++ 170, 154, 139, 153, 139, 123, 123, 63, ++ 124, 166, 183, 140, 136, 153, 154, 166, ++ 183, 140, 136, 153, 154, 166, 183, 140, ++ 136, 153, 154, 170, 153, 138, 138, 122, ++ 121, 122, 121, 167, 151, 183, 140, 151, ++ 183, 140, 0, 0, }, ++}; ++ ++ ++////////////////////////////////////////////////////////////////////////////// ++// Phase 1 command and bit FIFOs ++ ++// ???? uint16_t addr - put in uint32_t ++static int p1_apb_write(dec_env_t * const de, const uint16_t addr, const uint32_t data) { ++ if (de->cmd_len==de->cmd_max) ++ av_assert0(de->cmd_fifo = realloc(de->cmd_fifo, (de->cmd_max*=2)*sizeof(struct RPI_CMD))); ++ de->cmd_fifo[de->cmd_len].addr = addr; ++ de->cmd_fifo[de->cmd_len].data = data; ++ return de->cmd_len++; ++} ++ ++static void p1_axi_write(dec_env_t * const de, const uint32_t len, const void * const ptr, const int cmd_idx) { ++ if (de->bit_len==de->bit_max) ++ av_assert0(de->bit_fifo = realloc(de->bit_fifo, (de->bit_max*=2)*sizeof(struct RPI_BIT))); ++ de->bit_fifo[de->bit_len].cmd = cmd_idx; ++ de->bit_fifo[de->bit_len].ptr = ptr; ++ de->bit_fifo[de->bit_len].len = len; ++ de->bit_len++; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Write probability and scaling factor memories ++ ++#if 0 ++static void WriteProb(dec_env_t * const de) { ++ int i; ++ const uint8_t *p = (uint8_t *) &de->probabilities; ++ for (i=0; ish.cabac_init_flag && s->sh.slice_type != HEVC_SLICE_I) ? ++ s->sh.slice_type + 1 : 2 - s->sh.slice_type; ++ const uint8_t * p = prob_init[init_type]; ++ const int q = av_clip(s->sh.slice_qp, 0, 51); ++ unsigned int i; ++ ++ for (i = 0; i < RPI_PROB_VALS; i++) { ++ int init_value = p[i]; ++ int m = (init_value >> 4) * 5 - 45; ++ int n = ((init_value & 15) << 3) - 16; ++ int pre = 2 * (((m * q) >> 4) + n) - 127; ++ ++ pre ^= pre >> 31; ++ if (pre > 124) ++ pre = 124 + (pre & 1); ++ dst[i] = pre; ++ } ++ for (i = RPI_PROB_VALS; i != RPI_PROB_ARRAY_SIZE; ++i) { ++ dst[i] = 0; ++ } ++ ++ for (i=0; i < RPI_PROB_ARRAY_SIZE; i+=4) ++ p1_apb_write(de, 0x1000+i, dst[i] + (dst[i+1]<<8) + (dst[i+2]<<16) + (dst[i+3]<<24)); ++ ++} ++ ++ ++static void WriteScalingFactors(dec_env_t * const de) { ++ int i; ++ const uint8_t *p = (uint8_t *) de->scaling_factors; ++ for (i=0; i= bd[i]; i++); // bd[] has num+1 elements; bd[0]=0; see hevc_ps.c ++ return i-1; ++} ++ ++static int ctb_to_slice_w_h (unsigned int ctb, int ctb_size, int width, unsigned int *bd, int num) { ++ if (ctb < bd[num-1]) return ctb_size; ++ else if (width % ctb_size) return width % ctb_size; ++ else return ctb_size; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Handle PU and COEFF stream overflow ++ ++ ++// Returns: ++// -2 Other error ++// -1 Out of coeff space ++// 0 OK ++// 1 Out of PU space ++ ++static int check_status(const RPI_T * const rpi, dec_env_t * const de) { ++ uint32_t status; ++ ++ // this is the definition of successful completion of phase 1 ++ // it assures that status register is zero and all blocks in each tile have completed ++ if (apb_read(rpi, RPI_CFSTATUS) == apb_read(rpi, RPI_CFNUM)) ++ return 0; ++ ++ status = apb_read(rpi, RPI_STATUS); ++ ++ if ((status & 8) != 0) ++ return -1; ++ ++ if ((status & 0x10) != 0) ++ return 1; ++ ++ return -2; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Write STATUS register with expected end CTU address of previous slice ++ ++static void end_previous_slice(dec_env_t * const de, const HEVCContext * const s, const int ctb_addr_ts) { ++ const HEVCPPS * const pps = s->ps.pps; ++ int last_x = pps->ctb_addr_ts_to_rs[ctb_addr_ts-1] % de->PicWidthInCtbsY; ++ int last_y = pps->ctb_addr_ts_to_rs[ctb_addr_ts-1] / de->PicWidthInCtbsY; ++ p1_apb_write(de, RPI_STATUS, 1 + (last_x<<5) + (last_y<<18)); ++} ++ ++static void wpp_pause(dec_env_t * const de, int ctb_row) { ++ p1_apb_write(de, RPI_STATUS, (ctb_row<<18) + 0x25); ++ p1_apb_write(de, RPI_TRANSFER, PROB_BACKUP); ++ p1_apb_write(de, RPI_MODE, ctb_row==de->PicHeightInCtbsY-1 ? 0x70000 : 0x30000); ++ p1_apb_write(de, RPI_CONTROL, (ctb_row<<16) + 2); ++} ++ ++static void wpp_end_previous_slice(dec_env_t * const de, const HEVCContext * const s, int ctb_addr_ts) { ++ const HEVCPPS *pps = s->ps.pps; ++ int new_x = s->sh.slice_ctb_addr_rs % de->PicWidthInCtbsY; ++ int new_y = s->sh.slice_ctb_addr_rs / de->PicWidthInCtbsY; ++ int last_x = pps->ctb_addr_ts_to_rs[ctb_addr_ts-1] % de->PicWidthInCtbsY; ++ int last_y = pps->ctb_addr_ts_to_rs[ctb_addr_ts-1] / de->PicWidthInCtbsY; ++ if (de->wpp_entry_x<2 && (de->wpp_entry_y2) && de->PicWidthInCtbsY>2) ++ wpp_pause(de, last_y); ++ p1_apb_write(de, RPI_STATUS, 1 + (last_x<<5) + (last_y<<18)); ++ if (new_x==2 || de->PicWidthInCtbsY==2 && de->wpp_entry_yps.sps; ++ const HEVCPPS *pps = s->ps.pps; ++ ++ p1_apb_write(de, RPI_SPS0, ++ (sps->log2_min_cb_size << 0) + ++ (sps->log2_ctb_size << 4) + ++ (sps->log2_min_tb_size << 8) + ++ (sps->log2_max_trafo_size << 12) + ++ (sps->bit_depth << 16) + ++ (sps->bit_depth << 20) + ++ (sps->max_transform_hierarchy_depth_intra << 24) + ++ (sps->max_transform_hierarchy_depth_inter << 28)); ++ ++ p1_apb_write(de, RPI_SPS1, ++ (sps->pcm.bit_depth << 0) + ++ (sps->pcm.bit_depth_chroma << 4) + ++ (sps->pcm.log2_min_pcm_cb_size << 8) + ++ (sps->pcm.log2_max_pcm_cb_size << 12) + ++ (sps->separate_colour_plane_flag? 0:sps->chroma_format_idc << 16) + ++ (sps->amp_enabled_flag << 18) + ++ (sps->pcm_enabled_flag << 19) + ++ (sps->scaling_list_enable_flag << 20) + ++ (sps->sps_strong_intra_smoothing_enable_flag << 21)); ++ ++ p1_apb_write(de, RPI_PPS, ++ (sps->log2_ctb_size - pps->diff_cu_qp_delta_depth << 0) + ++ (pps->cu_qp_delta_enabled_flag << 4) + ++ (pps->transquant_bypass_enable_flag << 5) + ++ (pps->transform_skip_enabled_flag << 6) + ++ (pps->sign_data_hiding_flag << 7) + ++ (((pps->cb_qp_offset + s->sh.slice_cb_qp_offset)&255) << 8) + ++ (((pps->cr_qp_offset + s->sh.slice_cr_qp_offset)&255) << 16) + ++ (pps->constrained_intra_pred_flag << 24)); ++ ++ if (s->ps.sps->scaling_list_enable_flag) WriteScalingFactors(de); ++ ++ if (!s->sh.dependent_slice_segment_flag) { ++ int ctb_col = s->sh.slice_ctb_addr_rs % de->PicWidthInCtbsY; ++ int ctb_row = s->sh.slice_ctb_addr_rs / de->PicWidthInCtbsY; ++ de->reg_slicestart = (ctb_col<<0) + (ctb_row<<16); ++ } ++ ++ p1_apb_write(de, RPI_SLICESTART, de->reg_slicestart); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static void write_slice(dec_env_t * const de, const HEVCContext * const s, ++ const unsigned int slice_w, const unsigned int slice_h) { ++ uint32_t u32 = ++ (s->sh.slice_type << 12) ++ + (s->sh.slice_sample_adaptive_offset_flag[0] << 14) ++ + (s->sh.slice_sample_adaptive_offset_flag[1] << 15) ++ + (slice_w << 17) ++ + (slice_h << 24); ++ ++ if (s->sh.slice_type==HEVC_SLICE_B || s->sh.slice_type==HEVC_SLICE_P) u32 |= ++ (s->sh.max_num_merge_cand << 0) ++ + (s->sh.nb_refs[L0] << 4) ++ + (s->sh.nb_refs[L1] << 8); ++ ++ if (s->sh.slice_type==HEVC_SLICE_B) ++ u32 |= s->sh.mvd_l1_zero_flag<<16; ++ p1_apb_write(de, RPI_SLICE, u32); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Wavefront mode ++ ++static void wpp_entry_point(dec_env_t * const de, const HEVCContext * const s, ++ const int do_bte, const int resetQPY, const int ctb_addr_ts) { ++ const HEVCSPS * const sps = s->ps.sps; ++ const HEVCPPS * const pps = s->ps.pps; ++ ++ int ctb_size = 1<log2_ctb_size; ++ int ctb_addr_rs = pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ ++ int ctb_col = de->wpp_entry_x = ctb_addr_rs % de->PicWidthInCtbsY; ++ int ctb_row = de->wpp_entry_y = ctb_addr_rs / de->PicWidthInCtbsY; ++ ++ int endx = de->PicWidthInCtbsY-1; ++ int endy = ctb_row; ++ ++ uint8_t slice_w = ctb_to_slice_w_h(ctb_col, ctb_size, sps->width, pps->col_bd, pps->num_tile_columns); ++ uint8_t slice_h = ctb_to_slice_w_h(ctb_row, ctb_size, sps->height, pps->row_bd, pps->num_tile_rows); ++ ++ p1_apb_write(de, RPI_TILESTART, 0); ++ p1_apb_write(de, RPI_TILEEND, endx + (endy<<16)); ++ ++ if (do_bte) ++ p1_apb_write(de, RPI_BEGINTILEEND, endx + (endy<<16)); ++ ++ write_slice(de, s, slice_w, ctb_row==de->PicHeightInCtbsY-1? slice_h : ctb_size); ++ ++ if (resetQPY) p1_apb_write(de, RPI_QP, sps->qp_bd_offset + s->sh.slice_qp); ++ ++ p1_apb_write(de, RPI_MODE, ctb_row==de->PicHeightInCtbsY-1? 0x60001 : 0x20001); ++ p1_apb_write(de, RPI_CONTROL, (ctb_col<<0) + (ctb_row<<16)); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Tiles mode ++ ++static void new_entry_point(dec_env_t * const de, const HEVCContext * const s, ++ const int do_bte, const int resetQPY, const int ctb_addr_ts) { ++ const HEVCSPS * const sps = s->ps.sps; ++ const HEVCPPS * const pps = s->ps.pps; ++ ++ int ctb_col = pps->ctb_addr_ts_to_rs[ctb_addr_ts] % de->PicWidthInCtbsY; ++ int ctb_row = pps->ctb_addr_ts_to_rs[ctb_addr_ts] / de->PicWidthInCtbsY; ++ ++ int tile_x = ctb_to_tile (ctb_col, pps->col_bd, pps->num_tile_columns); ++ int tile_y = ctb_to_tile (ctb_row, pps->row_bd, pps->num_tile_rows); ++ ++ int endx = pps->col_bd[tile_x+1] - 1; ++ int endy = pps->row_bd[tile_y+1] - 1; ++ ++ uint8_t slice_w = ctb_to_slice_w_h(ctb_col, 1<log2_ctb_size, sps->width, pps->col_bd, pps->num_tile_columns); ++ uint8_t slice_h = ctb_to_slice_w_h(ctb_row, 1<log2_ctb_size, sps->height, pps->row_bd, pps->num_tile_rows); ++ ++ p1_apb_write(de, RPI_TILESTART, pps->col_bd[tile_x] + (pps->row_bd[tile_y]<<16)); ++ p1_apb_write(de, RPI_TILEEND, endx + (endy<<16)); ++ ++ if (do_bte) ++ p1_apb_write(de, RPI_BEGINTILEEND, endx + (endy<<16)); ++ ++ write_slice(de, s, slice_w, slice_h); ++ ++ if (resetQPY) ++ p1_apb_write(de, RPI_QP, sps->qp_bd_offset + s->sh.slice_qp); ++ ++ p1_apb_write(de, RPI_MODE, (0xFFFF << 0) ++ + (0x0 << 16) ++ + ((tile_x==pps->num_tile_columns-1) << 17) ++ + ((tile_y==pps->num_tile_rows-1) << 18)); ++ ++ p1_apb_write(de, RPI_CONTROL, (ctb_col<<0) + (ctb_row<<16)); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++// Doesn't attempt to remove from context as we should only do this at the end ++// of time or on create error ++static void ++dec_env_delete(dec_env_t * const de) ++{ ++// gpu_free(&de->gbuf); ++ ++ av_freep(&de->cmd_fifo); ++ av_freep(&de->bit_fifo); ++ ++ sem_destroy(&de->phase_wait); ++ av_free(de); ++} ++ ++static dec_env_t * ++dec_env_new(AVCodecContext * const avctx, RPI_T * const rpi) ++{ ++ dec_env_t * const de = av_mallocz(sizeof(*de)); ++ int i; ++ ++ if (de == NULL) ++ return NULL; ++ ++ de->avctx = avctx; ++ de->phase_no = RPIVID_PHASE_NEW; ++ ++ sem_init(&de->phase_wait, 0, 0); ++ ++ if ((de->cmd_fifo = malloc((de->cmd_max=1024)*sizeof(struct RPI_CMD))) == NULL) ++ goto fail; ++ ++ if ((de->bit_fifo = malloc((de->bit_max=1024)*sizeof(struct RPI_BIT))) == NULL) ++ goto fail; ++ ++ pthread_mutex_lock(&rpi->phase_lock); // Abuse - not worth creating a lock just for this ++ for (i = 0; i != avctx->thread_count; ++i) { ++ if (rpi->dec_envs[i] == NULL) ++ { ++ rpi->dec_envs[i] = de; ++ break; ++ } ++ } ++ pthread_mutex_unlock(&rpi->phase_lock); ++ ++ if (i == avctx->thread_count) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to find a slot for hw thread context\n"); ++ goto fail; ++ } ++ ++ return de; ++ ++fail: ++ dec_env_delete(de); ++ return NULL; ++} ++ ++ ++static dec_env_t * ++dec_env_get(AVCodecContext * const avctx, RPI_T * const rpi) ++{ ++ dec_env_t * de = NULL; ++ const int ref_count = atomic_fetch_add(&rpi->ref_count, 1); ++ ++ if (ref_count <= 0) { ++ // Already dead ++ av_log(avctx, AV_LOG_ERROR, "RPIVID called whilst dead\n");; ++ return NULL; ++ } ++ ++ for (int i = 0; i != avctx->thread_count; ++i) { ++ if (rpi->dec_envs[i] == NULL) ++ { ++ de = dec_env_new(avctx, rpi); ++ break; ++ } ++ if (rpi->dec_envs[i]->avctx == avctx) ++ { ++ de = rpi->dec_envs[i]; ++ break; ++ } ++ } ++ return de; ++} ++ ++// Call at end of fn ++// Used to ensure we aren't in a worker thead when killed ++static void ++dec_env_release(RPI_T * const rpi, dec_env_t * const de) ++{ ++ const int n = atomic_fetch_sub(&rpi->ref_count, 1); ++ if (n == 1) { ++ sem_post(&rpi->ref_zero); ++ } ++} ++ ++//---------------------------------------------------------------------------- ++ ++// Wait for a slot in the given phase ++// Any error return is probably fatal ++static int ++wait_phase(RPI_T * const rpi, dec_env_t * const de, const int phase_no) ++{ ++ int needs_wait = 0; ++ phase_wait_env_t *const p = rpi->phase_reqs + phase_no; ++ ++ pthread_mutex_lock(&rpi->phase_lock); ++ if (p->last_order + 1 != de->decode_order) { ++ de->phase_wait_q_next = p->q; ++ p->q = de; ++ needs_wait = 1; ++ } ++ pthread_mutex_unlock(&rpi->phase_lock); ++ ++ if (needs_wait) { ++ while (sem_wait(&de->phase_wait) == -1) ++ { ++ int err; ++ if ((err = errno) != EINTR) ++ return AVERROR(err); ++ } ++ } ++ ++ de->phase_no = phase_no; ++ return 0; ++} ++ ++static void ++post_phase(RPI_T * const rpi, dec_env_t * const de, const int phase_no) ++{ ++ dec_env_t * next_de = NULL; ++ phase_wait_env_t *const p = rpi->phase_reqs + phase_no; ++ dec_env_t ** q = &p->q; ++ ++ pthread_mutex_lock(&rpi->phase_lock); ++ ++ p->last_order = de->decode_order; ++ while (*q != NULL) { ++ dec_env_t * const t_de = *q; ++ ++ if (t_de->decode_order == p->last_order + 1) { ++ // This is us - remove from Q ++ *q = t_de->phase_wait_q_next; ++ t_de->phase_wait_q_next = NULL; // Tidy ++ next_de = t_de; ++ break; ++ } ++ q = &t_de->phase_wait_q_next; ++ } ++ ++ pthread_mutex_unlock(&rpi->phase_lock); ++ ++ if (next_de != NULL) ++ sem_post(&next_de->phase_wait); ++} ++ ++// Wait & signal stuff s.t. threads in other phases can continue ++static void ++abort_phases(RPI_T * const rpi, dec_env_t * const de) ++{ ++ for (int i = de->phase_no + 1; i < RPIVID_PHASE_NEW; ++i) { ++ wait_phase(rpi, de, i); ++ post_phase(rpi, de, i); ++ } ++ de->phase_no = RPIVID_PHASE_NEW; ++} ++ ++// Start timing for phase ++// Stats only - no actual effect ++static inline void tstart_phase(RPI_T * const rpi, const int phase_no) ++{ ++#if OPT_PHASE_TIMING ++ phase_wait_env_t *const p = rpi->phase_reqs + phase_no; ++ const int64_t now = tus64(); ++ if (p->phase_time != 0) ++ p->time_out_phase += now - p->phase_time; ++ p->phase_time = now; ++#endif ++} ++ ++#if OPT_PHASE_TIMING ++static unsigned int tavg_bin_phase(phase_wait_env_t *const p, const unsigned int avg_n) ++{ ++ uint64_t tsum = 0; ++ unsigned int i; ++ for (i = 0; i != avg_n; ++i) ++ tsum += p->time_stash[(p->i3 - i) & 15]; ++ for (i = 0; i != 9; ++i) { ++ if (time_thresholds[i] * 1000 * avg_n > tsum) ++ break; ++ } ++ return i; ++} ++#endif ++ ++// End timing for phase ++// Stats only - no actual effect ++static inline void tend_phase(RPI_T * const rpi, const int phase_no) ++{ ++#if OPT_PHASE_TIMING ++ phase_wait_env_t *const p = rpi->phase_reqs + phase_no; ++ const uint64_t now = tus64(); ++ const uint64_t in_time = now - p->phase_time; ++ ++ p->time_in_phase += in_time; ++ p->phase_time = now; ++ p->time_stash[p->i3] = in_time; ++ if (in_time > p->max_phase_time) { ++ p->max_phase_time = in_time; ++ p->max_time_decode_order = p->last_order; ++ } ++ ++p->time_bins[tavg_bin_phase(p, 1)]; ++ ++p->time_bins3[tavg_bin_phase(p, 3)]; ++ ++p->time_bins5[tavg_bin_phase(p, 5)]; ++ ++ p->i3 = (p->i3 + 1) & 15; ++#endif ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Start frame ++ ++static int rpi_hevc_start_frame( ++ AVCodecContext * avctx, ++ const uint8_t *buffer, ++ uint32_t size) { ++ ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ dec_env_t * const de = dec_env_get(avctx, rpi); ++ const HEVCContext * const s = avctx->priv_data; ++ const HEVCSPS * const sps = s->ps.sps; ++ const unsigned int CtbSizeY = 1U << sps->log2_ctb_size; ++ ++#if TRACE_ENTRY ++ printf("<<< %s[%p]\n", __func__, de); ++#endif ++ ++ if (de == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Cannot find find context for thread\n", __func__); ++ return -1; ++ } ++ ++ de->phase_no = RPIVID_PHASE_START; ++ de->decode_order = ++rpi->decode_order; // *** atomic? ++ ++ ff_thread_finish_setup(avctx); // Allow next thread to enter rpi_hevc_start_frame ++ ++ if (de->state != RPIVID_DECODE_NEW && de->state != RPIVID_DECODE_END) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected state transition: %d", __func__, de->state); ++ return -1; ++ } ++ de->state = RPIVID_DECODE_START; ++ ++ de->PicWidthInCtbsY = (sps->width + CtbSizeY - 1) / CtbSizeY; //7-15 ++ de->PicHeightInCtbsY = (sps->height + CtbSizeY - 1) / CtbSizeY; //7-17 ++ de->bit_len = 0; ++ de->cmd_len = 0; ++ ++#if TRACE_ENTRY ++ printf(">>> %s[%p]\n", __func__, de); ++#endif ++ ++ dec_env_release(rpi, de); ++ return 0; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Slice messages ++ ++static void msg_slice(dec_env_t * const de, const uint16_t msg) { ++ de->slice_msgs[de->num_slice_msgs++] = msg; ++} ++ ++static void program_slicecmds(dec_env_t * const de, const int sliceid) { ++ int i; ++ p1_apb_write(de, RPI_SLICECMDS, de->num_slice_msgs+(sliceid<<8)); ++ for(i=0; i < de->num_slice_msgs; i++) { ++ p1_apb_write(de, 0x4000+4*i, de->slice_msgs[i] & 0xffff); ++ } ++} ++ ++static void pre_slice_decode(dec_env_t * const de, const HEVCContext * const s) { ++ const HEVCSPS * const sps = s->ps.sps; ++ const HEVCPPS * const pps = s->ps.pps; ++ const SliceHeader *sh = &s->sh; ++ ++ int weightedPredFlag, i, rIdx; ++ uint16_t cmd_slice; ++ unsigned int collocated_from_l0_flag; ++ ++ de->num_slice_msgs=0; ++ de->dpbno_col = 0; ++ cmd_slice = 0; ++ if (sh->slice_type==HEVC_SLICE_I) cmd_slice = 1; ++ if (sh->slice_type==HEVC_SLICE_P) cmd_slice = 2; ++ if (sh->slice_type==HEVC_SLICE_B) cmd_slice = 3; ++ ++ if (sh->slice_type!=HEVC_SLICE_I) { ++ cmd_slice += sh->nb_refs[L0]<<2; ++ cmd_slice += sh->nb_refs[L1]<<6; ++ } ++ ++ if (sh->slice_type==HEVC_SLICE_P || sh->slice_type==HEVC_SLICE_B) ++ cmd_slice |= sh->max_num_merge_cand<<11; ++ ++ collocated_from_l0_flag = ++ !sh->slice_temporal_mvp_enabled_flag ? ++ 0 : ++ sh->slice_type == HEVC_SLICE_B ? ++ (sh->collocated_list == L0) : ++ (sh->slice_type==HEVC_SLICE_P); ++ cmd_slice |= collocated_from_l0_flag<<14; ++ ++ if (sh->slice_type==HEVC_SLICE_P || sh->slice_type==HEVC_SLICE_B) { ++ ++ int NoBackwardPredFlag = 1; // Flag to say all reference pictures are from the past ++ for(i=L0; i<=L1; i++) { ++ for(rIdx=0; rIdx nb_refs[i]; rIdx++) { ++ HEVCFrame *f = s->ref->refPicList[i].ref[rIdx]; ++ HEVCFrame *c = s->ref; // CurrentPicture ++ if (c->poc < f->poc) NoBackwardPredFlag = 0; ++ } ++ } ++ ++ if (sps->sps_temporal_mvp_enabled_flag) ++ { ++ const RefPicList *rpl = (sh->slice_type != HEVC_SLICE_B || collocated_from_l0_flag) ? ++ s->ref->refPicList + 0 : ++ s->ref->refPicList + 1; ++ de->dpbno_col = rpl->ref[sh->collocated_ref_idx] - s->DPB; ++ } ++ ++ cmd_slice += NoBackwardPredFlag<<10; ++ msg_slice(de, cmd_slice); ++ ++ // Write reference picture descriptions ++ weightedPredFlag = sh->slice_type==HEVC_SLICE_P? pps->weighted_pred_flag : pps->weighted_bipred_flag; ++ ++ for(i=L0; i<=L1; i++) ++ for(rIdx=0; rIdx nb_refs[i]; rIdx++) { ++ HEVCFrame *f = s->ref->refPicList[i].ref[rIdx]; ++ HEVCFrame *c = s->ref; // CurrentPicture ++ int pic = f - s->DPB; ++ // Make sure pictures are in range 0 to 15 ++ int adjusted_pic = fref->refPicList[i].isLongTerm[rIdx]; ++ msg_slice(de, adjusted_pic+(lt<<4)+(weightedPredFlag<<5)+(weightedPredFlag<<6)); ++ msg_slice(de, f->poc); ++ if (weightedPredFlag) { ++ msg_slice(de, s->sh.luma_log2_weight_denom+(((i?s-> sh.luma_weight_l1: s->sh.luma_weight_l0)[rIdx] &0x1ff)<<3)); ++ msg_slice(de, (i?s-> sh.luma_offset_l1: s->sh.luma_offset_l0)[rIdx] & 0xff); ++ msg_slice(de, s->sh.chroma_log2_weight_denom+(((i?s->sh.chroma_weight_l1:s->sh.chroma_weight_l0)[rIdx][0]&0x1ff)<<3)); ++ msg_slice(de, (i?s->sh.chroma_offset_l1:s->sh.chroma_offset_l0)[rIdx][0]& 0xff); ++ msg_slice(de, s->sh.chroma_log2_weight_denom+(((i?s->sh.chroma_weight_l1:s->sh.chroma_weight_l0)[rIdx][1]&0x1ff)<<3)); ++ msg_slice(de, (i?s->sh.chroma_offset_l1:s->sh.chroma_offset_l0)[rIdx][1]& 0xff); ++ } ++ } ++ } ++ else ++ msg_slice(de, cmd_slice); ++ ++ msg_slice(de, ((sh->beta_offset/2)&15) ++ + (((sh->tc_offset/2)&15) << 4) ++ + (sh->disable_deblocking_filter_flag << 8) ++ + (sh->slice_loop_filter_across_slices_enabled_flag << 9) ++ + (pps->loop_filter_across_tiles_enabled_flag << 10)); // CMD_DEBLOCK ++ ++ msg_slice(de, ((sh->slice_cr_qp_offset&31)<<5) + (sh->slice_cb_qp_offset&31)); // CMD_QPOFF ++} ++ ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static void rpi_hevc_abort_frame(AVCodecContext * const avctx) { ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ dec_env_t * const de = dec_env_get(avctx, rpi); ++ ++#if TRACE_ENTRY ++ printf("<<< %s[%p]\n", __func__, de); ++#endif ++ ++ if (de == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Cannot find find context for thread\n", __func__); ++ return; ++ } ++ ++ switch (de->state) { ++ case RPIVID_DECODE_NEW: ++ case RPIVID_DECODE_END: ++ // Expected transition ++ break; ++ ++ case RPIVID_DECODE_SLICE: ++ // Error transition ++ av_log(avctx, AV_LOG_INFO, "Error in decode - aborting\n"); ++ break; ++ ++ case RPIVID_DECODE_START: ++ default: ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected state transition: %d", __func__, de->state); ++ break; ++ } ++ ++ abort_phases(rpi, de); ++ de->state = RPIVID_DECODE_NEW; ++ ++ dec_env_release(rpi, de); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// End frame ++ ++static int rpi_hevc_end_frame(AVCodecContext * const avctx) { ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ const HEVCContext * const s = avctx->priv_data; ++ const HEVCPPS * const pps = s->ps.pps; ++ const HEVCSPS * const sps = s->ps.sps; ++ dec_env_t * const de = dec_env_get(avctx, rpi); ++ AVFrame * const f = s->ref->frame; ++ const unsigned int dpbno_cur = s->ref - s->DPB; ++ vid_vc_addr_t cmds_vc; ++ vid_vc_addr_t pu_base_vc; ++ unsigned int pu_stride; ++ vid_vc_addr_t coeff_base_vc; ++ unsigned int coeff_stride; ++ unsigned int i; ++ int rv = 0; ++ int status = 0; ++ int coeffbuf_sem_claimed = 0; ++ ++#if TRACE_ENTRY ++ fprintf("<<< %s[%p]\n", __func__, de); ++#endif ++ ++ if (de == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Cannot find find context for thread\n", __func__); ++ return AVERROR_BUG; // Should never happen ++ } ++ ++ if (de->state != RPIVID_DECODE_SLICE) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected state: %d\n", __func__, de->state); ++ rv = AVERROR_UNKNOWN; ++ goto fail; ++ } ++ de->state = RPIVID_DECODE_END; ++ ++ // End of command compilation ++ { ++ const unsigned int last_x = pps->col_bd[pps->num_tile_columns]-1; ++ const unsigned int last_y = pps->row_bd[pps->num_tile_rows]-1; ++ if (pps->entropy_coding_sync_enabled_flag) { ++ if (de->wpp_entry_x<2 && de->PicWidthInCtbsY>2) ++ wpp_pause(de, last_y); ++ } ++ p1_apb_write(de, RPI_STATUS, 1 + (last_x<<5) + (last_y<<18)); ++ } ++ ++ // Phase 0 --------------------------------------------------------------- ++ ++ wait_phase(rpi, de, 0); ++ rpi_sem_wait(&rpi->bitbuf_sem); ++ tstart_phase(rpi, 0); ++ ++ // Copy cmds & bits into gpu side buffer ++ // Layout: CMDS, BITS ++ { ++ uint8_t * const armbase = rpi->gbitbufs[rpi->bitbuf_no].arm; ++ vid_vc_addr_t vcbase = rpi->gbitbufs[rpi->bitbuf_no].vc; ++ unsigned int cmd_bytes = de->cmd_len * sizeof(struct RPI_CMD); ++ ++ uint8_t * p = armbase + rnd64(cmd_bytes); ++ uint8_t * const eobits = armbase + rpi->gbitbufs[rpi->bitbuf_no].numbytes; ++ ++ cmds_vc = vcbase; ++ ++ // Copy all the bits & update bitstream cmds to point at the right bits ++ for (i = 0; i < de->bit_len; ++i) ++ { ++ const unsigned int seg_len = de->bit_fifo[i].len; ++ ++ if (p + seg_len > eobits) { ++ status = -1; ++ break; ++ } ++ ++ memcpy(p, de->bit_fifo[i].ptr, seg_len); ++ de->cmd_fifo[de->bit_fifo[i].cmd].data = MANGLE64((p - armbase) + vcbase); ++ ++ p += rnd64(seg_len); ++ } ++ ++ memcpy(armbase, de->cmd_fifo, cmd_bytes); ++ } ++ ++ if (status == 0) ++ { ++ if (++rpi->bitbuf_no >= RPIVID_BITBUFS) ++ rpi->bitbuf_no = 0; ++ } ++ else ++ { ++ sem_post(&rpi->bitbuf_sem); ++ av_log(avctx, AV_LOG_ERROR, "Out of HEVC bit/cmd memory\n"); ++ rv = AVERROR_BUFFER_TOO_SMALL; ++ } ++ ++ tend_phase(rpi, 0); ++ post_phase(rpi, de, 0); ++ ++ if (status < 0) ++ goto fail; ++ ++ // Phase 1 --------------------------------------------------------------- ++ ++ wait_phase(rpi, de, 1); ++ rpi_sem_wait(&rpi->coeffbuf_sem); ++ coeffbuf_sem_claimed = 1; ++ tstart_phase(rpi, 1); ++ ++ for (;;) ++ { ++ // (Re-)allocate PU/COEFF stream space ++ const unsigned int total_size = rpi->gcoeffbufs[rpi->coeffbuf_no].numbytes; ++ unsigned int pu_size; ++ ++ pu_base_vc = rpi->gcoeffbufs[rpi->coeffbuf_no].vc; ++ pu_stride = rnd64(rpi->max_pu_msgs * 2 * de->PicWidthInCtbsY); ++ pu_size = pu_stride * de->PicHeightInCtbsY; ++ ++ if (pu_size > total_size) { ++ status = -1; ++ break; ++ } ++ ++ // Allocate all remaining space to coeff ++ coeff_base_vc = pu_base_vc + pu_size; ++ coeff_stride = ((total_size - pu_size) / de->PicHeightInCtbsY) & ~63; // Round down to multiple of 64 ++ ++ apb_write_vc_addr(rpi, RPI_PUWBASE, pu_base_vc); ++ apb_write_vc_len(rpi, RPI_PUWSTRIDE, pu_stride); ++ apb_write_vc_addr(rpi, RPI_COEFFWBASE, coeff_base_vc); ++ apb_write_vc_len(rpi, RPI_COEFFWSTRIDE, coeff_stride); ++ ++ // Trigger command FIFO ++ apb_write(rpi, RPI_CFNUM, de->cmd_len); ++#if TRACE_DEV ++ apb_dump_regs(rpi, 0x0, 32); ++ apb_dump_regs(rpi, 0x8000, 24); ++ axi_dump(de, ((uint64_t)a64)<<6, de->cmd_len * sizeof(struct RPI_CMD)); ++#endif ++ apb_write_vc_addr(rpi, RPI_CFBASE, cmds_vc); ++ ++ int_wait(rpi, 1); ++ ++ status = check_status(rpi, de); ++ ++ if (status != 1) ++ break; ++ ++ // Status 1 means out of PU space so try again with more ++ // If we ran out of Coeff space then we are out of memory - we could possibly realloc? ++ rpi->max_pu_msgs += rpi->max_pu_msgs / 2; ++ } ++ ++ // Inc inside the phase 1 lock, but only inc if we succeeded otherwise we ++ // may reuse a live buffer when we kick the coeff sem ++ if (status == 0) ++ { ++ if (++rpi->coeffbuf_no >= RPIVID_COEFFBUFS) ++ rpi->coeffbuf_no = 0; ++ } ++ else ++ { ++ if (status == -1) ++ { ++ av_log(avctx, AV_LOG_ERROR, "Out of pu + coeff intermediate memory: pus=%d\n", rpi->max_pu_msgs); ++ rv = AVERROR_BUFFER_TOO_SMALL; ++ } ++ else ++ { ++ av_log(avctx, AV_LOG_WARNING, "Phase 1 decode error\n"); ++ rv = AVERROR_INVALIDDATA; ++ } ++ } ++ ++ tend_phase(rpi, 1); ++ sem_post(&rpi->bitbuf_sem); ++ post_phase(rpi, de, 1); ++ ++ if (status != 0) ++ goto fail; ++ ++ // Phase 2 --------------------------------------------------------------- ++ ++ wait_phase(rpi, de, 2); ++ ++ if ((rv = av_rpi_zc_resolve_frame(f, ZC_RESOLVE_ALLOC)) != 0) ++ { ++ // As we are in phase 2 already here we don't need to worry about ++ // ceoffbuf_no despite the early exit ++ post_phase(rpi, de, 2); ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output frame\n"); ++ goto fail; ++ } ++ ++ tstart_phase(rpi, 2); ++ ++ apb_write_vc_addr(rpi, RPI_PURBASE, pu_base_vc); ++ apb_write_vc_len(rpi, RPI_PURSTRIDE, pu_stride); ++ apb_write_vc_addr(rpi, RPI_COEFFRBASE, coeff_base_vc); ++ apb_write_vc_len(rpi, RPI_COEFFRSTRIDE, coeff_stride); ++ ++ apb_write_vc_addr(rpi, RPI_OUTYBASE, get_vc_address_y(f)); ++ apb_write_vc_addr(rpi, RPI_OUTCBASE, get_vc_address_u(f)); ++ apb_write_vc_len(rpi, RPI_OUTYSTRIDE, f->linesize[3] * 128); ++ apb_write_vc_len(rpi, RPI_OUTCSTRIDE, f->linesize[3] * 128); ++ ++ // Keep the last thing we resolved as fallback for any ref we fail to ++ // resolve. As a final fallback use our current frame. The pels might ++ // not be there yet but at least the memory is valid. ++ // ++ // Attempt to resolve the entire DPB - we could note what we have used ++ // in ref lists but probably simpler and more reliable to set the whole thing ++ { ++ AVFrame * fallback_frame = f; ++ for (i = 0; i != 16; ++i) { ++ // Avoid current frame ++ const HEVCFrame * hevc_fr = (s->DPB + i >= s->ref) ? s->DPB + i + 1 : s->DPB + i; ++ AVFrame * fr = hevc_fr->frame; ++ ++ if (fr != NULL && ++ av_rpi_zc_resolve_frame(fr, ZC_RESOLVE_FAIL) == 0) ++ { ++ fallback_frame = fr; ++ } ++ else ++ { ++ fr = fallback_frame; ++ } ++ ++ apb_write_vc_addr(rpi, 0x9000+16*i, get_vc_address_y(fr)); ++ apb_write(rpi, 0x9004+16*i, 0); ++ apb_write_vc_addr(rpi, 0x9008+16*i, get_vc_address_u(fr)); ++ apb_write(rpi, 0x900C+16*i, 0); ++ } ++ } ++ ++ apb_write(rpi, RPI_CONFIG2, ++ (sps->bit_depth << 0) // BitDepthY ++ + (sps->bit_depth << 4) // BitDepthC ++ + ((sps->bit_depth>8) << 8) // BitDepthY ++ + ((sps->bit_depth>8) << 9) // BitDepthC ++ + (sps->log2_ctb_size <<10) ++ + (pps->constrained_intra_pred_flag <<13) ++ + (sps->sps_strong_intra_smoothing_enable_flag<<14) ++ + (sps->sps_temporal_mvp_enabled_flag <<15) ++ + (pps->log2_parallel_merge_level <<16) ++ + (s->sh.slice_temporal_mvp_enabled_flag <<19) ++ + (sps->pcm.loop_filter_disable_flag <<20) ++ + ((pps->cb_qp_offset&31) <<21) ++ + ((pps->cr_qp_offset&31) <<26)); ++ ++ apb_write(rpi, RPI_FRAMESIZE, (sps->height<<16) + sps->width); ++ apb_write(rpi, RPI_CURRPOC, s->poc); ++ ++ // collocated reads/writes ++ if (sps->sps_temporal_mvp_enabled_flag) { ++ av_assert0(de->dpbno_col < RPIVID_COL_PICS); ++ av_assert0(dpbno_cur < RPIVID_COL_PICS); ++ ++ apb_write_vc_len(rpi, RPI_COLSTRIDE, rpi->col_stride); ++ apb_write_vc_len(rpi, RPI_MVSTRIDE, rpi->col_stride); ++ apb_write_vc_addr(rpi, RPI_MVBASE, rpi->gcolbuf.vc + dpbno_cur * rpi->col_picsize); ++ apb_write_vc_addr(rpi, RPI_COLBASE, rpi->gcolbuf.vc + de->dpbno_col * rpi->col_picsize); ++ } ++ ++#if TRACE_DEV ++ apb_dump_regs(rpi, 0x0, 32); ++ apb_dump_regs(rpi, 0x8000, 24); ++#endif ++ ++ apb_write(rpi, RPI_NUMROWS, de->PicHeightInCtbsY); ++ apb_read(rpi, RPI_NUMROWS); // Read back to confirm write has reached block ++ ++ int_wait(rpi, 2); ++ ++ tend_phase(rpi, 2); ++ coeffbuf_sem_claimed = 0; ++ sem_post(&rpi->coeffbuf_sem); ++ // Set valid here to avoid race in resolving in any pending phase 2 ++ av_rpi_zc_set_valid_frame(f); ++ ++ post_phase(rpi, de, 2); ++ ++ // Flush frame for CPU access ++ // Arguably the best place would be at the start of phase 2 but here ++ // will overlap with the wait ++ // ++ // * Even better would be to have better lock/unlock control in ZC for external access ++ if (rpi->gpu_init_type == GPU_INIT_GPU) // * CMA is currently always uncached ++ { ++ rpi_cache_buf_t cbuf; ++ rpi_cache_flush_env_t * const fe = rpi_cache_flush_init(&cbuf); ++ rpi_cache_flush_add_frame(fe, f, RPI_CACHE_FLUSH_MODE_INVALIDATE); ++ rpi_cache_flush_finish(fe); ++ } ++ ++#if TRACE_ENTRY ++ printf(">>> %s[%p] OK\n", __func__, de); ++#endif ++ ++ dec_env_release(rpi, de); ++ return 0; ++ ++fail: ++ av_rpi_zc_set_broken_frame(f); ++ if (coeffbuf_sem_claimed) ++ sem_post(&rpi->coeffbuf_sem); ++ abort_phases(rpi, de); // Dummy any unresolved phases ++ ++#if TRACE_ENTRY ++ printf(">>> %s[%p] FAIL\n", __func__, de); ++#endif ++ ++ dec_env_release(rpi, de); ++ return rv; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static void WriteBitstream(dec_env_t * const de, const HEVCContext * const s) { ++ const int rpi_use_emu = 0; // FFmpeg removes emulation prevention bytes ++ const int offset = 0; // Always 64-byte aligned in sim, need not be on real hardware ++ const GetBitContext *gb = &s->HEVClc->gb; ++ const int len = 1 + gb->size_in_bits/8 - gb->index/8; ++ const void *ptr = &gb->buffer[gb->index/8]; ++ ++ p1_axi_write(de, len, ptr, p1_apb_write(de, RPI_BFBASE, 0)); // BFBASE set later ++ p1_apb_write(de, RPI_BFNUM, len); ++ p1_apb_write(de, RPI_BFCONTROL, offset + (1<<7)); // Stop ++ p1_apb_write(de, RPI_BFCONTROL, offset + (rpi_use_emu<<6)); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Wavefront mode ++ ++static void wpp_decode_slice(dec_env_t * const de, const HEVCContext * const s, int ctb_addr_ts) ++{ ++ const HEVCPPS * const pps = s->ps.pps; ++ ++ int i, resetQPY=1; ++ int indep = !s->sh.dependent_slice_segment_flag; ++ int ctb_col = s->sh.slice_ctb_addr_rs % de->PicWidthInCtbsY; ++ ++ if (ctb_addr_ts) ++ wpp_end_previous_slice(de, s, ctb_addr_ts); ++ pre_slice_decode(de, s); ++ WriteBitstream(de, s); ++ if (ctb_addr_ts==0 || indep || de->PicWidthInCtbsY==1) ++ WriteProb(de, s); ++ else if (ctb_col==0) ++ p1_apb_write(de, RPI_TRANSFER, PROB_RELOAD); ++ else ++ resetQPY=0; ++ program_slicecmds(de, s->slice_idx); ++ new_slice_segment(de, s); ++ wpp_entry_point(de, s, indep, resetQPY, ctb_addr_ts); ++ for (i=0; ish.num_entry_point_offsets; i++) { ++ int ctb_addr_rs = pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ int ctb_row = ctb_addr_rs / de->PicWidthInCtbsY; ++ int last_x = de->PicWidthInCtbsY-1; ++ if (de->PicWidthInCtbsY>2) ++ wpp_pause(de, ctb_row); ++ p1_apb_write(de, RPI_STATUS, (ctb_row<<18) + (last_x<<5) + 2); ++ if (de->PicWidthInCtbsY==2) ++ p1_apb_write(de, RPI_TRANSFER, PROB_BACKUP); ++ if (de->PicWidthInCtbsY==1) ++ WriteProb(de, s); ++ else ++ p1_apb_write(de, RPI_TRANSFER, PROB_RELOAD); ++ ctb_addr_ts += pps->column_width[0]; ++ wpp_entry_point(de, s, 0, 1, ctb_addr_ts); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// Tiles mode ++ ++static void decode_slice(dec_env_t * const de, const HEVCContext * const s, int ctb_addr_ts) { ++ const HEVCPPS * const pps = s->ps.pps; ++ int i, resetQPY; ++ ++ if (ctb_addr_ts) end_previous_slice(de, s, ctb_addr_ts); ++ pre_slice_decode(de, s); ++ WriteBitstream(de, s); ++ resetQPY = ctb_addr_ts==0 ++ || pps->tile_id[ctb_addr_ts]!=pps->tile_id[ctb_addr_ts-1] ++ || !s->sh.dependent_slice_segment_flag; ++ if (resetQPY) WriteProb(de, s); ++ program_slicecmds(de, s->slice_idx); ++ new_slice_segment(de, s); ++ new_entry_point(de, s, !s->sh.dependent_slice_segment_flag, resetQPY, ctb_addr_ts); ++ for (i=0; ish.num_entry_point_offsets; i++) { ++ int ctb_addr_rs = pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ int ctb_col = ctb_addr_rs % de->PicWidthInCtbsY; ++ int ctb_row = ctb_addr_rs / de->PicWidthInCtbsY; ++ int tile_x = ctb_to_tile (ctb_col, pps->col_bd, pps->num_tile_columns); ++ int tile_y = ctb_to_tile (ctb_row, pps->row_bd, pps->num_tile_rows); ++ int last_x = pps->col_bd[tile_x+1]-1; ++ int last_y = pps->row_bd[tile_y+1]-1; ++ p1_apb_write(de, RPI_STATUS, 2 + (last_x<<5) + (last_y<<18)); ++ WriteProb(de, s); ++ ctb_addr_ts += pps->column_width[tile_x] * pps->row_height[tile_y]; ++ new_entry_point(de, s, 0, 1, ctb_addr_ts); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static int cabac_start_align(HEVCContext *s) ++{ ++ GetBitContext *gb = &s->HEVClc->gb; ++ skip_bits(gb, 1); ++ align_get_bits(gb); ++ // Should look at getting rid of this ++ return ff_init_cabac_decoder(&s->HEVClc->cc, ++ gb->buffer + get_bits_count(gb) / 8, ++ (get_bits_left(gb) + 7) / 8); ++} ++ ++static int rpi_hevc_decode_slice( ++ AVCodecContext *avctx, ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ HEVCContext * const s = avctx->priv_data; ++ dec_env_t * const de = dec_env_get(avctx, rpi); ++ const HEVCPPS *pps = s->ps.pps; ++ int ctb_addr_ts = pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ ++#if TRACE_ENTRY ++ printf("<<< %s[%p]\n", __func__, de); ++#endif ++ if (de == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Cannot find find context for thread\n", __func__); ++ return -1; ++ } ++ ++ if (de->state != RPIVID_DECODE_START && de->state != RPIVID_DECODE_SLICE) { ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected state: %d\n", __func__, de->state); ++ return -1; ++ } ++ de->state = RPIVID_DECODE_SLICE; ++ ++// ff_hevc_cabac_init(s, ctb_addr_ts); ++ cabac_start_align(s); ++ if (s->ps.sps->scaling_list_enable_flag) ++ populate_scaling_factors(de, s); ++ pps->entropy_coding_sync_enabled_flag? wpp_decode_slice(de, s, ctb_addr_ts) ++ : decode_slice(de, s, ctb_addr_ts); ++#if TRACE_ENTRY ++ printf(">>> %s[%p]\n", __func__, de); ++#endif ++ dec_env_release(rpi, de); ++ return 0; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static int rpivid_retrieve_data(void *logctx, AVFrame *frame) ++{ ++ int rv; ++ if ((rv = av_rpi_zc_resolve_frame(frame, ZC_RESOLVE_WAIT_VALID)) != 0) ++ av_log(logctx, AV_LOG_ERROR, "Unable to resolve output frame\n"); ++ return rv; ++} ++ ++static int rpivid_hevc_alloc_frame(AVCodecContext * avctx, AVFrame *frame) ++{ ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ HEVCContext * const s = avctx->priv_data; ++ // Frame buffering + 1 output. Would need thread_count extra but we now ++ // alloc at the start of phase 2 so that is the only thread we need the ++ // extra buffer for. ++ const unsigned int pool_req = s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].max_dec_pic_buffering + 1; ++ int rv; ++ ++ if (av_rpi_zc_in_use(avctx)) ++ { ++ const AVZcEnvPtr zc = avctx->opaque; ++ av_rpi_zc_set_decoder_pool_size(zc, pool_req); ++ av_rpi_zc_get_buffer(zc, frame); // get_buffer2 would alloc ++ } ++ else ++ { ++ if (rpi->zc == NULL) { ++ pthread_mutex_lock(&rpi->phase_lock); // Abuse - not worth creating a lock just for this ++ // Alloc inside lock to make sure we only ever alloc one ++ if (rpi->zc == NULL) { ++ rpi->zc = av_rpi_zc_int_env_alloc(s); ++ } ++ pthread_mutex_unlock(&rpi->phase_lock); ++ } ++ av_rpi_zc_set_decoder_pool_size(rpi->zc, pool_req); // Ignored by local allocator, but set anyway :-) ++ rv = (rpi->zc == NULL) ? AVERROR(ENOMEM) : ++ av_rpi_zc_get_buffer(rpi->zc, frame); ++ } ++ ++ if (rv == 0 && ++ (rv = ff_attach_decode_data(frame)) < 0) ++ { ++ av_frame_unref(frame); ++ } ++ ++ if (rv == 0) ++ { ++ FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; ++ fdd->post_process = rpivid_retrieve_data; ++ } ++ ++ return rv; ++} ++ ++#if OPT_PHASE_TIMING ++static void log_bin_phase(AVCodecContext * const avctx, const unsigned int * const bins) ++{ ++ av_log(avctx, AV_LOG_INFO, "%7d %7d %7d %7d %7d %7d %7d %7d %7d\n", ++ bins[0], bins[1], bins[2], bins[3], ++ bins[4], bins[5], bins[6], bins[7], bins[8]); ++} ++#endif ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static int rpi_hevc_free(AVCodecContext *avctx) { ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++ ++#if TRACE_ENTRY ++ printf("<<< %s\n", __func__); ++#endif ++ ++ dec_env_release(rpi, NULL); ++ ++ // Wait for everything else to stop ++ { ++ struct timespec tt; ++ clock_gettime(CLOCK_REALTIME, &tt); ++ tt.tv_sec += 2; ++ while (sem_timedwait(&rpi->ref_zero, &tt) == -1) { ++ const int err = errno; ++ if (err == ETIMEDOUT) { ++ av_log(avctx, AV_LOG_FATAL, "Rpivid worker threads still running\n"); ++ return -1; ++ } ++ if (err != EINTR) { ++ av_log(avctx, AV_LOG_ERROR, "Unexpected error %d waiting for work thread to stop\n", err); ++ break; ++ } ++ } ++ } ++ ++#if OPT_PHASE_TIMING ++ { ++ unsigned int i; ++ for (i = 0; i != RPIVID_PHASES; ++i) { ++ const phase_wait_env_t * const p = rpi->phase_reqs + i; ++ av_log(avctx, AV_LOG_INFO, "Phase %u: In %3u.%06u, Out %3u.%06u\n", i, ++ (unsigned int)(p->time_in_phase / 1000000), (unsigned int)(p->time_in_phase % 1000000), ++ (unsigned int)(p->time_out_phase / 1000000), (unsigned int)(p->time_out_phase % 1000000)); ++ av_log(avctx, AV_LOG_INFO, "%7d %7d %7d %7d %7d %7d %7d %7d >\n", ++ time_thresholds[0], time_thresholds[1], time_thresholds[2], time_thresholds[3], ++ time_thresholds[4], time_thresholds[5], time_thresholds[6], time_thresholds[7]); ++ log_bin_phase(avctx, p->time_bins); ++ log_bin_phase(avctx, p->time_bins3); ++ log_bin_phase(avctx, p->time_bins5); ++ av_log(avctx, AV_LOG_INFO, "Longest duraction: %ums @ frame %u\n", ++ (unsigned int)(p->max_phase_time / 1000), ++ p->max_time_decode_order); ++ } ++ av_log(avctx, AV_LOG_INFO, "PU max=%d\n", rpi->max_pu_msgs); ++ } ++#endif ++ ++ if (rpi->dec_envs != NULL) ++ { ++ for (int i; i < avctx->thread_count && rpi->dec_envs[i] != NULL; ++i) { ++ dec_env_delete(rpi->dec_envs[i]); ++ } ++ av_freep(&rpi->dec_envs); ++ } ++ ++ av_rpi_zc_int_env_freep(&rpi->zc); ++ ++ gpu_free(&rpi->gcolbuf); ++ ++ for (unsigned int i = 0; i != RPIVID_BITBUFS; ++i) { ++ gpu_free(rpi->gbitbufs + i); ++ } ++ for (unsigned int i = 0; i != RPIVID_COEFFBUFS; ++i) { ++ gpu_free(rpi->gcoeffbufs + i); ++ } ++ ++ unmap_devp(&rpi->regs, REGS_SIZE); ++ unmap_devp(&rpi->ints, INTS_SIZE); ++ ++ if (rpi->gpu_init_type > 0) ++ rpi_mem_gpu_uninit(); ++ ++ if (rpi->mbox_fd >= 0) { ++ mbox_release_clock(rpi->mbox_fd); ++ mbox_close(rpi->mbox_fd); ++ } ++ ++ sem_destroy(&rpi->ref_zero); ++ sem_destroy(&rpi->coeffbuf_sem); ++ sem_destroy(&rpi->bitbuf_sem); ++ ++#if TRACE_ENTRY ++ printf(">>> %s\n", __func__); ++#endif ++ return 0; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++static int rpi_hevc_init(AVCodecContext *avctx) { ++ RPI_T * const rpi = avctx->internal->hwaccel_priv_data; ++// const char *err; ++ ++#if TRACE_ENTRY ++ printf("<<< %s\n", __func__); ++#endif ++ ++ if (avctx->width>4096 || avctx->height>4096) { ++ av_log(NULL, AV_LOG_FATAL, "Picture size %dx%d exceeds 4096x4096 maximum for HWAccel\n", avctx->width, avctx->height); ++ return AVERROR(ENOTSUP); ++ } ++ ++ memset(rpi, 0, sizeof(*rpi)); ++ ++ rpi->mbox_fd = -1; ++ rpi->decode_order = 0; ++ ++ // Initial PU/COEFF stream buffer split chosen as worst case seen so far ++ rpi->max_pu_msgs = 768; // 7.2 says at most 1611 messages per CTU ++ ++ ++ atomic_store(&rpi->ref_count, 1); ++ sem_init(&rpi->ref_zero, 0, 0); ++ ++ sem_init(&rpi->bitbuf_sem, 0, RPIVID_BITBUFS); ++ sem_init(&rpi->coeffbuf_sem, 0, RPIVID_COEFFBUFS); ++ ++ pthread_mutex_init(&rpi->phase_lock, NULL); ++ ++ if ((rpi->mbox_fd = mbox_open()) < 0) ++ { ++ av_log(avctx, AV_LOG_ERROR, "Failed to open mailbox\n"); ++ goto fail; ++ } ++ mbox_request_clock(rpi->mbox_fd); ++ ++ if ((rpi->regs = map_dev(avctx, REGS_NAME, REGS_SIZE)) == NULL || ++ (rpi->ints = map_dev(avctx, INTS_NAME, INTS_SIZE)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to open rpivid devices\n"); ++ goto fail; ++ } ++ ++ if ((rpi->gpu_init_type = rpi_mem_gpu_init(0)) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to init GPU\n"); ++ goto fail; ++ } ++ ++ if ((rpi->dec_envs = av_mallocz(sizeof(dec_env_t *) * avctx->thread_count)) == NULL) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to alloc %d dec envs\n", avctx->thread_count); ++ goto fail; ++ } ++ ++ rpi->col_stride = rnd64(avctx->width); ++ rpi->col_picsize = rpi->col_stride * (((avctx->height + 63) & ~63) >> 4); ++ if (gpu_malloc_uncached(rpi->col_picsize * RPIVID_COL_PICS, &rpi->gcolbuf) != 0) ++ { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate col mv buffer\n"); ++ goto fail; ++ } ++ ++ for (unsigned int i = 0; i != RPIVID_BITBUFS; ++i) { ++ if (gpu_malloc_uncached(RPIVID_BITBUF_SIZE, rpi->gbitbufs + i) != 0) ++ { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate bitbuf %d\n", i); ++ goto fail; ++ } ++ } ++ ++ for (unsigned int i = 0; i != RPIVID_COEFFBUFS; ++i) { ++ if (gpu_malloc_uncached(RPIVID_COEFFBUF_SIZE, rpi->gcoeffbufs + i) != 0) ++ { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate coeffbuf %d\n", i); ++ goto fail; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ rpi_hevc_free(avctx); ++ return AVERROR_EXTERNAL; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++ ++const AVHWAccel ff_hevc_rpi4_8_hwaccel = { ++ .name = "hevc_rpi4_8", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .pix_fmt = AV_PIX_FMT_RPI4_8, ++ .alloc_frame = rpivid_hevc_alloc_frame, ++ .start_frame = rpi_hevc_start_frame, ++ .end_frame = rpi_hevc_end_frame, ++ .abort_frame = rpi_hevc_abort_frame, ++ .decode_slice = rpi_hevc_decode_slice, ++ .init = rpi_hevc_init, ++ .uninit = rpi_hevc_free, ++ .priv_data_size = sizeof(RPI_T), ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_MT_SAFE, ++}; ++ ++const AVHWAccel ff_hevc_rpi4_10_hwaccel = { ++ .name = "hevc_rpi4_10", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .pix_fmt = AV_PIX_FMT_RPI4_10, ++ .alloc_frame = rpivid_hevc_alloc_frame, ++ .start_frame = rpi_hevc_start_frame, ++ .end_frame = rpi_hevc_end_frame, ++ .abort_frame = rpi_hevc_abort_frame, ++ .decode_slice = rpi_hevc_decode_slice, ++ .init = rpi_hevc_init, ++ .uninit = rpi_hevc_free, ++ .priv_data_size = sizeof(RPI_T), ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_MT_SAFE, ++}; ++ +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 02f23d954b..b516aa934a 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -21,6 +21,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include + #include + #include + #include +@@ -30,12 +31,13 @@ + #include "libavcodec/avcodec.h" + #include "libavcodec/internal.h" + #include "libavutil/pixdesc.h" ++#include "libavutil/hwcontext.h" + #include "v4l2_context.h" + #include "v4l2_buffers.h" + #include "v4l2_m2m.h" + + #define USEC_PER_SEC 1000000 +-static AVRational v4l2_timebase = { 1, USEC_PER_SEC }; ++static const AVRational v4l2_timebase = { 1, USEC_PER_SEC }; + + static inline V4L2m2mContext *buf_to_m2mctx(V4L2Buffer *buf) + { +@@ -52,34 +54,44 @@ static inline AVCodecContext *logger(V4L2Buffer *buf) + static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf) + { + V4L2m2mContext *s = buf_to_m2mctx(avbuf); +- +- if (s->avctx->pkt_timebase.num) +- return s->avctx->pkt_timebase; +- return s->avctx->time_base; ++ const AVRational tb = s->avctx->pkt_timebase.num ? ++ s->avctx->pkt_timebase : ++ s->avctx->time_base; ++ return tb.num && tb.den ? tb : v4l2_timebase; + } + +-static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts) ++static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts, int no_rescale) + { +- int64_t v4l2_pts; +- +- if (pts == AV_NOPTS_VALUE) +- pts = 0; +- + /* convert pts to v4l2 timebase */ +- v4l2_pts = av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase); ++ const int64_t v4l2_pts = ++ no_rescale ? pts : ++ pts == AV_NOPTS_VALUE ? 0 : ++ av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase); + out->buf.timestamp.tv_usec = v4l2_pts % USEC_PER_SEC; + out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC; + } + +-static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) ++static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf, int no_rescale) + { +- int64_t v4l2_pts; +- + /* convert pts back to encoder timebase */ +- v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + ++ const int64_t v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + + avbuf->buf.timestamp.tv_usec; + +- return av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf)); ++ return ++ no_rescale ? v4l2_pts : ++ v4l2_pts == 0 ? AV_NOPTS_VALUE : ++ av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf)); ++} ++ ++static void set_buf_length(V4L2Buffer *out, unsigned int plane, uint32_t bytesused, uint32_t length) ++{ ++ if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { ++ out->planes[plane].bytesused = bytesused; ++ out->planes[plane].length = length; ++ } else { ++ out->buf.bytesused = bytesused; ++ out->buf.length = length; ++ } + } + + static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) +@@ -210,7 +222,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) + return AVCOL_TRC_UNSPECIFIED; + } + +-static void v4l2_free_buffer(void *opaque, uint8_t *unused) ++static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) ++{ ++ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; ++ AVDRMLayerDescriptor *layer; ++ ++ /* fill the DRM frame descriptor */ ++ drm_desc->nb_objects = avbuf->num_planes; ++ drm_desc->nb_layers = 1; ++ ++ layer = &drm_desc->layers[0]; ++ layer->nb_planes = avbuf->num_planes; ++ ++ for (int i = 0; i < avbuf->num_planes; i++) { ++ layer->planes[i].object_index = i; ++ layer->planes[i].offset = 0; ++ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline; ++ } ++ ++ switch (avbuf->context->av_pix_fmt) { ++ case AV_PIX_FMT_YUYV422: ++ ++ layer->format = DRM_FORMAT_YUYV; ++ layer->nb_planes = 1; ++ ++ break; ++ ++ case AV_PIX_FMT_NV12: ++ case AV_PIX_FMT_NV21: ++ ++ layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ? ++ DRM_FORMAT_NV12 : DRM_FORMAT_NV21; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 2; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height; ++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; ++ break; ++ ++ case AV_PIX_FMT_YUV420P: ++ ++ layer->format = DRM_FORMAT_YUV420; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 3; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height; ++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1; ++ ++ layer->planes[2].object_index = 0; ++ layer->planes[2].offset = layer->planes[1].offset + ++ ((avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height) >> 2); ++ layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1; ++ break; ++ ++ default: ++ drm_desc->nb_layers = 0; ++ break; ++ } ++ ++ return (uint8_t *) drm_desc; ++} ++ ++static void v4l2_free_buffer(void *opaque, uint8_t *data) + { + V4L2Buffer* avbuf = opaque; + V4L2m2mContext *s = buf_to_m2mctx(avbuf); +@@ -226,14 +310,52 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) + /* no need to queue more buffers to the driver */ + avbuf->status = V4L2BUF_AVAILABLE; + } +- else if (avbuf->context->streamon) ++ else if (avbuf->context->streamon) { ++ avbuf->buf.timestamp.tv_sec = 0; ++ avbuf->buf.timestamp.tv_usec = 0; + ff_v4l2_buffer_enqueue(avbuf); ++ } ++ else { ++ av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer freed but streamoff\n", avbuf->context->name); ++ } + } + + av_buffer_unref(&avbuf->context_ref); + } + } + ++static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) ++{ ++ struct v4l2_exportbuffer expbuf; ++ int i, ret; ++ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ memset(&expbuf, 0, sizeof(expbuf)); ++ ++ expbuf.index = avbuf->buf.index; ++ expbuf.type = avbuf->buf.type; ++ expbuf.plane = i; ++ ++ ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_EXPBUF, &expbuf); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) { ++ /* drm frame */ ++ avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length; ++ avbuf->drm_frame.objects[i].fd = expbuf.fd; ++ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ } else { ++ /* drm frame */ ++ avbuf->drm_frame.objects[0].size = avbuf->buf.length; ++ avbuf->drm_frame.objects[0].fd = expbuf.fd; ++ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ } ++ } ++ ++ return 0; ++} ++ + static int v4l2_buf_increase_ref(V4L2Buffer *in) + { + V4L2m2mContext *s = buf_to_m2mctx(in); +@@ -254,6 +376,24 @@ static int v4l2_buf_increase_ref(V4L2Buffer *in) + return 0; + } + ++static int v4l2_buf_to_bufref_drm(V4L2Buffer *in, AVBufferRef **buf) ++{ ++ int ret; ++ ++ *buf = av_buffer_create((uint8_t *) &in->drm_frame, ++ sizeof(in->drm_frame), ++ v4l2_free_buffer, ++ in, AV_BUFFER_FLAG_READONLY); ++ if (!*buf) ++ return AVERROR(ENOMEM); ++ ++ ret = v4l2_buf_increase_ref(in); ++ if (ret) ++ av_buffer_unref(buf); ++ ++ return ret; ++} ++ + static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) + { + int ret; +@@ -274,7 +414,7 @@ static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) + return ret; + } + +-static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset, AVBufferRef* bref) ++static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) + { + unsigned int bytesused, length; + +@@ -286,13 +426,7 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i + + memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, FFMIN(size, length-offset)); + +- if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { +- out->planes[plane].bytesused = bytesused; +- out->planes[plane].length = length; +- } else { +- out->buf.bytesused = bytesused; +- out->buf.length = length; +- } ++ set_buf_length(out, plane, bytesused, length); + + return 0; + } +@@ -303,13 +437,25 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + + frame->format = avbuf->context->av_pix_fmt; + +- for (i = 0; i < avbuf->num_planes; i++) { +- ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ /* 1. get references to the actual data */ ++ ret = v4l2_buf_to_bufref_drm(avbuf, &frame->buf[0]); + if (ret) + return ret; + +- frame->linesize[i] = avbuf->plane_info[i].bytesperline; +- frame->data[i] = frame->buf[i]->data; ++ frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf); ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ frame->hw_frames_ctx = av_buffer_ref(avbuf->context->frames_ref); ++ } else { ++ /* 1. get references to the actual data */ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); ++ if (ret) ++ return ret; ++ ++ frame->linesize[i] = avbuf->plane_info[i].bytesperline; ++ frame->data[i] = frame->buf[i]->data; ++ } + } + + /* fixup special cases */ +@@ -338,68 +484,95 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + return 0; + } + +-static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) ++static void cpy_2d(uint8_t * dst, int dst_stride, const uint8_t * src, int src_stride, int w, int h) + { +- int i, ret; +- struct v4l2_format fmt = out->context->format; +- int pixel_format = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? +- fmt.fmt.pix_mp.pixelformat : fmt.fmt.pix.pixelformat; +- int height = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? +- fmt.fmt.pix_mp.height : fmt.fmt.pix.height; +- int is_planar_format = 0; +- +- switch (pixel_format) { +- case V4L2_PIX_FMT_YUV420M: +- case V4L2_PIX_FMT_YVU420M: +-#ifdef V4L2_PIX_FMT_YUV422M +- case V4L2_PIX_FMT_YUV422M: +-#endif +-#ifdef V4L2_PIX_FMT_YVU422M +- case V4L2_PIX_FMT_YVU422M: +-#endif +-#ifdef V4L2_PIX_FMT_YUV444M +- case V4L2_PIX_FMT_YUV444M: +-#endif +-#ifdef V4L2_PIX_FMT_YVU444M +- case V4L2_PIX_FMT_YVU444M: +-#endif +- case V4L2_PIX_FMT_NV12M: +- case V4L2_PIX_FMT_NV21M: +- case V4L2_PIX_FMT_NV12MT_16X16: +- case V4L2_PIX_FMT_NV12MT: +- case V4L2_PIX_FMT_NV16M: +- case V4L2_PIX_FMT_NV61M: +- is_planar_format = 1; ++ if (dst_stride == src_stride && w + 32 >= dst_stride) { ++ memcpy(dst, src, dst_stride * h); ++ } ++ else { ++ while (--h >= 0) { ++ memcpy(dst, src, w); ++ dst += dst_stride; ++ src += src_stride; ++ } + } ++} ++ ++static int is_chroma(const AVPixFmtDescriptor *desc, int i, int num_planes) ++{ ++ return i != 0 && !(i == num_planes - 1 && (desc->flags & AV_PIX_FMT_FLAG_ALPHA)); ++} + +- if (!is_planar_format) { +- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); +- int planes_nb = 0; +- int offset = 0; ++static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) ++{ ++ int i; ++ int num_planes = 0; ++ int pel_strides[4] = {0}; + +- for (i = 0; i < desc->nb_components; i++) +- planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); ++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); ++ ++ if ((desc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0) { ++ av_log(NULL, AV_LOG_ERROR, "%s: HWACCEL cannot be copied\n", __func__); ++ return -1; ++ } + +- for (i = 0; i < planes_nb; i++) { +- int size, h = height; +- if (i == 1 || i == 2) { ++ for (i = 0; i != desc->nb_components; ++i) { ++ if (desc->comp[i].plane >= num_planes) ++ num_planes = desc->comp[i].plane + 1; ++ pel_strides[desc->comp[i].plane] = desc->comp[i].step; ++ } ++ ++ if (out->num_planes > 1) { ++ if (num_planes != out->num_planes) { ++ av_log(NULL, AV_LOG_ERROR, "%s: Num planes mismatch: %d != %d\n", __func__, num_planes, out->num_planes); ++ return -1; ++ } ++ for (i = 0; i != num_planes; ++i) { ++ int w = frame->width; ++ int h = frame->height; ++ if (is_chroma(desc, i, num_planes)) { ++ w = AV_CEIL_RSHIFT(w, desc->log2_chroma_w); + h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); + } +- size = frame->linesize[i] * h; +- ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset, frame->buf[i]); +- if (ret) +- return ret; +- offset += size; ++ ++ cpy_2d(out->plane_info[i].mm_addr, out->plane_info[i].bytesperline, ++ frame->data[i], frame->linesize[i], ++ w * pel_strides[i], h); ++ set_buf_length(out, i, out->plane_info[i].bytesperline * h, out->plane_info[i].length); + } +- return 0; + } ++ else ++ { ++ unsigned int offset = 0; ++ ++ for (i = 0; i != num_planes; ++i) { ++ int w = frame->width; ++ int h = frame->height; ++ int dst_stride = out->plane_info[0].bytesperline; ++ uint8_t * const dst = (uint8_t *)out->plane_info[0].mm_addr + offset; ++ ++ if (is_chroma(desc, i, num_planes)) { ++ // Is chroma ++ dst_stride >>= desc->log2_chroma_w; ++ offset += dst_stride * (out->context->height >> desc->log2_chroma_h); ++ w = AV_CEIL_RSHIFT(w, desc->log2_chroma_w); ++ h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); ++ } ++ else { ++ // Is luma or alpha ++ offset += dst_stride * out->context->height; ++ } ++ if (offset > out->plane_info[0].length) { ++ av_log(NULL, AV_LOG_ERROR, "%s: Plane total %d > buffer size %d\n", __func__, offset, out->plane_info[0].length); ++ return -1; ++ } + +- for (i = 0; i < out->num_planes; i++) { +- ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0, frame->buf[i]); +- if (ret) +- return ret; ++ cpy_2d(dst, dst_stride, ++ frame->data[i], frame->linesize[i], ++ w * pel_strides[i], h); ++ } ++ set_buf_length(out, 0, offset, out->plane_info[0].length); + } +- + return 0; + } + +@@ -411,12 +584,12 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) + + int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out) + { +- v4l2_set_pts(out, frame->pts); ++ v4l2_set_pts(out, frame->pts, 0); + + return v4l2_buffer_swframe_to_buf(frame, out); + } + +-int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) ++int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf, int no_rescale_pts) + { + int ret; + +@@ -433,7 +606,7 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) + frame->colorspace = v4l2_get_color_space(avbuf); + frame->color_range = v4l2_get_color_range(avbuf); + frame->color_trc = v4l2_get_color_trc(avbuf); +- frame->pts = v4l2_get_pts(avbuf); ++ frame->pts = v4l2_get_pts(avbuf, no_rescale_pts); + frame->pkt_dts = AV_NOPTS_VALUE; + + /* these values are updated also during re-init in v4l2_process_driver_event */ +@@ -470,20 +643,27 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) + pkt->flags |= AV_PKT_FLAG_CORRUPT; + } + +- pkt->dts = pkt->pts = v4l2_get_pts(avbuf); ++ pkt->dts = pkt->pts = v4l2_get_pts(avbuf, 0); + + return 0; + } + +-int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) ++int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket *pkt, V4L2Buffer *out, ++ const void *extdata, size_t extlen, int no_rescale_pts) + { + int ret; + +- ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0, pkt->buf); ++ if (extlen) { ++ ret = v4l2_bufref_to_buf(out, 0, extdata, extlen, 0); ++ if (ret) ++ return ret; ++ } ++ ++ ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, extlen); + if (ret) + return ret; + +- v4l2_set_pts(out, pkt->pts); ++ v4l2_set_pts(out, pkt->pts, no_rescale_pts); + + if (pkt->flags & AV_PKT_FLAG_KEY) + out->flags = V4L2_BUF_FLAG_KEYFRAME; +@@ -491,6 +671,11 @@ int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) + return 0; + } + ++int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) ++{ ++ return ff_v4l2_buffer_avpkt_to_buf_ext(pkt, out, NULL, 0, 0); ++} ++ + int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + { + V4L2Context *ctx = avbuf->context; +@@ -500,6 +685,27 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + avbuf->buf.type = ctx->type; + avbuf->buf.index = index; + ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ AVHWFramesContext *hwframes; ++ ++ av_buffer_unref(&ctx->frames_ref); ++ ++ ctx->frames_ref = av_hwframe_ctx_alloc(buf_to_m2mctx(avbuf)->device_ref); ++ if (!ctx->frames_ref) { ++ ret = AVERROR(ENOMEM); ++ return ret; ++ } ++ ++ hwframes = (AVHWFramesContext*)ctx->frames_ref->data; ++ hwframes->format = AV_PIX_FMT_DRM_PRIME; ++ hwframes->sw_format = ctx->av_pix_fmt; ++ hwframes->width = ctx->width; ++ hwframes->height = ctx->height; ++ ret = av_hwframe_ctx_init(ctx->frames_ref); ++ if (ret < 0) ++ return ret; ++ } ++ + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->buf.length = VIDEO_MAX_PLANES; + avbuf->buf.m.planes = avbuf->planes; +@@ -527,14 +733,22 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length; +- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length, +- PROT_READ | PROT_WRITE, MAP_SHARED, +- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset); ++ ++ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) || ++ !buf_to_m2mctx(avbuf)->output_drm) { ++ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset); ++ } + } else { + avbuf->plane_info[i].length = avbuf->buf.length; +- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length, +- PROT_READ | PROT_WRITE, MAP_SHARED, +- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset); ++ ++ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) || ++ !buf_to_m2mctx(avbuf)->output_drm) { ++ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset); ++ } + } + + if (avbuf->plane_info[i].mm_addr == MAP_FAILED) +@@ -543,9 +757,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + + avbuf->status = V4L2BUF_AVAILABLE; + +- if (V4L2_TYPE_IS_OUTPUT(ctx->type)) +- return 0; +- + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->buf.m.planes = avbuf->planes; + avbuf->buf.length = avbuf->num_planes; +@@ -555,6 +766,15 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + avbuf->buf.length = avbuf->planes[0].length; + } + ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) ++ return 0; ++ ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ ret = v4l2_buffer_export_drm(avbuf); ++ if (ret) ++ return ret; ++ } ++ + return ff_v4l2_buffer_enqueue(avbuf); + } + +@@ -568,6 +788,9 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) + if (ret < 0) + return AVERROR(errno); + ++ ++avbuf->context->q_count; ++ av_log(logger(avbuf), AV_LOG_DEBUG, "--- %s VIDIOC_QBUF: index %d, count=%d\n", avbuf->context->name, avbuf->buf.index, avbuf->context->q_count); ++ + avbuf->status = V4L2BUF_IN_DRIVER; + + return 0; +diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h +index 8dbc7fc104..46ca85ce65 100644 +--- a/libavcodec/v4l2_buffers.h ++++ b/libavcodec/v4l2_buffers.h +@@ -27,6 +27,7 @@ + #include + #include + ++#include "libavutil/hwcontext_drm.h" + #include "avcodec.h" + + enum V4L2Buffer_status { +@@ -42,6 +43,9 @@ typedef struct V4L2Buffer { + /* each buffer needs to have a reference to its context */ + struct V4L2Context *context; + ++ /* DRM descriptor */ ++ AVDRMFrameDescriptor drm_frame; ++ + /* This object is refcounted per-plane, so we need to keep track + * of how many context-refs we are holding. */ + AVBufferRef *context_ref; +@@ -70,11 +74,12 @@ typedef struct V4L2Buffer { + * + * @param[in] frame The AVFRame to push the information to + * @param[in] buf The V4L2Buffer to get the information from ++ * @param[in] no_rescale_pts If non-zero do not rescale PTS + * + * @returns 0 in case of success, AVERROR(EINVAL) if the number of planes is incorrect, + * AVERROR(ENOMEM) if the AVBufferRef can't be created. + */ +-int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *buf); ++int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *buf, int no_rescale_pts); + + /** + * Extracts the data from a V4L2Buffer to an AVPacket +@@ -98,6 +103,9 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *buf); + */ + int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out); + ++int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket *pkt, V4L2Buffer *out, ++ const void *extdata, size_t extlen, int no_rescale_pts); ++ + /** + * Extracts the data from an AVFrame to a V4L2Buffer + * +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index 29b144ed73..31b406769b 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -173,7 +173,8 @@ static int v4l2_handle_event(V4L2Context *ctx) + } + + if (evt.type == V4L2_EVENT_EOS) { +- ctx->done = 1; ++// ctx->done = 1; ++ av_log(logger(ctx), AV_LOG_TRACE, "%s VIDIOC_EVENT_EOS\n", ctx->name); + return 0; + } + +@@ -280,6 +281,21 @@ static int v4l2_stop_encode(V4L2Context *ctx) + return 0; + } + ++static int count_in_driver(const V4L2Context * const ctx) ++{ ++ int i; ++ int n = 0; ++ ++ if (!ctx->buffers) ++ return -1; ++ ++ for (i = 0; i < ctx->num_buffers; ++i) { ++ if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) ++ ++n; ++ } ++ return n; ++} ++ + static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) + { + struct v4l2_plane planes[VIDEO_MAX_PLANES]; +@@ -296,11 +312,13 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) + break; + } ++#if 1 + if (i == ctx->num_buffers) +- av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to " ++ av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers (%d) returned to " + "userspace. Increase num_capture_buffers " + "to prevent device deadlock or dropped " +- "packets/frames.\n"); ++ "packets/frames.\n", i); ++#endif + } + + /* if we are draining and there are no more capture buffers queued in the driver we are done */ +@@ -329,11 +347,16 @@ start: + } + + for (;;) { +- ret = poll(&pfd, 1, timeout); ++ int t2 = timeout < 0 ? 3000 : timeout; ++ int e = pfd.events; ++ ret = poll(&pfd, 1, t2); + if (ret > 0) + break; + if (errno == EINTR) + continue; ++ if (timeout == -1) { ++ av_log(logger(ctx), AV_LOG_ERROR, "=== poll unexpected TIMEOUT: events=%#x, cap buffers=%d\n", e, count_in_driver(ctx));; ++ } + return NULL; + } + +@@ -398,23 +421,43 @@ dequeue: + if (ret) { + if (errno != EAGAIN) { + ctx->done = 1; +- if (errno != EPIPE) ++// if (errno != EPIPE) + av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n", + ctx->name, av_err2str(AVERROR(errno))); + } + return NULL; + } ++ --ctx->q_count; ++ av_log(logger(ctx), AV_LOG_TRACE, "--- %s VIDIOC_DQBUF OK: index=%d, count=%d\n", ++ ctx->name, buf.index, ctx->q_count); ++ + + if (ctx_to_m2mctx(ctx)->draining && !V4L2_TYPE_IS_OUTPUT(ctx->type)) { + int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ? + buf.m.planes[0].bytesused : buf.bytesused; + if (bytesused == 0) { ++ av_log(logger(ctx), AV_LOG_TRACE, "Buffer empty - reQ\n"); ++ ++ // Must reQ so we don't leak ++ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_QBUF, &buf); ++ if (ret) { ++ av_log(logger(ctx), AV_LOG_WARNING, "%s VIDIOC_QBUF, errno (%s): reQ empty buf failed\n", ++ ctx->name, av_err2str(AVERROR(errno))); ++ } ++ else { ++ ++ctx->q_count; ++ av_log(logger(ctx), AV_LOG_TRACE, "--- %s VIDIOC_QBUF OK: index=%d, count=%d\n", ++ ctx->name, buf.index, ctx->q_count); ++ } ++ + ctx->done = 1; + return NULL; + } + #ifdef V4L2_BUF_FLAG_LAST +- if (buf.flags & V4L2_BUF_FLAG_LAST) ++ if (buf.flags & V4L2_BUF_FLAG_LAST){ ++ av_log(logger(ctx), AV_LOG_TRACE, "FLAG_LAST set\n"); + ctx->done = 1; ++ } + #endif + } + +@@ -455,22 +498,54 @@ static int v4l2_release_buffers(V4L2Context* ctx) + struct v4l2_requestbuffers req = { + .memory = V4L2_MEMORY_MMAP, + .type = ctx->type, +- .count = 0, /* 0 -> unmaps buffers from the driver */ ++ .count = 0, /* 0 -> unmap all buffers from the driver */ + }; +- int i, j; ++ int ret, i, j; + + for (i = 0; i < ctx->num_buffers; i++) { + V4L2Buffer *buffer = &ctx->buffers[i]; + + for (j = 0; j < buffer->num_planes; j++) { + struct V4L2Plane_info *p = &buffer->plane_info[j]; ++ ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) { ++ /* output buffers are not EXPORTED */ ++ goto unmap; ++ } ++ ++ if (ctx_to_m2mctx(ctx)->output_drm) { ++ /* use the DRM frame to close */ ++ if (buffer->drm_frame.objects[j].fd >= 0) { ++ if (close(buffer->drm_frame.objects[j].fd) < 0) { ++ av_log(logger(ctx), AV_LOG_ERROR, "%s close drm fd " ++ "[buffer=%2d, plane=%d, fd=%2d] - %s \n", ++ ctx->name, i, j, buffer->drm_frame.objects[j].fd, ++ av_err2str(AVERROR(errno))); ++ } ++ } ++ } ++unmap: + if (p->mm_addr && p->length) + if (munmap(p->mm_addr, p->length) < 0) +- av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno))); ++ av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ++ ctx->name, av_err2str(AVERROR(errno))); + } + } + +- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); ++ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); ++ if (ret < 0) { ++ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n", ++ ctx->name, av_err2str(AVERROR(errno))); ++ ++ if (ctx_to_m2mctx(ctx)->output_drm) ++ av_log(logger(ctx), AV_LOG_ERROR, ++ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n" ++ "for all buffers: \n" ++ " 1. drmModeRmFB(..)\n" ++ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n"); ++ } ++ ++ return ret; + } + + static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt) +@@ -499,6 +574,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm + + static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) + { ++ V4L2m2mContext* s = ctx_to_m2mctx(ctx); ++ V4L2m2mPriv *priv = s->avctx->priv_data; + enum AVPixelFormat pixfmt = ctx->av_pix_fmt; + struct v4l2_fmtdesc fdesc; + int ret; +@@ -517,6 +594,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) + if (ret) + return AVERROR(EINVAL); + ++ if (priv->pix_fmt != AV_PIX_FMT_NONE) { ++ if (fdesc.pixelformat != ff_v4l2_format_avfmt_to_v4l2(priv->pix_fmt)) { ++ fdesc.index++; ++ continue; ++ } ++ } ++ + pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO); + ret = v4l2_try_raw_format(ctx, pixfmt); + if (ret){ +@@ -575,10 +659,16 @@ int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) + int ret; + + ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type); +- if (ret < 0) +- return AVERROR(errno); ++ if (ret < 0) { ++ const int err = errno; ++ av_log(logger(ctx), AV_LOG_ERROR, "%s set status %d (%s) failed: err=%d\n", ctx->name, ++ cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF", err); ++ return AVERROR(err); ++ } + + ctx->streamon = (cmd == VIDIOC_STREAMON); ++ av_log(logger(ctx), AV_LOG_DEBUG, "%s set status %d (%s) OK\n", ctx->name, ++ cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF"); + + return 0; + } +@@ -608,7 +698,8 @@ int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) + return ff_v4l2_buffer_enqueue(avbuf); + } + +-int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) ++int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt, ++ const void * extdata, size_t extlen, int no_rescale_pts) + { + V4L2m2mContext *s = ctx_to_m2mctx(ctx); + V4L2Buffer* avbuf; +@@ -616,8 +707,9 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) + + if (!pkt->size) { + ret = v4l2_stop_decode(ctx); ++ // Log but otherwise ignore stop failure + if (ret) +- av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode\n", ctx->name); ++ av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode failed: err=%d\n", ctx->name, ret); + s->draining = 1; + return 0; + } +@@ -626,14 +718,14 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) + if (!avbuf) + return AVERROR(EAGAIN); + +- ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf); ++ ret = ff_v4l2_buffer_avpkt_to_buf_ext(pkt, avbuf, extdata, extlen, no_rescale_pts); + if (ret) + return ret; + + return ff_v4l2_buffer_enqueue(avbuf); + } + +-int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) ++int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout, int no_rescale_pts) + { + V4L2Buffer *avbuf; + +@@ -650,7 +742,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) + return AVERROR(EAGAIN); + } + +- return ff_v4l2_buffer_buf_to_avframe(frame, avbuf); ++ return ff_v4l2_buffer_buf_to_avframe(frame, avbuf, no_rescale_pts); + } + + int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) +diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h +index 22a9532444..3484a25a9c 100644 +--- a/libavcodec/v4l2_context.h ++++ b/libavcodec/v4l2_context.h +@@ -92,6 +92,9 @@ typedef struct V4L2Context { + */ + int done; + ++ AVBufferRef *frames_ref; ++ int q_count; ++ + } V4L2Context; + + /** +@@ -156,9 +159,12 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt); + * @param[in] ctx The V4L2Context to dequeue from. + * @param[inout] f The AVFrame to dequeue to. + * @param[in] timeout The timeout for dequeue (-1 to block, 0 to return immediately, or milliseconds) ++ * @param[in] no_rescale_pts (0 rescale pts, 1 use pts as ++ * timestamp directly) ++ * + * @return 0 in case of success, AVERROR(EAGAIN) if no buffer was ready, another negative error in case of error. + */ +-int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); ++int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout, int no_rescale_pts); + + /** + * Enqueues a buffer to a V4L2Context from an AVPacket +@@ -170,7 +176,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); + * @param[in] pkt A pointer to an AVPacket. + * @return 0 in case of success, a negative error otherwise. + */ +-int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt); ++int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt, const void * ext_data, size_t ext_size, int no_rescale_pts); + + /** + * Enqueues a buffer to a V4L2Context from an AVFrame +diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c +index e48b3a8ccf..cac2b3e2f2 100644 +--- a/libavcodec/v4l2_m2m.c ++++ b/libavcodec/v4l2_m2m.c +@@ -338,18 +338,30 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + V4L2m2mContext *s = priv->context; + int ret; + +- ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); +- if (ret) +- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); ++ if (!s) ++ return 0; + +- ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); +- if (ret) +- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ if (av_codec_is_decoder(s->avctx->codec)) ++ av_packet_unref(&s->buf_pkt); ++ ++ if (s->fd >= 0) { ++ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); ++ if (ret) ++ av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); ++ ++ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); ++ if (ret) ++ av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ } + + ff_v4l2_context_release(&s->output); + + s->self_ref = NULL; ++ // This is only called on avctx close so after this point we don't have that ++ // Crash sooner if we find we are using it (can still log with avctx = NULL) ++ s->avctx = NULL; + av_buffer_unref(&priv->context_ref); ++ priv->context = NULL; + + return 0; + } +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 456281f48c..b08a5b38ac 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -30,6 +30,7 @@ + #include + + #include "libavcodec/avcodec.h" ++#include "libavutil/pixfmt.h" + #include "v4l2_context.h" + + #define container_of(ptr, type, member) ({ \ +@@ -38,7 +39,18 @@ + + #define V4L_M2M_DEFAULT_OPTS \ + { "num_output_buffers", "Number of buffers in the output context",\ +- OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS } ++ OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 2, INT_MAX, FLAGS } ++ ++#define FF_V4L2_M2M_TRACK_SIZE 128 ++typedef struct V4L2m2mTrackEl { ++ int discard; // If we see this buffer its been flushed, so discard ++ int pkt_size; ++ int64_t pts; ++ int64_t reordered_opaque; ++ int64_t pkt_pos; ++ int64_t pkt_duration; ++ int64_t track_pts; ++} V4L2m2mTrackEl; + + typedef struct V4L2m2mContext { + char devname[PATH_MAX]; +@@ -63,6 +75,23 @@ typedef struct V4L2m2mContext { + + /* reference back to V4L2m2mPriv */ + void *priv; ++ ++ AVBufferRef *device_ref; ++ ++ /* generate DRM frames */ ++ int output_drm; ++ ++ /* Frame tracking */ ++ int64_t last_pkt_dts; ++ int64_t last_opaque; ++ unsigned int track_no; ++ V4L2m2mTrackEl track_els[FF_V4L2_M2M_TRACK_SIZE]; ++ ++ /* req pkt */ ++ int req_pkt; ++ ++ /* Ext data sent */ ++ int extdata_sent; + } V4L2m2mContext; + + typedef struct V4L2m2mPriv { +@@ -73,6 +102,7 @@ typedef struct V4L2m2mPriv { + + int num_output_buffers; + int num_capture_buffers; ++ enum AVPixelFormat pix_fmt; + } V4L2m2mPriv; + + /** +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 3e17e0fcac..678d390103 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -23,6 +23,10 @@ + + #include + #include ++ ++#include "libavutil/avassert.h" ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" + #include "libavutil/pixfmt.h" + #include "libavutil/pixdesc.h" + #include "libavutil/opt.h" +@@ -30,26 +34,51 @@ + #include "libavcodec/decode.h" + #include "libavcodec/internal.h" + ++#include "libavcodec/hwaccels.h" ++#include "libavcodec/internal.h" ++#include "libavcodec/hwconfig.h" ++ + #include "v4l2_context.h" + #include "v4l2_m2m.h" + #include "v4l2_fmt.h" + ++static int check_output_streamon(AVCodecContext *const avctx, V4L2m2mContext *const s) ++{ ++ int ret; ++ struct v4l2_decoder_cmd cmd = { ++ .cmd = V4L2_DEC_CMD_START, ++ .flags = 0, ++ }; ++ ++ if (s->output.streamon) ++ return 0; ++ ++ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMON); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON on output context\n"); ++ ++ if (!s->capture.streamon || ret < 0) ++ return ret; ++ ++ ret = ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_DECODER_CMD start error: %d\n", errno); ++ else ++ av_log(avctx, AV_LOG_DEBUG, "VIDIOC_DECODER_CMD start OK\n"); ++ ++ return ret; ++} ++ + static int v4l2_try_start(AVCodecContext *avctx) + { + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; + V4L2Context *const capture = &s->capture; +- V4L2Context *const output = &s->output; + struct v4l2_selection selection = { 0 }; + int ret; + + /* 1. start the output process */ +- if (!output->streamon) { +- ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON); +- if (ret < 0) { +- av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON on output context\n"); +- return ret; +- } +- } ++ if ((ret = check_output_streamon(avctx, s)) != 0) ++ return ret; + + if (capture->streamon) + return 0; +@@ -63,8 +92,14 @@ static int v4l2_try_start(AVCodecContext *avctx) + } + + /* 2.1 update the AVCodecContext */ +- avctx->pix_fmt = ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO); +- capture->av_pix_fmt = avctx->pix_fmt; ++ capture->av_pix_fmt = ++ ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO); ++ if (s->output_drm) { ++ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; ++ avctx->sw_pix_fmt = capture->av_pix_fmt; ++ } ++ else ++ avctx->pix_fmt = capture->av_pix_fmt; + + /* 3. set the crop parameters */ + selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +@@ -133,54 +168,286 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) + return 0; + } + +-static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ++static inline int64_t track_to_pts(AVCodecContext *avctx, unsigned int n) + { +- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; +- V4L2Context *const capture = &s->capture; +- V4L2Context *const output = &s->output; +- AVPacket avpkt = {0}; +- int ret; ++ return (int64_t)n; ++} ++ ++static inline unsigned int pts_to_track(AVCodecContext *avctx, const int64_t pts) ++{ ++ return (unsigned int)pts; ++} ++ ++// FFmpeg requires us to propagate a number of vars from the coded pkt into ++// the decoded frame. The only thing that tracks like that in V4L2 stateful ++// is timestamp. PTS maps to timestamp for this decode. FFmpeg makes no ++// guarantees about PTS being unique or specified for every frame so replace ++// the supplied PTS with a simple incrementing number and keep a circular ++// buffer of all the things we want preserved (including the original PTS) ++// indexed by the tracking no. ++static void ++xlat_pts_in(AVCodecContext *const avctx, V4L2m2mContext *const s, AVPacket *const avpkt) ++{ ++ int64_t track_pts; ++ ++ // Avoid 0 ++ if (++s->track_no == 0) ++ s->track_no = 1; ++ ++ track_pts = track_to_pts(avctx, s->track_no); ++ ++ av_log(avctx, AV_LOG_TRACE, "In PTS=%" PRId64 ", DTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", avpkt->pts, avpkt->dts, track_pts, s->track_no); ++ s->last_pkt_dts = avpkt->dts; ++ s->track_els[s->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){ ++ .discard = 0, ++ .pkt_size = avpkt->size, ++ .pts = avpkt->pts, ++ .reordered_opaque = avctx->reordered_opaque, ++ .pkt_pos = avpkt->pos, ++ .pkt_duration = avpkt->duration, ++ .track_pts = track_pts ++ }; ++ avpkt->pts = track_pts; ++} ++ ++// Returns -1 if we should discard the frame ++static int ++xlat_pts_out(AVCodecContext *const avctx, V4L2m2mContext *const s, AVFrame *const frame) ++{ ++ unsigned int n = pts_to_track(avctx, frame->pts) % FF_V4L2_M2M_TRACK_SIZE; ++ const V4L2m2mTrackEl *const t = s->track_els + n; ++ if (frame->pts == AV_NOPTS_VALUE || frame->pts != t->track_pts) ++ { ++ av_log(avctx, AV_LOG_INFO, "Tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts); ++ frame->pts = AV_NOPTS_VALUE; ++ frame->pkt_dts = s->last_pkt_dts; ++ frame->reordered_opaque = s->last_opaque; ++ frame->pkt_pos = -1; ++ frame->pkt_duration = 0; ++ frame->pkt_size = -1; ++ } ++ else if (!t->discard) ++ { ++ frame->pts = t->pts; ++ frame->pkt_dts = s->last_pkt_dts; ++ frame->reordered_opaque = t->reordered_opaque; ++ frame->pkt_pos = t->pkt_pos; ++ frame->pkt_duration = t->pkt_duration; ++ frame->pkt_size = t->pkt_size; ++ ++ s->last_opaque = s->track_els[n].reordered_opaque; ++ s->track_els[n].pts = AV_NOPTS_VALUE; // If we hit this again deny accurate knowledge of PTS ++ } ++ else ++ { ++ av_log(avctx, AV_LOG_DEBUG, "Discard frame (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts); ++ return -1; ++ } ++ ++#if FF_API_PKT_PTS ++FF_DISABLE_DEPRECATION_WARNINGS ++ frame->pkt_pts = frame->pts; ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ frame->best_effort_timestamp = frame->pts; ++ frame->pkt_dts = frame->pts; // We can't emulate what s/w does in a useful manner? ++ av_log(avctx, AV_LOG_TRACE, "Out PTS=%" PRId64 ", DTS=%" PRId64 "\n", frame->pts, frame->pkt_dts); ++ return 0; ++} ++ ++static inline int stream_started(const V4L2m2mContext * const s) { ++ return s->capture.streamon && s->output.streamon; ++} ++ ++#define NQ_OK 0 ++#define NQ_Q_FULL 1 ++#define NQ_SRC_EMPTY 2 ++#define NQ_DRAINING 3 ++#define NQ_DEAD 4 + +- if (s->buf_pkt.size) { +- avpkt = s->buf_pkt; +- memset(&s->buf_pkt, 0, sizeof(AVPacket)); +- } else { +- ret = ff_decode_get_packet(avctx, &avpkt); +- if (ret < 0 && ret != AVERROR_EOF) ++#define TRY_DQ(nq_status) ((nq_status) >= NQ_OK && (nq_status) <= NQ_DRAINING) ++ ++// AVERROR_EOF Flushing an already flushed stream ++// -ve Error (all errors except EOF are unexpected) ++// NQ_OK (0) OK ++// NQ_Q_FULL Dst full (retry if we think V4L2 Q has space now) ++// NQ_SRC_EMPTY Src empty (do not retry) ++// NQ_DRAINING At EOS, dQ dest until EOS there too ++// NQ_DEAD Not running (do not retry, do not attempt capture dQ) ++ ++static int try_enqueue_src(AVCodecContext * const avctx, V4L2m2mContext * const s) ++{ ++ int ret = 0; ++ int ret2 = 0; ++ ++ if (!s->buf_pkt.size) { ++ ret = ff_decode_get_packet(avctx, &s->buf_pkt); ++ ++ if (ret == AVERROR(EAGAIN)) { ++ if (!stream_started(s)) { ++ av_log(avctx, AV_LOG_TRACE, "%s: receive_frame before 1st coded packet\n", __func__); ++ return NQ_DEAD; ++ } ++ return NQ_SRC_EMPTY; ++ } ++ ++ if (ret == AVERROR_EOF) { ++ // EOF - enter drain mode ++ av_log(avctx, AV_LOG_TRACE, "--- EOS req: ret=%d, size=%d, started=%d, drain=%d\n", ++ ret, s->buf_pkt.size, stream_started(s), s->draining); ++ if (!stream_started(s)) { ++ av_log(avctx, AV_LOG_DEBUG, "EOS on flushed stream\n"); ++ s->draining = 1; ++ s->capture.done = 1; ++ return AVERROR_EOF; ++ } ++ ++ if (!s->draining) { ++ // Calling enqueue with an empty pkt starts drain ++ av_assert0(s->buf_pkt.size == 0); ++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, NULL, 0, 1); ++ if (ret) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to start drain: ret=%d\n", ret); ++ return ret; ++ } ++ } ++ return NQ_DRAINING; ++ } ++ ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get coded packet: err=%d\n", ret); + return ret; ++ } ++ ++ xlat_pts_in(avctx, s, &s->buf_pkt); + } + +- if (s->draining) +- goto dequeue; ++ if ((ret = check_output_streamon(avctx, s)) != 0) ++ return ret; + +- ret = ff_v4l2_context_enqueue_packet(output, &avpkt); +- if (ret < 0) { +- if (ret != AVERROR(EAGAIN)) +- return ret; ++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, ++ avctx->extradata, s->extdata_sent ? 0 : avctx->extradata_size, ++ 1); + +- s->buf_pkt = avpkt; +- /* no input buffers available, continue dequeing */ ++ if (ret == AVERROR(EAGAIN)) { ++ // Out of input buffers - keep packet ++ ret = NQ_Q_FULL; + } ++ else { ++ // In all other cases we are done with this packet ++ av_packet_unref(&s->buf_pkt); ++ s->extdata_sent = 1; + +- if (avpkt.size) { +- ret = v4l2_try_start(avctx); + if (ret) { +- av_packet_unref(&avpkt); ++ av_log(avctx, AV_LOG_ERROR, "Packet enqueue failure: err=%d\n", ret); ++ return ret; ++ } ++ } ++ ++ // Start if we haven't ++ ret2 = v4l2_try_start(avctx); ++ if (ret2) { ++ av_log(avctx, AV_LOG_DEBUG, "Start failure: err=%d\n", ret2); ++ ret = (ret2 == AVERROR(ENOMEM)) ? ret2 : NQ_DEAD; ++ } ++ ++ return ret; ++} ++ ++static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ++{ ++ V4L2m2mContext *const s = ((V4L2m2mPriv*)avctx->priv_data)->context; ++ int src_rv; ++ int dst_rv = 1; // Non-zero (done), non-negative (error) number ++ ++ do { ++ src_rv = try_enqueue_src(avctx, s); ++ ++ // If we got a frame last time and we have nothing to enqueue then ++ // return now. rv will be AVERROR(EAGAIN) indicating that we want more input ++ // This should mean that once decode starts we enter a stable state where ++ // we alternately ask for input and produce output ++ if (s->req_pkt && src_rv == NQ_SRC_EMPTY) ++ break; ++ ++ if (src_rv == NQ_Q_FULL && dst_rv == AVERROR(EAGAIN)) { ++ av_log(avctx, AV_LOG_WARNING, "Poll says src Q has space but enqueue fail"); ++ src_rv = NQ_SRC_EMPTY; // If we can't enqueue pretend that there is nothing to enqueue ++ } + +- /* cant recover */ +- if (ret == AVERROR(ENOMEM)) +- return ret; ++ // Try to get a new frame if ++ // (a) we haven't already got one AND ++ // (b) enqueue returned a status indicating that decode should be attempted ++ if (dst_rv != 0 && TRY_DQ(src_rv)) { ++ do { ++ // Dequeue frame will unref any previous contents of frame ++ // so we don't need an explicit unref when discarding ++ // This returns AVERROR(EAGAIN) if there isn't a frame ready yet ++ // but there is room in the input Q ++ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, -1, 1); ++ ++ if (dst_rv == AVERROR_EOF && (s->draining || s->capture.done)) ++ av_log(avctx, AV_LOG_DEBUG, "Dequeue EOF: draining=%d, cap.done=%d\n", ++ s->draining, s->capture.done); ++ else if (dst_rv && dst_rv != AVERROR(EAGAIN)) ++ av_log(avctx, AV_LOG_ERROR, "Packet dequeue failure: draining=%d, cap.done=%d, err=%d\n", ++ s->draining, s->capture.done, dst_rv); ++ ++ // Go again if we got a frame that we need to discard ++ } while (dst_rv == 0 && xlat_pts_out(avctx, s, frame)); ++ } + +- return 0; ++ // Continue trying to enqueue packets if either ++ // (a) we succeeded last time OR ++ // (b) enqueue failed due to input Q full AND there is now room ++ } while (src_rv == NQ_OK || (src_rv == NQ_Q_FULL && dst_rv == AVERROR(EAGAIN)) ); ++ ++ if (dst_rv) ++ av_frame_unref(frame); ++ ++ // If we got a frame this time ask for a pkt next time ++ s->req_pkt = (dst_rv == 0); ++ ++#if 0 ++ if (dst_rv == 0) ++ { ++ static int z = 0; ++ if (++z > 50) { ++ av_log(avctx, AV_LOG_ERROR, "Streamoff and die?\n"); ++ ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); ++ return -1; + } + } ++#endif + +-dequeue: +- if (!s->buf_pkt.size) +- av_packet_unref(&avpkt); +- return ff_v4l2_context_dequeue_frame(capture, frame, -1); ++ return dst_rv == 0 ? 0 : ++ src_rv < 0 ? src_rv : ++ dst_rv < 0 ? dst_rv : ++ AVERROR(EAGAIN); ++} ++ ++#if 0 ++#include ++static int64_t us_time(void) ++{ ++ struct timespec ts; ++ clock_gettime(CLOCK_MONOTONIC, &ts); ++ return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + } + ++static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ++{ ++ int ret; ++ const int64_t now = us_time(); ++ int64_t done; ++ av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__); ++ ret = v4l2_receive_frame2(avctx, frame); ++ done = us_time(); ++ av_log(avctx, AV_LOG_TRACE, ">>> %s: rx time=%" PRId64 ", rv=%d\n", __func__, done - now, ret); ++ return ret; ++} ++#endif ++ + static av_cold int v4l2_decode_init(AVCodecContext *avctx) + { + V4L2Context *capture, *output; +@@ -188,6 +455,9 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + V4L2m2mPriv *priv = avctx->priv_data; + int ret; + ++ av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__); ++ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; ++ + ret = ff_v4l2_m2m_create_context(priv, &s); + if (ret < 0) + return ret; +@@ -208,13 +478,32 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; + capture->av_pix_fmt = avctx->pix_fmt; + ++ /* the client requests the codec to generate DRM frames: ++ * - data[0] will therefore point to the returned AVDRMFrameDescriptor ++ * check the ff_v4l2_buffer_to_avframe conversion function. ++ * - the DRM frame format is passed in the DRM frame descriptor layer. ++ * check the v4l2_get_drm_frame function. ++ */ ++ switch (ff_get_format(avctx, avctx->codec->pix_fmts)) { ++ default: ++ s->output_drm = 1; ++ break; ++ } ++ ++ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM); ++ if (!s->device_ref) { ++ ret = AVERROR(ENOMEM); ++ return ret; ++ } ++ ++ ret = av_hwdevice_ctx_init(s->device_ref); ++ if (ret < 0) ++ return ret; ++ + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); +- s->self_ref = NULL; +- av_buffer_unref(&priv->context_ref); +- + return ret; + } + +@@ -223,10 +512,59 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + + static av_cold int v4l2_decode_close(AVCodecContext *avctx) + { ++ int rv; ++ av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__); ++ rv = ff_v4l2_m2m_codec_end(avctx->priv_data); ++ av_log(avctx, AV_LOG_TRACE, ">>> %s: rv=%d\n", __func__, rv); ++ return rv; ++} ++ ++static void v4l2_decode_flush(AVCodecContext *avctx) ++{ ++ // An alternatve and more drastic form of flush is to simply do this: ++ // v4l2_decode_close(avctx); ++ // v4l2_decode_init(avctx); ++ // The downside is that this keeps a decoder open until all the frames ++ // associated with it have been returned. This is a bit wasteful on ++ // possibly limited h/w resources and fails on a Pi for this reason unless ++ // more GPU mem is allocated than is the default. ++ + V4L2m2mPriv *priv = avctx->priv_data; +- V4L2m2mContext *s = priv->context; +- av_packet_unref(&s->buf_pkt); +- return ff_v4l2_m2m_codec_end(priv); ++ V4L2m2mContext* s = priv->context; ++ V4L2Context* output = &s->output; ++ V4L2Context* capture = &s->capture; ++ int ret, i; ++ ++ av_log(avctx, AV_LOG_TRACE, "<<< %s: streamon=%d\n", __func__, output->streamon); ++ ++ if (!output->streamon) ++ goto done; ++ ++ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s error: %d\n", output->name, ret); ++ ++ for (i = 0; i < output->num_buffers; i++) { ++ if (output->buffers[i].status == V4L2BUF_IN_DRIVER) ++ output->buffers[i].status = V4L2BUF_AVAILABLE; ++ } ++ ++ // V4L2 makes no guarantees about whether decoded frames are flushed or not ++ // so mark all frames we are tracking to be discarded if they appear ++ for (i = 0; i != FF_V4L2_M2M_TRACK_SIZE; ++i) ++ s->track_els[i].discard = 1; ++ ++ // resend extradata ++ s->extdata_sent = 0; ++ // clear EOS status vars ++ s->draining = 0; ++ output->done = 0; ++ capture->done = 0; ++ ++ // Stream on will occur when we actually submit a new frame ++ ++done: ++ av_log(avctx, AV_LOG_TRACE, ">>> %s\n", __func__); + } + + #define OFFSET(x) offsetof(V4L2m2mPriv, x) +@@ -235,10 +573,16 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) + static const AVOption options[] = { + V4L_M2M_DEFAULT_OPTS, + { "num_capture_buffers", "Number of buffers in the capture context", +- OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, ++ OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS }, ++ { "pixel_format", "Pixel format to be used by the decoder", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, AV_PIX_FMT_NB, FLAGS }, + { NULL}, + }; + ++static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = { ++ HW_CONFIG_INTERNAL(DRM_PRIME), ++ NULL ++}; ++ + #define M2MDEC_CLASS(NAME) \ + static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ + .class_name = #NAME "_v4l2m2m_decoder", \ +@@ -259,9 +603,14 @@ static const AVOption options[] = { + .init = v4l2_decode_init, \ + .receive_frame = v4l2_receive_frame, \ + .close = v4l2_decode_close, \ ++ .flush = v4l2_decode_flush, \ + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ +- .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ ++ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ ++ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NV12, \ ++ AV_PIX_FMT_NONE}, \ ++ .hw_configs = v4l2_m2m_hw_configs, \ + .wrapper_name = "v4l2m2m", \ + } + +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index 32321f392f..9f1b2c2ffc 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -416,6 +416,7 @@ static const AVCodecDefault v4l2_m2m_defaults[] = { + .close = v4l2_encode_close, \ + .defaults = v4l2_m2m_defaults, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "v4l2m2m", \ + } + +diff --git a/libavcodec/v4l2_phase.c b/libavcodec/v4l2_phase.c +new file mode 100644 +index 0000000000..0a7f6abd33 +--- /dev/null ++++ b/libavcodec/v4l2_phase.c +@@ -0,0 +1,140 @@ ++// v4l2_phase.c ++ ++#include ++#include ++#include ++ ++#include "libavutil/log.h" ++#include "v4l2_phase.h" ++ ++typedef struct phase_envss { ++ unsigned int last_order; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++} phase_env; ++ ++struct V4L2PhaseControl { ++ unsigned int order; ++ unsigned int phase_count; ++ phase_env p[V4L2PHASE_PHASE_COUNT]; ++}; ++ ++ ++unsigned int ff_v4l2_phase_order_next(V4L2PhaseControl * const pc) ++{ ++ return ++pc->order; ++} ++ ++// Phase isn't required but it acts as a check that we know what we are doing ++int ++ff_v4l2_phase_claim(V4L2PhaseInfo * const pi, unsigned int phase) ++{ ++ V4L2PhaseControl *const pc = pi->ctrl; ++ phase_env * const p = pc->p + phase; ++ ++ if (pi->n2 != phase * 2) { ++ av_log(NULL, AV_LOG_ERROR, "%s: Unexpected phase: req=%d, cur=%d/%d\n", __func__, phase, pi->n2 >> 1, pi->n2 & 1); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&p->lock); ++ ++ while (pi->order != p->last_order + 1) { ++ pthread_cond_wait(&p->cond, &p->lock); ++ } ++ ++ pi->n2++; ++ pthread_mutex_unlock(&p->lock); ++ return 0; ++} ++ ++int ++ff_v4l2_phase_release(V4L2PhaseInfo * const pi, unsigned int phase) ++{ ++ V4L2PhaseControl *const pc = pi->ctrl; ++ phase_env * const p = pc->p + phase; ++ ++ if (pi->n2 != ((phase << 1) | 1)) { ++ av_log(NULL, AV_LOG_ERROR, "%s: Unexpected phase: req=%d, cur=%d/%d\n", __func__, phase, pi->n2 >> 1, pi->n2 & 1); ++ return -1; ++ } ++ ++ if (pi->order != p->last_order + 1) { ++ av_log(NULL, AV_LOG_ERROR, "%s: order_mismatch\n", __func__); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&p->lock); ++ p->last_order = pi->order; ++ pi->n2++; ++ pthread_cond_broadcast(&p->cond); ++ pthread_mutex_unlock(&p->lock); ++ return 0; ++} ++ ++// Init the PhaseInfo, assign a new order, claim phase 0 ++int ++ff_v4l2_phase_start(V4L2PhaseInfo * const pi, V4L2PhaseControl * const pc) ++{ ++ pi->n2 = 0; ++ pi->ctrl = pc; ++ pi->order = ff_v4l2_phase_order_next(pc); ++ return ff_v4l2_phase_claim(pi, 0); ++} ++ ++// Release any claimed phase and claim+release all remaining phases ++void ff_v4l2_phase_abort(V4L2PhaseInfo * const pi) ++{ ++ V4L2PhaseControl *const pc = pi->ctrl; ++ ++ // Nothing to do ++ if (pi->n2 == 0 || pi->n2 >= pc->phase_count * 2) ++ return; ++ ++ // Run through all remaining phases ++ do { ++ if ((pi->n2 & 1) == 0) ++ ff_v4l2_phase_claim(pi, pi->n2 >> 1); ++ else ++ ff_v4l2_phase_release(pi, pi->n2 >> 1); ++ } while (pi->n2 < pc->phase_count * 2); ++} ++ ++ ++V4L2PhaseControl * ++ff_v4l2_phase_control_new(unsigned int phase_count) ++{ ++ V4L2PhaseControl * pc; ++ unsigned int i; ++ if (phase_count > V4L2PHASE_PHASE_COUNT) ++ return NULL; ++ if ((pc = av_mallocz(sizeof(*pc))) == NULL) ++ return NULL; ++ pc->phase_count = phase_count; ++ for (i = 0; i != phase_count; ++i) { ++ phase_env * const p = pc->p + i; ++ p->last_order = 0; ++ pthread_mutex_init(&p->lock, NULL); ++ pthread_cond_init(&p->cond, NULL); ++ } ++ return pc; ++} ++ ++void ++ff_v4l2_phase_control_deletez(V4L2PhaseControl ** const ppc) ++{ ++ V4L2PhaseControl * const pc = *ppc; ++ unsigned int i; ++ ++ if (pc == NULL) ++ return; ++ *ppc = NULL; ++ ++ for (i = 0; i != pc->phase_count; ++i) { ++ phase_env * const p = pc->p + i; ++ pthread_mutex_destroy(&p->lock); ++ pthread_cond_destroy(&p->cond); ++ } ++} ++ ++ +diff --git a/libavcodec/v4l2_phase.h b/libavcodec/v4l2_phase.h +new file mode 100644 +index 0000000000..392f22b988 +--- /dev/null ++++ b/libavcodec/v4l2_phase.h +@@ -0,0 +1,37 @@ ++// v4l2_phase.h ++#ifndef AVCODEC_V4L2_PHASE_H ++#define AVCODEC_V4L2_PHASE_H ++ ++#define V4L2PHASE_PHASE_COUNT 2 ++ ++struct V4L2PhaseControl; ++typedef struct V4L2PhaseControl V4L2PhaseControl; ++ ++typedef struct V4L2PhaseInfo { ++ unsigned int n2; // (phase << 1) | (claimed) ++ unsigned int order; ++ V4L2PhaseControl * ctrl; ++} V4L2PhaseInfo; ++ ++unsigned int ff_v4l2_phase_order_next(V4L2PhaseControl * const pc); ++ ++static inline int ff_v4l2_phase_started(const V4L2PhaseInfo * const pi) ++{ ++ return pi->n2 != 0; ++} ++ ++// Init the PhaseInfo, assign a new order, claim phase 0 ++int ff_v4l2_phase_start(V4L2PhaseInfo * const pi, V4L2PhaseControl * const pc); ++ ++// Phase isn't required but it acts as a check that we know what we are doing ++int ff_v4l2_phase_claim(V4L2PhaseInfo * const pi, unsigned int phase); ++int ff_v4l2_phase_release(V4L2PhaseInfo * const pi, unsigned int phase); ++ ++// Release any claimed phase and claim+release all remaining phases ++void ff_v4l2_phase_abort(V4L2PhaseInfo * const pi); ++ ++ ++V4L2PhaseControl * ff_v4l2_phase_control_new(unsigned int phase_count); ++void ff_v4l2_phase_control_deletez(V4L2PhaseControl ** const ppc); ++ ++#endif +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +new file mode 100644 +index 0000000000..2306c21836 +--- /dev/null ++++ b/libavcodec/v4l2_request.c +@@ -0,0 +1,1094 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "decode.h" ++#include "internal.h" ++#include "v4l2_request.h" ++#include "v4l2_phase.h" ++ ++#ifndef DRM_FORMAT_NV15 ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') ++#endif ++ ++#ifndef DRM_FORMAT_NV20 ++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') ++#endif ++ ++// P030 should be defined in drm_fourcc.h and hopefully will be sometime ++// in the future but until then... ++#ifndef DRM_FORMAT_P030 ++#define DRM_FORMAT_P030 fourcc_code('P', '0', '3', '0') ++#endif ++ ++#ifndef DRM_FORMAT_NV15 ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') ++#endif ++ ++#ifndef DRM_FORMAT_NV20 ++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') ++#endif ++ ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ return req ? v4l2_timeval_to_ns(&req->capture.buffer.timestamp) : 0; ++} ++ ++int ff_v4l2_request_start_phase_control(AVFrame *frame, struct V4L2PhaseControl * ctrl) ++{ ++ V4L2RequestDescriptor * const req = (V4L2RequestDescriptor*)frame->data[0]; ++ return ff_v4l2_phase_start(&req->phase, ctrl); ++} ++ ++void ff_v4l2_request_abort_phase_control(AVFrame *frame) ++{ ++ if (frame != NULL && frame->data[0] != NULL) { ++ V4L2RequestDescriptor *const req = (V4L2RequestDescriptor *)frame->data[0]; ++ ff_v4l2_phase_abort(&req->phase); ++ } ++} ++ ++int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ memset(&req->drm, 0, sizeof(AVDRMFrameDescriptor)); ++ req->output.used = 0; ++ return 0; ++} ++ ++int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ if (req->output.used + size + (AV_INPUT_BUFFER_PADDING_SIZE * 4) <= req->output.size) { ++ memcpy(req->output.addr + req->output.used, data, size); ++ req->output.used += size; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "%s: output.used=%u output.size=%u size=%u\n", __func__, req->output.used, req->output.size, size); ++ } ++ return 0; ++} ++ ++static int v4l2_request_controls(V4L2RequestContext *ctx, int request_fd, unsigned long type, struct v4l2_ext_control *control, int count) ++{ ++ struct v4l2_ext_controls controls = { ++ .controls = control, ++ .count = count, ++ .request_fd = request_fd, ++ .which = (request_fd >= 0) ? V4L2_CTRL_WHICH_REQUEST_VAL : 0, ++ }; ++ ++ if (!control || !count) ++ return 0; ++ ++ return ioctl(ctx->video_fd, type, &controls); ++} ++ ++static int v4l2_request_set_controls(V4L2RequestContext *ctx, int request_fd, struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_controls(ctx, request_fd, VIDIOC_S_EXT_CTRLS, control, count); ++} ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = v4l2_request_controls(ctx, -1, VIDIOC_S_EXT_CTRLS, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return ret; ++} ++ ++int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = v4l2_request_controls(ctx, -1, VIDIOC_G_EXT_CTRLS, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return ret; ++} ++ ++int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control) ++{ ++ int ret; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERY_EXT_CTRL, control); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id) ++{ ++ int ret; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_queryctrl control = { ++ .id = id, ++ }; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYCTRL, &control); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return control.default_value; ++} ++ ++static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf, uint32_t flags) ++{ ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_buffer buffer = { ++ .type = buf->buffer.type, ++ .memory = buf->buffer.memory, ++ .index = buf->index, ++ .timestamp.tv_usec = ctx->timestamp, ++ .bytesused = buf->used, ++ .request_fd = request_fd, ++ .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags, ++ }; ++ ++ buf->buffer.timestamp = buffer.timestamp; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { ++ planes[0].bytesused = buf->used; ++ buffer.bytesused = 0; ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ return ioctl(ctx->video_fd, VIDIOC_QBUF, &buffer); ++} ++ ++static int v4l2_request_dequeue_buffer(V4L2RequestContext *ctx, V4L2RequestBuffer *buf) ++{ ++ int ret; ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_buffer buffer = { ++ .type = buf->buffer.type, ++ .memory = buf->buffer.memory, ++ .index = buf->index, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_DQBUF, &buffer); ++ if (ret < 0) ++ return ret; ++ ++ buf->buffer.timestamp = buffer.timestamp; ++ buf->buffer.flags = buffer.flags; ++ return 0; ++} ++ ++const uint32_t v4l2_request_capture_pixelformats[] = { ++#if CONFIG_SAND ++ V4L2_PIX_FMT_NV12_COL128, ++ V4L2_PIX_FMT_NV12_10_COL128, ++#endif ++ V4L2_PIX_FMT_NV12, ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ V4L2_PIX_FMT_SUNXI_TILED_NV12, ++#endif ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ V4L2_PIX_FMT_NV15, ++#endif ++ V4L2_PIX_FMT_NV16, ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ V4L2_PIX_FMT_NV20, ++#endif ++}; ++ ++static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format) ++{ ++ AVDRMFrameDescriptor *desc = &req->drm; ++ AVDRMLayerDescriptor *layer = &desc->layers[0]; ++ uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.pixelformat : format->fmt.pix.pixelformat; ++ ++ switch (pixelformat) { ++ case V4L2_PIX_FMT_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#if CONFIG_SAND ++ case V4L2_PIX_FMT_NV12_COL128: ++ layer->format = DRM_FORMAT_NV12; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(format->fmt.pix.bytesperline); ++ break; ++ case V4L2_PIX_FMT_NV12_10_COL128: ++ layer->format = DRM_FORMAT_P030; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(format->fmt.pix.bytesperline); ++ break; ++#endif ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ case V4L2_PIX_FMT_SUNXI_TILED_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_ALLWINNER_TILED; ++ break; ++#endif ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ case V4L2_PIX_FMT_NV15: ++ layer->format = DRM_FORMAT_NV15; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#endif ++ case V4L2_PIX_FMT_NV16: ++ layer->format = DRM_FORMAT_NV16; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ case V4L2_PIX_FMT_NV20: ++ layer->format = DRM_FORMAT_NV20; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#endif ++ default: ++ return -1; ++ } ++ ++ desc->nb_objects = 1; ++ desc->objects[0].fd = req->capture.fd; ++ desc->objects[0].size = req->capture.size; ++ ++ desc->nb_layers = 1; ++ layer->nb_planes = 2; ++ ++ layer->planes[0].object_index = 0; ++ layer->planes[0].offset = 0; ++ layer->planes[0].pitch = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.plane_fmt[0].bytesperline : format->fmt.pix.bytesperline; ++#if CONFIG_SAND ++ if (pixelformat == V4L2_PIX_FMT_NV12_COL128) { ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = format->fmt.pix.height * 128; ++ layer->planes[0].pitch = format->fmt.pix.width; ++ layer->planes[1].pitch = format->fmt.pix.width; ++ } ++ else if (pixelformat == V4L2_PIX_FMT_NV12_10_COL128) { ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = format->fmt.pix.height * 128; ++ layer->planes[0].pitch = format->fmt.pix.width * 2; // Lies but it keeps DRM import happy ++ layer->planes[1].pitch = format->fmt.pix.width * 2; ++ } ++ else ++#endif ++ { ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height); ++ layer->planes[1].pitch = layer->planes[0].pitch; ++ } ++ ++ return 0; ++} ++ ++static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ struct timeval tv = { 2, 0 }; ++ fd_set except_fds; ++ int ret; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice); ++ ++ if (first_slice) ++ ctx->timestamp++; ++ ++ ret = v4l2_request_set_controls(ctx, req->request_fd, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ memset(req->output.addr + req->output.used, 0, AV_INPUT_BUFFER_PADDING_SIZE * 4); ++ ++ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output, last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ if (first_slice) { ++ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture, 0); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ } ++ ++ // NOTE: do we need to dequeue when request fails/timeout? ++ ++ // 4. queue request and wait ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_QUEUE, NULL); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ goto fail; ++ } ++ ++ FD_ZERO(&except_fds); ++ FD_SET(req->request_fd, &except_fds); ++ ++ ret = select(req->request_fd + 1, NULL, NULL, &except_fds, &tv); ++ if (ret == 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: request %d timeout\n", __func__, req->request_fd); ++ goto fail; ++ } else if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: select request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ goto fail; ++ } ++ ++ ret = v4l2_request_dequeue_buffer(ctx, &req->output); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ if (last_slice) { ++ if (ff_v4l2_phase_started(&req->phase)) { ++ ff_v4l2_phase_release(&req->phase, 0); ++ ff_v4l2_phase_claim(&req->phase, 1); ++ } ++ ++ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); ++ ++ if (ff_v4l2_phase_started(&req->phase)) { ++ ff_v4l2_phase_release(&req->phase, 1); ++ } ++ ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ } ++ ++ // TODO: check errors ++ // buffer.flags & V4L2_BUF_FLAG_ERROR ++ ++ if (last_slice) ++ return v4l2_request_set_drm_descriptor(req, &ctx->format); ++ ++ return 0; ++ ++fail: ++ ret = v4l2_request_dequeue_buffer(ctx, &req->output); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ ++ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ ++ return -1; ++} ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ ++ // fall back to queue each slice as a full frame ++ if ((req->output.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++ ++ return v4l2_request_queue_decode(avctx, frame, control, count, first_slice, last_slice); ++} ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++} ++ ++static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ struct v4l2_create_buffers buffers = { ++ .count = 0, ++ .memory = V4L2_MEMORY_MMAP, ++ .format.type = type, ++ }; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return -1; ++ } ++ ++ if ((buffers.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) != V4L2_BUF_CAP_SUPPORTS_REQUESTS) { ++ av_log(avctx, AV_LOG_INFO, "%s: output buffer type do not support requests, capabilities %u\n", __func__, buffers.capabilities); ++ return -1; ++ } ++ } ++ ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ if (fmtdesc.pixelformat == pixelformat) ++ return 0; ++ ++ fmtdesc.index++; ++ } ++ ++ av_log(avctx, AV_LOG_INFO, "%s: pixelformat %u not supported for type %u\n", __func__, pixelformat, type); ++ return -1; ++} ++ ++static int v4l2_request_set_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat, uint32_t buffersize) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_format format = { ++ .type = type, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ format.fmt.pix_mp.width = avctx->coded_width; ++ format.fmt.pix_mp.height = avctx->coded_height; ++ format.fmt.pix_mp.pixelformat = pixelformat; ++ format.fmt.pix_mp.plane_fmt[0].sizeimage = buffersize; ++ format.fmt.pix_mp.num_planes = 1; ++ } else { ++ format.fmt.pix.width = avctx->coded_width; ++ format.fmt.pix.height = avctx->coded_height; ++ format.fmt.pix.pixelformat = pixelformat; ++ format.fmt.pix.sizeimage = buffersize; ++ } ++ ++ return ioctl(ctx->video_fd, VIDIOC_S_FMT, &format); ++} ++ ++static int v4l2_request_select_capture_format(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ enum v4l2_buf_type type = ctx->format.type; ++ ++#if 0 ++ struct v4l2_format format = { ++ .type = type, ++ }; ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ uint32_t pixelformat; ++ int i; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &format) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return -1; ++ } ++ ++ pixelformat = V4L2_TYPE_IS_MULTIPLANAR(type) ? format.fmt.pix_mp.pixelformat : format.fmt.pix.pixelformat; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (pixelformat == v4l2_request_capture_pixelformats[i]) ++ return v4l2_request_set_format(avctx, type, pixelformat, 0); ++ } ++ ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ for (i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (fmtdesc.pixelformat == v4l2_request_capture_pixelformats[i]) ++ return v4l2_request_set_format(avctx, type, fmtdesc.pixelformat, 0); ++ } ++ ++ fmtdesc.index++; ++ } ++#else ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ uint32_t pixelformat = v4l2_request_capture_pixelformats[i]; ++ if (!v4l2_request_try_format(avctx, type, pixelformat)) ++ return v4l2_request_set_format(avctx, type, pixelformat, 0); ++ } ++#endif ++ ++ return -1; ++} ++ ++static int v4l2_request_probe_video_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret = AVERROR(EINVAL); ++ struct v4l2_capability capability = {0}; ++ unsigned int capabilities = 0; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get video device devnode failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++// ctx->video_fd = open(path, O_RDWR | O_NONBLOCK, 0); ++ ctx->video_fd = open(path, O_RDWR, 0); ++ if (ctx->video_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYCAP, &capability); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get video capability failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (capability.capabilities & V4L2_CAP_DEVICE_CAPS) ++ capabilities = capability.device_caps; ++ else ++ capabilities = capability.capabilities; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p path=%s capabilities=%u\n", __func__, avctx, ctx, path, capabilities); ++ ++ if ((capabilities & V4L2_CAP_STREAMING) != V4L2_CAP_STREAMING) { ++ av_log(avctx, AV_LOG_ERROR, "%s: missing required streaming capability\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if ((capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) == V4L2_CAP_VIDEO_M2M_MPLANE) { ++ ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ } else if ((capabilities & V4L2_CAP_VIDEO_M2M) == V4L2_CAP_VIDEO_M2M) { ++ ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "%s: missing required mem2mem capability\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_try_format(avctx, ctx->output_type, pixelformat); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_WARNING, "%s: try output format failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_set_format(avctx, ctx->output_type, pixelformat, buffersize); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set output format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_set_controls(ctx, -1, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_select_capture_format(avctx); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_WARNING, "%s: select capture format failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ if (ctx->video_fd >= 0) { ++ close(ctx->video_fd); ++ ctx->video_fd = -1; ++ } ++ return ret; ++} ++ ++static int v4l2_request_init_context(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &ctx->format); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__, ctx->format.fmt.pix_mp.pixelformat, ctx->format.fmt.pix_mp.width, ctx->format.fmt.pix_mp.height, ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline, ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage, ctx->format.fmt.pix_mp.num_planes); ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__, ctx->format.fmt.pix.pixelformat, ctx->format.fmt.pix.width, ctx->format.fmt.pix.height, ctx->format.fmt.pix.bytesperline, ctx->format.fmt.pix.sizeimage); ++ } ++ ++ ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_DRM); ++ if (ret < 0) ++ goto fail; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->output_type); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: output stream on failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->format.type); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: capture stream on failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ ff_v4l2_request_uninit(avctx); ++ return ret; ++} ++ ++static int v4l2_request_probe_media_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ struct media_device_info device_info = {0}; ++ struct media_v2_topology topology = {0}; ++ struct media_v2_interface *interfaces = NULL; ++ struct udev *udev = udev_device_get_udev(device); ++ struct udev_device *video_device; ++ dev_t devnum; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media device devnode failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ctx->media_fd = open(path, O_RDWR, 0); ++ if (ctx->media_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media device info failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p path=%s driver=%s\n", __func__, avctx, ctx, path, device_info.driver); ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (topology.num_interfaces <= 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: media device has no interfaces\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ interfaces = av_mallocz(topology.num_interfaces * sizeof(struct media_v2_interface)); ++ if (!interfaces) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating media interface struct failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces; ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = AVERROR(EINVAL); ++ for (int i = 0; i < topology.num_interfaces; i++) { ++ if (interfaces[i].intf_type != MEDIA_INTF_T_V4L_VIDEO) ++ continue; ++ ++ devnum = makedev(interfaces[i].devnode.major, interfaces[i].devnode.minor); ++ video_device = udev_device_new_from_devnum(udev, 'c', devnum); ++ if (!video_device) { ++ av_log(avctx, AV_LOG_ERROR, "%s: video_device=%p\n", __func__, video_device); ++ continue; ++ } ++ ++ ret = v4l2_request_probe_video_device(video_device, avctx, pixelformat, buffersize, control, count); ++ udev_device_unref(video_device); ++ ++ if (!ret) ++ break; ++ } ++ ++ av_freep(&interfaces); ++ return ret; ++ ++fail: ++ av_freep(&interfaces); ++ if (ctx->media_fd >= 0) { ++ close(ctx->media_fd); ++ ctx->media_fd = -1; ++ } ++ return ret; ++} ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret = AVERROR(EINVAL); ++ struct udev *udev; ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices; ++ struct udev_list_entry *entry; ++ struct udev_device *device; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p hw_device_ctx=%p hw_frames_ctx=%p\n", __func__, avctx, avctx->hw_device_ctx, avctx->hw_frames_ctx); ++ ++ ctx->media_fd = -1; ++ ctx->video_fd = -1; ++ ctx->timestamp = 0; ++ ++ udev = udev_new(); ++ if (!udev) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating udev context failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ enumerate = udev_enumerate_new(udev); ++ if (!enumerate) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating udev enumerator failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ udev_enumerate_add_match_subsystem(enumerate, "media"); ++ udev_enumerate_scan_devices(enumerate); ++ ++ devices = udev_enumerate_get_list_entry(enumerate); ++ udev_list_entry_foreach(entry, devices) { ++ const char *path = udev_list_entry_get_name(entry); ++ if (!path) ++ continue; ++ ++ device = udev_device_new_from_syspath(udev, path); ++ if (!device) ++ continue; ++ ++ ret = v4l2_request_probe_media_device(device, avctx, pixelformat, buffersize, control, count); ++ udev_device_unref(device); ++ ++ if (!ret) ++ break; ++ } ++ ++ udev_enumerate_unref(enumerate); ++ ++ if (!ret) ++ ret = v4l2_request_init_context(avctx); ++ ++fail: ++ udev_unref(udev); ++ return ret; ++} ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p\n", __func__, avctx, ctx); ++ ++ if (ctx->video_fd >= 0) { ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->output_type); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: output stream off failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->format.type); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: capture stream off failed, %s (%d)\n", __func__, strerror(errno), errno); ++ } ++ ++ if (avctx->hw_frames_ctx) { ++ AVHWFramesContext *hwfc = (AVHWFramesContext*)avctx->hw_frames_ctx->data; ++ av_buffer_pool_flush(hwfc->pool); ++ } ++ ++ if (ctx->video_fd >= 0) ++ close(ctx->video_fd); ++ ++ if (ctx->media_fd >= 0) ++ close(ctx->media_fd); ++ ++ return 0; ++} ++ ++static int v4l2_request_buffer_alloc(AVCodecContext *avctx, V4L2RequestBuffer *buf, enum v4l2_buf_type type) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_create_buffers buffers = { ++ .count = 1, ++ .memory = V4L2_MEMORY_MMAP, ++ .format.type = type, ++ }; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p buf=%p type=%u\n", __func__, avctx, buf, type); ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &buffers.format); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get format failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buffers.format.type)) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__, buffers.format.fmt.pix_mp.pixelformat, buffers.format.fmt.pix_mp.width, buffers.format.fmt.pix_mp.height, buffers.format.fmt.pix_mp.plane_fmt[0].bytesperline, buffers.format.fmt.pix_mp.plane_fmt[0].sizeimage, buffers.format.fmt.pix_mp.num_planes); ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__, buffers.format.fmt.pix.pixelformat, buffers.format.fmt.pix.width, buffers.format.fmt.pix.height, buffers.format.fmt.pix.bytesperline, buffers.format.fmt.pix.sizeimage); ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ buf->width = buffers.format.fmt.pix_mp.width; ++ buf->height = buffers.format.fmt.pix_mp.height; ++ buf->size = buffers.format.fmt.pix_mp.plane_fmt[0].sizeimage; ++ buf->buffer.length = 1; ++ buf->buffer.m.planes = planes; ++ } else { ++ buf->width = buffers.format.fmt.pix.width; ++ buf->height = buffers.format.fmt.pix.height; ++ buf->size = buffers.format.fmt.pix.sizeimage; ++ } ++ ++ buf->index = buffers.index; ++ buf->capabilities = buffers.capabilities; ++ buf->used = 0; ++ ++ buf->buffer.type = type; ++ buf->buffer.memory = V4L2_MEMORY_MMAP; ++ buf->buffer.index = buf->index; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYBUF, &buf->buffer); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset); ++ if (addr == MAP_FAILED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: mmap failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return -1; ++ } ++ ++ buf->addr = (uint8_t*)addr; ++ } else { ++ struct v4l2_exportbuffer exportbuffer = { ++ .type = type, ++ .index = buf->index, ++ .flags = O_RDONLY, ++ }; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_EXPBUF, &exportbuffer); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: export buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno); ++ return ret; ++ } ++ ++ buf->fd = exportbuffer.fd; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__, buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size); ++ return 0; ++} ++ ++static void v4l2_request_buffer_free(V4L2RequestBuffer *buf) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__, buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size); ++ ++ if (buf->addr) ++ munmap(buf->addr, buf->size); ++ ++ if (buf->fd >= 0) ++ close(buf->fd); ++} ++ ++static void v4l2_request_frame_free(void *opaque, uint8_t *data) ++{ ++ AVCodecContext *avctx = opaque; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)data; ++ ++ av_log(NULL, AV_LOG_DEBUG, "%s: avctx=%p data=%p request_fd=%d\n", __func__, avctx, data, req->request_fd); ++ ++ if (req->request_fd >= 0) ++ close(req->request_fd); ++ ++ v4l2_request_buffer_free(&req->capture); ++ v4l2_request_buffer_free(&req->output); ++ ++ av_free(data); ++} ++ ++static AVBufferRef *v4l2_request_frame_alloc(void *opaque, int size) ++{ ++ AVCodecContext *avctx = opaque; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req; ++ AVBufferRef *ref; ++ uint8_t *data; ++ int ret; ++ ++ data = av_mallocz(size); ++ if (!data) ++ return NULL; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p size=%d data=%p\n", __func__, avctx, size, data); ++ ++ ref = av_buffer_create(data, size, v4l2_request_frame_free, avctx, 0); ++ if (!ref) { ++ av_freep(&data); ++ return NULL; ++ } ++ ++ req = (V4L2RequestDescriptor*)data; ++ req->request_fd = -1; ++ req->output.fd = -1; ++ req->capture.fd = -1; ++ ++ ret = v4l2_request_buffer_alloc(avctx, &req->output, ctx->output_type); ++ if (ret < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ ret = v4l2_request_buffer_alloc(avctx, &req->capture, ctx->format.type); ++ if (ret < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_REQUEST_ALLOC, &req->request_fd); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: request alloc failed, %s (%d)\n", __func__, strerror(errno), errno); ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p size=%d data=%p request_fd=%d\n", __func__, avctx, size, data, req->request_fd); ++ return ref; ++} ++ ++static void v4l2_request_pool_free(void *opaque) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p\n", __func__, opaque); ++} ++ ++static void v4l2_request_hwframe_ctx_free(AVHWFramesContext *hwfc) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: hwfc=%p pool=%p\n", __func__, hwfc, hwfc->pool); ++ ++ av_buffer_pool_flush(hwfc->pool); ++ av_buffer_pool_uninit(&hwfc->pool); ++} ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ AVHWFramesContext *hwfc = (AVHWFramesContext*)hw_frames_ctx->data; ++ ++ hwfc->format = AV_PIX_FMT_DRM_PRIME; ++ hwfc->sw_format = AV_PIX_FMT_NV12; ++ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { ++ hwfc->width = ctx->format.fmt.pix_mp.width; ++ hwfc->height = ctx->format.fmt.pix_mp.height; ++ } else { ++ hwfc->width = ctx->format.fmt.pix.width; ++ hwfc->height = ctx->format.fmt.pix.height; ++#if CONFIG_SAND ++ if (ctx->format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12_COL128) { ++ hwfc->sw_format = AV_PIX_FMT_RPI4_8; ++ } ++ else if (ctx->format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12_10_COL128) { ++ hwfc->sw_format = AV_PIX_FMT_RPI4_10; ++ } ++#endif ++ } ++ ++ hwfc->pool = av_buffer_pool_init2(sizeof(V4L2RequestDescriptor), avctx, v4l2_request_frame_alloc, v4l2_request_pool_free); ++ if (!hwfc->pool) ++ return AVERROR(ENOMEM); ++ ++ hwfc->free = v4l2_request_hwframe_ctx_free; ++ ++ hwfc->initial_pool_size = 1; ++ ++ switch (avctx->codec_id) { ++ case AV_CODEC_ID_VP9: ++ hwfc->initial_pool_size += 8; ++ break; ++ case AV_CODEC_ID_VP8: ++ hwfc->initial_pool_size += 3; ++ break; ++ default: ++ hwfc->initial_pool_size += 2; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p hw_frames_ctx=%p hwfc=%p pool=%p width=%d height=%d initial_pool_size=%d\n", __func__, avctx, ctx, hw_frames_ctx, hwfc, hwfc->pool, hwfc->width, hwfc->height, hwfc->initial_pool_size); ++ ++ return 0; ++} +diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h +new file mode 100644 +index 0000000000..20b56cfbfb +--- /dev/null ++++ b/libavcodec/v4l2_request.h +@@ -0,0 +1,96 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_V4L2_REQUEST_H ++#define AVCODEC_V4L2_REQUEST_H ++ ++#include ++ ++#include "libavutil/hwcontext_drm.h" ++#include "v4l2_phase.h" ++ ++typedef struct V4L2RequestContext { ++ int video_fd; ++ int media_fd; ++ enum v4l2_buf_type output_type; ++ struct v4l2_format format; ++ int timestamp; ++} V4L2RequestContext; ++ ++typedef struct V4L2RequestBuffer { ++ int index; ++ int fd; ++ uint8_t *addr; ++ uint32_t width; ++ uint32_t height; ++ uint32_t size; ++ uint32_t used; ++ uint32_t capabilities; ++ struct v4l2_buffer buffer; ++} V4L2RequestBuffer; ++ ++struct V4l2PhaseControl; ++ ++typedef struct V4L2PhaseEnv { ++ struct V4L2PhaseEnv * next; ++ struct V4L2PhaseControl * ctrl; ++ unsigned int order; ++} V4L2PhaseEnv; ++ ++typedef struct V4L2RequestDescriptor { ++ AVDRMFrameDescriptor drm; ++ int request_fd; ++ V4L2RequestBuffer output; ++ V4L2RequestBuffer capture; ++ ++ // Phase control ++ V4L2PhaseInfo phase; ++} V4L2RequestDescriptor; ++ ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame); ++ ++// Sets phase control on this frame & gives it an order ++int ff_v4l2_request_start_phase_control(AVFrame *frame, struct V4L2PhaseControl * phase); ++ ++// Had error - release all phases ++void ff_v4l2_request_abort_phase_control(AVFrame *frame); ++ ++ ++int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame); ++ ++int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size); ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control); ++ ++int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id); ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice); ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx); ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); ++ ++#endif /* AVCODEC_V4L2_REQUEST_H */ +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +new file mode 100644 +index 0000000000..d6332c01c7 +--- /dev/null ++++ b/libavcodec/v4l2_request_h264.c +@@ -0,0 +1,456 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "h264dec.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "h264-ctrls.h" ++ ++typedef struct V4L2RequestControlsH264 { ++ struct v4l2_ctrl_h264_sps sps; ++ struct v4l2_ctrl_h264_pps pps; ++ struct v4l2_ctrl_h264_scaling_matrix scaling_matrix; ++ struct v4l2_ctrl_h264_decode_params decode_params; ++ struct v4l2_ctrl_h264_slice_params slice_params; ++ struct v4l2_ctrl_h264_pred_weights pred_weights; ++ int pred_weights_required; ++ int first_slice; ++ int num_slices; ++} V4L2RequestControlsH264; ++ ++typedef struct V4L2RequestContextH264 { ++ V4L2RequestContext base; ++ int decode_mode; ++ int start_code; ++} V4L2RequestContextH264; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int list, const H264SliceContext *sl) ++{ ++ for (int i = 0; i < sl->ref_count[list]; i++) { ++ if (sl->pwt.luma_weight_flag[list]) { ++ factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0]; ++ factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1]; ++ } else { ++ factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom; ++ factors->luma_offset[i] = 0; ++ } ++ for (int j = 0; j < 2; j++) { ++ if (sl->pwt.chroma_weight_flag[list]) { ++ factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0]; ++ factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1]; ++ } else { ++ factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom; ++ factors->chroma_offset[i][j] = 0; ++ } ++ } ++ } ++} ++ ++static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic) ++{ ++ entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f); ++ entry->pic_num = pic->pic_id; ++ entry->frame_num = pic->frame_num; ++ entry->fields = pic->reference & V4L2_H264_FRAME_REF; ++ entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID; ++ if (entry->fields) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; ++ if (pic->long_ref) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; ++ if (pic->field_picture) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD; ++ if (pic->field_poc[0] != INT_MAX) ++ entry->top_field_order_cnt = pic->field_poc[0]; ++ if (pic->field_poc[1] != INT_MAX) ++ entry->bottom_field_order_cnt = pic->field_poc[1]; ++} ++ ++static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Context *h) ++{ ++ int entries = 0; ++ ++ for (int i = 0; i < h->short_ref_count; i++) { ++ const H264Picture *pic = h->short_ref[i]; ++ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX)) ++ fill_dpb_entry(&decode->dpb[entries++], pic); ++ } ++ ++ if (!h->long_ref_count) ++ return; ++ ++ for (int i = 0; i < FF_ARRAY_ELEMS(h->long_ref); i++) { ++ const H264Picture *pic = h->long_ref[i]; ++ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX)) ++ fill_dpb_entry(&decode->dpb[entries++], pic); ++ } ++} ++ ++static void fill_ref_list(struct v4l2_h264_reference *reference, struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref) ++{ ++ uint64_t timestamp; ++ ++ if (!ref->parent) ++ return; ++ ++ timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f); ++ ++ for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) { ++ struct v4l2_h264_dpb_entry *entry = &decode->dpb[i]; ++ if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) && ++ entry->reference_ts == timestamp) { ++ reference->fields = ref->reference & V4L2_H264_FRAME_REF; ++ reference->index = i; ++ return; ++ } ++ } ++} ++ ++static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h) ++{ ++ const SPS *sps = h->ps.sps; ++ ++ *ctrl = (struct v4l2_ctrl_h264_sps) { ++ .profile_idc = sps->profile_idc, ++ .constraint_set_flags = sps->constraint_set_flags, ++ .level_idc = sps->level_idc, ++ .seq_parameter_set_id = sps->sps_id, ++ .chroma_format_idc = sps->chroma_format_idc, ++ .bit_depth_luma_minus8 = sps->bit_depth_luma - 8, ++ .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, ++ .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, ++ .pic_order_cnt_type = sps->poc_type, ++ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, ++ .max_num_ref_frames = sps->ref_frame_count, ++ .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length, ++ .offset_for_non_ref_pic = sps->offset_for_non_ref_pic, ++ .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field, ++ .pic_width_in_mbs_minus1 = h->mb_width - 1, ++ .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1, ++ }; ++ ++ if (sps->poc_cycle_length > 0 && sps->poc_cycle_length <= 255) ++ memcpy(ctrl->offset_for_ref_frame, sps->offset_for_ref_frame, sps->poc_cycle_length * sizeof(ctrl->offset_for_ref_frame[0])); ++ ++ if (sps->residual_color_transform_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ if (sps->transform_bypass) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS; ++ if (sps->delta_pic_order_always_zero_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO; ++ if (sps->gaps_in_frame_num_allowed_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED; ++ if (sps->frame_mbs_only_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY; ++ if (sps->mb_aff) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD; ++ if (sps->direct_8x8_inference_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE; ++} ++ ++static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h) ++{ ++ const SPS *sps = h->ps.sps; ++ const PPS *pps = h->ps.pps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; ++ int qp_bd_offset = 6 * (sps->bit_depth_luma - 8); ++ ++ *ctrl = (struct v4l2_ctrl_h264_pps) { ++ .pic_parameter_set_id = sl->pps_id, ++ .seq_parameter_set_id = pps->sps_id, ++ .num_slice_groups_minus1 = pps->slice_group_count - 1, ++ .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1, ++ .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1, ++ .weighted_bipred_idc = pps->weighted_bipred_idc, ++ .pic_init_qp_minus26 = pps->init_qp - 26 - qp_bd_offset, ++ .pic_init_qs_minus26 = pps->init_qs - 26 - qp_bd_offset, ++ .chroma_qp_index_offset = pps->chroma_qp_index_offset[0], ++ .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1], ++ }; ++ ++ if (pps->cabac) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE; ++ if (pps->pic_order_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT; ++ if (pps->weighted_pred) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED; ++ if (pps->deblocking_filter_parameters_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT; ++ if (pps->constrained_intra_pred) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ if (pps->redundant_pic_cnt_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT; ++ if (pps->transform_8x8_mode) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE; ++ /* FFmpeg always provide a scaling matrix */ ++ ctrl->flags |= V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT; ++} ++ ++static int v4l2_request_h264_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const H264Context *h = avctx->priv_data; ++ const PPS *pps = h->ps.pps; ++ const SPS *sps = h->ps.sps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ ++ fill_sps(&controls->sps, h); ++ fill_pps(&controls->pps, h); ++ ++ memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4)); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1])); ++ ++ if (sps->chroma_format_idc == 3) { ++ memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5])); ++ } ++ ++ controls->decode_params = (struct v4l2_ctrl_h264_decode_params) { ++ .nal_ref_idc = h->nal_ref_idc, ++ .frame_num = h->poc.frame_num, ++ .top_field_order_cnt = h->cur_pic_ptr->field_poc[0] != INT_MAX ? h->cur_pic_ptr->field_poc[0] : 0, ++ .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1] != INT_MAX ? h->cur_pic_ptr->field_poc[1] : 0, ++ .idr_pic_id = sl->idr_pic_id, ++ .pic_order_cnt_lsb = sl->poc_lsb, ++ .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, ++ .delta_pic_order_cnt0 = sl->delta_poc[0], ++ .delta_pic_order_cnt1 = sl->delta_poc[1], ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_size_in_bits, ++ /* Size in bits of pic order count syntax. */ ++ .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size, ++ .slice_group_change_cycle = 0, /* slice group not supported by FFmpeg */ ++ }; ++ ++ if (h->picture_idr) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC; ++ if (FIELD_PICTURE(h)) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC; ++ if (h->picture_structure == PICT_BOTTOM_FIELD) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD; ++ ++ fill_dpb(&controls->decode_params, h); ++ ++ controls->first_slice = !FIELD_PICTURE(h) || h->first_field; ++ controls->num_slices = 0; ++ ++ return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); ++} ++ ++static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice) ++{ ++ const H264Context *h = avctx->priv_data; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS, ++ .ptr = &controls->pred_weights, ++ .size = sizeof(controls->pred_weights), ++ }, ++ }; ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) { ++ int count = FF_ARRAY_ELEMS(control) - (controls->pred_weights_required ? 0 : 1); ++ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, count, controls->first_slice, last_slice); ++ } ++ ++ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control) - 2); ++} ++ ++static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const H264Context *h = avctx->priv_data; ++ const PPS *pps = h->ps.pps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ int i, ret, count; ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && controls->num_slices) { ++ ret = v4l2_request_h264_queue_decode(avctx, 0); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); ++ controls->first_slice = 0; ++ } ++ ++ if (ctx->start_code == V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size); ++ if (ret) ++ return ret; ++ ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) ++ return 0; ++ ++ controls->slice_params = (struct v4l2_ctrl_h264_slice_params) { ++ /* Offset in bits to slice_data() from the beginning of this slice. */ ++ .header_bit_size = get_bits_count(&sl->gb), ++ ++ .first_mb_in_slice = sl->first_mb_addr, ++ ++ .slice_type = ff_h264_get_slice_type(sl), ++ .colour_plane_id = 0, /* separate colour plane not supported by FFmpeg */ ++ .redundant_pic_cnt = sl->redundant_pic_count, ++ .cabac_init_idc = sl->cabac_init_idc, ++ .slice_qp_delta = sl->qscale - pps->init_qp, ++ .slice_qs_delta = 0, /* not implemented by FFmpeg */ ++ .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter, ++ .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2, ++ .slice_beta_offset_div2 = sl->slice_beta_offset / 2, ++ .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0, ++ .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0, ++ }; ++ ++ if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred) ++ controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED; ++ /* V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH: not implemented by FFmpeg */ ++ ++ controls->pred_weights_required = V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(&controls->pps, &controls->slice_params); ++ if (controls->pred_weights_required) { ++ controls->pred_weights.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; ++ controls->pred_weights.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; ++ } ++ ++ count = sl->list_count > 0 ? sl->ref_count[0] : 0; ++ for (i = 0; i < count; i++) ++ fill_ref_list(&controls->slice_params.ref_pic_list0[i], &controls->decode_params, &sl->ref_list[0][i]); ++ if (count && controls->pred_weights_required) ++ fill_weight_factors(&controls->pred_weights.weight_factors[0], 0, sl); ++ ++ count = sl->list_count > 1 ? sl->ref_count[1] : 0; ++ for (i = 0; i < count; i++) ++ fill_ref_list(&controls->slice_params.ref_pic_list1[i], &controls->decode_params, &sl->ref_list[1][i]); ++ if (count && controls->pred_weights_required) ++ fill_weight_factors(&controls->pred_weights.weight_factors[1], 1, sl); ++ ++ controls->num_slices++; ++ return 0; ++} ++ ++static int v4l2_request_h264_end_frame(AVCodecContext *avctx) ++{ ++ const H264Context *h = avctx->priv_data; ++ return v4l2_request_h264_queue_decode(avctx, !FIELD_PICTURE(h) || !h->first_field); ++} ++ ++static int v4l2_request_h264_set_controls(AVCodecContext *avctx) ++{ ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, }, ++ { .id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, }, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_START_CODE); ++ if (ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_NONE && ++ ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ control[0].value = ctx->decode_mode; ++ control[1].value = ctx->start_code; ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_h264_init(AVCodecContext *avctx) ++{ ++ const H264Context *h = avctx->priv_data; ++ struct v4l2_ctrl_h264_sps sps; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ }; ++ ++ fill_sps(&sps, h); ++ ++ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ return v4l2_request_h264_set_controls(avctx); ++} ++ ++const AVHWAccel ff_h264_v4l2request_hwaccel = { ++ .name = "h264_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_H264, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_h264_start_frame, ++ .decode_slice = v4l2_request_h264_decode_slice, ++ .end_frame = v4l2_request_h264_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsH264), ++ .init = v4l2_request_h264_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContextH264), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +new file mode 100644 +index 0000000000..1c675d6dee +--- /dev/null ++++ b/libavcodec/v4l2_request_hevc.c +@@ -0,0 +1,652 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "decode.h" ++#include "hevcdec.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "hevc-ctrls.h" ++#include "v4l2_phase.h" ++ ++#define MAX_SLICES 16 ++ ++typedef struct V4L2RequestControlsHEVC { ++ struct v4l2_ctrl_hevc_sps sps; ++ struct v4l2_ctrl_hevc_pps pps; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; ++ struct v4l2_ctrl_hevc_slice_params slice_params[MAX_SLICES]; ++ int first_slice; ++ int num_slices; //TODO: this should be in control ++} V4L2RequestControlsHEVC; ++ ++typedef struct V4L2RequestContextHEVC { ++ V4L2RequestContext base; ++ int decode_mode; ++ int start_code; ++ int max_slices; ++ ++ unsigned int order; ++ V4L2PhaseControl * pctrl; ++} V4L2RequestContextHEVC; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table) ++{ ++ int32_t luma_weight_denom, chroma_weight_denom; ++ const SliceHeader *sh = &h->sh; ++ ++ if (sh->slice_type == HEVC_SLICE_I || ++ (sh->slice_type == HEVC_SLICE_P && !h->ps.pps->weighted_pred_flag) || ++ (sh->slice_type == HEVC_SLICE_B && !h->ps.pps->weighted_bipred_flag)) ++ return; ++ ++ table->luma_log2_weight_denom = sh->luma_log2_weight_denom; ++ ++ if (h->ps.sps->chroma_format_idc) ++ table->delta_chroma_log2_weight_denom = sh->chroma_log2_weight_denom - sh->luma_log2_weight_denom; ++ ++ luma_weight_denom = (1 << sh->luma_log2_weight_denom); ++ chroma_weight_denom = (1 << sh->chroma_log2_weight_denom); ++ ++ for (int i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { ++ table->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - luma_weight_denom; ++ table->luma_offset_l0[i] = sh->luma_offset_l0[i]; ++ table->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - chroma_weight_denom; ++ table->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - chroma_weight_denom; ++ table->chroma_offset_l0[i][0] = sh->chroma_offset_l0[i][0]; ++ table->chroma_offset_l0[i][1] = sh->chroma_offset_l0[i][1]; ++ } ++ ++ if (sh->slice_type != HEVC_SLICE_B) ++ return; ++ ++ for (int i = 0; i < 15 && i < sh->nb_refs[L1]; i++) { ++ table->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - luma_weight_denom; ++ table->luma_offset_l1[i] = sh->luma_offset_l1[i]; ++ table->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - chroma_weight_denom; ++ table->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - chroma_weight_denom; ++ table->chroma_offset_l1[i][0] = sh->chroma_offset_l1[i][0]; ++ table->chroma_offset_l1[i][1] = sh->chroma_offset_l1[i][1]; ++ } ++} ++ ++static int find_frame_rps_type(const HEVCContext *h, uint64_t timestamp) ++{ ++ const HEVCFrame *frame; ++ int i; ++ ++ for (i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { ++ frame = h->rps[ST_CURR_BEF].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE; ++ } ++ ++ for (i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { ++ frame = h->rps[ST_CURR_AFT].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER; ++ } ++ ++ for (i = 0; i < h->rps[LT_CURR].nb_refs; i++) { ++ frame = h->rps[LT_CURR].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR; ++ } ++ ++ return 0; ++} ++ ++static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame, ++ struct v4l2_ctrl_hevc_slice_params *slice_params) ++{ ++ uint64_t timestamp; ++ ++ if (!frame) ++ return 0; ++ ++ timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame); ++ ++ for (uint8_t i = 0; i < slice_params->num_active_dpb_entries; i++) { ++ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[i]; ++ if (entry->timestamp == timestamp) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h, ++ struct v4l2_ctrl_hevc_slice_params *slice_params) ++{ ++ const HEVCFrame *pic = h->ref; ++ const SliceHeader *sh = &h->sh; ++ int i, entries = 0; ++ RefPicList *rpl; ++ ++ *slice_params = (struct v4l2_ctrl_hevc_slice_params) { ++ .bit_size = 0, ++ .data_bit_offset = get_bits_count(&h->HEVClc->gb), ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .slice_segment_addr = sh->slice_segment_addr, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ ++ .nal_unit_type = h->nal_unit_type, ++ .nuh_temporal_id_plus1 = h->temporal_id + 1, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .slice_type = sh->slice_type, ++ .colour_plane_id = sh->colour_plane_id, ++ .slice_pic_order_cnt = pic->poc, ++ .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0, ++ .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0, ++ .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0, ++ .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand, ++ .slice_qp_delta = sh->slice_qp_delta, ++ .slice_cb_qp_offset = sh->slice_cb_qp_offset, ++ .slice_cr_qp_offset = sh->slice_cr_qp_offset, ++ .slice_act_y_qp_offset = 0, ++ .slice_act_cb_qp_offset = 0, ++ .slice_act_cr_qp_offset = 0, ++ .slice_beta_offset_div2 = sh->beta_offset / 2, ++ .slice_tc_offset_div2 = sh->tc_offset / 2, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ ++ .pic_struct = h->sei.picture_timing.picture_struct, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs, ++ .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs, ++ .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs, ++ }; ++ ++ if (sh->slice_sample_adaptive_offset_flag[0]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA; ++ ++ if (sh->slice_sample_adaptive_offset_flag[1]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA; ++ ++ if (sh->slice_temporal_mvp_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED; ++ ++ if (sh->mvd_l1_zero_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO; ++ ++ if (sh->cabac_init_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT; ++ ++ if (sh->collocated_list == L0) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0; ++ ++ if (sh->disable_deblocking_filter_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED; ++ ++ if (sh->slice_loop_filter_across_slices_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ if (sh->dependent_slice_segment_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { ++ const HEVCFrame *frame = &h->DPB[i]; ++ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { ++ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[entries++]; ++ ++ entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame); ++ entry->rps = find_frame_rps_type(h, entry->timestamp); ++ entry->field_pic = frame->frame->interlaced_frame; ++ ++ /* TODO: Interleaved: Get the POC for each field. */ ++ entry->pic_order_cnt[0] = frame->poc; ++ entry->pic_order_cnt[1] = frame->poc; ++ } ++ } ++ ++ slice_params->num_active_dpb_entries = entries; ++ ++ if (sh->slice_type != HEVC_SLICE_I) { ++ rpl = &h->ref->refPicList[0]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], slice_params); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ rpl = &h->ref->refPicList[1]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], slice_params); ++ } ++ ++ v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table); ++ ++ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets; ++ if (slice_params->num_entry_point_offsets > 256) { ++ slice_params->num_entry_point_offsets = 256; ++ av_log(NULL, AV_LOG_ERROR, "%s: Currently only 256 entry points are supported, but slice has %d entry points.\n", __func__, sh->num_entry_point_offsets); ++ } ++ ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) ++ slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1; ++} ++ ++static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h) ++{ ++ const HEVCSPS *sps = h->ps.sps; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ *ctrl = (struct v4l2_ctrl_hevc_sps) { ++ .chroma_format_idc = sps->chroma_format_idc, ++ .pic_width_in_luma_samples = sps->width, ++ .pic_height_in_luma_samples = sps->height, ++ .bit_depth_luma_minus8 = sps->bit_depth - 8, ++ .bit_depth_chroma_minus8 = sps->bit_depth - 8, ++ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, ++ .sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1, ++ .sps_max_num_reorder_pics = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics, ++ .sps_max_latency_increase_plus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_latency_increase + 1, ++ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, ++ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size, ++ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2, ++ .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size, ++ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, ++ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, ++ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1, ++ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1, ++ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3, ++ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, ++ .num_short_term_ref_pic_sets = sps->nb_st_rps, ++ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, ++ }; ++ ++ if (sps->separate_colour_plane_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ ++ if (sps->scaling_list_enable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED; ++ ++ if (sps->amp_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED; ++ ++ if (sps->sao_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET; ++ ++ if (sps->pcm_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED; ++ ++ if (sps->pcm.loop_filter_disable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED; ++ ++ if (sps->long_term_ref_pics_present_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT; ++ ++ if (sps->sps_temporal_mvp_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED; ++ ++ if (sps->sps_strong_intra_smoothing_enable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED; ++} ++ ++static int v4l2_request_hevc_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ const HEVCSPS *sps = h->ps.sps; ++ const HEVCPPS *pps = h->ps.pps; ++ const ScalingList *sl = pps->scaling_list_data_present_flag ? ++ &pps->scaling_list : ++ sps->scaling_list_enable_flag ? ++ &sps->scaling_list : NULL; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data; ++ int rv; ++ ++ fill_sps(&controls->sps, h); ++ ++ if (sl) { ++ for (int i = 0; i < 6; i++) { ++ for (int j = 0; j < 16; j++) ++ controls->scaling_matrix.scaling_list_4x4[i][j] = sl->sl[0][i][j]; ++ for (int j = 0; j < 64; j++) { ++ controls->scaling_matrix.scaling_list_8x8[i][j] = sl->sl[1][i][j]; ++ controls->scaling_matrix.scaling_list_16x16[i][j] = sl->sl[2][i][j]; ++ if (i < 2) ++ controls->scaling_matrix.scaling_list_32x32[i][j] = sl->sl[3][i * 3][j]; ++ } ++ controls->scaling_matrix.scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i]; ++ if (i < 2) ++ controls->scaling_matrix.scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3]; ++ } ++ } ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ controls->pps = (struct v4l2_ctrl_hevc_pps) { ++ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, ++ .init_qp_minus26 = pps->pic_init_qp_minus26, ++ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, ++ .pps_cb_qp_offset = pps->cb_qp_offset, ++ .pps_cr_qp_offset = pps->cr_qp_offset, ++ .pps_beta_offset_div2 = pps->beta_offset / 2, ++ .pps_tc_offset_div2 = pps->tc_offset / 2, ++ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, ++ }; ++ ++ if (pps->dependent_slice_segments_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT; ++ ++ if (pps->output_flag_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT; ++ ++ if (pps->sign_data_hiding_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED; ++ ++ if (pps->cabac_init_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT; ++ ++ if (pps->constrained_intra_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ ++ if (pps->transform_skip_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED; ++ ++ if (pps->cu_qp_delta_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED; ++ ++ if (pps->pic_slice_level_chroma_qp_offsets_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT; ++ ++ if (pps->weighted_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED; ++ ++ if (pps->weighted_bipred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED; ++ ++ if (pps->transquant_bypass_enable_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED; ++ ++ if (pps->tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED; ++ ++ if (pps->entropy_coding_sync_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED; ++ ++ if (pps->loop_filter_across_tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; ++ ++ if (pps->seq_loop_filter_across_slices_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ if (pps->deblocking_filter_override_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED; ++ ++ if (pps->disable_dbf) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER; ++ ++ if (pps->lists_modification_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT; ++ ++ if (pps->slice_header_extension_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT; ++ ++ if (pps->tiles_enabled_flag) { ++ controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1; ++ controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1; ++ ++ for (int i = 0; i < pps->num_tile_columns; i++) ++ controls->pps.column_width_minus1[i] = pps->column_width[i] - 1; ++ ++ for (int i = 0; i < pps->num_tile_rows; i++) ++ controls->pps.row_height_minus1[i] = pps->row_height[i] - 1; ++ } ++ ++ controls->first_slice = 1; ++ controls->num_slices = 0; ++ ++ if ((rv = ff_v4l2_request_reset_frame(avctx, h->ref->frame)) != 0) ++ return rv; ++ ++ ff_v4l2_request_start_phase_control(h->ref->frame, ctx->pctrl); ++ ++ ff_thread_finish_setup(avctx); // Allow next thread to enter rpi_hevc_start_frame ++ ++ return 0; ++} ++ ++static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params[0]) * FFMAX(FFMIN(controls->num_slices, MAX_SLICES), ctx->max_slices), ++ }, ++ }; ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); ++ ++ return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0]; ++ int ret, slice = FFMIN(controls->num_slices, MAX_SLICES - 1); ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && slice) { ++ ret = v4l2_request_hevc_queue_decode(avctx, 0); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_frame(avctx, h->ref->frame); ++ slice = controls->num_slices = 0; ++ controls->first_slice = 0; ++ } ++ ++ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params[slice]); ++ ++ if (ctx->start_code == V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size); ++ if (ret) ++ return ret; ++ ++ controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME ++ controls->num_slices++; ++ return 0; ++} ++ ++static void v4l2_request_hevc_abort_frame(AVCodecContext * const avctx) { ++ const HEVCContext *h = avctx->priv_data; ++ ++ if (h->ref != NULL) ++ ff_v4l2_request_abort_phase_control(h->ref->frame); ++} ++ ++static int v4l2_request_hevc_end_frame(AVCodecContext *avctx) ++{ ++ int rv = v4l2_request_hevc_queue_decode(avctx, 1); ++ if (rv < 0) ++ v4l2_request_hevc_abort_frame(avctx); ++ return rv; ++} ++ ++// Called before finally returning the frame to the user ++// Set corrupt flag here as this is actually the frame structure that ++// is going to the user (in MT land each thread has its own pool) ++static int v4l2_request_post_process(void *logctx, AVFrame *frame) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ if (req) { ++ av_log(logctx, AV_LOG_DEBUG, "%s: flags=%#x, ts=%ld.%06ld\n", __func__, req->capture.buffer.flags, ++ req->capture.buffer.timestamp.tv_sec, req->capture.buffer.timestamp.tv_usec); ++ frame->flags = (req->capture.buffer.flags & V4L2_BUF_FLAG_ERROR) == 0 ? 0 : AV_FRAME_FLAG_CORRUPT; ++ } ++ ++ return 0; ++} ++ ++static int v4l2_request_hevc_alloc_frame(AVCodecContext * avctx, AVFrame *frame) ++{ ++ int ret; ++ ++ // This dups the remainder of ff_get_buffer but adds a post_process callback ++ ret = avctx->get_buffer2(avctx, frame, AV_GET_BUFFER_FLAG_REF); ++ if (ret < 0) ++ goto fail; ++ ++ ret = ff_attach_decode_data(frame); ++ if (ret < 0) ++ goto fail; ++ ++ { ++ FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; ++ fdd->post_process = v4l2_request_post_process; ++ } ++ ++ return 0; ++ ++fail: ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s failed\n", __func__); ++ av_frame_unref(frame); ++ } ++ ++ return ret; ++} ++ ++static int v4l2_request_hevc_set_controls(AVCodecContext *avctx) ++{ ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, }, ++ }; ++ struct v4l2_query_ext_ctrl slice_params = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_START_CODE); ++ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE && ++ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ ret = ff_v4l2_request_query_control(avctx, &slice_params); ++ if (ret) ++ return ret; ++ ++ ctx->max_slices = slice_params.elems; ++ if (ctx->max_slices > MAX_SLICES) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %d\n", __func__, ctx->max_slices); ++ return AVERROR(EINVAL); ++ } ++ ++ control[0].value = ctx->decode_mode; ++ control[1].value = ctx->start_code; ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_hevc_uninit(AVCodecContext *avctx) ++{ ++ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data; ++ ff_v4l2_phase_control_deletez(&ctx->pctrl); ++ return ff_v4l2_request_uninit(avctx); ++} ++ ++static int v4l2_request_hevc_init(AVCodecContext *avctx) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_ctrl_hevc_sps sps; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ }; ++ ++ if ((ctx->pctrl = ff_v4l2_phase_control_new(2)) == NULL) ++ return AVERROR(ENOMEM); ++ ++ fill_sps(&sps, h); ++ ++ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ return v4l2_request_hevc_set_controls(avctx); ++} ++ ++const AVHWAccel ff_hevc_v4l2request_hwaccel = { ++ .name = "hevc_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .alloc_frame = v4l2_request_hevc_alloc_frame, ++ .start_frame = v4l2_request_hevc_start_frame, ++ .decode_slice = v4l2_request_hevc_decode_slice, ++ .end_frame = v4l2_request_hevc_end_frame, ++ .abort_frame = v4l2_request_hevc_abort_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC), ++ .init = v4l2_request_hevc_init, ++ .uninit = v4l2_request_hevc_uninit, ++ .priv_data_size = sizeof(V4L2RequestContextHEVC), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_MT_SAFE, ++}; +diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c +new file mode 100644 +index 0000000000..bc251a6fd2 +--- /dev/null ++++ b/libavcodec/v4l2_request_mpeg2.c +@@ -0,0 +1,155 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "mpegvideo.h" ++#include "v4l2_request.h" ++#include "mpeg2-ctrls.h" ++ ++typedef struct V4L2RequestControlsMPEG2 { ++ struct v4l2_ctrl_mpeg2_slice_params slice_params; ++ struct v4l2_ctrl_mpeg2_quantization quantization; ++} V4L2RequestControlsMPEG2; ++ ++static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0]; ++ ++ controls->slice_params = (struct v4l2_ctrl_mpeg2_slice_params) { ++ .bit_size = 0, ++ .data_bit_offset = 0, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */ ++ .quantiser_scale_code = s->qscale >> 1, ++ ++ .sequence = { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */ ++ .horizontal_size = s->width, ++ .vertical_size = s->height, ++ .vbv_buffer_size = req->output.size, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */ ++ .profile_and_level_indication = 0, ++ .progressive_sequence = s->progressive_sequence, ++ .chroma_format = s->chroma_format, ++ }, ++ ++ .picture = { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */ ++ .picture_coding_type = s->pict_type, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */ ++ .f_code[0][0] = s->mpeg_f_code[0][0], ++ .f_code[0][1] = s->mpeg_f_code[0][1], ++ .f_code[1][0] = s->mpeg_f_code[1][0], ++ .f_code[1][1] = s->mpeg_f_code[1][1], ++ .intra_dc_precision = s->intra_dc_precision, ++ .picture_structure = s->picture_structure, ++ .top_field_first = s->top_field_first, ++ .frame_pred_frame_dct = s->frame_pred_frame_dct, ++ .concealment_motion_vectors = s->concealment_motion_vectors, ++ .q_scale_type = s->q_scale_type, ++ .intra_vlc_format = s->intra_vlc_format, ++ .alternate_scan = s->alternate_scan, ++ .repeat_first_field = s->repeat_first_field, ++ .progressive_frame = s->progressive_frame, ++ }, ++ }; ++ ++ switch (s->pict_type) { ++ case AV_PICTURE_TYPE_B: ++ controls->slice_params.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f); ++ // fall-through ++ case AV_PICTURE_TYPE_P: ++ controls->slice_params.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f); ++ } ++ ++ controls->quantization = (struct v4l2_ctrl_mpeg2_quantization) { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */ ++ .load_intra_quantiser_matrix = 1, ++ .load_non_intra_quantiser_matrix = 1, ++ .load_chroma_intra_quantiser_matrix = 1, ++ .load_chroma_non_intra_quantiser_matrix = 1, ++ }; ++ ++ for (int i = 0; i < 64; i++) { ++ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; ++ controls->quantization.intra_quantiser_matrix[i] = s->intra_matrix[n]; ++ controls->quantization.non_intra_quantiser_matrix[i] = s->inter_matrix[n]; ++ controls->quantization.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; ++ controls->quantization.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n]; ++ } ++ ++ return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f); ++} ++ ++static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size); ++} ++ ++static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0]; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION, ++ .ptr = &controls->quantization, ++ .size = sizeof(controls->quantization), ++ }, ++ }; ++ ++ controls->slice_params.bit_size = req->output.used * 8; ++ ++ return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_mpeg2_init(AVCodecContext *avctx) ++{ ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_mpeg2_v4l2request_hwaccel = { ++ .name = "mpeg2_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_MPEG2VIDEO, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_mpeg2_start_frame, ++ .decode_slice = v4l2_request_mpeg2_decode_slice, ++ .end_frame = v4l2_request_mpeg2_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2), ++ .init = v4l2_request_mpeg2_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c +new file mode 100644 +index 0000000000..ea2c55fa2f +--- /dev/null ++++ b/libavcodec/v4l2_request_vp8.c +@@ -0,0 +1,181 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp8.h" ++#include "vp8-ctrls.h" ++ ++typedef struct V4L2RequestControlsVP8 { ++ struct v4l2_ctrl_vp8_frame_header ctrl; ++} V4L2RequestControlsVP8; ++ ++static int v4l2_request_vp8_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ ++ memset(&controls->ctrl, 0, sizeof(controls->ctrl)); ++ return ff_v4l2_request_reset_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f); ++} ++ ++static int v4l2_request_vp8_end_frame(AVCodecContext *avctx) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, ++ .ptr = &controls->ctrl, ++ .size = sizeof(controls->ctrl), ++ }, ++ }; ++ ++ return ff_v4l2_request_decode_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_vp8_decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ struct v4l2_ctrl_vp8_frame_header *hdr = &controls->ctrl; ++ const uint8_t *data = buffer + 3 + 7 * s->keyframe; ++ unsigned int i, j, k; ++ ++ hdr->version = s->profile & 0x3; ++ hdr->width = avctx->width; ++ hdr->height = avctx->height; ++ /* FIXME: set ->xx_scale */ ++ hdr->prob_skip_false = s->prob->mbskip; ++ hdr->prob_intra = s->prob->intra; ++ hdr->prob_gf = s->prob->golden; ++ hdr->prob_last = s->prob->last; ++ hdr->first_part_size = s->header_partition_size; ++ hdr->first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) - ++ s->coder_state_at_header_end.bit_count - 8); ++ hdr->num_dct_parts = s->num_coeff_partitions; ++ for (i = 0; i < 8; i++) ++ hdr->dct_part_sizes[i] = s->coeff_partition_size[i]; ++ ++ hdr->coder_state.range = s->coder_state_at_header_end.range; ++ hdr->coder_state.value = s->coder_state_at_header_end.value; ++ hdr->coder_state.bit_count = s->coder_state_at_header_end.bit_count; ++ if (s->framep[VP56_FRAME_PREVIOUS]) ++ hdr->last_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_PREVIOUS]->tf.f); ++ if (s->framep[VP56_FRAME_GOLDEN]) ++ hdr->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN]->tf.f); ++ if (s->framep[VP56_FRAME_GOLDEN2]) ++ hdr->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN2]->tf.f); ++ hdr->flags |= s->invisible ? 0 : V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME; ++ hdr->flags |= s->mbskip_enabled ? V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF : 0; ++ hdr->flags |= (s->profile & 0x4) ? V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL : 0; ++ hdr->flags |= s->keyframe ? V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME : 0; ++ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN : 0; ++ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN2] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT : 0; ++ hdr->segment_header.flags |= s->segmentation.enabled ? V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED : 0; ++ hdr->segment_header.flags |= s->segmentation.update_map ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP : 0; ++ hdr->segment_header.flags |= s->segmentation.update_feature_data ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA : 0; ++ hdr->segment_header.flags |= s->segmentation.absolute_vals ? 0 : V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE; ++ for (i = 0; i < 4; i++) { ++ hdr->segment_header.quant_update[i] = s->segmentation.base_quant[i]; ++ hdr->segment_header.lf_update[i] = s->segmentation.filter_level[i]; ++ } ++ ++ for (i = 0; i < 3; i++) ++ hdr->segment_header.segment_probs[i] = s->prob->segmentid[i]; ++ ++ hdr->lf_header.level = s->filter.level; ++ hdr->lf_header.sharpness_level = s->filter.sharpness; ++ hdr->lf_header.flags |= s->lf_delta.enabled ? V4L2_VP8_LF_HEADER_ADJ_ENABLE : 0; ++ hdr->lf_header.flags |= s->lf_delta.update ? V4L2_VP8_LF_HEADER_DELTA_UPDATE : 0; ++ hdr->lf_header.flags |= s->filter.simple ? V4L2_VP8_LF_FILTER_TYPE_SIMPLE : 0; ++ for (i = 0; i < 4; i++) { ++ hdr->lf_header.ref_frm_delta[i] = s->lf_delta.ref[i]; ++ hdr->lf_header.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4]; ++ } ++ ++ // Probabilites ++ if (s->keyframe) { ++ static const uint8_t keyframe_y_mode_probs[4] = { ++ 145, 156, 163, 128 ++ }; ++ static const uint8_t keyframe_uv_mode_probs[3] = { ++ 142, 114, 183 ++ }; ++ ++ memcpy(hdr->entropy_header.y_mode_probs, keyframe_y_mode_probs, 4); ++ memcpy(hdr->entropy_header.uv_mode_probs, keyframe_uv_mode_probs, 3); ++ } else { ++ for (i = 0; i < 4; i++) ++ hdr->entropy_header.y_mode_probs[i] = s->prob->pred16x16[i]; ++ for (i = 0; i < 3; i++) ++ hdr->entropy_header.uv_mode_probs[i] = s->prob->pred8x8c[i]; ++ } ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 19; j++) ++ hdr->entropy_header.mv_probs[i][j] = s->prob->mvc[i][j]; ++ ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < 8; j++) { ++ static const int coeff_bands_inverse[8] = { ++ 0, 1, 2, 3, 5, 6, 4, 15 ++ }; ++ int coeff_pos = coeff_bands_inverse[j]; ++ ++ for (k = 0; k < 3; k++) { ++ memcpy(hdr->entropy_header.coeff_probs[i][j][k], ++ s->prob->token[i][coeff_pos][k], 11); ++ } ++ } ++ } ++ ++ hdr->quant_header.y_ac_qi = s->quant.yac_qi; ++ hdr->quant_header.y_dc_delta = s->quant.ydc_delta; ++ hdr->quant_header.y2_dc_delta = s->quant.y2dc_delta; ++ hdr->quant_header.y2_ac_delta = s->quant.y2ac_delta; ++ hdr->quant_header.uv_dc_delta = s->quant.uvdc_delta; ++ hdr->quant_header.uv_ac_delta = s->quant.uvac_delta; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, buffer, size); ++} ++ ++static int v4l2_request_vp8_init(AVCodecContext *avctx) ++{ ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP8_FRAME, 2 * 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_vp8_v4l2request_hwaccel = { ++ .name = "vp8_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_VP8, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_vp8_start_frame, ++ .decode_slice = v4l2_request_vp8_decode_slice, ++ .end_frame = v4l2_request_vp8_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsVP8), ++ .init = v4l2_request_vp8_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c +new file mode 100644 +index 0000000000..2e10b7ad1a +--- /dev/null ++++ b/libavcodec/v4l2_request_vp9.c +@@ -0,0 +1,353 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp9dec.h" ++#include "vp9-ctrls.h" ++ ++typedef struct V4L2RequestControlsVP9 { ++ struct v4l2_ctrl_vp9_frame_decode_params decode_params; ++} V4L2RequestControlsVP9; ++ ++static const uint8_t ff_to_v4l2_intramode[] = { ++ [VERT_PRED] = V4L2_VP9_INTRA_PRED_MODE_V, ++ [HOR_PRED] = V4L2_VP9_INTRA_PRED_MODE_H, ++ [DC_PRED] = V4L2_VP9_INTRA_PRED_MODE_DC, ++ [DIAG_DOWN_LEFT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D45, ++ [DIAG_DOWN_RIGHT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D135, ++ [VERT_RIGHT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D117, ++ [HOR_DOWN_PRED] = V4L2_VP9_INTRA_PRED_MODE_D153, ++ [VERT_LEFT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D63, ++ [HOR_UP_PRED] = V4L2_VP9_INTRA_PRED_MODE_D207, ++ [TM_VP8_PRED] = V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++static int v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx, unsigned int id) ++{ ++ VP9Context *s = avctx->priv_data; ++ struct v4l2_ctrl_vp9_frame_ctx fctx = {}; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(id), ++ .ptr = &fctx, ++ .size = sizeof(fctx), ++ }, ++ }; ++ ++ memcpy(fctx.probs.tx8, s->prob_ctx[id].p.tx8p, sizeof(s->prob_ctx[id].p.tx8p)); ++ memcpy(fctx.probs.tx16, s->prob_ctx[id].p.tx16p, sizeof(s->prob_ctx[id].p.tx16p)); ++ memcpy(fctx.probs.tx32, s->prob_ctx[id].p.tx32p, sizeof(s->prob_ctx[id].p.tx32p)); ++ memcpy(fctx.probs.coef, s->prob_ctx[id].coef, sizeof(s->prob_ctx[id].coef)); ++ memcpy(fctx.probs.skip, s->prob_ctx[id].p.skip, sizeof(s->prob_ctx[id].p.skip)); ++ memcpy(fctx.probs.inter_mode, s->prob_ctx[id].p.mv_mode, sizeof(s->prob_ctx[id].p.mv_mode)); ++ memcpy(fctx.probs.interp_filter, s->prob_ctx[id].p.filter, sizeof(s->prob_ctx[id].p.filter)); ++ memcpy(fctx.probs.is_inter, s->prob_ctx[id].p.intra, sizeof(s->prob_ctx[id].p.intra)); ++ memcpy(fctx.probs.comp_mode, s->prob_ctx[id].p.comp, sizeof(s->prob_ctx[id].p.comp)); ++ memcpy(fctx.probs.single_ref, s->prob_ctx[id].p.single_ref, sizeof(s->prob_ctx[id].p.single_ref)); ++ memcpy(fctx.probs.comp_ref, s->prob_ctx[id].p.comp_ref, sizeof(s->prob_ctx[id].p.comp_ref)); ++ memcpy(fctx.probs.y_mode, s->prob_ctx[id].p.y_mode, sizeof(s->prob_ctx[id].p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(fctx.probs.uv_mode[ff_to_v4l2_intramode[i]], s->prob_ctx[id].p.uv_mode[i], sizeof(s->prob_ctx[id].p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(fctx.probs.partition[i * 4], s->prob_ctx[id].p.partition[3 - i], sizeof(s->prob_ctx[id].p.partition[0])); ++ memcpy(fctx.probs.mv.joint, s->prob_ctx[id].p.mv_joint, sizeof(s->prob_ctx[id].p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ fctx.probs.mv.sign[i] = s->prob_ctx[id].p.mv_comp[i].sign; ++ memcpy(fctx.probs.mv.class[i], s->prob_ctx[id].p.mv_comp[i].classes, sizeof(s->prob_ctx[id].p.mv_comp[0].classes)); ++ fctx.probs.mv.class0_bit[i] = s->prob_ctx[id].p.mv_comp[i].class0; ++ memcpy(fctx.probs.mv.bits[i], s->prob_ctx[id].p.mv_comp[i].bits, sizeof(s->prob_ctx[id].p.mv_comp[0].bits)); ++ memcpy(fctx.probs.mv.class0_fr[i], s->prob_ctx[id].p.mv_comp[i].class0_fp, sizeof(s->prob_ctx[id].p.mv_comp[0].class0_fp)); ++ memcpy(fctx.probs.mv.fr[i], s->prob_ctx[id].p.mv_comp[i].fp, sizeof(s->prob_ctx[id].p.mv_comp[0].fp)); ++ fctx.probs.mv.class0_hp[i] = s->prob_ctx[id].p.mv_comp[i].class0_hp; ++ fctx.probs.mv.hp[i] = s->prob_ctx[id].p.mv_comp[i].hp; ++ } ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_vp9_get_frame_ctx(AVCodecContext *avctx, unsigned int id) ++{ ++ VP9Context *s = avctx->priv_data; ++ struct v4l2_ctrl_vp9_frame_ctx fctx = {}; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(id), ++ .ptr = &fctx, ++ .size = sizeof(fctx), ++ }, ++ }; ++ ++ int ret = ff_v4l2_request_get_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ memcpy(s->prob_ctx[id].p.tx8p, fctx.probs.tx8, sizeof(s->prob_ctx[id].p.tx8p)); ++ memcpy(s->prob_ctx[id].p.tx16p, fctx.probs.tx16, sizeof(s->prob_ctx[id].p.tx16p)); ++ memcpy(s->prob_ctx[id].p.tx32p, fctx.probs.tx32, sizeof(s->prob_ctx[id].p.tx32p)); ++ memcpy(s->prob_ctx[id].coef, fctx.probs.coef, sizeof(s->prob_ctx[id].coef)); ++ memcpy(s->prob_ctx[id].p.skip, fctx.probs.skip, sizeof(s->prob_ctx[id].p.skip)); ++ memcpy(s->prob_ctx[id].p.mv_mode, fctx.probs.inter_mode, sizeof(s->prob_ctx[id].p.mv_mode)); ++ memcpy(s->prob_ctx[id].p.filter, fctx.probs.interp_filter, sizeof(s->prob_ctx[id].p.filter)); ++ memcpy(s->prob_ctx[id].p.intra, fctx.probs.is_inter, sizeof(s->prob_ctx[id].p.intra)); ++ memcpy(s->prob_ctx[id].p.comp, fctx.probs.comp_mode, sizeof(s->prob_ctx[id].p.comp)); ++ memcpy(s->prob_ctx[id].p.single_ref, fctx.probs.single_ref, sizeof(s->prob_ctx[id].p.single_ref)); ++ memcpy(s->prob_ctx[id].p.comp_ref, fctx.probs.comp_ref, sizeof(s->prob_ctx[id].p.comp_ref)); ++ memcpy(s->prob_ctx[id].p.y_mode, fctx.probs.y_mode, sizeof(s->prob_ctx[id].p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(s->prob_ctx[id].p.uv_mode[i], fctx.probs.uv_mode[ff_to_v4l2_intramode[i]], sizeof(s->prob_ctx[id].p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(s->prob_ctx[id].p.partition[3 - i], fctx.probs.partition[i * 4], sizeof(s->prob_ctx[id].p.partition[0])); ++ memcpy(s->prob_ctx[id].p.mv_joint, fctx.probs.mv.joint, sizeof(s->prob_ctx[id].p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ s->prob_ctx[id].p.mv_comp[i].sign = fctx.probs.mv.sign[i]; ++ memcpy(s->prob_ctx[id].p.mv_comp[i].classes, fctx.probs.mv.class[i], sizeof(s->prob_ctx[id].p.mv_comp[0].classes)); ++ s->prob_ctx[id].p.mv_comp[i].class0 = fctx.probs.mv.class0_bit[i]; ++ memcpy(s->prob_ctx[id].p.mv_comp[i].bits, fctx.probs.mv.bits[i], sizeof(s->prob_ctx[id].p.mv_comp[0].bits)); ++ memcpy(s->prob_ctx[id].p.mv_comp[i].class0_fp, fctx.probs.mv.class0_fr[i], sizeof(s->prob_ctx[id].p.mv_comp[0].class0_fp)); ++ memcpy(s->prob_ctx[id].p.mv_comp[i].fp, fctx.probs.mv.fr[i], sizeof(s->prob_ctx[id].p.mv_comp[0].fp)); ++ s->prob_ctx[id].p.mv_comp[i].class0_hp = fctx.probs.mv.class0_hp[i]; ++ s->prob_ctx[id].p.mv_comp[i].hp = fctx.probs.mv.hp[i]; ++ } ++ ++ return 0; ++} ++ ++static int v4l2_request_vp9_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ struct v4l2_ctrl_vp9_frame_decode_params *dec_params = &controls->decode_params; ++ int ret; ++ ++ if (s->s.h.keyframe || s->s.h.errorres || (s->s.h.intraonly && s->s.h.resetctx == 3)) { ++ for (unsigned i = 0; i < 4; i++) { ++ ret = v4l2_request_vp9_set_frame_ctx(avctx, i); ++ if (ret) ++ return ret; ++ } ++ } else if (s->s.h.intraonly && s->s.h.resetctx == 2) { ++ ret = v4l2_request_vp9_set_frame_ctx(avctx, s->s.h.framectxid); ++ if (ret) ++ return ret; ++ } ++ ++ if (s->s.h.keyframe) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_KEY_FRAME; ++ if (!s->s.h.invisible) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_SHOW_FRAME; ++ if (s->s.h.errorres) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT; ++ if (s->s.h.intraonly) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_INTRA_ONLY; ++ if (!s->s.h.keyframe && s->s.h.highprecisionmvs) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV; ++ if (s->s.h.refreshctx) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX; ++ if (s->s.h.parallelmode) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE; ++ if (s->ss_h) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING; ++ if (s->ss_v) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; ++ if (avctx->color_range == AVCOL_RANGE_JPEG) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING; ++ ++ dec_params->compressed_header_size = s->s.h.compressed_header_size; ++ dec_params->uncompressed_header_size = s->s.h.uncompressed_header_size; ++ dec_params->profile = s->s.h.profile; ++ dec_params->reset_frame_context = s->s.h.resetctx > 0 ? s->s.h.resetctx - 1 : 0; ++ dec_params->frame_context_idx = s->s.h.framectxid; ++ dec_params->bit_depth = s->s.h.bpp; ++ ++ dec_params->interpolation_filter = s->s.h.filtermode ^ (s->s.h.filtermode <= 1); ++ dec_params->tile_cols_log2 = s->s.h.tiling.log2_tile_cols; ++ dec_params->tile_rows_log2 = s->s.h.tiling.log2_tile_rows; ++ dec_params->tx_mode = s->s.h.txfmmode; ++ dec_params->reference_mode = s->s.h.comppredmode; ++ dec_params->frame_width_minus_1 = s->w - 1; ++ dec_params->frame_height_minus_1 = s->h - 1; ++ //dec_params->render_width_minus_1 = avctx->width - 1; ++ //dec_params->render_height_minus_1 = avctx->height - 1; ++ ++ for (unsigned i = 0; i < 3; i++) { ++ const ThreadFrame *ref = &s->s.refs[s->s.h.refidx[i]]; ++ if (ref->f && ref->f->buf[0]) ++ dec_params->refs[i] = ff_v4l2_request_get_capture_timestamp(ref->f); ++ } ++ ++ if (s->s.h.lf_delta.enabled) ++ dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED; ++ if (s->s.h.lf_delta.updated) ++ dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE; ++ ++ dec_params->lf.level = s->s.h.filter.level; ++ dec_params->lf.sharpness = s->s.h.filter.sharpness; ++ for (unsigned i = 0; i < 4; i++) ++ dec_params->lf.ref_deltas[i] = s->s.h.lf_delta.ref[i]; ++ for (unsigned i = 0; i < 2; i++) ++ dec_params->lf.mode_deltas[i] = s->s.h.lf_delta.mode[i]; ++ for (unsigned i = 0; i < 8; i++) { ++ for (unsigned j = 0; j < 4; j++) ++ memcpy(dec_params->lf.level_lookup[i][j], s->s.h.segmentation.feat[i].lflvl[j], sizeof(dec_params->lf.level_lookup[0][0])); ++ } ++ ++ dec_params->quant.base_q_idx = s->s.h.yac_qi; ++ dec_params->quant.delta_q_y_dc = s->s.h.ydc_qdelta; ++ dec_params->quant.delta_q_uv_dc = s->s.h.uvdc_qdelta; ++ dec_params->quant.delta_q_uv_ac = s->s.h.uvac_qdelta; ++ ++ if (s->s.h.segmentation.enabled) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ENABLED; ++ if (s->s.h.segmentation.update_map) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP; ++ if (s->s.h.segmentation.temporal) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE; ++ if (s->s.h.segmentation.update_data) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA; ++ if (s->s.h.segmentation.absolute_vals) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE; ++ ++ for (unsigned i = 0; i < 7; i++) ++ dec_params->seg.tree_probs[i] = s->s.h.segmentation.prob[i]; ++ ++ if (s->s.h.segmentation.temporal) { ++ for (unsigned i = 0; i < 3; i++) ++ dec_params->seg.pred_probs[i] = s->s.h.segmentation.pred_prob[i]; ++ } else { ++ memset(dec_params->seg.pred_probs, 255, sizeof(dec_params->seg.pred_probs)); ++ } ++ ++ for (unsigned i = 0; i < 8; i++) { ++ if (s->s.h.segmentation.feat[i].q_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_QP_DELTA; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_QP_DELTA] = s->s.h.segmentation.feat[i].q_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].lf_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_LF; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_LF] = s->s.h.segmentation.feat[i].lf_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].ref_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_REF_FRAME; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_REF_FRAME] = s->s.h.segmentation.feat[i].ref_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].skip_enabled) ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_SKIP; ++ } ++ ++ memcpy(dec_params->probs.tx8, s->prob.p.tx8p, sizeof(s->prob.p.tx8p)); ++ memcpy(dec_params->probs.tx16, s->prob.p.tx16p, sizeof(s->prob.p.tx16p)); ++ memcpy(dec_params->probs.tx32, s->prob.p.tx32p, sizeof(s->prob.p.tx32p)); ++ for (unsigned i = 0; i < 4; i++) { ++ for (unsigned j = 0; j < 2; j++) { ++ for (unsigned k = 0; k < 2; k++) { ++ for (unsigned l = 0; l < 6; l++) { ++ for (unsigned m = 0; m < 6; m++) { ++ memcpy(dec_params->probs.coef[i][j][k][l][m], s->prob.coef[i][j][k][l][m], sizeof(dec_params->probs.coef[0][0][0][0][0])); ++ } ++ } ++ } ++ } ++ } ++ memcpy(dec_params->probs.skip, s->prob.p.skip, sizeof(s->prob.p.skip)); ++ memcpy(dec_params->probs.inter_mode, s->prob.p.mv_mode, sizeof(s->prob.p.mv_mode)); ++ memcpy(dec_params->probs.interp_filter, s->prob.p.filter, sizeof(s->prob.p.filter)); ++ memcpy(dec_params->probs.is_inter, s->prob.p.intra, sizeof(s->prob.p.intra)); ++ memcpy(dec_params->probs.comp_mode, s->prob.p.comp, sizeof(s->prob.p.comp)); ++ memcpy(dec_params->probs.single_ref, s->prob.p.single_ref, sizeof(s->prob.p.single_ref)); ++ memcpy(dec_params->probs.comp_ref, s->prob.p.comp_ref, sizeof(s->prob.p.comp_ref)); ++ memcpy(dec_params->probs.y_mode, s->prob.p.y_mode, sizeof(s->prob.p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(dec_params->probs.uv_mode[ff_to_v4l2_intramode[i]], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(dec_params->probs.partition[i * 4], s->prob.p.partition[3 - i], sizeof(s->prob.p.partition[0])); ++ memcpy(dec_params->probs.mv.joint, s->prob.p.mv_joint, sizeof(s->prob.p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ dec_params->probs.mv.sign[i] = s->prob.p.mv_comp[i].sign; ++ memcpy(dec_params->probs.mv.class[i], s->prob.p.mv_comp[i].classes, sizeof(s->prob.p.mv_comp[0].classes)); ++ dec_params->probs.mv.class0_bit[i] = s->prob.p.mv_comp[i].class0; ++ memcpy(dec_params->probs.mv.bits[i], s->prob.p.mv_comp[i].bits, sizeof(s->prob.p.mv_comp[0].bits)); ++ memcpy(dec_params->probs.mv.class0_fr[i], s->prob.p.mv_comp[i].class0_fp, sizeof(s->prob.p.mv_comp[0].class0_fp)); ++ memcpy(dec_params->probs.mv.fr[i], s->prob.p.mv_comp[i].fp, sizeof(s->prob.p.mv_comp[0].fp)); ++ dec_params->probs.mv.class0_hp[i] = s->prob.p.mv_comp[i].class0_hp; ++ dec_params->probs.mv.hp[i] = s->prob.p.mv_comp[i].hp; ++ } ++ ++ return ff_v4l2_request_reset_frame(avctx, f->tf.f); ++} ++ ++static int v4l2_request_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, f->tf.f, buffer, size); ++} ++ ++static int v4l2_request_vp9_end_frame(AVCodecContext *avctx) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, ++ }; ++ ++ ret = ff_v4l2_request_decode_frame(avctx, f->tf.f, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ if (!s->s.h.refreshctx) ++ return 0; ++ ++ return v4l2_request_vp9_get_frame_ctx(avctx, s->s.h.framectxid); ++} ++ ++static int v4l2_request_vp9_init(AVCodecContext *avctx) ++{ ++ // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_vp9_v4l2request_hwaccel = { ++ .name = "vp9_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_VP9, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_vp9_start_frame, ++ .decode_slice = v4l2_request_vp9_decode_slice, ++ .end_frame = v4l2_request_vp9_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsVP9), ++ .init = v4l2_request_vp9_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/vp8-ctrls.h b/libavcodec/vp8-ctrls.h +new file mode 100644 +index 0000000000..53cba826e4 +--- /dev/null ++++ b/libavcodec/vp8-ctrls.h +@@ -0,0 +1,112 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP8 state controls for use with stateless VP8 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP8_CTRLS_H_ ++#define _VP8_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000) ++#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301 ++ ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08 ++ ++struct v4l2_vp8_segment_header { ++ __s8 quant_update[4]; ++ __s8 lf_update[4]; ++ __u8 segment_probs[3]; ++ __u8 padding; ++ __u32 flags; ++}; ++ ++#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01 ++#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02 ++#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04 ++struct v4l2_vp8_loopfilter_header { ++ __s8 ref_frm_delta[4]; ++ __s8 mb_mode_delta[4]; ++ __u8 sharpness_level; ++ __u8 level; ++ __u16 padding; ++ __u32 flags; ++}; ++ ++struct v4l2_vp8_quantization_header { ++ __u8 y_ac_qi; ++ __s8 y_dc_delta; ++ __s8 y2_dc_delta; ++ __s8 y2_ac_delta; ++ __s8 uv_dc_delta; ++ __s8 uv_ac_delta; ++ __u16 padding; ++}; ++ ++struct v4l2_vp8_entropy_header { ++ __u8 coeff_probs[4][8][3][11]; ++ __u8 y_mode_probs[4]; ++ __u8 uv_mode_probs[3]; ++ __u8 mv_probs[2][19]; ++ __u8 padding[3]; ++}; ++ ++struct v4l2_vp8_entropy_coder_state { ++ __u8 range; ++ __u8 value; ++ __u8 bit_count; ++ __u8 padding; ++}; ++ ++#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01 ++#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04 ++#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20 ++ ++#define VP8_FRAME_IS_KEY_FRAME(hdr) \ ++ (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) ++ ++struct v4l2_ctrl_vp8_frame_header { ++ struct v4l2_vp8_segment_header segment_header; ++ struct v4l2_vp8_loopfilter_header lf_header; ++ struct v4l2_vp8_quantization_header quant_header; ++ struct v4l2_vp8_entropy_header entropy_header; ++ struct v4l2_vp8_entropy_coder_state coder_state; ++ ++ __u16 width; ++ __u16 height; ++ ++ __u8 horizontal_scale; ++ __u8 vertical_scale; ++ ++ __u8 version; ++ __u8 prob_skip_false; ++ __u8 prob_intra; ++ __u8 prob_last; ++ __u8 prob_gf; ++ __u8 num_dct_parts; ++ ++ __u32 first_part_size; ++ __u32 first_part_header_bits; ++ __u32 dct_part_sizes[8]; ++ ++ __u64 last_frame_ts; ++ __u64 golden_frame_ts; ++ __u64 alt_frame_ts; ++ ++ __u64 flags; ++}; ++ ++#endif +diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c +index bab4223aca..0e1edb46fb 100644 +--- a/libavcodec/vp8.c ++++ b/libavcodec/vp8.c +@@ -175,6 +175,9 @@ static enum AVPixelFormat get_pixel_format(VP8Context *s) + #endif + #if CONFIG_VP8_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, ++#endif ++#if CONFIG_VP8_V4L2REQUEST_HWACCEL ++ AV_PIX_FMT_DRM_PRIME, + #endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE, +@@ -198,7 +201,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7) + return ret; + } + +- if (!s->actually_webp && !is_vp7) { ++ if (!s->actually_webp && !is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { + s->pix_fmt = get_pixel_format(s); + if (s->pix_fmt < 0) + return AVERROR(EINVAL); +@@ -2968,6 +2971,9 @@ AVCodec ff_vp8_decoder = { + #endif + #if CONFIG_VP8_NVDEC_HWACCEL + HWACCEL_NVDEC(vp8), ++#endif ++#if CONFIG_VP8_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp8), + #endif + NULL + }, +diff --git a/libavcodec/vp9-ctrls.h b/libavcodec/vp9-ctrls.h +new file mode 100644 +index 0000000000..0cdea8a18b +--- /dev/null ++++ b/libavcodec/vp9-ctrls.h +@@ -0,0 +1,485 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP9 state controls for use with stateless VP9 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP9_CTRLS_H_ ++#define _VP9_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i)) ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004) ++#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400 ++#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404 ++ ++/** ++ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags ++ * ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on ++ * the mode and reference frame used ++ * to predict a block ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional ++ * syntax elements that specify which ++ * mode and reference frame deltas ++ * are to be updated ++ * ++ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See ++ * section '7.2.8 Loop filter semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_loop_filter_flags { ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0, ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1, ++}; ++ ++/** ++ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters ++ * ++ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags ++ * @level: indicates the loop filter strength ++ * @sharpness: indicates the sharpness level ++ * @ref_deltas: contains the adjustment needed for the filter level based on ++ * the chosen reference frame ++ * @mode_deltas: contains the adjustment needed for the filter level based on ++ * the chosen mode ++ * @level_lookup: level lookup table ++ * ++ * This structure contains all loop filter related parameters. See sections ++ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process' ++ * of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_loop_filter { ++ __u8 flags; ++ __u8 level; ++ __u8 sharpness; ++ __s8 ref_deltas[4]; ++ __s8 mode_deltas[2]; ++ __u8 level_lookup[8][4][2]; ++}; ++ ++/** ++ * struct v4l2_vp9_quantization - VP9 quantization parameters ++ * ++ * @base_q_idx: indicates the base frame qindex ++ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx ++ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx ++ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx ++ * @padding: padding bytes to align things on 64 bits. Must be set to 0 ++ * ++ * Encodes the quantization parameters. See section '7.2.9 Quantization params ++ * syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_quantization { ++ __u8 base_q_idx; ++ __s8 delta_q_y_dc; ++ __s8 delta_q_uv_dc; ++ __s8 delta_q_uv_ac; ++ __u8 padding[4]; ++}; ++ ++/** ++ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags ++ * ++ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of ++ * the segmentation tool ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map ++ * should be updated during the ++ * decoding of this frame ++ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to ++ * the segmentation map are coded ++ * relative to the existing ++ * segmentation map ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are ++ * about to be specified for each ++ * segment ++ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the ++ * segmentation parameters ++ * represent the actual values ++ * to be used ++ * ++ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See ++ * section '7.2.10 Segmentation params syntax' of the VP9 specification for ++ * more details. ++ */ ++enum v4l2_vp9_segmentation_flags { ++ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1, ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3, ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4, ++}; ++ ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf ++ ++/** ++ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs ++ * ++ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features ++ * ++ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the ++ * VP9 specification for more details. ++ */ ++enum v4l2_vp9_segment_feature { ++ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA, ++ V4L2_VP9_SEGMENT_FEATURE_LF, ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME, ++ V4L2_VP9_SEGMENT_FEATURE_SKIP, ++ V4L2_VP9_SEGMENT_FEATURE_CNT, ++}; ++ ++/** ++ * struct v4l2_vp9_segmentation - VP9 segmentation parameters ++ * ++ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags ++ * @tree_probs: specifies the probability values to be used when ++ * decoding a Segment-ID. See '5.15. Segmentation map' ++ * section of the VP9 specification for more details. ++ * @pred_prob: specifies the probability values to be used when decoding a ++ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ * section of :ref:`vp9` for more details.. ++ * @padding: padding used to make things aligned on 64 bits. Shall be zero ++ * filled ++ * @feature_enabled: bitmask defining which features are enabled in each ++ * segment ++ * @feature_data: data attached to each feature. Data entry is only valid if ++ * the feature is enabled ++ * ++ * Encodes the quantization parameters. See section '7.2.10 Segmentation ++ * params syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_segmentation { ++ __u8 flags; ++ __u8 tree_probs[7]; ++ __u8 pred_probs[3]; ++ __u8 padding[5]; ++ __u8 feature_enabled[8]; ++ __s16 feature_data[8][4]; ++}; ++ ++/** ++ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes ++ * ++ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction ++ * ++ * See section '7.4.5 Intra frame mode info semantics' for more details. ++ */ ++enum v4l2_vp9_intra_prediction_mode { ++ V4L2_VP9_INTRA_PRED_MODE_DC, ++ V4L2_VP9_INTRA_PRED_MODE_V, ++ V4L2_VP9_INTRA_PRED_MODE_H, ++ V4L2_VP9_INTRA_PRED_MODE_D45, ++ V4L2_VP9_INTRA_PRED_MODE_D135, ++ V4L2_VP9_INTRA_PRED_MODE_D117, ++ V4L2_VP9_INTRA_PRED_MODE_D153, ++ V4L2_VP9_INTRA_PRED_MODE_D207, ++ V4L2_VP9_INTRA_PRED_MODE_D63, ++ V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++/** ++ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities ++ * @joint: motion vector joint probabilities ++ * @sign: motion vector sign probabilities ++ * @class: motion vector class probabilities ++ * @class0_bit: motion vector class0 bit probabilities ++ * @bits: motion vector bits probabilities ++ * @class0_fr: motion vector class0 fractional bit probabilities ++ * @fr: motion vector fractional bit probabilities ++ * @class0_hp: motion vector class0 high precision fractional bit probabilities ++ * @hp: motion vector high precision fractional bit probabilities ++ */ ++struct v4l2_vp9_mv_probabilities { ++ __u8 joint[3]; ++ __u8 sign[2]; ++ __u8 class[2][10]; ++ __u8 class0_bit[2]; ++ __u8 bits[2][10]; ++ __u8 class0_fr[2][2][3]; ++ __u8 fr[2][3]; ++ __u8 class0_hp[2]; ++ __u8 hp[2]; ++}; ++ ++/** ++ * struct v4l2_vp9_probabilities - VP9 Probabilities ++ * ++ * @tx8: TX 8x8 probabilities ++ * @tx16: TX 16x16 probabilities ++ * @tx32: TX 32x32 probabilities ++ * @coef: coefficient probabilities ++ * @skip: skip probabilities ++ * @inter_mode: inter mode probabilities ++ * @interp_filter: interpolation filter probabilities ++ * @is_inter: is inter-block probabilities ++ * @comp_mode: compound prediction mode probabilities ++ * @single_ref: single ref probabilities ++ * @comp_ref: compound ref probabilities ++ * @y_mode: Y prediction mode probabilities ++ * @uv_mode: UV prediction mode probabilities ++ * @partition: partition probabilities ++ * @mv: motion vector probabilities ++ * ++ * Structure containing most VP9 probabilities. See the VP9 specification ++ * for more details. ++ */ ++struct v4l2_vp9_probabilities { ++ __u8 tx8[2][1]; ++ __u8 tx16[2][2]; ++ __u8 tx32[2][3]; ++ __u8 coef[4][2][2][6][6][3]; ++ __u8 skip[3]; ++ __u8 inter_mode[7][3]; ++ __u8 interp_filter[4][2]; ++ __u8 is_inter[4]; ++ __u8 comp_mode[5]; ++ __u8 single_ref[5][2]; ++ __u8 comp_ref[5]; ++ __u8 y_mode[4][9]; ++ __u8 uv_mode[10][9]; ++ __u8 partition[16][3]; ++ ++ struct v4l2_vp9_mv_probabilities mv; ++}; ++ ++/** ++ * enum v4l2_vp9_reset_frame_context - Valid values for ++ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context ++ * ++ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context ++ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by ++ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx ++ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts ++ * ++ * See section '7.2 Uncompressed header semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reset_frame_context { ++ V4L2_VP9_RESET_FRAME_CTX_NONE, ++ V4L2_VP9_RESET_FRAME_CTX_SPEC, ++ V4L2_VP9_RESET_FRAME_CTX_ALL, ++}; ++ ++/** ++ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types ++ * ++ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter ++ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter ++ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the ++ * block level ++ * ++ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_interpolation_filter { ++ V4L2_VP9_INTERP_FILTER_8TAP, ++ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH, ++ V4L2_VP9_INTERP_FILTER_8TAP_SHARP, ++ V4L2_VP9_INTERP_FILTER_BILINEAR, ++ V4L2_VP9_INTERP_FILTER_SWITCHABLE, ++}; ++ ++/** ++ * enum v4l2_vp9_reference_mode - VP9 reference modes ++ * ++ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a ++ * single reference frame to generate motion ++ * compensated prediction ++ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound ++ * mode. Single reference frame prediction is not ++ * allowed ++ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select ++ * between single and compound prediction modes ++ * ++ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reference_mode { ++ V4L2_VP9_REF_MODE_SINGLE, ++ V4L2_VP9_REF_MODE_COMPOUND, ++ V4L2_VP9_REF_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_tx_mode - VP9 TX modes ++ * ++ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4 ++ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8 ++ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16 ++ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32 ++ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block ++ * ++ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_tx_mode { ++ V4L2_VP9_TX_MODE_ONLY_4X4, ++ V4L2_VP9_TX_MODE_ALLOW_8X8, ++ V4L2_VP9_TX_MODE_ALLOW_16X16, ++ V4L2_VP9_TX_MODE_ALLOW_32X32, ++ V4L2_VP9_TX_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs ++ * ++ * @V4L2_REF_ID_LAST: last reference frame ++ * @V4L2_REF_ID_GOLDEN: golden reference frame ++ * @V4L2_REF_ID_ALTREF: alternative reference frame ++ * @V4L2_REF_ID_CNT: number of reference frames ++ * ++ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_ref_id { ++ V4L2_REF_ID_LAST, ++ V4L2_REF_ID_GOLDEN, ++ V4L2_REF_ID_ALTREF, ++ V4L2_REF_ID_CNT, ++}; ++ ++/** ++ * enum v4l2_vp9_frame_flags - VP9 frame flags ++ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame ++ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed ++ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient ++ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames ++ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision ++ * motion vectors ++ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated ++ * after decoding ++ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used ++ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used ++ * ++ * Check the VP9 specification for more details. ++ */ ++enum v4l2_vp9_frame_flags { ++ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0, ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1, ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2, ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3, ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4, ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5, ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6, ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7, ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8, ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9, ++}; ++ ++#define V4L2_VP9_PROFILE_MAX 3 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control ++ * ++ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags ++ * @compressed_header_size: compressed header size in bytes ++ * @uncompressed_header_size: uncompressed header size in bytes ++ * @profile: VP9 profile. Can be 0, 1, 2 or 3 ++ * @reset_frame_context: specifies whether the frame context should be reset ++ * to default values. See &v4l2_vp9_reset_frame_context ++ * for more details ++ * @frame_context_idx: frame context that should be used/updated ++ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all ++ * profiles support 10 and/or 12 bits depths ++ * @interpolation_filter: specifies the filter selection used for performing ++ * inter prediction. See &v4l2_vp9_interpolation_filter ++ * for more details ++ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile ++ * (where the width is measured in units of 8x8 blocks). ++ * Shall be less than or equal to 6 ++ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile ++ * (where the height is measured in units of 8x8 blocks) ++ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details ++ * @reference_mode: specifies the type of inter prediction to be used. See ++ * &v4l2_vp9_reference_mode for more details ++ * @padding: needed to make this struct 64 bit aligned. Shall be filled with ++ * zeros ++ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed ++ * in pixels ++ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed ++ * in pixels ++ * @frame_width_minus_1: add 1 to it and you'll get the expected render width ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @frame_height_minus_1: add 1 to it and you'll get the expected render height ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @refs: array of reference frames. See &v4l2_vp9_ref_id for more details ++ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details ++ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details ++ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details ++ * @probs: probabilities. See &v4l2_vp9_probabilities for more details ++ */ ++struct v4l2_ctrl_vp9_frame_decode_params { ++ __u32 flags; ++ __u16 compressed_header_size; ++ __u16 uncompressed_header_size; ++ __u8 profile; ++ __u8 reset_frame_context; ++ __u8 frame_context_idx; ++ __u8 bit_depth; ++ __u8 interpolation_filter; ++ __u8 tile_cols_log2; ++ __u8 tile_rows_log2; ++ __u8 tx_mode; ++ __u8 reference_mode; ++ __u8 padding[6]; ++ __u16 frame_width_minus_1; ++ __u16 frame_height_minus_1; ++ __u16 render_width_minus_1; ++ __u16 render_height_minus_1; ++ __u64 refs[V4L2_REF_ID_CNT]; ++ struct v4l2_vp9_loop_filter lf; ++ struct v4l2_vp9_quantization quant; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#define V4L2_VP9_NUM_FRAME_CTX 4 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control ++ * ++ * @probs: VP9 probabilities ++ * ++ * This control is accessed in both direction. The user should initialize the ++ * 4 contexts with default values just after starting the stream. Then before ++ * decoding a frame it should query the current frame context (the one passed ++ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize ++ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based ++ * on the bitstream info and passed to the kernel. The codec should update ++ * the frame context after the frame has been decoded, so that next time ++ * userspace query this context it contains the updated probabilities. ++ */ ++struct v4l2_ctrl_vp9_frame_ctx { ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#endif /* _VP9_CTRLS_H_ */ +diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c +index fd0bab14a2..434f905c62 100644 +--- a/libavcodec/vp9.c ++++ b/libavcodec/vp9.c +@@ -191,6 +191,7 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \ + CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ + CONFIG_VP9_NVDEC_HWACCEL + \ ++ CONFIG_VP9_V4L2REQUEST_HWACCEL + \ + CONFIG_VP9_VAAPI_HWACCEL + \ + CONFIG_VP9_VDPAU_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; +@@ -223,6 +224,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #endif + #if CONFIG_VP9_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ *fmtp++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P12: +@@ -231,6 +235,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #endif + #if CONFIG_VP9_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ *fmtp++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + } +@@ -700,7 +707,8 @@ static int decode_frame_header(AVCodecContext *avctx, + get_bits(&s->gb, 8) : 255; + } + +- if (get_bits1(&s->gb)) { ++ s->s.h.segmentation.update_data = get_bits1(&s->gb); ++ if (s->s.h.segmentation.update_data) { + s->s.h.segmentation.absolute_vals = get_bits1(&s->gb); + for (i = 0; i < 8; i++) { + if ((s->s.h.segmentation.feat[i].q_enabled = get_bits1(&s->gb))) +@@ -1909,6 +1917,9 @@ AVCodec ff_vp9_decoder = { + #endif + #if CONFIG_VP9_VDPAU_HWACCEL + HWACCEL_VDPAU(vp9), ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp9), + #endif + NULL + }, +diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h +index 54726df742..fee3568736 100644 +--- a/libavcodec/vp9shared.h ++++ b/libavcodec/vp9shared.h +@@ -131,6 +131,7 @@ typedef struct VP9BitstreamHeader { + uint8_t temporal; + uint8_t absolute_vals; + uint8_t update_map; ++ uint8_t update_data; + uint8_t prob[7]; + uint8_t pred_prob[3]; + struct { +diff --git a/libavdevice/Makefile b/libavdevice/Makefile +index 6ea62b914e..c8c9eeb22b 100644 +--- a/libavdevice/Makefile ++++ b/libavdevice/Makefile +@@ -45,6 +45,9 @@ OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o + OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_enc.o sndio.o + OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o v4l2-common.o timefilter.o + OBJS-$(CONFIG_V4L2_OUTDEV) += v4l2enc.o v4l2-common.o ++OBJS-$(CONFIG_VOUT_DRM_OUTDEV) += drm_vout.o ++OBJS-$(CONFIG_VOUT_EGL_OUTDEV) += egl_vout.o ++OBJS-$(CONFIG_VOUT_RPI_OUTDEV) += rpi_vout.o + OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o + OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o + OBJS-$(CONFIG_XV_OUTDEV) += xv.o +diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c +index 8633433254..bc15112a00 100644 +--- a/libavdevice/alldevices.c ++++ b/libavdevice/alldevices.c +@@ -52,6 +52,9 @@ extern AVOutputFormat ff_sndio_muxer; + extern AVInputFormat ff_v4l2_demuxer; + extern AVOutputFormat ff_v4l2_muxer; + extern AVInputFormat ff_vfwcap_demuxer; ++extern AVOutputFormat ff_vout_drm_muxer; ++extern AVOutputFormat ff_vout_egl_muxer; ++extern AVOutputFormat ff_vout_rpi_muxer; + extern AVInputFormat ff_xcbgrab_demuxer; + extern AVOutputFormat ff_xv_muxer; + +diff --git a/libavdevice/drm_vout.c b/libavdevice/drm_vout.c +new file mode 100644 +index 0000000000..c427b60d30 +--- /dev/null ++++ b/libavdevice/drm_vout.c +@@ -0,0 +1,613 @@ ++/* ++ * Copyright (c) 2020 John Cox for Raspberry Pi Trading ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++// *** This module is a work in progress and its utility is strictly ++// limited to testing. ++// Amongst other issues it doesn't wait for the pic to be displayed before ++// returning the buffer so flikering does occur. ++ ++#include "libavutil/opt.h" ++#include "libavutil/avassert.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/imgutils.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavformat/internal.h" ++#include "avdevice.h" ++ ++#include "pthread.h" ++#include ++#include ++ ++#include "drm_fourcc.h" ++#include ++#include ++#include ++#include ++ ++#include "libavutil/rpi_sand_fns.h" ++ ++#define TRACE_ALL 0 ++ ++#define NUM_BUFFERS 4 ++#define RPI_DISPLAY_ALL 0 ++ ++#define DRM_MODULE "vc4" ++ ++#define ERRSTR strerror(errno) ++ ++struct drm_setup { ++ int conId; ++ uint32_t crtcId; ++ int crtcIdx; ++ uint32_t planeId; ++ unsigned int out_fourcc; ++ struct { ++ int x, y, width, height; ++ } compose; ++}; ++ ++typedef struct drm_aux_s { ++ int fd; ++ uint32_t bo_handles[4]; ++ unsigned int fb_handle; ++} drm_aux_t; ++ ++typedef struct drm_display_env_s ++{ ++ AVClass *class; ++ ++ int drm_fd; ++ uint32_t con_id; ++ struct drm_setup setup; ++ enum AVPixelFormat avfmt; ++ ++ drm_aux_t aux[32]; ++ ++ pthread_t q_thread; ++ pthread_mutex_t q_lock; ++ sem_t q_sem; ++ int q_terminate; ++ AVFrame * q_this; ++ AVFrame * q_next; ++ ++} drm_display_env_t; ++ ++ ++static int drm_vout_write_trailer(AVFormatContext *s) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ ++ return 0; ++} ++ ++static int drm_vout_write_header(AVFormatContext *s) ++{ ++ const AVCodecParameters * const par = s->streams[0]->codecpar; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ if ( s->nb_streams > 1 ++ || par->codec_type != AVMEDIA_TYPE_VIDEO ++ || par->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) { ++ av_log(s, AV_LOG_ERROR, "Only supports one wrapped avframe stream\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++ ++static int do_display(AVFormatContext * const s, drm_display_env_t * const de, AVFrame * const frame) ++{ ++ int ret = 0; ++ ++ const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)frame->data[0]; ++ drm_aux_t * da = NULL; ++ unsigned int i; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++#endif ++ ++ for (i = 0; i != 32; ++i) { ++ if (de->aux[i].fd == -1 || de->aux[i].fd == desc->objects[0].fd) { ++ da = de->aux + i; ++ break; ++ } ++ } ++ ++ if (da == NULL) { ++ av_log(s, AV_LOG_INFO, "%s: Out of handles\n", __func__); ++ return AVERROR(EINVAL); ++ } ++ ++ if (da->fd == -1) { ++ uint32_t pitches[4] = {0}; ++ uint32_t offsets[4] = {0}; ++ uint64_t modifiers[4] = {0}; ++ uint32_t bo_plane_handles[4] = {0}; ++ int i, j, n; ++ ++ for (i = 0; i < desc->nb_objects; ++i) { ++ if (drmPrimeFDToHandle(de->drm_fd, desc->objects[i].fd, da->bo_handles + i) != 0) { ++ av_log(s, AV_LOG_WARNING, "drmPrimeFDToHandle failed: %s\n", ERRSTR); ++ return -1; ++ } ++ } ++ ++ n = 0; ++ for (i = 0; i < desc->nb_layers; ++i) { ++ for (j = 0; j < desc->layers[i].nb_planes; ++j) { ++ const AVDRMPlaneDescriptor * const p = desc->layers[i].planes + j; ++ const AVDRMObjectDescriptor * const obj = desc->objects + p->object_index; ++ pitches[n] = p->pitch; ++ offsets[n] = p->offset; ++ modifiers[n] = obj->format_modifier; ++ bo_plane_handles[n] = da->bo_handles[p->object_index]; ++ ++n; ++ } ++ } ++ ++#if 0 ++ av_log(s, AV_LOG_INFO, "%dx%d, fmt: %x, boh=%d,%d,%d,%d, pitch=%d,%d,%d,%d," ++ " offset=%d,%d,%d,%d, mod=%llx,%llx,%llx,%llx\n", ++ av_frame_cropped_width(frame), ++ av_frame_cropped_height(frame), ++ desc->layers[0].format, ++ bo_plane_handles[0], ++ bo_plane_handles[1], ++ bo_plane_handles[2], ++ bo_plane_handles[3], ++ pitches[0], ++ pitches[1], ++ pitches[2], ++ pitches[3], ++ offsets[0], ++ offsets[1], ++ offsets[2], ++ offsets[3], ++ (long long)modifiers[0], ++ (long long)modifiers[1], ++ (long long)modifiers[2], ++ (long long)modifiers[3] ++ ); ++#endif ++ ++ if (drmModeAddFB2WithModifiers(de->drm_fd, ++ av_frame_cropped_width(frame), ++ av_frame_cropped_height(frame), ++ desc->layers[0].format, bo_plane_handles, ++ pitches, offsets, modifiers, ++ &da->fb_handle, DRM_MODE_FB_MODIFIERS /** 0 if no mods */) != 0) { ++ av_log(s, AV_LOG_WARNING, "drmModeAddFB2WithModifiers failed: %s\n", ERRSTR); ++ return -1; ++ } ++ ++ da->fd = desc->objects[0].fd; ++ } ++ ++ ret = drmModeSetPlane(de->drm_fd, de->setup.planeId, de->setup.crtcId, ++ da->fb_handle, 0, ++ de->setup.compose.x, de->setup.compose.y, ++ de->setup.compose.width, ++ de->setup.compose.height, ++ 0, 0, ++ av_frame_cropped_width(frame) << 16, ++ av_frame_cropped_height(frame) << 16); ++ ++ if (ret != 0) { ++ av_log(s, AV_LOG_WARNING, "drmModeSetPlane failed: %s\n", ERRSTR); ++ } ++ ++ return ret; ++} ++ ++static void * display_thread(void * v) ++{ ++ AVFormatContext * const s = v; ++ drm_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++#endif ++ ++ for (;;) { ++ AVFrame * frame; ++ ++ while (sem_wait(&de->q_sem) != 0) { ++ av_assert0(errno == EINTR); ++ } ++ ++ if (de->q_terminate) ++ break; ++ ++ pthread_mutex_lock(&de->q_lock); ++ frame = de->q_next; ++ de->q_next = NULL; ++ pthread_mutex_unlock(&de->q_lock); ++ ++ do_display(s, de, frame); ++ ++ av_frame_free(&de->q_this); ++ de->q_this = frame; ++ } ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, ">>> %s\n", __func__); ++#endif ++ ++ return NULL; ++} ++ ++static int drm_vout_write_packet(AVFormatContext *s, AVPacket *pkt) ++{ ++ const AVFrame * const src_frame = (AVFrame *)pkt->data; ++ AVFrame * frame; ++ drm_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ ++ if ((src_frame->flags & AV_FRAME_FLAG_CORRUPT) != 0) { ++ av_log(s, AV_LOG_WARNING, "Discard corrupt frame: ts=%" PRId64 "\n", src_frame->format, src_frame->pts); ++ return 0; ++ } ++ ++ if (src_frame->format == AV_PIX_FMT_DRM_PRIME) { ++ frame = av_frame_alloc(); ++ av_frame_ref(frame, src_frame); ++ } ++ else if (src_frame->format == AV_PIX_FMT_VAAPI) { ++ frame = av_frame_alloc(); ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ if (av_hwframe_map(frame, src_frame, 0) != 0) ++ { ++ av_log(s, AV_LOG_WARNING, "Failed to map frame (format=%d) to DRM_PRiME\n", src_frame->format); ++ av_frame_free(&frame); ++ return AVERROR(EINVAL); ++ } ++ } ++ else { ++ av_log(s, AV_LOG_WARNING, "Frame (format=%d) not DRM_PRiME\n", src_frame->format); ++ return AVERROR(EINVAL); ++ } ++ ++ ++ pthread_mutex_lock(&de->q_lock); ++ { ++ AVFrame * const t = de->q_next; ++ de->q_next = frame; ++ frame = t; ++ } ++ pthread_mutex_unlock(&de->q_lock); ++ ++ if (frame == NULL) ++ sem_post(&de->q_sem); ++ else ++ av_frame_free(&frame); ++ ++ return 0; ++} ++ ++static int drm_vout_write_frame(AVFormatContext *s, int stream_index, AVFrame **ppframe, ++ unsigned flags) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++#endif ++ ++ /* drm_vout_write_header() should have accepted only supported formats */ ++ if ((flags & AV_WRITE_UNCODED_FRAME_QUERY)) ++ return 0; ++ ++ return 0; ++} ++ ++static int drm_vout_control_message(AVFormatContext *s, int type, void *data, size_t data_size) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: %d\n", __func__, type); ++#endif ++ switch(type) { ++ case AV_APP_TO_DEV_WINDOW_REPAINT: ++ return 0; ++ default: ++ break; ++ } ++ return AVERROR(ENOSYS); ++} ++ ++static int find_crtc(struct AVFormatContext * const avctx, int drmfd, struct drm_setup *s, uint32_t * const pConId) ++{ ++ int ret = -1; ++ int i; ++ drmModeRes *res = drmModeGetResources(drmfd); ++ drmModeConnector *c; ++ ++ if(!res) ++ { ++ printf( "drmModeGetResources failed: %s\n", ERRSTR); ++ return -1; ++ } ++ ++ if (res->count_crtcs <= 0) ++ { ++ printf( "drm: no crts\n"); ++ goto fail_res; ++ } ++ ++ if (!s->conId) { ++ fprintf(stderr, ++ "No connector ID specified. Choosing default from list:\n"); ++ ++ for (i = 0; i < res->count_connectors; i++) { ++ drmModeConnector *con = ++ drmModeGetConnector(drmfd, res->connectors[i]); ++ drmModeEncoder *enc = NULL; ++ drmModeCrtc *crtc = NULL; ++ ++ if (con->encoder_id) { ++ enc = drmModeGetEncoder(drmfd, con->encoder_id); ++ if (enc->crtc_id) { ++ crtc = drmModeGetCrtc(drmfd, enc->crtc_id); ++ } ++ } ++ ++ if (!s->conId && crtc) { ++ s->conId = con->connector_id; ++ s->crtcId = crtc->crtc_id; ++ } ++ ++ av_log(avctx, AV_LOG_INFO, "Connector %d (crtc %d): type %d, %dx%d%s\n", ++ con->connector_id, ++ crtc ? crtc->crtc_id : 0, ++ con->connector_type, ++ crtc ? crtc->width : 0, ++ crtc ? crtc->height : 0, ++ (s->conId == (int)con->connector_id ? ++ " (chosen)" : "")); ++ } ++ ++ if (!s->conId) { ++ av_log(avctx, AV_LOG_ERROR, ++ "No suitable enabled connector found.\n"); ++ return -1;; ++ } ++ } ++ ++ s->crtcIdx = -1; ++ ++ for (i = 0; i < res->count_crtcs; ++i) { ++ if (s->crtcId == res->crtcs[i]) { ++ s->crtcIdx = i; ++ break; ++ } ++ } ++ ++ if (s->crtcIdx == -1) ++ { ++ av_log(avctx, AV_LOG_WARNING, "drm: CRTC %u not found\n", s->crtcId); ++ goto fail_res; ++ } ++ ++ if (res->count_connectors <= 0) ++ { ++ av_log(avctx, AV_LOG_WARNING, "drm: no connectors\n"); ++ goto fail_res; ++ } ++ ++ c = drmModeGetConnector(drmfd, s->conId); ++ if (!c) ++ { ++ av_log(avctx, AV_LOG_WARNING, "drmModeGetConnector failed: %s\n", ERRSTR); ++ goto fail_res; ++ } ++ ++ if (!c->count_modes) ++ { ++ av_log(avctx, AV_LOG_WARNING, "connector supports no mode\n"); ++ goto fail_conn; ++ } ++ ++ { ++ drmModeCrtc *crtc = drmModeGetCrtc(drmfd, s->crtcId); ++ s->compose.x = crtc->x; ++ s->compose.y = crtc->y; ++ s->compose.width = crtc->width; ++ s->compose.height = crtc->height; ++ drmModeFreeCrtc(crtc); ++ } ++ ++ if (pConId) ++ *pConId = c->connector_id; ++ ret = 0; ++ ++fail_conn: ++ drmModeFreeConnector(c); ++ ++fail_res: ++ drmModeFreeResources(res); ++ ++ return ret; ++} ++ ++static int find_plane(struct AVFormatContext * const avctx, int drmfd, struct drm_setup *s) ++{ ++ drmModePlaneResPtr planes; ++ drmModePlanePtr plane; ++ unsigned int i; ++ unsigned int j; ++ int ret = 0; ++ ++ planes = drmModeGetPlaneResources(drmfd); ++ if (!planes) ++ { ++ av_log(avctx, AV_LOG_WARNING, "drmModeGetPlaneResources failed: %s\n", ERRSTR); ++ return -1; ++ } ++ ++ for (i = 0; i < planes->count_planes; ++i) { ++ plane = drmModeGetPlane(drmfd, planes->planes[i]); ++ if (!planes) ++ { ++ av_log(avctx, AV_LOG_WARNING, "drmModeGetPlane failed: %s\n", ERRSTR); ++ break; ++ } ++ ++ if (!(plane->possible_crtcs & (1 << s->crtcIdx))) { ++ drmModeFreePlane(plane); ++ continue; ++ } ++ ++ for (j = 0; j < plane->count_formats; ++j) { ++ if (plane->formats[j] == s->out_fourcc) ++ break; ++ } ++ ++ if (j == plane->count_formats) { ++ drmModeFreePlane(plane); ++ continue; ++ } ++ ++ s->planeId = plane->plane_id; ++ drmModeFreePlane(plane); ++ break; ++ } ++ ++ if (i == planes->count_planes) ++ ret = -1; ++ ++ drmModeFreePlaneResources(planes); ++ return ret; ++} ++ ++// deinit is called if init fails so no need to clean up explicity here ++static int drm_vout_init(struct AVFormatContext * s) ++{ ++ drm_display_env_t * const de = s->priv_data; ++ unsigned int i; ++ ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++ ++ de->drm_fd = -1; ++ de->con_id = 0; ++ de->setup = (struct drm_setup){0}; ++ ++ de->setup.out_fourcc = DRM_FORMAT_NV12; // **** Need some sort of select ++ ++ for (i = 0; i != 32; ++i) { ++ de->aux[i].fd = -1; ++ } ++ ++ if ((de->drm_fd = drmOpen(DRM_MODULE, NULL)) < 0) ++ { ++ av_log(s, AV_LOG_ERROR, "Failed to drmOpen %s\n", DRM_MODULE); ++ return -1; ++ } ++ ++ if (find_crtc(s, de->drm_fd, &de->setup, &de->con_id) != 0) ++ { ++ av_log(s, AV_LOG_ERROR, "failed to find valid mode\n"); ++ return -1; ++ } ++ ++ if (find_plane(s, de->drm_fd, &de->setup) != 0) ++ { ++ av_log(s, AV_LOG_ERROR, "failed to find compatible plane\n"); ++ return -1; ++ } ++ ++ de->q_terminate = 0; ++ pthread_mutex_init(&de->q_lock, NULL); ++ sem_init(&de->q_sem, 0, 0); ++ av_assert0(pthread_create(&de->q_thread, NULL, display_thread, s) == 0); ++ ++ av_log(s, AV_LOG_INFO, ">>> %s\n", __func__); ++ ++ return 0; ++} ++ ++static void drm_vout_deinit(struct AVFormatContext * s) ++{ ++ drm_display_env_t * const de = s->priv_data; ++ ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++ ++ de->q_terminate = 1; ++ sem_post(&de->q_sem); ++ pthread_join(de->q_thread, NULL); ++ sem_destroy(&de->q_sem); ++ pthread_mutex_destroy(&de->q_lock); ++ ++ av_frame_free(&de->q_next); ++ av_frame_free(&de->q_this); ++ ++ if (de->drm_fd >= 0) { ++ close(de->drm_fd); ++ de->drm_fd = -1; ++ } ++ ++ av_log(s, AV_LOG_INFO, ">>> %s\n", __func__); ++} ++ ++ ++#define OFFSET(x) offsetof(drm_display_env_t, x) ++static const AVOption options[] = { ++#if 0 ++ { "display_name", "set display name", OFFSET(display_name), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_id", "set existing window id", OFFSET(window_id), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_size", "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_x", "set window x offset", OFFSET(window_x), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_y", "set window y offset", OFFSET(window_y), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++#endif ++ { NULL } ++ ++}; ++ ++static const AVClass drm_vout_class = { ++ .class_name = "drm vid outdev", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++ .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, ++}; ++ ++AVOutputFormat ff_vout_drm_muxer = { ++ .name = "vout_drm", ++ .long_name = NULL_IF_CONFIG_SMALL("Drm video output device"), ++ .priv_data_size = sizeof(drm_display_env_t), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .write_header = drm_vout_write_header, ++ .write_packet = drm_vout_write_packet, ++ .write_uncoded_frame = drm_vout_write_frame, ++ .write_trailer = drm_vout_write_trailer, ++ .control_message = drm_vout_control_message, ++ .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &drm_vout_class, ++ .init = drm_vout_init, ++ .deinit = drm_vout_deinit, ++}; +diff --git a/libavdevice/egl_vout.c b/libavdevice/egl_vout.c +new file mode 100644 +index 0000000000..d5b2e161d5 +--- /dev/null ++++ b/libavdevice/egl_vout.c +@@ -0,0 +1,805 @@ ++/* ++ * Copyright (c) 2020 John Cox for Raspberry Pi Trading ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++// *** This module is a work in progress and its utility is strictly ++// limited to testing. ++// Amongst other issues it doesn't wait for the pic to be displayed before ++// returning the buffer so flikering does occur. ++ ++#include ++#include ++ ++#include "libavutil/opt.h" ++#include "libavutil/avassert.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/imgutils.h" ++#include "libavutil/hwcontext_drm.h" ++#include "libavformat/internal.h" ++#include "avdevice.h" ++ ++#include "pthread.h" ++#include ++#include ++ ++#include "drm_fourcc.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "libavutil/rpi_sand_fns.h" ++ ++#define TRACE_ALL 0 ++ ++struct egl_setup { ++ int conId; ++ ++ Display *dpy; ++ EGLDisplay egl_dpy; ++ EGLContext ctx; ++ EGLSurface surf; ++ Window win; ++ ++ uint32_t crtcId; ++ int crtcIdx; ++ uint32_t planeId; ++ struct { ++ int x, y, width, height; ++ } compose; ++}; ++ ++typedef struct egl_aux_s { ++ int fd; ++ GLuint texture; ++ ++} egl_aux_t; ++ ++typedef struct egl_display_env_s ++{ ++ AVClass *class; ++ ++ struct egl_setup setup; ++ enum AVPixelFormat avfmt; ++ ++ egl_aux_t aux[32]; ++ ++ pthread_t q_thread; ++ pthread_mutex_t q_lock; ++ sem_t display_start_sem; ++ sem_t q_sem; ++ int q_terminate; ++ AVFrame * q_this; ++ AVFrame * q_next; ++ ++} egl_display_env_t; ++ ++ ++/** ++ * Remove window border/decorations. ++ */ ++static void ++no_border( Display *dpy, Window w) ++{ ++ static const unsigned MWM_HINTS_DECORATIONS = (1 << 1); ++ static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5; ++ ++ typedef struct ++ { ++ unsigned long flags; ++ unsigned long functions; ++ unsigned long decorations; ++ long inputMode; ++ unsigned long status; ++ } PropMotifWmHints; ++ ++ PropMotifWmHints motif_hints; ++ Atom prop, proptype; ++ unsigned long flags = 0; ++ ++ /* setup the property */ ++ motif_hints.flags = MWM_HINTS_DECORATIONS; ++ motif_hints.decorations = flags; ++ ++ /* get the atom for the property */ ++ prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True ); ++ if (!prop) { ++ /* something went wrong! */ ++ return; ++ } ++ ++ /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */ ++ proptype = prop; ++ ++ XChangeProperty( dpy, w, /* display, window */ ++ prop, proptype, /* property, type */ ++ 32, /* format: 32-bit datums */ ++ PropModeReplace, /* mode */ ++ (unsigned char *) &motif_hints, /* data */ ++ PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */ ++ ); ++} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static int ++make_window(struct AVFormatContext * const s, ++ Display *dpy, EGLDisplay egl_dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet, EGLContext *ctxRet, EGLSurface *surfRet) ++{ ++ int scrnum = DefaultScreen( dpy ); ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root = RootWindow( dpy, scrnum ); ++ Window win; ++ EGLContext ctx; ++ bool fullscreen = false; /* Hook this up to a command line arg */ ++ EGLConfig config; ++ ++ if (fullscreen) { ++ int scrnum = DefaultScreen(dpy); ++ ++ x = 0; y = 0; ++ width = DisplayWidth(dpy, scrnum); ++ height = DisplayHeight(dpy, scrnum); ++ } ++ ++ { ++ EGLint num_configs; ++ static const EGLint attribs[] = { ++ EGL_RED_SIZE, 1, ++ EGL_GREEN_SIZE, 1, ++ EGL_BLUE_SIZE, 1, ++ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, ++ EGL_NONE ++ }; ++ ++ if (!eglChooseConfig(egl_dpy, attribs, &config, 1, &num_configs)) { ++ av_log(s, AV_LOG_ERROR, "Error: couldn't get an EGL visual config\n"); ++ return -1; ++ } ++ } ++ ++ { ++ EGLint vid; ++ if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { ++ av_log(s, AV_LOG_ERROR, "Error: eglGetConfigAttrib() failed\n"); ++ return -1; ++ } ++ ++ { ++ XVisualInfo visTemplate = { ++ .visualid = vid, ++ }; ++ int num_visuals; ++ XVisualInfo *visinfo = XGetVisualInfo(dpy, VisualIDMask, ++ &visTemplate, &num_visuals); ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ /* XXX this is a bad way to get a borderless window! */ ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow( dpy, root, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ XFree(visinfo); ++ } ++ } ++ ++ if (fullscreen) ++ no_border(dpy, win); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ eglBindAPI(EGL_OPENGL_ES_API); ++ ++ { ++ static const EGLint ctx_attribs[] = { ++ EGL_CONTEXT_CLIENT_VERSION, 2, ++ EGL_NONE ++ }; ++ ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs ); ++ if (!ctx) { ++ av_log(s, AV_LOG_ERROR, "Error: eglCreateContext failed\n"); ++ return -1; ++ } ++ } ++ ++ ++ XMapWindow(dpy, win); ++ ++ { ++ EGLSurface surf = eglCreateWindowSurface(egl_dpy, config, ++ (void *)(uintptr_t)win, NULL); ++ if (!surf) { ++ av_log(s, AV_LOG_ERROR, "Error: eglCreateWindowSurface failed\n"); ++ return -1; ++ } ++ ++ if (!eglMakeCurrent(egl_dpy, surf, surf, ctx)) { ++ av_log(s, AV_LOG_ERROR, "Error: eglCreateContext failed\n"); ++ return -1; ++ } ++ ++ *winRet = win; ++ *ctxRet = ctx; ++ *surfRet = surf; ++ } ++ ++ return 0; ++} ++ ++static GLint ++compile_shader(struct AVFormatContext * const avctx, GLenum target, const char *source) ++{ ++ GLuint s = glCreateShader(target); ++ ++ if (s == 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create shader\n"); ++ return 0; ++ } ++ ++ glShaderSource(s, 1, (const GLchar **) &source, NULL); ++ glCompileShader(s); ++ ++ { ++ GLint ok; ++ glGetShaderiv(s, GL_COMPILE_STATUS, &ok); ++ ++ if (!ok) { ++ GLchar *info; ++ GLint size; ++ ++ glGetShaderiv(s, GL_INFO_LOG_LENGTH, &size); ++ info = malloc(size); ++ ++ glGetShaderInfoLog(s, size, NULL, info); ++ av_log(avctx, AV_LOG_ERROR, "Failed to compile shader: %ssource:\n%s\n", info, source); ++ ++ return 0; ++ } ++ } ++ ++ return s; ++} ++ ++static GLuint link_program(struct AVFormatContext * const s, GLint vs, GLint fs) ++{ ++ GLuint prog = glCreateProgram(); ++ ++ if (prog == 0) { ++ av_log(s, AV_LOG_ERROR, "Failed to create program\n"); ++ return 0; ++ } ++ ++ glAttachShader(prog, vs); ++ glAttachShader(prog, fs); ++ glLinkProgram(prog); ++ ++ { ++ GLint ok; ++ glGetProgramiv(prog, GL_LINK_STATUS, &ok); ++ if (!ok) { ++ /* Some drivers return a size of 1 for an empty log. This is the size ++ * of a log that contains only a terminating NUL character. ++ */ ++ GLint size; ++ GLchar *info = NULL; ++ glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); ++ if (size > 1) { ++ info = malloc(size); ++ glGetProgramInfoLog(prog, size, NULL, info); ++ } ++ ++ av_log(s, AV_LOG_ERROR, "Failed to link: %s\n", ++ (info != NULL) ? info : ""); ++ return 0; ++ } ++ } ++ ++ return prog; ++} ++ ++static int ++gl_setup(struct AVFormatContext * const s) ++{ ++ const char *vs = ++ "attribute vec4 pos;\n" ++ "varying vec2 texcoord;\n" ++ "\n" ++ "void main() {\n" ++ " gl_Position = pos;\n" ++ " texcoord.x = (pos.x + 1.0) / 2.0;\n" ++ " texcoord.y = (-pos.y + 1.0) / 2.0;\n" ++ "}\n"; ++ const char *fs = ++ "#extension GL_OES_EGL_image_external : enable\n" ++ "precision mediump float;\n" ++ "uniform samplerExternalOES s;\n" ++ "varying vec2 texcoord;\n" ++ "void main() {\n" ++ " gl_FragColor = texture2D(s, texcoord);\n" ++ "}\n"; ++ ++ GLuint vs_s; ++ GLuint fs_s; ++ GLuint prog; ++ ++ if (!(vs_s = compile_shader(s, GL_VERTEX_SHADER, vs)) || ++ !(fs_s = compile_shader(s, GL_FRAGMENT_SHADER, fs)) || ++ !(prog = link_program(s, vs_s, fs_s))) ++ return -1; ++ ++ glUseProgram(prog); ++ ++ { ++ static const float verts[] = { ++ -1, -1, ++ 1, -1, ++ 1, 1, ++ -1, 1, ++ }; ++ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts); ++ } ++ ++ glEnableVertexAttribArray(0); ++ return 0; ++} ++ ++static int egl_vout_write_trailer(AVFormatContext *s) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ ++ return 0; ++} ++ ++static int egl_vout_write_header(AVFormatContext *s) ++{ ++ const AVCodecParameters * const par = s->streams[0]->codecpar; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ if ( s->nb_streams > 1 ++ || par->codec_type != AVMEDIA_TYPE_VIDEO ++ || par->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) { ++ av_log(s, AV_LOG_ERROR, "Only supports one wrapped avframe stream\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++ ++static int do_display(AVFormatContext * const s, egl_display_env_t * const de, AVFrame * const frame) ++{ ++ const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)frame->data[0]; ++ egl_aux_t * da = NULL; ++ unsigned int i; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++#endif ++ ++ for (i = 0; i != 32; ++i) { ++ if (de->aux[i].fd == -1 || de->aux[i].fd == desc->objects[0].fd) { ++ da = de->aux + i; ++ break; ++ } ++ } ++ ++ if (da == NULL) { ++ av_log(s, AV_LOG_INFO, "%s: Out of handles\n", __func__); ++ return AVERROR(EINVAL); ++ } ++ ++ if (da->texture == 0) { ++ EGLint attribs[50]; ++ EGLint * a = attribs; ++ int i, j; ++ static const EGLint anames[] = { ++ EGL_DMA_BUF_PLANE0_FD_EXT, ++ EGL_DMA_BUF_PLANE0_OFFSET_EXT, ++ EGL_DMA_BUF_PLANE0_PITCH_EXT, ++ EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, ++ EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, ++ EGL_DMA_BUF_PLANE1_FD_EXT, ++ EGL_DMA_BUF_PLANE1_OFFSET_EXT, ++ EGL_DMA_BUF_PLANE1_PITCH_EXT, ++ EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, ++ EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, ++ EGL_DMA_BUF_PLANE2_FD_EXT, ++ EGL_DMA_BUF_PLANE2_OFFSET_EXT, ++ EGL_DMA_BUF_PLANE2_PITCH_EXT, ++ EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, ++ EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, ++ }; ++ const EGLint * b = anames; ++ ++ *a++ = EGL_WIDTH; ++ *a++ = av_frame_cropped_width(frame); ++ *a++ = EGL_HEIGHT; ++ *a++ = av_frame_cropped_height(frame); ++ *a++ = EGL_LINUX_DRM_FOURCC_EXT; ++ *a++ = desc->layers[0].format; ++ ++ for (i = 0; i < desc->nb_layers; ++i) { ++ for (j = 0; j < desc->layers[i].nb_planes; ++j) { ++ const AVDRMPlaneDescriptor * const p = desc->layers[i].planes + j; ++ const AVDRMObjectDescriptor * const obj = desc->objects + p->object_index; ++ *a++ = *b++; ++ *a++ = obj->fd; ++ *a++ = *b++; ++ *a++ = p->offset; ++ *a++ = *b++; ++ *a++ = p->pitch; ++ if (obj->format_modifier == 0) { ++ b += 2; ++ } ++ else { ++ *a++ = *b++; ++ *a++ = (EGLint)(obj->format_modifier & 0xFFFFFFFF); ++ *a++ = *b++; ++ *a++ = (EGLint)(obj->format_modifier >> 32); ++ } ++ } ++ } ++ ++ *a = EGL_NONE; ++ ++#if TRACE_ALL ++ for (a = attribs, i = 0; *a != EGL_NONE; a += 2, ++i) { ++ av_log(s, AV_LOG_INFO, "[%2d] %4x: %d\n", i, a[0], a[1]); ++ } ++#endif ++ { ++ const EGLImage image = eglCreateImageKHR(de->setup.egl_dpy, ++ EGL_NO_CONTEXT, ++ EGL_LINUX_DMA_BUF_EXT, ++ NULL, attribs); ++ if (!image) { ++ av_log(s, AV_LOG_ERROR, "Failed to import fd %d\n", desc->objects[0].fd); ++ return -1; ++ } ++ ++ glGenTextures(1, &da->texture); ++ glBindTexture(GL_TEXTURE_EXTERNAL_OES, da->texture); ++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image); ++ ++ eglDestroyImageKHR(de->setup.egl_dpy, image); ++ } ++ ++ da->fd = desc->objects[0].fd; ++ ++#if 0 ++ av_log(s, AV_LOG_INFO, "%dx%d, fmt: %x, boh=%d,%d,%d,%d, pitch=%d,%d,%d,%d," ++ " offset=%d,%d,%d,%d, mod=%llx,%llx,%llx,%llx\n", ++ av_frame_cropped_width(frame), ++ av_frame_cropped_height(frame), ++ desc->layers[0].format, ++ bo_plane_handles[0], ++ bo_plane_handles[1], ++ bo_plane_handles[2], ++ bo_plane_handles[3], ++ pitches[0], ++ pitches[1], ++ pitches[2], ++ pitches[3], ++ offsets[0], ++ offsets[1], ++ offsets[2], ++ offsets[3], ++ (long long)modifiers[0], ++ (long long)modifiers[1], ++ (long long)modifiers[2], ++ (long long)modifiers[3] ++ ); ++#endif ++ } ++ ++ glClearColor(0.5, 0.5, 0.5, 0.5); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ glBindTexture(GL_TEXTURE_EXTERNAL_OES, da->texture); ++ glDrawArrays(GL_TRIANGLE_FAN, 0, 4); ++ eglSwapBuffers(de->setup.egl_dpy, de->setup.surf); ++ ++ return 0; ++} ++ ++static void * display_thread(void * v) ++{ ++ AVFormatContext * const s = v; ++ egl_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "<<< %s\n", __func__); ++#endif ++ { ++ EGLint egl_major, egl_minor; ++ ++ de->setup.dpy = XOpenDisplay(NULL); ++ if (!de->setup.dpy) { ++ av_log(s, AV_LOG_ERROR, "Couldn't open X display\n"); ++ goto fail; ++ } ++ ++ de->setup.egl_dpy = eglGetDisplay(de->setup.dpy); ++ if (!de->setup.egl_dpy) { ++ av_log(s, AV_LOG_ERROR, "eglGetDisplay() failed\n"); ++ goto fail; ++ } ++ ++ if (!eglInitialize(de->setup.egl_dpy, &egl_major, &egl_minor)) { ++ av_log(s, AV_LOG_ERROR, "Error: eglInitialize() failed\n"); ++ goto fail; ++ } ++ ++ av_log(s, AV_LOG_INFO, "EGL version %d.%d\n", egl_major, egl_minor); ++ ++ if (!epoxy_has_egl_extension(de->setup.egl_dpy, "EGL_KHR_image_base")) { ++ av_log(s, AV_LOG_ERROR, "Missing EGL KHR image extension\n"); ++ goto fail; ++ } ++ } ++ ++ if (make_window(s, de->setup.dpy, de->setup.egl_dpy, "ffmpeg-vout", ++ 0, 0, 1280, 720, &de->setup.win, &de->setup.ctx, &de->setup.surf)) { ++ av_log(s, AV_LOG_ERROR, "%s: make_window failed\n", __func__); ++ goto fail; ++ } ++ ++ if (gl_setup(s)) { ++ av_log(s, AV_LOG_ERROR, "%s: gl_setup failed\n", __func__); ++ goto fail; ++ } ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "--- %s: Start done\n", __func__); ++#endif ++ sem_post(&de->display_start_sem); ++ ++ for (;;) { ++ AVFrame * frame; ++ ++ while (sem_wait(&de->q_sem) != 0) { ++ av_assert0(errno == EINTR); ++ } ++ ++ if (de->q_terminate) ++ break; ++ ++ pthread_mutex_lock(&de->q_lock); ++ frame = de->q_next; ++ de->q_next = NULL; ++ pthread_mutex_unlock(&de->q_lock); ++ ++ do_display(s, de, frame); ++ ++ av_frame_free(&de->q_this); ++ de->q_this = frame; ++ } ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, ">>> %s\n", __func__); ++#endif ++ ++ return NULL; ++ ++fail: ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, ">>> %s: FAIL\n", __func__); ++#endif ++ de->q_terminate = 1; ++ sem_post(&de->display_start_sem); ++ ++ return NULL; ++} ++ ++static int egl_vout_write_packet(AVFormatContext *s, AVPacket *pkt) ++{ ++ const AVFrame * const src_frame = (AVFrame *)pkt->data; ++ AVFrame * frame; ++ egl_display_env_t * const de = s->priv_data; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ ++ if (src_frame->format == AV_PIX_FMT_DRM_PRIME) { ++ frame = av_frame_alloc(); ++ av_frame_ref(frame, src_frame); ++ } ++ else if (src_frame->format == AV_PIX_FMT_VAAPI) { ++ frame = av_frame_alloc(); ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ if (av_hwframe_map(frame, src_frame, 0) != 0) ++ { ++ av_log(s, AV_LOG_WARNING, "Failed to map frame (format=%d) to DRM_PRiME\n", src_frame->format); ++ av_frame_free(&frame); ++ return AVERROR(EINVAL); ++ } ++ } ++ else { ++ av_log(s, AV_LOG_WARNING, "Frame (format=%d) not DRM_PRiME\n", src_frame->format); ++ return AVERROR(EINVAL); ++ } ++ ++ ++ pthread_mutex_lock(&de->q_lock); ++ { ++ AVFrame * const t = de->q_next; ++ de->q_next = frame; ++ frame = t; ++ } ++ pthread_mutex_unlock(&de->q_lock); ++ ++ if (frame == NULL) ++ sem_post(&de->q_sem); ++ else ++ av_frame_free(&frame); ++ ++ return 0; ++} ++ ++static int egl_vout_write_frame(AVFormatContext *s, int stream_index, AVFrame **ppframe, ++ unsigned flags) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++#endif ++ ++ /* egl_vout_write_header() should have accepted only supported formats */ ++ if ((flags & AV_WRITE_UNCODED_FRAME_QUERY)) ++ return 0; ++ ++ return 0; ++} ++ ++static int egl_vout_control_message(AVFormatContext *s, int type, void *data, size_t data_size) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: %d\n", __func__, type); ++#endif ++ switch(type) { ++ case AV_APP_TO_DEV_WINDOW_REPAINT: ++ return 0; ++ default: ++ break; ++ } ++ return AVERROR(ENOSYS); ++} ++ ++// deinit is called if init fails so no need to clean up explicity here ++static int egl_vout_init(struct AVFormatContext * s) ++{ ++ egl_display_env_t * const de = s->priv_data; ++ unsigned int i; ++ ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ de->setup = (struct egl_setup){0}; ++ ++ for (i = 0; i != 32; ++i) { ++ de->aux[i].fd = -1; ++ } ++ ++ de->q_terminate = 0; ++ pthread_mutex_init(&de->q_lock, NULL); ++ sem_init(&de->q_sem, 0, 0); ++ sem_init(&de->display_start_sem, 0, 0); ++ av_assert0(pthread_create(&de->q_thread, NULL, display_thread, s) == 0); ++ ++ sem_wait(&de->display_start_sem); ++ if (de->q_terminate) { ++ av_log(s, AV_LOG_ERROR, "%s: Display startup failure\n", __func__); ++ return -1; ++ } ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++ ++ return 0; ++} ++ ++static void egl_vout_deinit(struct AVFormatContext * s) ++{ ++ egl_display_env_t * const de = s->priv_data; ++ ++ av_log(s, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ de->q_terminate = 1; ++ sem_post(&de->q_sem); ++ pthread_join(de->q_thread, NULL); ++ sem_destroy(&de->q_sem); ++ pthread_mutex_destroy(&de->q_lock); ++ ++ av_frame_free(&de->q_next); ++ av_frame_free(&de->q_this); ++ ++ av_log(s, AV_LOG_DEBUG, ">>> %s\n", __func__); ++} ++ ++#define OFFSET(x) offsetof(egl_display_env_t, x) ++static const AVOption options[] = { ++#if 0 ++ { "display_name", "set display name", OFFSET(display_name), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_id", "set existing window id", OFFSET(window_id), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_size", "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_x", "set window x offset", OFFSET(window_x), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_y", "set window y offset", OFFSET(window_y), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++#endif ++ { NULL } ++ ++}; ++ ++static const AVClass egl_vout_class = { ++ .class_name = "egl vid outdev", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++ .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, ++}; ++ ++AVOutputFormat ff_vout_egl_muxer = { ++ .name = "vout_egl", ++ .long_name = NULL_IF_CONFIG_SMALL("Egl video output device"), ++ .priv_data_size = sizeof(egl_display_env_t), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .write_header = egl_vout_write_header, ++ .write_packet = egl_vout_write_packet, ++ .write_uncoded_frame = egl_vout_write_frame, ++ .write_trailer = egl_vout_write_trailer, ++ .control_message = egl_vout_control_message, ++ .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &egl_vout_class, ++ .init = egl_vout_init, ++ .deinit = egl_vout_deinit, ++}; ++ +diff --git a/libavdevice/rpi_vout.c b/libavdevice/rpi_vout.c +new file mode 100644 +index 0000000000..60fe8a7075 +--- /dev/null ++++ b/libavdevice/rpi_vout.c +@@ -0,0 +1,534 @@ ++/* ++ * Copyright (c) 2013 Jeff Moguillansky ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/** ++ * @file ++ * XVideo output device ++ * ++ * TODO: ++ * - add support to more formats ++ */ ++ ++#include "libavutil/opt.h" ++#include "libavutil/avassert.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/imgutils.h" ++#include "libavformat/internal.h" ++#include "avdevice.h" ++ ++#include ++ ++#pragma GCC diagnostic push ++// Many many redundant decls in the header files ++#pragma GCC diagnostic ignored "-Wredundant-decls" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#pragma GCC diagnostic pop ++#include "libavutil/rpi_sand_fns.h" ++#include "libavcodec/rpi_zc.h" ++ ++#define TRACE_ALL 0 ++ ++#define RPI_DISPLAY_ALL 0 ++#define DISPLAY_PORT_DEPTH 4 ++ ++typedef struct rpi_display_env_s ++{ ++ AVClass *class; ++ ++ MMAL_COMPONENT_T* display; ++ MMAL_COMPONENT_T* isp; ++ MMAL_PORT_T * port_in; // Input port of either isp or display depending on pipe setup ++ MMAL_CONNECTION_T * conn; ++ ++ MMAL_POOL_T *rpi_pool; ++ volatile int rpi_display_count; ++ ++ MMAL_FOURCC_T req_fmt; ++ MMAL_VIDEO_FORMAT_T req_vfmt; ++ ++ AVZcEnvPtr zc; ++ ++ int window_width, window_height; ++ int window_x, window_y; ++ int layer, fullscreen; ++} rpi_display_env_t; ++ ++ ++static void display_cb_input(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { ++ mmal_buffer_header_release(buffer); ++} ++ ++static void display_cb_control(MMAL_PORT_T *port,MMAL_BUFFER_HEADER_T *buffer) { ++ mmal_buffer_header_release(buffer); ++} ++ ++ ++static MMAL_FOURCC_T mmfmt_from_avfmt(const enum AVPixelFormat fmt) ++{ ++ switch (fmt) { ++ case AV_PIX_FMT_SAND128: ++ case AV_PIX_FMT_RPI4_8: ++ return MMAL_ENCODING_YUVUV128; ++ case AV_PIX_FMT_RPI4_10: ++ return MMAL_ENCODING_YUV10_COL; ++ case AV_PIX_FMT_SAND64_10: ++ return MMAL_ENCODING_YUVUV64_10; ++ case AV_PIX_FMT_SAND64_16: ++ return MMAL_ENCODING_YUVUV64_16; ++ case AV_PIX_FMT_YUV420P: ++ return MMAL_ENCODING_I420; ++ ++ default: ++ break; ++ } ++ return 0; ++} ++ ++ ++static void video_format_from_zc_frame(MMAL_ES_FORMAT_T* const es_fmt, ++ const AVFrame * const frame, const AVRpiZcRefPtr fr_ref) ++{ ++ MMAL_VIDEO_FORMAT_T *const vfmt = &es_fmt->es->video; ++ const AVRpiZcFrameGeometry * geo = av_rpi_zc_geometry(fr_ref); ++ if (av_rpi_is_sand_format(geo->format)) { ++ // Sand formats are a bit "special" ++ // stride1 implicit in format ++ // width = stride2 ++ vfmt->width = geo->stripe_is_yc ? ++ geo->height_y + geo->height_c : geo->height_y; ++// es->height = geo->video_height; //*** When we get the FLAG this will change ++ vfmt->height = geo->height_y; ++ es_fmt->flags = MMAL_ES_FORMAT_FLAG_COL_FMTS_WIDTH_IS_COL_STRIDE; ++ } ++ else { ++ vfmt->width = geo->stride_y / geo->bytes_per_pel; ++ vfmt->height = geo->height_y; ++ es_fmt->flags = 0; ++ } ++ ++ es_fmt->type = MMAL_ES_TYPE_VIDEO; ++ es_fmt->encoding = mmfmt_from_avfmt(geo->format); ++ es_fmt->encoding_variant = 0; ++ es_fmt->bitrate = 0; ++ ++ vfmt->crop.x = frame->crop_left; ++ vfmt->crop.y = frame->crop_top; ++ vfmt->crop.width = av_frame_cropped_width(frame); ++ vfmt->crop.height = av_frame_cropped_height(frame); ++ ++ vfmt->frame_rate.den = 0; // Don't think I know it here ++ vfmt->frame_rate.num = 0; ++ ++ vfmt->par.den = frame->sample_aspect_ratio.den; ++ vfmt->par.num = frame->sample_aspect_ratio.num; ++ ++ vfmt->color_space = 0; // Unknown currently ++} ++ ++static MMAL_BOOL_T buf_release_cb(MMAL_BUFFER_HEADER_T * buf, void *userdata) ++{ ++ rpi_display_env_t * const de = userdata; ++ if (buf->user_data != NULL) { ++ av_rpi_zc_unref((AVRpiZcRefPtr)buf->user_data); ++ buf->user_data = NULL; ++ } ++ atomic_fetch_add(&de->rpi_display_count, -1); ++ return MMAL_FALSE; ++} ++ ++static inline int avfmt_needs_isp(const enum AVPixelFormat avfmt) ++{ ++ return avfmt == AV_PIX_FMT_SAND64_10; ++} ++ ++static void isp_remove(AVFormatContext * const s, rpi_display_env_t * const de) ++{ ++ if (de->isp != NULL) ++ { ++ if (de->isp->input[0]->is_enabled) ++ mmal_port_disable(de->isp->input[0]); ++ if (de->isp->control->is_enabled) ++ mmal_port_disable(de->isp->control); ++ } ++ if (de->conn != NULL) { ++ mmal_connection_destroy(de->conn); ++ de->conn = NULL; ++ } ++ if (de->isp != NULL) { ++ mmal_component_destroy(de->isp); ++ de->isp = NULL; ++ } ++} ++ ++static void display_frame(AVFormatContext * const s, rpi_display_env_t * const de, const AVFrame* const fr) ++{ ++ MMAL_BUFFER_HEADER_T* buf = NULL; ++ AVRpiZcRefPtr fr_buf = NULL; ++ ++ if (de == NULL) ++ return; ++ ++ if (atomic_load(&de->rpi_display_count) >= DISPLAY_PORT_DEPTH - 1) { ++ av_log(s, AV_LOG_VERBOSE, "Frame dropped\n"); ++ return; ++ } ++ ++ if ((fr_buf = av_rpi_zc_ref(s, de->zc, fr, fr->format, 1)) == NULL) { ++ return; ++ } ++ ++ buf = mmal_queue_get(de->rpi_pool->queue); ++ if (!buf) { ++ // Running too fast so drop the frame (unexpected) ++ goto fail; ++ } ++ ++ buf->cmd = 0; ++ buf->offset = 0; ++ buf->flags = 0; ++ mmal_buffer_header_reset(buf); ++ ++ atomic_fetch_add(&de->rpi_display_count, 1); // Deced on release ++ mmal_buffer_header_pre_release_cb_set(buf, buf_release_cb, de); ++ ++ buf->user_data = fr_buf; ++ buf->data = (uint8_t *)av_rpi_zc_vc_handle(fr_buf); // Cast our handle to a pointer for mmal ++ buf->offset = av_rpi_zc_offset(fr_buf); ++ buf->length = av_rpi_zc_length(fr_buf); ++ buf->alloc_size = av_rpi_zc_numbytes(fr_buf); ++ ++#if RPI_DISPLAY_ALL ++ while (atomic_load(&de->rpi_display_count) >= DISPLAY_PORT_DEPTH - 1) { ++ usleep(5000); ++ } ++#endif ++ ++ { ++ MMAL_ES_SPECIFIC_FORMAT_T new_ess = {.video = {0}}; ++ MMAL_ES_FORMAT_T new_es = {.es = &new_ess}; ++ MMAL_VIDEO_FORMAT_T * const new_vfmt = &new_ess.video; ++ ++ video_format_from_zc_frame(&new_es, fr, fr_buf); ++ if (de->req_fmt != new_es.encoding || ++ de->req_vfmt.width != new_vfmt->width || ++ de->req_vfmt.height != new_vfmt->height || ++ de->req_vfmt.crop.x != new_vfmt->crop.x || ++ de->req_vfmt.crop.y != new_vfmt->crop.y || ++ de->req_vfmt.crop.width != new_vfmt->crop.width || ++ de->req_vfmt.crop.height != new_vfmt->crop.height) { ++ // Something has changed ++ ++ // If we have an ISP tear it down ++ isp_remove(s, de); ++ de->port_in = de->display->input[0]; ++ ++ // If we still need an ISP create it now ++ if (avfmt_needs_isp(fr->format)) ++ { ++ if (mmal_component_create("vc.ril.isp", &de->isp) != MMAL_SUCCESS) ++ { ++ av_log(s, AV_LOG_ERROR, "ISP creation failed\n"); ++ goto fail; ++ } ++ de->port_in = de->isp->input[0]; ++ } ++ ++ mmal_format_copy(de->port_in->format, &new_es); ++ ++ if (mmal_port_format_commit(de->port_in)) { ++ av_log(s, AV_LOG_ERROR, "Failed to commit input format\n"); ++ goto fail; ++ } ++ ++ // If we have an ISP then we must want to use it ++ if (de->isp != NULL) { ++ MMAL_PORT_T * const port_out = de->isp->output[0]; ++ MMAL_VIDEO_FORMAT_T* vfmt_in = &de->port_in->format->es->video; ++ MMAL_VIDEO_FORMAT_T* vfmt_out = &port_out->format->es->video; ++ ++ port_out->format->type = MMAL_ES_TYPE_VIDEO; ++ port_out->format->encoding = MMAL_ENCODING_YUVUV128; ++ port_out->format->encoding_variant = 0; ++ port_out->format->bitrate = 0; ++ port_out->format->flags = 0; ++ port_out->format->extradata = NULL; ++ port_out->format->extradata_size = 0; ++ ++ vfmt_out->width = (vfmt_in->crop.width + 31) & ~31; ++ vfmt_out->height = (vfmt_in->crop.height + 15) & ~15; ++ vfmt_out->crop.x = 0; ++ vfmt_out->crop.y = 0; ++ vfmt_out->crop.width = vfmt_in->crop.width; ++ vfmt_out->crop.height = vfmt_in->crop.height; ++ vfmt_out->frame_rate = vfmt_in->frame_rate; ++ vfmt_out->par = vfmt_in->par; ++ vfmt_out->color_space = vfmt_in->color_space; ++ ++ if (mmal_port_format_commit(port_out)) { ++ av_log(s, AV_LOG_ERROR, "Failed to commit output format\n"); ++ goto fail; ++ } ++ ++ if (mmal_connection_create(&de->conn, port_out, de->display->input[0], MMAL_CONNECTION_FLAG_TUNNELLING) != MMAL_SUCCESS) { ++ av_log(s, AV_LOG_ERROR, "Failed to create connection\n"); ++ goto fail; ++ } ++ if (mmal_connection_enable(de->conn) != MMAL_SUCCESS) { ++ av_log(s, AV_LOG_ERROR, "Failed to enable connection\n"); ++ goto fail; ++ } ++ mmal_port_enable(de->isp->control,display_cb_control); ++ mmal_component_enable(de->isp); ++ } ++ ++ // Number of slots in my port Q ++ de->port_in->buffer_num = DISPLAY_PORT_DEPTH; ++ // Size to keep it happy - isn't used for anything other than error checking ++ de->port_in->buffer_size = buf->alloc_size; ++ if (!de->port_in->is_enabled) ++ { ++ mmal_port_parameter_set_boolean(de->port_in, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); // Does this mark that the buffer contains a vc_handle? Would have expected a vc_image? ++ if (mmal_port_enable(de->port_in, display_cb_input) != MMAL_SUCCESS) { ++ av_log(s, AV_LOG_ERROR, "Failed to enable input port\n"); ++ goto fail; ++ } ++ } ++ ++ de->req_fmt = new_es.encoding; ++ de->req_vfmt = *new_vfmt; ++ } ++ } ++ ++ if (mmal_port_send_buffer(de->port_in, buf) != MMAL_SUCCESS) ++ { ++ av_log(s, AV_LOG_ERROR, "mmal_port_send_buffer failed: depth=%d\n", de->rpi_display_count); ++ goto fail; ++ } ++ return; ++ ++fail: ++ // If we have a buf then fr_buf is held by that ++ if (buf != NULL) ++ mmal_buffer_header_release(buf); ++ else if (fr_buf != NULL) ++ av_rpi_zc_unref(fr_buf); ++} ++ ++ ++static int xv_write_trailer(AVFormatContext *s) ++{ ++ rpi_display_env_t * const de = s->priv_data; ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ if (de->port_in != NULL && de->port_in->is_enabled) { ++ mmal_port_disable(de->port_in); ++ } ++ ++ // The above disable should kick out all buffers - check that ++ if (atomic_load(&de->rpi_display_count) != 0) { ++ av_log(s, AV_LOG_WARNING, "Exiting with display count non-zero:%d\n", atomic_load(&de->rpi_display_count)); ++ } ++ ++ isp_remove(s, de); ++ if (de->rpi_pool != NULL) { ++ mmal_pool_destroy(de->rpi_pool); ++ de->rpi_pool = NULL; ++ } ++ if (de->display != NULL) { ++ mmal_component_destroy(de->display); ++ de->display = NULL; ++ } ++ ++ return 0; ++} ++ ++static int xv_write_header(AVFormatContext *s) ++{ ++ rpi_display_env_t * const de = s->priv_data; ++ const AVCodecParameters * const par = s->streams[0]->codecpar; ++ const unsigned int w = de->window_width ? de->window_width : par->width; ++ const unsigned int h = de->window_height ? de->window_height : par->height; ++ const unsigned int x = de->window_x; ++ const unsigned int y = de->window_y; ++ const int layer = de->layer ? de->layer : 2; ++ const MMAL_BOOL_T fullscreen = de->fullscreen; ++ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: %dx%d\n", __func__, w, h); ++#endif ++ if ( s->nb_streams > 1 ++ || par->codec_type != AVMEDIA_TYPE_VIDEO ++ || par->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) { ++ av_log(s, AV_LOG_ERROR, "Only supports one wrapped avframe stream\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ { ++ MMAL_DISPLAYREGION_T region = ++ { ++ .hdr = {MMAL_PARAMETER_DISPLAYREGION, sizeof(region)}, ++ .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_FULLSCREEN | ++ MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_ALPHA, ++ .layer = layer, ++ .fullscreen = fullscreen, ++ .dest_rect = {x, y, w, h}, ++ .alpha = !fullscreen ? 0xff : 0xff | MMAL_DISPLAY_ALPHA_FLAGS_DISCARD_LOWER_LAYERS, ++ }; ++ ++ bcm_host_init(); // Needs to be done by someone... ++ ++ if (mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &de->display) != MMAL_SUCCESS) ++ { ++ av_log(s, AV_LOG_ERROR, "Failed to create display component\n"); ++ goto fail; ++ } ++ de->port_in = de->display->input[0]; ++ ++ mmal_port_parameter_set(de->display->input[0], ®ion.hdr); ++ ++ if (mmal_component_enable(de->display) != MMAL_SUCCESS) ++ { ++ av_log(s, AV_LOG_ERROR, "Failed to enable display component\n"); ++ goto fail; ++ } ++ if (mmal_port_enable(de->display->control,display_cb_control) != MMAL_SUCCESS) ++ { ++ av_log(s, AV_LOG_ERROR, "Failed to enable display control port\n"); ++ goto fail; ++ } ++ ++ if ((de->rpi_pool = mmal_pool_create(DISPLAY_PORT_DEPTH, 0)) == NULL) ++ { ++ av_log(s, AV_LOG_ERROR, "Failed to create pool\n"); ++ goto fail; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ xv_write_trailer(s); ++ return AVERROR_UNKNOWN; ++} ++ ++static int xv_write_packet(AVFormatContext *s, AVPacket *pkt) ++{ ++ AVFrame * const frame = (AVFrame *)pkt->data; ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s\n", __func__); ++#endif ++ display_frame(s, s->priv_data, frame); ++ return 0; ++} ++ ++static int xv_write_frame(AVFormatContext *s, int stream_index, AVFrame **ppframe, ++ unsigned flags) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: idx=%d, flags=%#x\n", __func__, stream_index, flags); ++#endif ++ ++ /* xv_write_header() should have accepted only supported formats */ ++ if ((flags & AV_WRITE_UNCODED_FRAME_QUERY)) ++ return 0; ++// return write_picture(s, (*frame)->data, (*frame)->linesize); ++ ++ display_frame(s, s->priv_data, *ppframe); ++ return 0; ++} ++ ++static int xv_control_message(AVFormatContext *s, int type, void *data, size_t data_size) ++{ ++#if TRACE_ALL ++ av_log(s, AV_LOG_INFO, "%s: %d\n", __func__, type); ++#endif ++ switch(type) { ++ case AV_APP_TO_DEV_WINDOW_REPAINT: ++ return 0; ++ default: ++ break; ++ } ++ return AVERROR(ENOSYS); ++} ++ ++// deinit is called if init fails so no need to clean up explicity here ++static int rpi_vout_init(struct AVFormatContext * s) ++{ ++ rpi_display_env_t * const de = s->priv_data; ++ ++ // Get a ZC context in case we need one - has little overhead if unused ++ if ((de->zc = av_rpi_zc_int_env_alloc(s)) == NULL) ++ return 1; ++ ++ return 0; ++} ++ ++static void rpi_vout_deinit(struct AVFormatContext * s) ++{ ++ rpi_display_env_t * const de = s->priv_data; ++ ++ av_rpi_zc_int_env_freep(&de->zc); ++} ++ ++ ++#define OFFSET(x) offsetof(rpi_display_env_t, x) ++static const AVOption options[] = { ++ { "window_size", "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_x", "set window x offset", OFFSET(window_x), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "window_y", "set window y offset", OFFSET(window_y), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "display_layer","set display layer", OFFSET(layer), AV_OPT_TYPE_INT, {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "fullscreen", "set fullscreen display", OFFSET(fullscreen), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { NULL } ++ ++}; ++ ++static const AVClass xv_class = { ++ .class_name = "rpi vid outdev", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++ .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, ++}; ++ ++AVOutputFormat ff_vout_rpi_muxer = { ++ .name = "vout_rpi", ++ .long_name = NULL_IF_CONFIG_SMALL("Rpi (mmal) video output device"), ++ .priv_data_size = sizeof(rpi_display_env_t), ++ .audio_codec = AV_CODEC_ID_NONE, ++ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, ++ .write_header = xv_write_header, ++ .write_packet = xv_write_packet, ++ .write_uncoded_frame = xv_write_frame, ++ .write_trailer = xv_write_trailer, ++ .control_message = xv_control_message, ++ .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, ++ .priv_class = &xv_class, ++ .init = rpi_vout_init, ++ .deinit = rpi_vout_deinit, ++}; +diff --git a/libavfilter/Makefile b/libavfilter/Makefile +index 5123540653..17ccea3150 100644 +--- a/libavfilter/Makefile ++++ b/libavfilter/Makefile +@@ -434,6 +434,7 @@ OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o o + OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o + OBJS-$(CONFIG_TRIM_FILTER) += trim.o + OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o ++OBJS-$(CONFIG_UNSAND_FILTER) += vf_unsand.o + OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o + OBJS-$(CONFIG_UNSHARP_OPENCL_FILTER) += vf_unsharp_opencl.o opencl.o \ + opencl/unsharp.o +diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c +index 1183e40267..2f569057dd 100644 +--- a/libavfilter/allfilters.c ++++ b/libavfilter/allfilters.c +@@ -414,6 +414,7 @@ extern AVFilter ff_vf_transpose_opencl; + extern AVFilter ff_vf_transpose_vaapi; + extern AVFilter ff_vf_trim; + extern AVFilter ff_vf_unpremultiply; ++extern AVFilter ff_vf_unsand; + extern AVFilter ff_vf_unsharp; + extern AVFilter ff_vf_unsharp_opencl; + extern AVFilter ff_vf_untile; +diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c +index 2fe4f0b0f9..5a8e6b3f24 100644 +--- a/libavfilter/avfiltergraph.c ++++ b/libavfilter/avfiltergraph.c +@@ -32,6 +32,9 @@ + #include "libavutil/internal.h" + #include "libavutil/opt.h" + #include "libavutil/pixdesc.h" ++#if CONFIG_UNSAND_FILTER ++#include "libavutil/rpi_sand_fns.h" ++#endif + + #define FF_INTERNAL_FIELDS 1 + #include "framequeue.h" +@@ -429,6 +432,19 @@ static int can_merge_formats(AVFilterFormats *a_arg, + } + } + ++#if CONFIG_UNSAND_FILTER ++static int has_sand_format(const AVFilterFormats * const ff) ++{ ++ int i; ++ for (i = 0; i != ff->nb_formats; ++i) { ++ if (av_rpi_is_sand_format(ff->formats[i])) { ++ return 1; ++ } ++ } ++ return 0; ++} ++#endif ++ + /** + * Perform one round of query_formats() and merging formats lists on the + * filter graph. +@@ -469,6 +485,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + for (j = 0; j < filter->nb_inputs; j++) { + AVFilterLink *link = filter->inputs[j]; + int convert_needed = 0; ++ unsigned int extra_convert_tried = 0; + + if (!link) + continue; +@@ -516,11 +533,14 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + ) + #undef MERGE_DISPATCH + +- if (convert_needed) { ++ while (convert_needed) { + AVFilterContext *convert; + const AVFilter *filter; + AVFilterLink *inlink, *outlink; + char inst_name[30]; ++ int can_retry = 0; ++ ++ convert_needed = 0; + + if (graph->disable_auto_convert) { + av_log(log_ctx, AV_LOG_ERROR, +@@ -533,19 +553,45 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + /* couldn't merge format lists. auto-insert conversion filter */ + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: +- if (!(filter = avfilter_get_by_name("scale"))) { +- av_log(log_ctx, AV_LOG_ERROR, "'scale' filter " +- "not present, cannot convert pixel formats.\n"); +- return AVERROR(EINVAL); +- } +- +- snprintf(inst_name, sizeof(inst_name), "auto_scaler_%d", +- scaler_count++); ++#if CONFIG_UNSAND_FILTER ++ // Only try each extra conversion once ++ // The unsand output pad should never trigger has_sand_format ++ // but it is better to be safe ++ if ((extra_convert_tried & 1) == 0 && has_sand_format(link->in_formats)) { ++ if (!(filter = avfilter_get_by_name("unsand"))) { ++ av_log(log_ctx, AV_LOG_ERROR, "'unsand' filter " ++ "not present, cannot convert pixel formats.\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ snprintf(inst_name, sizeof(inst_name), "auto_unsand_%d", ++ scaler_count++); ++ ++ if ((ret = avfilter_graph_create_filter(&convert, filter, ++ inst_name, "", NULL, ++ graph)) < 0) ++ return ret; + +- if ((ret = avfilter_graph_create_filter(&convert, filter, +- inst_name, graph->scale_sws_opts, NULL, +- graph)) < 0) +- return ret; ++ extra_convert_tried |= 1; ++ can_retry = 1; ++ } ++ else ++#endif ++ { ++ if (!(filter = avfilter_get_by_name("scale"))) { ++ av_log(log_ctx, AV_LOG_ERROR, "'scale' filter " ++ "not present, cannot convert pixel formats.\n"); ++ return AVERROR(EINVAL); ++ } ++ ++ snprintf(inst_name, sizeof(inst_name), "auto_scaler_%d", ++ scaler_count++); ++ ++ if ((ret = avfilter_graph_create_filter(&convert, filter, ++ inst_name, graph->scale_sws_opts, NULL, ++ graph)) < 0) ++ return ret; ++ } + break; + case AVMEDIA_TYPE_AUDIO: + if (!(filter = avfilter_get_by_name("aresample"))) { +@@ -587,9 +633,19 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + av_assert0(outlink-> in_channel_layouts->refcount > 0); + av_assert0(outlink->out_channel_layouts->refcount > 0); + } +- if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type) || +- !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) ++ // If we have added an extra filter we must merge the input ++ // side but we can have another go at the output ++ if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type)) ++ ret = AVERROR(ENOSYS); ++ else if (!ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) ++ { ++ if (can_retry) { ++ link = outlink; ++ convert_needed = 1; ++ continue; ++ } + ret = AVERROR(ENOSYS); ++ } + if (inlink->type == AVMEDIA_TYPE_AUDIO && + (!ff_merge_samplerates(inlink->in_samplerates, + inlink->out_samplerates) || +diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c +index bf30f54177..eb5dfa22f8 100644 +--- a/libavfilter/buffersrc.c ++++ b/libavfilter/buffersrc.c +@@ -210,7 +210,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, + + switch (ctx->outputs[0]->type) { + case AVMEDIA_TYPE_VIDEO: +- CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height, ++ CHECK_VIDEO_PARAM_CHANGE(ctx, s, av_frame_cropped_width(frame), av_frame_cropped_height(frame), + frame->format, frame->pts); + break; + case AVMEDIA_TYPE_AUDIO: +diff --git a/libavfilter/vf_unsand.c b/libavfilter/vf_unsand.c +new file mode 100644 +index 0000000000..fbea56dd09 +--- /dev/null ++++ b/libavfilter/vf_unsand.c +@@ -0,0 +1,234 @@ ++/* ++ * Copyright (c) 2007 Bobby Bingham ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/** ++ * @file ++ * format and noformat video filters ++ */ ++ ++#include ++ ++#include "libavutil/internal.h" ++#include "libavutil/mem.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/opt.h" ++#include "libavutil/rpi_sand_fns.h" ++ ++#include "avfilter.h" ++#include "formats.h" ++#include "internal.h" ++#include "video.h" ++ ++typedef struct UnsandContext { ++ const AVClass *class; ++} UnsandContext; ++ ++static av_cold void uninit(AVFilterContext *ctx) ++{ ++// UnsandContext *s = ctx->priv; ++} ++ ++static av_cold int init(AVFilterContext *ctx) ++{ ++// UnsandContext *s = ctx->priv; ++ ++ return 0; ++} ++ ++ ++static int filter_frame(AVFilterLink *link, AVFrame *in) ++{ ++ AVFilterLink * const outlink = link->dst->outputs[0]; ++ AVFrame *out = NULL; ++ int rv = 0; ++ ++ if (outlink->format == in->format) { ++ // If nothing to do then do nothing ++ out = in; ++ } ++ else ++ { ++ if ((out = ff_get_video_buffer(outlink, av_frame_cropped_width(in), av_frame_cropped_height(in))) == NULL) ++ { ++ rv = AVERROR(ENOMEM); ++ goto fail; ++ } ++ if (av_rpi_sand_to_planar_frame(out, in) != 0) ++ { ++ rv = -1; ++ goto fail; ++ } ++ ++ av_frame_free(&in); ++ } ++ ++ return ff_filter_frame(outlink, out); ++ ++fail: ++ av_frame_free(&out); ++ av_frame_free(&in); ++ return rv; ++} ++ ++#if 0 ++static void dump_fmts(const AVFilterFormats * fmts) ++{ ++ int i; ++ if (fmts== NULL) { ++ printf("NULL\n"); ++ return; ++ } ++ for (i = 0; i < fmts->nb_formats; ++i) { ++ printf(" %d", fmts->formats[i]); ++ } ++ printf("\n"); ++} ++#endif ++ ++static int query_formats(AVFilterContext *ctx) ++{ ++// UnsandContext *s = ctx->priv; ++ int ret; ++ ++ // If we aren't connected at both ends then just do nothing ++ if (ctx->inputs[0] == NULL || ctx->outputs[0] == NULL) ++ return 0; ++ ++// printf("Unsand: %s in: ", __func__); ++// dump_fmts(ctx->inputs[0]->in_formats); ++// printf("Unsand: %s out: ", __func__); ++// dump_fmts(ctx->outputs[0]->out_formats); ++ ++ // Our output formats depend on our input formats and we can't/don't ++ // want to convert between bit depths so we need to wait for the source ++ // to have an opinion before we do ++ if (ctx->inputs[0]->in_formats == NULL) ++ return AVERROR(EAGAIN); ++ ++ // Accept anything ++ if (ctx->inputs[0]->out_formats == NULL && ++ (ret = ff_formats_ref(ctx->inputs[0]->in_formats, &ctx->inputs[0]->out_formats)) < 0) ++ return ret; ++ ++ // Filter out sand formats ++ ++ // Generate a container if we don't already have one ++ if (ctx->outputs[0]->in_formats == NULL) ++ { ++ // Somewhat rubbish way of ensuring we have a good structure ++ const static enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}; ++ AVFilterFormats *formats = ff_make_format_list(out_fmts); ++ ++ if (formats == NULL) ++ return AVERROR(ENOMEM); ++ if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) ++ return ret; ++ } ++ ++ // Replace old format list with new filtered list derived from what our ++ // input says it can do ++ { ++ const AVFilterFormats * const src_ff = ctx->inputs[0]->out_formats; ++ AVFilterFormats * const dst_ff = ctx->outputs[0]->in_formats; ++ enum AVPixelFormat *dst_fmts = av_malloc(sizeof(enum AVPixelFormat) * src_ff->nb_formats); ++ int i; ++ int n = 0; ++ int seen_420p = 0; ++ int seen_420p10 = 0; ++ ++ for (i = 0; i < src_ff->nb_formats; ++i) { ++ const enum AVPixelFormat f = src_ff->formats[i]; ++ ++ switch (f){ ++ case AV_PIX_FMT_YUV420P: ++ case AV_PIX_FMT_SAND128: ++ case AV_PIX_FMT_RPI4_8: ++ if (!seen_420p) { ++ seen_420p = 1; ++ dst_fmts[n++] = AV_PIX_FMT_YUV420P; ++ } ++ break; ++ case AV_PIX_FMT_SAND64_10: ++ case AV_PIX_FMT_YUV420P10: ++ case AV_PIX_FMT_RPI4_10: ++ if (!seen_420p10) { ++ seen_420p10 = 1; ++ dst_fmts[n++] = AV_PIX_FMT_YUV420P10; ++ } ++ break; ++ default: ++ dst_fmts[n++] = f; ++ break; ++ } ++ } ++ ++ av_freep(&dst_ff->formats); ++ dst_ff->formats = dst_fmts; ++ dst_ff->nb_formats = n; ++ } ++ ++// printf("Unsand: %s calc: ", __func__); ++// dump_fmts(ctx->outputs[0]->in_formats); ++ ++ return 0; ++} ++ ++ ++#define OFFSET(x) offsetof(UnsandContext, x) ++static const AVOption unsand_options[] = { ++ { NULL } ++}; ++ ++ ++AVFILTER_DEFINE_CLASS(unsand); ++ ++static const AVFilterPad avfilter_vf_unsand_inputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .filter_frame = filter_frame, ++ }, ++ { NULL } ++}; ++ ++static const AVFilterPad avfilter_vf_unsand_outputs[] = { ++ { ++ .name = "default", ++ .type = AVMEDIA_TYPE_VIDEO ++ }, ++ { NULL } ++}; ++ ++AVFilter ff_vf_unsand = { ++ .name = "unsand", ++ .description = NULL_IF_CONFIG_SMALL("Convert sand pix fmt to yuv"), ++ ++ .init = init, ++ .uninit = uninit, ++ ++ .query_formats = query_formats, ++ ++ .priv_size = sizeof(UnsandContext), ++ .priv_class = &unsand_class, ++ ++ .inputs = avfilter_vf_unsand_inputs, ++ .outputs = avfilter_vf_unsand_outputs, ++}; ++ +diff --git a/libavformat/utils.c b/libavformat/utils.c +index ba8aaebfb7..4c7bd7f5e1 100644 +--- a/libavformat/utils.c ++++ b/libavformat/utils.c +@@ -3044,6 +3044,40 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr) + return 1; + } + ++#if CONFIG_HEVC_RPI_DECODER && CONFIG_HEVC_DECODER ++// This should be quite general purpose but avoid possible conflicts ++// by limiting usage to cases wehere we know it works. ++static int try_fallback_decoder(AVCodecContext * const avctx, const AVCodec *const old_codec, AVDictionary ** const opts) ++{ ++ // Only try fallback if we know it is supported (HEVC only) ++ const AVCodec *const new_codec = old_codec->id != AV_CODEC_ID_HEVC ? NULL : ++ avcodec_find_decoder_by_id_and_fmt(old_codec->id, AV_PIX_FMT_NONE); ++ int err; ++ ++ // Failed to find fallback or we are already at the fallback ++ if (new_codec == NULL || new_codec == old_codec) ++ { ++ return AVERROR_DECODER_NOT_FOUND; ++ } ++ ++ // * This may be dodgy - header says to not use this fn, ++ // especially if we are going to reopen the context... ++ // (but it does seem to work for our cases) ++ if (avcodec_is_open(avctx)) { ++ avcodec_close(avctx); ++ } ++ ++ if ((err = avcodec_open2(avctx, new_codec, opts)) < 0) ++ { ++ return err; ++ } ++ ++ return 0; ++} ++#else ++#define try_fallback_decoder(avctx, old_codec, opts) (AVERROR_DECODER_NOT_FOUND) ++#endif ++ + /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ + static int try_decode_frame(AVFormatContext *s, AVStream *st, + const AVPacket *avpkt, AVDictionary **options) +@@ -3078,7 +3112,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, + av_dict_set(options ? options : &thread_opt, "threads", "1", 0); + if (s->codec_whitelist) + av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0); +- ret = avcodec_open2(avctx, codec, options ? options : &thread_opt); ++ if ((ret = avcodec_open2(avctx, codec, options ? options : &thread_opt)) == AVERROR_DECODER_NOT_FOUND) ++ { ++ // Try fallback if if looks worth a try ++ ret = try_fallback_decoder(avctx, codec, options ? options : &thread_opt); ++ } + if (!options) + av_dict_free(&thread_opt); + if (ret < 0) { +@@ -3109,6 +3147,14 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || + avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = avcodec_send_packet(avctx, &pkt); ++ ++ // If we are going to want to fall back we should know here ++ if (ret == AVERROR_DECODER_NOT_FOUND) { ++ if ((ret = try_fallback_decoder(avctx, avctx->codec, options)) < 0) ++ break; ++ continue; ++ } ++ + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + break; + if (ret >= 0) +@@ -3719,9 +3765,20 @@ FF_ENABLE_DEPRECATION_WARNINGS + // Try to just open decoders, in case this is enough to get parameters. + if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) { + if (codec && !avctx->codec) +- if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0) +- av_log(ic, AV_LOG_WARNING, +- "Failed to open codec in %s\n",__FUNCTION__); ++ { ++ int err; ++ ++ if ((err = avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt)) < 0) ++ { ++ if (err == AVERROR_DECODER_NOT_FOUND) { ++ err = try_fallback_decoder(avctx, codec, options ? &options[i] : &thread_opt); ++ } ++ if (err < 0) { ++ av_log(ic, AV_LOG_WARNING, ++ "Failed to open codec in %s\n",__FUNCTION__); ++ } ++ } ++ } + } + if (!options) + av_dict_free(&thread_opt); +diff --git a/libavutil/Makefile b/libavutil/Makefile +index 9b08372eb2..b0b5be0fa6 100644 +--- a/libavutil/Makefile ++++ b/libavutil/Makefile +@@ -68,6 +68,7 @@ HEADERS = adler32.h \ + rational.h \ + replaygain.h \ + ripemd.h \ ++ rpi_sand_fns.h \ + samplefmt.h \ + sha.h \ + sha512.h \ +@@ -86,6 +87,7 @@ HEADERS = adler32.h \ + tx.h \ + + HEADERS-$(CONFIG_LZO) += lzo.h ++HEADERS-$(CONFIG-RPI) += rpi_sand_fn_pw.h + + ARCH_HEADERS = bswap.h \ + intmath.h \ +@@ -180,10 +182,12 @@ OBJS-$(CONFIG_LZO) += lzo.o + OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o + OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o + OBJS-$(CONFIG_QSV) += hwcontext_qsv.o ++OBJS-$(CONFIG_SAND) += rpi_sand_fns.o + OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o + OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o + OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o + OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o ++OBJS-$(CONFIG_RPI) += rpi_sand_fns.o + + OBJS += $(COMPAT_OBJS:%=../compat/%) + +diff --git a/libavutil/aarch64/Makefile b/libavutil/aarch64/Makefile +index 5613813ba8..ab8bcfcf34 100644 +--- a/libavutil/aarch64/Makefile ++++ b/libavutil/aarch64/Makefile +@@ -1,4 +1,6 @@ + OBJS += aarch64/cpu.o \ + aarch64/float_dsp_init.o \ + +-NEON-OBJS += aarch64/float_dsp_neon.o ++NEON-OBJS += aarch64/float_dsp_neon.o \ ++ aarch64/rpi_sand_neon.o \ ++ +diff --git a/libavutil/aarch64/rpi_sand_neon.S b/libavutil/aarch64/rpi_sand_neon.S +new file mode 100644 +index 0000000000..641242dd8f +--- /dev/null ++++ b/libavutil/aarch64/rpi_sand_neon.S +@@ -0,0 +1,239 @@ ++/* ++Copyright (c) 2021 Michael Eiler ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: Michael Eiler ++*/ ++ ++#include "asm.S" ++ ++// void ff_rpi_sand8_lines_to_planar_y8( ++// uint8_t * dest, : x0 ++// unsigned int dst_stride, : w1 ++// const uint8_t * src, : x2 ++// unsigned int src_stride1, : w3, always 128 ++// unsigned int src_stride2, : w4 ++// unsigned int _x, : w5 ++// unsigned int y, : w6 ++// unsigned int _w, : w7 ++// unsigned int h); : [sp, #0] ++ ++function ff_rpi_sand8_lines_to_planar_y8, export=1 ++ // w15 contains the number of rows we need to process ++ ldr w15, [sp, #0] ++ ++ // w8 will contain the number of blocks per row ++ // w8 = floor(_w/stride1) ++ // stride1 is assumed to always be 128 ++ mov w8, w1 ++ lsr w8, w8, #7 ++ ++ // in case the width of the image is not a multiple of 128, there will ++ // be an incomplete block at the end of every row ++ // w9 contains the number of pixels stored within this block ++ // w9 = _w - w8 * 128 ++ lsl w9, w8, #7 ++ sub w9, w7, w9 ++ ++ // this is the value we have to add to the src pointer after reading a complete block ++ // it will move the address to the start of the next block ++ // w10 = stride2 * stride1 - stride1 ++ mov w10, w4 ++ lsl w10, w10, #7 ++ sub w10, w10, #128 ++ ++ // w11 is the row offset, meaning the start offset of the first block of every collumn ++ // this will be increased with stride1 within every iteration of the row_loop ++ eor w11, w11, w11 ++ ++ // w12 = 0, processed row count ++ eor w12, w12, w12 ++row_loop: ++ // start of the first block within the current row ++ // x13 = row offset + src ++ mov x13, x2 ++ add x13, x13, x11 ++ ++ // w14 = 0, processed block count ++ eor w14, w14, w14 ++block_loop: ++ // copy 128 bytes (a full block) into the vector registers v0-v7 and increase the src address by 128 ++ // fortunately these aren't callee saved ones, meaning we don't need to backup them ++ ld1 { v0.16b, v1.16b, v2.16b, v3.16b}, [x13], #64 ++ ld1 { v4.16b, v5.16b, v6.16b, v7.16b}, [x13], #64 ++ ++ // write these registers back to the destination vector and increase the dst address by 128 ++ st1 { v0.16b, v1.16b, v2.16b, v3.16b }, [x0], #64 ++ st1 { v4.16b, v5.16b, v6.16b, v7.16b }, [x0], #64 ++ ++ // move the source register to the beginning of the next block (x13 = src + block offset) ++ add x13, x13, x10 ++ // increase the block counter ++ add w14, w14, #1 ++ ++ // continue with the block_loop if we haven't copied all full blocks yet ++ cmp w8, w14 ++ bgt block_loop ++ ++ // handle the last block at the end of each row ++ // at most 127 byte values copied from src to dst ++ eor w5, w5, w5 // i = 0 ++incomplete_block_loop_y8: ++ cmp w5, w9 ++ bge incomplete_block_loop_end_y8 ++ ++ ldrb w6, [x13] ++ strb w6, [x0] ++ add x13, x13, #1 ++ add x0, x0, #1 ++ ++ add w5, w5, #1 ++ b incomplete_block_loop_y8 ++incomplete_block_loop_end_y8: ++ ++ ++ // increase the row offset by 128 (stride1) ++ add w11, w11, #128 ++ // increment the row counter ++ add w12, w12, #1 ++ ++ // process the next row if we haven't finished yet ++ cmp w15, w12 ++ bgt row_loop ++ ++ ret ++endfunc ++ ++ ++ ++// void ff_rpi_sand8_lines_to_planar_c8( ++// uint8_t * dst_u, : x0 ++// unsigned int dst_stride_u, : w1 == width ++// uint8_t * dst_v, : x2 ++// unsigned int dst_stride_v, : w3 == width ++// const uint8_t * src, : x4 ++// unsigned int stride1, : w5 == 128 ++// unsigned int stride2, : w6 ++// unsigned int _x, : w7 ++// unsigned int y, : [sp, #0] ++// unsigned int _w, : [sp, #8] ++// unsigned int h); : [sp, #16] ++ ++function ff_rpi_sand8_lines_to_planar_c8, export=1 ++ // w7 = width ++ ldr w7, [sp, #8] ++ ++ // w15 contains the number of rows we need to process ++ ldr w15, [sp, #16] ++ ++ // number of full blocks, w8 = _w / (stride1 >> 1) == _w / 64 == _w >> 6 ++ mov w8, w7 ++ lsr w8, w8, #6 ++ ++ // number of pixels in block at the end of every row ++ // w9 = _w - (w8 * 64) ++ lsl w9, w8, #6 ++ sub w9, w7, w9 ++ ++ // address delta to the beginning of the next block ++ // w10 = (stride2 * stride1 - stride1) = stride2 * 128 - 128 ++ lsl w10, w6, #7 ++ sub w10, w10, #128 ++ ++ // w11 = row address start offset = 0 ++ eor w11, w11, w11 ++ ++ // w12 = 0, row counter ++ eor w12, w12, w12 ++row_loop_c8: ++ // start of the first block within the current row ++ // x13 = row offset + src ++ mov x13, x4 ++ add x13, x13, x11 ++ ++ // w14 = 0, processed block count ++ eor w14, w14, w14 ++block_loop_c8: ++ // load the full block -> 128 bytes, the block contains 64 interleaved U and V values ++ ld2 { v0.16b, v1.16b }, [x13], #32 ++ ld2 { v2.16b, v3.16b }, [x13], #32 ++ ld2 { v4.16b, v5.16b }, [x13], #32 ++ ld2 { v6.16b, v7.16b }, [x13], #32 ++ ++ // swap register so that we can write them out with a single instruction ++ mov v16.16b, v1.16b ++ mov v17.16b, v3.16b ++ mov v18.16b, v5.16b ++ mov v1.16b, v2.16b ++ mov v2.16b, v4.16b ++ mov v3.16b, v6.16b ++ mov v4.16b, v16.16b ++ mov v5.16b, v17.16b ++ mov v6.16b, v18.16b ++ ++ st1 { v0.16b, v1.16b, v2.16b, v3.16b }, [x0], #64 ++ st1 { v4.16b, v5.16b, v6.16b, v7.16b }, [x2], #64 ++ ++ // increment row counter and move src to the beginning of the next block ++ add w14, w14, #1 ++ add x13, x13, x10 ++ ++ // jump to block_loop_c8 iff the block count is smaller than the number of full blocks ++ cmp w8, w14 ++ bgt block_loop_c8 ++ ++ // handle incomplete block at the end of every row ++ eor w5, w5, w5 // point counter, this might be ++incomplete_block_loop_c8: ++ cmp w5, w9 ++ bge incomplete_block_loop_end_c8 ++ ++ ldrb w1, [x13] ++ strb w1, [x0] ++ add x13, x13, #1 ++ ++ ldrb w1, [x13] ++ strb w1, [x2] ++ add x13, x13, #1 ++ ++ add x0, x0, #1 ++ add x2, x2, #1 ++ ++ add w5, w5, #1 ++ b incomplete_block_loop_c8 ++incomplete_block_loop_end_c8: ++ ++ ++ // increase row_offset by stride1 ++ add w11, w11, #128 ++ add w12, w12, #1 ++ ++ // jump to row_Loop_c8 iff the row count is small than the height ++ cmp w15, w12 ++ bgt row_loop_c8 ++ ++ ret ++endfunc ++ ++ +diff --git a/libavutil/aarch64/rpi_sand_neon.h b/libavutil/aarch64/rpi_sand_neon.h +new file mode 100644 +index 0000000000..2894ce5aa3 +--- /dev/null ++++ b/libavutil/aarch64/rpi_sand_neon.h +@@ -0,0 +1,47 @@ ++/* ++Copyright (c) 2021 Michael Eiler ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: Michael Eiler ++*/ ++ ++#pragma once ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void ff_rpi_sand8_lines_to_planar_y8(uint8_t * dest, unsigned int dst_stride, ++ const uint8_t * src, unsigned int src_stride1, unsigned int src_stride2, ++ unsigned int _x, unsigned int y, unsigned int _w, unsigned int h); ++ ++void ff_rpi_sand8_lines_to_planar_c8(uint8_t * dst_u, unsigned int dst_stride_u, ++ uint8_t * dst_v, unsigned int dst_stride_v, const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++#ifdef __cplusplus ++} ++#endif ++ +diff --git a/libavutil/arm/Makefile b/libavutil/arm/Makefile +index 5da44b0542..b74b7c4e2f 100644 +--- a/libavutil/arm/Makefile ++++ b/libavutil/arm/Makefile +@@ -6,3 +6,4 @@ VFP-OBJS += arm/float_dsp_init_vfp.o \ + + NEON-OBJS += arm/float_dsp_init_neon.o \ + arm/float_dsp_neon.o \ ++ arm/rpi_sand_neon.o \ +diff --git a/libavutil/arm/rpi_sand_neon.S b/libavutil/arm/rpi_sand_neon.S +new file mode 100644 +index 0000000000..80890fe985 +--- /dev/null ++++ b/libavutil/arm/rpi_sand_neon.S +@@ -0,0 +1,768 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++#include "libavutil/arm/asm.S" ++ ++ ++@ General notes: ++@ Having done some timing on this in sand8->y8 (Pi4) ++@ vst1 (680fps) is a bit faster than vstm (660fps) ++@ vldm (680fps) is noticably faster than vld1 (480fps) ++@ (or it might be that a mix is what is required) ++@ ++@ At least on a Pi4 it is no more expensive to have a single auto-inc register ++@ for dest address than it is to have 2 used alternately (On Pi3 Ben asserted ++@ the latter was better) ++@ ++@ vstm will bus error on unaligned access (so will vldm), vst1 is safe unless ++@ the memory is uncached. ++@ As these are Sand -> planar we can assume that src is going to be aligned but ++@ it is possible that dest isn't (converting to .yuv or other packed format). ++@ Luckily vst1 is faster than vstm :-) so all is well ++@ vst1 has alignment requirements of el size so maybe splitting vst1.32 into 4 ++@ .8 stores would let us do non-word aligned stores into uncached but it ++@ probably isn't worth it. ++ ++ ++ ++ ++@ void ff_rpi_sand128b_stripe_to_8_10( ++@ uint8_t * dest, // [r0] ++@ const uint8_t * src1, // [r1] ++@ const uint8_t * src2, // [r2] ++@ unsigned int lines); // [r3] ++ ++.macro stripe2_to_8, bit_depth ++ vpush {q4-q7} ++1: ++ vldm r1!, {q0-q7} ++ subs r3, #1 ++ vldm r2!, {q8-q15} ++ vqrshrn.u16 d0, q0, #\bit_depth - 8 ++ vqrshrn.u16 d1, q1, #\bit_depth - 8 ++ vqrshrn.u16 d2, q2, #\bit_depth - 8 ++ vqrshrn.u16 d3, q3, #\bit_depth - 8 ++ vqrshrn.u16 d4, q4, #\bit_depth - 8 ++ vqrshrn.u16 d5, q5, #\bit_depth - 8 ++ vqrshrn.u16 d6, q6, #\bit_depth - 8 ++ vqrshrn.u16 d7, q7, #\bit_depth - 8 ++ vqrshrn.u16 d8, q8, #\bit_depth - 8 ++ vqrshrn.u16 d9, q9, #\bit_depth - 8 ++ vqrshrn.u16 d10, q10, #\bit_depth - 8 ++ vqrshrn.u16 d11, q11, #\bit_depth - 8 ++ vqrshrn.u16 d12, q12, #\bit_depth - 8 ++ vqrshrn.u16 d13, q13, #\bit_depth - 8 ++ vqrshrn.u16 d14, q14, #\bit_depth - 8 ++ vqrshrn.u16 d15, q15, #\bit_depth - 8 ++ vstm r0!, {q0-q7} ++ bne 1b ++ vpop {q4-q7} ++ bx lr ++.endm ++ ++function ff_rpi_sand128b_stripe_to_8_10, export=1 ++ stripe2_to_8 10 ++endfunc ++ ++@ void ff_rpi_sand8_lines_to_planar_y8( ++@ uint8_t * dest, // [r0] ++@ unsigned int dst_stride, // [r1] ++@ const uint8_t * src, // [r2] ++@ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++@ unsigned int src_stride2, // [sp, #0] -> r3 ++@ unsigned int _x, // [sp, #4] Ignored - 0 ++@ unsigned int y, // [sp, #8] (r7 in prefix) ++@ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++@ unsigned int h); // [sp, #16] -> r7 ++@ ++@ Assumes that we are starting on a stripe boundary and that overreading ++@ within the stripe is OK. However it does respect the dest size for writing ++ ++function ff_rpi_sand8_lines_to_planar_y8, export=1 ++ push {r4-r8, lr} @ +24 L ++ ldr r3, [sp, #24] ++ ldr r6, [sp, #36] ++ ldr r7, [sp, #32] @ y ++ lsl r3, #7 ++ sub r1, r6 ++ add r8, r2, r7, lsl #7 ++ ldr r7, [sp, #40] ++ ++10: ++ mov r2, r8 ++ add r4, r0, #24 ++ mov r5, r6 ++ mov lr, #0 ++1: ++ vldm r2, {q8-q15} ++ add r2, r3 ++ subs r5, #128 ++ blt 2f ++ vst1.8 {d16, d17, d18, d19}, [r0]! ++ vst1.8 {d20, d21, d22, d23}, [r0]! ++ vst1.8 {d24, d25, d26, d27}, [r0]! ++ vst1.8 {d28, d29, d30, d31}, [r0]! ++ bne 1b ++11: ++ subs r7, #1 ++ add r0, r1 ++ add r8, #128 ++ bne 10b ++ ++ pop {r4-r8, pc} ++ ++@ Partial final write ++2: ++ cmp r5, #64-128 ++ blt 1f ++ vst1.8 {d16, d17, d18, d19}, [r0]! ++ vst1.8 {d20, d21, d22, d23}, [r0]! ++ beq 11b ++ vmov q8, q12 ++ vmov q9, q13 ++ sub r5, #64 ++ vmov q10, q14 ++ vmov q11, q15 ++1: ++ cmp r5, #32-128 ++ blt 1f ++ vst1.8 {d16, d17, d18, d19}, [r0]! ++ beq 11b ++ vmov q8, q10 ++ sub r5, #32 ++ vmov q9, q11 ++1: ++ cmp r5, #16-128 ++ blt 1f ++ vst1.8 {d16, d17}, [r0]! ++ beq 11b ++ sub r5, #16 ++ vmov q8, q9 ++1: ++ cmp r5, #8-128 ++ blt 1f ++ vst1.8 {d16}, [r0]! ++ beq 11b ++ sub r5, #8 ++ vmov d16, d17 ++1: ++ cmp r5, #4-128 ++ blt 1f ++ vst1.32 {d16[0]}, [r0]! ++ beq 11b ++ sub r5, #4 ++ vshr.u64 d16, #32 ++1: ++ cmp r5, #2-128 ++ blt 1f ++ vst1.16 {d16[0]}, [r0]! ++ beq 11b ++ vst1.8 {d16[2]}, [r0]! ++ b 11b ++1: ++ vst1.8 {d16[0]}, [r0]! ++ b 11b ++endfunc ++ ++@ void ff_rpi_sand8_lines_to_planar_c8( ++@ uint8_t * dst_u, // [r0] ++@ unsigned int dst_stride_u, // [r1] ++@ uint8_t * dst_v, // [r2] ++@ unsigned int dst_stride_v, // [r3] ++@ const uint8_t * src, // [sp, #0] -> r4, r5 ++@ unsigned int stride1, // [sp, #4] 128 ++@ unsigned int stride2, // [sp, #8] -> r8 ++@ unsigned int _x, // [sp, #12] 0 ++@ unsigned int y, // [sp, #16] (r7 in prefix) ++@ unsigned int _w, // [sp, #20] -> r12, r6 ++@ unsigned int h); // [sp, #24] -> r7 ++@ ++@ Assumes that we are starting on a stripe boundary and that overreading ++@ within the stripe is OK. However it does respect the dest size for writing ++ ++function ff_rpi_sand8_lines_to_planar_c8, export=1 ++ push {r4-r8, lr} @ +24 ++ ++ ldr r5, [sp, #24] ++ ldr r8, [sp, #32] ++ ldr r7, [sp, #40] ++ ldr r6, [sp, #44] ++ lsl r8, #7 ++ add r5, r5, r7, lsl #7 ++ sub r1, r1, r6 ++ sub r3, r3, r6 ++ ldr r7, [sp, #48] ++ vpush {q4-q7} ++ ++10: ++ mov r4, r5 ++ mov r12, r6 ++1: ++ subs r12, #64 ++ vldm r4, {q0-q7} ++ add r4, r8 ++ it gt ++ vldmgt r4, {q8-q15} ++ add r4, r8 ++ ++ vuzp.8 q0, q1 ++ vuzp.8 q2, q3 ++ vuzp.8 q4, q5 ++ vuzp.8 q6, q7 ++ ++ vuzp.8 q8, q9 ++ vuzp.8 q10, q11 ++ vuzp.8 q12, q13 ++ vuzp.8 q14, q15 ++ subs r12, #64 ++ ++ @ Rearrange regs so we can use vst1 with 4 regs ++ vswp q1, q2 ++ vswp q5, q6 ++ vswp q9, q10 ++ vswp q13, q14 ++ blt 2f ++ ++ vst1.8 {d0, d1, d2, d3 }, [r0]! ++ vst1.8 {d8, d9, d10, d11}, [r0]! ++ vst1.8 {d16, d17, d18, d19}, [r0]! ++ vst1.8 {d24, d25, d26, d27}, [r0]! ++ ++ vst1.8 {d4, d5, d6, d7 }, [r2]! ++ vst1.8 {d12, d13, d14, d15}, [r2]! ++ vst1.8 {d20, d21, d22, d23}, [r2]! ++ vst1.8 {d28, d29, d30, d31}, [r2]! ++ bne 1b ++11: ++ subs r7, #1 ++ add r5, #128 ++ add r0, r1 ++ add r2, r3 ++ bne 10b ++ vpop {q4-q7} ++ pop {r4-r8,pc} ++ ++2: ++ cmp r12, #64-128 ++ blt 1f ++ vst1.8 {d0, d1, d2, d3 }, [r0]! ++ vst1.8 {d8, d9, d10, d11}, [r0]! ++ vst1.8 {d4, d5, d6, d7 }, [r2]! ++ vst1.8 {d12, d13, d14, d15}, [r2]! ++ beq 11b ++ sub r12, #64 ++ vmov q0, q8 ++ vmov q1, q9 ++ vmov q2, q10 ++ vmov q3, q11 ++ vmov q4, q12 ++ vmov q5, q13 ++ vmov q6, q14 ++ vmov q7, q15 ++1: ++ cmp r12, #32-128 ++ blt 1f ++ vst1.8 {d0, d1, d2, d3 }, [r0]! ++ vst1.8 {d4, d5, d6, d7 }, [r2]! ++ beq 11b ++ sub r12, #32 ++ vmov q0, q4 ++ vmov q1, q5 ++ vmov q2, q6 ++ vmov q3, q7 ++1: ++ cmp r12, #16-128 ++ blt 1f ++ vst1.8 {d0, d1 }, [r0]! ++ vst1.8 {d4, d5 }, [r2]! ++ beq 11b ++ sub r12, #16 ++ vmov q0, q1 ++ vmov q2, q3 ++1: ++ cmp r12, #8-128 ++ blt 1f ++ vst1.8 {d0}, [r0]! ++ vst1.8 {d4}, [r2]! ++ beq 11b ++ sub r12, #8 ++ vmov d0, d1 ++ vmov d4, d5 ++1: ++ cmp r12, #4-128 ++ blt 1f ++ vst1.32 {d0[0]}, [r0]! ++ vst1.32 {d4[0]}, [r2]! ++ beq 11b ++ sub r12, #4 ++ vmov s0, s1 ++ vmov s8, s9 ++1: ++ cmp r12, #2-128 ++ blt 1f ++ vst1.16 {d0[0]}, [r0]! ++ vst1.16 {d4[0]}, [r2]! ++ beq 11b ++ vst1.8 {d0[2]}, [r0]! ++ vst1.8 {d4[2]}, [r2]! ++ b 11b ++1: ++ vst1.8 {d0[0]}, [r0]! ++ vst1.8 {d4[0]}, [r2]! ++ b 11b ++endfunc ++ ++ ++ ++@ void ff_rpi_sand30_lines_to_planar_y16( ++@ uint8_t * dest, // [r0] ++@ unsigned int dst_stride, // [r1] ++@ const uint8_t * src, // [r2] ++@ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++@ unsigned int src_stride2, // [sp, #0] -> r3 ++@ unsigned int _x, // [sp, #4] Ignored - 0 ++@ unsigned int y, // [sp, #8] (r7 in prefix) ++@ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++@ unsigned int h); // [sp, #16] -> r7 ++@ ++@ Assumes that we are starting on a stripe boundary and that overreading ++@ within the stripe is OK. However it does respect the dest size for writing ++ ++function ff_rpi_sand30_lines_to_planar_y16, export=1 ++ push {r4-r8, lr} @ +24 ++ ldr r3, [sp, #24] ++ ldr r6, [sp, #36] ++ ldr r7, [sp, #32] @ y ++ mov r12, #48 ++ vmov.u16 q15, #0x3ff ++ sub r3, #1 ++ lsl r3, #7 ++ sub r1, r1, r6, lsl #1 ++ add r8, r2, r7, lsl #7 ++ ldr r7, [sp, #40] ++ ++10: ++ mov r2, r8 ++ add r4, r0, #24 ++ mov r5, r6 ++ mov lr, #0 ++1: ++ vldm r2!, {q10-q13} ++ add lr, #64 ++ ++ vshr.u32 q14, q10, #20 @ Cannot vshrn.u32 #20! ++ ands lr, #127 ++ vshrn.u32 d2, q10, #10 ++ vmovn.u32 d0, q10 ++ vmovn.u32 d4, q14 ++ ++ vshr.u32 q14, q11, #20 ++ it eq ++ addeq r2, r3 ++ vshrn.u32 d3, q11, #10 ++ vmovn.u32 d1, q11 ++ vmovn.u32 d5, q14 ++ ++ subs r5, #48 ++ vand q0, q15 ++ vand q1, q15 ++ vand q2, q15 ++ ++ vshr.u32 q14, q12, #20 ++ vshrn.u32 d18, q12, #10 ++ vmovn.u32 d16, q12 ++ vmovn.u32 d20, q14 ++ ++ vshr.u32 q14, q13, #20 ++ vshrn.u32 d19, q13, #10 ++ vmovn.u32 d17, q13 ++ vmovn.u32 d21, q14 ++ ++ vand q8, q15 ++ vand q9, q15 ++ vand q10, q15 ++ blt 2f ++ ++ vst3.16 {d0, d2, d4}, [r0], r12 ++ vst3.16 {d1, d3, d5}, [r4], r12 ++ vst3.16 {d16, d18, d20}, [r0], r12 ++ vst3.16 {d17, d19, d21}, [r4], r12 ++ ++ bne 1b ++ ++11: ++ subs r7, #1 ++ add r0, r1 ++ add r8, #128 ++ bne 10b ++ ++ pop {r4-r8, pc} ++ ++@ Partial final write ++2: ++ cmp r5, #24-48 ++ blt 1f ++ vst3.16 {d0, d2, d4}, [r0], r12 ++ vst3.16 {d1, d3, d5}, [r4] ++ beq 11b ++ vmov q0, q8 ++ sub r5, #24 ++ vmov q1, q9 ++ vmov q2, q10 ++1: ++ cmp r5, #12-48 ++ blt 1f ++ vst3.16 {d0, d2, d4}, [r0]! ++ beq 11b ++ vmov d0, d1 ++ sub r5, #12 ++ vmov d2, d3 ++ vmov d4, d5 ++1: ++ cmp r5, #6-48 ++ add r4, r0, #6 @ avoid [r0]! on sequential instructions ++ blt 1f ++ vst3.16 {d0[0], d2[0], d4[0]}, [r0] ++ vst3.16 {d0[1], d2[1], d4[1]}, [r4] ++ add r0, #12 ++ beq 11b ++ vmov s0, s1 ++ sub r5, #6 ++ vmov s4, s5 ++ vmov s8, s9 ++1: ++ cmp r5, #3-48 ++ blt 1f ++ vst3.16 {d0[0], d2[0], d4[0]}, [r0]! ++ beq 11b ++ sub r5, #3 ++ vshr.u32 d0, #16 ++ vshr.u32 d2, #16 ++1: ++ cmp r5, #2-48 ++ blt 1f ++ vst2.16 {d0[0], d2[0]}, [r0]! ++ b 11b ++1: ++ vst1.16 {d0[0]}, [r0]! ++ b 11b ++ ++endfunc ++ ++ ++@ void ff_rpi_sand30_lines_to_planar_c16( ++@ uint8_t * dst_u, // [r0] ++@ unsigned int dst_stride_u, // [r1] ++@ uint8_t * dst_v, // [r2] ++@ unsigned int dst_stride_v, // [r3] ++@ const uint8_t * src, // [sp, #0] -> r4, r5 ++@ unsigned int stride1, // [sp, #4] 128 ++@ unsigned int stride2, // [sp, #8] -> r8 ++@ unsigned int _x, // [sp, #12] 0 ++@ unsigned int y, // [sp, #16] (r7 in prefix) ++@ unsigned int _w, // [sp, #20] -> r6, r9 ++@ unsigned int h); // [sp, #24] -> r7 ++@ ++@ Assumes that we are starting on a stripe boundary and that overreading ++@ within the stripe is OK. However it does respect the dest size for writing ++ ++function ff_rpi_sand30_lines_to_planar_c16, export=1 ++ push {r4-r10, lr} @ +32 ++ ldr r5, [sp, #32] ++ ldr r8, [sp, #40] ++ ldr r7, [sp, #48] ++ ldr r9, [sp, #52] ++ mov r12, #48 ++ vmov.u16 q15, #0x3ff ++ sub r8, #1 ++ lsl r8, #7 ++ add r5, r5, r7, lsl #7 ++ sub r1, r1, r9, lsl #1 ++ sub r3, r3, r9, lsl #1 ++ ldr r7, [sp, #56] ++10: ++ mov lr, #0 ++ mov r4, r5 ++ mov r6, r9 ++1: ++ vldm r4!, {q0-q3} ++ add lr, #64 ++ ++ @ N.B. unpack [0,1,2] -> (reg order) 1, 0, 2 ++ vshr.u32 q14, q0, #20 ++ vshrn.u32 d16, q0, #10 ++ vmovn.u32 d18, q0 ++ ands lr, #127 ++ vmovn.u32 d20, q14 ++ ++ vshr.u32 q14, q1, #20 ++ vshrn.u32 d17, q1, #10 ++ vmovn.u32 d19, q1 ++ vmovn.u32 d21, q14 ++ ++ vshr.u32 q14, q2, #20 ++ vshrn.u32 d22, q2, #10 ++ vmovn.u32 d24, q2 ++ vmovn.u32 d26, q14 ++ ++ vshr.u32 q14, q3, #20 ++ vshrn.u32 d23, q3, #10 ++ vmovn.u32 d25, q3 ++ add r10, r0, #24 ++ vmovn.u32 d27, q14 ++ ++ it eq ++ addeq r4, r8 ++ vuzp.16 q8, q11 ++ vuzp.16 q9, q12 ++ vuzp.16 q10, q13 ++ ++ @ q8 V0, V3,.. -> q0 ++ @ q9 U0, U3... ++ @ q10 U1, U4... ++ @ q11 U2, U5,.. ++ @ q12 V1, V4,.. -> q1 ++ @ q13 V2, V5,.. -> q2 ++ ++ subs r6, #24 ++ vand q11, q15 ++ vand q9, q15 ++ vand q10, q15 ++ vand q0, q8, q15 ++ vand q1, q12, q15 ++ vand q2, q13, q15 ++ ++ blt 2f ++ ++ vst3.16 {d18, d20, d22}, [r0], r12 ++ vst3.16 {d19, d21, d23}, [r10] ++ add r10, r2, #24 ++ vst3.16 {d0, d2, d4}, [r2], r12 ++ vst3.16 {d1, d3, d5}, [r10] ++ ++ bne 1b ++ ++11: ++ subs r7, #1 ++ add r5, #128 ++ add r0, r1 ++ add r2, r3 ++ bne 10b ++ ++ pop {r4-r10, pc} ++ ++@ Partial final write ++2: ++ cmp r6, #-12 ++ blt 1f ++ vst3.16 {d18, d20, d22}, [r0]! ++ vst3.16 {d0, d2, d4}, [r2]! ++ beq 11b ++ vmov d18, d19 ++ vmov d20, d21 ++ vmov d22, d23 ++ sub r6, #12 ++ vmov d0, d1 ++ vmov d2, d3 ++ vmov d4, d5 ++1: ++ cmp r6, #-18 ++ @ Rezip here as it makes the remaining tail handling easier ++ vzip.16 d0, d18 ++ vzip.16 d2, d20 ++ vzip.16 d4, d22 ++ blt 1f ++ vst3.16 {d0[1], d2[1], d4[1]}, [r0]! ++ vst3.16 {d0[0], d2[0], d4[0]}, [r2]! ++ vst3.16 {d0[3], d2[3], d4[3]}, [r0]! ++ vst3.16 {d0[2], d2[2], d4[2]}, [r2]! ++ beq 11b ++ vmov d0, d18 ++ vmov d2, d20 ++ sub r6, #6 ++ vmov d4, d22 ++1: ++ cmp r6, #-21 ++ blt 1f ++ vst3.16 {d0[1], d2[1], d4[1]}, [r0]! ++ vst3.16 {d0[0], d2[0], d4[0]}, [r2]! ++ beq 11b ++ vmov s4, s5 ++ sub r6, #3 ++ vmov s0, s1 ++1: ++ cmp r6, #-22 ++ blt 1f ++ vst2.16 {d0[1], d2[1]}, [r0]! ++ vst2.16 {d0[0], d2[0]}, [r2]! ++ b 11b ++1: ++ vst1.16 {d0[1]}, [r0]! ++ vst1.16 {d0[0]}, [r2]! ++ b 11b ++ ++endfunc ++ ++@ void ff_rpi_sand30_lines_to_planar_p010( ++@ uint8_t * dest, // [r0] ++@ unsigned int dst_stride, // [r1] ++@ const uint8_t * src, // [r2] ++@ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++@ unsigned int src_stride2, // [sp, #0] -> r3 ++@ unsigned int _x, // [sp, #4] Ignored - 0 ++@ unsigned int y, // [sp, #8] (r7 in prefix) ++@ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++@ unsigned int h); // [sp, #16] -> r7 ++@ ++@ Assumes that we are starting on a stripe boundary and that overreading ++@ within the stripe is OK. However it does respect the dest size for writing ++ ++function ff_rpi_sand30_lines_to_planar_p010, export=1 ++ push {r4-r8, lr} @ +24 ++ ldr r3, [sp, #24] ++ ldr r6, [sp, #36] ++ ldr r7, [sp, #32] @ y ++ mov r12, #48 ++ vmov.u16 q15, #0xffc0 ++ sub r3, #1 ++ lsl r3, #7 ++ sub r1, r1, r6, lsl #1 ++ add r8, r2, r7, lsl #7 ++ ldr r7, [sp, #40] ++ ++10: ++ mov r2, r8 ++ add r4, r0, #24 ++ mov r5, r6 ++ mov lr, #0 ++1: ++ vldm r2!, {q10-q13} ++ add lr, #64 ++ ++ vshl.u32 q14, q10, #6 ++ ands lr, #127 ++ vshrn.u32 d4, q10, #14 ++ vshrn.u32 d2, q10, #4 ++ vmovn.u32 d0, q14 ++ ++ vshl.u32 q14, q11, #6 ++ it eq ++ addeq r2, r3 ++ vshrn.u32 d5, q11, #14 ++ vshrn.u32 d3, q11, #4 ++ vmovn.u32 d1, q14 ++ ++ subs r5, #48 ++ vand q2, q15 ++ vand q1, q15 ++ vand q0, q15 ++ ++ vshl.u32 q14, q12, #6 ++ vshrn.u32 d20, q12, #14 ++ vshrn.u32 d18, q12, #4 ++ vmovn.u32 d16, q14 ++ ++ vshl.u32 q14, q13, #6 ++ vshrn.u32 d21, q13, #14 ++ vshrn.u32 d19, q13, #4 ++ vmovn.u32 d17, q14 ++ ++ vand q10, q15 ++ vand q9, q15 ++ vand q8, q15 ++ blt 2f ++ ++ vst3.16 {d0, d2, d4}, [r0], r12 ++ vst3.16 {d1, d3, d5}, [r4], r12 ++ vst3.16 {d16, d18, d20}, [r0], r12 ++ vst3.16 {d17, d19, d21}, [r4], r12 ++ ++ bne 1b ++ ++11: ++ subs r7, #1 ++ add r0, r1 ++ add r8, #128 ++ bne 10b ++ ++ pop {r4-r8, pc} ++ ++@ Partial final write ++2: ++ cmp r5, #24-48 ++ blt 1f ++ vst3.16 {d0, d2, d4}, [r0], r12 ++ vst3.16 {d1, d3, d5}, [r4] ++ beq 11b ++ vmov q0, q8 ++ sub r5, #24 ++ vmov q1, q9 ++ vmov q2, q10 ++1: ++ cmp r5, #12-48 ++ blt 1f ++ vst3.16 {d0, d2, d4}, [r0]! ++ beq 11b ++ vmov d0, d1 ++ sub r5, #12 ++ vmov d2, d3 ++ vmov d4, d5 ++1: ++ cmp r5, #6-48 ++ add r4, r0, #6 @ avoid [r0]! on sequential instructions ++ blt 1f ++ vst3.16 {d0[0], d2[0], d4[0]}, [r0] ++ vst3.16 {d0[1], d2[1], d4[1]}, [r4] ++ add r0, #12 ++ beq 11b ++ vmov s0, s1 ++ sub r5, #6 ++ vmov s4, s5 ++ vmov s8, s9 ++1: ++ cmp r5, #3-48 ++ blt 1f ++ vst3.16 {d0[0], d2[0], d4[0]}, [r0]! ++ beq 11b ++ sub r5, #3 ++ vshr.u32 d0, #16 ++ vshr.u32 d2, #16 ++1: ++ cmp r5, #2-48 ++ blt 1f ++ vst2.16 {d0[0], d2[0]}, [r0]! ++ b 11b ++1: ++ vst1.16 {d0[0]}, [r0]! ++ b 11b ++ ++endfunc ++ ++ ++ +diff --git a/libavutil/arm/rpi_sand_neon.h b/libavutil/arm/rpi_sand_neon.h +new file mode 100644 +index 0000000000..447f367bea +--- /dev/null ++++ b/libavutil/arm/rpi_sand_neon.h +@@ -0,0 +1,99 @@ ++/* ++Copyright (c) 2020 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++#ifndef AVUTIL_ARM_SAND_NEON_H ++#define AVUTIL_ARM_SAND_NEON_H ++ ++void ff_rpi_sand128b_stripe_to_8_10( ++ uint8_t * dest, // [r0] ++ const uint8_t * src1, // [r1] ++ const uint8_t * src2, // [r2] ++ unsigned int lines); // [r3] ++ ++void ff_rpi_sand8_lines_to_planar_y8( ++ uint8_t * dest, // [r0] ++ unsigned int dst_stride, // [r1] ++ const uint8_t * src, // [r2] ++ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++ unsigned int src_stride2, // [sp, #0] -> r3 ++ unsigned int _x, // [sp, #4] Ignored - 0 ++ unsigned int y, // [sp, #8] (r7 in prefix) ++ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++ unsigned int h); // [sp, #16] -> r7 ++ ++void ff_rpi_sand8_lines_to_planar_c8( ++ uint8_t * dst_u, // [r0] ++ unsigned int dst_stride_u, // [r1] ++ uint8_t * dst_v, // [r2] ++ unsigned int dst_stride_v, // [r3] ++ const uint8_t * src, // [sp, #0] -> r4, r5 ++ unsigned int stride1, // [sp, #4] 128 ++ unsigned int stride2, // [sp, #8] -> r8 ++ unsigned int _x, // [sp, #12] 0 ++ unsigned int y, // [sp, #16] (r7 in prefix) ++ unsigned int _w, // [sp, #20] -> r12, r6 ++ unsigned int h); // [sp, #24] -> r7 ++ ++void ff_rpi_sand30_lines_to_planar_y16( ++ uint8_t * dest, // [r0] ++ unsigned int dst_stride, // [r1] ++ const uint8_t * src, // [r2] ++ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++ unsigned int src_stride2, // [sp, #0] -> r3 ++ unsigned int _x, // [sp, #4] Ignored - 0 ++ unsigned int y, // [sp, #8] (r7 in prefix) ++ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++ unsigned int h); // [sp, #16] -> r7 ++ ++void ff_rpi_sand30_lines_to_planar_c16( ++ uint8_t * dst_u, // [r0] ++ unsigned int dst_stride_u, // [r1] ++ uint8_t * dst_v, // [r2] ++ unsigned int dst_stride_v, // [r3] ++ const uint8_t * src, // [sp, #0] -> r4, r5 ++ unsigned int stride1, // [sp, #4] 128 ++ unsigned int stride2, // [sp, #8] -> r8 ++ unsigned int _x, // [sp, #12] 0 ++ unsigned int y, // [sp, #16] (r7 in prefix) ++ unsigned int _w, // [sp, #20] -> r6, r9 ++ unsigned int h); // [sp, #24] -> r7 ++ ++void ff_rpi_sand30_lines_to_planar_p010( ++ uint8_t * dest, // [r0] ++ unsigned int dst_stride, // [r1] ++ const uint8_t * src, // [r2] ++ unsigned int src_stride1, // [r3] Ignored - assumed 128 ++ unsigned int src_stride2, // [sp, #0] -> r3 ++ unsigned int _x, // [sp, #4] Ignored - 0 ++ unsigned int y, // [sp, #8] (r7 in prefix) ++ unsigned int _w, // [sp, #12] -> r6 (cur r5) ++ unsigned int h); // [sp, #16] -> r7 ++ ++#endif // AVUTIL_ARM_SAND_NEON_H ++ +diff --git a/libavutil/buffer.c b/libavutil/buffer.c +index 38a554208a..b0fedabc3e 100644 +--- a/libavutil/buffer.c ++++ b/libavutil/buffer.c +@@ -273,6 +273,19 @@ static void buffer_pool_free(AVBufferPool *pool) + av_freep(&pool); + } + ++void av_buffer_pool_flush(AVBufferPool *pool) ++{ ++ ff_mutex_lock(&pool->mutex); ++ while (pool->pool) { ++ BufferPoolEntry *buf = pool->pool; ++ pool->pool = buf->next; ++ ++ buf->free(buf->opaque, buf->data); ++ av_freep(&buf); ++ } ++ ff_mutex_unlock(&pool->mutex); ++} ++ + void av_buffer_pool_uninit(AVBufferPool **ppool) + { + AVBufferPool *pool; +diff --git a/libavutil/buffer.h b/libavutil/buffer.h +index c0f3f6cc9a..998beec9ac 100644 +--- a/libavutil/buffer.h ++++ b/libavutil/buffer.h +@@ -267,6 +267,11 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), + void (*pool_free)(void *opaque)); + ++/** ++ * Free all available buffers in a buffer pool. ++ */ ++ void av_buffer_pool_flush(AVBufferPool *pool); ++ + /** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it +diff --git a/libavutil/frame.c b/libavutil/frame.c +index 2e952edd29..96e8bf5b3e 100644 +--- a/libavutil/frame.c ++++ b/libavutil/frame.c +@@ -16,6 +16,8 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include "config.h" ++ + #include "channel_layout.h" + #include "avassert.h" + #include "buffer.h" +@@ -26,6 +28,9 @@ + #include "mem.h" + #include "samplefmt.h" + #include "hwcontext.h" ++#if CONFIG_SAND ++#include "rpi_sand_fns.h" ++#endif + + #if FF_API_FRAME_GET_SET + MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) +@@ -902,6 +907,12 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) + (frame->crop_top + frame->crop_bottom) >= frame->height) + return AVERROR(ERANGE); + ++#if CONFIG_SAND ++ // Sand cannot be cropped - do not try ++ if (av_rpi_is_sand_format(frame->format)) ++ return 0; ++#endif ++ + desc = av_pix_fmt_desc_get(frame->format); + if (!desc) + return AVERROR_BUG; +diff --git a/libavutil/frame.h b/libavutil/frame.h +index fc67db0f6c..b1a7eb4858 100644 +--- a/libavutil/frame.h ++++ b/libavutil/frame.h +@@ -968,6 +968,16 @@ int av_frame_apply_cropping(AVFrame *frame, int flags); + */ + const char *av_frame_side_data_name(enum AVFrameSideDataType type); + ++ ++static inline int av_frame_cropped_width(const AVFrame * const frame) ++{ ++ return frame->width - (frame->crop_left + frame->crop_right); ++} ++static inline int av_frame_cropped_height(const AVFrame * const frame) ++{ ++ return frame->height - (frame->crop_top + frame->crop_bottom); ++} ++ + /** + * @} + */ +diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c +index 32cbde82eb..9ba8b7b2dd 100644 +--- a/libavutil/hwcontext_drm.c ++++ b/libavutil/hwcontext_drm.c +@@ -21,6 +21,7 @@ + #include + + #include ++#include + #include + + #include "avassert.h" +@@ -28,6 +29,7 @@ + #include "hwcontext_drm.h" + #include "hwcontext_internal.h" + #include "imgutils.h" ++#include "libavutil/rpi_sand_fns.h" + + + static void drm_device_free(AVHWDeviceContext *hwdev) +@@ -43,6 +45,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device, + AVDRMDeviceContext *hwctx = hwdev->hwctx; + drmVersionPtr version; + ++ if (device == NULL) { ++ hwctx->fd = -1; ++ return 0; ++ } ++ + hwctx->fd = open(device, O_RDWR); + if (hwctx->fd < 0) + return AVERROR(errno); +@@ -120,6 +127,9 @@ static int drm_map_frame(AVHWFramesContext *hwfc, + if (flags & AV_HWFRAME_MAP_WRITE) + mmap_prot |= PROT_WRITE; + ++ if (dst->format == AV_PIX_FMT_NONE) ++ dst->format = hwfc->sw_format; ++ + av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES); + for (i = 0; i < desc->nb_objects; i++) { + addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED, +@@ -151,6 +161,23 @@ static int drm_map_frame(AVHWFramesContext *hwfc, + + dst->width = src->width; + dst->height = src->height; ++ dst->crop_top = src->crop_top; ++ dst->crop_bottom = src->crop_bottom; ++ dst->crop_left = src->crop_left; ++ dst->crop_right = src->crop_right; ++ ++#if CONFIG_SAND ++ // Rework for sand frames ++ if (av_rpi_is_sand_frame(dst)) { ++ // As it stands the sand formats hold stride2 in linesize[3] ++ // linesize[0] & [1] contain stride1 which is always 128 for everything we do ++ // * Arguably this should be reworked s.t. stride2 is in linesize[0] & [1] ++ dst->linesize[3] = fourcc_mod_broadcom_param(desc->objects[0].format_modifier); ++ dst->linesize[0] = 128; ++ dst->linesize[1] = 128; ++ // *** Are we sure src->height is actually what we want ??? ++ } ++#endif + + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, + &drm_unmap_frame, map); +@@ -178,7 +205,15 @@ static int drm_transfer_get_formats(AVHWFramesContext *ctx, + if (!pix_fmts) + return AVERROR(ENOMEM); + +- pix_fmts[0] = ctx->sw_format; ++ // **** Offer native sand too ???? ++ pix_fmts[0] = ++#if CONFIG_SAND ++ ctx->sw_format == AV_PIX_FMT_RPI4_8 || ctx->sw_format == AV_PIX_FMT_SAND128 ? ++ AV_PIX_FMT_YUV420P : ++ ctx->sw_format == AV_PIX_FMT_RPI4_10 ? ++ AV_PIX_FMT_YUV420P10LE : ++#endif ++ ctx->sw_format; + pix_fmts[1] = AV_PIX_FMT_NONE; + + *formats = pix_fmts; +@@ -197,18 +232,82 @@ static int drm_transfer_data_from(AVHWFramesContext *hwfc, + map = av_frame_alloc(); + if (!map) + return AVERROR(ENOMEM); +- map->format = dst->format; + ++ // Map to default ++ map->format = AV_PIX_FMT_NONE; + err = drm_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ); + if (err) + goto fail; + +- map->width = dst->width; +- map->height = dst->height; ++#if 0 ++ av_log(hwfc, AV_LOG_INFO, "%s: src fmt=%d (%d), dst fmt=%d (%d) s=%dx%d l=%d/%d/%d/%d, d=%dx%d l=%d/%d/%d\n", __func__, ++ hwfc->sw_format, AV_PIX_FMT_RPI4_8, dst->format, AV_PIX_FMT_YUV420P10LE, ++ map->width, map->height, ++ map->linesize[0], ++ map->linesize[1], ++ map->linesize[2], ++ map->linesize[3], ++ dst->width, dst->height, ++ dst->linesize[0], ++ dst->linesize[1], ++ dst->linesize[2]); ++#endif ++#if CONFIG_SAND ++ if (av_rpi_is_sand_frame(map)) { ++ unsigned int stride2 = map->linesize[3]; ++ const unsigned int w = FFMIN(dst->width, av_frame_cropped_width(map)); ++ const unsigned int h = FFMIN(dst->height, av_frame_cropped_height(map)); ++ ++ if (map->format == AV_PIX_FMT_RPI4_8 && dst->format == AV_PIX_FMT_YUV420P) { ++ av_rpi_sand_to_planar_y8(dst->data[0], dst->linesize[0], ++ map->data[0], ++ 128, stride2, ++ map->crop_left, map->crop_top, ++ w, h); ++ av_rpi_sand_to_planar_c8(dst->data[1], dst->linesize[1], ++ dst->data[2], dst->linesize[2], ++ map->data[1], ++ 128, stride2, ++ map->crop_left / 2, map->crop_top / 2, ++ w / 2, h / 2); ++ } ++ else if (map->format == AV_PIX_FMT_RPI4_10 && dst->format == AV_PIX_FMT_YUV420P10LE) { ++ av_rpi_sand30_to_planar_y16(dst->data[0], dst->linesize[0], ++ map->data[0], ++ 128, stride2, ++ map->crop_left, map->crop_top, ++ w, h); // *** ??? crop ++ av_rpi_sand30_to_planar_c16(dst->data[1], dst->linesize[1], ++ dst->data[2], dst->linesize[2], ++ map->data[1], ++ 128, stride2, ++ map->crop_left / 2, map->crop_top / 2, ++ w / 2, h / 2); ++ } ++ else ++ { ++ av_log(hwfc, AV_LOG_ERROR, "%s: Incompatible output pixfmt for sand\n", __func__); ++ err = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ dst->width = w; ++ dst->height = h; ++ } ++ else ++#endif ++ { ++ // Kludge mapped h/w s.t. frame_copy works ++ map->width = dst->width; ++ map->height = dst->height; ++ err = av_frame_copy(dst, map); ++ } + +- err = av_frame_copy(dst, map); + if (err) ++ { ++ av_log(hwfc, AV_LOG_ERROR, "%s: Copy fail\n", __func__); + goto fail; ++ } + + err = 0; + fail: +@@ -223,7 +322,10 @@ static int drm_transfer_data_to(AVHWFramesContext *hwfc, + int err; + + if (src->width > hwfc->width || src->height > hwfc->height) ++ { ++ av_log(hwfc, AV_LOG_ERROR, "%s: H/w mismatch: %d/%d, %d/%d\n", __func__, dst->width, hwfc->width, dst->height, hwfc->height); + return AVERROR(EINVAL); ++ } + + map = av_frame_alloc(); + if (!map) +diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c +index 9d61c52567..4e36a110c1 100644 +--- a/libavutil/pixdesc.c ++++ b/libavutil/pixdesc.c +@@ -2073,6 +2073,18 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { + .name = "cuda", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, ++ [AV_PIX_FMT_RPI] = { ++ .name = "rpi", ++ .flags = AV_PIX_FMT_FLAG_HWACCEL, ++ }, ++ [AV_PIX_FMT_RPI4_10] = { ++ .name = "rpi", ++ .flags = AV_PIX_FMT_FLAG_HWACCEL, ++ }, ++ [AV_PIX_FMT_RPI4_8] = { ++ .name = "rpi", ++ .flags = AV_PIX_FMT_FLAG_HWACCEL, ++ }, + [AV_PIX_FMT_AYUV64LE] = { + .name = "ayuv64le", + .nb_components = 4, +@@ -2371,6 +2383,30 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { + .name = "vulkan", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, ++ [AV_PIX_FMT_SAND128] = { ++ .name = "sand128", ++ .nb_components = 3, ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .comp = { ++ { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ ++ { 1, 2, 0, 0, 8, 1, 7, 1 }, /* U */ ++ { 1, 2, 1, 0, 8, 1, 7, 2 }, /* V */ ++ }, ++ .flags = 0, ++ }, ++ [AV_PIX_FMT_SAND64_10] = { ++ .name = "sand64_10", ++ .nb_components = 3, ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .comp = { ++ { 0, 2, 0, 0, 10, 0, 9, 1 }, /* Y */ ++ { 1, 4, 0, 0, 10, 1, 9, 1 }, /* U */ ++ { 1, 4, 1, 0, 10, 1, 9, 2 }, /* V */ ++ }, ++ .flags = 0, ++ }, + }; + #if FF_API_PLUS1_MINUS1 + FF_ENABLE_DEPRECATION_WARNINGS +diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h +index 1c625cfc8a..3400390a77 100644 +--- a/libavutil/pixfmt.h ++++ b/libavutil/pixfmt.h +@@ -234,6 +234,11 @@ enum AVPixelFormat { + */ + AV_PIX_FMT_CUDA, + ++ /** ++ * HW acceleration through RPI. ++ */ ++ AV_PIX_FMT_RPI, ++ + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined +@@ -357,6 +362,12 @@ enum AVPixelFormat { + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian ++// RPI - not on ifdef so can be got at by calling progs ++ AV_PIX_FMT_SAND128, ///< 4:2:0 8-bit 128x*Y stripe, 64x*UV stripe, then next x stripe, mysterious padding ++ AV_PIX_FMT_SAND64_10, ///< 4:2:0 10-bit 64x*Y stripe, 32x*UV stripe, then next x stripe, mysterious padding ++ AV_PIX_FMT_SAND64_16, ///< 4:2:0 16-bit 64x*Y stripe, 32x*UV stripe, then next x stripe, mysterious padding ++ AV_PIX_FMT_RPI4_8, ++ AV_PIX_FMT_RPI4_10, + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions + }; +diff --git a/libavutil/rpi_sand_fn_pw.h b/libavutil/rpi_sand_fn_pw.h +new file mode 100644 +index 0000000000..0324f6826d +--- /dev/null ++++ b/libavutil/rpi_sand_fn_pw.h +@@ -0,0 +1,227 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++// * Included twice from rpi_sand_fn with different PW ++ ++#define STRCAT(x,y) x##y ++ ++#if PW == 1 ++#define pixel uint8_t ++#define FUNC(f) STRCAT(f, 8) ++#elif PW == 2 ++#define pixel uint16_t ++#define FUNC(f) STRCAT(f, 16) ++#else ++#error Unexpected PW ++#endif ++ ++// Fetches a single patch - offscreen fixup not done here ++// w <= stride1 ++// unclipped ++void FUNC(av_rpi_sand_to_planar_y)(uint8_t * dst, const unsigned int dst_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h) ++{ ++ const unsigned int x = _x; ++ const unsigned int w = _w; ++ const unsigned int mask = stride1 - 1; ++ ++#if PW == 1 && (HAVE_SAND_ASM || HAVE_SAND_ASM64) ++ if (_x == 0) { ++ ff_rpi_sand8_lines_to_planar_y8(dst, dst_stride, ++ src, stride1, stride2, _x, y, _w, h); ++ return; ++ } ++#endif ++ ++ if ((x & ~mask) == ((x + w) & ~mask)) { ++ // All in one sand stripe ++ const uint8_t * p = src + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ for (unsigned int i = 0; i != h; ++i, dst += dst_stride, p += stride1) { ++ memcpy(dst, p, w); ++ } ++ } ++ else ++ { ++ // Two+ stripe ++ const unsigned int sstride = stride1 * stride2; ++ const uint8_t * p1 = src + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ const uint8_t * p2 = p1 + sstride - (x & mask); ++ const unsigned int w1 = stride1 - (x & mask); ++ const unsigned int w3 = (x + w) & mask; ++ const unsigned int w2 = w - (w1 + w3); ++ ++ for (unsigned int i = 0; i != h; ++i, dst += dst_stride, p1 += stride1, p2 += stride1) { ++ unsigned int j; ++ const uint8_t * p = p2; ++ uint8_t * d = dst; ++ memcpy(d, p1, w1); ++ d += w1; ++ for (j = 0; j < w2; j += stride1, d += stride1, p += sstride) { ++ memcpy(d, p, stride1); ++ } ++ memcpy(d, p, w3); ++ } ++ } ++} ++ ++// x & w in bytes but not of interleave (i.e. offset = x*2 for U&V) ++ ++void FUNC(av_rpi_sand_to_planar_c)(uint8_t * dst_u, const unsigned int dst_stride_u, ++ uint8_t * dst_v, const unsigned int dst_stride_v, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h) ++{ ++ const unsigned int x = _x * 2; ++ const unsigned int w = _w * 2; ++ const unsigned int mask = stride1 - 1; ++ ++#if PW == 1 && (HAVE_SAND_ASM || HAVE_SAND_ASM64) ++ if (_x == 0) { ++ ff_rpi_sand8_lines_to_planar_c8(dst_u, dst_stride_u, dst_v, dst_stride_v, ++ src, stride1, stride2, _x, y, _w, h); ++ return; ++ } ++#endif ++ ++ if ((x & ~mask) == ((x + w) & ~mask)) { ++ // All in one sand stripe ++ const uint8_t * p1 = src + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ for (unsigned int i = 0; i != h; ++i, dst_u += dst_stride_u, dst_v += dst_stride_v, p1 += stride1) { ++ pixel * du = (pixel *)dst_u; ++ pixel * dv = (pixel *)dst_v; ++ const pixel * p = (const pixel *)p1; ++ for (unsigned int k = 0; k < w; k += 2 * PW) { ++ *du++ = *p++; ++ *dv++ = *p++; ++ } ++ } ++ } ++ else ++ { ++ // Two+ stripe ++ const unsigned int sstride = stride1 * stride2; ++ const unsigned int sstride_p = (sstride - stride1) / PW; ++ ++ const uint8_t * p1 = src + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ const uint8_t * p2 = p1 + sstride - (x & mask); ++ const unsigned int w1 = stride1 - (x & mask); ++ const unsigned int w3 = (x + w) & mask; ++ const unsigned int w2 = w - (w1 + w3); ++ ++ for (unsigned int i = 0; i != h; ++i, dst_u += dst_stride_u, dst_v += dst_stride_v, p1 += stride1, p2 += stride1) { ++ unsigned int j; ++ const pixel * p = (const pixel *)p1; ++ pixel * du = (pixel *)dst_u; ++ pixel * dv = (pixel *)dst_v; ++ for (unsigned int k = 0; k < w1; k += 2 * PW) { ++ *du++ = *p++; ++ *dv++ = *p++; ++ } ++ for (j = 0, p = (const pixel *)p2; j < w2; j += stride1, p += sstride_p) { ++ for (unsigned int k = 0; k < stride1; k += 2 * PW) { ++ *du++ = *p++; ++ *dv++ = *p++; ++ } ++ } ++ for (unsigned int k = 0; k < w3; k += 2 * PW) { ++ *du++ = *p++; ++ *dv++ = *p++; ++ } ++ } ++ } ++} ++ ++void FUNC(av_rpi_planar_to_sand_c)(uint8_t * dst_c, ++ unsigned int stride1, unsigned int stride2, ++ const uint8_t * src_u, const unsigned int src_stride_u, ++ const uint8_t * src_v, const unsigned int src_stride_v, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h) ++{ ++ const unsigned int x = _x * 2; ++ const unsigned int w = _w * 2; ++ const unsigned int mask = stride1 - 1; ++ if ((x & ~mask) == ((x + w) & ~mask)) { ++ // All in one sand stripe ++ uint8_t * p1 = dst_c + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ for (unsigned int i = 0; i != h; ++i, src_u += src_stride_u, src_v += src_stride_v, p1 += stride1) { ++ const pixel * su = (const pixel *)src_u; ++ const pixel * sv = (const pixel *)src_v; ++ pixel * p = (pixel *)p1; ++ for (unsigned int k = 0; k < w; k += 2 * PW) { ++ *p++ = *su++; ++ *p++ = *sv++; ++ } ++ } ++ } ++ else ++ { ++ // Two+ stripe ++ const unsigned int sstride = stride1 * stride2; ++ const unsigned int sstride_p = (sstride - stride1) / PW; ++ ++ const uint8_t * p1 = dst_c + (x & mask) + y * stride1 + (x & ~mask) * stride2; ++ const uint8_t * p2 = p1 + sstride - (x & mask); ++ const unsigned int w1 = stride1 - (x & mask); ++ const unsigned int w3 = (x + w) & mask; ++ const unsigned int w2 = w - (w1 + w3); ++ ++ for (unsigned int i = 0; i != h; ++i, src_u += src_stride_u, src_v += src_stride_v, p1 += stride1, p2 += stride1) { ++ unsigned int j; ++ const pixel * su = (const pixel *)src_u; ++ const pixel * sv = (const pixel *)src_v; ++ pixel * p = (pixel *)p1; ++ for (unsigned int k = 0; k < w1; k += 2 * PW) { ++ *p++ = *su++; ++ *p++ = *sv++; ++ } ++ for (j = 0, p = (pixel *)p2; j < w2; j += stride1, p += sstride_p) { ++ for (unsigned int k = 0; k < stride1; k += 2 * PW) { ++ *p++ = *su++; ++ *p++ = *sv++; ++ } ++ } ++ for (unsigned int k = 0; k < w3; k += 2 * PW) { ++ *p++ = *su++; ++ *p++ = *sv++; ++ } ++ } ++ } ++} ++ ++ ++#undef pixel ++#undef STRCAT ++#undef FUNC ++ +diff --git a/libavutil/rpi_sand_fns.c b/libavutil/rpi_sand_fns.c +new file mode 100644 +index 0000000000..038c306877 +--- /dev/null ++++ b/libavutil/rpi_sand_fns.c +@@ -0,0 +1,357 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++#include "config.h" ++#include ++#include ++#include "rpi_sand_fns.h" ++#include "avassert.h" ++#include "frame.h" ++ ++#if ARCH_ARM && HAVE_NEON ++#include "arm/rpi_sand_neon.h" ++#define HAVE_SAND_ASM 1 ++#elif ARCH_AARCH64 && HAVE_NEON ++#include "aarch64/rpi_sand_neon.h" ++#define HAVE_SAND_ASM 0 ++#define HAVE_SAND_ASM64 1 ++#else ++#define HAVE_SAND_ASM 0 ++#endif ++ ++#define PW 1 ++#include "rpi_sand_fn_pw.h" ++#undef PW ++ ++#define PW 2 ++#include "rpi_sand_fn_pw.h" ++#undef PW ++ ++#if 1 ++// Simple round ++static void cpy16_to_8(uint8_t * dst, const uint8_t * _src, unsigned int n, const unsigned int shr) ++{ ++ const unsigned int rnd = (1 << shr) >> 1; ++ const uint16_t * src = (const uint16_t *)_src; ++ ++ for (; n != 0; --n) { ++ *dst++ = (*src++ + rnd) >> shr; ++ } ++} ++#else ++// Dithered variation ++static void cpy16_to_8(uint8_t * dst, const uint8_t * _src, unsigned int n, const unsigned int shr) ++{ ++ unsigned int rnd = (1 << shr) >> 1; ++ const unsigned int mask = ((1 << shr) - 1); ++ const uint16_t * src = (const uint16_t *)_src; ++ ++ for (; n != 0; --n) { ++ rnd = *src++ + (rnd & mask); ++ *dst++ = rnd >> shr; ++ } ++} ++#endif ++ ++// Fetches a single patch - offscreen fixup not done here ++// w <= stride1 ++// unclipped ++// _x & _w in pixels, strides in bytes ++void av_rpi_sand30_to_planar_y16(uint8_t * dst, const unsigned int dst_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h) ++{ ++ const unsigned int x0 = (_x / 3) * 4; // Byte offset of the word ++ const unsigned int xskip0 = _x - (x0 >> 2) * 3; ++ const unsigned int x1 = ((_x + _w) / 3) * 4; ++ const unsigned int xrem1 = _x + _w - (x1 >> 2) * 3; ++ const unsigned int mask = stride1 - 1; ++ const uint8_t * p0 = src + (x0 & mask) + y * stride1 + (x0 & ~mask) * stride2; ++ const unsigned int slice_inc = ((stride2 - 1) * stride1) >> 2; // RHS of a stripe to LHS of next in words ++ ++#if HAVE_SAND_ASM ++ if (_x == 0) { ++ ff_rpi_sand30_lines_to_planar_y16(dst, dst_stride, src, stride1, stride2, _x, y, _w, h); ++ return; ++ } ++#endif ++ ++ if (x0 == x1) { ++ // ******************* ++ // Partial single word xfer ++ return; ++ } ++ ++ for (unsigned int i = 0; i != h; ++i, dst += dst_stride, p0 += stride1) ++ { ++ unsigned int x = x0; ++ const uint32_t * p = (const uint32_t *)p0; ++ uint16_t * d = (uint16_t *)dst; ++ ++ if (xskip0 != 0) { ++ const uint32_t p3 = *p++; ++ ++ if (xskip0 == 1) ++ *d++ = (p3 >> 10) & 0x3ff; ++ *d++ = (p3 >> 20) & 0x3ff; ++ ++ if (((x += 4) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ while (x != x1) { ++ const uint32_t p3 = *p++; ++ *d++ = p3 & 0x3ff; ++ *d++ = (p3 >> 10) & 0x3ff; ++ *d++ = (p3 >> 20) & 0x3ff; ++ ++ if (((x += 4) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ if (xrem1 != 0) { ++ const uint32_t p3 = *p; ++ ++ *d++ = p3 & 0x3ff; ++ if (xrem1 == 2) ++ *d++ = (p3 >> 10) & 0x3ff; ++ } ++ } ++} ++ ++ ++void av_rpi_sand30_to_planar_c16(uint8_t * dst_u, const unsigned int dst_stride_u, ++ uint8_t * dst_v, const unsigned int dst_stride_v, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h) ++{ ++ const unsigned int x0 = (_x / 3) * 8; // Byte offset of the word ++ const unsigned int xskip0 = _x - (x0 >> 3) * 3; ++ const unsigned int x1 = ((_x + _w) / 3) * 8; ++ const unsigned int xrem1 = _x + _w - (x1 >> 3) * 3; ++ const unsigned int mask = stride1 - 1; ++ const uint8_t * p0 = src + (x0 & mask) + y * stride1 + (x0 & ~mask) * stride2; ++ const unsigned int slice_inc = ((stride2 - 1) * stride1) >> 2; // RHS of a stripe to LHS of next in words ++ ++#if HAVE_SAND_ASM ++ if (_x == 0) { ++ ff_rpi_sand30_lines_to_planar_c16(dst_u, dst_stride_u, dst_v, dst_stride_v, ++ src, stride1, stride2, _x, y, _w, h); ++ return; ++ } ++#endif ++ ++ if (x0 == x1) { ++ // ******************* ++ // Partial single word xfer ++ return; ++ } ++ ++ for (unsigned int i = 0; i != h; ++i, dst_u += dst_stride_u, dst_v += dst_stride_v, p0 += stride1) ++ { ++ unsigned int x = x0; ++ const uint32_t * p = (const uint32_t *)p0; ++ uint16_t * du = (uint16_t *)dst_u; ++ uint16_t * dv = (uint16_t *)dst_v; ++ ++ if (xskip0 != 0) { ++ const uint32_t p3a = *p++; ++ const uint32_t p3b = *p++; ++ ++ if (xskip0 == 1) ++ { ++ *du++ = (p3a >> 20) & 0x3ff; ++ *dv++ = (p3b >> 0) & 0x3ff; ++ } ++ *du++ = (p3b >> 10) & 0x3ff; ++ *dv++ = (p3b >> 20) & 0x3ff; ++ ++ if (((x += 8) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ while (x != x1) { ++ const uint32_t p3a = *p++; ++ const uint32_t p3b = *p++; ++ ++ *du++ = p3a & 0x3ff; ++ *dv++ = (p3a >> 10) & 0x3ff; ++ *du++ = (p3a >> 20) & 0x3ff; ++ *dv++ = p3b & 0x3ff; ++ *du++ = (p3b >> 10) & 0x3ff; ++ *dv++ = (p3b >> 20) & 0x3ff; ++ ++ if (((x += 8) & mask) == 0) ++ p += slice_inc; ++ } ++ ++ if (xrem1 != 0) { ++ const uint32_t p3a = *p++; ++ const uint32_t p3b = *p++; ++ ++ *du++ = p3a & 0x3ff; ++ *dv++ = (p3a >> 10) & 0x3ff; ++ if (xrem1 == 2) ++ { ++ *du++ = (p3a >> 20) & 0x3ff; ++ *dv++ = p3b & 0x3ff; ++ } ++ } ++ } ++} ++ ++ ++// w/h in pixels ++void av_rpi_sand16_to_sand8(uint8_t * dst, const unsigned int dst_stride1, const unsigned int dst_stride2, ++ const uint8_t * src, const unsigned int src_stride1, const unsigned int src_stride2, ++ unsigned int w, unsigned int h, const unsigned int shr) ++{ ++ const unsigned int n = dst_stride1 / 2; ++ unsigned int j; ++ ++ // This is true for our current layouts ++ av_assert0(dst_stride1 == src_stride1); ++ ++ // As we have the same stride1 for src & dest and src is wider than dest ++ // then if we loop on src we can always write contiguously to dest ++ // We make no effort to copy an exact width - round up to nearest src stripe ++ // as we will always have storage in dest for that ++ ++#if ARCH_ARM && HAVE_NEON ++ if (shr == 3 && src_stride1 == 128) { ++ for (j = 0; j + n < w; j += dst_stride1) { ++ uint8_t * d = dst + j * dst_stride2; ++ const uint8_t * s1 = src + j * 2 * src_stride2; ++ const uint8_t * s2 = s1 + src_stride1 * src_stride2; ++ ++ ff_rpi_sand128b_stripe_to_8_10(d, s1, s2, h); ++ } ++ } ++ else ++#endif ++ { ++ for (j = 0; j + n < w; j += dst_stride1) { ++ uint8_t * d = dst + j * dst_stride2; ++ const uint8_t * s1 = src + j * 2 * src_stride2; ++ const uint8_t * s2 = s1 + src_stride1 * src_stride2; ++ ++ for (unsigned int i = 0; i != h; ++i, s1 += src_stride1, s2 += src_stride1, d += dst_stride1) { ++ cpy16_to_8(d, s1, n, shr); ++ cpy16_to_8(d + n, s2, n, shr); ++ } ++ } ++ } ++ ++ // Fix up a trailing dest half stripe ++ if (j < w) { ++ uint8_t * d = dst + j * dst_stride2; ++ const uint8_t * s1 = src + j * 2 * src_stride2; ++ ++ for (unsigned int i = 0; i != h; ++i, s1 += src_stride1, d += dst_stride1) { ++ cpy16_to_8(d, s1, n, shr); ++ } ++ } ++} ++ ++int av_rpi_sand_to_planar_frame(AVFrame * const dst, const AVFrame * const src) ++{ ++ const int w = av_frame_cropped_width(src); ++ const int h = av_frame_cropped_height(src); ++ const int x = src->crop_left; ++ const int y = src->crop_top; ++ ++ // We will crop as part of the conversion ++ dst->crop_top = 0; ++ dst->crop_left = 0; ++ dst->crop_bottom = 0; ++ dst->crop_right = 0; ++ ++ switch (src->format){ ++ case AV_PIX_FMT_SAND128: ++ case AV_PIX_FMT_RPI4_8: ++ switch (dst->format){ ++ case AV_PIX_FMT_YUV420P: ++ av_rpi_sand_to_planar_y8(dst->data[0], dst->linesize[0], ++ src->data[0], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x, y, w, h); ++ av_rpi_sand_to_planar_c8(dst->data[1], dst->linesize[1], ++ dst->data[2], dst->linesize[2], ++ src->data[1], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x/2, y/2, w/2, h/2); ++ break; ++ default: ++ return -1; ++ } ++ break; ++ case AV_PIX_FMT_SAND64_10: ++ switch (dst->format){ ++ case AV_PIX_FMT_YUV420P10: ++ av_rpi_sand_to_planar_y16(dst->data[0], dst->linesize[0], ++ src->data[0], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x*2, y, w*2, h); ++ av_rpi_sand_to_planar_c16(dst->data[1], dst->linesize[1], ++ dst->data[2], dst->linesize[2], ++ src->data[1], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x, y/2, w, h/2); ++ break; ++ default: ++ return -1; ++ } ++ break; ++ case AV_PIX_FMT_RPI4_10: ++ switch (dst->format){ ++ case AV_PIX_FMT_YUV420P10: ++ av_rpi_sand30_to_planar_y16(dst->data[0], dst->linesize[0], ++ src->data[0], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x, y, w, h); ++ av_rpi_sand30_to_planar_c16(dst->data[1], dst->linesize[1], ++ dst->data[2], dst->linesize[2], ++ src->data[1], ++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src), ++ x/2, y/2, w/2, h/2); ++ break; ++ default: ++ return -1; ++ } ++ break; ++ default: ++ return -1; ++ } ++ ++ return av_frame_copy_props(dst, src); ++} +diff --git a/libavutil/rpi_sand_fns.h b/libavutil/rpi_sand_fns.h +new file mode 100644 +index 0000000000..634b55e800 +--- /dev/null ++++ b/libavutil/rpi_sand_fns.h +@@ -0,0 +1,183 @@ ++/* ++Copyright (c) 2018 Raspberry Pi (Trading) Ltd. ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ * Neither the name of the copyright holder nor the ++ names of its contributors may be used to endorse or promote products ++ derived from this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++Authors: John Cox ++*/ ++ ++#ifndef AVUTIL_RPI_SAND_FNS ++#define AVUTIL_RPI_SAND_FNS ++ ++#include "libavutil/frame.h" ++ ++// For all these fns _x & _w are measured as coord * PW ++// For the C fns coords are in chroma pels (so luma / 2) ++// Strides are in bytes ++ ++void av_rpi_sand_to_planar_y8(uint8_t * dst, const unsigned int dst_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++void av_rpi_sand_to_planar_y16(uint8_t * dst, const unsigned int dst_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++void av_rpi_sand_to_planar_c8(uint8_t * dst_u, const unsigned int dst_stride_u, ++ uint8_t * dst_v, const unsigned int dst_stride_v, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++void av_rpi_sand_to_planar_c16(uint8_t * dst_u, const unsigned int dst_stride_u, ++ uint8_t * dst_v, const unsigned int dst_stride_v, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++void av_rpi_planar_to_sand_c8(uint8_t * dst_c, ++ unsigned int stride1, unsigned int stride2, ++ const uint8_t * src_u, const unsigned int src_stride_u, ++ const uint8_t * src_v, const unsigned int src_stride_v, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++void av_rpi_planar_to_sand_c16(uint8_t * dst_c, ++ unsigned int stride1, unsigned int stride2, ++ const uint8_t * src_u, const unsigned int src_stride_u, ++ const uint8_t * src_v, const unsigned int src_stride_v, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++void av_rpi_sand30_to_planar_y16(uint8_t * dst, const unsigned int dst_stride, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++void av_rpi_sand30_to_planar_c16(uint8_t * dst_u, const unsigned int dst_stride_u, ++ uint8_t * dst_v, const unsigned int dst_stride_v, ++ const uint8_t * src, ++ unsigned int stride1, unsigned int stride2, ++ unsigned int _x, unsigned int y, ++ unsigned int _w, unsigned int h); ++ ++ ++// w/h in pixels ++void av_rpi_sand16_to_sand8(uint8_t * dst, const unsigned int dst_stride1, const unsigned int dst_stride2, ++ const uint8_t * src, const unsigned int src_stride1, const unsigned int src_stride2, ++ unsigned int w, unsigned int h, const unsigned int shr); ++ ++ ++// dst must contain required pixel format & allocated data buffers ++// Cropping on the src buffer will be honoured and dst crop will be set to zero ++int av_rpi_sand_to_planar_frame(AVFrame * const dst, const AVFrame * const src); ++ ++ ++static inline unsigned int av_rpi_sand_frame_stride1(const AVFrame * const frame) ++{ ++#ifdef RPI_ZC_SAND128_ONLY ++ // If we are sure we only only support 128 byte sand formats replace the ++ // var with a constant which should allow for better optimisation ++ return 128; ++#else ++ return frame->linesize[0]; ++#endif ++} ++ ++static inline unsigned int av_rpi_sand_frame_stride2(const AVFrame * const frame) ++{ ++ return frame->linesize[3]; ++} ++ ++ ++static inline int av_rpi_is_sand_format(const int format) ++{ ++ return (format >= AV_PIX_FMT_SAND128 && format <= AV_PIX_FMT_RPI4_10); ++} ++ ++static inline int av_rpi_is_sand_frame(const AVFrame * const frame) ++{ ++ return av_rpi_is_sand_format(frame->format); ++} ++ ++static inline int av_rpi_is_sand8_frame(const AVFrame * const frame) ++{ ++ return (frame->format == AV_PIX_FMT_SAND128 || frame->format == AV_PIX_FMT_RPI4_8); ++} ++ ++static inline int av_rpi_is_sand16_frame(const AVFrame * const frame) ++{ ++ return (frame->format >= AV_PIX_FMT_SAND64_10 && frame->format <= AV_PIX_FMT_SAND64_16); ++} ++ ++static inline int av_rpi_is_sand30_frame(const AVFrame * const frame) ++{ ++ return (frame->format == AV_PIX_FMT_RPI4_10); ++} ++ ++static inline int av_rpi_sand_frame_xshl(const AVFrame * const frame) ++{ ++ return av_rpi_is_sand8_frame(frame) ? 0 : 1; ++} ++ ++// If x is measured in bytes (not pixels) then this works for sand64_16 as ++// well as sand128 - but in the general case we work that out ++ ++static inline unsigned int av_rpi_sand_frame_off_y(const AVFrame * const frame, const unsigned int x_y, const unsigned int y) ++{ ++ const unsigned int stride1 = av_rpi_sand_frame_stride1(frame); ++ const unsigned int stride2 = av_rpi_sand_frame_stride2(frame); ++ const unsigned int x = x_y << av_rpi_sand_frame_xshl(frame); ++ const unsigned int x1 = x & (stride1 - 1); ++ const unsigned int x2 = x ^ x1; ++ ++ return x1 + stride1 * y + stride2 * x2; ++} ++ ++static inline unsigned int av_rpi_sand_frame_off_c(const AVFrame * const frame, const unsigned int x_c, const unsigned int y_c) ++{ ++ const unsigned int stride1 = av_rpi_sand_frame_stride1(frame); ++ const unsigned int stride2 = av_rpi_sand_frame_stride2(frame); ++ const unsigned int x = x_c << (av_rpi_sand_frame_xshl(frame) + 1); ++ const unsigned int x1 = x & (stride1 - 1); ++ const unsigned int x2 = x ^ x1; ++ ++ return x1 + stride1 * y_c + stride2 * x2; ++} ++ ++static inline uint8_t * av_rpi_sand_frame_pos_y(const AVFrame * const frame, const unsigned int x, const unsigned int y) ++{ ++ return frame->data[0] + av_rpi_sand_frame_off_y(frame, x, y); ++} ++ ++static inline uint8_t * av_rpi_sand_frame_pos_c(const AVFrame * const frame, const unsigned int x, const unsigned int y) ++{ ++ return frame->data[1] + av_rpi_sand_frame_off_c(frame, x, y); ++} ++ ++#endif ++ +diff --git a/pi-util/BUILD.txt b/pi-util/BUILD.txt +new file mode 100644 +index 0000000000..7f16dff6a2 +--- /dev/null ++++ b/pi-util/BUILD.txt +@@ -0,0 +1,29 @@ ++Building Pi FFmpeg ++================== ++ ++Configuration: ++============= ++ ++These instructions work for cross compiles from Ubuntu 16.04 & Ubuntu ++18.04. I would expect most other linux environments to work but I haven't ++tried them. ++ ++pi-util/conf_pi2.sh ++ ++contains suitable options to build the code for Pi2/3. It expects to find ++git clones of ++ ++https://github.com/raspberrypi/tools ++https://github.com/raspberrypi/firmware ++ ++in the parent of the FFmpeg directory. I recommend using --depth 1 to avoid a ++lot of history you don't want. ++ ++If you have a copy of qasm.py in ../local/bin then the .qasm sources will be ++rebuilt. Otherwise the prebuilt .c & .h files will be used. ++Likewise ../local/bin/vasmvidcore_std will enable VPU code rebuild ++ ++pi-util/conf_p1.sh should configure for Pi1. Beware that as of this time ++H265 QPU acceleration is broken on Pi1 and so it is disabled. ++ ++ +diff --git a/pi-util/NOTES.txt b/pi-util/NOTES.txt +new file mode 100644 +index 0000000000..fcce72226a +--- /dev/null ++++ b/pi-util/NOTES.txt +@@ -0,0 +1,69 @@ ++Notes on the hevc_rpi decoder & associated support code ++------------------------------------------------------- ++ ++There are 3 main parts to the existing code: ++ ++1) The decoder - this is all in libavcodec as rpi_hevc*. ++ ++2) A few filters to deal with Sand frames and a small patch to ++automatically select the sand->i420 converter when required. ++ ++3) A kludge in ffmpeg.c to display the decoded video. This could & should ++be converted into a proper ffmpeg display module. ++ ++ ++Decoder ++------- ++ ++The decoder is a modified version of the existing ffmpeg hevc decoder. ++Generally it is ~100% faster than the existing ffmpeg hevc s/w decoder. ++More complex bitstreams can be up to ~200% faster but particularly easy ++streams can cut its advantage down to ~50%. This means that a Pi3+ can ++display nearly all 8-bit 1080p30 streams and with some overclocking it can ++display most lower bitrate 10-bit 1080p30 streams - this latter case is ++not helped by the requirement to downsample to 8-bit before display on a ++Pi. ++ ++It has had co-processor offload added for inter-pred and large block ++residual transform. Various parts have had optimized ARM NEON assembler ++added and the existing ARM asm sections have been profiled and ++re-optimized for A53. The main C code has been substantially reworked at ++its lower levels in an attempt to optimize it and minimize memory ++bandwidth. To some extent code paths that deal with frame types that it ++doesn't support have been pruned. ++ ++It outputs frames in Broadcom Sand format. This is a somewhat annoying ++layout that doesn't fit into ffmpegs standard frame descriptions. It has ++vertical stripes of 128 horizontal pixels (64 in 10 bit forms) with Y for ++the stripe followed by interleaved U & V, that is then followed by the Y ++for the next stripe, etc. The final stripe is always padded to ++stripe-width. This is used in an attempt to help with cache locality and ++cut down on the number of dram bank switches. It is annoying to use for ++inter-pred with conventional processing but the way the Pi QPU (which is ++used for inter-pred) works means that it has negligible downsides here and ++the improved memory performance exceeds the overhead of the increased ++complexity in the rest of the code. ++ ++Frames must be allocated out of GPU memory (as otherwise they can't be ++accessed by the co-processors). Utility functions (in rpi_zc.c) have been ++written to make this easier. As the frames are already in GPU memory they ++can be displayed by the Pi h/w without any further copying. ++ ++ ++Known non-features ++------------------ ++ ++Frame allocation should probably be done in some other way in order to fit ++into the standard framework better. ++ ++Sand frames are currently declared as software frames, there is an ++argument that they should be hardware frames but they aren't really. ++ ++There must be a better way of auto-selecting the hevc_rpi decoder over the ++normal s/w hevc decoder, but I became confused by the existing h/w ++acceleration framework and what I wanted to do didn't seem to fit in ++neatly. ++ ++Display should be a proper device rather than a kludge in ffmpeg.c ++ ++ +diff --git a/pi-util/conf_arm64_native.sh b/pi-util/conf_arm64_native.sh +new file mode 100644 +index 0000000000..9e3bbfa190 +--- /dev/null ++++ b/pi-util/conf_arm64_native.sh +@@ -0,0 +1,45 @@ ++echo "Configure for ARM64 native build" ++ ++#RPI_KEEPS="-save-temps=obj" ++ ++SHARED_LIBS="--enable-shared" ++if [ "$1" == "--noshared" ]; then ++ SHARED_LIBS="--disable-shared" ++ echo Static libs ++ OUT=out/arm64-static-rel ++else ++ echo Shared libs ++ OUT=out/arm64-shared-rel ++fi ++ ++mkdir -p $OUT ++cd $OUT ++ ++A=aarch64-linux-gnu ++USR_PREFIX=`pwd`/install ++LIB_PREFIX=$USR_PREFIX/lib/$A ++INC_PREFIX=$USR_PREFIX/include/$A ++ ++../../configure \ ++ --prefix=$USR_PREFIX\ ++ --libdir=$LIB_PREFIX\ ++ --incdir=$INC_PREFIX\ ++ --disable-stripping\ ++ --disable-thumb\ ++ --disable-mmal\ ++ --enable-sand\ ++ --enable-v4l2-request\ ++ --enable-libdrm\ ++ --enable-epoxy\ ++ --enable-libudev\ ++ --enable-vout-drm\ ++ --enable-vout-egl\ ++ $SHARED_LIBS\ ++ --extra-cflags="-ggdb" ++ ++# --enable-decoder=hevc_rpi\ ++# --enable-extra-warnings\ ++# --arch=armv71\ ++ ++# gcc option for getting asm listing ++# -Wa,-ahls +diff --git a/pi-util/conf_h265.2016.csv b/pi-util/conf_h265.2016.csv +new file mode 100644 +index 0000000000..4efd5d1c67 +--- /dev/null ++++ b/pi-util/conf_h265.2016.csv +@@ -0,0 +1,195 @@ ++1,HEVC_v1/AMP_A_Samsung_7,AMP_A_Samsung_7.bin,AMP_A_Samsung_7.md5,8 ++1,HEVC_v1/AMP_B_Samsung_7,AMP_B_Samsung_7.bin,AMP_B_Samsung_7.md5,8 ++1,HEVC_v1/AMP_D_Hisilicon_3,AMP_D_Hisilicon.bit,AMP_D_Hisilicon_3.yuv.md5,8 ++1,HEVC_v1/AMP_E_Hisilicon_3,AMP_E_Hisilicon.bit,AMP_E_Hisilicon_3.yuv.md5,8 ++1,HEVC_v1/AMP_F_Hisilicon_3,AMP_F_Hisilicon_3.bit,AMP_F_Hisilicon_3.yuv.md5,8 ++1,HEVC_v1/AMVP_A_MTK_4,AMVP_A_MTK_4.bit,AMVP_A_MTK_4.md5,8 ++1,HEVC_v1/AMVP_B_MTK_4,AMVP_B_MTK_4.bit,AMVP_B_MTK_4.md5,8 ++1,HEVC_v1/AMVP_C_Samsung_7,AMVP_C_Samsung_7.bin,AMVP_C_Samsung_7.md5,8 ++1,HEVC_v1/BUMPING_A_ericsson_1,BUMPING_A_ericsson_1.bit,BUMPING_A_ericsson_1.md5,8 ++1,HEVC_v1/CAINIT_A_SHARP_4,CAINIT_A_SHARP_4.bit,CAINIT_A_SHARP_4.md5,8 ++1,HEVC_v1/CAINIT_B_SHARP_4,CAINIT_B_SHARP_4.bit,CAINIT_B_SHARP_4.md5,8 ++1,HEVC_v1/CAINIT_C_SHARP_3,CAINIT_C_SHARP_3.bit,CAINIT_C_SHARP_3.md5,8 ++1,HEVC_v1/CAINIT_D_SHARP_3,CAINIT_D_SHARP_3.bit,CAINIT_D_SHARP_3.md5,8 ++1,HEVC_v1/CAINIT_E_SHARP_3,CAINIT_E_SHARP_3.bit,CAINIT_E_SHARP_3.md5,8 ++1,HEVC_v1/CAINIT_F_SHARP_3,CAINIT_F_SHARP_3.bit,CAINIT_F_SHARP_3.md5,8 ++1,HEVC_v1/CAINIT_G_SHARP_3,CAINIT_G_SHARP_3.bit,CAINIT_G_SHARP_3.md5,8 ++1,HEVC_v1/CAINIT_H_SHARP_3,CAINIT_H_SHARP_3.bit,CAINIT_H_SHARP_3.md5,8 ++1,HEVC_v1/CIP_A_Panasonic_3,CIP_A_Panasonic_3.bit,CIP_A_Panasonic_3_yuv.md5,8 ++1,HEVC_v1/cip_B_NEC_3,cip_B_NEC_3.bit,cip_B_NEC_3.md5,8 ++1,HEVC_v1/CIP_C_Panasonic_2,CIP_C_Panasonic_2.bit,CIP_C_Panasonic_2_yuv.md5,8 ++1,HEVC_v1/CONFWIN_A_Sony_1,CONFWIN_A_Sony_1.bit,CONFWIN_A_Sony_1.md5,8 ++1,HEVC_v1/DBLK_A_MAIN10_VIXS_4,DBLK_A_MAIN10_VIXS_4.bit,DBLK_A_MAIN10_VIXS_4.md5,10 ++1,HEVC_v1/DBLK_A_SONY_3,DBLK_A_SONY_3.bit,DBLK_A_SONY_3.bit.yuv.md5,8 ++1,HEVC_v1/DBLK_B_SONY_3,DBLK_B_SONY_3.bit,DBLK_B_SONY_3.bit.yuv.md5,8 ++1,HEVC_v1/DBLK_C_SONY_3,DBLK_C_SONY_3.bit,DBLK_C_SONY_3.bit.yuv.md5,8 ++1,HEVC_v1/DBLK_D_VIXS_2,DBLK_D_VIXS_2.bit,DBLK_D_VIXS_2_yuv.md5,8 ++1,HEVC_v1/DBLK_E_VIXS_2,DBLK_E_VIXS_2.bit,DBLK_E_VIXS_2_yuv.md5,8 ++1,HEVC_v1/DBLK_F_VIXS_2,DBLK_F_VIXS_2.bit,DBLK_F_VIXS_2_yuv.md5,8 ++1,HEVC_v1/DBLK_G_VIXS_2,DBLK_G_VIXS_2.bit,DBLK_G_VIXS_2_yuv.md5,8 ++1,HEVC_v1/DELTAQP_A_BRCM_4,DELTAQP_A_BRCM_4.bit,DELTAQP_A_BRCM_4_yuv.md5,8 ++1,HEVC_v1/DELTAQP_B_SONY_3,DELTAQP_B_SONY_3.bit,DELTAQP_B_SONY_3.bit.yuv.md5,8 ++1,HEVC_v1/DELTAQP_C_SONY_3,DELTAQP_C_SONY_3.bit,DELTAQP_C_SONY_3.bit.yuv.md5,8 ++1,HEVC_v1/DSLICE_A_HHI_5,DSLICE_A_HHI_5.bin,DSLICE_A_HHI_5.md5,8 ++1,HEVC_v1/DSLICE_B_HHI_5,DSLICE_B_HHI_5.bin,DSLICE_B_HHI_5.md5,8 ++1,HEVC_v1/DSLICE_C_HHI_5,DSLICE_C_HHI_5.bin,DSLICE_C_HHI_5.md5,8 ++1,HEVC_v1/ENTP_A_QUALCOMM_1,ENTP_A_Qualcomm_1.bit,ENTP_A_Qualcomm_1.md5,8 ++1,HEVC_v1/ENTP_B_Qualcomm_1,ENTP_B_Qualcomm_1.bit,ENTP_B_Qualcomm_1.md5,8 ++1,HEVC_v1/ENTP_C_Qualcomm_1,ENTP_C_Qualcomm_1.bit,ENTP_C_Qualcomm_1.md5,8 ++1,HEVC_v1/EXT_A_ericsson_4,EXT_A_ericsson_4.bit,EXT_A_ericsson_4.md5,8 ++1,HEVC_v1/FILLER_A_Sony_1,FILLER_A_Sony_1.bit,FILLER_A_Sony_1.md5,8 ++1,HEVC_v1/HRD_A_Fujitsu_3,HRD_A_Fujitsu_3.bin,HRD_A_Fujitsu_3.md5,8 ++1,HEVC_v1/INITQP_A_Sony_1,INITQP_A_Sony_1.bit,INITQP_A_Sony_1.md5,8 ++1,HEVC_v1/INITQP_B_Main10_Sony_1,INITQP_B_Main10_Sony_1.bit,INITQP_B_Main10_Sony_1.md5,10 ++1,HEVC_v1/ipcm_A_NEC_3,ipcm_A_NEC_3.bit,ipcm_A_NEC_3.md5,8 ++1,HEVC_v1/ipcm_B_NEC_3,ipcm_B_NEC_3.bit,ipcm_B_NEC_3.md5,8 ++1,HEVC_v1/ipcm_C_NEC_3,ipcm_C_NEC_3.bit,ipcm_C_NEC_3.md5,8 ++1,HEVC_v1/ipcm_D_NEC_3,ipcm_D_NEC_3.bit,ipcm_D_NEC_3.md5,8 ++1,HEVC_v1/ipcm_E_NEC_2,ipcm_E_NEC_2.bit,ipcm_E_NEC_2.md5,8 ++1,HEVC_v1/IPRED_A_docomo_2,IPRED_A_docomo_2.bit,IPRED_A_docomo_2.md5,8 ++1,HEVC_v1/IPRED_B_Nokia_3,IPRED_B_Nokia_3.bit,IPRED_B_Nokia_3_yuv.md5,8 ++1,HEVC_v1/IPRED_C_Mitsubishi_3,IPRED_C_Mitsubishi_3.bit,IPRED_C_Mitsubishi_3_yuv.md5,8 ++1,HEVC_v1/LS_A_Orange_2,LS_A_Orange_2.bit,LS_A_Orange_2_yuv.md5,8 ++1,HEVC_v1/LS_B_Orange_4,LS_B_Orange_4.bit,LS_B_Orange_4_yuv.md5,8 ++1,HEVC_v1/LTRPSPS_A_Qualcomm_1,LTRPSPS_A_Qualcomm_1.bit,LTRPSPS_A_Qualcomm_1.md5,8 ++1,HEVC_v1/MAXBINS_A_TI_5,MAXBINS_A_TI_5.bit,MAXBINS_A_TI_5_yuv.md5,8 ++1,HEVC_v1/MAXBINS_B_TI_5,MAXBINS_B_TI_5.bit,MAXBINS_B_TI_5_yuv.md5,8 ++1,HEVC_v1/MAXBINS_C_TI_5,MAXBINS_C_TI_5.bit,MAXBINS_C_TI_5_yuv.md5,8 ++1,HEVC_v1/MERGE_A_TI_3,MERGE_A_TI_3.bit,MERGE_A_TI_3.md5,8 ++1,HEVC_v1/MERGE_B_TI_3,MERGE_B_TI_3.bit,MERGE_B_TI_3.md5,8 ++1,HEVC_v1/MERGE_C_TI_3,MERGE_C_TI_3.bit,MERGE_C_TI_3.md5,8 ++1,HEVC_v1/MERGE_D_TI_3,MERGE_D_TI_3.bit,MERGE_D_TI_3.md5,8 ++1,HEVC_v1/MERGE_E_TI_3,MERGE_E_TI_3.bit,MERGE_E_TI_3.md5,8 ++1,HEVC_v1/MERGE_F_MTK_4,MERGE_F_MTK_4.bit,MERGE_F_MTK_4.md5,8 ++1,HEVC_v1/MERGE_G_HHI_4,MERGE_G_HHI_4.bit,MERGE_G_HHI_4.md5,8 ++1,HEVC_v1/MVCLIP_A_qualcomm_3,MVCLIP_A_qualcomm_3.bit,MVCLIP_A_qualcomm_3.yuv.md5,8 ++1,HEVC_v1/MVDL1ZERO_A_docomo_4,MVDL1ZERO_A_docomo_4.bit,MVDL1ZERO_A_docomo_4.md5,8 ++1,HEVC_v1/MVEDGE_A_qualcomm_3,MVEDGE_A_qualcomm_3.bit,MVEDGE_A_qualcomm_3.yuv.md5,8 ++1,HEVC_v1/NoOutPrior_A_Qualcomm_1,NoOutPrior_A_Qualcomm_1.bit,NoOutPrior_A_Qualcomm_1.md5,8 ++1,HEVC_v1/NoOutPrior_B_Qualcomm_1,NoOutPrior_B_Qualcomm_1.bit,NoOutPrior_B_Qualcomm_1.md5,8 ++1,HEVC_v1/NUT_A_ericsson_5,NUT_A_ericsson_5.bit,NUT_A_ericsson_5.md5,8 ++1,HEVC_v1/OPFLAG_A_Qualcomm_1,OPFLAG_A_Qualcomm_1.bit,OPFLAG_A_Qualcomm_1.md5,8 ++1,HEVC_v1/OPFLAG_B_Qualcomm_1,OPFLAG_B_Qualcomm_1.bit,OPFLAG_B_Qualcomm_1.md5,8 ++1,HEVC_v1/OPFLAG_C_Qualcomm_1,OPFLAG_C_Qualcomm_1.bit,OPFLAG_C_Qualcomm_1.md5,8 ++1,HEVC_v1/PICSIZE_A_Bossen_1,PICSIZE_A_Bossen_1.bin,PICSIZE_A_Bossen_1.md5,8 ++1,HEVC_v1/PICSIZE_B_Bossen_1,PICSIZE_B_Bossen_1.bin,PICSIZE_B_Bossen_1.md5,8 ++1,HEVC_v1/PICSIZE_C_Bossen_1,PICSIZE_C_Bossen_1.bin,PICSIZE_C_Bossen_1.md5,8 ++1,HEVC_v1/PICSIZE_D_Bossen_1,PICSIZE_D_Bossen_1.bin,PICSIZE_D_Bossen_1.md5,8 ++1,HEVC_v1/PMERGE_A_TI_3,PMERGE_A_TI_3.bit,PMERGE_A_TI_3.md5,8 ++1,HEVC_v1/PMERGE_B_TI_3,PMERGE_B_TI_3.bit,PMERGE_B_TI_3.md5,8 ++1,HEVC_v1/PMERGE_C_TI_3,PMERGE_C_TI_3.bit,PMERGE_C_TI_3.md5,8 ++1,HEVC_v1/PMERGE_D_TI_3,PMERGE_D_TI_3.bit,PMERGE_D_TI_3.md5,8 ++1,HEVC_v1/PMERGE_E_TI_3,PMERGE_E_TI_3.bit,PMERGE_E_TI_3.md5,8 ++1,HEVC_v1/POC_A_Bossen_3,POC_A_Bossen_3.bin,POC_A_Bossen_3.md5,8 ++1,HEVC_v1/PPS_A_qualcomm_7,PPS_A_qualcomm_7.bit,PPS_A_qualcomm_7.yuv.md5,8 ++1,HEVC_v1/PS_B_VIDYO_3,PS_B_VIDYO_3.bit,PS_B_VIDYO_3_yuv.md5,8 ++1,HEVC_v1/RAP_A_docomo_6,RAP_A_docomo_6.bit,RAP_A_docomo_6.md5,8 ++1,HEVC_v1/RAP_B_Bossen_2,RAP_B_Bossen_2.bit,RAP_B_Bossen_2.md5,8 ++1,HEVC_v1/RPLM_A_qualcomm_4,RPLM_A_qualcomm_4.bit,RPLM_A_qualcomm_4.yuv.md5,8 ++1,HEVC_v1/RPLM_B_qualcomm_4,RPLM_B_qualcomm_4.bit,RPLM_B_qualcomm_4.yuv.md5,8 ++1,HEVC_v1/RPS_A_docomo_5,RPS_A_docomo_5.bit,RPS_A_docomo_5.md5,8 ++1,HEVC_v1/RPS_B_qualcomm_5,RPS_B_qualcomm_5.bit,RPS_B_qualcomm_5.yuv.md5,8 ++1,HEVC_v1/RPS_C_ericsson_5,RPS_C_ericsson_5.bit,RPS_C_ericsson_5.md5,8 ++1,HEVC_v1/RPS_D_ericsson_6,RPS_D_ericsson_6.bit,RPS_D_ericsson_6.md5,8 ++1,HEVC_v1/RPS_E_qualcomm_5,RPS_E_qualcomm_5.bit,RPS_E_qualcomm_5.yuv.md5,8 ++1,HEVC_v1/RPS_F_docomo_2,RPS_F_docomo_2.bit,RPS_F_docomo_2.md5,8 ++1,HEVC_v1/RQT_A_HHI_4,RQT_A_HHI_4.bit,RQT_A_HHI_4.md5,8 ++1,HEVC_v1/RQT_B_HHI_4,RQT_B_HHI_4.bit,RQT_B_HHI_4.md5,8 ++1,HEVC_v1/RQT_C_HHI_4,RQT_C_HHI_4.bit,RQT_C_HHI_4.md5,8 ++1,HEVC_v1/RQT_D_HHI_4,RQT_D_HHI_4.bit,RQT_D_HHI_4.md5,8 ++1,HEVC_v1/RQT_E_HHI_4,RQT_E_HHI_4.bit,RQT_E_HHI_4.md5,8 ++1,HEVC_v1/RQT_F_HHI_4,RQT_F_HHI_4.bit,RQT_F_HHI_4.md5,8 ++1,HEVC_v1/RQT_G_HHI_4,RQT_G_HHI_4.bit,RQT_G_HHI_4.md5,8 ++1,HEVC_v1/SAO_A_MediaTek_4,SAO_A_MediaTek_4.bit,SAO_A_MediaTek_4.md5,8 ++1,HEVC_v1/SAO_B_MediaTek_5,SAO_B_MediaTek_5.bit,SAO_B_MediaTek_5.md5,8 ++1,HEVC_v1/SAO_C_Samsung_5,SAO_C_Samsung_5.bin,SAO_C_Samsung_5.md5,8 ++1,HEVC_v1/SAO_D_Samsung_5,SAO_D_Samsung_5.bin,SAO_D_Samsung_5.md5,8 ++1,HEVC_v1/SAO_E_Canon_4,SAO_E_Canon_4.bit,SAO_E_Canon_4.md5,8 ++1,HEVC_v1/SAO_F_Canon_3,SAO_F_Canon_3.bit,SAO_F_Canon_3.md5,8 ++1,HEVC_v1/SAO_G_Canon_3,SAO_G_Canon_3.bit,SAO_G_Canon_3.md5,8 ++1,HEVC_v1/SAO_H_Parabola_1,SAO_H_Parabola_1.bit,SAO_H_Parabola_1.md5,8 ++1,HEVC_v1/SAODBLK_A_MainConcept_4,SAODBLK_A_MainConcept_4.bin,SAODBLK_A_MainConcept_4_md5.txt,8 ++1,HEVC_v1/SAODBLK_B_MainConcept_4,SAODBLK_B_MainConcept_4.bin,SAODBLK_B_MainConcept_4_md5.txt,8 ++1,HEVC_v1/SDH_A_Orange_4,SDH_A_Orange_4.bit,SDH_A_Orange_4_yuv.md5,8 ++1,HEVC_v1/SLICES_A_Rovi_3,SLICES_A_Rovi_3.bin,SLICES_A_Rovi_3.md5,8 ++1,HEVC_v1/SLIST_A_Sony_5,SLIST_A_Sony_5.bin,SLIST_A_Sony_5_yuv.md5,8 ++1,HEVC_v1/SLIST_B_Sony_9,SLIST_B_Sony_9.bin,SLIST_B_Sony_9_yuv.md5,8 ++1,HEVC_v1/SLIST_C_Sony_4,SLIST_C_Sony_4.bin,SLIST_C_Sony_4_yuv.md5,8 ++1,HEVC_v1/SLIST_D_Sony_9,str.bin,SLIST_D_Sony_9_yuv.md5,8 ++1,HEVC_v1/SLPPLP_A_VIDYO_2,SLPPLP_A_VIDYO_2.bit,SLPPLP_A_VIDYO_2_yuv.md5,8 ++1,HEVC_v1/STRUCT_A_Samsung_7,STRUCT_A_Samsung_7.bin,STRUCT_A_Samsung_7.md5,8 ++1,HEVC_v1/STRUCT_B_Samsung_7,STRUCT_B_Samsung_7.bin,STRUCT_B_Samsung_7.md5,8 ++1,HEVC_v1/TILES_A_Cisco_2,TILES_A_Cisco_2.bin,TILES_A_Cisco_2_yuv.md5,8 ++1,HEVC_v1/TILES_B_Cisco_1,TILES_B_Cisco_1.bin,TILES_B_Cisco_1_yuv.md5,8 ++1,HEVC_v1/TMVP_A_MS_3,TMVP_A_MS_3.bit,TMVP_A_MS_3.yuv.md5,8 ++1,HEVC_v1/TSCL_A_VIDYO_5,TSCL_A_VIDYO_5.bit,TSCL_A_VIDYO_5_yuv.md5,8 ++1,HEVC_v1/TSCL_B_VIDYO_4,TSCL_B_VIDYO_4.bit,TSCL_B_VIDYO_4_yuv.md5,8 ++1,HEVC_v1/TSKIP_A_MS_3,TSKIP_A_MS_3.bit,TSKIP_A_MS_3.yuv.md5,8 ++3,HEVC_v1/TSUNEQBD_A_MAIN10_Technicolor_2,TSUNEQBD_A_MAIN10_Technicolor_2.bit,TSUNEQBD_A_MAIN10_Technicolor_2_yuv.md5, # unequal bit depth,10 ++1,HEVC_v1/TUSIZE_A_Samsung_1,TUSIZE_A_Samsung_1.bin,TUSIZE_A_Samsung_1.md5,8 ++1,HEVC_v1/VPSID_A_VIDYO_2,VPSID_A_VIDYO_2.bit,VPSID_A_VIDYO_2_yuv.md5,8 ++3,HEVC_v1/VPSSPSPPS_A_MainConcept_1,VPSSPSPPS_A_MainConcept_1.bin,VPSSPSPPS_A_MainConcept_1_md5.txt, # ???,8 ++1,HEVC_v1/WP_A_MAIN10_Toshiba_3,WP_A_MAIN10_Toshiba_3.bit,WP_A_MAIN10_Toshiba_3_yuv.md5,10 ++1,HEVC_v1/WP_A_Toshiba_3,WP_A_Toshiba_3.bit,WP_A_Toshiba_3_yuv.md5,8 ++1,HEVC_v1/WP_B_Toshiba_3,WP_B_Toshiba_3.bit,WP_B_Toshiba_3_yuv.md5,8 ++1,HEVC_v1/WP_MAIN10_B_Toshiba_3,WP_MAIN10_B_Toshiba_3.bit,WP_MAIN10_B_Toshiba_3_yuv.md5,10 ++1,HEVC_v1/WPP_A_ericsson_MAIN10_2,WPP_A_ericsson_MAIN10_2.bit,WPP_A_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_A_ericsson_MAIN_2,WPP_A_ericsson_MAIN_2.bit,WPP_A_ericsson_MAIN_2_yuv.md5,8 ++1,HEVC_v1/WPP_B_ericsson_MAIN10_2,WPP_B_ericsson_MAIN10_2.bit,WPP_B_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_B_ericsson_MAIN_2,WPP_B_ericsson_MAIN_2.bit,WPP_B_ericsson_MAIN_2_yuv.md5,8 ++1,HEVC_v1/WPP_C_ericsson_MAIN10_2,WPP_C_ericsson_MAIN10_2.bit,WPP_C_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_C_ericsson_MAIN_2,WPP_C_ericsson_MAIN_2.bit,WPP_C_ericsson_MAIN_2_yuv.md5,8 ++1,HEVC_v1/WPP_D_ericsson_MAIN10_2,WPP_D_ericsson_MAIN10_2.bit,WPP_D_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_D_ericsson_MAIN_2,WPP_D_ericsson_MAIN_2.bit,WPP_D_ericsson_MAIN_2_yuv.md5,8 ++1,HEVC_v1/WPP_E_ericsson_MAIN10_2,WPP_E_ericsson_MAIN10_2.bit,WPP_E_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_E_ericsson_MAIN_2,WPP_E_ericsson_MAIN_2.bit,WPP_E_ericsson_MAIN_2_yuv.md5,8 ++1,HEVC_v1/WPP_F_ericsson_MAIN10_2,WPP_F_ericsson_MAIN10_2.bit,WPP_F_ericsson_MAIN10_yuv.md5,10 ++1,HEVC_v1/WPP_F_ericsson_MAIN_2,WPP_F_ericsson_MAIN_2.bit,WPP_F_ericsson_MAIN_2_yuv.md5,8 ++1,RExt/ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_2,ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_2.bit,ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_yuv_2.md5,0 ++0,RExt/Bitdepth_A_RExt_Sony_1,Bitdepth_A_RExt_Sony_1.bin,md5sum.txt,8 ++0,RExt/Bitdepth_B_RExt_Sony_1,Bitdepth_B_RExt_Sony_1.bin,md5sum.txt,8 ++0,RExt/CCP_10bit_RExt_QCOM,CCP_10bit_RExt_QCOM.bin,CCP_10bit_RExt_QCOM_md5sum.txt,10 ++0,RExt/CCP_12bit_RExt_QCOM,CCP_12bit_RExt_QCOM.bin,CCP_12bit_RExt_QCOM_md5sum.txt,8 ++0,RExt/CCP_8bit_RExt_QCOM,CCP_8bit_RExt_QCOM.bin,CCP_8bit_RExt_QCOM_md5sum.txt,8 ++1,RExt/ExplicitRdpcm_A_BBC_1,ExplicitRdpcm_A_BBC_1.bit,md5sum.txt,0 ++0,RExt/ExplicitRdpcm_B_BBC_2,ExplicitRdpcm_B_BBC_1.bit,md5sum.txt,8 ++0,RExt/EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_10BIT_RExt_Sony_1,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_10BIT_RExt_Sony_1.bit,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_10BIT_RExt_Sony_1.md5,10 ++0,RExt/EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_12BIT_RExt_Sony_1,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_12BIT_RExt_Sony_1.bit,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_12BIT_RExt_Sony_1.md5,8 ++0,RExt/EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_16BIT_RExt_Sony_1,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_16BIT_RExt_Sony_1.bit,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_16BIT_RExt_Sony_1.md5,8 ++0,RExt/EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_8BIT_RExt_Sony_1,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_8BIT_RExt_Sony_1.bit,EXTPREC_HIGHTHROUGHPUT_444_16_INTRA_8BIT_RExt_Sony_1.md5,8 ++0,RExt/EXTPREC_MAIN_444_16_INTRA_10BIT_RExt_Sony_1,EXTPREC_MAIN_444_16_INTRA_10BIT_RExt_Sony_1.bit,EXTPREC_MAIN_444_16_INTRA_10BIT_RExt_Sony_1.md5,10 ++0,RExt/EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1,EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.bit,EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.md5,8 ++0,RExt/EXTPREC_MAIN_444_16_INTRA_16BIT_RExt_Sony_1,EXTPREC_MAIN_444_16_INTRA_16BIT_RExt_Sony_1.bit,EXTPREC_MAIN_444_16_INTRA_16BIT_RExt_Sony_1.md5,8 ++0,RExt/EXTPREC_MAIN_444_16_INTRA_8BIT_RExt_Sony_1,EXTPREC_MAIN_444_16_INTRA_8BIT_RExt_Sony_1.bit,EXTPREC_MAIN_444_16_INTRA_8BIT_RExt_Sony_1.md5,8 ++1,RExt/GENERAL_10b_420_RExt_Sony_1,GENERAL_10b_420_RExt_Sony_1.bit,GENERAL_10b_420_RExt_Sony_1.md5,10 ++1,RExt/GENERAL_10b_422_RExt_Sony_1,GENERAL_10b_422_RExt_Sony_1.bit,GENERAL_10b_422_RExt_Sony_1.md5,0 ++1,RExt/GENERAL_10b_444_RExt_Sony_2,GENERAL_10b_444_RExt_Sony_2.bit,GENERAL_10b_444_RExt_Sony_2.md5,0 ++1,RExt/GENERAL_12b_400_RExt_Sony_1,GENERAL_12b_400_RExt_Sony_1.bit,GENERAL_12b_400_RExt_Sony_1.md5,0 ++1,RExt/GENERAL_12b_420_RExt_Sony_1,GENERAL_12b_420_RExt_Sony_1.bit,GENERAL_12b_420_RExt_Sony_1.md5,0 ++1,RExt/GENERAL_12b_422_RExt_Sony_1,GENERAL_12b_422_RExt_Sony_1.bit,GENERAL_12b_422_RExt_Sony_1.md5,0 ++1,RExt/GENERAL_12b_444_RExt_Sony_2,GENERAL_12b_444_RExt_Sony_2.bit,GENERAL_12b_444_RExt_Sony_2.md5,0 ++0,RExt/GENERAL_16b_400_RExt_Sony_1,GENERAL_16b_400_RExt_Sony_1.bit,GENERAL_16b_400_RExt_Sony_1.md5,0 ++0,RExt/GENERAL_16b_444_highThroughput_RExt_Sony_2,GENERAL_16b_444_highThroughput_RExt_Sony_2.bit,GENERAL_16b_444_highThroughput_RExt_Sony_2.md5,8 ++0,RExt/GENERAL_16b_444_RExt_Sony_2,GENERAL_16b_444_RExt_Sony_2.bit,GENERAL_16b_444_RExt_Sony_2.md5,8 ++1,RExt/GENERAL_8b_400_RExt_Sony_1,GENERAL_8b_400_RExt_Sony_1.bit,GENERAL_8b_400_RExt_Sony_1.md5,0 ++1,RExt/GENERAL_8b_420_RExt_Sony_1,GENERAL_8b_420_RExt_Sony_1.bit,GENERAL_8b_420_RExt_Sony_1.md5,8 ++1,RExt/GENERAL_8b_444_RExt_Sony_2,GENERAL_8b_444_RExt_Sony_2.bit,GENERAL_8b_444_RExt_Sony_2.md5,0 ++1,RExt/IPCM_A_RExt_NEC_2,IPCM_A_RExt_NEC_2.bit,IPCM_A_RExt_NEC_2_yuv.md5,0 ++1,RExt/IPCM_B_RExt_NEC,IPCM_B_RExt_NEC.bit,IPCM_B_RExt_NEC_yuv.md5,0 ++1,RExt/Main_422_10_A_RExt_Sony_2,Main_422_10_A_RExt_Sony_2.bin,md5sum.txt,0 ++1,RExt/Main_422_10_B_RExt_Sony_2,Main_422_10_B_RExt_Sony_2.bin,md5sum.txt,0 ++1,RExt/PERSIST_RPARAM_A_RExt_Sony_3,PERSIST_RPARAM_A_RExt_Sony_3.bit,PERSIST_RPARAM_A_RExt_Sony_3.md5,0 ++1,RExt/QMATRIX_A_RExt_Sony_1,QMATRIX_A_RExt_Sony_1.bit,QMATRIX_A_RExt_Sony_1.md5,0 ++0,RExt/SAO_A_RExt_MediaTek_1,SAO_A_RExt_MediaTek_1.bit,SAO_A_RExt_MediaTek_1.md5, # Runs out of memory - could be fixed,8 ++0,RExt/TSCTX_10bit_I_RExt_SHARP_1,TSCTX_10bit_I_RExt_SHARP_1.bin,TSCTX_10bit_I_RExt_SHARP_1.md5,10 ++0,RExt/TSCTX_10bit_RExt_SHARP_1,TSCTX_10bit_RExt_SHARP_1.bin,TSCTX_10bit_RExt_SHARP_1.md5,10 ++0,RExt/TSCTX_12bit_I_RExt_SHARP_1,TSCTX_12bit_I_RExt_SHARP_1.bin,TSCTX_12bit_I_RExt_SHARP_1.md5,8 ++0,RExt/TSCTX_12bit_RExt_SHARP_1,TSCTX_12bit_RExt_SHARP_1.bin,TSCTX_12bit_RExt_SHARP_1.md5,8 ++0,RExt/TSCTX_8bit_I_RExt_SHARP_1,TSCTX_8bit_I_RExt_SHARP_1.bin,TSCTX_8bit_I_RExt_SHARP_1.md5,8 ++0,RExt/TSCTX_8bit_RExt_SHARP_1,TSCTX_8bit_RExt_SHARP_1.bin,TSCTX_8bit_RExt_SHARP_1.md5,8 ++0,RExt/WAVETILES_RExt_Sony_2,WAVETILES_RExt_Sony_2.bit,WAVETILES_RExt_Sony_2.md5,8 ++1,local/sao_cu16_mobile_344x280,sao_cu16_mobile_344x280.265,sao_cu16_mobile_344x280.md5,8 ++1,local/dblk_cu16_mobile_344x280,dblk_cu16_mobile_344x280.265,dblk_cu16_mobile_344x280.md5,8 ++1,local/dblksao_cu16_mobile_344x280,dblksao_cu16_mobile_344x280.265,dblksao_cu16_mobile_344x280.md5,8 ++1,local/dblk_pu32_horses_832x448,dblk_pu32_horses_832x448.265,dblk_pu32_horses_832x448.md5,8 ++1,local/intra_pred_21_laps,intra_pred_21_laps.265,intra_pred_21_laps.md5,8 +diff --git a/pi-util/conf_h265.2016_HEVC_v1.csv b/pi-util/conf_h265.2016_HEVC_v1.csv +new file mode 100644 +index 0000000000..6082641271 +--- /dev/null ++++ b/pi-util/conf_h265.2016_HEVC_v1.csv +@@ -0,0 +1,147 @@ ++1,AMP_A_Samsung_7,AMP_A_Samsung_7.bin,AMP_A_Samsung_7.md5 ++1,AMP_B_Samsung_7,AMP_B_Samsung_7.bin,AMP_B_Samsung_7.md5 ++1,AMP_D_Hisilicon_3,AMP_D_Hisilicon.bit,AMP_D_Hisilicon_3.yuv.md5 ++1,AMP_E_Hisilicon_3,AMP_E_Hisilicon.bit,AMP_E_Hisilicon_3.yuv.md5 ++1,AMP_F_Hisilicon_3,AMP_F_Hisilicon_3.bit,AMP_F_Hisilicon_3.yuv.md5 ++1,AMVP_A_MTK_4,AMVP_A_MTK_4.bit,AMVP_A_MTK_4.md5 ++1,AMVP_B_MTK_4,AMVP_B_MTK_4.bit,AMVP_B_MTK_4.md5 ++1,AMVP_C_Samsung_7,AMVP_C_Samsung_7.bin,AMVP_C_Samsung_7.md5 ++1,BUMPING_A_ericsson_1,BUMPING_A_ericsson_1.bit,BUMPING_A_ericsson_1.md5 ++1,CAINIT_A_SHARP_4,CAINIT_A_SHARP_4.bit,CAINIT_A_SHARP_4.md5 ++1,CAINIT_B_SHARP_4,CAINIT_B_SHARP_4.bit,CAINIT_B_SHARP_4.md5 ++1,CAINIT_C_SHARP_3,CAINIT_C_SHARP_3.bit,CAINIT_C_SHARP_3.md5 ++1,CAINIT_D_SHARP_3,CAINIT_D_SHARP_3.bit,CAINIT_D_SHARP_3.md5 ++1,CAINIT_E_SHARP_3,CAINIT_E_SHARP_3.bit,CAINIT_E_SHARP_3.md5 ++1,CAINIT_F_SHARP_3,CAINIT_F_SHARP_3.bit,CAINIT_F_SHARP_3.md5 ++1,CAINIT_G_SHARP_3,CAINIT_G_SHARP_3.bit,CAINIT_G_SHARP_3.md5 ++1,CAINIT_H_SHARP_3,CAINIT_H_SHARP_3.bit,CAINIT_H_SHARP_3.md5 ++1,CIP_A_Panasonic_3,CIP_A_Panasonic_3.bit,CIP_A_Panasonic_3_yuv.md5 ++1,cip_B_NEC_3,cip_B_NEC_3.bit,cip_B_NEC_3.md5 ++1,CIP_C_Panasonic_2,CIP_C_Panasonic_2.bit,CIP_C_Panasonic_2_yuv.md5 ++1,CONFWIN_A_Sony_1,CONFWIN_A_Sony_1.bit,CONFWIN_A_Sony_1.md5 ++1,DBLK_A_MAIN10_VIXS_4,DBLK_A_MAIN10_VIXS_4.bit,DBLK_A_MAIN10_VIXS_4.md5 ++1,DBLK_A_SONY_3,DBLK_A_SONY_3.bit,DBLK_A_SONY_3.bit.yuv.md5 ++1,DBLK_B_SONY_3,DBLK_B_SONY_3.bit,DBLK_B_SONY_3.bit.yuv.md5 ++1,DBLK_C_SONY_3,DBLK_C_SONY_3.bit,DBLK_C_SONY_3.bit.yuv.md5 ++1,DBLK_D_VIXS_2,DBLK_D_VIXS_2.bit,DBLK_D_VIXS_2_yuv.md5 ++1,DBLK_E_VIXS_2,DBLK_E_VIXS_2.bit,DBLK_E_VIXS_2_yuv.md5 ++1,DBLK_F_VIXS_2,DBLK_F_VIXS_2.bit,DBLK_F_VIXS_2_yuv.md5 ++1,DBLK_G_VIXS_2,DBLK_G_VIXS_2.bit,DBLK_G_VIXS_2_yuv.md5 ++1,DELTAQP_A_BRCM_4,DELTAQP_A_BRCM_4.bit,DELTAQP_A_BRCM_4_yuv.md5 ++1,DELTAQP_B_SONY_3,DELTAQP_B_SONY_3.bit,DELTAQP_B_SONY_3.bit.yuv.md5 ++1,DELTAQP_C_SONY_3,DELTAQP_C_SONY_3.bit,DELTAQP_C_SONY_3.bit.yuv.md5 ++1,DSLICE_A_HHI_5,DSLICE_A_HHI_5.bin,DSLICE_A_HHI_5.md5 ++1,DSLICE_B_HHI_5,DSLICE_B_HHI_5.bin,DSLICE_B_HHI_5.md5 ++1,DSLICE_C_HHI_5,DSLICE_C_HHI_5.bin,DSLICE_C_HHI_5.md5 ++1,ENTP_A_QUALCOMM_1,ENTP_A_Qualcomm_1.bit,ENTP_A_Qualcomm_1.md5 ++1,ENTP_B_Qualcomm_1,ENTP_B_Qualcomm_1.bit,ENTP_B_Qualcomm_1.md5 ++1,ENTP_C_Qualcomm_1,ENTP_C_Qualcomm_1.bit,ENTP_C_Qualcomm_1.md5 ++1,EXT_A_ericsson_4,EXT_A_ericsson_4.bit,EXT_A_ericsson_4.md5 ++1,FILLER_A_Sony_1,FILLER_A_Sony_1.bit,FILLER_A_Sony_1.md5 ++1,HRD_A_Fujitsu_3,HRD_A_Fujitsu_3.bin,HRD_A_Fujitsu_3.md5 ++1,INITQP_A_Sony_1,INITQP_A_Sony_1.bit,INITQP_A_Sony_1.md5 ++1,INITQP_B_Main10_Sony_1,INITQP_B_Main10_Sony_1.bit,INITQP_B_Main10_Sony_1.md5 ++1,ipcm_A_NEC_3,ipcm_A_NEC_3.bit,ipcm_A_NEC_3.md5 ++1,ipcm_B_NEC_3,ipcm_B_NEC_3.bit,ipcm_B_NEC_3.md5 ++1,ipcm_C_NEC_3,ipcm_C_NEC_3.bit,ipcm_C_NEC_3.md5 ++1,ipcm_D_NEC_3,ipcm_D_NEC_3.bit,ipcm_D_NEC_3.md5 ++1,ipcm_E_NEC_2,ipcm_E_NEC_2.bit,ipcm_E_NEC_2.md5 ++1,IPRED_A_docomo_2,IPRED_A_docomo_2.bit,IPRED_A_docomo_2.md5 ++1,IPRED_B_Nokia_3,IPRED_B_Nokia_3.bit,IPRED_B_Nokia_3_yuv.md5 ++1,IPRED_C_Mitsubishi_3,IPRED_C_Mitsubishi_3.bit,IPRED_C_Mitsubishi_3_yuv.md5 ++1,LS_A_Orange_2,LS_A_Orange_2.bit,LS_A_Orange_2_yuv.md5 ++1,LS_B_Orange_4,LS_B_Orange_4.bit,LS_B_Orange_4_yuv.md5 ++1,LTRPSPS_A_Qualcomm_1,LTRPSPS_A_Qualcomm_1.bit,LTRPSPS_A_Qualcomm_1.md5 ++1,MAXBINS_A_TI_5,MAXBINS_A_TI_5.bit,MAXBINS_A_TI_5_yuv.md5 ++1,MAXBINS_B_TI_5,MAXBINS_B_TI_5.bit,MAXBINS_B_TI_5_yuv.md5 ++1,MAXBINS_C_TI_5,MAXBINS_C_TI_5.bit,MAXBINS_C_TI_5_yuv.md5 ++1,MERGE_A_TI_3,MERGE_A_TI_3.bit,MERGE_A_TI_3.md5 ++1,MERGE_B_TI_3,MERGE_B_TI_3.bit,MERGE_B_TI_3.md5 ++1,MERGE_C_TI_3,MERGE_C_TI_3.bit,MERGE_C_TI_3.md5 ++1,MERGE_D_TI_3,MERGE_D_TI_3.bit,MERGE_D_TI_3.md5 ++1,MERGE_E_TI_3,MERGE_E_TI_3.bit,MERGE_E_TI_3.md5 ++1,MERGE_F_MTK_4,MERGE_F_MTK_4.bit,MERGE_F_MTK_4.md5 ++1,MERGE_G_HHI_4,MERGE_G_HHI_4.bit,MERGE_G_HHI_4.md5 ++1,MVCLIP_A_qualcomm_3,MVCLIP_A_qualcomm_3.bit,MVCLIP_A_qualcomm_3.yuv.md5 ++1,MVDL1ZERO_A_docomo_4,MVDL1ZERO_A_docomo_4.bit,MVDL1ZERO_A_docomo_4.md5 ++1,MVEDGE_A_qualcomm_3,MVEDGE_A_qualcomm_3.bit,MVEDGE_A_qualcomm_3.yuv.md5 ++1,NoOutPrior_A_Qualcomm_1,NoOutPrior_A_Qualcomm_1.bit,NoOutPrior_A_Qualcomm_1.md5 ++1,NoOutPrior_B_Qualcomm_1,NoOutPrior_B_Qualcomm_1.bit,NoOutPrior_B_Qualcomm_1.md5 ++1,NUT_A_ericsson_5,NUT_A_ericsson_5.bit,NUT_A_ericsson_5.md5 ++1,OPFLAG_A_Qualcomm_1,OPFLAG_A_Qualcomm_1.bit,OPFLAG_A_Qualcomm_1.md5 ++1,OPFLAG_B_Qualcomm_1,OPFLAG_B_Qualcomm_1.bit,OPFLAG_B_Qualcomm_1.md5 ++1,OPFLAG_C_Qualcomm_1,OPFLAG_C_Qualcomm_1.bit,OPFLAG_C_Qualcomm_1.md5 ++1,PICSIZE_A_Bossen_1,PICSIZE_A_Bossen_1.bin,PICSIZE_A_Bossen_1.md5 ++1,PICSIZE_B_Bossen_1,PICSIZE_B_Bossen_1.bin,PICSIZE_B_Bossen_1.md5 ++1,PICSIZE_C_Bossen_1,PICSIZE_C_Bossen_1.bin,PICSIZE_C_Bossen_1.md5 ++1,PICSIZE_D_Bossen_1,PICSIZE_D_Bossen_1.bin,PICSIZE_D_Bossen_1.md5 ++1,PMERGE_A_TI_3,PMERGE_A_TI_3.bit,PMERGE_A_TI_3.md5 ++1,PMERGE_B_TI_3,PMERGE_B_TI_3.bit,PMERGE_B_TI_3.md5 ++1,PMERGE_C_TI_3,PMERGE_C_TI_3.bit,PMERGE_C_TI_3.md5 ++1,PMERGE_D_TI_3,PMERGE_D_TI_3.bit,PMERGE_D_TI_3.md5 ++1,PMERGE_E_TI_3,PMERGE_E_TI_3.bit,PMERGE_E_TI_3.md5 ++1,POC_A_Bossen_3,POC_A_Bossen_3.bin,POC_A_Bossen_3.md5 ++1,PPS_A_qualcomm_7,PPS_A_qualcomm_7.bit,PPS_A_qualcomm_7.yuv.md5 ++1,PS_B_VIDYO_3,PS_B_VIDYO_3.bit,PS_B_VIDYO_3_yuv.md5 ++1,RAP_A_docomo_6,RAP_A_docomo_6.bit,RAP_A_docomo_6.md5 ++1,RAP_B_Bossen_2,RAP_B_Bossen_2.bit,RAP_B_Bossen_2.md5 ++1,RPLM_A_qualcomm_4,RPLM_A_qualcomm_4.bit,RPLM_A_qualcomm_4.yuv.md5 ++1,RPLM_B_qualcomm_4,RPLM_B_qualcomm_4.bit,RPLM_B_qualcomm_4.yuv.md5 ++1,RPS_A_docomo_5,RPS_A_docomo_5.bit,RPS_A_docomo_5.md5 ++1,RPS_B_qualcomm_5,RPS_B_qualcomm_5.bit,RPS_B_qualcomm_5.yuv.md5 ++1,RPS_C_ericsson_5,RPS_C_ericsson_5.bit,RPS_C_ericsson_5.md5 ++1,RPS_D_ericsson_6,RPS_D_ericsson_6.bit,RPS_D_ericsson_6.md5 ++1,RPS_E_qualcomm_5,RPS_E_qualcomm_5.bit,RPS_E_qualcomm_5.yuv.md5 ++1,RPS_F_docomo_2,RPS_F_docomo_2.bit,RPS_F_docomo_2.md5 ++1,RQT_A_HHI_4,RQT_A_HHI_4.bit,RQT_A_HHI_4.md5 ++1,RQT_B_HHI_4,RQT_B_HHI_4.bit,RQT_B_HHI_4.md5 ++1,RQT_C_HHI_4,RQT_C_HHI_4.bit,RQT_C_HHI_4.md5 ++1,RQT_D_HHI_4,RQT_D_HHI_4.bit,RQT_D_HHI_4.md5 ++1,RQT_E_HHI_4,RQT_E_HHI_4.bit,RQT_E_HHI_4.md5 ++1,RQT_F_HHI_4,RQT_F_HHI_4.bit,RQT_F_HHI_4.md5 ++1,RQT_G_HHI_4,RQT_G_HHI_4.bit,RQT_G_HHI_4.md5 ++1,SAO_A_MediaTek_4,SAO_A_MediaTek_4.bit,SAO_A_MediaTek_4.md5 ++1,SAO_B_MediaTek_5,SAO_B_MediaTek_5.bit,SAO_B_MediaTek_5.md5 ++1,SAO_C_Samsung_5,SAO_C_Samsung_5.bin,SAO_C_Samsung_5.md5 ++1,SAO_D_Samsung_5,SAO_D_Samsung_5.bin,SAO_D_Samsung_5.md5 ++1,SAO_E_Canon_4,SAO_E_Canon_4.bit,SAO_E_Canon_4.md5 ++1,SAO_F_Canon_3,SAO_F_Canon_3.bit,SAO_F_Canon_3.md5 ++1,SAO_G_Canon_3,SAO_G_Canon_3.bit,SAO_G_Canon_3.md5 ++1,SAO_H_Parabola_1,SAO_H_Parabola_1.bit,SAO_H_Parabola_1.md5 ++2,SAODBLK_A_MainConcept_4,SAODBLK_A_MainConcept_4.bin,SAODBLK_A_MainConcept_4_md5.txt ++2,SAODBLK_B_MainConcept_4,SAODBLK_B_MainConcept_4.bin,SAODBLK_B_MainConcept_4_md5.txt ++1,SDH_A_Orange_4,SDH_A_Orange_4.bit,SDH_A_Orange_4_yuv.md5 ++1,SLICES_A_Rovi_3,SLICES_A_Rovi_3.bin,SLICES_A_Rovi_3.md5 ++1,SLIST_A_Sony_5,SLIST_A_Sony_5.bin,SLIST_A_Sony_5_yuv.md5 ++1,SLIST_B_Sony_9,SLIST_B_Sony_9.bin,SLIST_B_Sony_9_yuv.md5 ++1,SLIST_C_Sony_4,SLIST_C_Sony_4.bin,SLIST_C_Sony_4_yuv.md5 ++1,SLIST_D_Sony_9,str.bin,SLIST_D_Sony_9_yuv.md5 ++1,SLPPLP_A_VIDYO_2,SLPPLP_A_VIDYO_2.bit,SLPPLP_A_VIDYO_2_yuv.md5 ++1,STRUCT_A_Samsung_7,STRUCT_A_Samsung_7.bin,STRUCT_A_Samsung_7.md5 ++1,STRUCT_B_Samsung_7,STRUCT_B_Samsung_7.bin,STRUCT_B_Samsung_7.md5 ++1,TILES_A_Cisco_2,TILES_A_Cisco_2.bin,TILES_A_Cisco_2_yuv.md5 ++1,TILES_B_Cisco_1,TILES_B_Cisco_1.bin,TILES_B_Cisco_1_yuv.md5 ++1,TMVP_A_MS_3,TMVP_A_MS_3.bit,TMVP_A_MS_3.yuv.md5 ++1,TSCL_A_VIDYO_5,TSCL_A_VIDYO_5.bit,TSCL_A_VIDYO_5_yuv.md5 ++1,TSCL_B_VIDYO_4,TSCL_B_VIDYO_4.bit,TSCL_B_VIDYO_4_yuv.md5 ++1,TSKIP_A_MS_3,TSKIP_A_MS_3.bit,TSKIP_A_MS_3.yuv.md5 ++3,TSUNEQBD_A_MAIN10_Technicolor_2,TSUNEQBD_A_MAIN10_Technicolor_2.bit,TSUNEQBD_A_MAIN10_Technicolor_2_yuv.md5, # unequal bit depth ++1,TUSIZE_A_Samsung_1,TUSIZE_A_Samsung_1.bin,TUSIZE_A_Samsung_1.md5 ++1,VPSID_A_VIDYO_2,VPSID_A_VIDYO_2.bit,VPSID_A_VIDYO_2_yuv.md5 ++3,VPSSPSPPS_A_MainConcept_1,VPSSPSPPS_A_MainConcept_1.bin,VPSSPSPPS_A_MainConcept_1_md5.txt, # ??? ++1,WP_A_MAIN10_Toshiba_3,WP_A_MAIN10_Toshiba_3.bit,WP_A_MAIN10_Toshiba_3_yuv.md5 ++1,WP_A_Toshiba_3,WP_A_Toshiba_3.bit,WP_A_Toshiba_3_yuv.md5 ++1,WP_B_Toshiba_3,WP_B_Toshiba_3.bit,WP_B_Toshiba_3_yuv.md5 ++1,WP_MAIN10_B_Toshiba_3,WP_MAIN10_B_Toshiba_3.bit,WP_MAIN10_B_Toshiba_3_yuv.md5 ++1,WPP_A_ericsson_MAIN10_2,WPP_A_ericsson_MAIN10_2.bit,WPP_A_ericsson_MAIN10_yuv.md5 ++1,WPP_A_ericsson_MAIN_2,WPP_A_ericsson_MAIN_2.bit,WPP_A_ericsson_MAIN_2_yuv.md5 ++1,WPP_B_ericsson_MAIN10_2,WPP_B_ericsson_MAIN10_2.bit,WPP_B_ericsson_MAIN10_yuv.md5 ++1,WPP_B_ericsson_MAIN_2,WPP_B_ericsson_MAIN_2.bit,WPP_B_ericsson_MAIN_2_yuv.md5 ++1,WPP_C_ericsson_MAIN10_2,WPP_C_ericsson_MAIN10_2.bit,WPP_C_ericsson_MAIN10_yuv.md5 ++1,WPP_C_ericsson_MAIN_2,WPP_C_ericsson_MAIN_2.bit,WPP_C_ericsson_MAIN_2_yuv.md5 ++1,WPP_D_ericsson_MAIN10_2,WPP_D_ericsson_MAIN10_2.bit,WPP_D_ericsson_MAIN10_yuv.md5 ++1,WPP_D_ericsson_MAIN_2,WPP_D_ericsson_MAIN_2.bit,WPP_D_ericsson_MAIN_2_yuv.md5 ++1,WPP_E_ericsson_MAIN10_2,WPP_E_ericsson_MAIN10_2.bit,WPP_E_ericsson_MAIN10_yuv.md5 ++1,WPP_E_ericsson_MAIN_2,WPP_E_ericsson_MAIN_2.bit,WPP_E_ericsson_MAIN_2_yuv.md5 ++1,WPP_F_ericsson_MAIN10_2,WPP_F_ericsson_MAIN10_2.bit,WPP_F_ericsson_MAIN10_yuv.md5 ++1,WPP_F_ericsson_MAIN_2,WPP_F_ericsson_MAIN_2.bit,WPP_F_ericsson_MAIN_2_yuv.md5 +diff --git a/pi-util/conf_h265.csv b/pi-util/conf_h265.csv +new file mode 100644 +index 0000000000..fc14f2a3c2 +--- /dev/null ++++ b/pi-util/conf_h265.csv +@@ -0,0 +1,144 @@ ++1,ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1,ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1.bit,ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1.md5 ++1,AMP_A_Samsung_6,AMP_A_Samsung_6.bin,AMP_A_Samsung_6.md5 ++1,AMP_B_Samsung_6,AMP_B_Samsung_6.bin,AMP_B_Samsung_6.md5 ++1,AMP_D_Hisilicon_3,AMP_D_Hisilicon.bit,AMP_D_Hisilicon_3.yuv.md5 ++1,AMP_E_Hisilicon_3,AMP_E_Hisilicon.bit,AMP_E_Hisilicon_3.yuv.md5 ++1,AMP_F_Hisilicon_3,AMP_F_Hisilicon_3.bit,AMP_F_Hisilicon_3.yuv.md5 ++1,AMVP_A_MTK_4,AMVP_A_MTK_4.bit,AMVP_A_MTK_4.md5 ++1,AMVP_B_MTK_4,AMVP_B_MTK_4.bit,AMVP_B_MTK_4.md5 ++1,AMVP_C_Samsung_6,AMVP_C_Samsung_6.bin,AMVP_C_Samsung_6.md5 ++1,BUMPING_A_ericsson_1,BUMPING_A_ericsson_1.bit,BUMPING_A_ericsson_1.md5 ++1,CAINIT_A_SHARP_4,CAINIT_A_SHARP_4.bit,CAINIT_A_SHARP_4.md5 ++1,CAINIT_B_SHARP_4,CAINIT_B_SHARP_4.bit,CAINIT_B_SHARP_4.md5 ++1,CAINIT_C_SHARP_3,CAINIT_C_SHARP_3.bit,CAINIT_C_SHARP_3.md5 ++1,CAINIT_D_SHARP_3,CAINIT_D_SHARP_3.bit,CAINIT_D_SHARP_3.md5 ++1,CAINIT_E_SHARP_3,CAINIT_E_SHARP_3.bit,CAINIT_E_SHARP_3.md5 ++1,CAINIT_F_SHARP_3,CAINIT_F_SHARP_3.bit,CAINIT_F_SHARP_3.md5 ++1,CAINIT_G_SHARP_3,CAINIT_G_SHARP_3.bit,CAINIT_G_SHARP_3.md5 ++1,CAINIT_H_SHARP_3,CAINIT_H_SHARP_3.bit,CAINIT_H_SHARP_3.md5 ++1,CIP_A_Panasonic_3,CIP_A_Panasonic_3.bit,CIP_A_Panasonic_3_yuv.md5 ++1,cip_B_NEC_3,cip_B_NEC_3.bit,cip_B_NEC_3.md5 ++1,CIP_C_Panasonic_2,CIP_C_Panasonic_2.bit,CIP_C_Panasonic_2_yuv.md5 ++1,CONFWIN_A_Sony_1,CONFWIN_A_Sony_1.bit,CONFWIN_A_Sony_1.md5 ++1,DBLK_A_MAIN10_VIXS_3,DBLK_A_MAIN10_VIXS_3.bit,DBLK_A_MAIN10_VIXS_3.md5 ++1,DBLK_A_SONY_3,DBLK_A_SONY_3.bit,DBLK_A_SONY_3.bit.yuv.md5 ++1,DBLK_B_SONY_3,DBLK_B_SONY_3.bit,DBLK_B_SONY_3.bit.yuv.md5 ++1,DBLK_C_SONY_3,DBLK_C_SONY_3.bit,DBLK_C_SONY_3.bit.yuv.md5 ++1,DBLK_D_VIXS_2,DBLK_D_VIXS_2.bit,DBLK_D_VIXS_2_yuv.md5 ++1,DBLK_E_VIXS_2,DBLK_E_VIXS_2.bit,DBLK_E_VIXS_2_yuv.md5 ++1,DBLK_F_VIXS_2,DBLK_F_VIXS_2.bit,DBLK_F_VIXS_2_yuv.md5 ++1,DBLK_G_VIXS_2,DBLK_G_VIXS_2.bit,DBLK_G_VIXS_2_yuv.md5 ++1,DELTAQP_A_BRCM_4,DELTAQP_A_BRCM_4.bit,DELTAQP_A_BRCM_4_yuv.md5 ++1,DELTAQP_B_SONY_3,DELTAQP_B_SONY_3.bit,DELTAQP_B_SONY_3.bit.yuv.md5 ++1,DELTAQP_C_SONY_3,DELTAQP_C_SONY_3.bit,DELTAQP_C_SONY_3.bit.yuv.md5 ++1,DSLICE_A_HHI_5,DSLICE_A_HHI_5.bin,DSLICE_A_HHI_5.md5 ++1,DSLICE_B_HHI_5,DSLICE_B_HHI_5.bin,DSLICE_B_HHI_5.md5 ++1,DSLICE_C_HHI_5,DSLICE_C_HHI_5.bin,DSLICE_C_HHI_5.md5 ++1,ENTP_A_QUALCOMM_1,ENTP_A_Qualcomm_1.bit,ENTP_A_Qualcomm_1.md5 ++1,ENTP_B_Qualcomm_1,ENTP_B_Qualcomm_1.bit,ENTP_B_Qualcomm_1.md5 ++1,ENTP_C_Qualcomm_1,ENTP_C_Qualcomm_1.bit,ENTP_C_Qualcomm_1.md5 ++1,EXT_A_ericsson_4,EXT_A_ericsson_4.bit,EXT_A_ericsson_4.md5 ++1,FILLER_A_Sony_1,FILLER_A_Sony_1.bit,FILLER_A_Sony_1.md5 ++1,HRD_A_Fujitsu_3,HRD_A_Fujitsu_3.bin,HRD_A_Fujitsu_3.md5 ++1,INITQP_A_Sony_1,INITQP_A_Sony_1.bit,INITQP_A_Sony_1.md5 ++1,INITQP_B_Main10_Sony_1,INITQP_B_Main10_Sony_1.bit,INITQP_B_Main10_Sony_1.md5 ++1,ipcm_A_NEC_3,ipcm_A_NEC_3.bit,ipcm_A_NEC_3.md5 ++1,ipcm_B_NEC_3,ipcm_B_NEC_3.bit,ipcm_B_NEC_3.md5 ++1,ipcm_C_NEC_3,ipcm_C_NEC_3.bit,ipcm_C_NEC_3.md5 ++1,ipcm_D_NEC_3,ipcm_D_NEC_3.bit,ipcm_D_NEC_3.md5 ++1,ipcm_E_NEC_2,ipcm_E_NEC_2.bit,ipcm_E_NEC_2.md5 ++1,IPRED_A_docomo_2,IPRED_A_docomo_2.bit,IPRED_A_docomo_2.md5 ++1,IPRED_B_Nokia_3,IPRED_B_Nokia_3.bit,IPRED_B_Nokia_3_yuv.md5 ++1,IPRED_C_Mitsubishi_3,IPRED_C_Mitsubishi_3.bit,IPRED_C_Mitsubishi_3_yuv.md5 ++1,LS_A_Orange_2,LS_A_Orange_2.bit,LS_A_Orange_2_yuv.md5 ++1,LS_B_Orange_4,LS_B_Orange_4.bit,LS_B_Orange_4_yuv.md5 ++1,LTRPSPS_A_Qualcomm_1,LTRPSPS_A_Qualcomm_1.bit,LTRPSPS_A_Qualcomm_1.md5 ++1,MAXBINS_A_TI_4,MAXBINS_A_TI_4.bit,MAXBINS_A_TI_4.md5 ++1,MAXBINS_B_TI_4,MAXBINS_B_TI_4.bit,MAXBINS_B_TI_4.md5 ++1,MAXBINS_C_TI_4,MAXBINS_C_TI_4.bit,MAXBINS_C_TI_4.md5 ++1,MERGE_A_TI_3,MERGE_A_TI_3.bit,MERGE_A_TI_3.md5 ++1,MERGE_B_TI_3,MERGE_B_TI_3.bit,MERGE_B_TI_3.md5 ++1,MERGE_C_TI_3,MERGE_C_TI_3.bit,MERGE_C_TI_3.md5 ++1,MERGE_D_TI_3,MERGE_D_TI_3.bit,MERGE_D_TI_3.md5 ++1,MERGE_E_TI_3,MERGE_E_TI_3.bit,MERGE_E_TI_3.md5 ++1,MERGE_F_MTK_4,MERGE_F_MTK_4.bit,MERGE_F_MTK_4.md5 ++1,MERGE_G_HHI_4,MERGE_G_HHI_4.bit,MERGE_G_HHI_4.md5 ++1,MVCLIP_A_qualcomm_3,MVCLIP_A_qualcomm_3.bit,MVCLIP_A_qualcomm_3.yuv.md5 ++1,MVDL1ZERO_A_docomo_4,MVDL1ZERO_A_docomo_4.bit,MVDL1ZERO_A_docomo_4.md5 ++1,MVEDGE_A_qualcomm_3,MVEDGE_A_qualcomm_3.bit,MVEDGE_A_qualcomm_3.yuv.md5 ++1,NoOutPrior_A_Qualcomm_1,NoOutPrior_A_Qualcomm_1.bit,NoOutPrior_A_Qualcomm_1.md5 ++1,NoOutPrior_B_Qualcomm_1,NoOutPrior_B_Qualcomm_1.bit,NoOutPrior_B_Qualcomm_1.md5 ++1,NUT_A_ericsson_5,NUT_A_ericsson_5.bit,NUT_A_ericsson_5.md5 ++1,OPFLAG_A_Qualcomm_1,OPFLAG_A_Qualcomm_1.bit,OPFLAG_A_Qualcomm_1.md5 ++1,OPFLAG_B_Qualcomm_1,OPFLAG_B_Qualcomm_1.bit,OPFLAG_B_Qualcomm_1.md5 ++1,OPFLAG_C_Qualcomm_1,OPFLAG_C_Qualcomm_1.bit,OPFLAG_C_Qualcomm_1.md5 ++1,PICSIZE_A_Bossen_1,PICSIZE_A_Bossen_1.bin,PICSIZE_A_Bossen_1.md5 ++1,PICSIZE_B_Bossen_1,PICSIZE_B_Bossen_1.bin,PICSIZE_B_Bossen_1.md5 ++1,PICSIZE_C_Bossen_1,PICSIZE_C_Bossen_1.bin,PICSIZE_C_Bossen_1.md5 ++1,PICSIZE_D_Bossen_1,PICSIZE_D_Bossen_1.bin,PICSIZE_D_Bossen_1.md5 ++1,PMERGE_A_TI_3,PMERGE_A_TI_3.bit,PMERGE_A_TI_3.md5 ++1,PMERGE_B_TI_3,PMERGE_B_TI_3.bit,PMERGE_B_TI_3.md5 ++1,PMERGE_C_TI_3,PMERGE_C_TI_3.bit,PMERGE_C_TI_3.md5 ++1,PMERGE_D_TI_3,PMERGE_D_TI_3.bit,PMERGE_D_TI_3.md5 ++1,PMERGE_E_TI_3,PMERGE_E_TI_3.bit,PMERGE_E_TI_3.md5 ++1,POC_A_Bossen_3,POC_A_Bossen_3.bin,POC_A_Bossen_3.md5 ++1,PPS_A_qualcomm_7,PPS_A_qualcomm_7.bit,PPS_A_qualcomm_7.yuv.md5 ++1,PS_B_VIDYO_3,PS_B_VIDYO_3.bit,PS_B_VIDYO_3_yuv.md5 ++1,RAP_A_docomo_6,RAP_A_docomo_6.bit,RAP_A_docomo_6.md5 ++1,RAP_B_Bossen_2,RAP_B_Bossen_2.bit,RAP_B_Bossen_2.md5 ++1,RPLM_A_qualcomm_4,RPLM_A_qualcomm_4.bit,RPLM_A_qualcomm_4.yuv.md5 ++1,RPLM_B_qualcomm_4,RPLM_B_qualcomm_4.bit,RPLM_B_qualcomm_4.yuv.md5 ++1,RPS_A_docomo_5,RPS_A_docomo_5.bit,RPS_A_docomo_5.md5 ++1,RPS_B_qualcomm_5,RPS_B_qualcomm_5.bit,RPS_B_qualcomm_5.yuv.md5 ++1,RPS_C_ericsson_5,RPS_C_ericsson_5.bit,RPS_C_ericsson_5.md5 ++1,RPS_D_ericsson_6,RPS_D_ericsson_6.bit,RPS_D_ericsson_6.md5 ++1,RPS_E_qualcomm_5,RPS_E_qualcomm_5.bit,RPS_E_qualcomm_5.yuv.md5 ++1,RPS_F_docomo_2,RPS_F_docomo_2.bit,RPS_F_docomo_2.md5 ++1,RQT_A_HHI_4,RQT_A_HHI_4.bit,RQT_A_HHI_4.md5 ++1,RQT_B_HHI_4,RQT_B_HHI_4.bit,RQT_B_HHI_4.md5 ++1,RQT_C_HHI_4,RQT_C_HHI_4.bit,RQT_C_HHI_4.md5 ++1,RQT_D_HHI_4,RQT_D_HHI_4.bit,RQT_D_HHI_4.md5 ++1,RQT_E_HHI_4,RQT_E_HHI_4.bit,RQT_E_HHI_4.md5 ++1,RQT_F_HHI_4,RQT_F_HHI_4.bit,RQT_F_HHI_4.md5 ++1,RQT_G_HHI_4,RQT_G_HHI_4.bit,RQT_G_HHI_4.md5 ++1,SAO_A_MediaTek_4,SAO_A_MediaTek_4.bit,SAO_A_MediaTek_4.md5 ++1,SAO_B_MediaTek_5,SAO_B_MediaTek_5.bit,SAO_B_MediaTek_5.md5 ++1,SAO_C_Samsung_5,SAO_C_Samsung_5.bin,SAO_C_Samsung_5.md5 ++1,SAO_D_Samsung_5,SAO_D_Samsung_5.bin,SAO_D_Samsung_5.md5 ++1,SAO_E_Canon_4,SAO_E_Canon_4.bit,SAO_E_Canon_4.md5 ++1,SAO_F_Canon_3,SAO_F_Canon_3.bit,SAO_F_Canon_3.md5 ++1,SAO_G_Canon_3,SAO_G_Canon_3.bit,SAO_G_Canon_3.md5 ++1,SDH_A_Orange_4,SDH_A_Orange_4.bit,SDH_A_Orange_4_yuv.md5 ++1,SLICES_A_Rovi_3,SLICES_A_Rovi_3.bin,SLICES_A_Rovi_3.md5 ++1,SLIST_A_Sony_4,str.bin,SLIST_A_Sony_4_yuv.md5 ++1,SLIST_B_Sony_8,str.bin,SLIST_B_Sony_8_yuv.md5 ++1,SLIST_C_Sony_3,str.bin,SLIST_C_Sony_3_yuv.md5 ++1,SLIST_D_Sony_9,str.bin,SLIST_D_Sony_9_yuv.md5 ++1,SLPPLP_A_VIDYO_2,SLPPLP_A_VIDYO_2.bit,SLPPLP_A_VIDYO_2_yuv.md5 ++1,STRUCT_A_Samsung_6,STRUCT_A_Samsung_6.bin,STRUCT_A_Samsung_6.md5 ++1,STRUCT_B_Samsung_6,STRUCT_B_Samsung_6.bin,STRUCT_B_Samsung_6.md5 ++1,TILES_A_Cisco_2,TILES_A_Cisco_2.bin,TILES_A_Cisco_2_yuv.md5 ++1,TILES_B_Cisco_1,TILES_B_Cisco_1.bin,TILES_B_Cisco_1_yuv.md5 ++1,TMVP_A_MS_3,TMVP_A_MS_3.bit,TMVP_A_MS_3.yuv.md5 ++1,TSCL_A_VIDYO_5,TSCL_A_VIDYO_5.bit,TSCL_A_VIDYO_5_yuv.md5 ++1,TSCL_B_VIDYO_4,TSCL_B_VIDYO_4.bit,TSCL_B_VIDYO_4_yuv.md5 ++1,TSKIP_A_MS_3,TSKIP_A_MS_3.bit,TSKIP_A_MS_3.yuv.md5 ++0,TSUNEQBD_A_MAIN10_Technicolor_2,TSUNEQBD_A_MAIN10_Technicolor_2.bit,TSUNEQBD_A_MAIN10_Technicolor_2_yuv.md5, # Y/C bit depth unmatched ++1,TUSIZE_A_Samsung_1,TUSIZE_A_Samsung_1.bin,TUSIZE_A_Samsung_1.md5 ++1,VPSID_A_VIDYO_2,VPSID_A_VIDYO_2.bit,VPSID_A_VIDYO_2_yuv.md5 ++1,WP_A_MAIN10_Toshiba_3,WP_A_MAIN10_Toshiba_3.bit,WP_A_MAIN10_Toshiba_3_yuv.md5 ++1,WP_A_Toshiba_3,WP_A_Toshiba_3.bit,WP_A_Toshiba_3_yuv.md5 ++1,WP_B_Toshiba_3,WP_B_Toshiba_3.bit,WP_B_Toshiba_3_yuv.md5 ++1,WP_MAIN10_B_Toshiba_3,WP_MAIN10_B_Toshiba_3.bit,WP_MAIN10_B_Toshiba_3_yuv.md5 ++1,WPP_A_ericsson_MAIN10_2,WPP_A_ericsson_MAIN10_2.bit,WPP_A_ericsson_MAIN10_yuv.md5 ++1,WPP_A_ericsson_MAIN_2,WPP_A_ericsson_MAIN_2.bit,WPP_A_ericsson_MAIN_2_yuv.md5 ++1,WPP_B_ericsson_MAIN10_2,WPP_B_ericsson_MAIN10_2.bit,WPP_B_ericsson_MAIN10_yuv.md5 ++1,WPP_B_ericsson_MAIN_2,WPP_B_ericsson_MAIN_2.bit,WPP_B_ericsson_MAIN_2_yuv.md5 ++1,WPP_C_ericsson_MAIN10_2,WPP_C_ericsson_MAIN10_2.bit,WPP_C_ericsson_MAIN10_yuv.md5 ++1,WPP_C_ericsson_MAIN_2,WPP_C_ericsson_MAIN_2.bit,WPP_C_ericsson_MAIN_2_yuv.md5 ++1,WPP_D_ericsson_MAIN10_2,WPP_D_ericsson_MAIN10_2.bit,WPP_D_ericsson_MAIN10_yuv.md5 ++1,WPP_D_ericsson_MAIN_2,WPP_D_ericsson_MAIN_2.bit,WPP_D_ericsson_MAIN_2_yuv.md5 ++1,WPP_E_ericsson_MAIN10_2,WPP_E_ericsson_MAIN10_2.bit,WPP_E_ericsson_MAIN10_yuv.md5 ++1,WPP_E_ericsson_MAIN_2,WPP_E_ericsson_MAIN_2.bit,WPP_E_ericsson_MAIN_2_yuv.md5 ++1,WPP_F_ericsson_MAIN10_2,WPP_F_ericsson_MAIN10_2.bit,WPP_F_ericsson_MAIN10_yuv.md5 ++1,WPP_F_ericsson_MAIN_2,WPP_F_ericsson_MAIN_2.bit,WPP_F_ericsson_MAIN_2_yuv.md5 +diff --git a/pi-util/conf_native.sh b/pi-util/conf_native.sh +new file mode 100755 +index 0000000000..063edbf8af +--- /dev/null ++++ b/pi-util/conf_native.sh +@@ -0,0 +1,56 @@ ++echo "Configure for native build" ++ ++FFSRC=`pwd` ++ ++RPI_OPT_VC=/opt/vc ++RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux" ++RPI_LIBDIRS="-L$RPI_OPT_VC/lib" ++RPI_DEFINES="-D__VCCOREVER__=0x4000000 -mfpu=neon-vfpv4" ++#RPI_KEEPS="-save-temps=obj" ++RPI_KEEPS="" ++ ++SHARED_LIBS="--enable-shared" ++if [ "$1" == "--noshared" ]; then ++ SHARED_LIBS="--disable-shared" ++ OUT=out/armv7-static-rel ++ echo Static libs ++else ++ echo Shared libs ++ OUT=out/armv7-shared-rel ++fi ++ ++USR_PREFIX=$FFSRC/$OUT/install ++LIB_PREFIX=$USR_PREFIX/lib/arm-linux-gnueabihf ++INC_PREFIX=$USR_PREFIX/include/arm-linux-gnueabihf ++ ++mkdir -p $FFSRC/$OUT ++cd $FFSRC/$OUT ++ ++$FFSRC/configure \ ++ --prefix=$USR_PREFIX\ ++ --libdir=$LIB_PREFIX\ ++ --incdir=$INC_PREFIX\ ++ --arch=armv6t2\ ++ --cpu=cortex-a7\ ++ --disable-stripping\ ++ --disable-thumb\ ++ --enable-mmal\ ++ --enable-rpi\ ++ --enable-v4l2-request\ ++ --enable-libdrm\ ++ --enable-epoxy\ ++ --enable-libudev\ ++ --enable-vout-drm\ ++ --enable-vout-egl\ ++ $SHARED_LIBS\ ++ --extra-cflags="-ggdb $RPI_KEEPS $RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-cxxflags="$RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-ldflags="$RPI_LIBDIRS"\ ++ --extra-libs="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm"\ ++ ++# --enable-decoder=hevc_rpi\ ++# --enable-extra-warnings\ ++# --arch=armv71\ ++ ++# gcc option for getting asm listing ++# -Wa,-ahls +diff --git a/pi-util/conf_pi1.sh b/pi-util/conf_pi1.sh +new file mode 100755 +index 0000000000..29fa9fa68d +--- /dev/null ++++ b/pi-util/conf_pi1.sh +@@ -0,0 +1,39 @@ ++echo "Configure for Pi1" ++ ++RPI_TOOLROOT=`pwd`/../tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf ++RPI_OPT_VC=`pwd`/../firmware/hardfp/opt/vc ++ ++RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux" ++RPI_LIBDIRS="-L$RPI_TOOLROOT/lib -L$RPI_OPT_VC/lib" ++#RPI_KEEPS="-save-temps=obj" ++RPI_KEEPS="" ++ ++SHARED_LIBS="--enable-shared" ++if [ "$1" == "--noshared" ]; then ++ SHARED_LIBS="--disable-shared" ++ echo Static libs ++else ++ echo Shared libs ++fi ++ ++./configure --enable-cross-compile\ ++ --cpu=arm1176jzf-s\ ++ --arch=arm\ ++ --disable-neon\ ++ --target-os=linux\ ++ --disable-stripping\ ++ --enable-mmal\ ++ $SHARED_LIBS\ ++ --extra-cflags="-g $RPI_KEEPS $RPI_INCLUDES"\ ++ --extra-cxxflags="$RPI_INCLUDES"\ ++ --extra-ldflags="$RPI_LIBDIRS -Wl,-rpath=/opt/vc/lib,-rpath-link=$RPI_OPT_VC/lib,-rpath=/lib,-rpath=/usr/lib,-rpath-link=$RPI_TOOLROOT/lib,-rpath-link=$RPI_TOOLROOT/lib"\ ++ --extra-libs="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm"\ ++ --cross-prefix=$RPI_TOOLROOT/bin/arm-linux-gnueabihf- ++ ++ ++# --enable-extra-warnings\ ++# --arch=armv71\ ++# --enable-shared\ ++ ++# gcc option for getting asm listing ++# -Wa,-ahls +diff --git a/pi-util/conf_pi2.sh b/pi-util/conf_pi2.sh +new file mode 100755 +index 0000000000..92cd9e7cfd +--- /dev/null ++++ b/pi-util/conf_pi2.sh +@@ -0,0 +1,57 @@ ++echo "Configure for Pi2/3" ++ ++FFSRC=`pwd` ++ ++RPI_TOOLROOT=$FFSRC/../tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf ++RPI_OPT_VC=$FFSRC/../firmware/hardfp/opt/vc ++ ++RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux" ++RPI_LIBDIRS="-L$RPI_TOOLROOT/lib -L$RPI_OPT_VC/lib" ++RPI_DEFINES="-D__VCCOREVER__=0x4000000 -mfpu=neon-vfpv4" ++#RPI_KEEPS="-save-temps=obj" ++RPI_KEEPS="" ++ ++SHARED_LIBS="--enable-shared" ++if [ "$1" == "--noshared" ]; then ++ SHARED_LIBS="--disable-shared" ++ OUT=out/x-armv7-static-rel ++ echo Static libs ++else ++ echo Shared libs ++ OUT=out/x-armv7-shared-rel ++fi ++ ++USR_PREFIX=$FFSRC/$OUT/install ++LIB_PREFIX=$USR_PREFIX/lib/arm-linux-gnueabihf ++INC_PREFIX=$USR_PREFIX/include/arm-linux-gnueabihf ++ ++mkdir -p $FFSRC/$OUT ++cd $FFSRC/$OUT ++ ++$FFSRC/configure --enable-cross-compile\ ++ --prefix=$USR_PREFIX\ ++ --libdir=$LIB_PREFIX\ ++ --incdir=$INC_PREFIX\ ++ --arch=armv6t2\ ++ --cpu=cortex-a7\ ++ --target-os=linux\ ++ --disable-stripping\ ++ --disable-thumb\ ++ --enable-mmal\ ++ --enable-rpi\ ++ $SHARED_LIBS\ ++ --extra-cflags="-ggdb $RPI_KEEPS $RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-cxxflags="$RPI_DEFINES $RPI_INCLUDES"\ ++ --extra-ldflags="$RPI_LIBDIRS -Wl,-rpath=/opt/vc/lib,-rpath-link=$RPI_OPT_VC/lib,-rpath=/lib,-rpath=/usr/lib,-rpath-link=$RPI_TOOLROOT/lib,-rpath-link=$RPI_TOOLROOT/lib"\ ++ --extra-libs="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm"\ ++ --cross-prefix=$RPI_TOOLROOT/bin/arm-linux-gnueabihf- ++ ++# --enable-shared\ ++ ++# --enable-decoder=hevc_rpi\ ++# --enable-extra-warnings\ ++# --arch=armv71\ ++# --enable-shared\ ++ ++# gcc option for getting asm listing ++# -Wa,-ahls +diff --git a/pi-util/ffconf.py b/pi-util/ffconf.py +new file mode 100755 +index 0000000000..2e59e6ceb5 +--- /dev/null ++++ b/pi-util/ffconf.py +@@ -0,0 +1,216 @@ ++#!/usr/bin/env python ++ ++import string ++import os ++import subprocess ++import re ++import argparse ++import sys ++import csv ++from stat import * ++ ++ffmpeg_exec = "./ffmpeg" ++ ++CODEC_HEVC_RPI = 1 ++HWACCEL_RPI = 2 ++HWACCEL_DRM = 3 ++HWACCEL_VAAPI = 4 ++ ++def testone(fileroot, srcname, es_file, md5_file, pix, dectype, vcodec): ++ hwaccel = "" ++ if dectype == HWACCEL_RPI: ++ hwaccel = "rpi" ++ elif dectype == HWACCEL_DRM: ++ hwaccel = "drm" ++ elif dectype == HWACCEL_VAAPI: ++ hwaccel = "vaapi" ++ ++ pix_fmt = [] ++ if pix == "8": ++ pix_fmt = ["-pix_fmt", "yuv420p"] ++ elif pix == "10": ++ pix_fmt = ["-pix_fmt", "yuv420p10le"] ++ elif pix == "12": ++ pix_fmt = ["-pix_fmt", "yuv420p12le"] ++ ++ tmp_root = "/tmp" ++ ++ names = srcname.split('/') ++ while len(names) > 1: ++ tmp_root = os.path.join(tmp_root, names[0]) ++ del names[0] ++ name = names[0] ++ ++ if not os.path.exists(tmp_root): ++ os.makedirs(tmp_root) ++ ++ dec_file = os.path.join(tmp_root, name + ".dec.md5") ++ try: ++ os.remove(dec_file) ++ except: ++ pass ++ ++ flog = open(os.path.join(tmp_root, name + ".log"), "wt") ++ ++ ffargs = [ffmpeg_exec, "-flags", "unaligned", "-hwaccel", hwaccel, "-vcodec", "hevc", "-i", os.path.join(fileroot, es_file)] + pix_fmt + ["-f", "md5", dec_file] ++ ++ # Unaligned needed for cropping conformance ++ if hwaccel: ++ rstr = subprocess.call(ffargs, stdout=flog, stderr=subprocess.STDOUT) ++ else: ++ rstr = subprocess.call( ++ [ffmpeg_exec, "-flags", "unaligned", "-vcodec", vcodec, "-i", os.path.join(fileroot, es_file), "-f", "md5", dec_file], ++ stdout=flog, stderr=subprocess.STDOUT) ++ ++ try: ++ m1 = None ++ m2 = None ++ with open(os.path.join(fileroot, md5_file)) as f: ++ for line in f: ++ m1 = re.search("[0-9a-f]{32}", line.lower()) ++ if m1: ++ break ++ ++ with open(dec_file) as f: ++ m2 = re.search("[0-9a-f]{32}", f.readline()) ++ except: ++ pass ++ ++ if m1 and m2 and m1.group() == m2.group(): ++ print >> flog, "Match: " + m1.group() ++ rv = 0 ++ elif not m1: ++ print >> flog, "****** Cannot find m1" ++ rv = 3 ++ elif not m2: ++ print >> flog, "****** Cannot find m2" ++ rv = 2 ++ else: ++ print >> flog, "****** Mismatch: " + m1.group() + " != " + m2.group() ++ rv = 1 ++ flog.close() ++ return rv ++ ++def scandir(root): ++ aconf = [] ++ ents = os.listdir(root) ++ ents.sort(key=str.lower) ++ for name in ents: ++ test_path = os.path.join(root, name) ++ if S_ISDIR(os.stat(test_path).st_mode): ++ files = os.listdir(test_path) ++ es_file = "?" ++ md5_file = "?" ++ for f in files: ++ (base, ext) = os.path.splitext(f) ++ if base[0] == '.': ++ pass ++ elif ext == ".bit" or ext == ".bin": ++ es_file = f ++ elif ext == ".md5" or (ext == ".txt" and (base[-4:] == "_md5" or base[-6:] == "md5sum")): ++ if md5_file == "?": ++ md5_file = f ++ elif base[-3:] == "yuv": ++ md5_file = f ++ aconf.append((1, name, es_file, md5_file)) ++ return aconf ++ ++def runtest(name, tests): ++ if not tests: ++ return True ++ for t in tests: ++ if name[0:len(t)] == t or name.find("/" + t) != -1: ++ return True ++ return False ++ ++def doconf(csva, tests, test_root, vcodec, dectype): ++ unx_failures = [] ++ unx_success = [] ++ failures = 0 ++ successes = 0 ++ for a in csva: ++ exp_test = int(a[0]) ++ if (exp_test and runtest(a[1], tests)): ++ name = a[1] ++ print "==== ", name, ++ sys.stdout.flush() ++ ++ rv = testone(os.path.join(test_root, name), name, a[2], a[3], a[4], dectype=dectype, vcodec=vcodec) ++ if (rv == 0): ++ successes += 1 ++ else: ++ failures += 1 ++ ++ if (rv == 0): ++ if exp_test == 2: ++ print ": * OK *" ++ unx_success.append(name) ++ else: ++ print ": ok" ++ elif exp_test == 2 and rv == 1: ++ print ": fail" ++ elif exp_test == 3 and rv == 2: ++ # Call an expected "crash" an abort ++ print ": abort" ++ else: ++ unx_failures.append(name) ++ if rv == 1: ++ print ": * FAIL *" ++ elif (rv == 2) : ++ print ": * CRASH *" ++ elif (rv == 3) : ++ print ": * MD5 MISSING *" ++ else : ++ print ": * BANG *" ++ ++ if unx_failures or unx_success: ++ print "Unexpected Failures:", unx_failures ++ print "Unexpected Success: ", unx_success ++ else: ++ print "All tests normal:", successes, "ok,", failures, "failed" ++ ++ ++class ConfCSVDialect(csv.Dialect): ++ delimiter = ',' ++ doublequote = True ++ lineterminator = '\n' ++ quotechar='"' ++ quoting = csv.QUOTE_MINIMAL ++ skipinitialspace = True ++ strict = True ++ ++if __name__ == '__main__': ++ ++ argp = argparse.ArgumentParser(description="FFmpeg h265 conformance tester") ++ argp.add_argument("tests", nargs='*') ++ argp.add_argument("--pi4", action='store_true', help="Force pi4 cmd line") ++ argp.add_argument("--drm", action='store_true', help="Force v4l2 drm cmd line") ++ argp.add_argument("--vaapi", action='store_true', help="Force vaapi cmd line") ++ argp.add_argument("--test_root", default="/opt/conform/h265.2016", help="Root dir for test") ++ argp.add_argument("--csvgen", action='store_true', help="Generate CSV file for dir") ++ argp.add_argument("--csv", default="pi-util/conf_h265.2016.csv", help="CSV filename") ++ argp.add_argument("--vcodec", default="hevc_rpi", help="vcodec name to use") ++ args = argp.parse_args() ++ ++ if args.csvgen: ++ csv.writer(sys.stdout).writerows(scandir(args.test_root)) ++ exit(0) ++ ++ with open(args.csv, 'rt') as csvfile: ++ csva = [a for a in csv.reader(csvfile, ConfCSVDialect())] ++ ++ dectype = CODEC_HEVC_RPI ++ if os.path.exists("/dev/rpivid-hevcmem"): ++ dectype = HWACCEL_RPI ++ if args.drm or os.path.exists("/sys/module/rpivid_hevc"): ++ dectype = HWACCEL_DRM ++ ++ if args.pi4: ++ dectype = HWACCEL_RPI ++ elif args.drm: ++ dectype = HWACCEL_DRM ++ elif args.vaapi: ++ dectype = HWACCEL_VAAPI ++ ++ doconf(csva, args.tests, args.test_root, args.vcodec, dectype) ++ +diff --git a/pi-util/ffperf.py b/pi-util/ffperf.py +new file mode 100755 +index 0000000000..65c5224cd8 +--- /dev/null ++++ b/pi-util/ffperf.py +@@ -0,0 +1,128 @@ ++#!/usr/bin/env python3 ++ ++import time ++import string ++import os ++import tempfile ++import subprocess ++import re ++import argparse ++import sys ++import csv ++from stat import * ++ ++class tstats: ++ close_threshold = 0.01 ++ ++ def __init__(self, stats_dict=None): ++ if stats_dict != None: ++ self.name = stats_dict["name"] ++ self.elapsed = float(stats_dict["elapsed"]) ++ self.user = float(stats_dict["user"]) ++ self.sys = float(stats_dict["sys"]) ++ ++ def times_str(self): ++ ctime = self.sys + self.user ++ return "time=%6.2f, cpu=%6.2f (%4.2f%%)" % (self.elapsed, ctime, (ctime * 100.0) / self.elapsed) ++ ++ def dict(self): ++ return {"name":self.name, "elapsed":self.elapsed, "user":self.user, "sys":self.sys} ++ ++ def is_close(self, other): ++ return abs(self.elapsed - other.elapsed) / self.elapsed < self.close_threshold ++ ++ def __lt__(self, other): ++ return self.elapsed < other.elapsed ++ def __gt__(self, other): ++ return self.elapsed > other.elapsed ++ ++ def time_file(name, prefix, ffmpeg="./ffmpeg"): ++ stats = tstats() ++ stats.name = name ++ start_time = time.clock_gettime(time.CLOCK_MONOTONIC); ++ cproc = subprocess.Popen([ffmpeg, "-no_cvt_hw", ++ "-vcodec", "hevc_rpi", ++ "-t", "30", "-i", prefix + name, ++ "-f", "vout_rpi", os.devnull], bufsize=-1, stdout=flog, stderr=flog); ++ pinfo = os.wait4(cproc.pid, 0) ++ end_time = time.clock_gettime(time.CLOCK_MONOTONIC); ++ stats.elapsed = end_time - start_time ++ stats.user = pinfo[2].ru_utime ++ stats.sys = pinfo[2].ru_stime ++ return stats ++ ++ ++def common_prefix(s1, s2): ++ for i in range(min(len(s1),len(s2))): ++ if s1[i] != s2[i]: ++ return s1[:i] ++ return s1[:i+1] ++ ++def main(): ++ global flog ++ ++ argp = argparse.ArgumentParser(description="FFmpeg performance tester", epilog=""" ++To blank the screen before starting use "xdg-screensaver activate" ++(For some reason this doesn't seem to work from within python). ++""") ++ ++ argp.add_argument("streams", nargs='*') ++ argp.add_argument("--csv_out", default="ffperf_out.csv", help="CSV output filename") ++ argp.add_argument("--csv_in", help="CSV input filename") ++ argp.add_argument("--prefix", help="Filename prefix (include terminal '/' if a directory).") ++ argp.add_argument("--repeat", default=3, type=int, help="Run repeat count") ++ argp.add_argument("--ffmpeg", default="./ffmpeg", help="FFmpeg executable") ++ ++ args = argp.parse_args() ++ ++ csv_out = csv.DictWriter(open(args.csv_out, 'w', newline=''), ["name", "elapsed", "user", "sys"]) ++ csv_out.writeheader() ++ ++ stats_in = {} ++ if args.csv_in != None: ++ with open(args.csv_in, 'r', newline='') as f_in: ++ stats_in = {x["name"]:tstats(x) for x in csv.DictReader(f_in)} ++ ++ flog = open(os.path.join(tempfile.gettempdir(), "ffperf.log"), "wt") ++ ++ streams = args.streams ++ if not streams: ++ if not stats_in: ++ print ("No source streams specified") ++ return 1 ++ prefix = "" if args.prefix == None else args.prefix ++ streams = [k for k in stats_in] ++ elif args.prefix != None: ++ prefix = args.prefix ++ else: ++ prefix = streams[0] ++ for f in streams[1:]: ++ prefix = common_prefix(prefix, f) ++ pp = prefix.rpartition(os.sep) ++ prefix = pp[0] + pp[1] ++ streams = [s[len(prefix):] for s in streams] ++ ++ for f in sorted(streams, key=lambda x : "~" * x.count(os.sep) + x.lower()): ++ print ("====", f) ++ ++ t0 = tstats({"name":f, "elapsed":999, "user":999, "sys":999}) ++ for i in range(args.repeat): ++ t = tstats.time_file(f, prefix, args.ffmpeg) ++ print ("...", t.times_str()) ++ if t0 > t: ++ t0 = t ++ ++ if t0.name in stats_in: ++ pstat = stats_in[t0.name] ++ print("---" if pstat.is_close(t0) else "<<<" if t0 < pstat else ">>>", pstat.times_str()) ++ ++ csv_out.writerow(t0.dict()) ++ ++ print () ++ ++ return 0 ++ ++ ++if __name__ == '__main__': ++ exit(main()) ++ +diff --git a/pi-util/genpatch.sh b/pi-util/genpatch.sh +new file mode 100755 +index 0000000000..0948a68a7a +--- /dev/null ++++ b/pi-util/genpatch.sh +@@ -0,0 +1,35 @@ ++set -e ++ ++NOPATCH= ++if [ "$1" == "--notag" ]; then ++ shift ++ NOPATCH=1 ++fi ++ ++if [ "$1" == "" ]; then ++ echo Usage: $0 [--notag] \ ++ echo e.g.: $0 mmal_4 ++ exit 1 ++fi ++ ++VERSION=`cat RELEASE` ++if [ "$VERSION" == "" ]; then ++ echo Can\'t find version RELEASE ++ exit 1 ++fi ++ ++PATCHFILE=../ffmpeg-$VERSION-$1.patch ++ ++if [ $NOPATCH ]; then ++ echo Not tagged ++else ++ # Only continue if we are all comitted ++ git diff --name-status --exit-code ++ ++ PATCHTAG=pi/$VERSION/$1 ++ echo Tagging: $PATCHTAG ++ ++ git tag $PATCHTAG ++fi ++echo Generating patch: $PATCHFILE ++git diff n$VERSION -- > $PATCHFILE +diff --git a/pi-util/make_array.py b/pi-util/make_array.py +new file mode 100755 +index 0000000000..67b22d2d51 +--- /dev/null ++++ b/pi-util/make_array.py +@@ -0,0 +1,23 @@ ++#!/usr/bin/env python ++ ++# Usage ++# make_array file.bin ++# Produces file.h with array of bytes. ++# ++import sys ++for file in sys.argv[1:]: ++ prefix,suffix = file.split('.') ++ assert suffix=='bin' ++ name=prefix.split('/')[-1] ++ print 'Converting',file ++ with open(prefix+'.h','wb') as out: ++ print >>out, 'static const unsigned char',name,'[] = {' ++ with open(file,'rb') as fd: ++ i = 0 ++ for byte in fd.read(): ++ print >>out, '0x%02x, ' % ord(byte), ++ i = i + 1 ++ if i % 8 == 0: ++ print >>out, ' // %04x' % (i - 8) ++ print >>out,'};' ++ +diff --git a/pi-util/mkinst.sh b/pi-util/mkinst.sh +new file mode 100755 +index 0000000000..271a39e846 +--- /dev/null ++++ b/pi-util/mkinst.sh +@@ -0,0 +1,5 @@ ++set -e ++ ++make install ++ ++cp -r install/* ../vlc/sysroot/raspian_stretch_pi1-sysroot/usr +diff --git a/pi-util/patkodi.sh b/pi-util/patkodi.sh +new file mode 100644 +index 0000000000..dcd05a606e +--- /dev/null ++++ b/pi-util/patkodi.sh +@@ -0,0 +1,9 @@ ++set -e ++KODIBASE=/home/jc/rpi/kodi/xbmc ++JOBS=-j20 ++make $JOBS ++git diff xbmc/release/4.3-kodi > $KODIBASE/tools/depends/target/ffmpeg/pfcd_hevc_optimisations.patch ++make -C $KODIBASE/tools/depends/target/ffmpeg $JOBS ++make -C $KODIBASE/build install ++ ++ +diff --git a/pi-util/perfcmp.py b/pi-util/perfcmp.py +new file mode 100755 +index 0000000000..e44cfa0c3c +--- /dev/null ++++ b/pi-util/perfcmp.py +@@ -0,0 +1,101 @@ ++#!/usr/bin/env python3 ++ ++import time ++import string ++import os ++import tempfile ++import subprocess ++import re ++import argparse ++import sys ++import csv ++from stat import * ++ ++class tstats: ++ close_threshold = 0.01 ++ ++ def __init__(self, stats_dict=None): ++ if stats_dict != None: ++ self.name = stats_dict["name"] ++ self.elapsed = float(stats_dict["elapsed"]) ++ self.user = float(stats_dict["user"]) ++ self.sys = float(stats_dict["sys"]) ++ ++ def times_str(self): ++ ctime = self.sys + self.user ++ return "time=%6.2f, cpu=%6.2f (%4.2f%%)" % (self.elapsed, ctime, (ctime * 100.0) / self.elapsed) ++ ++ def dict(self): ++ return {"name":self.name, "elapsed":self.elapsed, "user":self.user, "sys":self.sys} ++ ++ def is_close(self, other): ++ return abs(self.elapsed - other.elapsed) / self.elapsed < self.close_threshold ++ ++ def __lt__(self, other): ++ return self.elapsed < other.elapsed ++ def __gt__(self, other): ++ return self.elapsed > other.elapsed ++ ++ def time_file(name, prefix): ++ stats = tstats() ++ stats.name = name ++ start_time = time.clock_gettime(time.CLOCK_MONOTONIC); ++ cproc = subprocess.Popen(["./ffmpeg", "-t", "30", "-i", prefix + name, ++ "-f", "null", os.devnull], bufsize=-1, stdout=flog, stderr=flog); ++ pinfo = os.wait4(cproc.pid, 0) ++ end_time = time.clock_gettime(time.CLOCK_MONOTONIC); ++ stats.elapsed = end_time - start_time ++ stats.user = pinfo[2].ru_utime ++ stats.sys = pinfo[2].ru_stime ++ return stats ++ ++ ++def common_prefix(s1, s2): ++ for i in range(min(len(s1),len(s2))): ++ if s1[i] != s2[i]: ++ return s1[:i] ++ return s1[:i+1] ++ ++def main(): ++ argp = argparse.ArgumentParser(description="FFmpeg performance compare") ++ ++ argp.add_argument("stream0", help="CSV to compare") ++ argp.add_argument("stream1", nargs='?', default="ffperf_out.csv", help="CSV to compare") ++ ++ args = argp.parse_args() ++ ++ with open(args.stream0, 'r', newline='') as f_in: ++ stats0 = {x["name"]:tstats(x) for x in csv.DictReader(f_in)} ++ with open(args.stream1, 'r', newline='') as f_in: ++ stats1 = {x["name"]:tstats(x) for x in csv.DictReader(f_in)} ++ ++ print (args.stream0, "<<-->>", args.stream1) ++ print () ++ ++ for f in sorted(stats0.keys() | stats1.keys(), key=lambda x : "~" * x.count(os.sep) + x.lower()): ++ if not (f in stats0) : ++ print (" XX :", f) ++ continue ++ if not (f in stats1) : ++ print (" XX :", f) ++ continue ++ ++ s0 = stats0[f] ++ s1 = stats1[f] ++ ++ pcent = ((s0.elapsed - s1.elapsed) / s0.elapsed) * 100.0 ++ thresh = 0.3 ++ tc = 6 ++ ++ nchar = min(tc - 1, int(abs(pcent) / thresh)) ++ cc = " -- " if nchar == 0 else "<" * nchar + " " * (tc - nchar) if pcent < 0 else " " * (tc - nchar) + ">" * nchar ++ ++ print ("%6.2f %s%6.2f (%+5.2f) : %s" % ++ (s0.elapsed, cc, s1.elapsed, pcent, f)) ++ ++ return 0 ++ ++ ++if __name__ == '__main__': ++ exit(main()) ++ +diff --git a/pi-util/qem.sh b/pi-util/qem.sh +new file mode 100755 +index 0000000000..a4dbb6eacd +--- /dev/null ++++ b/pi-util/qem.sh +@@ -0,0 +1,9 @@ ++TARGET_DIR=../src/eupton_vc4dev_2012a/software/vc4/DEV/applications/tutorials/user_shader_example_tex ++QASM=python\ ../local/bin/qasm.py ++SRC_FILE=libavcodec/rpi_hevc_shader.qasm ++DST_BASE=shader ++ ++cp libavcodec/rpi_hevc_shader_cmd.h $TARGET_DIR ++$QASM -mc_c:$DST_BASE,$DST_BASE,$DST_BASE $SRC_FILE > $TARGET_DIR/$DST_BASE.c ++$QASM -mc_h:$DST_BASE,$DST_BASE,$DST_BASE $SRC_FILE > $TARGET_DIR/$DST_BASE.h ++ +diff --git a/pi-util/v3dusage.py b/pi-util/v3dusage.py +new file mode 100755 +index 0000000000..5935a11ca5 +--- /dev/null ++++ b/pi-util/v3dusage.py +@@ -0,0 +1,128 @@ ++#!/usr/bin/env python ++ ++import sys ++import argparse ++import re ++ ++def do_logparse(logname): ++ ++ rmatch = re.compile(r'^([0-9]+\.[0-9]{3}): (done )?((vpu0)|(vpu1)|(qpu1)) ([A-Z_]+) cb:([0-9a-f]+) ') ++ rqcycle = re.compile(r'^([0-9]+\.[0-9]{3}): v3d: QPU Total clock cycles for all QPUs doing vertex/coordinate shading +([0-9]+)$') ++ rqtscycle = re.compile(r'^([0-9]+\.[0-9]{3}): v3d: QPU Total clock cycles for all QPUs stalled waiting for TMUs +([0-9]+)$') ++ rl2hits = re.compile(r'^([0-9]+\.[0-9]{3}): v3d: L2C Total Level 2 cache ([a-z]+) +([0-9]+)$') ++ ++ ttotal = {'idle':0.0} ++ tstart = {} ++ qctotal = {} ++ qtstotal = {} ++ l2hits = {} ++ l2total = {} ++ time0 = None ++ idle_start = None ++ qpu_op_no = 0 ++ op_count = 0 ++ ++ with open(logname, "rt") as infile: ++ for line in infile: ++ match = rmatch.match(line) ++ if match: ++# print match.group(1), ":", match.group(2), ":", match.group(3), ":", match.group(7), ":" ++ time = float(match.group(1)) ++ unit = match.group(3) ++ opstart = not match.group(2) ++ optype = match.group(7) ++ hascb = match.group(8) != "0" ++ ++ if unit == 'qpu1': ++ unit = unit + "." + str(qpu_op_no) ++ if not opstart: ++ if hascb or optype == 'EXECUTE_SYNC': ++ qpu_op_no = 0 ++ else: ++ qpu_op_no += 1 ++ ++ # Ignore sync type ++ if optype == 'EXECUTE_SYNC': ++ continue ++ ++ if not time0: ++ time0 = time ++ ++ if opstart: ++ tstart[unit] = time; ++ elif unit in tstart: ++ op_count += 1 ++ if not unit in ttotal: ++ ttotal[unit] = 0.0 ++ ttotal[unit] += time - tstart[unit] ++ del tstart[unit] ++ ++ if not idle_start and not tstart: ++ idle_start = time ++ elif idle_start and tstart: ++ ttotal['idle'] += time - idle_start ++ idle_start = None ++ ++ match = rqcycle.match(line) ++ if match: ++ unit = "qpu1." + str(qpu_op_no) ++ if not unit in qctotal: ++ qctotal[unit] = 0 ++ qctotal[unit] += int(match.group(2)) ++ ++ match = rqtscycle.match(line) ++ if match: ++ unit = "qpu1." + str(qpu_op_no) ++ if not unit in qtstotal: ++ qtstotal[unit] = 0 ++ qtstotal[unit] += int(match.group(2)) ++ ++ match = rl2hits.match(line) ++ if match: ++ unit = "qpu1." + str(qpu_op_no) ++ if not unit in l2total: ++ l2total[unit] = 0 ++ l2hits[unit] = 0 ++ l2total[unit] += int(match.group(3)) ++ if match.group(2) == "hits": ++ l2hits[unit] += int(match.group(3)) ++ ++ ++ if not time0: ++ print "No v3d profile records found" ++ else: ++ tlogged = time - time0 ++ ++ print "Logged time:", tlogged, " Op count:", op_count ++ for unit in sorted(ttotal): ++ print b'%6s: %10.3f %7.3f%%' % (unit, ttotal[unit], ttotal[unit] * 100.0 / tlogged) ++ print ++ for unit in sorted(qctotal): ++ if not unit in qtstotal: ++ qtstotal[unit] = 0; ++ print b'%6s: Qcycles: %10d, TMU stall: %10d (%7.3f%%)' % (unit, qctotal[unit], qtstotal[unit], (qtstotal[unit] * 100.0)/qctotal[unit]) ++ if unit in l2total: ++ print b' L2Total: %10d, hits: %10d (%7.3f%%)' % (l2total[unit], l2hits[unit], (l2hits[unit] * 100.0)/l2total[unit]) ++ ++ ++ ++if __name__ == '__main__': ++ argp = argparse.ArgumentParser( ++ formatter_class=argparse.RawDescriptionHelpFormatter, ++ description="QPU/VPU perf summary from VC logging", ++ epilog = """ ++Will also summarise TMU stalls if logging requests set in qpu noflush param ++in the profiled code. ++ ++Example use: ++ vcgencmd set_logging level=0xc0 ++ ++ sudo vcdbg log msg >& t.log ++ v3dusage.py t.log ++""") ++ ++ argp.add_argument("logfile") ++ args = argp.parse_args() ++ ++ do_logparse(args.logfile) ++ diff --git a/packages/multimedia/ffmpeg/patches/v4l2-drmprime/ffmpeg-001-v4l2-drmprime.patch b/packages/multimedia/ffmpeg/patches/v4l2-drmprime/ffmpeg-001-v4l2-drmprime.patch new file mode 100644 index 000000000..9313375a3 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/v4l2-drmprime/ffmpeg-001-v4l2-drmprime.patch @@ -0,0 +1,970 @@ +From b29b5b9f529bbb10cd9880adebf0fb287dcf233b Mon Sep 17 00:00:00 2001 +From: Andriy Gelman +Date: Tue, 28 Apr 2020 22:54:21 -0400 +Subject: [PATCH 01/11] avcodec/v4l2_m2m: Adapt to call close() on init fail + +This fixes several mem leaks when init of encoder/decoder failed. + +Fixes ticket #8285 + +Signed-off-by: Andriy Gelman +--- + libavcodec/v4l2_m2m.c | 8 ++++++++ + libavcodec/v4l2_m2m_dec.c | 10 ++-------- + libavcodec/v4l2_m2m_enc.c | 1 + + 3 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c +index e48b3a8ccf..bfea70ff0c 100644 +--- a/libavcodec/v4l2_m2m.c ++++ b/libavcodec/v4l2_m2m.c +@@ -338,6 +338,13 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + V4L2m2mContext *s = priv->context; + int ret; + ++ if (!s) ++ return 0; ++ ++ if (av_codec_is_decoder(s->avctx->codec)) ++ av_packet_unref(&s->buf_pkt); ++ ++ if (s->fd >= 0) { + ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); + if (ret) + av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); +@@ -345,6 +352,7 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); + if (ret) + av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ } + + ff_v4l2_context_release(&s->output); + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 3e17e0fcac..a2ea0ff73a 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -212,9 +212,6 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + ret = ff_v4l2_m2m_codec_init(priv); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); +- s->self_ref = NULL; +- av_buffer_unref(&priv->context_ref); +- + return ret; + } + +@@ -223,10 +220,7 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + + static av_cold int v4l2_decode_close(AVCodecContext *avctx) + { +- V4L2m2mPriv *priv = avctx->priv_data; +- V4L2m2mContext *s = priv->context; +- av_packet_unref(&s->buf_pkt); +- return ff_v4l2_m2m_codec_end(priv); ++ return ff_v4l2_m2m_codec_end(avctx->priv_data); + } + + #define OFFSET(x) offsetof(V4L2m2mPriv, x) +@@ -261,7 +255,7 @@ static const AVOption options[] = { + .close = v4l2_decode_close, \ + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ +- .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ ++ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "v4l2m2m", \ + } + +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index 32321f392f..9f1b2c2ffc 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -416,6 +416,7 @@ static const AVCodecDefault v4l2_m2m_defaults[] = { + .close = v4l2_encode_close, \ + .defaults = v4l2_m2m_defaults, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "v4l2m2m", \ + } + + +From 7aaac68934c0e03a78c9f477ec64e522729a64b7 Mon Sep 17 00:00:00 2001 +From: Andriy Gelman +Date: Tue, 5 May 2020 01:54:54 -0400 +Subject: [PATCH 02/11] avcodec/v4l2_m2m_dec: Use av_packet_move_ref() + +Signed-off-by: Andriy Gelman +--- + libavcodec/v4l2_m2m_dec.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index a2ea0ff73a..45e9a8e9fe 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -142,8 +142,7 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) + int ret; + + if (s->buf_pkt.size) { +- avpkt = s->buf_pkt; +- memset(&s->buf_pkt, 0, sizeof(AVPacket)); ++ av_packet_move_ref(&avpkt, &s->buf_pkt); + } else { + ret = ff_decode_get_packet(avctx, &avpkt); + if (ret < 0 && ret != AVERROR_EOF) + +From c6b85ed30f06ea99513b13cc768a922ebe4d68c2 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Tue, 24 Apr 2018 23:00:23 -0700 +Subject: [PATCH 03/11] libavcodec: v4l2m2m: output AVDRMFrameDescriptor + +This allows for a zero-copy output by exporting the v4l2 buffer then wrapping that buffer +in the AVDRMFrameDescriptor like it is done in rkmpp. + +This has been in use for quite some time with great success on many platforms including: + - Amlogic S905 + - Raspberry Pi + - i.MX6 + - Dragonboard 410c + +This was developed in conjunction with Kodi to allow handling the zero-copy buffer rendering. +A simply utility for testing is also available here: https://github.com/BayLibre/ffmpeg-drm + +todo: + - allow selecting pixel format output from decoder + - allow configuring amount of output and capture buffers + +V2: + - allow selecting AV_PIX_FMT_DRM_PRIME + +V3: + - use get_format to select AV_PIX_FMT_DRM_PRIME + - use hw_configs + - add handling of AV_PIX_FMT_YUV420P format (for raspberry pi) + - add handling of AV_PIX_FMT_YUYV422 format (for i.MX6 coda decoder) + +V4: + - rebased on 4.2.2 + +V5: + - rebased on 4.3 +--- + libavcodec/v4l2_buffers.c | 155 ++++++++++++++++++++++++++++++++++++-- + libavcodec/v4l2_buffers.h | 4 + + libavcodec/v4l2_context.c | 40 +++++++++- + libavcodec/v4l2_m2m.h | 3 + + libavcodec/v4l2_m2m_dec.c | 23 ++++++ + 5 files changed, 213 insertions(+), 12 deletions(-) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 02f23d954b..4bb2bf6f87 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -21,6 +21,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#include + #include + #include + #include +@@ -30,6 +31,7 @@ + #include "libavcodec/avcodec.h" + #include "libavcodec/internal.h" + #include "libavutil/pixdesc.h" ++#include "libavutil/hwcontext.h" + #include "v4l2_context.h" + #include "v4l2_buffers.h" + #include "v4l2_m2m.h" +@@ -210,7 +212,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) + return AVCOL_TRC_UNSPECIFIED; + } + +-static void v4l2_free_buffer(void *opaque, uint8_t *unused) ++static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) ++{ ++ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; ++ AVDRMLayerDescriptor *layer; ++ ++ /* fill the DRM frame descriptor */ ++ drm_desc->nb_objects = avbuf->num_planes; ++ drm_desc->nb_layers = 1; ++ ++ layer = &drm_desc->layers[0]; ++ layer->nb_planes = avbuf->num_planes; ++ ++ for (int i = 0; i < avbuf->num_planes; i++) { ++ layer->planes[i].object_index = i; ++ layer->planes[i].offset = 0; ++ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline; ++ } ++ ++ switch (avbuf->context->av_pix_fmt) { ++ case AV_PIX_FMT_YUYV422: ++ ++ layer->format = DRM_FORMAT_YUYV; ++ layer->nb_planes = 1; ++ ++ break; ++ ++ case AV_PIX_FMT_NV12: ++ case AV_PIX_FMT_NV21: ++ ++ layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ? ++ DRM_FORMAT_NV12 : DRM_FORMAT_NV21; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 2; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height; ++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; ++ break; ++ ++ case AV_PIX_FMT_YUV420P: ++ ++ layer->format = DRM_FORMAT_YUV420; ++ ++ if (avbuf->num_planes > 1) ++ break; ++ ++ layer->nb_planes = 3; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height; ++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1; ++ ++ layer->planes[2].object_index = 0; ++ layer->planes[2].offset = layer->planes[1].offset + ++ ((avbuf->plane_info[0].bytesperline * ++ avbuf->context->format.fmt.pix.height) >> 2); ++ layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1; ++ break; ++ ++ default: ++ drm_desc->nb_layers = 0; ++ break; ++ } ++ ++ return (uint8_t *) drm_desc; ++} ++ ++static void v4l2_free_buffer(void *opaque, uint8_t *data) + { + V4L2Buffer* avbuf = opaque; + V4L2m2mContext *s = buf_to_m2mctx(avbuf); +@@ -234,6 +308,36 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) + } + } + ++static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) ++{ ++ struct v4l2_exportbuffer expbuf; ++ int i, ret; ++ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ memset(&expbuf, 0, sizeof(expbuf)); ++ ++ expbuf.index = avbuf->buf.index; ++ expbuf.type = avbuf->buf.type; ++ expbuf.plane = i; ++ ++ ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_EXPBUF, &expbuf); ++ if (ret < 0) ++ return AVERROR(errno); ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) { ++ /* drm frame */ ++ avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length; ++ avbuf->drm_frame.objects[i].fd = expbuf.fd; ++ } else { ++ /* drm frame */ ++ avbuf->drm_frame.objects[0].size = avbuf->buf.length; ++ avbuf->drm_frame.objects[0].fd = expbuf.fd; ++ } ++ } ++ ++ return 0; ++} ++ + static int v4l2_buf_increase_ref(V4L2Buffer *in) + { + V4L2m2mContext *s = buf_to_m2mctx(in); +@@ -254,6 +358,24 @@ static int v4l2_buf_increase_ref(V4L2Buffer *in) + return 0; + } + ++static int v4l2_buf_to_bufref_drm(V4L2Buffer *in, AVBufferRef **buf) ++{ ++ int ret; ++ ++ *buf = av_buffer_create((uint8_t *) &in->drm_frame, ++ sizeof(in->drm_frame), ++ v4l2_free_buffer, ++ in, AV_BUFFER_FLAG_READONLY); ++ if (!*buf) ++ return AVERROR(ENOMEM); ++ ++ ret = v4l2_buf_increase_ref(in); ++ if (ret) ++ av_buffer_unref(buf); ++ ++ return ret; ++} ++ + static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) + { + int ret; +@@ -303,13 +425,24 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + + frame->format = avbuf->context->av_pix_fmt; + +- for (i = 0; i < avbuf->num_planes; i++) { +- ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ /* 1. get references to the actual data */ ++ ret = v4l2_buf_to_bufref_drm(avbuf, &frame->buf[0]); + if (ret) + return ret; + +- frame->linesize[i] = avbuf->plane_info[i].bytesperline; +- frame->data[i] = frame->buf[i]->data; ++ frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf); ++ frame->format = AV_PIX_FMT_DRM_PRIME; ++ } else { ++ /* 1. get references to the actual data */ ++ for (i = 0; i < avbuf->num_planes; i++) { ++ ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); ++ if (ret) ++ return ret; ++ ++ frame->linesize[i] = avbuf->plane_info[i].bytesperline; ++ frame->data[i] = frame->buf[i]->data; ++ } + } + + /* fixup special cases */ +@@ -543,9 +676,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + + avbuf->status = V4L2BUF_AVAILABLE; + +- if (V4L2_TYPE_IS_OUTPUT(ctx->type)) +- return 0; +- + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->buf.m.planes = avbuf->planes; + avbuf->buf.length = avbuf->num_planes; +@@ -555,6 +685,15 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + avbuf->buf.length = avbuf->planes[0].length; + } + ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) ++ return 0; ++ ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ ret = v4l2_buffer_export_drm(avbuf); ++ if (ret) ++ return ret; ++ } ++ + return ff_v4l2_buffer_enqueue(avbuf); + } + +diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h +index 8dbc7fc104..037e667997 100644 +--- a/libavcodec/v4l2_buffers.h ++++ b/libavcodec/v4l2_buffers.h +@@ -27,6 +27,7 @@ + #include + #include + ++#include "libavutil/hwcontext_drm.h" + #include "avcodec.h" + + enum V4L2Buffer_status { +@@ -42,6 +43,9 @@ typedef struct V4L2Buffer { + /* each buffer needs to have a reference to its context */ + struct V4L2Context *context; + ++ /* DRM descriptor */ ++ AVDRMFrameDescriptor drm_frame; ++ + /* This object is refcounted per-plane, so we need to keep track + * of how many context-refs we are holding. */ + AVBufferRef *context_ref; +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index 29b144ed73..7a92df2c3e 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -455,22 +455,54 @@ static int v4l2_release_buffers(V4L2Context* ctx) + struct v4l2_requestbuffers req = { + .memory = V4L2_MEMORY_MMAP, + .type = ctx->type, +- .count = 0, /* 0 -> unmaps buffers from the driver */ ++ .count = 0, /* 0 -> unmap all buffers from the driver */ + }; +- int i, j; ++ int ret, i, j; + + for (i = 0; i < ctx->num_buffers; i++) { + V4L2Buffer *buffer = &ctx->buffers[i]; + + for (j = 0; j < buffer->num_planes; j++) { + struct V4L2Plane_info *p = &buffer->plane_info[j]; ++ ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) { ++ /* output buffers are not EXPORTED */ ++ goto unmap; ++ } ++ ++ if (ctx_to_m2mctx(ctx)->output_drm) { ++ /* use the DRM frame to close */ ++ if (buffer->drm_frame.objects[j].fd >= 0) { ++ if (close(buffer->drm_frame.objects[j].fd) < 0) { ++ av_log(logger(ctx), AV_LOG_ERROR, "%s close drm fd " ++ "[buffer=%2d, plane=%d, fd=%2d] - %s \n", ++ ctx->name, i, j, buffer->drm_frame.objects[j].fd, ++ av_err2str(AVERROR(errno))); ++ } ++ } ++ } ++unmap: + if (p->mm_addr && p->length) + if (munmap(p->mm_addr, p->length) < 0) +- av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno))); ++ av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ++ ctx->name, av_err2str(AVERROR(errno))); + } + } + +- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); ++ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); ++ if (ret < 0) { ++ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n", ++ ctx->name, av_err2str(AVERROR(errno))); ++ ++ if (ctx_to_m2mctx(ctx)->output_drm) ++ av_log(logger(ctx), AV_LOG_ERROR, ++ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n" ++ "for all buffers: \n" ++ " 1. drmModeRmFB(..)\n" ++ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n"); ++ } ++ ++ return ret; + } + + static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt) +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 456281f48c..4ee0be653b 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -63,6 +63,9 @@ typedef struct V4L2m2mContext { + + /* reference back to V4L2m2mPriv */ + void *priv; ++ ++ /* generate DRM frames */ ++ int output_drm; + } V4L2m2mContext; + + typedef struct V4L2m2mPriv { +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 45e9a8e9fe..eb6ecc8ed5 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -23,6 +23,9 @@ + + #include + #include ++ ++#include "libavutil/hwcontext.h" ++#include "libavutil/hwcontext_drm.h" + #include "libavutil/pixfmt.h" + #include "libavutil/pixdesc.h" + #include "libavutil/opt.h" +@@ -30,6 +33,9 @@ + #include "libavcodec/decode.h" + #include "libavcodec/internal.h" + ++#include "libavcodec/hwaccels.h" ++#include "libavcodec/internal.h" ++ + #include "v4l2_context.h" + #include "v4l2_m2m.h" + #include "v4l2_fmt.h" +@@ -207,6 +213,15 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; + capture->av_pix_fmt = avctx->pix_fmt; + ++ /* the client requests the codec to generate DRM frames: ++ * - data[0] will therefore point to the returned AVDRMFrameDescriptor ++ * check the ff_v4l2_buffer_to_avframe conversion function. ++ * - the DRM frame format is passed in the DRM frame descriptor layer. ++ * check the v4l2_get_drm_frame function. ++ */ ++ if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME) ++ s->output_drm = 1; ++ + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); + if (ret) { +@@ -232,6 +247,11 @@ static const AVOption options[] = { + { NULL}, + }; + ++static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = { ++ HW_CONFIG_INTERNAL(DRM_PRIME), ++ NULL ++}; ++ + #define M2MDEC_CLASS(NAME) \ + static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ + .class_name = #NAME "_v4l2m2m_decoder", \ +@@ -255,6 +275,9 @@ static const AVOption options[] = { + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ ++ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NONE}, \ ++ .hw_configs = v4l2_m2m_hw_configs, \ + .wrapper_name = "v4l2m2m", \ + } + + +From 2b5cd753892dceba3b211053a6266c40aab38c55 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:09:40 -0700 +Subject: [PATCH 04/11] libavcodec: v4l2m2m: depends on libdrm + +--- + configure | 1 + + libavcodec/v4l2_buffers.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index 8569a60bf8..a049707dd6 100755 +--- a/configure ++++ b/configure +@@ -3401,6 +3401,7 @@ sndio_indev_deps="sndio" + sndio_outdev_deps="sndio" + v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" + v4l2_indev_suggest="libv4l2" ++v4l2_outdev_deps="libdrm" + v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h" + v4l2_outdev_suggest="libv4l2" + vfwcap_indev_deps="vfw32 vfwcap_defines" +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 4bb2bf6f87..c36a73d1fa 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -21,7 +21,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include ++#include + #include + #include + #include + +From 09a0f1b99548a249991891ee4e02ae6613b545d7 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:10:13 -0700 +Subject: [PATCH 05/11] libavcodec: v4l2m2m: set format_modifier to + DRM_FORMAT_MOD_LINEAR + +--- + libavcodec/v4l2_buffers.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index c36a73d1fa..072b77bbda 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -328,10 +328,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) + /* drm frame */ + avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length; + avbuf->drm_frame.objects[i].fd = expbuf.fd; ++ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR; + } else { + /* drm frame */ + avbuf->drm_frame.objects[0].size = avbuf->buf.length; + avbuf->drm_frame.objects[0].fd = expbuf.fd; ++ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; + } + } + + +From e8df5a982f705aaba1e03aef653169bc17a0d464 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:10:53 -0700 +Subject: [PATCH 06/11] libavcodec: v4l2m2m: only mmap the buffer when it is + output type and drm prime is used + +--- + libavcodec/v4l2_buffers.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 072b77bbda..8162531973 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -662,14 +662,22 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length; +- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length, +- PROT_READ | PROT_WRITE, MAP_SHARED, +- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset); ++ ++ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) || ++ !buf_to_m2mctx(avbuf)->output_drm) { ++ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset); ++ } + } else { + avbuf->plane_info[i].length = avbuf->buf.length; +- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length, +- PROT_READ | PROT_WRITE, MAP_SHARED, +- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset); ++ ++ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) || ++ !buf_to_m2mctx(avbuf)->output_drm) { ++ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset); ++ } + } + + if (avbuf->plane_info[i].mm_addr == MAP_FAILED) + +From 4fb7664bb6be542b691323a03050cdd024585afc Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Thu, 16 Aug 2018 21:11:38 -0700 +Subject: [PATCH 07/11] libavcodec: v4l2m2m: allow using software pixel formats + +--- + libavcodec/v4l2_m2m_dec.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index eb6ecc8ed5..3b2449ae6c 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -219,8 +219,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + * - the DRM frame format is passed in the DRM frame descriptor layer. + * check the v4l2_get_drm_frame function. + */ +- if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME) ++ switch (ff_get_format(avctx, avctx->codec->pix_fmts)) { ++ case AV_PIX_FMT_DRM_PRIME: + s->output_drm = 1; ++ break; ++ case AV_PIX_FMT_NONE: ++ return 0; ++ break; ++ default: ++ break; ++ } + + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); +@@ -276,6 +284,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = { + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_NV12, \ + AV_PIX_FMT_NONE}, \ + .hw_configs = v4l2_m2m_hw_configs, \ + .wrapper_name = "v4l2m2m", \ + +From 27ae887df07992385b1afc9b532f978066e83774 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Mon, 24 Sep 2018 13:39:31 -0700 +Subject: [PATCH 08/11] libavcodec: v4l2m2m: implement hwcontext + +--- + libavcodec/v4l2_buffers.c | 22 ++++++++++++++++++++++ + libavcodec/v4l2_context.h | 2 ++ + libavcodec/v4l2_m2m.h | 2 ++ + libavcodec/v4l2_m2m_dec.c | 11 +++++++++++ + 4 files changed, 37 insertions(+) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index 8162531973..9c5d471c9b 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -435,6 +435,7 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + + frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf); + frame->format = AV_PIX_FMT_DRM_PRIME; ++ frame->hw_frames_ctx = av_buffer_ref(avbuf->context->frames_ref); + } else { + /* 1. get references to the actual data */ + for (i = 0; i < avbuf->num_planes; i++) { +@@ -635,6 +636,27 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + avbuf->buf.type = ctx->type; + avbuf->buf.index = index; + ++ if (buf_to_m2mctx(avbuf)->output_drm) { ++ AVHWFramesContext *hwframes; ++ ++ av_buffer_unref(&ctx->frames_ref); ++ ++ ctx->frames_ref = av_hwframe_ctx_alloc(buf_to_m2mctx(avbuf)->device_ref); ++ if (!ctx->frames_ref) { ++ ret = AVERROR(ENOMEM); ++ return ret; ++ } ++ ++ hwframes = (AVHWFramesContext*)ctx->frames_ref->data; ++ hwframes->format = AV_PIX_FMT_DRM_PRIME; ++ hwframes->sw_format = ctx->av_pix_fmt; ++ hwframes->width = ctx->width; ++ hwframes->height = ctx->height; ++ ret = av_hwframe_ctx_init(ctx->frames_ref); ++ if (ret < 0) ++ return ret; ++ } ++ + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + avbuf->buf.length = VIDEO_MAX_PLANES; + avbuf->buf.m.planes = avbuf->planes; +diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h +index 22a9532444..e804e94131 100644 +--- a/libavcodec/v4l2_context.h ++++ b/libavcodec/v4l2_context.h +@@ -92,6 +92,8 @@ typedef struct V4L2Context { + */ + int done; + ++ AVBufferRef *frames_ref; ++ + } V4L2Context; + + /** +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 4ee0be653b..61cb919771 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -64,6 +64,8 @@ typedef struct V4L2m2mContext { + /* reference back to V4L2m2mPriv */ + void *priv; + ++ AVBufferRef *device_ref; ++ + /* generate DRM frames */ + int output_drm; + } V4L2m2mContext; +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 3b2449ae6c..c6b865fde8 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -35,6 +35,7 @@ + + #include "libavcodec/hwaccels.h" + #include "libavcodec/internal.h" ++#include "libavcodec/hwconfig.h" + + #include "v4l2_context.h" + #include "v4l2_m2m.h" +@@ -230,6 +231,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + break; + } + ++ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM); ++ if (!s->device_ref) { ++ ret = AVERROR(ENOMEM); ++ return ret; ++ } ++ ++ ret = av_hwdevice_ctx_init(s->device_ref); ++ if (ret < 0) ++ return ret; ++ + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); + if (ret) { + +From aee464209ec6ad060d352dfb638344a1f4db3ce4 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Mon, 4 May 2020 13:01:29 -0700 +Subject: [PATCH 09/11] libavcodec: v4l2m2m: allow lower minimum buffer values + +There is no reason to enforce a high minimum. In the context +of streaming only a few output buffers and capture buffers +are even needed for continuous playback. This also helps +alleviate memory pressure when decoding 4K media. +--- + libavcodec/v4l2_m2m.h | 2 +- + libavcodec/v4l2_m2m_dec.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index 61cb919771..feeb162812 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -38,7 +38,7 @@ + + #define V4L_M2M_DEFAULT_OPTS \ + { "num_output_buffers", "Number of buffers in the output context",\ +- OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS } ++ OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 2, INT_MAX, FLAGS } + + typedef struct V4L2m2mContext { + char devname[PATH_MAX]; +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index c6b865fde8..b9725be377 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -262,7 +262,7 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) + static const AVOption options[] = { + V4L_M2M_DEFAULT_OPTS, + { "num_capture_buffers", "Number of buffers in the capture context", +- OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, ++ OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS }, + { NULL}, + }; + + +From ffc4419f456c00ab71cf93f792b0473c6de14e64 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Wed, 6 May 2020 11:12:58 -0700 +Subject: [PATCH 10/11] libavcodec: v4l2m2m: add option to specify pixel format + used by the decoder + +--- + libavcodec/v4l2_context.c | 9 +++++++++ + libavcodec/v4l2_m2m.h | 2 ++ + libavcodec/v4l2_m2m_dec.c | 1 + + 3 files changed, 12 insertions(+) + +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index 7a92df2c3e..fa2deae888 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -531,6 +531,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm + + static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) + { ++ V4L2m2mContext* s = ctx_to_m2mctx(ctx); ++ V4L2m2mPriv *priv = s->avctx->priv_data; + enum AVPixelFormat pixfmt = ctx->av_pix_fmt; + struct v4l2_fmtdesc fdesc; + int ret; +@@ -549,6 +551,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) + if (ret) + return AVERROR(EINVAL); + ++ if (priv->pix_fmt != AV_PIX_FMT_NONE) { ++ if (fdesc.pixelformat != ff_v4l2_format_avfmt_to_v4l2(priv->pix_fmt)) { ++ fdesc.index++; ++ continue; ++ } ++ } ++ + pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO); + ret = v4l2_try_raw_format(ctx, pixfmt); + if (ret){ +diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h +index feeb162812..0e88bf9329 100644 +--- a/libavcodec/v4l2_m2m.h ++++ b/libavcodec/v4l2_m2m.h +@@ -30,6 +30,7 @@ + #include + + #include "libavcodec/avcodec.h" ++#include "libavutil/pixfmt.h" + #include "v4l2_context.h" + + #define container_of(ptr, type, member) ({ \ +@@ -78,6 +79,7 @@ typedef struct V4L2m2mPriv { + + int num_output_buffers; + int num_capture_buffers; ++ enum AVPixelFormat pix_fmt; + } V4L2m2mPriv; + + /** +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index b9725be377..6109deee8a 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -263,6 +263,7 @@ static const AVOption options[] = { + V4L_M2M_DEFAULT_OPTS, + { "num_capture_buffers", "Number of buffers in the capture context", + OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS }, ++ { "pixel_format", "Pixel format to be used by the decoder", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, AV_PIX_FMT_NB, FLAGS }, + { NULL}, + }; + + +From 8595d06d4909bbec0aa14625fcfc869c6bcef696 Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Mon, 24 Sep 2018 13:39:56 -0700 +Subject: [PATCH 11/11] libavcodec: v4l2m2m: implement flush + +--- + libavcodec/v4l2_m2m_dec.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 6109deee8a..820cdf241f 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -256,6 +256,41 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) + return ff_v4l2_m2m_codec_end(avctx->priv_data); + } + ++static void v4l2_decode_flush(AVCodecContext *avctx) ++{ ++ V4L2m2mPriv *priv = avctx->priv_data; ++ V4L2m2mContext* s = priv->context; ++ V4L2Context* output = &s->output; ++ V4L2Context* capture = &s->capture; ++ int ret, i; ++ ++ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s error: %d\n", output->name, ret); ++ ++ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON %s error: %d\n", output->name, ret); ++ ++ for (i = 0; i < output->num_buffers; i++) { ++ if (output->buffers[i].status == V4L2BUF_IN_DRIVER) ++ output->buffers[i].status = V4L2BUF_AVAILABLE; ++ } ++ ++ struct v4l2_decoder_cmd cmd = { ++ .cmd = V4L2_DEC_CMD_START, ++ .flags = 0, ++ }; ++ ++ ret = ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_DECODER_CMD start error: %d\n", errno); ++ ++ s->draining = 0; ++ output->done = 0; ++ capture->done = 0; ++} ++ + #define OFFSET(x) offsetof(V4L2m2mPriv, x) + #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +@@ -292,6 +327,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = { + .init = v4l2_decode_init, \ + .receive_frame = v4l2_receive_frame, \ + .close = v4l2_decode_close, \ ++ .flush = v4l2_decode_flush, \ + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ diff --git a/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch b/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch new file mode 100644 index 000000000..344fa1112 --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch @@ -0,0 +1,5843 @@ +From 785728e72dbd513b58d97af2590fafba0f8a24bb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 3 Dec 2018 23:48:04 +0100 +Subject: [PATCH 01/20] avutil: add av_buffer_pool_flush() + +Signed-off-by: Jonas Karlman +--- + libavutil/buffer.c | 13 +++++++++++++ + libavutil/buffer.h | 5 +++++ + 2 files changed, 18 insertions(+) + +diff --git a/libavutil/buffer.c b/libavutil/buffer.c +index 38a554208a9..b0fedabc3e7 100644 +--- a/libavutil/buffer.c ++++ b/libavutil/buffer.c +@@ -273,6 +273,19 @@ static void buffer_pool_free(AVBufferPool *pool) + av_freep(&pool); + } + ++void av_buffer_pool_flush(AVBufferPool *pool) ++{ ++ ff_mutex_lock(&pool->mutex); ++ while (pool->pool) { ++ BufferPoolEntry *buf = pool->pool; ++ pool->pool = buf->next; ++ ++ buf->free(buf->opaque, buf->data); ++ av_freep(&buf); ++ } ++ ff_mutex_unlock(&pool->mutex); ++} ++ + void av_buffer_pool_uninit(AVBufferPool **ppool) + { + AVBufferPool *pool; +diff --git a/libavutil/buffer.h b/libavutil/buffer.h +index c0f3f6cc9ab..998beec9ac5 100644 +--- a/libavutil/buffer.h ++++ b/libavutil/buffer.h +@@ -267,6 +267,11 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), + void (*pool_free)(void *opaque)); + ++/** ++ * Free all available buffers in a buffer pool. ++ */ ++ void av_buffer_pool_flush(AVBufferPool *pool); ++ + /** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + +From abd5308771a71ba582155a1665a1c40878232040 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 02/20] Add common V4L2 request API code + +Signed-off-by: Jonas Karlman +--- + configure | 12 + + libavcodec/Makefile | 1 + + libavcodec/hwconfig.h | 2 + + libavcodec/v4l2_request.c | 984 ++++++++++++++++++++++++++++++++++++++ + libavcodec/v4l2_request.h | 77 +++ + 5 files changed, 1076 insertions(+) + create mode 100644 libavcodec/v4l2_request.c + create mode 100644 libavcodec/v4l2_request.h + +diff --git a/configure b/configure +index 8569a60bf82..9f9909a2369 100755 +--- a/configure ++++ b/configure +@@ -274,6 +274,7 @@ External library support: + --enable-libtls enable LibreSSL (via libtls), needed for https support + if openssl, gnutls or mbedtls is not used [no] + --enable-libtwolame enable MP2 encoding via libtwolame [no] ++ --enable-libudev enable libudev [no] + --enable-libv4l2 enable libv4l2/v4l-utils [no] + --enable-libvidstab enable video stabilization using vid.stab [no] + --enable-libvmaf enable vmaf filter via libvmaf [no] +@@ -342,6 +343,7 @@ External library support: + --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] + --enable-rkmpp enable Rockchip Media Process Platform code [no] + --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect] ++ --enable-v4l2-request enable V4L2 request API code [no] + --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] + --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] + --disable-videotoolbox disable VideoToolbox code [autodetect] +@@ -1807,6 +1809,7 @@ EXTERNAL_LIBRARY_LIST=" + libtesseract + libtheora + libtwolame ++ libudev + libv4l2 + libvorbis + libvpx +@@ -1861,6 +1864,7 @@ HWACCEL_LIBRARY_LIST=" + mmal + omx + opencl ++ v4l2_request + vulkan + " + +@@ -2903,6 +2907,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" + dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" + ffnvcodec_deps_any="libdl LoadLibrary" + nvdec_deps="ffnvcodec" ++v4l2_request_deps="linux_videodev2_h linux_media_h v4l2_timeval_to_ns libdrm libudev" + vaapi_x11_deps="xlib" + videotoolbox_hwaccel_deps="videotoolbox pthreads" + videotoolbox_hwaccel_extralibs="-framework QuartzCore" +@@ -6376,6 +6381,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur + enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && + { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || + die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } ++enabled libudev && require_pkg_config libudev libudev libudev.h udev_new + enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl + enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit + enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf +@@ -6475,6 +6481,10 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/r + { enabled libdrm || + die "ERROR: rkmpp requires --enable-libdrm"; } + } ++enabled v4l2_request && { enabled libdrm || ++ die "ERROR: v4l2-request requires --enable-libdrm"; } && ++ { enabled libudev || ++ die "ERROR: v4l2-request requires --enable-libudev"; } + enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init + + +@@ -6556,6 +6566,8 @@ if enabled v4l2_m2m; then + check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" + fi + ++check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++ + check_headers sys/videoio.h + test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete + +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 5a6ea59715a..d7422051682 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -153,6 +153,7 @@ OBJS-$(CONFIG_VP3DSP) += vp3dsp.o + OBJS-$(CONFIG_VP56DSP) += vp56dsp.o + OBJS-$(CONFIG_VP8DSP) += vp8dsp.o + OBJS-$(CONFIG_V4L2_M2M) += v4l2_m2m.o v4l2_context.o v4l2_buffers.o v4l2_fmt.o ++OBJS-$(CONFIG_V4L2_REQUEST) += v4l2_request.o + OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o + OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o + +diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h +index f421dc909f4..ee78d8ab8e8 100644 +--- a/libavcodec/hwconfig.h ++++ b/libavcodec/hwconfig.h +@@ -80,6 +80,8 @@ typedef struct AVCodecHWConfigInternal { + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) + #define HWACCEL_XVMC(codec) \ + HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) ++#define HWACCEL_V4L2REQUEST(codec) \ ++ HW_CONFIG_HWACCEL(1, 0, 0, DRM_PRIME, DRM, ff_ ## codec ## _v4l2request_hwaccel) + + #define HW_CONFIG_ENCODER(device, frames, ad_hoc, format, device_type_) \ + &(const AVCodecHWConfigInternal) { \ +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +new file mode 100644 +index 00000000000..5234b5049b0 +--- /dev/null ++++ b/libavcodec/v4l2_request.c +@@ -0,0 +1,984 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "decode.h" ++#include "internal.h" ++#include "v4l2_request.h" ++ ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ return req ? v4l2_timeval_to_ns(&req->capture.buffer.timestamp) : 0; ++} ++ ++int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ memset(&req->drm, 0, sizeof(AVDRMFrameDescriptor)); ++ req->output.used = 0; ++ return 0; ++} ++ ++int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ if (req->output.used + size + (AV_INPUT_BUFFER_PADDING_SIZE * 4) <= req->output.size) { ++ memcpy(req->output.addr + req->output.used, data, size); ++ req->output.used += size; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "%s: output.used=%u output.size=%u size=%u\n", __func__, req->output.used, req->output.size, size); ++ } ++ return 0; ++} ++ ++static int v4l2_request_controls(V4L2RequestContext *ctx, int request_fd, unsigned long type, struct v4l2_ext_control *control, int count) ++{ ++ struct v4l2_ext_controls controls = { ++ .controls = control, ++ .count = count, ++ .request_fd = request_fd, ++ .which = (request_fd >= 0) ? V4L2_CTRL_WHICH_REQUEST_VAL : 0, ++ }; ++ ++ if (!control || !count) ++ return 0; ++ ++ return ioctl(ctx->video_fd, type, &controls); ++} ++ ++static int v4l2_request_set_controls(V4L2RequestContext *ctx, int request_fd, struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_controls(ctx, request_fd, VIDIOC_S_EXT_CTRLS, control, count); ++} ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = v4l2_request_controls(ctx, -1, VIDIOC_S_EXT_CTRLS, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return ret; ++} ++ ++int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = v4l2_request_controls(ctx, -1, VIDIOC_G_EXT_CTRLS, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return ret; ++} ++ ++int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control) ++{ ++ int ret; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERY_EXT_CTRL, control); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return 0; ++} ++ ++int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id) ++{ ++ int ret; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_queryctrl control = { ++ .id = id, ++ }; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYCTRL, &control); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return AVERROR(EINVAL); ++ } ++ ++ return control.default_value; ++} ++ ++static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf, uint32_t flags) ++{ ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_buffer buffer = { ++ .type = buf->buffer.type, ++ .memory = buf->buffer.memory, ++ .index = buf->index, ++ .timestamp.tv_usec = ctx->timestamp, ++ .bytesused = buf->used, ++ .request_fd = request_fd, ++ .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags, ++ }; ++ ++ buf->buffer.timestamp = buffer.timestamp; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { ++ planes[0].bytesused = buf->used; ++ buffer.bytesused = 0; ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ return ioctl(ctx->video_fd, VIDIOC_QBUF, &buffer); ++} ++ ++static int v4l2_request_dequeue_buffer(V4L2RequestContext *ctx, V4L2RequestBuffer *buf) ++{ ++ int ret; ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_buffer buffer = { ++ .type = buf->buffer.type, ++ .memory = buf->buffer.memory, ++ .index = buf->index, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) { ++ buffer.length = 1; ++ buffer.m.planes = planes; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_DQBUF, &buffer); ++ if (ret < 0) ++ return ret; ++ ++ buf->buffer.timestamp = buffer.timestamp; ++ return 0; ++} ++ ++const uint32_t v4l2_request_capture_pixelformats[] = { ++ V4L2_PIX_FMT_NV12, ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ V4L2_PIX_FMT_SUNXI_TILED_NV12, ++#endif ++}; ++ ++static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format) ++{ ++ AVDRMFrameDescriptor *desc = &req->drm; ++ AVDRMLayerDescriptor *layer = &desc->layers[0]; ++ uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.pixelformat : format->fmt.pix.pixelformat; ++ ++ switch (pixelformat) { ++ case V4L2_PIX_FMT_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED ++ case V4L2_PIX_FMT_SUNXI_TILED_NV12: ++ layer->format = DRM_FORMAT_NV12; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_ALLWINNER_TILED; ++ break; ++#endif ++ default: ++ return -1; ++ } ++ ++ desc->nb_objects = 1; ++ desc->objects[0].fd = req->capture.fd; ++ desc->objects[0].size = req->capture.size; ++ ++ desc->nb_layers = 1; ++ layer->nb_planes = 2; ++ ++ layer->planes[0].object_index = 0; ++ layer->planes[0].offset = 0; ++ layer->planes[0].pitch = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.plane_fmt[0].bytesperline : format->fmt.pix.bytesperline; ++ ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height); ++ layer->planes[1].pitch = layer->planes[0].pitch; ++ ++ return 0; ++} ++ ++static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ struct timeval tv = { 2, 0 }; ++ fd_set except_fds; ++ int ret; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice); ++ ++ if (first_slice) ++ ctx->timestamp++; ++ ++ ret = v4l2_request_set_controls(ctx, req->request_fd, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ memset(req->output.addr + req->output.used, 0, AV_INPUT_BUFFER_PADDING_SIZE * 4); ++ ++ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output, last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ if (first_slice) { ++ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture, 0); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ } ++ ++ // NOTE: do we need to dequeue when request fails/timeout? ++ ++ // 4. queue request and wait ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_QUEUE, NULL); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: queue request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ goto fail; ++ } ++ ++ FD_ZERO(&except_fds); ++ FD_SET(req->request_fd, &except_fds); ++ ++ ret = select(req->request_fd + 1, NULL, NULL, &except_fds, &tv); ++ if (ret == 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: request %d timeout\n", __func__, req->request_fd); ++ goto fail; ++ } else if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: select request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ goto fail; ++ } ++ ++ ret = v4l2_request_dequeue_buffer(ctx, &req->output); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ if (last_slice) { ++ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ } ++ ++ // TODO: check errors ++ // buffer.flags & V4L2_BUF_FLAG_ERROR ++ ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ return -1; ++ } ++ ++ if (last_slice) ++ return v4l2_request_set_drm_descriptor(req, &ctx->format); ++ ++ return 0; ++ ++fail: ++ ret = v4l2_request_dequeue_buffer(ctx, &req->output); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno); ++ ++ ret = v4l2_request_dequeue_buffer(ctx, &req->capture); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno); ++ ++ ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno); ++ ++ return -1; ++} ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice) ++{ ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; ++ ++ // fall back to queue each slice as a full frame ++ if ((req->output.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++ ++ return v4l2_request_queue_decode(avctx, frame, control, count, first_slice, last_slice); ++} ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count) ++{ ++ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1); ++} ++ ++static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ struct v4l2_create_buffers buffers = { ++ .count = 0, ++ .memory = V4L2_MEMORY_MMAP, ++ .format.type = type, ++ }; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return -1; ++ } ++ ++ if ((buffers.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) != V4L2_BUF_CAP_SUPPORTS_REQUESTS) { ++ av_log(avctx, AV_LOG_INFO, "%s: output buffer type do not support requests, capabilities %u\n", __func__, buffers.capabilities); ++ return -1; ++ } ++ } ++ ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ if (fmtdesc.pixelformat == pixelformat) ++ return 0; ++ ++ fmtdesc.index++; ++ } ++ ++ av_log(avctx, AV_LOG_INFO, "%s: pixelformat %u not supported for type %u\n", __func__, pixelformat, type); ++ return -1; ++} ++ ++static int v4l2_request_set_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat, uint32_t buffersize) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ struct v4l2_format format = { ++ .type = type, ++ }; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ format.fmt.pix_mp.width = avctx->coded_width; ++ format.fmt.pix_mp.height = avctx->coded_height; ++ format.fmt.pix_mp.pixelformat = pixelformat; ++ format.fmt.pix_mp.plane_fmt[0].sizeimage = buffersize; ++ format.fmt.pix_mp.num_planes = 1; ++ } else { ++ format.fmt.pix.width = avctx->coded_width; ++ format.fmt.pix.height = avctx->coded_height; ++ format.fmt.pix.pixelformat = pixelformat; ++ format.fmt.pix.sizeimage = buffersize; ++ } ++ ++ return ioctl(ctx->video_fd, VIDIOC_S_FMT, &format); ++} ++ ++static int v4l2_request_select_capture_format(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ enum v4l2_buf_type type = ctx->format.type; ++ ++#if 0 ++ struct v4l2_format format = { ++ .type = type, ++ }; ++ struct v4l2_fmtdesc fmtdesc = { ++ .index = 0, ++ .type = type, ++ }; ++ uint32_t pixelformat; ++ int i; ++ ++ if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &format) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return -1; ++ } ++ ++ pixelformat = V4L2_TYPE_IS_MULTIPLANAR(type) ? format.fmt.pix_mp.pixelformat : format.fmt.pix.pixelformat; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (pixelformat == v4l2_request_capture_pixelformats[i]) ++ return v4l2_request_set_format(avctx, type, pixelformat, 0); ++ } ++ ++ while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) { ++ for (i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ if (fmtdesc.pixelformat == v4l2_request_capture_pixelformats[i]) ++ return v4l2_request_set_format(avctx, type, fmtdesc.pixelformat, 0); ++ } ++ ++ fmtdesc.index++; ++ } ++#else ++ for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) { ++ uint32_t pixelformat = v4l2_request_capture_pixelformats[i]; ++ if (!v4l2_request_try_format(avctx, type, pixelformat)) ++ return v4l2_request_set_format(avctx, type, pixelformat, 0); ++ } ++#endif ++ ++ return -1; ++} ++ ++static int v4l2_request_probe_video_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret = AVERROR(EINVAL); ++ struct v4l2_capability capability = {0}; ++ unsigned int capabilities = 0; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get video device devnode failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ctx->video_fd = open(path, O_RDWR | O_NONBLOCK, 0); ++ if (ctx->video_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYCAP, &capability); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get video capability failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (capability.capabilities & V4L2_CAP_DEVICE_CAPS) ++ capabilities = capability.device_caps; ++ else ++ capabilities = capability.capabilities; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p path=%s capabilities=%u\n", __func__, avctx, ctx, path, capabilities); ++ ++ if ((capabilities & V4L2_CAP_STREAMING) != V4L2_CAP_STREAMING) { ++ av_log(avctx, AV_LOG_ERROR, "%s: missing required streaming capability\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if ((capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) == V4L2_CAP_VIDEO_M2M_MPLANE) { ++ ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ } else if ((capabilities & V4L2_CAP_VIDEO_M2M) == V4L2_CAP_VIDEO_M2M) { ++ ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "%s: missing required mem2mem capability\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_try_format(avctx, ctx->output_type, pixelformat); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_WARNING, "%s: try output format failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_set_format(avctx, ctx->output_type, pixelformat, buffersize); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set output format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_set_controls(ctx, -1, control, count); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = v4l2_request_select_capture_format(avctx); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_WARNING, "%s: select capture format failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ if (ctx->video_fd >= 0) { ++ close(ctx->video_fd); ++ ctx->video_fd = -1; ++ } ++ return ret; ++} ++ ++static int v4l2_request_init_context(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &ctx->format); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__, ctx->format.fmt.pix_mp.pixelformat, ctx->format.fmt.pix_mp.width, ctx->format.fmt.pix_mp.height, ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline, ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage, ctx->format.fmt.pix_mp.num_planes); ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__, ctx->format.fmt.pix.pixelformat, ctx->format.fmt.pix.width, ctx->format.fmt.pix.height, ctx->format.fmt.pix.bytesperline, ctx->format.fmt.pix.sizeimage); ++ } ++ ++ ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_DRM); ++ if (ret < 0) ++ goto fail; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->output_type); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: output stream on failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->format.type); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: capture stream on failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ ff_v4l2_request_uninit(avctx); ++ return ret; ++} ++ ++static int v4l2_request_probe_media_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ struct media_device_info device_info = {0}; ++ struct media_v2_topology topology = {0}; ++ struct media_v2_interface *interfaces = NULL; ++ struct udev *udev = udev_device_get_udev(device); ++ struct udev_device *video_device; ++ dev_t devnum; ++ ++ const char *path = udev_device_get_devnode(device); ++ if (!path) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media device devnode failed\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ctx->media_fd = open(path, O_RDWR, 0); ++ if (ctx->media_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media device info failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p path=%s driver=%s\n", __func__, avctx, ctx, path, device_info.driver); ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ if (topology.num_interfaces <= 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: media device has no interfaces\n", __func__); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ interfaces = av_mallocz(topology.num_interfaces * sizeof(struct media_v2_interface)); ++ if (!interfaces) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating media interface struct failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces; ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ret = AVERROR(EINVAL); ++ goto fail; ++ } ++ ++ ret = AVERROR(EINVAL); ++ for (int i = 0; i < topology.num_interfaces; i++) { ++ if (interfaces[i].intf_type != MEDIA_INTF_T_V4L_VIDEO) ++ continue; ++ ++ devnum = makedev(interfaces[i].devnode.major, interfaces[i].devnode.minor); ++ video_device = udev_device_new_from_devnum(udev, 'c', devnum); ++ if (!video_device) { ++ av_log(avctx, AV_LOG_ERROR, "%s: video_device=%p\n", __func__, video_device); ++ continue; ++ } ++ ++ ret = v4l2_request_probe_video_device(video_device, avctx, pixelformat, buffersize, control, count); ++ udev_device_unref(video_device); ++ ++ if (!ret) ++ break; ++ } ++ ++ av_freep(&interfaces); ++ return ret; ++ ++fail: ++ av_freep(&interfaces); ++ if (ctx->media_fd >= 0) { ++ close(ctx->media_fd); ++ ctx->media_fd = -1; ++ } ++ return ret; ++} ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret = AVERROR(EINVAL); ++ struct udev *udev; ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices; ++ struct udev_list_entry *entry; ++ struct udev_device *device; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p hw_device_ctx=%p hw_frames_ctx=%p\n", __func__, avctx, avctx->hw_device_ctx, avctx->hw_frames_ctx); ++ ++ ctx->media_fd = -1; ++ ctx->video_fd = -1; ++ ctx->timestamp = 0; ++ ++ udev = udev_new(); ++ if (!udev) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating udev context failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ enumerate = udev_enumerate_new(udev); ++ if (!enumerate) { ++ av_log(avctx, AV_LOG_ERROR, "%s: allocating udev enumerator failed\n", __func__); ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ udev_enumerate_add_match_subsystem(enumerate, "media"); ++ udev_enumerate_scan_devices(enumerate); ++ ++ devices = udev_enumerate_get_list_entry(enumerate); ++ udev_list_entry_foreach(entry, devices) { ++ const char *path = udev_list_entry_get_name(entry); ++ if (!path) ++ continue; ++ ++ device = udev_device_new_from_syspath(udev, path); ++ if (!device) ++ continue; ++ ++ ret = v4l2_request_probe_media_device(device, avctx, pixelformat, buffersize, control, count); ++ udev_device_unref(device); ++ ++ if (!ret) ++ break; ++ } ++ ++ udev_enumerate_unref(enumerate); ++ ++ if (!ret) ++ ret = v4l2_request_init_context(avctx); ++ ++fail: ++ udev_unref(udev); ++ return ret; ++} ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p\n", __func__, avctx, ctx); ++ ++ if (ctx->video_fd >= 0) { ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->output_type); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: output stream off failed, %s (%d)\n", __func__, strerror(errno), errno); ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->format.type); ++ if (ret < 0) ++ av_log(avctx, AV_LOG_ERROR, "%s: capture stream off failed, %s (%d)\n", __func__, strerror(errno), errno); ++ } ++ ++ if (avctx->hw_frames_ctx) { ++ AVHWFramesContext *hwfc = (AVHWFramesContext*)avctx->hw_frames_ctx->data; ++ av_buffer_pool_flush(hwfc->pool); ++ } ++ ++ if (ctx->video_fd >= 0) ++ close(ctx->video_fd); ++ ++ if (ctx->media_fd >= 0) ++ close(ctx->media_fd); ++ ++ return 0; ++} ++ ++static int v4l2_request_buffer_alloc(AVCodecContext *avctx, V4L2RequestBuffer *buf, enum v4l2_buf_type type) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ struct v4l2_plane planes[1] = {}; ++ struct v4l2_create_buffers buffers = { ++ .count = 1, ++ .memory = V4L2_MEMORY_MMAP, ++ .format.type = type, ++ }; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p buf=%p type=%u\n", __func__, avctx, buf, type); ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &buffers.format); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: get format failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buffers.format.type)) { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__, buffers.format.fmt.pix_mp.pixelformat, buffers.format.fmt.pix_mp.width, buffers.format.fmt.pix_mp.height, buffers.format.fmt.pix_mp.plane_fmt[0].bytesperline, buffers.format.fmt.pix_mp.plane_fmt[0].sizeimage, buffers.format.fmt.pix_mp.num_planes); ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat=%d width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__, buffers.format.fmt.pix.pixelformat, buffers.format.fmt.pix.width, buffers.format.fmt.pix.height, buffers.format.fmt.pix.bytesperline, buffers.format.fmt.pix.sizeimage); ++ } ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ buf->width = buffers.format.fmt.pix_mp.width; ++ buf->height = buffers.format.fmt.pix_mp.height; ++ buf->size = buffers.format.fmt.pix_mp.plane_fmt[0].sizeimage; ++ buf->buffer.length = 1; ++ buf->buffer.m.planes = planes; ++ } else { ++ buf->width = buffers.format.fmt.pix.width; ++ buf->height = buffers.format.fmt.pix.height; ++ buf->size = buffers.format.fmt.pix.sizeimage; ++ } ++ ++ buf->index = buffers.index; ++ buf->capabilities = buffers.capabilities; ++ buf->used = 0; ++ ++ buf->buffer.type = type; ++ buf->buffer.memory = V4L2_MEMORY_MMAP; ++ buf->buffer.index = buf->index; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_QUERYBUF, &buf->buffer); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: query buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno); ++ return ret; ++ } ++ ++ if (V4L2_TYPE_IS_OUTPUT(type)) { ++ void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset); ++ if (addr == MAP_FAILED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: mmap failed, %s (%d)\n", __func__, strerror(errno), errno); ++ return -1; ++ } ++ ++ buf->addr = (uint8_t*)addr; ++ } else { ++ struct v4l2_exportbuffer exportbuffer = { ++ .type = type, ++ .index = buf->index, ++ .flags = O_RDONLY, ++ }; ++ ++ ret = ioctl(ctx->video_fd, VIDIOC_EXPBUF, &exportbuffer); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: export buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno); ++ return ret; ++ } ++ ++ buf->fd = exportbuffer.fd; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__, buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size); ++ return 0; ++} ++ ++static void v4l2_request_buffer_free(V4L2RequestBuffer *buf) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__, buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size); ++ ++ if (buf->addr) ++ munmap(buf->addr, buf->size); ++ ++ if (buf->fd >= 0) ++ close(buf->fd); ++} ++ ++static void v4l2_request_frame_free(void *opaque, uint8_t *data) ++{ ++ AVCodecContext *avctx = opaque; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)data; ++ ++ av_log(NULL, AV_LOG_DEBUG, "%s: avctx=%p data=%p request_fd=%d\n", __func__, avctx, data, req->request_fd); ++ ++ if (req->request_fd >= 0) ++ close(req->request_fd); ++ ++ v4l2_request_buffer_free(&req->capture); ++ v4l2_request_buffer_free(&req->output); ++ ++ av_free(data); ++} ++ ++static AVBufferRef *v4l2_request_frame_alloc(void *opaque, int size) ++{ ++ AVCodecContext *avctx = opaque; ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req; ++ AVBufferRef *ref; ++ uint8_t *data; ++ int ret; ++ ++ data = av_mallocz(size); ++ if (!data) ++ return NULL; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p size=%d data=%p\n", __func__, avctx, size, data); ++ ++ ref = av_buffer_create(data, size, v4l2_request_frame_free, avctx, 0); ++ if (!ref) { ++ av_freep(&data); ++ return NULL; ++ } ++ ++ req = (V4L2RequestDescriptor*)data; ++ req->request_fd = -1; ++ req->output.fd = -1; ++ req->capture.fd = -1; ++ ++ ret = v4l2_request_buffer_alloc(avctx, &req->output, ctx->output_type); ++ if (ret < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ ret = v4l2_request_buffer_alloc(avctx, &req->capture, ctx->format.type); ++ if (ret < 0) { ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ ret = ioctl(ctx->media_fd, MEDIA_IOC_REQUEST_ALLOC, &req->request_fd); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "%s: request alloc failed, %s (%d)\n", __func__, strerror(errno), errno); ++ av_buffer_unref(&ref); ++ return NULL; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p size=%d data=%p request_fd=%d\n", __func__, avctx, size, data, req->request_fd); ++ return ref; ++} ++ ++static void v4l2_request_pool_free(void *opaque) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p\n", __func__, opaque); ++} ++ ++static void v4l2_request_hwframe_ctx_free(AVHWFramesContext *hwfc) ++{ ++ av_log(NULL, AV_LOG_DEBUG, "%s: hwfc=%p pool=%p\n", __func__, hwfc, hwfc->pool); ++ ++ av_buffer_pool_flush(hwfc->pool); ++ av_buffer_pool_uninit(&hwfc->pool); ++} ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) ++{ ++ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; ++ AVHWFramesContext *hwfc = (AVHWFramesContext*)hw_frames_ctx->data; ++ ++ hwfc->format = AV_PIX_FMT_DRM_PRIME; ++ hwfc->sw_format = AV_PIX_FMT_NV12; ++ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { ++ hwfc->width = ctx->format.fmt.pix_mp.width; ++ hwfc->height = ctx->format.fmt.pix_mp.height; ++ } else { ++ hwfc->width = ctx->format.fmt.pix.width; ++ hwfc->height = ctx->format.fmt.pix.height; ++ } ++ ++ hwfc->pool = av_buffer_pool_init2(sizeof(V4L2RequestDescriptor), avctx, v4l2_request_frame_alloc, v4l2_request_pool_free); ++ if (!hwfc->pool) ++ return AVERROR(ENOMEM); ++ ++ hwfc->free = v4l2_request_hwframe_ctx_free; ++ ++ hwfc->initial_pool_size = 1; ++ ++ switch (avctx->codec_id) { ++ case AV_CODEC_ID_VP9: ++ hwfc->initial_pool_size += 8; ++ break; ++ case AV_CODEC_ID_VP8: ++ hwfc->initial_pool_size += 3; ++ break; ++ default: ++ hwfc->initial_pool_size += 2; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p hw_frames_ctx=%p hwfc=%p pool=%p width=%d height=%d initial_pool_size=%d\n", __func__, avctx, ctx, hw_frames_ctx, hwfc, hwfc->pool, hwfc->width, hwfc->height, hwfc->initial_pool_size); ++ ++ return 0; ++} +diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h +new file mode 100644 +index 00000000000..58d2aa70af8 +--- /dev/null ++++ b/libavcodec/v4l2_request.h +@@ -0,0 +1,77 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef AVCODEC_V4L2_REQUEST_H ++#define AVCODEC_V4L2_REQUEST_H ++ ++#include ++ ++#include "libavutil/hwcontext_drm.h" ++ ++typedef struct V4L2RequestContext { ++ int video_fd; ++ int media_fd; ++ enum v4l2_buf_type output_type; ++ struct v4l2_format format; ++ int timestamp; ++} V4L2RequestContext; ++ ++typedef struct V4L2RequestBuffer { ++ int index; ++ int fd; ++ uint8_t *addr; ++ uint32_t width; ++ uint32_t height; ++ uint32_t size; ++ uint32_t used; ++ uint32_t capabilities; ++ struct v4l2_buffer buffer; ++} V4L2RequestBuffer; ++ ++typedef struct V4L2RequestDescriptor { ++ AVDRMFrameDescriptor drm; ++ int request_fd; ++ V4L2RequestBuffer output; ++ V4L2RequestBuffer capture; ++} V4L2RequestDescriptor; ++ ++uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame); ++ ++int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame); ++ ++int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size); ++ ++int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control); ++ ++int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id); ++ ++int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice); ++ ++int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count); ++ ++int ff_v4l2_request_uninit(AVCodecContext *avctx); ++ ++int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); ++ ++#endif /* AVCODEC_V4L2_REQUEST_H */ + +From e1ae7e32ce4798f3032a04ccb20a1f76834c3bea Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 03/20] Add V4L2 request API mpeg2 hwaccel + +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/mpeg12dec.c | 6 ++ + libavcodec/v4l2_request_mpeg2.c | 154 ++++++++++++++++++++++++++++++++ + 5 files changed, 165 insertions(+) + create mode 100644 libavcodec/v4l2_request_mpeg2.c + +diff --git a/configure b/configure +index 9f9909a2369..6b157d6d3ef 100755 +--- a/configure ++++ b/configure +@@ -2967,6 +2967,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2" + mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" + mpeg2_nvdec_hwaccel_deps="nvdec" + mpeg2_nvdec_hwaccel_select="mpeg2video_decoder" ++mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request" ++mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder" + mpeg2_vaapi_hwaccel_deps="vaapi" + mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" + mpeg2_vdpau_hwaccel_deps="vdpau" +@@ -6567,6 +6569,7 @@ if enabled v4l2_m2m; then + fi + + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" + + check_headers sys/videoio.h + test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index d7422051682..8963bd3e91c 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -922,6 +922,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o + OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o ++OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL) += v4l2_request_mpeg2.o + OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o + OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o + OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 6109c89bd63..172a546bb28 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -47,6 +47,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel; + extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel; + extern const AVHWAccel ff_mpeg2_nvdec_hwaccel; + extern const AVHWAccel ff_mpeg2_dxva2_hwaccel; ++extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel; + extern const AVHWAccel ff_mpeg2_vaapi_hwaccel; + extern const AVHWAccel ff_mpeg2_vdpau_hwaccel; + extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel; +diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c +index 99e56532a59..15aaf97a34c 100644 +--- a/libavcodec/mpeg12dec.c ++++ b/libavcodec/mpeg12dec.c +@@ -1154,6 +1154,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { + #endif + #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL + AV_PIX_FMT_VIDEOTOOLBOX, ++#endif ++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL ++ AV_PIX_FMT_DRM_PRIME, + #endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +@@ -2952,6 +2955,9 @@ AVCodec ff_mpeg2video_decoder = { + #endif + #if CONFIG_MPEG2_XVMC_HWACCEL + HWACCEL_XVMC(mpeg2), ++#endif ++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(mpeg2), + #endif + NULL + }, +diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c +new file mode 100644 +index 00000000000..88d86cc4c23 +--- /dev/null ++++ b/libavcodec/v4l2_request_mpeg2.c +@@ -0,0 +1,154 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "mpegvideo.h" ++#include "v4l2_request.h" ++ ++typedef struct V4L2RequestControlsMPEG2 { ++ struct v4l2_ctrl_mpeg2_slice_params slice_params; ++ struct v4l2_ctrl_mpeg2_quantization quantization; ++} V4L2RequestControlsMPEG2; ++ ++static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0]; ++ ++ controls->slice_params = (struct v4l2_ctrl_mpeg2_slice_params) { ++ .bit_size = 0, ++ .data_bit_offset = 0, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */ ++ .quantiser_scale_code = s->qscale >> 1, ++ ++ .sequence = { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */ ++ .horizontal_size = s->width, ++ .vertical_size = s->height, ++ .vbv_buffer_size = req->output.size, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */ ++ .profile_and_level_indication = 0, ++ .progressive_sequence = s->progressive_sequence, ++ .chroma_format = s->chroma_format, ++ }, ++ ++ .picture = { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */ ++ .picture_coding_type = s->pict_type, ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */ ++ .f_code[0][0] = s->mpeg_f_code[0][0], ++ .f_code[0][1] = s->mpeg_f_code[0][1], ++ .f_code[1][0] = s->mpeg_f_code[1][0], ++ .f_code[1][1] = s->mpeg_f_code[1][1], ++ .intra_dc_precision = s->intra_dc_precision, ++ .picture_structure = s->picture_structure, ++ .top_field_first = s->top_field_first, ++ .frame_pred_frame_dct = s->frame_pred_frame_dct, ++ .concealment_motion_vectors = s->concealment_motion_vectors, ++ .q_scale_type = s->q_scale_type, ++ .intra_vlc_format = s->intra_vlc_format, ++ .alternate_scan = s->alternate_scan, ++ .repeat_first_field = s->repeat_first_field, ++ .progressive_frame = s->progressive_frame, ++ }, ++ }; ++ ++ switch (s->pict_type) { ++ case AV_PICTURE_TYPE_B: ++ controls->slice_params.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f); ++ // fall-through ++ case AV_PICTURE_TYPE_P: ++ controls->slice_params.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f); ++ } ++ ++ controls->quantization = (struct v4l2_ctrl_mpeg2_quantization) { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */ ++ .load_intra_quantiser_matrix = 1, ++ .load_non_intra_quantiser_matrix = 1, ++ .load_chroma_intra_quantiser_matrix = 1, ++ .load_chroma_non_intra_quantiser_matrix = 1, ++ }; ++ ++ for (int i = 0; i < 64; i++) { ++ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; ++ controls->quantization.intra_quantiser_matrix[i] = s->intra_matrix[n]; ++ controls->quantization.non_intra_quantiser_matrix[i] = s->inter_matrix[n]; ++ controls->quantization.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; ++ controls->quantization.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n]; ++ } ++ ++ return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f); ++} ++ ++static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size); ++} ++ ++static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx) ++{ ++ const MpegEncContext *s = avctx->priv_data; ++ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0]; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION, ++ .ptr = &controls->quantization, ++ .size = sizeof(controls->quantization), ++ }, ++ }; ++ ++ controls->slice_params.bit_size = req->output.used * 8; ++ ++ return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_mpeg2_init(AVCodecContext *avctx) ++{ ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_mpeg2_v4l2request_hwaccel = { ++ .name = "mpeg2_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_MPEG2VIDEO, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_mpeg2_start_frame, ++ .decode_slice = v4l2_request_mpeg2_decode_slice, ++ .end_frame = v4l2_request_mpeg2_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2), ++ .init = v4l2_request_mpeg2_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; + +From 8a728ea300aee2fab7a181cab06c2c3cfdd0b705 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 04/20] Add V4L2 request API h264 hwaccel + +Signed-off-by: Jernej Skrabec +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/h264_slice.c | 4 + + libavcodec/h264dec.c | 3 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_h264.c | 460 +++++++++++++++++++++++++++++++++ + 6 files changed, 472 insertions(+) + create mode 100644 libavcodec/v4l2_request_h264.c + +diff --git a/configure b/configure +index 6b157d6d3ef..1a7720ebe3b 100755 +--- a/configure ++++ b/configure +@@ -2925,6 +2925,8 @@ h264_dxva2_hwaccel_deps="dxva2" + h264_dxva2_hwaccel_select="h264_decoder" + h264_nvdec_hwaccel_deps="nvdec" + h264_nvdec_hwaccel_select="h264_decoder" ++h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request" ++h264_v4l2request_hwaccel_select="h264_decoder" + h264_vaapi_hwaccel_deps="vaapi" + h264_vaapi_hwaccel_select="h264_decoder" + h264_vdpau_hwaccel_deps="vdpau" +@@ -6569,6 +6571,7 @@ if enabled v4l2_m2m; then + fi + + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns ++check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" + + check_headers sys/videoio.h +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 8963bd3e91c..9a10a292e37 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -903,6 +903,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o + OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o ++OBJS-$(CONFIG_H264_V4L2REQUEST_HWACCEL) += v4l2_request_h264.o + OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o + OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o + OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index db8363e4cc9..3ae11ac8a71 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -759,6 +759,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ + (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ + CONFIG_H264_NVDEC_HWACCEL + \ ++ CONFIG_H264_V4L2REQUEST_HWACCEL + \ + CONFIG_H264_VAAPI_HWACCEL + \ + CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_H264_VDPAU_HWACCEL) +@@ -843,6 +844,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + #endif + #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + if (h->avctx->codec->pix_fmts) + choices = h->avctx->codec->pix_fmts; +diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c +index 5eedeb3c275..a504c89565c 100644 +--- a/libavcodec/h264dec.c ++++ b/libavcodec/h264dec.c +@@ -1102,6 +1102,9 @@ AVCodec ff_h264_decoder = { + #endif + #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(h264), ++#endif ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(h264), + #endif + NULL + }, +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 172a546bb28..44e00e79b51 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -27,6 +27,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel; + extern const AVHWAccel ff_h264_d3d11va2_hwaccel; + extern const AVHWAccel ff_h264_dxva2_hwaccel; + extern const AVHWAccel ff_h264_nvdec_hwaccel; ++extern const AVHWAccel ff_h264_v4l2request_hwaccel; + extern const AVHWAccel ff_h264_vaapi_hwaccel; + extern const AVHWAccel ff_h264_vdpau_hwaccel; + extern const AVHWAccel ff_h264_videotoolbox_hwaccel; +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +new file mode 100644 +index 00000000000..94b9aca8ad4 +--- /dev/null ++++ b/libavcodec/v4l2_request_h264.c +@@ -0,0 +1,460 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "h264dec.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++ ++typedef struct V4L2RequestControlsH264 { ++ struct v4l2_ctrl_h264_sps sps; ++ struct v4l2_ctrl_h264_pps pps; ++ struct v4l2_ctrl_h264_scaling_matrix scaling_matrix; ++ struct v4l2_ctrl_h264_decode_params decode_params; ++ struct v4l2_ctrl_h264_slice_params slice_params[MAX_SLICES]; ++ int first_slice; ++} V4L2RequestControlsH264; ++ ++typedef struct V4L2RequestContextH264 { ++ V4L2RequestContext base; ++ int decode_mode; ++ int start_code; ++ int max_slices; ++} V4L2RequestContextH264; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int list, const H264SliceContext *sl) ++{ ++ for (int i = 0; i < sl->ref_count[list]; i++) { ++ if (sl->pwt.luma_weight_flag[list]) { ++ factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0]; ++ factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1]; ++ } else { ++ factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom; ++ factors->luma_offset[i] = 0; ++ } ++ for (int j = 0; j < 2; j++) { ++ if (sl->pwt.chroma_weight_flag[list]) { ++ factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0]; ++ factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1]; ++ } else { ++ factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom; ++ factors->chroma_offset[i][j] = 0; ++ } ++ } ++ } ++} ++ ++static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic) ++{ ++ entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f); ++ entry->frame_num = pic->frame_num; ++ entry->pic_num = pic->pic_id; ++ entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID; ++ if (pic->reference) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; ++ if (pic->long_ref) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; ++ if (pic->field_poc[0] != INT_MAX) ++ entry->top_field_order_cnt = pic->field_poc[0]; ++ if (pic->field_poc[1] != INT_MAX) ++ entry->bottom_field_order_cnt = pic->field_poc[1]; ++} ++ ++static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Context *h) ++{ ++ int entries = 0; ++ ++ for (int i = 0; i < h->short_ref_count; i++) { ++ const H264Picture *pic = h->short_ref[i]; ++ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX)) ++ fill_dpb_entry(&decode->dpb[entries++], pic); ++ } ++ ++ if (!h->long_ref_count) ++ return; ++ ++ for (int i = 0; i < FF_ARRAY_ELEMS(h->long_ref); i++) { ++ const H264Picture *pic = h->long_ref[i]; ++ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX)) ++ fill_dpb_entry(&decode->dpb[entries++], pic); ++ } ++} ++ ++static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref) ++{ ++ uint64_t timestamp; ++ ++ if (!ref->parent) ++ return 0; ++ ++ timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f); ++ ++ for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) { ++ struct v4l2_h264_dpb_entry *entry = &decode->dpb[i]; ++ if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) && ++ entry->reference_ts == timestamp) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h) ++{ ++ const SPS *sps = h->ps.sps; ++ ++ *ctrl = (struct v4l2_ctrl_h264_sps) { ++ .profile_idc = sps->profile_idc, ++ .constraint_set_flags = sps->constraint_set_flags, ++ .level_idc = sps->level_idc, ++ .seq_parameter_set_id = sps->sps_id, ++ .chroma_format_idc = sps->chroma_format_idc, ++ .bit_depth_luma_minus8 = sps->bit_depth_luma - 8, ++ .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, ++ .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, ++ .pic_order_cnt_type = sps->poc_type, ++ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, ++ .max_num_ref_frames = sps->ref_frame_count, ++ .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length, ++ //.offset_for_ref_frame[255] - not required? not set by libva-v4l2-request - copy sps->offset_for_ref_frame ++ .offset_for_non_ref_pic = sps->offset_for_non_ref_pic, ++ .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field, ++ .pic_width_in_mbs_minus1 = h->mb_width - 1, ++ .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1, ++ }; ++ ++ if (sps->residual_color_transform_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ if (sps->transform_bypass) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS; ++ if (sps->delta_pic_order_always_zero_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO; ++ if (sps->gaps_in_frame_num_allowed_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED; ++ if (sps->frame_mbs_only_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY; ++ if (sps->mb_aff) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD; ++ if (sps->direct_8x8_inference_flag) ++ ctrl->flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE; ++} ++ ++static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h) ++{ ++ const SPS *sps = h->ps.sps; ++ const PPS *pps = h->ps.pps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; ++ int qp_bd_offset = 6 * (sps->bit_depth_luma - 8); ++ ++ *ctrl = (struct v4l2_ctrl_h264_pps) { ++ .pic_parameter_set_id = sl->pps_id, ++ .seq_parameter_set_id = pps->sps_id, ++ .num_slice_groups_minus1 = pps->slice_group_count - 1, ++ .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1, ++ .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1, ++ .weighted_bipred_idc = pps->weighted_bipred_idc, ++ .pic_init_qp_minus26 = pps->init_qp - 26 - qp_bd_offset, ++ .pic_init_qs_minus26 = pps->init_qs - 26 - qp_bd_offset, ++ .chroma_qp_index_offset = pps->chroma_qp_index_offset[0], ++ .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1], ++ }; ++ ++ if (pps->cabac) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE; ++ if (pps->pic_order_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT; ++ if (pps->weighted_pred) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED; ++ if (pps->deblocking_filter_parameters_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT; ++ if (pps->constrained_intra_pred) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ if (pps->redundant_pic_cnt_present) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT; ++ if (pps->transform_8x8_mode) ++ ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE; ++} ++ ++static int v4l2_request_h264_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const H264Context *h = avctx->priv_data; ++ const PPS *pps = h->ps.pps; ++ const SPS *sps = h->ps.sps; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ ++ fill_sps(&controls->sps, h); ++ fill_pps(&controls->pps, h); ++ ++ memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4)); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1])); ++ ++ if (sps->chroma_format_idc == 3) { ++ memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4])); ++ memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5])); ++ } ++ ++ controls->decode_params = (struct v4l2_ctrl_h264_decode_params) { ++ .num_slices = 0, ++ .nal_ref_idc = h->nal_ref_idc, ++ .top_field_order_cnt = h->cur_pic_ptr->field_poc[0] != INT_MAX ? h->cur_pic_ptr->field_poc[0] : 0, ++ .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1] != INT_MAX ? h->cur_pic_ptr->field_poc[1] : 0, ++ }; ++ ++ if (h->picture_idr) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC; ++ ++ fill_dpb(&controls->decode_params, h); ++ ++ controls->first_slice = !FIELD_PICTURE(h) || h->first_field; ++ ++ return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); ++} ++ ++static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice) ++{ ++ const H264Context *h = avctx->priv_data; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params[0]) * FFMAX(FFMIN(controls->decode_params.num_slices, MAX_SLICES), ctx->max_slices), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, ++ }; ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); ++ ++ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const H264Context *h = avctx->priv_data; ++ const PPS *pps = h->ps.pps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; ++ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->cur_pic_ptr->f->data[0]; ++ int i, ret, count, slice = FFMIN(controls->decode_params.num_slices, MAX_SLICES - 1); ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && slice) { ++ ret = v4l2_request_h264_queue_decode(avctx, 0); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); ++ slice = controls->decode_params.num_slices = 0; ++ controls->first_slice = 0; ++ } ++ ++ controls->slice_params[slice] = (struct v4l2_ctrl_h264_slice_params) { ++ /* Size in bytes, including header */ ++ .size = 0, ++ .start_byte_offset = req->output.used, ++ /* Offset in bits to slice_data() from the beginning of this slice. */ ++ .header_bit_size = get_bits_count(&sl->gb), ++ ++ .first_mb_in_slice = sl->first_mb_addr, ++ .slice_type = ff_h264_get_slice_type(sl), ++ .pic_parameter_set_id = sl->pps_id, ++ .colour_plane_id = 0, /* what is this? */ ++ .frame_num = h->poc.frame_num, ++ .idr_pic_id = 0, /* what is this? */ ++ .pic_order_cnt_lsb = sl->poc_lsb, ++ .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, ++ .delta_pic_order_cnt0 = sl->delta_poc[0], ++ .delta_pic_order_cnt1 = sl->delta_poc[1], ++ .redundant_pic_cnt = sl->redundant_pic_count, ++ ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ .dec_ref_pic_marking_bit_size = 0, ++ /* Size in bits of pic order count syntax. */ ++ .pic_order_cnt_bit_size = 0, ++ ++ .cabac_init_idc = sl->cabac_init_idc, ++ .slice_qp_delta = sl->qscale - pps->init_qp, ++ .slice_qs_delta = 0, /* XXX not implemented by FFmpeg */ ++ .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter, ++ .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2, ++ .slice_beta_offset_div2 = sl->slice_beta_offset / 2, ++ .slice_group_change_cycle = 0, /* what is this? */ ++ ++ .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0, ++ .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0, ++ }; ++ ++ if (FIELD_PICTURE(h)) ++ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_FIELD_PIC; ++ if (h->picture_structure == PICT_BOTTOM_FIELD) ++ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_BOTTOM_FIELD; ++ if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred) ++ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED; ++ ++ controls->slice_params[slice].pred_weight_table.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; ++ controls->slice_params[slice].pred_weight_table.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; ++ ++ count = sl->list_count > 0 ? sl->ref_count[0] : 0; ++ for (i = 0; i < count; i++) ++ controls->slice_params[slice].ref_pic_list0[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[0][i]); ++ if (count) ++ fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[0], 0, sl); ++ ++ count = sl->list_count > 1 ? sl->ref_count[1] : 0; ++ for (i = 0; i < count; i++) ++ controls->slice_params[slice].ref_pic_list1[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[1][i]); ++ if (count) ++ fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[1], 1, sl); ++ ++ if (ctx->start_code == V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size); ++ if (ret) ++ return ret; ++ ++ controls->slice_params[slice].size = req->output.used - controls->slice_params[slice].start_byte_offset; ++ controls->decode_params.num_slices++; ++ return 0; ++} ++ ++static int v4l2_request_h264_end_frame(AVCodecContext *avctx) ++{ ++ const H264Context *h = avctx->priv_data; ++ return v4l2_request_h264_queue_decode(avctx, !FIELD_PICTURE(h) || !h->first_field); ++} ++ ++static int v4l2_request_h264_set_controls(AVCodecContext *avctx) ++{ ++ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, }, ++ { .id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, }, ++ }; ++ struct v4l2_query_ext_ctrl slice_params = { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_START_CODE); ++ if (ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_NONE && ++ ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ ret = ff_v4l2_request_query_control(avctx, &slice_params); ++ if (ret) ++ return ret; ++ ++ ctx->max_slices = slice_params.elems; ++ if (ctx->max_slices > MAX_SLICES) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %d\n", __func__, ctx->max_slices); ++ return AVERROR(EINVAL); ++ } ++ ++ control[0].value = ctx->decode_mode; ++ control[1].value = ctx->start_code; ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_h264_init(AVCodecContext *avctx) ++{ ++ const H264Context *h = avctx->priv_data; ++ struct v4l2_ctrl_h264_sps sps; ++ struct v4l2_ctrl_h264_pps pps; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_PPS, ++ .ptr = &pps, ++ .size = sizeof(pps), ++ }, ++ }; ++ ++ fill_sps(&sps, h); ++ fill_pps(&pps, h); ++ ++ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ return v4l2_request_h264_set_controls(avctx); ++} ++ ++const AVHWAccel ff_h264_v4l2request_hwaccel = { ++ .name = "h264_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_H264, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_h264_start_frame, ++ .decode_slice = v4l2_request_h264_decode_slice, ++ .end_frame = v4l2_request_h264_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsH264), ++ .init = v4l2_request_h264_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContextH264), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; + +From 72758190a3d062b64db756c60761187a2b9ce1c9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 05/20] Add V4L2 request API hevc hwaccel + +Signed-off-by: Jernej Skrabec +Signed-off-by: Jonas Karlman +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hevcdec.c | 10 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_hevc.c | 533 +++++++++++++++++++++++++++++++++ + 5 files changed, 548 insertions(+) + create mode 100644 libavcodec/v4l2_request_hevc.c + +diff --git a/configure b/configure +index 1a7720ebe3b..58abd99335b 100755 +--- a/configure ++++ b/configure +@@ -2941,6 +2941,8 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" + hevc_dxva2_hwaccel_select="hevc_decoder" + hevc_nvdec_hwaccel_deps="nvdec" + hevc_nvdec_hwaccel_select="hevc_decoder" ++hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request" ++hevc_v4l2request_hwaccel_select="hevc_decoder" + hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" + hevc_vaapi_hwaccel_select="hevc_decoder" + hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" +@@ -6572,6 +6574,7 @@ fi + + check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;" ++check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" + + check_headers sys/videoio.h +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 9a10a292e37..5d0e1d7dae7 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -911,6 +911,7 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o + OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o + OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o ++OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o + OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o + OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o + OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o +diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c +index 0772608a30e..d01b7b34bce 100644 +--- a/libavcodec/hevcdec.c ++++ b/libavcodec/hevcdec.c +@@ -372,6 +372,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \ + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ + CONFIG_HEVC_NVDEC_HWACCEL + \ ++ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \ + CONFIG_HEVC_VAAPI_HWACCEL + \ + CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ + CONFIG_HEVC_VDPAU_HWACCEL) +@@ -398,6 +399,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P10: +@@ -416,6 +420,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) + #endif + #if CONFIG_HEVC_NVDEC_HWACCEL + *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV444P: +@@ -3588,6 +3595,9 @@ AVCodec ff_hevc_decoder = { + #endif + #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(hevc), ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(hevc), + #endif + NULL + }, +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index 44e00e79b51..e2f90a5fdd5 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -35,6 +35,7 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel; + extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; + extern const AVHWAccel ff_hevc_dxva2_hwaccel; + extern const AVHWAccel ff_hevc_nvdec_hwaccel; ++extern const AVHWAccel ff_hevc_v4l2request_hwaccel; + extern const AVHWAccel ff_hevc_vaapi_hwaccel; + extern const AVHWAccel ff_hevc_vdpau_hwaccel; + extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +new file mode 100644 +index 00000000000..f7249095465 +--- /dev/null ++++ b/libavcodec/v4l2_request_hevc.c +@@ -0,0 +1,533 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hevcdec.h" ++#include "hwconfig.h" ++#include "v4l2_request.h" ++ ++#define MAX_SLICES 16 ++ ++typedef struct V4L2RequestControlsHEVC { ++ struct v4l2_ctrl_hevc_sps sps; ++ struct v4l2_ctrl_hevc_pps pps; ++ struct v4l2_ctrl_hevc_slice_params slice_params[MAX_SLICES]; ++ int first_slice; ++ int num_slices; //TODO: this should be in control ++} V4L2RequestControlsHEVC; ++ ++typedef struct V4L2RequestContextHEVC { ++ V4L2RequestContext base; ++ int decode_mode; ++ int start_code; ++ int max_slices; ++} V4L2RequestContextHEVC; ++ ++static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; ++ ++static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table) ++{ ++ int32_t luma_weight_denom, chroma_weight_denom; ++ const SliceHeader *sh = &h->sh; ++ ++ if (sh->slice_type == HEVC_SLICE_I || ++ (sh->slice_type == HEVC_SLICE_P && !h->ps.pps->weighted_pred_flag) || ++ (sh->slice_type == HEVC_SLICE_B && !h->ps.pps->weighted_bipred_flag)) ++ return; ++ ++ table->luma_log2_weight_denom = sh->luma_log2_weight_denom; ++ ++ if (h->ps.sps->chroma_format_idc) ++ table->delta_chroma_log2_weight_denom = sh->chroma_log2_weight_denom - sh->luma_log2_weight_denom; ++ ++ luma_weight_denom = (1 << sh->luma_log2_weight_denom); ++ chroma_weight_denom = (1 << sh->chroma_log2_weight_denom); ++ ++ for (int i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { ++ table->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - luma_weight_denom; ++ table->luma_offset_l0[i] = sh->luma_offset_l0[i]; ++ table->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - chroma_weight_denom; ++ table->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - chroma_weight_denom; ++ table->chroma_offset_l0[i][0] = sh->chroma_offset_l0[i][0]; ++ table->chroma_offset_l0[i][1] = sh->chroma_offset_l0[i][1]; ++ } ++ ++ if (sh->slice_type != HEVC_SLICE_B) ++ return; ++ ++ for (int i = 0; i < 15 && i < sh->nb_refs[L1]; i++) { ++ table->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - luma_weight_denom; ++ table->luma_offset_l1[i] = sh->luma_offset_l1[i]; ++ table->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - chroma_weight_denom; ++ table->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - chroma_weight_denom; ++ table->chroma_offset_l1[i][0] = sh->chroma_offset_l1[i][0]; ++ table->chroma_offset_l1[i][1] = sh->chroma_offset_l1[i][1]; ++ } ++} ++ ++static int find_frame_rps_type(const HEVCContext *h, uint64_t timestamp) ++{ ++ const HEVCFrame *frame; ++ int i; ++ ++ for (i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { ++ frame = h->rps[ST_CURR_BEF].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE; ++ } ++ ++ for (i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { ++ frame = h->rps[ST_CURR_AFT].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER; ++ } ++ ++ for (i = 0; i < h->rps[LT_CURR].nb_refs; i++) { ++ frame = h->rps[LT_CURR].ref[i]; ++ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame)) ++ return V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR; ++ } ++ ++ return 0; ++} ++ ++static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame, ++ struct v4l2_ctrl_hevc_slice_params *slice_params) ++{ ++ uint64_t timestamp; ++ ++ if (!frame) ++ return 0; ++ ++ timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame); ++ ++ for (uint8_t i = 0; i < slice_params->num_active_dpb_entries; i++) { ++ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[i]; ++ if (entry->timestamp == timestamp) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h, ++ struct v4l2_ctrl_hevc_slice_params *slice_params) ++{ ++ const HEVCFrame *pic = h->ref; ++ const SliceHeader *sh = &h->sh; ++ int i, entries = 0; ++ RefPicList *rpl; ++ ++ *slice_params = (struct v4l2_ctrl_hevc_slice_params) { ++ .bit_size = 0, ++ .data_bit_offset = get_bits_count(&h->HEVClc->gb), ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ ++ .nal_unit_type = h->nal_unit_type, ++ .nuh_temporal_id_plus1 = h->temporal_id + 1, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .slice_type = sh->slice_type, ++ .colour_plane_id = sh->colour_plane_id, ++ .slice_pic_order_cnt = pic->poc, ++ .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0, ++ .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0, ++ .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0, ++ .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand, ++ .slice_qp_delta = sh->slice_qp_delta, ++ .slice_cb_qp_offset = sh->slice_cb_qp_offset, ++ .slice_cr_qp_offset = sh->slice_cr_qp_offset, ++ .slice_act_y_qp_offset = 0, ++ .slice_act_cb_qp_offset = 0, ++ .slice_act_cr_qp_offset = 0, ++ .slice_beta_offset_div2 = sh->beta_offset / 2, ++ .slice_tc_offset_div2 = sh->tc_offset / 2, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ ++ .pic_struct = h->sei.picture_timing.picture_struct, ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs, ++ .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs, ++ .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs, ++ }; ++ ++ if (sh->slice_sample_adaptive_offset_flag[0]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA; ++ ++ if (sh->slice_sample_adaptive_offset_flag[1]) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA; ++ ++ if (sh->slice_temporal_mvp_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED; ++ ++ if (sh->mvd_l1_zero_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO; ++ ++ if (sh->cabac_init_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT; ++ ++ if (sh->collocated_list == L0) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0; ++ ++ if (sh->disable_deblocking_filter_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED; ++ ++ if (sh->slice_loop_filter_across_slices_enabled_flag) ++ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { ++ const HEVCFrame *frame = &h->DPB[i]; ++ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { ++ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[entries++]; ++ ++ entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame); ++ entry->rps = find_frame_rps_type(h, entry->timestamp); ++ entry->field_pic = frame->frame->interlaced_frame; ++ ++ /* TODO: Interleaved: Get the POC for each field. */ ++ entry->pic_order_cnt[0] = frame->poc; ++ entry->pic_order_cnt[1] = frame->poc; ++ } ++ } ++ ++ slice_params->num_active_dpb_entries = entries; ++ ++ if (sh->slice_type != HEVC_SLICE_I) { ++ rpl = &h->ref->refPicList[0]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], slice_params); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ rpl = &h->ref->refPicList[1]; ++ for (i = 0; i < rpl->nb_refs; i++) ++ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], slice_params); ++ } ++ ++ v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table); ++} ++ ++static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h) ++{ ++ const HEVCSPS *sps = h->ps.sps; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ *ctrl = (struct v4l2_ctrl_hevc_sps) { ++ .chroma_format_idc = sps->chroma_format_idc, ++ .pic_width_in_luma_samples = sps->width, ++ .pic_height_in_luma_samples = sps->height, ++ .bit_depth_luma_minus8 = sps->bit_depth - 8, ++ .bit_depth_chroma_minus8 = sps->bit_depth - 8, ++ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, ++ .sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1, ++ .sps_max_num_reorder_pics = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics, ++ .sps_max_latency_increase_plus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_latency_increase + 1, ++ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, ++ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size, ++ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2, ++ .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size, ++ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, ++ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, ++ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1, ++ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1, ++ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3, ++ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, ++ .num_short_term_ref_pic_sets = sps->nb_st_rps, ++ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, ++ }; ++ ++ if (sps->separate_colour_plane_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE; ++ ++ if (sps->scaling_list_enable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED; ++ ++ if (sps->amp_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED; ++ ++ if (sps->sao_enabled) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET; ++ ++ if (sps->pcm_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED; ++ ++ if (sps->pcm.loop_filter_disable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED; ++ ++ if (sps->long_term_ref_pics_present_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT; ++ ++ if (sps->sps_temporal_mvp_enabled_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED; ++ ++ if (sps->sps_strong_intra_smoothing_enable_flag) ++ ctrl->flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED; ++} ++ ++static int v4l2_request_hevc_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ const HEVCSPS *sps = h->ps.sps; ++ const HEVCPPS *pps = h->ps.pps; ++ const ScalingList *sl = pps->scaling_list_data_present_flag ? ++ &pps->scaling_list : ++ sps->scaling_list_enable_flag ? ++ &sps->scaling_list : NULL; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ ++ fill_sps(&controls->sps, h); ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ controls->pps = (struct v4l2_ctrl_hevc_pps) { ++ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, ++ .init_qp_minus26 = pps->pic_init_qp_minus26, ++ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, ++ .pps_cb_qp_offset = pps->cb_qp_offset, ++ .pps_cr_qp_offset = pps->cr_qp_offset, ++ .pps_beta_offset_div2 = pps->beta_offset / 2, ++ .pps_tc_offset_div2 = pps->tc_offset / 2, ++ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, ++ }; ++ ++ if (pps->dependent_slice_segments_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT; ++ ++ if (pps->output_flag_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT; ++ ++ if (pps->sign_data_hiding_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED; ++ ++ if (pps->cabac_init_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT; ++ ++ if (pps->constrained_intra_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED; ++ ++ if (pps->transform_skip_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED; ++ ++ if (pps->cu_qp_delta_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED; ++ ++ if (pps->pic_slice_level_chroma_qp_offsets_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT; ++ ++ if (pps->weighted_pred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED; ++ ++ if (pps->weighted_bipred_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED; ++ ++ if (pps->transquant_bypass_enable_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED; ++ ++ if (pps->tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED; ++ ++ if (pps->entropy_coding_sync_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED; ++ ++ if (pps->loop_filter_across_tiles_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; ++ ++ if (pps->seq_loop_filter_across_slices_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED; ++ ++ if (pps->deblocking_filter_override_enabled_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED; ++ ++ if (pps->disable_dbf) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER; ++ ++ if (pps->lists_modification_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT; ++ ++ if (pps->slice_header_extension_present_flag) ++ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT; ++ ++ if (pps->tiles_enabled_flag) { ++ controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1; ++ controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1; ++ ++ for (int i = 0; i < pps->num_tile_columns; i++) ++ controls->pps.column_width_minus1[i] = pps->column_width[i] - 1; ++ ++ for (int i = 0; i < pps->num_tile_rows; i++) ++ controls->pps.row_height_minus1[i] = pps->row_height[i] - 1; ++ } ++ ++ controls->first_slice = 1; ++ controls->num_slices = 0; ++ ++ return ff_v4l2_request_reset_frame(avctx, h->ref->frame); ++} ++ ++static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .ptr = &controls->sps, ++ .size = sizeof(controls->sps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, ++ .ptr = &controls->pps, ++ .size = sizeof(controls->pps), ++ }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ .ptr = &controls->slice_params, ++ .size = sizeof(controls->slice_params[0]) * FFMAX(FFMIN(controls->num_slices, MAX_SLICES), ctx->max_slices), ++ }, ++ }; ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED) ++ return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); ++ ++ return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private; ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0]; ++ int ret, slice = FFMIN(controls->num_slices, MAX_SLICES - 1); ++ ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && slice) { ++ ret = v4l2_request_hevc_queue_decode(avctx, 0); ++ if (ret) ++ return ret; ++ ++ ff_v4l2_request_reset_frame(avctx, h->ref->frame); ++ slice = controls->num_slices = 0; ++ controls->first_slice = 0; ++ } ++ ++ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params[slice]); ++ ++ if (ctx->start_code == V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size); ++ if (ret) ++ return ret; ++ ++ controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME ++ controls->num_slices++; ++ return 0; ++} ++ ++static int v4l2_request_hevc_end_frame(AVCodecContext *avctx) ++{ ++ return v4l2_request_hevc_queue_decode(avctx, 1); ++} ++ ++static int v4l2_request_hevc_set_controls(AVCodecContext *avctx) ++{ ++ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, }, ++ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, }, ++ }; ++ struct v4l2_query_ext_ctrl slice_params = { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, ++ }; ++ ++ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE); ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && ++ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode); ++ return AVERROR(EINVAL); ++ } ++ ++ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_START_CODE); ++ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE && ++ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code); ++ return AVERROR(EINVAL); ++ } ++ ++ ret = ff_v4l2_request_query_control(avctx, &slice_params); ++ if (ret) ++ return ret; ++ ++ ctx->max_slices = slice_params.elems; ++ if (ctx->max_slices > MAX_SLICES) { ++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %d\n", __func__, ctx->max_slices); ++ return AVERROR(EINVAL); ++ } ++ ++ control[0].value = ctx->decode_mode; ++ control[1].value = ctx->start_code; ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_hevc_init(AVCodecContext *avctx) ++{ ++ const HEVCContext *h = avctx->priv_data; ++ struct v4l2_ctrl_hevc_sps sps; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, ++ .ptr = &sps, ++ .size = sizeof(sps), ++ }, ++ }; ++ ++ fill_sps(&sps, h); ++ ++ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ return v4l2_request_hevc_set_controls(avctx); ++} ++ ++const AVHWAccel ff_hevc_v4l2request_hwaccel = { ++ .name = "hevc_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_hevc_start_frame, ++ .decode_slice = v4l2_request_hevc_decode_slice, ++ .end_frame = v4l2_request_hevc_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC), ++ .init = v4l2_request_hevc_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContextHEVC), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; + +From ebc06b180bfc3c4c6e02cfe2f559e140ce0020e8 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Wed, 22 May 2019 14:46:58 +0200 +Subject: [PATCH 06/20] Add V4L2 request API vp8 hwaccel + +Need to fix the STREAMOFF/STREAMON issue in a proper way. + +Signed-off-by: Boris Brezillon +Signed-off-by: Ezequiel Garcia +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_vp8.c | 180 ++++++++++++++++++++++++++++++++++ + libavcodec/vp8.c | 8 +- + 5 files changed, 192 insertions(+), 1 deletion(-) + create mode 100644 libavcodec/v4l2_request_vp8.c + +diff --git a/configure b/configure +index 58abd99335b..cbb91c2bca4 100755 +--- a/configure ++++ b/configure +@@ -3003,6 +3003,8 @@ vc1_vdpau_hwaccel_deps="vdpau" + vc1_vdpau_hwaccel_select="vc1_decoder" + vp8_nvdec_hwaccel_deps="nvdec" + vp8_nvdec_hwaccel_select="vp8_decoder" ++vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request" ++vp8_v4l2request_hwaccel_select="vp8_decoder" + vp8_vaapi_hwaccel_deps="vaapi" + vp8_vaapi_hwaccel_select="vp8_decoder" + vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" +@@ -6576,6 +6578,7 @@ check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns + check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;" + check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" ++check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;" + + check_headers sys/videoio.h + test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 5d0e1d7dae7..d6af854daaa 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -940,6 +940,7 @@ OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o + OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o + OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o + OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o ++OBJS-$(CONFIG_VP8_V4L2REQUEST_HWACCEL) += v4l2_request_vp8.o + OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o + OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index e2f90a5fdd5..bd75e94f4ca 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -65,6 +65,7 @@ extern const AVHWAccel ff_vc1_nvdec_hwaccel; + extern const AVHWAccel ff_vc1_vaapi_hwaccel; + extern const AVHWAccel ff_vc1_vdpau_hwaccel; + extern const AVHWAccel ff_vp8_nvdec_hwaccel; ++extern const AVHWAccel ff_vp8_v4l2request_hwaccel; + extern const AVHWAccel ff_vp8_vaapi_hwaccel; + extern const AVHWAccel ff_vp9_d3d11va_hwaccel; + extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; +diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c +new file mode 100644 +index 00000000000..7e75ee398a2 +--- /dev/null ++++ b/libavcodec/v4l2_request_vp8.c +@@ -0,0 +1,180 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp8.h" ++ ++typedef struct V4L2RequestControlsVP8 { ++ struct v4l2_ctrl_vp8_frame_header ctrl; ++} V4L2RequestControlsVP8; ++ ++static int v4l2_request_vp8_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ ++ memset(&controls->ctrl, 0, sizeof(controls->ctrl)); ++ return ff_v4l2_request_reset_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f); ++} ++ ++static int v4l2_request_vp8_end_frame(AVCodecContext *avctx) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, ++ .ptr = &controls->ctrl, ++ .size = sizeof(controls->ctrl), ++ }, ++ }; ++ ++ return ff_v4l2_request_decode_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, ++ control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_vp8_decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ const VP8Context *s = avctx->priv_data; ++ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; ++ struct v4l2_ctrl_vp8_frame_header *hdr = &controls->ctrl; ++ const uint8_t *data = buffer + 3 + 7 * s->keyframe; ++ unsigned int i, j, k; ++ ++ hdr->version = s->profile & 0x3; ++ hdr->width = avctx->width; ++ hdr->height = avctx->height; ++ /* FIXME: set ->xx_scale */ ++ hdr->prob_skip_false = s->prob->mbskip; ++ hdr->prob_intra = s->prob->intra; ++ hdr->prob_gf = s->prob->golden; ++ hdr->prob_last = s->prob->last; ++ hdr->first_part_size = s->header_partition_size; ++ hdr->first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) - ++ s->coder_state_at_header_end.bit_count - 8); ++ hdr->num_dct_parts = s->num_coeff_partitions; ++ for (i = 0; i < 8; i++) ++ hdr->dct_part_sizes[i] = s->coeff_partition_size[i]; ++ ++ hdr->coder_state.range = s->coder_state_at_header_end.range; ++ hdr->coder_state.value = s->coder_state_at_header_end.value; ++ hdr->coder_state.bit_count = s->coder_state_at_header_end.bit_count; ++ if (s->framep[VP56_FRAME_PREVIOUS]) ++ hdr->last_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_PREVIOUS]->tf.f); ++ if (s->framep[VP56_FRAME_GOLDEN]) ++ hdr->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN]->tf.f); ++ if (s->framep[VP56_FRAME_GOLDEN2]) ++ hdr->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN2]->tf.f); ++ hdr->flags |= s->invisible ? 0 : V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME; ++ hdr->flags |= s->mbskip_enabled ? V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF : 0; ++ hdr->flags |= (s->profile & 0x4) ? V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL : 0; ++ hdr->flags |= s->keyframe ? V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME : 0; ++ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN : 0; ++ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN2] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT : 0; ++ hdr->segment_header.flags |= s->segmentation.enabled ? V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED : 0; ++ hdr->segment_header.flags |= s->segmentation.update_map ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP : 0; ++ hdr->segment_header.flags |= s->segmentation.update_feature_data ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA : 0; ++ hdr->segment_header.flags |= s->segmentation.absolute_vals ? 0 : V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE; ++ for (i = 0; i < 4; i++) { ++ hdr->segment_header.quant_update[i] = s->segmentation.base_quant[i]; ++ hdr->segment_header.lf_update[i] = s->segmentation.filter_level[i]; ++ } ++ ++ for (i = 0; i < 3; i++) ++ hdr->segment_header.segment_probs[i] = s->prob->segmentid[i]; ++ ++ hdr->lf_header.level = s->filter.level; ++ hdr->lf_header.sharpness_level = s->filter.sharpness; ++ hdr->lf_header.flags |= s->lf_delta.enabled ? V4L2_VP8_LF_HEADER_ADJ_ENABLE : 0; ++ hdr->lf_header.flags |= s->lf_delta.update ? V4L2_VP8_LF_HEADER_DELTA_UPDATE : 0; ++ hdr->lf_header.flags |= s->filter.simple ? V4L2_VP8_LF_FILTER_TYPE_SIMPLE : 0; ++ for (i = 0; i < 4; i++) { ++ hdr->lf_header.ref_frm_delta[i] = s->lf_delta.ref[i]; ++ hdr->lf_header.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4]; ++ } ++ ++ // Probabilites ++ if (s->keyframe) { ++ static const uint8_t keyframe_y_mode_probs[4] = { ++ 145, 156, 163, 128 ++ }; ++ static const uint8_t keyframe_uv_mode_probs[3] = { ++ 142, 114, 183 ++ }; ++ ++ memcpy(hdr->entropy_header.y_mode_probs, keyframe_y_mode_probs, 4); ++ memcpy(hdr->entropy_header.uv_mode_probs, keyframe_uv_mode_probs, 3); ++ } else { ++ for (i = 0; i < 4; i++) ++ hdr->entropy_header.y_mode_probs[i] = s->prob->pred16x16[i]; ++ for (i = 0; i < 3; i++) ++ hdr->entropy_header.uv_mode_probs[i] = s->prob->pred8x8c[i]; ++ } ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < 19; j++) ++ hdr->entropy_header.mv_probs[i][j] = s->prob->mvc[i][j]; ++ ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < 8; j++) { ++ static const int coeff_bands_inverse[8] = { ++ 0, 1, 2, 3, 5, 6, 4, 15 ++ }; ++ int coeff_pos = coeff_bands_inverse[j]; ++ ++ for (k = 0; k < 3; k++) { ++ memcpy(hdr->entropy_header.coeff_probs[i][j][k], ++ s->prob->token[i][coeff_pos][k], 11); ++ } ++ } ++ } ++ ++ hdr->quant_header.y_ac_qi = s->quant.yac_qi; ++ hdr->quant_header.y_dc_delta = s->quant.ydc_delta; ++ hdr->quant_header.y2_dc_delta = s->quant.y2dc_delta; ++ hdr->quant_header.y2_ac_delta = s->quant.y2ac_delta; ++ hdr->quant_header.uv_dc_delta = s->quant.uvdc_delta; ++ hdr->quant_header.uv_ac_delta = s->quant.uvac_delta; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, buffer, size); ++} ++ ++static int v4l2_request_vp8_init(AVCodecContext *avctx) ++{ ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP8_FRAME, 2 * 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_vp8_v4l2request_hwaccel = { ++ .name = "vp8_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_VP8, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_vp8_start_frame, ++ .decode_slice = v4l2_request_vp8_decode_slice, ++ .end_frame = v4l2_request_vp8_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsVP8), ++ .init = v4l2_request_vp8_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c +index bab4223aca1..0e1edb46fb2 100644 +--- a/libavcodec/vp8.c ++++ b/libavcodec/vp8.c +@@ -175,6 +175,9 @@ static enum AVPixelFormat get_pixel_format(VP8Context *s) + #endif + #if CONFIG_VP8_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, ++#endif ++#if CONFIG_VP8_V4L2REQUEST_HWACCEL ++ AV_PIX_FMT_DRM_PRIME, + #endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE, +@@ -198,7 +201,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7) + return ret; + } + +- if (!s->actually_webp && !is_vp7) { ++ if (!s->actually_webp && !is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { + s->pix_fmt = get_pixel_format(s); + if (s->pix_fmt < 0) + return AVERROR(EINVAL); +@@ -2968,6 +2971,9 @@ AVCodec ff_vp8_decoder = { + #endif + #if CONFIG_VP8_NVDEC_HWACCEL + HWACCEL_NVDEC(vp8), ++#endif ++#if CONFIG_VP8_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp8), + #endif + NULL + }, + +From cf21ba63945bf6a0a60616ceb0a000e42d02f044 Mon Sep 17 00:00:00 2001 +From: Ezequiel Garcia +Date: Wed, 20 Feb 2019 11:18:00 -0300 +Subject: [PATCH 07/20] avcodec/h264: parse idr_pic_id + +Signed-off-by: Ezequiel Garcia +--- + libavcodec/h264_slice.c | 2 +- + libavcodec/h264dec.h | 2 ++ + libavcodec/v4l2_request_h264.c | 2 +- + 3 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index 3ae11ac8a71..96e8edd1028 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -1822,7 +1822,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + } + + if (nal->type == H264_NAL_IDR_SLICE) +- get_ue_golomb_long(&sl->gb); /* idr_pic_id */ ++ sl->idr_pic_id = get_ue_golomb_long(&sl->gb); + + if (sps->poc_type == 0) { + sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb); +diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h +index a419615124b..aebc5ed2f61 100644 +--- a/libavcodec/h264dec.h ++++ b/libavcodec/h264dec.h +@@ -190,6 +190,8 @@ typedef struct H264SliceContext { + int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) + int slice_type_fixed; + ++ int idr_pic_id; ++ + int qscale; + int chroma_qp[2]; // QPc + int qp_thresh; ///< QP threshold to skip loopfilter +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +index 94b9aca8ad4..9382e573b40 100644 +--- a/libavcodec/v4l2_request_h264.c ++++ b/libavcodec/v4l2_request_h264.c +@@ -303,7 +303,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * + .pic_parameter_set_id = sl->pps_id, + .colour_plane_id = 0, /* what is this? */ + .frame_num = h->poc.frame_num, +- .idr_pic_id = 0, /* what is this? */ ++ .idr_pic_id = sl->idr_pic_id, + .pic_order_cnt_lsb = sl->poc_lsb, + .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, + .delta_pic_order_cnt0 = sl->delta_poc[0], + +From 13d2f3430db4d83ce30c921bf2b3ee44e1d6ec55 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Wed, 22 May 2019 14:44:22 +0200 +Subject: [PATCH 08/20] avcodec/h264: parse ref_pic_marking_size_in_bits and + pic_order_cnt_bit_size + +Signed-off-by: Boris Brezillon +--- + libavcodec/h264_slice.c | 6 +++++- + libavcodec/h264dec.h | 2 ++ + libavcodec/v4l2_request_h264.c | 4 ++-- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index 96e8edd1028..c3896cfd90a 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -1740,7 +1740,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + unsigned int slice_type, tmp, i; + int field_pic_flag, bottom_field_flag; + int first_slice = sl == h->slice_ctx && !h->current_slice; +- int picture_structure; ++ int picture_structure, pos; + + if (first_slice) + av_assert0(!h->setup_finished); +@@ -1824,6 +1824,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + if (nal->type == H264_NAL_IDR_SLICE) + sl->idr_pic_id = get_ue_golomb_long(&sl->gb); + ++ pos = sl->gb.index; + if (sps->poc_type == 0) { + sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb); + +@@ -1837,6 +1838,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) + sl->delta_poc[1] = get_se_golomb(&sl->gb); + } ++ sl->pic_order_cnt_bit_size = sl->gb.index - pos; + + sl->redundant_pic_count = 0; + if (pps->redundant_pic_cnt_present) +@@ -1876,9 +1878,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, + + sl->explicit_ref_marking = 0; + if (nal->ref_idc) { ++ int bit_pos = sl->gb.index; + ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, h->avctx); + if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; ++ sl->ref_pic_marking_size_in_bits = sl->gb.index - bit_pos; + } + + if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) { +diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h +index aebc5ed2f61..b3dcd6e7da3 100644 +--- a/libavcodec/h264dec.h ++++ b/libavcodec/h264dec.h +@@ -330,11 +330,13 @@ typedef struct H264SliceContext { + MMCO mmco[MAX_MMCO_COUNT]; + int nb_mmco; + int explicit_ref_marking; ++ int ref_pic_marking_size_in_bits; + + int frame_num; + int poc_lsb; + int delta_poc_bottom; + int delta_poc[2]; ++ int pic_order_cnt_bit_size; + int curr_pic_num; + int max_pic_num; + } H264SliceContext; +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +index 9382e573b40..bdaeb67d261 100644 +--- a/libavcodec/v4l2_request_h264.c ++++ b/libavcodec/v4l2_request_h264.c +@@ -311,9 +311,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * + .redundant_pic_cnt = sl->redundant_pic_count, + + /* Size in bits of dec_ref_pic_marking() syntax element. */ +- .dec_ref_pic_marking_bit_size = 0, ++ .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_size_in_bits, + /* Size in bits of pic order count syntax. */ +- .pic_order_cnt_bit_size = 0, ++ .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size, + + .cabac_init_idc = sl->cabac_init_idc, + .slice_qp_delta = sl->qscale - pps->init_qp, + +From 5ba945f011277dee7b4fb36af60810fd9b401f79 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 14 Feb 2019 23:20:05 +0100 +Subject: [PATCH 09/20] Add and use private linux headers for V4L2 request API + ctrls + +Signed-off-by: Jernej Skrabec +--- + configure | 6 +- + libavcodec/h264-ctrls.h | 210 +++++++++++++++++++++++++++++++ + libavcodec/hevc-ctrls.h | 212 ++++++++++++++++++++++++++++++++ + libavcodec/mpeg2-ctrls.h | 82 ++++++++++++ + libavcodec/v4l2_request_h264.c | 1 + + libavcodec/v4l2_request_hevc.c | 1 + + libavcodec/v4l2_request_mpeg2.c | 1 + + libavcodec/v4l2_request_vp8.c | 1 + + libavcodec/vp8-ctrls.h | 112 +++++++++++++++++ + 9 files changed, 623 insertions(+), 3 deletions(-) + create mode 100644 libavcodec/h264-ctrls.h + create mode 100644 libavcodec/hevc-ctrls.h + create mode 100644 libavcodec/mpeg2-ctrls.h + create mode 100644 libavcodec/vp8-ctrls.h + +diff --git a/configure b/configure +index cbb91c2bca4..623012757c6 100755 +--- a/configure ++++ b/configure +@@ -2925,7 +2925,7 @@ h264_dxva2_hwaccel_deps="dxva2" + h264_dxva2_hwaccel_select="h264_decoder" + h264_nvdec_hwaccel_deps="nvdec" + h264_nvdec_hwaccel_select="h264_decoder" +-h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request" ++h264_v4l2request_hwaccel_deps="v4l2_request" + h264_v4l2request_hwaccel_select="h264_decoder" + h264_vaapi_hwaccel_deps="vaapi" + h264_vaapi_hwaccel_select="h264_decoder" +@@ -2941,7 +2941,7 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" + hevc_dxva2_hwaccel_select="hevc_decoder" + hevc_nvdec_hwaccel_deps="nvdec" + hevc_nvdec_hwaccel_select="hevc_decoder" +-hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request" ++hevc_v4l2request_hwaccel_deps="v4l2_request" + hevc_v4l2request_hwaccel_select="hevc_decoder" + hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" + hevc_vaapi_hwaccel_select="hevc_decoder" +@@ -3003,7 +3003,7 @@ vc1_vdpau_hwaccel_deps="vdpau" + vc1_vdpau_hwaccel_select="vc1_decoder" + vp8_nvdec_hwaccel_deps="nvdec" + vp8_nvdec_hwaccel_select="vp8_decoder" +-vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request" ++vp8_v4l2request_hwaccel_deps="v4l2_request" + vp8_v4l2request_hwaccel_select="vp8_decoder" + vp8_vaapi_hwaccel_deps="vaapi" + vp8_vaapi_hwaccel_select="vp8_decoder" +diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h +new file mode 100644 +index 00000000000..e877bf1d537 +--- /dev/null ++++ b/libavcodec/h264-ctrls.h +@@ -0,0 +1,210 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the H.264 state controls for use with stateless H.264 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _H264_CTRLS_H_ ++#define _H264_CTRLS_H_ ++ ++#include ++ ++/* Our pixel format isn't stable at the moment */ ++#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ ++ ++/* ++ * This is put insanely high to avoid conflicting with controls that ++ * would be added during the phase where those controls are not ++ * stable. It should be fixed eventually. ++ */ ++#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+1000) ++#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+1001) ++#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+1002) ++#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (V4L2_CID_MPEG_BASE+1003) ++#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004) ++#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005) ++#define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_H264_SPS 0x0110 ++#define V4L2_CTRL_TYPE_H264_PPS 0x0111 ++#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112 ++#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113 ++#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114 ++ ++enum v4l2_mpeg_video_h264_decode_mode { ++ V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_h264_start_code { ++ V4L2_MPEG_VIDEO_H264_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, ++}; ++ ++#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01 ++#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02 ++#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04 ++#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08 ++#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10 ++#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20 ++ ++#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01 ++#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02 ++#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04 ++#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08 ++#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10 ++#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20 ++#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40 ++ ++struct v4l2_ctrl_h264_sps { ++ __u8 profile_idc; ++ __u8 constraint_set_flags; ++ __u8 level_idc; ++ __u8 seq_parameter_set_id; ++ __u8 chroma_format_idc; ++ __u8 bit_depth_luma_minus8; ++ __u8 bit_depth_chroma_minus8; ++ __u8 log2_max_frame_num_minus4; ++ __u8 pic_order_cnt_type; ++ __u8 log2_max_pic_order_cnt_lsb_minus4; ++ __u8 max_num_ref_frames; ++ __u8 num_ref_frames_in_pic_order_cnt_cycle; ++ __s32 offset_for_ref_frame[255]; ++ __s32 offset_for_non_ref_pic; ++ __s32 offset_for_top_to_bottom_field; ++ __u16 pic_width_in_mbs_minus1; ++ __u16 pic_height_in_map_units_minus1; ++ __u32 flags; ++}; ++ ++#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001 ++#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002 ++#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004 ++#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008 ++#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 ++#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 ++#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 ++#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080 ++ ++struct v4l2_ctrl_h264_pps { ++ __u8 pic_parameter_set_id; ++ __u8 seq_parameter_set_id; ++ __u8 num_slice_groups_minus1; ++ __u8 num_ref_idx_l0_default_active_minus1; ++ __u8 num_ref_idx_l1_default_active_minus1; ++ __u8 weighted_bipred_idc; ++ __s8 pic_init_qp_minus26; ++ __s8 pic_init_qs_minus26; ++ __s8 chroma_qp_index_offset; ++ __s8 second_chroma_qp_index_offset; ++ __u16 flags; ++}; ++ ++struct v4l2_ctrl_h264_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++}; ++ ++struct v4l2_h264_weight_factors { ++ __s16 luma_weight[32]; ++ __s16 luma_offset[32]; ++ __s16 chroma_weight[32][2]; ++ __s16 chroma_offset[32][2]; ++}; ++ ++struct v4l2_h264_pred_weight_table { ++ __u16 luma_log2_weight_denom; ++ __u16 chroma_log2_weight_denom; ++ struct v4l2_h264_weight_factors weight_factors[2]; ++}; ++ ++#define V4L2_H264_SLICE_TYPE_P 0 ++#define V4L2_H264_SLICE_TYPE_B 1 ++#define V4L2_H264_SLICE_TYPE_I 2 ++#define V4L2_H264_SLICE_TYPE_SP 3 ++#define V4L2_H264_SLICE_TYPE_SI 4 ++ ++#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01 ++#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02 ++#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 ++#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 ++ ++struct v4l2_ctrl_h264_slice_params { ++ /* Size in bytes, including header */ ++ __u32 size; ++ ++ /* Offset in bytes to the start of slice in the OUTPUT buffer. */ ++ __u32 start_byte_offset; ++ ++ /* Offset in bits to slice_data() from the beginning of this slice. */ ++ __u32 header_bit_size; ++ ++ __u16 first_mb_in_slice; ++ __u8 slice_type; ++ __u8 pic_parameter_set_id; ++ __u8 colour_plane_id; ++ __u8 redundant_pic_cnt; ++ __u16 frame_num; ++ __u16 idr_pic_id; ++ __u16 pic_order_cnt_lsb; ++ __s32 delta_pic_order_cnt_bottom; ++ __s32 delta_pic_order_cnt0; ++ __s32 delta_pic_order_cnt1; ++ ++ struct v4l2_h264_pred_weight_table pred_weight_table; ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ __u32 dec_ref_pic_marking_bit_size; ++ /* Size in bits of pic order count syntax. */ ++ __u32 pic_order_cnt_bit_size; ++ ++ __u8 cabac_init_idc; ++ __s8 slice_qp_delta; ++ __s8 slice_qs_delta; ++ __u8 disable_deblocking_filter_idc; ++ __s8 slice_alpha_c0_offset_div2; ++ __s8 slice_beta_offset_div2; ++ __u8 num_ref_idx_l0_active_minus1; ++ __u8 num_ref_idx_l1_active_minus1; ++ __u32 slice_group_change_cycle; ++ ++ /* ++ * Entries on each list are indices into ++ * v4l2_ctrl_h264_decode_params.dpb[]. ++ */ ++ __u8 ref_pic_list0[32]; ++ __u8 ref_pic_list1[32]; ++ ++ __u32 flags; ++}; ++ ++#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01 ++#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 ++#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 ++ ++struct v4l2_h264_dpb_entry { ++ __u64 reference_ts; ++ __u16 frame_num; ++ __u16 pic_num; ++ /* Note that field is indicated by v4l2_buffer.field */ ++ __s32 top_field_order_cnt; ++ __s32 bottom_field_order_cnt; ++ __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ ++}; ++ ++#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++ ++struct v4l2_ctrl_h264_decode_params { ++ struct v4l2_h264_dpb_entry dpb[16]; ++ __u16 num_slices; ++ __u16 nal_ref_idc; ++ __s32 top_field_order_cnt; ++ __s32 bottom_field_order_cnt; ++ __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */ ++}; ++ ++#endif +diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h +new file mode 100644 +index 00000000000..1009cf0891c +--- /dev/null ++++ b/libavcodec/hevc-ctrls.h +@@ -0,0 +1,212 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the HEVC state controls for use with stateless HEVC ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _HEVC_CTRLS_H_ ++#define _HEVC_CTRLS_H_ ++ ++#include ++ ++/* The pixel format isn't stable at the moment and will likely be renamed. */ ++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ ++ ++#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) ++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) ++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 ++#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 ++#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++ ++enum v4l2_mpeg_video_hevc_decode_mode { ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, ++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED, ++}; ++ ++enum v4l2_mpeg_video_hevc_start_code { ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, ++ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B, ++}; ++ ++#define V4L2_HEVC_SLICE_TYPE_B 0 ++#define V4L2_HEVC_SLICE_TYPE_P 1 ++#define V4L2_HEVC_SLICE_TYPE_I 2 ++ ++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0) ++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1) ++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3) ++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4) ++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5) ++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6) ++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7) ++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8) ++ ++/* The controls are not stable at the moment and will likely be reworked. */ ++struct v4l2_ctrl_hevc_sps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */ ++ __u16 pic_width_in_luma_samples; ++ __u16 pic_height_in_luma_samples; ++ __u8 bit_depth_luma_minus8; ++ __u8 bit_depth_chroma_minus8; ++ __u8 log2_max_pic_order_cnt_lsb_minus4; ++ __u8 sps_max_dec_pic_buffering_minus1; ++ __u8 sps_max_num_reorder_pics; ++ __u8 sps_max_latency_increase_plus1; ++ __u8 log2_min_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_luma_coding_block_size; ++ __u8 log2_min_luma_transform_block_size_minus2; ++ __u8 log2_diff_max_min_luma_transform_block_size; ++ __u8 max_transform_hierarchy_depth_inter; ++ __u8 max_transform_hierarchy_depth_intra; ++ __u8 pcm_sample_bit_depth_luma_minus1; ++ __u8 pcm_sample_bit_depth_chroma_minus1; ++ __u8 log2_min_pcm_luma_coding_block_size_minus3; ++ __u8 log2_diff_max_min_pcm_luma_coding_block_size; ++ __u8 num_short_term_ref_pic_sets; ++ __u8 num_long_term_ref_pics_sps; ++ __u8 chroma_format_idc; ++ ++ __u8 padding; ++ ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0) ++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) ++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) ++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) ++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4) ++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5) ++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6) ++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8) ++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9) ++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10) ++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11) ++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12) ++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13) ++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14) ++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15) ++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16) ++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17) ++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18) ++ ++struct v4l2_ctrl_hevc_pps { ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ ++ __u8 num_extra_slice_header_bits; ++ __s8 init_qp_minus26; ++ __u8 diff_cu_qp_delta_depth; ++ __s8 pps_cb_qp_offset; ++ __s8 pps_cr_qp_offset; ++ __u8 num_tile_columns_minus1; ++ __u8 num_tile_rows_minus1; ++ __u8 column_width_minus1[20]; ++ __u8 row_height_minus1[22]; ++ __s8 pps_beta_offset_div2; ++ __s8 pps_tc_offset_div2; ++ __u8 log2_parallel_merge_level_minus2; ++ ++ __u8 padding[4]; ++ __u64 flags; ++}; ++ ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01 ++#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02 ++#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03 ++ ++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16 ++ ++struct v4l2_hevc_dpb_entry { ++ __u64 timestamp; ++ __u8 rps; ++ __u8 field_pic; ++ __u16 pic_order_cnt[2]; ++ __u8 padding[2]; ++}; ++ ++struct v4l2_hevc_pred_weight_table { ++ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2]; ++ ++ __u8 padding[6]; ++ ++ __u8 luma_log2_weight_denom; ++ __s8 delta_chroma_log2_weight_denom; ++}; ++ ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) ++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) ++ ++struct v4l2_ctrl_hevc_slice_params { ++ __u32 bit_size; ++ __u32 data_bit_offset; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ ++ __u8 nal_unit_type; ++ __u8 nuh_temporal_id_plus1; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 slice_type; ++ __u8 colour_plane_id; ++ __u16 slice_pic_order_cnt; ++ __u8 num_ref_idx_l0_active_minus1; ++ __u8 num_ref_idx_l1_active_minus1; ++ __u8 collocated_ref_idx; ++ __u8 five_minus_max_num_merge_cand; ++ __s8 slice_qp_delta; ++ __s8 slice_cb_qp_offset; ++ __s8 slice_cr_qp_offset; ++ __s8 slice_act_y_qp_offset; ++ __s8 slice_act_cb_qp_offset; ++ __s8 slice_act_cr_qp_offset; ++ __s8 slice_beta_offset_div2; ++ __s8 slice_tc_offset_div2; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */ ++ __u8 pic_struct; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u8 num_active_dpb_entries; ++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ __u8 num_rps_poc_st_curr_before; ++ __u8 num_rps_poc_st_curr_after; ++ __u8 num_rps_poc_lt_curr; ++ ++ __u8 padding; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; ++ ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */ ++ struct v4l2_hevc_pred_weight_table pred_weight_table; ++ ++ __u64 flags; ++}; ++ ++#endif +diff --git a/libavcodec/mpeg2-ctrls.h b/libavcodec/mpeg2-ctrls.h +new file mode 100644 +index 00000000000..6601455b3d5 +--- /dev/null ++++ b/libavcodec/mpeg2-ctrls.h +@@ -0,0 +1,82 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the MPEG2 state controls for use with stateless MPEG-2 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _MPEG2_CTRLS_H_ ++#define _MPEG2_CTRLS_H_ ++ ++#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS (V4L2_CID_MPEG_BASE+250) ++#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION (V4L2_CID_MPEG_BASE+251) ++ ++/* enum v4l2_ctrl_type type values */ ++#define V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS 0x0103 ++#define V4L2_CTRL_TYPE_MPEG2_QUANTIZATION 0x0104 ++ ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_I 1 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_P 2 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_B 3 ++#define V4L2_MPEG2_PICTURE_CODING_TYPE_D 4 ++ ++struct v4l2_mpeg2_sequence { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */ ++ __u16 horizontal_size; ++ __u16 vertical_size; ++ __u32 vbv_buffer_size; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */ ++ __u16 profile_and_level_indication; ++ __u8 progressive_sequence; ++ __u8 chroma_format; ++}; ++ ++struct v4l2_mpeg2_picture { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */ ++ __u8 picture_coding_type; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */ ++ __u8 f_code[2][2]; ++ __u8 intra_dc_precision; ++ __u8 picture_structure; ++ __u8 top_field_first; ++ __u8 frame_pred_frame_dct; ++ __u8 concealment_motion_vectors; ++ __u8 q_scale_type; ++ __u8 intra_vlc_format; ++ __u8 alternate_scan; ++ __u8 repeat_first_field; ++ __u16 progressive_frame; ++}; ++ ++struct v4l2_ctrl_mpeg2_slice_params { ++ __u32 bit_size; ++ __u32 data_bit_offset; ++ __u64 backward_ref_ts; ++ __u64 forward_ref_ts; ++ ++ struct v4l2_mpeg2_sequence sequence; ++ struct v4l2_mpeg2_picture picture; ++ ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */ ++ __u32 quantiser_scale_code; ++}; ++ ++struct v4l2_ctrl_mpeg2_quantization { ++ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */ ++ __u8 load_intra_quantiser_matrix; ++ __u8 load_non_intra_quantiser_matrix; ++ __u8 load_chroma_intra_quantiser_matrix; ++ __u8 load_chroma_non_intra_quantiser_matrix; ++ ++ __u8 intra_quantiser_matrix[64]; ++ __u8 non_intra_quantiser_matrix[64]; ++ __u8 chroma_intra_quantiser_matrix[64]; ++ __u8 chroma_non_intra_quantiser_matrix[64]; ++}; ++ ++#endif +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +index bdaeb67d261..0254716e523 100644 +--- a/libavcodec/v4l2_request_h264.c ++++ b/libavcodec/v4l2_request_h264.c +@@ -19,6 +19,7 @@ + #include "h264dec.h" + #include "hwconfig.h" + #include "v4l2_request.h" ++#include "h264-ctrls.h" + + typedef struct V4L2RequestControlsH264 { + struct v4l2_ctrl_h264_sps sps; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +index f7249095465..c16f8a868e3 100644 +--- a/libavcodec/v4l2_request_hevc.c ++++ b/libavcodec/v4l2_request_hevc.c +@@ -19,6 +19,7 @@ + #include "hevcdec.h" + #include "hwconfig.h" + #include "v4l2_request.h" ++#include "hevc-ctrls.h" + + #define MAX_SLICES 16 + +diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c +index 88d86cc4c23..bc251a6fd2c 100644 +--- a/libavcodec/v4l2_request_mpeg2.c ++++ b/libavcodec/v4l2_request_mpeg2.c +@@ -19,6 +19,7 @@ + #include "hwconfig.h" + #include "mpegvideo.h" + #include "v4l2_request.h" ++#include "mpeg2-ctrls.h" + + typedef struct V4L2RequestControlsMPEG2 { + struct v4l2_ctrl_mpeg2_slice_params slice_params; +diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c +index 7e75ee398a2..ea2c55fa2f5 100644 +--- a/libavcodec/v4l2_request_vp8.c ++++ b/libavcodec/v4l2_request_vp8.c +@@ -19,6 +19,7 @@ + #include "hwconfig.h" + #include "v4l2_request.h" + #include "vp8.h" ++#include "vp8-ctrls.h" + + typedef struct V4L2RequestControlsVP8 { + struct v4l2_ctrl_vp8_frame_header ctrl; +diff --git a/libavcodec/vp8-ctrls.h b/libavcodec/vp8-ctrls.h +new file mode 100644 +index 00000000000..53cba826e48 +--- /dev/null ++++ b/libavcodec/vp8-ctrls.h +@@ -0,0 +1,112 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP8 state controls for use with stateless VP8 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP8_CTRLS_H_ ++#define _VP8_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000) ++#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301 ++ ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04 ++#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08 ++ ++struct v4l2_vp8_segment_header { ++ __s8 quant_update[4]; ++ __s8 lf_update[4]; ++ __u8 segment_probs[3]; ++ __u8 padding; ++ __u32 flags; ++}; ++ ++#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01 ++#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02 ++#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04 ++struct v4l2_vp8_loopfilter_header { ++ __s8 ref_frm_delta[4]; ++ __s8 mb_mode_delta[4]; ++ __u8 sharpness_level; ++ __u8 level; ++ __u16 padding; ++ __u32 flags; ++}; ++ ++struct v4l2_vp8_quantization_header { ++ __u8 y_ac_qi; ++ __s8 y_dc_delta; ++ __s8 y2_dc_delta; ++ __s8 y2_ac_delta; ++ __s8 uv_dc_delta; ++ __s8 uv_ac_delta; ++ __u16 padding; ++}; ++ ++struct v4l2_vp8_entropy_header { ++ __u8 coeff_probs[4][8][3][11]; ++ __u8 y_mode_probs[4]; ++ __u8 uv_mode_probs[3]; ++ __u8 mv_probs[2][19]; ++ __u8 padding[3]; ++}; ++ ++struct v4l2_vp8_entropy_coder_state { ++ __u8 range; ++ __u8 value; ++ __u8 bit_count; ++ __u8 padding; ++}; ++ ++#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01 ++#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04 ++#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10 ++#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20 ++ ++#define VP8_FRAME_IS_KEY_FRAME(hdr) \ ++ (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME)) ++ ++struct v4l2_ctrl_vp8_frame_header { ++ struct v4l2_vp8_segment_header segment_header; ++ struct v4l2_vp8_loopfilter_header lf_header; ++ struct v4l2_vp8_quantization_header quant_header; ++ struct v4l2_vp8_entropy_header entropy_header; ++ struct v4l2_vp8_entropy_coder_state coder_state; ++ ++ __u16 width; ++ __u16 height; ++ ++ __u8 horizontal_scale; ++ __u8 vertical_scale; ++ ++ __u8 version; ++ __u8 prob_skip_false; ++ __u8 prob_intra; ++ __u8 prob_last; ++ __u8 prob_gf; ++ __u8 num_dct_parts; ++ ++ __u32 first_part_size; ++ __u32 first_part_header_bits; ++ __u32 dct_part_sizes[8]; ++ ++ __u64 last_frame_ts; ++ __u64 golden_frame_ts; ++ __u64 alt_frame_ts; ++ ++ __u64 flags; ++}; ++ ++#endif + +From 77c91a97c87424c1d6bff888bc8562a9b6697aa2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 2 May 2020 11:00:26 +0000 +Subject: [PATCH 10/20] Update to v5.7 private linux headers + +--- + libavcodec/h264-ctrls.h | 2 ++ + libavcodec/v4l2_request_h264.c | 8 +++++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h +index e877bf1d537..1c6ff7d63bc 100644 +--- a/libavcodec/h264-ctrls.h ++++ b/libavcodec/h264-ctrls.h +@@ -185,6 +185,8 @@ struct v4l2_ctrl_h264_slice_params { + #define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01 + #define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 + #define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 ++#define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 ++#define V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD 0x10 + + struct v4l2_h264_dpb_entry { + __u64 reference_ts; +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +index 0254716e523..d28ed07da3b 100644 +--- a/libavcodec/v4l2_request_h264.c ++++ b/libavcodec/v4l2_request_h264.c +@@ -67,8 +67,14 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture + entry->frame_num = pic->frame_num; + entry->pic_num = pic->pic_id; + entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID; +- if (pic->reference) ++ if (pic->reference) { + entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; ++ if (pic->reference != PICT_FRAME) { ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD; ++ if (pic->reference == PICT_BOTTOM_FIELD) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD; ++ } ++ } + if (pic->long_ref) + entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; + if (pic->field_poc[0] != INT_MAX) + +From 40407184ac1cd48d35acc6b0d8bdec48a98c74fb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 2 May 2020 22:03:42 +0000 +Subject: [PATCH 11/20] Update to v5.8 private linux headers + +--- + libavcodec/h264-ctrls.h | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h +index 1c6ff7d63bc..080fd1293c4 100644 +--- a/libavcodec/h264-ctrls.h ++++ b/libavcodec/h264-ctrls.h +@@ -13,6 +13,12 @@ + + #include + ++/* ++ * Maximum DPB size, as specified by section 'A.3.1 Level limits ++ * common to the Baseline, Main, and Extended profiles'. ++ */ ++#define V4L2_H264_NUM_DPB_ENTRIES 16 ++ + /* Our pixel format isn't stable at the moment */ + #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ + +@@ -201,7 +207,7 @@ struct v4l2_h264_dpb_entry { + #define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 + + struct v4l2_ctrl_h264_decode_params { +- struct v4l2_h264_dpb_entry dpb[16]; ++ struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; + __u16 num_slices; + __u16 nal_ref_idc; + __s32 top_field_order_cnt; + +From 6a151e35d99c430030709b49a6abd36349a65887 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 6 Sep 2020 16:07:13 +0000 +Subject: [PATCH 12/20] Update to v5.10 private linux headers + +--- + libavcodec/h264-ctrls.h | 87 +++++++++------- + libavcodec/v4l2_request_h264.c | 182 ++++++++++++++++----------------- + 2 files changed, 136 insertions(+), 133 deletions(-) + +diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h +index 080fd1293c4..ec479915443 100644 +--- a/libavcodec/h264-ctrls.h ++++ b/libavcodec/h264-ctrls.h +@@ -19,6 +19,8 @@ + */ + #define V4L2_H264_NUM_DPB_ENTRIES 16 + ++#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) ++ + /* Our pixel format isn't stable at the moment */ + #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ + +@@ -34,6 +36,7 @@ + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004) + #define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005) + #define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006) ++#define V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS (V4L2_CID_MPEG_BASE+1007) + + /* enum v4l2_ctrl_type type values */ + #define V4L2_CTRL_TYPE_H264_SPS 0x0110 +@@ -41,6 +44,7 @@ + #define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112 + #define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113 + #define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114 ++#define V4L2_CTRL_TYPE_H264_PRED_WEIGHTS 0x0115 + + enum v4l2_mpeg_video_h264_decode_mode { + V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED, +@@ -95,7 +99,7 @@ struct v4l2_ctrl_h264_sps { + #define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010 + #define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020 + #define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040 +-#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080 ++#define V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT 0x0080 + + struct v4l2_ctrl_h264_pps { + __u8 pic_parameter_set_id; +@@ -123,7 +127,14 @@ struct v4l2_h264_weight_factors { + __s16 chroma_offset[32][2]; + }; + +-struct v4l2_h264_pred_weight_table { ++#define V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(pps, slice) \ ++ ((((pps)->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) && \ ++ ((slice)->slice_type == V4L2_H264_SLICE_TYPE_P || \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_SP)) || \ ++ ((pps)->weighted_bipred_idc == 1 && \ ++ (slice)->slice_type == V4L2_H264_SLICE_TYPE_B)) ++ ++struct v4l2_ctrl_h264_pred_weights { + __u16 luma_log2_weight_denom; + __u16 chroma_log2_weight_denom; + struct v4l2_h264_weight_factors weight_factors[2]; +@@ -135,39 +146,29 @@ struct v4l2_h264_pred_weight_table { + #define V4L2_H264_SLICE_TYPE_SP 3 + #define V4L2_H264_SLICE_TYPE_SI 4 + +-#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01 +-#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02 +-#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04 +-#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08 ++#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 ++#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 + +-struct v4l2_ctrl_h264_slice_params { +- /* Size in bytes, including header */ +- __u32 size; ++#define V4L2_H264_TOP_FIELD_REF 0x1 ++#define V4L2_H264_BOTTOM_FIELD_REF 0x2 ++#define V4L2_H264_FRAME_REF 0x3 + +- /* Offset in bytes to the start of slice in the OUTPUT buffer. */ +- __u32 start_byte_offset; ++struct v4l2_h264_reference { ++ __u8 fields; ++ ++ /* Index into v4l2_ctrl_h264_decode_params.dpb[] */ ++ __u8 index; ++}; + ++struct v4l2_ctrl_h264_slice_params { + /* Offset in bits to slice_data() from the beginning of this slice. */ + __u32 header_bit_size; + +- __u16 first_mb_in_slice; ++ __u32 first_mb_in_slice; ++ + __u8 slice_type; +- __u8 pic_parameter_set_id; + __u8 colour_plane_id; + __u8 redundant_pic_cnt; +- __u16 frame_num; +- __u16 idr_pic_id; +- __u16 pic_order_cnt_lsb; +- __s32 delta_pic_order_cnt_bottom; +- __s32 delta_pic_order_cnt0; +- __s32 delta_pic_order_cnt1; +- +- struct v4l2_h264_pred_weight_table pred_weight_table; +- /* Size in bits of dec_ref_pic_marking() syntax element. */ +- __u32 dec_ref_pic_marking_bit_size; +- /* Size in bits of pic order count syntax. */ +- __u32 pic_order_cnt_bit_size; +- + __u8 cabac_init_idc; + __s8 slice_qp_delta; + __s8 slice_qs_delta; +@@ -176,14 +177,11 @@ struct v4l2_ctrl_h264_slice_params { + __s8 slice_beta_offset_div2; + __u8 num_ref_idx_l0_active_minus1; + __u8 num_ref_idx_l1_active_minus1; +- __u32 slice_group_change_cycle; + +- /* +- * Entries on each list are indices into +- * v4l2_ctrl_h264_decode_params.dpb[]. +- */ +- __u8 ref_pic_list0[32]; +- __u8 ref_pic_list1[32]; ++ __u8 reserved; ++ ++ struct v4l2_h264_reference ref_pic_list0[V4L2_H264_REF_LIST_LEN]; ++ struct v4l2_h264_reference ref_pic_list1[V4L2_H264_REF_LIST_LEN]; + + __u32 flags; + }; +@@ -192,26 +190,41 @@ struct v4l2_ctrl_h264_slice_params { + #define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02 + #define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04 + #define V4L2_H264_DPB_ENTRY_FLAG_FIELD 0x08 +-#define V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD 0x10 + + struct v4l2_h264_dpb_entry { + __u64 reference_ts; ++ __u32 pic_num; + __u16 frame_num; +- __u16 pic_num; ++ __u8 fields; ++ __u8 reserved[5]; + /* Note that field is indicated by v4l2_buffer.field */ + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; + __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */ + }; + +-#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01 ++#define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02 ++#define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04 + + struct v4l2_ctrl_h264_decode_params { + struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES]; +- __u16 num_slices; + __u16 nal_ref_idc; ++ __u16 frame_num; + __s32 top_field_order_cnt; + __s32 bottom_field_order_cnt; ++ __u16 idr_pic_id; ++ __u16 pic_order_cnt_lsb; ++ __s32 delta_pic_order_cnt_bottom; ++ __s32 delta_pic_order_cnt0; ++ __s32 delta_pic_order_cnt1; ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ __u32 dec_ref_pic_marking_bit_size; ++ /* Size in bits of pic order count syntax. */ ++ __u32 pic_order_cnt_bit_size; ++ __u32 slice_group_change_cycle; ++ ++ __u32 reserved; + __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */ + }; + +diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c +index d28ed07da3b..c9dbaf8c3e3 100644 +--- a/libavcodec/v4l2_request_h264.c ++++ b/libavcodec/v4l2_request_h264.c +@@ -26,15 +26,17 @@ typedef struct V4L2RequestControlsH264 { + struct v4l2_ctrl_h264_pps pps; + struct v4l2_ctrl_h264_scaling_matrix scaling_matrix; + struct v4l2_ctrl_h264_decode_params decode_params; +- struct v4l2_ctrl_h264_slice_params slice_params[MAX_SLICES]; ++ struct v4l2_ctrl_h264_slice_params slice_params; ++ struct v4l2_ctrl_h264_pred_weights pred_weights; ++ int pred_weights_required; + int first_slice; ++ int num_slices; + } V4L2RequestControlsH264; + + typedef struct V4L2RequestContextH264 { + V4L2RequestContext base; + int decode_mode; + int start_code; +- int max_slices; + } V4L2RequestContextH264; + + static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 }; +@@ -64,19 +66,16 @@ static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int li + static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic) + { + entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f); +- entry->frame_num = pic->frame_num; + entry->pic_num = pic->pic_id; ++ entry->frame_num = pic->frame_num; ++ entry->fields = pic->reference & V4L2_H264_FRAME_REF; + entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID; +- if (pic->reference) { ++ if (entry->fields) + entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE; +- if (pic->reference != PICT_FRAME) { +- entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD; +- if (pic->reference == PICT_BOTTOM_FIELD) +- entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_BOTTOM_FIELD; +- } +- } + if (pic->long_ref) + entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; ++ if (pic->field_picture) ++ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD; + if (pic->field_poc[0] != INT_MAX) + entry->top_field_order_cnt = pic->field_poc[0]; + if (pic->field_poc[1] != INT_MAX) +@@ -103,23 +102,24 @@ static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Cont + } + } + +-static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref) ++static void fill_ref_list(struct v4l2_h264_reference *reference, struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref) + { + uint64_t timestamp; + + if (!ref->parent) +- return 0; ++ return; + + timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f); + + for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) { + struct v4l2_h264_dpb_entry *entry = &decode->dpb[i]; + if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) && +- entry->reference_ts == timestamp) +- return i; ++ entry->reference_ts == timestamp) { ++ reference->fields = ref->reference & V4L2_H264_FRAME_REF; ++ reference->index = i; ++ return; ++ } + } +- +- return 0; + } + + static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h) +@@ -139,13 +139,15 @@ static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h) + .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, + .max_num_ref_frames = sps->ref_frame_count, + .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length, +- //.offset_for_ref_frame[255] - not required? not set by libva-v4l2-request - copy sps->offset_for_ref_frame + .offset_for_non_ref_pic = sps->offset_for_non_ref_pic, + .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field, + .pic_width_in_mbs_minus1 = h->mb_width - 1, + .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1, + }; + ++ if (sps->poc_cycle_length > 0 && sps->poc_cycle_length <= 255) ++ memcpy(ctrl->offset_for_ref_frame, sps->offset_for_ref_frame, sps->poc_cycle_length * sizeof(ctrl->offset_for_ref_frame[0])); ++ + if (sps->residual_color_transform_flag) + ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; + if (sps->transform_bypass) +@@ -196,6 +198,9 @@ static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h) + ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT; + if (pps->transform_8x8_mode) + ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE; ++ ++ /* FFmpeg always provide a scaling matrix */ ++ ctrl->flags |= V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT; + } + + static int v4l2_request_h264_start_frame(AVCodecContext *avctx, +@@ -205,6 +210,7 @@ static int v4l2_request_h264_start_frame(AVCodecContext *avctx, + const H264Context *h = avctx->priv_data; + const PPS *pps = h->ps.pps; + const SPS *sps = h->ps.sps; ++ const H264SliceContext *sl = &h->slice_ctx[0]; + V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; + + fill_sps(&controls->sps, h); +@@ -222,18 +228,33 @@ static int v4l2_request_h264_start_frame(AVCodecContext *avctx, + } + + controls->decode_params = (struct v4l2_ctrl_h264_decode_params) { +- .num_slices = 0, + .nal_ref_idc = h->nal_ref_idc, ++ .frame_num = h->poc.frame_num, + .top_field_order_cnt = h->cur_pic_ptr->field_poc[0] != INT_MAX ? h->cur_pic_ptr->field_poc[0] : 0, + .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1] != INT_MAX ? h->cur_pic_ptr->field_poc[1] : 0, ++ .idr_pic_id = sl->idr_pic_id, ++ .pic_order_cnt_lsb = sl->poc_lsb, ++ .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, ++ .delta_pic_order_cnt0 = sl->delta_poc[0], ++ .delta_pic_order_cnt1 = sl->delta_poc[1], ++ /* Size in bits of dec_ref_pic_marking() syntax element. */ ++ .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_size_in_bits, ++ /* Size in bits of pic order count syntax. */ ++ .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size, ++ .slice_group_change_cycle = 0, /* slice group not supported by FFmpeg */ + }; + + if (h->picture_idr) + controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC; ++ if (FIELD_PICTURE(h)) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC; ++ if (h->picture_structure == PICT_BOTTOM_FIELD) ++ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD; + + fill_dpb(&controls->decode_params, h); + + controls->first_slice = !FIELD_PICTURE(h) || h->first_field; ++ controls->num_slices = 0; + + return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); + } +@@ -260,22 +281,29 @@ static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice) + .ptr = &controls->scaling_matrix, + .size = sizeof(controls->scaling_matrix), + }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, + { + .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, + .ptr = &controls->slice_params, +- .size = sizeof(controls->slice_params[0]) * FFMAX(FFMIN(controls->decode_params.num_slices, MAX_SLICES), ctx->max_slices), ++ .size = sizeof(controls->slice_params), + }, + { +- .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, +- .ptr = &controls->decode_params, +- .size = sizeof(controls->decode_params), ++ .id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS, ++ .ptr = &controls->pred_weights, ++ .size = sizeof(controls->pred_weights), + }, + }; + +- if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) +- return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice); ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) { ++ int count = FF_ARRAY_ELEMS(control) - (controls->pred_weights_required ? 0 : 1); ++ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, count, controls->first_slice, last_slice); ++ } + +- return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control)); ++ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control) - 2); + } + + static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +@@ -285,89 +313,72 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t * + const H264SliceContext *sl = &h->slice_ctx[0]; + V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private; + V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; +- V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->cur_pic_ptr->f->data[0]; +- int i, ret, count, slice = FFMIN(controls->decode_params.num_slices, MAX_SLICES - 1); ++ int i, ret, count; + +- if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && slice) { ++ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && controls->num_slices) { + ret = v4l2_request_h264_queue_decode(avctx, 0); + if (ret) + return ret; + + ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f); +- slice = controls->decode_params.num_slices = 0; + controls->first_slice = 0; + } + +- controls->slice_params[slice] = (struct v4l2_ctrl_h264_slice_params) { +- /* Size in bytes, including header */ +- .size = 0, +- .start_byte_offset = req->output.used, ++ if (ctx->start_code == V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3); ++ if (ret) ++ return ret; ++ } ++ ++ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size); ++ if (ret) ++ return ret; ++ ++ if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED) ++ return 0; ++ ++ controls->slice_params = (struct v4l2_ctrl_h264_slice_params) { + /* Offset in bits to slice_data() from the beginning of this slice. */ + .header_bit_size = get_bits_count(&sl->gb), + + .first_mb_in_slice = sl->first_mb_addr, ++ + .slice_type = ff_h264_get_slice_type(sl), +- .pic_parameter_set_id = sl->pps_id, +- .colour_plane_id = 0, /* what is this? */ +- .frame_num = h->poc.frame_num, +- .idr_pic_id = sl->idr_pic_id, +- .pic_order_cnt_lsb = sl->poc_lsb, +- .delta_pic_order_cnt_bottom = sl->delta_poc_bottom, +- .delta_pic_order_cnt0 = sl->delta_poc[0], +- .delta_pic_order_cnt1 = sl->delta_poc[1], ++ .colour_plane_id = 0, /* separate colour plane not supported by FFmpeg */ + .redundant_pic_cnt = sl->redundant_pic_count, +- +- /* Size in bits of dec_ref_pic_marking() syntax element. */ +- .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_size_in_bits, +- /* Size in bits of pic order count syntax. */ +- .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size, +- + .cabac_init_idc = sl->cabac_init_idc, + .slice_qp_delta = sl->qscale - pps->init_qp, +- .slice_qs_delta = 0, /* XXX not implemented by FFmpeg */ ++ .slice_qs_delta = 0, /* not implemented by FFmpeg */ + .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter, + .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2, + .slice_beta_offset_div2 = sl->slice_beta_offset / 2, +- .slice_group_change_cycle = 0, /* what is this? */ +- + .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0, + .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0, + }; + +- if (FIELD_PICTURE(h)) +- controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_FIELD_PIC; +- if (h->picture_structure == PICT_BOTTOM_FIELD) +- controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_BOTTOM_FIELD; + if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred) +- controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED; ++ controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED; ++ /* V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH: not implemented by FFmpeg */ + +- controls->slice_params[slice].pred_weight_table.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; +- controls->slice_params[slice].pred_weight_table.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; ++ controls->pred_weights_required = V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(&controls->pps, &controls->slice_params); ++ if (controls->pred_weights_required) { ++ controls->pred_weights.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; ++ controls->pred_weights.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; ++ } + + count = sl->list_count > 0 ? sl->ref_count[0] : 0; + for (i = 0; i < count; i++) +- controls->slice_params[slice].ref_pic_list0[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[0][i]); +- if (count) +- fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[0], 0, sl); ++ fill_ref_list(&controls->slice_params.ref_pic_list0[i], &controls->decode_params, &sl->ref_list[0][i]); ++ if (count && controls->pred_weights_required) ++ fill_weight_factors(&controls->pred_weights.weight_factors[0], 0, sl); + + count = sl->list_count > 1 ? sl->ref_count[1] : 0; + for (i = 0; i < count; i++) +- controls->slice_params[slice].ref_pic_list1[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[1][i]); +- if (count) +- fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[1], 1, sl); +- +- if (ctx->start_code == V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) { +- ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3); +- if (ret) +- return ret; +- } ++ fill_ref_list(&controls->slice_params.ref_pic_list1[i], &controls->decode_params, &sl->ref_list[1][i]); ++ if (count && controls->pred_weights_required) ++ fill_weight_factors(&controls->pred_weights.weight_factors[1], 1, sl); + +- ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size); +- if (ret) +- return ret; +- +- controls->slice_params[slice].size = req->output.used - controls->slice_params[slice].start_byte_offset; +- controls->decode_params.num_slices++; ++ controls->num_slices++; + return 0; + } + +@@ -380,15 +391,11 @@ static int v4l2_request_h264_end_frame(AVCodecContext *avctx) + static int v4l2_request_h264_set_controls(AVCodecContext *avctx) + { + V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data; +- int ret; + + struct v4l2_ext_control control[] = { + { .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, }, + { .id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, }, + }; +- struct v4l2_query_ext_ctrl slice_params = { +- .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, +- }; + + ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE); + if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && +@@ -404,16 +411,6 @@ static int v4l2_request_h264_set_controls(AVCodecContext *avctx) + return AVERROR(EINVAL); + } + +- ret = ff_v4l2_request_query_control(avctx, &slice_params); +- if (ret) +- return ret; +- +- ctx->max_slices = slice_params.elems; +- if (ctx->max_slices > MAX_SLICES) { +- av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %d\n", __func__, ctx->max_slices); +- return AVERROR(EINVAL); +- } +- + control[0].value = ctx->decode_mode; + control[1].value = ctx->start_code; + +@@ -424,7 +421,6 @@ static int v4l2_request_h264_init(AVCodecContext *avctx) + { + const H264Context *h = avctx->priv_data; + struct v4l2_ctrl_h264_sps sps; +- struct v4l2_ctrl_h264_pps pps; + int ret; + + struct v4l2_ext_control control[] = { +@@ -433,15 +429,9 @@ static int v4l2_request_h264_init(AVCodecContext *avctx) + .ptr = &sps, + .size = sizeof(sps), + }, +- { +- .id = V4L2_CID_MPEG_VIDEO_H264_PPS, +- .ptr = &pps, +- .size = sizeof(pps), +- }, + }; + + fill_sps(&sps, h); +- fill_pps(&pps, h); + + ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control)); + if (ret) + +From f9f4a89058a6fac25712cc385eab72f70e9ac4c8 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 29 Apr 2019 22:08:59 +0000 +Subject: [PATCH 13/20] HACK: hwcontext_drm: do not require drm device + +Signed-off-by: Jonas Karlman +--- + libavutil/hwcontext_drm.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c +index 32cbde82ebf..aa4794c5e66 100644 +--- a/libavutil/hwcontext_drm.c ++++ b/libavutil/hwcontext_drm.c +@@ -43,6 +43,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device, + AVDRMDeviceContext *hwctx = hwdev->hwctx; + drmVersionPtr version; + ++ if (device == NULL) { ++ hwctx->fd = -1; ++ return 0; ++ } ++ + hwctx->fd = open(device, O_RDWR); + if (hwctx->fd < 0) + return AVERROR(errno); + +From 027f8c90ec25c42899b24d96b434e6ed1a1a8c40 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 14/20] WIP: hevc scaling matrix + +Signed-off-by: Jernej Skrabec +--- + libavcodec/hevc-ctrls.h | 11 +++++++++++ + libavcodec/v4l2_request_hevc.c | 22 ++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h +index 1009cf0891c..1592e52c361 100644 +--- a/libavcodec/hevc-ctrls.h ++++ b/libavcodec/hevc-ctrls.h +@@ -19,6 +19,7 @@ + #define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008) + #define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009) + #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010) ++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011) + #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015) + #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016) + +@@ -26,6 +27,7 @@ + #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 + #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 + #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 ++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 + + enum v4l2_mpeg_video_hevc_decode_mode { + V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, +@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { + __u64 flags; + }; + ++struct v4l2_ctrl_hevc_scaling_matrix { ++ __u8 scaling_list_4x4[6][16]; ++ __u8 scaling_list_8x8[6][64]; ++ __u8 scaling_list_16x16[6][64]; ++ __u8 scaling_list_32x32[2][64]; ++ __u8 scaling_list_dc_coef_16x16[6]; ++ __u8 scaling_list_dc_coef_32x32[2]; ++}; ++ + #endif +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +index c16f8a868e3..f400bf4f3c8 100644 +--- a/libavcodec/v4l2_request_hevc.c ++++ b/libavcodec/v4l2_request_hevc.c +@@ -26,6 +26,7 @@ + typedef struct V4L2RequestControlsHEVC { + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_pps pps; ++ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; + struct v4l2_ctrl_hevc_slice_params slice_params[MAX_SLICES]; + int first_slice; + int num_slices; //TODO: this should be in control +@@ -295,6 +296,22 @@ static int v4l2_request_hevc_start_frame(AVCodecContext *avctx, + + fill_sps(&controls->sps, h); + ++ if (sl) { ++ for (int i = 0; i < 6; i++) { ++ for (int j = 0; j < 16; j++) ++ controls->scaling_matrix.scaling_list_4x4[i][j] = sl->sl[0][i][j]; ++ for (int j = 0; j < 64; j++) { ++ controls->scaling_matrix.scaling_list_8x8[i][j] = sl->sl[1][i][j]; ++ controls->scaling_matrix.scaling_list_16x16[i][j] = sl->sl[2][i][j]; ++ if (i < 2) ++ controls->scaling_matrix.scaling_list_32x32[i][j] = sl->sl[3][i * 3][j]; ++ } ++ controls->scaling_matrix.scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i]; ++ if (i < 2) ++ controls->scaling_matrix.scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3]; ++ } ++ } ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */ + controls->pps = (struct v4l2_ctrl_hevc_pps) { + .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, +@@ -398,6 +415,11 @@ static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice) + .ptr = &controls->pps, + .size = sizeof(controls->pps), + }, ++ { ++ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX, ++ .ptr = &controls->scaling_matrix, ++ .size = sizeof(controls->scaling_matrix), ++ }, + { + .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, + .ptr = &controls->slice_params, + +From 9c4a66cca0df6fd0976f907f1e315a715e5ffd87 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 15/20] WIP: hevc segment address + +Signed-off-by: Jernej Skrabec +--- + libavcodec/hevc-ctrls.h | 5 ++++- + libavcodec/v4l2_request_hevc.c | 3 +++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h +index 1592e52c361..3e2e3209831 100644 +--- a/libavcodec/hevc-ctrls.h ++++ b/libavcodec/hevc-ctrls.h +@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u32 bit_size; + __u32 data_bit_offset; + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ __u32 slice_segment_addr; ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; + __u8 nuh_temporal_id_plus1; +@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding; ++ __u8 padding[5]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +index f400bf4f3c8..98222fc74c3 100644 +--- a/libavcodec/v4l2_request_hevc.c ++++ b/libavcodec/v4l2_request_hevc.c +@@ -138,6 +138,9 @@ static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h, + .bit_size = 0, + .data_bit_offset = get_bits_count(&h->HEVClc->gb), + ++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ ++ .slice_segment_addr = sh->slice_segment_addr, ++ + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + .nal_unit_type = h->nal_unit_type, + .nuh_temporal_id_plus1 = h->temporal_id + 1, + +From 62795e555cfcccfc29c144f0ed5acae5336479c7 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 15 Dec 2018 22:32:16 +0100 +Subject: [PATCH 16/20] WIP: hevc entry point offsets + +Signed-off-by: Jernej Skrabec +--- + libavcodec/hevc-ctrls.h | 5 ++++- + libavcodec/v4l2_request_hevc.c | 9 +++++++++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h +index 3e2e3209831..d1b094c8aae 100644 +--- a/libavcodec/hevc-ctrls.h ++++ b/libavcodec/hevc-ctrls.h +@@ -169,6 +169,7 @@ struct v4l2_ctrl_hevc_slice_params { + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + __u32 slice_segment_addr; ++ __u32 num_entry_point_offsets; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ + __u8 nal_unit_type; +@@ -203,7 +204,9 @@ struct v4l2_ctrl_hevc_slice_params { + __u8 num_rps_poc_st_curr_after; + __u8 num_rps_poc_lt_curr; + +- __u8 padding[5]; ++ __u8 padding; ++ ++ __u32 entry_point_offset_minus1[256]; + + /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ + struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c +index 98222fc74c3..7e77c83e4e4 100644 +--- a/libavcodec/v4l2_request_hevc.c ++++ b/libavcodec/v4l2_request_hevc.c +@@ -225,6 +225,15 @@ static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h, + } + + v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table); ++ ++ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets; ++ if (slice_params->num_entry_point_offsets > 256) { ++ slice_params->num_entry_point_offsets = 256; ++ av_log(NULL, AV_LOG_ERROR, "%s: Currently only 256 entry points are supported, but slice has %d entry points.\n", __func__, sh->num_entry_point_offsets); ++ } ++ ++ for (i = 0; i < slice_params->num_entry_point_offsets; i++) ++ slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1; + } + + static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h) + +From edaaede001e7fbae26a0a668ea1db2b642896322 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 12 Dec 2019 16:13:55 +0100 +Subject: [PATCH 17/20] WIP: Add V4L2 request API vp9 hwaccel + +Signed-off-by: Boris Brezillon +--- + configure | 3 + + libavcodec/Makefile | 1 + + libavcodec/hwaccels.h | 1 + + libavcodec/v4l2_request_vp9.c | 352 ++++++++++++++++++++++++++++++++++ + libavcodec/vp9.c | 13 +- + libavcodec/vp9shared.h | 1 + + 6 files changed, 370 insertions(+), 1 deletion(-) + create mode 100644 libavcodec/v4l2_request_vp9.c + +diff --git a/configure b/configure +index 623012757c6..2b723df55ae 100755 +--- a/configure ++++ b/configure +@@ -3015,6 +3015,8 @@ vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" + vp9_dxva2_hwaccel_select="vp9_decoder" + vp9_nvdec_hwaccel_deps="nvdec" + vp9_nvdec_hwaccel_select="vp9_decoder" ++vp9_v4l2request_hwaccel_deps="v4l2_request vp9_v4l2_request" ++vp9_v4l2request_hwaccel_select="vp9_decoder" + vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" + vp9_vaapi_hwaccel_select="vp9_decoder" + vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9" +@@ -6579,6 +6581,7 @@ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;" + check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;" + check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;" + check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;" ++check_cc vp9_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP9_FRAME;" + + check_headers sys/videoio.h + test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index d6af854daaa..2f0e0a0976f 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -945,6 +945,7 @@ OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o + OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o + OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o ++OBJS-$(CONFIG_VP9_V4L2REQUEST_HWACCEL) += v4l2_request_vp9.o + OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o + OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o + OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o +diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h +index bd75e94f4ca..03a1aefe09b 100644 +--- a/libavcodec/hwaccels.h ++++ b/libavcodec/hwaccels.h +@@ -71,6 +71,7 @@ extern const AVHWAccel ff_vp9_d3d11va_hwaccel; + extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; + extern const AVHWAccel ff_vp9_dxva2_hwaccel; + extern const AVHWAccel ff_vp9_nvdec_hwaccel; ++extern const AVHWAccel ff_vp9_v4l2request_hwaccel; + extern const AVHWAccel ff_vp9_vaapi_hwaccel; + extern const AVHWAccel ff_vp9_vdpau_hwaccel; + extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; +diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c +new file mode 100644 +index 00000000000..4074c7fe4b8 +--- /dev/null ++++ b/libavcodec/v4l2_request_vp9.c +@@ -0,0 +1,352 @@ ++/* ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "hwconfig.h" ++#include "v4l2_request.h" ++#include "vp9dec.h" ++ ++typedef struct V4L2RequestControlsVP9 { ++ struct v4l2_ctrl_vp9_frame_decode_params decode_params; ++} V4L2RequestControlsVP9; ++ ++static const uint8_t ff_to_v4l2_intramode[] = { ++ [VERT_PRED] = V4L2_VP9_INTRA_PRED_MODE_V, ++ [HOR_PRED] = V4L2_VP9_INTRA_PRED_MODE_H, ++ [DC_PRED] = V4L2_VP9_INTRA_PRED_MODE_DC, ++ [DIAG_DOWN_LEFT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D45, ++ [DIAG_DOWN_RIGHT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D135, ++ [VERT_RIGHT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D117, ++ [HOR_DOWN_PRED] = V4L2_VP9_INTRA_PRED_MODE_D153, ++ [VERT_LEFT_PRED] = V4L2_VP9_INTRA_PRED_MODE_D63, ++ [HOR_UP_PRED] = V4L2_VP9_INTRA_PRED_MODE_D207, ++ [TM_VP8_PRED] = V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++static int v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx, unsigned int id) ++{ ++ VP9Context *s = avctx->priv_data; ++ struct v4l2_ctrl_vp9_frame_ctx fctx = {}; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(id), ++ .ptr = &fctx, ++ .size = sizeof(fctx), ++ }, ++ }; ++ ++ memcpy(fctx.probs.tx8, s->prob_ctx[id].p.tx8p, sizeof(s->prob_ctx[id].p.tx8p)); ++ memcpy(fctx.probs.tx16, s->prob_ctx[id].p.tx16p, sizeof(s->prob_ctx[id].p.tx16p)); ++ memcpy(fctx.probs.tx32, s->prob_ctx[id].p.tx32p, sizeof(s->prob_ctx[id].p.tx32p)); ++ memcpy(fctx.probs.coef, s->prob_ctx[id].coef, sizeof(s->prob_ctx[id].coef)); ++ memcpy(fctx.probs.skip, s->prob_ctx[id].p.skip, sizeof(s->prob_ctx[id].p.skip)); ++ memcpy(fctx.probs.inter_mode, s->prob_ctx[id].p.mv_mode, sizeof(s->prob_ctx[id].p.mv_mode)); ++ memcpy(fctx.probs.interp_filter, s->prob_ctx[id].p.filter, sizeof(s->prob_ctx[id].p.filter)); ++ memcpy(fctx.probs.is_inter, s->prob_ctx[id].p.intra, sizeof(s->prob_ctx[id].p.intra)); ++ memcpy(fctx.probs.comp_mode, s->prob_ctx[id].p.comp, sizeof(s->prob_ctx[id].p.comp)); ++ memcpy(fctx.probs.single_ref, s->prob_ctx[id].p.single_ref, sizeof(s->prob_ctx[id].p.single_ref)); ++ memcpy(fctx.probs.comp_ref, s->prob_ctx[id].p.comp_ref, sizeof(s->prob_ctx[id].p.comp_ref)); ++ memcpy(fctx.probs.y_mode, s->prob_ctx[id].p.y_mode, sizeof(s->prob_ctx[id].p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(fctx.probs.uv_mode[ff_to_v4l2_intramode[i]], s->prob_ctx[id].p.uv_mode[i], sizeof(s->prob_ctx[id].p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(fctx.probs.partition[i * 4], s->prob_ctx[id].p.partition[3 - i], sizeof(s->prob_ctx[id].p.partition[0])); ++ memcpy(fctx.probs.mv.joint, s->prob_ctx[id].p.mv_joint, sizeof(s->prob_ctx[id].p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ fctx.probs.mv.sign[i] = s->prob_ctx[id].p.mv_comp[i].sign; ++ memcpy(fctx.probs.mv.class[i], s->prob_ctx[id].p.mv_comp[i].classes, sizeof(s->prob_ctx[id].p.mv_comp[0].classes)); ++ fctx.probs.mv.class0_bit[i] = s->prob_ctx[id].p.mv_comp[i].class0; ++ memcpy(fctx.probs.mv.bits[i], s->prob_ctx[id].p.mv_comp[i].bits, sizeof(s->prob_ctx[id].p.mv_comp[0].bits)); ++ memcpy(fctx.probs.mv.class0_fr[i], s->prob_ctx[id].p.mv_comp[i].class0_fp, sizeof(s->prob_ctx[id].p.mv_comp[0].class0_fp)); ++ memcpy(fctx.probs.mv.fr[i], s->prob_ctx[id].p.mv_comp[i].fp, sizeof(s->prob_ctx[id].p.mv_comp[0].fp)); ++ fctx.probs.mv.class0_hp[i] = s->prob_ctx[id].p.mv_comp[i].class0_hp; ++ fctx.probs.mv.hp[i] = s->prob_ctx[id].p.mv_comp[i].hp; ++ } ++ ++ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++} ++ ++static int v4l2_request_vp9_get_frame_ctx(AVCodecContext *avctx, unsigned int id) ++{ ++ VP9Context *s = avctx->priv_data; ++ struct v4l2_ctrl_vp9_frame_ctx fctx = {}; ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(id), ++ .ptr = &fctx, ++ .size = sizeof(fctx), ++ }, ++ }; ++ ++ int ret = ff_v4l2_request_get_controls(avctx, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ memcpy(s->prob_ctx[id].p.tx8p, fctx.probs.tx8, sizeof(s->prob_ctx[id].p.tx8p)); ++ memcpy(s->prob_ctx[id].p.tx16p, fctx.probs.tx16, sizeof(s->prob_ctx[id].p.tx16p)); ++ memcpy(s->prob_ctx[id].p.tx32p, fctx.probs.tx32, sizeof(s->prob_ctx[id].p.tx32p)); ++ memcpy(s->prob_ctx[id].coef, fctx.probs.coef, sizeof(s->prob_ctx[id].coef)); ++ memcpy(s->prob_ctx[id].p.skip, fctx.probs.skip, sizeof(s->prob_ctx[id].p.skip)); ++ memcpy(s->prob_ctx[id].p.mv_mode, fctx.probs.inter_mode, sizeof(s->prob_ctx[id].p.mv_mode)); ++ memcpy(s->prob_ctx[id].p.filter, fctx.probs.interp_filter, sizeof(s->prob_ctx[id].p.filter)); ++ memcpy(s->prob_ctx[id].p.intra, fctx.probs.is_inter, sizeof(s->prob_ctx[id].p.intra)); ++ memcpy(s->prob_ctx[id].p.comp, fctx.probs.comp_mode, sizeof(s->prob_ctx[id].p.comp)); ++ memcpy(s->prob_ctx[id].p.single_ref, fctx.probs.single_ref, sizeof(s->prob_ctx[id].p.single_ref)); ++ memcpy(s->prob_ctx[id].p.comp_ref, fctx.probs.comp_ref, sizeof(s->prob_ctx[id].p.comp_ref)); ++ memcpy(s->prob_ctx[id].p.y_mode, fctx.probs.y_mode, sizeof(s->prob_ctx[id].p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(s->prob_ctx[id].p.uv_mode[i], fctx.probs.uv_mode[ff_to_v4l2_intramode[i]], sizeof(s->prob_ctx[id].p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(s->prob_ctx[id].p.partition[3 - i], fctx.probs.partition[i * 4], sizeof(s->prob_ctx[id].p.partition[0])); ++ memcpy(s->prob_ctx[id].p.mv_joint, fctx.probs.mv.joint, sizeof(s->prob_ctx[id].p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ s->prob_ctx[id].p.mv_comp[i].sign = fctx.probs.mv.sign[i]; ++ memcpy(s->prob_ctx[id].p.mv_comp[i].classes, fctx.probs.mv.class[i], sizeof(s->prob_ctx[id].p.mv_comp[0].classes)); ++ s->prob_ctx[id].p.mv_comp[i].class0 = fctx.probs.mv.class0_bit[i]; ++ memcpy(s->prob_ctx[id].p.mv_comp[i].bits, fctx.probs.mv.bits[i], sizeof(s->prob_ctx[id].p.mv_comp[0].bits)); ++ memcpy(s->prob_ctx[id].p.mv_comp[i].class0_fp, fctx.probs.mv.class0_fr[i], sizeof(s->prob_ctx[id].p.mv_comp[0].class0_fp)); ++ memcpy(s->prob_ctx[id].p.mv_comp[i].fp, fctx.probs.mv.fr[i], sizeof(s->prob_ctx[id].p.mv_comp[0].fp)); ++ s->prob_ctx[id].p.mv_comp[i].class0_hp = fctx.probs.mv.class0_hp[i]; ++ s->prob_ctx[id].p.mv_comp[i].hp = fctx.probs.mv.hp[i]; ++ } ++ ++ return 0; ++} ++ ++static int v4l2_request_vp9_start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ struct v4l2_ctrl_vp9_frame_decode_params *dec_params = &controls->decode_params; ++ int ret; ++ ++ if (s->s.h.keyframe || s->s.h.errorres || (s->s.h.intraonly && s->s.h.resetctx == 3)) { ++ for (unsigned i = 0; i < 4; i++) { ++ ret = v4l2_request_vp9_set_frame_ctx(avctx, i); ++ if (ret) ++ return ret; ++ } ++ } else if (s->s.h.intraonly && s->s.h.resetctx == 2) { ++ ret = v4l2_request_vp9_set_frame_ctx(avctx, s->s.h.framectxid); ++ if (ret) ++ return ret; ++ } ++ ++ if (s->s.h.keyframe) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_KEY_FRAME; ++ if (!s->s.h.invisible) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_SHOW_FRAME; ++ if (s->s.h.errorres) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT; ++ if (s->s.h.intraonly) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_INTRA_ONLY; ++ if (!s->s.h.keyframe && s->s.h.highprecisionmvs) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV; ++ if (s->s.h.refreshctx) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX; ++ if (s->s.h.parallelmode) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE; ++ if (s->ss_h) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING; ++ if (s->ss_v) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; ++ if (avctx->color_range == AVCOL_RANGE_JPEG) ++ dec_params->flags |= V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING; ++ ++ dec_params->compressed_header_size = s->s.h.compressed_header_size; ++ dec_params->uncompressed_header_size = s->s.h.uncompressed_header_size; ++ dec_params->profile = s->s.h.profile; ++ dec_params->reset_frame_context = s->s.h.resetctx > 0 ? s->s.h.resetctx - 1 : 0; ++ dec_params->frame_context_idx = s->s.h.framectxid; ++ dec_params->bit_depth = s->s.h.bpp; ++ ++ dec_params->interpolation_filter = s->s.h.filtermode ^ (s->s.h.filtermode <= 1); ++ dec_params->tile_cols_log2 = s->s.h.tiling.log2_tile_cols; ++ dec_params->tile_rows_log2 = s->s.h.tiling.log2_tile_rows; ++ dec_params->tx_mode = s->s.h.txfmmode; ++ dec_params->reference_mode = s->s.h.comppredmode; ++ dec_params->frame_width_minus_1 = s->w - 1; ++ dec_params->frame_height_minus_1 = s->h - 1; ++ //dec_params->render_width_minus_1 = avctx->width - 1; ++ //dec_params->render_height_minus_1 = avctx->height - 1; ++ ++ for (unsigned i = 0; i < 3; i++) { ++ const ThreadFrame *ref = &s->s.refs[s->s.h.refidx[i]]; ++ if (ref->f && ref->f->buf[0]) ++ dec_params->refs[i] = ff_v4l2_request_get_capture_timestamp(ref->f); ++ } ++ ++ if (s->s.h.lf_delta.enabled) ++ dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED; ++ if (s->s.h.lf_delta.updated) ++ dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE; ++ ++ dec_params->lf.level = s->s.h.filter.level; ++ dec_params->lf.sharpness = s->s.h.filter.sharpness; ++ for (unsigned i = 0; i < 4; i++) ++ dec_params->lf.ref_deltas[i] = s->s.h.lf_delta.ref[i]; ++ for (unsigned i = 0; i < 2; i++) ++ dec_params->lf.mode_deltas[i] = s->s.h.lf_delta.mode[i]; ++ for (unsigned i = 0; i < 8; i++) { ++ for (unsigned j = 0; j < 4; j++) ++ memcpy(dec_params->lf.level_lookup[i][j], s->s.h.segmentation.feat[i].lflvl[j], sizeof(dec_params->lf.level_lookup[0][0])); ++ } ++ ++ dec_params->quant.base_q_idx = s->s.h.yac_qi; ++ dec_params->quant.delta_q_y_dc = s->s.h.ydc_qdelta; ++ dec_params->quant.delta_q_uv_dc = s->s.h.uvdc_qdelta; ++ dec_params->quant.delta_q_uv_ac = s->s.h.uvac_qdelta; ++ ++ if (s->s.h.segmentation.enabled) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ENABLED; ++ if (s->s.h.segmentation.update_map) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP; ++ if (s->s.h.segmentation.temporal) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE; ++ if (s->s.h.segmentation.update_data) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA; ++ if (s->s.h.segmentation.absolute_vals) ++ dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE; ++ ++ for (unsigned i = 0; i < 7; i++) ++ dec_params->seg.tree_probs[i] = s->s.h.segmentation.prob[i]; ++ ++ if (s->s.h.segmentation.temporal) { ++ for (unsigned i = 0; i < 3; i++) ++ dec_params->seg.pred_probs[i] = s->s.h.segmentation.pred_prob[i]; ++ } else { ++ memset(dec_params->seg.pred_probs, 255, sizeof(dec_params->seg.pred_probs)); ++ } ++ ++ for (unsigned i = 0; i < 8; i++) { ++ if (s->s.h.segmentation.feat[i].q_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_QP_DELTA; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_QP_DELTA] = s->s.h.segmentation.feat[i].q_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].lf_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_LF; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_LF] = s->s.h.segmentation.feat[i].lf_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].ref_enabled) { ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_REF_FRAME; ++ dec_params->seg.feature_data[i][V4L2_VP9_SEGMENT_FEATURE_REF_FRAME] = s->s.h.segmentation.feat[i].ref_val; ++ } ++ ++ if (s->s.h.segmentation.feat[i].skip_enabled) ++ dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEGMENT_FEATURE_SKIP; ++ } ++ ++ memcpy(dec_params->probs.tx8, s->prob.p.tx8p, sizeof(s->prob.p.tx8p)); ++ memcpy(dec_params->probs.tx16, s->prob.p.tx16p, sizeof(s->prob.p.tx16p)); ++ memcpy(dec_params->probs.tx32, s->prob.p.tx32p, sizeof(s->prob.p.tx32p)); ++ for (unsigned i = 0; i < 4; i++) { ++ for (unsigned j = 0; j < 2; j++) { ++ for (unsigned k = 0; k < 2; k++) { ++ for (unsigned l = 0; l < 6; l++) { ++ for (unsigned m = 0; m < 6; m++) { ++ memcpy(dec_params->probs.coef[i][j][k][l][m], s->prob.coef[i][j][k][l][m], sizeof(dec_params->probs.coef[0][0][0][0][0])); ++ } ++ } ++ } ++ } ++ } ++ memcpy(dec_params->probs.skip, s->prob.p.skip, sizeof(s->prob.p.skip)); ++ memcpy(dec_params->probs.inter_mode, s->prob.p.mv_mode, sizeof(s->prob.p.mv_mode)); ++ memcpy(dec_params->probs.interp_filter, s->prob.p.filter, sizeof(s->prob.p.filter)); ++ memcpy(dec_params->probs.is_inter, s->prob.p.intra, sizeof(s->prob.p.intra)); ++ memcpy(dec_params->probs.comp_mode, s->prob.p.comp, sizeof(s->prob.p.comp)); ++ memcpy(dec_params->probs.single_ref, s->prob.p.single_ref, sizeof(s->prob.p.single_ref)); ++ memcpy(dec_params->probs.comp_ref, s->prob.p.comp_ref, sizeof(s->prob.p.comp_ref)); ++ memcpy(dec_params->probs.y_mode, s->prob.p.y_mode, sizeof(s->prob.p.y_mode)); ++ for (unsigned i = 0; i < 10; i++) ++ memcpy(dec_params->probs.uv_mode[ff_to_v4l2_intramode[i]], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0])); ++ for (unsigned i = 0; i < 4; i++) ++ memcpy(dec_params->probs.partition[i * 4], s->prob.p.partition[3 - i], sizeof(s->prob.p.partition[0])); ++ memcpy(dec_params->probs.mv.joint, s->prob.p.mv_joint, sizeof(s->prob.p.mv_joint)); ++ for (unsigned i = 0; i < 2; i++) { ++ dec_params->probs.mv.sign[i] = s->prob.p.mv_comp[i].sign; ++ memcpy(dec_params->probs.mv.class[i], s->prob.p.mv_comp[i].classes, sizeof(s->prob.p.mv_comp[0].classes)); ++ dec_params->probs.mv.class0_bit[i] = s->prob.p.mv_comp[i].class0; ++ memcpy(dec_params->probs.mv.bits[i], s->prob.p.mv_comp[i].bits, sizeof(s->prob.p.mv_comp[0].bits)); ++ memcpy(dec_params->probs.mv.class0_fr[i], s->prob.p.mv_comp[i].class0_fp, sizeof(s->prob.p.mv_comp[0].class0_fp)); ++ memcpy(dec_params->probs.mv.fr[i], s->prob.p.mv_comp[i].fp, sizeof(s->prob.p.mv_comp[0].fp)); ++ dec_params->probs.mv.class0_hp[i] = s->prob.p.mv_comp[i].class0_hp; ++ dec_params->probs.mv.hp[i] = s->prob.p.mv_comp[i].hp; ++ } ++ ++ return ff_v4l2_request_reset_frame(avctx, f->tf.f); ++} ++ ++static int v4l2_request_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ ++ return ff_v4l2_request_append_output_buffer(avctx, f->tf.f, buffer, size); ++} ++ ++static int v4l2_request_vp9_end_frame(AVCodecContext *avctx) ++{ ++ const VP9Context *s = avctx->priv_data; ++ const VP9Frame *f = &s->s.frames[CUR_FRAME]; ++ V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private; ++ int ret; ++ ++ struct v4l2_ext_control control[] = { ++ { ++ .id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS, ++ .ptr = &controls->decode_params, ++ .size = sizeof(controls->decode_params), ++ }, ++ }; ++ ++ ret = ff_v4l2_request_decode_frame(avctx, f->tf.f, control, FF_ARRAY_ELEMS(control)); ++ if (ret) ++ return ret; ++ ++ if (!s->s.h.refreshctx) ++ return 0; ++ ++ return v4l2_request_vp9_get_frame_ctx(avctx, s->s.h.framectxid); ++} ++ ++static int v4l2_request_vp9_init(AVCodecContext *avctx) ++{ ++ // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE ++ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, NULL, 0); ++} ++ ++const AVHWAccel ff_vp9_v4l2request_hwaccel = { ++ .name = "vp9_v4l2request", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_VP9, ++ .pix_fmt = AV_PIX_FMT_DRM_PRIME, ++ .start_frame = v4l2_request_vp9_start_frame, ++ .decode_slice = v4l2_request_vp9_decode_slice, ++ .end_frame = v4l2_request_vp9_end_frame, ++ .frame_priv_data_size = sizeof(V4L2RequestControlsVP9), ++ .init = v4l2_request_vp9_init, ++ .uninit = ff_v4l2_request_uninit, ++ .priv_data_size = sizeof(V4L2RequestContext), ++ .frame_params = ff_v4l2_request_frame_params, ++ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, ++}; +diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c +index fd0bab14a23..434f905c62c 100644 +--- a/libavcodec/vp9.c ++++ b/libavcodec/vp9.c +@@ -191,6 +191,7 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \ + CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ + CONFIG_VP9_NVDEC_HWACCEL + \ ++ CONFIG_VP9_V4L2REQUEST_HWACCEL + \ + CONFIG_VP9_VAAPI_HWACCEL + \ + CONFIG_VP9_VDPAU_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; +@@ -223,6 +224,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #endif + #if CONFIG_VP9_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ *fmtp++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + case AV_PIX_FMT_YUV420P12: +@@ -231,6 +235,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) + #endif + #if CONFIG_VP9_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ *fmtp++ = AV_PIX_FMT_DRM_PRIME; + #endif + break; + } +@@ -700,7 +707,8 @@ static int decode_frame_header(AVCodecContext *avctx, + get_bits(&s->gb, 8) : 255; + } + +- if (get_bits1(&s->gb)) { ++ s->s.h.segmentation.update_data = get_bits1(&s->gb); ++ if (s->s.h.segmentation.update_data) { + s->s.h.segmentation.absolute_vals = get_bits1(&s->gb); + for (i = 0; i < 8; i++) { + if ((s->s.h.segmentation.feat[i].q_enabled = get_bits1(&s->gb))) +@@ -1909,6 +1917,9 @@ AVCodec ff_vp9_decoder = { + #endif + #if CONFIG_VP9_VDPAU_HWACCEL + HWACCEL_VDPAU(vp9), ++#endif ++#if CONFIG_VP9_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(vp9), + #endif + NULL + }, +diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h +index 54726df742f..fee3568736f 100644 +--- a/libavcodec/vp9shared.h ++++ b/libavcodec/vp9shared.h +@@ -131,6 +131,7 @@ typedef struct VP9BitstreamHeader { + uint8_t temporal; + uint8_t absolute_vals; + uint8_t update_map; ++ uint8_t update_data; + uint8_t prob[7]; + uint8_t pred_prob[3]; + struct { + +From ef82ae9fffba44e88d59a3fa4b958a38d1b5cd9e Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 12 Dec 2019 16:13:55 +0100 +Subject: [PATCH 18/20] WIP: Add and use vp9 private linux header + +Signed-off-by: Boris Brezillon +--- + configure | 2 +- + libavcodec/v4l2_request_vp9.c | 1 + + libavcodec/vp9-ctrls.h | 485 ++++++++++++++++++++++++++++++++++ + 3 files changed, 487 insertions(+), 1 deletion(-) + create mode 100644 libavcodec/vp9-ctrls.h + +diff --git a/configure b/configure +index 2b723df55ae..87c6836af27 100755 +--- a/configure ++++ b/configure +@@ -3015,7 +3015,7 @@ vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" + vp9_dxva2_hwaccel_select="vp9_decoder" + vp9_nvdec_hwaccel_deps="nvdec" + vp9_nvdec_hwaccel_select="vp9_decoder" +-vp9_v4l2request_hwaccel_deps="v4l2_request vp9_v4l2_request" ++vp9_v4l2request_hwaccel_deps="v4l2_request" + vp9_v4l2request_hwaccel_select="vp9_decoder" + vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" + vp9_vaapi_hwaccel_select="vp9_decoder" +diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c +index 4074c7fe4b8..2e10b7ad1ac 100644 +--- a/libavcodec/v4l2_request_vp9.c ++++ b/libavcodec/v4l2_request_vp9.c +@@ -19,6 +19,7 @@ + #include "hwconfig.h" + #include "v4l2_request.h" + #include "vp9dec.h" ++#include "vp9-ctrls.h" + + typedef struct V4L2RequestControlsVP9 { + struct v4l2_ctrl_vp9_frame_decode_params decode_params; +diff --git a/libavcodec/vp9-ctrls.h b/libavcodec/vp9-ctrls.h +new file mode 100644 +index 00000000000..0cdea8a18b7 +--- /dev/null ++++ b/libavcodec/vp9-ctrls.h +@@ -0,0 +1,485 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * These are the VP9 state controls for use with stateless VP9 ++ * codec drivers. ++ * ++ * It turns out that these structs are not stable yet and will undergo ++ * more changes. So keep them private until they are stable and ready to ++ * become part of the official public API. ++ */ ++ ++#ifndef _VP9_CTRLS_H_ ++#define _VP9_CTRLS_H_ ++ ++#include ++ ++#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') ++ ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_CONTEXT(i) (V4L2_CID_MPEG_BASE + 4000 + (i)) ++#define V4L2_CID_MPEG_VIDEO_VP9_FRAME_DECODE_PARAMS (V4L2_CID_MPEG_BASE + 4004) ++#define V4L2_CTRL_TYPE_VP9_FRAME_CONTEXT 0x400 ++#define V4L2_CTRL_TYPE_VP9_FRAME_DECODE_PARAMS 0x404 ++ ++/** ++ * enum v4l2_vp9_loop_filter_flags - VP9 loop filter flags ++ * ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED: the filter level depends on ++ * the mode and reference frame used ++ * to predict a block ++ * @V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE: the bitstream contains additional ++ * syntax elements that specify which ++ * mode and reference frame deltas ++ * are to be updated ++ * ++ * Those are the flags you should pass to &v4l2_vp9_loop_filter.flags. See ++ * section '7.2.8 Loop filter semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_loop_filter_flags { ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED = 1 << 0, ++ V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE = 1 << 1, ++}; ++ ++/** ++ * struct v4l2_vp9_loop_filter - VP9 loop filter parameters ++ * ++ * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags ++ * @level: indicates the loop filter strength ++ * @sharpness: indicates the sharpness level ++ * @ref_deltas: contains the adjustment needed for the filter level based on ++ * the chosen reference frame ++ * @mode_deltas: contains the adjustment needed for the filter level based on ++ * the chosen mode ++ * @level_lookup: level lookup table ++ * ++ * This structure contains all loop filter related parameters. See sections ++ * '7.2.8 Loop filter semantics' and '8.8.1 Loop filter frame init process' ++ * of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_loop_filter { ++ __u8 flags; ++ __u8 level; ++ __u8 sharpness; ++ __s8 ref_deltas[4]; ++ __s8 mode_deltas[2]; ++ __u8 level_lookup[8][4][2]; ++}; ++ ++/** ++ * struct v4l2_vp9_quantization - VP9 quantization parameters ++ * ++ * @base_q_idx: indicates the base frame qindex ++ * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx ++ * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx ++ * @delta_q_uv_ac indicates the UV AC quantizer relative to base_q_idx ++ * @padding: padding bytes to align things on 64 bits. Must be set to 0 ++ * ++ * Encodes the quantization parameters. See section '7.2.9 Quantization params ++ * syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_quantization { ++ __u8 base_q_idx; ++ __s8 delta_q_y_dc; ++ __s8 delta_q_uv_dc; ++ __s8 delta_q_uv_ac; ++ __u8 padding[4]; ++}; ++ ++/** ++ * enum v4l2_vp9_segmentation_flags - VP9 segmentation flags ++ * ++ * @V4L2_VP9_SEGMENTATION_FLAG_ENABLED: indicates that this frame makes use of ++ * the segmentation tool ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP: indicates that the segmentation map ++ * should be updated during the ++ * decoding of this frame ++ * @V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE: indicates that the updates to ++ * the segmentation map are coded ++ * relative to the existing ++ * segmentation map ++ * @V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA: indicates that new parameters are ++ * about to be specified for each ++ * segment ++ * @V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE: indicates that the ++ * segmentation parameters ++ * represent the actual values ++ * to be used ++ * ++ * Those are the flags you should pass to &v4l2_vp9_segmentation.flags. See ++ * section '7.2.10 Segmentation params syntax' of the VP9 specification for ++ * more details. ++ */ ++enum v4l2_vp9_segmentation_flags { ++ V4L2_VP9_SEGMENTATION_FLAG_ENABLED = 1 << 0, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP = 1 << 1, ++ V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE = 1 << 2, ++ V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA = 1 << 3, ++ V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE = 1 << 4, ++}; ++ ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) ++#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf ++ ++/** ++ * enum v4l2_vp9_segment_feature - VP9 segment feature IDs ++ * ++ * @V4L2_VP9_SEGMENT_FEATURE_QP_DELTA: QP delta segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_LF: loop filter segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_REF_FRAME: reference frame segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_SKIP: skip segment feature ++ * @V4L2_VP9_SEGMENT_FEATURE_CNT: number of segment features ++ * ++ * Segment feature IDs. See section '7.2.10 Segmentation params syntax' of the ++ * VP9 specification for more details. ++ */ ++enum v4l2_vp9_segment_feature { ++ V4L2_VP9_SEGMENT_FEATURE_QP_DELTA, ++ V4L2_VP9_SEGMENT_FEATURE_LF, ++ V4L2_VP9_SEGMENT_FEATURE_REF_FRAME, ++ V4L2_VP9_SEGMENT_FEATURE_SKIP, ++ V4L2_VP9_SEGMENT_FEATURE_CNT, ++}; ++ ++/** ++ * struct v4l2_vp9_segmentation - VP9 segmentation parameters ++ * ++ * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_* flags ++ * @tree_probs: specifies the probability values to be used when ++ * decoding a Segment-ID. See '5.15. Segmentation map' ++ * section of the VP9 specification for more details. ++ * @pred_prob: specifies the probability values to be used when decoding a ++ * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' ++ * section of :ref:`vp9` for more details.. ++ * @padding: padding used to make things aligned on 64 bits. Shall be zero ++ * filled ++ * @feature_enabled: bitmask defining which features are enabled in each ++ * segment ++ * @feature_data: data attached to each feature. Data entry is only valid if ++ * the feature is enabled ++ * ++ * Encodes the quantization parameters. See section '7.2.10 Segmentation ++ * params syntax' of the VP9 specification for more details. ++ */ ++struct v4l2_vp9_segmentation { ++ __u8 flags; ++ __u8 tree_probs[7]; ++ __u8 pred_probs[3]; ++ __u8 padding[5]; ++ __u8 feature_enabled[8]; ++ __s16 feature_data[8][4]; ++}; ++ ++/** ++ * enum v4l2_vp9_intra_prediction_mode - VP9 Intra prediction modes ++ * ++ * @V4L2_VP9_INTRA_PRED_DC: DC intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_V: vertical intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_H: horizontal intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D45: D45 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D135: D135 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D117: D117 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D153: D153 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D207: D207 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_D63: D63 intra prediction ++ * @V4L2_VP9_INTRA_PRED_MODE_TM: True Motion intra prediction ++ * ++ * See section '7.4.5 Intra frame mode info semantics' for more details. ++ */ ++enum v4l2_vp9_intra_prediction_mode { ++ V4L2_VP9_INTRA_PRED_MODE_DC, ++ V4L2_VP9_INTRA_PRED_MODE_V, ++ V4L2_VP9_INTRA_PRED_MODE_H, ++ V4L2_VP9_INTRA_PRED_MODE_D45, ++ V4L2_VP9_INTRA_PRED_MODE_D135, ++ V4L2_VP9_INTRA_PRED_MODE_D117, ++ V4L2_VP9_INTRA_PRED_MODE_D153, ++ V4L2_VP9_INTRA_PRED_MODE_D207, ++ V4L2_VP9_INTRA_PRED_MODE_D63, ++ V4L2_VP9_INTRA_PRED_MODE_TM, ++}; ++ ++/** ++ * struct v4l2_vp9_mv_probabilities - VP9 Motion vector probabilities ++ * @joint: motion vector joint probabilities ++ * @sign: motion vector sign probabilities ++ * @class: motion vector class probabilities ++ * @class0_bit: motion vector class0 bit probabilities ++ * @bits: motion vector bits probabilities ++ * @class0_fr: motion vector class0 fractional bit probabilities ++ * @fr: motion vector fractional bit probabilities ++ * @class0_hp: motion vector class0 high precision fractional bit probabilities ++ * @hp: motion vector high precision fractional bit probabilities ++ */ ++struct v4l2_vp9_mv_probabilities { ++ __u8 joint[3]; ++ __u8 sign[2]; ++ __u8 class[2][10]; ++ __u8 class0_bit[2]; ++ __u8 bits[2][10]; ++ __u8 class0_fr[2][2][3]; ++ __u8 fr[2][3]; ++ __u8 class0_hp[2]; ++ __u8 hp[2]; ++}; ++ ++/** ++ * struct v4l2_vp9_probabilities - VP9 Probabilities ++ * ++ * @tx8: TX 8x8 probabilities ++ * @tx16: TX 16x16 probabilities ++ * @tx32: TX 32x32 probabilities ++ * @coef: coefficient probabilities ++ * @skip: skip probabilities ++ * @inter_mode: inter mode probabilities ++ * @interp_filter: interpolation filter probabilities ++ * @is_inter: is inter-block probabilities ++ * @comp_mode: compound prediction mode probabilities ++ * @single_ref: single ref probabilities ++ * @comp_ref: compound ref probabilities ++ * @y_mode: Y prediction mode probabilities ++ * @uv_mode: UV prediction mode probabilities ++ * @partition: partition probabilities ++ * @mv: motion vector probabilities ++ * ++ * Structure containing most VP9 probabilities. See the VP9 specification ++ * for more details. ++ */ ++struct v4l2_vp9_probabilities { ++ __u8 tx8[2][1]; ++ __u8 tx16[2][2]; ++ __u8 tx32[2][3]; ++ __u8 coef[4][2][2][6][6][3]; ++ __u8 skip[3]; ++ __u8 inter_mode[7][3]; ++ __u8 interp_filter[4][2]; ++ __u8 is_inter[4]; ++ __u8 comp_mode[5]; ++ __u8 single_ref[5][2]; ++ __u8 comp_ref[5]; ++ __u8 y_mode[4][9]; ++ __u8 uv_mode[10][9]; ++ __u8 partition[16][3]; ++ ++ struct v4l2_vp9_mv_probabilities mv; ++}; ++ ++/** ++ * enum v4l2_vp9_reset_frame_context - Valid values for ++ * &v4l2_ctrl_vp9_frame_decode_params->reset_frame_context ++ * ++ * @V4L2_VP9_RESET_FRAME_CTX_NONE: don't reset any frame context ++ * @V4L2_VP9_RESET_FRAME_CTX_SPEC: reset the frame context pointed by ++ * &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx ++ * @V4L2_VP9_RESET_FRAME_CTX_ALL: reset all frame contexts ++ * ++ * See section '7.2 Uncompressed header semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reset_frame_context { ++ V4L2_VP9_RESET_FRAME_CTX_NONE, ++ V4L2_VP9_RESET_FRAME_CTX_SPEC, ++ V4L2_VP9_RESET_FRAME_CTX_ALL, ++}; ++ ++/** ++ * enum v4l2_vp9_interpolation_filter - VP9 interpolation filter types ++ * ++ * @V4L2_VP9_INTERP_FILTER_8TAP: height tap filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH: height tap smooth filter ++ * @V4L2_VP9_INTERP_FILTER_8TAP_SHARP: height tap sharp filter ++ * @V4L2_VP9_INTERP_FILTER_BILINEAR: bilinear filter ++ * @V4L2_VP9_INTERP_FILTER_SWITCHABLE: filter selection is signaled at the ++ * block level ++ * ++ * See section '7.2.7 Interpolation filter semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_interpolation_filter { ++ V4L2_VP9_INTERP_FILTER_8TAP, ++ V4L2_VP9_INTERP_FILTER_8TAP_SMOOTH, ++ V4L2_VP9_INTERP_FILTER_8TAP_SHARP, ++ V4L2_VP9_INTERP_FILTER_BILINEAR, ++ V4L2_VP9_INTERP_FILTER_SWITCHABLE, ++}; ++ ++/** ++ * enum v4l2_vp9_reference_mode - VP9 reference modes ++ * ++ * @V4L2_VP9_REF_MODE_SINGLE: indicates that all the inter blocks use only a ++ * single reference frame to generate motion ++ * compensated prediction ++ * @V4L2_VP9_REF_MODE_COMPOUND: requires all the inter blocks to use compound ++ * mode. Single reference frame prediction is not ++ * allowed ++ * @V4L2_VP9_REF_MODE_SELECT: allows each individual inter block to select ++ * between single and compound prediction modes ++ * ++ * See section '7.3.6 Frame reference mode semantics' of the VP9 specification ++ * for more details. ++ */ ++enum v4l2_vp9_reference_mode { ++ V4L2_VP9_REF_MODE_SINGLE, ++ V4L2_VP9_REF_MODE_COMPOUND, ++ V4L2_VP9_REF_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_tx_mode - VP9 TX modes ++ * ++ * @V4L2_VP9_TX_MODE_ONLY_4X4: transform size is 4x4 ++ * @V4L2_VP9_TX_MODE_ALLOW_8X8: transform size can be up to 8x8 ++ * @V4L2_VP9_TX_MODE_ALLOW_16X16: transform size can be up to 16x16 ++ * @V4L2_VP9_TX_MODE_ALLOW_32X32: transform size can be up to 32x32 ++ * @V4L2_VP9_TX_MODE_SELECT: bitstream contains transform size for each block ++ * ++ * See section '7.3.1 Tx mode semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_tx_mode { ++ V4L2_VP9_TX_MODE_ONLY_4X4, ++ V4L2_VP9_TX_MODE_ALLOW_8X8, ++ V4L2_VP9_TX_MODE_ALLOW_16X16, ++ V4L2_VP9_TX_MODE_ALLOW_32X32, ++ V4L2_VP9_TX_MODE_SELECT, ++}; ++ ++/** ++ * enum v4l2_vp9_ref_id - VP9 Reference frame IDs ++ * ++ * @V4L2_REF_ID_LAST: last reference frame ++ * @V4L2_REF_ID_GOLDEN: golden reference frame ++ * @V4L2_REF_ID_ALTREF: alternative reference frame ++ * @V4L2_REF_ID_CNT: number of reference frames ++ * ++ * See section '7.4.12 Ref frames semantics' of the VP9 specification for more ++ * details. ++ */ ++enum v4l2_vp9_ref_id { ++ V4L2_REF_ID_LAST, ++ V4L2_REF_ID_GOLDEN, ++ V4L2_REF_ID_ALTREF, ++ V4L2_REF_ID_CNT, ++}; ++ ++/** ++ * enum v4l2_vp9_frame_flags - VP9 frame flags ++ * @V4L2_VP9_FRAME_FLAG_KEY_FRAME: the frame is a key frame ++ * @V4L2_VP9_FRAME_FLAG_SHOW_FRAME: the frame should be displayed ++ * @V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT: the decoding should be error resilient ++ * @V4L2_VP9_FRAME_FLAG_INTRA_ONLY: the frame does not reference other frames ++ * @V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV: the frame might can high precision ++ * motion vectors ++ * @V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX: frame context should be updated ++ * after decoding ++ * @V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE: parallel decoding is used ++ * @V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING: vertical subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING: horizontal subsampling is enabled ++ * @V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING: full UV range is used ++ * ++ * Check the VP9 specification for more details. ++ */ ++enum v4l2_vp9_frame_flags { ++ V4L2_VP9_FRAME_FLAG_KEY_FRAME = 1 << 0, ++ V4L2_VP9_FRAME_FLAG_SHOW_FRAME = 1 << 1, ++ V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT = 1 << 2, ++ V4L2_VP9_FRAME_FLAG_INTRA_ONLY = 1 << 3, ++ V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV = 1 << 4, ++ V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX = 1 << 5, ++ V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE = 1 << 6, ++ V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING = 1 << 7, ++ V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING = 1 << 8, ++ V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING = 1 << 9, ++}; ++ ++#define V4L2_VP9_PROFILE_MAX 3 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_decode_params - VP9 frame decoding control ++ * ++ * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags ++ * @compressed_header_size: compressed header size in bytes ++ * @uncompressed_header_size: uncompressed header size in bytes ++ * @profile: VP9 profile. Can be 0, 1, 2 or 3 ++ * @reset_frame_context: specifies whether the frame context should be reset ++ * to default values. See &v4l2_vp9_reset_frame_context ++ * for more details ++ * @frame_context_idx: frame context that should be used/updated ++ * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all ++ * profiles support 10 and/or 12 bits depths ++ * @interpolation_filter: specifies the filter selection used for performing ++ * inter prediction. See &v4l2_vp9_interpolation_filter ++ * for more details ++ * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile ++ * (where the width is measured in units of 8x8 blocks). ++ * Shall be less than or equal to 6 ++ * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile ++ * (where the height is measured in units of 8x8 blocks) ++ * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details ++ * @reference_mode: specifies the type of inter prediction to be used. See ++ * &v4l2_vp9_reference_mode for more details ++ * @padding: needed to make this struct 64 bit aligned. Shall be filled with ++ * zeros ++ * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed ++ * in pixels ++ * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed ++ * in pixels ++ * @frame_width_minus_1: add 1 to it and you'll get the expected render width ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @frame_height_minus_1: add 1 to it and you'll get the expected render height ++ * expressed in pixels. This is not used during the ++ * decoding process but might be used by HW scalers to ++ * prepare a frame that's ready for scanout ++ * @refs: array of reference frames. See &v4l2_vp9_ref_id for more details ++ * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details ++ * @quant: quantization parameters. See &v4l2_vp9_quantization for more details ++ * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details ++ * @probs: probabilities. See &v4l2_vp9_probabilities for more details ++ */ ++struct v4l2_ctrl_vp9_frame_decode_params { ++ __u32 flags; ++ __u16 compressed_header_size; ++ __u16 uncompressed_header_size; ++ __u8 profile; ++ __u8 reset_frame_context; ++ __u8 frame_context_idx; ++ __u8 bit_depth; ++ __u8 interpolation_filter; ++ __u8 tile_cols_log2; ++ __u8 tile_rows_log2; ++ __u8 tx_mode; ++ __u8 reference_mode; ++ __u8 padding[6]; ++ __u16 frame_width_minus_1; ++ __u16 frame_height_minus_1; ++ __u16 render_width_minus_1; ++ __u16 render_height_minus_1; ++ __u64 refs[V4L2_REF_ID_CNT]; ++ struct v4l2_vp9_loop_filter lf; ++ struct v4l2_vp9_quantization quant; ++ struct v4l2_vp9_segmentation seg; ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#define V4L2_VP9_NUM_FRAME_CTX 4 ++ ++/** ++ * struct v4l2_ctrl_vp9_frame_ctx - VP9 frame context control ++ * ++ * @probs: VP9 probabilities ++ * ++ * This control is accessed in both direction. The user should initialize the ++ * 4 contexts with default values just after starting the stream. Then before ++ * decoding a frame it should query the current frame context (the one passed ++ * through &v4l2_ctrl_vp9_frame_decode_params.frame_context_idx) to initialize ++ * &v4l2_ctrl_vp9_frame_decode_params.probs. The probs are then adjusted based ++ * on the bitstream info and passed to the kernel. The codec should update ++ * the frame context after the frame has been decoded, so that next time ++ * userspace query this context it contains the updated probabilities. ++ */ ++struct v4l2_ctrl_vp9_frame_ctx { ++ struct v4l2_vp9_probabilities probs; ++}; ++ ++#endif /* _VP9_CTRLS_H_ */ + +From 4b268a93e5945dc7863a8dc953a12fa157b4f8e6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 15 May 2020 16:54:05 +0000 +Subject: [PATCH 19/20] WIP: add NV15 and NV20 support + +Signed-off-by: Jonas Karlman +--- + libavcodec/h264_slice.c | 14 ++++++++++++-- + libavcodec/v4l2_request.c | 23 +++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c +index c3896cfd90a..39ae8fabfd3 100644 +--- a/libavcodec/h264_slice.c ++++ b/libavcodec/h264_slice.c +@@ -785,10 +785,17 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + *fmt++ = AV_PIX_FMT_GBRP10; + } else + *fmt++ = AV_PIX_FMT_YUV444P10; +- } else if (CHROMA422(h)) ++ } else if (CHROMA422(h)) { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + *fmt++ = AV_PIX_FMT_YUV422P10; +- else ++ } else { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + *fmt++ = AV_PIX_FMT_YUV420P10; ++ } + break; + case 12: + if (CHROMA444(h)) { +@@ -827,6 +834,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) + else + *fmt++ = AV_PIX_FMT_YUV444P; + } else if (CHROMA422(h)) { ++#if CONFIG_H264_V4L2REQUEST_HWACCEL ++ *fmt++ = AV_PIX_FMT_DRM_PRIME; ++#endif + if (h->avctx->color_range == AVCOL_RANGE_JPEG) + *fmt++ = AV_PIX_FMT_YUVJ422P; + else +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +index 5234b5049b0..0b294feff2e 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -188,6 +188,13 @@ const uint32_t v4l2_request_capture_pixelformats[] = { + #ifdef DRM_FORMAT_MOD_ALLWINNER_TILED + V4L2_PIX_FMT_SUNXI_TILED_NV12, + #endif ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ V4L2_PIX_FMT_NV15, ++#endif ++ V4L2_PIX_FMT_NV16, ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ V4L2_PIX_FMT_NV20, ++#endif + }; + + static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format) +@@ -206,6 +213,22 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4 + layer->format = DRM_FORMAT_NV12; + desc->objects[0].format_modifier = DRM_FORMAT_MOD_ALLWINNER_TILED; + break; ++#endif ++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15) ++ case V4L2_PIX_FMT_NV15: ++ layer->format = DRM_FORMAT_NV15; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#endif ++ case V4L2_PIX_FMT_NV16: ++ layer->format = DRM_FORMAT_NV16; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; ++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20) ++ case V4L2_PIX_FMT_NV20: ++ layer->format = DRM_FORMAT_NV20; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; + #endif + default: + return -1; + +From fa7165e391287bf970569e36b0b19bff947b084f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 27 Jul 2020 23:15:45 +0000 +Subject: [PATCH 20/20] HACK: define drm NV15 and NV20 format + +--- + libavcodec/v4l2_request.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +index 0b294feff2e..a8f0ee79eee 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -30,6 +30,14 @@ + #include "internal.h" + #include "v4l2_request.h" + ++#ifndef DRM_FORMAT_NV15 ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') ++#endif ++ ++#ifndef DRM_FORMAT_NV20 ++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') ++#endif ++ + uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame) + { + V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; diff --git a/packages/multimedia/intel-vaapi-driver/package.mk b/packages/multimedia/intel-vaapi-driver/package.mk new file mode 100644 index 000000000..78f18a9ed --- /dev/null +++ b/packages/multimedia/intel-vaapi-driver/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="intel-vaapi-driver" +PKG_VERSION="2.3.0" +PKG_SHA256="fcc3f09291e58fd316fd015d4e1329e7e03c38cffa4651bda725d500a66aa74e" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://01.org/linuxmedia" +PKG_URL="https://github.com/intel/intel-vaapi-driver/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libva libdrm" +PKG_LONGDESC="intel-vaapi-driver: VA-API user mode driver for Intel GEN Graphics family" +PKG_TOOLCHAIN="autotools" + +if [ "$DISPLAYSERVER" = "x11" ]; then + DISPLAYSERVER_LIBVA="--enable-x11 --disable-wayland" +elif [ "$DISPLAYSERVER" = "weston" ]; then + DISPLAYSERVER_LIBVA="--disable-x11 --enable-wayland" +else + DISPLAYSERVER_LIBVA="--disable-x11 --disable-wayland" +fi + +PKG_CONFIGURE_OPTS_TARGET="--disable-silent-rules \ + $DISPLAYSERVER_LIBVA" diff --git a/packages/multimedia/libaacs/package.mk b/packages/multimedia/libaacs/package.mk new file mode 100644 index 000000000..e6b610654 --- /dev/null +++ b/packages/multimedia/libaacs/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libaacs" +PKG_VERSION="0.9.0" +PKG_SHA256="47e0bdc9c9f0f6146ed7b4cc78ed1527a04a537012cf540cf5211e06a248bace" +PKG_LICENSE="GPL" +PKG_SITE="http://www.videolan.org/developers/libaacs.html" +PKG_URL="http://download.videolan.org/pub/videolan/libaacs/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libgcrypt" +PKG_LONGDESC="libaacs is a research project to implement the Advanced Access Content System specification." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-werror \ + --disable-extra-warnings \ + --disable-optimizations \ + --with-libgcrypt-prefix=$SYSROOT_PREFIX/usr \ + --with-libgpg-error-prefix=$SYSROOT_PREFIX/usr \ + --with-gnu-ld" + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/config/aacs + cp -P ../KEYDB.cfg $INSTALL/usr/config/aacs +} diff --git a/packages/multimedia/libamcodec/package.mk b/packages/multimedia/libamcodec/package.mk new file mode 100644 index 000000000..c0d927c1b --- /dev/null +++ b/packages/multimedia/libamcodec/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="libamcodec" +PKG_VERSION="31cd6eceaa1402b9f4ff5cc349e53899860fe9b9" +PKG_SHA256="9052aaa00c827d3bfef7de83f55678aa1674368f06911a003b138953409f4d7c" +PKG_LICENSE="proprietary" +PKG_SITE="http://openlinux.amlogic.com" +PKG_URL="https://sources.coreelec.org/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libamplayer: Interface library for Amlogic media codecs" +PKG_TOOLCHAIN="manual" + +make_target() { + cp -PR * $SYSROOT_PREFIX +} + +makeinstall_target() { + mkdir -p $INSTALL/usr + cp -PR usr/lib $INSTALL/usr +} diff --git a/packages/multimedia/libass/package.mk b/packages/multimedia/libass/package.mk new file mode 100644 index 000000000..b85b83191 --- /dev/null +++ b/packages/multimedia/libass/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libass" +PKG_VERSION="0.14.0" +PKG_SHA256="881f2382af48aead75b7a0e02e65d88c5ebd369fe46bc77d9270a94aa8fd38a2" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/libass/libass" +PKG_URL="https://github.com/libass/libass/releases/download/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain freetype fontconfig fribidi" +PKG_LONGDESC="A portable subtitle renderer for the ASS/SSA (Advanced Substation Alpha/Substation Alpha) subtitle format." + +PKG_CONFIGURE_OPTS_TARGET="--disable-test \ + --enable-fontconfig \ + --disable-harfbuzz \ + --disable-silent-rules \ + --with-gnu-ld" + +if [ $TARGET_ARCH = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" + PKG_CONFIGURE_OPTS_TARGET+=" --enable-asm" +fi diff --git a/packages/multimedia/libbdplus/package.mk b/packages/multimedia/libbdplus/package.mk new file mode 100644 index 000000000..40f8044f0 --- /dev/null +++ b/packages/multimedia/libbdplus/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libbdplus" +PKG_VERSION="0.1.2" +PKG_SHA256="a631cae3cd34bf054db040b64edbfc8430936e762eb433b1789358ac3d3dc80a" +PKG_LICENSE="GPL" +PKG_SITE="https://www.videolan.org/developers/libbdplus.html" +PKG_URL="http://download.videolan.org/pub/videolan/$PKG_NAME/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libgcrypt libgpg-error" +PKG_LONGDESC="libbdplus is a research project to implement the BD+ System Specifications." + +PKG_CONFIGURE_OPTS_TARGET="--disable-werror \ + --disable-extra-warnings \ + --disable-optimizations \ + --with-libgcrypt-prefix=$SYSROOT_PREFIX/usr \ + --with-gpg-error-prefix=$SYSROOT_PREFIX/usr \ + --with-gnu-ld" + +if [ "$BLURAY_AACS_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libaacs" + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --with-libaacs" +else + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --without-libaacs" +fi diff --git a/packages/multimedia/libbluray/package.mk b/packages/multimedia/libbluray/package.mk new file mode 100644 index 000000000..b1fd2ac44 --- /dev/null +++ b/packages/multimedia/libbluray/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libbluray" +PKG_VERSION="1.0.2" +PKG_SHA256="6d9e7c4e416f664c330d9fa5a05ad79a3fb39b95adfc3fd6910cbed503b7aeff" +PKG_LICENSE="LGPL" +PKG_SITE="https://www.videolan.org/developers/libbluray.html" +PKG_URL="http://download.videolan.org/pub/videolan/libbluray/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain fontconfig freetype libxml2" +PKG_LONGDESC="libbluray is an open-source library designed for Blu-Ray Discs playback for media players." +PKG_TOOLCHAIN="autotools" + +if [ "$BLURAY_AACS_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libaacs" +fi + +if [ "$BLURAY_BDPLUS_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libbdplus" +fi + +PKG_CONFIGURE_OPTS_TARGET="--disable-werror \ + --disable-extra-warnings \ + --disable-optimizations \ + --disable-examples \ + --disable-bdjava-jar \ + --disable-doxygen-doc \ + --disable-doxygen-dot \ + --disable-doxygen-man \ + --disable-doxygen-rtf \ + --disable-doxygen-xml \ + --disable-doxygen-chm \ + --disable-doxygen-chi \ + --disable-doxygen-html \ + --disable-doxygen-ps \ + --disable-doxygen-pdf \ + --with-freetype \ + --with-fontconfig \ + --with-libxml2 \ + --with-gnu-ld" diff --git a/packages/multimedia/libbluray/patches/libbluray-00-fix-build-with-autoconf-archive-2016-or-later.patch b/packages/multimedia/libbluray/patches/libbluray-00-fix-build-with-autoconf-archive-2016-or-later.patch new file mode 100644 index 000000000..56a4a999a --- /dev/null +++ b/packages/multimedia/libbluray/patches/libbluray-00-fix-build-with-autoconf-archive-2016-or-later.patch @@ -0,0 +1,30 @@ +From bc746413e07c504535873cf860a8f2c38862896e Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Thu, 1 Feb 2018 08:15:27 +0000 +Subject: [PATCH] Fix build failure with recent ax_prog_doxygen.m4 + +Recent autotool-archives doxygen macros breaks the current build, +so this patch updates to the method of the latest autoconf-archive version. + +The required autoconf-archive macro has been committed to their repository +in November 2015, so anything later should work. + +Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=837020 +--- + Makefile.am | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 33813b0..f92e741 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,4 +1,5 @@ +-include $(top_srcdir)/doxygen-include.am ++# include Doxygen rules (requires autoconf-archive >2016-03-20) ++@DX_RULES@ + + ACLOCAL_AMFLAGS = -I m4 + +-- +2.14.1 + diff --git a/packages/multimedia/libbluray/patches/libbluray-01-bump_to_Nevcairiel_vL20170904.patch b/packages/multimedia/libbluray/patches/libbluray-01-bump_to_Nevcairiel_vL20170904.patch new file mode 100644 index 000000000..2111faef5 --- /dev/null +++ b/packages/multimedia/libbluray/patches/libbluray-01-bump_to_Nevcairiel_vL20170904.patch @@ -0,0 +1,2247 @@ +diff --git a/Makefile.am b/Makefile.am +index 04365fd..ff15527 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,10 +1,15 @@ + include $(top_srcdir)/doxygen-include.am + + ACLOCAL_AMFLAGS = -I m4 ++DISTCHECK_CONFIGURE_FLAGS = --enable-bdjava --enable-udf + + MOSTLYCLEANFILES = $(DX_CLEANFILES) + ++if ENABLE_UDF + POSIX_C_SOURCE=200809L ++else ++POSIX_C_SOURCE=200112L ++endif + + EXTRA_DIST = \ + bootstrap \ +@@ -35,7 +40,7 @@ libbluray_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_builddir)/src/libbluray \ + $(BDJAVA_CFLAGS) \ +- -I${top_srcdir}/contrib/libudfread/src/ \ ++ $(UDF_CFLAGS) \ + $(LIBXML2_CFLAGS) \ + $(FT2_CFLAGS) \ + $(FONTCONFIG_CFLAGS) +@@ -166,6 +171,7 @@ libbluray_la_SOURCES += \ + src/libbluray/bdj/native/util.c + + # libudfread ++if ENABLE_UDF + libbluray_la_SOURCES += \ + src/libbluray/disc/udf_fs.h \ + src/libbluray/disc/udf_fs.c\ +@@ -177,6 +183,7 @@ libbluray_la_SOURCES += \ + contrib/libudfread/src/ecma167.c \ + contrib/libudfread/src/udfread.h \ + contrib/libudfread/src/udfread.c ++endif + + if HAVE_DARWIN + libbluray_la_SOURCES+= \ +@@ -223,7 +230,7 @@ pkginclude_HEADERS = \ + src/libbluray/decoders/overlay.h \ + src/util/log_control.h + +- ++if USING_BDJAVA + if USING_BDJAVA_BUILD_JAR + jardir=$(datadir)/java/ + jar_DATA=$(top_builddir)/.libs/libbluray-$(BDJ_TYPE)-$(VERSION).jar +@@ -245,6 +252,7 @@ clean-local: + -Dversion='$(BDJ_TYPE)-$(VERSION)' \ + clean + endif ++endif + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = src/libbluray.pc +@@ -257,7 +265,6 @@ pkgconfig_DATA = src/libbluray.pc + if USING_EXAMPLES + + noinst_PROGRAMS = \ +- bdj_test \ + bdjo_dump \ + bdsplice \ + clpi_dump \ +@@ -269,6 +276,11 @@ noinst_PROGRAMS = \ + mpls_dump \ + sound_dump + ++if USING_BDJAVA ++noinst_PROGRAMS += \ ++ bdj_test ++endif ++ + bin_PROGRAMS = \ + bd_info + +diff --git a/configure.ac b/configure.ac +index 5fd3c8d..15f53ca 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -81,6 +81,16 @@ AC_ARG_ENABLE([examples], + [use_examples=$enableval], + [use_examples=yes]) + ++AC_ARG_ENABLE([bdjava], ++ [AS_HELP_STRING([--disable-bdjava], [disable BD-Java support @<:@default=enabled@:>@])], ++ [use_bdjava=$enableval], ++ [use_bdjava=yes]) ++ ++AC_ARG_ENABLE([udf], ++ [AS_HELP_STRING([--disable-udf], [disable UDF support @<:@default=enabled@:>@])], ++ [enable_udf=$enableval], ++ [enable_udf=yes]) ++ + AC_ARG_ENABLE([bdjava-jar], + [AS_HELP_STRING([--disable-bdjava-jar], + [disable building of BD-Java JAR file @<:@default=enabled@:>@])], +@@ -196,23 +206,24 @@ dnl use examples + AM_CONDITIONAL([USING_EXAMPLES], [ test $use_examples = "yes" ]) + + dnl use bdjava +-case $host_cpu in +- x86_64) java_arch=amd64 ;; +- i?86) java_arch=i386 ;; +- arm*) java_arch=arm ;; +- *) java_arch=$host_cpu ;; +-esac +-case $host_os in +- linux*) java_os=linux ;; +- win*) java_os=win32 ;; +- mingw*) java_os=win32 ;; +- freebsd*) java_os=freebsd ;; +- solaris*) java_os=solaris ;; +- darwin*) java_os=darwin ;; +- *) java_os=$host_os ;; +-esac +- +-AS_IF([test "x${JDK_HOME}" != "x"], [ ++if [[ $use_bdjava = "yes" ]]; then ++ case $host_cpu in ++ x86_64) java_arch=amd64 ;; ++ i?86) java_arch=i386 ;; ++ arm*) java_arch=arm ;; ++ *) java_arch=$host_cpu ;; ++ esac ++ case $host_os in ++ linux*) java_os=linux ;; ++ win*) java_os=win32 ;; ++ mingw*) java_os=win32 ;; ++ freebsd*) java_os=freebsd ;; ++ solaris*) java_os=solaris ;; ++ darwin*) java_os=darwin ;; ++ *) java_os=$host_os ;; ++ esac ++ ++ AS_IF([test "x${JDK_HOME}" != "x"], [ + BDJAVA_CFLAGS="-I${JDK_HOME}/include -I${JDK_HOME}/include/$java_os" + + temp_CPPFLAGS="$CPPFLAGS" +@@ -223,13 +234,16 @@ AS_IF([test "x${JDK_HOME}" != "x"], [ + BDJAVA_CFLAGS='-I${abs_top_srcdir}/jni -I${abs_top_srcdir}/jni/'"${java_os}" + ]) + +-AC_CHECK_PROG(HAVE_ANT, [ant], yes, no) +-if test "x$use_bdjava_jar" = "xyes" && test "x$HAVE_ANT" = "xno"; then +- AC_MSG_ERROR([BD-J requires ANT, but ant was not found. Please install it.]) +-fi ++ AC_CHECK_PROG(HAVE_ANT, [ant], yes, no) ++ if test "x$use_bdjava_jar" = "xyes" && test "x$HAVE_ANT" = "xno"; then ++ AC_MSG_ERROR([BD-J requires ANT, but ant was not found. Please install it.]) ++ fi + +-AC_DEFINE_UNQUOTED([JAVA_ARCH], ["$java_arch"], ["Defines the architecture of the java vm."]) +-AC_DEFINE_UNQUOTED([JDK_HOME], ["$JDK_HOME"], [""]) ++ AC_DEFINE([USING_BDJAVA], [1], ["Define to 1 if using BD-Java"]) ++ AC_DEFINE_UNQUOTED([JAVA_ARCH], ["$java_arch"], ["Defines the architecture of the java vm."]) ++ AC_DEFINE_UNQUOTED([JDK_HOME], ["$JDK_HOME"], [""]) ++fi ++AM_CONDITIONAL([USING_BDJAVA], [ test $use_bdjava = "yes" ]) + AM_CONDITIONAL([USING_BDJAVA_BUILD_JAR], [ test $use_bdjava_jar = "yes" ]) + + dnl BD-J type +@@ -243,13 +257,22 @@ dnl bootclasspath + AC_SUBST(BDJ_BOOTCLASSPATH) + + dnl udf support (using git submodule) +-if test ! -f "${srcdir}/contrib/libudfread/src/udfread.h"; then +- AC_MSG_ERROR("libudfread source tree not found") +-fi +-AC_CHECK_HEADERS([unistd.h fcntl.h]) +-AS_IF([test "${SYS}" != "mingw32"], [ +- AC_CHECK_FUNC([pread],, [AC_DEFINE([NEED_PREAD_IMPL], [1], [Define to 1 to use inefficient pread() replacement])]) +-]) ++AS_IF([test "x$enable_udf" = "xyes"], [ ++ if test ! -f "${srcdir}/contrib/libudfread/src/udfread.h"; then ++ AC_MSG_ERROR("libudfread source tree not found") ++ fi ++ AC_CHECK_HEADERS([unistd.h fcntl.h]) ++ AS_IF([test "${SYS}" != "mingw32"], [ ++ AC_CHECK_FUNC([pread],, [AC_MSG_ERROR("Function pread not found. Try with --disable-udf.")]) ++ ]) ++ ++ AC_DEFINE([ENABLE_UDF], [1], [Define to 1 if libudfread is to be used for disc image access]) ++ UDF_CFLAGS='-I${srcdir}/contrib/libudfread/src/' ++ AC_SUBST(UDF_CFLAGS) ++ ], ++ [enable_udf=no]) ++ ++AM_CONDITIONAL([ENABLE_UDF], [test $enable_udf = "yes" ]) + + dnl generate documentation + DX_INIT_DOXYGEN(libbluray, doc/doxygen-config, [doc/doxygen]) +@@ -279,19 +302,25 @@ dnl --------------------------------------------- + + echo " Summary:" + echo " --------" ++echo " BD-J support: $use_bdjava" ++if [[ $use_bdjava = "yes" ]]; then + echo " BD-J type: $BDJ_TYPE" + echo " build JAR: $use_bdjava_jar" + if test x"$BDJ_BOOTCLASSPATH" != x""; then + echo " BD-J bootclasspath: $BDJ_BOOTCLASSPATH" + fi ++fi + echo " Font support (freetype2): $with_freetype" + if [[ $with_freetype = "yes" ]]; then ++if [[ $use_bdjava = "yes" ]]; then + if test "${SYS}" != "mingw32"; then + echo " Use system fonts (fontconfig): $with_fontconfig" + else + echo " Use system fonts: yes" + fi + fi ++fi + echo " Metadata support (libxml2): $with_libxml2" ++echo " UDF filesystem support: $enable_udf" + echo " Build examples: $use_examples" + +diff --git a/includes/inttypes.h b/includes/inttypes.h +new file mode 100644 +index 0000000..ead903f +--- /dev/null ++++ b/includes/inttypes.h +@@ -0,0 +1,305 @@ ++// ISO C9x compliant inttypes.h for Microsoft Visual Studio ++// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 ++// ++// Copyright (c) 2006 Alexander Chemeris ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are met: ++// ++// 1. Redistributions of source code must retain the above copyright notice, ++// this list of conditions and the following disclaimer. ++// ++// 2. Redistributions in binary form must reproduce the above copyright ++// notice, this list of conditions and the following disclaimer in the ++// documentation and/or other materials provided with the distribution. ++// ++// 3. The name of the author may be used to endorse or promote products ++// derived from this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED ++// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO ++// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ++// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ++// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++/////////////////////////////////////////////////////////////////////////////// ++ ++#ifndef _MSC_VER // [ ++#error "Use this header only with Microsoft Visual C++ compilers!" ++#endif // _MSC_VER ] ++ ++#ifndef _MSC_INTTYPES_H_ // [ ++#define _MSC_INTTYPES_H_ ++ ++#if _MSC_VER > 1000 ++#pragma once ++#endif ++ ++#include "stdint.h" ++ ++// 7.8 Format conversion of integer types ++ ++typedef struct { ++ intmax_t quot; ++ intmax_t rem; ++} imaxdiv_t; ++ ++// 7.8.1 Macros for format specifiers ++ ++#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 ++ ++// The fprintf macros for signed integers are: ++#define PRId8 "d" ++#define PRIi8 "i" ++#define PRIdLEAST8 "d" ++#define PRIiLEAST8 "i" ++#define PRIdFAST8 "d" ++#define PRIiFAST8 "i" ++ ++#define PRId16 "hd" ++#define PRIi16 "hi" ++#define PRIdLEAST16 "hd" ++#define PRIiLEAST16 "hi" ++#define PRIdFAST16 "hd" ++#define PRIiFAST16 "hi" ++ ++#define PRId32 "I32d" ++#define PRIi32 "I32i" ++#define PRIdLEAST32 "I32d" ++#define PRIiLEAST32 "I32i" ++#define PRIdFAST32 "I32d" ++#define PRIiFAST32 "I32i" ++ ++#define PRId64 "I64d" ++#define PRIi64 "I64i" ++#define PRIdLEAST64 "I64d" ++#define PRIiLEAST64 "I64i" ++#define PRIdFAST64 "I64d" ++#define PRIiFAST64 "I64i" ++ ++#define PRIdMAX "I64d" ++#define PRIiMAX "I64i" ++ ++#define PRIdPTR "Id" ++#define PRIiPTR "Ii" ++ ++// The fprintf macros for unsigned integers are: ++#define PRIo8 "o" ++#define PRIu8 "u" ++#define PRIx8 "x" ++#define PRIX8 "X" ++#define PRIoLEAST8 "o" ++#define PRIuLEAST8 "u" ++#define PRIxLEAST8 "x" ++#define PRIXLEAST8 "X" ++#define PRIoFAST8 "o" ++#define PRIuFAST8 "u" ++#define PRIxFAST8 "x" ++#define PRIXFAST8 "X" ++ ++#define PRIo16 "ho" ++#define PRIu16 "hu" ++#define PRIx16 "hx" ++#define PRIX16 "hX" ++#define PRIoLEAST16 "ho" ++#define PRIuLEAST16 "hu" ++#define PRIxLEAST16 "hx" ++#define PRIXLEAST16 "hX" ++#define PRIoFAST16 "ho" ++#define PRIuFAST16 "hu" ++#define PRIxFAST16 "hx" ++#define PRIXFAST16 "hX" ++ ++#define PRIo32 "I32o" ++#define PRIu32 "I32u" ++#define PRIx32 "I32x" ++#define PRIX32 "I32X" ++#define PRIoLEAST32 "I32o" ++#define PRIuLEAST32 "I32u" ++#define PRIxLEAST32 "I32x" ++#define PRIXLEAST32 "I32X" ++#define PRIoFAST32 "I32o" ++#define PRIuFAST32 "I32u" ++#define PRIxFAST32 "I32x" ++#define PRIXFAST32 "I32X" ++ ++#define PRIo64 "I64o" ++#define PRIu64 "I64u" ++#define PRIx64 "I64x" ++#define PRIX64 "I64X" ++#define PRIoLEAST64 "I64o" ++#define PRIuLEAST64 "I64u" ++#define PRIxLEAST64 "I64x" ++#define PRIXLEAST64 "I64X" ++#define PRIoFAST64 "I64o" ++#define PRIuFAST64 "I64u" ++#define PRIxFAST64 "I64x" ++#define PRIXFAST64 "I64X" ++ ++#define PRIoMAX "I64o" ++#define PRIuMAX "I64u" ++#define PRIxMAX "I64x" ++#define PRIXMAX "I64X" ++ ++#define PRIoPTR "Io" ++#define PRIuPTR "Iu" ++#define PRIxPTR "Ix" ++#define PRIXPTR "IX" ++ ++// The fscanf macros for signed integers are: ++#define SCNd8 "d" ++#define SCNi8 "i" ++#define SCNdLEAST8 "d" ++#define SCNiLEAST8 "i" ++#define SCNdFAST8 "d" ++#define SCNiFAST8 "i" ++ ++#define SCNd16 "hd" ++#define SCNi16 "hi" ++#define SCNdLEAST16 "hd" ++#define SCNiLEAST16 "hi" ++#define SCNdFAST16 "hd" ++#define SCNiFAST16 "hi" ++ ++#define SCNd32 "ld" ++#define SCNi32 "li" ++#define SCNdLEAST32 "ld" ++#define SCNiLEAST32 "li" ++#define SCNdFAST32 "ld" ++#define SCNiFAST32 "li" ++ ++#define SCNd64 "I64d" ++#define SCNi64 "I64i" ++#define SCNdLEAST64 "I64d" ++#define SCNiLEAST64 "I64i" ++#define SCNdFAST64 "I64d" ++#define SCNiFAST64 "I64i" ++ ++#define SCNdMAX "I64d" ++#define SCNiMAX "I64i" ++ ++#ifdef _WIN64 // [ ++# define SCNdPTR "I64d" ++# define SCNiPTR "I64i" ++#else // _WIN64 ][ ++# define SCNdPTR "ld" ++# define SCNiPTR "li" ++#endif // _WIN64 ] ++ ++// The fscanf macros for unsigned integers are: ++#define SCNo8 "o" ++#define SCNu8 "u" ++#define SCNx8 "x" ++#define SCNX8 "X" ++#define SCNoLEAST8 "o" ++#define SCNuLEAST8 "u" ++#define SCNxLEAST8 "x" ++#define SCNXLEAST8 "X" ++#define SCNoFAST8 "o" ++#define SCNuFAST8 "u" ++#define SCNxFAST8 "x" ++#define SCNXFAST8 "X" ++ ++#define SCNo16 "ho" ++#define SCNu16 "hu" ++#define SCNx16 "hx" ++#define SCNX16 "hX" ++#define SCNoLEAST16 "ho" ++#define SCNuLEAST16 "hu" ++#define SCNxLEAST16 "hx" ++#define SCNXLEAST16 "hX" ++#define SCNoFAST16 "ho" ++#define SCNuFAST16 "hu" ++#define SCNxFAST16 "hx" ++#define SCNXFAST16 "hX" ++ ++#define SCNo32 "lo" ++#define SCNu32 "lu" ++#define SCNx32 "lx" ++#define SCNX32 "lX" ++#define SCNoLEAST32 "lo" ++#define SCNuLEAST32 "lu" ++#define SCNxLEAST32 "lx" ++#define SCNXLEAST32 "lX" ++#define SCNoFAST32 "lo" ++#define SCNuFAST32 "lu" ++#define SCNxFAST32 "lx" ++#define SCNXFAST32 "lX" ++ ++#define SCNo64 "I64o" ++#define SCNu64 "I64u" ++#define SCNx64 "I64x" ++#define SCNX64 "I64X" ++#define SCNoLEAST64 "I64o" ++#define SCNuLEAST64 "I64u" ++#define SCNxLEAST64 "I64x" ++#define SCNXLEAST64 "I64X" ++#define SCNoFAST64 "I64o" ++#define SCNuFAST64 "I64u" ++#define SCNxFAST64 "I64x" ++#define SCNXFAST64 "I64X" ++ ++#define SCNoMAX "I64o" ++#define SCNuMAX "I64u" ++#define SCNxMAX "I64x" ++#define SCNXMAX "I64X" ++ ++#ifdef _WIN64 // [ ++# define SCNoPTR "I64o" ++# define SCNuPTR "I64u" ++# define SCNxPTR "I64x" ++# define SCNXPTR "I64X" ++#else // _WIN64 ][ ++# define SCNoPTR "lo" ++# define SCNuPTR "lu" ++# define SCNxPTR "lx" ++# define SCNXPTR "lX" ++#endif // _WIN64 ] ++ ++#endif // __STDC_FORMAT_MACROS ] ++ ++// 7.8.2 Functions for greatest-width integer types ++ ++// 7.8.2.1 The imaxabs function ++#define imaxabs _abs64 ++ ++// 7.8.2.2 The imaxdiv function ++ ++// This is modified version of div() function from Microsoft's div.c found ++// in %MSVC.NET%\crt\src\div.c ++#ifdef STATIC_IMAXDIV // [ ++static ++#else // STATIC_IMAXDIV ][ ++_inline ++#endif // STATIC_IMAXDIV ] ++imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) ++{ ++ imaxdiv_t result; ++ ++ result.quot = numer / denom; ++ result.rem = numer % denom; ++ ++ if (numer < 0 && result.rem > 0) { ++ // did division wrong; must fix up ++ ++result.quot; ++ result.rem -= denom; ++ } ++ ++ return result; ++} ++ ++// 7.8.2.3 The strtoimax and strtoumax functions ++#define strtoimax _strtoi64 ++#define strtoumax _strtoui64 ++ ++// 7.8.2.4 The wcstoimax and wcstoumax functions ++#define wcstoimax _wcstoi64 ++#define wcstoumax _wcstoui64 ++ ++ ++#endif // _MSC_INTTYPES_H_ ] +diff --git a/libbluray.def b/libbluray.def +new file mode 100644 +index 0000000..d4c93cb +--- /dev/null ++++ b/libbluray.def +@@ -0,0 +1,63 @@ ++; libbluray.def ; declares the exports ++ ++LIBRARY "libbluray.dll" ++ ++EXPORTS ++ ; bluray.h ++ bd_get_version ++ bd_get_titles ++ bd_get_title_info ++ bd_get_playlist_info ++ bd_free_title_info ++ bd_open ++ bd_close ++ bd_seek ++ bd_seek_time ++ bd_find_seek_point ++ bd_read ++ bd_read_skip_still ++ bd_seek_chapter ++ bd_chapter_pos ++ bd_get_current_chapter ++ bd_seek_mark ++ bd_seek_playitem ++ bd_select_playlist ++ bd_select_title ++ bd_select_angle ++ bd_seamless_angle_change ++ bd_get_title_size ++ bd_get_current_title ++ bd_get_current_angle ++ bd_tell ++ bd_tell_time ++ bd_get_disc_info ++ bd_set_player_setting ++ bd_set_player_setting_str ++ bd_start_bdj ++ bd_stop_bdj ++ bd_get_event ++ bd_play ++ bd_read_ext ++ bd_play_title ++ bd_menu_call ++ bd_register_overlay_proc ++ bd_register_argb_overlay_proc ++ bd_set_scr ++ bd_user_input ++ bd_mouse_select ++ bd_get_sound_effect ++ bd_get_meta ++ bd_get_clpi ++ bd_read_clpi ++ bd_free_clpi ++ bd_read_mpls ++ bd_free_mpls ++ bd_read_mobj ++ bd_free_mobj ++ bd_get_clip_infos ++ bd_get_title_mpls ++ ++ ; additional functions ++ bd_set_debug_handler ++ bd_set_debug_mask ++ bd_get_debug_mask +diff --git a/libbluray.vcxproj b/libbluray.vcxproj +new file mode 100644 +index 0000000..6de7ad2 +--- /dev/null ++++ b/libbluray.vcxproj +@@ -0,0 +1,241 @@ ++ ++ ++ ++ ++ DebugRelease ++ Win32 ++ ++ ++ DebugRelease ++ x64 ++ ++ ++ Debug ++ Win32 ++ ++ ++ Debug ++ x64 ++ ++ ++ Release ++ Win32 ++ ++ ++ Release ++ x64 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ {E1DA1B95-71F1-4C21-A271-121176925062} ++ Win32Proj ++ libbluray ++ ++ ++ ++ v120 ++ ++ ++ v140 ++ 8.1 ++ ++ ++ v141 ++ 8.1 ++ ++ ++ DynamicLibrary ++ true ++ Unicode ++ ++ ++ DynamicLibrary ++ false ++ true ++ Unicode ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ true ++ $(SolutionDir)bin_$(PlatformName)d\ ++ $(SolutionDir)bin_$(PlatformName)d\$(ProjectName)\ ++ ++ ++ false ++ $(SolutionDir)bin_$(PlatformName)\$(ProjectName)\ ++ $(SolutionDir)bin_$(PlatformName)\$(ProjectName)\ ++ ++ ++ ++ ++ ++ Level3 ++ Disabled ++ HAVE_CONFIG_H;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBBLURAY_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ++ __STDC_FORMAT_MACROS;%(PreprocessorDefinitions) ++ $(ProjectDir);$(ProjectDir)includes;$(ProjectDir)src;$(ProjectDir)src\libbluray;%(AdditionalIncludeDirectories) ++ MultiThreadedDebugDLL ++ CompileAsCpp ++ ++ ++ Windows ++ true ++ libbluray.def ++ ++ ++ xcopy /I /Y "$(OutDir)$(TargetName).lib" "$(OutDir)lib\" ++ Copy .lib into library path ++ ++ ++ ++ ++ MultiThreadedDebug ++ ++ ++ ++ ++ Level3 ++ MaxSpeed ++ true ++ true ++ HAVE_CONFIG_H;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBBLURAY_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ++ __STDC_FORMAT_MACROS;%(PreprocessorDefinitions) ++ $(ProjectDir);$(ProjectDir)includes;$(ProjectDir)src;$(ProjectDir)src\libbluray;%(AdditionalIncludeDirectories) ++ MultiThreaded ++ StreamingSIMDExtensions ++ CompileAsCpp ++ ++ ++ Windows ++ true ++ true ++ true ++ libbluray.def ++ true ++ ++ ++ xcopy /I /Y "$(TargetDir)$(TargetName)$(TargetExt)" "$(OutDir)..\" ++xcopy /I /Y "$(TargetDir)$(TargetName).lib" "$(OutDir)..\lib\" ++ Copy .dll/.lib into library path ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/libbluray.vcxproj.filters b/libbluray.vcxproj.filters +new file mode 100644 +index 0000000..02a4161 +--- /dev/null ++++ b/libbluray.vcxproj.filters +@@ -0,0 +1,377 @@ ++ ++ ++ ++ ++ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} ++ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx ++ ++ ++ {93995380-89BD-4b04-88EB-625FBE52EBFB} ++ h;hpp;hxx;hm;inl;inc;xsd ++ ++ ++ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} ++ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms ++ ++ ++ {1ab0e905-7c04-4090-b385-6363dd1c961c} ++ ++ ++ {b8fa3348-a089-461f-9ef5-3d9df997b8e5} ++ ++ ++ {125333e9-0b5e-45f9-a444-f0aaaf547d9b} ++ ++ ++ {a743058f-f07a-4d0f-bab6-02dc57defda9} ++ ++ ++ {7dacc7c4-ef59-452b-9e5b-392c9df07c98} ++ ++ ++ {c7895c81-c186-4d5e-a8ff-645c6d55a731} ++ ++ ++ {c8619466-211b-4c85-9d30-d1b1a822d32e} ++ ++ ++ {8afb6919-994f-4d1f-9638-ce4a06d0b473} ++ ++ ++ {0e9086a7-eebf-4b8e-a4fe-b1724d148877} ++ ++ ++ {fc5e776b-0f32-493a-b823-240288288502} ++ ++ ++ {96d2d786-cd45-4856-937d-9e6f85ced241} ++ ++ ++ {9f4ea4ae-217a-4d97-a5f3-e561ce1e49cd} ++ ++ ++ {09e1b1b8-3aa3-4918-b157-3dfc0554ccbb} ++ ++ ++ {1e02e503-752e-4765-9dfb-8cc67a7b79f8} ++ ++ ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\file ++ ++ ++ Header Files\file ++ ++ ++ Header Files\file ++ ++ ++ Header Files\libbluray ++ ++ ++ Header Files\libbluray ++ ++ ++ Header Files\libbluray ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\hdmv ++ ++ ++ Header Files\libbluray\hdmv ++ ++ ++ Header Files\libbluray\hdmv ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\util ++ ++ ++ Header Files\util ++ ++ ++ Header Files\libbluray ++ ++ ++ Header Files\libbluray\decoders ++ ++ ++ Header Files\file ++ ++ ++ Header Files\libbluray ++ ++ ++ Header Files\util ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ Header Files\file ++ ++ ++ Header Files\util ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\bdnav ++ ++ ++ Header Files\libbluray\disc ++ ++ ++ ++ ++ Source Files\util ++ ++ ++ Source Files\util ++ ++ ++ Source Files\file ++ ++ ++ Source Files\libbluray ++ ++ ++ Source Files\libbluray ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\hdmv ++ ++ ++ Source Files\libbluray\hdmv ++ ++ ++ Source Files\libbluray\hdmv ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\util ++ ++ ++ Source Files\file ++ ++ ++ Source Files\file ++ ++ ++ Source Files\file ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\util ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\libbluray\decoders ++ ++ ++ Source Files\file ++ ++ ++ Source Files\file ++ ++ ++ Source Files\util ++ ++ ++ Source Files\util ++ ++ ++ Source Files\libbluray\disc ++ ++ ++ Source Files\libbluray\disc ++ ++ ++ Source Files\libbluray\disc ++ ++ ++ Source Files\libbluray\disc ++ ++ ++ Source Files\util ++ ++ ++ Source Files\file ++ ++ ++ Source Files\util ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\bdnav ++ ++ ++ Source Files\libbluray\disc ++ ++ ++ ++ ++ Source Files ++ ++ ++ +\ No newline at end of file +diff --git a/src/file/dir_win32.c b/src/file/dir_win32.c +index 5cbc3c8..4030896 100644 +--- a/src/file/dir_win32.c ++++ b/src/file/dir_win32.c +@@ -76,7 +76,7 @@ static dir_data_t *_open_impl(const char *dirname) + { + dir_data_t *priv; + char *filespec; +- wchar_t wfilespec[MAX_PATH]; ++ wchar_t wfilespec[4096 + 1]; + int result; + + filespec = str_printf("%s" DIR_SEP "*", dirname); +@@ -84,7 +84,7 @@ static dir_data_t *_open_impl(const char *dirname) + return NULL; + } + +- result = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filespec, -1, wfilespec, MAX_PATH); ++ result = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filespec, -1, wfilespec, 4096); + X_FREE(filespec); + if (!result) { + return NULL; +diff --git a/src/file/dirs_win32.c b/src/file/dirs_win32.c +index e165fea..3d07251 100644 +--- a/src/file/dirs_win32.c ++++ b/src/file/dirs_win32.c +@@ -36,7 +36,7 @@ + + char *win32_get_font_dir(const char *font_file) + { +- wchar_t wdir[MAX_PATH]; ++ wchar_t wdir[MAX_PATH+1] = {0}; + if (S_OK != SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, wdir)) { + int lenght = GetWindowsDirectoryW(wdir, MAX_PATH); + if (lenght == 0 || lenght > (MAX_PATH - 8)) { +@@ -67,7 +67,7 @@ char *file_get_config_home(void) + + char *file_get_data_home(void) + { +- wchar_t wdir[MAX_PATH]; ++ wchar_t wdir[MAX_PATH+1] = {0}; + + /* Get the "Application Data" folder for the user */ + if (S_OK == SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, +@@ -92,7 +92,7 @@ char *file_get_cache_home(void) + const char *file_get_config_system(const char *dir) + { + static char *appdir = NULL; +- wchar_t wdir[MAX_PATH]; ++ wchar_t wdir[MAX_PATH+1] = {0}; + + if (!dir) { + // first call +diff --git a/src/file/dl_win32.c b/src/file/dl_win32.c +index 6155ad6..c7e3eee 100644 +--- a/src/file/dl_win32.c ++++ b/src/file/dl_win32.c +@@ -57,7 +57,7 @@ void *dl_dlopen(const char *path, const char *version) + { + (void)version; + +- wchar_t wname[MAX_PATH]; ++ wchar_t wname[MAX_PATH+1] = {0}; + char *name; + void *result; + int iresult; +@@ -125,7 +125,7 @@ const char *dl_get_path(void) + if (!initialized) { + initialized = 1; + +- static char path[MAX_PATH]; ++ static char path[MAX_PATH + 1]; + HMODULE hModule; + wchar_t wpath[MAX_PATH]; + +diff --git a/src/file/file_win32.c b/src/file/file_win32.c +index 11aaf82..f551863 100644 +--- a/src/file/file_win32.c ++++ b/src/file/file_win32.c +@@ -107,9 +107,9 @@ static BD_FILE_H *_file_open(const char* filename, const char *mode) + { + BD_FILE_H *file; + FILE *fp; +- wchar_t wfilename[MAX_PATH], wmode[8]; ++ wchar_t wfilename[4096 + 1] = {0}, wmode[8] = {0}; + +- if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, wfilename, MAX_PATH) || ++ if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, wfilename, 4096) || + !MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mode, -1, wmode, 8)) { + + BD_DEBUG(DBG_FILE, "Error opening file %s\n", filename); +@@ -122,6 +122,9 @@ static BD_FILE_H *_file_open(const char* filename, const char *mode) + return NULL; + } + ++ // Set file buffer ++ setvbuf(fp, NULL, _IOFBF, 6144 * 10); ++ + file = calloc(1, sizeof(BD_FILE_H)); + if (!file) { + BD_DEBUG(DBG_FILE | DBG_CRIT, "Error opening file %s (out of memory)\n", filename); +diff --git a/src/libbluray/bdnav/bdmv_parse.c b/src/libbluray/bdnav/bdmv_parse.c +index e298ca3..2c310aa 100644 +--- a/src/libbluray/bdnav/bdmv_parse.c ++++ b/src/libbluray/bdnav/bdmv_parse.c +@@ -59,6 +59,7 @@ int bdmv_parse_header(BITSTREAM *bs, uint32_t type, uint32_t *version) + switch (ver) { + case BDMV_VERSION_0100: + case BDMV_VERSION_0200: ++ case BDMV_VERSION_0240: + case BDMV_VERSION_0300: + break; + default: +diff --git a/src/libbluray/bdnav/bdmv_parse.h b/src/libbluray/bdnav/bdmv_parse.h +index 8f953a3..9dbbed5 100644 +--- a/src/libbluray/bdnav/bdmv_parse.h ++++ b/src/libbluray/bdnav/bdmv_parse.h +@@ -27,6 +27,7 @@ + + #define BDMV_VERSION_0100 ('0' << 24 | '1' << 16 | '0' << 8 | '0') + #define BDMV_VERSION_0200 ('0' << 24 | '2' << 16 | '0' << 8 | '0') ++#define BDMV_VERSION_0240 ('0' << 24 | '2' << 16 | '4' << 8 | '0') + #define BDMV_VERSION_0300 ('0' << 24 | '3' << 16 | '0' << 8 | '0') + + BD_PRIVATE int bdmv_parse_header(BITSTREAM *bs, uint32_t type, uint32_t *version); +diff --git a/src/libbluray/bdnav/index_parse.c b/src/libbluray/bdnav/index_parse.c +index 0deb617..300a1bf 100644 +--- a/src/libbluray/bdnav/index_parse.c ++++ b/src/libbluray/bdnav/index_parse.c +@@ -105,12 +105,11 @@ static int _parse_index(BITSTREAM *bs, INDX_ROOT *index) + + index->num_titles = bs_read(bs, 16); + if (!index->num_titles) { +- BD_DEBUG(DBG_CRIT, "empty index\n"); +- return 0; ++ BD_DEBUG(DBG_NAV, "empty index\n"); + } + + index->titles = calloc(index->num_titles, sizeof(INDX_TITLE)); +- if (!index->titles) { ++ if (index->num_titles && !index->titles) { + BD_DEBUG(DBG_CRIT, "out of memory\n"); + return 0; + } +diff --git a/src/libbluray/bdnav/mpls_data.h b/src/libbluray/bdnav/mpls_data.h +index 2ceac92..d23d40e 100644 +--- a/src/libbluray/bdnav/mpls_data.h ++++ b/src/libbluray/bdnav/mpls_data.h +@@ -47,6 +47,7 @@ typedef struct + uint8_t sv_num_pip_pg_ref; + uint8_t *sv_secondary_audio_ref; + uint8_t *sv_pip_pg_ref; ++ uint8_t ss_offset_sequence_id; + } MPLS_STREAM; + + typedef struct +@@ -107,6 +108,7 @@ typedef struct + uint8_t random_access_flag; + uint8_t audio_mix_flag; + uint8_t lossless_bypass_flag; ++ uint8_t mvc_base_view_r_flag; + } MPLS_AI; + + typedef struct +diff --git a/src/libbluray/bdnav/mpls_parse.c b/src/libbluray/bdnav/mpls_parse.c +index 358b634..569c015 100644 +--- a/src/libbluray/bdnav/mpls_parse.c ++++ b/src/libbluray/bdnav/mpls_parse.c +@@ -77,9 +77,10 @@ _parse_appinfo(BITSTREAM *bits, MPLS_AI *ai) + ai->random_access_flag = bs_read(bits, 1); + ai->audio_mix_flag = bs_read(bits, 1); + ai->lossless_bypass_flag = bs_read(bits, 1); ++ ai->mvc_base_view_r_flag = bs_read(bits, 1); + #if 0 + // Reserved +- bs_skip(bits, 13); ++ bs_skip(bits, 12); + bs_seek_byte(bits, pos + len); + #endif + return 1; +@@ -194,6 +195,7 @@ _parse_stream(BITSTREAM *bits, MPLS_STREAM *s) + break; + }; + s->lang[3] = '\0'; ++ s->ss_offset_sequence_id = 0xFF; + + if (bs_seek_byte(bits, pos + len) < 0) { + return 0; +@@ -958,6 +960,99 @@ _parse_subpath_extension(BITSTREAM *bits, MPLS_PL *pl) + return 0; + } + ++static int ++_parse_stn_ss_extension(BITSTREAM *bits, MPLS_PL *pl) ++{ ++ int ii, s; ++ int64_t pos; ++ ++ for (ii = 0; ii < pl->list_count; ii++) { ++ uint32_t len = bs_read(bits, 16); ++ pos = bs_pos(bits) >> 3; ++ int Fixed_offset_during_PopUp_flag = bs_read(bits, 1); ++ bs_skip(bits, 15); // reserved ++ ++ for (s = 0; s < pl->play_item[ii].stn.num_video; s++) { ++ // stream_entry ++ uint32_t slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ // stream_attributes_ss ++ slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ bs_skip(bits, 10); // reserved ++ bs_skip(bits, 6); // number_of_offset_sequences ++ } ++ ++ for (s = 0; s < pl->play_item[ii].stn.num_pg; s++) { ++ pl->play_item[ii].stn.pg[s].ss_offset_sequence_id = bs_read(bits, 8); ++ ++ bs_skip(bits, 4); // reserved ++ bs_skip(bits, 1); // dialog_region_offset_valid_flag ++ int is_SS_PG = bs_read(bits, 1); ++ int is_top_AS_PG_textST = bs_read(bits, 1); ++ int is_bottom_AS_PG_textST = bs_read(bits, 1); ++ if (is_SS_PG) { ++ // stream_entry left eye ++ uint32_t slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ // stream_entry right eye ++ slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ bs_skip(bits, 8); // reserved ++ bs_skip(bits, 8); // PG offset ++ } ++ if (is_top_AS_PG_textST) { ++ // stream_entry ++ uint32_t slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ bs_skip(bits, 8); // reserved ++ bs_skip(bits, 8); // PG offset ++ } ++ if (is_bottom_AS_PG_textST) { ++ // stream_entry ++ uint32_t slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ bs_skip(bits, 8); // reserved ++ bs_skip(bits, 8); // PG offset ++ } ++ } ++ ++ for (s = 0; s < pl->play_item[ii].stn.num_ig; s++) { ++ if (Fixed_offset_during_PopUp_flag) ++ bs_skip(bits, 8); ++ else ++ pl->play_item[ii].stn.ig[s].ss_offset_sequence_id = bs_read(bits, 8); ++ ++ bs_skip(bits, 16); // IG_Plane_offset_during_BB_video ++ bs_skip(bits, 7); // reserved ++ int is_SS_IG = bs_read(bits, 1); ++ if (is_SS_IG) { ++ // stream_entry left eye ++ uint32_t slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ // stream_entry right eye ++ slen = bs_read(bits, 8); ++ bs_skip(bits, slen * 8); ++ ++ bs_skip(bits, 8); // reserved ++ bs_skip(bits, 8); // PG offset ++ } ++ } ++ ++ // Skip to next play item ++ bs_seek_byte(bits, pos + len); ++ } ++ ++ return 0; ++} ++ + static int + _parse_mpls_extension(BITSTREAM *bits, int id1, int id2, void *handle) + { +@@ -972,7 +1067,7 @@ _parse_mpls_extension(BITSTREAM *bits, int id1, int id2, void *handle) + + if (id1 == 2) { + if (id2 == 1) { +- return 0; ++ return _parse_stn_ss_extension(bits, pl); + } + if (id2 == 2) { + // SubPath entries extension +diff --git a/src/libbluray/bluray.c b/src/libbluray/bluray.c +index 883b35c..8220787 100644 +--- a/src/libbluray/bluray.c ++++ b/src/libbluray/bluray.c +@@ -51,8 +51,10 @@ + #include "disc/disc.h" + #include "disc/enc_info.h" + #include "file/file.h" ++#ifdef USING_BDJAVA + #include "bdj/bdj.h" + #include "bdj/bdjo_parse.h" ++#endif + + #include // SEEK_ + #include +@@ -150,9 +152,11 @@ struct bluray { + uint8_t hdmv_suspended; + + /* BD-J */ ++#ifdef USING_BDJAVA + BDJAVA *bdjava; + BDJ_STORAGE bdjstorage; + uint8_t bdj_wait_start; /* BD-J has selected playlist (prefetch) but not yet started playback */ ++#endif + + /* HDMV graphics */ + GRAPHICS_CONTROLLER *graphics_controller; +@@ -166,10 +170,12 @@ struct bluray { + uint64_t gc_wakeup_pos; /* stream position of gc_wakeup_time */ + + /* ARGB overlay output */ ++#ifdef USING_BDJAVA + void *argb_overlay_proc_handle; + bd_argb_overlay_proc_f argb_overlay_proc; + BD_ARGB_BUFFER *argb_buffer; + BD_MUTEX argb_buffer_mutex; ++#endif + }; + + /* Stream Packet Number = byte offset / 192. Avoid 64-bit division. */ +@@ -532,6 +538,16 @@ static void _update_uo_mask(BLURAY *bd) + bd->uo_mask = new_mask; + } + ++#ifdef USING_BDJAVA ++void bd_set_bdj_uo_mask(BLURAY *bd, unsigned mask) ++{ ++ bd->title_uo_mask.title_search = !!(mask & BDJ_TITLE_SEARCH_MASK); ++ bd->title_uo_mask.menu_call = !!(mask & BDJ_MENU_CALL_MASK); ++ ++ _update_uo_mask(bd); ++} ++#endif ++ + static void _update_hdmv_uo_mask(BLURAY *bd) + { + uint32_t mask = hdmv_vm_get_uo_mask(bd->hdmv_vm); +@@ -899,6 +915,7 @@ static int _run_gc(BLURAY *bd, gc_ctrl_e msg, uint32_t param) + + static void _check_bdj(BLURAY *bd) + { ++#ifdef USING_BDJAVA + if (!bd->disc_info.bdj_handled) { + if (!bd->disc || bd->disc_info.bdj_detected) { + +@@ -911,6 +928,7 @@ static void _check_bdj(BLURAY *bd) + } + } + } ++#endif /* USING_BDJAVA */ + } + + static void _fill_disc_info(BLURAY *bd, BD_ENC_INFO *enc_info) +@@ -940,7 +958,7 @@ static void _fill_disc_info(BLURAY *bd, BD_ENC_INFO *enc_info) + bd->disc_info.num_unsupported_titles = 0; + + bd->disc_info.bdj_detected = 0; +- bd->disc_info.bdj_supported = 1; ++ bd->disc_info.bdj_supported = 0; + + bd->disc_info.num_titles = 0; + bd->disc_info.titles = NULL; +@@ -1104,22 +1122,17 @@ const BLURAY_DISC_INFO *bd_get_disc_info(BLURAY *bd) + } + + /* +- * bdj callbacks ++ * bdj + */ + +-void bd_set_bdj_uo_mask(BLURAY *bd, unsigned mask) +-{ +- bd->title_uo_mask.title_search = !!(mask & BDJ_TITLE_SEARCH_MASK); +- bd->title_uo_mask.menu_call = !!(mask & BDJ_MENU_CALL_MASK); +- +- _update_uo_mask(bd); +-} +- ++#ifdef USING_BDJAVA + const uint8_t *bd_get_aacs_data(BLURAY *bd, int type) + { + return disc_get_data(bd->disc, type); + } ++#endif + ++#ifdef USING_BDJAVA + uint64_t bd_get_uo_mask(BLURAY *bd) + { + /* internal function. Used by BD-J. */ +@@ -1134,25 +1147,16 @@ uint64_t bd_get_uo_mask(BLURAY *bd) + + return mask.u64; + } ++#endif + ++#ifdef USING_BDJAVA + void bd_set_bdj_kit(BLURAY *bd, int mask) + { + _queue_event(bd, BD_EVENT_KEY_INTEREST_TABLE, mask); + } ++#endif + +-int bd_bdj_sound_effect(BLURAY *bd, int id) +-{ +- if (bd->sound_effects && id >= bd->sound_effects->num_sounds) { +- return -1; +- } +- if (id < 0 || id > 0xff) { +- return -1; +- } +- +- _queue_event(bd, BD_EVENT_SOUND_EFFECT, id); +- return 0; +-} +- ++#ifdef USING_BDJAVA + void bd_select_rate(BLURAY *bd, float rate, int reason) + { + if (reason == BDJ_PLAYBACK_STOP) { +@@ -1171,26 +1175,9 @@ void bd_select_rate(BLURAY *bd, float rate, int reason) + _queue_event(bd, BD_EVENT_STILL, 0); + } + } ++#endif + +-int bd_bdj_seek(BLURAY *bd, int playitem, int playmark, int64_t time) +-{ +- bd_mutex_lock(&bd->mutex); +- +- if (playitem > 0) { +- bd_seek_playitem(bd, playitem); +- } +- if (playmark >= 0) { +- bd_seek_mark(bd, playmark); +- } +- if (time >= 0) { +- bd_seek_time(bd, time); +- } +- +- bd_mutex_unlock(&bd->mutex); +- +- return 1; +-} +- ++#ifdef USING_BDJAVA + int bd_set_virtual_package(BLURAY *bd, const char *vp_path, int psr_init_backup) + { + bd_mutex_lock(&bd->mutex); +@@ -1216,12 +1203,16 @@ int bd_set_virtual_package(BLURAY *bd, const char *vp_path, int psr_init_backup) + + return 0; + } ++#endif + ++#ifdef USING_BDJAVA + BD_DISC *bd_get_disc(BLURAY *bd) + { + return bd ? bd->disc : NULL; + } ++#endif + ++#ifdef USING_BDJAVA + uint32_t bd_reg_read(BLURAY *bd, int psr, int reg) + { + if (psr) { +@@ -1230,7 +1221,9 @@ uint32_t bd_reg_read(BLURAY *bd, int psr, int reg) + return bd_gpr_read(bd->regs, reg); + } + } ++#endif + ++#ifdef USING_BDJAVA + int bd_reg_write(BLURAY *bd, int psr, int reg, uint32_t value, uint32_t psr_value_mask) + { + if (psr) { +@@ -1247,7 +1240,9 @@ int bd_reg_write(BLURAY *bd, int psr, int reg, uint32_t value, uint32_t psr_valu + return bd_gpr_write(bd->regs, reg, value); + } + } ++#endif + ++#ifdef USING_BDJAVA + BD_ARGB_BUFFER *bd_lock_osd_buffer(BLURAY *bd) + { + bd_mutex_lock(&bd->argb_buffer_mutex); +@@ -1333,13 +1328,11 @@ void bd_bdj_osd_cb(BLURAY *bd, const unsigned *img, int w, int h, + bd->argb_buffer->dirty[BD_OVERLAY_IG].y1 = 0; + } + } +- +-/* +- * BD-J +- */ ++#endif + + static int _start_bdj(BLURAY *bd, unsigned title) + { ++#ifdef USING_BDJAVA + if (bd->bdjava == NULL) { + const char *root = disc_root(bd->disc); + bd->bdjava = bdj_open(root, bd, bd->disc_info.bdj_disc_id, &bd->bdjstorage); +@@ -1349,8 +1342,14 @@ static int _start_bdj(BLURAY *bd, unsigned title) + } + + return !bdj_process_event(bd->bdjava, BDJ_EVENT_START, title); ++#else ++ (void)bd; ++ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Title %d: BD-J not compiled in\n", title); ++ return 0; ++#endif + } + ++#ifdef USING_BDJAVA + static int _bdj_event(BLURAY *bd, unsigned ev, unsigned param) + { + if (bd->bdjava != NULL) { +@@ -1358,7 +1357,11 @@ static int _bdj_event(BLURAY *bd, unsigned ev, unsigned param) + } + return -1; + } ++#else ++#define _bdj_event(bd, ev, param) do{}while(0) ++#endif + ++#ifdef USING_BDJAVA + static void _stop_bdj(BLURAY *bd) + { + if (bd->bdjava != NULL) { +@@ -1367,7 +1370,11 @@ static void _stop_bdj(BLURAY *bd) + _queue_event(bd, BD_EVENT_KEY_INTEREST_TABLE, 0); + } + } ++#else ++#define _stop_bdj(bd) do{}while(0) ++#endif + ++#ifdef USING_BDJAVA + static void _close_bdj(BLURAY *bd) + { + if (bd->bdjava != NULL) { +@@ -1375,6 +1382,20 @@ static void _close_bdj(BLURAY *bd) + bd->bdjava = NULL; + } + } ++#else ++#define _close_bdj(bd) do{}while(0) ++#endif ++ ++#ifdef USING_BDJAVA ++static void _storage_free(BLURAY *bd) ++{ ++ X_FREE(bd->bdjstorage.cache_root); ++ X_FREE(bd->bdjstorage.persistent_root); ++ X_FREE(bd->bdjstorage.classpath); ++} ++#else ++#define _storage_free(bd) do{}while(0) ++#endif + + /* + * open / close +@@ -1401,6 +1422,7 @@ BLURAY *bd_init(void) + } + + bd_mutex_init(&bd->mutex); ++#ifdef USING_BDJAVA + bd_mutex_init(&bd->argb_buffer_mutex); + + env = getenv("LIBBLURAY_PERSISTENT_STORAGE"); +@@ -1408,6 +1430,7 @@ BLURAY *bd_init(void) + int v = (!strcmp(env, "yes")) ? 1 : (!strcmp(env, "no")) ? 0 : atoi(env); + bd->bdjstorage.no_persistent_storage = !v; + } ++#endif + + BD_DEBUG(DBG_BLURAY, "BLURAY initialized!\n"); + +@@ -1522,7 +1545,9 @@ void bd_close(BLURAY *bd) + disc_close(&bd->disc); + + bd_mutex_destroy(&bd->mutex); ++#ifdef USING_BDJAVA + bd_mutex_destroy(&bd->argb_buffer_mutex); ++#endif + + BD_DEBUG(DBG_BLURAY, "BLURAY destroyed!\n"); + +@@ -1654,6 +1679,25 @@ int64_t bd_seek_time(BLURAY *bd, uint64_t tick) + return bd->s_pos; + } + ++int64_t bd_find_seek_point(BLURAY *bd, uint64_t tick) ++{ ++ uint32_t clip_pkt, out_pkt; ++ NAV_CLIP *clip; ++ ++ tick /= 2; ++ ++ if (bd->title && ++ tick < bd->title->duration) { ++ ++ // Find the closest access unit to the requested position ++ clip = nav_time_search(bd->title, (uint32_t)tick, &clip_pkt, &out_pkt); ++ ++ return (int64_t)out_pkt * 192; ++ } ++ ++ return bd->s_pos; ++} ++ + uint64_t bd_tell_time(BLURAY *bd) + { + uint32_t clip_pkt = 0, out_pkt = 0, out_time = 0; +@@ -2394,7 +2438,26 @@ int bd_select_playlist(BLURAY *bd, uint32_t playlist) + return result; + } + +-/* BD-J callback */ ++#ifdef USING_BDJAVA ++int bd_bdj_seek(BLURAY *bd, int playitem, int playmark, int64_t time) ++{ ++ bd_mutex_lock(&bd->mutex); ++ ++ if (playitem > 0) { ++ bd_seek_playitem(bd, playitem); ++ } ++ if (playmark >= 0) { ++ bd_seek_mark(bd, playmark); ++ } ++ if (time >= 0) { ++ bd_seek_time(bd, time); ++ } ++ ++ bd_mutex_unlock(&bd->mutex); ++ ++ return 1; ++} ++ + static int _play_playlist_at(BLURAY *bd, int playlist, int playitem, int playmark, int64_t time) + { + if (playlist < 0) { +@@ -2406,14 +2469,15 @@ static int _play_playlist_at(BLURAY *bd, int playlist, int playitem, int playmar + return 0; + } + ++#ifdef USING_BDJAVA + bd->bdj_wait_start = 1; /* playback is triggered by bd_select_rate() */ ++#endif + + bd_bdj_seek(bd, playitem, playmark, time); + + return 1; + } + +-/* BD-J callback */ + int bd_play_playlist_at(BLURAY *bd, int playlist, int playitem, int playmark, int64_t time) + { + int result; +@@ -2426,6 +2490,21 @@ int bd_play_playlist_at(BLURAY *bd, int playlist, int playitem, int playmark, in + return result; + } + ++int bd_bdj_sound_effect(BLURAY *bd, int id) ++{ ++ if (bd->sound_effects && id >= bd->sound_effects->num_sounds) { ++ return -1; ++ } ++ if (id < 0 || id > 0xff) { ++ return -1; ++ } ++ ++ _queue_event(bd, BD_EVENT_SOUND_EFFECT, id); ++ return 0; ++} ++ ++#endif /* USING_BDJAVA */ ++ + // Select a title for playback + // The title index is an index into the list + // established by bd_get_titles() +@@ -2651,6 +2730,7 @@ static BLURAY_TITLE_INFO* _fill_title_info(NAV_TITLE* title, uint32_t title_idx, + NAV_CLIP *nc = &title->clip_list.clip[ii]; + + memcpy(ci->clip_id, pi->clip->clip_id, sizeof(ci->clip_id)); ++ ci->idx = nc->clip_id; + ci->pkt_count = nc->end_pkt - nc->start_pkt; + ci->start_time = (uint64_t)nc->title_time * 2; + ci->in_time = (uint64_t)pi->in_time * 2; +@@ -2675,6 +2755,8 @@ static BLURAY_TITLE_INFO* _fill_title_info(NAV_TITLE* title, uint32_t title_idx, + } + } + ++ title_info->mvc_base_view_r_flag = title->pl->app_info.mvc_base_view_r_flag; ++ + return title_info; + + error: +@@ -2802,7 +2884,7 @@ int bd_set_player_setting(BLURAY *bd, uint32_t idx, uint32_t value) + bd_mutex_unlock(&bd->mutex); + return result; + } +- ++#ifdef USING_BDJAVA + if (idx == BLURAY_PLAYER_SETTING_PERSISTENT_STORAGE) { + if (bd->title_type != title_undef) { + BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Can't disable persistent storage during playback\n"); +@@ -2811,6 +2893,7 @@ int bd_set_player_setting(BLURAY *bd, uint32_t idx, uint32_t value) + bd->bdjstorage.no_persistent_storage = !value; + return 1; + } ++#endif + + for (i = 0; i < sizeof(map) / sizeof(map[0]); i++) { + if (idx == map[i].idx) { +@@ -2835,6 +2918,7 @@ int bd_set_player_setting_str(BLURAY *bd, uint32_t idx, const char *s) + case BLURAY_PLAYER_SETTING_COUNTRY_CODE: + return bd_set_player_setting(bd, idx, str_to_uint32(s, 2)); + ++#ifdef USING_BDJAVA + case BLURAY_PLAYER_CACHE_ROOT: + bd_mutex_lock(&bd->mutex); + X_FREE(bd->bdjstorage.cache_root); +@@ -2850,6 +2934,7 @@ int bd_set_player_setting_str(BLURAY *bd, uint32_t idx, const char *s) + bd_mutex_unlock(&bd->mutex); + BD_DEBUG(DBG_BDJ, "Persistent root dir set to %s\n", bd->bdjstorage.persistent_root); + return 1; ++#endif /* USING_BDJAVA */ + + default: + return 0; +@@ -3265,7 +3350,7 @@ static int _play_title(BLURAY *bd, unsigned title) + return 0; + } + +-/* BD-J callback */ ++#ifdef USING_BDJAVA + int bd_play_title_internal(BLURAY *bd, unsigned title) + { + /* used by BD-J. Like bd_play_title() but bypasses UO mask checks. */ +@@ -3275,6 +3360,7 @@ int bd_play_title_internal(BLURAY *bd, unsigned title) + bd_mutex_unlock(&bd->mutex); + return ret; + } ++#endif + + int bd_play(BLURAY *bd) + { +@@ -3505,6 +3591,7 @@ static int _read_ext(BLURAY *bd, unsigned char *buf, int len, BD_EVENT *event) + return 0; + } + ++#ifdef USING_BDJAVA + if (bd->title_type == title_bdj) { + if (bd->end_of_playlist == 1) { + _bdj_event(bd, BDJ_EVENT_END_OF_PLAYLIST, bd_psr_read(bd->regs, PSR_PLAYLIST)); +@@ -3523,6 +3610,7 @@ static int _read_ext(BLURAY *bd, unsigned char *buf, int len, BD_EVENT *event) + return 0; + } + } ++#endif + + int bytes = _bd_read(bd, buf, len); + +@@ -3584,9 +3672,11 @@ static int _set_rate(BLURAY *bd, uint32_t rate) + return -1; + } + ++#ifdef USING_BDJAVA + if (bd->title_type == title_bdj) { + return _bdj_event(bd, BDJ_EVENT_RATE, rate); + } ++#endif + + return 0; + } +@@ -3613,8 +3703,10 @@ int bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x, uint16_t y) + + if (bd->title_type == title_hdmv) { + result = _run_gc(bd, GC_CTRL_MOUSE_MOVE, param); ++#ifdef USING_BDJAVA + } else if (bd->title_type == title_bdj) { + result = _bdj_event(bd, BDJ_EVENT_MOUSE, param); ++#endif + } + + bd_mutex_unlock(&bd->mutex); +@@ -3636,8 +3728,10 @@ int bd_user_input(BLURAY *bd, int64_t pts, uint32_t key) + + if (bd->title_type == title_hdmv) { + result = _run_gc(bd, GC_CTRL_VK_KEY, key); ++#ifdef USING_BDJAVA + } else if (bd->title_type == title_bdj) { + result = _bdj_event(bd, BDJ_EVENT_VK_KEY, key); ++#endif + } + + bd_mutex_unlock(&bd->mutex); +@@ -3664,6 +3758,7 @@ void bd_register_overlay_proc(BLURAY *bd, void *handle, bd_overlay_proc_f func) + + void bd_register_argb_overlay_proc(BLURAY *bd, void *handle, bd_argb_overlay_proc_f func, BD_ARGB_BUFFER *buf) + { ++#ifdef USING_BDJAVA + if (!bd) { + return; + } +@@ -3675,6 +3770,12 @@ void bd_register_argb_overlay_proc(BLURAY *bd, void *handle, bd_argb_overlay_pro + bd->argb_buffer = buf; + + bd_mutex_unlock(&bd->argb_buffer_mutex); ++#else ++ (void)bd; ++ (void)handle; ++ (void)func; ++ (void)buf; ++#endif + } + + int bd_get_sound_effect(BLURAY *bd, unsigned sound_id, BLURAY_SOUND_EFFECT *effect) +@@ -3825,10 +3926,44 @@ void bd_free_mobj(struct mobj_objects *obj) + + struct bdjo_data *bd_read_bdjo(const char *bdjo_file) + { ++#ifdef USING_BDJAVA + return bdjo_parse(bdjo_file); ++#else ++ (void)bdjo_file; ++ return NULL; ++#endif + } + + void bd_free_bdjo(struct bdjo_data *obj) + { ++#ifdef USING_BDJAVA + bdjo_free(&obj); ++#else ++ (void)obj; ++#endif ++} ++ ++int bd_get_clip_infos(BLURAY *bd, unsigned clip, uint64_t *clip_start_time, uint64_t *stream_start_time, uint64_t *pos, uint64_t *duration) ++{ ++ if (bd && bd->title && bd->title->clip_list.count > clip) { ++ if (clip_start_time) ++ *clip_start_time = (uint64_t)bd->title->clip_list.clip[clip].title_time << 1; ++ if (stream_start_time) ++ *stream_start_time = (uint64_t)bd->title->clip_list.clip[clip].in_time << 1; ++ if (pos) ++ *pos = (uint64_t)bd->title->clip_list.clip[clip].title_pkt * 192; ++ if (duration) ++ *duration = (uint64_t)bd->title->clip_list.clip[clip].duration << 1; ++ ++ return 1; ++ } ++ return 0; ++} ++ ++struct mpls_pl* bd_get_title_mpls(BLURAY * bd) ++{ ++ if (bd && bd->title) { ++ return bd->title->pl; ++ } ++ return NULL; + } +diff --git a/src/libbluray/bluray.h b/src/libbluray/bluray.h +index 70e6a84..0cd6047 100644 +--- a/src/libbluray/bluray.h ++++ b/src/libbluray/bluray.h +@@ -32,6 +32,7 @@ extern "C" { + */ + + #include ++#include "bdnav/clpi_data.h" + + #define TITLES_ALL 0 /**< all titles. */ + #define TITLES_FILTER_DUP_TITLE 0x01 /**< remove duplicate titles. */ +@@ -90,7 +91,7 @@ typedef struct { + + /* BD-J info (valid only if disc uses BD-J) */ + uint8_t bdj_detected; /* 1 if disc uses BD-J */ +- uint8_t bdj_supported; /* (deprecated) */ ++ uint8_t bdj_supported; /* 1 if BD-J support was compiled in */ + uint8_t libjvm_detected; /* 1 if usable Java VM was found */ + uint8_t bdj_handled; /* 1 if usable Java VM + libbluray.jar was found */ + +@@ -224,6 +225,7 @@ typedef struct bd_stream_info { + } BLURAY_STREAM_INFO; + + typedef struct bd_clip { ++ uint32_t idx; + uint32_t pkt_count; + uint8_t still_mode; + uint16_t still_time; /* seconds */ +@@ -274,6 +276,8 @@ typedef struct bd_title_info { + BLURAY_CLIP_INFO *clips; + BLURAY_TITLE_CHAPTER *chapters; + BLURAY_TITLE_MARK *marks; ++ ++ uint8_t mvc_base_view_r_flag; + } BLURAY_TITLE_INFO; + + /* +@@ -480,6 +484,16 @@ int bd_select_playlist(BLURAY *bd, uint32_t playlist); + */ + uint32_t bd_get_current_title(BLURAY *bd); + ++/** ++ * ++ * Find the byte position to specific time in 90Khz ticks ++ * ++ * @param bd BLURAY ojbect ++ * @param tick tick count ++ * @return byte position ++ */ ++int64_t bd_find_seek_point(BLURAY *bd, uint64_t tick); ++ + /** + * + * Read from currently selected title file, decrypt if possible +@@ -1039,7 +1053,6 @@ int bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x, uint16_t y); + + /* access to internal information */ + +-struct clpi_cl; + /** + * + * Get copy of clip information for requested playitem. +@@ -1092,6 +1105,28 @@ void bd_stop_bdj(BLURAY *bd); // shutdown BD-J and clean up resources + */ + int bd_read_file(BLURAY *, const char *path, void **data, int64_t *size); + ++/** ++ * ++ * Get information about the clip ++ * ++ * @param bd BLURAY object ++ * @param clip clip index ++ * @param clip_start_time start of the clip (in the total title) (in 90khz) ++ * @param stream_start_time first pts in the clip (in 90khz) ++ * @param byte position of the clip (absolute) ++ * @param duration duration of the clip (in 90khz) ++ */ ++int bd_get_clip_infos(BLURAY *bd, unsigned clip, uint64_t *clip_start_time, uint64_t *stream_start_time, uint64_t *pos, uint64_t *duration); ++ ++/** ++ * Get the MPLS struct of the current title ++ * ++ * @param bd BLURAY object ++ * @return the MPLS struct ++ * ++ * Lifetime of the MPLS pointer is limited to the lifetime of the BD title ++ */ ++struct mpls_pl* bd_get_title_mpls(BLURAY * bd); + + #ifdef __cplusplus + } +diff --git a/src/libbluray/disc/disc.c b/src/libbluray/disc/disc.c +index be6a279..e96539a 100644 +--- a/src/libbluray/disc/disc.c ++++ b/src/libbluray/disc/disc.c +@@ -38,7 +38,9 @@ + #include + #include + ++#ifdef ENABLE_UDF + #include "udf_fs.h" ++#endif + + struct bd_disc { + BD_MUTEX ovl_mutex; /* protect access to overlay root */ +@@ -75,7 +77,7 @@ static BD_FILE_H *_bdrom_open_path(void *p, const char *rel_path) + return NULL; + } + +- fp = file_open(abs_path, "rb"); ++ fp = file_open(abs_path, "rbS"); + X_FREE(abs_path); + + return fp; +@@ -316,6 +318,7 @@ BD_DISC *disc_open(const char *device_path, + _set_paths(p, device_path); + + /* check if disc root directory can be opened. If not, treat it as device/image file. */ ++#ifdef ENABLE_UDF + BD_DIR_H *dp_img = device_path ? dir_open(device_path) : NULL; + if (!dp_img) { + void *udf = udf_image_open(device_path, p_fs ? p_fs->fs_handle : NULL, p_fs ? p_fs->read_blocks : NULL); +@@ -336,6 +339,7 @@ BD_DISC *disc_open(const char *device_path, + dir_close(dp_img); + BD_DEBUG(DBG_FILE, "%s does not seem to be image file or device node\n", device_path); + } ++#endif + + struct dec_dev dev = { p->fs_handle, p->pf_file_open_bdrom, p, (file_openFp)disc_open_path, p->disc_root, device_path }; + p->dec = dec_init(&dev, enc_info, keyfile_path, regs, psr_read, psr_write); diff --git a/packages/multimedia/libbluray/patches/libbluray-02-install-extra-MVC-headers.patch b/packages/multimedia/libbluray/patches/libbluray-02-install-extra-MVC-headers.patch new file mode 100644 index 000000000..ca961f1cd --- /dev/null +++ b/packages/multimedia/libbluray/patches/libbluray-02-install-extra-MVC-headers.patch @@ -0,0 +1,42 @@ +From 316310d889d0bcffa299ef6a7fb5726847f2dd3a Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Wed, 20 Jun 2018 15:01:32 +0100 +Subject: [PATCH] add missing 3D MVC headers + +--- + Makefile.am | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index ff15527..00db9af 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -219,6 +219,14 @@ noinst_HEADERS = \ + jni/win32/jni_md.h \ + jni/darwin/jni_md.h + ++bdnavdir=$(pkgincludedir)/bdnav ++bdnav_HEADERS = \ ++ src/libbluray/bdnav/clpi_data.h ++ ++utildir=$(pkgincludedir)/util ++util_HEADERS = \ ++ src/util/attributes.h ++ + pkginclude_HEADERS = \ + src/file/filesystem.h \ + src/libbluray/bluray.h \ +@@ -226,6 +234,10 @@ pkginclude_HEADERS = \ + src/libbluray/keys.h \ + src/libbluray/player_settings.h \ + src/libbluray/bdnav/clpi_data.h \ ++ src/libbluray/bdnav/clpi_parse.h \ ++ src/libbluray/bdnav/mpls_parse.h \ ++ src/libbluray/bdnav/mpls_data.h \ ++ src/libbluray/bdnav/uo_mask_table.h \ + src/libbluray/bdnav/meta_data.h \ + src/libbluray/decoders/overlay.h \ + src/util/log_control.h +-- +2.14.1 + diff --git a/packages/multimedia/libdvbpsi/package.mk b/packages/multimedia/libdvbpsi/package.mk new file mode 100644 index 000000000..1afdf8640 --- /dev/null +++ b/packages/multimedia/libdvbpsi/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="libdvbpsi" +PKG_VERSION="1.3.3" +#PKG_SHA256="" +PKG_REV="2" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://www.videolan.org/developers/libdvbpsi.html" +PKG_URL="http://download.videolan.org/pub/libdvbpsi/$PKG_VERSION/libdvbpsi-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="tools" +PKG_SHORTDESC="library for MPEG TS and DVB PSI tables decoding and generating" +PKG_LONGDESC="libdvbpsi is a simple library designed for MPEG TS and DVB PSI tables decoding and generating." +PKG_IS_ADDON="no" +PKG_AUTORECONF="yes" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/multimedia/libdvdcss/package.mk b/packages/multimedia/libdvdcss/package.mk new file mode 100644 index 000000000..07d544351 --- /dev/null +++ b/packages/multimedia/libdvdcss/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdvdcss" +PKG_VERSION="1.4.2-Leia-Beta-5" +PKG_SHA256="38816f8373e243bc5950449b4f3b18938c4e1c59348e3411e23f31db4072e40d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/xbmc/libdvdcss" +PKG_URL="https://github.com/xbmc/libdvdcss/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libdvdcss is a simple library designed for accessing DVDs as a block device without having to bother about the decryption." +PKG_TOOLCHAIN="manual" diff --git a/packages/multimedia/libdvdnav/package.mk b/packages/multimedia/libdvdnav/package.mk new file mode 100644 index 000000000..e6c05cacf --- /dev/null +++ b/packages/multimedia/libdvdnav/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdvdnav" +PKG_VERSION="9277007" +PKG_SHA256="e50db40a823ddc795d1fe5f18db2517fb3e05fe0c4a88abf1578d95d7a1cce63" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/xbmc/libdvdnav" +PKG_URL="https://github.com/xbmc/libdvdnav/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libdvdread" +PKG_LONGDESC="libdvdnav is a library that allows easy use of sophisticated DVD navigation features such as DVD menus, multiangle playback and even interactive DVD games." +PKG_TOOLCHAIN="manual" diff --git a/packages/multimedia/libdvdread/package.mk b/packages/multimedia/libdvdread/package.mk new file mode 100644 index 000000000..7231ae763 --- /dev/null +++ b/packages/multimedia/libdvdread/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdvdread" +PKG_VERSION="bd6b329" +PKG_SHA256="2d9d6d185dd25a983d6dfc2a00207cafdc396a969c227d5edd84b6215b2fba89" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/xbmc/libdvdread" +PKG_URL="https://github.com/xbmc/libdvdread/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libdvdread is a library which provides a simple foundation for reading DVDs." +PKG_TOOLCHAIN="manual" + +if [ "$KODI_DVDCSS_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libdvdcss" +fi diff --git a/packages/multimedia/libhdhomerun/package.mk b/packages/multimedia/libhdhomerun/package.mk new file mode 100644 index 000000000..6c0cf2655 --- /dev/null +++ b/packages/multimedia/libhdhomerun/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libhdhomerun" +PKG_VERSION="b0e5d5f5c8e2bf37dea34beb014e08ebb598ebf6" #20190625 +PKG_SHA256="ac39e03090c148678e1a8d4f928a728caccd2d29a0555287e7e5ece28c876959" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.silicondust.com" +PKG_URL="https://github.com/Silicondust/libhdhomerun/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The library provides functionality to setup the HDHomeRun." + +PKG_MAKE_OPTS_TARGET="CROSS_COMPILE=$TARGET_PREFIX" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp -PR hdhomerun_config $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/lib/ + cp -PR libhdhomerun.so $INSTALL/usr/lib/ + + mkdir -p $SYSROOT_PREFIX/usr/include/hdhomerun + cp *.h $SYSROOT_PREFIX/usr/include/hdhomerun + + mkdir -p $SYSROOT_PREFIX/usr/lib + cp libhdhomerun.so $SYSROOT_PREFIX/usr/lib +} diff --git a/packages/multimedia/libmpeg2/package.mk b/packages/multimedia/libmpeg2/package.mk new file mode 100644 index 000000000..692732281 --- /dev/null +++ b/packages/multimedia/libmpeg2/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmpeg2" +PKG_VERSION="0.5.1" +PKG_SHA256="dee22e893cb5fc2b2b6ebd60b88478ab8556cb3b93f9a0d7ce8f3b61851871d4" +PKG_LICENSE="GPLv2" +PKG_SITE="http://libmpeg2.sourceforge.net/" +PKG_URL="http://libmpeg2.sourceforge.net/files/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The MPEG Library is a collection of C routines to decode MPEG-1 and MPEG-2 movies." + +PKG_CONFIGURE_OPTS_TARGET="--disable-sdl \ + --without-x" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-altivec.patch b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-altivec.patch new file mode 100644 index 000000000..4928a62e6 --- /dev/null +++ b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-altivec.patch @@ -0,0 +1,23 @@ +[PATCH] fix altivec.h detection + +Patch from Gentoo: + +http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/media-libs/libmpeg2/files/libmpeg2-0.5.1-altivec.patch?revision=1.1&view=markup + +Signed-off-by: Peter Korsgaard +--- a/configure.ac.bak 2010-05-25 17:12:14.756245990 +0000 ++++ b/configure.ac 2010-05-25 17:11:51.629581723 +0000 +@@ -79,11 +79,10 @@ + CFLAGS="$OPT_CFLAGS $TRY_CFLAGS $CFLAGS" + AC_MSG_CHECKING([if is needed]) + AC_TRY_COMPILE([], +- [typedef vector int t; +- vec_ld(0, (unsigned char *)0);], ++ [vector int t; t = vec_add(t,t);], + [have_altivec=yes; AC_MSG_RESULT(no)], + [AC_TRY_COMPILE([#include ], +- [typedef vector int t; vec_ld(0, (unsigned char *)0);], ++ [vector int t; t = vec_add(t,t);], + [AC_DEFINE([HAVE_ALTIVEC_H],, + [Define to 1 if you have the header.]) + have_altivec=yes; AC_MSG_RESULT(yes)], diff --git a/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-arm-private-symbols.patc b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-arm-private-symbols.patc new file mode 100644 index 000000000..222ff9954 --- /dev/null +++ b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-arm-private-symbols.patc @@ -0,0 +1,44 @@ +Set visibility of global symbols used in ARM specific assembly file to internal + +--- a/libmpeg2/motion_comp_arm_s.S ++++ b/libmpeg2/motion_comp_arm_s.S +@@ -23,7 +23,8 @@ + + @ ---------------------------------------------------------------- + .align +- .global MC_put_o_16_arm ++ .global MC_put_o_16_arm ++ .internal MC_put_o_16_arm + MC_put_o_16_arm: + @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) + pld [r1] +@@ -83,7 +84,8 @@ + + @ ---------------------------------------------------------------- + .align +- .global MC_put_o_8_arm ++ .global MC_put_o_8_arm ++ .internal MC_put_o_8_arm + MC_put_o_8_arm: + @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) + pld [r1] +@@ -152,7 +154,8 @@ + .endm + + .align +- .global MC_put_x_16_arm ++ .global MC_put_x_16_arm ++ .internal MC_put_x_16_arm + MC_put_x_16_arm: + @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) + pld [r1] +@@ -244,7 +247,8 @@ + + @ ---------------------------------------------------------------- + .align +- .global MC_put_x_8_arm ++ .global MC_put_x_8_arm ++ .internal MC_put_x_8_arm + MC_put_x_8_arm: + @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) + pld [r1] diff --git a/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-armv4l.patch b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-armv4l.patch new file mode 100644 index 000000000..48b1648f4 --- /dev/null +++ b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-armv4l.patch @@ -0,0 +1,19 @@ +--- a/libmpeg2/motion_comp_arm_s.S ++++ b/libmpeg2/motion_comp_arm_s.S +@@ -19,6 +19,16 @@ + @ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ++@ Data preload is supported only by ARM V5TE and above ++ ++#if (defined (__ARM_ARCH_2__) || defined (__ARM_ARCH_3__) \ ++ || defined (__ARM_ARCH_3M__) || defined (__ARM_ARCH_4__) \ ++ || defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_5__) \ ++ || defined (__ARM_ARCH_5T__)) ++.macro pld reg ++.endm ++#endif ++ + .text + + @ ---------------------------------------------------------------- diff --git a/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-global-symbol-test.patch b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-global-symbol-test.patch new file mode 100644 index 000000000..1eb01f43f --- /dev/null +++ b/packages/multimedia/libmpeg2/patches/libmpeg2-0.5.1-global-symbol-test.patch @@ -0,0 +1,60 @@ +Rewrite the public symbol check to verify the shared libraries, to check for +more things, and to avoid duplication; fixes make check on ARM + +--- a/test/globals ++++ b/test/globals +@@ -1,4 +1,8 @@ + #!/bin/sh ++# TODO ++# - fix checking of .a libs; problem is that "nm -g --defined-only" lists ++# internal symbols; this can be solved by using objdump, but it's probably ++# good enough to just run the tests on the shared lib + + if test x"$srcdir" != x""; then + builddir="." # running from make check, but it does not define that +@@ -14,22 +18,30 @@ + + error=0 + +-bad_globals=`nm -g --defined-only $builddir/../libmpeg2/*.o |\ +- awk '{if ($3) print $3}' | grep -v '^_\?mpeg2_'` +- +-if test x"$bad_globals" != x""; then +- echo BAD GLOBAL SYMBOLS: +- for s in $bad_globals; do echo $s; done ++# check_bad_public_symbols [...] ++# ++# checks public symbols in shared libs: ++# - allow prefix_anything ++# - reject _prefixanything ++# - allow _anything ++# - reject anything else ++# ++# NB: skips missing files ++check_bad_public_symbols() { ++ symbols_prefix="$1" ++ shift ++ lib_files=`ls "$@" 2>/dev/null` ++ [ -z "$lib_files" ] && return ++ bad_globals=`nm -g --defined-only $lib_files | ++ awk '{if ($3) print $3}' | ++ sed -n "/^${symbols_prefix}_/ d; /^_${symbols_prefix}/ { p; d }; /^_/ d; p"` ++ [ -z "$bad_globals" ] && return + error=1 +-fi +- +-bad_globals=`nm -g --defined-only $builddir/../libmpeg2/convert/*.o |\ +- awk '{if ($3) print $3}' | grep -v '^_\?mpeg2convert_'` ++ echo BAD GLOBAL SYMBOLS in $lib_files: ++ echo "$bad_globals" ++} + +-if test x"$bad_globals" != x""; then +- echo BAD GLOBAL SYMBOLS: +- for s in $bad_globals; do echo $s; done +- error=1 +-fi ++check_bad_public_symbols mpeg2 $builddir/../libmpeg2/.libs/libmpeg2.so ++check_bad_public_symbols mpeg2convert $builddir/../libmpeg2/convert/.libs/libmpeg2convert.so + + exit $error diff --git a/packages/multimedia/libva/package.mk b/packages/multimedia/libva/package.mk new file mode 100644 index 000000000..fe6cd9991 --- /dev/null +++ b/packages/multimedia/libva/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libva" +PKG_VERSION="2.5.0" +PKG_SHA256="9b6264dade6b6d3edb59c6c4f3c9217d1d5a195635fc07da875d565f58624418" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://01.org/linuxmedia" +PKG_URL="https://github.com/intel/libva/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Libva is an implementation for VA-API (VIdeo Acceleration API)." +PKG_TOOLCHAIN="autotools" + +if [ "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="toolchain libX11 libXext libXfixes libdrm" + DISPLAYSERVER_LIBVA="--enable-x11 --disable-glx --disable-wayland" +elif [ "$DISPLAYSERVER" = "weston" ]; then + DISPLAYSERVER_LIBVA="--disable-x11 --disable-glx --enable-wayland" + PKG_DEPENDS_TARGET="toolchain libdrm wayland" +else + PKG_DEPENDS_TARGET="toolchain libdrm" + DISPLAYSERVER_LIBVA="--disable-x11 --disable-glx --disable-wayland" +fi + +PKG_CONFIGURE_OPTS_TARGET="--disable-silent-rules \ + --disable-docs \ + --enable-drm \ + $DISPLAYSERVER_LIBVA" diff --git a/packages/multimedia/libvdpau/package.mk b/packages/multimedia/libvdpau/package.mk new file mode 100644 index 000000000..42d2d5a0b --- /dev/null +++ b/packages/multimedia/libvdpau/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libvdpau" +PKG_VERSION="1.1.1" +PKG_SHA256="5fe093302432ef05086ca2ee429c789b7bf843e166d482d166e56859b08bef55" +PKG_LICENSE="MIT" +PKG_SITE="https://wiki.freedesktop.org/www/Software/VDPAU/" +PKG_URL="https://secure.freedesktop.org/~aplattner/vdpau/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libX11 xorgproto libXext" +PKG_LONGDESC="VDPAU is the Video Decode and Presentation API for UNIX." + +PKG_CONFIGURE_OPTS_TARGET="--enable-dri2 \ + --disable-documentation \ + --with-module-dir=/usr/lib/vdpau" diff --git a/packages/multimedia/mpv/package.mk b/packages/multimedia/mpv/package.mk new file mode 100644 index 000000000..e6f4b822d --- /dev/null +++ b/packages/multimedia/mpv/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="mpv" +PKG_VERSION="70b991749df389bcc0a4e145b5687233a03b4ed7" +PKG_SHA256="417b45c2ac88b9e020b55adf9238a4b46dc8c80d4c1a3efe301d55aaae4b0b99" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/mpv-player/mpv" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain ffmpeg SDL2 ${OPENGLES} luajit libass" +PKG_LONGDESC="Video player based on MPlayer/mplayer2 https://mpv.io" +PKG_TOOLCHAIN="manual" + +configure_target() { + #./bootstrap.py + # the bootstrap was failing for some reason. + cp $PKG_DIR/waf/* $PKG_BUILD + + ./waf configure --enable-sdl2 --enable-sdl2-gamepad --disable-pulse --enable-egl --disable-libbluray --disable-gl +} + +make_target() { + ./waf build +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp ./build/mpv $INSTALL/usr/bin +} diff --git a/packages/multimedia/mpv/waf/waf b/packages/multimedia/mpv/waf/waf new file mode 100755 index 000000000..42d36055b --- /dev/null +++ b/packages/multimedia/mpv/waf/waf @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# encoding: latin-1 +# Thomas Nagy, 2005-2018 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.9" +REVISION="10a533182bd85c3f45a157fb5d62db50" +GIT="c543921e7de1e319d9d3e425484d5a4d0794bb00" +INSTALL='' +C1='#1' +C2='#,' +C3='#*' +cwd = os.getcwd() +join = os.path.join + + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) + +if __name__ == '__main__': + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SYÓu#,®N\ÿÿ°ðÿÿÿÿÿÿÿÿÿÿÿÿÅ°‚„C 0˜(b#,œ÷½¾ÛÑ#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*¼ðuµf1l/m÷±Tê¡WÐ:N²û}·iºÝkY±î©'X‘¾Ù=Û•õkíÛkXŽÝ\ww#,™<ú¾òá³¾Ýmë˜{¶ö<•N¨Û]—½ëÀK¶« ÊŽö'lv×{2KÐ7¾w•O®ó_qðko»ƒ«Üä2¬÷¾{ß}ñè oö÷¾w>ôÞ ìwÝ\vÝ÷Ç#*#*#*¡ ¯¦€(£#*»4{Á£»2ìmíîöà;6¨í”îk³4j#*#*]•Ý¤úöAÊ#*#,ìl#,Û"»b‡l¦Ø4`#1T$P ÞáÂöÕkD‘B…ª¨U»‡¯Û¾|ÞÞë§Û¸ö¨º'»Âåît\ÉQÝÝÛ§%)·]«éíwdÕš#*Þ|žhןlöÞ¶Ì÷­“­{ÏwZ’œµrûîvûæ«ïf_n朞¼ß;£Ëî>NsÝ{y¯ï{ï¾ì}­µ[ìé\€€…I{¤Öô]Ž±7YëwÛÎåyÁëÒ»kaÛ"REUM¼å{‚´#*¨$ªˆ hõ LÁ•:;ÎåzZÃ5wT}¸-ßlùî÷›·¶(ô€tY‹ìdÒcéØÀW½ÁÉ67ÓÏ#*wvöe¤,}Çׯm]Þ@û¦ßW8{Üï;ß\Z}×Þ«¼uã×"Vxw–|}õïWnës”ûžzöݸq¶>÷šÝ$ÛËݵÜÞÚ»+¸nô_kÇo}ådV·»½=:3#1Û×»×¢¶O ˶m9qöÃÓí«w»{Öåöå÷Ò DµŸtµçÙ¯nåì÷lÓ»>ÙËÖÍœãïwg·uök­žÛ[²¾îw±fžN»Éë^Û¾d#*7§=¯;Ó®ûß}ÝNíðä{ÀxQJQ(P$(ƒÙæ×#,K;›’§C¯»ÊëØéîÁÕ73vlè{¶½M¨»¤êóx÷š¡o]æÖlÌôÎð#*îuq#*Uè½½ìÝæ­ÞNû3ÏFv¾µÜ½ƒ^¾ìùžèßNËsF8²Ò6/Mti]óŸOfé)ê²ÍªûÞˆƒßn:Ú|½±æ÷ÛWŸw¼÷[o€Jª#*×¼Öç«©MìÞîžžÛnjŸFûm½ðÓovÓ³ùÞ\}ó0Ù¶ë{½wy®÷rñ¼ucîûw]o7£Yñzr{vå1»w׎úi›X&m€ú+£{ w±å·½v·7@Ÿw ‘<ø˜ïUÛ»87léÞ½ÒsÛÌ#*ÀSg£€îi”öyç»w]Ö­ok;N¶ï]^¼Ÿ85Þó»¹ÛlmŸ7a{Ûî}Þg7u€zé@÷¹ÎƒA¸Šæçw»kl3Wƒ{Ã¥W£s–{Æ÷·ŸO½€{gtô%˜WoWlkØ#*v#ÄÞíÍáöÆ@#,#1hÐ=h›;Ù/v;HÏY¸Ýäë$ê3#,ë]«šÙÎÖíÛ1¤EéX×Nìê—vÝ·Ku§#,÷{ÞF¬núw¦/×—@ó˜õæùº¼C¼ù_zÖ{A{0dÑçÛcmæàÐÊåèûn³k_tëº.Þ]÷ÜN„¾wLuâëžyÛÔt7Í|vpÓD#*@#* #*Lš™¤É“Lb5?$ÅM£Ôl‘ #,LÔÞ¤šd&FI“‰àòM5#,2†¦€#*#*#*#*Hˆ M4ž‚i“)“Ò§•6ôM¤Ú©ù5OÔžõ=CF™=@õ4#*#*h#*#*ž©I€‰€š=E&§èQ¦FOMF ¡  Aê4h#*#*#,#*#*#*‰!#*@4È#*š˜ÓE60šh¦ÚHž“@ h¡¦€I¨ˆ M#*&@„ÄÓÔi3TÔüÔ“ñSõ'êzjžMG¦£õ!é#*#*#*óÿû?©Uk·µÚºýŠ­yÓ™4o•Vœ‰ E‚E!Jˆ¢ˆ ù¬B~£ïý•Ÿ–[øþR¹»®ók|Òi¼{{ãNu#ÅÍb¬r­V4gûó?×fp#1§4@t‚´(4m€jƒ´ŠHÆȈ)UQGœÇ7u3Yæk™qDNG˜ÃÜÓª|97TCÅ*“‡r¦ðg!‹Ô¾¬°•øî­¿I#1ßH€AHÃer»U¦«Ej¤«Y›kP€ªH*H¨È #,À £PdPË„- ƒ¡Iˆ(9DD,(AÄ@÷Áo-ki[SWt[½¦Ôkmµ¶¾+U­S2d,”fj3M‘&0H¤ØÚˆ™š„K#*š”£J)¶“a‰š$ÐJ2Zš± ÂÚ3IdÓHÑ•¤MJPH´jXИ²¦Ñ¤ŠM’ѵBRËJi­1 -!³A0e™ŒmFÔdš#,)²ŠÓJÃF–ZF0"”´ji°–Ò¶²ÛZ±&ŒÌ™š"ƒ,›im¦›@š’”•5±–¦Û3fZL’b(6"Íi‰¢ÉE2(Ù-‘Qf‘´R`4TH!`ؤ©„f•Jb0lB ‘QhdFIR&B4±ClÍ ˆ˜¦!™4¬°fbD#,%‘ˆ¥’²llhؘT‹Ée!#E¥)‚lII‘FQ&ŒšdÄ‚¤£H”F’@¬‚›$‹DÌ¥¦"™‚lk$3b$Å436 …ˆÚ’À$²°„X$¤ØÔ&¢Š#1HKH”h"‘DÁ`ÀL3 d”Â0™Be$¤ÔY›5„Ù5$I1„´¦È$Y-ˆ 1e™E#fIDÙ™3bdE(Í‘˜&U4Ä‹)Af¢ÈY ÓHlb#R²Y#b‰R"šIˆ&¤Jšd 4!$Ô’Ê2ƒ&iESMMj€ÄË(4–FB1d¤Èš ¦R%FŒÂee#1LTa”‚B@E&c$Œh"Y!–²L©™¶˜ÆÙMbQ2‘LB‘±e#1Êh©"Š ŠI$Ù#ɳHÔÍ,FRB“31K#+6˜JÄFŠ$ɦ¦M2AHc(ŠBÍSb‹5*R’š) #&2dSi#1,‘ŠQ”¤E6Å$˜’M)¨Ù5DŠFÀ˜Œh&k4˜›A£c0fšL£cH™ 2$”Ù)‘J"²d%¬Ù±k%€É ¤²bCTU ™l)d1±‘ Â2IcQ¦‰£©M(U0Г2“Ã,›"2˜$RÍe„5 ¤ÊDHhšÚ•µ£”&¦hÊdbiE$̈ŠÐjRسE˜¤Ò2„²Ê›4E©•…²ŒHb›#1QHÀÒ›_¶Úè„©ªDAb3h£±µŠ“)šj)RMZBÔl#dš¬ˆÃPÒc(ÉS*H¶D‰™¦[%´F&J[QHZ2i„KY‹5 ¥-4É“*MA±²­#EM”"¶L²*•JÌ)³c1™kbÅ‘Ù4ÊÈ•2Êmd«-”¥4ÈÖÈÐ)QbšËZC%-Fª la#1Z2TUd¬”mQ´TT”kDÑ$m‹h‹¨°ËFÖ,¤É…‚ª˜ E –4c!i’iZklhÚbV1l‘bÚH6ª¦Ú²ÅC!2™©«&‰*F$"i´Š,‘µ©VmŒR›M²ÊTË6mSHˆÖÒ©dLÍR¤bÄ-¡%2šË,šÊË![4ÄBAC*4‘!bˆ±`M‰!´…-£T%¢†KQY&š6LšJ,€›,R)²4lˆ¬² Œ¦bP¤£f™ b#1-™!›M¤Å±²Â3L‰ cFJ,4ÂFf ±Ù1 ’f¢S"”h,Òª¦#*Â4˜Ó J™d„ÔZ2fZŒ¥2’J2Œ…!‹)Xˆ¦FÆ5%,#Ad‹,!FKE#,ŠC1&e6e%,¥fd¬aš,‘± jE¨Õ5£4ECEJi6b¥ŠÌ¢Ôh2d ŒƒLM‰*J“(ce4ÆÉ&[%)Q¨6Ì6i,›¤Ñ£f"PÒŒ›LÖ²#M#1™¢RÃ"lÙ‚!f‘±FˆÍ&ÉLBÄÄM%$$‹E°•E¬bÑ™¬4˜i$СdÈØÅ(‚6(ØÐVY²Y Ê Ø¨ÈY)e%L‚Ú*5Qª$ÑBe•EŠ$Ôš£`Ɇ!aÕ)CV6ƒJi–BŠ4IL’Ñj‹b2•¶EJ*cI‚"É¢)™BԢ̔ISbQ6Õ«Š™Qd¨Ú0¦,Ò‹dÉXµi1IYM²%²lm#,d”È2•$%MDb6ÉŠIA«2`ÐB£Jl͉ˆ¦±ª*edÖdi#1i&¢‚(ÅM©6‹e$±²b1¢‚4˜2JÔˆÑie£he¨“QjŠ±”£i+dA#1£ljJ,R)¡2)‘™jDb53d™­b©,[F¤©fÚMh™µƤ(ØØÉئU4ÛFÑ´l[cÔ™Œ¥–VV%¨ÅbÌØÚ¥JŠR©Fb¡I”#,,%F“hbÌ©"Ô•±dÛ)2Ôh¬CH´RcFÑ­m•«‰•#,LIDb¡€D–4lSI6¦É*ÆضŦjÚ1­e¤©¡–¶Rɶ¦¦Ù j4Õ‰£(¢#FFÒJ(6ÍI©36YQTI‰$ÊI‘Œ…R[E™lÆO÷ÿËØò@Êt“/§šÿ#1áÊg`ŸñS³gÉ®_B½>k÷èökrÐhÒlùÎyÛ©çczsOú}z[Ó)»Ž]Çýûl™÷y¦Q9` †Ïù«;­@ D°0\:8À¥‰pÁI äˆm½È?'çý5áúžF¿ð.¿Üÿ7…ãþ³m¦¼2c#/,$b/«]X…ÔÑ­NÒ["‡ÃÕˆk§àêZX%=×\“7S-ÝF«“‡’¶¤¤PÙ'6ä䱈ÿ-nÙ³RÅV…£)+U7eè•ÂVP£Ü›F EDjê„Tfj¦i+.P0%°¤5I™wåu™Í\ƒ&ÃßµÌV÷} Ñ2©×\Ê*R€‰$HÆÁsk±dµŒiÄ`Wd@ÛLù7,Œ¯MÍ&ƒdŠJ/W*1™ 9Òªž›ÿ½JèhuÔi |Ýóî¼kƼšŒ+Aˆ1†3s'´ýîkÏ¡ÊæùÊœ¨Cªmû;CÀöø±µj²1¡¶ž¥ cœº.â™\Û¦ÔUͺyÜhبŸ‚ëç5¼Z4E‹}ÝÕô·ë«ÅøÚäS+ääkcG6?÷š‚#1ã#Q·Ïh„°ïß0ƒ¦‘Æ*áI¢a˪‚«ÊêŒÃîµ\¤Ú3ºå9ô÷ËåÏWwW+ßÛ¼—Šæ÷W4j&ºåwعGJåÌ”e×t’9Ì…ùÛËοݿŻËáu¾Cž÷",0!M îÛtÉÄe«#1ü¨¤G¹Âÿz›œºûWYf)mÿõ\te1Òä„5#1“×kø•ê•¯Ùõ»äýÕðÔzR—;ëéˆs@ÇGßz_-±þ£&F芺±ŠÊ‹|Ù{+àdu²ïU®I”ÐõœL£?C¶¼ ,ò>Ì)ÄZ¯oQß#,z&ŒœÙ%ó¯;® Ë3+·£[Â}{ÙH4›w„#fµ³V}É&Aùµ:$¨Åb,"2(vU³µÐ´Â¹ïeá¨$`²˜,5m’è)J´âÚDí©–´ð¨eÐñ£ÁÆéE2„R]U¥"»wÕ¬ü*烣¿…e99eéÝv XEFœ#1(SfˆZjÒAS¬çX‚UØXùE;´F–ÚZj×Ú”»¨ƒ<áÜÑ\xØ[Ebv$ô2Ö"<4º:Q@'…SÉõ·è ¦u¢„øß+7×@-9º³~U[ß|B5bâ/Ñýpù³½D9z§~`cí!ÍÖq&ý±KZ©ØàUŽ&x:JÆ}³]b½|ŽL\ð—óP拘~dƒâ Øʯ´€[”¾2.ºÞýuч&mŠŠÿ`fýsqôQH‹ÀÍX£‹##1NuwàÕµ4«=zVL'ÇwTùoÓ7ÀãDŠ>ÆA—ŽÝ°Á¥Ž'ÃÕ‹õ’1xE÷ÚüfkÛÐÚÞÍÙåõóÍOÙ´âuÓs2 ¯h>SÒJd0úY—jCèžæfDÙüFs³‹»Ã¦‡pˆv^×C)”…Fg³œ™|/¶© ÖáON»\ÃðKÛE€Š¥&Çg Ö3Hˆ¢¢ÊaPðüò‚ÛzÕR ¾`R#1:§v•ˆy2{¡îÈØ·y£Li×cõèe÷TÚÎûÑ-Áð‡7ÓÓÙêgd$™”¸t5ˆ´k†v=Dÿ÷/Në§:éÇ=$Ê À²ð˜Èé3“?•p.ÏF4ÕMzÔ¹2Œõ+Z+g1U 1Õ!Q ×â,öžýX(EBåT#,™N/ؼÖô¯#Hc;®¾¾Ý10A—ƒÏ}<átßCD÷Êêíh-"ª…½ªÞù¹p^C˜T‹CwB¥õAqúáå÷CØ™ðç_'ã\ÁÓo(ÿ,Äp¢þj¥ÐÌîùN¡vAzrVUˇ·@¸¹ÏÞ¥ Üf¯¹¬×o*8ÙA—<ó|ê–a‹+º°šòžuT[Ž¾u™–ÊŽ7•¸^|'=¨{Èq«”$A©Nʨr¼Ä¼Ä.… YìgóeTˆŽðá~×éUSí1"Sئ>’øuUÝ;ðæp»¢POa¥Âò*õæãRWKj>‰(Àé¶;<¯g—«•˜ôØ°J¦Š£˜*lÓíPb‚&®w"”÷üP×þMG@Ã^« %"5¯"ùüŠŒòcb×ÛC£GMO}‹|K>bC{§Ë5Ù¹ZíÃŒWºµ¡Bʪ8xbäøŽ°Vï¤gÝÇ»·[ܪYÀgË“~:ê§pK·ç_å±×r"Uc"cpÑŽ5•ç±Í3® ½Ò²ðÑj+­JÍVŠùÕELHgôð¦S…Buü¹’R#1ˆüQË#˜çNÂëΨ{£&اZiÛaǪ‰lEæþ=ñ_#†ÔG¥Œo2Òû|*ñÍé2íe٥Ҿ󿥂åèÜwpîÎoÖ¨8¹R=£Ûà<1‰âæ¤ÀrüDiᬦ´É¿r¤Rrtæ“ËvDGÑ:«Ì\–È%0/’v¹ßIŒ/#,zCm’dBo_ÍP!H÷4›:ðÅ’µÅ˜*õÍ¯í¯®#J;Y˜*1b,ÿ'LÛÕ*ª',cgUI‘WK¾t{²9ãJ³LøµA*!ÁµNH>,–e"4ÅCØ@f‹zÝëÆÓY,HÓÞ±(ô,„/ÏËìÚ¦¥iþU n«œ“„1#,+W?——™~Þxró#3!¾ðÉ@¿Í5À^21íR1þg’WóE—®$ ù£ó–×Óxí°üªû|dìÆ<‘¿ä‹Á»øë¤Q¸dðpƒ7mDüÔ¥?†´›V]6k¦aõiFM²ª…«ãA`«DYæžzrÍKø´[¶¡wUø Z 3±[9ñ³Û€¯Ô£ËÅ@½F&€ô>Ò‚;ˆÄ£œ–Ä[C;Wª<|¶8•»ws”ºqª´ß´Ûoà€ÚqôvÌé×wOÓuÍE¬ˆó`õ6¢oäå`Ø;+²[7ÚŽuú{¶ÛH~‡€!ºpLÛEª3ZŒX¬C÷&0b¦¶Öq‹⬠.…ÌÔìJf*ó‚rufXWæk Ÿ'N™,òaÇZ oUQ8$±…«!XwètZtL´,øÝÈ-øª¾.@ˆ8ÃêÓT$)³Öû@Pueðòå¼ï0pÝô‡êçYa—¢€åZx¿áò‰;srŒTïQ¤ø4­}2-å¾ö3øTœÓ<žƒöšW¿U^!œT󃜄}ð5M“8Û*Éb ;{ª#¿œeJci³o‚všmö¡œÍf8uŒÁ®[Â4íŒ95jý-µÞŨã#z¤c_»NuÜ[}›$œî)u¬ÁÑÜÂôÃÞßjëpÙ@¸OXýÐÛF׃ÿ(e‚‰`¢ÒŒCŠdCÈqK,YžG8ÿÕÀSØ5ßrœÆ›`¼¡—¤è§‘‘¼š¡tŒ˪€_÷üV¿V…¶ÍF†ˆ8ÄW¶À>²coÔÛuBN½ªãäÑGy%®j?I·b¢ eþž¨V9Û=Šò«<©Ô÷œw?ü…Ò£‹UÞÓûG¦wýð8ÉŸ×Þª¹|ÿ&BN¬æCè|Æ¡ªÈ÷þ;±ÀI ¹w¡Ïµv‡nqõvÔÜq]*Ñ*ˆ\Cø¼s§!œLîœ+mV¼‰¦UÕ#,ø‘[Ç8–ÒP±œjroj pÉÍ+ÕÌ«†è®ÕÃ÷ñÇ`[Zit‰Y·ñ¹$~¥¨#,óÌ7kp-3¤.²y¿&¹iu“ðÜ|Lh¬ž#(AG#|Aü:ròa: HÞ_íSh¤vIvLV~q©Í)X+4£ÐÓzüt¼iÝ\]“,v­{éCdgY¦V3Ó—|0éV:7éÍ°dÜ7eäÁ'D(`¹VnPv]rª0âÒs¢l+¯'·`GßløºñHz²côÒŒÉõüöó¢?R#,eÔàêþ1Bé©ñ"rc#18š¥{Á.™v£zx¥ÓoD@JÁŽON.vÏ2d–ÔK„†S¹-Ö.6-sÊØá0ç.ò˜‰â0.ÅÌ( HH”Dy‘H–Š=§ÇÚÚÜ.^|nkÿUÊÏZ2ä_†û[7E½ïŽ›Dy+It”.)2)–ÖñCè í2Ù Õxèkø_ÇV­JN‰b·ŒDipÁf ±õ òد–“Ñ; n·JÝÛ¯…Œ[²¤õ¢ ü¢Ö#*‘!t:þÿ‡˜¾n(Ô#ÛÙ¹L~{”ÁðÏÇã}æXkpaï·«SƒîE—¶™Øø‡cÔÄÇ5O¨·û®”$,]–§jËÌ­ù»ï‚…>¨#,’)#á@˜ÿe>ínHx3h$ö¤]ôNÅw|[>#1z?ÏÅÇm9º1%^í?Ü2u³r#,mQ€c@¤ÛDÐðXéß1Ý€›Ç¢³‚ÀP,Ëé*:kQËKîA(›ç™Ì¾Í-"Y÷Iÿæ ˆÉñÇCÅ’­¿™׺uèæ;;bà-ÐF–žS+É÷Ö¡½¶U|ˆq›ö³ôxðáËwláú#*o»HI€Š]ÙúÜ(( z Ï^º Gö¹nSŽ1^*êª?¢ÒÉ)²I.ÛyQÌ#1<¾G'¥:ÀòËËÎ5é²iã›u½^OWÅQÓêÔ6" üÈQ#,Üʽޚ_ñëúukwE‡r{]]ć9r‰?ü0y#*1‡Ë²! ÅV#*’û¿Ó»Ñü›EÝ«Ãí·l?»KÁzï”$6#,®ˆwˆƒ@3v!˜¢"÷e¹Â¡¨-ü÷¶ÍFÜÊŠ°£®¶l¹ù·`¸iøʲ¼ ‰51sº¨LŠ"~gΧy#*gîÞ¯hò¤2ÄQ¢}äêB":¤‡=¤ºË½{»)‡Éï·¬Ó‰Am¬à3ÒÿM®‘+ûŽÓ#,ãNТ;Ñ2rÑQXsÙňßC2½>z‹\1ˆ[é¥W¬ äc#,H›Uã fƒ¯áŠLÆ’€1óÞý~ë’ƒõßIý¢’õÏgãŸêüÚlÏMZñËýÿ¸þLÐùôŒuD]ŒÜxŸ‡í°“ͥߵA®¬1ºY|67S,V_÷6àÅ ÷üîêâyA#*ù?Ü"ÉP+ŠAÞ7 `.|¯"Ô}áë.š¤zçü´¹ãlæøk§Ýæx¿u•Äuûü·Ì`Ì¢*–`ìHБü-Š>’Ÿó?– @Ñè“´ÓW@ßÍú7í·mÕùóƒï¿™F¸WÍÎüoNßËÎç$5µ¯AMà".Ï#*怳³§¦sëÜ¡Èxd`Š@@@Ø‹ì#1¯zC“­KJļ „ JcËWóš¥j”(“!BIN@­žc \R¡0xzøtCÅj)ueôËV,![žD$à¦Ê¶£þûü»0êœá ßé>Ý7þ\í»åˆ1#1@“!ÝÈz‰:„Èÿ“”¾å[€:ý2ú„¶è¶ß y¬¦´›‹Þo‹’ÂA@ÚÚjHoçÐÙ­å_Á‘,ó½l}~‚ÿ‡Ï‹$L1¥Û¯¾‰Fö>O!àÜûóï1“ ÍÙ# RSYƒFí’cYQ d¡jç©ÉŸÄ®L˜BÞyÌ­­¤”7Šñª„Ïéç:øyD'Ãé‹#É)Wæïë ht@X¡z¼UʃéòÁÈÅ™EJrfžü¶Œá'ðøsø+jf_¾²î„%Ò‡uŸ×™fðz»êåù@÷‘š» 6k€ú(/z²LMmŸhªc?|ó‹ f]~Wi#1ÿ¿¢¨ùuii`’ÙžtÄÄü™ÿåµHvHô‰M™ÇXâØ ¤­Ï±ùE”øvŸLIîF“bÂ0Óá×íÁÂ×®[H臭„#,“¦;@Hc #, ?áGi,-äKÔßòÞ›.‡Wö‰\:Šª¤¡9-¿ÊÉ„¢ás„Ÿ^w¡r;˜ˆÔ7ºá±üç‚X„†4ŽäÛCôV˜ì )#¯“|X~ÆÕëÊ:ó»#Îãªñ_ îýƒ×¡“꺳Hä ]Åä#*8Ot¹¥EnºïuóàÀ©ó€#1,"È“–5¢|(¦H/0:#´µÿ@÷j“ÒtÓ#,g%‚³õýUšÆ„NIŠwC}1MðLõYjÕ#*îËÃ#,$×ra›³þ®Ô`ø‡d]ÙE;@X"Æ£0Dj«é#,ïÊ}Öi™Ëj:p°çZ[*_„Ê*¾íMyíîE<áÆòéWŒŽ½³ñâ¿…êœõã*/„)Âzaõx{š…ö«¦¬ƒ‰Ù²&f‰ocǼwš'ýxÀõÇh’NG=þ)Œ¬Ž¨ññ«$¡p=w4R*ûŸUø|#*ðÜ7ÕõEÐìq+ÌŒ¤šD59øGÕˆtToËNznÞ—ãùo™§¡í¡('²ýDä;ÔÆÿZÒÃ…â€2qQbìX¡™ ¡`E[¦{ŸÖnðQŽœó±ó#,DMJ…>NÙÖò:Bƒ©š& ˆÅÂÂwÞº|þSLô‚PD!OhšŒáCŠBîS#1‰–]Üã¾lPDciÄô©å¡6”\®:`¡4¦c<¿ñjŽqê¨2:}"Ý~ú`”1í{Y›#1`1`}†ØÓV;#,ÖPœn/'åÿÐ0¸ŒèHI„#*c³%ðGíÕç÷,q_ê¢ÞÕhâ¯"ðUQÛhga¸IâØdK´?,CsŠb³j‡R oÙ­c×1:s·InŠÿXøRŽØ~èxF3çÖZ°>ÅíäþkÀ0Ûï=ö9´ÇïGæ‰[YÓ³‰ÒYîÆ&M9Ú±’Ñ™Dfhsg6Rrz•]7>ĬÓJYb¦”ÔTœ-¨¦Å¾bàèÁF‚ÐáëzÔPý‘£ÉøG¡™Õ#, ”i@ë†òBÕ:`FqaÍä5Š#,¸ôùÑæXÎcD0ŽMFbç/P”ÃôG b±(z¬Ä1OãÙÎT»tP3x ÅG\ž¯l%ŽµësÑŽ"”„Ž)Xîì:?K{uð+fý9ÅQ´†K\w|×Ï·ÇGšõÀx%¾×tÍ•íÐu¨ÔôÅYdÛêÊ,Ÿ{^ÜÉaÅÔpLÂÄÇ•#,pèü¿¸ÊYE³>v–«¯Ïˆ ÏöúJgÙOSº{>´søiM+#*®{ßaœ:zšÜ:nÛ5ÎøŸBŠ;‰A8°¶x»¢€=µ¬Ùl—T"(‘/]ÚîóÌ»\ZxìŒÆ"4st‹›rÑQG‰òóñü{|_‘Â0ï×M3MÅ|z/Jõ¾­ÏÑrƒ €)0é ±¦¢!I Ú¦*°¦0iDëøëÓ‹lÃq21ƒŽ0ÄC#*x8>‡%“ˆ.ܧ=ý9¬»Ô7|I6,lŽ.Z5 I×µ\œ½šné;I?¢IÑc±Þ•îî,ýìUµ·f†hMXþm$”.h1[0í`C½²«Þ< ïÆkÊj‰Ú¥,» éÒœ†$Û° $È´ç#1¼dÈUÕ<ÞD\ ˜ˆµÉÝu;9ë4ImÇ0PÔÖ©G#1Dù4üù÷‹ÊYb!Éhƒsð&ˆøu†;UÇÒN-Sëqü_IÉKNÀᮋû,Ÿ…/9Ö†~+¯7ÛŒ1™3^~Vrýã#1´Œ`ã«6t@'uI’›ùî¶DsKZmÿÅÉSF4FÓ„x»éBg%ÎVmŽÖb–Š†éLipFÞåÐÇ%s0V°[u,}M BhØÔCQ#,5·1…b >kb)ûФ%áp‰hºEºÞSudPºËÈaFŒƒ=ý¿S= Øý¾Ýß'³kå×~ƒ|áI#,’J`±@FС«Ó¯±^{öÛÆ™bÄÑ–½’UîÛÆŠöh² †ñŠÙ¦ê¥ '‰]¹¼E^…®¦ÖHÕ¯§·ËÕËIw‹$ê€àÕìÏeRýºÙ€x­˜±UÄHÂ`Í+γÏ)h¢˜Õ‚Åñt: µ †[­Tb_\xKç†6¦²×%‚"Z`Șq؃†ÁdØ'€aٳƟÆwϯjoÛP:>ïnè‰ÑÃJhø£^# DÊ#,ãߣPþ|{š W¢Á'^šU,ÎWÑ!çwŸªÑ\†ÙxF÷³G[g×R¼<Êy“½gcé.èÜ< 2à¸å±•¥]u„VFÆ”±#,Ù%Æ·©ƒ_6ÃÊç‡ãR嵩Ñ2¬%–®µDªpl1 Zg׋gn/ŽüðÅ·‡éꢎ©8âòPæŸÃì¶oÒµ¶¿oúfƒqžW—D±æú¾sœ;ƒñ‡?2?D^®ØâtÔËÉ8i6ˆ<&êF0›Rx´2@Ô 7ý6ùAÖ¸}n³9¿ÛÝãµí68÷eßÓGð¿¿n¦³>3)$”Íut·õ†j´•?X°„á®h7>¼+9y#,lZ¤¢#1*D À˜¡[çÙy| ΉÉ?Óí’Ò `6†ÓŇ«;I–DVA£—Jf¦ zM#µ’Pȳ IÑÖ‹hN¬ƒik%"ŒtŠ(à·¤#,¨’oÃÇmи ©ÚEiB0å–¸À€ÑĸwOœfÔQ4¬Y#10š7ÌX™-),q¶àëÐÐ;F¤j#™†Š¡"„ 2Uz4öøkž/v´o’Ijl#,åh–zA¬`¡Ä&3PƀЉ™öçZçJß6z#,#ĸ(i\£Hð—fxpŽŽ#,Ómºb±#öwG0ÎPâ6\dÊú\®vä^¥&ŸÅÊ‘uG—Ág#Ì©gÞ_^šNñûþÙ¯MŠB{3°ÄF7l–]e¥w5ÈkhX-Ö+²øo.õœÌóÇÓ§¤3±È·4ˆdØôcÖäG—nª7øœÀ°pP’ì$÷¹a­ê<Îï;bžÏc%,,`–å˜åâ–Wûn^ØVd´Èù=ª,¡’œàYÞ¸ŠMŒB|¡òå56ù}ø(Ú÷Ë¥O”ŠRE©#1k›ÄìñäÜ\ØŽ.¥Ë7#1<É["Ê1†X,;’) H‹œÓg°Ü¡Ñi=âÓ¡}qç¾¥2c¸ 4ó$„Á;|S›evâB,°x?Û‹S~AúÛå¸}¼ÖFË1)…_kH†ƒp ¡Ú(霖ÀæºÝJ*UÅS¦ïô¼¥ë·Û~+á™ÇS¬iceJdˆ¡âÞ^2_Ÿ‹ò~~ngp}þ|t ¹Ù«faFǘþk£6ܹ2­$F(¡Yª†!›òò•õáU¿°\ìÈCâöÊ£q0IÆOá,ï­N0‡õqgÈ辩îʼnøã߀TØñf#,Ä‚$/…,·˜¯?\³ç^ó¤vÅV1?Óìµàå¹ÝÙ·»eeåQ«²Õ«ÙGY¡`IÁµZ·%®Š ¼Í¨„¿’•GJí刺۽½q­-FnU®–HÕͺVn[n›i¥»õ¡¢ÌD# c#´¶C½‚ ˆß@ˆÛ̲D€ÂiC%¯¿5'nE×3kP!™é«6ów³}5†w®ŽŸ´êÎ 5e=¿ ¨|Ï™ì å¤#*Oµ(7z9–ûkuœW› ~¢õ^có-¿hoŸ‚ë„Ù9×Ùƒ]gµòðsoG<0Ò0èRìÆJ5Óth,šŸ¶ïÝ°~#‡ã§GGZ ö¨yAûÊZG2yà,=Õ³¿…‚_l6øù¸gòoxFnf #ø˜úµ¢íô¯è^”r¹H5:Ë.×ÐÖ?LC¶¸Þ`¿›˜¹Bë/rÆ[‡ÔýC…BÙ$Ýsê•WfR#1æ•ep…‚ž©Šßž2ßÚûaäµ[¶C—‰~€Fžõ‰Ó),»à¾/þ<ý¿7רDl†1÷#,Ü¿vÇwÖ²fæ²Þ®{§SóW‡WSþ­öϯ×Ñ07z-Ó#,Çác/·fÓøø>ížÊ×mâÈ7›®Œ`6Ÿ¦°øštˆp°qrB;Ù$ y6#,÷z¹>‰>‰uÃ×;­Žï_ψ€˜J›4®¢ G0U!Ê¥Yƒ c#þˆŒFPAúþ?‡Ëž;œE2À4ý$Æ£ŠÂ¹ãžÅ^KÅ-!·GmAd•·,-ˆüÿ³¯øÐ:Ewþ°k4¿¦Í”Riåý>í²à#*':(@H#1€”»›¿¦Û¡\;rýGê”};ó÷xûŠõHhuCìÖï÷7¥dT(¶#=NÖ‚)›RY4Iˆ ÙRÄ¢ýG‰£MŠ¿˜½·j(Ö[¹×n RRþä¡@Ò_ÞÀjnbÚ¿_ôô‚!4ÏL6›h¥+÷þ|Ò¡Ó²XN¡Fâ#*–8ô£~>÷›ÙF¯¹·uÕº’ŒQ¶!Ÿ lóg=§ãßú6~—ø)„)Y)Û6~Új#*³Ëùx‹äü+™B%pE7H¤(Oó0„¦AaÞ÷,ý 4J:3#Þ'$!éÿ#1  ²#1«z•q#,·¤‘µ¾kUäÚÕéa!$M úXÑýG÷ŸžÅãìyQØq¥YÕ1²˜ÔlÁؤÏq¹þo" å– ªWû•ÁÁw…pd_Í’×’Yÿ€s+Óœ¡²ÿ9ÿ?sV,_<óûÚ]C«\‚0¶²Âç³Õ«gö÷3†µ`õ¨ñ°X74|g°²¸=<ÜˉĢ{…ê¡B‘C«¡h#1Ví-9úŒ–0#,”ô¤=Á”Ý$‡ƒ]VÛGq‹û‘ý j ÁPz­ãLeoí²cünóÑ4³Ç˜õ?í]>‹ã î—¢>B5|#*÷‡ÒkzØræ Â#17Õµ^†]Ê9ÀÆ‘n{ŽßßÎ@r ß2F×·¥tÜ.¥g>6,¤9‹œfWÇ¢Ik®ýÐQ÷G_W=¦Äµ ìù=âš-ìý’#,½—qÔå•Îÿ‚;ãîm”®þg墶òp®–¿º «Æ#PâMåT„ž©§ÁWOÞ */âƘ1Ý@z{¯R÷¨evœ5o²ëf–õk#*l9h7èþõI™8†!žƒ}è2”ÐH¡Ã&ûl¥ŽÐç;ŸMñõßD2ƒ'aÑ~3rœdûñÏš]ä5áH@U|L&3ä@zn—<]Àˆ°œÊ«™¨v0úaìÜçÅT(¯é•’Sþå˜ ¦9=ö}?w.Ÿ¤É÷ž&¥Rå«ö×ÚlƒÊ\T'—PGy×/)#*Þ#,Qˆ¬FŽ,Ì"m§as÷÷ 1ªÞÖ?¶Á%øÇŒe'[ÏË{+Þ0ëé#½ÆÖ¤:@þ[:IIi}ÌÆ¿H禅û;”DKßZ½@ü\tˆH Äx«ïˆeyTY¯* (N²ŸÓ?­†‹~Fúf-Š¹1!1î! kœ ÎP=Ä‘ ˆÑäL¼•TDKîþžçÁœ˜°Kþ zOn=IŒ(/Ò©÷ÑÛu$ItWž~Uˆe2јŠÂCcëÌÓ×Ý ñë5±x¿SÓâØÏ#ÇÄxÖ¥€ÀŽ öh`,”1 JùÞ^¾˜"åð‚6ø_¢iæDgSÛòî’Tƒ„2W?#,O9u5¥O;\«ÅvI$'¡Ý°ñìžwöðå­?©Y7OæR¿“‡D:AιÂÉb%BÑ#1 Ô²zaÔ¤¸B-⎅}yýæ™æšï ‘äH”F@<}Baðñ32êÙÙ‡FÏç×àùœÛ6éÖ¾ƒTw=þ —…´ðG:d«wF´.ÙwKWªZ|äè‘chæýº=­ˆ7ßm¶k¥×uÈÛ‚·™ê)HkïÎÊÌKǧ‹„l4ÓDj?@TÂçCMðeêæ}ÝžüáAó:Ð}ù¢¼q+ˆQׇá_¥Ø#,z}‹`ù5owÈúÞëù¹ÜÙCãè“ U¥Š¿ÃwÆÎ÷a&Á9ÁPyaò·÷òJ¿ðý#,n(ᆖENu#*`x\+Ϻ3Õg·ÙýkgÑ`çå•éóâ~¤ýg÷;Gvzëw(&!ÂËÕè§m–B£ÍªâRòýüùŒüñ¶M.¿?»SSóöþHJˆPŒeœ¡A(JQ¯îæ`ÏAø&—²ýaR)-ŒŠ¼D-ËXSŠý0Wßôþȵ“þ?ö˜þþ\è¦è°˜Ã¯C¹Ÿ÷üú¹Ô¯ÐòîÔòôŒ>þ¿ŽÞkùh?7·åõvgÜ%ûEŒÍ¯¿¬vÝšzŸ¨îûˆì¿ƒ¤úujкµý¯çòšºô"rû—¹qA£§®ÇãÇHðwû§×Õøë¸aôöûÄ?`â:Ç—„~Bå¸u6Ϫg¾çJ³÷iÝDAþKóSòÍ&ÿòÑbgÐ?^¿ñü?†ê·OÏ\Ü4ý|Z·Uÿ%ƒ`°mô'£¿õfჶjjÜ:cóy?Bùÿ_)úðÔ(<ÉãÞ%¤A@Ø!«áÑËw=ã÷}GÖ–§xðxøŽ\ÐåVˆQúJø^ÀvŸÆCc?o jëSíþ,Í\±]ü‡½¶¥Ö9/oö>gV#,>½¿ŸWzñíçéþR<ûãò+÷7'b’ÎþeÑÎïÆ|+2d¿9ðÎÚxæŠ>pGùþxYBAÜ<}p§½Tc§Å÷~­ˆo¾œzù’:Ÿ¾#[°¨§¯DÌÚX#*QŽò¡9™AŸ5H{0­šeÐWz% ™ ›G’¶`ÏÞ¸›LXÿ’Èl‹úYÊôOîÏ1=mÕÖÛÑz1á¦uÆ7‰ü½·»<ð¯Müü]xâ•#,µJ‘ÖÁ€ÔúíŽR#×Çìã4¶L¹QÄWzïv\=S3$°!ÔKÈä:Fá-@@Cõ&ßƾIéù}A8 î«Þ/ø»´Ãˆ„Ðw»¥ƒÁn6:[p}á „S´x0Õß*V”Epç1”Ú±!ËH(2…eQ=e峈¢rºháܵÑe67ŒKÌPŠÔÇú“ÞóG)Þµ{Båº÷0”#*´Y¢(SÊ<ÁSIDˆKU5JgdÉ™þÀø%½›#,Ç­ñs´û¿Oãî‚2aàó#,€Ž ‡!zŸ#*ÒoŸ[kaä<äþ;WCW÷òô³þ\>&˹_ç»Í°zÔòI&ÇMÞÜú.é}Œ„NÒ{£º¶:ÙŒn ÇŸðu+éÂù;ÁüŸ§×AŸ¨dÂŽ@fƒ|ת,!Ф’¼Ù ¶ÃÕ1Qý&J¥9óáôp¿êˆ=’SÊ>O›Ò6^±†@ûy£²ö˜Ø_`b­áÑœÿËàƒô‘´yÙ>drŸäT~A™œæs”•[r²Á¨9G…?O¥F5¨0Ò¨6Ø©A ©EJ$ݱ!¡Ìn,$U¥EDXéýÛµ,†f®îSVe™ªŽ„CIvGb–Ç`SX æ°Æ£#,2J`B#,YCCt!I± ÕŠØ"²¸äb4#,Ñ^œ³Jß°Y7ˆ`RUT7üô·‹¦¡É¡Œä„½¢Ðž¸­2m:ÄþÏÎ÷[Ñß"/³‘((>Øæ?‡ì)庬 ñf¿Û- Ô–¢ËשÈN¤,8Š!tT¤Y¨¤-06þ|?Ž»qóý¸÷½€Îáìòð"4i[F2@‘ÑÒ¬ÅÛBÒoPc Ø°©J¢L†­Abm6Ì-$•Iþ™Úw‹~nŸâ~ߧBe8ÛðËåñcrÌŠs{ÓEýbf’è7ÞÈßáÑ/‚C' F™õ,Ó,`'9Ú­Õ]yrÝg“ÚñÏ㮺rõ×V¯ÇÃéØ%ãe[>¿«Íœ ÇXÇñèèæ׿é&ñÊJÛÖ¡œÃ@Ùà»á+Æíx%tèVåÝ.Ž$Þnçƒ0¤c]¹ DÜŠ#1˜)F „ ÜÁ”ilÀ‚`,N®³›WM’šÆ1ÕÚ1‰fDÃ3#1ΕE¤> ;ŽŽ‹)ms8$…¡Ã|ñIÚÐ@AFšþ³«X#,<éD³‰:7³YhlbbÉeC…N"G«…Dt„Òdþ#,¢Ö–#1¹‘Tä"Pgj*ˆÂ®´ÊŒp#®²R1ˆ¥u #1Lnó’æÚ˜âV¥¹Ð5ÁfUV§rˆ²Vô”uÔåU9™#,zO€v=<Ñ”½&¬a/øÜβßØdjEböò­ž:aûßêNãÚ5ÇåTSÓ§5ëÃáú螨{~ÇGŸÇ!ö*c#Äó±Cð·B+sþKUØWöVžQA0«““È0H#Æ õëdÚs(¥H®N—zfîx…„!<=ž3»0óXõ…ï¹A|~!dDDéÑä^¹ë§õe®Ã?#,¿—#*á5–ZœâogãüW¿; ÿ?<ÑËCÓâ¾)ðQĺϱŸj"~ƒÂ‘ì«_4ÔŽ0Ví6T>qMˆ4¯Åç.eÒ ª’IfUUk{T}HîК@rX‘²ÄóðïñG?7û'.O :_—Áy„Cð#,åõßcø*D·UŒ:¹y¶¤bø6ÛcD¿çý5QY·«N°†µ[q· "d¦«|ÔLŒª%E%¤Ú`2&X°Ä -£‡-¬j9"Ù@>œ¸ 2i:ÚvËÁíMÕ€¹ ¢Ù6Ò¢å4æÏãþÜ™2‘ß0Ö²óE#1«—§z— ®è_c¯]ƒ½6êòÙî¸xZ¶ü.Šv„áÆf~x0“#1œ2!a.ˆz$=^`©J#*B ¨"Þ»·ss>.Ýܶ¼úµ×½#1ž›c¡B`ÈŽ&0Å(‰x™oÝö“¼˜A(þ’‡8œzU5ÿCíúi¸#pú¸S‘Æå ~9Ò‰çã¹ý#,Aæõ}Þ)žyµz/éN‘¿´xÃïÂu·P ÖÆ@èœ\nc¶+Pƒ¥ò)2ÉÂ1ƒ”+"«Ù0W½ß[H·r{ºejhŒo2yØ}˜éëô½cÖ¦7?Ô"wWœæk›æ<-é…eáž4«POºOËú|Âl ìãðŽü<úS8‹ä7ø“˜úz°hz§“=Ž’¹ N¶‰B_ÉÝlÓoêjÛÃQÁ&SÁH%˜õ;óa¥ry ª¤:#T m"ÉuÏÉN¤_C¸5Úæiªë×o“6ÛÇã\†óÃôf£nMÉ*éKqŒz±µZ$Â-à<¡Ä;²IUBw~ ø-x@kdnfhײònEñ˜×]ã6Å;"h§&“6†)’ŒÃlÞbX±AO…`PwÍUí«*3¼B…ûT!¿I|›?¼Ùf¬)ʧÓp„ Ü>%—àÞÌÕA—#1#,¬:M·c[×Ccç0„$Å',¡ˆã±5˹C:˱°ÁX/›ø‘°þçùË„;$žvû¢;#ÆlïÀÎÌ1n{@a=¬4mÃ~dX0Ù¨!µS®gÉl(b[s‰§C|7Êr7›¢ÀÕŠ)ëo YBùöÎï<4c´k\>¯!rК׆¼Z—`ÝÓÕl˜½J­äVª»É•P]ÃK¨Î•cÇ-ãÑ]‚'…ôÇ+“˜äÉoжÄÄ!ÜÔt—„ÊÊQoùŲnZë]Gè’éÃ\#,#,É¢<#1:²8#1^7òjÿ­ÇâQø~&&•%•`ñ'FÔk#öÜö‚htÍsÅ’VFëÓ²Ào‘k$,(ã9M£5«—Æ‹t©$ÞŠaÉ!â‡Â0š,z[TW½],Û/3¦˜K¢¹·áOŒº[…½•yg >ýåÙëta¹ðºÊŒ\%,éª/¯µ„×x-¬iw „, ìÆ1-¤ÑÅÔb0TX«ßewvW“nï7ú=üÅÚOf#,uÍ`ôcgm´’˜T¸¼´§MIÛÖ°Õl˜Â†×… ÿÎ2bNÃñØ:aÍN¸‰÷«¿wŽêÎ6î$Žfõñó}‡ò‡—øoÍx΄j+';BˆÝåjÜ8é¸yL%ŒŠ%XísâLKsF}Uy[þçýð==ÎG¤²p`º“Áæú¥öš|@BiUSÒ5›yž¶’»Kv~ÔµÇã÷™ÝHÚ bÅz2Ç7óGŠá:jx¤ú|võœÉçú°Œ O‡Ó`DFzŠ#*ãg­›×ÞZW(Ý‹Ž¯è®•É°>3âÚì×€gÁ–ï$΃NýOòÖ’^$™boCÌ LüÖ¢@îêáq›Ÿ|;ƒ=ð:¥{†3”Ò,ð3 MÖ¡å:º9¼L%÷áù/ˆO<´ £‹1#1‚æÈ’À8? ï¾îñ§úé×[ÒÛ° Žù˜l âÜá!`£X#* ;d#áµ@=5Ü )l¶± ±&.2Å•¨rÚP0gnØ41° epé®RØ[•Ä I\æ}aËÙ.l°ò:ÔØ…3ŽèÚN(:„æ÷® ðœþ"ºÜ~RD|²Ñr³¹Áï¨*Kpx¶iÄÓÛ2¥T=çã¬Àµúÿœ´e;#1¹Ë»ý7c„ˆóƒ´#,oÇãK‹SEð/°8Á2f*Ÿ)ŽÙ”?-åžFÈ¥%\2YpF\¹#1Q¹‚U‡ò%¸7l˜¶dv…¢µ,tb]­8ð3ŠÏcÝÏÊûžO¥Ÿ^B“$ÄKÁφ.`è&ã³1CÀ™ßIü‰«j°xæ¡ÝªúÉHB¤…Lƒ ²‰XX¸O6ÆÅ=ûTO×€ä°{Ï|“'õu=[oÁ¥Ý}ÄžbÃx£¿÷3¢:Ï*–"q£(´ø8¶ÞŸÛýj¹f¼ŸEž…Õ¼ôÛ£9õRPå¸é:ã+ºˆ>¾½±”M ¡AÓ„É&¦óÀ²ì¹êŠ$à{#ÝÕøNòkÔ™)'®«Ñ›(îËߪb;;„™‚aÆÎMõŸ*íÒuÃøYÃS@Ýdþ$½õ#†(|_ëçÂ;NQ†:VAZÊŠù.B0[©YP³õ‘ÄElͽ¼»h¥bÐ!JuiÚ”ùGèŠÝ'ŠñY/¢w˜—šßž^I#1µÙóMZ·†I¾ÛËÞÎÖßΰŸ=#,ÎVá™ûµ&§‡(ñ\˜H5Æé,—™HeÔ¡åH¬™ÆE‹2ãÎçó™çÖ¾Å[ãÎ:çPrïŒÂik­§ë%æÄøVFø¹_/.=½}<û#*ryIsšœšÈÉB¶G×¼ã[s4„#,-\ÌÜç›±•º/› /1ÅÄKSk¥wE¶ß&@׋;Zê¾/6û‘F¬w“Õs[oVžô82a·´ŸfJ_ŠÉò»ãIÛªÙ·6øH@¡Áåt8EM†æð€â¤îBÅš½#,ùÝì<<¡ñGûfÂJ—(^M¢ìÚY`ðÍŠ‡©&“ܯöb% O*œ¡açoüæ=.ç)}œr¤ã^­üç:¶ê$sCónuáPbÔ[Û4IDòð>Ÿ¦*î#_Ó3²ƒÎ呱´UÐ"£Nßf‘ãÈ"/à gZh¤Á¹1g•~î Ï­œûñöUF«žJlõR9¢)ÄüÃÊ_.¶ÆèKïF3l>KMÓxÛg|Îé[/rÇ´Zdˆì‹½¶óeÔð²eÝÕÕҽȔbQÙ&ž`àá †÷u óŽ!è×ÛG0æ8? ‰ðáßpðFœ¿)°¥KW~„)l¦/?CdïndM,žûÈðäoÎZC-lŸÆgÇÞ5^-Ç~¸ãF$JˆŸ*xù@cMO:oZƒ#AÉØ• ’"“„õvt7IÁŠ¬üKÇËo ÝkT§¶‡–„ûèÇ0„/+ÑìF!ä÷œb~8ÉáÝÊ°~Û‘ ÎŽï•-Oc4XD3‹”k ÁžIxQodGT{aºåôÉçwI;Ô@…ÅþK=$éŒt6Ù,=×xßlLÒÉàóÐõ¿•:óaµÐ«féÕÏVËÄ3Ýl¦'PÖ’¶¹ÊÇ1ù\òKE)ª|ð‘ñà‡ÔX÷WO#,eÛ÷_i¾1õÊöœ~ŽÐ§·â`æ©—Š+ç×<ânÊ”+d»k+ãFuPUc}X#,—ÇŒ)<Üû.{Í…î·9죥FÀçjË?$Ü],©}ªëÜ轄BÐYC™;m”3#2´Õ¢°Ù­»# þ¶°Ý¸¬k“ížß|óª8˜ÕG»Ë“6붞Téi~•rüî½+ÁÜ ¼Œ¼Ô¼è¶Q{ó,û×O sÆ`Ùâmp'Bœpša«TEE&’XìÈÇ^<´Jª¼oó¢9%¸qp™':FUÊxÉÐ&p`u½©wg\gÆR£¤ `è(€D²#tQ†üµ@E‡ç<¤ñ‹YRÙ#*ýº,¯†,A£fŒNómÂo“·aµš¸p–V #1Ö•ɤ«Š‡½Ý+AGX#èŒmB‘:ÈãA++à­´®·'Éd¥k'0ðo¥¾Á”¬/Ul[{rµÛF–£ÚÉVíw]¢_‰…ã¡óÞÙU«…ÃÅ=ÖóÚsŠ²%ë™T:…ó˜¬K?Ž¯c¯¸º† ¼fP¨Š#‘~‡oú\Û°ßWˆÔ-LV¨XFÊe¹î¶<Üa¶ Òè½û0¹öBó9hÁÍxŠ†renh7NMh6Özéª*üô9õƒ‰²gbÆ­¯æ9螢Ò*ûKߘ¦ü` Ôék3ŒlɉÒŽq<¿eÖûg¦­ÞßÔý?#,÷j¢É>Ñ°ìóR sÒdÉ×å‰5gHÇkߟ>v8µù¨m3¯öpíÁÜr•œ?ÞOé{Ï—YÀwûLÆ9œïtZ^cªç梎x‹Ð-ß’`µŽ1Øã·Ý€ßâ»ËÅ/ÁEVú2ÉÙÊÈT†I*›ÃÖV¥Dr§'#1KP`ßÕ‡ŒÞ•rɤ'—†®´ü¿g•Ö‰žUâUð°êŸëŽTñæºnšùý[ÂB(HT{¯×Š+“ŸÃwƒ‰àðàG‡ø¬È$uÙ£¸u®B­*£è©Ýî»jÚUõ‡;'3øâàãÀ†ž—OÐè_Ý¥‰Êv=ñt%{¨±­ëm«oœ^ë(·[¹Îu,æXØõ.GtC4ë²³ëóËÞ5)ªc==ž)È÷ç³·N:aÎq5QöÈU=ý±fúÁ»y··I™L?ßÉÑs^x—úòj|ÛxÐuéˆç¶7Úw±¬¸9ò“à2ˆ‘Rx›¦Škh+ª—»j­ª%0$þ9<—zzÖ{ñstÞjGLA#,Ä:D&”/¯Ù»>»Ãe{Qa¦÷|^Õsã©~ÐZ^ÂiJ­áÝwQaê[›:y¿œ—ù=yº“žÙ”ƒñ¯Ñ#,Ôóíã1ß®¥±€ÔTØ„ì€Òç‹à©/-ŒèÅl¿¦#,|2æyŠ"MìiLTh¨´UÀó°Ú]UQi…Òƒ˜‘ QåŠkz@ûû©åŽß¦áƒã*/W÷wj“;Î¥©(¶Ë›êÐ9M"Ìe¥ï/ƒ~s>ÓžùË jjUL$°ÛË…xm‚ÅI”§G%ÐWó#1ÇéìjN#(þVä<¤LLÞC‘ÞÕõÖ2€J>ÂåÀt¾b·´êæ”ɆŒ];#1ß¹c[îUOàyÈ}#é1xõÝøx0èöóÔ¢Ƕ][¡×jŽŒf~´y¯1&£Ž•N½‹\¤ß²!À\@ð”Èó©wK´#1  XÝ}ðŠq)ñÚ p¯"Ä ¼Û6hð]ŽêgnÔ4½óæ¶É·T^g5tM¢ðºáô»/Z÷^Èm#**”¨Üþù‹fªëæIY¡³fÖý{NŒGÏ•5œ¢"XC¹<…(Öß#1üÕ¡Ê›Y^LùÿÄÅøÛÈi°NG”—c‹£íŸæº…´‰£Q¤É/î|ïÙ­u³f}²T…æVÈuk¢%]»…̆󌖇d{ÕÈ8×—S…’N ›æ0g®W«™íð=ÇDº%U˜sLoÁ·:N.˜±(]Ôj%9Vh鵦l ú{«u‚Òó=Øu×7sâ‡ZBSãÒ|9±@u啕jÞ ì®"ŠÒuKØ=^¦Çˆ»Ñì]–mœ©#*;Èk_­Ö?ÅúÆèÒƒ¾ssÌ×yWâì"tÜЊɱ_‹8Øû Î®JÁ`QŽÂ l÷«#1IƒSeÉñpƒeåÅ#1#1ú;èÀdv¹@³=#$^Ç.Ýé÷?×_dÜóåžÔzzUY¿™e{PJŒØ¹CÆ×ò¤!9º×BË+p,÷zÖµ2¤ÎêÙn@÷á}+*ôªqƒöyÚbûßãsLNr`¤s8zÏŠ]>ž©:(ÛÌ Pt™EKÇŒA€ýŠC@ªªBž£NÏÈk¾r˜BWzâÎm^§c¦pH”(EïVç—SlOŠYtÊŠWÞç$ÏsM×!º%NA3þ—Uù¸C6Á_\F»2Üy·Ó“YDcœ™çˆSËÎý%ä€VÅT$½Û€¼dº\¹:ÿ £¬EXèÔÖ™ôCÁh{Z]ÕV²îpzûW1D¬…*„¸¡÷ɺ5(–e{ËRBaãÞš³ùRB#1n:sÙ ÄŸ7²QÛšè„wÌk/òs`ÕKJ à ©Ais‘>1ÜCt=õEžÀ’Ž9ùsÈ_$hÓ¤V”é஌ٖaU܈$L¾û#ƒæD÷¿šÕ骺,»Ç*Ìšs·‹™ËûaØÓüf7MH‚<3]–ÌÛqàsߧØÜ‘0>ù’gÆýTÝaý×·^[Ö]#Ñzzx+ï‹ì.ëÈM½>±3Ìf)·(â`„"Ô`“¬ZÒ3sPÚ-™±'Ê6É&sÅlC68é@â´ÌŠˆ·ÿOír»Ø`žÁó®Ù¿¢ËE ¶Å«”4½ä6úI„CŠòŸ,8Ršg1m°æèczV, CŒüàÅN”`\#ÂáLÃü¥£ßGI=¢¿oM#»»Ô,y¦íøê ^#1ºÍgÆnÝ®ŒPßKãÎ[×å’/ÃÕ¹FµÖqá= ’‘ÖÖB©Giž}¼z¯®Žªyg#×ì’Û£ã‰LéÆ¢¹¸xÕ¼¹õô~Î9ž×€â-¢lhAº·t þãe0pˆÞœƒêïÍ¿Ì’Îú.náà#1,ò†ÍñŒj„ª÷9~qD€¢­ bÐY^êéïÒ$HL𕻟¡°ŒN¼Þ±ÐçŠf¢éÍî׃P]tVÒʱ¢¯ƒ¢âŸ$h§Œ«[pxA)³NTÿ†se‡žê gÔÃMìîùГ=µ£¿&o[Âû+ãÓÍÈU‚b-Š\sƒ ¯Û×3÷7 KŽ|QÌz@nêÚnŠcâíè@ÙèíNúsG©ÕЃiúǯϛ7^ðZEõŸ>×ëoGΔ3l­\ø§8š”‘-ãžžà«Wˆtàètp?ÄæÜÙŠˆÛ=pPF+ Ë”s‚’Ĺw:ô®!zMªÙˆññ5-‘/sš¡#û \xuCTÜœˆA¿ƒçeÔŠ}Q”Z—ƒ;@Ê@G(8HW #žw˜;¶w!íé#1Óg¯kK‚´Ö§YímÁ4 ໸Îõ4¦Ž×/Ö®*©z=rIs>•×Ãd¶8¢ð¾ìæ|«¯—,p‚ÜïÑ}Î9êuÔ"Ó¸SÁ+ÂÚÆ)iíJ/ŒUß™#,ê›;,çþD[’®"LI©f“Ñsâü·¬70,*øG‹ÁRîÝû7Hõ[¿jô€ÛŸ-=G !”#1*zN±¬÷ëN­zôñÄ7¦£mzSšLî3 Çd`@½¾«€ª¶4ìA¿únÙÓp#1·èݪÄ~=–ÖÛGZ š§3MDf\È¥¥©­#W»Äùq^Ñ«z‡‚ ¤['lvMï#* <¡_:©â©ÙQ!&іؽÛ>L$5éOxk]^£ñ6b ¹•¦{«€xr„l=Ûþ[Ð|]kÁjÏÞàGç`pí¬·½#,ÁTŽ»U´©>íIუ7kS±ü„ë;h–†j,/y©Ø-xó9MT_ -9d¢ƒ>÷êóðžGŽ^$ÌÙäõöÙ³Õwé¥ÒÐ#14» ã¯-¹oŸ?´ü'¹6é(ýÃÌ PÜ#iGAI@¯^ñœÝ‘#*å­P3Ä›-«’Y“HÑ$³£­Œå ã\ÄJ·l,1(ò³T#,œraƒê¦Âf ?_¸¯”kÌÇݧ|Ð@x‚åú<·×ïîð'|O³—_Ù>R–•ðsr(#*`P§ÃҠޟ΋­Ïa°sOw!öÉò“VŽÔP0 =!êñãS8¡ <¦À^i‚‰ü_eq*+ãWyl.™/ï9ÀÞø•¯ðÒ¹×rØ’Ò~nÙ_ÁFĤZ“l›­¢Úºêù_Öü«óâq2"Z"@út Ë0›Êþ+bFmp–ߌù\ÏÇZþ˜æ³ç&Zù…á$dV,#1 Q© æ&©ÙÃÐ^¯NÃõÛaÒa:dõùüŒG•;UólåÙhý©æÌíL6l+QÊI•´ªöÀ§ï|©0dûÃüÿoÎ8ÜQ¨Z=÷B÷ØH‡ê®Éù_Ü9f"`ÄD•˜«ñû§ó‚ʦ#1¡Å!Q¤¨Ü®‡øOWûüN_‰öE(69[õ"´-¿õI5îè#*èÜMÏi—>b´`£Ø@Rã/PwV-Ý2_ÛówÇ„>E-TxT^;×VñÌÚôp]v×à#,Üœ¼†Óø°·îò²}¤ õXÜ ŽŒÆØê©bK»¥)±v´‡?œRåPyü´ããÜÃû'Èþ|\}Ri$ì6’XeøH|ñ“‰"~¯Ô©¡ýj!Š#,K¤šÍ\ÉéÍ×'BÏÈCÒêh%?¯~^ÔõNo•Q^ U™oA£Xuúþuýz~/¸•s<­7M‰açVNŽvP—¯êvYÇÕº.2ŽÐÁ“ö3¹­“Ôj2l…î2è樈yc% 3t4ìÿGx]ë’…uò–A¿}Ž|¼­––þ>÷Þ‡Y˜%Œ¡G(*,Šgï©Íˆjü/Õ>ô'¥2”Àåtºÿﶸ#*N£:^pF¢zµÒá;¢`JÖq.jQžæE2À_+™¡i:ãP#,E©[4…á`s Ø‘GA(,õZuQÜGUµ%ƒÛg•#*û"@6Fþ®zûö™;]-a?¢PìŠp'£ù±c›«!/y4eŸ7ÊÊ·?:+¢¥»P¥kçZ!‚vFÓq?% ùøÄÇÃÓMw0mÀÌ`LÒQP¨,xÞ°Ç ’(ròø±‚?–±”n>ùðèsı(Êg:ûñx¸Å7B8üíÍ"† ’“'}è+mfö[•÷Ö{n/®¶½…ï”ë1Ýg8í€çY5;*†#1NI¢P>²˜aÝÿ)Û¡o˜G}ûnéÅ+« *ž¢ÂÜ`ë±!#*™”@Ä2…Ðh ƒmêºú#eä„Š¨@ȱŽq`æá|Ež»F$ó×m/×Ë×A€˜Áä<ôJ“G"§±‘yäð1pEùQLJirÎ=›²Aoé ·dk™|TÈZ¯k/ÏÈ-@&œ9ô‡„§ ·%p*·œñÔëH (tŽX°º0Á&#*(fQ¥ÀEÄÚôÎ8ºKXHJæl•ÃD‘.#*¼¬]6ˆÿggˆgˆ#@ÍÎ@áåe#,}Û\/3ä4Œfôvy¾DÙy:F¬f,Iùî}Êäàó¯†ó‡SÙuó4œñÙ!h˜&w¡oÀªåÏI´Ú ›}òˆŠ¥¦¾”›‘níµ™àá iÉÁõTÆií’8qªH*H-ãÉÞt,¹?_Ónt>Ôjõ¤vžš†haXK‰Ê+¿úÙ«,Ž<<ƒvïm|Í![˷εÐBË{sœyuÁxÉX;¥=xÒø+–çÆcÙàÛËhîs—£sb¸›”.è_ÝïÓ&Ol\íG‹EîÑÍ{—l5Çn~š+ÄA©®µîADŒ.NFÙ¸n;ÄE,®L”á1Û#,Ò“„©H°;²aŒ pGÍ09ÖLršœÍÃüÖúú]õÛ×^h8(úù÷OÖ;#ðÕ¶ÊFT¼¸Ø¡aËÂt^hP9±äÃãÇ-ÑÆv±—ZÝQóïœä’ ÷œöEŽ´A)‚ö8ÉôG5¨„¨°\9ùs(ÍrÝ_d’Ž½:Ñ©Ú ùbÁz'§ÍñµCû]ˆ§Ã#,>Y,±74”–ˆ—ô"¼°¼Sɸe+ÕÌw´9®|y¼ôe.Ÿf%Šîá +Ýpe2Èâ©û´Æ ¾tž„¸qpÁ#*¶€Q¥êCHB^›Üï×~âðî'~Ì´Õ³r~w)UJ±ûR¢œ!ÁÄ828UÖjàug ¬f¡{7§¤ ‘çºüN@5ߌ±>Ì\bܘ+¦]L:E(™í£Ž!¼üe£Ùª8‘KÔ<×°(¸§'E¤;•Z ÛÇw`Ê0t“aÔåÇÊx`Y#1qR—º|Ä=q©óвn‰P=êãT) %¼uŽf­÷íH¢æ¶r]÷íêJAŽ1bIâ¬7y)@ÂV-´­@b~ÍSi|‰•"„ªc‚óç8PptÛ1•i/:£‡ªòìõåû÷‡tø~Îx‡·ØlÂ(âÂZg¬z×ÅÖãôJÂP`\ª›MÇÑÄbáát£¡`(.ß#,d)G3×·PçåM‘Ö.·˜ÜCŽŠ£ µsÞkÄ]aõäé¦<©><¬½RôvD¦s=¼§»Á}•Éˆ€j¹Ý¥§¬L0›Ý$ݾT“æÚdéP[G>-ñ·ö¸8×J¶ ç:Î ·´ÆÝ!¹:ç`Ÿa%A"͇jŒ/Böši½+&ï²û’ˆ kOèÈ©$( ‡g!2;Წóot •¸o)Wц!åiOñ¾ —Õ#*Ÿ#N‡*_Ö™Á4ú]Lˆ‚ùÝ+Y‘¶äM1b‹tбÖ÷½ösîãÊŽ?n†e÷Ø|Ï ¾›3ÒgpAñÜ{ùʱwqÍC¨ç·aC†6{JJÅMšQi"4ؘuëã»_FtÆvä×C<´öà,r¾ÃÖ …J=B€bƒÜ ÆDiÙÙ|Ò”’žÂ;êF¼“G“¦‰[¿Vë\à 6ð5kÇ›tdb#Š=ð7Bš#1©—Ÿ7Ø«BJzÿu@¤§£»áßÓ3Q5I‡þ·ú’‚ÑTQY‹JVíÝ¿a;v¯<ò¼ÌK•©UýÿóÞö¾ÛTÓ<’€5þÏ–]q~º¨Dÿ{¬bŒBí>è¯ì÷ú«MQ×ÕAUSÏ`ÿ¾¥ùÉÕçÄòÊpæ}¾)xãÂHzqárF¯K„¯±^-L¿›5·¶þÞ€ÿiü¿Êøï#,ßi£ù¾Ï®Ø<‡÷mO#*ô駎†#*Šy´*|Î[JG¤#1ùzöq(Mr«œ¼iuÎLæwnÔÙ CñaP>Yâ„/õ£ƒ*$ym®d5béµn–~n§F:Þ:9Ž¿^»ã^¢"p…çÍñë–/ãTå#1MìNÿ.¼j&9™Ø·gªÃ•Ð018Š€¤…ì…GÀª7Ò¦ˆvœ{»ÕÛ1êÙª•†DafÞDÆ8N8–™ð§€}Ò¨®)¨^¼0`,Ì#,:\’ »P=é—¤÷wZ÷…ê\õ0Á“ƒIiB®¼X#‘ÛÀü܈ÀZ#*QøÛÔ)t 9ÆÂ<_÷Nfɬš^­ë¦“d^ÈÃÝú,<7Pç<ó%¬b+¢D’OˆzK5 |pøü>Ú¨_§×gùý½;qõMá´>D¢û3–ù?çÔ­½^ÏëCÂ?ÙÒÅÝÅŽ?½5 ÿšÅù‡—ñ;Ë–pÇ©Ù”hd"Ô@„2%YÚ Xt@äBÌ=¬TL ‡\G&úÛ9f–dBÜ€‹@ë…Ž _P0BÌ&¶ÊXÛ=2…nÍ5”–3 ¤‚\W)J7h,ˆ…#,\¡37X_“€Â6#*ƪP#dÔ”i´]Âéc2±˜ƒ¶,‰aÂD°©Œ)iŒh0‚:¼¡Hr·”€ –)ÀhCÐIõwªŸí·_ŽÿPôèT·.,€8–wIžÓº•±<½òóäËùqWû2hp>S¥ÁrÿM ü‹q§úz<KÍ^i¨,àvduj¯©0ïŸPü׆ý/õ¿®;Š…ëiŒŒÂ-$-®õª8âÃ!õá:zóÇöô¾—) ]ê)øº§´/ÉÍç:É+MnGð圀l o¥è^ë:×OBGGB¸¶ªƒ’ˆ§¼“”€v¦ Ø*…c)’‰Ub è'ÙÉÂ"o^·rjRKrš'~rQz¿g®—÷×ׯ{Jã®2¯ã' Ú‹9i˜Sl0>Zn•Ø–qQÀ\Õ¨Á«‰”•¹D­Ú2‚f¸¸¶TÂRUV\½ìº¨nÜͪ5YCÍýî=O‹LVÌþqàÝŸ¡ë0Ø<ŽÊŠ®¯ß/0KãÍÙ1½SØî”}èx3Øó£ÒZÓDñ/¸þÉ­5Å𱟠j°þ`Ö}ö ³h_ðî6%uy†Aúà‰íÎÏãÇy`;¼U£ßuÉbÍFÚ)šl²´ŒD¤^öúžgfEŽFŠª¤ieIc–~9¸#,ÏqÊÍ[M¶hïuƒ´Üe`‘vÄ5h^ÊÜfM·PÈ‚¾qR &&6I#*Œðd„P!(§´²+î€e“*iòÇ#,»wÔTó>7S¤“šA,ƒ¤ˆ²,` €v# h¶N¨!ÇÀ¼ï’™«†SÙã dØðn,žGžÁ ž™ ‹;¹4hõC•pj¶ÅQš$‘–óÅRJK_#1…&IÏ#+Ýõ;¶¯ÃeIå ˜Gvl|³šÂŸ£µð9¶¥Ö¯¢½û¦·6·SkEBllîµ½õkÏï/qch+^òéF—v– ÎÚ‚jé28[=´;2ÏÎç—#*0t ª­xuÀF"¬.Mªy(Èv2XƒÍ4¨Úg!„&I©«€ž+µ³åV˜íÊÆE%B"lÔ ÊMúü8ú¶W|?gcÛ`k¦§|#,dFÛwÉn¸Èß1(|«Æ’Ò…—I#1ƒl6#*³üÄ÷ü9cžîZ;ŽœÃpn§PðŒbIˆÑí ÛaHóHƒžÛÅn•1V$‡ ñ&¼PcÆŒ*¨´Â™hDJwôÑÒ¬é“Dº%+$RÊU19võ×í™nñ×;rÅ`°†D6°xoÃé” ûÏ[DÔ€Q¶=ô{›ì¿N+ƒ©ÇØQô²ƒ(Šš*¼IãîADx¡AUé1‹¶®K•Ô¸g¯/7vj»ºRK] ˜Ï]¨Ô÷üâ=í)òs„å+vç¶d5µ­Ò.Ò‹ÖVî¼|u¦ZÏSî—%Fá<öS²¡D g6О’¦‰_:’PÀ#,bÆÏ,àÝ`A‘w(NCoœu‰ š<ŽðÃ;¸œ_$Ož8½M|èí¦Íûu få3g`ú3¥Ï![˜*s)•½@îï#áŒÃc8Â0„‘‡°?Îù8ñš±Ï—źpÜ“ꌜˆ›¸FÌ•Ä…+2XL&‘4QèÕ“ž4¨ä`¹‘°1šQ.ž¹¹#åÞØ¼²ï»bÖ4î|8†‡·ˆCœ¿•wjºu¨\²p¥ÒŽŠ¯É©†ßÛÁµÏxeɯVWG06 @†Ým#,üFŠ#,tëé§[é˜#,’hÇJ| ƒ#*±ëÄÃìݳ¼]•èåîöù<»Žçw9wÚ}µxѺÍbˆ<* ˆZvÝF(]/•RÄ[ÍÓbă zÐyþqÆ“½;7”¤Çxx¤\ÞÀÐÂØO‡ÍÅͲ.W]G8¥ÑºQUÛ=½Þz÷gED-*Ç#*B­ ¬ ªI#*ë€&°]ý‡žjäÆ#,Þ×]¡<Ò‰¢€ûlÊß Ù)!+;dv¨µsÛ!ŠR@ã•ßý’[ ¿-ŒITêCŸ\ßgùÓ8ÂêûBóLVò›¸ÞMH…Ì#,;׌núÙöX©qQ2aØæd±q'¡Ÿ¢`;ÇŸ\´»§Õ~ÐÂá:@ëØØÀc †pˆÄ4]3‰Ð©¸™#ÝEP«[-¼»²†$=zrPQAeÃ:“…n³ £´xµR@è!N¯owÚÉMÒlèMˆˆŠ ÃºŽÞÒ¡”0bÔ»!²{öE@êŒË3a#,@ï <_‰í8]v…`g*rˆô ÂEÙtèòF–ë-dó´3­rÖ·\#, °ÐrØêaÕ¡ È»mrUÐ`-ò»®úUx´Œ¢h´žší²i2e67®­ð1kÓkï/¥×¾m±R¡T¦2k‹K;în|Î…©x8œ 7FIs”5#*Úì@ñLÂwï÷cžU‘{95Æn«IyœzbâŸmwݨý盜u™CŇ¥‘VCGÐv}›jƺêù"%h¡#* |â€ËáÇF®`S±F¦‹‡"`~hVEèŠzoC‘*JÕ#1ÔNÌ^ʯ,ðýÏÑ feDøØŸVýuO Ë ÚöY|aœRãÆ‹[—vcÂœê³&¨˜ü)¸KÃn³Æþ#*Í.ˆùæÌ<ø§áIPæa€§Õ¿oÍ•Ò>Gh®yÇ|'_¦coA›ßðûâ6¶téêʸû#TdµRco„×èšÐa! wØÝþŠ+õuÔ½ÚUýÿâPÒ%@’H)#,QrÂÓ>ÊþßçwÏü7Ù✼wùbÚ²ÛÃù¬éûáHoÙPÀaZO®RSÑËhУӜ@ß7‰ýÕá"zˆâ€?y]xY¢n;ð€""k]$0@?ðñúõü?»ñ‘?‘„Ø/üÛ#1êw¼óŸe#1yx¿‰«ÃœŸx¯õµ¼[~¯/µ}W¶*Oyîôõ­Óû`DQÿÄ#*QLMûˆ÷~µ¤:¥¨Èú4f ¸ÿO¦Kþ<?9X@° ‚€ëR:'¾Ý™Ú‡?‚ÞŸ$¼½Ç:B #ºaÑX4Ï•\ZHO@´Nb{­ý< Ò?ÎFß}ÿÜ1¬`Ïïlv&'º¬ÊWðfgØæmlJyг¯˜Ð¯§ÅdJ½HˆW:î°¾,ü¯Ü‰‡q>#1‚H!’Œ/ÞkùeàOÛËH@#ëBšQÝ£ w?ªîÒqp{ºŸ.Ɉ'ÅÐSk—+Çž¿ª½ÒˆêØ·0FœóRåmì#*€U®UðükÞ1ýûÑõÛÝÅà;òØ!ísEz÷o§’¶ÇÄOñ‘ê\_ðK C“Ö¦.QÀ‡DáÕø~êÌ_–®V:¾¿Ríú}>ÏZ¨zæ÷ÅIœY7ßëú>{o.8F!~˾7Qž#* çHff.×ëÀì|ûFÈ åpë×æO7*fŠ0ù´|8êË~¶QP¾]Õluã}bvóÐôÁNÈÙÙ@{ûÊÖtq÷KáèÛ»¢CÜ0±<½#1íWlêë¬#*…ªZl Ò£Èð²ò­Ʊ¡•Œ,KÒ¨Z»òǯ*pz÷ã<£‘ò€#*\RST E!=ß'3ïxÜ+Ç—N6§Ç˜³ Ï››ðénÞjj½&ªfjQOÆ ~•âO’܆?6Ø“t•D×ò1~ÊpO¾ÜaÉ×Ãø}—á×à 촄^‰­½*‚ÖAíÒÑ¢³•žJ3"Œ'ÓY¾¦$“&3éÙ[HI$Š °tÄÑ öd1/‘Ëg}¹qáíò4ë¾eHHH„;¥Ì¥ÒuÊ®{í¹Š´^æðÂ2æñbˆ$fçâòÒÉ‹UlÖý˜ÅˆDDŒLBÕõäЄ2WEÂîn½H<€•>Çï>ÏÌz³ÌÌ»øëÔöéÌxöðüëæªÊñ'.ù‡KÀÌkÙ·më™~×UIÚœÓN§…™#*¤ê+çŠ#*âÚf‹zø`Æ?Ã_µ Ïñ}ó&x_pD~§ë—w¸Ä¹™šm®%9™«~;ŸÄlÙÅÿ“nwÉE€°xðÓê×ÓŽ~#*A#1ˆ¯ä€ÝµÜ®‡Ý»Á1éã¶Ab@Çr¢¶þNc®Ë¼Âüò³v—:1ú8í)ÄN¶à9¾êQ‘<6#*Á0oí¢[L½9}Ë¢’Gš:Þ¯8º¤ý½ïNŠð½ûVrýŸL•}å¡‹ È™˜qѯôZkV<—Ú½ñŸç!êg1·;í¿ñ•òU7siˆ¯÷Û‰p‡ªxzdïv:JWöI©-.Ÿˆï¦Þýöòod:÷üþË!â¬Ñà«sÃ@¾€m7¿•íÂÉtÛÄN¤1µYŽ…T"x‡KuèXêI¥–NÌø>MÂK™œô*º¢ŒZ±#1ò½%S‚Mø(åG–⎴,xÂÆPèL*3(#,ßã9ÇÎü®9éù8ùðv66¯-Šâ°Œ#*Sræ«é‡_ǃp^žHÿFÊ­žx8çÇ9¯òAPtƒÊj‰Ç½º¹»ƒh%ê>Ã@AJäXË°±·ÊÔ°*» ß]¹iÿ¡á2·K+१…tò™ÄŽLþ½TnÈëîr+´9±8¼Ót!×O8AlñìcHH*Â3k%mÊáåoó+@Ûk 'yºèEÒM°Imz¦Æ_ºN9ÎÒά¹‹nŠ²<,4ÅhÜŽ@è¥wçvC*ñõâ{éÅsšNî¶~âS#1ºÓy÷ßYјòÁ<óƒ1¬•œœùÅ~.LOˆzûë1Í槞<âŽÝuÏ…g]îuOPcßëŒÓcŸE7ãå˜<<ó!Ðuç§yÏu«É§?<@ 1½™å N$%c?d¶_12I$™œ 5ó`oUÒõF +ÞT³•9ô0^ýDkW9ö@L Cä?jÀ 0§uCÓoÄpP®¥h îÔö•AzÁrfé ìÏÍJ#ÔiŸ1~TRHï¶PG€ð®`•s|w¯7™¾oG#1Òe.˜ühÞÐußH[ˆyʉö¼ï˜øqímØLSˆåÎ)×îš9SGýCL¢œÔH¡%÷žZïN£ÃƒZ¤ï飌ð^ﶣImœÏozv"ž·/Š!Ç_ÑÛžh™œ>Igéíôƒï¡Ò_Ó#1駆áüùäÛ¿gˆ¹›ôï)y¬ü‘1ÛYv ÷ðΡÝmþëâ°âéÏ5Ç;Ï„è¶;S¬8P#1#¬“Ãé/БŒ¿ÅÜSm©Áw—tî‹sÆ \÷iò5œSŒ<#1‡b=û.™èÒ®[#1 DqD QJY¥Ÿ<Œÿ*šs ð’‹ð—?žbq—ÃfeWg"90ûýsŠë¸)ÊŒŸÓ¬Ïç9ío–R×j=µìAÒ&1ðE øqÎ#1hNÅ€#ÂЮÕÕ ž°"˜êµÓäqd¢©½³°»§C^ûÕGª1#,©W>)˜Ë5½Ó¡g³ôPv'lh×z_ÕÏ:ûk"bQ*E×tln4¤¨fBî/W@‘W*)Q„þwEOíE)ðü.‘ÃDïË‚ëîÇ‘Yòû¡ã%»Îrû}²›#ã‚ôœ†–´ò Û#,Êß„=^ÜnÅú ú>{í{¦lû*ÍsâDZ~ÖIÙÞì~O†®q†÷4b+2Y–z—];µåÝ7}ëçMÏݾH˜#ƒçu{Ší›ï:9§+𭣡»ò¶»qþ—q4Ãù_[Ž½ü-öûîƒg´ŠTÛÖ×TdX†»Fç#1 5e>îž\ù›`¼JÚä(¾#ÖÎB¾?Gb1é™{ÜOɘ½ËGaò”`ìD‹Ü#1ôªk(þ¶‘ìD£ÎÕZ/kÓÆ¡e"+DzGàÛ¦££#Dqûh#*¸%³lϽùú<Àmås†6ÎÓ–y]{ÎV‹­}Yáô† ¹ü®s`}¿N¶@ÝÑ=^Uúƒ IL »Íè̉ÁÚMܯžÔ[ߥXè{ö¾k¯ˆ†-mçìüŠç»†ìŸ±ÔuÞá’—q2ñð³Úc£†ñÝÀcr=Éó/nº:˜Iœ<=l4E…T(— ¨àÃJøN‰¬>ÅSÜ¡A#*“ÞÈ`×w–%Œ1óø|×#,°ã,ú³F1®7fø08ª¦ÍÀ Zଢj®u¼°…ñ®‰ÑOñ ÷Áxr[ÎsIµ \ôÜtN†üÎŽÏ„Éü­JÏ1…úð8W§mÿ¥òƒœ;éøŽ"~Ç`Û iKˆ»eïAxüb¿T;ò¥Ê$#«×CëÇñœ£ÆûAóAƒÝˆÔ»²L8;oˆlÐü8!CÃ-€©n²¡‚âÁcÒž6O \G’Þ§uôz9ù^ž'¯„™¤÷1z³ÚM•"´.¬G2KûÎ vÖ¸ ¤‹«”>üŸ}ö§Ôd;7©IÉ> = ¼…ìGC9B¬ÒäDõ3 òaÞå4d-'© Řâ±H[I·Ã²Ï3©w+w èC)Ex¨êT°lÕÎ&!@P®z¿v;Žr‘÷z½V&Ia¯NŠ )†Å¢€#*P+éA#*¼”«%bˆHxA^ñŒ•E•/[Æä TuUb"bUCÙ#*4µ"5çÙ»¾K'á{jݘPzü’«ìæðå`âùGÜT¤-ºdguAX¯|¾Ù“#,ñKÉçgÂ!ú¬"g¬´‹Â<¢HO2ÎC~˜ï$ò~^šc)ûÆ×ÍŒG;#*0ŸÍéü>±êòafµpþäí~ëÈX‹ìaxbŠ†=6{ïke…FñEîä~ùƒgãíþC #_£Š{¹;Dͪ0$;à~{‡õsÿ)Ã"‘cÀ¤ý¤P,}œ<úî<~ƒuJ*ÿAMþ’8§êŠk-iFù?ºWôµþšlþÓú‹¡ôû>PPy§-WC‰íÉ#1úÿ´ÿ!þ'#,5Kÿ®r¹#*ö À‡èÑëöŸó¼Ãù¾ßØ\ïþ)E´…§ûƲŠ|œ½?Ê#,¼Þ;´#*ž?ÿ>dÕØ<ñùn³ÚíÞ•åËê‚^ô‰½ÃºYõ#,½ŠçÛôþÏ~}`) 1é ¤tt† Ž#Ço°ê}\ùÁiœ¢Sñ]²š¿¨*DR‰‰gƃìë #*#1 T‚‰…ÃKÚ·X„#16ÕH.>aÌ>h ’Où•cDF!óûÂD}¨~žÏŠ\ÛtóêzE€s#,`}¡Qb›ÿ2ËM„DfküY_3Øö?Êb¸]ß'ö©J#1SÆÂûßõüoVwë^Ð5};ćÝ-:íÖ<™.’Ÿ!ˆÈylp`9ÊŒH¶‹“¹î{]8ð­“í8ùþi$ Á#*‘¾‹ã:z0.ˆ0}×jÚ¤bW#n“X0ÚW2ò@é}4í|¾Ü»“³Ä8§*‰ãd¹ÙI;ë̽$¿½ÏV}Úu}Ÿ2¢zÈ9ŒÇh¶¹BD”è"Bjƒ+1&>Oãî¥^'sr#ˆ #*XÃÖ˖Ĩ(vv|0¸€Jjo<Od;}œZx³Ë2çòËH†7•í¢Š û PE¢|Õ¾ù íUö)>Sæ׋s#,ÌÈ,(.T ˆ©²Dò÷ $bF'm†©§<´¹,,`bf²› ]ó¹Û™D5K±'ð§ í„âoŒó&¿#1Sn˜ô |u¢qìîpn=@œ®Ë_QYÑ×Â~èÍ'q>D5JXG‚éå5W5×Þ÷gÁ,–ÊQ­zMcR*azÊ|ñÑ'ôö¶Â`圛åÞ ŽŸ§éæÊ#,#íYÍñj‡~[–æi›k+™¯'ˆÙðfNÇsŽêá*~fv9Ÿn£‡× ê gEùrð‘ËR¹%ŽÀÒ}nè=¦¥W°:ù0­½üñ;‡èÀÈc÷€ý[Ê(J“ w>ˆéM±”f )<1ù Æ‡Ž*ê…‰J€íëT-o¥Ý`Ó5M¡´¢8_äÍáÕPÓéM\ôõ/5œ^áf;ƒ· {$PkËâçŸ.:ƒjžBøE³±úbù9Bƒº²•Y·™ …òÓåÐõLÃ(Õemº)w¤‹c@2¸<Êwˆª’D#4Œ J’P¢©/ úq¨ucqQvæ[«bÊSN™ÂDæaÚ~þ³Ó¯F,ïû³±.ðGK8Sw£´y1Ñ-l²4z>W¸ùBG3¨3Ù»Ý8dVÜíxÄÖöz\æ!†E%1¬G¢>9i?OÝk|Å9‘ðE#,AÃëó‹:8ؼxs×í{ZCkNØirä©ž‘ã—]ô‘þý\¡·¥#1ÑÓsŠt"íÌ}òÄG‹ç~¬rx¸Ü³ŽÇõ€˜µÄÞ¦¢òvÏzO 43¼#,$‘ÒJLÒ,ûòSO/÷®Buö–,ébæßµÓ$ྒྷÃ]3¥Ïµ9•:ó°î–V ¢ô+PSAÛè¥óýŸ(¤µ¼N·#,‚àGšávcL…¡¦ÛÚ¾ªÞ=[ªpy-Qc¶ÑXôz4ucu)ˆrj-©s›1ì./Ó#*®Prö9¤¡ÏTXŽY¸H^ôÓ°PòÖ~•Zª¨Äœ0€%9†–dó^“õW½<žmwë’XÃ#1À¨<.‡„Ù'—ìÖR€¡f~ÏŠÁâZŠ"Q€T¥÷~Ÿo¬Ú¨øvp4>´vÔÊ¢ÅU÷òé4–Žé'«Á³mþamË¢×i!QÈoÐæp¥_†¼Ž~Odzî„[íÚÏÕgíýM;Þ‘Ñ'Ž#,·™sª¶|…ׄ˜¢u#*£µ¯¼‚J"sl‘ä-É„g¶a:ü°#]6 uï ²C'Ù 7N#*[€‡màðË) aÁ6 h[4Åw¯§ðÚÀ>ÀW¶Äí#&œv#«­“²^j 5bíå~Ü·ßàÓuG‰×þ÷H ©˜\û{ÚUR&ƒ‘nF½–,¥Õ8KEáQHŠJׇ;% «é{ì/x=6«bþŽ~IAóÅ×å€À؃}ƒ²ÉÚt¾§}÷h8MpwmOh"âY#VÑà,z‘Üc0ºÂ#1í’žSÌ\#™#*ÌY)CŸ/"3Ó-ÕjÇmàk_Òý¦ûÛLïÏNæ’Äaž"N³3(•’¾™¨¥2?11L#*fr‘Q2¢E@¼‰É]A‚ä¾vŽcv£»TÚ9þÕpÂz¶GNÖ©qØfBæP Ö¡µÖfnÞ¡Â%21míÜ. ȶº6Ìñv‰I¯|ƒ_áÂ2GOIÒ0z Syè{RI'ë•üò¾H+dÂÀnI@¢@#1h!“Á£& ‹0ՖǸáTàë Š#1\Aë <»<™Ó¿ÑžÅ±k¸›|IÊv$^¯áñs5†ð‰ô\øœeA$TÛp§ñ«¯º!¯ÍFŒˆ¢Þ[¶8κ¯¬¼Š_fƒ:¿~qšø=ù?„i½H¶ô!Õ Üe¾sxF!eY3Šä‰"®Iù1âv°Ðd£'wo¯ŸgJ7ö¶£j[ËÞ!n 5ÒV8#,™*'A@ãÎm#*Ö9l®FùcngP^/Ñ(]Wœ{0QÓß6oõkÅ(çZs¼cÎ.߈*sŸwi5‘ÃÌJI@íod/(&_ÊX·¡ùC¥ÚV‰¡÷–a`ýŒöëÌÁHœ²ü¥©OˆÖ/›`.¿®_ht¶Ã@»$Òá *#,¸Ù65Ÿåœì€ax à(“ã‰KI¶ã[S.(·‹¶ÀLÆÄðÕÕuXà¢ýºàîú´ãÛÛÚ«Ô^ÁSm6yáì˜éƒ7Æ2=Äv½-#,ØÇäEáñzKû|)ΤVÅÀh†øbHßáJk<5ˆÀ Â(‡¯ÀFj1=Š‹pÅQ0çÎ඀Ò#1sóóõ¿ áÄáeâÙ`PfE½‘ß;¶TVrž=}Pß#,_ð¹j i)¨!d2ÍsƒƒúÍÊ@ºw9Éá½DÜ ÄÓ.Ž’åe\\À›?§ß«gßïö”{~ò:s·érüáÓùD4QôhP'üÖZyÙÒ|ŒpœyU<=§á#,£.µ O cJ¡`ŒMØ TŠÔ%b9ž#1¤ˆw‰^ߨ#àþÿ*Z-€µö㈟Ãä­©ãsœÍ#w3#*|'ÛÁyµ…˜«;FœO ÊuÉ]Ÿâ½^ {:²áøtÿñgšXŒ²‡æÛ†)üÓyü™n-ò­×Ó§a5›WúŽ¤OêœxñœL(’“µ ŽOÞ1ígc§?‡éX·ê‡ï€xúêr";(N¨D'"…8ãYl­žêüØÏïã»óíø~É°“úÐþ ¡ýH@°@ —Ç€%êÉ*ÿå’E TŸçjª?Åý¤º–A@îþMjú ?ÒÂG`¼;±(°ÃRqE",#*Ñþ«B`vjÏö³ùËyg­îí±Àú!vçv…†ßã7Ù5-ƒüª¤2r¹Ç—.´a}½;¦¥Í#,‡b\ƒ¼ê#ƒ—1+Ï™µ'«ÁÁ¦óÇpXxbPªgýßYTB¼büêQ‚¡°Ù@¶`K]UAþ\‚ʩدö?ßéù¾e·rô°kmd#,š€öT¢œtïëÁ´ý/v°?šýv­7žö-ÇóN|‚A”™%Ui¥‹¾ô%Ãèƒ6ŸY©º%ó¥¨>²µ_ýzvvÀÄ …·—¹ ÐÿxØ0…Æž!à†Úüá¿«ö—oM“~ƪ-ˆY‚Rå9cw $ÙHÝè,ü›#,@ÑÎÁšPë<á!°ƒgVƒsNaj+]ˆm!‰²Ô?²x†ì©>«ìlôŒ_ä`gÃJ•\nZãü¾ÿ ñîêˆu=‰ØtŠï:v¶îÚ´y&†Âpã tÌ| zƒø{ïYåallŠƒu, bꌉ"„ƒ Y†ñËÐ縸.ÇzÒ”`BÉÙì-›!)Ì9ÜÈNLÞ†ð$Ùtðp›‚0+d„îûIµ0š‚Ð*ÚÃz}P‚µ#*é>Êò½\4¤Ÿoع;ÿ¿ËÁd1QP•`vmó- ‡„Ö›ôÐ.¡QG8 cQc@Œd0WõÕ—üˆz¹¢}@#*WNâëX8 kóÆÔs¼_ÎÊÿ'~Ê>Œ2‘dìŒ&ØúMœ~<Îç˜IK÷Ük¶õwëÈØX°5ßX³‘èQ‘á­Ã£Oã+?õ´xø玫{m³ìÓÿŒJ+9.$ØÁ¡2É Ÿtú<»S‘áIJûæõPÉUó[áæÅ5ùÀÖþÚÛ²Ž=Sãó¬óƒ&FØèÃebÎ*¸[°ß­\æ–'â1Ø8m >Õî©Mpªg5»¿ϱƒ½–}ÚÃ;e!Óì5Ä|³5:IF}y/p*D7˜[R+õOw‰»‹¨â!#*ÓñþªàƒÄ#1S/ÎQik*,@ €p#,Ëx.Í¡ü(‘27¹»Ê>a’hD4Ôd&°‡ÄBƒ?³ìÿš>§ëêî h¡¦Ezu©´ÜŸvJc#Š}¤!ºYzIj/±°P„ ø\;$ ”SÇ{Y#* ¢~ gÀ¸lY#,Žût±I>‰J˜ßLâ¯"öɶK‡#",Ý#1i „ØÔ*" 2È,Ór¥Èa0&ff¤Zlñ#;¹ww•ð ̘͑¸žÉ…@Xy5¤Mu¹ýÜ|ÃY¹Á8v"ñ –F=ÏVr@#£Ðz òÖfõ°”f]L1²IÁAp3!÷?»Õúϳ¬mËw^º#*mBáý›6W)('î`­—C—?kÎ5àÛù|8×O^º¤ÞŒ”ŒLT©E¦øºªº3çù^1#,'fKK½Fá2™¢WYY£Y§­2'¨6C¤ k9 Z]`Þ:Ë2¹JD4Y¹y$’Iš¨ÓX¤ÅLºÔÔ––¶Úyš¹«-f³™Y„uã.¡Ž½aG‰êךÐjÄ45¯ÏEÍCx]á‘Î0ÜÃpÁm,YPJL«ý,•œv|ÿ®ÚìÆ¢'-Qªß¤­¿ñµÀð&Xeæef“ú‰¨õîvüOWÑçoIìÕ˜üã{Säé^|šŽ÷#ÄD”M#*<É`#1Ô@¸†RIñ­êjéŒó˼ÉI~}~åÕ¼@íïö'Ô·ëC<8RÐûsð´%²¸ÓaÍEÜBBAxM¤îÛÛWÔ}VñûÌ‹¶Ì‡Ì"b;‘ MCi ¥;ê-‘:]êË5ƒ‘B–Ê)6œ2NŸ÷oc;ŽÆxézZªÎÀ«àU¶#AIE5º&W¾f^%áôO§&°”Õ%yt2 µ °#1›Æâ…5ň>×7T_2°}2àeè{òShž€Íýе‹67Oš9–N[iK»Ss’D‘c$R2Hý»î®œfíJnQisr™j¤…þ·ggÝq`}éÔÛðŸS?&:ÿâe‘}‘ÑÛÚÒJíúJÕF/ò ƒ#úÅ´\bûÄ…×龃þ¦¦ü§¨²F³Ï™þÓ©ñÏl³ËæUJ*JR‘DS†M¤2CnÐ=3S-Ôšî!lÁCtUovkK*Šƒ”ŠYÒ•#ôü~ƒväÚWv¡£ùÐBoà¾ØœL/Ôq”W¸€XB‚Š7CÙ&*ŸØÈ[‡¤#1Ð:ÈHFá·ÃÀ-šÄÀ¼CG+ «pwEÀ/’uÇÀÖ@\Yú6p§®‡"#˜@#*„ ñ»ßõ’Ï}Ïæï!+‘oÛÇò=·@B#1;G¾¬&Qì_)>7Þ#,zÂ[Ôõˆ¥ŸE-Kí6¢y–9>¼‹–~ñ=}cÿÇ/žOz;N`rù/Ϭl–çóh›0È¡ˆD?˜èúZÖæqÚø›Ãøt„XÆœ€ïìýoÒv †Ê§8»ÀþÉú#*ö»6x'âoæ#*ïí"¥HÝàm|{Tbf”k¼<¬H§NªîñwžaÅÜÑ€lzQ§- Öá«;#*îõ>}J–´ÿ˨{‰¹B-íîˆv$ˆ$ŠFBÌvŸ¬,ëW÷Îq{ÐÜdP ³ËUÎôâøýúü@Ì-A5é9¤Uo(vqAùš¯¤#1‡Ó×пݗ´²ñâ£ï ìŠýDú‡Öúä×î¬n˜,J×ðüÙ]îËQ×õA|>ˆyü#1¾«q ºšÐõ)šf!!èÄd’Iì@¸ªy­ôˆnýš„*Åd# Ø#*²@O—êWðH¤ŸO`)ÙZ]ÝZ{ž_T£¯ÒÑ9µ~í#,N™ÚÜ«kÊþüF÷°\™sŒºD‹á‘T#1òú½{ÑØW*úÏeIX çó†›ýÙ…È@ŽÆÖ=ÅWèŒð:˜É'ÑHÐÁà»ÃªÂ㘙À¦ç ˆk,= PçÌn~Þx6 óN2!,ìŒIënƒô”=‘ ÕZˆ*>RQÀɹ ³õÁ.&ÕT҉Æư«¢bF„¦_ê¥Dã³±%èÔ<|~u0À.öÉ!Å ²HB”±³9Ãv馉‰F‹]bÜ´y¢ØÞÂ\ïzŠèŸ_ZléÉÌŠfW€ÿ˜ñÕ3ÆbÁIH¡÷x[d¦™.³Öž¤ñVŒ£ˆD ¿o¡êbgÚ˜äëѱÒT‘%kØîæé‚{úzžÃÖ‰ä4ò4£7¬;ÁÛ¿„èÈ+äƒÜm5öÆŠ[GfO›UJ/sÇßô<_Þ}Õú2÷õKæñÄËÞ˜¥~Å¿˜b ƒI*0j«ú*ácþ7*¬-ÿ‰©#, Ëeá¥AÀÓYÓe k½•–c¥I#1U)*µFá¯éêëîž“ºNÙåk`ü…Š`s‰Å4§ê½aí=(•ÆÉV·ÍÛUVÔ‘Ê*æ#1?¹3ö»—y©ï"=Ò…Oh9,}G#,»#,Ÿ ÛóM¢C¸„Œj¤$‰#1€”Å©ñSÅ8Ÿ`}¹"æCuÀí;iN¿¨™§¢7ç¤#1ðÕ{bŸŽGuÞ&Uû.ý»3ûò•æï@_tB3ŠÛõ„”#F°=õZøS㮨l…,JfQ¾}æ×ÍF¹ªô®n‘µ®˜l¨LAYl¶î¼ó.Öž\T´KHŒŒwú#,ÉÄ<þŸOÕœ¿À ¼yA–}žsÈ=§qì  Þ¾7]=ÌÁ¿A פ÷ 9¾¿7š0ÖìHäÜc°Úýº€¦È~ iÖíBÄK#ŒˆÂ!@d#1p\áR#*‡Hm4Bˆ}(⥅¬ÄñRòyʲ¼9;7¤$£Ï.‡ ÎÌéæ/ÂýÔZZ^C´iVܯr~™õÑI8×,ßÚ¸éCÎ ÂCyGY`_fÒ½±#1Ü<šN|ÁØç¡<½s¶Ý-õÛa˜Û’.Ó à49°¶¨ <ïªÊ=gág³·v…È{«#,BëgÌV˜—n–— LPQEýë%Oèöz›}¤•$®Ï>ã•Ê|=ï®éôG÷ÔHVɳÒO‹ki?!1ØŠŸÏ#1Ðø$¶L¦ JÁƒ.äa¤tD!½Š=‹$«$’>ç=>¼dá @óò[xZÀ51 ÐfT´¯â^‘!š³b ¨C‚jÀˆý#*Pøž°;}~ïÐ=EIi ¸;6ëGvèd„F“|úúD¡ßEÁ$!‰?D>AÓ ž¾_å}?²½0­‘“˜wÄ+# ¤³¹žha¶*ª`©×®–)‘•#3h'Î_ì#1Ïìªãø ùßïÅ#*¯P–2?ª?æû1”»õ§ú½‡§ì1s‚vbà@Å”QP|JUZ*@æ1œ(2ýÌ)ʶý2/¼B¿:TËzƒVaPšM'!úRd¾©ÂÃÄœ=BD¡ªµîÙH!H?’¿’D\?SŽ¨³«âßÜøuil¹|T„ tæ«H¥,A ‹€ƒŠÀÁvdž†èEqètÍ<#,ñú‚ÇmÃ\ýÈ]9nî6oGŒ#*;Œ÷«ÚkÌ2 €;>®ÉqbªaA3Ñ]G£°å’A“ëÛ¨zÔê ë#,ïH8Ôãi#$B­ÃõÙ#1šÀ®o;ÝeIáƒËˆªtà`x‡’ê"Š°ï20BË#,þÈsõ,£ÏßOOÑõýžý8¿‡ÆB.7åèO@r&Ó½¿o›ÇoöünÌ';¢N“Ó¬3çÁR’EâG˜ÌûH|WÄñVDäB§ <#¤¤#,Šñ{xsv’m±&n"4y1“9XôèØÓxãËEvD<ïŸy/ñVÏØ9Ìã,â7ƒ&<¶îYÔX"¡Ê¥R~RmÑ]åTZS£RÄ˵… Ö.áA‰ƒnWmk=açÜ]=¢÷üñÊÁàoãã݃¸Üc'·Ú’*ï9×R|[8%ÈŠæ’M’¨ÜwïèB99Ô™d€à+æ(;‹¯V]!Å؉ÕGb\3>ZuZA+ÂÜ'®Ÿëï2Æð}Óˆ6#*@â‡N'e#*á5¯¿·Ûtx'È·ø%œìôÑÏÃaP“k’Bºx߀ëC²:ç¬!ÕêÈ[OÝ·Yþ'fãÙ':-µŒì«mDEEX‰ºâ!$‰‡—ÜU/M—"þùüvb¬c„úÿÄÒ-iºr~WØÜÜç¬X†€Ö׬#,´õƒ´Ø[M—]Òõݤ̦ß>·­RµôBÛÑš~“ŸúÉþœXÞw+ÏŸ…BSAÚ]OOêÃDˆÈ.?#Ã2Eûæéïžã]©”nÁœ²T®ÚÐQµÚ¡±´ö›|§ÑÆò}²)L[Éï0Ýø(kÛ~Ò#*ó8WY#*¯:°êWÎŽÔÁÕý5®l†?\$a÷=È·< »¸{÷:¸zÖ?§s©ò*V¤€)¶¥&´#*}OœÛûwôã’©ª—GÙjjçAxÄšuÚòð¬ƒÝ…Q/¯EÈF“QDã"‚ö‰x|Š4P 8CƬ›éP ç ‡û·³ø¡ÔllWTKw{ú­‘#€r=_ø[îϳï7Ĭ‘jòÚì7kä¨Il#,ÏIîÏjî B$a†Û¢SÒçÃáLÓ4' ñ¸èÍûÐúTn΢åóë09ùq¯Û‘_½áÉ#,9ýßÍBwýú"cF›AÒë-sS7œë¦e²yJwžm»ayxå.kØ^6¿rmí)1Pa4Ýa55|Ž„ÌsC‰ÉÒ¡¨QX'B#,L-%LÅ+Œ%eO4ÿÀM©þC43R£ÿ¤fÙ5³xƒ Q÷‡í،Ŧ ÿf¢¬\Mr“^׫;µg`¸M}çV´¸æ#,ðrb¯Ä89 ŒIìe¢ÛÙw+rÿ  ! YRä)„#,=\`Ç•K%‰Nƒù#1‡áõ¦ÿ#*ý¿#1®¼˜p {2¾"¦«ÓgÊŸv€+ü#,N³Òª0V(Á 7¿¶^… LG2IÐçþó•JÁ&ŸØÌæ×oípMfùouŸ(…¸ÔCÆü-pqƒÚ>BH4)-KIiiƦk¯o\þãB»ºù´ÛRsÿA*-p€ P¯V`»ù#1èx0”í¬ÞÍÒWñp`Š¡¹ø¹¸­¸…[ã~µ¿7¶³(NèåQ„xŽt­?›DãõzˆuùõðÓÀOÞö—Ìã/J4T°êÿ‡S©ù˜†¾eËþ?«.ðù ?u7€ „1¼#1e2Š¿A÷ð,†Sd„”‚°Sî×1{« j¯WÇ ø}YÛ‹>›”OG®Ú­}dcpNãµTÓ€WøÊ&RúX.Í5ÝÎ`ð5Óm°6iA¦ôxì"/9å7¡}ÂAÀd,êõª :o™#*øðs\DýƒFn‰–I—Gt{ð×™6ɾiÀÁR88hñû<ûAŽÎ#Wø‡¼ŠèØl~¢ý ŒÝg “{¢Í඀{gøóžZ þÆñ][þ)Û Š¾ÐSz%\XõAt‘ÝCÈó曾"‚9‡,7¢š_!5¡¥ûJð/Ѷb²rv¢ÌÉÉíg1ÅP›aª̃ƃûJ"¼Nón{?Ôyâ*FèÅXÙ÷xªþi=†qpÎ#½w?¡®à¢b«aAý¿ŽÂ“Äk[ªaÙD#,?ÉÏ–ßû?eþx¯º‚ôƒ=‚ôýyj¿ûÿÆüyG,õ6>êP»=¤?"o€Ïßúí×õv6GOíðª(¿Pç TzÈ™~»'IÛmÓÊç©åÀ9Ñáù•z[µá“æn~Ý#,惼•’ÊÔL#1s/ö YÛùu]C8½ÚÀäP(›mr¨Ueì#,†}²üã@ñ¨ƒúð@èAŒEÃœIïˆvj7¶7°1äì:`«ÿ£‡ƒßæ»UŸ¾Iêìç×ç ߶#1?Ë@Þ9|oÄÒÁº6åf¬znÞ!Mn îÈr+mæw˜ ã¸ÁÔŸo½­Pÿk¼§t$Xô|e‘æv˜Q Ý?™â[ÝòÏàßÎBŽŽ7(Ê$ïÔS‹îû×ÏÈ[sepkâÖPçå|C4]MC·Í ÒW½PåS¥aeëh”#IêÉc«û¯TÝ[ßò´ð”´Õ×ç!¨4spÈUšÄ½®¿XíÑ8¸c%ù6:ǹ–ÄìTÄÀ ÝY²´ªfï-®aa›¦ù àÑ¡x³-Ïž˜“}ü Ör8éœLðF»?ÃzêYŸWÃ%å<â]ZÒf”Ç8vl¦^ÎÙð~ÆbÉ÷­wg ‹„<¸%Ãb#*xiG¿o¥ë‹‹íÚ)’¿Xí9††Â¾W‰ã„›7Å먽kŠ¥òƒ¶.rƒ‚Ö($xVT7¸¯ÆÛÎóåßžqI¼œ0'w1#,Êh]]ζ±=Ð?”ëÀ…×/×8L³M™yj5J'©Ï6µ8UO49-ÐÁ@AbŒ¦hÐZùutÛ5%E¾ž¾7ã\µé©»ªõ­ÓlIL*Žî¼¬˜ÝEr¨~·žå) œïÁP.…°†ôlq\g]¤ÀÂÝ_í #*‚!À|‡Ü>bï®^Œ¸# ÈÄTenÎÒCß#,ÏÕ±T=íJá&Ö°gõìÄGä›áŒ„Hì|°¾rzÍÝó{ÕYacJ‰I½ªË)RÑÃö_&’ß0²G+a/ éNÅz͋įt™^ËϽê„ý»aÏkçÂâ€O;wë¯;š’g·†`aÛÀ¢BF‹‰#*#,º”D‹N~‹m ºž®èÒå·U<‹Ê‡ædâ„æõ}ºv·¿NO=fzvÕ?*”¢8 Q£rŽw¨~-ûv€;?Ó%æO£êN®ØRÞõG 6D\%ìéºðvñ·ÓÍm¡ˆÀý»|Â4mœòסƒÈD:Uô>šÃáÔg§:ÐÃËB}¬e|·uðì©44Z÷™Ë#Á¤¿äø3Ï&˜F’ǧåøä#ŽN9ž¶'u«>2"¥DëXp¤D*vn:¼ƒô?w^Ü,øÃpùé‰=øÎ';JÓ1óM“^¦O»`Û$P&5>ÏK™Þ„É4âYð%ÚŠf(i²/räËHpíçf#1×xu+'‡¢½LÛ‚î@zfd%Ü=8i ;&f¸åæ|·ë“©Æ±öab%šù~Êxvð:ÜG<Åê˸´¬@x#,PÏ¢ 5"Æ’R.²aV&¤Bœó׳VQX"ô6T'.#Ê¢‘¹ê;#, *‘a[“ ªÉ\â1ëÑÑ1Wß®CÅ­2LGHiàÁ¨9¡‡A’2ð!PÕüýô3ô΄³4wQq<Ïh€±d?Ïê÷ÿ¬§Ü}®:Ée…€PÈ*#*¼ßíð ½×ÿ‚ÞŽG#*déüѦ”E¥Ïçûý]g#,Z:Š_ô@ð/;¡R¾ÿšÝnZE‘6PDñ-R~Ÿ³¾çõþÑôÛýð>cqîË[3z¦6†ÃlßÐGϪ5S‹$u_—pá&0àf0ÐjÃ`,MÄb D”j ÒÐ`8pl¾À2ŽÑ¥sŽƒvqô†q3XŒË#1â¯; i½lk^íÎÓ:$ã°#,Lôúõ0Ú«"0# ZRKA4»1Oœõ§¸'Œð+@ óíòÆÝi!N¼û¹5“±rû~.›Ý-ÉøÂ0ôðÕ¨qùcúÛ騳>­¿v¯”¢Ðdöîˆ÷]¨Ž¸TŠÑ³†”ZÉÆFÚ …+Lm“-­ ˆ$#,­D2ã5?H$ÊBþT¿°•vÚî[‰6Õþ'mÉ‘y_Ãý/âö·´³Yš#,£Eüïu…åck?‡Î†›Îˆë«ø5Ý<¬·èþ}õkê$ù@îF{Ñ‹WvÝžPàw†Fõó_ÖÀ!÷iœ0d÷^ýí`B-›8³—a­¿ÊX{û³°Õx•QXˆäèÏÉãȱì7’ d3Z\ËØC[ƒ#QÈsDŒb&¬9Y Pö/\VÚ°žv(±¼¶çvvK—ª ‘9C4…&ÓEÚ“Y¸1SÁ·èl<Ž@fÕGé„x$xÂ1' @d¶îƒÈžÙ2LK·#AßNž’ç¨J.a„\ˆÑª£ó”Ø÷™¦‰#,Ô1ˆ1ãã¯u·{³Å܆ÛõåWWГ˜ šÉLÀ·äØÝÛnÁsî8Gl%­+»‹ ê+ÊTîÑp*u¯L+¨¹ß äò-·S8[ cZY7'óðÇø^–V¿*n:á#,6™ÝdȆ >²È]ÙJ¼M#,Dz%ηs‰™IA¥wøÑ"ëû-ËJswaUŒ#1o«¥â1°É™ÎxOÎãÙN£#,¯L{ÔC¿£Ã¿w~¶õÞâ0»pÇHÑJVšWàv};gi;vpƒÈæÛ¹˜®¦BE¶u³ ·Åæè„Øâr[,ë¼Ìâ‘àÉƃ@uàÛ‚öÄîö÷Gà‡ŸsàõFˆtø!ž‚±Þi6Ç£‘Ãi8–ç±3.Xr¾Â#1Îk‚ÉÕ#1 r(*W@Ö<7ðB3;C³p«¶kÀF#Ë_ïÕ@#,¨¸ Të{MÐÉJ&㇠ɸ£½ºlx])¶A•½Òw%Üp:;Œ9"„T±äõ•tÐÍ'‹9Ôÿq±¡§"Æ%&æåW®Sf :wt’¥›ÎÍ0ÙCX¹É( d¤Éoæ×â÷¬$1Ž<*Í]-½Sv—{¤Nõ¢so†ñ‰ ؘ]¤Úƒ™Í#1„’#PT,=àÚ9ËÈ”Xw›JaÃeëÓ¹£ào#13“|”(yNÆ'~'3s›Ä‘e0)ªAc%4™$'/©®ð,q'GQÏb»rÇ6–§G9 ¶ãëÒ¦`–[y™qæfL¹™™–6Ìk*̳2IV;fy#é~ÝVÛ5ìÖÐ؃³F­ò„UNïºv³m£J•÷ûˆÛÏG¯žºÁ¬Z~ï-úMY^lî.Ä\#*Çï¹=i˜˜'£Ó…ãlÉOƒOF´Öç0kdÌøUŒ‡†hYCS8GEÆœÊ×ç¥k»QÏ#·‹3ŒF™;÷BP!%­víÌ”&€ø¯Ë¸R]Æ,ª(IuK,Z*(ƒgM&þ§¿•è‚±—p\&E{­HÔ¢Â#Pbâ,Ìé%²_NiÖÛkúÅèrÖ_Ñá¡’ª×eÕ׃ÓÖɧ$‡a˜ŽSE,%@»WK‚óÒu(,KÿH(‡9ÑÙœ$„’Q¯y]¤7hªlªwÅiñpùv0jíÿeðlZ¯=e¤ ðvŽ¹Ô[ÑU 1`FœÌÂœºœáp#,à0÷v|\l»| ×~¼ðgÉ?•á´Nzýx¡O@YaãNø½D?/Ì{(ÛaÄŽPé–¸–9Å„gªY-˜CóZ£VÛ\&|q½ìꔄ€¶êÜ2›ð›<ÔšÚ†¸± #*‰°Z:õ±Í±å—.E–,>iò\4Ï!Dö›”„Ðà£J(‹Ðã$ßdÌÁºÌªµB½z&žP“!ÖŠÇ×°¸›#,¡¬ÏÁ£0¡ :wëÃÀ}ÄB â’˜ÓaØš”»“Rr$†hešc í(“©ÕT™]Pç›>#1f:ÀàP{rhçȘñ D46‘…dðp–CÆN#*k©XËÈ1ä Õ #,=+xIËÓKESJÐJLœhqÈØ£ &E<Ó†q¹FPÂó’Ôû.™¯o~M3ÜvÁ.7%@ŒwÓÔHM]^Ðk|QÃÛŠÍQutÄĪo­Tu;î&›ˆ.¬:“$áò`"Q¡¹†ÃpAšêT‰¥Nñ(©v¡Dä†þ4ÑÝN™F,ŠÂ@É!‰Ât5cÛ”ìø0Ì ”4 &µK‘#%Œˆå%5X& ÄdÅÙœæø|Srk½3nÖå2á‚œB›§4ò G’ÂËÕ8íUzšéÍ'wƳå|Ü®%#*%NÐn_~L#*X‚#,’ÆÑ4Ùªf)7½¾/‰5ÞEô’AÄÑŠÎn`>/#*È÷+‘M}^¹-n¸ÎF¾Z o#Ôõ–ì{Œèìî"æ³#YCcbõ¢ÄÛJå'Xo 8x´8”*æ\¨¹&šl*J %ß^Šù?n#*Ø·Ýsf̼dÎu=##,Õ/ÑO—]åÍØŸ¿¤.nDÄQT1ÃÀ;Äúy]#,™¹¦jÆ×;yCCjKįçá{«'²ó~#,\ºÓ›¦™„Â@¹Áb#*cýƒA-É~ø¦$›¥•d’X·-È•ó–(#1 ?_j8d}¦ÉŸ÷ô:~À PÑ´$$~'Ð|ÄZ~汊´F%’|™Í9Ö.ÙÑ¥³|ã¨H¢‚PMÓws W‘¦Þ†x–SaÏUJsã3Ì?W¢ ´‰—ÔOGbúø]þ(Ÿ;fÇúºáÿÜ#ø&# RÀá{* •ð±ö?Rj‰þ¾á+ÅMEGmJªÛ=#|e8–N#{ðñðÏZX´­%×áéÚ:ï9Ýê$ö•‹Fˆ† ¶\€6#lÙ:¯bz#*P¢4mþIÀ„‹ƒˆÑÀFØŠ#,D8«ŸœÝR5æ\Ö¹‘ãÞæz™ÏôCÿ›Ý2Ì?ßþùÀCç\N;WO‡æ<`PA>ÁQQšßwëÚµ>ꞥԥÌÙ% ¤銲ŽÞßOˆ÷U!³Ò@‡‡]ŸÈ‹í:Ó¥úÝ騉"Œ ‘1+{wQ&þ·i›)B!)øqÛ˜J@89Ê¥Ï/3ÕUÊ¡pÁ#*Ò¶—Û€Ã$(»zÐÅ$¤ŠÔ‘m*"ª¢¥íe¼W·úúnà(Qï‰$$$¥¯h¸Îô”z,ùðOë’&MP*A¨#*´Š>Ô‚©íz'&ÖÑc¥€oÕxϧe?ÉW,쪉¿¡<“É’™Ò)U#,Cç#*ëüb‘ G#,¬ÈBX‚Z-¢¹#*äªÕ¡í$T“ZR·ÅûÏÙz»u_Çl͵å"hŽµ ‚”7‡C ù©#,¤ˆ2A€àà °>œ/ô!©YÒïñ7â⇠$™[ƒl¶z`ˆÚiÈXº$ÃäåNݽ¶¾wjôÛ¡µŠF°gÓ ™þæÈ‹t#1jØ/#X(ßæÀ1 R¨²òA:r’DæN»Pï‹_s#1*“³È.ˆ²  tA‚¨Ìë dGî§× 3eOœ…G2H\Æ‚p#,ÀÕ½5ÞÈ„bøƒ_Á­¯³Jð cm;óë·>\¶qü¢/  êÌpá<` bˆé·ªdóPÊm¶úÕ«–Š¥¤³iP„Qö9â8Ø€¿Ç‘E$E Tb0SŽ/ÐôrI=vçmöK1¹L£º_˜”#m-P²R{€BÒÕ›8•AwQ¶P ÌÁfa‘ 0 1à@Õò¼¯,õó+ú$ú…2¿¥5êbñ^Š”’E½]ÛÇ¥·7©½MÍv%wh$¼ºê5Ëwô<óo7Ls£º¹¹d¬®í’ùôâP—H­[)BA5)Ÿñç˜53VV>ú¤Ù6Hk¶Ÿ€uö€78#*OtÉ †ŸÓ(l!™cwSÄETPõ¾AÌž¼/Çå?³'oÚW&¨¦’ç}TAîde£§Ýœc§—¡~ îãÏ=Í1c.Ê´yo‘¾nÉø“]2¶)€îÐ]£LòÏ@è}j1ÛP¢ÞI$:#1àÐ6¾5ÿÍÚZøOŽù«oøSÁ´É‚#1iR¥[šÖ4ûÚÏXÊi˜«(³O–G#:¬ÿ®/!ê÷㘖í#*OPÐ?ÆUHïR©Æ?”ý…úô¸4wõ¢ pa¸´Q.Ír£6Öæ%"˜3Í '”*HŠÌBP†–ÐÓu*ot0SK#1K€²asýlP @Ȇ]p6Ñߟ>^{²‹ÝñÂÿÑçÁò¿Ãê~~:šZž$Kopiw£Ì×n´÷w”OÒwšÂ}õj°w;ïl!%м.v³}¤„³Ë¹µ‡è#,nˆ#1/€xo;´å߆C ?åá»UÌÓ¤½ZÅ“½DD°t,ü‡þßI#1Ùº¾‡ÌOyù®z`Ùf8ëN.râ"í Jl‡œh‘÷~ЕØ~0Wéös(„%Tª”Rvö|ƒ«zu-PJ:ÄM‰ê ÕKÛÎy¹#1½p €¬÷ÈDw 3P² 1" éTæ3)_9IÒ6/U$‰¸´x@íŠ<ª¦À^kº¯åeÝB•"‚{ïçpÝ•ÛÞª‘Ö–s³`ÄPwùoË}m>l!AK$¦%DzZ ;àMÁåØ´¥E¿”½Wí{kkj m“Z‹dÄlÕ$ÙD•¬Vm-«M²ZIkÒZ²2£M™•ZjÚ[[1T=G“„øÎ6ú%IÊvžHoŠ’#1$#*dPyú@÷@ #*ÞäÀˆ2ý~”×´{~‹]¶Eº¬k›mò—20qTsQ¡‘ŒK ¤¾2Àž#*‡b*Ë"—튡…`ëF¦ÚCmk\våÏ®´GãŠESˆ†°ØÒÙ¢m≧JùTÜÐÒQ‘h á…ˆ"ù€BúV@LÀÉ3UãÎun[ .ðTöDAnåJ EA$êÏn 9ïIØ⪆M5»PH¶Ôºxé“(d&_¶‡±¥õýôôÓi7ic@ª©P']*$h#1D^`tÏ!ÑEƒB$m¾ÌµÊÆ$Õ«›sd®mr™°¥L¢©˜5 H¡šEdû3>ÙàÖ#,:·4Éš†Ð8FEV„@ÉTíQ]J¯¯ƒåÐ~«ßw¤û=Ø·*i£|´†F\"nø"¹OK̃¼Ï;”ï»Gô@5‚@Àï ¢ ±í$tFÏùý>O¯âåý¿Æ "Ä„â{:PŒ=ñ€²K;½x2ñPX8¦*À#T%â£D#*-$¿:ƒ‘©…À¨„BD|êªmï}ÇiÓ§+.¨š¥BP¼PÙ?Æ.PÎHMŸ^š]?–SÜÄÍQ‘-ú`tœ0 !\˜û;-A§¶ŒÔHõåDyú?wþPq$ý4"í`fCk˜ƒ"(g¿ØwŒ‰«Ž;·f>'ru6ë!N|o /ªp6¾L‚>íCSÝ`‚JŸe°Tœ–d÷ðÏ4“„×@Ù#*Pd!ѤtF+M½?ïCšu³§×GkÛ¼ 6Å4œQ2@fýIìG°”:SY:zþÞ mŸÜ-4ñS#m^§¯Öû·¿Œ'ˆCµÎïѹÁöPï¶(ø]¿*nǘò8z©^‹{~Û>•«w[apLÇ, HÃèðȇ°û)ÓÆd¬to .ý5[ màü¦ %ˆÒà(3š Õ^!Ê#,µÂÀ„cÚ€ì‚.Îΰ€‰ÕEÚêCßmÀÃ+¼k}&øØœˆ[|`Ž†9éŠE^T½A4€f ä?ÊÈ$”O†ŽuØY{Wåe b7kksŒÓa“w]ý‚ü\žnˆ‡!Ž|¬žïñèsÆEîzÙÉÙŽWÙ#*FJ–›ÁÊ\0'ô?.)|Šk}Ž#1ð‚¢D;Cô:ã¬mЬ“b`ЦöjÂbr‚ÂŽÉ´ŽÂ`[1×?¥¦úÑÁ>(=P ð­`tx½õ¶ç¯zîºøóÚ;ë§EËœóÍï«1Ô²øm#p·’¡6%Ñù}çÇ];WP¾xž».ŽÜû™¡èì»(Á±°Ýúßavðé϶2¥°Ý:c¤=r&ñ–ÁÉ}x;YÛ¡¼îƒF®ƒ8oŽÂ½]ÁNÛ8~¸¶teµ ]Gˆ¹Ï#*°|p}P²”‹tG-‡-fÔïE¨Ñ0¤ö"(ÀZ"¸¹™´B™EôG¥Ð{d(Ñbz> Nl;uâ}yä ±2±ç2A0H0صOfN×ݨ©f…#1 ã…iê;H!Üã uo!SÚ_x %ô¢3éB“.¯¢á+­ÑžO;K².K#ÀR¯Ðs÷"!<ƒï'Ãä³Õ€}Ã#ÐüHíתÇÅ‘’Áì]YámÒ ºðÐÏœ0bÛ?f~˜*rDäð#1t] Š‰""M*7ï%³ÆµÅ>,Î]Ôf( ò„Y»ÑÄ1È#! k;Æ#*ès2„UÄgQÝαµÎ#* k1P©…éxDˆÂŒÃhgƒd±'@:#,RhD°Ü×›%ìÏ’ZÙûËn;?׳#*rÓI³Î¤tI¦<ûx#,–nN q£ŸVÂͦ¼ûNa}"…C¶PdÜä§g!’ªšl@„DÀz9rì}Ûõàa‹¸ngE"Ÿ;¯%‘#šh¬–U7T'¶±‰î÷ncÌõ"€¥¾ܙȂ!† 8„W3³y×yôÎ[ùe½44äZĆd/Á‰$]zý„#*Ê‘”wãÆÉÓ^z{ƒÇ©o}¬K°ÁvtžŽØš¹sU "×~Óxl¯aîÖ~£â¦¾È ^žÍÅ#%T9JÐê’Nµ4{¦¦¤m—«"œŸÈÑ(ç}ŽÝu†€ìÖ#1Ð?zà^P}Ô+Ÿ„jàp„-Ý#1H5AH´²—î å~¶¶ -)Á8鳜ÔoŽ><·Ò7‹!¯ñï×Xë ;”6äíðpbe$’C}ôÜx»1\U`—`ã]AkpÐBm.Á²‹ÇˆHAš#,xêUº †Á`—íæ 6#,!ˆé7”I°y 8è” gyÄ9%š¨È=#1ê­:é—…@QaAâHÈ‹ýqvW³áهƈ‚Ìí,à"\$ËÜ®áÌ°$‹Ö#*Ô#1‚­A¥×ÔVj#1kƒ´h7ÚY‰‚q¶$C˜#¢­`ÄÃCL  \YæikDpžQ.ì¹ Ç ¹c$)i/¡ ñ±h!¬ qJ½SoUku#I¨†Semóº(’eŒ0 u)a‡¦ËvA—éç8vÞÜž¦¢{!ê¸%}´¦\$)Ú^²¦Q k #*êoÙáQ‹ÝË"ø²®» ‚4pa®Ï^Óàpd›Ù¡¤9#*üÁ(Gƒ'rgW>ö1A©å 4"Å‘fú}i¾'©Áø_¼–²_»1q×Y8?S[€“z¡¸ƒ­L­¡ÒOÎÞgá‹{FÊinlû¾=>/íø!õ‹’÷ñu|ÁÙÁ’þÒÞî ¦&¦Ä©;–?K<¢t“¯áB& I±E’B¨Q¡Û=]Ç÷$EX1P=J Ð£·Ž‰s¬A¶CÈË¥“¨äðs ö‰P…¾™¹Rª«Ó,‰É¥Å)qQˆŠ*ÇUU‚‚4L Š=é•/1ÌV¦ éÕõ0öQ*-DxÄ°±‚’ Õ ÈMŒ-Ñ‚'éJU…ÓP¼´\Á#XÂë+8تSÐЈh ÆK©<)]& LIÏÕaâ"‰ˆ#*…5xí¶00*¤ZbëŠ#½ætsèqÇx—ªRqÌlÀL2nËôíM¯Š@y‹iб¢ûF>š0À"'…¦?ÓâC5ËÓ³œÈ›­@ÁoŒB=ôÆÀm š¡'‰uV+Óç•TèHCfa"1CǺ]—„ÝÔ•ÇZ«@x-ðÍüjÎFÌJa¾n§#,¤ÝcξqÈÚØÛ²Ž}9ÉfY’bTcïÉ´f1W"J¡xbÌ Guðxa •@PÇ{¤ûg ªT¥kÊ39rÏKu”_ó²CɘàWtCÛ]ìyYPXŽVR6²i±äŒä*r¬lSIü¶b1èÔ0emŠ‘EJW}žÇ †{[›ãµš3šg8,±¢3¯ì f‰IW±#'J˜ Mcódd„ôÇžkÔ¦£lme¦"¢Li¹ w€¾YõÎ#1 ØÂèÊx0á¬`-î•e;1±¦ ¾Ò†ämc–#*y°®jäÀ1«I;çôöÍ-ÈyÆ›ë!,W#1H^¨g¯êK.±Nª^ /^hIŠ.0°Ñ­ÇÚÛÖ$€Å×¥Å*TIqàŸnLÌ!ÝÒC88ÛK–ï®fp×C%i82!’&âÈÃXhaJšŒ‘VmçX*Å‘,††í[°èéGO²í8û(ïãÎçÂ/¦8WS&d”t§Ê%$Fðòb3lVw/w7C¬ÄJ>Ö:‘±8ìsEÎØŒ¸+ŸÔ…SƒÅ’ÄÅËýá_ƒ"U°JbCh”6¥ÎIŸ­PͶö¬¾0ÒšZšç>‚ƒ¡rÃ,räeÊR¢4Eê‚j"íñ¡gJl5…#ª'Þ7ŠâjõÖdãúÍn¢A‰¼Œ™ÍðìuR\ÿbû–ÎÈÃÄ=§I­=w¨–D×E8Å·yn!ЙYRùãI×eœÁb«¢pÆІ²¸õ2U­rÈV\ÅI×MYõQ—1øCl\µ3åäûŸ8Ûc­CƤ+GJ|žøoT°æVë„j[îše¶Œoƒfr‘!ÆŽ³»%È°÷’ÀÐàK€Ø/´#,e=i£@B ;mÇ@„XmÌ4€Ø2#*§#,ŽãgÍçÖNHùl5[^²ÇcD`6Q,D0(€ùÃH±9à´¤Æ}^ÚR@5ðX (p°è³#,,"HU˜Ò£¡xš¯UU*à•ˆ˜ •b60ðÕq±ÆúÖÁ‡D#*„P$¾í,h7Ô1(Ý ÄLR Œ!Rn äd#1™(n×ɸä?C‚ó¨Nv`¸ˆ>Íý‹ÙBAµâ?_­ªf¯ºÚ[Ò<¡"!Lg]XÞƒ]¹:±ÒPû¡¸×"ݽš©Mä°<[ËÙL9ÐŽD„Ém}!ƒæîmÒqì"çÅ'ò•pdxgì4SJ¦Ú™f1Xíšñl`G®"ˆ £sºvXAèJ²§ }È*ˆ‚=IM¤œA`V‹Z‹kÅF®VÖÆÛZ­\­¹­‹m£jº #1aóê>Òâs"!~÷Ž,^¨é'a¶Ýê¹T#1#*üñ™žž0ÒÏ<¦š}öz¾ëøךKV¿™BHÐ’ L™”Í6¦Y’R“LRj‹Išƒö]I„µ¤0b¢i©C%4D¡Eic^ý¹†Mi1d”JelЦLLÓ2F`Q¡F˜”¢h}}ÔDTY)˜¤”–PÃT%¢Ò£EL¦FQŒ™+LSXÙ ”MJBšƒ)Q˜ƒM3iŒi‚‚,ÓGpîI¼Ùí©ÄyYKõ…H1 ¾šË –0z¢íÈø·ÖVŽº?›Å}#,Ê×]´µÑ­´h Q5 ‚Ñr;ɧÊà &E²ÆöIVqsž\·if£´Ê%x4ûß'ÛŒc]‰ˆÌxÇ%·JÁ¢ÝúU]‹±6uçÃC×Ëû‚Ð91MLAàÌÇÅZº#1¤–Úo§Ÿ\7´áû™FÖxµÝfñP‹¡Qp^KsÄD®‚Ùß*FØÙÝU…õ²ÛyÓkœaŽ:n`ïÖÃ4ûL9å\qGL®I&¹Œj(þ Œ ) #1<ØRm†VÎi(‚Þ"^8—gÎœ<éŠÊƒ±ni§=æy%Õ¡¦Í¯=#10š¹~S@Š”õ>^Y®„=ñ‡2ð—µ¥,&#,»–`m„¡ù8÷Bdë;¥ÜcI Y¦{†™Iì¶@ Æ[#14iÙa!ÛäÏ­”„‘Î (¾„À&Äy½§RnXQ?Gªj°úùkÕ<öïînÎþ@”‡-ßu•o§S¨O]z»á×Ùcèõ– œ>¿¦¸Þÿ¤éi:’$3Ǿ;êNåžû}ì;¶}}_,¶ýV²ý=TàüC¦VŸ2©a–4¤‡w=Ý®ó:ûa°B·ö”¿OeüP܉l"ýÙ ¶ ¤wœ8cØNÀã|²UÙ©RWËac¼ ÅÜ "¨èëÁÌÊÎ|u¦d#,Zf¤ê#´7ÁðÈ𙙣¾¸ ³Ç-Ð’dpüÌ àH¡À­à50­b ¶(ÆûCÀ׳Ë#¨‚H(9Õ_Üç8o!YÔÔ¦ê&Ùy>–ˆèÈÅ5©ãyY–ðkClɪˆ=B+…éŽ#,êfciü7™‹y\ùFÌXÜÔnœÌçQ桦e­¶iÎdf3‘’ìY!‹ âhѨ¢¦¥—­b$YB,.7…¶—;Y3#1m]Y56¶øÍÎ1ôxÝ1iIÆ~9­d¹8ÃtÝ/NzŸœ¦¸ÛeòÌ:l‡–˜CàƒÌÇ5GæëœEÀ–ÄÔ̶‡«$™ME’¡BH•éOK‰8‡”Lm?$;OWÔêƒ+„Tâ .‚ÆÜq'Hyz—ƒ;Œ-.óZFfôC#,Cr²H03†-±$ä­#¥'FÁùk<2ï¿S2¢ý¢ÉÔCr \˜Á•%¼Áb¥û ­ZžÎÎÚyçLÕGÚ£ïç ëÖ#,`à,ìš«.n0>y’é‚ vÇZG À9^Ò#t«Xd+ž¡¦†#,5sy‹™;N-£'z“/‚,D@ìlçN^q“,¹ÝôD¬Ýï5™Þg3]_5;Õp)$™ÐÐí³v‡ªËý‚Þl8Äsë¼ã8sÉs\¶ÈOÀŒè¢ö¸t“¤÷)0±·3ZTç®<¤;¼Ž $Fg®ü×'fÕ£s,q]Í5ŠsθËã¦3#,Õêì…ìõ PíÎIÓì{›3#,G‡#,c†¸ÉCëÍÔr÷ÃTQD—ÓÓtiXÑ 2cÇXBcÃз &¶dÐ!²‡Þµ}0<ÂA§m#,¬[Hi€= Ú^Ò”:X5¥\F™µ® “$KÛì‰Qtih¼TG¡¤Fµi…¾š…5r+fÛq®¯Xþ5…NL1(©X«#1ç7VMôwáVïhÊ`HB,bŒj®6mž£ŽpLž C¸Eô‰ÜÉ_Dòˤ²¾uF‡[ï¼èpG™µ—¢fnPÐcZXƒa”Ñ%&æ`¬½F;HBdÜn éø!¥’mš’reà¶èˆ\;ˆGDp˜uÉÙÎQk“®©Éc„9)¯Y7TtÃ&jp. 6&nИŒ‰%ÐÁÇPq#M|æ\~T¡ÓA¼Ý¨’´DÇ¥šfµÛfµ7]i8Íu‚åÈe¸‹+•ã‡9‡¤Ž!(Ì°Faöå”Â#O=d˜x7Nئ–Í*$6úiv^¹hë—+/—mÀ®˜„Ó(*/r)ÕŠPI(ÀB™2lZg‘ê#‘صB̤ý´Ðöã7,)dFò;oZ/òâÀó0øX»)™ Â P\Ćðú£<ßÙFôoƒX>)xݤ&“.œûr\$d!¿'tf£m‡Ø7ÍIª¾î0ÒxÖ¸ìs/€NUº´Ò“Æ;»•HBË'ÄD+y@š"*i-à¸H¨I=íB ‘#äHö·ObµÄ—S#1ƒ33(d2S+U‰åt˜0¡:ßK<E¦Ù¶ŽŒiS£„Là˜Uº™AœlgQžy—)›Pà†ÈclÄÚp/ObY܉g†ðK§/ÃdÃî ú!áø^Ýy•Î›¦¬à¦\£Csº¼ãlÆŸËé:[C›9'-#*ëÑŒQ âÔ7G f‡ÚjÂqéóºVL#1ÙÄgPiËçªÉ€Ëð¹—ê²#,CÊRisšÂhCiÊXÀšÕÔÓFa³´2qYà58è(4Êý¹0ÄÎŽ1A¥$Pkl¬Atjž.mîøÂ,zàÏêe̲aòEh€‚‡áˆ%Y™Ãi©Ø&˜åÜW1„߉#1KÕ5B˜E ¥ ¡I HX.ÄBä¨6¥1®"àÔv\*f.f‡aDhéàe‘Œm°’0Ù´ºø^?^¹…²åXëZÈïûª‘ƒ;@‰´2#°À¥:WoC`ÌZ’Šé[Í4¹S‚c°_fجÑ]a8lPÎÅ0ˆ,g*¬Ã5Œ8SnTäS,$€³i¢†Bˆp5¬É™¥Ìkcp²>ÌËÖÅÖ¸©Hˆv9GL³#­3t庙#1zŽÅ‡S2:b9BcÚ(‚\¸'i©@# c#*&³i©ÒŒöqìd˜#ÄÃHf7t‡43š3Œc¢jfÁ#,° » MåÓ ½2,Cc9´h¦Û“>R „“P6G¡¨®éQLØd…;™Ž³jæ]#,c hlÈLœK‘›› &¤¤p#&wMx“+p*°êqæŠ.ÇSà4™‰u[Îp¡@*Àé †ÀâØØ’Ãq3ª„bHÂ1 ¿è ”(~îâ‡øÉ"Š ®š½™ÞJ›A5”QzR ÅPkýzø¨ý^óóp"ƒµ^â’¤’"+D€€ º¨æ~r~ó@Ô`“’‚0ÄTä9¶H¤ýÄ9F¤š”«|)Õuº®Æ#1’½½{jZ#*À2€º¤’¤Ùië–³¾{L]¤B® 'Ʋª“†}(=ý8‰Zmïí81úâÈåôãòû!ð©³&‰‚ ª.P÷2Û¤Õé3‡×Kn(U†ôñ¸ëá›&A±¨#œ¹R:é'M•.áiR¸m†…œ–09Þ»ÈÀ­‡#*Ù¸ìl-–:ðÜ¡ C£³kÐŒ÷>"÷?{@RC´æŽ«‚ F#1AŒæ‡!øì벂#*PÓD©Oæ²Z!)çÀT„n@„#*…B†È¼<¢”6TAÓ Ö&) ÷|}ÈhØUíäó+PZF>&¼rT"Q“K”=Þï#*5©’ ñ‡¢-ÐÛÏåšw*ýAUÝônR 6B¡ú%N]]ÝWf5ºî̹ºé»`!Lˆ‡îK€Ùü’ª"À›!H Àø!à ðëD°(PþùÌÐGl¦;Gz¹CxׄUy ùPæ¿1ã8õPÉÄ‹V¤£#18"Ÿ1ï OÞWiFcéV5£)2.þõˆ·AÚäýM€=˜6Æ|>f9m™—ÈFÙÓwG*ɽ Ðb@!*ŒŒ²È)õ6!Fñt e À÷3a ¨pc÷rr‘0„BôbPbÞ ª”Ð(éˆákHÃæ#ˆ„¸0o”!F;ÿPóã‘š@‘gcB D5§àÄÍøH†°ê~6ùþrå‰z¸nPLîfŒÂ¶h;‡#ä|hüzH ‚£)-cXѨգj$Æ¢&&Æi™hÔ[bÉ lÑ‘#1–‰ðMþÃ:VŠÂ¢WZœ6uw®Id»Ë£¨í€&³Wh‡¨ áPÁûîìDMxZ ²Xˆ‘ˆÚc–1àˆ’"µ¤rˆ¶ÀVƒ•²`3pž.§ÝÞöju °u½(´ó5ýÛYz G¤Ñ Ú;az±Q¢/ÓtXÉ’MO®’¬˜WàÝw hÎç<ªã¯ Êë új¢™¨0É–[„:”ÿŠ"´˜ÒÇZH²‰î+½5«•t¶ù¶õ/M½ªf#1±dÆ-™JY±M‚n0­.š!±€Èçð8ÊDÍŒpgÜ¢#1Ä9Íï„_‘Ö–ŒúÈÓMnHÐq ²@Q¶“Uúio~ù‚ §XreK¿¡æN÷+2Ò®sš¡“{NM(ªÆR$¹â”1ùqãdÞ7a¢P¨9!R9{Õ)r=h…k«£la˜Ê‰Ø¸Ej#,^&Ž²Ð†þ¤`Ai"iÀá&q¸ÖTt‰ŒŒ´ -±uD²d+®FjÊó¦-—èó(’xÄí;¼ˆ°†&ÛI&Æ2´‘&ÄDŒ¼bYúÃT—\ZO¸€ZÈ!PKÅGæ²íŠš"  ÒX#—ã#*2v>nð§hˆ/S2¾4LY‹A‡tšU'å*(Û´ÏËq#18ƒ}"äaV¦¹8+hŒŒ&EÇË(øzë“>”Ӓ)„€ ÚÙ•ÃÛ­n’µ^rΞTD!+BˆHÒpÓ.Å ¥¬Pe1l5´s†¦¦ˆj—ÄWøø 't9`vhU#1‰í¤@…/…‹ŸfaáÒvÖfZbCJ€„[¦Æ÷(¼5¬ p@“‡#3™<#*÷¿ì´Z-ðƒ(*?†“†iƒñídg)&;‘y˜Y"„èu›n­N4i°î—¡­k•’”à7±½šµÞÑŠHV¹,+M¨ræòà³jRo#,kœð\fÑ‘¥磼\Cµd"ju¹¤YÆYÚ¸¦4(=a°°Õ¾A(ĸ!r1RŒ£vêìaf$0·DRË@ð€¢1*%TM¨’lQ¥ƦB `1Ðœ#*-RPRÈIƒ±fÇWÆz(ÔÌÐÀ­üa#1#1îT#Ã^аúƒ²¼cäU#oÙ{Õým¯c)XžÊQýªÝ(0ûl SÐOâΆÅ|(ìl!šáŽÆ¶2ûmCŸúŒ`G¦A¢dºÌç¥14’ˆÈy£Å},»+.ë»»—rݾº×’«bÅQµ“mX«i6­_žÔ´´‰ KÞ¦h}#1ž~zñ*«+Ö/GŒ2µ{+ ó\J¾§ò€ÒÖŠ_Nk™®1ÖÙÔ­^øsuelZŽÊÎ-GFÕi%r(lœY×NÏ+i¦^L«U3£*T¸¥–³)Ö²÷›m&Êt2Vø»–½•¢®”¢&†ClC8M$iL¥âiÁã[xR@Ûeæo$Ã)ƲFÞVèôs3S"Ôã#,õñÆpûèD’±M9&zK†¤á72] ƒÁ#,öáæ¨D]Ê4c:Úo¡Æ:Ø·gË<ª›8éi Œ}Ȉ7¥;ìOX°ï¹u¶»8Í'ÃØñÎnš6ó{I´‘ãzwÜݩœôÕ™'[oT4Þø<,m½M¦¸I®g%|Í>™Jg8ûLîÉo¤.2I¬ ¸†<1Ⱥçq¡FÓºll8˜)÷¥Rù:¶M”PÖÔ9¦ ö3ø3”6°d,…bˆÅ†ääcŒëVéJ¬k«²ÙT·6ìÙš¶÷ØIG)>Zíóª\m,dU))„FñVƒªBÁ–†#, °l$J‚¤¡¥H‘"È­ÍAg4º©J®AWò† µcT‰`¼´˜§öUG8ìhX9ªz©O%wqm»C±vk¦ÅGwF1Ž<¥jÆY*d–AÑۥꉭÒÍ76èUÛWi5ƒt®ë®î)7Šå¯]®L´í<Ýw™W“bB·S[†Æ»Q ‘!#*…™O÷èd¤Há”Si¼ÜW¶ÜZÛÆÆRÚeRHJL‰³XÛÓR)šêZéZYKLšÒÌ©UFŸF¾~xMEª *f‹mjH@$‰RÞ[ÙæfòÐW刴&­HLPCŠd]&AC…DÚnm#1]‰DJ#*D:¢€2h°CtWÎ#´ˆzNãÛ`õg‰ê!\׫WêaKÞ9S@Ð×î6ýY‡†°O¶0L'œ}"Š æ ð@¶a€¸öÚÖ#,\`óG®¼t±°51bÜ  U$4~ufJš–0òj´ÛN9¦*žGª½F‹—#1Žý½Z†Óñc'Aü›û4³;é/*¡‹‘`\qº8qå™mD_tO;Ý<áº:ãæ„Š†÷·rY¯ÃûêÙ×^¶h ÛY Ì¾ÜŒò]Mø”£v’‡w Š”®Øºë|o^ÌÂßݘeÏã}s @ßD“àh1dP /°B¨Ódìï—|»ÏeÎi2Y|¯W Jj.U«¼‘B +õ”ó#*©ntÚ ù›5\ÝGI¬6A9r#1T±Jýå(CÕÃT‡hŸhÌ"ã)eš~q>çÚàXÄÙ‘bh=YŒÑ!"ëÒ%»ìíLšñ*í5+ݲb—]<ÂèÀ™È6(nÆñ"Ê~Ä}¾…b\èû2R®j»õ?oÕ47÷qöY¸˜ì#1“8Tø*b¥ÈÁ÷Õ:%+¯ÒÏ ?kˆýYœ6ó,’3¦õRiP:'¡¨¢Àªñ¸@¡Õ­îý.ªŽnêÅ©Mæ³X#äHšëÎN `¾¥âD*®Ò a{V }tC|Êêâ’T’HH%H<»€#*bÛª0m¾™WuÕr§Ü*`7”j‹pOPA²'_:]‰®Ö+¥W;ÕŠ³'¶wËîÞzP²+€,78»ˆþÆòÔ¤†E‚BÉBïþ+·f[Zܬ¶(ÆÚYIQ‹FsU@Ʊ¢&F¶h4=â!©&·u玽EFÍ'³Å½7¥¢òFrN6i£Ž!‰†±ÅXƒVFA4^XEXÙÃAƒnÛTŠ3› ˆl LÅY^e£ÈÚmW¶Ž#1H“i4k¥Ò@É‚¥«CÅ"“#1˜üõ#1C\R7é©5A5Ð#*ØézwÐQá3ƒ·nÑë €jÔß9D"œ]¡cQêÑí@[í}<{È(3Ntâ‘£T•’®3;°|`&Ø$N1iWtz¡ÔT®ßfã)w>¨ôièVg•B ¤GòfŸÃ§ÚüÕ4q¾.·;’NtÌ+É[q©b*¡¥¯7‘Ç&ä…„½´/z„¨ÄÐÚ7J6|c–´Ò¤ÐÏh;bãf©,Ú’VTÊÁ\vñ¡¼ñäã§àõËßœ;Ð<×Óâå‰ëÛ²òèVÞx¸G;˜¿¤°âeŸ|щ´€´Å¾ b¬ISöC‚°ŽtñÞ|Èa¥¤Œâò`Øn¶™µœ…ý☪Áø|%lMiÙÎ6’úyyM3mW­O)1 š””ž-íDVCCpš€P±Èi“(£Ý3€ÛƒëgcƒßÏO„ê’äOˆº°]X ¡T2HÎéà=G"×mãf(¨4ÛiÄáAž^Èž²…ps'GΉtB©! ºâƒj#‘VµéY,×JÐïS°ú_¶* ‰Ôôñ |µ$oŨ0dv}œMgŒ]­÷©ž’ƒxÀ"*LÌŠklh³u8J&‡&(‡­•i4ªƒ©;óæÏF89 ûo{ÈâK(€®¶¼#,åá´€W=@ðÈRÀ!€²ŒŠx£$–Dªœä°®GëÄ McöøÂs‹IàrÂÕÏ~k2#'u74Lo¦‰¢:D’#,Ÿ<ƩÀägnŸ†!7FÈå·Pv8jj n`Öœ‘¬dƬdBî3ÉŒepÚdÎ6H˜saÈÄ–#,DÈCû€8rUb*úh¥^žeê,Äôöœ3»¬ÞVÌòT.4îóG{h¸j¹»‰7‘aLŒ…#PŒCP¢@èˆDô]9U{WhDÐú'hDÅRË Rd€y9å3Ó‚Àˆn.ôc(ü#*]ÛI:‘Þ#±æm(#*NqÕ‚¤BÉEN#("»ðX¨2#1F&µLXÌQ]Âbá(QU«JKkNzîÆszîLo;®îõ•ƒœSÍSç¾æ¤Æó`¤TÚ©EUCf-zkQ-¢REM*u&Í`ÆÓCmt„V#1'Ë\TL’B ²!žv¹ÍÄÀŽ+µ¹,Òçžu ñYéº`(0žž¦[%¿.…–’j@U&j˜*ÈÃëøàÐrw0K:{ýH… #O}Ë x‰Å%â˜&^·RH¢‚bˆyyrïRmø[²&f$'zò½j½jé%º¶ÑÕ_m¯H¶*µç©àŒöï)xéݸ¦H))Š ”A. ]Œ”’첊,dl×Õ[ ¸H‡AGtWÚ]MÝúl]š<æcéúvñˆ1.³ÀCY®äž^3§Vwª\i®0;άŠvµÛ@ÄŽ•L•~¼½/kñ.³!›4[¡Ý)6°Â¯Õ­{5dÚ«#0ÿr@°T*™23a²I-Bh€Á‚Í(¢Ú«”fÙ¦“MJë¢æÝLIdlmѪýFۘň­¯•(ª½+ÂäQ-€0bÿ7ôÕ¢¬ ¢Eb J)†(ßá—#*‚¹ 0¯–(sB̧»XLºífq!”…²#1Ð)*!C$@e§Ómt!>Ô2Hæô½Âæ#*§™‘”„.$ò›,–Æ3PS#,bŠCT 4°Å Cû±õÁ¾èÊï¨Ö7,#íÞË`ð7Ý—®)î’Š†¥ýAµ‹JPñ†¨B:äŠZ›l*~5J£-U=4T*éd“W˜fTnLX1<#,h:õ¸;ýd‡ëÛP¨ÔB¦ÓMw]±´È¨ÒmF©H«@ ¬7{wJò #\$lQ¾X1{ ¸eË7#ßPá\05Ý ¹G¤*èLƒ+(6ô[æŸ/°7»ÉÇ­#ßÀ„ŠL¡@ ˆ(À°,ä]ža’~xgLüqõÿË\ »]"k r-¡qT'?oÀÙŒ(4d @A(ÿ„ÇùoI&‡?+Ÿeú››yÜ>@s;Õùý¤"ÿܸìôyI$@S´€)+¶¹[jém¶-l•ÍµÊªÈ C4w£bÌ Å*+"!\„Vš†3Ýne2Ù½ïkϹ NR73%t`¬PZi,X)ÀÊ6BýyÔ:ŒÂ&GqÑ:]­ìSòûö-ŠÁÝ'Ò<Ò M©éOjQ¡Ô‹ÀÔ9—ô¿˜r‘PY ¤Àa(`C­ø–ÈwGÚÉj‘BÒR+†—‘D‡oÙÕñ>Y…Þ)Tbb³ðóôrâ’p,°qDÕ¹æp( ^˜Žqr( M‡¶ tÖnð”hÔ´±_vj {ÃNYvå¼êï£ÔŸ‚‘;ˆ¨™’"tŒÌ4í%z´°EkãE‚©©h¤sU+ùèËÎ̤ÓAþ"ýn¨hÃ5P*6ØH!³_ÓkÈá¦`]1¨°–;²Vha–…Å hÿB^ߺå]j¬iRDd€¦×Pï‘$Ú̉^¡uË;¾¹Zcm¦×iÎtÐc»`‘Ã4,Â#12dµÒLÎ.í©0ÂL‡L0Žõ e(G˜˜éÆ‚Ú¬ÞThÈi¡±ŒÊÉX(Å#Pš˜ÆÕk«Q v sj6½×*“]òí\­¶ödA¹ª#1³–”y1†&&ùe5k¤Õé«{µÍ´[pƽ›Æɵx“io"Œ ddg9\±í¡  Á5KI£•hÌ „´µ‚ÙK-Mì¼Òæ®—. #1•- Cl…¨±7ª‡¬«në ä#,´uÈfâJ¶Â1^NîÛ–ÅËhÚWth®k–Œn[šæ$Ƽîñql¢‰6b¬)%ã[&‰¬ÍÕ †cV`±˜ÂaF£:‘vÿkY†™tU1ujMY”,aË.Pd+I³«nHc,q‰º5@€ák[R¥¡É–fΘ¶#1*kR˜"HXâfæz^à?× ûAƒ,…æÂ2C0ÄåÇÈ•-¶IçR`B扭–?š’˜F:d£ùú²·kÓàÞú:#*òäPZl#1 žÀÜ~èýíƒD,Â)®"½‚D`kçýüÓjÓº5—•±©RÉQfÛª£¨“%âÝ%±…b‹–ªêV5b–£B°‚DˆÄÉ(€ÁZʃ¨ÜUXµ*H‚H¨þ%“qõ'ì €§"õQE!c!ÿFóÀû^Îe€Ô~¸*D~]#,½›R#::Õ Äh¸¨Z7aq&³Ž›0¹¹aÌ°oËŽuÑ>˜½PR ¡§Î° Ê/âëå{«™XU#,œunEØj!ä„=Ã`ì+À‚ZT ¥ªŠJ4¥¥*Ucj´×¼®ØÓUšk)êWQ´ˆÆ#1EJˆ_ÏCÄædG£¯#,4!Iðaðk/‡+õ)0•p4'‡ÛòHØ}¯²q:Bðý$Gìó°üÏj3‹£„Þ«z§t÷BåÑëÞœ°ÆXΑ#,i™Æìý’¯ —žxÕß(á#Š8ÆÄÚ7ß8À*Ým$HŒŠXP]X"!¦#*Ž×*14ÄmÁ•"öQõ\°fä”I®ñ%PØ 1‡Áwû„Å=_tE`u’I$‰ 4œGõÆä¤qÃ7+q”:}ž(©C@¨@÷Še\ ¿„ŒŠ0”ÔÑ$PÝ0ÂÔZj°S7ùÿF9ÑÊI³£¨Ïâ½LòÁGYW'XtEý» 4-#³m<8×K\„ØtÄb5)Ò͘hšàŽL[èÛ[L Q#** WgÆ4®…DÒQ0& @1aB؉ Ir¦w²”Z¦‰æ€†>ɲü'¿‘¤ôæ8C7 ÖC<‘x ñ‡ÖéåÕ©¿õÙAðùxÞ×Dÿ‡õre]f¥ qšÆ{ źw×cæQ­šÓ>˜jdêêèOJ zŸjjÐUÃY’‡Ïð#,S†«MÍöÕçÓ½WêmF‹aÄ[(0µ%&K4ÌkS[KRlkFF2šüòº “DÊ™igíµn[S3TÙŠed•²Š¦%‹lª¥iµše¬Ël±%¬ZQM©˜›5Y¢iªm­±lih3i³Þ£QùšQùSŸäý#,'Ø#,’ØÑ!EG9#*=QN±(„¨© "PJˆê‹kº•Zæ·fðmæ#$ƒú‰x¡ô¶ 8!°zŽþ¾¾Úª¾®¾–·5s˜Õ¹F2]ð#*¹‡æ »"?‘zœW׶©ˆÛÞî‹3œÛ˺ý6¹//ÖÝP.|×¹æàŸ>DÍ\BE!>ÎVª ‚ŽÍÅÛE/iÐA #1zøeÌãïé³ZH‡JÕBü8ùE>Ù>]  ñ‡Ôeµ¥nâqÆQ:ðÄ–êÚ2’!ƒ®-uüüŽŒT‚ˆB^ÿ–¼8çÛùŸŠóiçA h)¬ß‘µ¾ ³’»ªgOÖoæÀæ>MþŸUË|-tœõw–¼¤ÃrêåÒ[ (=ÿLvmZ‡É7 ¥"†1–V!•Ø×à]zW“å½k/ÝÞœC¶–ô$ä÷ÿ¦b`]ăÆ@|s9Þ^^[YIR–fü]u¾!n[$#M0©Ø#,RFÚ`ýÓéøþªŒ‘A³3݃LoˆƒÓ‚X[,{#1ç·v»¸Þ=6½/TÒ¤±°¼H>¦#IqF1‚kVžë‹yÔõ—ˆa¨–Ì™æªÒšÒ»þ…abÉ h•A#*ΔL#Rx¶„ý¥:£ˆ‰¶±£™$H˜¡õÅ^t@Añô#*G^u ŠGd#1xÊLçìÒçŽeéIb\&p5p½s¦&ΛÍãCk“( ,Àš¤Á¹xÄë;Æ„¬J‰Œõ*Λ››j¦¿Æ „7ŠØvïFˆ$Aä@rð(¹iŒ„H¢DEÐ2¡0Pe'‚Î#1Pzï0C.¾€ú]½¾$Núª Tozv –½îæ®Þ7Øù÷·w]ôžÄü“<»„#,6YBF½ºÃf‚Г@­4Á`®µ9Ѐw ØìÛ5h¨rÌÔ@<°Hy{ ’LÛ "Ȭb£“d«Æ¹L®v)¯SòK{pô»êl$tR¢ZªlhŠÙX–‘aÂÂ㉠* O&òå2Ryç˜m÷$Y䉶ÊâFpj‡èãeEs\Hˆaï*… ¤aC¬è1—v´i›ä»0â—g3&¨A±D4*Ï© ODÑCtd±N4i9Öé&SŽÅ@Ô ú¼C¹¦uK@ê‰ð)È­Ýʯ¨0¨ùR/ª"*ãÃCl¨m+—*Y\Š-†Þ´Ÿ¿wf¦#*"|é‰UºTöš‚ šÙT8­‰öÛ!8¥„ò^N£-¡¶àïÝ$%‰“fÙu¢ …µ2‡++¢Û­è’#RÊÒGa!XA§b<úßÍ„#*åö‘ôÃô0Ü!Ë;5*TNI©¹FlÞâÁÚáS]2ÂÄjÈÉ9€`ã)Û&–@ÀYöìÅÓ4±)ùgNÊ4Í=¾¯Jµ:ê¢N%ï½ákK•­Bhå–ù\Ë6Æ×@‚jVÎŒGdÁà–ÊÎÞÙÍbN•S·a«ï~ÆPyøý7#K8JFº  VF%UAÇj#1°ôöÚÍY#1‡Í5"”ãÔrã¼ì4÷å—W2Ÿ(ײ|åBú‘2˜†t;mïIðƒ‹¨óÎ!Wžݶâªøm£S…Wô¿%‘m—›Ý>“Ák}LÖãi„“dÙTA¿G”Ê#,çúúñìõãò7»öfûÃ#1ÀgX”½T@M 8XN¤Åí°¸ã|q½ÀÂ"ɦM¼b}:ô1‹±Fz«8›Ã°˜wdÌ fFÃXf­0ìpd«#,‚VúS~Ç ÁmËD³4¦ žóäRø˽¾­±n|ÍÈ$/çåŽ-»~’8;ÑÈ築-Wa“¬]¼Ž5´“<þR÷žßç¯ÑŽ9ˆ<‡Ï¯©Ùtf(š¶uþ^ÓÄS^´GÌñEGÝ‚!p6m=ßeÃÝŒ#1NÓ0¨^b!”d%]±‚,ŽKF]™íÛ4/„"oâ²z2#xõfå$ëΚÕç’8VXuŠkC6öskë¢Hß39¦îò÷‡HT`¾p\`ûxKêÜðð¸ÙÉîBràC—j_¨J~¡á Í[Ö57D‰D.Tî‚6Òˆj7?å¯Mc;§˜¼:æ>Kãшð–àF1‡ÅÌ"g^ÕrÚŽóÏ#1Å£]woM·4A¾9,™ª%¢¬(",!/ÚT”;°Z9ûõ3æ9QåÓC @·#àrÍ€~"BãÿÞ_«²]PXˆ x k ‹„dÉ(ËQbH$x£]Yçnç[¹×z©«n–°ÓÀˆˆŸ#1ÂààˆˆØ—DÔeH8Új>7®eϯ¯‘Ï.‡©9 Ôó]9*I0øüØþfáÉ5ilì’¤Mè{}Û“ášE>;¶råŽ&é£çys™ÝGÆ¿Qô44èÓwR`†ÚÔYrå9!IIä¡_ªƒÚK€“¶©T8RcB€@Fœ#w#ÈIj¶"üCÅ£‘¯X¾,5eË%QÈ:Ñ¿¹À>-'Å›ˆ6ºünÊp*]oÂP˜ûrr“lj‚™ØïÌK§ƒ‰6@œÄ¿Ku:£]¢±ãA°Ø–„ÎjC"k#(ÅèS Ü8>C¹Ø5gS)d,¥1§ÈkŽú¿Õ¸=bwÁÎe±áÊÛÉ·2Œº •ûÜ7ξ¸\™Y {ˆdßï®Ón±ñ¤ó.mÔßÑëBÆEØð9zõ…¼¨W»>N#*#ª"^ܵ#,`ëZ­ì[¬걿Ê24UˆÁY† <¥Mö¨R~l뤚äÀ.4ð–#*Úk›F#,Æ8õ§Î!œ€£/דöÿíþ?›~Vj2…,NuF¹Í¨‡6 ¤e,9Tˆ÷A>Ô–©#1jŽ™j««wB†’A°-m‰…ã ©Ök/h D…X>­³3#,k𺵠„+Éy4#*jAAXËt¡Û .°)`ŠøÉÔåËkÂCì}ËÄÅ¡´ÁëX>Ú(E#¸¹ýK#ãˆäËNŽ¨ˆºØ„áóOúZ DfØÓQV$…P¨]âò^êÀx I$èD˜-™`ðĆٗâòß”0dL\¶5™º Ó®ù0"À0ö1¾¬í „¹ãAµ\À‡OCÆÍ6€›¶ÐÞ?‹„Fáw/N–Û}zc(˜ÒÃ%cŒ/Ñd¤À£>ADÎ$†‹è?]¨ òÃ5‡ç±¹á¤^HAY›&dl“HTý5rÀê ž¯Ü×Ypê`ñfÀJK-]’¿á†aº„eŽZMm«G—+©c(çö? i é±,#‚†AŽ‘ÇjzDETð{†bÎ ,&CX[‰tce€À±‡e>­á]L†pÏnZtä«„ó\ʇ{øÉ/$ /ã¼®ŸN×Ë^^  AúH0Œ"¯\U#1’†$à<8)’ ϯ]Ç#*œ¥TT<ëUÍ®Ÿ}±xÚ-XÚ£kX­FÑh«lhÛ&5IZ+%¬mjñmnm‘R¢*ka”.GY¨Ìx÷ývç{•Ê£Ir v"‘ˆ€Ó"Aûô-I¨^`Ai ÁñêÚp;[o»~ì3ˆ›ˆ7,àî}EŠnµî2D.ÄšÕžJÜ>ÃŽ6˜1ûœãžP¶ëú§·ÖáÕL|@;i«©ä<·Fo$$†ŠÙ¦4ƒÁ`d#1Õ1>ÌÞ#ˆÿh{Ž±#,&ú5ú=€ $a¨óWÏnaæ‚M”"”ŽÒƒar ¨W2[®žX©¬º?f‚nŸÄBnÍeIªZMJœxé9‰Ál€vH?#qË¿M¾D‡˜‰Ô=4Mšì= 8©73.µËÓLGÇVö`Ù´&©ªVÍ(·ü{^ºé‚P˜6u$HV½ày›Çqÿ«mõºÙ¡—ª‘#1‰º X¯×%UIAäå#ãáW¯&s»™zDÏ:£z”“d™Ilè€~t¶BÓX pRëb”2¸¾¡Ž»„Šês$l¡?Ö©h(ØVÃXPf$n|tֵ활t„Ù#*‰Õ8 ŒâÃ2A#,™U š*µB 8ìÏ¿éö»êÊ|\÷üýOãc׆!¬M" „‹°*ƒ#!5HE ëO:ög/–.㇄Шs÷û+º¦Idw¯°ÔÆŪXGE+|•±1é=d(ᣬ3<#1UQhuäî‡nÆpðŽzò,Z#*f/‹õX‹– õUFSµPF:,P3ýzUÿ'X äîΨ÷¨¼sof!Dõžáº={ ©ÏÒuºVGÃS?{M×¥-’ê…V3M(Õ]k)£!L…2UP¢Á#*‡Ü›´›%•æ†\j#¤¥Ò¨¢¨p2¢(6…‚„U5 “‚ƒMˆ`ÆÚ™™´T4Z5×uôÕ:ýÃÞ\x4ž{ª8É´Ø @Ü ¹4× Ã3u¡¾˜³yzc3ïÅåêÞnÕŠ ­zÚéEøîVjK_ t‚z¦•m´ÝwYd„¢Ž i),…  eŒ‹Y¸d‰Xvó^í¯j—+©¾MW{æW!†½Î%J³+ÅdEaFÒbò7ÒÆH“1²ÒJÊЇ¢­$xÈœÖØÆ6$Ý‘ hc3µ1†o×.qÂ#Q¬o C+ve#v6\32 jqŒÚ¡»±×Rµ,!14ˆÁ̸7ž¶¶6µ!’/¥‘éŸe¦I°¡ŽG{›³oJd< sÊ™­ÔÕ#ûSÕ«¹ê€æ <­©šSJ½žPÒý píÀÓ‰ò±,‘á«76¶Œp¶u¤ipÀ5cM"á°#,f1m˜ÞÞªƒ©³ÃK`P‡ÄÈ‘ôçzGí º ùOy̳?ÈÑ„§7#,0á.ˆàɪø =Ùó˦Äwi eÀìŸyåa~ \ó2ûžÞ<0ÙmŽ¹5À¤Ã,L*â¶BÛÅîŠÈcØBÍ×À€Ýq¥ƒÆŒLÕi*›l¬ßK¨õMñÆjIN'É#, 0뜪ÈE£fÖT5pŠ¨å±R…ðZ”bô Á‹bðÃÜDyû¼Ÿ( ¿rÀ4&Å#,«(~õé@»)e k"â €õr¥n2ƒ2ªÝ±ù ¹¸ GßO8a¤)¡ ä¥P04ZQ!$4¶Ê´†Àƒ@šTŠƒ@ÃLA„lt1ÒE#ÉERÅ7iÑ0”BIq)¿ð°B:p:ºÏPuÇÛ®6»0{>Z¦—hxx¹äðfÿnãï½P{z¢Õ‡û1bºe2~L,`U5ƒÝñšcDɯmwn±G±¯«Jmò!Ã&ÒVý_ÃsÅÛ xµlMHŸÖúyCɽb¹ë4<5£ŒÏVÓo=»º™)doowIØrãór¼Ý5xôóz¹¬š¸Ùs«"–U™/ É)ÃÃÛåКVO>ºêf–ÿcÙ’·33nN£mçEvÏ>fùI„cn3¸ãG!hÂ,Cî.GK/QŒ#,¨°*°ƒ&cŽv i"9z]#,r$‹ªè[•÷éOƒ¿xð÷˜"ƒŽ…ÕA¢w݃ 7‡ÍôcL˜Qü'DI ˜üàäôSySÜýýYÙךnxàˆW— íš…]sVý–qøÃÑ=)¥7eDL´5ÒˆCÐßíõáš'ÉŸEHðÇždy~Ê7òü|—lC¤eÀ¦¼A„B`znÒŽ!Q©œù{ÔÕõÌzYqô¡Ä} jƒoH´m„ªVù×ñµcVÙí0¢6„º…’ÀL SaHüi¤/ˆ*GT£‘²)Hzyæòy[ÇMãmÙkpµºZ¤µwŽ‹cWr髵·6îÜÈrêñµðË%‹HÔŒT©W8î«»ªÅ©6Ì ¤-ˆÀ‚2„ RQw-ÅbŠ¶ñmoV¿"ñÒÝ+ó{Û¾ö›¬(ǨØG$R_v)Ì÷á5‘m$‹E"0²ƒP¨‘„(F˜ªÁ-eYé’#][HAß*ùZê»Ü´5x„æµÚöÚòfIÂ@1 ¢÷–úe#,b²«¥Ûi]kÙZˆ¨µJST‹øTSe±Y‰šR¢Øª6*f*65¢ØÚ̬4cLÕ&ÉfQ3&%SEµ3&ȱ­³Wªèß{ŠºÈZ¾³ëá™ ~Ý÷ÁF"ŒxÂBVÈÈ* "°XBäûNþ8ý/éõãgÍ0Dr»—Kƒ‡çÁC NÀÀn 12 ìefk#1 Ì HK}4p:#1$(„H¶’™Z7äs}[ÕÔ,Ѫ¿Nk~Ekp¶¯º~ïWPZ4Ï7v"Úwvék»IMµ¹m£IµÝÕÚRµ¥k+×nÄbŒ€)š>«?ñHf;qN çBâQëUö…#*C0ÐC˜š$& ‘Y$!Ìظ“y8æHKU@PHhFA£{T,!´ìçÀ-©(GJé1#,vÅ €™—κk‘fñÖ¶!4ž€õ…>ûµ>aÖùñkÑ6ãå‚Ƹäùæ?}z(¨…Ì]hʈ°Ÿ<Ó`û6Š¨þ†pÖ±£H.’Ìc …¯ºËÆWs$ÓP˜ ƘHX3jiº8$Ó ÉpîM¾ŽÓ)Ä¥µÜH“©þ‹œyø÷­BM½<&6)¢ ˜¬vø «Yxsà*Ö A­¡ÌŸy]eØÚù»Þ8B˜²^l3&$¼‰æH.{rmi¸|XBe­óž­k¯™J뇣Û+bz‹Mì0îe8Ó-»=ÏÑ`«ûdí¡XÄ‹'‘:0!ƒ¯\vîVCèì7^Wª‰µM™ÆËgêÆÓòñ¡ÿ™XðÁP91V-ô™–SªVÕJÅRÝ àiEh}b`hŠp‚|ñM²Z¶+F©-¾t¾úµtÑȉýl°‹•èUʶ&p°žFÙ6ÚÆÚ«•Zòºóêò¶0­—«•§â/#*ߎþt\gÊ$ ¡sÒ¬üÀñø3/ØóF m ‚Ù-¦ºí=¸±kc3jºZ-…‰NÇ),‘”0”$ÊcJ‘GU8 †TÈÀŸ`.E̹ZßQ*¶Ì“Ù+Z¹¦±|½²UyÝW=—x«´ˆŒ†FŠR¥ìÈñ’M4„Á ºŒ#,k7p¬xi;XÛ#2ˆ™ƒm¶³V¥(1Ä*ÛAÍXU¦D…FÆÐ0ÄÂ… •Q#1#1ŠÆ,—€ÊŽXI˜…vU‡úÐ#1KÖ#*K‚Ê¡t g„ðªÙÝÊH(N#,1ˆ‚#1 =D²¤€g“ùquòQZ¸ÆÇìÙð?^ïD[TáðkPõ²Ö“ç§ZÅÙ0víÖmžFpAÊ1ŒÆ²Z»t÷oÏvˆÎÎ`X#*Tä@m«ò^#*‘*Þ­_Š¯Vµ± $E7~~ÀðÓ?¤øÐ*‡Ô?mÚŒÇOöþ ñ…²/Õê†p¹ô²¼#,tOwõ€"ˆ¼Žs?­¦ôU"U0óªºJÖÎ߆œO¤½,iÈ1ú$7ðòÚÕÖ³æìß­AGB®w÷£xàt׃tûYw eËÆ@*,Û}ìèúBAlxÅW§MgKãf@_dSL†à É˜- b2í3±–P!§€h8ÃÙP¯L|Ta÷5X#³# hLCZ¢«x`ÒPmgbèŠR‡‰JÒ(Á9"ªÒÄ^•HÂi …Í°`°y~#1‰x¿xE]ppæW£W)ÛPæÄpÈÞÛÕ£ Ì>%S§9Œá$ïJž _Ôþl×8#*cÛÍWá”w:æªéE«»Yn#1¦F!Ñ(b!V@Ïö]ð¤¡#1Œ¤¡é†uëü×=x'H@âáQ¨#1Z "£D!Qæ,„è~\IñbØÚW¯|óÏ4ï;¬Œ¹já¥wx¼†Ä§72óq´ÙdM$„ÙRÔxÛv›dÑb’“cÃA„¹·+›nnãºo7—n:ë¶c •ÝÛ¤W/ñäÛ¦Ëy<–êåÜÖeÝåªm¨‘çmµÍË]5Y-£R–6nSfi6Mgݧ5wft×$R§vè9WYs¬ÔZ4rÀH%!¨#D£ûlØEw7K"ìO\á³ ° ¯fßVðh@ö‡aê€Ø‡”#*Èÿ_pwÂð`Äj€ ”¨'k,-ˆˆ/°ÄMéÓ5Ýœ'¸;l¤¤‚ð$R 9¾¨÷xBz½7Øl÷ZøšV€|"_`‡£>ñIöСAù{÷'çí:Uø¯ØÕåko®«ÌÁµF1!±.T²#*• J ³ÿ rÏôÀŒ3^î6S!DXD"„* ch #,äÌp*Šýz­-|¹vŒd®[·:Ôã®î¥•‹ní¯R׊òMø¼U64Ò†{‚»–H•`/O´‚µ|¥é«rÝ)ç[|LHÇ®é“$ÍÄ^ëV¾ž·\Ú½ýZתèò¯lô£I!F¼^˜@± ŠF”‹5Å°( ZA¦0! ŒT#,GTý»—12#1SçJμáDÿOØ_ŠhD„F1X¥ÁóÁû&£ÙX#,@nèÓ8»ÅU^È‚ÈU !,DbE#*H#1@°Hïn_"â:dÌGEXÈŒ B2Ó&j[Pµ¨«ð~­ú™WÙ«çU¦ú¯Ñöûê(¤Ô–™Œ(Š P‘ˆ’@#X„.\1¸DýptÌ×jgmf¸»õAI3ŠšìP¦€Ö?9ÞƤ’l#,E¯;ê[ÐÛÓÓÝómÝú®‰ñ_½‘‚|È@È TüĽïÓß_žüï$ ¹u²¬ ]à¬×èNEÁV"#,#,‘ ghv³ž`h5HOºÑu`i¥Õò1±E!$œdR4ã¡É¾Éí ~T¤– u‚tî9ÃaÉy;èujÓõˆxQ>°‰àyko#,¦‡h}h:`¨'ù´éŽÄn¯Œ¨‰¶~š Ò ;{ÁD܃#ùâ,ˆ€‘@I롦(«d©áj"A#1h@¢vMr.iMƒ±ûà-ö#1p ch}>Ë8`Ù«obß»ïIï~Møµý¥)&ŒBÁS4$ø"|ñ„ÚÙò‚b*j> *jÜñìîQö?ŸOì³a_¯éX§EÖ¥~C%lt_ªô:ÿ‹E1­îÊË·¢éŽæðE”dMæß鹬9wIxl¼ßi5ç‚A›(77üÍ“)|…¨Õ·ºÌ."c•M·Fª¸jÈ}YÌC>eQ¸ëœÝĨs\ò¶6ÅУÅ"c"ªhœ³ÂÌJe;ÐpDIhñˆ`®£\¨l‰i |³òðO#*ÜoÜØ¢wcœCîûÖ×=l'Ð@11 Sä3»ççé5å~ØÓÃi#ï¥py¨‘Ï£Ï⼧¢·Œ{âӖ抣Ù$Â0ü;#•U9±Ì¤KÙüÕÁ(Gï~0ío_Æ>ÄÅ1÷²ÍÖùJÚ¸¸é‘ìhzÅ{Ù.ÙL7£L€ÁA€Œ¸Êª0"ZcÓé²9uhÙ1Œc#äñ#*Á´–&õ OK´fñÚZcÑ&“F*h;)ÝÃ"ÉÍ ìÏ®_Lš·õ±Í;£‡¼;:!#1¹7Î5–À™šÑJ.bièÓ»:ÓÍ/oÞõ¤ó``WÄìW2Áö$á@û`ú»5 ”gâÉÛ µ{ðç>ÛØS”#,@Ó5׈ãË´®Ä<›ñ¬ÂnòòÍëçïÍã:j¦hHB™38&y#¥È-ÄxË’x ƒIJqLB XÒ ÛÂ=*~™u4½ŸÍÁMdŽó“ÚüÕtÊäˆá¸r´B!‰@6‡‰R¤}Š”hé«1¤P£j¹÷rËè¾Ü#,1˜‡OÙÛñHyªŸ)Pzx#*s$Eù[ÀIõ<zÂÿ|€˜V#,ß"H!"B"È‘YC»qzº¦ÀŽþX*G²»Ï¶½'¥2™º€ŠpDÛØpcaó˜úÏzvË¢¿#Òna¨-ÀÀ{™ý¢Šb*¤ ‰Ý¤b6áÜÔ3®ñ€žíÓ„šŽÁÔ+ú†çG°")z’RЭ&1ŠB@q+œZ×»oê}¾I‹K*§…Ÿ¨³ /z e,‡Þ–ËvºP4;‰ôåÇÖ#*•$*”&Ê‘#*,¡¨xƒ¾4Þ{èL>¸'€Äðþã¡[8Š€…ºqóI~1î‚Š™ŸµCLï#,ºsµôj|Üf†5ó‘Eþ¥Îlàd]`1sèUÂÙæÉSŽ=`v~Œ2q®Ž¶ìb cŠö—#¥ãÝwû_ÓÝ\=¡)?Ûî¾å¬ïbÐ* ]ÿáÕx;$&ôí~k·K(ì¬$â¯#$o‚l^;àe„ÉдI«H‰sŽ <ðU¹HFjT*„‡Æßçú¶ÖÔ5zný¬?‡#æ‰ýù_îú™‘°¹Â«Lr.RHæD¾¼ºÄ¦;“Û¿QÝ7¬eU8àÁaããÕ€^ÁÃÚÄkºü™•xš^*0R;„¨ã± ê0ŒÁ¾Sƒµi8ÕÒ¢Ý š"€È®ÇA¨…&liMHÅ-ΠŒàù±ŒcÜ5T]Œ>ö¸±š~´ËÒl¦l@a¦Ä3’£TÑH ˆjãÜÊ+#ÓÊÜÝ'Cd|Iç#[h5x#1‰_3ÐÃk9Q‰²]ò|i½Ä°¡_LLB¤Ì­~2”º#*ÆõDUHOL¢§ã‡ ®O‡±&ºÁ•ŠZ²Ø#i‘Lg‹Tƒ±x:vÜF#,UDI-‰¦u0¦ˆˆ$i-ÅA‰sŒ¡Ch(±%EQ‘R`ÀFÄÅŒ­ÔŒi#, ØÂÓGÚš’(R?†ðçÄ$!U!Q‘*Ó¹Ãwvñ?ƒÎòéQ“WzêéoäuÄõr;§rV;ç|[è¯Á´”j-¶(Z›6™²É“VÖ­T²ˆ~Ú)ûƒ…ßè1®CN¥4¯Ѻý#*2ˆ,AƒßœÂ@,vàEÔX·Ùz¨£ïÅ)TOMkú$ªÌ¸&ÑýA¶¤µRZ+SLÖm®¾T¸"…ËkÒöNrDöÔ¤¨¾¼Â#‘9ºéõ³Œ 4¨,ÀÈT"É÷N‘+îd³ž^bŒå#,0ÁÊ€Ë$ ›¯tëÉûí½zî(»»b1±­Õ BZD Á·$ ÐžÅ!F†Š Øe1´: ò¶pštŒF(N¨‰÷ÈX²ÂPfj5ݘrÁˆÃfñ¹()¢ºÉwÃ4Y6èþï“XDlXl¤Íµ61.ÎòX× xÓ{k¯]Ê·;E˜#,¾/=–´òp‘d³g‰‹A=Á©R¨ ¾ˆìƒw|Y/z‘Û¦/¤b8 ó¶œÎ/·W†‰^¤­£êP5ý?¿P|y IÊ}úñ2T:™p^#1jŠ Ø1»“¡%gÀïAÞ&¤Ähîüzö½Úñ|/JÉÐð†*È”AÖ¾ïÆ)ï=#ü}Úû#*ýóâS g¯®ïçGë:òîèýσêv0€z6UóáêœpøØLm3¥ŠozLWЫîÏKoϤs¡ †Gw’þ‰¼È?¼øŒc4šñG‘rA¨ª WЂdç£ï;/i´<$2E7Þ¡ƒ”¢ v¥¶w*À×`LëuX©¯¼¡ë€%DSsujÖk¬¶ØäP<:|‹á‰TëÎÚäb„áfD:#¸Ö%’¤ˆ&V( °ˆªŸVCæ1#,%§ZR©D=•S;zRåÃH«és¬k"ÕU– Lè0ßÛ‰cZb5sTR`K¶¢Â~†³ÈßçHœŽÈ­írm± ± î1mÿTp1Ùw†»y×KÅWH»¶â²QE¯ÚÉmñkv%¹wujåb¨Ö4ssk¦ÖÝ5d5®›kšÉ®\¶×6w{5ÈѶM¨"Q\¼YÝXªþ`Éne#,ÎÖYwa¹8ç„=¬#,Ù'Ð1h¨æ#,÷Îæ™`aðF9ûCä[Ã#,ÐKc:FêH„@ÝPhˆ€ŠÓzÖÿ" ]¤ŒÝ»·Õrü3|MT]õPå’ƒíZQø*9ýȇì"È4Ö¾5$±ðSè2w@d#*ª¹kO§ówžü×&ÖìÒ×q¶ë»Ž×H¤¢ª„îï.åJ%¥Õ 1Š‚#,€ÈÖ‚b*’ #1#1B´V‰[]&ÁiZüM·£^·ª™Bƒ!.Þï"¢î‰ç0$dÖHÑURU±«ù×ç¿Eµj°h(:ƒª„ç#*OPkü"}TvèQ«4hÈxÒ6}Pˆ7Ž8þYk×ÁC¤BRñ#*t#*îÉ™}Çp(º ÄŠ‰ßé6¥dÝg<ò©3Ù¨3`Ð9ÀFDL Sä(P¡ü#)ªfl’JPÁc–HËF“bÍ#,©(¬XÙJJIL›F…6ÖŠÔU±[Qµ©iZf©¨ÔÊšÖ-¤ÚMo>ë×çððîëW¤þÐÐÐË›Eào¿inD˜ÆÃ(è÷(–!„møq€Q#1@†©Áùx÷Ö]ÖcØÒ=í#ŒÙ¢žt¤4 I´…ý:}È쇢œîˆŠ‚Ó#1RµmYR¥u¼²êT¦e ô.õ­\Ô#12 ª¨­I ƒKbÙæá,ï#,lþ·û•’Y‚§ž*“G½ÃlË *‡?åyz¦ʔݥò›ëh.؈\j>ÿð(ü±YD©Ë³eJ[˜þxû¢ºã=.g¼MÓÀ´à”¾µh?àüõh%KÈEu#1ð¦¬ÑU)¾MY?)iß»¶'¡ Ž?ž/9õÌWoÊ×°¦Šënn. ^9’»öƒnûÊg]5ùÎ#1iÏ)yÜÙ‚êÔ°“_z¼å2¬J"2ƒ›µÍ¦Q•,¬ñ…1WZ%m]9Nù‹ÒE¤œù«i`ÎUWdì"¡Ò¤n#]žUQuÅ=ïèesÎÞŽ #,Ø°ÍszC¿'J˜MŽåß_Þ#,ôMâ½I—Â`öœQýªâaµ´Z0RÁ!aˆ4 ]êsG&†­qרLe;zé Å"ö3ÅñÆåvXÂq²XÆÝiÅŒá21§L©4÷qgÀÉݽfÂðÁCj0½§#iäGaÌ1“yLu)½…”Ý6ò§†áMTÐÈèå#1%#,-í/u/ŽP$Ì–»àeÞ©’tóŽ›ÑŒ3z8ùè¨Û>9ÄŸÊf Åz2ìçµ8ÏN0˜€n¨_ÀòÕ NÏnÑŒf˜x™aµžc86ärŠAâ3ø¯ Œy`ÃÎS1Üøè~–n`”ˆ)5½…8[pªæ”*£sD¦»ùˆfù<Î=0^šP YvyŒc0Â)Ï#*é3c#1Q¿·Û¬@ªNÁ®£‚C¿/xÇå{9aÜ;8Zm™ì!x/T:#,‹\»8à`Llí@Çlª†1¸:î#,ÊH’Ft 8rb¹P§ˆ%îà¡TL#q°(„`0Š–¤yo8CR9™¹ð®Í½™ež–)ºÊ¥›¤•`qG=æ26ð•:h•ÖkSACž#*l3T €“ä¦LjºôË 0'Ë,È I‚Y•¼M—0æñ†¾4QøÕZú# šàóŠ”(•¯]XÐy»ÉÇe£+QmÚ¬"õFr‚V]xb˜¢¸OõÌ'(‰„ÎA…}©œ"VsïÎ ´##Ëmu‡:é¦×MFåÒÃôC·”úÏ6ògqÒ{"Ï=£ª¥¥'¹åÁÇhéQB(ª›J"ªjiÈã“MEŠŸ¾úbltËkksÞ‚îŽ{ZíÖ·CA†ñàœœãØl¢½Ýù‰€b\걄»Ñ=ÎÑôr¯ž{HJ‡¬&f!­„Š1/î6äB¿Ð’¶­P®2x™Qs_yÏ2á¤F­KV¡qqj\D=$ê™PSÆ&PUÒÞ9‹6/4aGN…5\‹${uå8TÝÁà΂ÄX\‘¨hM`®Ø™ÁfCEE»£ÎŒž-áÔÉós“ñ8欜ðVóv£— #踄Ä(ßZ¸Û?Ñ`k#1yë;…6!Ë0°‡j÷ÓrÂBܳk—<%ÝæС….l˃‡µÙdyàÕ¤#,Š;§)]Ë<ˆò……—Œá4EǧrÙTUÔ*ðQä[O^&t‡L‹=´«I°nyw#,@jQ„r2ƒx¡e»´#1™PŒ“‚׬„oavÓ8±!$Èß$×w q9œ#,C­A`Bç;¬Ú«$L8{þÁ~*»kÃQ©ã¼0Ù†`nY‚¸\O7‘üŠuö½™‡‘KŠ{Öâ!…ˆë.݇¨ëÁšßÚVç"ñÐ5úÐiG—1 ¦Ú² <ß’ð(ÍýÞ0ÍÖÿ±1ìUT4úÿ„ëÅ-°b%áÑh{W´¶HgÕ=ííMJ©$©Ùë¡X3éÕWÕªÑç#*£Xœ;’'¢&ðàkÜœvŸ2¶¨ÄY‡Í¥B,‹$ùE}­ƒ(„(Ò$³eÞkh°‹dÐôÛÖ“Š¦ÛhŒÐãQ²Ø”¤cT! Û4LVV…Z`Á°À¬£@ÙY‘T "#1cHJñ¶éj¿ Ù­¯$ÔÚŠ¬V¶’R@”É(TÎ#18Y‹"ÈŠ v°XÚk¨¡…A‘QUd*P{Ò_#,óžYÎþ'=ú•õÚ*P œúÝFwxFµÆgŠHdŒß^øˆ_—ÅzoxÛ‘rlkM­Zû–ÑVÑU«•TbKŒe¯çnFfþ¸s¨U[ÁöC5õ]cÇ-–§AK›¼UŒc–(Vê É”5Ëç…X>›nÚçfàkF:COõŽ˜´H®ÂŒ\L‚û&•O‡»šÓ%Yˆg†WVØ)K9ðÌy4ÅBBb®ƒ),Lª"¾\iêGx˺oÌ"D°L‰”)‹I›«R@mÇ6C#1&£I´ÚXÔ‘K wQXØšiÂ+–Šr«YÈdÛ{‘§„m±ëƒ|μÍJâVŒÞä(¶MÕ ,˜ †MAj<1#,˜íܸ1LÔ­Æ&àc±ºö2ôÔ¦™Z:ñÎÖY½ÈÍMi¢ŠµM­kTÈ7&5—IÖÃZº½qsš¶VødÁbC ¸È†óšÕBÀEšfU‹‹KÁˆ¬ƒVl[l2Lé-~;ãZœó“³v´ÀXVC3”ﳯ$ÃÁ1¡ { õkµ7K¦ë'92kÓßÎzÞ•æcèÊ(ú#111(÷"Ñ„Ž·e0QsÞš z°7`9Èæ9”Ðñ¤sš$‰ÃÓoÌ¥08âd€Ó#,XÌî›hÑpV«ƒ,„c±¦x;„Œ‡>©f΃Ý5#1êpZ†Ž5@Á¢gƒ5`®fV&¶æÙ­mÖ´"#Ñ*Œ­N4¡¦–ž3¾€ˆ)¨H7ÛYˆk,ä#B FðI‰È²äA+½TS-7? ffôOLÓÝóp~-T¦Dˆ‚‘)GR˺‡&ÚñÉž Ï»_ë¯uJ"#‘7OÖµ~”šá÷µÖír¸†¯RéôáC¼ìßn3{Ÿ{ÝÕèõw#MÝ'wra«CHÕJŒŒª§<ƒ3ÐÄ[<¼ë¿”ëÔÄö´{ÀêyDaÁ!ʨÕY½øQBYM#,#,o (ôà ü‡O4ÐàyQ¸ø“ñõÔ £ÜÜó@CtBäFDZe´”•v©”µiyuÍXÖÁDmÅ#*QTŠûÕ€7~Ê͸?Ti®ÍÁØ—~h 2Dxrç'Þh#,Åv6õ¡‡FäAL£ f'£ˆm¼’H]C™®Öó>oO–hƒójë7=;£õQªj@æ·V_²¢VüôjÅ-v9…©Ô0¦æÝjßj5Q&¶M¢"²%ªMX£íjµÍ¤[(Rj4b¶#?Jí\ÍYj)E*‘ö%„².üCw^."TH0©C$(ü=yÌÜYLm`·OYx6 ø.…DvZ†™ˆÃsîË£Uø¸º„òôtŸ¶Ö9EA”QQ`1¯Np†ðå·»Á~$°Ô3ôíC°5#1,"B@MjŠæA]ß#*ܪæ#*‘—B½¸¨\@ÔCk2‚½Qáy6©®‰i}§Ln²tPiþCàZ0TÜ1`Czs,½Çñ¨æÙàm&-£¤Žë©\ƒµ¦Ý7à°(&#,ˆs½ô©0Löqªd0`TÈ\_BY¯—oEUמº¹*¨=v¢/è‚nŒ†ræQ½´ŠÈ‹À†úæM~ÊÂ^%4T#³RŒ:Õœ{6³DÇnôÓ'àÒ«„¨“¹¨™åÊ‘8r°2Å"diZ ûì²M1ÝuÉO*¶BúÕF#Ë󓈴.Ic0Ô˜ë¥Â?¥=¿a“!9ÌTÍ@Z¿HTV,‡)qK뛚à2't“ïZz>jíûCñS”ÈHIdÅ­•°2Ý*Æ u‚/­}uüñõ#*"ESÛF\8?ä§C–[äL«3õlrøª–}±mÝ“—3á¦KÈ )ïP‚GT%T‘{ÒÂèˆ#R…¨Ð”@ˆoàww‹QKÄÝÀ*v’´`ÄFÒÁxrîÖóI ‰E¼MNóºb©¶“ I–$ÇH0Œ„!,¤Ã!TM°CR¨±¡ÃH“1æ˜ïduÉ4A¤:ënbª&±Ã…'€–‰¨ÃT8ìÚ¡ ÈÌÍJ³6E˜”H!ÀѾz:û'kíîò|!¿V½ÊÒBÒœ“˜@,lùÚc8? ÍB25—’¬Ÿ=ÚÛF'„j#*ðƒ¤Ì-±¸*ÐÑX•Ù"b)…x{ÃXCX$ŽÒ„éÀJ#,Å éæXœŽ;Ù71ØŽöZw½¬æ!Üú¬çÖ4v*&Œª§²¦,ªòÌ…ýÞýE}åd”P°ò¬Yȱ·e†9/958ãMHÀîí¹z“ã£Qª×³¨bb>%¹C3åpºmbꘉ¨:À±#*: B!9Ò¨žÿXÓÑQ1ÓfÜKµ$ DìÀ¹¡°ãFŽšÁï»TT5 ³ü<˜©ãÆú¼¯¤q³g@Ú.Œá¬Ø;×qÖ˜·«:ŸJd35ê¶G8Di!O0Ѳ„ÓhàL–$›#1ÉrªÑD‘F+<ó]ÙpìË;¥·&ñW ¯]ç•·)zÖɵ™ºíX¼Ë\µ,Т²N*uõ\³3¬‚@ÔTuã%3Uw)aiCeÌ‹0Í-i÷('ju<ÏOšX`BLUoOiî¦fäæã ¨r¬äƒNï*0ôP‡ý• J­›f#1Å=C×É¡ŽÑØÒ*—!,H(,çÃ^A´KÓR|Š>ö¥žõE›èbC€ú‹¢(#1:Ô)„ H¢&RB†iÆ¥°2ÞÕ!ÃUV§„Øb#*¸#*qhFÕ9¢’|ží|É1ák$Áv*|ù\¡ˆNñ!ÐQ,xÆ·#13i¥¡F”šTT(b- ãeªDT¯]}’,,u4)B½œy_á[/iùt›Yêúq¡/êˆwÃL¨:§Ö² ¬úâ"s,F@@IR¥ %(g^hœ81ñß{c埭>³ÐwïÜ‘ŠÙ= ˆåãròk5´S6“RMK-1ŠÉ)A[k³#,BhE6¦-µ&ß¼ÑZ¸Îk‰"H X¥çy¾!¶y'ª8±UË#05÷kFýD8ý&ÿ)©Ìt@;œ#,#,¾®¾¤ÏÍbv9íå‡#*› ’,€¹³äFÉêÀ¾zfÅ-7q™´Oq︢fDE€„½li™’39÷߉Ds«]Î$tªÂ(ß)Œ¸eà‰5-/PA@tDÙA«”㈃Á¥ËXÃlCâ:¾/Tšff¡4&…¬aMl>g~yÛ¡´€Ø u¤j¶ñn1u…º8«|¹£q•…lj‰[ë{ÖÙK†6Ú˜#rÈ#* ²ãb#,¥ V,¡¹ ´&…Ö†ÇéÖíôÅMóÕ#*> ¶…‘ ˆúCS&e@õ‰EÛ"È=ʨփ‚µ¡ó3KZ[­aÉÂ_"èõ&t+ uSt¤,ØûË0ŽDL_g©è#,’È/q]ë;ú!J#*+»ä —QAýh "AÄ„È÷ðäa:ƒºN1|Ø—L¯#1‰Ì6 âP$`D`C ÀÌQŠ¦×¤yÝ,nø“áè(P+Ë™ÃÒsñ$’Äi‚U&ÃÁRŒ^±EF†½{çÀ“ìJ!¥1Èe êU™¨y€¡qf¾÷PÑÔícšúßyECÄ#1|¢›9Ž¸ P.åtl±:»5#1YW—ÓE1™<ë¨ÔF$»« ²4Êú»Ì?Gv×6æç=y¼ó×qlᢲŠl†¢Š1/&îk W‘²XÚ*¼î×5Ä1‹»·‹yåv•¤æÚÞdÛ÷ëvÙ®bŠ'ëH¦ÀŠ!´ËnÏ£ÜwøJ((ªùÊø{lx˜/fzƒ¼’³TÂyš|¯¤ôçØ]DXªCY[1fÖm§­[óß]¿­^ÿ†-Ò¢B¢¥#ch²Y’©³jü¿tTo·UûÛê4‚ÅMFت6”¥-kñê¢J^Õã_» .EVÑ?®–¶±ŽEÄ…Ôñ"K$9$'*Etz#1¢ƒ*ŠfE65…¬«k21XÊÅL¢Ù`ÄõçxÛi%PNºP-»Ô(öâ(š¿Ýähóí'µóùÿÌaב$ðWÀ šõ‡#*£'¸}—ÇeL|³*j¹ ý;.³ƒæɃxv÷’,aÚ°3œ…ó˜ÈIÀôªyæ8öÑUãoÊ÷°Xˆ%AI Ѧ|‡ù®„ÄÍÏC ä*`,F)`7àC¤8÷pù`) a½ƒ[Ô­BçÈR‘0#1tOrµBAy …#*©Nci© ¢Dˆ„ •7IZ¦Ú“JMRÚu9n¬šl‘@njm¯a0(€ÿ>R(‚”+Ô\/*SÞR¬‹e¬Ë/n£.¯a³Pû£ãÕ:³]¨ÎzK˜¹{LJÃp›‰C°?ž…³³8–”€çÝBp‘Êýlhy´†Óh‚æÐíµzD |´·É±ƒý*=êå½á׬½xFÌU$sÒÄ}$Á–écAp±ïD™Oï«ýÀ A䮤‡•HÓ ¢Ø¥4Ä©6F¢–Æ*LµI¶Â–ùÛoÊÕâl(­m&™@l $ýÇ?>¶u–i!`¡P*…ˆûÈhUÑøÍ°0ΤiDbdÂEÑ46m(Ö#*J]úÀ=/Œú£žõÛ²^뺕 £ý`BE,ƒ"!# ¤R†¨Ð•fËk ,A!ŸQè8c§Ÿa¿ÉÛÛJ¬²Tý&~Wûãó@¢#*†ŒÙYb>¨Ã¸¡4¤»ÂŒjxÅݤº|`cKí$ú;dUZQÛ?SÃÁ,µí™bJ8,,¤ˆ"rÍÛŽú™0Š(’p‚^/,WWMã­ó[¬Òjh¥KzÍ…vÓ»-wvWy¼­uM¢É­éW%E¼ÝÖfì̪뛶¢®v¡–ȲÕåÝ4M®î®î¶“eIS"ScB²¨h°"°‘%N#1U„†»]#,Ëyy+L"ôÞ¼¸Š©M-“Re•zVº·]yç[oeLµ–ÊZó»–íwn‹,elºk¤®ZíÏkçêö ¼@1TZ¡L}h%°†ÀMš Ÿ×Uf…Ðj‘bɸ} áFBÙ`¥íhÙž¨-Sm\ü^×kj?ŸM&RÚ3E(~)2ƒU —¾LË<ó®fè¢mM›êÒ£ú´6 dóÓ’äcÚ‹³ø\¿zàÃ× .ÂIÌo«Rzðž–"Ý ¹íôÆ$ÞOI¶³‹QÆpuF±³É¼øæBÝÚñÓ¡ñüÈ‚] ÈTîÊ ¹eƦ÷ηN4À¦³M4ÀeÂß?3fB†nÞQH¢Ž+”R3‰x\ëØLo-#,ì!$Ôè"FMÀfV]›äæ£à¡f ÂD“ð#,r#S3å#,9Âáw4•—uÖ¤õ×1ú‘lIÈ$¯ .Ž$aKTh†¸©òú†µŽÚ¬Þ§MòOc x–¢•#,ðÛ]Të|#,Aœ(€}65s9#,ñÞpÅ`×L‹ÝŸ£§¡’nÅ /ðÉZÕêÈ|¯G‡›Á(R'º? ú%‹0'œÝlA­«IÔ’Ø*) ì92cµ;Ø:˜D vmÖÌ@¿T29If}>Ð+zaȱ|*é €ŠDŘaRÐ E°D¢4RÓzº³Jáû'^ÇÑž/ý†×wÑÕÈ#¹:»ºu`—ƒœîÿÍÌ6‘Ž¨gL–‰(Öj3æhè@ãÞàò9ÍmÐ/÷Ђk p|>¥Çq&=óÇ:Þ­²#1j‘£'ä’娈¨g¶ N³ª¾U[¯ÁÖÁÔbƒKøÁµŽÂ.àÒWJ"8¼HÛÑl5#1ºw§Žý4*ÜXœÀ |³¥³dý¤r Óc¦tˆŒS¹Ð5Oh‚÷ÞšA±dI´‡…h®G1!!ÐñJ2œLùß1 ËPWž—#*#*Èp>†Ç>]’^çì=âQí3Ÿ8=lYÜj/µ^gQÄzˆ†AÁï…œÎãËß¡‘{™–v¶ò¶žØmFwu–üžï¿Ým<5ë‰ö\ ‘DŸf „PÆ& €²i½TŽRÊÎ@3»H¾_˜´K9W³)‚ xO'¸÷#åWì#*ÇßwïÙƒhùÖµ3’Ffl2e —벫hÿ«ÿ¿ß÷ÿwý?ý¿èÿ¯ÿOæÿ£WýŸ?«ÝÛÿËÿoÿÏû+þßÕ߯þÍõÿÛÙÿ‡þ÷|?ìø¿ñÿ÷Í,¿íþ?òÿ/V¿ÿ‹ú5¯Óþ·ÿßÿù¥ÿúëÿ/Ó»þ^Ï‹ý×oÇÿw–#ýì?øüßGÏ ¨|ê?"È`o8Ž^ñ¤@CÚJÅ2 ʸGõHŠo!Pw#,RçµþE ¡[è`ï#i Oë`õQYCÛ¼þ]ý ýžçwQ$&f}Vß;f’=€q(ŽYîÈHVz5!Ù§ŒgÀТÌ)¬ÄDm–䳿…ì–#*NÁÿNýûS!ÓiAsT?¤[tx†ëqëþ•2{âÿ¨I”s#³i]J‘‚@ÞU·Z˜ÖxfQùçäc%Qú»LîÖù‡ÿ6_ù#+—Ñgð¿§ðò=ì‡&ñ=>=¼#.”¶¯ýÜËJ#1,K’‚(#®þÜüª»¹NI(»^ý½ÿ~»>YÃñ–´Ç1Ò·YÜ­™Ÿäâì {R¦¤ˆoô25íÝf˜ØÖìÐHã#,–þ S0Ãgþ<4B)•S½£zÛÇ¿-,~Àêj3¹´¥RqeºpÐÒðe Ke±‚TK,=Í<Ù”Þ¨v©«nÑëNÛÜÓTmƶ9T¨¨ëø¼ƒQ!vÕI„œ^2{¥› %Ü‘‚C šÔ7¼ú¼bÓœE#nîtÑ5¡Ý#…qVÄ½Ñ ÷šud4|áð÷S5¦ÇCºè#,”+Š™‹$âIHÄb×/=ñy €1—CŸô ß33ðË<2œüÊjÝkÈ ã]ÛÉuiÒ6h×+lh§p(hcËF)tòocüŠ¿ê h3‡œ^j×°ÙªwD±4èÖj¦+½%˜'DX¤G\Hà…D;CXK¸RNÁW+ÇÌ ëí›ù§ °pŽž§s“Eeaèû¼|úóð+ºãFæ=…Œì3PEAVOš,5ŸEÃ:º‰ÃC{¢à„$‹t^F²×ÓMëó6·R–zq|9GgšX)6I8²¢E io¾×5&ÑðÛskÞ6ÛÒ^ËVõ4Z¤Ñ´«ß4ˆÒKL§uh7]Q`Ø<¡Ý‡7"ŒHlÂCCH}ì Ÿù„Âsëaª‹€7:‚ˆŽ§m‹ã‚íÅ 0¤#,#1ܹ ŒyƸUpX±øÔ”s#11!êÿœðMûb.¥áA®H²#7b•þ_\îïúÙG£G¢;‘Ôûy åÈ£€W@üúÄúb‹ ]¨î;µ#D”¡QbÉmLÍtÖíªìµ}kfˆD¹­=$$ ‘BPr¿Ûïøfyý@ûúÐÕ„QßÓÓÓ<ox³æÀ?ÿÅÜ‘N$4ÝCk€ +#<== +#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAltDdogACgkQSbTGfAUn\neqqy+Q/+KeccLyV5gQT+NBLB8FNexJKiHAKAgwtFwhrJuScD0XpedrsaPkoWfXLW\nSQVM672l/6DNpX7Cu8Z1sKDV5NRu6BecsKJ59xZm3Pv4FT3b+j938/cv4VTCp30v\n18o/Dgp2zoAPcQeiyEw92dGTz7V3xAfWkEj4bc2Fl5cGo4vo+JB56AUfJ+00fKfE\nevVkOly6HSftRgTngiKNXi2uolbXX8zuFMPmRNxny781JJpRHUt87eytMgTBurLv\ngT05JLq4p4TCOnTtrY9MSYdr+KRJooOJB8BmrOIpm8xK3TNXFF57OijsilBgtDwx\nD28f0SnkYUvp55f0j7xhd49QnLG/5DTfqMnIaDz3vG/2mJvGb9UizPLkLgxsHVHn\nsbkX2K2sm7faPZJlTS9VACCPrGVZESCVK9Yvk4x9bINju/TYixqVlyFob3YyicV+\n5BhwoVD6lLNKvVIXrxcgBkJL0D/N5evMe5QV5fP1kpSn9WQg0Kw/fzaR5igJdZrh\n0IsN935Kk75vISIt1KW/2Hm7Ew/Dx1tbLwVD3B4oGmgtV7VV6xUCg4/FNLAx8f9Q\nSNe4VytpHDW6Y2n9Ki13ZPm4gvV071jAxYFxoznmJbYb/QUjlTzMD5H/cY/D9U6H\nYwqm7cZFJ4nI23gwldJNn41i+DyN1k0nfP6h7ZalXxmuqiRr8sA=\n=+zXZ\n-----END PGP SIGNATURE-----\n diff --git a/packages/multimedia/opus/package.mk b/packages/multimedia/opus/package.mk new file mode 100644 index 000000000..a75152e31 --- /dev/null +++ b/packages/multimedia/opus/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="opus" +PKG_VERSION="1.3.1" +PKG_SHA256="65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d" +PKG_LICENSE="BSD" +PKG_SITE="http://www.opus-codec.org" +PKG_URL="https://archive.mozilla.org/pub/opus/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Codec designed for interactive speech and audio transmission over the Internet." +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="+pic" + +#if [ "$TARGET_ARCH" = "arm" ]; then + PKG_FIXED_POINT="--enable-fixed-point" +#else +# PKG_FIXED_POINT="--disable-fixed-point" +#fi + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + $PKG_FIXED_POINT" diff --git a/packages/multimedia/opusfile/package.mk b/packages/multimedia/opusfile/package.mk new file mode 100644 index 000000000..2bd3c2f5b --- /dev/null +++ b/packages/multimedia/opusfile/package.mk @@ -0,0 +1,35 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program 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 2, or (at your option) +# any later version. +# +# This Program 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 OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="opusfile" +PKG_VERSION="58b229a" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="https://github.com/xiph/opusfile" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain opus" +PKG_PRIORITY="optional" +PKG_SHORTDESC="Stand-alone decoder library for .opus streams" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + ./autogen.sh +} diff --git a/packages/multimedia/rkmpp/package.mk b/packages/multimedia/rkmpp/package.mk new file mode 100644 index 000000000..a4f865166 --- /dev/null +++ b/packages/multimedia/rkmpp/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rkmpp" +PKG_VERSION="2e5ea77cb2969a1b240d8154fe42f33d898546f5" +#PKG_SHA256="b2f6478783caa8ffb9698b4207bae3a684fe861ba09cd371414fe26d41a3433e" +PKG_ARCH="arm aarch64" +PKG_LICENSE="APL" +PKG_SITE="https://github.com/rockchip-linux/mpp" +PKG_URL="https://github.com/rockchip-linux/mpp/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libdrm" +PKG_LONGDESC="rkmpp: Rockchip Media Process Platform (MPP) module" + +if [ "$DEVICE" = "RK3328" -o "$DEVICE" = "RK3399" ]; then + PKG_ENABLE_VP9D="ON" +else + PKG_ENABLE_VP9D="OFF" +fi + +PKG_CMAKE_OPTS_TARGET="-DENABLE_VP9D=$PKG_ENABLE_VP9D \ + -DHAVE_DRM=ON" diff --git a/packages/multimedia/rtmpdump/package.mk b/packages/multimedia/rtmpdump/package.mk new file mode 100644 index 000000000..bcdaa9b6f --- /dev/null +++ b/packages/multimedia/rtmpdump/package.mk @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="rtmpdump" +PKG_VERSION="fa8646d" +PKG_SHA256="dba4d4d2e1c7de6884b01d98194b83cab6784669089fa3c919152087a3a38fd2" +PKG_LICENSE="GPL" +PKG_SITE="http://rtmpdump.mplayerhq.hu/" +PKG_URL="http://repo.or.cz/rtmpdump.git/snapshot/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_LONGDESC="rtmpdump is a toolkit for RTMP streams." +PKG_BUILD_FLAGS="+pic" + +make_target() { + make prefix=/usr \ + incdir=/usr/include/librtmp \ + libdir=/usr/lib \ + mandir=/usr/share/man \ + CC="$CC" \ + LD="$LD" \ + AR="$AR" \ + SHARED=no \ + CRYPTO="OPENSSL" \ + OPT="" \ + XCFLAGS="$CFLAGS" \ + XCFLAGS="$CFLAGS -Wno-unused-but-set-variable -Wno-unused-const-variable" \ + XLDFLAGS="$LDFLAGS" \ + XLIBS="-lm" +} + +makeinstall_target() { + make DESTDIR=$SYSROOT_PREFIX \ + prefix=/usr \ + incdir=/usr/include/librtmp \ + libdir=/usr/lib \ + mandir=/usr/share/man \ + CC="$CC" \ + LD="$LD" \ + AR="$AR" \ + SHARED=no \ + CRYPTO="OPENSSL" \ + OPT="" \ + XCFLAGS="$CFLAGS" \ + XLDFLAGS="$LDFLAGS" \ + XLIBS="-lm" \ + install + + make DESTDIR=$INSTALL \ + prefix=/usr \ + incdir=/usr/include/librtmp \ + libdir=/usr/lib \ + mandir=/usr/share/man \ + CC="$CC" \ + LD="$LD" \ + AR="$AR" \ + SHARED=no \ + CRYPTO="OPENSSL" \ + OPT="" \ + XCFLAGS="$CFLAGS" \ + XLDFLAGS="$LDFLAGS" \ + XLIBS="-lm" \ + install +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/sbin + +# # to be removed: hack for "compatibility" +# mkdir -p $INSTALL/usr/lib +# ln -sf librtmp.so.1 $INSTALL/usr/lib/librtmp.so.0 +} diff --git a/packages/multimedia/rtmpdump/patches/001_fix-racing-build-issue.patch b/packages/multimedia/rtmpdump/patches/001_fix-racing-build-issue.patch new file mode 100644 index 000000000..0af9240b5 --- /dev/null +++ b/packages/multimedia/rtmpdump/patches/001_fix-racing-build-issue.patch @@ -0,0 +1,10 @@ +--- a/librtmp/Makefile 2018-02-01 18:38:52.866867721 +0100 ++++ b/librtmp/Makefile 2018-02-01 18:39:23.315007740 +0100 +@@ -115,6 +115,7 @@ + cp librtmp.3 $(MANDIR)/man3 + + install_so: librtmp$(SO_EXT) ++ -mkdir -p $(SODIR) + cp librtmp$(SO_EXT) $(SODIR) + $(INSTALL_IMPLIB) + cd $(SODIR); ln -sf librtmp$(SO_EXT) librtmp.$(SOX) diff --git a/packages/multimedia/rtmpdump/patches/002_build-with-openssl11.patch b/packages/multimedia/rtmpdump/patches/002_build-with-openssl11.patch new file mode 100644 index 000000000..caed1d19e --- /dev/null +++ b/packages/multimedia/rtmpdump/patches/002_build-with-openssl11.patch @@ -0,0 +1,249 @@ +Source: https://github.com/xbmc/inputstream.rtmp/tree/master/depends/common/librtmp +Date: Feb 9, 2019 + +--- a/librtmp/dh.h ++++ b/librtmp/dh.h +@@ -253,20 +253,42 @@ + if (!dh) + goto failed; + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + MP_new(dh->g); + + if (!dh->g) + goto failed; ++#else ++ BIGNUM *g = NULL; ++ MP_new(g); ++ if (!g) ++ goto failed; ++#endif + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */ ++#else ++ BIGNUM* p = NULL; ++ DH_get0_pqg(dh, (BIGNUM const**)&p, NULL, NULL); ++ MP_gethex(p, P1024, res); /* prime P1024, see dhgroups.h */ ++#endif + if (!res) + { + goto failed; + } + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + MP_set_w(dh->g, 2); /* base 2 */ ++#else ++ MP_set_w(g, 2); /* base 2 */ ++ DH_set0_pqg(dh, p, NULL, g); ++#endif + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + dh->length = nKeyBits; ++#else ++ DH_set_length(dh, nKeyBits); ++#endif + return dh; + + failed: +@@ -293,12 +315,24 @@ + MP_gethex(q1, Q1024, res); + assert(res); + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + res = isValidPublicKey(dh->pub_key, dh->p, q1); ++#else ++ BIGNUM const* pub_key = NULL; ++ BIGNUM const* p = NULL; ++ DH_get0_key(dh, &pub_key, NULL); ++ DH_get0_pqg(dh, &p, NULL, NULL); ++ res = isValidPublicKey((BIGNUM*)pub_key, (BIGNUM*)p, q1); ++#endif + if (!res) + { ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + MP_free(dh->pub_key); + MP_free(dh->priv_key); + dh->pub_key = dh->priv_key = 0; ++#else ++ DH_free(dh); ++#endif + } + + MP_free(q1); +@@ -314,15 +348,29 @@ + DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen) + { + int len; ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + if (!dh || !dh->pub_key) ++#else ++ BIGNUM const* pub_key = NULL; ++ DH_get0_key(dh, &pub_key, NULL); ++ if (!dh || !pub_key) ++#endif + return 0; + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + len = MP_bytes(dh->pub_key); ++#else ++ len = MP_bytes(pub_key); ++#endif + if (len <= 0 || len > (int) nPubkeyLen) + return 0; + + memset(pubkey, 0, nPubkeyLen); ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len); ++#else ++ MP_setbin(pub_key, pubkey + (nPubkeyLen - len), len); ++#endif + return 1; + } + +@@ -364,7 +412,13 @@ + MP_gethex(q1, Q1024, len); + assert(len); + ++#if !defined(USE_OPENSSL) || !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L + if (isValidPublicKey(pubkeyBn, dh->p, q1)) ++#else ++ BIGNUM const* p = NULL; ++ DH_get0_pqg(dh, &p, NULL, NULL); ++ if (isValidPublicKey(pubkeyBn, (BIGNUM*)p, q1)) ++#endif + res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh); + else + res = -1; +--- a/librtmp/handshake.h ++++ b/librtmp/handshake.h +@@ -31,9 +31,9 @@ + #define SHA256_DIGEST_LENGTH 32 + #endif + #define HMAC_CTX sha2_context +-#define HMAC_setup(ctx, key, len) sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0) +-#define HMAC_crunch(ctx, buf, len) sha2_hmac_update(&ctx, buf, len) +-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig) ++#define HMAC_setup(ctx, key, len) sha2_hmac_starts(ctx, (unsigned char *)key, len, 0) ++#define HMAC_crunch(ctx, buf, len) sha2_hmac_update(ctx, buf, len) ++#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(ctx, dig) + + typedef arc4_context * RC4_handle; + #define RC4_alloc(h) *h = malloc(sizeof(arc4_context)) +@@ -50,9 +50,9 @@ + #endif + #undef HMAC_CTX + #define HMAC_CTX struct hmac_sha256_ctx +-#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key) +-#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf) +-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig) ++#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(ctx, len, key) ++#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(ctx, len, buf) ++#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(ctx, SHA256_DIGEST_LENGTH, dig) + #define HMAC_close(ctx) + + typedef struct arcfour_ctx* RC4_handle; +@@ -64,14 +64,23 @@ + + #else /* USE_OPENSSL */ + #include ++#include + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x0090800 || !defined(SHA256_DIGEST_LENGTH) + #error Your OpenSSL is too old, need 0.9.8 or newer with SHA256 + #endif +-#define HMAC_setup(ctx, key, len) HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, len, EVP_sha256(), 0) +-#define HMAC_crunch(ctx, buf, len) HMAC_Update(&ctx, buf, len) +-#define HMAC_finish(ctx, dig, dlen) HMAC_Final(&ctx, dig, &dlen); HMAC_CTX_cleanup(&ctx) ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#define HMAC_setup(ctx, key, len) HMAC_CTX_init(ctx); HMAC_Init_ex(ctx, key, len, EVP_sha256(), 0) ++#else ++#define HMAC_setup(ctx, key, len) ctx = HMAC_CTX_new(); HMAC_CTX_reset(ctx); HMAC_Init_ex(ctx, key, len, EVP_sha256(), 0) ++#endif ++#define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, buf, len) ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, dig, &dlen); HMAC_CTX_cleanup(ctx) ++#else ++#define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, dig, &dlen); HMAC_CTX_free(ctx) ++#endif + + typedef RC4_KEY * RC4_handle; + #define RC4_alloc(h) *h = malloc(sizeof(RC4_KEY)) +@@ -117,7 +126,7 @@ + { + uint8_t digest[SHA256_DIGEST_LENGTH]; + unsigned int digestLen = 0; +- HMAC_CTX ctx; ++ HMAC_CTX* ctx = NULL; + + RC4_alloc(rc4keyIn); + RC4_alloc(rc4keyOut); +@@ -266,7 +275,7 @@ + size_t keylen, uint8_t *digest) + { + unsigned int digestLen; +- HMAC_CTX ctx; ++ HMAC_CTX* ctx = NULL; + + HMAC_setup(ctx, key, keylen); + HMAC_crunch(ctx, message, messageLen); +--- a/librtmp/hashswf.c ++++ b/librtmp/hashswf.c +@@ -37,9 +37,9 @@ + #define SHA256_DIGEST_LENGTH 32 + #endif + #define HMAC_CTX sha2_context +-#define HMAC_setup(ctx, key, len) sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0) +-#define HMAC_crunch(ctx, buf, len) sha2_hmac_update(&ctx, buf, len) +-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig) ++#define HMAC_setup(ctx, key, len) sha2_hmac_starts(ctx, (unsigned char *)key, len, 0) ++#define HMAC_crunch(ctx, buf, len) sha2_hmac_update(ctx, buf, len) ++#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(ctx, dig) + #define HMAC_close(ctx) + #elif defined(USE_GNUTLS) + #include +@@ -48,19 +48,27 @@ + #endif + #undef HMAC_CTX + #define HMAC_CTX struct hmac_sha256_ctx +-#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key) +-#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf) +-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig) ++#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(ctx, len, key) ++#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(ctx, len, buf) ++#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(ctx, SHA256_DIGEST_LENGTH, dig) + #define HMAC_close(ctx) + #else /* USE_OPENSSL */ + #include + #include + #include + #include +-#define HMAC_setup(ctx, key, len) HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, (unsigned char *)key, len, EVP_sha256(), 0) +-#define HMAC_crunch(ctx, buf, len) HMAC_Update(&ctx, (unsigned char *)buf, len) +-#define HMAC_finish(ctx, dig, dlen) HMAC_Final(&ctx, (unsigned char *)dig, &dlen); +-#define HMAC_close(ctx) HMAC_CTX_cleanup(&ctx) ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#define HMAC_setup(ctx, key, len) HMAC_CTX_init(ctx); HMAC_Init_ex(ctx, (unsigned char *)key, len, EVP_sha256(), 0) ++#else ++#define HMAC_setup(ctx, key, len) ctx = HMAC_CTX_new(); HMAC_CTX_reset(ctx); HMAC_Init_ex(ctx, key, len, EVP_sha256(), 0) ++#endif ++#define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, (unsigned char *)buf, len) ++#define HMAC_finish(ctx, dig, dlen) HMAC_Final(ctx, (unsigned char *)dig, &dlen); ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#define HMAC_close(ctx) HMAC_CTX_cleanup(ctx) ++#else ++#define HMAC_close(ctx) HMAC_CTX_reset(ctx); HMAC_CTX_free(ctx) ++#endif + #endif + + extern void RTMP_TLS_Init(); +@@ -289,7 +297,7 @@ + struct info + { + z_stream *zs; +- HMAC_CTX ctx; ++ HMAC_CTX *ctx; + int first; + int zlib; + int size; diff --git a/packages/multimedia/vlc/package.mk b/packages/multimedia/vlc/package.mk new file mode 100644 index 000000000..b535e22e5 --- /dev/null +++ b/packages/multimedia/vlc/package.mk @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="vlc" +PKG_VERSION="3.0.12" +#PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://www.videolan.org" +PKG_URL="https://mirror.netcologne.de/videolan.org/$PKG_NAME/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libdvbpsi gnutls ffmpeg libmpeg2 zlib flac libvorbis libxml2 pulseaudio SDL2 x264 x265 aom libogg" +PKG_SHORTDESC="VideoLAN multimedia player and streamer" +PKG_LONGDESC="VLC is the VideoLAN project's media player. It plays MPEG, MPEG2, MPEG4, DivX, MOV, WMV, QuickTime, mp3, Ogg/Vorbis files, DVDs, VCDs, and multimedia streams from various network sources." +PKG_AUTORECONF="yes" +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="-fpic" + +ENABLED_FEATURES="--enable-silent-rules \ + --enable-run-as-root \ + --enable-sout \ + --enable-vlm \ + --enable-v4l2 \ + --enable-mpc \ + --enable-avcodec \ + --enable-avformat \ + --enable-swscale \ + --enable-postproc \ + --enable-aa \ + --enable-libmpeg2 \ + --enable-x264 \ + --enable-png \ + --enable-jpeg \ + --enable-libxml2 \ + --enable-alsa \ + --enable-udev \ + --enable-vlc \ + --enable-neon" + +DISABLED_FEATURES="--disable-dependency-tracking \ + --without-contrib \ + --disable-nls \ + --disable-rpath \ + --disable-dbus \ + --disable-gprof \ + --disable-cprof \ + --disable-debug \ + --disable-coverage \ + --disable-lua \ + --disable-notify \ + --disable-taglib \ + --disable-mpg123 \ + --disable-live555 \ + --disable-dc1394 \ + --disable-dvdread \ + --disable-dvdnav \ + --disable-opencv \ + --disable-decklink \ + --disable-sftp \ + --disable-vcd \ + --disable-libcddb \ + --disable-dvbpsi \ + --disable-screen \ + --disable-ogg \ + --disable-shout\ + --disable-mod \ + --disable-gme \ + --disable-wma-fixed \ + --disable-shine \ + --disable-omxil \ + --disable-mad \ + --disable-merge-ffmpeg \ + --disable-faad \ + --disable-flac \ + --disable-twolame \ + --disable-realrtsp \ + --disable-libtar \ + --disable-a52 \ + --disable-dca \ + --disable-vorbis \ + --disable-tremor \ + --disable-speex \ + --disable-theora \ + --disable-schroedinger \ + --disable-fluidsynth \ + --disable-zvbi \ + --disable-telx \ + --disable-libass \ + --disable-kate \ + --disable-tiger \ + --disable-libva \ + --disable-vdpau \ + --without-x \ + --disable-xcb \ + --disable-xvideo \ + --disable-sdl-image \ + --disable-freetype \ + --disable-fribidi \ + --disable-fontconfig \ + --disable-svg \ + --disable-directx \ + --disable-caca \ + --disable-oss \ + --disable-jack \ + --disable-upnp \ + --disable-skins2 \ + --disable-kai \ + --disable-macosx \ + --disable-macosx-qtkit \ + --disable-ncurses \ + --disable-goom \ + --disable-projectm \ + --disable-mtp \ + --disable-lirc \ + --disable-libgcrypt \ + -disable-update-check \ + --disable-kva \ + --disable-bluray \ + --disable-samplerate \ + --disable-sid \ + --disable-crystalhd \ + --disable-dxva2 \ + --disable-dav1d \ + --disable-qt" + + if [ "$PROJECT" == "Amlogic" ]; then + ENABLED_FEATURES+=" --enable-pulse" + else + DISABLED_FEATURES+=" --disable-pulse" + fi + +PKG_CONFIGURE_OPTS_TARGET="$ENABLED_FEATURES $DISABLED_FEATURES" + +pre_configure_target() { + export LDFLAGS="$LDFLAGS -lresolv -fopenmp -lm" +} + +post_makeinstall_target() { + rm -fr $INSTALL/usr/share/applications + rm -fr $INSTALL/usr/share/icons + rm -fr $INSTALL/usr/share/kde4 + rm -f $INSTALL/usr/bin/rvlc + rm -f $INSTALL/usr/bin/vlc-wrapper +} diff --git a/packages/multimedia/x264/package.mk b/packages/multimedia/x264/package.mk new file mode 100644 index 000000000..44bccb6e5 --- /dev/null +++ b/packages/multimedia/x264/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="x264" +PKG_VERSION="b86ae3c66f51ac9eab5ab7ad09a9d62e67961b8a" +#PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.videolan.org/developers/x264.html" +PKG_URL="https://code.videolan.org/videolan/x264/-/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="x264 codec" + +if [ "$TARGET_ARCH" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" nasm:host" +fi + +pre_configure_target() { + cd $PKG_BUILD + rm -rf .$TARGET_NAME + + if [ "$TARGET_ARCH" = "x86_64" ]; then + export AS="$TOOLCHAIN/bin/nasm" + else + PKG_X264_ASM="--disable-asm" + fi +} + +configure_target() { + ./configure \ + --cross-prefix="$TARGET_PREFIX" \ + --extra-cflags="$CFLAGS" \ + --extra-ldflags="$LDFLAGS" \ + --host="$TARGET_NAME" \ + --prefix="/usr" \ + --sysroot="$SYSROOT_PREFIX" \ + $PKG_X264_ASM \ + --disable-cli \ + --enable-lto \ + --enable-shared \ + --enable-pic \ + --enable-strip +} diff --git a/packages/multimedia/x265/package.mk b/packages/multimedia/x265/package.mk new file mode 100644 index 000000000..c3245c36b --- /dev/null +++ b/packages/multimedia/x265/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="x265" +PKG_VERSION="3.2" +PKG_SHA256="364d79bcd56116a9e070fdeb1d9d2aaef1a786b4970163fb56ff0991a183133b" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://www.videolan.org/developers/x265.html" +PKG_URL="http://download.videolan.org/pub/videolan/x265/${PKG_NAME}_${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="x265 is a H.265/HEVC video encoder application library" +PKG_TOOLCHAIN="make" + +pre_configure_target() { + LDFLAGS="$LDFLAGS -ldl" + cmake -G "Unix Makefiles" ./source +} diff --git a/packages/network/avahi/debug.d/avahi.conf b/packages/network/avahi/debug.d/avahi.conf new file mode 100644 index 000000000..5917ec5ef --- /dev/null +++ b/packages/network/avahi/debug.d/avahi.conf @@ -0,0 +1 @@ +AVAHI_DEBUG="--debug" diff --git a/packages/network/avahi/default.d/avahi.conf b/packages/network/avahi/default.d/avahi.conf new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/avahi/package.mk b/packages/network/avahi/package.mk new file mode 100644 index 000000000..d47b7340e --- /dev/null +++ b/packages/network/avahi/package.mk @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="avahi" +PKG_VERSION="0.8" +PKG_SHA256="c15e750ef7c6df595fb5f2ce10cac0fee2353649600e6919ad08ae8871e4945f" +PKG_LICENSE="GPL" +PKG_SITE="http://avahi.org/" +PKG_URL="https://github.com/lathiat/avahi/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain expat libdaemon dbus connman gettext" +PKG_LONGDESC="Service Discovery for Linux using mDNS/DNS-SD, compatible with Bonjour." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="py_cv_mod_gtk_=yes \ + py_cv_mod_dbus_=yes \ + ac_cv_func_chroot=no \ + --with-distro=none \ + --disable-glib \ + --disable-gobject \ + --disable-qt3 \ + --disable-qt4 \ + --disable-qt5 \ + --disable-gtk \ + --disable-gtk3 \ + --enable-dbus \ + --disable-dbm \ + --disable-gdbm \ + --enable-libdaemon \ + --disable-python \ + --disable-python-dbus \ + --disable-mono \ + --disable-monodoc \ + --disable-autoipd \ + --disable-doxygen-doc \ + --disable-doxygen-dot \ + --disable-doxygen-man \ + --disable-doxygen-rtf \ + --disable-doxygen-xml \ + --disable-doxygen-chm \ + --disable-doxygen-chi \ + --disable-doxygen-html \ + --disable-doxygen-ps \ + --disable-doxygen-pdf \ + --disable-core-docs \ + --disable-manpages \ + --disable-xmltoman \ + --disable-tests \ + --disable-libevent \ + --enable-compat-libdns_sd \ + --disable-compat-howl \ + --with-xml=expat \ + --with-avahi-user=avahi \ + --with-avahi-group=avahi \ + --disable-nls" + +pre_configure_target() { + NOCONFIGURE=1 ./autogen.sh +} + +post_makeinstall_target() { +# disable wide-area + sed -e "s,^.*enable-wide-area=.*$,enable-wide-area=no,g" -i ${INSTALL}/etc/avahi/avahi-daemon.conf +# publish-hinfo + sed -e "s,^.*publish-hinfo=.*$,publish-hinfo=no,g" -i ${INSTALL}/etc/avahi/avahi-daemon.conf +# publish-workstation + sed -e "s,^.*publish-workstation=.*$,publish-workstation=no,g" -i ${INSTALL}/etc/avahi/avahi-daemon.conf +# browse domains? + sed -e "s,^.*browse-domains=.*$,# browse-domains=,g" -i ${INSTALL}/etc/avahi/avahi-daemon.conf +# set root user as default + sed -e "s,22,22\n path=/storage\n u=root,g" -i ${INSTALL}/etc/avahi/services/sftp-ssh.service + + rm -rf ${INSTALL}/etc/avahi/avahi-dnsconfd.action + rm -rf ${INSTALL}/etc/avahi/services/ssh.service + if [ ! ${SFTP_SERVER} = "yes" ]; then + rm -rf ${INSTALL}/etc/avahi/services/sftp-ssh.service + fi + rm -rf ${INSTALL}/usr/lib/systemd + rm -f ${INSTALL}/usr/share/dbus-1/system-services/org.freedesktop.Avahi.service + rm -f ${INSTALL}/usr/sbin/avahi-dnsconfd + rm -f ${INSTALL}/usr/bin/avahi-bookmarks + rm -f ${INSTALL}/usr/bin/avahi-publish* + rm -f ${INSTALL}/usr/bin/avahi-resolve* + rm -f ${INSTALL}/usr/lib/libdns_sd* + + mkdir -p ${INSTALL}/usr/share/services + cp -P ${PKG_DIR}/default.d/*.conf ${INSTALL}/usr/share/services +} + +post_install() { + add_user avahi x 495 495 "avahi-daemon" "/var/run/avahi-daemon" "/bin/sh" + add_group avahi 495 + + enable_service avahi-defaults.service + enable_service avahi-daemon.service +} diff --git a/packages/network/avahi/system.d/avahi-daemon.service b/packages/network/avahi/system.d/avahi-daemon.service new file mode 100644 index 000000000..63cd640cb --- /dev/null +++ b/packages/network/avahi/system.d/avahi-daemon.service @@ -0,0 +1,18 @@ +[Unit] +Description=Avahi Daemon +After=network.target avahi-defaults.service +Requires=avahi-defaults.service +ConditionPathExists=/storage/.cache/services/avahi.conf + +[Service] +Restart=on-failure +EnvironmentFile=-/run/libreelec/debug/avahi.conf +ExecStart=/usr/sbin/avahi-daemon -s $AVAHI_DEBUG +ExecReload=/usr/sbin/avahi-daemon -r +TimeoutStopSec=1s +RestartSec=2 +StartLimitInterval=60 +StartLimitBurst=10 + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/avahi/system.d/avahi-defaults.service b/packages/network/avahi/system.d/avahi-defaults.service new file mode 100644 index 000000000..2db5833be --- /dev/null +++ b/packages/network/avahi/system.d/avahi-defaults.service @@ -0,0 +1,11 @@ +[Unit] +Description=Avahi defaults +After=local-fs.target + +ConditionPathExists=!/storage/.cache/services/avahi.conf +ConditionPathExists=!/storage/.cache/services/avahi.disabled + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /usr/share/services/avahi.conf /storage/.cache/services/' +RemainAfterExit=yes diff --git a/packages/network/bluez/debug.d/bluez.conf b/packages/network/bluez/debug.d/bluez.conf new file mode 100644 index 000000000..d0cf58bd7 --- /dev/null +++ b/packages/network/bluez/debug.d/bluez.conf @@ -0,0 +1 @@ +BLUEZ_DEBUG="--debug" diff --git a/packages/network/bluez/debug.d/obexd.conf b/packages/network/bluez/debug.d/obexd.conf new file mode 100644 index 000000000..b78fd35c0 --- /dev/null +++ b/packages/network/bluez/debug.d/obexd.conf @@ -0,0 +1 @@ +OBEXD_DEBUG="--debug" diff --git a/packages/network/bluez/default.d/bluez.conf b/packages/network/bluez/default.d/bluez.conf new file mode 100644 index 000000000..e69de29bb diff --git a/packages/network/bluez/package.mk b/packages/network/bluez/package.mk new file mode 100644 index 000000000..a208a1d3f --- /dev/null +++ b/packages/network/bluez/package.mk @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="bluez" +PKG_VERSION="5.50" +PKG_SHA256="c44b776660bf78e664e388b979da152976296e444dece833f3ddbd5be5a3b1b4" +PKG_LICENSE="GPL" +PKG_SITE="http://www.bluez.org/" +PKG_URL="https://git.kernel.org/pub/scm/bluetooth/bluez.git/snapshot/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain dbus glib readline systemd" +PKG_LONGDESC="Bluetooth Tools and System Daemons for Linux." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+lto" + +if build_with_debug; then + BLUEZ_CONFIG="--enable-debug" +else + BLUEZ_CONFIG="--disable-debug" +fi + +BLUEZ_CONFIG="$BLUEZ_CONFIG --enable-monitor --enable-test" + +PKG_CONFIGURE_OPTS_TARGET="--disable-dependency-tracking \ + --disable-silent-rules \ + --disable-library \ + --enable-udev \ + --disable-cups \ + --disable-obex \ + --enable-client \ + --enable-systemd \ + --enable-tools --enable-deprecated \ + --enable-datafiles \ + --disable-experimental \ + --enable-sixaxis \ + --with-gnu-ld \ + $BLUEZ_CONFIG \ + storagedir=/storage/.cache/bluetooth" + +pre_configure_target() { +# bluez fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME + + export LIBS="-lncurses" +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/lib/systemd + rm -rf $INSTALL/usr/bin/bccmd + rm -rf $INSTALL/usr/bin/bluemoon + rm -rf $INSTALL/usr/bin/ciptool + rm -rf $INSTALL/usr/share/dbus-1 + + mkdir -p $INSTALL/etc/bluetooth + cp src/main.conf $INSTALL/etc/bluetooth + sed -i $INSTALL/etc/bluetooth/main.conf \ + -e "s|^#\[Policy\]|\[Policy\]|g" \ + -e "s|^#AutoEnable.*|AutoEnable=true|g" + + mkdir -p $INSTALL/usr/share/services + cp -P $PKG_DIR/default.d/*.conf $INSTALL/usr/share/services + + # bluez looks in /etc/firmware/ + ln -sf /usr/lib/firmware $INSTALL/etc/firmware +} + +post_install() { + enable_service bluetooth-defaults.service + enable_service bluetooth.service + enable_service obex.service +} diff --git a/packages/network/bluez/patches/bluez-01_add-obexd-policy.patch b/packages/network/bluez/patches/bluez-01_add-obexd-policy.patch new file mode 100644 index 000000000..8afb641a1 --- /dev/null +++ b/packages/network/bluez/patches/bluez-01_add-obexd-policy.patch @@ -0,0 +1,41 @@ +diff -Naur bluez-5.29/src/bluetooth.conf bluez-5.29.patch/src/bluetooth.conf +--- bluez-5.29/src/bluetooth.conf 2015-03-11 11:01:57.000000000 +0100 ++++ bluez-5.29.patch/src/bluetooth.conf 2015-03-31 12:02:20.128341381 +0200 +@@ -22,20 +22,37 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + ++ + + ++ + + + + + ++ + + + + ++ + + + diff --git a/packages/network/bluez/patches/bluez-02_obexd-use-system-bus.patch b/packages/network/bluez/patches/bluez-02_obexd-use-system-bus.patch new file mode 100644 index 000000000..dd52a299e --- /dev/null +++ b/packages/network/bluez/patches/bluez-02_obexd-use-system-bus.patch @@ -0,0 +1,25 @@ +From 20dfa1079c088236bcd63f1a986956b488177ebf Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 6 Aug 2013 11:18:09 +0300 +Subject: [PATCH] obexd: use system bus + +--- + obexd/src/manager.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/obexd/src/manager.c b/obexd/src/manager.c +index dbfbef8..9a29f8c 100644 +--- a/obexd/src/manager.c ++++ b/obexd/src/manager.c +@@ -569,7 +569,7 @@ gboolean manager_init(void) + + dbus_error_init(&err); + +- connection = g_dbus_setup_bus(DBUS_BUS_SESSION, OBEXD_SERVICE, &err); ++ connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, OBEXD_SERVICE, &err); + if (connection == NULL) { + if (dbus_error_is_set(&err) == TRUE) { + fprintf(stderr, "%s\n", err.message); +-- +1.7.2.5 + diff --git a/packages/network/bluez/patches/bluez-03_storagedir.patch b/packages/network/bluez/patches/bluez-03_storagedir.patch new file mode 100644 index 000000000..6bad3b146 --- /dev/null +++ b/packages/network/bluez/patches/bluez-03_storagedir.patch @@ -0,0 +1,21 @@ +diff -Naur bluez-5.7/configure.ac bluez-5.7.patch/configure.ac +--- bluez-5.7/configure.ac 2013-06-26 18:17:07.000000000 +0200 ++++ bluez-5.7.patch/configure.ac 2013-07-12 20:21:17.000000000 +0200 +@@ -238,10 +238,13 @@ + prefix="${ac_default_prefix}" + fi + +-if (test "$localstatedir" = '${prefix}/var'); then +- storagedir="${prefix}/var/lib/bluetooth" +-else +- storagedir="${localstatedir}/lib/bluetooth" ++ ++if (test "x$storagedir" = 'x'); then ++ if (test "$localstatedir" = '${prefix}/var'); then ++ storagedir="${prefix}/var/lib/bluetooth" ++ else ++ storagedir="${localstatedir}/lib/bluetooth" ++ fi + fi + AC_DEFINE_UNQUOTED(STORAGEDIR, "${storagedir}", + [Directory for the storage files]) diff --git a/packages/network/bluez/patches/bluez-04_work-around-Logitech-diNovo-Edge-keyboard-firmware-i.patch b/packages/network/bluez/patches/bluez-04_work-around-Logitech-diNovo-Edge-keyboard-firmware-i.patch new file mode 100644 index 000000000..e583320ec --- /dev/null +++ b/packages/network/bluez/patches/bluez-04_work-around-Logitech-diNovo-Edge-keyboard-firmware-i.patch @@ -0,0 +1,29 @@ +From aa73bf5039dfd2cf0a52dd6fd22501d955cc1a00 Mon Sep 17 00:00:00 2001 +From: Tommy +Date: Thu, 10 Jan 2013 09:18:43 +0100 +Subject: [PATCH] work around Logitech diNovo Edge keyboard firmware issue + +https://bugs.launchpad.net/ubuntu/+source/bluez/+bug/269851 +--- + tools/hid2hci.rules | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/tools/hid2hci.rules b/tools/hid2hci.rules +index db6bb03..7db4572 100644 +--- a/tools/hid2hci.rules ++++ b/tools/hid2hci.rules +@@ -11,7 +11,10 @@ ATTR{bInterfaceClass}=="03", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProt + RUN+="hid2hci --method=dell --devpath=%p", ENV{HID2HCI_SWITCH}="1" + + # Logitech devices +-KERNEL=="hiddev*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c70[345abce]|c71[34bc]", \ ++KERNEL=="hiddev*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c70[345abce]|c71[3bc]", \ ++ RUN+="hid2hci --method=logitech-hid --devpath=%p" ++# Logitech, Inc. diNovo Edge Keyboard ++KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c714", \ + RUN+="hid2hci --method=logitech-hid --devpath=%p" + + ENV{DEVTYPE}!="usb_device", GOTO="hid2hci_end" +-- +1.8.0.1 + diff --git a/packages/network/bluez/patches/bluez-05-046d-c52b-Logitech-Inc.-Unifying-Receiver.patch b/packages/network/bluez/patches/bluez-05-046d-c52b-Logitech-Inc.-Unifying-Receiver.patch new file mode 100644 index 000000000..f9f827fe5 --- /dev/null +++ b/packages/network/bluez/patches/bluez-05-046d-c52b-Logitech-Inc.-Unifying-Receiver.patch @@ -0,0 +1,26 @@ +From 50f34d1b65c2fb6c557e2b802e908986e8ec0b74 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 7 Feb 2014 12:50:29 +0200 +Subject: [PATCH] 046d:c52b Logitech, Inc. Unifying Receiver + +--- + tools/hid2hci.rules | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/tools/hid2hci.rules b/tools/hid2hci.rules +index 7db4572..1feca6e 100644 +--- a/tools/hid2hci.rules ++++ b/tools/hid2hci.rules +@@ -16,6 +16,9 @@ KERNEL=="hiddev*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c70[345abce]|c71[ + # Logitech, Inc. diNovo Edge Keyboard + KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c714", \ + RUN+="hid2hci --method=logitech-hid --devpath=%p" ++# Logitech, Inc. Unifying Receiver ++KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", \ ++ RUN+="hid2hci --method=logitech-hid --devpath=%p" + + ENV{DEVTYPE}!="usb_device", GOTO="hid2hci_end" + +-- +1.7.2.5 + diff --git a/packages/network/bluez/patches/bluez-06-broadcom-fixes.patch b/packages/network/bluez/patches/bluez-06-broadcom-fixes.patch new file mode 100644 index 000000000..aa2e08007 --- /dev/null +++ b/packages/network/bluez/patches/bluez-06-broadcom-fixes.patch @@ -0,0 +1,51 @@ +From 874990be3b958bd3d5d5f61989f8d6314be3358a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 16 Feb 2016 16:40:46 +0000 +Subject: [PATCH 1/4] bcm43xx: Add bcm43xx-3wire variant + +--- + tools/hciattach.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/hciattach.c b/tools/hciattach.c +index 1904ac5..835d5ff 100644 +--- a/tools/hciattach.c ++++ b/tools/hciattach.c +@@ -1144,6 +1144,9 @@ struct uart_t uart[] = { + { "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000, + FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL }, + ++ { "bcm43xx-3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 3000000, ++ 0, DISABLE_PM, NULL, bcm43xx, NULL }, ++ + { "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200, + FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm }, + +-- +1.9.1 + +From 74e6869ecce13b1066741ba995fc47b437c4c72f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 20 Jan 2016 16:00:37 +0000 +Subject: [PATCH 3/4] Increase firmware load timeout to 30s + +--- + tools/hciattach.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/hciattach.c b/tools/hciattach.c +index 9391458..b1168d4 100644 +--- a/tools/hciattach.c ++++ b/tools/hciattach.c +@@ -1287,7 +1287,7 @@ int main(int argc, char *argv[]) + { + struct uart_t *u = NULL; + int detach, printpid, raw, opt, i, n, ld, err; +- int to = 10; ++ int to = 30; + int init_speed = 0; + int send_break = 0; + pid_t pid; +-- +1.9.1 + diff --git a/packages/network/bluez/patches/bluez-07-broadcom-dont-set-speed-before-loading.patch b/packages/network/bluez/patches/bluez-07-broadcom-dont-set-speed-before-loading.patch new file mode 100644 index 000000000..9a78ba029 --- /dev/null +++ b/packages/network/bluez/patches/bluez-07-broadcom-dont-set-speed-before-loading.patch @@ -0,0 +1,21 @@ +diff -Naur a/tools/hciattach_bcm43xx.c b/tools/hciattach_bcm43xx.c +--- a/tools/hciattach_bcm43xx.c 2016-02-25 18:23:15.468717720 +0000 ++++ b/tools/hciattach_bcm43xx.c 2016-02-25 18:24:08.028997243 +0000 +@@ -368,9 +368,6 @@ + if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) { + fprintf(stderr, "Patch not found, continue anyway\n"); + } else { +- if (bcm43xx_set_speed(fd, ti, speed)) +- return -1; +- + if (bcm43xx_load_firmware(fd, fw_path)) + return -1; + +@@ -379,6 +376,7 @@ + perror("Can't set host baud rate"); + return -1; + } ++ sleep(1); + + if (bcm43xx_reset(fd)) + return -1; diff --git a/packages/network/bluez/patches/bluez-08-hciattach-retry-device-reset-when-no-response.patch b/packages/network/bluez/patches/bluez-08-hciattach-retry-device-reset-when-no-response.patch new file mode 100644 index 000000000..1dd60846a --- /dev/null +++ b/packages/network/bluez/patches/bluez-08-hciattach-retry-device-reset-when-no-response.patch @@ -0,0 +1,62 @@ +From d4eafedce242f6c96b46b5a3122a39cc8d2f1373 Mon Sep 17 00:00:00 2001 +From: meijjaa +Date: Mon, 23 Jan 2017 22:35:33 +0100 +Subject: [PATCH] hciattach: retry device reset when no response + +Some bcm chips need a couple of retries to reset. Currently init will just +timeout after a failed reset. + +Signed-off-by: meijjaa +--- + tools/hciattach_bcm43xx.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/tools/hciattach_bcm43xx.c b/tools/hciattach_bcm43xx.c +index 81f38cb..4fd01e2 100644 +--- a/tools/hciattach_bcm43xx.c ++++ b/tools/hciattach_bcm43xx.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #include "lib/bluetooth.h" + #include "lib/hci.h" +@@ -97,21 +98,31 @@ fail: + return -1; + } + ++int _fd; ++void expired(int sig) ++{ ++ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x03, 0x0C, 0x00 }; ++ write(_fd, cmd, sizeof(cmd)) != sizeof(cmd); ++ alarm(4); ++} ++ + static int bcm43xx_reset(int fd) + { + unsigned char cmd[] = { HCI_COMMAND_PKT, 0x03, 0x0C, 0x00 }; + unsigned char resp[CC_MIN_SIZE]; + ++ _fd = fd; ++ signal(SIGALRM, expired); + if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) { + fprintf(stderr, "Failed to write reset command\n"); + return -1; + } +- ++ alarm(4); + if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) { + fprintf(stderr, "Failed to reset chip, invalid HCI event\n"); + return -1; + } +- ++ alarm(0); + if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) { + fprintf(stderr, "Failed to reset chip, command failure\n"); + return -1; +-- +2.7.4 + diff --git a/packages/network/bluez/patches/bluez-09-hciattach-more-verbose.patch b/packages/network/bluez/patches/bluez-09-hciattach-more-verbose.patch new file mode 100644 index 000000000..1248bb758 --- /dev/null +++ b/packages/network/bluez/patches/bluez-09-hciattach-more-verbose.patch @@ -0,0 +1,11 @@ +--- a/tools/hciattach_bcm43xx.c ++++ b/tools/hciattach_bcm43xx.c +@@ -366,7 +366,7 @@ + return -1; + + if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) { +- fprintf(stderr, "Patch not found, continue anyway\n"); ++ fprintf(stderr, "Patch not found for chip %s, continue anyway\n", chip_name); + } else { + if (bcm43xx_load_firmware(fd, fw_path)) + return -1; diff --git a/packages/network/bluez/patches/bluez-11_sixaxis-fix-PID-navigation-controller.patch b/packages/network/bluez/patches/bluez-11_sixaxis-fix-PID-navigation-controller.patch new file mode 100644 index 000000000..a2768cc55 --- /dev/null +++ b/packages/network/bluez/patches/bluez-11_sixaxis-fix-PID-navigation-controller.patch @@ -0,0 +1,48 @@ +From: Szymon Janc +Subject: [PATCH 1/5] sixaxis: Fix PID for Navigation Controller +Newsgroups: gmane.linux.bluez.kernel +Date: 2015-06-15 18:28:26 GMT (36 weeks, 4 days, 21 hours and 32 minutes ago) + +Navigation Controller is using PID 0x042f over USB but PID 0x0268 +(same as Dualshock 3) over BT. +--- + plugins/sixaxis.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/plugins/sixaxis.c ++++ b/plugins/sixaxis.c +@@ -363,7 +363,13 @@ + info("sixaxis: setting up new device"); + + btd_device_device_set_name(device, cp->name); +- btd_device_set_pnpid(device, cp->source, cp->vid, cp->pid, cp->version); ++ ++ /* if device reports different pid/vid on BT prefer those over USB */ ++ if (cp->bt_pid) ++ btd_device_set_pnpid(device, cp->source, cp->vid, cp->bt_pid, cp->version); ++ else ++ btd_device_set_pnpid(device, cp->source, cp->vid, cp->pid, cp->version); ++ + btd_device_set_temporary(device, true); + + closure = g_new0(struct authentication_closure, 1); +--- a/profiles/input/sixaxis.h ++++ b/profiles/input/sixaxis.h +@@ -38,6 +38,7 @@ + uint16_t vid; + uint16_t pid; + uint16_t version; ++ uint16_t bt_pid; + CablePairingType type; + }; + +@@ -59,6 +60,7 @@ + .vid = 0x054c, + .pid = 0x042f, + .version = 0x0000, ++ .bt_pid = 0x0268, + .type = CABLE_PAIRING_SIXAXIS, + }, + { +-- +2.1.4 diff --git a/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_50.patch b/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_50.patch new file mode 100644 index 000000000..24311aac0 --- /dev/null +++ b/packages/network/bluez/patches/bluez-12-fix-obexd-after-5_50.patch @@ -0,0 +1,40 @@ +diff --git a/Makefile.obexd b/Makefile.obexd +index cd3ace4..89f1609 100644 +--- a/Makefile.obexd ++++ b/Makefile.obexd +@@ -8,8 +8,6 @@ endif + + EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service + +-if OBEX +- + obex_plugindir = $(libdir)/obex/plugins + + obexd_builtin_modules = +@@ -33,6 +31,8 @@ obexd_builtin_sources += obexd/plugins/opp.c + obexd_builtin_modules += ftp + obexd_builtin_sources += obexd/plugins/ftp.c obexd/plugins/ftp.h + ++if OBEX ++ + obexd_builtin_modules += irmc + obexd_builtin_sources += obexd/plugins/irmc.c + +@@ -47,6 +47,8 @@ obexd_builtin_sources += obexd/plugins/mas.c obexd/src/map_ap.h \ + obexd/plugins/messages.h \ + obexd/plugins/messages-dummy.c + ++endif ++ + obexd_builtin_modules += mns + obexd_builtin_sources += obexd/client/mns.c obexd/src/map_ap.h \ + obexd/client/map-event.h +@@ -90,8 +92,6 @@ obexd_src_obexd_CFLAGS = $(AM_CFLAGS) @GLIB_CFLAGS@ @DBUS_CFLAGS@ \ + + obexd_src_obexd_CPPFLAGS = -I$(builddir)/lib -I$(builddir)/obexd/src + +-endif +- + obexd_src_obexd_SHORTNAME = obexd + + obexd_builtin_files = obexd/src/builtin.h $(obexd_builtin_nodist) diff --git a/packages/network/bluez/patches/bluez-20-sixaxis-autotrust.patch b/packages/network/bluez/patches/bluez-20-sixaxis-autotrust.patch new file mode 100644 index 000000000..a2ed445ba --- /dev/null +++ b/packages/network/bluez/patches/bluez-20-sixaxis-autotrust.patch @@ -0,0 +1,10 @@ +--- a/plugins/sixaxis.c ++++ b/plugins/sixaxis.c +@@ -370,6 +370,7 @@ + else + btd_device_set_pnpid(device, cp->source, cp->vid, cp->pid, cp->version); + ++ btd_device_set_trusted(device, true); + btd_device_set_temporary(device, true); + + closure = g_new0(struct authentication_closure, 1); diff --git a/packages/network/bluez/patches/bluez-21-hciattach-add-QCA9377-Tuffello-support.patch b/packages/network/bluez/patches/bluez-21-hciattach-add-QCA9377-Tuffello-support.patch new file mode 100644 index 000000000..98355a612 --- /dev/null +++ b/packages/network/bluez/patches/bluez-21-hciattach-add-QCA9377-Tuffello-support.patch @@ -0,0 +1,2376 @@ +From b42a087411199d7f480f1683bddd3206c5fd17b1 Mon Sep 17 00:00:00 2001 +From: Gary Bisson +Date: Wed, 17 Aug 2016 11:36:28 +0200 +Subject: [PATCH] hciattach: add QCA9377 Tuffello support + +From CodeAurora repository: +https://source.codeaurora.org/quic/la/platform/external/bluetooth/bluez/ + +Modifications: +- code indentation +- remove verbose traces +- use H4 protocol instead of IBS + +Also squashed: +hciattach_rome: simplify baudrate setting +hciattach_rome: do not override module internal MAC address +hciattach_rome: force IBS to disabled in NVM +hciattach_rome: display ROM and TLV info by default + +Signed-off-by: Gary Bisson +--- + Makefile.tools | 1 + + android/Android.mk | 1 + + tools/hciattach.c | 12 + + tools/hciattach.h | 1 + + tools/hciattach_rome.c | 1872 ++++++++++++++++++++++++++++++++++++++++ + tools/hciattach_rome.h | 388 +++++++++ + 6 files changed, 2275 insertions(+) + create mode 100644 tools/hciattach_rome.c + create mode 100644 tools/hciattach_rome.h + +diff --git a/Makefile.tools b/Makefile.tools +index b7b422506..e0e995089 100644 +--- a/Makefile.tools ++++ b/Makefile.tools +@@ -304,6 +304,7 @@ tools_hciattach_SOURCES = tools/hciattach.c tools/hciattach.h \ + tools/hciattach_ti.c \ + tools/hciattach_tialt.c \ + tools/hciattach_ath3k.c \ ++ tools/hciattach_rome.c \ + tools/hciattach_qualcomm.c \ + tools/hciattach_intel.c \ + tools/hciattach_bcm43xx.c +diff --git a/android/Android.mk b/android/Android.mk +index 76a826b47..01599c04b 100644 +--- a/android/Android.mk ++++ b/android/Android.mk +@@ -696,6 +696,7 @@ LOCAL_SRC_FILES := \ + bluez/tools/hciattach_ti.c \ + bluez/tools/hciattach_tialt.c \ + bluez/tools/hciattach_ath3k.c \ ++ bluez/tools/hciattach_rome.c \ + bluez/tools/hciattach_qualcomm.c \ + bluez/tools/hciattach_intel.c \ + bluez/tools/hciattach_bcm43xx.c \ +diff --git a/tools/hciattach.c b/tools/hciattach.c +index fad176c9b..02a65c692 100644 +--- a/tools/hciattach.c ++++ b/tools/hciattach.c +@@ -263,6 +263,11 @@ static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti) + return ath3k_post(fd, u->pm); + } + ++static int qca(int fd, struct uart_t *u, struct termios *ti) ++{ ++ return qca_soc_init(fd, u->speed, u->bdaddr); ++} ++ + static int qualcomm(int fd, struct uart_t *u, struct termios *ti) + { + return qualcomm_init(fd, u->speed, ti, u->bdaddr); +@@ -1093,6 +1098,10 @@ struct uart_t uart[] = { + { "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200, + FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm }, + ++ /* QCA ROME */ ++ { "qca", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, ++ FLOW_CTL, DISABLE_PM, NULL, qca, NULL }, ++ + /* QUALCOMM BTS */ + { "qualcomm", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, + FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL }, +@@ -1145,6 +1154,9 @@ static int init_uart(char *dev, struct uart_t *u, int send_break, int raw) + if (u->flags & AMP_DEV) + flags |= 1 << HCI_UART_CREATE_AMP; + ++ if (!strncmp(u->type, "qca", 3)) ++ flags |= 1 << HCI_UART_RESET_ON_INIT; ++ + fd = open(dev, O_RDWR | O_NOCTTY); + if (fd < 0) { + perror("Can't open serial port"); +diff --git a/tools/hciattach.h b/tools/hciattach.h +index 249aab49e..85c801ccf 100644 +--- a/tools/hciattach.h ++++ b/tools/hciattach.h +@@ -65,6 +65,7 @@ int bgb2xx_init(int dd, bdaddr_t *bdaddr); + int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, + struct termios *ti); + int ath3k_post(int fd, int pm); ++int qca_soc_init(int fd, int speed, char *bdaddr); + int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr); + int intel_init(int fd, int init_speed, int *speed, struct termios *ti); + int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti, +diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c +new file mode 100644 +index 000000000..9a7f222c4 +--- /dev/null ++++ b/tools/hciattach_rome.c +@@ -0,0 +1,1872 @@ ++/* ++ * ++ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++ * Not a Contribution. ++ * ++ * Copyright 2012 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); you ++ * may not use this file except in compliance with the License. You may ++ * obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ * implied. See the License for the specific language governing ++ * permissions and limitations under the License. ++ * ++ */ ++ ++/****************************************************************************** ++ * ++ * Filename: hciattach_rome.c ++ * ++ * Description: Contains controller-specific functions, like ++ * firmware patch download ++ * low power mode operations ++ * ++ ******************************************************************************/ ++ ++#define MODULE_HAS_MAC_ADDR ++#define LOG_TAG "bt_vendor" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hciattach_rome.h" ++#include "hciattach.h" ++ ++/****************************************************************************** ++ ** Variables ++ ******************************************************************************/ ++FILE *file; ++unsigned char *phdr_buffer; ++unsigned char *pdata_buffer = NULL; ++patch_info rampatch_patch_info; ++int rome_ver = ROME_VER_UNKNOWN; ++unsigned char gTlv_type; ++unsigned char gtlv_dwndcfg; ++char *rampatch_file_path; ++char *nvm_file_path; ++vnd_userial_cb_t vnd_userial; ++unsigned char wait_vsc_evt = TRUE; ++ ++/***************************************************************************** ++ ** Functions ++ *****************************************************************************/ ++ ++/******************************************************************************* ++ ** ++ ** Function userial_to_tcio_baud ++ ** ++ ** Description helper function converts USERIAL baud rates into TCIO ++ ** conforming baud rates ++ ** ++ ** Returns TRUE/FALSE ++ ** ++ *******************************************************************************/ ++unsigned char userial_to_tcio_baud(unsigned char cfg_baud, unsigned int *baud) ++{ ++ if (cfg_baud == USERIAL_BAUD_115200) ++ *baud = B115200; ++ else if (cfg_baud == USERIAL_BAUD_4M) ++ *baud = B4000000; ++ else if (cfg_baud == USERIAL_BAUD_3M) ++ *baud = B3000000; ++ else if (cfg_baud == USERIAL_BAUD_2M) ++ *baud = B2000000; ++ else if (cfg_baud == USERIAL_BAUD_1M) ++ *baud = B1000000; ++ else if (cfg_baud == USERIAL_BAUD_921600) ++ *baud = B921600; ++ else if (cfg_baud == USERIAL_BAUD_460800) ++ *baud = B460800; ++ else if (cfg_baud == USERIAL_BAUD_230400) ++ *baud = B230400; ++ else if (cfg_baud == USERIAL_BAUD_57600) ++ *baud = B57600; ++ else if (cfg_baud == USERIAL_BAUD_19200) ++ *baud = B19200; ++ else if (cfg_baud == USERIAL_BAUD_9600) ++ *baud = B9600; ++ else if (cfg_baud == USERIAL_BAUD_1200) ++ *baud = B1200; ++ else if (cfg_baud == USERIAL_BAUD_600) ++ *baud = B600; ++ else { ++ fprintf(stderr, "userial vendor open: unsupported baud idx %i\n", cfg_baud); ++ *baud = B115200; ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++ ++/******************************************************************************* ++ ** ++ ** Function userial_vendor_set_baud ++ ** ++ ** Description Set new baud rate ++ ** ++ ** Returns None ++ ** ++ *******************************************************************************/ ++void userial_vendor_set_baud(unsigned char userial_baud) ++{ ++ unsigned int tcio_baud; ++ ++ if (tcgetattr(vnd_userial.fd, &vnd_userial.termios) < 0) { ++ perror("Can't get port settings"); ++ return; ++ } ++ cfmakeraw(&vnd_userial.termios); ++ vnd_userial.termios.c_cflag |= CLOCAL; ++ vnd_userial.termios.c_cflag |= CREAD; ++ vnd_userial.termios.c_cflag |= CS8; ++ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); ++ ++ userial_to_tcio_baud(userial_baud, &tcio_baud); ++ ++ cfsetospeed(&vnd_userial.termios, tcio_baud); ++ cfsetispeed(&vnd_userial.termios, tcio_baud); ++ tcsetattr(vnd_userial.fd, TCSADRAIN, &vnd_userial.termios); /* don't change speed until last write done */ ++ ++} ++ ++ ++/******************************************************************************* ++ ** ++ ** Function userial_vendor_ioctl ++ ** ++ ** Description ioctl inteface ++ ** ++ ** Returns None ++ ** ++ *******************************************************************************/ ++int userial_vendor_ioctl(int fd, userial_vendor_ioctl_op_t op, int *p_data) ++{ ++ int err = -1; ++ struct termios ti; ++ ++ if (tcgetattr(fd, &ti) < 0) { ++ perror("Can't get port settings"); ++ return -1; ++ } ++ cfmakeraw(&ti); ++ ti.c_cflag |= CLOCAL; ++ ti.c_cflag |= CREAD; ++ ti.c_cflag |= CS8; ++ ++ switch(op) { ++#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) ++ case USERIAL_OP_ASSERT_BT_WAKE: ++ VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); ++ err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); ++ break; ++ ++ case USERIAL_OP_DEASSERT_BT_WAKE: ++ VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); ++ err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); ++ break; ++ ++ case USERIAL_OP_GET_BT_WAKE_STATE: ++ err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); ++ break; ++#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) ++ case USERIAL_OP_FLOW_ON: ++ ti.c_cflag |= CRTSCTS; ++ if (err = tcsetattr(fd, TCSANOW, &ti) < 0) { ++ perror("Can't set port settings"); ++ return -1; ++ } ++ ++ break; ++ ++ case USERIAL_OP_FLOW_OFF: ++ ti.c_cflag &= ~CRTSCTS; ++ if (err = tcsetattr(fd, TCSANOW, &ti) < 0) { ++ fprintf(stderr, "Can't set port settings"); ++ return -1; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return err; ++} ++ ++ ++int get_vs_hci_event(unsigned char *rsp) ++{ ++ int err = 0, soc_id =0; ++ unsigned char paramlen = 0; ++ ++ if ( (rsp[EVENTCODE_OFFSET] == VSEVENT_CODE) || (rsp[EVENTCODE_OFFSET] == EVT_CMD_COMPLETE)) ++ PR_DBG("%s: Received HCI-Vendor Specific event\n", __FUNCTION__); ++ else { ++ fprintf(stderr, "%s: Failed to receive HCI-Vendor Specific event\n", __FUNCTION__); ++ err = -EIO; ++ goto failed; ++ } ++ ++ /* Check the status of the operation */ ++ switch ( rsp[CMD_RSP_OFFSET] ) { ++ case EDL_CMD_REQ_RES_EVT: ++ switch(rsp[RSP_TYPE_OFFSET]) { ++ case EDL_PATCH_VER_RES_EVT: ++ case EDL_APP_VER_RES_EVT: ++ PR_INFO("Current Product ID\t\t: 0x%08x\n", ++ (unsigned int)(rsp[PATCH_PROD_ID_OFFSET +3] << 24 | ++ rsp[PATCH_PROD_ID_OFFSET+2] << 16 | ++ rsp[PATCH_PROD_ID_OFFSET+1] << 8 | ++ rsp[PATCH_PROD_ID_OFFSET] )); ++ ++ /* Patch Version indicates FW patch version */ ++ PR_INFO("Current Patch Version\t\t: 0x%04x\n", ++ (unsigned short)(rsp[PATCH_PATCH_VER_OFFSET + 1] << 8 | ++ rsp[PATCH_PATCH_VER_OFFSET] )); ++ ++ /* ROM Build Version indicates ROM build version like 1.0/1.1/2.0 */ ++ rome_ver = (int)(rsp[PATCH_ROM_BUILD_VER_OFFSET + 1] << 8 | ++ rsp[PATCH_ROM_BUILD_VER_OFFSET]); ++ PR_INFO("Current ROM Build Version\t: 0x%04x\n", rome_ver); ++ ++ /* In case rome 1.0/1.1, there is no SOC ID version available */ ++ if (paramlen - 10) { ++ soc_id = (unsigned int)(rsp[PATCH_SOC_VER_OFFSET +3] << 24 | ++ rsp[PATCH_SOC_VER_OFFSET+2] << 16 | ++ rsp[PATCH_SOC_VER_OFFSET+1] << 8 | ++ rsp[PATCH_SOC_VER_OFFSET]); ++ PR_INFO("Current SOC Version\t\t: 0x%08x\n", soc_id); ++ } ++ ++ /* Rome Chipset Version can be decided by Patch version and SOC version, ++ Upper 2 bytes will be used for Patch version and Lower 2 bytes will be ++ used for SOC as combination for BT host driver */ ++ rome_ver = (rome_ver << 16) | (soc_id & 0x0000ffff); ++ break; ++ case EDL_TVL_DNLD_RES_EVT: ++ case EDL_CMD_EXE_STATUS_EVT: ++ switch (err = rsp[CMD_STATUS_OFFSET]) { ++ case HCI_CMD_SUCCESS: ++ PR_DBG("%s: Download Packet successfully!\n", __FUNCTION__); ++ break; ++ case PATCH_LEN_ERROR: ++ fprintf(stderr, "%s: Invalid patch length argument passed for EDL PATCH " ++ "SET REQ cmd\n", __FUNCTION__); ++ break; ++ case PATCH_VER_ERROR: ++ fprintf(stderr, "%s: Invalid patch version argument passed for EDL PATCH " ++ "SET REQ cmd\n", __FUNCTION__); ++ break; ++ case PATCH_CRC_ERROR: ++ fprintf(stderr, "%s: CRC check of patch failed!!!\n", __FUNCTION__); ++ break; ++ case PATCH_NOT_FOUND: ++ fprintf(stderr, "%s: Invalid patch data!!!\n", __FUNCTION__); ++ break; ++ case TLV_TYPE_ERROR: ++ fprintf(stderr, "%s: TLV Type Error !!!\n", __FUNCTION__); ++ break; ++ default: ++ fprintf(stderr, "%s: Undefined error (0x%x)", __FUNCTION__, err); ++ break; ++ } ++ break; ++ } ++ break; ++ ++ case NVM_ACCESS_CODE: ++ PR_DBG("%s: NVM Access Code!!!\n", __FUNCTION__); ++ err = HCI_CMD_SUCCESS; ++ break; ++ case EDL_SET_BAUDRATE_RSP_EVT: ++ /* Rome 1.1 has bug with the response, so it should ignore it. */ ++ if (rsp[BAUDRATE_RSP_STATUS_OFFSET] != BAUDRATE_CHANGE_SUCCESS) { ++ fprintf(stderr, "%s: Set Baudrate request failed - 0x%x\n", __FUNCTION__, ++ rsp[CMD_STATUS_OFFSET]); ++ err = -1; ++ } ++ break; ++ default: ++ fprintf(stderr, "%s: Not a valid status!!!\n", __FUNCTION__); ++ err = -1; ++ break; ++ } ++ ++failed: ++ return err; ++} ++ ++ ++int wait_for_data(int fd, int maxTimeOut) ++{ ++ fd_set infids; ++ struct timeval timeout; ++ ++ if (maxTimeOut <= 0) { ++ fprintf(stderr, "%s: Invalid timeout value specified", __func__); ++ return -EINVAL; ++ } ++ ++ FD_ZERO (&infids); ++ FD_SET (fd, &infids); ++ timeout.tv_sec = maxTimeOut; ++ timeout.tv_usec = 0; ++ ++ /* Check whether data is available in TTY buffer before calling read() */ ++ if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1) { ++ fprintf(stderr, "%s: Timing out on select for %d secs.\n", __FUNCTION__, maxTimeOut); ++ return -1; ++ } ++ ++ return 1; ++} ++ ++/* ++ * Read an VS HCI event from the given file descriptor. ++ */ ++int read_vs_hci_event(int fd, unsigned char* buf, int size) ++{ ++ int remain, r, retry = 0; ++ int count = 0; ++ ++ if (size <= 0) { ++ fprintf(stderr, "Invalid size arguement!\n"); ++ return -1; ++ } ++ ++ /* Check whether data is available in TTY buffer before calling read() */ ++ if (wait_for_data(fd, SELECT_TIMEOUT) < 1) ++ return -1; ++ ++ /* The first byte identifies the packet type. For HCI event packets, it ++ * should be 0x04, so we read until we get to the 0x04. */ ++ /* It will keep reading until find 0x04 byte */ ++ while (1) { ++ /* Read UART Buffer for HCI-DATA */ ++ r = read(fd, buf, 1); ++ if (r <= 0) { ++ fprintf(stderr, "%s: read() failed. error: %d\n", ++ __FUNCTION__, r); ++ return -1; ++ } ++ ++ /* Check if received data is HCI-DATA or not. ++ * If not HCI-DATA, then retry reading the UART Buffer once. ++ * Sometimes there could be corruption on the UART lines and to ++ * avoid that retry once reading the UART Buffer for HCI-DATA. ++ */ ++ if (buf[0] == 0x04) { /* Recvd. HCI DATA */ ++ retry = 0; ++ break; ++ } ++ else if (retry < MAX_RETRY_CNT) { /* Retry mechanism */ ++ retry++; ++ fprintf(stderr, "%s: Not an HCI-VS-Event! buf[0]: %d", ++ __FUNCTION__, buf[0]); ++ if (wait_for_data(fd, SELECT_TIMEOUT) < 1) ++ return -1; ++ else /* Data available in UART Buffer: Continue to read */ ++ continue; ++ } ++ else { /* RETRY failed : Exiting with failure */ ++ fprintf(stderr, "%s: RETRY failed!", __FUNCTION__); ++ return -1; ++ } ++ } ++ count++; ++ ++ /* The next two bytes are the event code and parameter total length. */ ++ while (count < 3) { ++ r = read(fd, buf + count, 3 - count); ++ if ((r <= 0) || (buf[1] != 0xFF )) { ++ fprintf(stderr, "It is not VS event !!\n"); ++ return -1; ++ } ++ count += r; ++ } ++ ++ /* Now we read the parameters. */ ++ if (buf[2] < (size - 3)) ++ remain = buf[2]; ++ else ++ remain = size - 3; ++ ++ while ((count - 3) < remain) { ++ r = read(fd, buf + count, remain - (count - 3)); ++ if (r <= 0) ++ return -1; ++ count += r; ++ } ++ ++ /* Check if the set patch command is successful or not */ ++ if (get_vs_hci_event(buf) != HCI_CMD_SUCCESS) ++ return -1; ++ ++ return count; ++} ++ ++ ++int hci_send_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size) ++{ ++ int ret = 0; ++ ++ /* Send the HCI command packet to UART for transmission */ ++ ret = write(fd, cmd, size); ++ if (ret != size) { ++ fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, ret); ++ goto failed; ++ } ++ ++ if (wait_vsc_evt) { ++ /* Check for response from the Controller */ ++ if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) { ++ ret = -ETIMEDOUT; ++ fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__); ++ goto failed; ++ } ++ } ++ ++failed: ++ return ret; ++} ++ ++void frame_hci_cmd_pkt( ++ unsigned char *cmd, ++ int edl_cmd, unsigned int p_base_addr, ++ int segtNo, int size ++ ) ++{ ++ int offset = 0; ++ hci_command_hdr *cmd_hdr; ++ ++ memset(cmd, 0x0, HCI_MAX_CMD_SIZE); ++ ++ cmd_hdr = (void *) (cmd + 1); ++ ++ cmd[0] = HCI_COMMAND_PKT; ++ cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, HCI_PATCH_CMD_OCF); ++ cmd_hdr->plen = size; ++ cmd[4] = edl_cmd; ++ ++ switch (edl_cmd) { ++ case EDL_PATCH_SET_REQ_CMD: ++ /* Copy the patch header info as CMD params */ ++ memcpy(&cmd[5], phdr_buffer, PATCH_HDR_LEN); ++ PR_DBG("%s: Sending EDL_PATCH_SET_REQ_CMD\n", __FUNCTION__); ++ PR_DBG("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n", ++ segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); ++ break; ++ case EDL_PATCH_DLD_REQ_CMD: ++ offset = ((segtNo - 1) * MAX_DATA_PER_SEGMENT); ++ p_base_addr += offset; ++ cmd_hdr->plen = (size + 6); ++ cmd[5] = (size + 4); ++ cmd[6] = EXTRACT_BYTE(p_base_addr, 0); ++ cmd[7] = EXTRACT_BYTE(p_base_addr, 1); ++ cmd[8] = EXTRACT_BYTE(p_base_addr, 2); ++ cmd[9] = EXTRACT_BYTE(p_base_addr, 3); ++ memcpy(&cmd[10], (pdata_buffer + offset), size); ++ ++ PR_DBG("%s: Sending EDL_PATCH_DLD_REQ_CMD: size: %d bytes\n", ++ __FUNCTION__, size); ++ PR_DBG("HCI-CMD %d:\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t" ++ "0x%x\t0x%x\t0x%x\t\n", segtNo, cmd[0], cmd[1], cmd[2], ++ cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]); ++ break; ++ case EDL_PATCH_ATCH_REQ_CMD: ++ PR_DBG("%s: Sending EDL_PATCH_ATTACH_REQ_CMD\n", __FUNCTION__); ++ PR_DBG("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n", ++ segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); ++ break; ++ case EDL_PATCH_RST_REQ_CMD: ++ PR_DBG("%s: Sending EDL_PATCH_RESET_REQ_CMD\n", __FUNCTION__); ++ PR_DBG("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n", ++ segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); ++ break; ++ case EDL_PATCH_VER_REQ_CMD: ++ PR_DBG("%s: Sending EDL_PATCH_VER_REQ_CMD\n", __FUNCTION__); ++ PR_DBG("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n", ++ segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); ++ break; ++ case EDL_PATCH_TLV_REQ_CMD: ++ PR_DBG("%s: Sending EDL_PATCH_TLV_REQ_CMD\n", __FUNCTION__); ++ /* Parameter Total Length */ ++ cmd[3] = size +2; ++ ++ /* TLV Segment Length */ ++ cmd[5] = size; ++ PR_DBG("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n", ++ segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]); ++ offset = (segtNo * MAX_SIZE_PER_TLV_SEGMENT); ++ memcpy(&cmd[6], (pdata_buffer + offset), size); ++ break; ++ default: ++ fprintf(stderr, "%s: Unknown EDL CMD !!!\n", __FUNCTION__); ++ } ++} ++ ++void rome_extract_patch_header_info(unsigned char *buf) ++{ ++ int index; ++ ++ /* Extract patch id */ ++ for (index = 0; index < 4; index++) ++ rampatch_patch_info.patch_id |= ++ (LSH(buf[index + P_ID_OFFSET], (index * 8))); ++ ++ /* Extract (ROM and BUILD) version information */ ++ for (index = 0; index < 2; index++) ++ rampatch_patch_info.patch_ver.rom_version |= ++ (LSH(buf[index + P_ROME_VER_OFFSET], (index * 8))); ++ ++ for (index = 0; index < 2; index++) ++ rampatch_patch_info.patch_ver.build_version |= ++ (LSH(buf[index + P_BUILD_VER_OFFSET], (index * 8))); ++ ++ /* Extract patch base and entry addresses */ ++ for (index = 0; index < 4; index++) ++ rampatch_patch_info.patch_base_addr |= ++ (LSH(buf[index + P_BASE_ADDR_OFFSET], (index * 8))); ++ ++ /* Patch BASE & ENTRY addresses are same */ ++ rampatch_patch_info.patch_entry_addr = rampatch_patch_info.patch_base_addr; ++ ++ /* Extract total length of the patch payload */ ++ for (index = 0; index < 4; index++) ++ rampatch_patch_info.patch_length |= ++ (LSH(buf[index + P_LEN_OFFSET], (index * 8))); ++ ++ /* Extract the CRC checksum of the patch payload */ ++ for (index = 0; index < 4; index++) ++ rampatch_patch_info.patch_crc |= ++ (LSH(buf[index + P_CRC_OFFSET], (index * 8))); ++ ++ /* Extract patch control value */ ++ for (index = 0; index < 4; index++) ++ rampatch_patch_info.patch_ctrl |= ++ (LSH(buf[index + P_CONTROL_OFFSET], (index * 8))); ++ ++ fprintf(stderr, "PATCH_ID\t : 0x%x\n", rampatch_patch_info.patch_id); ++ fprintf(stderr, "ROM_VERSION\t : 0x%x\n", rampatch_patch_info.patch_ver.rom_version); ++ fprintf(stderr, "BUILD_VERSION\t : 0x%x\n", rampatch_patch_info.patch_ver.build_version); ++ fprintf(stderr, "PATCH_LENGTH\t : 0x%x\n", rampatch_patch_info.patch_length); ++ fprintf(stderr, "PATCH_CRC\t : 0x%x\n", rampatch_patch_info.patch_crc); ++ fprintf(stderr, "PATCH_CONTROL\t : 0x%x\n", rampatch_patch_info.patch_ctrl); ++ fprintf(stderr, "PATCH_BASE_ADDR\t : 0x%x\n", rampatch_patch_info.patch_base_addr); ++ ++} ++ ++int rome_edl_set_patch_request(int fd) ++{ ++ int size, err; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++ /* Frame the HCI CMD to be sent to the Controller */ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_SET_REQ_CMD, 0, ++ -1, PATCH_HDR_LEN + 1); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to set the patch info to the Controller!\n"); ++ goto error; ++ } ++ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__); ++ goto error; ++ } ++error: ++ return err; ++} ++ ++int rome_edl_patch_download_request(int fd) ++{ ++ int no_of_patch_segment; ++ int index = 1, err = 0, size = 0; ++ unsigned int p_base_addr; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++ no_of_patch_segment = (rampatch_patch_info.patch_length / ++ MAX_DATA_PER_SEGMENT); ++ ++ /* Initialize the patch base address from the one read from bin file */ ++ p_base_addr = rampatch_patch_info.patch_base_addr; ++ ++ /* ++ * Depending upon size of the patch payload, download the patches in ++ * segments with a max. size of 239 bytes ++ */ ++ for (index = 1; index <= no_of_patch_segment; index++) { ++ /* Frame the HCI CMD PKT to be sent to Controller*/ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr, ++ index, MAX_DATA_PER_SEGMENT); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]); ++ ++ /* Initialize the RSP packet everytime to 0 */ ++ memset(rsp, 0x0, HCI_MAX_EVENT_SIZE); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to send the patch payload to the Controller!\n"); ++ goto error; ++ } ++ ++ /* Read Command Complete Event */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n", ++ __FUNCTION__, index); ++ goto error; ++ } ++ } ++ ++ /* Check if any pending patch data to be sent */ ++ size = (rampatch_patch_info.patch_length < MAX_DATA_PER_SEGMENT) ? ++ rampatch_patch_info.patch_length : ++ (rampatch_patch_info.patch_length % MAX_DATA_PER_SEGMENT); ++ ++ if (size) { ++ /* Frame the HCI CMD PKT to be sent to Controller*/ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr, index, size); ++ ++ /* Initialize the RSP packet everytime to 0 */ ++ memset(rsp, 0x0, HCI_MAX_EVENT_SIZE); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to send the patch payload to the Controller!\n"); ++ goto error; ++ } ++ ++ /* Read Command Complete Event */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n", ++ __FUNCTION__, index); ++ goto error; ++ } ++ } ++ ++error: ++ return err; ++} ++ ++static int rome_download_rampatch(int fd) ++{ ++ int c, size, index, ret = -1; ++ ++ /* Get handle to the RAMPATCH binary file */ ++ fprintf(stderr, "%s: Getting handle to the RAMPATCH binary file from %s\n", __FUNCTION__, ROME_FW_PATH); ++ file = fopen(ROME_FW_PATH, "r"); ++ if (file == NULL) { ++ fprintf(stderr, "%s: Failed to get handle to the RAMPATCH bin file!\n", ++ __FUNCTION__); ++ return -ENFILE; ++ } ++ ++ /* Allocate memory for the patch headder info */ ++ fprintf(stderr, "%s: Allocating memory for the patch header\n", __FUNCTION__); ++ phdr_buffer = (unsigned char *) malloc(PATCH_HDR_LEN + 1); ++ if (phdr_buffer == NULL) { ++ fprintf(stderr, "%s: Failed to allocate memory for patch header\n", ++ __FUNCTION__); ++ goto phdr_alloc_failed; ++ } ++ for (index = 0; index < PATCH_HDR_LEN + 1; index++) ++ phdr_buffer[index] = 0x0; ++ ++ /* Read 28 bytes of patch header information */ ++ fprintf(stderr, "%s: Reading patch header info\n", __FUNCTION__); ++ index = 0; ++ do { ++ c = fgetc (file); ++ phdr_buffer[index++] = (unsigned char)c; ++ } while (index != PATCH_HDR_LEN); ++ ++ /* Save the patch header info into local structure */ ++ fprintf(stderr, "%s: Saving patch hdr. info\n", __FUNCTION__); ++ rome_extract_patch_header_info((unsigned char *)phdr_buffer); ++ ++ /* Set the patch header info onto the Controller */ ++ ret = rome_edl_set_patch_request(fd); ++ if (ret < 0) { ++ fprintf(stderr, "%s: Error setting the patchheader info!\n", __FUNCTION__); ++ goto pdata_alloc_failed; ++ } ++ ++ /* Allocate memory for the patch payload */ ++ fprintf(stderr, "%s: Allocating memory for patch payload\n", __FUNCTION__); ++ size = rampatch_patch_info.patch_length; ++ pdata_buffer = (unsigned char *) malloc(size+1); ++ if (pdata_buffer == NULL) { ++ fprintf(stderr, "%s: Failed to allocate memory for patch payload\n", ++ __FUNCTION__); ++ goto pdata_alloc_failed; ++ } ++ for (index = 0; index < size+1; index++) ++ pdata_buffer[index] = 0x0; ++ ++ /* Read the patch data from Rampatch binary image */ ++ fprintf(stderr, "%s: Reading patch payload from RAMPATCH file\n", __FUNCTION__); ++ index = 0; ++ do { ++ c = fgetc (file); ++ pdata_buffer[index++] = (unsigned char)c; ++ } while (c != EOF); ++ ++ /* Downloading patches in segments to controller */ ++ ret = rome_edl_patch_download_request(fd); ++ if (ret < 0) { ++ fprintf(stderr, "%s: Error downloading patch segments!\n", __FUNCTION__); ++ goto cleanup; ++ } ++cleanup: ++ free(pdata_buffer); ++pdata_alloc_failed: ++ free(phdr_buffer); ++phdr_alloc_failed: ++ fclose(file); ++ ++ return ret; ++} ++ ++int rome_attach_rampatch(int fd) ++{ ++ int size, err; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++ /* Frame the HCI CMD to be sent to the Controller */ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_ATCH_REQ_CMD, 0, ++ -1, EDL_PATCH_CMD_LEN); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to attach the patch payload to the Controller!\n"); ++ goto error; ++ } ++ ++ /* Read Command Complete Event */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to attach the patch segment(s)\n", __FUNCTION__); ++ goto error; ++ } ++error: ++ return err; ++} ++ ++int rome_rampatch_reset(int fd) ++{ ++ int size, err = 0; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ struct timespec tm = { 0, 100*1000*1000 }; /* 100 ms */ ++ ++ /* Frame the HCI CMD to be sent to the Controller */ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_RST_REQ_CMD, 0, ++ -1, EDL_PATCH_CMD_LEN); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN); ++ ++ /* Send HCI Command packet to Controller */ ++ err = write(fd, cmd, size); ++ if (err != size) { ++ fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err); ++ goto error; ++ } ++ ++ /* ++ * Controller doesn't sends any response for the patch reset ++ * command. HOST has to wait for 100ms before proceeding. ++ */ ++ nanosleep(&tm, NULL); ++ ++error: ++ return err; ++} ++ ++int get_value_from_config(char *file_path,char *param) ++{ ++ FILE *pfile = NULL; ++ char *line = NULL; ++ char *pch = NULL; ++ char param_str[20]; ++ int bytes_read = 0, position; ++ int ret = -1; ++ ++ if (!file_path || !param) { ++ fprintf(stderr,"Invalid arguments\n"); ++ return -EINVAL; ++ } ++ ++ pfile = fopen(file_path, "r" ); ++ if (!pfile) { ++ fprintf(stderr, "Failed to open %s\n", file_path); ++ return ret; ++ } ++ ++ while (getline(&line, &bytes_read, pfile) > 0 ) { ++ if (line[0] != '#' && line[0] != '\n') { ++ pch = memchr(line, '=', strlen(line)); ++ if (pch != NULL) { ++ position = pch - line; ++ strncpy(param_str, line, position); ++ if (strncmp(param_str, param, position) == 0) { ++ ret = atoi(pch + 1); ++ break; ++ } ++ } ++ } ++ } ++ free(line); ++ fclose(pfile); ++ return ret; ++} ++ ++int read_bd_address(unsigned char *bdaddr) ++{ ++ int fd = -1; ++ int readPtr = 0; ++ unsigned char data[BD_ADDR_LEN]; ++ ++ /* Open the persist file for reading device address*/ ++ fd = open("/etc/bluetooth/.bt_nv.bin", O_RDONLY); ++ if (fd < 0) { ++ fprintf(stderr, "%s: Open failed: Programming default BD ADDR\n", __func__); ++ return -1; ++ } ++ ++ /* Read the NVM Header : fp will be advanced by readPtr number of bytes */ ++ readPtr = read(fd, data, PERSIST_HEADER_LEN); ++ if (readPtr > 0) ++ fprintf(stderr, "%s: Persist header data: %02x \t %02x \t %02x\n", __func__, ++ data[NVITEM], data[RDWR_PROT], data[NVITEM_SIZE]); ++ else { ++ fprintf(stderr, "%s: Read from persist memory failed : Programming default" ++ " BD ADDR\n"); ++ close(fd); ++ return -1; ++ } ++ ++ /* Check for BD ADDR length before programming */ ++ if (data[NVITEM_SIZE] != BD_ADDR_LEN) { ++ fprintf(stderr, "Invalid BD ADDR: Programming default BD ADDR!\n"); ++ close(fd); ++ return -1; ++ } ++ ++ /* Read the BD ADDR info */ ++ readPtr = read(fd, data, BD_ADDR_LEN); ++ if (readPtr > 0) ++ fprintf(stderr, "BD-ADDR: ==> %02x:%02x:%02x:%02x:%02x:%02x\n", data[0], ++ data[1], data[2], data[3], data[4], data[5]); ++ else { ++ fprintf(stderr, "%s: Read from persist memory failed : Programming default" ++ " BD ADDR\n"); ++ close(fd); ++ return -1; ++ } ++ memcpy(bdaddr, data, BD_ADDR_LEN); ++ close(fd); ++ return 0; ++} ++ ++int isSpeedValid(int speed, unsigned char *baud_rate) ++{ ++ switch(speed) { ++ case 9600: ++ *baud_rate = BAUDRATE_9600; ++ break; ++ case 19200: ++ *baud_rate = BAUDRATE_19200; ++ break; ++ case 57600: ++ *baud_rate = BAUDRATE_57600; ++ break; ++ case 115200: ++ *baud_rate = BAUDRATE_115200; ++ break; ++ case 230400: ++ *baud_rate = BAUDRATE_230400; ++ break; ++ case 460800: ++ *baud_rate = BAUDRATE_460800; ++ break; ++ case 921600: ++ *baud_rate = BAUDRATE_921600; ++ break; ++ case 1000000: ++ *baud_rate = BAUDRATE_1000000; ++ break; ++ case 2000000: ++ *baud_rate = BAUDRATE_2000000; ++ break; ++ case 3000000: ++ *baud_rate = BAUDRATE_3000000; ++ break; ++ case 4000000: ++ *baud_rate = BAUDRATE_4000000; ++ break; ++ case 300: ++ case 600: ++ case 1200: ++ case 2400: ++ default: ++ fprintf(stderr, "Invalid baudrate, default to 115200!\n"); ++ *baud_rate = BAUDRATE_115200; ++ break; ++ } ++ return -1; ++} ++ ++int rome_get_tlv_file(char *file_path, unsigned char baud_rate) ++{ ++ FILE * pFile; ++ long fileSize; ++ int readSize, nvm_length, nvm_index, i; ++ unsigned short nvm_tag_len; ++ tlv_patch_info *ptlv_header; ++ tlv_nvm_hdr *nvm_ptr; ++ unsigned char data_buf[PRINT_BUF_SIZE]={0,}; ++ unsigned char *nvm_byte_ptr; ++ unsigned char bdaddr[6]; ++ unsigned short pcm_value, ibs_value; ++ unsigned short deep_sleep_value; ++ ++ pFile = fopen ( file_path , "r" ); ++ if (pFile==NULL) { ++ fprintf(stderr, "%s File Open Fail\n", file_path); ++ return -1; ++ } ++ ++ /* Get File Size */ ++ fseek (pFile , 0 , SEEK_END); ++ ++ if ((fileSize = ftell(pFile)) < 0) { ++ fprintf(stderr, "%s: fail to get current file position\n", file_path); ++ fclose(pFile); ++ return -1; ++ } ++ ++ if (fileSize == 0) { ++ fprintf(stderr, "%s: no content in the file\n", file_path); ++ fclose(pFile); ++ return -1; ++ } ++ ++ rewind (pFile); ++ ++ pdata_buffer = (unsigned char*) malloc (sizeof(char)*fileSize); ++ if (pdata_buffer == NULL) { ++ fprintf(stderr, "Allocated Memory failed\n"); ++ fclose (pFile); ++ return -1; ++ } ++ ++ /* Copy file into allocated buffer */ ++ readSize = fread (pdata_buffer,1,fileSize,pFile); ++ ++ /* File Close */ ++ fclose (pFile); ++ ++ if (readSize != fileSize) { ++ fprintf(stderr, "Read file size(%d) not matched with actual file size (%ld bytes)\n",readSize,fileSize); ++ return -1; ++ } ++ ++ ptlv_header = (tlv_patch_info *) pdata_buffer; ++ ++ /* To handle different event between rampatch and NVM */ ++ gTlv_type = ptlv_header->tlv_type; ++ gtlv_dwndcfg = ptlv_header->tlv.patch.dwnd_cfg; ++ ++ if (ptlv_header->tlv_type == TLV_TYPE_PATCH) { ++ PR_INFO("====================================================\n"); ++ PR_INFO("TLV Type : 0x%x\n", ptlv_header->tlv_type); ++ PR_INFO("Length : %d bytes\n", (ptlv_header->tlv_length1) | ++ (ptlv_header->tlv_length2 << 8) | ++ (ptlv_header->tlv_length3 << 16)); ++ PR_INFO("Total Length : %d bytes\n", ptlv_header->tlv.patch.tlv_data_len); ++ PR_INFO("Patch Data Length : %d bytes\n",ptlv_header->tlv.patch.tlv_patch_data_len); ++ PR_INFO("Signing Format Version : 0x%x\n", ptlv_header->tlv.patch.sign_ver); ++ PR_INFO("Signature Algorithm : 0x%x\n", ptlv_header->tlv.patch.sign_algorithm); ++ PR_INFO("Event Handling : 0x%x\n", ptlv_header->tlv.patch.dwnd_cfg); ++ PR_INFO("Reserved : 0x%x\n", ptlv_header->tlv.patch.reserved1); ++ PR_INFO("Product ID : 0x%04x\n", ptlv_header->tlv.patch.prod_id); ++ PR_INFO("Rom Build Version : 0x%04x\n", ptlv_header->tlv.patch.build_ver); ++ PR_INFO("Patch Version : 0x%04x\n", ptlv_header->tlv.patch.patch_ver); ++ PR_INFO("Reserved : 0x%x\n", ptlv_header->tlv.patch.reserved2); ++ PR_INFO("Patch Entry Address : 0x%x\n", (ptlv_header->tlv.patch.patch_entry_addr)); ++ PR_INFO("====================================================\n"); ++ ++ } else if (ptlv_header->tlv_type == TLV_TYPE_NVM) { ++ PR_INFO("====================================================\n"); ++ PR_INFO("TLV Type : 0x%x\n", ptlv_header->tlv_type); ++ PR_INFO("Length : %d bytes\n", nvm_length = ++ (ptlv_header->tlv_length1) | ++ (ptlv_header->tlv_length2 << 8) | ++ (ptlv_header->tlv_length3 << 16)); ++ ++ if (nvm_length <= 0) ++ return readSize; ++ ++ for(nvm_byte_ptr=(unsigned char *)(nvm_ptr = &(ptlv_header->tlv.nvm)), nvm_index=0; ++ nvm_index < nvm_length ; nvm_ptr = (tlv_nvm_hdr *) nvm_byte_ptr) { ++ PR_DBG("TAG ID\t\t\t : %d\n", nvm_ptr->tag_id); ++ PR_DBG("TAG Length\t\t\t : %d\n", nvm_tag_len = nvm_ptr->tag_len); ++ PR_DBG("TAG Pointer\t\t\t : %d\n", nvm_ptr->tag_ptr); ++ PR_DBG("TAG Extended Flag\t\t : %d\n", nvm_ptr->tag_ex_flag); ++ ++ /* Increase nvm_index to NVM data */ ++ nvm_index+=sizeof(tlv_nvm_hdr); ++ nvm_byte_ptr+=sizeof(tlv_nvm_hdr); ++ ++#ifndef MODULE_HAS_MAC_ADDR ++ /* Write BD Address */ ++ if (nvm_ptr->tag_id == TAG_NUM_2 && read_bd_address(bdaddr) == 0) { ++ memcpy(nvm_byte_ptr, bdaddr, 6); ++ PR_INFO("Overriding default BD ADDR with user" ++ " programmed BD Address: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2), ++ *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5)); ++ } ++#else ++ /* Remove it from NVM data */ ++ if (nvm_ptr->tag_id == TAG_NUM_2) { ++ int nvm_size = nvm_ptr->tag_len + sizeof(tlv_nvm_hdr); ++ PR_INFO("Skip BD Address from NVM\n"); ++ nvm_index += nvm_ptr->tag_len; ++ nvm_byte_ptr += nvm_ptr->tag_len; ++ memmove(nvm_ptr, nvm_byte_ptr, nvm_length - nvm_index); ++ nvm_length -= nvm_size; ++ nvm_byte_ptr -= nvm_size; ++ readSize -= nvm_size; ++ nvm_index -= nvm_size; ++ continue; ++ } ++#endif ++ ++ if (nvm_ptr->tag_id == TAG_NUM_17) { ++ PR_DBG("Forcing IBS to be disabled\n"); ++ nvm_byte_ptr[FWCONF_IBS_VAL_OFFSET] &= ++ (~(FWCONF_IBS_ENABLE << FWCONF_IBS_VAL_BIT)); ++ if (baud_rate != nvm_byte_ptr[FWCONF_BAUD_VAL_OFFSET]) { ++ PR_INFO("Change Vendor Baud from 0x%02x to 0x%02x\n", ++ nvm_byte_ptr[FWCONF_BAUD_VAL_OFFSET], baud_rate); ++ nvm_byte_ptr[FWCONF_BAUD_VAL_OFFSET] = baud_rate; ++ } ++ } ++ ++ if (nvm_ptr->tag_id == TAG_NUM_27) { ++ if ((deep_sleep_value = ++ get_value_from_config(FW_CONFIG_FILE_PATH, "DEEP_SLEEP")) >= 0) { ++ if (deep_sleep_value == FWCONF_DEEP_SLEEP_DISABLE) { ++ nvm_byte_ptr[FWCONF_DEEP_SLEEP_BYTE_OFFSET] &= ++ (~(1 << FWCONF_DEEP_SLEEP_BIT_OFFSET)); ++ } else if (deep_sleep_value == FWCONF_DEEP_SLEEP_ENABLE) { ++ nvm_byte_ptr[FWCONF_DEEP_SLEEP_BYTE_OFFSET] |= ++ (1 << FWCONF_DEEP_SLEEP_BIT_OFFSET); ++ } else { ++ fprintf(stderr, "Ignoring invalid deep sleep config value\n"); ++ } ++ } ++ } ++ ++ /* Read from file and check what PCM Configuration is required: ++ * Master = 0 /Slave = 1 */ ++ /* Override PCM configuration */ ++ if (nvm_ptr->tag_id == TAG_NUM_44) { ++ if ((pcm_value = ++ get_value_from_config(FW_CONFIG_FILE_PATH, "PCM")) >= 0) { ++ ++ if (pcm_value == FWCONF_PCM_SLAVE) { ++ nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_1] |= ++ (1 << FWCONF_PCM_ROLE_BIT_OFFSET); ++ nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_2] |= ++ (1 << FWCONF_PCM_ROLE_BIT_OFFSET); ++ } else if (pcm_value == FWCONF_PCM_MASTER) { ++ nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_1] &= ++ (~(1 << FWCONF_PCM_ROLE_BIT_OFFSET)); ++ nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_2] &= ++ (~(1 << FWCONF_PCM_ROLE_BIT_OFFSET)); ++ } ++ } ++ } ++ ++ for(i =0;(itag_len && (i*3 + 2) < PRINT_BUF_SIZE);i++) ++ snprintf((char *) data_buf, PRINT_BUF_SIZE, "%s%.02x ", ++ (char *)data_buf, *(nvm_byte_ptr + i)); ++ ++ PR_DBG("TAG Data\t\t\t : %s\n", data_buf); ++ ++ /* Clear buffer */ ++ memset(data_buf, 0x0, PRINT_BUF_SIZE); ++ ++ /* increased by tag_len */ ++ nvm_index+=nvm_ptr->tag_len; ++ nvm_byte_ptr +=nvm_ptr->tag_len; ++ } ++ ++ PR_INFO("====================================================\n"); ++ ++ } else { ++ fprintf(stderr, "TLV Header type is unknown (%d) \n", ptlv_header->tlv_type); ++ } ++ ++ return readSize; ++} ++ ++int rome_tlv_dnld_segment(int fd, int index, int seg_size, unsigned char wait_cc_evt) ++{ ++ int size=0, err = -1; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++ /* Frame the HCI CMD PKT to be sent to Controller*/ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_TLV_REQ_CMD, 0, index, seg_size); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]); ++ ++ /* Initialize the RSP packet everytime to 0 */ ++ memset(rsp, 0x0, HCI_MAX_EVENT_SIZE); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to send the patch payload to the Controller! 0x%x\n", err); ++ return err; ++ } ++ ++ if (wait_cc_evt) { ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n", __FUNCTION__, index); ++ return err; ++ } ++ } ++ ++ return err; ++} ++ ++int rome_tlv_dnld_req(int fd, int tlv_size) ++{ ++ int total_segment, remain_size, i, err = -1; ++ unsigned char wait_cc_evt = FALSE; ++ unsigned int rom = rome_ver >> 16; ++ ++ total_segment = tlv_size/MAX_SIZE_PER_TLV_SEGMENT; ++ remain_size = (tlv_size < MAX_SIZE_PER_TLV_SEGMENT)?\ ++ tlv_size: (tlv_size%MAX_SIZE_PER_TLV_SEGMENT); ++ ++ if (gTlv_type == TLV_TYPE_PATCH) { ++ /* Prior to Rome version 3.2(including inital few rampatch release of ++ * Rome 3.2), the event handling mechanism is ROME_SKIP_EVT_NONE. After ++ * few release of rampatch for Rome 3.2, the mechamism is changed to ++ * ROME_SKIP_EVT_VSE_CC. Rest of the mechanism is not used for now ++ */ ++ switch (gtlv_dwndcfg) ++ { ++ case ROME_SKIP_EVT_NONE: ++ wait_vsc_evt = TRUE; ++ wait_cc_evt = TRUE; ++ PR_DBG("%s: Event handling type: ROME_SKIP_EVT_NONE", __func__); ++ break; ++ case ROME_SKIP_EVT_VSE_CC: ++ wait_vsc_evt = FALSE; ++ wait_cc_evt = FALSE; ++ PR_DBG("%s: Event handling type: ROME_SKIP_EVT_VSE_CC", __func__); ++ break; ++ /* Not handled for now */ ++ case ROME_SKIP_EVT_VSE: ++ case ROME_SKIP_EVT_CC: ++ default: ++ fprintf(stderr, "%s: Unsupported Event handling: %d", __func__, gtlv_dwndcfg); ++ break; ++ } ++ } else { ++ wait_vsc_evt = TRUE; ++ wait_cc_evt = TRUE; ++ } ++ ++ for(i = 0; i < total_segment; i++) { ++ if ((i+1) == total_segment) { ++ if ((rom >= ROME_PATCH_VER_0100) && (rom < ROME_PATCH_VER_0302) && ++ (gTlv_type == TLV_TYPE_PATCH)) { ++ /* If the Rome version is from 1.1 to 3.1 ++ * 1. No CCE for the last command segment but all other segment ++ * 2. All the command segments get VSE including the last one ++ */ ++ wait_cc_evt = !remain_size ? FALSE: TRUE; ++ } else if ((rom == ROME_PATCH_VER_0302) && ++ (gTlv_type == TLV_TYPE_PATCH)) { ++ /* If the Rome version is 3.2 ++ * 1. None of the command segments receive CCE ++ * 2. No command segments receive VSE except the last one ++ * 3. If gtlv_dwndcfg is ROME_SKIP_EVT_NONE then the logic is ++ * same as Rome 2.1, 2.2, 3.0 ++ */ ++ if (gtlv_dwndcfg == ROME_SKIP_EVT_NONE) { ++ wait_cc_evt = !remain_size ? FALSE: TRUE; ++ } else if (gtlv_dwndcfg == ROME_SKIP_EVT_VSE_CC) { ++ wait_vsc_evt = !remain_size ? TRUE: FALSE; ++ } ++ } ++ } ++ ++ if ((err = rome_tlv_dnld_segment(fd, i, MAX_SIZE_PER_TLV_SEGMENT, wait_cc_evt )) < 0) ++ goto error; ++ } ++ ++ if ((rom >= ROME_PATCH_VER_0100) && (rom < ROME_PATCH_VER_0302) && ++ (gTlv_type == TLV_TYPE_PATCH)) { ++ /* If the Rome version is from 1.1 to 3.1 ++ * 1. No CCE for the last command segment but all other segment ++ * 2. All the command segments get VSE including the last one ++ */ ++ wait_cc_evt = remain_size ? FALSE: TRUE; ++ } else if ((rom == ROME_PATCH_VER_0302) && (gTlv_type == TLV_TYPE_PATCH)) { ++ /* If the Rome version is 3.2 ++ * 1. None of the command segments receive CCE ++ * 2. No command segments receive VSE except the last one ++ * 3. If gtlv_dwndcfg is ROME_SKIP_EVT_NONE then the logic is ++ * same as Rome 2.1, 2.2, 3.0 ++ */ ++ if (gtlv_dwndcfg == ROME_SKIP_EVT_NONE) { ++ wait_cc_evt = remain_size ? FALSE: TRUE; ++ } else if (gtlv_dwndcfg == ROME_SKIP_EVT_VSE_CC) { ++ wait_vsc_evt = remain_size ? TRUE: FALSE; ++ } ++ } ++ ++ if (remain_size) err =rome_tlv_dnld_segment(fd, i, remain_size, wait_cc_evt); ++ ++error: ++ return err; ++} ++ ++int rome_download_tlv_file(int fd, unsigned char baud_rate) ++{ ++ int tlv_size, err = -1; ++ ++ /* Rampatch TLV file Downloading */ ++ pdata_buffer = NULL; ++ ++ if ((tlv_size = rome_get_tlv_file(rampatch_file_path, baud_rate)) < 0) ++ goto error; ++ ++ if ((err = rome_tlv_dnld_req(fd, tlv_size)) < 0) ++ goto error; ++ ++ if (pdata_buffer != NULL) { ++ free (pdata_buffer); ++ pdata_buffer = NULL; ++ } ++ ++ /* NVM TLV file Downloading */ ++ if ((tlv_size = rome_get_tlv_file(nvm_file_path, baud_rate)) < 0) ++ goto error; ++ ++ if ((err = rome_tlv_dnld_req(fd, tlv_size)) < 0) ++ goto error; ++ ++error: ++ if (pdata_buffer != NULL) ++ free (pdata_buffer); ++ ++ return err; ++} ++ ++int rome_1_0_nvm_tag_dnld(int fd) ++{ ++ int i, size, err = 0; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++#if (NVM_VERSION >= ROME_1_0_100019) ++ unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] = ++ { ++ /* Tag 2 */ /* BD Address */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 9, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 2, ++ /* Tag Len */ 6, ++ /* Tag Value */ 0x77,0x78,0x23,0x01,0x56,0x22 ++ }, ++ /* Tag 6 */ /* Bluetooth Support Features */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 11, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 6, ++ /* Tag Len */ 8, ++ /* Tag Value */ 0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B ++ }, ++ /* Tag 17 */ /* HCI Transport Layer Setting */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 11, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 17, ++ /* Tag Len */ 8, ++ /* Tag Value */ 0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00 ++ }, ++ /* Tag 35 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 58, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 35, ++ /* Tag Len */ 55, ++ /* Tag Value */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x58, 0x59, ++ 0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F, ++ 0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F, ++ 0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80, ++ 0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80, ++ 0x1B, 0x14, 0x01, 0x04, 0x48 ++ }, ++ /* Tag 36 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 15, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 36, ++ /* Tag Len */ 12, ++ /* Tag Value */ 0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00 ++ }, ++ /* Tag 39 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 7, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 39, ++ /* Tag Len */ 4, ++ /* Tag Value */ 0x12,0x00,0x00,0x00 ++ }, ++ /* Tag 41 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 91, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 41, ++ /* Tag Len */ 88, ++ /* Tag Value */ 0x15, 0x00, 0x00, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x76, 0x00, ++ 0x1E, 0x00, 0x29, 0x02, 0x1F, 0x00, 0x61, 0x00, 0x1A, 0x00, ++ 0x76, 0x00, 0x1E, 0x00, 0x7D, 0x00, 0x40, 0x00, 0x91, 0x00, ++ 0x06, 0x00, 0x92, 0x00, 0x03, 0x00, 0xA6, 0x01, 0x50, 0x00, ++ 0xAA, 0x01, 0x15, 0x00, 0xAB, 0x01, 0x0A, 0x00, 0xAC, 0x01, ++ 0x00, 0x00, 0xB0, 0x01, 0xC5, 0x00, 0xB3, 0x01, 0x03, 0x00, ++ 0xB4, 0x01, 0x13, 0x00, 0xB5, 0x01, 0x0C, 0x00, 0xC5, 0x01, ++ 0x0D, 0x00, 0xC6, 0x01, 0x10, 0x00, 0xCA, 0x01, 0x2B, 0x00, ++ 0xCB, 0x01, 0x5F, 0x00, 0xCC, 0x01, 0x48, 0x00 ++ }, ++ /* Tag 42 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 63, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 42, ++ /* Tag Len */ 60, ++ /* Tag Value */ 0xD7, 0xC0, 0x00, 0x00, 0x8F, 0x5C, 0x02, 0x00, 0x80, 0x47, ++ 0x60, 0x0C, 0x70, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x01, ++ 0x42, 0x01, 0x69, 0x01, 0x95, 0x01, 0xC7, 0x01, 0xFE, 0x01, ++ 0x3D, 0x02, 0x83, 0x02, 0xD1, 0x02, 0x29, 0x03, 0x00, 0x0A, ++ 0x10, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x7F, 0x00, 0xFD, 0x00, ++ 0xF9, 0x01, 0xF1, 0x03, 0xDE, 0x07, 0x00, 0x00, 0x9A, 0x01 ++ }, ++ /* Tag 84 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 153, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 84, ++ /* Tag Len */ 150, ++ /* Tag Value */ 0x7C, 0x6A, 0x59, 0x47, 0x19, 0x36, 0x35, 0x25, 0x25, 0x28, ++ 0x2C, 0x2B, 0x2B, 0x28, 0x2C, 0x28, 0x29, 0x28, 0x29, 0x28, ++ 0x29, 0x29, 0x2C, 0x29, 0x2C, 0x29, 0x2C, 0x28, 0x29, 0x28, ++ 0x29, 0x28, 0x29, 0x2A, 0x00, 0x00, 0x2C, 0x2A, 0x2C, 0x18, ++ 0x98, 0x98, 0x98, 0x98, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, ++ 0x1E, 0x13, 0x1E, 0x1E, 0x1E, 0x1E, 0x13, 0x13, 0x11, 0x13, ++ 0x1E, 0x1E, 0x13, 0x12, 0x12, 0x12, 0x11, 0x12, 0x1F, 0x12, ++ 0x12, 0x12, 0x10, 0x0C, 0x18, 0x0D, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x0D, 0x0D, ++ 0x0E, 0x0D, 0x01, 0x01, 0x0D, 0x0D, 0x0D, 0x0D, 0x0F, 0x0D, ++ 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x05, 0x10, 0x03, 0x00, ++ 0x7E, 0x7B, 0x7B, 0x72, 0x71, 0x50, 0x50, 0x50, 0x00, 0x40, ++ 0x60, 0x60, 0x30, 0x08, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x08, 0x16, 0x16, 0x08, 0x08, 0x00, ++ 0x00, 0x00, 0x1E, 0x34, 0x2B, 0x1B, 0x23, 0x2B, 0x15, 0x0D ++ }, ++ /* Tag 85 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 119, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 85, ++ /* Tag Len */ 116, ++ /* Tag Value */ 0x03, 0x00, 0x38, 0x00, 0x45, 0x77, 0x00, 0xE8, 0x00, 0x59, ++ 0x01, 0xCA, 0x01, 0x3B, 0x02, 0xAC, 0x02, 0x1D, 0x03, 0x8E, ++ 0x03, 0x00, 0x89, 0x01, 0x0E, 0x02, 0x5C, 0x02, 0xD7, 0x02, ++ 0xF8, 0x08, 0x01, 0x00, 0x1F, 0x00, 0x0A, 0x02, 0x55, 0x02, ++ 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0x00, 0x00, ++ 0x00, 0x1E, 0xDE, 0x00, 0x00, 0x00, 0x14, 0x0F, 0x0A, 0x0F, ++ 0x0A, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x04, 0x0C, 0x0C, ++ 0x0C, 0x0C, 0x06, 0x06, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, ++ 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, ++ 0x06, 0x0F, 0x14, 0x05, 0x47, 0xCF, 0x77, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0xAC, 0x7C, 0xFF, 0x40, 0x00, 0x00, 0x00, ++ 0x12, 0x04, 0x04, 0x01, 0x04, 0x03 ++ }, ++ {TAG_END} ++ }; ++#elif (NVM_VERSION == ROME_1_0_6002) ++ unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] = ++ { ++ /* Tag 2 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 9, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 2, ++ /* Tag Len */ 6, ++ /* Tag Value */ 0x77,0x78,0x23,0x01,0x56,0x22 /* BD Address */ ++ }, ++ /* Tag 6 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 11, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 6, ++ /* Tag Len */ 8, ++ /* Tag Value */ 0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B ++ }, ++ /* Tag 17 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 11, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 17, ++ /* Tag Len */ 8, ++ /* Tag Value */ 0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00 ++ }, ++ /* Tag 36 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 15, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 36, ++ /* Tag Len */ 12, ++ /* Tag Value */ 0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00 ++ }, ++ ++ /* Tag 39 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 7, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 39, ++ /* Tag Len */ 4, ++ /* Tag Value */ 0x12,0x00,0x00,0x00 ++ }, ++ ++ /* Tag 41 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 199, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 41, ++ /* Tag Len */ 196, ++ /* Tag Value */ 0x30,0x00,0x00,0x00,0xD5,0x00,0x0E,0x00,0xD6,0x00,0x0E,0x00, ++ 0xD7,0x00,0x16,0x00,0xD8,0x00,0x16,0x00,0xD9,0x00,0x16,0x00, ++ 0xDA,0x00,0x1E,0x00,0xDB,0x00,0x26,0x00,0xDC,0x00,0x5F,0x00, ++ 0xDD,0x00,0x2F,0x00,0xDE,0x00,0x5F,0x00,0xE0,0x00,0x0E,0x00, ++ 0xE1,0x00,0x0E,0x00,0xE2,0x00,0x16,0x00,0xE3,0x00,0x16,0x00, ++ 0xE4,0x00,0x16,0x00,0xE5,0x00,0x1E,0x00,0xE6,0x00,0x26,0x00, ++ 0xE7,0x00,0x5F,0x00,0xE8,0x00,0x2F,0x00,0xE9,0x00,0x5F,0x00, ++ 0xEC,0x00,0x0C,0x00,0xED,0x00,0x08,0x00,0xEE,0x00,0x14,0x00, ++ 0xEF,0x00,0x24,0x00,0xF0,0x00,0x40,0x00,0xF1,0x00,0x4C,0x00, ++ 0xF2,0x00,0x70,0x00,0xF3,0x00,0x80,0x00,0xF4,0x00,0x80,0x00, ++ 0xF5,0x00,0x80,0x00,0xF8,0x00,0x0C,0x00,0xF9,0x00,0x18,0x00, ++ 0xFA,0x00,0x14,0x00,0xFB,0x00,0x24,0x00,0xFC,0x00,0x40,0x00, ++ 0xFD,0x00,0x4C,0x00,0xFE,0x00,0x70,0x00,0xFF,0x00,0x80,0x00, ++ 0x00,0x01,0x80,0x00,0x01,0x01,0x80,0x00,0x04,0x01,0x1B,0x00, ++ 0x05,0x01,0x14,0x00,0x06,0x01,0x01,0x00,0x07,0x01,0x04,0x00, ++ 0x08,0x01,0x00,0x00,0x09,0x01,0x00,0x00,0x0A,0x01,0x03,0x00, ++ 0x0B,0x01,0x03,0x00 ++ }, ++ ++ /* Tag 44 */ ++ { /* Packet Type */HCI_COMMAND_PKT, ++ /* Opcode */ 0x0b,0xfc, ++ /* Total Len */ 44, ++ /* NVM CMD */ NVM_ACCESS_SET, ++ /* Tag Num */ 44, ++ /* Tag Len */ 41, ++ /* Tag Value */ 0x6F,0x0A,0x00,0x00,0x00,0x00,0x00,0x50,0xFF,0x10,0x02,0x02, ++ 0x01,0x00,0x14,0x01,0x06,0x28,0xA0,0x62,0x03,0x64,0x01,0x01, ++ 0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xFF,0x10,0x02,0x01, ++ 0x00,0x14,0x01,0x02,0x03 ++ }, ++ {TAG_END} ++ }; ++#endif ++ ++ for (i=0; (i < MAX_TAG_CMD) && (cmds[i][0] != TAG_END); i++) { ++ /* Write BD Address */ ++ if (cmds[i][TAG_NUM_OFFSET] == TAG_NUM_2){ ++ memcpy(&cmds[i][TAG_BDADDR_OFFSET], vnd_local_bd_addr, 6); ++ fprintf(stderr, "BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", ++ cmds[i][TAG_BDADDR_OFFSET ], cmds[i][TAG_BDADDR_OFFSET + 1], ++ cmds[i][TAG_BDADDR_OFFSET + 2], cmds[i][TAG_BDADDR_OFFSET + 3], ++ cmds[i][TAG_BDADDR_OFFSET + 4], cmds[i][TAG_BDADDR_OFFSET + 5]); ++ } ++ size = cmds[i][3] + HCI_COMMAND_HDR_SIZE + 1; ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)&cmds[i][0], rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to attach the patch payload to the Controller!\n"); ++ goto error; ++ } ++ ++ /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to get patch version(s)\n", __FUNCTION__); ++ goto error; ++ } ++ } ++ ++error: ++ return err; ++} ++ ++ ++ ++int rome_patch_ver_req(int fd) ++{ ++ int size, err = 0; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ ++ /* Frame the HCI CMD to be sent to the Controller */ ++ frame_hci_cmd_pkt(cmd, EDL_PATCH_VER_REQ_CMD, 0, ++ -1, EDL_PATCH_CMD_LEN); ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN); ++ ++ /* Send HCI Command packet to Controller */ ++ err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size); ++ if (err != size) { ++ fprintf(stderr, "Failed to attach the patch payload to the Controller!\n"); ++ goto error; ++ } ++ ++ /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to get patch version(s)\n", __FUNCTION__); ++ goto error; ++ } ++error: ++ return err; ++ ++} ++ ++static void flow_control(int fd, int opt) ++{ ++ struct termios c_opt; ++ ++ ioctl(fd, TIOCMGET, &c_opt); ++ c_opt.c_cc[VTIME] = 0; /* inter-character timer unused */ ++ c_opt.c_cc[VMIN] = 0; /* blocking read until 8 chars received */ ++ c_opt.c_cflag &= ~CSIZE; ++ c_opt.c_cflag |= (CS8 | CLOCAL | CREAD); ++ if (opt == MSM_ENABLE_FLOW_CTRL) ++ c_opt.c_cflag |= CRTSCTS; ++ else if (opt == MSM_DISABLE_FLOW_CTRL) ++ c_opt.c_cflag &= ~CRTSCTS; ++ else { ++ fprintf(stderr, "%s: Incorrect option passed for TIOCMSET\n", __func__); ++ return; ++ } ++ c_opt.c_iflag = IGNPAR; ++ c_opt.c_oflag = 0; ++ c_opt.c_lflag = 0; ++ ioctl(fd, TIOCMSET, &c_opt); ++} ++ ++ ++int rome_set_baudrate_req(int fd, unsigned char baud_rate) ++{ ++ int size, err = 0; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ hci_command_hdr *cmd_hdr; ++ int flags; ++ ++ memset(cmd, 0x0, HCI_MAX_CMD_SIZE); ++ ++ cmd_hdr = (void *) (cmd + 1); ++ cmd[0] = HCI_COMMAND_PKT; ++ cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_SET_BAUDRATE_CMD_OCF); ++ cmd_hdr->plen = VSC_SET_BAUDRATE_REQ_LEN; ++ cmd[4] = baud_rate; ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN); ++ ++ /* Flow off during baudrate change */ ++ flow_control(fd, MSM_DISABLE_FLOW_CTRL); ++ ++ /* Send the HCI command packet to UART for transmission */ ++ err = write(fd, cmd, size); ++ if (err != size) { ++ fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err); ++ goto error; ++ } ++ /* Change Local UART baudrate to high speed UART */ ++ userial_vendor_set_baud(baud_rate); ++ ++ /* Flow on after changing local uart baudrate */ ++ flow_control(fd, MSM_ENABLE_FLOW_CTRL); ++ ++ /* Check for response from the Controller */ ++ if ((err = read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) { ++ fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__); ++ goto error; ++ } ++ ++ /* Wait for command complete event */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__); ++ goto error; ++ } ++error: ++ return err; ++ ++} ++ ++ ++int rome_hci_reset_req(int fd, char baud) ++{ ++ int size, err = 0; ++ unsigned char cmd[HCI_MAX_CMD_SIZE]; ++ unsigned char rsp[HCI_MAX_EVENT_SIZE]; ++ hci_command_hdr *cmd_hdr; ++ int flags; ++ ++ memset(cmd, 0x0, HCI_MAX_CMD_SIZE); ++ ++ cmd_hdr = (void *) (cmd + 1); ++ cmd[0] = HCI_COMMAND_PKT; ++ cmd_hdr->opcode = HCI_RESET; ++ cmd_hdr->plen = 0; ++ ++ /* Total length of the packet to be sent to the Controller */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE); ++ ++ /* Flow off during baudrate change */ ++ flow_control(fd, MSM_DISABLE_FLOW_CTRL); ++ ++ /* Send the HCI command packet to UART for transmission */ ++ err = write(fd, cmd, size); ++ if (err != size) { ++ fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err); ++ goto error; ++ } ++ ++ /* Change Local UART baudrate to high speed UART */ ++ userial_vendor_set_baud(baud); ++ ++ /* Flow on after changing local uart baudrate */ ++ flow_control(fd, MSM_ENABLE_FLOW_CTRL); ++ ++ /* Wait for command complete event */ ++ err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE); ++ if (err < 0) { ++ fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__); ++ goto error; ++ } ++ ++error: ++ return err; ++ ++} ++ ++int qca_soc_init(int fd, int speed, char *bdaddr) ++{ ++ int err = -1; ++ int ret = 0; ++ int size; ++ unsigned char baud_rate = 0; ++ ++ vnd_userial.fd = fd; ++ ++ /* Get Rome version information */ ++ if ((err = rome_patch_ver_req(fd)) < 0) { ++ fprintf(stderr, "%s: Fail to get Rome Version (0x%x)\n", __FUNCTION__, err); ++ ret = -1; ++ goto error; ++ } ++ ++ fprintf(stderr, "%s: Rome Version (0x%08x)\n", __FUNCTION__, rome_ver); ++ ++ switch (rome_ver){ ++ case ROME_VER_1_0: ++ /* Set and Download the RAMPATCH */ ++ fprintf(stderr, "%s: Setting Patch Header & Downloading Patches\n", __FUNCTION__); ++ err = rome_download_rampatch(fd); ++ if (err < 0) { ++ fprintf(stderr, "%s: DOWNLOAD RAMPATCH failed!\n", __FUNCTION__); ++ ret = -1; ++ goto error; ++ } ++ ++ /* Attach the RAMPATCH */ ++ fprintf(stderr, "%s: Attaching the patches\n", __FUNCTION__); ++ err = rome_attach_rampatch(fd); ++ if (err < 0) { ++ fprintf(stderr, "%s: ATTACH RAMPATCH failed!\n", __FUNCTION__); ++ ret = -1; ++ goto error; ++ } ++ ++ /* Send Reset */ ++ size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN); ++ err = rome_rampatch_reset(fd); ++ if (err < 0) { ++ fprintf(stderr, "Failed to RESET after RAMPATCH upgrade!\n"); ++ ret = -1; ++ goto error; ++ } ++ ++ /* NVM download */ ++ fprintf(stderr, "%s: Downloading NVM\n", __FUNCTION__); ++ err = rome_1_0_nvm_tag_dnld(fd); ++ if (err < 0) { ++ fprintf(stderr, "Downloading NVM Failed !!\n"); ++ ret = -1; ++ goto error; ++ } ++ ++ /* Change baud rate 115.2 kbps to 3Mbps*/ ++ err = rome_hci_reset_req(fd, baud_rate); ++ if (err < 0) { ++ fprintf(stderr, "HCI Reset Failed !!\n"); ++ ret = -1; ++ goto error; ++ } ++ break; ++ case ROME_VER_1_1: ++ rampatch_file_path = ROME_RAMPATCH_TLV_PATH; ++ nvm_file_path = ROME_NVM_TLV_PATH; ++ goto download; ++ case ROME_VER_1_3: ++ rampatch_file_path = ROME_RAMPATCH_TLV_1_0_3_PATH; ++ nvm_file_path = ROME_NVM_TLV_1_0_3_PATH; ++ goto download; ++ case ROME_VER_2_1: ++ rampatch_file_path = ROME_RAMPATCH_TLV_2_0_1_PATH; ++ nvm_file_path = ROME_NVM_TLV_2_0_1_PATH; ++ goto download; ++ case ROME_VER_3_0: ++ rampatch_file_path = ROME_RAMPATCH_TLV_3_0_0_PATH; ++ nvm_file_path = ROME_NVM_TLV_3_0_0_PATH; ++ goto download; ++ case ROME_VER_3_2: ++ rampatch_file_path = ROME_RAMPATCH_TLV_3_0_2_PATH; ++ nvm_file_path = ROME_NVM_TLV_3_0_2_PATH; ++ goto download; ++ case TUFELLO_VER_1_0: ++ rampatch_file_path = TF_RAMPATCH_TLV_1_0_0_PATH; ++ nvm_file_path = TF_NVM_TLV_1_0_0_PATH; ++ goto download; ++ case TUFELLO_VER_1_1: ++ rampatch_file_path = TF_RAMPATCH_TLV_1_0_1_PATH; ++ nvm_file_path = TF_NVM_TLV_1_0_1_PATH; ++download: ++ isSpeedValid(speed, &baud_rate); ++ if (baud_rate < 0) { ++ ret = -1; ++ goto error; ++ } ++ ++ /* Donwload TLV files (rampatch, NVM) */ ++ err = rome_download_tlv_file(fd, baud_rate); ++ if (err < 0) { ++ fprintf(stderr, "%s: Download TLV file failed!\n", __FUNCTION__); ++ ret = -1; ++ goto error; ++ } ++ ++ /* ++ * Overriding the baud rate value in NVM file with the user ++ * requested baud rate, since default baud rate in NVM file is 3M. ++ */ ++ err = rome_set_baudrate_req(fd, baud_rate); ++ if (err < 0) { ++ fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__); ++ ret = -1; ++ goto error; ++ } ++ ++ /* Perform HCI reset here*/ ++ err = rome_hci_reset_req(fd, baud_rate); ++ if (err < 0) { ++ fprintf(stderr, "HCI Reset Failed !!!\n"); ++ ret = -1; ++ goto error; ++ } ++ ++ break; ++ case ROME_VER_UNKNOWN: ++ default: ++ fprintf(stderr, "%s: Detected unknown ROME version\n", __FUNCTION__); ++ ret = -1; ++ break; ++ } ++ ++error: ++ return ret; ++} +diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h +new file mode 100644 +index 000000000..597743e0b +--- /dev/null ++++ b/tools/hciattach_rome.h +@@ -0,0 +1,388 @@ ++/* ++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * Not a Contribution. ++ * Copyright 2012 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++#ifndef HW_ROME_H ++#define HW_ROME_H ++ ++/****************************************************************************** ++** Constants & Macros ++******************************************************************************/ ++#define HCI_MAX_CMD_SIZE 260 ++#define HCI_MAX_EVENT_SIZE 260 ++#define PRINT_BUF_SIZE ((HCI_MAX_CMD_SIZE * 3) + 2) ++/* HCI Command/Event Opcode */ ++#define HCI_RESET 0x0C03 ++#define EVT_CMD_COMPLETE 0x0E ++/* HCI Packet types */ ++#define HCI_COMMAND_PKT 0x01 ++#define HCI_ACLDATA_PKT 0x02 ++#define HCI_SCODATA_PKT 0x03 ++#define HCI_EVENT_PKT 0x04 ++#define HCI_VENDOR_PKT 0xff ++#define cmd_opcode_pack(ogf, ocf) (unsigned short)((ocf & 0x03ff)|(ogf << 10)) ++ ++#define NVITEM 0 ++#define RDWR_PROT 1 ++#define NVITEM_SIZE 2 ++#define PERSIST_HEADER_LEN 3 ++#define BD_ADDR_LEN 6 ++#define MSM_DISABLE_FLOW_CTRL 0 ++#define MSM_ENABLE_FLOW_CTRL 1 ++ ++#ifdef _PLATFORM_MDM_ ++#define USERIAL_OP_CLK_ON 0x5441 ++#define USERIAL_OP_CLK_OFF 0x5442 ++#endif ++ ++#define PR_INFO(fmt, arg...) printf(fmt, ## arg) ++#ifdef DEBUG ++ #define PR_DBG(fmt, arg...) printf(fmt, ## arg) ++#else ++ #define PR_DBG(fmt, arg...) ++#endif ++ ++unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++typedef enum { ++ USERIAL_OP_FLOW_ON, ++ USERIAL_OP_FLOW_OFF, ++ USERIAL_OP_NOP, ++} userial_vendor_ioctl_op_t; ++ ++ ++/* vendor serial control block */ ++typedef struct ++{ ++ int fd; /* fd to Bluetooth device */ ++ struct termios termios; /* serial terminal of BT port */ ++ char port_name[256]; ++} vnd_userial_cb_t; ++ ++/**** baud rates ****/ ++#define USERIAL_BAUD_300 0 ++#define USERIAL_BAUD_600 1 ++#define USERIAL_BAUD_1200 2 ++#define USERIAL_BAUD_2400 3 ++#define USERIAL_BAUD_9600 4 ++#define USERIAL_BAUD_19200 5 ++#define USERIAL_BAUD_57600 6 ++#define USERIAL_BAUD_115200 7 ++#define USERIAL_BAUD_230400 8 ++#define USERIAL_BAUD_460800 9 ++#define USERIAL_BAUD_921600 10 ++#define USERIAL_BAUD_1M 11 ++#define USERIAL_BAUD_1_5M 12 ++#define USERIAL_BAUD_2M 13 ++#define USERIAL_BAUD_3M 14 ++#define USERIAL_BAUD_4M 15 ++#define USERIAL_BAUD_AUTO 16 ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE (!FALSE) ++#endif ++ ++#define HCI_CHG_BAUD_CMD_OCF 0x0C ++#define HCI_VENDOR_CMD_OGF 0x3F ++#define WRITE_BDADDR_CMD_LEN 14 ++#define WRITE_BAUD_CMD_LEN 6 ++#define MAX_CMD_LEN WRITE_BDADDR_CMD_LEN ++#define GET_VERSION_OCF 0x1E ++ ++#define PS_HDR_LEN 4 ++#define HCI_VENDOR_CMD_OGF 0x3F ++#define HCI_PS_CMD_OCF 0x0B ++ ++#define HCI_COMMAND_HDR_SIZE 3 ++#define EVT_CMD_COMPLETE_SIZE 3 ++#define EVT_CMD_STATUS 0x0F ++#define EVT_CMD_STATUS_SIZE 4 ++#define HCI_EVENT_HDR_SIZE 2 ++#define HCI_EV_SUCCESS 0x00 ++/* HCI Socket options */ ++#define HCI_DATA_DIR 1 ++#define HCI_FILTER 2 ++#define HCI_TIME_STAMP 3 ++ ++#define P_ID_OFFSET (0) ++#define HCI_CMD_IND (1) ++#define EVENTCODE_OFFSET (1) ++#define EVT_PLEN (2) ++#define PLEN (3) ++#define CMD_RSP_OFFSET (3) ++#define RSP_TYPE_OFFSET (4) ++#define BAUDRATE_RSP_STATUS_OFFSET (4) ++#define CMD_STATUS_OFFSET (5) ++#define P_ROME_VER_OFFSET (4) ++#define P_BUILD_VER_OFFSET (6) ++#define P_BASE_ADDR_OFFSET (8) ++#define P_ENTRY_ADDR_OFFSET (12) ++#define P_LEN_OFFSET (16) ++#define P_CRC_OFFSET (20) ++#define P_CONTROL_OFFSET (24) ++#define PATCH_HDR_LEN (28) ++#define MAX_DATA_PER_SEGMENT (239) ++#define VSEVENT_CODE (0xFF) ++#define HC_VS_MAX_CMD_EVENT (0xFF) ++#define PATCH_PROD_ID_OFFSET (5) ++#define PATCH_PATCH_VER_OFFSET (9) ++#define PATCH_ROM_BUILD_VER_OFFSET (11) ++#define PATCH_SOC_VER_OFFSET (13) ++#define MAX_SIZE_PER_TLV_SEGMENT (243) ++ ++/* VS Opcode */ ++#define HCI_PATCH_CMD_OCF (0) ++#define EDL_SET_BAUDRATE_CMD_OCF (0x48) ++ ++/* VS Commands */ ++#define VSC_SET_BAUDRATE_REQ_LEN (1) ++#define EDL_PATCH_CMD_LEN (1) ++#define EDL_PATCH_CMD_REQ_LEN (1) ++#define EDL_PATCH_DLD_REQ_CMD (0x01) ++#define EDL_PATCH_RST_REQ_CMD (0x05) ++#define EDL_PATCH_SET_REQ_CMD (0x16) ++#define EDL_PATCH_ATCH_REQ_CMD (0x17) ++#define EDL_PATCH_VER_REQ_CMD (0x19) ++#define EDL_PATCH_TLV_REQ_CMD (0x1E) ++#define VSC_DISABLE_IBS_LEN (0x04) ++ ++/* VS Event */ ++#define EDL_CMD_REQ_RES_EVT (0x00) ++#define EDL_CMD_EXE_STATUS_EVT (0x00) ++#define EDL_SET_BAUDRATE_RSP_EVT (0x92) ++#define EDL_PATCH_VER_RES_EVT (0x19) ++#define EDL_TVL_DNLD_RES_EVT (0x04) ++#define EDL_APP_VER_RES_EVT (0x02) ++ ++/* Status Codes of HCI CMD execution*/ ++#define HCI_CMD_SUCCESS (0x0) ++#define PATCH_LEN_ERROR (0x1) ++#define PATCH_VER_ERROR (0x2) ++#define PATCH_CRC_ERROR (0x3) ++#define PATCH_NOT_FOUND (0x4) ++#define TLV_TYPE_ERROR (0x10) ++#define NVM_ACCESS_CODE (0x0B) ++#define BAUDRATE_CHANGE_SUCCESS (1) ++ ++/* TLV_TYPE */ ++#define TLV_TYPE_PATCH (1) ++#define TLV_TYPE_NVM (2) ++ ++/* NVM */ ++#define MAX_TAG_CMD 30 ++#define TAG_END 0xFF ++#define NVM_ACCESS_SET 0x01 ++#define TAG_NUM_OFFSET 5 ++#define TAG_NUM_2 2 ++#define TAG_NUM_17 (17) ++#define TAG_NUM_27 27 ++#define TAG_NUM_44 44 ++#define TAG_BDADDR_OFFSET 7 ++ ++/* FW PCM Configuration */ ++#define FWCONF_PCM_MS_OFFSET_1 9 ++#define FWCONF_PCM_MS_OFFSET_2 33 ++#define FWCONF_PCM_SLAVE 1 ++#define FWCONF_PCM_MASTER 0 ++#define FWCONF_PCM_ROLE_BIT_OFFSET 4 ++ ++/* FW HCI Transport Layer Configuration */ ++#define FWCONF_IBS_DISABLE (0) ++#define FWCONF_IBS_ENABLE (1) ++#define FWCONF_IBS_VAL_BIT (7) ++#define FWCONF_IBS_VAL_OFFSET (0) ++#define FWCONF_BAUD_VAL_OFFSET (2) ++ ++/* FW DEEP SLEEP Configuration */ ++#define FWCONF_DEEP_SLEEP_DISABLE 0 ++#define FWCONF_DEEP_SLEEP_ENABLE 1 ++#define FWCONF_DEEP_SLEEP_BYTE_OFFSET 0 ++#define FWCONF_DEEP_SLEEP_BIT_OFFSET 0 ++ ++#define MAX_RETRY_CNT 1 ++#define SELECT_TIMEOUT 3 ++ ++/* NVM Tags specifically used for ROME 1.0 */ ++#define ROME_1_0_100022_1 0x101000221 ++#define ROME_1_0_100019 0x101000190 ++#define ROME_1_0_6002 0x100600200 ++ ++/* Default NVM Version setting for ROME 1.0 */ ++#define NVM_VERSION ROME_1_0_100022_1 ++ ++ ++#define LSH(val, n) ((unsigned int)(val) << (n)) ++#define EXTRACT_BYTE(val, pos) (char) (((val) >> (8 * (pos))) & 0xFF) ++#define CALC_SEG_SIZE(len, max) ((plen) % (max))?((plen/max)+1) : ((plen) / (max)) ++ ++#define ROME_FW_PATH "/lib/firmware/rampatch.img" ++#define ROME_RAMPATCH_TLV_PATH "/lib/firmware/rampatch_tlv.img" ++#define ROME_NVM_TLV_PATH "/lib/firmware/nvm_tlv.bin" ++#define ROME_RAMPATCH_TLV_1_0_3_PATH "/lib/firmware/rampatch_tlv_1.3.tlv" ++#define ROME_NVM_TLV_1_0_3_PATH "/lib/firmware/nvm_tlv_1.3.bin" ++#define ROME_RAMPATCH_TLV_2_0_1_PATH "/lib/firmware/rampatch_tlv_2.1.tlv" ++#define ROME_NVM_TLV_2_0_1_PATH "/lib/firmware/nvm_tlv_2.1.bin" ++#define ROME_RAMPATCH_TLV_3_0_0_PATH "/lib/firmware/rampatch_tlv_3.0.tlv" ++#define ROME_NVM_TLV_3_0_0_PATH "/lib/firmware/nvm_tlv_3.0.bin" ++#define ROME_RAMPATCH_TLV_3_0_2_PATH "/lib/firmware/btfw32.tlv" ++#define ROME_NVM_TLV_3_0_2_PATH "/lib/firmware/btnv32.bin" ++#ifdef _PLATFORM_MDM_ ++#define TF_RAMPATCH_TLV_1_0_0_PATH "/lib/firmware/rampatch_tlv_tf_1.0.tlv" ++#define TF_NVM_TLV_1_0_0_PATH "/lib/firmware/nvm_tlv_tf_1.0.bin" ++#define TF_RAMPATCH_TLV_1_0_1_PATH "/lib/firmware/tfbtfw11.tlv" ++#define TF_NVM_TLV_1_0_1_PATH "/lib/firmware/tfbtnv11.bin" ++#else ++#define TF_RAMPATCH_TLV_1_0_0_PATH "/lib/firmware/qca/rampatch_tlv_tf_1.0.tlv" ++#define TF_NVM_TLV_1_0_0_PATH "/lib/firmware/qca/nvm_tlv_tf_1.0.bin" ++#define TF_RAMPATCH_TLV_1_0_1_PATH "/lib/firmware/qca/tfbtfw11.tlv" ++#define TF_NVM_TLV_1_0_1_PATH "/lib/firmware/qca/tfbtnv11.bin" ++#endif ++ ++/* This header value in rampatch file decides event handling mechanism in the HOST */ ++#define ROME_SKIP_EVT_NONE 0x00 ++#define ROME_SKIP_EVT_VSE 0x01 ++#define ROME_SKIP_EVT_CC 0x02 ++#define ROME_SKIP_EVT_VSE_CC 0x03 ++ ++#define FW_CONFIG_FILE_PATH "/etc/bluetooth/firmware.conf" ++/****************************************************************************** ++** Local type definitions ++******************************************************************************/ ++ ++typedef struct { ++ unsigned char ncmd; ++ unsigned short opcode; ++} __attribute__ ((packed)) evt_cmd_complete; ++ ++typedef struct { ++ unsigned char status; ++ unsigned char ncmd; ++ unsigned short opcode; ++} __attribute__ ((packed)) evt_cmd_status; ++ ++typedef struct { ++ unsigned short opcode; ++ unsigned char plen; ++} __attribute__ ((packed)) hci_command_hdr; ++ ++typedef struct { ++ unsigned char evt; ++ unsigned char plen; ++} __attribute__ ((packed)) hci_event_hdr; ++typedef struct { ++ unsigned short rom_version; ++ unsigned short build_version; ++} __attribute__ ((packed)) patch_version; ++ ++typedef struct { ++ unsigned int patch_id; ++ patch_version patch_ver; ++ unsigned int patch_base_addr; ++ unsigned int patch_entry_addr; ++ unsigned short patch_length; ++ int patch_crc; ++ unsigned short patch_ctrl; ++} __attribute__ ((packed)) patch_info; ++ ++typedef struct { ++ unsigned int tlv_data_len; ++ unsigned int tlv_patch_data_len; ++ unsigned char sign_ver; ++ unsigned char sign_algorithm; ++ unsigned char dwnd_cfg; ++ unsigned char reserved1; ++ unsigned short prod_id; ++ unsigned short build_ver; ++ unsigned short patch_ver; ++ unsigned short reserved2; ++ unsigned int patch_entry_addr; ++} __attribute__ ((packed)) tlv_patch_hdr; ++ ++typedef struct { ++ unsigned short tag_id; ++ unsigned short tag_len; ++ unsigned int tag_ptr; ++ unsigned int tag_ex_flag; ++} __attribute__ ((packed)) tlv_nvm_hdr; ++ ++typedef struct { ++ unsigned char tlv_type; ++ unsigned char tlv_length1; ++ unsigned char tlv_length2; ++ unsigned char tlv_length3; ++ ++ union{ ++ tlv_patch_hdr patch; ++ tlv_nvm_hdr nvm; ++ }tlv; ++} __attribute__ ((packed)) tlv_patch_info; ++ ++enum{ ++ BAUDRATE_115200 = 0x00, ++ BAUDRATE_57600 = 0x01, ++ BAUDRATE_38400 = 0x02, ++ BAUDRATE_19200 = 0x03, ++ BAUDRATE_9600 = 0x04, ++ BAUDRATE_230400 = 0x05, ++ BAUDRATE_250000 = 0x06, ++ BAUDRATE_460800 = 0x07, ++ BAUDRATE_500000 = 0x08, ++ BAUDRATE_720000 = 0x09, ++ BAUDRATE_921600 = 0x0A, ++ BAUDRATE_1000000 = 0x0B, ++ BAUDRATE_1250000 = 0x0C, ++ BAUDRATE_2000000 = 0x0D, ++ BAUDRATE_3000000 = 0x0E, ++ BAUDRATE_4000000 = 0x0F, ++ BAUDRATE_1600000 = 0x10, ++ BAUDRATE_3200000 = 0x11, ++ BAUDRATE_3500000 = 0x12, ++ BAUDRATE_AUTO = 0xFE, ++ BAUDRATE_Reserved = 0xFF ++}; ++ ++enum{ ++ ROME_PATCH_VER_0100 = 0x0100, ++ ROME_PATCH_VER_0101 = 0x0101, ++ ROME_PATCH_VER_0200 = 0x0200, ++ ROME_PATCH_VER_0300 = 0x0300, ++ ROME_PATCH_VER_0302 = 0x0302 ++ }; ++ ++enum{ ++ ROME_SOC_ID_00 = 0x00000000, ++ ROME_SOC_ID_11 = 0x00000011, ++ ROME_SOC_ID_13 = 0x00000013, ++ ROME_SOC_ID_22 = 0x00000022, ++ ROME_SOC_ID_23 = 0x00000023, ++ ROME_SOC_ID_44 = 0x00000044 ++}; ++ ++enum{ ++ ROME_VER_UNKNOWN = 0, ++ ROME_VER_1_0 = ((ROME_PATCH_VER_0100 << 16 ) | ROME_SOC_ID_00 ), ++ ROME_VER_1_1 = ((ROME_PATCH_VER_0101 << 16 ) | ROME_SOC_ID_00 ), ++ ROME_VER_1_3 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_00 ), ++ ROME_VER_2_1 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_11 ), ++ ROME_VER_3_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_22 ), ++ ROME_VER_3_2 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_44 ), ++ TUFELLO_VER_1_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_13 ), ++ TUFELLO_VER_1_1 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_23 ) ++}; ++#endif /* HW_ROME_H */ diff --git a/packages/network/bluez/system.d/bluetooth-defaults.service b/packages/network/bluez/system.d/bluetooth-defaults.service new file mode 100644 index 000000000..7d751631e --- /dev/null +++ b/packages/network/bluez/system.d/bluetooth-defaults.service @@ -0,0 +1,11 @@ +[Unit] +Description=Bluetooth defaults +After=local-fs.target + +ConditionPathExists=!/storage/.cache/services/bluez.conf +ConditionPathExists=!/storage/.cache/services/bluez.disabled + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /usr/share/services/bluez.conf /storage/.cache/services/' +RemainAfterExit=yes diff --git a/packages/network/bluez/system.d/bluetooth.service b/packages/network/bluez/system.d/bluetooth.service new file mode 100644 index 000000000..4a6313944 --- /dev/null +++ b/packages/network/bluez/system.d/bluetooth.service @@ -0,0 +1,21 @@ +[Unit] +Description=Bluetooth service +After=syslog.target bluetooth-defaults.service +Requires=bluetooth-defaults.service + +ConditionPathExists=/storage/.cache/services/bluez.conf + +[Service] +NotifyAccess=main +EnvironmentFile=/storage/.cache/services/bluez.conf +EnvironmentFile=-/run/libreelec/debug/bluez.conf +ExecStart=/usr/lib/bluetooth/bluetoothd $BLUEZ_ARGS $BLUEZ_DEBUG +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW +LimitNPROC=1 +TimeoutStopSec=1s +Restart=on-failure +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=bluetooth.target diff --git a/packages/network/bluez/system.d/obex.service b/packages/network/bluez/system.d/obex.service new file mode 100644 index 000000000..919d75bab --- /dev/null +++ b/packages/network/bluez/system.d/obex.service @@ -0,0 +1,17 @@ +[Unit] +Description=Bluetooth service +Requires=bluetooth.target bluetooth.service +After=bluetooth.service + +ConditionPathExists=/storage/.cache/services/obexd.conf +ConditionPathExists=/storage/.cache/services/bluez.conf + +[Service] +EnvironmentFile=/storage/.cache/services/obexd.conf +EnvironmentFile=-/run/libreelec/debug/obexd.conf +ExecStartPre=/bin/sh -c 'mkdir -p $OBEXD_ROOT' +ExecStart=/usr/lib/bluetooth/obexd -r $OBEXD_ROOT $OBEXD_DEBUG +TimeoutStopSec=1s + +[Install] +WantedBy=bluetooth.target diff --git a/packages/network/bluez/tmpfiles.d/z_05_bluez.conf b/packages/network/bluez/tmpfiles.d/z_05_bluez.conf new file mode 100644 index 000000000..f0df6f4b3 --- /dev/null +++ b/packages/network/bluez/tmpfiles.d/z_05_bluez.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /storage/.cache/bluetooth 0755 root root - - diff --git a/packages/network/connman/config/settings b/packages/network/connman/config/settings new file mode 100644 index 000000000..632a97b7a --- /dev/null +++ b/packages/network/connman/config/settings @@ -0,0 +1,8 @@ +[global] +OfflineMode=false + +[Wired] +Enable=true + +[WiFi] +Enable=true diff --git a/packages/network/connman/debug.d/connman.conf b/packages/network/connman/debug.d/connman.conf new file mode 100644 index 000000000..86502aa3e --- /dev/null +++ b/packages/network/connman/debug.d/connman.conf @@ -0,0 +1,2 @@ +CONNMAN_DEBUG="--debug" +CONNMANVPN_DEBUG="--debug" diff --git a/packages/network/connman/package.mk b/packages/network/connman/package.mk new file mode 100644 index 000000000..5e99637f1 --- /dev/null +++ b/packages/network/connman/package.mk @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="connman" +PKG_VERSION="25479cf866e60b0101cda0d80e825cd8128bb4eb" # 1.40 +PKG_LICENSE="GPL" +PKG_SITE="http://www.connman.net" +PKG_URL="https://git.kernel.org/pub/scm/network/connman/connman.git/snapshot/connman-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib readline dbus iptables wpa_supplicant" +PKG_LONGDESC="A modular network connection manager." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="WPASUPPLICANT=/usr/bin/wpa_supplicant \ + --srcdir=.. \ + --disable-debug \ + --disable-hh2serial-gps \ + --disable-openconnect \ + --disable-openvpn \ + --disable-vpnc \ + --disable-l2tp \ + --disable-pptp \ + --disable-iospm \ + --disable-tist \ + --disable-session-policy-local \ + --disable-test \ + --disable-nmcompat \ + --disable-polkit \ + --disable-selinux \ + --enable-loopback \ + --enable-ethernet \ + --disable-gadget \ + --enable-wifi \ + --disable-bluetooth \ + --disable-ofono \ + --disable-dundee \ + --disable-pacrunner \ + --disable-neard \ + --disable-wispr \ + --disable-tools \ + --disable-stats \ + --enable-client \ + --enable-datafiles \ + --with-dbusconfdir=/etc \ + --with-systemdunitdir=/usr/lib/systemd/system \ + --disable-silent-rules" + +if [ "$WIREGUARD_SUPPORT" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-wireguard=builtin" +else + PKG_CONGIGURE_OPTS_TARGET+=" --disable-wireguard" +fi + +PKG_MAKE_OPTS_TARGET="storagedir=/storage/.cache/connman \ + vpn_storagedir=/storage/.config/wireguard \ + statedir=/run/connman" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/lib/systemd + rm -rf $INSTALL/usr/lib/tmpfiles.d/connman_resolvconf.conf + + mkdir -p $INSTALL/usr/bin + cp -P client/connmanctl $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/lib/connman + cp -P $PKG_DIR/scripts/connman-setup $INSTALL/usr/lib/connman + + mkdir -p $INSTALL/etc/connman + cp ../src/main.conf $INSTALL/etc/connman + sed -i $INSTALL/etc/connman/main.conf \ + -e "s|^# BackgroundScanning.*|BackgroundScanning = true|g" \ + -e "s|^# UseGatewaysAsTimeservers.*|UseGatewaysAsTimeservers = false|g" \ + -e "s|^# FallbackNameservers.*|FallbackNameservers = 8.8.8.8,8.8.4.4|g" \ + -e "s|^# FallbackTimeservers.*|FallbackTimeservers = 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org|g" \ + -e "s|^# PreferredTechnologies.*|PreferredTechnologies = ethernet,wifi,cellular|g" \ + -e "s|^# TetheringTechnologies.*|TetheringTechnologies = wifi|g" \ + -e "s|^# AllowHostnameUpdates.*|AllowHostnameUpdates = false|g" \ + -e "s|^# PersistentTetheringMode.*|PersistentTetheringMode = true|g" \ + -e "s|^# SingleConnectedTechnology.*|SingleConnectedTechnology = true|g" \ + -e "s|^# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb|NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,docker,veth,zt|g" + + mkdir -p $INSTALL/usr/share/connman/ + cp $PKG_DIR/config/settings $INSTALL/usr/share/connman/ +} + +post_install() { + add_user system x 430 430 "service" "/var/run/connman" "/bin/sh" + add_group system 430 + + enable_service connman.service + if [ "$WIREGUARD_SUPPORT" = "yes" ]; then + enable_service connman-vpn.service + fi +} diff --git a/packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch b/packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch new file mode 100644 index 000000000..940945829 --- /dev/null +++ b/packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch @@ -0,0 +1,13 @@ +diff --git a/src/device.c b/src/device.c +index 0fda950..eb09e53 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -1247,8 +1247,6 @@ int __connman_device_init(const char *device, const char *nodevice) + if (nodevice != NULL) + nodevice_filter = g_strsplit(nodevice, ",", -1); + +- cleanup_devices(); +- + return 0; + } + diff --git a/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch b/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch new file mode 100644 index 000000000..9199ec54e --- /dev/null +++ b/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch @@ -0,0 +1,22 @@ +commit 707a0d73d7231b1821072712a7771c7aef140e21 +Author: Stefan Saraev +Date: Tue Jul 23 11:28:10 2013 +0300 + + ipv6 disabled by default + +diff --git a/src/ipconfig.c b/src/ipconfig.c +index fbeff8f..3eb61c4 100644 +--- a/src/ipconfig.c ++++ b/src/ipconfig.c +@@ -1123,10 +1123,7 @@ static struct connman_ipconfig *create_ipv6config(int index) + ipv6config->enabled = false; + ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6; + +- if (!is_ipv6_supported) +- ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF; +- else +- ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO; ++ ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF; + + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); + if (ipdevice != NULL) diff --git a/packages/network/connman/patches/connman-05_link-against-ncurses.patch b/packages/network/connman/patches/connman-05_link-against-ncurses.patch new file mode 100644 index 000000000..1cdf631b0 --- /dev/null +++ b/packages/network/connman/patches/connman-05_link-against-ncurses.patch @@ -0,0 +1,25 @@ +From 59bd0267cc8a581ff6f3388756a5524159a75b3b Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 13 Dec 2014 14:36:57 +0200 +Subject: [PATCH 5/5] link against ncurses + +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index 41efc1f..d1d3ddc 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -252,7 +252,7 @@ client_connmanctl_SOURCES = client/dbus_helpers.h client/dbus_helpers.c \ + client/main.c + + client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ \ +- -lreadline -ldl ++ -lreadline -lncurses -ltinfo -ldl + endif + + noinst_PROGRAMS += unit/test-pbkdf2-sha1 unit/test-prf-sha1 unit/test-ippool +-- +1.7.10.4 + diff --git a/packages/network/connman/scripts/connman-setup b/packages/network/connman/scripts/connman-setup new file mode 100755 index 000000000..16bc279ad --- /dev/null +++ b/packages/network/connman/scripts/connman-setup @@ -0,0 +1,25 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# creating initial settings file + if [ ! -f /storage/.cache/connman/settings ]; then + mkdir -p /storage/.cache/connman + cp /usr/share/connman/settings /storage/.cache/connman + fi + +# set variable for connman main.conf location + if [ -f /storage/.config/connman_main.conf ]; then + export CONNMAN_MAIN="--config=/storage/.config/connman_main.conf" + else + export CONNMAN_MAIN="--config=/etc/connman/main.conf" + fi + +# switch resolv.conf management to connman and use current contents +# as a fallback +if [ -f /run/libreelec/resolv.conf ]; then + cat /run/libreelec/resolv.conf > /run/connman/resolv.conf +fi +rm -f /run/libreelec/resolv.conf +ln -s /run/connman/resolv.conf /run/libreelec/resolv.conf diff --git a/packages/network/connman/system.d/connman-vpn.service b/packages/network/connman/system.d/connman-vpn.service new file mode 100644 index 000000000..6711bd4b6 --- /dev/null +++ b/packages/network/connman/system.d/connman-vpn.service @@ -0,0 +1,14 @@ +[Unit] +Description=ConnMan VPN service + +[Service] +Type=dbus +BusName=net.connman.vpn +ExecStart=/usr/sbin/connman-vpnd -n +StandardOutput=null +CapabilityBoundingSet=CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID +ProtectHome=read-only +ProtectSystem=full + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/connman/system.d/connman.service b/packages/network/connman/system.d/connman.service new file mode 100644 index 000000000..7ae77172e --- /dev/null +++ b/packages/network/connman/system.d/connman.service @@ -0,0 +1,21 @@ +[Unit] +Description=Connection service +DefaultDependencies=false +Conflicts=shutdown.target +Before=network.target multi-user.target shutdown.target +After=dbus.service network-base.service +Wants=network.target +ConditionPathExists=!/dev/.kernel_ipconfig + +[Service] +Type=dbus +BusName=net.connman +Restart=on-failure +EnvironmentFile=-/run/libreelec/debug/connman.conf +ExecStart=/bin/sh -c ". /usr/lib/connman/connman-setup; exec /usr/sbin/connmand -nr $CONNMAN_MAIN $CONNMAN_DEBUG" +StandardOutput=null +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/connman/system.d/network-online.service b/packages/network/connman/system.d/network-online.service new file mode 100644 index 000000000..935f63893 --- /dev/null +++ b/packages/network/connman/system.d/network-online.service @@ -0,0 +1,17 @@ +[Unit] +Description=Wait for network to be configured by ConnMan +After=connman.service +Before=network-online.target +DefaultDependencies=no +Conflicts=shutdown.target +ConditionPathExists=!/dev/.kernel_ipconfig + +[Service] +Type=oneshot +ExecStartPre=/bin/sh -c 'echo "waiting on Network to come online ..."' +ExecStart=/usr/sbin/connmand-wait-online --timeout=30 +StandardOutput=tty +RemainAfterExit=yes + +[Install] +WantedBy=network-online.target diff --git a/packages/network/connman/tmpfiles.d/z_03_connman.conf b/packages/network/connman/tmpfiles.d/z_03_connman.conf new file mode 100644 index 000000000..ebadc7ae1 --- /dev/null +++ b/packages/network/connman/tmpfiles.d/z_03_connman.conf @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /run/connman 0755 root root - - +d /storage/.cache/connman 0755 root root - - diff --git a/packages/network/ethtool/package.mk b/packages/network/ethtool/package.mk new file mode 100644 index 000000000..2414126d4 --- /dev/null +++ b/packages/network/ethtool/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ethtool" +PKG_VERSION="5.1" +PKG_SHA256="65feac1fec6565290b7784b2efc925dee900a9b11202ce7c6c30a967c3da3387" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kernel.org/pub/software/network/ethtool/" +PKG_URL="http://www.kernel.org/pub/software/network/ethtool/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Ethtool is used for querying settings of an ethernet device and changing them." diff --git a/packages/network/ethtool/udev.d/99-wakeup-eth.rules b/packages/network/ethtool/udev.d/99-wakeup-eth.rules new file mode 100644 index 000000000..add3a4a97 --- /dev/null +++ b/packages/network/ethtool/udev.d/99-wakeup-eth.rules @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv) +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end" +SUBSYSTEM!="net", GOTO="end" +ENV{INTERFACE}!="eth*", GOTO="end" + +TEST=="/sys/class/net/$env{INTERFACE}/device/power/wakeup", RUN+="/bin/sh -c 'echo enabled >/sys/class/net/$env{INTERFACE}/device/power/wakeup'" +RUN+="/usr/sbin/ethtool -s $env{INTERFACE} wol g" + +LABEL="end" diff --git a/packages/network/fping/package.mk b/packages/network/fping/package.mk new file mode 100644 index 000000000..d0c618ce5 --- /dev/null +++ b/packages/network/fping/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="fping" +PKG_VERSION="5.0" +PKG_SHA256="ed38c0b9b64686a05d1b3bc1d66066114a492e04e44eef1821d43b1263cd57b8" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://fping.org/" +PKG_URL="http://fping.org/dist/fping-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="auto" + +PKG_CONFIGURE_OPTS_TARGET="--sbindir=/usr/bin" diff --git a/packages/network/iptables/config/README b/packages/network/iptables/config/README new file mode 100644 index 000000000..77d75ff59 --- /dev/null +++ b/packages/network/iptables/config/README @@ -0,0 +1,17 @@ +To create your own set of Netfilters you can save your rules in: + +/storage/.config/iptables/rules.v4 for ipv4 +/storage/.config/iptables/rules.v6 for ipv6 + +To modify tables, edit with nano then save with: + +iptables-save >/storage/.config/iptables/rules.v4 +ip6tables-save >/storage/.config/iptables/rules.v6 + +To disable iptables use the following command: + +systemctl mask iptables + +To enable iptables again: + +systemctl unmask iptables diff --git a/packages/network/iptables/config/home.v4 b/packages/network/iptables/config/home.v4 new file mode 100644 index 000000000..583a3e845 --- /dev/null +++ b/packages/network/iptables/config/home.v4 @@ -0,0 +1,44 @@ +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:DOCKER-USER - [0:0] +:private-subnets - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -i tether -p udp -m conntrack --ctstate NEW -j ACCEPT +-A INPUT -j private-subnets +-A FORWARD -i tether -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -o tether -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A DOCKER-USER -j private-subnets +-A private-subnets -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A private-subnets -s 10.0.0.0/8 -i eth+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 172.16.0.0/12 -i eth+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 192.168.0.0/16 -i eth+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 10.0.0.0/8 -i en+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 172.16.0.0/12 -i en+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 192.168.0.0/16 -i en+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 10.0.0.0/8 -i wl+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 172.16.0.0/12 -i wl+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 192.168.0.0/16 -i wl+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 10.0.0.0/8 -i tether -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 172.16.0.0/12 -i tether -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 192.168.0.0/16 -i tether -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 10.0.0.0/8 -i docker+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 172.16.0.0/12 -i docker+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s 192.168.0.0/16 -i docker+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -j REJECT --reject-with icmp-port-unreachable +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT diff --git a/packages/network/iptables/config/home.v6 b/packages/network/iptables/config/home.v6 new file mode 100644 index 000000000..44074d090 --- /dev/null +++ b/packages/network/iptables/config/home.v6 @@ -0,0 +1,34 @@ +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:DOCKER-USER - [0:0] +:private-subnets - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -i tether -p udp -m conntrack --ctstate NEW -j ACCEPT +-A INPUT -j private-subnets +-A FORWARD -i tether -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -o tether -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A DOCKER-USER -j private-subnets +-A private-subnets -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A private-subnets -s fc00::/7 -i eth+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s fc00::/7 -i en+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s fc00::/7 -i wl+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s fc00::/7 -i tether -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -s fc00::/7 -i docker+ -m conntrack --ctstate NEW -j ACCEPT +-A private-subnets -j REJECT --reject-with icmp6-port-unreachable +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT diff --git a/packages/network/iptables/config/public.v4 b/packages/network/iptables/config/public.v4 new file mode 100644 index 000000000..7872e8d4b --- /dev/null +++ b/packages/network/iptables/config/public.v4 @@ -0,0 +1,31 @@ +# Netfilter rules for public "untrusted" networks +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:DOCKER-USER - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +# Allow tethered Wifi AP +-A INPUT -i tether -p udp -m conntrack --ctstate NEW -j ACCEPT +-A INPUT -i tether -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -m conntrack --ctstate NEW -j ACCEPT +-A FORWARD -i tether -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -m conntrack --ctstate NEW -j ACCEPT +-A FORWARD -i tether -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A FORWARD -o tether -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +# Block DOCKER +-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN +-A DOCKER-USER -j REJECT --reject-with icmp-port-unreachable +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT diff --git a/packages/network/iptables/config/public.v6 b/packages/network/iptables/config/public.v6 new file mode 100644 index 000000000..bddcccdd4 --- /dev/null +++ b/packages/network/iptables/config/public.v6 @@ -0,0 +1,30 @@ +# Netfilter Rules for trusted home networks. +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:DOCKER-USER - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +# Allow tethered Wifi AP +-A INPUT -i tether -p udp -m conntrack --ctstate NEW -j ACCEPT +-A INPUT -i tether -s fc00::/7 -m conntrack --ctstate NEW -j ACCEPT +-A FORWARD -i tether -s fc00::/7 -m conntrack --ctstate NEW -j ACCEPT +-A FORWARD -i tether -s fc00::/7 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A FORWARD -o tether -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A DOCKER-USER -j REJECT --reject-with icmp6-port-unreachable +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT diff --git a/packages/network/iptables/package.mk b/packages/network/iptables/package.mk new file mode 100644 index 000000000..7b15d5bee --- /dev/null +++ b/packages/network/iptables/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="iptables" +PKG_VERSION="1.8.3" +PKG_SHA256="a23cac034181206b4545f4e7e730e76e08b5f3dd78771ba9645a6756de9cdd80" +PKG_LICENSE="GPL" +PKG_SITE="http://www.netfilter.org/" +PKG_URL="http://www.netfilter.org/projects/iptables/files/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain linux libmnl libnftnl" +PKG_LONGDESC="IP packet filter administration." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--with-kernel=$(kernel_path) + CPPFLAGS=-I${SYSROOT_PREFIX}/usr/include" + + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/config/iptables/ + cp -PR $PKG_DIR/config/README $INSTALL/usr/config/iptables/ + + mkdir -p $INSTALL/etc/iptables/ + cp -PR $PKG_DIR/config/* $INSTALL/etc/iptables/ + + mkdir -p $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/iptables_helper $INSTALL/usr/lib/coreelec +} + +post_install() { + enable_service iptables.service +} + diff --git a/packages/network/iptables/scripts/iptables_helper b/packages/network/iptables/scripts/iptables_helper new file mode 100755 index 000000000..308f00c87 --- /dev/null +++ b/packages/network/iptables/scripts/iptables_helper @@ -0,0 +1,99 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +IPTABLES4="/usr/sbin/iptables" +IPTABLES6="/usr/sbin/ip6tables" +IPTABLES_CMDS="$IPTABLES4 $IPTABLES6" +PUBLIC_RULES="/etc/iptables/public.v" +HOME_RULES="/etc/iptables/home.v" +CUSTOM_RULES="/storage/.config/iptables/rules.v" +DOCKER="service.system.docker.service" +SYSTEMCTL="/usr/bin/systemctl" +CONNMANCTL="/usr/bin/connmanctl" + +check_docker() { + $SYSTEMCTL is-active --quiet $DOCKER && $SYSTEMCTL restart $DOCKER +} + +get_technology_config() { + $CONNMANCTL technologies | awk -v pattern="^/.*/technology/$1$" -e 'BEGIN {S=0}; /^\/.*/ {S=0}; $0 ~ pattern {S=1}; S==1 {print $0}' +} + +check_tether() { + for technology in wifi ethernet; do + if get_technology_config $technology | grep -q 'Tethering = True'; then + $CONNMANCTL tether $technology off + sleep 1 + $CONNMANCTL tether $technology on + break + fi + done +} + +flush() { + for cmd in $IPTABLES_CMDS; do + $cmd -F + $cmd -X + $cmd -t nat -F + $cmd -t nat -X + $cmd -t mangle -F + $cmd -t mangle -X + $cmd -P INPUT ACCEPT + $cmd -P FORWARD ACCEPT + $cmd -P OUTPUT ACCEPT + done + check_docker + check_tether +} + +enable() { + for cmd in $IPTABLES_CMDS; do + case "$cmd" in + *6*) + rules="$RULES6" + ipv="6" + ;; + *) + rules="$RULES4" + ipv="4" + ;; + esac + if [ -e "$rules" ]; then + "$cmd-restore" "$rules" + fi + done + check_docker + check_tether +} + +if [ "$1" = "enable" ]; then + case "${RULES}" in + "none") + flush + ;; + "public") + RULES4="${PUBLIC_RULES}4" + RULES6="${PUBLIC_RULES}6" + ;; + "home") + RULES4="${HOME_RULES}4" + RULES6="${HOME_RULES}6" + ;; + "custom") + RULES4="${CUSTOM_RULES}4" + RULES6="${CUSTOM_RULES}6" + ;; + *) + exit 1 + ;; + esac + enable +elif [ "$1" = "disable" ]; then + flush +else + exit 1 +fi + +exit 0 diff --git a/packages/network/iptables/system.d/iptables.service b/packages/network/iptables/system.d/iptables.service new file mode 100644 index 000000000..5e23ef1de --- /dev/null +++ b/packages/network/iptables/system.d/iptables.service @@ -0,0 +1,17 @@ +[Unit] +Description=IPTABLES Packet Filtering +ConditionPathExists=/usr/lib/coreelec/iptables_helper +ConditionPathExists=|/storage/.cache/services/iptables.conf +Before=network.target +Wants=network.target + +[Service] +Type=oneshot +EnvironmentFile=-/storage/.cache/services/iptables.conf +ExecStart=/usr/lib/coreelec/iptables_helper enable +ExecReload=/usr/lib/coreelec/iptables_helper enable +ExecStop=/usr/lib/coreelec/iptables_helper disable +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/iw/package.mk b/packages/network/iw/package.mk new file mode 100644 index 000000000..f63ce692c --- /dev/null +++ b/packages/network/iw/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="iw" +PKG_VERSION="5.4" +PKG_SHA256="a2469f677088d7b1070a7fbb28f3c747041697e8f6ec70783339cb1bc27a395f" +PKG_LICENSE="PUBLIC_DOMAIN" +PKG_SITE="https://wireless.wiki.kernel.org/en/users/documentation/iw" +PKG_URL="https://www.kernel.org/pub/software/network/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libnl" +PKG_LONGDESC="A new nl80211 based CLI configuration utility for wireless devices." +# iw fails at runtime with lto enabled + +pre_configure_target() { + export LDFLAGS="$LDFLAGS -pthread" +} + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/lib/iw + cp $PKG_DIR/scripts/setregdomain $INSTALL/usr/lib/iw +} diff --git a/packages/network/iw/scripts/setregdomain b/packages/network/iw/scripts/setregdomain new file mode 100755 index 000000000..538bfddb5 --- /dev/null +++ b/packages/network/iw/scripts/setregdomain @@ -0,0 +1,8 @@ +#!/bin/sh + +REGDOMAIN= +REGDOMAIN_CONF="/storage/.cache/regdomain.conf" +[ -r "$REGDOMAIN_CONF" ] && . "$REGDOMAIN_CONF" +[ -z "$REGDOMAIN" ] && exit 0 + +exec /usr/sbin/iw reg set "$REGDOMAIN" diff --git a/packages/network/iw/udev.d/60-iw-regdomain.rules b/packages/network/iw/udev.d/60-iw-regdomain.rules new file mode 100644 index 000000000..a9f929c45 --- /dev/null +++ b/packages/network/iw/udev.d/60-iw-regdomain.rules @@ -0,0 +1 @@ +SUBSYSTEM=="ieee80211", ACTION=="add", RUN+="/usr/lib/iw/setregdomain" diff --git a/packages/network/libdnet/package.mk b/packages/network/libdnet/package.mk new file mode 100644 index 000000000..dbdd90859 --- /dev/null +++ b/packages/network/libdnet/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libdnet" +PKG_VERSION="8029bf9" +PKG_SHA256="1e41cbe5e4884108b08fa92964305354f1662b7e889f62736b3749845d7a8c56" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/sgeto/libdnet" +PKG_URL="https://github.com/sgeto/libdnet/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A simplified, portable interface to several low-level networking routines" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_strlcat=no \ + ac_cv_func_strlcpy=no \ + --enable-static \ + --disable-shared \ + --disable-python" + +pre_configure_target() { + export CFLAGS+=" -I$PKG_BUILD/include" +} + +post_makeinstall_target() { + cp $SYSROOT_PREFIX/usr/bin/dnet-config \ + $TOOLCHAIN/bin/dnet-config +} diff --git a/packages/network/libmnl/package.mk b/packages/network/libmnl/package.mk new file mode 100644 index 000000000..ec2eb2b51 --- /dev/null +++ b/packages/network/libmnl/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libmnl" +PKG_VERSION="1.0.4" +PKG_SHA256="171f89699f286a5854b72b91d06e8f8e3683064c5901fb09d954a9ab6f551f81" +PKG_LICENSE="GPL" +PKG_SITE="http://netfilter.org/projects/libmnl" +PKG_URL="http://netfilter.org/projects/libmnl/files/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A minimalistic user-space library oriented to Netlink developers." diff --git a/packages/network/libnfs/package.mk b/packages/network/libnfs/package.mk new file mode 100644 index 000000000..6dacdd241 --- /dev/null +++ b/packages/network/libnfs/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libnfs" +PKG_VERSION="4.0.0" +PKG_SHA256="6ee77e9fe220e2d3e3b1f53cfea04fb319828cc7dbb97dd9df09e46e901d797d" +PKG_LICENSE="LGPL2.1+" +PKG_SITE="https://github.com/sahlberg/libnfs" +PKG_URL="https://github.com/sahlberg/libnfs/archive/libnfs-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A client library for accessing NFS shares over a network." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-examples" + +pre_configure_target() { + export CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64" +} diff --git a/packages/network/libnftnl/package.mk b/packages/network/libnftnl/package.mk new file mode 100644 index 000000000..edcbaafaa --- /dev/null +++ b/packages/network/libnftnl/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libnftnl" +PKG_VERSION="1.1.3" +PKG_SHA256="22dd97d3b06ae8c67499506e2bfd6803ce116479076ec3700e7a4c7cd9fcba0f" +PKG_LICENSE="GPL" +PKG_SITE="http://netfilter.org/projects/libnftnl" +PKG_URL="http://netfilter.org/projects/libnftnl/files/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libmnl" +PKG_LONGDESC="A userspace library providing a low-level netlink programming interface (API) to the in-kernel nf_tables subsystem." + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared --enable-static" diff --git a/packages/network/libnl/package.mk b/packages/network/libnl/package.mk new file mode 100644 index 000000000..29abe2249 --- /dev/null +++ b/packages/network/libnl/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libnl" +PKG_VERSION="3.4.0" +PKG_SHA256="b7287637ae71c6db6f89e1422c995f0407ff2fe50cecd61a312b6a9b0921f5bf" +PKG_LICENSE="LGPL" +PKG_SITE="https://github.com/thom311/libnl" +PKG_URL="https://github.com/thom311/libnl/releases/download/libnl${PKG_VERSION//./_}/libnl-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library for applications dealing with netlink socket." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-cli" diff --git a/packages/network/libshairplay/package.mk b/packages/network/libshairplay/package.mk new file mode 100644 index 000000000..afbe86bb4 --- /dev/null +++ b/packages/network/libshairplay/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libshairplay" +PKG_VERSION="096b61ad14c90169f438e690d096e3fcf87e504e" +PKG_SHA256="7e2b013ffe75ea2f13fb12b1aa38b8e2e8b1899ac292d57f05d7b352a3a181cf" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/juhovh/shairplay" +PKG_URL="https://github.com/juhovh/shairplay/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain avahi" +PKG_LONGDESC="Apple airplay and raop protocol server" +PKG_TOOLCHAIN="autotools" + +pre_configure_target() { + CFLAGS="$CFLAGS -I$(get_build_dir avahi)/avahi-compat-libdns_sd" +} + +post_makeinstall_target() { + mkdir -p $INSTALL/etc/shairplay + cp -P ../airport.key $INSTALL/etc/shairplay +} diff --git a/packages/network/libshairplay/patches/libshairplay-read_airportkey_from_etc.patch b/packages/network/libshairplay/patches/libshairplay-read_airportkey_from_etc.patch new file mode 100644 index 000000000..d7ecbd0b7 --- /dev/null +++ b/packages/network/libshairplay/patches/libshairplay-read_airportkey_from_etc.patch @@ -0,0 +1,19 @@ +--- shairplay-0.9.0.orig/src/shairplay.c ++++ shairplay-0.9.0/src/shairplay.c +@@ -313,9 +313,12 @@ main(int argc, char *argv[]) + + raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key", NULL); + if (raop == NULL) { +- fprintf(stderr, "Could not initialize the RAOP service\n"); +- fprintf(stderr, "Please make sure the airport.key file is in the current directory.\n"); +- return -1; ++ raop = raop_init_from_keyfile(10, &raop_cbs, "/etc/shairplay/airport.key", NULL); ++ if (raop == NULL) { ++ fprintf(stderr, "Could not initialize the RAOP service\n"); ++ fprintf(stderr, "Please make sure the airport.key file is in the current directory.\n"); ++ return -1; ++ } + } + + if (strlen(options.password)) { + diff --git a/packages/network/libssh/package.mk b/packages/network/libssh/package.mk new file mode 100644 index 000000000..103608fe5 --- /dev/null +++ b/packages/network/libssh/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libssh" +PKG_VERSION="0.8.9" +PKG_SHA256="8559e19da0c40b6f93482b6160219ad77a4d9f1dc190bf174757455c6ae26825" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.libssh.org/" +PKG_URL="https://www.libssh.org/files/${PKG_VERSION%.*}/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_LONGDESC="Library for accessing ssh client services through C libraries." + +PKG_CMAKE_OPTS_TARGET="-DWITH_STATIC_LIB=1 \ + -DWITH_SERVER=OFF \ + -DWITH_GCRYPT=OFF \ + -DWITH_GSSAPI=OFF \ + -DWITH_INTERNAL_DOC=OFF" + +makeinstall_target() { +# install static library only + mkdir -p $SYSROOT_PREFIX/usr/lib + cp src/libssh.a $SYSROOT_PREFIX/usr/lib + + mkdir -p $SYSROOT_PREFIX/usr/lib/pkgconfig + cp libssh.pc $SYSROOT_PREFIX/usr/lib/pkgconfig + + mkdir -p $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/callbacks.h $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/legacy.h $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/libssh.h $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/server.h $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/sftp.h $SYSROOT_PREFIX/usr/include/libssh + cp ../include/libssh/ssh2.h $SYSROOT_PREFIX/usr/include/libssh +} diff --git a/packages/network/libssh2/package.mk b/packages/network/libssh2/package.mk new file mode 100644 index 000000000..403f7871d --- /dev/null +++ b/packages/network/libssh2/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libssh2" +PKG_VERSION="1.8.0" +PKG_SHA256="39f34e2f6835f4b992cafe8625073a88e5a28ba78f83e8099610a7b3af4676d4" +PKG_LICENSE="BSD" +PKG_SITE="https://www.libssh2.org" +PKG_URL="https://www.libssh2.org/download/libssh2-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain openssl" +PKG_LONGDESC="A library implementing the SSH2 protocol" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=OFF" diff --git a/packages/network/libtirpc/package.mk b/packages/network/libtirpc/package.mk new file mode 100644 index 000000000..6d7537d5e --- /dev/null +++ b/packages/network/libtirpc/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libtirpc" +PKG_VERSION="1.1.4" +PKG_SHA256="2ca529f02292e10c158562295a1ffd95d2ce8af97820e3534fe1b0e3aec7561d" +PKG_LICENSE="GPL" +PKG_SITE="https://sourceforge.net/projects/libtirpc/" +PKG_URL="https://downloads.sourceforge.net/project/libtirpc/libtirpc/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A port of Suns Transport-Independent RPC library to Linux." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared \ + --disable-silent-rules \ + --enable-ipv6 \ + --disable-gssapi \ + --with-gnu-ld" diff --git a/packages/network/netbase/package.mk b/packages/network/netbase/package.mk new file mode 100644 index 000000000..3aaf84829 --- /dev/null +++ b/packages/network/netbase/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="netbase" +PKG_VERSION="5.4" +PKG_SHA256="66ff73d2d162e2d49db43988d8b8cd328cf7fffca042db73397f14c71825e80d" +PKG_LICENSE="GPL" +PKG_SITE="https://anonscm.debian.org/cgit/users/md/netbase.git/" +PKG_URL="http://ftp.debian.org/debian/pool/main/n/netbase/netbase_$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The netbase package provides data for network services and protocols from the iana db." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/etc + cp etc-protocols $INSTALL/etc/protocols + cp etc-services $INSTALL/etc/services +} diff --git a/packages/network/nss-mdns/config/nsswitch.conf b/packages/network/nss-mdns/config/nsswitch.conf new file mode 100644 index 000000000..2c405773c --- /dev/null +++ b/packages/network/nss-mdns/config/nsswitch.conf @@ -0,0 +1,19 @@ +# /etc/nsswitch.conf +# +# Example configuration of GNU Name Service Switch functionality. +# + +passwd: files +group: files +shadow: files +gshadow: files + +hosts: files mdns_minimal [NOTFOUND=return] dns +networks: files dns + +protocols: files +services: files +ethers: files +rpc: files + +netgroup: files diff --git a/packages/network/nss-mdns/package.mk b/packages/network/nss-mdns/package.mk new file mode 100644 index 000000000..baa64e18b --- /dev/null +++ b/packages/network/nss-mdns/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nss-mdns" +PKG_VERSION="0.14.1" +PKG_SHA256="4fe54bffd20e410fc41382dc6c4708cdfa3a65f50c3753f262dc4c78fd864a6e" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lathiat/nss-mdns" +PKG_URL="https://github.com/lathiat/nss-mdns/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain avahi" +PKG_LONGDESC="A plugin for nss to allow name resolution via Multicast DNS." +PKG_TOOLCHAIN="autotools" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/etc + cp ${PKG_DIR}/config/nsswitch.conf ${INSTALL}/etc/nsswitch.conf +} diff --git a/packages/network/openssh/package.mk b/packages/network/openssh/package.mk new file mode 100644 index 000000000..78b1a8551 --- /dev/null +++ b/packages/network/openssh/package.mk @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="openssh" +PKG_VERSION="8.8p1" +PKG_LICENSE="OSS" +PKG_SITE="https://www.openssh.com/" +PKG_URL="https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain openssl zlib" +PKG_LONGDESC="An open re-implementation of the SSH package." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+lto" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_rpc_types_h=no \ + --sysconfdir=/etc/ssh \ + --libexecdir=/usr/lib/openssh \ + --disable-strip \ + --disable-lastlog \ + --with-sandbox=no \ + --disable-utmp \ + --disable-utmpx \ + --disable-wtmp \ + --disable-wtmpx \ + --without-rpath \ + --with-ssl-engine \ + --with-privsep-user=nobody \ + --disable-pututline \ + --disable-pututxline \ + --disable-etc-default-login \ + --with-keydir=/storage/.cache/ssh \ + --without-pam" + +pre_configure_target() { + export LD="$CC" + export LDFLAGS="$TARGET_CFLAGS $TARGET_LDFLAGS" +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/lib/openssh/ssh-keysign + rm -rf $INSTALL/usr/lib/openssh/ssh-pkcs11-helper + if [ ! $SFTP_SERVER = "yes" ]; then + rm -rf $INSTALL/usr/lib/openssh/sftp-server + fi + rm -rf $INSTALL/usr/bin/ssh-add + rm -rf $INSTALL/usr/bin/ssh-agent + rm -rf $INSTALL/usr/bin/ssh-keyscan + + sed -e "s|^#PermitRootLogin.*|PermitRootLogin yes|g" \ + -e "s|^#StrictModes.*|StrictModes no|g" \ + -i $INSTALL/etc/ssh/sshd_config + + debug_strip $INSTALL/usr +} + +post_install() { + enable_service sshd.service +} diff --git a/packages/network/openssh/patches/openssh-7.9p1-keydir.patch b/packages/network/openssh/patches/openssh-7.9p1-keydir.patch new file mode 100644 index 000000000..fd0f4a887 --- /dev/null +++ b/packages/network/openssh/patches/openssh-7.9p1-keydir.patch @@ -0,0 +1,119 @@ +diff -u a/configure.ac b/configure.ac +--- a/configure.ac 2018-10-16 20:01:20.000000000 -0400 ++++ b/configure.ac 2018-12-06 04:08:42.718993760 -0500 +@@ -4903,6 +4903,19 @@ + ) + + ++# Set keydir ++AC_ARG_WITH([keydir], ++ [ --with-keydir= Specify different path for storing keys], ++ [ ++ if test -n "$withval" && test "x$withval" != "xno" && \ ++ test "x${withval}" != "xyes"; then ++ KEYDIR=$withval ++ fi ++ ] ++) ++AC_SUBST([KEYDIR]) ++ ++ + AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses]) + IPV4_IN6_HACK_MSG="no" + AC_ARG_WITH(4in6, +@@ -5277,6 +5290,7 @@ + H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}` + I=`eval echo ${user_path}` ; I=`eval echo ${I}` + J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` ++K=`eval echo ${KEYDIR}` ; K=`eval echo ${K}` + + echo "" + echo "OpenSSH has been configured with the following options:" +@@ -5300,6 +5314,9 @@ + if test ! -z "$superuser_path" ; then + echo " sshd superuser user PATH: $J" + fi ++if test ! -z "$KEYDIR" ; then ++echo " sshd keydir: $K" ++fi + echo " Manpage format: $MANTYPE" + echo " PAM support: $PAM_MSG" + echo " OSF SIA support: $SIA_MSG" +Common subdirectories: a/contrib and b/contrib +diff -u a/Makefile.in b/Makefile.in +--- a/Makefile.in 2018-10-16 20:01:20.000000000 -0400 ++++ b/Makefile.in 2018-12-06 04:00:04.301968236 -0500 +@@ -28,8 +28,10 @@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ + STRIP_OPT=@STRIP_OPT@ + TEST_SHELL=@TEST_SHELL@ ++KEYDIR=@KEYDIR@ + + PATHS= -DSSHDIR=\"$(sysconfdir)\" \ ++ -DKEYDIR=\"$(KEYDIR)\" \ + -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ + -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ + -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ +@@ -133,11 +135,11 @@ + -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \ + -e 's|/usr/libexec|$(libexecdir)|g' \ + -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \ +- -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \ +- -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \ +- -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ +- -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \ +- -e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \ ++ -e 's|/etc/ssh/ssh_host_key|$(KEYDIR)/ssh_host_key|g' \ ++ -e 's|/etc/ssh/ssh_host_ecdsa_key|$(KEYDIR)/ssh_host_ecdsa_key|g' \ ++ -e 's|/etc/ssh/ssh_host_dsa_key|$(KEYDIR)/ssh_host_dsa_key|g' \ ++ -e 's|/etc/ssh/ssh_host_rsa_key|$(KEYDIR)/ssh_host_rsa_key|g' \ ++ -e 's|/etc/ssh/ssh_host_ed25519_key|$(KEYDIR)/ssh_host_ed25519_key|g' \ + -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \ + -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \ + -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \ +Common subdirectories: a/openbsd-compat and b/openbsd-compat +diff -u a/pathnames.h b/pathnames.h +--- a/pathnames.h 2018-10-16 20:01:20.000000000 -0400 ++++ b/pathnames.h 2018-12-06 04:15:01.286012398 -0500 +@@ -18,6 +18,10 @@ + #define SSHDIR ETCDIR "/ssh" + #endif + ++#ifndef KEYDIR ++#define KEYDIR SSHDIR ++#endif ++ + #ifndef _PATH_SSH_PIDDIR + #define _PATH_SSH_PIDDIR "/var/run" + #endif +@@ -26,9 +30,9 @@ + * System-wide file containing host keys of known hosts. This file should be + * world-readable. + */ +-#define _PATH_SSH_SYSTEM_HOSTFILE SSHDIR "/ssh_known_hosts" ++#define _PATH_SSH_SYSTEM_HOSTFILE KEYDIR "/ssh_known_hosts" + /* backward compat for protocol 2 */ +-#define _PATH_SSH_SYSTEM_HOSTFILE2 SSHDIR "/ssh_known_hosts2" ++#define _PATH_SSH_SYSTEM_HOSTFILE2 KEYDIR "/ssh_known_hosts2" + + /* + * Of these, ssh_host_key must be readable only by root, whereas ssh_config +@@ -36,11 +40,11 @@ + */ + #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" + #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" +-#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" +-#define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" +-#define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" +-#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key" +-#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" +-#define _PATH_DH_MODULI SSHDIR "/moduli" ++#define _PATH_HOST_DSA_KEY_FILE KEYDIR "/ssh_host_dsa_key" ++#define _PATH_HOST_ECDSA_KEY_FILE KEYDIR "/ssh_host_ecdsa_key" ++#define _PATH_HOST_ED25519_KEY_FILE KEYDIR "/ssh_host_ed25519_key" ++#define _PATH_HOST_XMSS_KEY_FILE KEYDIR "/ssh_host_xmss_key" ++#define _PATH_HOST_RSA_KEY_FILE KEYDIR "/ssh_host_rsa_key" ++#define _PATH_DH_MODULI KEYDIR "/moduli" + + #ifndef _PATH_SSH_PROGRAM + #define _PATH_SSH_PROGRAM "/usr/bin/ssh" diff --git a/packages/network/openssh/system.d/sshd.service b/packages/network/openssh/system.d/sshd.service new file mode 100644 index 000000000..436edac09 --- /dev/null +++ b/packages/network/openssh/system.d/sshd.service @@ -0,0 +1,20 @@ +[Unit] +Description=OpenSSH server daemon +ConditionKernelCommandLine=|ssh +ConditionPathExists=|/storage/.cache/services/sshd.conf + +[Service] +Restart=on-failure +EnvironmentFile=-/storage/.cache/services/sshd.conf +ExecStartPre=-/bin/sh -c 'mkdir -p /storage/.cache/ssh' +ExecStartPre=/usr/bin/ssh-keygen -A +ExecStartPre=-/bin/sh -c 'chmod 600 /storage/.cache/ssh/ssh_host_*' +ExecStartPre=-/bin/sh -c 'chmod 644 /storage/.cache/ssh/ssh_host_*.pub' +ExecStart=/usr/sbin/sshd -D $SSH_ARGS +ExecReload=/bin/kill -HUP $MAINPID +TimeoutStopSec=1s +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/openssh/tmpfiles.d/z_04_openssh.conf b/packages/network/openssh/tmpfiles.d/z_04_openssh.conf new file mode 100644 index 000000000..baae3c662 --- /dev/null +++ b/packages/network/openssh/tmpfiles.d/z_04_openssh.conf @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /var/empty 0600 root root - - +d /storage/.cache/ssh 0755 root root - - +d /storage/.ssh 0700 root root - - diff --git a/packages/network/openvpn/package.mk b/packages/network/openvpn/package.mk new file mode 100644 index 000000000..09352eb84 --- /dev/null +++ b/packages/network/openvpn/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="openvpn" +PKG_VERSION="2.4.9" +PKG_SHA256="641f3add8694b2ccc39fd4fd92554e4f089ad16a8db6d2b473ec284839a5ebe2" +PKG_LICENSE="GPL" +PKG_SITE="https://openvpn.net" +PKG_URL="https://swupdate.openvpn.org/community/releases/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain lzo openssl" +PKG_LONGDESC="A full featured SSL VPN software solution that integrates OpenVPN server capabilities." + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_have_decl_TUNSETPERSIST=no \ + --disable-plugins \ + --enable-iproute2 IPROUTE=/sbin/ip \ + --enable-management \ + --enable-fragment \ + --disable-multihome \ + --disable-port-share \ + --disable-debug" + +post_makeinstall_target() { + mkdir -p $INSTALL/usr/bin + ln -sf ../sbin/openvpn $INSTALL/usr/bin/openvpn +} diff --git a/packages/network/rfkill/package.mk b/packages/network/rfkill/package.mk new file mode 100644 index 000000000..382e9d1f0 --- /dev/null +++ b/packages/network/rfkill/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rfkill" +PKG_VERSION="0.5" +PKG_SHA256="e0ae3004215e39a6c5c36e0726558740728d16f67ebdb8bea621250f6091d86a" +PKG_LICENSE="GPL" +PKG_SITE="https://wireless.wiki.kernel.org/en/users/documentation/rfkill" +PKG_URL="https://www.kernel.org/pub/software/network/rfkill/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small userspace tool to query the state of the rfkill switches, buttons and subsystem interfaces." diff --git a/packages/network/rfkill/patches/rfkill-0001-fix-version-sh.patch b/packages/network/rfkill/patches/rfkill-0001-fix-version-sh.patch new file mode 100644 index 000000000..8d5190363 --- /dev/null +++ b/packages/network/rfkill/patches/rfkill-0001-fix-version-sh.patch @@ -0,0 +1,23 @@ +diff -Naur a/version.sh b/version.sh +--- a/version.sh ++++ b/version.sh +@@ -12,19 +12,6 @@ + + if test "x$SUFFIX" != 'x'; then + v="$VERSION$SUFFIX" +-elif head=`git rev-parse --verify HEAD 2>/dev/null`; then +- git update-index --refresh --unmerged > /dev/null +- descr=$(git describe 2>/dev/null || echo "v$VERSION") +- +- # on git builds check that the version number above +- # is correct... +- [ "${descr%%-*}" = "v$VERSION" ] || exit 2 +- +- echo -n 'const char rfkill_version[] = "' > "$OUT" +- v="${descr#v}" +- if git diff-index --name-only HEAD | read dummy ; then +- v="$v"-dirty +- fi + else + v="$VERSION" + fi diff --git a/packages/network/rpcbind/package.mk b/packages/network/rpcbind/package.mk new file mode 100644 index 000000000..0c921e44c --- /dev/null +++ b/packages/network/rpcbind/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rpcbind" +PKG_VERSION="0.2.4" +PKG_SHA256="074a9a530dc7c11e0d905aa59bcb0847c009313f02e98d3d798aa9568f414c66" +PKG_LICENSE="OSS" +PKG_SITE="http://rpcbind.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/rpcbind/rpcbind/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libtirpc systemd" +PKG_LONGDESC="The rpcbind utility is a server that converts RPC program numbers into universal addresses." + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_rpcsvc_mount_h=no \ + --disable-warmstarts \ + --disable-libwrap \ + --with-statedir=/tmp \ + --with-rpcuser=root" + +post_install() { + enable_service rpcbind.service +} diff --git a/packages/network/rpcbind/patches/rpcbind-01-drop-warm-start-as-it-fails.patch b/packages/network/rpcbind/patches/rpcbind-01-drop-warm-start-as-it-fails.patch new file mode 100644 index 000000000..b85d4af2e --- /dev/null +++ b/packages/network/rpcbind/patches/rpcbind-01-drop-warm-start-as-it-fails.patch @@ -0,0 +1,18 @@ +diff -Naur a/systemd/rpcbind.service.in b/systemd/rpcbind.service.in +--- a/systemd/rpcbind.service.in 2016-12-20 03:18:51.839794796 +0000 ++++ b/systemd/rpcbind.service.in 2016-12-20 03:21:30.476854474 +0000 +@@ -6,12 +6,12 @@ + # Make sure we use the IP addresses listed for + # rpcbind.socket, no matter how this unit is started. + Wants=rpcbind.socket +-After=rpcbind.socket ++After=rpcbind.socket systemd-tmpfiles-setup.service + + [Service] + Type=notify + # distro can provide a drop-in adding EnvironmentFile=-/??? if needed. +-ExecStart=@_bindir@/rpcbind $RPCBIND_OPTIONS -w -f ++ExecStart=@_bindir@/rpcbind $RPCBIND_OPTIONS -f + + [Install] + WantedBy=multi-user.target diff --git a/packages/network/rsync/package.mk b/packages/network/rsync/package.mk new file mode 100644 index 000000000..09f9dee36 --- /dev/null +++ b/packages/network/rsync/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rsync" +PKG_VERSION="3.1.3" +PKG_SHA256="55cc554efec5fdaad70de921cd5a5eeb6c29a95524c715f3bbf849235b0800c0" +PKG_LICENSE="GPLv3" +PKG_SITE="http://www.samba.org/ftp/rsync/rsync.html" +PKG_URL="https://download.samba.org/pub/rsync/src/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A very fast method for bringing remote files into sync." + +PKG_CONFIGURE_OPTS_TARGET="--disable-acl-support \ + --disable-xattr-support \ + --with-included-popt" diff --git a/packages/network/samba/config/samba4-cache.txt b/packages/network/samba/config/samba4-cache.txt new file mode 100644 index 000000000..1989baa28 --- /dev/null +++ b/packages/network/samba/config/samba4-cache.txt @@ -0,0 +1,46 @@ +Checking simple C program: OK +rpath library support: OK +-Wl,--version-script support: OK +Checking getconf LFS_CFLAGS: NO +Checking for large file support without additional flags: OK +Checking for -D_LARGE_FILES: OK +Checking correct behavior of strtoll: NO +Checking for working strptime: OK +Checking for C99 vsnprintf: OK +Checking for HAVE_SHARED_MMAP: OK +Checking for HAVE_MREMAP: OK +Checking for HAVE_INCOHERENT_MMAP: NO +Checking for HAVE_SECURE_MKSTEMP: OK +Checking for HAVE_IFACE_GETIFADDRS: OK +Checking for kernel change notify support: OK +Checking for Linux kernel oplocks: OK +Checking for kernel share modes: OK +Checking if can we convert from CP850 to UCS-2LE: OK +Checking if can we convert from UTF-8 to UCS-2LE: OK +Checking whether we can use Linux thread-specific credentials with 32-bit system calls: OK +Checking whether we can use Linux thread-specific credentials: OK +Checking whether setreuid is available: OK +Checking whether setresuid is available: OK +Checking whether seteuid is available: OK +Checking whether fcntl locking is available: OK +Checking whether fcntl lock supports open file description locks: OK +Checking for the maximum value of the 'time_t' type: OK +Checking whether the realpath function allows a NULL argument: OK +Checking whether POSIX capabilities are available: OK +Checking for ftruncate extend: OK +vfs_fileid checking for statfs() and struct statfs.f_fsid: OK +getcwd takes a NULL argument: OK +Checking uname sysname type: "Linux" +Checking uname release type: "3.0.0" +Checking uname version type: "#1 Tue Nov 1 12:34:56 UTC 2013" +Checking value of NSIG: "32" +Checking value of _NSIG: "64" +Checking value of SIGRTMAX: "64" +Checking value of SIGRTMIN: "32" +Checking errno of iconv for illegal multibyte sequence: "0" +Checking for a 64-bit host to support lmdb: NO +Checking value of GNUTLS_CIPHER_AES_128_CFB8: OK +Checking value of GNUTLS_MAC_AES_CMAC_128: OK +Checking whether fcntl supports flags to send direct I/O availability signals: OK +Checking whether fcntl supports setting/geting hints: OK + diff --git a/packages/network/samba/config/smb.conf b/packages/network/samba/config/smb.conf new file mode 100644 index 000000000..f74be0e6d --- /dev/null +++ b/packages/network/samba/config/smb.conf @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# samba.conf v4 (do not remove) + +# This configuration file allows you to customize the samba shares +# available from your machine + +[global] + server string = JELOS + unix extensions = no + browseable = yes + writeable = yes + printable = no + deadtime = 30 + mangled names = no + name resolve order = host bcast + printcap name = /dev/null + load printers = no + enable core files = no + passdb backend = smbpasswd + smb encrypt = disabled + fruit:model = Xserve + + # samba share options + map to guest = Bad User + security = user + + # samba tuning options + socket options = TCP_NODELAY IPTOS_LOWDELAY + min receivefile size = 16384 + aio read size = 16384 + aio write size = 16384 + use sendfile = yes + + # The following are default values for the master selection process + # local master = yes + # preferred master = auto + # domain master = auto + # os level = 20 + + # "strict allocate = yes" breaks large network transfers to external hdd + # Force this to "no" in case "yes" becomes the default in future + strict allocate = no + +# Using the following configurations as a template allows you to add +# writeable shares of disks and paths under /storage + +[update] + path = /storage/roms/update + available = yes + browseable = yes + writeable = yes + root preexec = mkdir -p /storage/roms/update + +[roms] + path = /storage/roms + available = yes + browseable = yes + writeable = yes + root preexec = mkdir -p /storage/roms + +[logs] + path = /tmp/logs + available = yes + browseable = yes + writeable = yes + follow symlinks = yes + wide links = yes + root preexec = mkdir -p /tmp/logs + +[themes] + path = /storage/.config/emulationstation/themes + available = yes + browseable = yes + writeable = yes + follow symlinks = yes + wide links = yes + root preexec = mkdir -p /storage/.config/emulationstation/themes + +[config] + path = /storage/.config + available = yes + browseable = yes + writeable = yes + follow symlinks = yes + wide links = yes + root preexec = mkdir -p /storage/.config diff --git a/packages/network/samba/default.d/samba.conf b/packages/network/samba/default.d/samba.conf new file mode 100644 index 000000000..9ad00368c --- /dev/null +++ b/packages/network/samba/default.d/samba.conf @@ -0,0 +1,7 @@ +SAMBA_AUTOSHARE="true" +SAMBA_USERNAME="libreelec" +SAMBA_PASSWORD="libreelec" +SAMBA_SECURE="false" +SAMBA_MINPROTOCOL="SMB2" +SAMBA_MAXPROTOCOL="SMB3" +SAMBA_WORKGROUP="WORKGROUP" diff --git a/packages/network/samba/package.mk b/packages/network/samba/package.mk new file mode 100644 index 000000000..e2cae51a4 --- /dev/null +++ b/packages/network/samba/package.mk @@ -0,0 +1,207 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="samba" +PKG_VERSION="4.14.4" +PKG_LICENSE="GPLv3+" +PKG_SITE="https://www.samba.org" +PKG_URL="https://download.samba.org/pub/samba/stable/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain attr heimdal:host e2fsprogs Python3 zlib readline popt libaio connman gnutls" +PKG_NEED_UNPACK="$(get_pkg_directory heimdal) $(get_pkg_directory e2fsprogs)" +PKG_LONGDESC="A free SMB / CIFS fileserver and client." +PKG_BUILD_FLAGS="-gold" + +configure_package() { + #PKG_WAF_VERBOSE="-v" + + if [ "${AVAHI_DAEMON}" = yes ]; then + PKG_DEPENDS_TARGET+=" avahi" + SMB_AVAHI="--enable-avahi" + else + SMB_AVAHI="--disable-avahi" + fi + + if [ "${TARGET_ARCH}" = x86_64 ]; then + SMB_AESNI="--accel-aes=intelaesni" + else + SMB_AESNI="--accel-aes=none" + fi + + PKG_CONFIGURE_OPTS="--prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --with-lockdir=/var/lock-samba \ + --with-logfilebase=/var/log \ + --with-piddir=/run/samba \ + --with-privatedir=/run/samba \ + --with-modulesdir=/usr/lib \ + --with-privatelibdir=/usr/lib \ + --with-sockets-dir=/run/samba \ + --with-configdir=/run/samba \ + --with-libiconv=${SYSROOT_PREFIX}/usr \ + --cross-compile \ + --cross-answers=${PKG_BUILD}/cache.txt \ + --hostcc=gcc \ + --enable-fhs \ + --with-static-modules=vfs_widelinks \ + --without-dmapi \ + --disable-glusterfs \ + --disable-rpath \ + --disable-rpath-install \ + --disable-rpath-private-install \ + ${SMB_AVAHI} \ + ${SMB_AESNI} \ + --disable-cups \ + --disable-iprint \ + --with-relro \ + --with-sendfile-support \ + --without-acl-support \ + --without-ads \ + --without-ad-dc \ + --without-automount \ + --without-cluster-support \ + --without-dnsupdate \ + --without-fam \ + --without-gettext \ + --without-gpgme \ + --without-iconv \ + --without-ldap \ + --without-libarchive \ + --without-pam \ + --without-pie \ + --without-regedit \ + --without-systemd \ + --without-utmp \ + --without-winbind \ + --enable-auto-reconfigure \ + --bundled-libraries='ALL,!asn1_compile,!compile_et,!zlib' \ + --without-quotas \ + --with-syslog \ + --without-json \ + --without-ldb-lmdb \ + --nopyc --nopyo" + + PKG_SAMBA_TARGET="smbclient,client/smbclient,smbtree,nmblookup,testparm" + + if [ "${SAMBA_SERVER}" = "yes" ]; then + PKG_SAMBA_TARGET+=",smbd/smbd,nmbd,smbpasswd" + fi +} + +pre_configure_target() { +# samba uses its own build directory + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + +# work around link issues + export LDFLAGS="${LDFLAGS} -lreadline -lncurses -ltinfo" + +# support 64-bit offsets and seeks on 32-bit platforms + if [ "${TARGET_ARCH}" = "arm" ]; then + export CFLAGS+=" -D_FILE_OFFSET_BITS=64 -D_OFF_T_DEFINED_ -Doff_t=off64_t -Dlseek=lseek64" + fi +} + +configure_target() { + cp ${PKG_DIR}/config/samba4-cache.txt ${PKG_BUILD}/cache.txt + echo "Checking uname machine type: \"${TARGET_ARCH}\"" >> ${PKG_BUILD}/cache.txt + + export COMPILE_ET=${TOOLCHAIN}/bin/heimdal_compile_et + export ASN1_COMPILE=${TOOLCHAIN}/bin/heimdal_asn1_compile + + PYTHON_CONFIG="${SYSROOT_PREFIX}/usr/bin/python3-config" \ + python_LDFLAGS="" python_LIBDIR="" \ + PYTHON=${TOOLCHAIN}/bin/python3 ./configure ${PKG_CONFIGURE_OPTS} +} + +# disable icu, there is no buildswitch to disable +pre_make_target() { + sed -e '/#define HAVE_ICU_I18N 1/d' \ + -e '/#define HAVE_LIBICUI.* 1/d' \ + -i bin/default/include/config.h +} + +make_target() { + ./buildtools/bin/waf build ${PKG_WAF_VERBOSE} --targets=${PKG_SAMBA_TARGET} -j${CONCURRENCY_MAKE_LEVEL} +} + +makeinstall_target() { + ./buildtools/bin/waf install ${PKG_WAF_VERBOSE} --destdir=${SYSROOT_PREFIX} --targets=smbclient -j${CONCURRENCY_MAKE_LEVEL} + ./buildtools/bin/waf install ${PKG_WAF_VERBOSE} --destdir=${INSTALL} --targets=${PKG_SAMBA_TARGET} -j${CONCURRENCY_MAKE_LEVEL} +} + +copy_directory_of_links() { + local _tmp link + for link in "${1}/"*.so*; do + if [ -L ${link} ]; then + _tmp="$(readlink -m "${link}")" + cp -P ${_tmp} ${2} + cp -P ${_tmp}.* ${2} 2>/dev/null || true + else + cp -P ${link} ${2} + fi + done +} + +perform_manual_install() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib + copy_directory_of_links ${PKG_BUILD}/bin/shared ${SYSROOT_PREFIX}/usr/lib + + mkdir -p ${INSTALL}/usr/lib + copy_directory_of_links ${PKG_BUILD}/bin/shared ${INSTALL}/usr/lib + copy_directory_of_links ${PKG_BUILD}/bin/shared/private ${INSTALL}/usr/lib + + if [ "${SAMBA_SERVER}" = "yes" ]; then + mkdir -p ${INSTALL}/usr/sbin + cp -L ${PKG_BUILD}/bin/smbd ${INSTALL}/usr/sbin + cp -L ${PKG_BUILD}/bin/nmbd ${INSTALL}/usr/sbin + fi +} + +post_makeinstall_target() { + perform_manual_install + + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/lib/python* + rm -rf ${INSTALL}/usr/share/perl* + rm -rf ${INSTALL}/usr/lib64 + + mkdir -p ${INSTALL}/usr/lib/samba + cp ${PKG_DIR}/scripts/samba-config ${INSTALL}/usr/lib/samba + cp ${PKG_DIR}/scripts/smbd-config ${INSTALL}/usr/lib/samba + cp ${PKG_DIR}/scripts/samba-autoshare ${INSTALL}/usr/lib/samba + + if find_file_path config/smb.conf; then + mkdir -p ${INSTALL}/etc/samba + cp ${FOUND_PATH} ${INSTALL}/etc/samba + mkdir -p ${INSTALL}/usr/config + cp ${INSTALL}/etc/samba/smb.conf ${INSTALL}/usr/config/samba.conf.sample + fi + + mkdir -p ${INSTALL}/usr/bin + cp -PR bin/default/source3/client/smbclient ${INSTALL}/usr/bin + cp -PR bin/default/source3/utils/smbtree ${INSTALL}/usr/bin + cp -PR bin/default/source3/utils/nmblookup ${INSTALL}/usr/bin + cp -PR bin/default/source3/utils/testparm ${INSTALL}/usr/bin + + if [ "${SAMBA_SERVER}" = "yes" ]; then + mkdir -p ${INSTALL}/usr/bin + cp -PR bin/default/source3/utils/smbpasswd ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/usr/lib/systemd/system + cp ${PKG_DIR}/system.d.opt/* ${INSTALL}/usr/lib/systemd/system + + mkdir -p ${INSTALL}/usr/share/services + cp -P ${PKG_DIR}/default.d/*.conf ${INSTALL}/usr/share/services + fi +} + +post_install() { + enable_service samba-config.service + + if [ "${SAMBA_SERVER}" = "yes" ]; then + enable_service nmbd.service + enable_service smbd.service + fi +} diff --git a/packages/network/samba/patches/samba-200-4.11-fix-ASN1-bso14164.patch b/packages/network/samba/patches/samba-200-4.11-fix-ASN1-bso14164.patch new file mode 100644 index 000000000..03b2f31d6 --- /dev/null +++ b/packages/network/samba/patches/samba-200-4.11-fix-ASN1-bso14164.patch @@ -0,0 +1,86 @@ +From 2e53f331104b29db7caf1641a30d3e9316b57184 Mon Sep 17 00:00:00 2001 +From: Uri Simchoni +Date: Sun, 20 Oct 2019 00:03:14 +0300 +Subject: [PATCH] build: find pre-built heimdal build tools in case of embedded + heimdal + +This patch fixes the case of finding asn1_compile and compile_et for +building embedded heimdal, by setting +--bundled-libraries='!asn1_compile,!compile_et' as configure flags. + +The Heimdal build tools compile_et and asn1_compile are needed *only* +if we use the embedded heimdal (otherwise we don't build heimdal and +use headers that have been generated by those tools elsewhere). + +For cross-compilation with embedded heimdal, it is vital to use host build +tools, and so asn1_compile and compile_et must be supplied and not +built. One way of doing this would be to set the COMPILE_ET and +ASN1_COMPILE env vars to the location of supplied binaries. Another way, +which is more commonly used, is to exclude asn1_compile and compile_et +from bundled packages via the switch +-bundled-libraries='!asn1_compile,!compile_et'. When this is done, +the build script searches the path for those tools and sets the +ASN1_COMPILE and COMPILE_ET vars accordingly. (this is admittedly +kind of a round-about way of doing things but this has become the +de-facto standard amongst embedded distro builders). + +In commit 8061983d4882f3ba3f12da71443b035d7b672eec, this process of +finding the binaris has been moved to be carried out only in the +system heimdal case. As explained above, we only need these tools, +and hence the check, in bundled mode. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14164 + +Signed-off-by: Uri Simchoni +--- + wscript_configure_embedded_heimdal | 11 +++++++++++ + wscript_configure_system_heimdal | 11 ----------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/wscript_configure_embedded_heimdal b/wscript_configure_embedded_heimdal +index 8c55ae2..4fdae80 100644 +--- a/wscript_configure_embedded_heimdal ++++ b/wscript_configure_embedded_heimdal +@@ -1 +1,12 @@ + conf.RECURSE('source4/heimdal_build') ++ ++def check_system_heimdal_binary(name): ++ if conf.LIB_MAY_BE_BUNDLED(name): ++ return False ++ if not conf.find_program(name, var=name.upper()): ++ return False ++ conf.define('USING_SYSTEM_%s' % name.upper(), 1) ++ return True ++ ++check_system_heimdal_binary("compile_et") ++check_system_heimdal_binary("asn1_compile") +diff --git a/wscript_configure_system_heimdal b/wscript_configure_system_heimdal +index 235fa19..4f4a83cd 100644 +--- a/wscript_configure_system_heimdal ++++ b/wscript_configure_system_heimdal +@@ -37,14 +37,6 @@ def check_system_heimdal_lib(name, functions='', headers='', onlyif=None): + conf.define('USING_SYSTEM_%s' % name.upper(), 1) + return True + +-def check_system_heimdal_binary(name): +- if conf.LIB_MAY_BE_BUNDLED(name): +- return False +- if not conf.find_program(name, var=name.upper()): +- return False +- conf.define('USING_SYSTEM_%s' % name.upper(), 1) +- return True +- + check_system_heimdal_lib("com_err", "com_right_r com_err", "com_err.h") + + if check_system_heimdal_lib("roken", "rk_socket_set_reuseaddr", "roken.h"): +@@ -96,7 +88,4 @@ finally: + #if conf.CHECK_BUNDLED_SYSTEM('tommath', checkfunctions='mp_init', headers='tommath.h'): + # conf.define('USING_SYSTEM_TOMMATH', 1) + +-check_system_heimdal_binary("compile_et") +-check_system_heimdal_binary("asn1_compile") +- + conf.define('USING_SYSTEM_KRB5', 1) +-- +2.20.1 + diff --git a/packages/network/samba/patches/samba-950-no-man.patch b/packages/network/samba/patches/samba-950-no-man.patch new file mode 100644 index 000000000..79f0c560c --- /dev/null +++ b/packages/network/samba/patches/samba-950-no-man.patch @@ -0,0 +1,39 @@ +From 0cb025d911dd3e2f9a9184293f571214192e3a54 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Tue, 19 Mar 2019 12:39:41 +0000 +Subject: [PATCH] disable man pages + +--- + buildtools/wafsamba/wafsamba.py | 8 -------- + docs-xml/wscript_build | 22 ---------------------- + 2 files changed, 30 deletions(-) + +diff --git a/buildtools/wafsamba/wafsamba.py b/buildtools/wafsamba/wafsamba.py +index a077026..2a897d0 100644 +--- a/buildtools/wafsamba/wafsamba.py ++++ b/buildtools/wafsamba/wafsamba.py +@@ -328,11 +328,6 @@ def SAMBA_LIBRARY(bld, libname, source, + else: + bld.PKG_CONFIG_FILES(pc_files, vnum=vnum) + +- if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and +- bld.env['XSLTPROC_MANPAGES']): +- bld.MANPAGES(manpages, install) +- +- + Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY + + +@@ -437,9 +432,6 @@ def SAMBA_BINARY(bld, binname, source, + samba_ldflags = pie_ldflags + ) + +- if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']: +- bld.MANPAGES(manpages, install) +- + Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY + + +-- +2.7.4 + diff --git a/packages/network/samba/patches/samba-951-no-man-4.13.patch b/packages/network/samba/patches/samba-951-no-man-4.13.patch new file mode 100644 index 000000000..1db3f9f4c --- /dev/null +++ b/packages/network/samba/patches/samba-951-no-man-4.13.patch @@ -0,0 +1,32 @@ +diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build +--- a/docs-xml/wscript_build 2020-12-05 09:01:19.652459634 +0000 ++++ b/docs-xml/wscript_build 2020-12-05 09:10:10.639446971 +0000 +@@ -153,28 +153,3 @@ + target=parameter_all, + rule=smbdotconf_generate_parameter_list, + dep_vars=bld.dynconfig_varnames()) +- +-def SMBDOTCONF_MANPAGE(bld, target): +- ''' assemble and build smb.conf.5 manual page''' +- bld.SAMBAMANPAGES(target, parameter_all) +- +-if ('XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']): +- +- SMBDOTCONF_MANPAGE(bld, 'manpages/smb.conf.5') +- bld.SAMBAMANPAGES(manpages) +- +- if bld.CONFIG_SET('WITH_PAM_MODULES') and bld.CONFIG_SET('HAVE_PAM_START'): +- bld.SAMBAMANPAGES(pam_winbind_manpages) +- +- if bld.CONFIG_SET('HAVE_KRB5_LOCATE_PLUGIN_H'): +- bld.SAMBAMANPAGES(krb5_locator_manpages) +- +- if bld.CONFIG_SET('HAVE_KRB5_LOCALAUTH_PLUGIN_H'): +- bld.SAMBAMANPAGES(krb5_localauth_manpages) +- +- if conf.env.build_winexe == True: +- bld.SAMBAMANPAGES(winexe_manpages) +- +- for manpage in vfs_module_manpages: +- if bld.SAMBA3_IS_ENABLED_MODULE(manpage): +- bld.SAMBAMANPAGES('manpages/%s.8' % manpage) diff --git a/packages/network/samba/scripts/samba-autoshare b/packages/network/samba/scripts/samba-autoshare new file mode 100755 index 000000000..7112925dd --- /dev/null +++ b/packages/network/samba/scripts/samba-autoshare @@ -0,0 +1,13 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) + +if [ -f /storage/.cache/services/samba.conf ]; then + . /storage/.cache/services/samba.conf + + if [ "$SAMBA_AUTOSHARE" == "true" ] ; then + /usr/lib/samba/samba-config + [ -f /run/samba/smbd.pid ] && pkill -HUP smbd + fi +fi diff --git a/packages/network/samba/scripts/samba-config b/packages/network/samba/scripts/samba-config new file mode 100755 index 000000000..927010695 --- /dev/null +++ b/packages/network/samba/scripts/samba-config @@ -0,0 +1,41 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) + +SMB_USERCONF="/storage/.config/samba.conf" +SMB_DEFCONF="/etc/samba/smb.conf" +SMB_CONF="/run/samba/smb.conf" + +SMB_USERCONF_IS_VALID=no +SMB_CONFIG_VERSION=4 + +# If user config is based on legacy OpenELEC, or old version (or no version) +# then don't use it, and log a warning. +if [ -f $SMB_USERCONF ]; then + SMB_IS_LEGACY="$(awk 'NR <= 2 && /This file is part of OpenELEC/{ print }' $SMB_USERCONF)" + SMB_THIS_VER="$(awk '/^# samba.conf v[0-9\.]*/{ print substr($3,2); exit }' $SMB_USERCONF)" + if [ -n "${SMB_IS_LEGACY}" ]; then + echo "WARNING: Ignoring user config $SMB_USERCONF due to incompatibility [Old style OpenELEC]" + elif [ -z "${SMB_THIS_VER}" ]; then + echo "WARNING: Ignoring user config $SMB_USERCONF due to incompatibility [version is unknown or invalid]" + elif [ ${SMB_THIS_VER} != ${SMB_CONFIG_VERSION} ]; then + echo "WARNING: Ignoring user config $SMB_USERCONF due to incompatibility [version ${SMB_THIS_VER} is not the required version $SMB_CONFIG_VERSION]" + else + SMB_USERCONF_IS_VALID=yes + fi +fi + +mkdir -p $(dirname $SMB_CONF) + if [ $SMB_USERCONF_IS_VALID = yes ]; then + cp $SMB_USERCONF $SMB_CONF + else + cp $SMB_DEFCONF $SMB_CONF + fi + +# Generate smb.conf, unless disabled +if [ ! -f /storage/.cache/services/samba.disabled ]; then + /usr/lib/samba/smbd-config +fi + +exit 0 diff --git a/packages/network/samba/scripts/smbd-config b/packages/network/samba/scripts/smbd-config new file mode 100755 index 000000000..aed4730a3 --- /dev/null +++ b/packages/network/samba/scripts/smbd-config @@ -0,0 +1,77 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +SMB_CONF="/run/samba/smb.conf" +SMB_TMP="$(mktemp -p /run/samba)" + +cp -f $SMB_CONF $SMB_TMP + +if [ ! -f /storage/.cache/services/samba.conf ]; then + cp /usr/share/services/samba.conf /storage/.cache/services +fi + +# Specify defaults here, in case these new properties not yet added in .cache +SAMBA_WORKGROUP=WORKGROUP +SAMBA_MINPROTOCOL=SMB2 +SAMBA_MAXPROTOCOL=SMB3 + +. /storage/.cache/services/samba.conf + +# fixup synonyms +sed -i 's/browsable/browseable/g; s/writable/writeable/g' $SMB_TMP + +# handle external drives +if [ "$SAMBA_AUTOSHARE" == "true" ] ; then + for dir in /media/* ; do + if [ -d "$dir" ] ; then + name=$(basename "$dir") + echo -e "[$name]\n path = $dir\n available = yes\n browseable = yes\n public = yes\n writeable = yes\n" >> $SMB_TMP + fi + done +fi + +# Allow access to a "failed" (safe mode) Kodi installation +if [ -d /storage/.kodi.FAILED ]; then + echo -e "[Kodi-Failed]\n path = /storage/.kodi.FAILED\n available = yes\n browseable = yes\n public = yes\n writeable = yes\n" >> $SMB_TMP +fi + +ADD_CONFIG= + +# If workgroup is not set, don't set it - who knows, user may know better. +if [ -n "$SAMBA_WORKGROUP" ]; then + # Remove any existing workgroup setting + sed -E '/^[[:space:]]*workgroup[[:space:]]*=/d' -i $SMB_TMP + ADD_CONFIG="${ADD_CONFIG} workgroup = ${SAMBA_WORKGROUP:-WORKGROUP}\n" +fi + +ADD_CONFIG="${ADD_CONFIG} server min protocol = ${SAMBA_MINPROTOCOL/SMB1/NT1}\n" +ADD_CONFIG="${ADD_CONFIG} server max protocol = ${SAMBA_MAXPROTOCOL/SMB1/NT1}\n" + +# Add extra config after [global], escaping spaces so that all are retained by sed +sed -e "/\[global\]/ a ${ADD_CONFIG// /\\ }" -i $SMB_TMP + +if [ "$SAMBA_SECURE" == "true" -a ! "$SAMBA_USERNAME" == "" -a ! "$SAMBA_PASSWORD" == "" ] ; then + # username map: first line makes sure plain root does not work all the time + # processing continues, so if user chooses root as username, second line overrides the first + # this is done always in case user uses passwords in userconf. + # many thanks to viljoviitanen for this + printf "%s\n%s" "$SAMBA_PASSWORD" "$SAMBA_PASSWORD" | smbpasswd -s -a root >/dev/null 2>&1 + printf "nobody = root\nroot = %s" "$SAMBA_USERNAME" > /run/samba/samba.map + + sed -e 's|^.[ \t]*.public.=.*| public = no |' \ + -e 's|^.[ \t]*.username map.=.*||' \ + -e 's|^.[ \t]*.security.=.*| security = user\n username map = /run/samba/samba.map|' \ + -e 's|^.[ \t]*.map.to.guest.=.*| map to guest = Never|' \ + -i $SMB_TMP +else + sed -e 's|^.[ \t]*.public.=.*| public = yes |' \ + -e 's|^.[ \t]*.username map.=.*||' \ + -e 's|^.[ \t]*.security.=.*| security = user|' \ + -e 's|^.[ \t]*.map.to.guest.=.*| map to guest = Bad User|' \ + -i $SMB_TMP +fi + +mv -f $SMB_TMP $SMB_CONF diff --git a/packages/network/samba/system.d.opt/nmbd.service b/packages/network/samba/system.d.opt/nmbd.service new file mode 100644 index 000000000..a2dc1b35a --- /dev/null +++ b/packages/network/samba/system.d.opt/nmbd.service @@ -0,0 +1,19 @@ +[Unit] +Description=Samba NMB Daemon +Wants=network-online.target samba-config.service +After=network-online.target samba-config.service +ConditionPathExists=!/storage/.cache/services/samba.disabled +ConditionPathExists=/run/samba/smb.conf + +[Service] +Type=forking +PIDFile=/run/samba/nmbd.pid +ExecStart=/usr/sbin/nmbd +ExecReload=/bin/kill -HUP $MAINPID +TimeoutStopSec=1s +Restart=always +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/samba/system.d.opt/smbd.service b/packages/network/samba/system.d.opt/smbd.service new file mode 100644 index 000000000..4353fa266 --- /dev/null +++ b/packages/network/samba/system.d.opt/smbd.service @@ -0,0 +1,20 @@ +[Unit] +Description=Samba SMB Daemon +Wants=network-online.target nmbd.service +After=network-online.target nmbd.service +ConditionPathExists=!/storage/.cache/services/samba.disabled +ConditionPathExists=/run/samba/smb.conf + +[Service] +Type=forking +PIDFile=/run/samba/smbd.pid +LimitNOFILE=16384 +ExecStart=/usr/sbin/smbd +ExecReload=/bin/kill -HUP $MAINPID +TimeoutStopSec=1s +Restart=always +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/samba/system.d/samba-config.service b/packages/network/samba/system.d/samba-config.service new file mode 100644 index 000000000..fe02a9697 --- /dev/null +++ b/packages/network/samba/system.d/samba-config.service @@ -0,0 +1,10 @@ +[Unit] +Description=Samba Configuration +DefaultDependencies=false +After=basic.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/samba/samba-config +StartLimitInterval=0 diff --git a/packages/network/wireguard-linux-compat/modules-load.d/wireguard.conf b/packages/network/wireguard-linux-compat/modules-load.d/wireguard.conf new file mode 100644 index 000000000..a82c63a20 --- /dev/null +++ b/packages/network/wireguard-linux-compat/modules-load.d/wireguard.conf @@ -0,0 +1 @@ +wireguard diff --git a/packages/network/wireguard-linux-compat/package.mk b/packages/network/wireguard-linux-compat/package.mk new file mode 100644 index 000000000..8dc4e8e52 --- /dev/null +++ b/packages/network/wireguard-linux-compat/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireguard-linux-compat" +PKG_VERSION="v1.0.20200611" +PKG_SHA256="0a15a6b9798d4df660093eca3e9cc8a9058b3a50130111182348a238e82911be" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.wireguard.com" +PKG_URL="https://git.zx2c4.com/wireguard-linux-compat/snapshot/wireguard-linux-compat-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux libmnl" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="WireGuard VPN kernel module" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make KERNELDIR=$(kernel_path) -C src/ module +} + +makeinstall_target() { + mkdir -p $INSTALL/$(get_full_module_dir)/$PKG_NAME + cp src/*.ko $INSTALL/$(get_full_module_dir)/$PKG_NAME +} diff --git a/packages/network/wireguard-tools/config/system.d/wireguard.service.sample b/packages/network/wireguard-tools/config/system.d/wireguard.service.sample new file mode 100644 index 000000000..5f7145e49 --- /dev/null +++ b/packages/network/wireguard-tools/config/system.d/wireguard.service.sample @@ -0,0 +1,13 @@ +[Unit] +Description=WireGuard VPN Service +After=network-online.target nss-lookup.target connman-vpn.service time-sync.target +Wants=network-online.target nss-lookup.target connman-vpn.service time-sync.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/connmanctl connect vpn_service_name_goes_here +ExecStop=/usr/bin/connmanctl disconnect vpn_service_name_goes_here + +[Install] +WantedBy=multi-user.target diff --git a/packages/network/wireguard-tools/config/wireguard/wireguard.config.sample b/packages/network/wireguard-tools/config/wireguard/wireguard.config.sample new file mode 100644 index 000000000..9ff945349 --- /dev/null +++ b/packages/network/wireguard-tools/config/wireguard/wireguard.config.sample @@ -0,0 +1,14 @@ +[provider_wireguard] +Type = WireGuard +Name = WireGuard VPN Tunnel +Host = 3.2.5.6 +Domain = my.home.network +WireGuard.Address = 10.2.0.2/24 +WireGuard.ListenPort = 51820 +WireGuard.PrivateKey = qKIj010hDdWSjQQyVCnEgthLXusBgm3I6HWrJUaJymc= +WireGuard.PublicKey = zzqUfWGIil6QxrAGz77HE5BGUEdD2PgHYnCg3CDKagE= +WireGuard.PresharedKey = DfEYeVs04HS9XhKGM4/ZXHG3Qc4MFK2AJd8XouYDbRQ= +WireGuard.DNS = 8.8.8.8, 1.1.1.1 +WireGuard.AllowedIPs = 0.0.0.0/0 +WireGuard.EndpointPort = 51820 +WireGuard.PersistentKeepalive = 25 diff --git a/packages/network/wireguard-tools/package.mk b/packages/network/wireguard-tools/package.mk new file mode 100644 index 000000000..80bab4a6b --- /dev/null +++ b/packages/network/wireguard-tools/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireguard-tools" +PKG_VERSION="v1.0.20200513" +PKG_SHA256="4effe7e9c79b70d6ff17a78bdf4e16fb02d4e6711f85beeaea80db5b11435fdb" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.wireguard.com" +PKG_URL="https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux libmnl" +PKG_NEED_UNPACK="$LINUX_DEPENDS" +PKG_LONGDESC="WireGuard VPN userspace tools" +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +pre_make_target() { + unset LDFLAGS +} + +make_target() { + kernel_make KERNELDIR=$(kernel_path) -C src/ wg +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/wg-keygen $INSTALL/usr/bin + cp $PKG_BUILD/src/wg $INSTALL/usr/bin + + mkdir -p $INSTALL/usr + cp -R $PKG_DIR/config $INSTALL/usr +} diff --git a/packages/network/wireguard-tools/scripts/wg-keygen b/packages/network/wireguard-tools/scripts/wg-keygen new file mode 100755 index 000000000..342e3add0 --- /dev/null +++ b/packages/network/wireguard-tools/scripts/wg-keygen @@ -0,0 +1,25 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +if [ -x /usr/bin/wg ]; then + + umask 077 + mkdir -p /storage/.cache/wireguard + + if [ ! -f /storage/.cache/wireguard/privatekey ]; then + wg genkey > /storage/.cache/wireguard/privatekey + fi + if [ ! -f /storage/.cache/wireguard/publickey ]; then + wg pubkey < /storage/.cache/wireguard/privatekey > /storage/.cache/wireguard/publickey + fi + if [ ! -f /storage/.cache/wireguard/preshared ]; then + wg genpsk > /storage/.cache/wireguard/preshared + fi + +fi + +echo "WireGuard keys have been saved to /storage/.cache/wireguard/" + +exit 0 diff --git a/packages/network/wireguard-tools/tmpfiles.d/z_03_wireguard.conf b/packages/network/wireguard-tools/tmpfiles.d/z_03_wireguard.conf new file mode 100644 index 000000000..655751767 --- /dev/null +++ b/packages/network/wireguard-tools/tmpfiles.d/z_03_wireguard.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +d /storage/.cache/wireguard 0755 root root - - diff --git a/packages/network/wireless-regdb/package.mk b/packages/network/wireless-regdb/package.mk new file mode 100644 index 000000000..5e9dd1da3 --- /dev/null +++ b/packages/network/wireless-regdb/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wireless-regdb" +PKG_VERSION="2019.06.03" +PKG_SHA256="cd917ed86b63ce8d93947979f1f18948f03a4ac0ad89ec25227b36ac00dc54bf" +PKG_LICENSE="GPL" +PKG_SITE="http://wireless.kernel.org/en/developers/Regulatory" +PKG_URL="https://www.kernel.org/pub/software/network/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_LONGDESC="wireless-regdb is a regulatory database" +PKG_TOOLCHAIN="manual" diff --git a/packages/network/wpa_supplicant/config/makefile.config b/packages/network/wpa_supplicant/config/makefile.config new file mode 100644 index 000000000..5c9843396 --- /dev/null +++ b/packages/network/wpa_supplicant/config/makefile.config @@ -0,0 +1,35 @@ +CONFIG_CTRL_IFACE=y +CONFIG_CTRL_IFACE_DBUS=y +CONFIG_CTRL_IFACE_DBUS_NEW=y +CONFIG_CTRL_IFACE_DBUS_INTRO=y +CONFIG_DRIVER_WEXT=y +CONFIG_LIBNL32=y +CONFIG_DRIVER_NL80211=y +CONFIG_DRIVER_WIRED=y +CONFIG_IEEE8021X_EAPOL=y +CONFIG_EAP_MD5=y +CONFIG_EAP_MSCHAPV2=y +CONFIG_EAP_TLS=y +CONFIG_EAP_PEAP=y +CONFIG_EAP_TTLS=y +CONFIG_EAP_PSK=y +CONFIG_EAP_FAST=y +CONFIG_EAP_GTC=y +CONFIG_EAP_OTP=y +CONFIG_EAP_AKA=y +CONFIG_EAP_PAX=y +CONFIG_EAP_LEAP=y +CONFIG_EAP_SAKE=y +CONFIG_EAP_GPSK=y +CONFIG_EAP_GPSK_SHA256=y +CONFIG_EAP_TNC=y +CONFIG_WPS=y +CONFIG_EAP_IKEV2=y +CONFIG_PKCS12=y +CONFIG_SMARTCARD=y +CONFIG_DEBUG_FILE=y +CONFIG_BACKEND=file +CONFIG_PEERKEY=y +CONFIG_BGSCAN_SIMPLE=y +CONFIG_AP=y +#CONFIG_FIPS=y \ No newline at end of file diff --git a/packages/network/wpa_supplicant/package.mk b/packages/network/wpa_supplicant/package.mk new file mode 100644 index 000000000..09bdbd4b3 --- /dev/null +++ b/packages/network/wpa_supplicant/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wpa_supplicant" +PKG_VERSION="2.9" +PKG_SHA256="fcbdee7b4a64bea8177973299c8c824419c413ec2e3a95db63dd6a5dc3541f17" +PKG_LICENSE="GPL" +PKG_SITE="https://w1.fi/wpa_supplicant/" +PKG_URL="https://w1.fi/releases/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain dbus libnl openssl" +PKG_LONGDESC="A free software implementation of an IEEE 802.11i supplicant." +PKG_TOOLCHAIN="make" +PKG_BUILD_FLAGS="+lto-parallel" + +PKG_MAKE_OPTS_TARGET="-C wpa_supplicant V=1 LIBDIR=/usr/lib BINDIR=/usr/bin" +PKG_MAKEINSTALL_OPTS_TARGET="-C wpa_supplicant V=1 LIBDIR=/usr/lib BINDIR=/usr/bin" + +configure_target() { + LDFLAGS="$LDFLAGS -lpthread -lm" + + cp $PKG_DIR/config/makefile.config wpa_supplicant/.config +} + +post_makeinstall_target() { + rm -r $INSTALL/usr/bin/wpa_cli + + mkdir -p $INSTALL/etc/dbus-1/system.d + cp wpa_supplicant/dbus/dbus-wpa_supplicant.conf $INSTALL/etc/dbus-1/system.d + + mkdir -p $INSTALL/usr/lib/systemd/system + cp wpa_supplicant/systemd/wpa_supplicant.service $INSTALL/usr/lib/systemd/system + + mkdir -p $INSTALL/usr/share/dbus-1/system-services + cp wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service $INSTALL/usr/share/dbus-1/system-services +} diff --git a/packages/network/wpa_supplicant/patches/wpa_supplicant-2.4-libnl3-includes.patch b/packages/network/wpa_supplicant/patches/wpa_supplicant-2.4-libnl3-includes.patch new file mode 100644 index 000000000..f3dce5172 --- /dev/null +++ b/packages/network/wpa_supplicant/patches/wpa_supplicant-2.4-libnl3-includes.patch @@ -0,0 +1,12 @@ +diff -Naur wpa_supplicant-2.4/src/drivers/drivers.mk wpa_supplicant-2.4.patch/src/drivers/drivers.mk +--- wpa_supplicant-2.4/src/drivers/drivers.mk 2015-03-15 18:30:39.000000000 +0100 ++++ wpa_supplicant-2.4.patch/src/drivers/drivers.mk 2015-03-17 13:16:01.390789977 +0100 +@@ -35,7 +35,7 @@ + ifdef CONFIG_LIBNL32 + DRV_LIBS += -lnl-3 + DRV_LIBS += -lnl-genl-3 +- DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3 ++ DRV_CFLAGS += -DCONFIG_LIBNL20 `pkg-config --cflags libnl-3.0` + ifdef CONFIG_LIBNL3_ROUTE + DRV_LIBS += -lnl-route-3 + DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE diff --git a/packages/oem/package.mk b/packages/oem/package.mk new file mode 100644 index 000000000..42e98d4e6 --- /dev/null +++ b/packages/oem/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="oem" +PKG_VERSION="" +PKG_LICENSE="various" +PKG_SITE="http://www.libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain $PROJECT" +PKG_SECTION="virtual" +PKG_LONGDESC="OEM: Metapackage for various OEM packages" diff --git a/packages/print/freetype/package.mk b/packages/print/freetype/package.mk new file mode 100644 index 000000000..a155d9800 --- /dev/null +++ b/packages/print/freetype/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="freetype" +PKG_VERSION="2.11.0" +PKG_SHA256="8bee39bd3968c4804b70614a0a3ad597299ad0e824bc8aad5ce8aaf48067bde7" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freetype.org" +PKG_URL="http://download.savannah.gnu.org/releases/freetype/freetype-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain zlib libpng" +PKG_LONGDESC="The FreeType engine is a free and portable TrueType font rendering engine." +PKG_TOOLCHAIN="configure" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="LIBPNG_CFLAGS=-I${SYSROOT_PREFIX}/usr/include \ + LIBPNG_LDFLAGS=-L${SYSROOT_PREFIX}/usr/lib \ + --with-zlib" + +#pre_configure_target() { +# # unset LIBTOOL because freetype uses its own +# ( cd .. +# unset LIBTOOL +# sh autogen.sh +# ) +#} + +post_makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/bin + sed -e "s#prefix=/usr#prefix=${SYSROOT_PREFIX}/usr#" -i "${SYSROOT_PREFIX}/usr/lib/pkgconfig/freetype2.pc" + cp -P "freetype-config" "${SYSROOT_PREFIX}/usr/bin" +} diff --git a/packages/print/poppler/package.mk b/packages/print/poppler/package.mk new file mode 100644 index 000000000..d3503958e --- /dev/null +++ b/packages/print/poppler/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="poppler" +PKG_VERSION="5d3e71c8215997a96d2ade7272217087f7e59fe2" +PKG_SHA256="01575e4c1510c657839e742cfeabdcbd8d99dd9e9cc3dff74748643a3e7ab7d9" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/freedesktop/poppler" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib libpng libjpeg-turbo fontconfig boost" +PKG_LONGDESC="This is Poppler, a library for rendering PDF files, and examining or modifying their structure." +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DENABLE_LIBOPENJPEG=none" + +#pre_configure_target() { +#} + +#post_makeinstall_target() { +# rm -rf $INSTALL/usr/bin +#} diff --git a/packages/python/devel/Mako/package.mk b/packages/python/devel/Mako/package.mk new file mode 100644 index 000000000..7a0f39752 --- /dev/null +++ b/packages/python/devel/Mako/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="Mako" +PKG_VERSION="1.1.3" +PKG_SHA256="8195c8c1400ceb53496064314c6736719c6f25e7479cd24c77be3d9361cddc27" +PKG_LICENSE="GPL" +PKG_SITE="https://pypi.org/project/Mako" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python3:host setuptools:host MarkupSafe:host" +PKG_LONGDESC="Mako is a super-fast templating language that borrows the best ideas from the existing templating languages." +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=${TOOLCHAIN} +} diff --git a/packages/python/devel/MarkupSafe/package.mk b/packages/python/devel/MarkupSafe/package.mk new file mode 100644 index 000000000..c3b7c6c57 --- /dev/null +++ b/packages/python/devel/MarkupSafe/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="MarkupSafe" +PKG_VERSION="1.1.1" +PKG_SHA256="29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b" +PKG_LICENSE="GPL" +PKG_SITE="https://pypi.org/project/MarkupSafe/" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python3:host setuptools:host" +PKG_LONGDESC="MarkupSafe implements a XML/HTML/XHTML Markup safe string for Python" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=${TOOLCHAIN} +} diff --git a/packages/python/devel/distutilscross/package.mk b/packages/python/devel/distutilscross/package.mk new file mode 100644 index 000000000..9d480e0e3 --- /dev/null +++ b/packages/python/devel/distutilscross/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="distutilscross" +PKG_VERSION="0.1" +PKG_SHA256="4ed3fb427708c8a3ed5fe9c599532480f581078a1e0aec0e50f40eb58e9f0015" +PKG_LICENSE="GPL" +PKG_SITE="http://bitbucket.org/lambacck/distutilscross/" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="Python3:host setuptools:host" +PKG_LONGDESC="distutilscross enhances distutils to support Cross Compile of Python extensions" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=$TOOLCHAIN +} diff --git a/packages/python/devel/distutilscross/patches/distutilscross-0000-fix-python3.patch b/packages/python/devel/distutilscross/patches/distutilscross-0000-fix-python3.patch new file mode 100644 index 000000000..0afb41733 --- /dev/null +++ b/packages/python/devel/distutilscross/patches/distutilscross-0000-fix-python3.patch @@ -0,0 +1,57 @@ +diff --git a/distutilscross/crosscompile.py b/distutilscross/crosscompile.py +index 31dfd6c..16b683e 100644 +--- a/distutilscross/crosscompile.py ++++ b/distutilscross/crosscompile.py +@@ -13,7 +13,7 @@ class build(_build): + self.cross_compile = 0 + + def finalize_options(self): +- if self.cross_compile and os.environ.has_key('PYTHONXCPREFIX'): ++ if self.cross_compile and 'PYTHONXCPREFIX' in os.environ: + prefix = os.environ['PYTHONXCPREFIX'] + sysconfig.get_python_lib = get_python_lib + sysconfig.PREFIX = prefix +@@ -31,8 +31,8 @@ class build(_build): + + _get_python_lib = sysconfig.get_python_lib + def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): +- if os.environ.has_key('PYTHONXCPREFIX'): +- print "Setting prefix" ++ if 'PYTHONXCPREFIX' in os.environ: ++ print("Setting prefix") + prefix = os.environ['PYTHONXCPREFIX'] + + return _get_python_lib(plat_specific, standard_lib, prefix) +@@ -50,24 +50,24 @@ def customize_compiler(compiler): + sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', + 'CCSHARED', 'LDSHARED', 'SO') + +- if os.environ.has_key('CC'): ++ if 'CC' in os.environ: + cc = os.environ['CC'] +- if os.environ.has_key('CXX'): ++ if 'CXX' in os.environ: + cxx = os.environ['CXX'] +- if os.environ.has_key('LDSHARED'): ++ if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] +- if os.environ.has_key('CPP'): ++ if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always +- if os.environ.has_key('LDFLAGS'): ++ if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] +- if os.environ.has_key('OPT'): ++ if 'OPT' in os.environ: + opt = os.environ['OPT'] +- if os.environ.has_key('CFLAGS'): ++ if 'CFLAGS' in os.environ: + cflags = opt + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] +- if os.environ.has_key('CPPFLAGS'): ++ if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] diff --git a/packages/python/devel/meson/package.mk b/packages/python/devel/meson/package.mk new file mode 100644 index 000000000..d5c3ce822 --- /dev/null +++ b/packages/python/devel/meson/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="meson" +PKG_VERSION="0.56.2" +PKG_SHA256="3cb8bdb91383f7f8da642f916e4c44066a29262caa499341e2880f010edb87f4" +PKG_LICENSE="Apache" +PKG_SITE="http://mesonbuild.com" +PKG_URL="https://github.com/mesonbuild/meson/releases/download/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="Python3:host setuptools:host pathlib:host" +PKG_LONGDESC="High productivity build system" +PKG_TOOLCHAIN="manual" + +make_host() { + python3 setup.py build +} + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=$TOOLCHAIN --skip-build + + # Avoid using full path to python3 that may exceed 128 byte limit. + # Instead use PATH as we know our toolchain is first. + sed -e '1 s/^#!.*$/#!\/usr\/bin\/env python3/' -i $TOOLCHAIN/bin/meson +} diff --git a/packages/python/devel/ninja/package.mk b/packages/python/devel/ninja/package.mk new file mode 100644 index 000000000..15dfd11e8 --- /dev/null +++ b/packages/python/devel/ninja/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ninja" +PKG_VERSION="1.10.2" +PKG_SHA256="ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed" +PKG_LICENSE="Apache" +PKG_SITE="https://ninja-build.org/" +PKG_URL="https://github.com/ninja-build/ninja/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python3:host" +PKG_LONGDESC="Small build system with a focus on speed" +PKG_TOOLCHAIN="cmake-make" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp ninja ${TOOLCHAIN}/bin +} diff --git a/packages/python/devel/pathlib/package.mk b/packages/python/devel/pathlib/package.mk new file mode 100644 index 000000000..6126e25be --- /dev/null +++ b/packages/python/devel/pathlib/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pathlib" +PKG_VERSION="1.0.1" +PKG_SHA256="6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f" +PKG_LICENSE="MIT" +PKG_SITE="http://pathlib.readthedocs.org" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python3:host" +PKG_LONGDESC="This module offers a set of classes featuring all the common operations on paths in an easy, object-oriented way" +PKG_TOOLCHAIN="manual" + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=${TOOLCHAIN} +} diff --git a/packages/python/devel/pygobject/package.mk b/packages/python/devel/pygobject/package.mk new file mode 100644 index 000000000..77003aa11 --- /dev/null +++ b/packages/python/devel/pygobject/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pygobject" +PKG_VERSION="2.28.7" +PKG_SHA256="bb9d25a3442ca7511385a7c01b057492095c263784ef31231ffe589d83a96a5a" +PKG_LICENSE="LGPL" +PKG_SITE="http://www.pygtk.org/" +PKG_URL="http://ftp.gnome.org/pub/GNOME/sources/pygobject/$(get_pkg_version_maj_min)/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain Python2 glib libffi" +PKG_LONGDESC="A convenient wrapper for the GObject+ library for use in Python programs." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-thread --disable-introspection" + +pre_configure_target() { + export PYTHON_INCLUDES="$(${SYSROOT_PREFIX}/usr/bin/python2-config --includes)" +} + +post_makeinstall_target() { + python_remove_source + + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/share/pygobject +} diff --git a/packages/python/devel/pygobject/patches/pygobject-0001-add-PYTHON_INCLUDES-override.patch b/packages/python/devel/pygobject/patches/pygobject-0001-add-PYTHON_INCLUDES-override.patch new file mode 100644 index 000000000..d883f60dd --- /dev/null +++ b/packages/python/devel/pygobject/patches/pygobject-0001-add-PYTHON_INCLUDES-override.patch @@ -0,0 +1,32 @@ +[PATCH] m4/python.m4: add PYTHON_INCLUDES override for cross compilation + +As the configure script mixes up host/target python. Equivalent to the +similar code in dbus-python. + +Signed-off-by: Peter Korsgaard +--- + m4/python.m4 | 4 ++++ + 1 file changed, 4 insertions(+) + +Index: python-gobject-2.28.6/m4/python.m4 +=================================================================== +--- python-gobject-2.28.6.orig/m4/python.m4 ++++ python-gobject-2.28.6/m4/python.m4 +@@ -43,6 +43,9 @@ + [AC_REQUIRE([AM_PATH_PYTHON]) + AC_MSG_CHECKING(for headers required to compile python extensions) + dnl deduce PYTHON_INCLUDES ++if test "${PYTHON_INCLUDES+set}" = set; then ++ AC_MSG_NOTICE([PYTHON_INCLUDES overridden to: $PYTHON_INCLUDES]) ++else + py_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.prefix)"` + py_exec_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)"` + PYTHON_CONFIG=`which $PYTHON`-config +@@ -54,6 +57,7 @@ + PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" + fi + fi ++fi + AC_SUBST(PYTHON_INCLUDES) + dnl check if the headers exist: + save_CPPFLAGS="$CPPFLAGS" diff --git a/packages/python/devel/pygobject/patches/pygobject-2.28.6-automake-1.13.patch b/packages/python/devel/pygobject/patches/pygobject-2.28.6-automake-1.13.patch new file mode 100644 index 000000000..5eb12e66e --- /dev/null +++ b/packages/python/devel/pygobject/patches/pygobject-2.28.6-automake-1.13.patch @@ -0,0 +1,20 @@ +diff -Naur pygobject-2.28.6/configure.ac pygobject-2.28.6.patch/configure.ac +--- pygobject-2.28.6/configure.ac 2011-06-13 18:33:56.000000000 +0200 ++++ pygobject-2.28.6.patch/configure.ac 2013-01-12 01:03:44.085557166 +0100 +@@ -35,7 +35,7 @@ + AC_DEFINE(PYGOBJECT_MICRO_VERSION, pygobject_micro_version, [pygobject micro version]) + AC_SUBST(PYGOBJECT_MICRO_VERSION, pygobject_micro_version) + +-AM_CONFIG_HEADER(config.h) ++AC_CONFIG_HEADERS(config.h) + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)]) + AM_INIT_AUTOMAKE(foreign) + AM_MAINTAINER_MODE +@@ -82,7 +82,6 @@ + m4_ifdef([LT_OUTPUT], [LT_OUTPUT]) + AC_ISC_POSIX + AC_PROG_CC +-AM_PROG_CC_STDC + AM_PROG_CC_C_O + + # check that we have the minimum version of python necisary to build diff --git a/packages/python/devel/setuptools/package.mk b/packages/python/devel/setuptools/package.mk new file mode 100644 index 000000000..d8ee636c2 --- /dev/null +++ b/packages/python/devel/setuptools/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="setuptools" +PKG_VERSION="39.2.0" +PKG_SHA256="ca8119dd5c2764a7d290518817de0b880d23d790913fcd797c02ad2aa39b8c41" +PKG_LICENSE="OSS" +PKG_SITE="https://pypi.org/project/setuptools" +PKG_URL="https://github.com/pypa/setuptools/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="Python2:host" +PKG_LONGDESC="Replaces Setuptools as the standard method for working with Python module distributions." +PKG_TOOLCHAIN="manual" + +make_host() { + python2 bootstrap.py +} + +makeinstall_host() { + exec_thread_safe python3 setup.py install --prefix=${TOOLCHAIN} +} diff --git a/packages/python/devel/waf/package.mk b/packages/python/devel/waf/package.mk new file mode 100644 index 000000000..5c1d056b4 --- /dev/null +++ b/packages/python/devel/waf/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="waf" +PKG_VERSION="2.0.21" +PKG_SHA256="7cebf2c5efe53cbb9a4b5bdc4b49ae90ecd64a8fce7a3222d58e591b58215306" +PKG_LICENSE="MIT" +PKG_SITE="https://waf.io" +PKG_URL="https://waf.io/${PKG_NAME}-${PKG_VERSION}" +PKG_LONGDESC="The Waf build system" +PKG_TOOLCHAIN="manual" + +unpack() { + mkdir -p ${PKG_BUILD} + cp ${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME} ${PKG_BUILD}/waf + chmod a+x ${PKG_BUILD}/waf +} + +makeinstall_host() { + cp -pf waf ${TOOLCHAIN}/bin/ +} diff --git a/packages/python/graphics/Pillow/package.mk b/packages/python/graphics/Pillow/package.mk new file mode 100644 index 000000000..72f9f4dcd --- /dev/null +++ b/packages/python/graphics/Pillow/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="Pillow" +PKG_VERSION="8.1.0" +PKG_SHA256="b670476feb912d1f07b8f42815ebef13a039cccfd549b2dac84d2a1599f68af8" +PKG_LICENSE="BSD" +PKG_SITE="https://python-pillow.org/" +PKG_URL="https://github.com/python-pillow/${PKG_NAME}/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 distutilscross:host zlib freetype libjpeg-turbo tiff" +PKG_LONGDESC="The Python Imaging Library adds image processing capabilities to your Python interpreter." +PKG_TOOLCHAIN="manual" + +pre_make_target() { + export PYTHONXCPREFIX="${SYSROOT_PREFIX}/usr" + export LDSHARED="${CC} -shared" +} + +make_target() { + python3 setup.py build --cross-compile +} + +makeinstall_target() { + python3 setup.py install --root=${INSTALL} --prefix=/usr +} + +post_makeinstall_target() { + python_remove_source + + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/python/graphics/Pillow/patches/Pillow-0001-crosscompiling.patch b/packages/python/graphics/Pillow/patches/Pillow-0001-crosscompiling.patch new file mode 100644 index 000000000..ab662d7b2 --- /dev/null +++ b/packages/python/graphics/Pillow/patches/Pillow-0001-crosscompiling.patch @@ -0,0 +1,13 @@ +diff --git a/setup.py b/setup.py +index 8eb0b3c..277e44a 100755 +--- a/setup.py ++++ b/setup.py +@@ -253,7 +253,7 @@ class pil_build_ext(build_ext): + ] + [('add-imaging-libs=', None, 'Add libs to _imaging build')] + + def initialize_options(self): +- self.disable_platform_guessing = None ++ self.disable_platform_guessing = True + self.add_imaging_libs = "" + build_ext.initialize_options(self) + for x in self.feature: diff --git a/packages/python/security/pycryptodome/package.mk b/packages/python/security/pycryptodome/package.mk new file mode 100644 index 000000000..323287a02 --- /dev/null +++ b/packages/python/security/pycryptodome/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pycryptodome" +PKG_VERSION="3.9.9" +PKG_SHA256="abb476e10b4266472d709697a9ec96eb4bdcaaa8708badcfec64daadbacbcef0" +PKG_LICENSE="BSD" +PKG_SITE="https://pypi.org/project/pycryptodome" +PKG_URL="https://github.com/Legrandin/${PKG_NAME}/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 distutilscross:host" +PKG_LONGDESC="PyCryptodome is a self-contained Python package of low-level cryptographic primitives." +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + cd ${PKG_BUILD} + rm -rf .${TARGET_NAME} + + export PYTHONXCPREFIX="${SYSROOT_PREFIX}/usr" + export LDSHARED="${CC} -shared" +} + +make_target() { + python3 setup.py build --cross-compile +} + +makeinstall_target() { + python3 setup.py install --root=${INSTALL} --prefix=/usr + + # Remove SelfTest bloat + find ${INSTALL} -type d -name SelfTest -exec rm -fr "{}" \; 2>/dev/null || true + find ${INSTALL} -name SOURCES.txt -exec sed -i "/\/SelfTest\//d;" "{}" \; + + # Create Cryptodome as an alternative namespace to Crypto (Kodi addons may use either) + ln -sf /usr/lib/${PKG_PYTHON_VERSION}/site-packages/Crypto ${INSTALL}/usr/lib/${PKG_PYTHON_VERSION}/site-packages/Cryptodome +} + +post_makeinstall_target() { + python_remove_source +} diff --git a/packages/python/system/dbus-python/package.mk b/packages/python/system/dbus-python/package.mk new file mode 100644 index 000000000..d352edb25 --- /dev/null +++ b/packages/python/system/dbus-python/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dbus-python" +PKG_VERSION="1.2.16" +PKG_SHA256="11238f1d86c995d8aed2e22f04a1e3779f0d70e587caffeab4857f3c662ed5a4" +PKG_LICENSE="GPL" +PKG_SITE="https://freedesktop.org/wiki/Software/dbus" +PKG_URL="https://dbus.freedesktop.org/releases/dbus-python/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 dbus dbus-glib" +PKG_LONGDESC="D-BUS is a message bus, used for sending messages between applications." +PKG_BUILD_FLAGS="+lto" + +pre_configure_target() { + export PYTHON_CONFIG="${SYSROOT_PREFIX}/usr/bin/python3-config" + export PYTHON_INCLUDES="$(${SYSROOT_PREFIX}/usr/bin/python3-config --includes)" + export PYTHON_LIBS="$(${SYSROOT_PREFIX}/usr/bin/python3-config --ldflags --embed)" +} + +post_makeinstall_target() { + python_remove_source +} diff --git a/packages/python/system/dbussy/package.mk b/packages/python/system/dbussy/package.mk new file mode 100644 index 000000000..b11342352 --- /dev/null +++ b/packages/python/system/dbussy/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dbussy" +PKG_VERSION="1.3" +PKG_SHA256="30a96caddcbbe7ef9e4f506c01c2d19f529cdaae6d3dac759c103b20e49641fe" +PKG_LICENSE="LGPLv2.1+" +PKG_SITE="https://gitlab.com/ldo/dbussy" +PKG_URL="https://github.com/ldo/${PKG_NAME}/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 dbus" +PKG_LONGDESC="DBussy is a wrapper around libdbus, written in pure Python" +PKG_TOOLCHAIN="manual" + +make_target() { + python3 setup.py build +} + +makeinstall_target() { + python3 setup.py install --root=${INSTALL} --prefix=/usr +} + +post_makeinstall_target() { + python_remove_source +} diff --git a/packages/python/system/simplejson/package.mk b/packages/python/system/simplejson/package.mk new file mode 100644 index 000000000..8e6ba88ab --- /dev/null +++ b/packages/python/system/simplejson/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="simplejson" +PKG_VERSION="3.17.2" +PKG_SHA256="75ecc79f26d99222a084fbdd1ce5aad3ac3a8bd535cd9059528452da38b68841" +PKG_LICENSE="OSS" +PKG_SITE="http://pypi.org/project/simplejson" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3 distutilscross:host" +PKG_LONGDESC="A simple, fast, complete, correct and extensible JSON encoder and decoder for Python 2.5+." +PKG_TOOLCHAIN="manual" + +pre_make_target() { + export PYTHONXCPREFIX="${SYSROOT_PREFIX}/usr" +} + +make_target() { + python3 setup.py build --cross-compile +} + +makeinstall_target() { + python3 setup.py install --root=${INSTALL} --prefix=/usr +} + +post_makeinstall_target() { + python_remove_source + + rm -rf ${INSTALL}/usr/lib/python*/site-packages/*/tests +} diff --git a/packages/security/gnupg/package.mk b/packages/security/gnupg/package.mk new file mode 100644 index 000000000..5cd13397c --- /dev/null +++ b/packages/security/gnupg/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="gnupg" +PKG_VERSION="1.4.23" +PKG_SHA256="c9462f17e651b6507848c08c430c791287cd75491f8b5a8b50c6ed46b12678ba" +PKG_LICENSE="GPL" +PKG_SITE="https://gnupg.org/ftp/gcrypt/gnupg" +PKG_URL="$PKG_SITE/gnupg-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain zlib libgpg-error libgcrypt" +PKG_LONGDESC="The GNU Privacy Guard (GnuPG, GPG) is a complete and free implementation +of the OpenPGP and S/MIME standards." + +PKG_CONFIGURE_OPTS_TARGET=" --disable-rpath \ + --enable-minimal \ + --disable-regex \ + --disable-asm \ + --enable-bzip2 \ + --enable-aes \ + --enable-rsa" + +pre_configure_target() { + export CFLAGS="$CFLAGS -fcommon" +} + +#makeinstall_target() { +# make install DESTDIR="$INSTALL/../.INSTALL_PKG" +#} diff --git a/packages/security/gnutls/package.mk b/packages/security/gnutls/package.mk new file mode 100644 index 000000000..03dedb3a5 --- /dev/null +++ b/packages/security/gnutls/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gnutls" +PKG_VERSION="3.7.0" +PKG_SHA256="49e2a22691d252c9f24a9829b293a8f359095bc5a818351f05f1c0a5188a1df8" +PKG_LICENSE="LGPL2.1" +PKG_SITE="https://gnutls.org" +PKG_URL="https://www.gnupg.org/ftp/gcrypt/gnutls/v${PKG_VERSION:0:3}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libidn2 nettle zlib" +PKG_LONGDESC="A library which provides a secure layer over a reliable transport layer." + +PKG_CONFIGURE_OPTS_TARGET="--disable-doc \ + --disable-full-test-suite \ + --disable-guile \ + --disable-libdane \ + --disable-padlock \ + --disable-tests \ + --disable-tools \ + --disable-valgrind-tests \ + --enable-local-libopts \ + --with-idn \ + --with-included-libtasn1 \ + --with-included-unistring \ + --without-p11-kit \ + --without-tpm" diff --git a/packages/security/libgcrypt/package.mk b/packages/security/libgcrypt/package.mk new file mode 100644 index 000000000..f2e836873 --- /dev/null +++ b/packages/security/libgcrypt/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libgcrypt" +PKG_VERSION="1.8.5" +PKG_SHA256="3b4a2a94cb637eff5bdebbcaf46f4d95c4f25206f459809339cdada0eb577ac3" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.gnupg.org/" +PKG_URL="https://www.gnupg.org/ftp/gcrypt/libgcrypt/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libgpg-error" +PKG_LONGDESC="A General purpose cryptographic library." +PKG_TOOLCHAIN="autotools" +# libgcrypt-1.7.x fails to build with LTO support +# see for example https://bugs.gentoo.org/show_bug.cgi?id=581114 + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="CC_FOR_BUILD=$HOST_CC \ + ac_cv_sys_symbol_underscore=no \ + --enable-asm \ + --with-gnu-ld \ + --with-libgpg-error-prefix=$SYSROOT_PREFIX/usr \ + --disable-doc" +} + +post_makeinstall_target() { + sed -e "s:\(['= ]\)\"/usr:\\1\"$SYSROOT_PREFIX/usr:g" -i src/$PKG_NAME-config + cp src/$PKG_NAME-config $SYSROOT_PREFIX/usr/bin + + rm -rf $INSTALL/usr/bin +} diff --git a/packages/security/libgcrypt/patches/libgcrypt-01-dont_replace_parts_of_path-0.1.patch b/packages/security/libgcrypt/patches/libgcrypt-01-dont_replace_parts_of_path-0.1.patch new file mode 100644 index 000000000..cbb9089ae --- /dev/null +++ b/packages/security/libgcrypt/patches/libgcrypt-01-dont_replace_parts_of_path-0.1.patch @@ -0,0 +1,24 @@ +diff -Naur libgcrypt-1.4.6/cipher/Makefile.am libgcrypt-1.4.6.patch/cipher/Makefile.am +--- libgcrypt-1.4.6/cipher/Makefile.am 2009-12-11 16:31:38.000000000 +0100 ++++ libgcrypt-1.4.6.patch/cipher/Makefile.am 2011-05-08 03:21:56.463021968 +0200 +@@ -68,7 +68,7 @@ + camellia.c camellia.h camellia-glue.c + + if ENABLE_O_FLAG_MUNGING +-o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' ++o_flag_munging = sed -e 's/-O\([2-9s][2-9s]\)/-O1/' -e 's/-Ofast/-O1/g' + else + o_flag_munging = cat + endif +diff -Naur libgcrypt-1.4.6/cipher/Makefile.in libgcrypt-1.4.6.patch/cipher/Makefile.in +--- libgcrypt-1.4.6/cipher/Makefile.in 2010-07-13 17:42:20.000000000 +0200 ++++ libgcrypt-1.4.6.patch/cipher/Makefile.in 2011-05-08 03:22:12.059208971 +0200 +@@ -274,7 +274,7 @@ + camellia.c camellia.h camellia-glue.c + + @ENABLE_O_FLAG_MUNGING_FALSE@o_flag_munging = cat +-@ENABLE_O_FLAG_MUNGING_TRUE@o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' ++@ENABLE_O_FLAG_MUNGING_TRUE@o_flag_munging = sed -e 's/-O\([2-9s][2-9s]\)/-O1/' -e 's/-Ofast/-O1/g' + all: all-am + + .SUFFIXES: diff --git a/packages/security/libgcrypt/patches/libgcrypt-ac_cv_sys_symbol_underscore.patch b/packages/security/libgcrypt/patches/libgcrypt-ac_cv_sys_symbol_underscore.patch new file mode 100644 index 000000000..95db0fbba --- /dev/null +++ b/packages/security/libgcrypt/patches/libgcrypt-ac_cv_sys_symbol_underscore.patch @@ -0,0 +1,27 @@ +diff --git a/acinclude.m4 b/acinclude.m4 +index a7bc0fa..1a5bffc 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -76,13 +76,14 @@ case "${host}" in + i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp) + ac_cv_sys_symbol_underscore=yes + ;; +- *) +- if test "$cross_compiling" = yes; then +- if test "x$ac_cv_sys_symbol_underscore" = x ; then +- ac_cv_sys_symbol_underscore=yes +- fi +- else +- tmp_do_check="yes" ++ *) if test -z "$ac_cv_sys_symbol_underscore"; then ++ if test "$cross_compiling" = yes; then ++ if test "x$ac_cv_sys_symbol_underscore" = x ; then ++ ac_cv_sys_symbol_underscore=yes ++ fi ++ else ++ tmp_do_check="yes" ++ fi + fi + ;; + esac + diff --git a/packages/security/libgpg-error/package.mk b/packages/security/libgpg-error/package.mk new file mode 100644 index 000000000..a955cff3d --- /dev/null +++ b/packages/security/libgpg-error/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libgpg-error" +PKG_VERSION="1.41" +PKG_SHA256="64b078b45ac3c3003d7e352a5e05318880a5778c42331ce1ef33d1a0d9922742" +PKG_LICENSE="GPLv2" +PKG_SITE="https://www.gnupg.org" +PKG_URL="https://www.gnupg.org/ftp/gcrypt/libgpg-error/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A library that defines common error values for all GnuPG components." + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--disable-tests CC_FOR_BUILD=${HOST_CC} --disable-nls --disable-rpath --with-gnu-ld --with-pic" + +# inspired by openembedded + case ${TARGET_ARCH} in + aarch64) + GPGERROR_TUPLE=aarch64-unknown-linux-gnu + GPGERROR_TARGET=linux-gnu${TARGET_ABI} + ;; + arm) + GPGERROR_TUPLE=arm-unknown-linux-gnueabi + GPGERROR_TARGET=linux-gnu${TARGET_ABI} + ;; + x86_64) + GPGERROR_TUPLE=x86_64-unknown-linux-gnu + GPGERROR_TARGET=linux-gnu + ;; + esac + + cp ${PKG_BUILD}/src/syscfg/lock-obj-pub.${GPGERROR_TUPLE}.h ${PKG_BUILD}/src/syscfg/lock-obj-pub.${GPGERROR_TARGET}.h +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin + rm -rf ${INSTALL}/usr/share + + sed -e "s:\(['= ]\)/usr:\\1${SYSROOT_PREFIX}/usr:g" -i src/gpg-error-config + cp src/gpg-error-config ${SYSROOT_PREFIX}/usr/bin +} diff --git a/packages/security/nettle/package.mk b/packages/security/nettle/package.mk new file mode 100644 index 000000000..256ea6b6c --- /dev/null +++ b/packages/security/nettle/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nettle" +PKG_VERSION="3.6" +PKG_SHA256="d24c0d0f2abffbc8f4f34dcf114b0f131ec3774895f3555922fe2f40f3d5e3f1" +PKG_LICENSE="GPL2" +PKG_SITE="http://www.lysator.liu.se/~nisse/nettle" +PKG_URL="http://ftpmirror.gnu.org/gnu/nettle/nettle-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain gmp" +PKG_LONGDESC="A low-level cryptographic library." + +PKG_CONFIGURE_OPTS_TARGET="--disable-documentation \ + --disable-openssl" + +if target_has_feature neon; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-arm-neon" +fi + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/security/nspr/package.mk b/packages/security/nspr/package.mk new file mode 100644 index 000000000..58f4f2200 --- /dev/null +++ b/packages/security/nspr/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nspr" +PKG_VERSION="4.19" +PKG_LICENSE="Mozilla Public License" +PKG_SITE="http://www.linuxfromscratch.org/blfs/view/svn/general/nspr.html" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain nss:host nspr:host" +PKG_DEPENDS_UNPACK="nss" +PKG_LONGDESC="Netscape Portable Runtime (NSPR) provides a platform-neutral API for system level and libc like functions" +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="-parallel" + +if [ "$TARGET_ARCH" = "x86_64" ] ; then + TARGET_USE_64="--enable-64bit" +fi + +PKG_CONFIGURE_OPTS_TARGET="--with-pthreads $TARGET_USE_64" +PKG_MAKE_OPTS_TARGET="NSINSTALL=$TOOLCHAIN/bin/nsinstall" +PKG_MAKEINSTALL_OPTS_TARGET="NSINSTALL=$TOOLCHAIN/bin/nsinstall" + +configure_host() { + cd $(get_build_dir nss)/nspr + ./configure --with-pthreads --enable-64bit --with-pthreads --prefix=$TOOLCHAIN +} + +pre_make_host() { + cd $(get_build_dir nss)/nspr + make clean +} + +configure_target() { + cd $(get_build_dir nss)/nspr + ./configure --with-pthreads $TARGET_USE_64 $TARGET_CONFIGURE_OPTS +} + +pre_make_target() { + cd $(get_build_dir nss)/nspr + make clean +} diff --git a/packages/security/nss/package.mk b/packages/security/nss/package.mk new file mode 100644 index 000000000..8b3fd439b --- /dev/null +++ b/packages/security/nss/package.mk @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nss" +PKG_VERSION="3.44" +PKG_SHA256="298d86e18e96660d3c98476274b5857b48c135d809a10d6528d8661bdf834a49" +PKG_LICENSE="Mozilla Public License" +PKG_SITE="http://ftp.mozilla.org/" +PKG_URL="http://ftp.mozilla.org/pub/security/nss/releases/NSS_3_44_RTM/src/nss-3.44-with-nspr-4.21.tar.gz" +PKG_DEPENDS_HOST="nspr:host zlib:host" +PKG_DEPENDS_TARGET="toolchain nss:host nspr zlib sqlite" +PKG_LONGDESC="The Network Security Services (NSS) package is a set of libraries designed to support cross-platform development of security-enabled client and server applications" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="-parallel" + +make_host() { + cd $PKG_BUILD/nss + + make clean || true + rm -rf $PKG_BUILD/dist + + INCLUDES="-I$TOOLCHAIN/include" \ + make BUILD_OPT=1 USE_64=1 \ + PREFIX=$TOOLCHAIN \ + NSPR_INCLUDE_DIR=$TOOLCHAIN/include/nspr \ + USE_SYSTEM_ZLIB=1 ZLIB_LIBS="-lz -L$TOOLCHAIN/lib" \ + SKIP_SHLIBSIGN=1 \ + NSS_TESTS="dummy" \ + CC=$CC LDFLAGS="$LDFLAGS -L$TOOLCHAIN/lib" \ + V=1 +} + +makeinstall_host() { + cd $PKG_BUILD + $STRIP dist/Linux*/lib/*.so + cp -L dist/Linux*/lib/*.so $TOOLCHAIN/lib + cp -L dist/Linux*/lib/libcrmf.a $TOOLCHAIN/lib + mkdir -p $TOOLCHAIN/include/nss + cp -RL dist/{public,private}/nss/* $TOOLCHAIN/include/nss + cp -L dist/Linux*/lib/pkgconfig/nss.pc $TOOLCHAIN/lib/pkgconfig + cp -L nss/coreconf/nsinstall/*/nsinstall $TOOLCHAIN/bin +} + +make_target() { + cd $PKG_BUILD/nss + + local TARGET_USE_64="" + [ "$TARGET_ARCH" = "x86_64" -o "$TARGET_ARCH" = "aarch64" ] && TARGET_USE_64="USE_64=1" + + make clean || true + rm -rf $PKG_BUILD/dist + + make BUILD_OPT=1 $TARGET_USE_64 \ + NSS_USE_SYSTEM_SQLITE=1 \ + NSPR_INCLUDE_DIR=$SYSROOT_PREFIX/usr/include/nspr \ + NSS_USE_SYSTEM_SQLITE=1 \ + USE_SYSTEM_ZLIB=1 ZLIB_LIBS=-lz \ + SKIP_SHLIBSIGN=1 \ + OS_TEST=$TARGET_ARCH \ + NSS_TESTS="dummy" \ + NSINSTALL=$TOOLCHAIN/bin/nsinstall \ + CPU_ARCH_TAG=$TARGET_ARCH \ + CC=$CC \ + LDFLAGS="$LDFLAGS -L$SYSROOT_PREFIX/usr/lib" \ + V=1 +} + +makeinstall_target() { + cd $PKG_BUILD + $STRIP dist/Linux*/lib/*.so + cp -L dist/Linux*/lib/*.so $SYSROOT_PREFIX/usr/lib + cp -L dist/Linux*/lib/libcrmf.a $SYSROOT_PREFIX/usr/lib + mkdir -p $SYSROOT_PREFIX/usr/include/nss + cp -RL dist/{public,private}/nss/* $SYSROOT_PREFIX/usr/include/nss + cp -L dist/Linux*/lib/pkgconfig/nss.pc $SYSROOT_PREFIX/usr/lib/pkgconfig + + mkdir -p .install_pkg/usr/lib + cp -PL dist/Linux*/lib/*.so .install_pkg/usr/lib +} diff --git a/packages/security/nss/patches/nss-02_3.15.5-standalone-1.patch b/packages/security/nss/patches/nss-02_3.15.5-standalone-1.patch new file mode 100644 index 000000000..b82c25d0d --- /dev/null +++ b/packages/security/nss/patches/nss-02_3.15.5-standalone-1.patch @@ -0,0 +1,241 @@ +Submitted By: Armin K. +Date: 2013-07-02 +Initial Package Version: 3.15 +Upstream Status: Not applicable +Origin: Based on dj's original patch, rediffed and modified for 3.15 +Description: Adds auto-generated nss.pc and nss-config script, and allows + building without nspr in the source tree. + +--- a/nss/config/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ b/nss/config/Makefile 2013-07-02 14:53:56.684750636 +0200 +@@ -0,0 +1,40 @@ ++CORE_DEPTH = .. ++DEPTH = .. ++ ++include $(CORE_DEPTH)/coreconf/config.mk ++ ++NSS_MAJOR_VERSION = `grep "NSS_VMAJOR" ../lib/nss/nss.h | awk '{print $$3}'` ++NSS_MINOR_VERSION = `grep "NSS_VMINOR" ../lib/nss/nss.h | awk '{print $$3}'` ++NSS_PATCH_VERSION = `grep "NSS_VPATCH" ../lib/nss/nss.h | awk '{print $$3}'` ++PREFIX = /usr ++ ++all: export libs ++ ++export: ++ # Create the nss.pc file ++ mkdir -p $(DIST)/lib/pkgconfig ++ sed -e "s,@prefix@,$(PREFIX)," \ ++ -e "s,@exec_prefix@,\$${prefix}," \ ++ -e "s,@libdir@,\$${prefix}/lib," \ ++ -e "s,@includedir@,\$${prefix}/include/nss," \ ++ -e "s,@NSS_MAJOR_VERSION@,$(NSS_MAJOR_VERSION),g" \ ++ -e "s,@NSS_MINOR_VERSION@,$(NSS_MINOR_VERSION)," \ ++ -e "s,@NSS_PATCH_VERSION@,$(NSS_PATCH_VERSION)," \ ++ nss.pc.in > nss.pc ++ chmod 0644 nss.pc ++ ln -sf ../../../../nss/config/nss.pc $(DIST)/lib/pkgconfig ++ ++ # Create the nss-config script ++ mkdir -p $(DIST)/bin ++ sed -e "s,@prefix@,$(PREFIX)," \ ++ -e "s,@NSS_MAJOR_VERSION@,$(NSS_MAJOR_VERSION)," \ ++ -e "s,@NSS_MINOR_VERSION@,$(NSS_MINOR_VERSION)," \ ++ -e "s,@NSS_PATCH_VERSION@,$(NSS_PATCH_VERSION)," \ ++ nss-config.in > nss-config ++ chmod 0755 nss-config ++ ln -sf ../../../nss/config/nss-config $(DIST)/bin ++ ++libs: ++ ++dummy: all export libs ++ +--- a/nss/config/nss-config.in 1970-01-01 01:00:00.000000000 +0100 ++++ b/nss/config/nss-config.in 2013-07-02 14:52:58.328084334 +0200 +@@ -0,0 +1,153 @@ ++#!/bin/sh ++ ++prefix=@prefix@ ++ ++major_version=@NSS_MAJOR_VERSION@ ++minor_version=@NSS_MINOR_VERSION@ ++patch_version=@NSS_PATCH_VERSION@ ++ ++usage() ++{ ++ cat <&2 ++fi ++ ++lib_nss=yes ++lib_nssutil=yes ++lib_smime=yes ++lib_ssl=yes ++lib_softokn=yes ++ ++while test $# -gt 0; do ++ case "$1" in ++ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; ++ *) optarg= ;; ++ esac ++ ++ case $1 in ++ --prefix=*) ++ prefix=$optarg ++ ;; ++ --prefix) ++ echo_prefix=yes ++ ;; ++ --exec-prefix=*) ++ exec_prefix=$optarg ++ ;; ++ --exec-prefix) ++ echo_exec_prefix=yes ++ ;; ++ --includedir=*) ++ includedir=$optarg ++ ;; ++ --includedir) ++ echo_includedir=yes ++ ;; ++ --libdir=*) ++ libdir=$optarg ++ ;; ++ --libdir) ++ echo_libdir=yes ++ ;; ++ --version) ++ echo ${major_version}.${minor_version}.${patch_version} ++ ;; ++ --cflags) ++ echo_cflags=yes ++ ;; ++ --libs) ++ echo_libs=yes ++ ;; ++ nss) ++ lib_nss=yes ++ ;; ++ nssutil) ++ lib_nssutil=yes ++ ;; ++ smime) ++ lib_smime=yes ++ ;; ++ ssl) ++ lib_ssl=yes ++ ;; ++ softokn) ++ lib_softokn=yes ++ ;; ++ *) ++ usage 1 1>&2 ++ ;; ++ esac ++ shift ++done ++ ++# Set variables that may be dependent upon other variables ++if test -z "$exec_prefix"; then ++ exec_prefix=`pkg-config --variable=exec_prefix nss` ++fi ++if test -z "$includedir"; then ++ includedir=`pkg-config --variable=includedir nss` ++fi ++if test -z "$libdir"; then ++ libdir=`pkg-config --variable=libdir nss` ++fi ++ ++if test "$echo_prefix" = "yes"; then ++ echo $prefix ++fi ++ ++if test "$echo_exec_prefix" = "yes"; then ++ echo $exec_prefix ++fi ++ ++if test "$echo_includedir" = "yes"; then ++ echo $includedir ++fi ++ ++if test "$echo_libdir" = "yes"; then ++ echo $libdir ++fi ++ ++if test "$echo_cflags" = "yes"; then ++ echo -I$includedir ++fi ++ ++if test "$echo_libs" = "yes"; then ++ libdirs="-L$libdir" ++ if test -n "$lib_nss"; then ++ libdirs="$libdirs -lnss${major_version}" ++ fi ++ if test -n "$lib_nssutil"; then ++ libdirs="$libdirs -lnssutil${major_version}" ++ fi ++ if test -n "$lib_smime"; then ++ libdirs="$libdirs -lsmime${major_version}" ++ fi ++ if test -n "$lib_ssl"; then ++ libdirs="$libdirs -lssl${major_version}" ++ fi ++ if test -n "$lib_softokn"; then ++ libdirs="$libdirs -lsoftokn${major_version}" ++ fi ++ echo $libdirs ++fi ++ +--- a/nss/config/nss.pc.in 1970-01-01 01:00:00.000000000 +0100 ++++ b/nss/config/nss.pc.in 2013-07-02 14:52:58.328084334 +0200 +@@ -0,0 +1,12 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@ ++ ++Name: NSS ++Description: Network Security Services ++Version: @NSS_MAJOR_VERSION@.@NSS_MINOR_VERSION@.@NSS_PATCH_VERSION@ ++Requires: nspr >= 4.8 ++Libs: -L@libdir@ -lnss@NSS_MAJOR_VERSION@ -lnssutil@NSS_MAJOR_VERSION@ -lsmime@NSS_MAJOR_VERSION@ -lssl@NSS_MAJOR_VERSION@ -lsoftokn@NSS_MAJOR_VERSION@ ++Cflags: -I${includedir} ++ +--- a/nss/Makefile 2013-05-28 23:43:24.000000000 +0200 ++++ b/nss/Makefile 2013-07-02 14:52:58.328084334 +0200 +@@ -46,7 +46,7 @@ + # (7) Execute "local" rules. (OPTIONAL). # + ####################################################################### + +-nss_build_all: build_nspr all latest ++nss_build_all: all latest + + nss_clean_all: clobber_nspr clobber + +--- a/nss/manifest.mn 2013-05-28 23:43:24.000000000 +0200 ++++ b/nss/manifest.mn 2013-07-02 14:52:58.331417666 +0200 +@@ -10,4 +10,4 @@ + + RELEASE = nss + +-DIRS = coreconf lib cmd cpputil gtests ++DIRS = coreconf lib cmd config diff --git a/packages/security/nss/patches/nss-04-skip_shlibsign.patch b/packages/security/nss/patches/nss-04-skip_shlibsign.patch new file mode 100644 index 000000000..dfee7cd0e --- /dev/null +++ b/packages/security/nss/patches/nss-04-skip_shlibsign.patch @@ -0,0 +1,12 @@ +diff -Naur nss-3.29.5.orig/nss/cmd/shlibsign/Makefile nss-3.29.5/nss/cmd/shlibsign/Makefile +--- nss-3.29.5.orig/nss/cmd/shlibsign/Makefile 2017-09-08 10:56:01.663876686 +0200 ++++ nss-3.29.5/nss/cmd/shlibsign/Makefile 2017-09-08 10:57:19.659306831 +0200 +@@ -95,5 +95,7 @@ + endif + endif + +-libs install :: $(CHECKLOC) ++ifndef SKIP_SHLIBSIGN ++ libs install :: $(CHECKLOC) ++endif + diff --git a/packages/security/nss/patches/nss-05-disable_host_cflags.patch b/packages/security/nss/patches/nss-05-disable_host_cflags.patch new file mode 100644 index 000000000..67fb94c3c --- /dev/null +++ b/packages/security/nss/patches/nss-05-disable_host_cflags.patch @@ -0,0 +1,12 @@ +diff -Naur nss-3.29.5.orig/nspr/config/autoconf.mk.in nss-3.29.5/nspr/config/autoconf.mk.in +--- nss-3.29.5.orig/nspr/config/autoconf.mk.in 2017-09-08 11:03:27.572619156 +0200 ++++ nss-3.29.5/nspr/config/autoconf.mk.in 2017-09-08 11:03:41.100520343 +0200 +@@ -104,7 +104,7 @@ + RESOLVE_LINK_SYMBOLS = @RESOLVE_LINK_SYMBOLS@ + + HOST_CC = @HOST_CC@ +-HOST_CFLAGS = @HOST_CFLAGS@ ++#HOST_CFLAGS = @HOST_CFLAGS@ + HOST_LDFLAGS = @HOST_LDFLAGS@ + + DEFINES = @DEFINES@ @DEFS@ diff --git a/packages/security/nss/patches/nss-06-always-include-fstar.patch b/packages/security/nss/patches/nss-06-always-include-fstar.patch new file mode 100644 index 000000000..60c0766dc --- /dev/null +++ b/packages/security/nss/patches/nss-06-always-include-fstar.patch @@ -0,0 +1,15 @@ +diff --git a/nss/lib/freebl/Makefile b/nss/lib/freebl/Makefile +index bff11c7..0c714c8 100644 +--- a/nss/lib/freebl/Makefile ++++ b/nss/lib/freebl/Makefile +@@ -541,9 +541,7 @@ else + ECL_SRCS += curve25519_32.c + endif + +-ifndef HAVE_INT128_SUPPORT +- VERIFIED_SRCS += FStar.c +-endif ++VERIFIED_SRCS += FStar.c + + ####################################################################### + # (5) Execute "global" rules. (OPTIONAL) # diff --git a/packages/security/openssl/cert/cacert.pem b/packages/security/openssl/cert/cacert.pem new file mode 100644 index 000000000..fba67edef --- /dev/null +++ b/packages/security/openssl/cert/cacert.pem @@ -0,0 +1,3512 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Dec 8 04:12:05 2020 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.28. +## SHA256: d820b8696d8ffe42064a1384a56a8981cdc7e7e198036bbb5fa04a6c282dd9a2 +## + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +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 +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +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 +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl +OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV +MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF +JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G3 +================================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC +TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l +ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y +olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t +x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy +EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K +Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur +mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5 +1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp +07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo +FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE +41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu +yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq +KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1 +v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA +8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b +8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r +mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq +1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI +JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV +tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk= +-----END CERTIFICATE----- + +Staat der Nederlanden EV Root CA +================================ +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M +MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl +cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk +SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW +O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r +0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 +Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV +XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr +08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV +0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd +74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx +fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa +ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu +c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq +5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN +b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN +f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi +5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 +WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK +DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy +eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +====================== +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +TrustCor RootCert CA-1 +====================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx +MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu +YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe +VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy +dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq +jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 +pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 +JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h +gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw +/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j +BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 +mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C +qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P +3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +TrustCor RootCert CA-2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +TrustCor ECA-1 +============== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw +N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 +MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y +IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR +MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 +xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc +p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ +fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj +YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL +f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF +AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u +/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs +J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC +jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +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 +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +======================================== +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +============================================== +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +=========================================== +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +GlobalSign Root CA - R6 +======================= +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GC CA +=============================== +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx +9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r +aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW +r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM +LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly +4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr +06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om +3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu +JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM +BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv +fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm +ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b +gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq +4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr +tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo +pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0 +sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql +CFF1pkgl +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk +k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo +7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI +m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm +dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu +ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz +cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl +aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy +5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM +BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ ++YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw +c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da +WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r +n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu +Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ +7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs +gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld +o/DUhgkC +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU +Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP +0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0 +glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa +KaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa +6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV +2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI +N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x +zPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +UCA Global G2 Root +================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE----- + +UCA Extended Validation Root +============================ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE----- + +Certigna Root CA +================ +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +emSign Root CA - G1 +=================== +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +emSign ECC Root CA - G3 +======================= +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +emSign Root CA - C1 +=================== +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +emSign ECC Root CA - C3 +======================= +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 3 +======================= +-----BEGIN CERTIFICATE----- +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 +dBb9HxEGmpv0 +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G4 +========================================= +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +Microsoft ECC Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +Microsoft RSA Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +e-Szigno Root CA 2017 +===================== +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE----- + +certSIGN Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +Trustwave Global Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +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 +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +Trustwave Global ECC P256 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +Trustwave Global ECC P384 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE----- + + +-----BEGIN CERTIFICATE----- +MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTIwMTAwNzE5MjE0MFoXDTIxMDkyOTE5MjE0MFow +MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT +AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs +jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp +Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB +U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7 +gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel +/xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R +oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E +BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p +ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE +p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE +AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu +Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0 +LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf +r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B +AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH +ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8 +S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL +qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p +O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw +UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICxjCCAk2gAwIBAgIRALO93/inhFu86QOgQTWzSkUwCgYIKoZIzj0EAwMwTzEL +MAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNo +IEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDIwHhcNMjAwOTA0MDAwMDAwWhcN +MjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5j +cnlwdDELMAkGA1UEAxMCRTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQkXC2iKv0c +S6Zdl3MnMayyoGli72XoprDwrEuf/xwLcA/TmC9N/A8AmzfwdAVXMpcuBe8qQyWj ++240JxP2T35p0wKZXuskR5LBJJvmsSGPwSSB/GjMH2m6WPUZIvd0xhajggEIMIIB +BDAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFFrz7Sv8NsI3eblSMOpUb89V +yy6sMB8GA1UdIwQYMBaAFHxClq7eS0g7+pL4nozPbYupcjeVMDIGCCsGAQUFBwEB +BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gyLmkubGVuY3Iub3JnLzAnBgNVHR8E +IDAeMBygGqAYhhZodHRwOi8veDIuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYG +Z4EMAQIBMA0GCysGAQQBgt8TAQEBMAoGCCqGSM49BAMDA2cAMGQCMHt01VITjWH+ +Dbo/AwCd89eYhNlXLr3pD5xcSAQh8suzYHKOl9YST8pE9kLJ03uGqQIwWrGxtO3q +YJkgsTgDyj2gJrjubi1K9sZmHzOa25JK1fUpE8ZwYii6I4zPPS/Lgul/ +-----END CERTIFICATE----- diff --git a/packages/security/openssl/package.mk b/packages/security/openssl/package.mk new file mode 100644 index 000000000..d01547929 --- /dev/null +++ b/packages/security/openssl/package.mk @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="openssl" +PKG_VERSION="1.1.1g" +PKG_SHA256="ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46" +PKG_LICENSE="BSD" +PKG_SITE="https://www.openssl.org" +PKG_URL="https://www.openssl.org/source/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The Open Source toolkit for Secure Sockets Layer and Transport Layer Security" +PKG_TOOLCHAIN="configure" +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_SHARED="--libdir=lib \ + shared \ + threads \ + no-ec2m \ + no-md2 \ + no-rc5 \ + no-rfc3779 \ + no-sctp \ + no-ssl-trace \ + no-ssl3 \ + no-unit-test \ + no-weak-ssl-ciphers \ + no-zlib \ + no-zlib-dynamic \ + no-static-engine" + +PKG_CONFIGURE_OPTS_HOST="--prefix=$TOOLCHAIN \ + --openssldir=$TOOLCHAIN/etc/ssl" +PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --openssldir=/etc/ssl" + +post_unpack() { + find $PKG_BUILD/apps -type f | xargs -n 1 -t sed 's|./demoCA|/etc/ssl|' -i +} + +pre_configure_host() { + mkdir -p $PKG_BUILD/.$HOST_NAME + cp -a $PKG_BUILD/* $PKG_BUILD/.$HOST_NAME/ +} + +configure_host() { + cd $PKG_BUILD/.$HOST_NAME + ./Configure $PKG_CONFIGURE_OPTS_HOST $PKG_CONFIGURE_OPTS_SHARED linux-${MACHINE_HARDWARE_NAME} $CFLAGS $LDFLAGS +} + +makeinstall_host() { + make install_sw +} + +pre_configure_target() { + mkdir -p $PKG_BUILD/.$TARGET_NAME + cp -a $PKG_BUILD/* $PKG_BUILD/.$TARGET_NAME/ + + case $TARGET_ARCH in + x86_64) + OPENSSL_TARGET=linux-x86_64 + PLATFORM_FLAGS=enable-ec_nistp_64_gcc_128 + ;; + arm) + OPENSSL_TARGET=linux-armv4 + ;; + aarch64) + OPENSSL_TARGET=linux-aarch64 + ;; + esac +} + +configure_target() { + cd $PKG_BUILD/.$TARGET_NAME + ./Configure $PKG_CONFIGURE_OPTS_TARGET $PKG_CONFIGURE_OPTS_SHARED $PLATFORM_FLAGS $OPENSSL_TARGET $CFLAGS $LDFLAGS +} + +makeinstall_target() { + make DESTDIR=$INSTALL install_sw + make DESTDIR=$SYSROOT_PREFIX install_sw +} + +post_makeinstall_target() { + rm -rf $INSTALL/etc/ssl/misc + rm -rf $INSTALL/usr/bin/c_rehash + + debug_strip $INSTALL/usr/bin/openssl + + # cert from https://curl.haxx.se/docs/caextract.html + mkdir -p $INSTALL/etc/ssl + cp $PKG_DIR/cert/cacert.pem $INSTALL/etc/ssl/cacert.pem.system + + # give user the chance to include their own CA + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/openssl-config $INSTALL/usr/bin + ln -sf /run/libreelec/cacert.pem $INSTALL/etc/ssl/cacert.pem + ln -sf /run/libreelec/cacert.pem $INSTALL/etc/ssl/cert.pem + + # backwards comatibility + mkdir -p $INSTALL/etc/pki/tls + ln -sf /run/libreelec/cacert.pem $INSTALL/etc/pki/tls/cacert.pem + mkdir -p $INSTALL/etc/pki/tls/certs + ln -sf /run/libreelec/cacert.pem $INSTALL/etc/pki/tls/certs/ca-bundle.crt + mkdir -p $INSTALL/usr/lib + ln -sf /etc/ssl $INSTALL/usr/lib/ssl +} + +post_install() { + enable_service openssl-config.service +} diff --git a/packages/security/openssl/scripts/openssl-config b/packages/security/openssl/scripts/openssl-config new file mode 100755 index 000000000..fc25eded2 --- /dev/null +++ b/packages/security/openssl/scripts/openssl-config @@ -0,0 +1,10 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +cp /etc/ssl/cacert.pem.system /run/libreelec/cacert.pem + +[ -f /storage/.config/cacert.pem ] && cat /storage/.config/cacert.pem >>/run/libreelec/cacert.pem + +exit 0 diff --git a/packages/security/openssl/system.d/openssl-config.service b/packages/security/openssl/system.d/openssl-config.service new file mode 100644 index 000000000..0f76b811d --- /dev/null +++ b/packages/security/openssl/system.d/openssl-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=OpenSSL configuration service +DefaultDependencies=no +After=systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/openssl-config + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/amremote/package.mk b/packages/sysutils/amremote/package.mk new file mode 100644 index 000000000..950240b7f --- /dev/null +++ b/packages/sysutils/amremote/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="amremote" +PKG_LICENSE="other" +PKG_SITE="http://www.amlogic.com" +PKG_DEPENDS_TARGET="toolchain usbutils" +PKG_LONGDESC="amremote - IR remote configuration utility for Amlogic-based devices" + +case "$LINUX" in + amlogic-3.14) + PKG_VERSION="05b85d1f9821ae65dca250ba87b369327dd71df3" + PKG_SHA256="895a64efc05cee3148b4c33f5acbffb87da095d8b8f289f78e0cec26d2ed6f9d" + PKG_URL="https://github.com/CoreELEC/amremote/archive/$PKG_VERSION.tar.gz" + ;; + amlogic-4.9) + PKG_VERSION="1db130a0ccd47f6b5c3d1dffab1e89613b796a8c" + PKG_SHA256="5b96f2a1dd03200909eed749f5d97d1d02ee7fc8ac92d8fce6b5d6772ee642dc" + PKG_URL="https://github.com/CoreELEC/amremote/archive/$PKG_VERSION.tar.gz" + ;; +esac + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp remotecfg $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/* $INSTALL/usr/lib/coreelec +} + +post_install() { + enable_service remote-config.service +} diff --git a/packages/sysutils/amremote/scripts/remote-config b/packages/sysutils/amremote/scripts/remote-config new file mode 100755 index 000000000..9529f0adf --- /dev/null +++ b/packages/sysutils/amremote/scripts/remote-config @@ -0,0 +1,84 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +remap_keys () { + [ ! -f "$1" ] && return + + sed -i 's/ 15[^0-9]*$/ 1/ + s/ 63[^0-9]*$/ 90/ + s/ 97[^0-9]*$/ 28/ + s/ 102[^0-9]*$/ 172/ + s/ 125[^0-9]*$/ 46/ + s/ 128[^0-9]*$/ 45/ + s/ 139[^0-9]*$/ 46/ + s/ 142[^0-9]*$/ 116/ + s/ 143[^0-9]*$/ 116/ + s/ 158[^0-9]*$/ 1/ + s/ 183[^0-9]*$/ 59/ + s/ 184[^0-9]*$/ 399/ + s/ 185[^0-9]*$/ 400/ + s/ 186[^0-9]*$/ 60/ + s/ 232[^0-9]*$/ 28/ + s/ 240[^0-9]*$/ 164/ + s/ 241[^0-9]*$/ 163/ + s/ 242[^0-9]*$/ 165/ + s/ 244[^0-9]*$/ 208/ + s/ 245[^0-9]*$/ 168/ + s/ 264[^0-9]*$/ 63/ + s/ 704[^0-9]*$/ 116/' \ + "$1" +} + +[ ! -e "/proc/device-tree/meson-ir/compatible" -o ! -e "/proc/device-tree/meson-remote/compatible" ] && exit + +if [ -f "/flash/remote.disable" -o -f "/storage/.config/remote.disable" ]; then + echo "remote control disabled by user" + exit 0 +fi + +if [ -f "/flash/remote.force_meson_ir" -o -f "/storage/.config/remote.force_meson_ir" ]; then + force_meson_ir="yes" +else + force_meson_ir="no" +fi + +if [ -f "/flash/remote.conf" ]; then + REMOTE_CONF_DIR="/flash" +elif [ -f "/storage/.config/remote.conf" ]; then + REMOTE_CONF_DIR="/storage/.config" +else + REMOTE_CONF_DIR="" + + if [ -d "/proc/device-tree/custom_maps" -a "$force_meson_ir" = "no" ]; then + MAP_NAME=$(cat /proc/device-tree/custom_maps/map_0/mapname 2>/dev/null) + echo "using meson-remote, with pre-defined map '$MAP_NAME' from dtb" + modprobe meson-remote + exit 0 + fi +fi + +if [ -d "$REMOTE_CONF_DIR" ]; then + echo "using meson-remote, conf from $REMOTE_CONF_DIR" + + if [ -d "/proc/device-tree/custom_maps" ]; then + MAP_NAME=$(cat /proc/device-tree/custom_maps/map_0/mapname 2>/dev/null) + echo "also using pre-defined map '$MAP_NAME' from dtb" + fi + + modprobe meson-remote + + for f in $REMOTE_CONF_DIR/remote*.conf; do + echo "configuring remote with $f" + cp "$f" /tmp/remote.conf + remap_keys /tmp/remote.conf + remotecfg /tmp/remote.conf + rm -f /tmp/remote.conf + done +else + echo "using meson-ir" + modprobe meson-ir +fi + +exit 0 diff --git a/packages/sysutils/amremote/system.d/remote-config.service b/packages/sysutils/amremote/system.d/remote-config.service new file mode 100644 index 000000000..3527bca12 --- /dev/null +++ b/packages/sysutils/amremote/system.d/remote-config.service @@ -0,0 +1,13 @@ +[Unit] +Description=IR remote control support +Before=graphical.target kodi.service +After=multi-user.target +ConditionPathExists=/proc/device-tree/meson-ir/compatible +ConditionPathExists=/proc/device-tree/meson-remote/compatible + +[Service] +Type=oneshot +ExecStart=/usr/lib/coreelec/remote-config + +[Install] +WantedBy=graphical.target diff --git a/packages/sysutils/autossh/package.mk b/packages/sysutils/autossh/package.mk new file mode 100644 index 000000000..9151a0f28 --- /dev/null +++ b/packages/sysutils/autossh/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="autossh" +PKG_VERSION="1.4g" +PKG_SHA256="5fc3cee3361ca1615af862364c480593171d0c54ec156de79fc421e31ae21277" +PKG_LICENSE="GPL" +PKG_SITE="http://www.harding.motd.ca/" +PKG_URL="http://www.harding.motd.ca/autossh/autossh-${PKG_VERSION}.tgz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Automatically restart SSH sessions and tunnels." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes" + +pre_configure_target() { + export CFLAGS="$CFLAGS -I." +} + +makeinstall_target() { + : +} diff --git a/packages/sysutils/bash/package.mk b/packages/sysutils/bash/package.mk new file mode 100644 index 000000000..b4360d466 --- /dev/null +++ b/packages/sysutils/bash/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-2020 Team LibreELEC +# Copyright (C) 2020-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="bash" +PKG_VERSION="5.1.16" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/bash/" +PKG_URL="http://ftpmirror.gnu.org/bash/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses readline" +PKG_LONGDESC="The GNU Bourne Again shell." + +PKG_CONFIGURE_OPTS_TARGET="--with-curses \ + --enable-readline \ + --without-bash-malloc \ + --with-installed-readline" diff --git a/packages/sysutils/bkeymaps/package.mk b/packages/sysutils/bkeymaps/package.mk new file mode 100644 index 000000000..1f67dd24d --- /dev/null +++ b/packages/sysutils/bkeymaps/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="bkeymaps" +PKG_VERSION="1.13" +PKG_SHA256="59d41ddb0c7a92d8ac155a82ed2875b7880c8957ea4308afa633c8b81e5b8887" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alpinelinux.org" +PKG_URL="http://dev.alpinelinux.org/archive/bkeymaps/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain busybox" +PKG_LONGDESC="bkeymaps: binary keyboard maps for busybox" + +make_target() { + : # nothing todo, we install manually +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/keymaps + cp -PR bkeymaps/* $INSTALL/usr/lib/keymaps +} diff --git a/packages/sysutils/busybox/config/busybox-host.conf b/packages/sysutils/busybox/config/busybox-host.conf new file mode 100644 index 000000000..6850c24ae --- /dev/null +++ b/packages/sysutils/busybox/config/busybox-host.conf @@ -0,0 +1,1162 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.31.0 +# Wed Jun 12 00:50:03 2019 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Settings +# +# CONFIG_DESKTOP is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_FEDORA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +CONFIG_LONG_OPTS=y +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +# CONFIG_FEATURE_COMPRESS_USAGE is not set +CONFIG_LFS=y +# CONFIG_PAM is not set +# CONFIG_FEATURE_DEVPTS is not set +# CONFIG_FEATURE_UTMP is not set +# CONFIG_FEATURE_WTMP is not set +# CONFIG_FEATURE_PIDFILE is not set +CONFIG_PID_FILE_PATH="" +CONFIG_BUSYBOX=y +CONFIG_FEATURE_SHOW_SCRIPT=y +# CONFIG_FEATURE_INSTALLER is not set +CONFIG_INSTALL_NO_USR=y +# CONFIG_FEATURE_SUID is not set +# CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set +CONFIG_FEATURE_PREFER_APPLETS=y +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +# CONFIG_FEATURE_SYSLOG_INFO is not set +# CONFIG_FEATURE_SYSLOG is not set +CONFIG_PLATFORM_LINUX=y + +# +# Build Options +# +# CONFIG_STATIC is not set +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_SYSROOT="" +CONFIG_EXTRA_CFLAGS="" +CONFIG_EXTRA_LDFLAGS="" +CONFIG_EXTRA_LDLIBS="" +# CONFIG_USE_PORTABLE_CODE is not set +# CONFIG_STACK_OPTIMIZATION_386 is not set + +# +# Installation Options ("make install" behavior) +# +CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install-hosttools" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set +# CONFIG_UNIT_TEST is not set +# CONFIG_WERROR is not set +# CONFIG_WARN_SIMPLE_MSG is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Library Tuning +# +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y +# CONFIG_FEATURE_RTMINMAX is not set +# CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS is not set +# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SMALL=1 +CONFIG_SHA3_SMALL=0 +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=15 +# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set +# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set +# CONFIG_FEATURE_REVERSE_SEARCH is not set +CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_FEATURE_USERNAME_COMPLETION is not set +# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set +# CONFIG_FEATURE_EDITING_WINCH is not set +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +# CONFIG_LOCALE_SUPPORT is not set +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_FEATURE_NON_POSIX_CP is not set +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +# CONFIG_FEATURE_SKIP_ROOTFS is not set +# CONFIG_MONOTONIC_SYSCALL is not set +# CONFIG_IOCTL_HEX2STR_ERROR is not set +# CONFIG_FEATURE_HWIB is not set + +# +# Applets +# + +# +# Archival Utilities +# +# CONFIG_FEATURE_SEAMLESS_XZ is not set +# CONFIG_FEATURE_SEAMLESS_LZMA is not set +# CONFIG_FEATURE_SEAMLESS_BZ2 is not set +# CONFIG_FEATURE_SEAMLESS_GZ is not set +# CONFIG_FEATURE_SEAMLESS_Z is not set +# CONFIG_AR is not set +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_FEATURE_AR_CREATE is not set +# CONFIG_UNCOMPRESS is not set +# CONFIG_GUNZIP is not set +# CONFIG_ZCAT is not set +# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set +# CONFIG_BUNZIP2 is not set +# CONFIG_BZCAT is not set +# CONFIG_UNLZMA is not set +# CONFIG_LZCAT is not set +# CONFIG_LZMA is not set +# CONFIG_UNXZ is not set +# CONFIG_XZCAT is not set +# CONFIG_XZ is not set +# CONFIG_BZIP2 is not set +CONFIG_BZIP2_SMALL=0 +# CONFIG_FEATURE_BZIP2_DECOMPRESS is not set +# CONFIG_CPIO is not set +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +# CONFIG_GZIP is not set +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_GZIP_FAST=0 +# CONFIG_FEATURE_GZIP_LEVELS is not set +# CONFIG_FEATURE_GZIP_DECOMPRESS is not set +# CONFIG_LZOP is not set +# CONFIG_UNLZOP is not set +# CONFIG_LZOPCAT is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM is not set +# CONFIG_RPM2CPIO is not set +# CONFIG_TAR is not set +# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_FEATURE_TAR_CREATE is not set +# CONFIG_FEATURE_TAR_AUTODETECT is not set +# CONFIG_FEATURE_TAR_FROM is not set +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNZIP is not set +# CONFIG_FEATURE_UNZIP_CDF is not set +# CONFIG_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_FEATURE_UNZIP_LZMA is not set +# CONFIG_FEATURE_UNZIP_XZ is not set +# CONFIG_FEATURE_LZMA_FAST is not set + +# +# Coreutils +# +# CONFIG_BASENAME is not set +# CONFIG_CAT is not set +# CONFIG_FEATURE_CATN is not set +# CONFIG_FEATURE_CATV is not set +# CONFIG_CHGRP is not set +# CONFIG_CHMOD is not set +# CONFIG_CHOWN is not set +# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set +# CONFIG_CHROOT is not set +# CONFIG_CKSUM is not set +# CONFIG_COMM is not set +# CONFIG_CP is not set +# CONFIG_FEATURE_CP_LONG_OPTIONS is not set +# CONFIG_FEATURE_CP_REFLINK is not set +# CONFIG_CUT is not set +# CONFIG_DATE is not set +# CONFIG_FEATURE_DATE_ISOFMT is not set +# CONFIG_FEATURE_DATE_NANO is not set +# CONFIG_FEATURE_DATE_COMPAT is not set +# CONFIG_DD is not set +# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set +# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set +# CONFIG_FEATURE_DD_IBS_OBS is not set +# CONFIG_FEATURE_DD_STATUS is not set +# CONFIG_DF is not set +# CONFIG_FEATURE_DF_FANCY is not set +# CONFIG_DIRNAME is not set +# CONFIG_DOS2UNIX is not set +# CONFIG_UNIX2DOS is not set +# CONFIG_DU is not set +# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set +# CONFIG_ECHO is not set +# CONFIG_FEATURE_FANCY_ECHO is not set +# CONFIG_ENV is not set +# CONFIG_EXPAND is not set +# CONFIG_UNEXPAND is not set +# CONFIG_EXPR is not set +# CONFIG_EXPR_MATH_SUPPORT_64 is not set +# CONFIG_FACTOR is not set +# CONFIG_FALSE is not set +# CONFIG_FOLD is not set +# CONFIG_HEAD is not set +# CONFIG_FEATURE_FANCY_HEAD is not set +# CONFIG_HOSTID is not set +# CONFIG_ID is not set +# CONFIG_GROUPS is not set +# CONFIG_INSTALL is not set +# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set +# CONFIG_LINK is not set +# CONFIG_LN is not set +# CONFIG_LOGNAME is not set +# CONFIG_LS is not set +# CONFIG_FEATURE_LS_FILETYPES is not set +# CONFIG_FEATURE_LS_FOLLOWLINKS is not set +# CONFIG_FEATURE_LS_RECURSIVE is not set +# CONFIG_FEATURE_LS_WIDTH is not set +# CONFIG_FEATURE_LS_SORTFILES is not set +# CONFIG_FEATURE_LS_TIMESTAMPS is not set +# CONFIG_FEATURE_LS_USERNAME is not set +# CONFIG_FEATURE_LS_COLOR is not set +# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set +# CONFIG_MD5SUM is not set +# CONFIG_SHA1SUM is not set +# CONFIG_SHA256SUM is not set +# CONFIG_SHA512SUM is not set +# CONFIG_SHA3SUM is not set +# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set +# CONFIG_MKDIR is not set +# CONFIG_MKFIFO is not set +# CONFIG_MKNOD is not set +# CONFIG_MKTEMP is not set +# CONFIG_MV is not set +# CONFIG_NICE is not set +# CONFIG_NL is not set +# CONFIG_NOHUP is not set +# CONFIG_NPROC is not set +# CONFIG_OD is not set +# CONFIG_PASTE is not set +# CONFIG_PRINTENV is not set +# CONFIG_PRINTF is not set +# CONFIG_PWD is not set +# CONFIG_READLINK is not set +# CONFIG_FEATURE_READLINK_FOLLOW is not set +# CONFIG_REALPATH is not set +# CONFIG_RM is not set +# CONFIG_RMDIR is not set +# CONFIG_SEQ is not set +# CONFIG_SHRED is not set +# CONFIG_SHUF is not set +# CONFIG_SLEEP is not set +# CONFIG_FEATURE_FANCY_SLEEP is not set +# CONFIG_SORT is not set +# CONFIG_FEATURE_SORT_BIG is not set +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +# CONFIG_STAT is not set +# CONFIG_FEATURE_STAT_FORMAT is not set +# CONFIG_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_STTY is not set +# CONFIG_SUM is not set +# CONFIG_SYNC is not set +# CONFIG_FEATURE_SYNC_FANCY is not set +# CONFIG_FSYNC is not set +# CONFIG_TAC is not set +# CONFIG_TAIL is not set +# CONFIG_FEATURE_FANCY_TAIL is not set +# CONFIG_TEE is not set +# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set +# CONFIG_TEST is not set +# CONFIG_TEST1 is not set +# CONFIG_TEST2 is not set +# CONFIG_FEATURE_TEST_64 is not set +# CONFIG_TIMEOUT is not set +# CONFIG_TOUCH is not set +# CONFIG_FEATURE_TOUCH_NODEREF is not set +# CONFIG_FEATURE_TOUCH_SUSV3 is not set +# CONFIG_TR is not set +# CONFIG_FEATURE_TR_CLASSES is not set +# CONFIG_FEATURE_TR_EQUIV is not set +# CONFIG_TRUE is not set +# CONFIG_TRUNCATE is not set +# CONFIG_TTY is not set +# CONFIG_UNAME is not set +CONFIG_UNAME_OSNAME="" +CONFIG_BB_ARCH=y +# CONFIG_UNIQ is not set +# CONFIG_UNLINK is not set +# CONFIG_USLEEP is not set +# CONFIG_UUDECODE is not set +# CONFIG_BASE64 is not set +# CONFIG_UUENCODE is not set +# CONFIG_WC is not set +# CONFIG_FEATURE_WC_LARGE is not set +# CONFIG_WHO is not set +# CONFIG_W is not set +# CONFIG_USERS is not set +# CONFIG_WHOAMI is not set +# CONFIG_YES is not set + +# +# Common options +# +# CONFIG_FEATURE_VERBOSE is not set +# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set +# CONFIG_FEATURE_HUMAN_READABLE is not set + +# +# Console Utilities +# +# CONFIG_CHVT is not set +# CONFIG_CLEAR is not set +# CONFIG_DEALLOCVT is not set +# CONFIG_DUMPKMAP is not set +# CONFIG_FGCONSOLE is not set +# CONFIG_KBD_MODE is not set +# CONFIG_LOADFONT is not set +# CONFIG_SETFONT is not set +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="" +# CONFIG_FEATURE_LOADFONT_PSF2 is not set +# CONFIG_FEATURE_LOADFONT_RAW is not set +# CONFIG_LOADKMAP is not set +# CONFIG_OPENVT is not set +# CONFIG_RESET is not set +# CONFIG_RESIZE is not set +# CONFIG_FEATURE_RESIZE_PRINT is not set +# CONFIG_SETCONSOLE is not set +# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_SETKEYCODES is not set +# CONFIG_SETLOGCONS is not set +# CONFIG_SHOWKEY is not set + +# +# Debian Utilities +# +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_WHICH is not set + +# +# klibc-utils +# +# CONFIG_MINIPS is not set +# CONFIG_NUKE is not set +# CONFIG_RESUME is not set +# CONFIG_RUN_INIT is not set + +# +# Editors +# +# CONFIG_AWK is not set +# CONFIG_FEATURE_AWK_LIBM is not set +# CONFIG_FEATURE_AWK_GNU_EXTENSIONS is not set +# CONFIG_CMP is not set +# CONFIG_DIFF is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_ED is not set +# CONFIG_PATCH is not set +# CONFIG_SED is not set +# CONFIG_VI is not set +CONFIG_FEATURE_VI_MAX_LEN=0 +# CONFIG_FEATURE_VI_8BIT is not set +# CONFIG_FEATURE_VI_COLON is not set +# CONFIG_FEATURE_VI_YANKMARK is not set +# CONFIG_FEATURE_VI_SEARCH is not set +# CONFIG_FEATURE_VI_REGEX_SEARCH is not set +# CONFIG_FEATURE_VI_USE_SIGNALS is not set +# CONFIG_FEATURE_VI_DOT_CMD is not set +# CONFIG_FEATURE_VI_READONLY is not set +# CONFIG_FEATURE_VI_SETOPTS is not set +# CONFIG_FEATURE_VI_SET is not set +# CONFIG_FEATURE_VI_WIN_RESIZE is not set +# CONFIG_FEATURE_VI_ASK_TERMINAL is not set +# CONFIG_FEATURE_VI_UNDO is not set +# CONFIG_FEATURE_VI_UNDO_QUEUE is not set +CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=0 +# CONFIG_FEATURE_ALLOW_EXEC is not set + +# +# Finding Utilities +# +# CONFIG_FIND is not set +# CONFIG_FEATURE_FIND_PRINT0 is not set +# CONFIG_FEATURE_FIND_MTIME is not set +# CONFIG_FEATURE_FIND_MMIN is not set +# CONFIG_FEATURE_FIND_PERM is not set +# CONFIG_FEATURE_FIND_TYPE is not set +# CONFIG_FEATURE_FIND_EXECUTABLE is not set +# CONFIG_FEATURE_FIND_XDEV is not set +# CONFIG_FEATURE_FIND_MAXDEPTH is not set +# CONFIG_FEATURE_FIND_NEWER is not set +# CONFIG_FEATURE_FIND_INUM is not set +# CONFIG_FEATURE_FIND_EXEC is not set +# CONFIG_FEATURE_FIND_EXEC_PLUS is not set +# CONFIG_FEATURE_FIND_USER is not set +# CONFIG_FEATURE_FIND_GROUP is not set +# CONFIG_FEATURE_FIND_NOT is not set +# CONFIG_FEATURE_FIND_DEPTH is not set +# CONFIG_FEATURE_FIND_PAREN is not set +# CONFIG_FEATURE_FIND_SIZE is not set +# CONFIG_FEATURE_FIND_PRUNE is not set +# CONFIG_FEATURE_FIND_QUIT is not set +# CONFIG_FEATURE_FIND_DELETE is not set +# CONFIG_FEATURE_FIND_EMPTY is not set +# CONFIG_FEATURE_FIND_PATH is not set +# CONFIG_FEATURE_FIND_REGEX is not set +# CONFIG_FEATURE_FIND_CONTEXT is not set +# CONFIG_FEATURE_FIND_LINKS is not set +# CONFIG_GREP is not set +# CONFIG_EGREP is not set +# CONFIG_FGREP is not set +# CONFIG_FEATURE_GREP_CONTEXT is not set +# CONFIG_XARGS is not set +# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set +# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set +# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set +# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set +# CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE is not set + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +# CONFIG_HALT is not set +# CONFIG_POWEROFF is not set +# CONFIG_REBOOT is not set +# CONFIG_FEATURE_WAIT_FOR_INIT is not set +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" +# CONFIG_INIT is not set +# CONFIG_LINUXRC is not set +# CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +# CONFIG_FEATURE_INIT_QUIET is not set +# CONFIG_FEATURE_INIT_COREDUMPS is not set +CONFIG_INIT_TERMINAL_TYPE="" +# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set + +# +# Login/Password Management Utilities +# +# CONFIG_FEATURE_SHADOWPASSWDS is not set +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +# CONFIG_USE_BB_CRYPT is not set +# CONFIG_USE_BB_CRYPT_SHA is not set +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +# CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_LAST_ID=0 +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 +# CONFIG_CHPASSWD is not set +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="sha512" +CONFIG_CRYPTPW=y +# CONFIG_MKPASSWD is not set +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_GETTY is not set +# CONFIG_LOGIN is not set +# CONFIG_LOGIN_SESSION_AS_CHILD is not set +# CONFIG_LOGIN_SCRIPTS is not set +# CONFIG_FEATURE_NOLOGIN is not set +# CONFIG_FEATURE_SECURETTY is not set +# CONFIG_PASSWD is not set +# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set +# CONFIG_SU is not set +# CONFIG_FEATURE_SU_SYSLOG is not set +# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +# CONFIG_FSCK is not set +# CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux Module Utilities +# +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_DEPMOD is not set +# CONFIG_INSMOD is not set +# CONFIG_LSMOD is not set +# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_MODINFO is not set +# CONFIG_MODPROBE is not set +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_RMMOD is not set + +# +# Options common to multiple modutils +# +# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_DEFAULT_MODULES_DIR="" +CONFIG_DEFAULT_DEPMOD_FILE="" + +# +# Linux System Utilities +# +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +# CONFIG_BLKDISCARD is not set +# CONFIG_BLKID is not set +# CONFIG_FEATURE_BLKID_TYPE is not set +# CONFIG_BLOCKDEV is not set +# CONFIG_CAL is not set +# CONFIG_CHRT is not set +# CONFIG_DMESG is not set +# CONFIG_FEATURE_DMESG_PRETTY is not set +# CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +# CONFIG_FALLOCATE is not set +# CONFIG_FATATTR is not set +# CONFIG_FBSET is not set +# CONFIG_FEATURE_FBSET_FANCY is not set +# CONFIG_FEATURE_FBSET_READMODE is not set +# CONFIG_FDFORMAT is not set +# CONFIG_FDISK is not set +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_FEATURE_FDISK_WRITABLE is not set +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +# CONFIG_FEATURE_GPT_LABEL is not set +# CONFIG_FEATURE_FDISK_ADVANCED is not set +# CONFIG_FINDFS is not set +# CONFIG_FLOCK is not set +# CONFIG_FDFLUSH is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +# CONFIG_FSFREEZE is not set +# CONFIG_FSTRIM is not set +# CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set +# CONFIG_HEXDUMP is not set +# CONFIG_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_HD is not set +# CONFIG_XXD is not set +# CONFIG_HWCLOCK is not set +# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_IONICE is not set +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set +# CONFIG_LOSETUP is not set +# CONFIG_LSPCI is not set +# CONFIG_LSUSB is not set +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_FEATURE_MDEV_DAEMON is not set +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +# CONFIG_MKE2FS is not set +# CONFIG_MKFS_EXT2 is not set +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +# CONFIG_MKDOSFS is not set +# CONFIG_MKFS_VFAT is not set +# CONFIG_MKSWAP is not set +# CONFIG_FEATURE_MKSWAP_UUID is not set +# CONFIG_MORE is not set +# CONFIG_MOUNT is not set +# CONFIG_FEATURE_MOUNT_FAKE is not set +# CONFIG_FEATURE_MOUNT_VERBOSE is not set +# CONFIG_FEATURE_MOUNT_HELPERS is not set +# CONFIG_FEATURE_MOUNT_LABEL is not set +# CONFIG_FEATURE_MOUNT_NFS is not set +# CONFIG_FEATURE_MOUNT_CIFS is not set +# CONFIG_FEATURE_MOUNT_FLAGS is not set +# CONFIG_FEATURE_MOUNT_FSTAB is not set +# CONFIG_FEATURE_MOUNT_OTHERTAB is not set +# CONFIG_MOUNTPOINT is not set +# CONFIG_NOLOGIN is not set +# CONFIG_NOLOGIN_DEPENDENCIES is not set +# CONFIG_NSENTER is not set +# CONFIG_PIVOT_ROOT is not set +# CONFIG_RDATE is not set +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +# CONFIG_RENICE is not set +# CONFIG_REV is not set +# CONFIG_RTCWAKE is not set +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +# CONFIG_LINUX32 is not set +# CONFIG_LINUX64 is not set +# CONFIG_SETPRIV is not set +# CONFIG_FEATURE_SETPRIV_DUMP is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITIES is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES is not set +# CONFIG_SETSID is not set +# CONFIG_SWAPON is not set +# CONFIG_FEATURE_SWAPON_DISCARD is not set +# CONFIG_FEATURE_SWAPON_PRI is not set +# CONFIG_SWAPOFF is not set +# CONFIG_FEATURE_SWAPONOFF_LABEL is not set +# CONFIG_SWITCH_ROOT is not set +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +# CONFIG_UEVENT is not set +# CONFIG_UMOUNT is not set +# CONFIG_FEATURE_UMOUNT_ALL is not set +# CONFIG_UNSHARE is not set +# CONFIG_WALL is not set +# CONFIG_FEATURE_MOUNT_LOOP is not set +# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set +# CONFIG_FEATURE_MTAB_SUPPORT is not set +# CONFIG_VOLUMEID is not set +# CONFIG_FEATURE_VOLUMEID_BCACHE is not set +# CONFIG_FEATURE_VOLUMEID_BTRFS is not set +# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set +# CONFIG_FEATURE_VOLUMEID_EXFAT is not set +# CONFIG_FEATURE_VOLUMEID_EXT is not set +# CONFIG_FEATURE_VOLUMEID_F2FS is not set +# CONFIG_FEATURE_VOLUMEID_FAT is not set +# CONFIG_FEATURE_VOLUMEID_HFS is not set +# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set +# CONFIG_FEATURE_VOLUMEID_JFS is not set +# CONFIG_FEATURE_VOLUMEID_LFS is not set +# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set +# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set +# CONFIG_FEATURE_VOLUMEID_LUKS is not set +# CONFIG_FEATURE_VOLUMEID_MINIX is not set +# CONFIG_FEATURE_VOLUMEID_NILFS is not set +# CONFIG_FEATURE_VOLUMEID_NTFS is not set +# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set +# CONFIG_FEATURE_VOLUMEID_REISERFS is not set +# CONFIG_FEATURE_VOLUMEID_ROMFS is not set +# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set +# CONFIG_FEATURE_VOLUMEID_SYSV is not set +# CONFIG_FEATURE_VOLUMEID_UBIFS is not set +# CONFIG_FEATURE_VOLUMEID_UDF is not set +# CONFIG_FEATURE_VOLUMEID_XFS is not set + +# +# Miscellaneous Utilities +# +# CONFIG_ADJTIMEX is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BC is not set +# CONFIG_DC is not set +# CONFIG_FEATURE_DC_BIG is not set +# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_FEATURE_BC_INTERACTIVE is not set +# CONFIG_FEATURE_BC_LONG_OPTIONS is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CONSPY is not set +# CONFIG_CROND is not set +# CONFIG_FEATURE_CROND_D is not set +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set +CONFIG_FEATURE_CROND_DIR="" +# CONFIG_CRONTAB is not set +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set +# CONFIG_FBSPLASH is not set +# CONFIG_FLASH_ERASEALL is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASHCP is not set +# CONFIG_HDPARM is not set +# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_HEXEDIT is not set +# CONFIG_I2CGET is not set +# CONFIG_I2CSET is not set +# CONFIG_I2CDUMP is not set +# CONFIG_I2CDETECT is not set +# CONFIG_I2CTRANSFER is not set +# CONFIG_INOTIFYD is not set +# CONFIG_LESS is not set +CONFIG_FEATURE_LESS_MAXLINES=0 +# CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_FEATURE_LESS_TRUNCATE is not set +# CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set +# CONFIG_FEATURE_LESS_RAW is not set +# CONFIG_FEATURE_LESS_ENV is not set +# CONFIG_LSSCSI is not set +# CONFIG_MAKEDEVS is not set +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MT is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +# CONFIG_PARTPROBE is not set +# CONFIG_RAIDAUTORUN is not set +# CONFIG_READAHEAD is not set +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +# CONFIG_SETFATTR is not set +# CONFIG_SETSERIAL is not set +# CONFIG_STRINGS is not set +# CONFIG_TIME is not set +# CONFIG_TS is not set +# CONFIG_TTYSIZE is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +# CONFIG_UBIMKVOL is not set +# CONFIG_UBIRMVOL is not set +# CONFIG_UBIRSVOL is not set +# CONFIG_UBIUPDATEVOL is not set +# CONFIG_UBIRENAME is not set +# CONFIG_VOLNAME is not set +# CONFIG_WATCHDOG is not set + +# +# Networking Utilities +# +# CONFIG_FEATURE_IPV6 is not set +# CONFIG_FEATURE_UNIX_LOCAL is not set +# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +# CONFIG_ARP is not set +# CONFIG_ARPING is not set +# CONFIG_BRCTL is not set +# CONFIG_FEATURE_BRCTL_FANCY is not set +# CONFIG_FEATURE_BRCTL_SHOW is not set +# CONFIG_DNSD is not set +# CONFIG_ETHER_WAKE is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTPD_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set +# CONFIG_FTPGET is not set +# CONFIG_FTPPUT is not set +# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_HOSTNAME is not set +# CONFIG_DNSDOMAINNAME is not set +# CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set +# CONFIG_FEATURE_HTTPD_SETUID is not set +# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_FEATURE_HTTPD_CGI is not set +# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set +# CONFIG_IFCONFIG is not set +# CONFIG_FEATURE_IFCONFIG_STATUS is not set +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +# CONFIG_FEATURE_IFCONFIG_HW is not set +# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set +# CONFIG_IFUP is not set +# CONFIG_IFDOWN is not set +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +# CONFIG_IP is not set +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +# CONFIG_IPNEIGH is not set +# CONFIG_FEATURE_IP_ADDRESS is not set +# CONFIG_FEATURE_IP_LINK is not set +# CONFIG_FEATURE_IP_ROUTE is not set +CONFIG_FEATURE_IP_ROUTE_DIR="" +# CONFIG_FEATURE_IP_TUNNEL is not set +# CONFIG_FEATURE_IP_RULE is not set +# CONFIG_FEATURE_IP_NEIGH is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_IPCALC is not set +# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_FEATURE_IPCALC_FANCY is not set +# CONFIG_FAKEIDENTD is not set +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +# CONFIG_NBDCLIENT is not set +# CONFIG_NC is not set +# CONFIG_NETCAT is not set +# CONFIG_NC_SERVER is not set +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +# CONFIG_NETSTAT is not set +# CONFIG_FEATURE_NETSTAT_WIDE is not set +# CONFIG_FEATURE_NETSTAT_PRG is not set +# CONFIG_NSLOOKUP is not set +# CONFIG_FEATURE_NSLOOKUP_BIG is not set +# CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS is not set +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set +# CONFIG_FEATURE_NTPD_CONF is not set +# CONFIG_FEATURE_NTP_AUTH is not set +# CONFIG_PING is not set +# CONFIG_PING6 is not set +# CONFIG_FEATURE_FANCY_PING is not set +# CONFIG_PSCAN is not set +# CONFIG_ROUTE is not set +# CONFIG_SLATTACH is not set +# CONFIG_SSL_CLIENT is not set +# CONFIG_TC is not set +# CONFIG_FEATURE_TC_INGRESS is not set +# CONFIG_TCPSVD is not set +# CONFIG_UDPSVD is not set +# CONFIG_TELNET is not set +# CONFIG_FEATURE_TELNET_TTYPE is not set +# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_FEATURE_TELNET_WIDTH is not set +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_FEATURE_TFTP_HPA_COMPAT is not set +# CONFIG_TFTPD is not set +# CONFIG_FEATURE_TFTP_GET is not set +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_TFTP_DEBUG is not set +# CONFIG_TLS is not set +# CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set +# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +# CONFIG_VCONFIG is not set +# CONFIG_WGET is not set +# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set +# CONFIG_FEATURE_WGET_STATUSBAR is not set +# CONFIG_FEATURE_WGET_AUTHENTICATION is not set +# CONFIG_FEATURE_WGET_TIMEOUT is not set +# CONFIG_FEATURE_WGET_HTTPS is not set +# CONFIG_FEATURE_WGET_OPENSSL is not set +# CONFIG_WHOIS is not set +# CONFIG_ZCIP is not set +# CONFIG_UDHCPD is not set +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +CONFIG_DHCPD_LEASES_FILE="" +# CONFIG_DUMPLEASES is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_UDHCPC is not set +# CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="" +# CONFIG_UDHCPC6 is not set +# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_FEATURE_UDHCPC6_RFC5970 is not set +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +# CONFIG_FEATURE_UDHCP_8021Q is not set +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" + +# +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set +CONFIG_FEATURE_MIME_CHARSET="" + +# +# Process Utilities +# +# CONFIG_FREE is not set +# CONFIG_FUSER is not set +# CONFIG_IOSTAT is not set +# CONFIG_KILL is not set +# CONFIG_KILLALL is not set +# CONFIG_KILLALL5 is not set +# CONFIG_LSOF is not set +# CONFIG_MPSTAT is not set +# CONFIG_NMETER is not set +# CONFIG_PGREP is not set +# CONFIG_PKILL is not set +# CONFIG_PIDOF is not set +# CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_FEATURE_PIDOF_OMIT is not set +# CONFIG_PMAP is not set +# CONFIG_POWERTOP is not set +# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set +# CONFIG_PS is not set +# CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_FEATURE_PS_LONG is not set +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_PSTREE is not set +# CONFIG_PWDX is not set +# CONFIG_SMEMCAP is not set +# CONFIG_BB_SYSCTL is not set +# CONFIG_TOP is not set +# CONFIG_FEATURE_TOP_INTERACTIVE is not set +# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set +# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set +# CONFIG_FEATURE_TOP_SMP_CPU is not set +# CONFIG_FEATURE_TOP_DECIMALS is not set +# CONFIG_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_FEATURE_TOPMEM is not set +# CONFIG_UPTIME is not set +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_WATCH is not set +# CONFIG_FEATURE_SHOW_THREADS is not set + +# +# Runit Utilities +# +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVC is not set +# CONFIG_SVOK is not set +# CONFIG_SVLOGD is not set +# CONFIG_CHCON is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RUNCON is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set +# CONFIG_SETSEBOOL is not set + +# +# Shells +# +# CONFIG_SH_IS_ASH is not set +# CONFIG_SH_IS_HUSH is not set +CONFIG_SH_IS_NONE=y +# CONFIG_BASH_IS_ASH is not set +# CONFIG_BASH_IS_HUSH is not set +CONFIG_BASH_IS_NONE=y +# CONFIG_ASH is not set +# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set +# CONFIG_ASH_INTERNAL_GLOB is not set +# CONFIG_ASH_BASH_COMPAT is not set +# CONFIG_ASH_BASH_SOURCE_CURDIR is not set +# CONFIG_ASH_BASH_NOT_FOUND_HOOK is not set +# CONFIG_ASH_JOB_CONTROL is not set +# CONFIG_ASH_ALIAS is not set +# CONFIG_ASH_RANDOM_SUPPORT is not set +# CONFIG_ASH_EXPAND_PRMT is not set +# CONFIG_ASH_IDLE_TIMEOUT is not set +# CONFIG_ASH_MAIL is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set +# CONFIG_ASH_HELP is not set +# CONFIG_ASH_GETOPTS is not set +# CONFIG_ASH_CMDCMD is not set +# CONFIG_CTTYHACK is not set +# CONFIG_HUSH is not set +# CONFIG_SHELL_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +# CONFIG_FEATURE_SH_MATH is not set +# CONFIG_FEATURE_SH_MATH_64 is not set +# CONFIG_FEATURE_SH_MATH_BASE is not set +# CONFIG_FEATURE_SH_EXTRA_QUIET is not set +# CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_FEATURE_SH_NOFORK is not set +# CONFIG_FEATURE_SH_READ_FRAC is not set +# CONFIG_FEATURE_SH_HISTFILESIZE is not set +# CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS is not set + +# +# System Logging Utilities +# +# CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set +# CONFIG_LOGGER is not set +# CONFIG_LOGREAD is not set +# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_SYSLOGD is not set +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_FEATURE_IPC_SYSLOG is not set +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_FEATURE_KMSG_SYSLOG is not set diff --git a/packages/sysutils/busybox/config/busybox-init.conf b/packages/sysutils/busybox/config/busybox-init.conf new file mode 100644 index 000000000..cbf36366d --- /dev/null +++ b/packages/sysutils/busybox/config/busybox-init.conf @@ -0,0 +1,1186 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.31.0 +# Tue Aug 13 17:29:50 2019 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Settings +# +# CONFIG_DESKTOP is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_FEDORA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +CONFIG_LONG_OPTS=y +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +# CONFIG_FEATURE_COMPRESS_USAGE is not set +CONFIG_LFS=y +# CONFIG_PAM is not set +CONFIG_FEATURE_DEVPTS=y +# CONFIG_FEATURE_UTMP is not set +# CONFIG_FEATURE_WTMP is not set +# CONFIG_FEATURE_PIDFILE is not set +CONFIG_PID_FILE_PATH="" +CONFIG_BUSYBOX=y +CONFIG_FEATURE_SHOW_SCRIPT=y +# CONFIG_FEATURE_INSTALLER is not set +CONFIG_INSTALL_NO_USR=y +# CONFIG_FEATURE_SUID is not set +# CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set +CONFIG_FEATURE_PREFER_APPLETS=y +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +# CONFIG_FEATURE_SYSLOG_INFO is not set +# CONFIG_FEATURE_SYSLOG is not set +CONFIG_PLATFORM_LINUX=y + +# +# Build Options +# +# CONFIG_STATIC is not set +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_SYSROOT="" +CONFIG_EXTRA_CFLAGS="" +CONFIG_EXTRA_LDFLAGS="" +CONFIG_EXTRA_LDLIBS="-ltirpc -lpthread" +# CONFIG_USE_PORTABLE_CODE is not set +# CONFIG_STACK_OPTIMIZATION_386 is not set + +# +# Installation Options ("make install" behavior) +# +# CONFIG_INSTALL_APPLET_SYMLINKS is not set +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +CONFIG_INSTALL_APPLET_DONT=y +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install-initramfs" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set +# CONFIG_UNIT_TEST is not set +# CONFIG_WERROR is not set +# CONFIG_WARN_SIMPLE_MSG is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Library Tuning +# +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y +# CONFIG_FEATURE_RTMINMAX is not set +# CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS is not set +# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SMALL=0 +CONFIG_SHA3_SMALL=0 +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=15 +# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set +# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set +# CONFIG_FEATURE_REVERSE_SEARCH is not set +CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_FEATURE_USERNAME_COMPLETION is not set +# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set +# CONFIG_FEATURE_EDITING_WINCH is not set +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +# CONFIG_LOCALE_SUPPORT is not set +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_FEATURE_NON_POSIX_CP is not set +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +CONFIG_FEATURE_SKIP_ROOTFS=y +# CONFIG_MONOTONIC_SYSCALL is not set +# CONFIG_IOCTL_HEX2STR_ERROR is not set +# CONFIG_FEATURE_HWIB is not set + +# +# Applets +# + +# +# Archival Utilities +# +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +# CONFIG_FEATURE_SEAMLESS_Z is not set +# CONFIG_AR is not set +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_FEATURE_AR_CREATE is not set +# CONFIG_UNCOMPRESS is not set +CONFIG_GUNZIP=y +# CONFIG_ZCAT is not set +# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set +# CONFIG_BUNZIP2 is not set +# CONFIG_BZCAT is not set +# CONFIG_UNLZMA is not set +# CONFIG_LZCAT is not set +# CONFIG_LZMA is not set +# CONFIG_UNXZ is not set +# CONFIG_XZCAT is not set +# CONFIG_XZ is not set +# CONFIG_BZIP2 is not set +CONFIG_BZIP2_SMALL=0 +# CONFIG_FEATURE_BZIP2_DECOMPRESS is not set +# CONFIG_CPIO is not set +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +CONFIG_GZIP=y +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_GZIP_FAST=0 +CONFIG_FEATURE_GZIP_LEVELS=y +CONFIG_FEATURE_GZIP_DECOMPRESS=y +# CONFIG_LZOP is not set +# CONFIG_UNLZOP is not set +# CONFIG_LZOPCAT is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM is not set +# CONFIG_RPM2CPIO is not set +CONFIG_TAR=y +# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_FEATURE_TAR_CREATE is not set +CONFIG_FEATURE_TAR_AUTODETECT=y +# CONFIG_FEATURE_TAR_FROM is not set +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNZIP is not set +# CONFIG_FEATURE_UNZIP_CDF is not set +# CONFIG_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_FEATURE_UNZIP_LZMA is not set +# CONFIG_FEATURE_UNZIP_XZ is not set +# CONFIG_FEATURE_LZMA_FAST is not set + +# +# Coreutils +# +CONFIG_BASENAME=y +CONFIG_CAT=y +CONFIG_FEATURE_CATN=y +# CONFIG_FEATURE_CATV is not set +# CONFIG_CHGRP is not set +# CONFIG_CHMOD is not set +# CONFIG_CHOWN is not set +# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set +CONFIG_CHROOT=y +# CONFIG_CKSUM is not set +# CONFIG_COMM is not set +CONFIG_CP=y +# CONFIG_FEATURE_CP_LONG_OPTIONS is not set +# CONFIG_FEATURE_CP_REFLINK is not set +# CONFIG_CUT is not set +# CONFIG_DATE is not set +# CONFIG_FEATURE_DATE_ISOFMT is not set +# CONFIG_FEATURE_DATE_NANO is not set +# CONFIG_FEATURE_DATE_COMPAT is not set +CONFIG_DD=y +CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y +CONFIG_FEATURE_DD_IBS_OBS=y +CONFIG_FEATURE_DD_STATUS=y +CONFIG_DF=y +# CONFIG_FEATURE_DF_FANCY is not set +# CONFIG_DIRNAME is not set +# CONFIG_DOS2UNIX is not set +# CONFIG_UNIX2DOS is not set +# CONFIG_DU is not set +# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set +# CONFIG_ECHO is not set +CONFIG_FEATURE_FANCY_ECHO=y +# CONFIG_ENV is not set +# CONFIG_EXPAND is not set +# CONFIG_UNEXPAND is not set +# CONFIG_EXPR is not set +# CONFIG_EXPR_MATH_SUPPORT_64 is not set +# CONFIG_FACTOR is not set +# CONFIG_FALSE is not set +# CONFIG_FOLD is not set +CONFIG_HEAD=y +# CONFIG_FEATURE_FANCY_HEAD is not set +# CONFIG_HOSTID is not set +# CONFIG_ID is not set +# CONFIG_GROUPS is not set +# CONFIG_INSTALL is not set +# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set +# CONFIG_LINK is not set +# CONFIG_LN is not set +# CONFIG_LOGNAME is not set +CONFIG_LS=y +# CONFIG_FEATURE_LS_FILETYPES is not set +# CONFIG_FEATURE_LS_FOLLOWLINKS is not set +# CONFIG_FEATURE_LS_RECURSIVE is not set +# CONFIG_FEATURE_LS_WIDTH is not set +# CONFIG_FEATURE_LS_SORTFILES is not set +# CONFIG_FEATURE_LS_TIMESTAMPS is not set +# CONFIG_FEATURE_LS_USERNAME is not set +# CONFIG_FEATURE_LS_COLOR is not set +# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set +CONFIG_MD5SUM=y +# CONFIG_SHA1SUM is not set +CONFIG_SHA256SUM=y +# CONFIG_SHA512SUM is not set +# CONFIG_SHA3SUM is not set + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum +# +CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_MKDIR=y +# CONFIG_MKFIFO is not set +CONFIG_MKNOD=y +# CONFIG_MKTEMP is not set +CONFIG_MV=y +CONFIG_NICE=y +# CONFIG_NL is not set +# CONFIG_NOHUP is not set +# CONFIG_NPROC is not set +# CONFIG_OD is not set +# CONFIG_PASTE is not set +# CONFIG_PRINTENV is not set +# CONFIG_PRINTF is not set +# CONFIG_PWD is not set +# CONFIG_READLINK is not set +# CONFIG_FEATURE_READLINK_FOLLOW is not set +# CONFIG_REALPATH is not set +CONFIG_RM=y +# CONFIG_RMDIR is not set +# CONFIG_SEQ is not set +# CONFIG_SHRED is not set +# CONFIG_SHUF is not set +CONFIG_SLEEP=y +# CONFIG_FEATURE_FANCY_SLEEP is not set +CONFIG_SORT=y +# CONFIG_FEATURE_SORT_BIG is not set +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +CONFIG_STAT=y +# CONFIG_FEATURE_STAT_FORMAT is not set +# CONFIG_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_STTY is not set +# CONFIG_SUM is not set +CONFIG_SYNC=y +CONFIG_FEATURE_SYNC_FANCY=y +# CONFIG_FSYNC is not set +# CONFIG_TAC is not set +CONFIG_TAIL=y +CONFIG_FEATURE_FANCY_TAIL=y +CONFIG_TEE=y +CONFIG_FEATURE_TEE_USE_BLOCK_IO=y +# CONFIG_TEST is not set +# CONFIG_TEST1 is not set +# CONFIG_TEST2 is not set +CONFIG_FEATURE_TEST_64=y +# CONFIG_TIMEOUT is not set +# CONFIG_TOUCH is not set +# CONFIG_FEATURE_TOUCH_NODEREF is not set +# CONFIG_FEATURE_TOUCH_SUSV3 is not set +CONFIG_TR=y +CONFIG_FEATURE_TR_CLASSES=y +CONFIG_FEATURE_TR_EQUIV=y +# CONFIG_TRUE is not set +# CONFIG_TRUNCATE is not set +# CONFIG_TTY is not set +CONFIG_UNAME=y +CONFIG_UNAME_OSNAME="GNU/Linux" +# CONFIG_BB_ARCH is not set +# CONFIG_UNIQ is not set +# CONFIG_UNLINK is not set +CONFIG_USLEEP=y +# CONFIG_UUDECODE is not set +# CONFIG_BASE64 is not set +# CONFIG_UUENCODE is not set +# CONFIG_WC is not set +# CONFIG_FEATURE_WC_LARGE is not set +# CONFIG_WHO is not set +# CONFIG_W is not set +# CONFIG_USERS is not set +# CONFIG_WHOAMI is not set +# CONFIG_YES is not set + +# +# Common options +# +# CONFIG_FEATURE_VERBOSE is not set + +# +# Common options for cp and mv +# +# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set + +# +# Common options for df, du, ls +# +# CONFIG_FEATURE_HUMAN_READABLE is not set + +# +# Console Utilities +# +CONFIG_CHVT=y +CONFIG_CLEAR=y +# CONFIG_DEALLOCVT is not set +# CONFIG_DUMPKMAP is not set +# CONFIG_FGCONSOLE is not set +# CONFIG_KBD_MODE is not set +CONFIG_LOADFONT=y +CONFIG_SETFONT=y +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="/usr/share" + +# +# Common options for loadfont and setfont +# +CONFIG_FEATURE_LOADFONT_PSF2=y +CONFIG_FEATURE_LOADFONT_RAW=y +# CONFIG_LOADKMAP is not set +# CONFIG_OPENVT is not set +# CONFIG_RESET is not set +# CONFIG_RESIZE is not set +# CONFIG_FEATURE_RESIZE_PRINT is not set +# CONFIG_SETCONSOLE is not set +# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_SETKEYCODES is not set +# CONFIG_SETLOGCONS is not set +# CONFIG_SHOWKEY is not set + +# +# Debian Utilities +# +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_WHICH is not set + +# +# klibc-utils +# +# CONFIG_MINIPS is not set +# CONFIG_NUKE is not set +# CONFIG_RESUME is not set +# CONFIG_RUN_INIT is not set + +# +# Editors +# +CONFIG_AWK=y +# CONFIG_FEATURE_AWK_LIBM is not set +CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y +# CONFIG_CMP is not set +# CONFIG_DIFF is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_ED is not set +# CONFIG_PATCH is not set +CONFIG_SED=y +CONFIG_VI=y +CONFIG_FEATURE_VI_MAX_LEN=4096 +# CONFIG_FEATURE_VI_8BIT is not set +CONFIG_FEATURE_VI_COLON=y +CONFIG_FEATURE_VI_YANKMARK=y +CONFIG_FEATURE_VI_SEARCH=y +# CONFIG_FEATURE_VI_REGEX_SEARCH is not set +CONFIG_FEATURE_VI_USE_SIGNALS=y +CONFIG_FEATURE_VI_DOT_CMD=y +CONFIG_FEATURE_VI_READONLY=y +CONFIG_FEATURE_VI_SETOPTS=y +CONFIG_FEATURE_VI_SET=y +CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_FEATURE_VI_ASK_TERMINAL=y +CONFIG_FEATURE_VI_UNDO=y +CONFIG_FEATURE_VI_UNDO_QUEUE=y +CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 +CONFIG_FEATURE_ALLOW_EXEC=y + +# +# Finding Utilities +# +# CONFIG_FIND is not set +# CONFIG_FEATURE_FIND_PRINT0 is not set +# CONFIG_FEATURE_FIND_MTIME is not set +# CONFIG_FEATURE_FIND_MMIN is not set +# CONFIG_FEATURE_FIND_PERM is not set +# CONFIG_FEATURE_FIND_TYPE is not set +# CONFIG_FEATURE_FIND_EXECUTABLE is not set +# CONFIG_FEATURE_FIND_XDEV is not set +# CONFIG_FEATURE_FIND_MAXDEPTH is not set +# CONFIG_FEATURE_FIND_NEWER is not set +# CONFIG_FEATURE_FIND_INUM is not set +# CONFIG_FEATURE_FIND_EXEC is not set +# CONFIG_FEATURE_FIND_EXEC_PLUS is not set +# CONFIG_FEATURE_FIND_USER is not set +# CONFIG_FEATURE_FIND_GROUP is not set +# CONFIG_FEATURE_FIND_NOT is not set +# CONFIG_FEATURE_FIND_DEPTH is not set +# CONFIG_FEATURE_FIND_PAREN is not set +# CONFIG_FEATURE_FIND_SIZE is not set +# CONFIG_FEATURE_FIND_PRUNE is not set +# CONFIG_FEATURE_FIND_QUIT is not set +# CONFIG_FEATURE_FIND_DELETE is not set +# CONFIG_FEATURE_FIND_EMPTY is not set +# CONFIG_FEATURE_FIND_PATH is not set +# CONFIG_FEATURE_FIND_REGEX is not set +# CONFIG_FEATURE_FIND_CONTEXT is not set +# CONFIG_FEATURE_FIND_LINKS is not set +CONFIG_GREP=y +# CONFIG_EGREP is not set +# CONFIG_FGREP is not set +CONFIG_FEATURE_GREP_CONTEXT=y +# CONFIG_XARGS is not set +# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set +# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set +# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set +# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set +# CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE is not set + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_HALT=y +CONFIG_POWEROFF=y +CONFIG_REBOOT=y +CONFIG_FEATURE_WAIT_FOR_INIT=y +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" +# CONFIG_INIT is not set +# CONFIG_LINUXRC is not set +# CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +# CONFIG_FEATURE_INIT_QUIET is not set +# CONFIG_FEATURE_INIT_COREDUMPS is not set +CONFIG_INIT_TERMINAL_TYPE="" +# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set + +# +# Login/Password Management Utilities +# +# CONFIG_FEATURE_SHADOWPASSWDS is not set +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +# CONFIG_USE_BB_CRYPT is not set +# CONFIG_USE_BB_CRYPT_SHA is not set +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +# CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_LAST_ID=0 +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 +# CONFIG_CHPASSWD is not set +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="" +# CONFIG_CRYPTPW is not set +# CONFIG_MKPASSWD is not set +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_GETTY is not set +# CONFIG_LOGIN is not set +# CONFIG_LOGIN_SESSION_AS_CHILD is not set +# CONFIG_LOGIN_SCRIPTS is not set +# CONFIG_FEATURE_NOLOGIN is not set +# CONFIG_FEATURE_SECURETTY is not set +# CONFIG_PASSWD is not set +# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set +# CONFIG_SU is not set +# CONFIG_FEATURE_SU_SYSLOG is not set +# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +# CONFIG_FSCK is not set +# CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux Module Utilities +# +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_DEPMOD is not set +CONFIG_INSMOD=y +# CONFIG_LSMOD is not set +# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_MODINFO is not set +# CONFIG_MODPROBE is not set +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_RMMOD is not set + +# +# Options common to multiple modutils +# +# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_DEFAULT_MODULES_DIR="" +CONFIG_DEFAULT_DEPMOD_FILE="" + +# +# Linux System Utilities +# +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +# CONFIG_BLKDISCARD is not set +CONFIG_BLKID=y +CONFIG_FEATURE_BLKID_TYPE=y +# CONFIG_BLOCKDEV is not set +# CONFIG_CAL is not set +# CONFIG_CHRT is not set +CONFIG_DMESG=y +# CONFIG_FEATURE_DMESG_PRETTY is not set +# CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +# CONFIG_FALLOCATE is not set +# CONFIG_FATATTR is not set +CONFIG_FBSET=y +CONFIG_FEATURE_FBSET_FANCY=y +CONFIG_FEATURE_FBSET_READMODE=y +# CONFIG_FDFORMAT is not set +CONFIG_FDISK=y +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +CONFIG_FEATURE_FDISK_WRITABLE=y +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +CONFIG_FEATURE_GPT_LABEL=y +# CONFIG_FEATURE_FDISK_ADVANCED is not set +# CONFIG_FINDFS is not set +# CONFIG_FLOCK is not set +# CONFIG_FDFLUSH is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +# CONFIG_FSFREEZE is not set +# CONFIG_FSTRIM is not set +# CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set +# CONFIG_HEXDUMP is not set +# CONFIG_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_HD is not set +# CONFIG_XXD is not set +# CONFIG_HWCLOCK is not set +# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +CONFIG_IONICE=y +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set +CONFIG_LOSETUP=y +# CONFIG_LSPCI is not set +# CONFIG_LSUSB is not set +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_FEATURE_MDEV_DAEMON is not set +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +# CONFIG_MKE2FS is not set +# CONFIG_MKFS_EXT2 is not set +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +# CONFIG_MKDOSFS is not set +# CONFIG_MKFS_VFAT is not set +# CONFIG_MKSWAP is not set +# CONFIG_FEATURE_MKSWAP_UUID is not set +# CONFIG_MORE is not set +CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +# CONFIG_FEATURE_MOUNT_VERBOSE is not set +# CONFIG_FEATURE_MOUNT_HELPERS is not set +CONFIG_FEATURE_MOUNT_LABEL=y +# CONFIG_FEATURE_MOUNT_NFS is not set +# CONFIG_FEATURE_MOUNT_CIFS is not set +CONFIG_FEATURE_MOUNT_FLAGS=y +# CONFIG_FEATURE_MOUNT_FSTAB is not set +# CONFIG_FEATURE_MOUNT_OTHERTAB is not set +CONFIG_MOUNTPOINT=y +# CONFIG_NOLOGIN is not set +# CONFIG_NOLOGIN_DEPENDENCIES is not set +# CONFIG_NSENTER is not set +CONFIG_PIVOT_ROOT=y +# CONFIG_RDATE is not set +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +# CONFIG_RENICE is not set +# CONFIG_REV is not set +# CONFIG_RTCWAKE is not set +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +# CONFIG_LINUX32 is not set +# CONFIG_LINUX64 is not set +# CONFIG_SETPRIV is not set +# CONFIG_FEATURE_SETPRIV_DUMP is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITIES is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES is not set +CONFIG_SETSID=y +# CONFIG_SWAPON is not set +# CONFIG_FEATURE_SWAPON_DISCARD is not set +# CONFIG_FEATURE_SWAPON_PRI is not set +# CONFIG_SWAPOFF is not set +# CONFIG_FEATURE_SWAPONOFF_LABEL is not set +CONFIG_SWITCH_ROOT=y +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +CONFIG_UEVENT=y +CONFIG_UMOUNT=y +CONFIG_FEATURE_UMOUNT_ALL=y +# CONFIG_UNSHARE is not set +# CONFIG_WALL is not set + +# +# Common options for mount/umount +# +CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y +# CONFIG_FEATURE_MTAB_SUPPORT is not set +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +# CONFIG_FEATURE_VOLUMEID_BCACHE is not set +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_EXFAT=y +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_F2FS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_JFS=y +# CONFIG_FEATURE_VOLUMEID_LFS is not set +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_MINIX=y +CONFIG_FEATURE_VOLUMEID_NILFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +CONFIG_FEATURE_VOLUMEID_SQUASHFS=y +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_UBIFS=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_XFS=y + +# +# Miscellaneous Utilities +# +# CONFIG_ADJTIMEX is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +CONFIG_BC=y +# CONFIG_DC is not set +# CONFIG_FEATURE_DC_BIG is not set +# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_FEATURE_BC_INTERACTIVE is not set +# CONFIG_FEATURE_BC_LONG_OPTIONS is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CONSPY is not set +# CONFIG_CROND is not set +# CONFIG_FEATURE_CROND_D is not set +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set +CONFIG_FEATURE_CROND_DIR="" +# CONFIG_CRONTAB is not set +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set +# CONFIG_FBSPLASH is not set +CONFIG_FLASH_ERASEALL=y +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASHCP is not set +# CONFIG_HDPARM is not set +# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_HEXEDIT is not set +# CONFIG_I2CGET is not set +# CONFIG_I2CSET is not set +# CONFIG_I2CDUMP is not set +# CONFIG_I2CDETECT is not set +# CONFIG_I2CTRANSFER is not set +# CONFIG_INOTIFYD is not set +CONFIG_LESS=y +CONFIG_FEATURE_LESS_MAXLINES=9999999 +# CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_FEATURE_LESS_TRUNCATE is not set +# CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set +# CONFIG_FEATURE_LESS_RAW is not set +# CONFIG_FEATURE_LESS_ENV is not set +# CONFIG_LSSCSI is not set +# CONFIG_MAKEDEVS is not set +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MT is not set +CONFIG_NANDWRITE=y +# CONFIG_NANDDUMP is not set +# CONFIG_PARTPROBE is not set +# CONFIG_RAIDAUTORUN is not set +# CONFIG_READAHEAD is not set +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +# CONFIG_SETFATTR is not set +# CONFIG_SETSERIAL is not set +# CONFIG_STRINGS is not set +# CONFIG_TIME is not set +# CONFIG_TS is not set +# CONFIG_TTYSIZE is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +# CONFIG_UBIMKVOL is not set +# CONFIG_UBIRMVOL is not set +# CONFIG_UBIRSVOL is not set +# CONFIG_UBIUPDATEVOL is not set +# CONFIG_UBIRENAME is not set +# CONFIG_VOLNAME is not set +# CONFIG_WATCHDOG is not set + +# +# Networking Utilities +# +# CONFIG_FEATURE_IPV6 is not set +# CONFIG_FEATURE_UNIX_LOCAL is not set +# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +# CONFIG_ARP is not set +# CONFIG_ARPING is not set +# CONFIG_BRCTL is not set +# CONFIG_FEATURE_BRCTL_FANCY is not set +# CONFIG_FEATURE_BRCTL_SHOW is not set +# CONFIG_DNSD is not set +CONFIG_ETHER_WAKE=y +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTPD_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set +# CONFIG_FTPGET is not set +# CONFIG_FTPPUT is not set +# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_HOSTNAME is not set +# CONFIG_DNSDOMAINNAME is not set +# CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set +# CONFIG_FEATURE_HTTPD_SETUID is not set +# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_FEATURE_HTTPD_CGI is not set +# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set +# CONFIG_IFCONFIG is not set +# CONFIG_FEATURE_IFCONFIG_STATUS is not set +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +# CONFIG_FEATURE_IFCONFIG_HW is not set +# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set +# CONFIG_IFUP is not set +# CONFIG_IFDOWN is not set +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +# CONFIG_IP is not set +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +# CONFIG_IPNEIGH is not set +# CONFIG_FEATURE_IP_ADDRESS is not set +# CONFIG_FEATURE_IP_LINK is not set +# CONFIG_FEATURE_IP_ROUTE is not set +CONFIG_FEATURE_IP_ROUTE_DIR="" +# CONFIG_FEATURE_IP_TUNNEL is not set +# CONFIG_FEATURE_IP_RULE is not set +# CONFIG_FEATURE_IP_NEIGH is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_IPCALC is not set +# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_FEATURE_IPCALC_FANCY is not set +# CONFIG_FAKEIDENTD is not set +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +CONFIG_NBDCLIENT=y +# CONFIG_NC is not set +# CONFIG_NETCAT is not set +# CONFIG_NC_SERVER is not set +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +# CONFIG_NETSTAT is not set +# CONFIG_FEATURE_NETSTAT_WIDE is not set +# CONFIG_FEATURE_NETSTAT_PRG is not set +# CONFIG_NSLOOKUP is not set +# CONFIG_FEATURE_NSLOOKUP_BIG is not set +# CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS is not set +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set +# CONFIG_FEATURE_NTPD_CONF is not set +# CONFIG_FEATURE_NTP_AUTH is not set +CONFIG_PING=y +# CONFIG_PING6 is not set +CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set +# CONFIG_ROUTE is not set +# CONFIG_SLATTACH is not set +# CONFIG_SSL_CLIENT is not set +# CONFIG_TC is not set +# CONFIG_FEATURE_TC_INGRESS is not set +# CONFIG_TCPSVD is not set +# CONFIG_UDPSVD is not set +# CONFIG_TELNET is not set +# CONFIG_FEATURE_TELNET_TTYPE is not set +# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_FEATURE_TELNET_WIDTH is not set +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_FEATURE_TFTP_HPA_COMPAT is not set +# CONFIG_TFTPD is not set +# CONFIG_FEATURE_TFTP_GET is not set +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_TFTP_DEBUG is not set +# CONFIG_TLS is not set +# CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set +# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +# CONFIG_VCONFIG is not set +# CONFIG_WGET is not set +# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set +# CONFIG_FEATURE_WGET_STATUSBAR is not set +# CONFIG_FEATURE_WGET_AUTHENTICATION is not set +# CONFIG_FEATURE_WGET_TIMEOUT is not set +# CONFIG_FEATURE_WGET_HTTPS is not set +# CONFIG_FEATURE_WGET_OPENSSL is not set +# CONFIG_WHOIS is not set +# CONFIG_ZCIP is not set +# CONFIG_UDHCPD is not set +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +CONFIG_DHCPD_LEASES_FILE="" +# CONFIG_DUMPLEASES is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_UDHCPC is not set +# CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="" +# CONFIG_UDHCPC6 is not set +# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_FEATURE_UDHCPC6_RFC5970 is not set +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +# CONFIG_FEATURE_UDHCP_8021Q is not set +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" + +# +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set +CONFIG_FEATURE_MIME_CHARSET="" + +# +# Process Utilities +# +# CONFIG_FREE is not set +# CONFIG_FUSER is not set +# CONFIG_IOSTAT is not set +# CONFIG_KILL is not set +# CONFIG_KILLALL is not set +# CONFIG_KILLALL5 is not set +# CONFIG_LSOF is not set +# CONFIG_MPSTAT is not set +# CONFIG_NMETER is not set +# CONFIG_PGREP is not set +# CONFIG_PKILL is not set +# CONFIG_PIDOF is not set +# CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_FEATURE_PIDOF_OMIT is not set +# CONFIG_PMAP is not set +# CONFIG_POWERTOP is not set +# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set +# CONFIG_PS is not set +# CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_FEATURE_PS_LONG is not set +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_PSTREE is not set +# CONFIG_PWDX is not set +# CONFIG_SMEMCAP is not set +# CONFIG_BB_SYSCTL is not set +# CONFIG_TOP is not set +# CONFIG_FEATURE_TOP_INTERACTIVE is not set +# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set +# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set +# CONFIG_FEATURE_TOP_SMP_CPU is not set +# CONFIG_FEATURE_TOP_DECIMALS is not set +# CONFIG_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_FEATURE_TOPMEM is not set +# CONFIG_UPTIME is not set +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_WATCH is not set +# CONFIG_FEATURE_SHOW_THREADS is not set + +# +# Runit Utilities +# +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVC is not set +# CONFIG_SVOK is not set +# CONFIG_SVLOGD is not set +# CONFIG_CHCON is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RUNCON is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set +# CONFIG_SETSEBOOL is not set + +# +# Shells +# +CONFIG_SH_IS_ASH=y +# CONFIG_SH_IS_HUSH is not set +# CONFIG_SH_IS_NONE is not set +# CONFIG_BASH_IS_ASH is not set +# CONFIG_BASH_IS_HUSH is not set +CONFIG_BASH_IS_NONE=y +CONFIG_ASH=y +# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set +CONFIG_ASH_INTERNAL_GLOB=y +CONFIG_ASH_BASH_COMPAT=y +# CONFIG_ASH_BASH_SOURCE_CURDIR is not set +# CONFIG_ASH_BASH_NOT_FOUND_HOOK is not set +CONFIG_ASH_JOB_CONTROL=y +# CONFIG_ASH_ALIAS is not set +# CONFIG_ASH_RANDOM_SUPPORT is not set +# CONFIG_ASH_EXPAND_PRMT is not set +# CONFIG_ASH_IDLE_TIMEOUT is not set +# CONFIG_ASH_MAIL is not set +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y +# CONFIG_ASH_HELP is not set +CONFIG_ASH_GETOPTS=y +# CONFIG_ASH_CMDCMD is not set +CONFIG_CTTYHACK=y +# CONFIG_HUSH is not set +# CONFIG_SHELL_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +CONFIG_FEATURE_SH_MATH=y +CONFIG_FEATURE_SH_MATH_64=y +CONFIG_FEATURE_SH_MATH_BASE=y +CONFIG_FEATURE_SH_EXTRA_QUIET=y +CONFIG_FEATURE_SH_STANDALONE=y +# CONFIG_FEATURE_SH_NOFORK is not set +CONFIG_FEATURE_SH_READ_FRAC=y +# CONFIG_FEATURE_SH_HISTFILESIZE is not set +# CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS is not set + +# +# System Logging Utilities +# +# CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set +# CONFIG_LOGGER is not set +# CONFIG_LOGREAD is not set +# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_SYSLOGD is not set +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_FEATURE_IPC_SYSLOG is not set +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_FEATURE_KMSG_SYSLOG is not set diff --git a/packages/sysutils/busybox/config/busybox-target.conf b/packages/sysutils/busybox/config/busybox-target.conf new file mode 100644 index 000000000..d6724f7b9 --- /dev/null +++ b/packages/sysutils/busybox/config/busybox-target.conf @@ -0,0 +1,1182 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.31.0 +# Mon Sep 23 04:46:37 2019 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Settings +# +CONFIG_DESKTOP=y +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_FEDORA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +CONFIG_LONG_OPTS=y +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +CONFIG_FEATURE_COMPRESS_USAGE=y +CONFIG_LFS=y +# CONFIG_PAM is not set +CONFIG_FEATURE_DEVPTS=y +# CONFIG_FEATURE_UTMP is not set +# CONFIG_FEATURE_WTMP is not set +CONFIG_FEATURE_PIDFILE=y +CONFIG_PID_FILE_PATH="/run" +CONFIG_BUSYBOX=y +CONFIG_FEATURE_SHOW_SCRIPT=y +CONFIG_FEATURE_INSTALLER=y +CONFIG_INSTALL_NO_USR=y +CONFIG_FEATURE_SUID=y +# CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set +# CONFIG_FEATURE_PREFER_APPLETS is not set +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_FEATURE_SYSLOG_INFO=y +CONFIG_FEATURE_SYSLOG=y +CONFIG_PLATFORM_LINUX=y + +# +# Build Options +# +# CONFIG_STATIC is not set +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_CROSS_COMPILER_PREFIX="" +CONFIG_SYSROOT="" +CONFIG_EXTRA_CFLAGS="" +CONFIG_EXTRA_LDFLAGS="" +CONFIG_EXTRA_LDLIBS="-ltirpc -lpthread" +# CONFIG_USE_PORTABLE_CODE is not set +# CONFIG_STACK_OPTIMIZATION_386 is not set + +# +# Installation Options ("make install" behavior) +# +CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install-system" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set +# CONFIG_UNIT_TEST is not set +# CONFIG_WERROR is not set +# CONFIG_WARN_SIMPLE_MSG is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Library Tuning +# +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y +CONFIG_FEATURE_RTMINMAX=y +CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y +# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SMALL=0 +CONFIG_SHA3_SMALL=0 +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=200 +CONFIG_FEATURE_EDITING_SAVEHISTORY=y +CONFIG_FEATURE_EDITING_SAVE_ON_EXIT=y +CONFIG_FEATURE_REVERSE_SEARCH=y +CONFIG_FEATURE_TAB_COMPLETION=y +CONFIG_FEATURE_USERNAME_COMPLETION=y +CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_FEATURE_EDITING_WINCH is not set +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +CONFIG_LOCALE_SUPPORT=y +CONFIG_UNICODE_SUPPORT=y +CONFIG_UNICODE_USING_LOCALE=y +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +CONFIG_UNICODE_WIDE_WCHARS=y +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +CONFIG_FEATURE_NON_POSIX_CP=y +CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +CONFIG_FEATURE_SKIP_ROOTFS=y +CONFIG_MONOTONIC_SYSCALL=y +# CONFIG_IOCTL_HEX2STR_ERROR is not set +# CONFIG_FEATURE_HWIB is not set + +# +# Applets +# + +# +# Archival Utilities +# +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +# CONFIG_FEATURE_SEAMLESS_Z is not set +CONFIG_AR=y +CONFIG_FEATURE_AR_LONG_FILENAMES=y +CONFIG_FEATURE_AR_CREATE=y +# CONFIG_UNCOMPRESS is not set +CONFIG_GUNZIP=y +CONFIG_ZCAT=y +# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set +CONFIG_BUNZIP2=y +CONFIG_BZCAT=y +# CONFIG_UNLZMA is not set +# CONFIG_LZCAT is not set +# CONFIG_LZMA is not set +CONFIG_UNXZ=y +CONFIG_XZCAT=y +CONFIG_XZ=y +CONFIG_BZIP2=y +CONFIG_BZIP2_SMALL=8 +CONFIG_FEATURE_BZIP2_DECOMPRESS=y +CONFIG_CPIO=y +CONFIG_FEATURE_CPIO_O=y +CONFIG_FEATURE_CPIO_P=y +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +# CONFIG_GZIP is not set +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +# CONFIG_GZIP_FAST is not set +# CONFIG_FEATURE_GZIP_LEVELS is not set +# CONFIG_FEATURE_GZIP_DECOMPRESS is not set +# CONFIG_LZOP is not set +# CONFIG_UNLZOP is not set +# CONFIG_LZOPCAT is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM is not set +CONFIG_RPM2CPIO=y +CONFIG_TAR=y +CONFIG_FEATURE_TAR_LONG_OPTIONS=y +CONFIG_FEATURE_TAR_CREATE=y +CONFIG_FEATURE_TAR_AUTODETECT=y +CONFIG_FEATURE_TAR_FROM=y +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y +CONFIG_FEATURE_TAR_TO_COMMAND=y +CONFIG_FEATURE_TAR_UNAME_GNAME=y +CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNZIP is not set +# CONFIG_FEATURE_UNZIP_CDF is not set +# CONFIG_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_FEATURE_UNZIP_LZMA is not set +# CONFIG_FEATURE_UNZIP_XZ is not set +# CONFIG_FEATURE_LZMA_FAST is not set + +# +# Coreutils +# +CONFIG_BASENAME=y +CONFIG_CAT=y +CONFIG_FEATURE_CATN=y +# CONFIG_FEATURE_CATV is not set +# CONFIG_CHGRP is not set +CONFIG_CHMOD=y +CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y +CONFIG_CHROOT=y +# CONFIG_CKSUM is not set +# CONFIG_COMM is not set +CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y +CONFIG_FEATURE_CP_REFLINK=y +CONFIG_CUT=y +CONFIG_DATE=y +CONFIG_FEATURE_DATE_ISOFMT=y +CONFIG_FEATURE_DATE_NANO=y +CONFIG_FEATURE_DATE_COMPAT=y +CONFIG_DD=y +CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y +CONFIG_FEATURE_DD_IBS_OBS=y +CONFIG_FEATURE_DD_STATUS=y +CONFIG_DF=y +# CONFIG_FEATURE_DF_FANCY is not set +CONFIG_DIRNAME=y +CONFIG_DOS2UNIX=y +CONFIG_UNIX2DOS=y +CONFIG_DU=y +# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set +# CONFIG_ECHO is not set +CONFIG_FEATURE_FANCY_ECHO=y +CONFIG_ENV=y +# CONFIG_EXPAND is not set +# CONFIG_UNEXPAND is not set +CONFIG_EXPR=y +# CONFIG_EXPR_MATH_SUPPORT_64 is not set +# CONFIG_FACTOR is not set +# CONFIG_FALSE is not set +# CONFIG_FOLD is not set +CONFIG_HEAD=y +CONFIG_FEATURE_FANCY_HEAD=y +# CONFIG_HOSTID is not set +CONFIG_ID=y +CONFIG_GROUPS=y +CONFIG_INSTALL=y +CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y +# CONFIG_LINK is not set +CONFIG_LN=y +# CONFIG_LOGNAME is not set +CONFIG_LS=y +CONFIG_FEATURE_LS_FILETYPES=y +CONFIG_FEATURE_LS_FOLLOWLINKS=y +CONFIG_FEATURE_LS_RECURSIVE=y +# CONFIG_FEATURE_LS_WIDTH is not set +CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_FEATURE_LS_TIMESTAMPS=y +CONFIG_FEATURE_LS_USERNAME=y +CONFIG_FEATURE_LS_COLOR=y +CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_MD5SUM=y +CONFIG_SHA1SUM=y +CONFIG_SHA256SUM=y +CONFIG_SHA512SUM=y +# CONFIG_SHA3SUM is not set + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum +# +CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_MKDIR=y +CONFIG_MKFIFO=y +CONFIG_MKNOD=y +CONFIG_MKTEMP=y +CONFIG_MV=y +CONFIG_NICE=y +# CONFIG_NL is not set +CONFIG_NOHUP=y +# CONFIG_NPROC is not set +CONFIG_OD=y +# CONFIG_PASTE is not set +CONFIG_PRINTENV=y +# CONFIG_PRINTF is not set +CONFIG_PWD=y +CONFIG_READLINK=y +CONFIG_FEATURE_READLINK_FOLLOW=y +CONFIG_REALPATH=y +CONFIG_RM=y +CONFIG_RMDIR=y +CONFIG_SEQ=y +# CONFIG_SHRED is not set +# CONFIG_SHUF is not set +CONFIG_SLEEP=y +CONFIG_FEATURE_FANCY_SLEEP=y +CONFIG_SORT=y +CONFIG_FEATURE_SORT_BIG=y +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +CONFIG_STAT=y +# CONFIG_FEATURE_STAT_FORMAT is not set +# CONFIG_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_STTY is not set +# CONFIG_SUM is not set +CONFIG_SYNC=y +CONFIG_FEATURE_SYNC_FANCY=y +# CONFIG_FSYNC is not set +# CONFIG_TAC is not set +CONFIG_TAIL=y +CONFIG_FEATURE_FANCY_TAIL=y +CONFIG_TEE=y +CONFIG_FEATURE_TEE_USE_BLOCK_IO=y +# CONFIG_TEST is not set +# CONFIG_TEST1 is not set +# CONFIG_TEST2 is not set +CONFIG_FEATURE_TEST_64=y +# CONFIG_TIMEOUT is not set +CONFIG_TOUCH=y +CONFIG_FEATURE_TOUCH_NODEREF=y +CONFIG_FEATURE_TOUCH_SUSV3=y +CONFIG_TR=y +CONFIG_FEATURE_TR_CLASSES=y +CONFIG_FEATURE_TR_EQUIV=y +CONFIG_TRUE=y +# CONFIG_TRUNCATE is not set +# CONFIG_TTY is not set +CONFIG_UNAME=y +CONFIG_UNAME_OSNAME="GNU/Linux" +CONFIG_BB_ARCH=y +CONFIG_UNIQ=y +# CONFIG_UNLINK is not set +CONFIG_USLEEP=y +# CONFIG_UUDECODE is not set +# CONFIG_BASE64 is not set +# CONFIG_UUENCODE is not set +CONFIG_WC=y +CONFIG_FEATURE_WC_LARGE=y +# CONFIG_WHO is not set +# CONFIG_W is not set +# CONFIG_USERS is not set +CONFIG_WHOAMI=y +# CONFIG_YES is not set + +# +# Common options +# +CONFIG_FEATURE_VERBOSE=y + +# +# Common options for cp and mv +# +# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set + +# +# Common options for df, du, ls +# +CONFIG_FEATURE_HUMAN_READABLE=y + +# +# Console Utilities +# +CONFIG_CHVT=y +CONFIG_CLEAR=y +CONFIG_DEALLOCVT=y +# CONFIG_DUMPKMAP is not set +CONFIG_FGCONSOLE=y +# CONFIG_KBD_MODE is not set +CONFIG_LOADFONT=y +CONFIG_SETFONT=y +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="" +CONFIG_FEATURE_LOADFONT_PSF2=y +CONFIG_FEATURE_LOADFONT_RAW=y +CONFIG_LOADKMAP=y +# CONFIG_OPENVT is not set +CONFIG_RESET=y +# CONFIG_RESIZE is not set +# CONFIG_FEATURE_RESIZE_PRINT is not set +CONFIG_SETCONSOLE=y +CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y +# CONFIG_SETKEYCODES is not set +# CONFIG_SETLOGCONS is not set +# CONFIG_SHOWKEY is not set + +# +# Debian Utilities +# +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +CONFIG_WHICH=y + +# +# klibc-utils +# +# CONFIG_MINIPS is not set +# CONFIG_NUKE is not set +# CONFIG_RESUME is not set +# CONFIG_RUN_INIT is not set + +# +# Editors +# +CONFIG_AWK=y +CONFIG_FEATURE_AWK_LIBM=y +CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y +# CONFIG_CMP is not set +# CONFIG_DIFF is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_ED is not set +# CONFIG_PATCH is not set +CONFIG_SED=y +CONFIG_VI=y +CONFIG_FEATURE_VI_MAX_LEN=4096 +CONFIG_FEATURE_VI_8BIT=y +CONFIG_FEATURE_VI_COLON=y +CONFIG_FEATURE_VI_YANKMARK=y +CONFIG_FEATURE_VI_SEARCH=y +# CONFIG_FEATURE_VI_REGEX_SEARCH is not set +CONFIG_FEATURE_VI_USE_SIGNALS=y +CONFIG_FEATURE_VI_DOT_CMD=y +CONFIG_FEATURE_VI_READONLY=y +CONFIG_FEATURE_VI_SETOPTS=y +CONFIG_FEATURE_VI_SET=y +CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_FEATURE_VI_ASK_TERMINAL=y +CONFIG_FEATURE_VI_UNDO=y +CONFIG_FEATURE_VI_UNDO_QUEUE=y +CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 +CONFIG_FEATURE_ALLOW_EXEC=y + +# +# Finding Utilities +# +CONFIG_FIND=y +CONFIG_FEATURE_FIND_PRINT0=y +CONFIG_FEATURE_FIND_MTIME=y +CONFIG_FEATURE_FIND_MMIN=y +CONFIG_FEATURE_FIND_PERM=y +CONFIG_FEATURE_FIND_TYPE=y +CONFIG_FEATURE_FIND_EXECUTABLE=y +CONFIG_FEATURE_FIND_XDEV=y +CONFIG_FEATURE_FIND_MAXDEPTH=y +CONFIG_FEATURE_FIND_NEWER=y +CONFIG_FEATURE_FIND_INUM=y +CONFIG_FEATURE_FIND_EXEC=y +CONFIG_FEATURE_FIND_EXEC_PLUS=y +CONFIG_FEATURE_FIND_USER=y +CONFIG_FEATURE_FIND_GROUP=y +CONFIG_FEATURE_FIND_NOT=y +CONFIG_FEATURE_FIND_DEPTH=y +CONFIG_FEATURE_FIND_PAREN=y +CONFIG_FEATURE_FIND_SIZE=y +CONFIG_FEATURE_FIND_PRUNE=y +CONFIG_FEATURE_FIND_QUIT=y +CONFIG_FEATURE_FIND_DELETE=y +CONFIG_FEATURE_FIND_EMPTY=y +CONFIG_FEATURE_FIND_PATH=y +CONFIG_FEATURE_FIND_REGEX=y +# CONFIG_FEATURE_FIND_CONTEXT is not set +CONFIG_FEATURE_FIND_LINKS=y +CONFIG_GREP=n +CONFIG_EGREP=y +CONFIG_FGREP=y +CONFIG_FEATURE_GREP_CONTEXT=y +CONFIG_XARGS=y +CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y +CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y +CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y +CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y +CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y +CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL=y +CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE=y + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +# CONFIG_HALT is not set +# CONFIG_POWEROFF is not set +# CONFIG_REBOOT is not set +# CONFIG_FEATURE_WAIT_FOR_INIT is not set +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" +# CONFIG_INIT is not set +# CONFIG_LINUXRC is not set +# CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +# CONFIG_FEATURE_INIT_QUIET is not set +# CONFIG_FEATURE_INIT_COREDUMPS is not set +CONFIG_INIT_TERMINAL_TYPE="" +# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set + +# +# Login/Password Management Utilities +# +CONFIG_FEATURE_SHADOWPASSWDS=y +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +CONFIG_USE_BB_CRYPT=y +CONFIG_USE_BB_CRYPT_SHA=y +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +# CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_LAST_ID=0 +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 +# CONFIG_CHPASSWD is not set +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="sha512" +CONFIG_CRYPTPW=y +CONFIG_MKPASSWD=y +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_GETTY is not set +CONFIG_LOGIN=y +# CONFIG_LOGIN_SESSION_AS_CHILD is not set +CONFIG_LOGIN_SCRIPTS=y +# CONFIG_FEATURE_NOLOGIN is not set +# CONFIG_FEATURE_SECURETTY is not set +CONFIG_PASSWD=y +CONFIG_FEATURE_PASSWD_WEAK_CHECK=y +CONFIG_SU=y +CONFIG_FEATURE_SU_SYSLOG=y +CONFIG_FEATURE_SU_CHECKS_SHELLS=y +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +# CONFIG_FSCK is not set +# CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux Module Utilities +# +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_DEPMOD is not set +# CONFIG_INSMOD is not set +# CONFIG_LSMOD is not set +# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_MODINFO is not set +# CONFIG_MODPROBE is not set +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_RMMOD is not set + +# +# Options common to multiple modutils +# +# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_DEFAULT_MODULES_DIR="" +CONFIG_DEFAULT_DEPMOD_FILE="" + +# +# Linux System Utilities +# +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +# CONFIG_BLKDISCARD is not set +# CONFIG_BLKID is not set +# CONFIG_FEATURE_BLKID_TYPE is not set +# CONFIG_BLOCKDEV is not set +# CONFIG_CAL is not set +# CONFIG_CHRT is not set +CONFIG_DMESG=y +CONFIG_FEATURE_DMESG_PRETTY=y +CONFIG_EJECT=y +CONFIG_FEATURE_EJECT_SCSI=y +# CONFIG_FALLOCATE is not set +# CONFIG_FATATTR is not set +CONFIG_FBSET=y +CONFIG_FEATURE_FBSET_FANCY=y +CONFIG_FEATURE_FBSET_READMODE=y +# CONFIG_FDFORMAT is not set +# CONFIG_FDISK is not set +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_FEATURE_FDISK_WRITABLE is not set +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +# CONFIG_FEATURE_GPT_LABEL is not set +# CONFIG_FEATURE_FDISK_ADVANCED is not set +CONFIG_FINDFS=y +CONFIG_FLOCK=y +# CONFIG_FDFLUSH is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +# CONFIG_FSFREEZE is not set +# CONFIG_FSTRIM is not set +CONFIG_GETOPT=y +CONFIG_FEATURE_GETOPT_LONG=y +CONFIG_HEXDUMP=y +# CONFIG_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_HD is not set +# CONFIG_XXD is not set +CONFIG_HWCLOCK=y +# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +CONFIG_IONICE=y +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set +# CONFIG_LOSETUP is not set +# CONFIG_LSPCI is not set +# CONFIG_LSUSB is not set +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_FEATURE_MDEV_DAEMON is not set +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +# CONFIG_MKE2FS is not set +# CONFIG_MKFS_EXT2 is not set +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +# CONFIG_MKDOSFS is not set +# CONFIG_MKFS_VFAT is not set +CONFIG_MKSWAP=y +CONFIG_FEATURE_MKSWAP_UUID=y +CONFIG_MORE=y +CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +CONFIG_FEATURE_MOUNT_VERBOSE=y +CONFIG_FEATURE_MOUNT_HELPERS=y +CONFIG_FEATURE_MOUNT_LABEL=y +# CONFIG_FEATURE_MOUNT_NFS is not set +CONFIG_FEATURE_MOUNT_CIFS=y +CONFIG_FEATURE_MOUNT_FLAGS=y +# CONFIG_FEATURE_MOUNT_FSTAB is not set +# CONFIG_FEATURE_MOUNT_OTHERTAB is not set +CONFIG_MOUNTPOINT=y +# CONFIG_NOLOGIN is not set +# CONFIG_NOLOGIN_DEPENDENCIES is not set +# CONFIG_NSENTER is not set +# CONFIG_PIVOT_ROOT is not set +CONFIG_RDATE=y +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +CONFIG_RENICE=y +# CONFIG_REV is not set +# CONFIG_RTCWAKE is not set +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +# CONFIG_LINUX32 is not set +# CONFIG_LINUX64 is not set +# CONFIG_SETPRIV is not set +# CONFIG_FEATURE_SETPRIV_DUMP is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITIES is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES is not set +# CONFIG_SETSID is not set +# CONFIG_SWAPON is not set +# CONFIG_FEATURE_SWAPON_DISCARD is not set +# CONFIG_FEATURE_SWAPON_PRI is not set +# CONFIG_SWAPOFF is not set +# CONFIG_FEATURE_SWAPONOFF_LABEL is not set +CONFIG_SWITCH_ROOT=y +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +CONFIG_UEVENT=y +CONFIG_UMOUNT=y +CONFIG_FEATURE_UMOUNT_ALL=y +# CONFIG_UNSHARE is not set +# CONFIG_WALL is not set + +# +# Common options for mount/umount +# +CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y +# CONFIG_FEATURE_MTAB_SUPPORT is not set +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +# CONFIG_FEATURE_VOLUMEID_BCACHE is not set +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_EXFAT=y +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_F2FS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_JFS=y +# CONFIG_FEATURE_VOLUMEID_LFS is not set +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_MINIX=y +CONFIG_FEATURE_VOLUMEID_NILFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_UBIFS=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_XFS=y + +# +# Miscellaneous Utilities +# +# CONFIG_ADJTIMEX is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +CONFIG_BC=y +# CONFIG_DC is not set +# CONFIG_FEATURE_DC_BIG is not set +# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_FEATURE_BC_INTERACTIVE is not set +# CONFIG_FEATURE_BC_LONG_OPTIONS is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CONSPY is not set +CONFIG_CROND=y +CONFIG_FEATURE_CROND_D=y +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set +CONFIG_FEATURE_CROND_DIR="/storage/.cache/cron" +CONFIG_CRONTAB=y +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +CONFIG_DEVMEM=y +# CONFIG_FBSPLASH is not set +CONFIG_FLASH_ERASEALL=y +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASHCP is not set +# CONFIG_HDPARM is not set +# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_HEXEDIT is not set +# CONFIG_I2CGET is not set +# CONFIG_I2CSET is not set +# CONFIG_I2CDUMP is not set +# CONFIG_I2CDETECT is not set +# CONFIG_I2CTRANSFER is not set +# CONFIG_INOTIFYD is not set +CONFIG_LESS=y +CONFIG_FEATURE_LESS_MAXLINES=9999999 +CONFIG_FEATURE_LESS_BRACKETS=y +CONFIG_FEATURE_LESS_FLAGS=y +CONFIG_FEATURE_LESS_TRUNCATE=y +CONFIG_FEATURE_LESS_MARKS=y +CONFIG_FEATURE_LESS_REGEXP=y +CONFIG_FEATURE_LESS_WINCH=y +CONFIG_FEATURE_LESS_ASK_TERMINAL=y +CONFIG_FEATURE_LESS_DASHCMD=y +CONFIG_FEATURE_LESS_LINENUMS=y +CONFIG_FEATURE_LESS_RAW=y +CONFIG_FEATURE_LESS_ENV=y +# CONFIG_LSSCSI is not set +# CONFIG_MAKEDEVS is not set +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MT is not set +CONFIG_NANDWRITE=y +# CONFIG_NANDDUMP is not set +# CONFIG_PARTPROBE is not set +# CONFIG_RAIDAUTORUN is not set +# CONFIG_READAHEAD is not set +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +# CONFIG_SETFATTR is not set +CONFIG_SETSERIAL=y +# CONFIG_STRINGS is not set +CONFIG_TIME=y +# CONFIG_TS is not set +CONFIG_TTYSIZE=y +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +# CONFIG_UBIMKVOL is not set +# CONFIG_UBIRMVOL is not set +# CONFIG_UBIRSVOL is not set +# CONFIG_UBIUPDATEVOL is not set +# CONFIG_UBIRENAME is not set +# CONFIG_VOLNAME is not set +# CONFIG_WATCHDOG is not set + +# +# Networking Utilities +# +CONFIG_FEATURE_IPV6=y +# CONFIG_FEATURE_UNIX_LOCAL is not set +CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +CONFIG_ARP=y +CONFIG_ARPING=y +CONFIG_BRCTL=y +CONFIG_FEATURE_BRCTL_FANCY=y +CONFIG_FEATURE_BRCTL_SHOW=y +# CONFIG_DNSD is not set +CONFIG_ETHER_WAKE=y +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTPD_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set +CONFIG_FTPGET=y +CONFIG_FTPPUT=y +CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y +CONFIG_HOSTNAME=y +CONFIG_DNSDOMAINNAME=y +CONFIG_HTTPD=y +CONFIG_FEATURE_HTTPD_RANGES=y +CONFIG_FEATURE_HTTPD_SETUID=y +CONFIG_FEATURE_HTTPD_BASIC_AUTH=y +CONFIG_FEATURE_HTTPD_AUTH_MD5=y +CONFIG_FEATURE_HTTPD_CGI=y +CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y +CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y +CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y +CONFIG_FEATURE_HTTPD_ERROR_PAGES=y +CONFIG_FEATURE_HTTPD_PROXY=y +CONFIG_FEATURE_HTTPD_GZIP=y +CONFIG_IFCONFIG=y +CONFIG_FEATURE_IFCONFIG_STATUS=y +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +CONFIG_FEATURE_IFCONFIG_HW=y +CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y +# CONFIG_IFENSLAVE is not set +CONFIG_IFPLUGD=y +# CONFIG_IFUP is not set +# CONFIG_IFDOWN is not set +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +CONFIG_IP=y +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +# CONFIG_IPNEIGH is not set +CONFIG_FEATURE_IP_ADDRESS=y +CONFIG_FEATURE_IP_LINK=y +CONFIG_FEATURE_IP_ROUTE=y +CONFIG_FEATURE_IP_ROUTE_DIR="/etc/iproute2" +CONFIG_FEATURE_IP_TUNNEL=y +CONFIG_FEATURE_IP_RULE=y +# CONFIG_FEATURE_IP_NEIGH is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_IPCALC is not set +# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_FEATURE_IPCALC_FANCY is not set +# CONFIG_FAKEIDENTD is not set +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +CONFIG_NBDCLIENT=y +CONFIG_NC=y +# CONFIG_NETCAT is not set +CONFIG_NC_SERVER=y +CONFIG_NC_EXTRA=y +CONFIG_NC_110_COMPAT=y +CONFIG_NETSTAT=y +# CONFIG_FEATURE_NETSTAT_WIDE is not set +CONFIG_FEATURE_NETSTAT_PRG=y +CONFIG_NSLOOKUP=y +# CONFIG_FEATURE_NSLOOKUP_BIG is not set +# CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS is not set +CONFIG_NTPD=y +# CONFIG_FEATURE_NTPD_SERVER is not set +CONFIG_FEATURE_NTPD_CONF=y +CONFIG_FEATURE_NTP_AUTH=y +CONFIG_PING=y +CONFIG_PING6=y +CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set +CONFIG_ROUTE=y +# CONFIG_SLATTACH is not set +# CONFIG_SSL_CLIENT is not set +# CONFIG_TC is not set +# CONFIG_FEATURE_TC_INGRESS is not set +# CONFIG_TCPSVD is not set +# CONFIG_UDPSVD is not set +CONFIG_TELNET=y +CONFIG_FEATURE_TELNET_TTYPE=y +CONFIG_FEATURE_TELNET_AUTOLOGIN=y +# CONFIG_FEATURE_TELNET_WIDTH is not set +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_FEATURE_TFTP_HPA_COMPAT is not set +# CONFIG_TFTPD is not set +# CONFIG_FEATURE_TFTP_GET is not set +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_TFTP_DEBUG is not set +# CONFIG_TLS is not set +CONFIG_TRACEROUTE=y +CONFIG_TRACEROUTE6=y +CONFIG_FEATURE_TRACEROUTE_VERBOSE=y +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +CONFIG_VCONFIG=y +CONFIG_WGET=n +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_STATUSBAR=y +CONFIG_FEATURE_WGET_AUTHENTICATION=y +CONFIG_FEATURE_WGET_TIMEOUT=y +# CONFIG_FEATURE_WGET_HTTPS is not set +CONFIG_FEATURE_WGET_OPENSSL=y +CONFIG_WHOIS=y +# CONFIG_ZCIP is not set +# CONFIG_UDHCPD is not set +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +CONFIG_DHCPD_LEASES_FILE="" +# CONFIG_DUMPLEASES is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_UDHCPC is not set +# CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="" +# CONFIG_UDHCPC6 is not set +# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_FEATURE_UDHCPC6_RFC5970 is not set +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +# CONFIG_FEATURE_UDHCP_8021Q is not set +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" + +# +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set +CONFIG_FEATURE_MIME_CHARSET="" + +# +# Process Utilities +# +# CONFIG_FREE is not set +CONFIG_FUSER=y +CONFIG_IOSTAT=y +CONFIG_KILL=y +CONFIG_KILLALL=y +CONFIG_KILLALL5=y +CONFIG_LSOF=y +CONFIG_MPSTAT=y +# CONFIG_NMETER is not set +CONFIG_PGREP=y +CONFIG_PKILL=y +CONFIG_PIDOF=y +CONFIG_FEATURE_PIDOF_SINGLE=y +CONFIG_FEATURE_PIDOF_OMIT=y +CONFIG_PMAP=y +# CONFIG_POWERTOP is not set +# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set +CONFIG_PS=y +# CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_FEATURE_PS_LONG is not set +CONFIG_FEATURE_PS_TIME=y +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y +CONFIG_PSTREE=y +CONFIG_PWDX=y +CONFIG_SMEMCAP=y +CONFIG_BB_SYSCTL=y +# CONFIG_TOP is not set +# CONFIG_FEATURE_TOP_INTERACTIVE is not set +# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set +# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set +# CONFIG_FEATURE_TOP_SMP_CPU is not set +# CONFIG_FEATURE_TOP_DECIMALS is not set +# CONFIG_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_FEATURE_TOPMEM is not set +CONFIG_UPTIME=y +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +CONFIG_WATCH=y +CONFIG_FEATURE_SHOW_THREADS=y + +# +# Runit Utilities +# +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVC is not set +# CONFIG_SVOK is not set +# CONFIG_SVLOGD is not set +# CONFIG_CHCON is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RUNCON is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set +# CONFIG_SETSEBOOL is not set + +# +# Shells +# +CONFIG_SH_IS_ASH=y +# CONFIG_SH_IS_HUSH is not set +# CONFIG_SH_IS_NONE is not set +CONFIG_BASH_IS_ASH=y +# CONFIG_BASH_IS_HUSH is not set +# CONFIG_BASH_IS_NONE is not set +CONFIG_ASH=y +# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set +# CONFIG_ASH_INTERNAL_GLOB is not set +CONFIG_ASH_BASH_COMPAT=y +# CONFIG_ASH_BASH_SOURCE_CURDIR is not set +# CONFIG_ASH_BASH_NOT_FOUND_HOOK is not set +CONFIG_ASH_JOB_CONTROL=y +CONFIG_ASH_ALIAS=y +CONFIG_ASH_RANDOM_SUPPORT=y +CONFIG_ASH_EXPAND_PRMT=y +# CONFIG_ASH_IDLE_TIMEOUT is not set +# CONFIG_ASH_MAIL is not set +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y +CONFIG_ASH_HELP=y +CONFIG_ASH_GETOPTS=y +CONFIG_ASH_CMDCMD=y +# CONFIG_CTTYHACK is not set +# CONFIG_HUSH is not set +# CONFIG_SHELL_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +CONFIG_FEATURE_SH_MATH=y +CONFIG_FEATURE_SH_MATH_64=y +CONFIG_FEATURE_SH_MATH_BASE=y +CONFIG_FEATURE_SH_EXTRA_QUIET=y +# CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_FEATURE_SH_NOFORK is not set +CONFIG_FEATURE_SH_READ_FRAC=y +CONFIG_FEATURE_SH_HISTFILESIZE=y +# CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS is not set + +# +# System Logging Utilities +# +# CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set +CONFIG_LOGGER=y +# CONFIG_LOGREAD is not set +# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_SYSLOGD is not set +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_FEATURE_IPC_SYSLOG is not set +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_FEATURE_KMSG_SYSLOG is not set diff --git a/packages/sysutils/busybox/config/httpd.conf b/packages/sysutils/busybox/config/httpd.conf new file mode 100644 index 000000000..152343e65 --- /dev/null +++ b/packages/sysutils/busybox/config/httpd.conf @@ -0,0 +1,46 @@ +# httpd.conf has the following format: +# +# H:/serverroot # define the server root. It will override -h +# A:172.20. # Allow address from 172.20.0.0/16 +# A:10.0.0.0/25 # Allow any address from 10.0.0.0-10.0.0.127 +# A:10.0.0.0/255.255.255.128 # Allow any address that previous set +# A:127.0.0.1 # Allow local loopback connections +# D:* # Deny from other IP connections +# E404:/path/e404.html # /path/e404.html is the 404 (not found) error page +# I:index.html # Show index.html when a directory is requested +# +# P:/url:[http://]hostname[:port]/new/path +# # When /urlXXXXXX is requested, reverse proxy +# # it to http://hostname[:port]/new/pathXXXXXX +# +# /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/ +# /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ +# /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ +# .au:audio/basic # additional mime type for audio.au files +# *.php:/path/php # run xxx.php through an interpreter +# +# A/D may be as a/d or allow/deny - only first char matters. +# Deny/Allow IP logic: +# - Default is to allow all (Allow all (A:*) is a no-op). +# - Deny rules take precedence over allow rules. +# - "Deny all" rule (D:*) is applied last. +# +# Example: +# 1. Allow only specified addresses +# A:172.20 # Allow any address that begins with 172.20. +# A:10.10. # Allow any address that begins with 10.10. +# A:127.0.0.1 # Allow local loopback connections +# D:* # Deny from other IP connections +# +# 2. Only deny specified addresses +# D:1.2.3. # deny from 1.2.3.0 - 1.2.3.255 +# D:2.3.4. # deny from 2.3.4.0 - 2.3.4.255 +# A:* # (optional line added for clarity) +# + +H:/usr/www # define the server root. It will override -h +A:* # Allow address from all ip's +E404:/usr/www/error/404.html # /path/e404.html is the 404 (not found) error page +I:index.html # Show index.html when a directory is requested + +*.php:/usr/bin/php-cgi \ No newline at end of file diff --git a/packages/sysutils/busybox/config/inputrc b/packages/sysutils/busybox/config/inputrc new file mode 100644 index 000000000..5253889c3 --- /dev/null +++ b/packages/sysutils/busybox/config/inputrc @@ -0,0 +1,66 @@ +# /etc/inputrc - global inputrc for libreadline +# See readline(3readline) and `info rluserman' for more information. + +# Be 8 bit clean. +set input-meta on +set output-meta on + +# To allow the use of 8bit-characters like the german umlauts, uncomment +# the line below. However this makes the meta key not work as a meta key, +# which is annoying to those which don't need to type in 8-bit characters. + +# set convert-meta off + +# try to enable the application keypad when it is called. Some systems +# need this to enable the arrow keys. +# set enable-keypad on + +# see /usr/share/doc/bash/inputrc.arrows for other codes of arrow keys + +# do not bell on tab-completion +# set bell-style none +# set bell-style visible + +# some defaults / modifications for the emacs mode +$if mode=emacs + +# allow the use of the Home/End keys +"\e[1~": beginning-of-line +"\e[4~": end-of-line + +# allow the use of the Delete/Insert keys +"\e[3~": delete-char +"\e[2~": quoted-insert + +# mappings for "page up" and "page down" to step to the beginning/end +# of the history +# "\e[5~": beginning-of-history +# "\e[6~": end-of-history + +# alternate mappings for "page up" and "page down" to search the history +# "\e[5~": history-search-backward +# "\e[6~": history-search-forward + +# mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving +"\e[1;5C": forward-word +"\e[1;5D": backward-word +"\e[5C": forward-word +"\e[5D": backward-word +"\e\e[C": forward-word +"\e\e[D": backward-word + +$if term=rxvt +"\e[8~": end-of-line +"\eOc": forward-word +"\eOd": backward-word +$endif + +# for non RH/Debian xterm, can't hurt for RH/Debian xterm +# "\eOH": beginning-of-line +# "\eOF": end-of-line + +# for freebsd console +# "\e[H": beginning-of-line +# "\e[F": end-of-line + +$endif diff --git a/packages/sysutils/busybox/config/profile b/packages/sysutils/busybox/config/profile new file mode 100644 index 000000000..79cce3c76 --- /dev/null +++ b/packages/sysutils/busybox/config/profile @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# parse command line arguments + for arg in $(cat /proc/cmdline); do + case $arg in + debugging) + export DEBUG=yes + ;; + progress) + PROGRESS=yes + ;; + esac + done + + if [ -e /storage/.cache/debug.libreelec ] ; then + export DEBUG=yes + fi + +# functions + progress() { + if test "$PROGRESS" = yes; then + logger -s -t Boot "### $1 ###" + else + logger -t Boot "### $1 ###" + fi + } + +# read config files + for config in /etc/profile.d/*; do + if [ -f "$config" ] ; then + . $config + fi + done diff --git a/packages/sysutils/busybox/config/suspend-modules.conf b/packages/sysutils/busybox/config/suspend-modules.conf new file mode 100644 index 000000000..10d1db19b --- /dev/null +++ b/packages/sysutils/busybox/config/suspend-modules.conf @@ -0,0 +1 @@ +SUSPEND_MODULES="jme asix anysee rtl8192se imon r8712u cx23885 cdc_acm ddbridge brcmfmac 8812au xpad" diff --git a/packages/sysutils/busybox/default.d/crond.conf b/packages/sysutils/busybox/default.d/crond.conf new file mode 100644 index 000000000..e69de29bb diff --git a/packages/sysutils/busybox/package.mk b/packages/sysutils/busybox/package.mk new file mode 100644 index 000000000..9122424c0 --- /dev/null +++ b/packages/sysutils/busybox/package.mk @@ -0,0 +1,231 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="busybox" +PKG_VERSION="1.32.1" +PKG_SHA256="9d57c4bd33974140fd4111260468af22856f12f5b5ef7c70c8d9b75c712a0dee" +PKG_LICENSE="GPL" +PKG_SITE="http://www.busybox.net" +PKG_URL="http://busybox.net/downloads/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain busybox:host hdparm hd-idle dosfstools e2fsprogs zip unzip usbutils parted procps-ng gptfdisk libtirpc" +PKG_DEPENDS_INIT="toolchain libtirpc" +PKG_LONGDESC="BusyBox combines tiny versions of many common UNIX utilities into a single small executable." +# busybox fails to build with GOLD support enabled with binutils-2.25 +PKG_BUILD_FLAGS="-parallel -gold" +PKG_NEED_UNPACK="$PROJECT_DIR/$PROJECT/initramfs" + +# nano text editor +if [ "$NANO_EDITOR" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET nano" +fi + +# nfs support +if [ "$NFS_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET rpcbind" +fi + +if [ "$TARGET_ARCH" = "x86_64" ]; then + PKG_DEPENDS_TARGET+=" pciutils" +fi + +pre_build_target() { + PKG_MAKE_OPTS_TARGET="ARCH=$TARGET_ARCH \ + HOSTCC=$HOST_CC \ + CROSS_COMPILE=$TARGET_PREFIX \ + KBUILD_VERBOSE=1 \ + install" + + mkdir -p $PKG_BUILD/.$TARGET_NAME + cp -RP $PKG_BUILD/* $PKG_BUILD/.$TARGET_NAME +} + +pre_build_host() { + PKG_MAKE_OPTS_HOST="ARCH=$TARGET_ARCH CROSS_COMPILE= KBUILD_VERBOSE=1 install" + + mkdir -p $PKG_BUILD/.$HOST_NAME + cp -RP $PKG_BUILD/* $PKG_BUILD/.$HOST_NAME +} + +pre_build_init() { + PKG_MAKE_OPTS_INIT="ARCH=$TARGET_ARCH \ + HOSTCC=$HOST_CC \ + CROSS_COMPILE=$TARGET_PREFIX \ + KBUILD_VERBOSE=1 \ + install" + + mkdir -p $PKG_BUILD/.$TARGET_NAME-init + cp -RP $PKG_BUILD/* $PKG_BUILD/.$TARGET_NAME-init +} + +configure_host() { + cd $PKG_BUILD/.$HOST_NAME + cp $PKG_DIR/config/busybox-host.conf .config + + # set install dir + sed -i -e "s|^CONFIG_PREFIX=.*$|CONFIG_PREFIX=\"$PKG_BUILD/.install_host\"|" .config + + make oldconfig +} + +configure_target() { + cd $PKG_BUILD/.$TARGET_NAME + find_file_path config/busybox-target.conf + cp $FOUND_PATH .config + + # set install dir + sed -i -e "s|^CONFIG_PREFIX=.*$|CONFIG_PREFIX=\"$INSTALL/usr\"|" .config + + if [ ! "$CRON_SUPPORT" = "yes" ] ; then + sed -i -e "s|^CONFIG_CROND=.*$|# CONFIG_CROND is not set|" .config + sed -i -e "s|^CONFIG_FEATURE_CROND_D=.*$|# CONFIG_FEATURE_CROND_D is not set|" .config + sed -i -e "s|^CONFIG_CRONTAB=.*$|# CONFIG_CRONTAB is not set|" .config + sed -i -e "s|^CONFIG_FEATURE_CROND_SPECIAL_TIMES=.*$|# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set|" .config + fi + + if [ ! "$SAMBA_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_FEATURE_MOUNT_CIFS=.*$|# CONFIG_FEATURE_MOUNT_CIFS is not set|" .config + fi + + # optimize for size + CFLAGS=`echo $CFLAGS | sed -e "s|-Ofast|-Os|"` + CFLAGS=`echo $CFLAGS | sed -e "s|-O.|-Os|"` + CFLAGS="$CFLAGS -I$SYSROOT_PREFIX/usr/include/tirpc" + + LDFLAGS="$LDFLAGS -fwhole-program" + + make oldconfig +} + +configure_init() { + cd $PKG_BUILD/.$TARGET_NAME-init + find_file_path config/busybox-init.conf + cp $FOUND_PATH .config + + # set install dir + sed -i -e "s|^CONFIG_PREFIX=.*$|CONFIG_PREFIX=\"$INSTALL/usr\"|" .config + + # optimize for size + CFLAGS=`echo $CFLAGS | sed -e "s|-Ofast|-Os|"` + CFLAGS=`echo $CFLAGS | sed -e "s|-O.|-Os|"` + CFLAGS="$CFLAGS -I$SYSROOT_PREFIX/usr/include/tirpc" + + LDFLAGS="$LDFLAGS -fwhole-program" + + make oldconfig +} + +makeinstall_host() { + mkdir -p $TOOLCHAIN/bin + cp -R $PKG_BUILD/.install_host/bin/* $TOOLCHAIN/bin +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + [ $TARGET_ARCH = x86_64 ] && cp $PKG_DIR/scripts/getedid $INSTALL/usr/bin + cp $PKG_DIR/scripts/createlog $INSTALL/usr/bin/ + cp $PKG_DIR/scripts/dtfile $INSTALL/usr/bin + cp $PKG_DIR/scripts/dtname $INSTALL/usr/bin + cp $PKG_DIR/scripts/lsb_release $INSTALL/usr/bin/ + cp $PKG_DIR/scripts/pastebinit $INSTALL/usr/bin/ + ln -sf pastebinit $INSTALL/usr/bin/paste + + mkdir -p $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/functions $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/fs-resize $INSTALL/usr/lib/coreelec + sed -e "s/@DISTRONAME@/$DISTRONAME/g" \ + -i $INSTALL/usr/lib/coreelec/fs-resize + + if listcontains "${FIRMWARE}" "rpi-eeprom"; then + cp $PKG_DIR/scripts/rpi-flash-firmware $INSTALL/usr/lib/libreelec + fi + + mkdir -p $INSTALL/etc + cp $PKG_DIR/config/profile $INSTALL/etc + cp $PKG_DIR/config/inputrc $INSTALL/etc + cp $PKG_DIR/config/httpd.conf $INSTALL/etc + cp $PKG_DIR/config/suspend-modules.conf $INSTALL/etc + + # /etc/fstab is needed by... + touch $INSTALL/etc/fstab + + # /etc/machine-id, needed by systemd and dbus + ln -sf /storage/.cache/systemd-machine-id $INSTALL/etc/machine-id + + # /etc/mtab is needed by udisks etc... + ln -sf /proc/self/mounts $INSTALL/etc/mtab + + # create /etc/hostname + ln -sf /proc/sys/kernel/hostname $INSTALL/etc/hostname + + # add webroot + mkdir -p $INSTALL/usr/www + echo "It works" > $INSTALL/usr/www/index.html + + mkdir -p $INSTALL/usr/www/error + echo "404" > $INSTALL/usr/www/error/404.html +} + +post_install() { + ROOT_PWD="`$TOOLCHAIN/bin/cryptpw -m sha512 $ROOT_PASSWORD`" + + echo "chmod 4755 $INSTALL/usr/bin/busybox" >> $FAKEROOT_SCRIPT + echo "chmod 000 $INSTALL/usr/cache/shadow" >> $FAKEROOT_SCRIPT + + add_user root "$ROOT_PWD" 0 0 "Root User" "/storage" "/bin/sh" + add_group root 0 + add_group users 100 + + add_user nobody x 65534 65534 "Nobody" "/" "/bin/sh" + add_group nogroup 65534 + + enable_service shell.service + enable_service show-version.service + enable_service var.mount + enable_service fs-resize.service + listcontains "${FIRMWARE}" "rpi-eeprom" && enable_service rpi-flash-firmware.service + + # cron support + if [ "$CRON_SUPPORT" = "yes" ] ; then + mkdir -p $INSTALL/usr/lib/systemd/system + cp $PKG_DIR/system.d.opt/cron.service $INSTALL/usr/lib/systemd/system + enable_service cron.service + mkdir -p $INSTALL/usr/share/services + cp -P $PKG_DIR/default.d/*.conf $INSTALL/usr/share/services + cp $PKG_DIR/system.d.opt/cron-defaults.service $INSTALL/usr/lib/systemd/system + enable_service cron-defaults.service + fi +} + +makeinstall_init() { + mkdir -p $INSTALL/bin + ln -sf busybox $INSTALL/usr/bin/sh + ln -sf busybox $INSTALL/usr/bin/bc + chmod 4755 $INSTALL/usr/bin/busybox + + mkdir -p $INSTALL/etc + touch $INSTALL/etc/fstab + ln -sf /proc/self/mounts $INSTALL/etc/mtab + + if find_file_path initramfs/platform_init; then + cp ${FOUND_PATH} $INSTALL + sed -e "s/@BOOT_LABEL@/$DISTRO_BOOTLABEL/g" \ + -e "s/@DISK_LABEL@/$DISTRO_DISKLABEL/g" \ + -i $INSTALL/platform_init + chmod 755 $INSTALL/platform_init + fi + + cp $PKG_DIR/scripts/functions $INSTALL + cp $PKG_DIR/scripts/init $INSTALL + + cp ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/device.config ${INSTALL} + cp ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/device.init ${INSTALL} + chmod 755 ${INSTALL}/device.config ${INSTALL}/device.init + + sed -e "s/@DISTRONAME@/$DISTRONAME/g" \ + -e "s/@KERNEL_NAME@/$KERNEL_NAME/g" \ + -i $INSTALL/init + chmod 755 $INSTALL/init +} diff --git a/packages/sysutils/busybox/patches/busybox-00_halt_no_init.patch b/packages/sysutils/busybox/patches/busybox-00_halt_no_init.patch new file mode 100644 index 000000000..ce454f4c0 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-00_halt_no_init.patch @@ -0,0 +1,12 @@ +diff -Naur busybox-1.13.2/init/halt.c busybox-1.13.2a/init/halt.c +--- busybox-1.13.2/init/halt.c 2008-11-09 18:28:19.000000000 +0100 ++++ busybox-1.13.2a/init/halt.c 2009-02-01 16:38:37.000000000 +0100 +@@ -79,7 +79,7 @@ + + /* Perform action. */ + rc = 1; +- if (!(flags & 4)) { /* no -f */ ++ if (ENABLE_INIT && !(flags & 4)) { /* no -f */ + //TODO: I tend to think that signalling linuxrc is wrong + // pity original author didn't comment on it... + if (ENABLE_FEATURE_INITRD) { diff --git a/packages/sysutils/busybox/patches/busybox-02_silence-crond-startup-logging.patch b/packages/sysutils/busybox/patches/busybox-02_silence-crond-startup-logging.patch new file mode 100644 index 000000000..30105bdb1 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-02_silence-crond-startup-logging.patch @@ -0,0 +1,20 @@ +From 5f4085ddb16c206b1dc36d481c2aa6684ba392ee Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Thu, 18 Jul 2013 19:26:21 +0300 +Subject: [PATCH] silence crond startup logging + +--- + miscutils/crond.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff -Naur busybox-1.23.0/miscutils/crond.c busybox-1.23.0.patch/miscutils/crond.c +--- busybox-1.23.0/miscutils/crond.c 2014-10-04 22:35:59.000000000 +0200 ++++ busybox-1.23.0.patch/miscutils/crond.c 2014-12-26 23:07:53.386118290 +0100 +@@ -1054,7 +1054,6 @@ + /* Useful on Android where DEFAULT_SHELL /bin/sh may not exist */ + G.default_shell = xstrdup(get_shell_name()); + +- log8("crond (busybox "BB_VER") started, log level %d", G.log_level); + rescan_crontab_dir(); + write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid"); + #if ENABLE_FEATURE_CROND_SPECIAL_TIMES diff --git a/packages/sysutils/busybox/patches/busybox-03-make_unicode_printable.patch b/packages/sysutils/busybox/patches/busybox-03-make_unicode_printable.patch new file mode 100644 index 000000000..ec7354f6d --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-03-make_unicode_printable.patch @@ -0,0 +1,26 @@ +# +# stolen from OpenWRT +# +# https://dev.openwrt.org/attachment/ticket/7993/701-make_unicode_printable.patch +# + +--- a/libbb/printable_string.c 2013-01-13 20:06:04.210089516 +0800 ++++ b/libbb/printable_string.c 2013-01-13 20:00:27.917211167 +0800 +@@ -31,8 +31,6 @@ + } + if (c < ' ') + break; +- if (c >= 0x7f) +- break; + s++; + } + +@@ -45,7 +43,7 @@ + unsigned char c = *d; + if (c == '\0') + break; +- if (c < ' ' || c >= 0x7f) ++ if (c < ' ') + *d = '?'; + d++; + } diff --git a/packages/sysutils/busybox/patches/busybox-04-revert-dd-fsync-change.patch b/packages/sysutils/busybox/patches/busybox-04-revert-dd-fsync-change.patch new file mode 100644 index 000000000..e5dabec86 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-04-revert-dd-fsync-change.patch @@ -0,0 +1,34 @@ +From 0a61b6174d86fd0300be7cd4fa0b47ff12735958 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Tue, 8 Aug 2017 22:25:03 +0100 +Subject: [PATCH] Revert "dd: call fsync() only once before exiting if + conv=fsync is specified" + +This reverts commit dba0dc1999bb1e8bfe64607e2a9385cda361fcb7. +--- + coreutils/dd.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/coreutils/dd.c b/coreutils/dd.c +index d302f35..bf0c4ab 100644 +--- a/coreutils/dd.c ++++ b/coreutils/dd.c +@@ -531,11 +531,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) + if (write_and_stats(ibuf, n, obs, outfile)) + goto out_status; + } +- } + +- if (G.flags & FLAG_FSYNC) { +- if (fsync(ofd) < 0) +- goto die_outfile; ++ if (G.flags & FLAG_FSYNC) { ++ if (fsync(ofd) < 0) ++ goto die_outfile; ++ } + } + + if (ENABLE_FEATURE_DD_IBS_OBS && oc) { +-- +2.7.4 + diff --git a/packages/sysutils/busybox/patches/busybox-05-update-shadow-or-passwd-not-both.patch b/packages/sysutils/busybox/patches/busybox-05-update-shadow-or-passwd-not-both.patch new file mode 100644 index 000000000..b2698c980 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-05-update-shadow-or-passwd-not-both.patch @@ -0,0 +1,12 @@ +diff -Naur a/loginutils/passwd.c b/loginutils/passwd.c +--- a/loginutils/passwd.c 2017-07-06 08:14:57.000000000 -0700 ++++ b/loginutils/passwd.c 2017-09-11 17:06:07.572805135 -0700 +@@ -220,7 +220,7 @@ + if (rc > 0) + /* password in /etc/shadow was updated */ + newp = (char*) "x"; +- if (rc >= 0) ++ if (rc == 0) + /* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */ + #endif + { diff --git a/packages/sysutils/busybox/patches/busybox-06-prevent-root-weak-passwd.patch b/packages/sysutils/busybox/patches/busybox-06-prevent-root-weak-passwd.patch new file mode 100644 index 000000000..a8e5c706c --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-06-prevent-root-weak-passwd.patch @@ -0,0 +1,12 @@ +diff --git a/loginutils/passwd.c b/loginutils/passwd.c +index 6c643d3..df8859d 100644 +--- a/loginutils/passwd.c ++++ b/loginutils/passwd.c +@@ -69,7 +69,6 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo + goto err_ret; + if (ENABLE_FEATURE_PASSWD_WEAK_CHECK + && obscure(orig, newp, pw) /* NB: passing NULL orig is ok */ +- && myuid != 0 + ) { + goto err_ret; /* non-root is not allowed to have weak passwd */ + } diff --git a/packages/sysutils/busybox/patches/busybox-10-add-MS_BIND-option-when-remouting-bind-mount.patch b/packages/sysutils/busybox/patches/busybox-10-add-MS_BIND-option-when-remouting-bind-mount.patch new file mode 100644 index 000000000..2fc431716 --- /dev/null +++ b/packages/sysutils/busybox/patches/busybox-10-add-MS_BIND-option-when-remouting-bind-mount.patch @@ -0,0 +1,86 @@ +From 5624e803c89ee79afe7c6fd0ef9929110505a800 Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Fri, 20 Sep 2019 18:58:30 +0200 +Subject: [PATCH] add MS_BIND option when remouting bind mount + +when remounting bind mount add explicit MS_BIND to parameters +to "hide" bind mount from user's view + +bind mount is only visible from /proc/self/mountinfo that's +why we traverse the lines and using last entry in case +multiple sources are mount over same mount point + +Signed-off-by: Peter Vicman +--- + util-linux/mount.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/util-linux/mount.c b/util-linux/mount.c +index 84c85c0..bc3fbda 100644 +--- a/util-linux/mount.c ++++ b/util-linux/mount.c +@@ -1887,6 +1887,50 @@ static int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts) + + #endif // !ENABLE_FEATURE_MOUNT_NFS + ++// Check mount point in /proc/self/mountinfo and identify bind mount ++// return 1 for bind mount, 0 for normal mount ++static int check_bind_mount(struct mntent *mp) ++{ ++int mnt_dir_len; ++char *p; ++FILE *fp; ++char *line = NULL; ++int ret = 0; ++ ++ // https://www.kernel.org/doc/Documentation/filesystems/proc.txt ++ // 21 20 179:20 /coreelec_flash /flash ro,noatime shared:2 - ext4 /dev/data rw,resgid=1065,data=ordered ++ // 20 22 179:1 / /flash ro,noatime shared:2 - vfat /dev/mmcblk1p1 ro,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro ++ ++ fp = fopen("/proc/self/mountinfo", "r"); ++ if (fp == NULL) ++ return ret; ++ ++ // remove trailing slash ++ mnt_dir_len = strlen(mp->mnt_dir); ++ if (mnt_dir_len > 1 && mp->mnt_dir[mnt_dir_len - 1] == '/') { ++ mnt_dir_len--; ++ mp->mnt_dir[mnt_dir_len] = '\0'; ++ } ++ ++ while ((line = xmalloc_fgetline(fp)) != NULL) { ++ // find mount point ++ p = strstr(line, mp->mnt_dir); ++ if (p == NULL) ++ continue; ++ ++ // bind mount has folder for root and not just "/" ++ ret = 0; // always use result from last entry ++ if (strncmp(p - 2, "/ ", 2) != 0) ++ ret = 1; ++ } ++ ++ if (line != NULL) ++ free(line); ++ ++ fclose(fp); ++ return ret; ++} ++ + // Mount one directory. Handles CIFS, NFS, loopback, autobind, and filesystem + // type detection. Returns 0 for success, nonzero for failure. + // NB: mp->xxx fields may be trashed on exit +@@ -2058,6 +2102,10 @@ static int singlemount(struct mntent *mp, int ignore_busy) + vfsflags |= MS_BIND; + } + ++ // add explicit MS_BIND if remounting bind mount ++ if ((vfsflags & MS_REMOUNT) && (check_bind_mount(mp) == 1)) ++ vfsflags |= MS_BIND; ++ + // If we know the fstype (or don't need to), jump straight + // to the actual mount. + if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) { +-- +2.7.4 + diff --git a/packages/sysutils/busybox/profile.d/98-busybox.conf b/packages/sysutils/busybox/profile.d/98-busybox.conf new file mode 100644 index 000000000..bd93a25fa --- /dev/null +++ b/packages/sysutils/busybox/profile.d/98-busybox.conf @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +export HOME="/storage" +export PATH="/usr/bin:/usr/sbin" +export LD_LIBRARY_PATH="/usr/lib" +export HOSTNAME=`cat /etc/hostname` +export PS1="\[\e[1;30m\]\w \[\e[0m\]\\$ " +# k0p +case "$TERM" in + linux|nxterm|screen|xterm|xterm-color) + ;; + "") + export TERM="linux" + ;; + *) + export TERM="xterm" + ;; +esac diff --git a/packages/sysutils/busybox/scripts/createlog b/packages/sysutils/busybox/scripts/createlog new file mode 100755 index 000000000..c8e4f2c86 --- /dev/null +++ b/packages/sysutils/busybox/scripts/createlog @@ -0,0 +1,180 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# create logfile + +DATE=`date -u +%Y-%m-%d-%H.%M.%S` +BASEDIR="/tmp" +LOGDIR="log-$DATE" +RELEASE="`cat /etc/release`" +GIT="`cat /etc/issue | grep git`" + +getlog_cmd() { + if command -v $1 >/dev/null; then + echo "################################################################################" >> $BASEDIR/$LOGDIR/$LOGFILE + echo "# ... output of $@" >> $BASEDIR/$LOGDIR/$LOGFILE + echo "# CoreELEC release: $RELEASE" >> $BASEDIR/$LOGDIR/$LOGFILE + echo "# $GIT" >> $BASEDIR/$LOGDIR/$LOGFILE + echo "################################################################################" >> $BASEDIR/$LOGDIR/$LOGFILE + $@ >> $BASEDIR/$LOGDIR/$LOGFILE 2>/dev/null + echo "" >> $BASEDIR/$LOGDIR/$LOGFILE + fi +} + +get_governor_details() { + ( + cat_all_files /sys/devices/system/cpu + cat_all_files /sys/devices/system/cpu/cpufreq + for cpun in /sys/devices/system/cpu/cpu[0-9]*; do + cat_all_files ${cpun}/cpufreq + done + ) +} + +cat_all_files() { + local adir=$1 + local afile var + + [ -d ${adir} ] || return 0 + + echo "${adir}" + + cd ${adir} + for afile in $(find . -maxdepth 1 -print | sort); do + afile=${afile:2} + if [ -n "${afile}" ]; then + if [ -d ${afile} ]; then + var="

      " + else + var="$(cat ${afile} 2>/dev/null)" + fi + [ -n "${var}" ] && printf " %-30s : %s\n" "${afile}" "${var}" + fi + done +} + +rm -rf $BASEDIR/$LOGDIR +mkdir -p $BASEDIR/$LOGDIR + +# kodi.log + KODI_LOG_DIR=/storage/.kodi/temp + + LOGFILE="01_KODI.log" + for i in kodi.log kodi.old.log; do + [ -f ${KODI_LOG_DIR}/${i} ] && getlog_cmd cat ${KODI_LOG_DIR}/$i + done + + LOGFILE="01_KODI_CRASH.log" + for i in `find ${KODI_LOG_DIR} -type f -name "kodi_crashlog_*.log" | sort -r`; do + getlog_cmd cat $i + done + + LOGFILE="01_KODI_OTHER.log" + for i in `find ${KODI_LOG_DIR} -type f -name "*.log" | sort`; do + iname="${i#${KODI_LOG_DIR}/}" + [ ${iname} == kodi.log ] && continue + [ ${iname} == kodi.old.log ] && continue + [ "${iname#kodi_crashlog_}" != "${iname}" ] && continue + getlog_cmd cat $i + done + +# System.log + LOGFILE="02_System.log" + getlog_cmd dmesg + getlog_cmd lsmod + getlog_cmd ps xa + for i in /storage/.config/hwdb.d/*.hwdb \ + /storage/.config/modprobe.d/*.conf \ + /storage/.config/modules-load.d/*.conf \ + /storage/.config/sleep.d/*.power \ + /storage/.config/sysctl.d/*.conf \ + /storage/.config/udev.rules.d/.rules \ + ; do + if [ -f "$i" ] ; then + getlog_cmd cat $i + fi + done + if [ -f "/storage/.config/autostart.sh" ] ; then + getlog_cmd cat /storage/.config/autostart.sh + fi + if [ -f "/storage/.config/shutdown.sh" ] ; then + getlog_cmd cat /storage/.config/shutdown.sh + fi + getlog_cmd ls -laR /storage/.config/system.d + # note: we dont add .mount units here as they may contan + # login credentials + for i in /storage/.config/system.d/*.service ; do + if [ -f "$i" -a ! -L "$i" ] ; then + getlog_cmd cat $i + fi + done + +# Hardware.log + LOGFILE="03_Hardware.log" + getlog_cmd lspci -vvvvnn + getlog_cmd lsusb -vvv + getlog_cmd lsusb -t + getlog_cmd cat /proc/cpuinfo + getlog_cmd get_governor_details + getlog_cmd cat /proc/meminfo + +# Audio.log + LOGFILE="04_Audio.log" + getlog_cmd aplay -l + getlog_cmd aplay -L + getlog_cmd amixer + +# Network.log + LOGFILE="05_Network.log" + getlog_cmd ifconfig -a + getlog_cmd netstat -rn + getlog_cmd netstat -nalp + getlog_cmd connmanctl services + getlog_cmd cat /etc/resolv.conf + +# varlog.log + LOGFILE="06_varlog.log" + for i in `find /var/log -type f`; do + getlog_cmd cat $i + done + +# Input.log + LOGFILE="07_input.log" + getlog_cmd cat /proc/bus/input/devices + # make RPi users happy + if [ -e /proc/acpi/wakeup ] ; then + getlog_cmd cat /proc/acpi/wakeup + fi + +# Filesystem.log + LOGFILE="08_Filesystem.log" + getlog_cmd cat /proc/mounts + getlog_cmd df -h + getlog_cmd blkid + +# Journal (current) + LOGFILE="09_Journal-cur.log" + getlog_cmd journalctl --no-pager -b -0 + +# Journal (prev) + LOGFILE="10_Journal-prev.log" + getlog_cmd journalctl --no-pager -b -1 + +# addons + LOGFILE="11_Addons.log" + for i in /storage/.kodi/userdata/addon_data/*/*.log \ + /storage/.kodi/userdata/addon_data/*/log/* \ + ; do + if [ -f "$i" ] ; then + getlog_cmd cat $i + fi + done + +# pack logfiles + mkdir -p /storage/logfiles + zip -jq /storage/logfiles/log-$DATE.zip $BASEDIR/$LOGDIR/* + +# remove logdir + rm -rf $BASEDIR/$LOGDIR diff --git a/packages/sysutils/busybox/scripts/dtfile b/packages/sysutils/busybox/scripts/dtfile new file mode 100755 index 000000000..04ca37194 --- /dev/null +++ b/packages/sysutils/busybox/scripts/dtfile @@ -0,0 +1,20 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +COMPATIBLE=$(cat /proc/device-tree/compatible 2>/dev/null | tr -d '\000' | sed -n -e 's/.*\(allwinner\|amlogic\|rockchip\).*/\1/p') + +if [ -n "$COMPATIBLE" ]; then + if [ -e /flash/extlinux/extlinux.conf ]; then + DTFILE=$(grep FDT /flash/extlinux/extlinux.conf | sed 's, *FDT /dtb/,,g') + elif [ -e /flash/boot.ini ]; then + DTFILE=$(grep -m 1 dtb_name /flash/boot.ini | cut -d \" -f2 | sed 's,/dtb/,,g') + elif [ -e /flash/uEnv.ini ]; then + DTFILE=$(grep dtb_name /flash/uEnv.ini | sed 's,dtb_name=/dtb/,,g') + else + DTFILE="" + fi +fi + +echo "$DTFILE" diff --git a/packages/sysutils/busybox/scripts/dtname b/packages/sysutils/busybox/scripts/dtname new file mode 100755 index 000000000..c328aeb6b --- /dev/null +++ b/packages/sysutils/busybox/scripts/dtname @@ -0,0 +1,21 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +source /etc/os-release + +if [ "${COREELEC_PROJECT}" = "Amlogic" -o "${COREELEC_PROJECT}" = "Amlogic-ng" ]; then + [ -f "/proc/device-tree/coreelec-dt-id" ] && DTNAME=$(cat /proc/device-tree/coreelec-dt-id) + [ -f "/proc/device-tree/le-dt-id" ] && DTNAME=$(cat /proc/device-tree/le-dt-id) +else + COMPATIBLE=$(cat /proc/device-tree/compatible 2>/dev/null | tr -d '\000' | sed -n -e 's/.*\(allwinner\|amlogic\|rockchip\).*/\1/p') + [ -n "$COMPATIBLE" ] && DTNAME=$(cat /proc/device-tree/compatible | cut -f1,2 -d',' | head -n 1) +fi + +if [ -n "$DTNAME" ]; then + echo "$DTNAME" +else + echo "unknown" +fi diff --git a/packages/sysutils/busybox/scripts/fs-resize b/packages/sysutils/busybox/scripts/fs-resize new file mode 100755 index 000000000..d3783b984 --- /dev/null +++ b/packages/sysutils/busybox/scripts/fs-resize @@ -0,0 +1,55 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +if [ -e /storage/.please_resize_me ] ; then + . /usr/lib/coreelec/functions + + hidecursor + + # this sh** was never intended to be used + # on already installed and runing system + if [ -d /storage/.kodi -o -d /storage/.config -o -d /storage/.cache ] ; then + rm -f /storage/.please_resize_me + sync + echo "Resizing is not permitted - the system has already been initialised." + StartProgress countdown "Rebooting in 15s... " 15 "NOW" + reboot -f + fi + + # get the disk. /storage on 2nd partition + PART=$(grep "/storage " /proc/mounts | cut -d" " -f1) + DISK=$(echo ${PART} | sed s/p2$//g) + + rm -f /storage/.please_resize_me + sync + + # just in case + if [ ! -z "${DISK}" -a ! -z "${PART}" ] ; then + umount ${PART} + + clear >/dev/console + echo "PARTITION RESIZING IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your @DISTRONAME@ device!" + echo "" + + # identify the partition scheme, and if gpt fix minor issues such as gpt header not at end of disk + SCHEME=$(blkid -s PTTYPE -o value ${DISK}) + if [ "$SCHEME" = "gpt" ]; then + StartProgress spinner "Checking layout... " "sgdisk -e ${DISK} &>/dev/null" + fi + + StartProgress spinner "Resizing partition... " "parted -s -a optimal -m ${DISK} resizepart 2 4GiB &>/dev/null" + StartProgress spinner "Checking file system... " "e2fsck -f -p ${PART} &>/dev/null" + StartProgress spinner "Resizing file system... " "resize2fs ${PART} &>/dev/null" + GAMESSTART="$(echo $(parted -m ${DISK} print all 2>/dev/null | awk 'BEGIN {FS=":"} /^2/ {gsub ("[A-Z]",""); print $3}') + 17 2>/dev/null | bc 2>/dev/null)" + StartProgress spinner "Creating exFAT partition..." "parted -s -a optimal -m ${DISK} mkpart primary ntfs ${GAMESSTART}MB 100% &>/dev/null" + partprobe &>/dev/null + StartProgress spinner "Formatting exFAT partition..." "mkfs.exfat -n GAMES ${DISK}p3 &>/dev/null" + StartProgress countdown "Rebooting in 5s... " 5 "NOW" + fi +fi +reboot -f &>/dev/null diff --git a/packages/sysutils/busybox/scripts/functions b/packages/sysutils/busybox/scripts/functions new file mode 100755 index 000000000..216c6fb99 --- /dev/null +++ b/packages/sysutils/busybox/scripts/functions @@ -0,0 +1,156 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +# Need a read/write location, as tmp may not always be available +mkdir -p /dev/.progress +rm -f /dev/.progress/* + +# Show frame-buffer cursor +showcursor() { + echo -en "\033[?25h" + + # show cursor + if [ -f /sys/devices/virtual/graphics/fbcon/cursor_blink ] ; then + echo 1 > /sys/devices/virtual/graphics/fbcon/cursor_blink + fi +} + +# Hide frame-buffer cursor +hidecursor() { + echo -en "\033[?25l" + + if [ -f /sys/devices/virtual/graphics/fbcon/cursor_blink ] ; then + echo 0 > /sys/devices/virtual/graphics/fbcon/cursor_blink + fi +} + +# Start a progress meter +# $1: spinner, percent, countdown +# $2: message to display +# [spinner] +# $3: optional command to execute +# $4: optional success completion message (nothing if not specified) +# $5: optional failure completion message ($4 if not specified) +# [percent] +# $3: name of filename to be progress monitored +# $4: terminal size (in bytes) of $3 when progress is complete +# $5: optional command to execute +# $6: optional success message (100% if not specified) +# $7: optional failure message ($6 if not specified) +# [countdown] +# $3: number of seconds to start counting down from +# $4: optional completion message, default is nothing +StartProgress() { + local cmdresult=0 + + # Use files for inter-process communication. + # This file is used to indicate a metter is running/active + + echo > /dev/.progress/run + + case "$1" in + spinner) + ProgressTask_Spinner "$2" & + if [ -n "$3" ]; then + eval "$3" + cmdresult=$? + [ $cmdresult -eq 0 ] && StopProgress "${4}" || StopProgress "${5:-$4}" + fi + ;; + percent) + ProgressTask_Percent "$2" "$3" $4 & + if [ -n "$5" ]; then + eval "$5" + cmdresult=$? + [ $cmdresult -eq 0 ] && StopProgress "${6}" || StopProgress "${7:-$6}" + fi + ;; + countdown) + ProgressTask_Countdown "$2" $3 "$4" + ;; + *) + echo "Unknown spinner type: $1" + return 1 + ;; + esac + + return $cmdresult +} + +# Stop a progress meter, displaying optional completion message +# $1: optional completion message (appropriate default used if not specified) +StopProgress() { + # Instruct running progress meter to end, showing specified completion message + echo "${1}" > /dev/.progress/stop + + # Wait for progress meter to stop running + while [ -f /dev/.progress/run ]; do + usleep 250000 + done + + # Clean up + rm -f /dev/.progress/stop + return 0 +} + +# Use this task for processes of indeterminate duration +ProgressTask_Spinner() { + local msg="$1" + local spinner="|/-\\|/-\\" + local count=0 donemsg + + echo -n "${msg} " + + while [ ! -f /dev/.progress/stop ]; do + echo -en "\b${spinner:$count:1}" + usleep 500000 + count=$(((count + 1) % 8)) + done + + donemsg="$(cat /dev/.progress/stop)" + echo -e "\b${donemsg:-done}" + + rm -f /dev/.progress/run + + exit 0 +} + +# Use this task when transferring a file of known size +ProgressTask_Percent() { + local msg="$1" filename="$2" fsize=$3 csize donemsg + + echo -n "${msg} " + + while [ ! -f /dev/.progress/stop ]; do + [ -f ${filename} ] && csize=$(stat -t "${filename}" | awk '{print $2}') || csize=0 + echo $csize $fsize | awk '{ printf "\b\b\b\b%3d%%", ($1 * 100 / $2) }' + usleep 250000 + done + + donemsg="$(cat /dev/.progress/stop)" + echo -e "\b\b\b\b${donemsg:-100%}" + + rm -f /dev/.progress/run + + exit 0 +} + +# Use this task to countdown a number of seconds +# (needs more work for durations > 99 seconds) +ProgressTask_Countdown() { + local msg="$1" countfrom=$2 donemsg="$3" + + echo -n "${msg} " + + while [ ${countfrom} -gt 0 ]; do + echo ${countfrom} | awk '{ printf "\b\b%2d", $1 }' + read -r -s -t1 && break + countfrom=$((countfrom - 1)) + done + + echo -e "\b\b${donemsg:- }" + + rm -f /dev/.progress/run + + return 0 +} diff --git a/packages/sysutils/busybox/scripts/getedid b/packages/sysutils/busybox/scripts/getedid new file mode 100755 index 000000000..3ca5353e5 --- /dev/null +++ b/packages/sysutils/busybox/scripts/getedid @@ -0,0 +1,256 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) +# +# exit 1 = unsupported GPU +# exit 2 = dual boot system +# exit 3 = no backup for syslinux.cfg or extlinux.conf +# exit 4 = extlinux.conf and syslinux.cfg are available +# exit 5 = changes are already made either to extlinux.conf or syslinux.cfg +# exit 6 = xorg.conf already exists in /storage/.config +# exit 7 = more than a single device detected + +# Help message and usage explanation +help() { + echo "This script generates a custom EDID depending on your GPU" + echo "" + echo "To check which GPU you are using, use: getedid gpu" + echo "" + echo "To create a custom EDID, just use this script like: getedid create" + echo "" + echo "If you don't want to use the created EDID file anymore use: getedid delete" + echo "" + echo "If your hardware or kernel has changed and you want to have a custom EDID again, then you have to delete the old EDID first." + echo "For this use: getedid delete " + echo "And then use: getedid create" +} + + +# check for GPU and store string +check_gpu() { + if lspci | grep -i vga | grep -i -q -E 'intel|amd' ; then + gpu="intel/amd" + elif lspci | grep -i vga | grep -i -q nvidia; then + gpu="nvidia" + else + echo "GPU is not supported" + exit 1 + fi +} + + +# run this first if the user already has a custom EDID but want to create a new one (TV or AVR change) +del_edid() { + if [ "$gpu" = "intel/amd" ]; then + check_file + if [ -f "$file".old ]; then + mount_rw + rm "$file" + mv "$file".old "$file" + rm -f /flash/edid.cpio + mount_ro + sys_reboot + else + echo "You don't have a backup file for $file. You did not use this script to create the custom EDID" + echo "Therefore we can't be sure the script is working properly. Exiting" + exit 3 + fi + else + rm -f /storage/.config/xorg.conf + rm -f /storage/.config/xorg.le.backup + systemctl restart xorg.service + fi +} + + +# run main script depending on the GPU +run() { + if [ "$gpu" = "intel/amd" ]; then + intel_amd + elif [ "$gpu" = "nvidia" ]; then + nvidia + fi +} + + +# mounting /flash to rw +mount_rw() { + mount -o remount,rw /flash +} + + +# mounting /flash to ro +mount_ro() { + mount -o remount,ro /flash +} + + +# remount /flash to ro and reboot +sys_reboot() { + mount_ro + echo "The system is rebooting in 15 seconds" + sleep 15 + reboot +} + + +# check syslinux.cfg and/or extlinux.conf +check_file() { + # check boot system + if [ -d /sys/firmware/efi -a -f /flash/EFI/BOOT/syslinux.cfg ] ; then + sys_boot="UEFI" + sys_path="/flash/EFI/BOOT" + else + sys_boot="BIOS" + sys_path="/flash" + fi + + # check which file is available + if [ -f "$sys_path/syslinux.cfg" -a -f "$sys_path/extlinux.conf" ]; then + echo "Your system contains both a /flash/syslinux.cfg and a /flash/extlinux.conf file" + echo "Something is wrong on your system. Exiting" + exit 4 + elif [ -f "$sys_path/extlinux.conf" ]; then + file="$sys_path/extlinux.conf" + elif [ -f "$sys_path/syslinux.cfg" ]; then + file="$sys_path/syslinux.cfg" + else + echo "You neither have a extlinux.conf nor do you have a syslinux.cfg." + echo "Dual boot systems aren't supported" + exit 2 + fi +} + + +check_content() { + # check if changes are already made to $file and exit if yes + if grep -q "initrd=/edid.cpio" $file ; then + echo "$file has been modified. Please run 'getedid delete' first if you want to modify it again. Exiting." + exit 5 + fi +} + + +check_kernel() { + # determine which kernel is in use and store it in a compareable format. This will probably be deprecated for LE10 + kernel="$(uname -r | sed 's/[^0-9\.].*//g' | awk -F. '{ printf "%d%02d%03d\n",int($1),int($2),int($3) }')" +} + + +create_edid() { + # create edid + mkdir -p /tmp/cpio/lib/firmware/edid + cat "/sys/class/drm/$card/edid" > /tmp/cpio/lib/firmware/edid/edid.bin + mkdir -p /storage/.config/firmware/edid + cp /tmp/cpio/lib/firmware/edid/edid.bin /storage/.config/firmware/edid + + + # create cpio archive + cd /tmp/cpio/ + find . -print | cpio -ov -H newc > /storage/edid.cpio +} + + +intel_amd() { + # check which output is connnected: + counter=0 + for i in /sys/class/drm/*; do + if [ "$(cat "$i"/status 2>/dev/null)" = "connected" ]; then + counter=$((counter + 1)) + if [ $counter -gt 0 -a $counter -lt 2 ]; then + card="$(echo "$i" | cut -d / -f 5)" + hdmi="$(echo "$i" | cut -d / -f 5 | sed 's/card[0-9]-//g')" + else + echo "More than a single device connected. Probably enable \"Disable all other monitors\" at Kodi settings. Aborting!" + exit 7 + fi + fi + done + + # create the edid + create_edid + + # check extlinux.conf and syslinux.cfg + check_file + check_content + + # remount /flash to rw + mount_rw + mv /storage/edid.cpio /flash + + # make a backup of $file + cp "$file" "$file".old + + #check kernel version + check_kernel + + # add boot parameters to $file + sed -i "/ APPEND/s/$/ initrd=\/edid.cpio drm.edid_firmware=edid\/edid.bin video=$hdmi:D/" "$file" + + # reboot + sys_reboot +} + + +nvidia() { + # check if xorg.conf already exists + if [ -f /storage/.config/xorg.conf -o -f /storage/.config/xorg-nvidia.conf ]; then + echo "Existing /storage/.config/xorg.conf detected. Aborting!" + exit 6 + fi + + + # check for multi-montior setup + monitors="$(grep -i -w "connected" /var/log/Xorg.0.log | grep -i -o "dfp-[0-9]" | sort -u | wc -l)" + if [ "$monitors" -gt "1" ]; then + echo "You have more than a single monitor connected. The script doesn't support a multi-monitor setup. Aborting!" + exit 7 + fi + + + # set debug and restart Xorg + cp /etc/X11/xorg-nvidia.conf /storage/.config/xorg.conf + sed -i 's/"ModeDebug" "false"/"ModeDebug" "true"/g' /storage/.config/xorg.conf + systemctl restart xorg.service + + + # get port + nv_port="$(grep -i -w connected /var/log/Xorg.0.log | grep -i -o "dfp-[0-9]" | sort -u)" + nvidia-xconfig --extract-edids-from-file=/var/log/Xorg.0.log --extract-edids-output-file=/storage/.config/edid.bin 1>/dev/null + + # set mode debug back to false + sed -i 's/"ModeDebug" "true"/"ModeDebug" "false"/g' /storage/.config/xorg.conf + + # set port and uncomment lines + sed -i "s/# Option \"ConnectedMonitor\" \"DFP-0\"/ Option \"ConnectedMonitor\" \"$nv_port\"/g" /storage/.config/xorg.conf + sed -i "s/# Option \"CustomEDID\" \"DFP-0:\/storage\/.config\/edid.bin\"/ Option \"CustomEDID\" \"$nv_port:\/storage\/.config\/edid.bin\"/g" /storage/.config/xorg.conf + sed -i "s/# Option \"IgnoreEDID\" \"false\"/ Option \"IgnoreEDID\" \"false\"/g" /storage/.config/xorg.conf + sed -i "s/# Option \"UseEDID\" \"true\"/ Option \"UseEDID\" \"true\"/g" /storage/.config/xorg.conf + + # restart xorg.service + systemctl restart xorg.service +} + + +# start script from here +case "$1" in + 'create') + check_gpu + run + ;; + 'gpu') + check_gpu + echo "$gpu" + ;; + 'delete') + check_gpu + del_edid + ;; + 'help') + help + ;; + *) + echo "Usage $0 { create | gpu | delete | help }" + ;; +esac diff --git a/packages/sysutils/busybox/scripts/init b/packages/sysutils/busybox/scripts/init new file mode 100755 index 000000000..8c4cf856c --- /dev/null +++ b/packages/sysutils/busybox/scripts/init @@ -0,0 +1,1403 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv) +# Copyright (C) 2012 Yann Cézard (eesprit@free.fr) +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) +# Copyright (C) 2020-present Fewtarius + +# create directories +/usr/bin/busybox mkdir -p /dev +/usr/bin/busybox mkdir -p /proc +/usr/bin/busybox mkdir -p /sys +/usr/bin/busybox mkdir -p /tmp +/usr/bin/busybox mkdir -p /flash +/usr/bin/busybox mkdir -p /sysroot +/usr/bin/busybox mkdir -p /storage + +# temp mountpoint for updates +/usr/bin/busybox mkdir -p /update + +# mount all needed special filesystems +/usr/bin/busybox mount -t devtmpfs devtmpfs /dev +/usr/bin/busybox mount -t proc proc /proc +/usr/bin/busybox mount -t sysfs sysfs /sys + +# set needed variables +MODULE_DIR=/usr/lib/modules + +UPDATE_ROOT=/storage/.update +UPDATE_DIR="$UPDATE_ROOT" + +UPDATE_KERNEL="KERNEL" +UPDATE_SYSTEM="SYSTEM" +IMAGE_KERNEL="@KERNEL_NAME@" +IMAGE_SYSTEM="SYSTEM" + +BOOT_STEP="start" +MD5_FAILED="0" +RUN_FSCK="yes" +RUN_FSCK_DISKS="" +SYSLINUX_DEFAULT="" +GRUB_DEFAULT="" + +NBD_DEVS="0" +FLASH_FREE_MIN="5" + +LIVE="no" + +BREAK_TRIPPED="no" + +BIGFONT="1080" + +TEE_PID="" + +# common functions +. /functions 2>/dev/null +. /device.config 2>/dev/null +. /device.init 2>/dev/null + +# Get a serial number if present (eg. RPi) otherwise use MAC address from eth0 +MACHINE_UID="$(awk '/^Serial/{s='0000000' $3; print substr(s, length(s) - 7)}' /proc/cpuinfo 2>/dev/null)" +[ -z "$MACHINE_UID" ] && MACHINE_UID="$(cat /sys/class/net/eth0/address 2>/dev/null | tr -d :)" + +clear >/dev/console + +# script functions +progress() { + if test "$PROGRESS" = "yes"; then + echo "### $1 ###" >&2 + fi +} + +debug_msg() { + echo "$1" >&$SILENT_OUT +} + +debug_shell() { + redirect_output_to_screen # restore output to a screen + echo "### Starting debugging shell for boot step: $BOOT_STEP... type exit to quit ###" + showcursor + setsid cttyhack sh +} + +error() { + # Display fatal error message + # $1:action which caused error, $2:message + # Send debug_shell output to stderr, in case caller is redirecting/consuming stdout + # Return exitcode=1 so that called may detect when an error has occurred + echo "*** Error in $BOOT_STEP: $1: $2 ***" >&2 + debug_shell >&2 + return 1 +} + +break_after() { + # Start debug shell after boot step $1, and all subsequent steps + if [ $BREAK_TRIPPED == yes ]; then + debug_shell + else + case $BREAK in + all|*$1*) + BREAK_TRIPPED=yes + debug_shell + ;; + esac + fi +} + +# Mount handlers +# All handlers take the following parameters: +# $1:target, $2:mountpoint, $3:mount options, [$4:fs type] +mount_common() { + # Common mount handler, handles block devices and filesystem images + MOUNT_OPTIONS="-o $3" + [ -n "$4" ] && MOUNT_OPTIONS="-t $4 $MOUNT_OPTIONS" + + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do + ERR_ENV=1 + + mount $MOUNT_OPTIONS $1 $2 >&$SILENT_OUT 2>&1 + [ "$?" -eq "0" ] && ERR_ENV=0 && break + + usleep 1000000 + done + [ "$ERR_ENV" -eq "0" ] && return 0 + error "mount_common" "Could not mount $1" +} + +get_iscsistart_options() { + # Convert kernel commandline ISCSI= options to iscsistart options + IFS_SAVE="$IFS" + IFS=, + + for arg in $1; do + val="${arg#*=}" + case "$arg" in + iscsi_initiator=*) + option="-i" + ;; + iscsi_target_name=*) + option="-t" + ;; + iscsi_target_ip=*) + option="-a" + ;; + iscsi_target_port=*) + option="-p" + ;; + iscsi_target_group=*) + option="-g" + ;; + iscsi_username=*) + option="-u" + ;; + iscsi_password=*) + option="-w" + ;; + iscsi_in_username=*) + option="-U" + ;; + iscsi_in_password=*) + option="-W" + ;; + esac + echo "$option $val" + done + + IFS="$IFS_SAVE" +} + +mount_iscsi() { + # Mount iSCSI target + ISCSI_DEV="${1##*,}" + ISCSI_OPTIONS="${1%,*}" + + if [ ! -f "/usr/sbin/iscsistart" ]; then + error "iscsistart" "iSCSI support not available" + fi + + if [ "$ISCSI_OPTIONS" = "auto" ]; then + progress "Network configuration based on iBFT" + /usr/sbin/iscsistart -N >&$SILENT_OUT 2>&1 || error "iscsistart" "Unable to configure network" + progress "iSCSI auto connect based on iBFT" + /usr/sbin/iscsistart -b >&$SILENT_OUT 2>&1 || error "iscsistart" "Unable to auto connect" + else + /usr/sbin/iscsistart $(get_iscsistart_options "$ISCSI_OPTIONS") >&$SILENT_OUT 2>&1 || error "iscsistart" "Unable to connect to ISCSI target" + fi + + mount_common "$ISCSI_DEV" "$2" "$3" "$4" +} + +mount_nbd() { +# Mount NBD device + NBD_SERVER="${1%%:*}" + NBD_PORT="${1#*:}" + NBD_DEV="/dev/nbd$NBD_DEVS" + + nbd-client $NBD_SERVER $NBD_PORT $NBD_DEV >&$SILENT_OUT 2>&1 || error "nbd-client" "Could not connect to NBD server $1" + + mount_common "$NBD_DEV" "$2" "$3" "$4" + + NBD_DEVS=$(( NBD_DEVS + 1 )) +} + +mount_nfs() { + # Mount NFS export + NFS_EXPORT="${1%%,*}" + NFS_OPTIONS="${1#*,}" + + [ "$NFS_OPTIONS" = "$1" ] && NFS_OPTIONS= + + mount_common "$NFS_EXPORT" "$2" "$3,nolock,rsize=32768,wsize=32768,$NFS_OPTIONS" "nfs" +} + +mount_ubifs() { + mount_common "$1" "$2" "$3" "ubifs" +} + +# mount_folder "$boot" "/flash" "ro,noatime" +# $1:[TYPE=]target, $2:mountpoint, $3:mount options, [$4:fs type] +mount_folder() { + local target="${1#*=}" + + mkdir -p /dev/bind_tmp + mount_common "$target" "/dev/bind_tmp" "rw,noatime" + mount_common "/dev/bind_tmp/coreelec_$(basename $2)" "$2" "bind" + umount /dev/bind_tmp &>/dev/null + + [ "$2" = "/flash" ] && mount -o remount,ro /flash + [ -z "$(ls -A /dev/bind_tmp)" ] && rm -rf /dev/bind_tmp +} + +mount_part() { + # Mount a local or network filesystem + # $1:[TYPE=]target, $2:mountpoint, $3:mount options, [$4:fs type] + progress "mount filesystem $1 ..." + + MOUNT_TARGET="${1#*=}" + case $1 in + /dev/ubi*) + MOUNT_CMD="mount_ubifs" + MOUNT_TARGET="$1" + RUN_FSCK="no" + ;; + LABEL=*|UUID=*|/*) + MOUNT_CMD="mount_common" + MOUNT_TARGET="$1" + ;; + ISCSI=*) + MOUNT_CMD="mount_iscsi" + ;; + NBD=*) + MOUNT_CMD="mount_nbd" + ;; + NFS=*) + MOUNT_CMD="mount_nfs" + ;; + FOLDER=*) + MOUNT_CMD="mount_folder" + MOUNT_TARGET="$1" + ;; + *) + error "mount_part" "Unknown filesystem $1" + ;; + esac + + # Substitute unique identifier if available or remove placeholder + MOUNT_TARGET="${MOUNT_TARGET//@UID@/$MACHINE_UID}" + + $MOUNT_CMD "$MOUNT_TARGET" "$2" "$3" "$4" +} + +mount_sysroot() { + if [ "$SYSTEM_TORAM" = "yes" ]; then + cp /flash/$IMAGE_SYSTEM /dev/$IMAGE_SYSTEM + mount_part "/dev/$IMAGE_SYSTEM" "/sysroot" "ro,loop" + else + mount_part "/flash/$IMAGE_SYSTEM" "/sysroot" "ro,loop" + fi + + if [ -f /flash/post-sysroot.sh ]; then + . /flash/post-sysroot.sh + fi + +} + +# mount the specified SYSTEM file and output arch from /etc/os-release +get_project_arch() { + if [ -f ${1}/etc/os-release ]; then + . ${1}/etc/os-release + echo "${COREELEC_ARCH:-${LIBREELEC_ARCH}}" + fi +} + +# mount the specified SYSTEM file and output version from /etc/os-release +get_project_version() { + if [ -f ${1}/etc/os-release ]; then + . ${1}/etc/os-release + echo "${VERSION}" + fi +} + +# If the project/arch of current matches the update, then it is considered compatible. +# Otherwise, mount the update SYSTEM partition and, if canupdate.sh is available, +# call the script to determine if the current update file can be applied on to the +# current system - 0 means it is compatible, non-zero that it is not compatible. +is_compatible() { + local result=1 + + if [ "${1}" = "${2}" ]; then + result=0 + else + if [ -f /update/usr/share/bootloader/canupdate.sh ]; then + sh /update/usr/share/bootloader/canupdate.sh "${1}" "${2}" && result=0 + fi + fi + + return ${result} +} + +# determine if the new SYSTEM file is compatible with the current SYSTEM file +check_is_compatible() { + local update_filename="${1}" + local old_project_arch new_project_arch + + old_project_arch="$(get_project_arch "/sysroot")" || return + new_project_arch="$(get_project_arch "/update")" || return + + # If old or new project/arch isn't available then could be very old (pre-/etc/os-release) build - have to trust it + if [ -n "${old_project_arch}" -a -n "${new_project_arch}" ]; then + # If the old project/arch is not compatible with the new project/arch then abort... + if ! is_compatible "${old_project_arch}" "${new_project_arch}"; then + echo "" + echo "ERROR: $(basename "${update_filename}") is not compatible with ${old_project_arch} hardware - update cancelled." + echo "" + echo "Current system: ${old_project_arch}" + echo "Update system: ${new_project_arch}" + echo "" + echo "Create $UPDATE_ROOT/.nocompat to disable compatibility checks and risk a non-booting system." + echo "" + return 1 + fi + fi + + return 0 +} + +display_versions() { + local old_project_version new_project_version + + old_project_version="$(get_project_version "/sysroot")" || return + new_project_version="$(get_project_version "/update")" || return + + if [ -n "${old_project_version}" -a -n "${new_project_version}" ]; then + echo "" + echo "Updating from ${old_project_version} to ${new_project_version}" + echo "" + fi + + return 0 +} + +update_file() { + if [ -f "$UPDATE_DIR/$2" -a -f "$3" ]; then + mount -o remount,rw /flash + + StartProgress percent "Updating $1... " "$3" $(stat -t "$UPDATE_DIR/$2" | awk '{print $2}') + # use dd here with conv=fsync so that all writes are non-buffered + # ensuring accurate progress - take the sync hit during the + # transfer, rather than when flushing file buffers after the progress + # meter declares the transfer already complete + dd if=$UPDATE_DIR/$2 of=$3 bs=1M conv=fsync 2>/dev/null + + StopProgress + + # loopback file needs writable /flash all the time + if [ "${disk%%=*}" != "FILE" ]; then + mount -o remount,ro /flash + fi + sync + fi +} + +update_partition() { + local result + + if [ -f "$UPDATE_DIR/$2" -a -b "$3" ]; then + StartProgress spinner "Updating $1... " + result="$(dd if="$UPDATE_DIR/$2" of="$3" 2>&1)" + StopProgress "done" + sync + echo "${result}" + fi +} + +update_bootloader() { + local result + + export BOOT_ROOT="/flash" + export SYSTEM_ROOT="/update" + + if [ -f $SYSTEM_ROOT/usr/share/bootloader/update.sh ]; then + echo "" + echo "Updating Boot Files... " + sh $SYSTEM_ROOT/usr/share/bootloader/update.sh + sync + echo "Boot Files Updated." + echo "" + fi +} + +load_modules() { + progress "Loading kernel modules" + + [ ! -f "/etc/modules" ] && return + for module in $(cat /etc/modules); do + progress "Loading kernel module $module" + insmod "$MODULE_DIR/$module.ko" || progress "... Failed to load kernel module $module, skipping" + done +} + +set_consolefont() { + local hres + + progress "Set console font" + if [ -e /dev/fb0 ]; then + hres="$(fbset 2>/dev/null | awk '/geometry/ { print $2 }')" + if [ "${hres}" -lt "1152" ] + then + setfont -C /dev/tty0 ter-v20n.psf + elif [ "${hres}" -ge "1152" ] + then + setfont -C /dev/tty0 ter-v32n.psf + fi + fi +} + +load_splash() { + local set_default_res=no + local vres + + if [ ! "$SPLASH" = "no" ]; then + progress "Loading bootsplash" + + # load uvesafb module if needed + if [ -f "$MODULE_DIR/uvesafb.ko" -a ! -e /dev/fb0 ]; then + progress "Loading kernel module uvesafb.ko" + insmod "$MODULE_DIR/uvesafb.ko" && set_default_res=yes || progress "... Failed to load kernel module uvesafb, skipping" + fi + + if [ -e /dev/fb0 ]; then + # Set framebuffer to a custom resolution and/or fallback to default resolution (1024x768-32), if required. + if [ ! "$SWITCH_FRAMEBUFFER" = "no" ]; then + if [ "$SWITCH_FRAMEBUFFER" = "1080" ]; then + SWITCH_FRAMEBUFFER="1920 1080 1920 1080 32" + elif [ "$SWITCH_FRAMEBUFFER" = "720" ]; then + SWITCH_FRAMEBUFFER="1280 720 1280 720 32" + fi + + # Try setting a custom framebuffer resolution + if [ ! "${SWITCH_FRAMEBUFFER:-yes}" = "yes" ]; then + fbset -g $SWITCH_FRAMEBUFFER 2>/dev/null && set_default_res=no + fi + + # Set a default resolution if required + if [ "$set_default_res" = "yes" ]; then + fbset -g 1024 768 1024 768 32 2>/dev/null + fi + fi + + # load splash + if [ -f /splash/splash.conf ]; then + . /splash/splash.conf + fi + + # Select splash image based on current native resolution + if [ -z "$SPLASHIMAGE" ]; then + vres="$(fbset 2>/dev/null | awk '/geometry/ { print $3 }')" + hres="$(fbset 2>/dev/null | awk '/geometry/ { print $2 }')" + if [ "${hres}" = "640" ] || [ "${hres}" = "1152" ] + then + RES="${hres}" + else + RES="${vres}" + fi + + if [ "${DISPLAY_ROTATED}" == true ] + then + RES="${RES}l" + fi + + for s in /splash/splash-${RES}.png \ + /splash/splash-1080.png \ + ; do + if [ -f "${s}" ]; then + SPLASHIMAGE="${s}" + break + fi + done + fi + + if [ -n "$SPLASHIMAGE" -a -f "$SPLASHIMAGE" ]; then + ply-image $SPLASHIMAGE > /dev/null 2>&1 + fi + + debug_msg "Framebuffer vertical res: $vres" + debug_msg "Framebuffer splash image: $SPLASHIMAGE" + fi + fi +} + +do_reboot() { + echo "System reboots now..." + + # stop output redirection + [ -n "$TEE_PID" ] && kill $TEE_PID &>/dev/null + if [ -s /dev/init.log ]; then + mv /dev/init.log /storage/init-previous.log + fi + redirect_output_to_screen + delete_descriptors + + # syncing filesystem + sync + + # unmount filesystems + if /usr/bin/busybox mountpoint -q /flash ; then + /usr/bin/busybox umount /flash &>/dev/null + fi + + if /usr/bin/busybox mountpoint -q /storage ; then + /usr/bin/busybox umount /storage &>/dev/null + fi + + usleep 2000000 + /usr/bin/busybox reboot +} + +force_fsck() { + echo "Filesystem corruption has been detected!" + echo "To prevent an automatic repair attempt continuing," + echo "press any key or power off your system within the next 120 seconds" + echo "" + read -t120 -n1 + # The exit status is 0 if input is available + # The exit status is greater than 128 if the timeout is exceeded + if [ $? -ne 0 -o $? -gt 128 ]; then + echo "Repairing filesystem..." + echo "" + /usr/sbin/fsck -T -M -y $RUN_FSCK_DISKS + FSCK_RET=$? + if [ $(( $FSCK_RET & 8 )) -eq 8 ]; then + # fubar + echo "Forced fsck failed. Your system is broken beyond repair" + echo "Please re-install @DISTRONAME@" + echo "" + echo "Press enter to shutdown now" + echo "" + read fubar + poweroff + fi + do_reboot + else + echo "Shutting down..." + sleep 5 + sync + poweroff + fi +} + +check_disks() { + if [ "$RUN_FSCK" = "yes" -a -n "$RUN_FSCK_DISKS" ]; then + progress "Checking disk(s): $RUN_FSCK_DISKS" + echo "Checking disk(s): $RUN_FSCK_DISKS" >/dev/kmsg + for i in 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0; do + /usr/sbin/fsck -T -M -p -a $RUN_FSCK_DISKS >/dev/fsck.latest 2>&1 + FSCK_RET=$? + cat /dev/fsck.latest >>/dev/fsck.log + + # FSCK_RET is the bit-wise OR of the exit codes for each filesystem that is checked. + if [ $FSCK_RET -ge 16 ]; then + progress "General error, continuing..." + break + elif [ $(( $FSCK_RET & 8 )) -eq 8 ]; then + # device not found + if [ $i -eq 0 ]; then + progress "Device not found, continuing..." + else + usleep 500000 + fi + elif [ $(( $FSCK_RET & 4 )) -eq 4 ]; then + # errors left + force_fsck + elif [ $(( $FSCK_RET & 2 )) -eq 2 ]; then + # reboot needed + echo "Filesystem repaired, reboot needed..." + do_reboot + elif [ $(( $FSCK_RET & 1 )) -eq 1 ]; then + # filesystem errors corrected + progress "Filesystem errors corrected , continuing..." + break + elif [ $FSCK_RET -eq 0 ]; then + # no errors found + progress "No filesystem errors found, continuing..." + break + fi + done + while read line; do + [ -n "$line" ] && echo "fsck: ${line::160}" >/dev/kmsg + done /dev/null; then + ether-wake "$wol_mac" + StartProgress countdown "WOL magic packet sent to $wol_ip, waiting $wol_wait seconds... " $wol_wait "done" + fi + fi +} + +mount_flash() { + progress "Mounting flash" + + wakeonlan + + mount_part "$boot" "/flash" "ro,noatime" + + if [ -f /flash/post-flash.sh ]; then + . /flash/post-flash.sh + fi +} + +cleanup_flash() { + progress "Cleaning up flash (if required)" + + if [ -f /flash/pieeprom.bin -o -f /flash/pieeprom.upd -o -f /flash/vl805.bin ]; then + mount -o remount,rw /flash + + rm -f /flash/pieeprom.bin /flash/pieeprom.upd /flash/pieeprom.sig + rm -f /flash/vl805.bin /flash/vl805.sig + rm -f /flash/recovery.bin /flash/recovery.[0-9][0-9][0-9] /flash/RECOVERY.[0-9][0-9][0-9] + + mount -o remount,ro /flash + fi +} + +mount_storage() { + progress "Mounting storage" + + if [ "$LIVE" = "yes" ]; then + # mount tmpfs and exit early. disk=xx is not allowed in live mode + mount -t tmpfs none /storage + return + fi + + wakeonlan + + if [ -n "$disk" ]; then + if [ -n "$OVERLAY" ]; then + OVERLAY_DIR=$(cat /sys/class/net/eth0/address | tr -d :) + + mount_part "$disk" "/storage" "rw,noatime" + mkdir -p /storage/$OVERLAY_DIR + umount /storage &>/dev/null + + # split $disk into $target,$options so we can append $OVERLAY_DIR + options="${disk#*,}" + target="${disk%%,*}" + if [ "$options" = "$disk" ]; then + disk="$target/$OVERLAY_DIR" + else + disk="$target/$OVERLAY_DIR,$options" + fi + fi + + if [ -f /flash/mount-storage.sh ]; then + . /flash/mount-storage.sh + else + mount_part "$disk" "/storage" "rw,noatime" + fi + else + # /storage should always be writable + mount -t tmpfs none /storage + fi +} + +mount_games() { + if /usr/bin/busybox mountpoint -q /storage ; then + progress "Mounting games" + if [ ! -d "/storage/roms" ] + then + /usr/bin/busybox mkdir -p /storage/roms >/dev/null 2>&1 + fi + + for DEV in $(blkid | awk 'BEGIN {FS=":"}; /ext4/ || /fat/ {print $1}' | sort -r) + do + if [ -e "${DEV}" ] && [ ! -e "/storage/.please_resize_me" ] + then + mount ${DEV} /storage/roms >/dev/null 2>&1 + break + fi + done + + if [ -d "/storage/.update" ] && [ ! -e "/storage/.please_resize_me" ] + then + /usr/bin/busybox rm -rf /storage/.update >/dev/null 2>&1 + /usr/bin/busybox mkdir -p /storage/.update >/dev/null 2>&1 + fi + + if [ ! -d "/storage/roms/update" ] + then + /usr/bin/busybox mkdir -p /storage/roms/update >/dev/null 2>&1 + fi + + /usr/bin/busybox mountpoint -q /storage/roms >/dev/null 2>&1 + if [ $? == "0" ] && [ ! -e "/storage/.please_resize_me" ] + then + /usr/bin/busybox mkdir -p "$UPDATE_ROOT" >/dev/null 2>&1 + mount --bind /storage/roms/update "$UPDATE_ROOT" >/dev/null 2>&1 + fi + fi +} + +# Make last bootloader label (installer, live, run etc.) as the new default +update_bootmenu() { + local crnt_default + + if [ -n "$SYSLINUX_DEFAULT" -a -f /flash/syslinux.cfg ]; then + if grep -q "^LABEL $SYSLINUX_DEFAULT\$" /flash/syslinux.cfg 2>/dev/null; then + crnt_default="$(awk '/^DEFAULT/ {print $2}' /flash/syslinux.cfg)" + if [ ! "$crnt_default" = "$SYSLINUX_DEFAULT" ]; then + progress "Updating /flash/syslinux.cfg [$crnt_default -> $SYSLINUX_DEFAULT]" + + mount -o remount,rw /flash + sed -e "s/^SAY Wait for .* mode/SAY Wait for ${SYSLINUX_DEFAULT} mode/" -i /flash/syslinux.cfg + sed -e "s/^DEFAULT .*/DEFAULT $SYSLINUX_DEFAULT/" -i /flash/syslinux.cfg + rm -f /flash/EFI/BOOT/syslinux.cfg + mount -o remount,ro /flash + fi + fi + fi + + if [ -n "$GRUB_DEFAULT" -a -f /flash/EFI/BOOT/grub.cfg ]; then + if grep -q "^menuentry \"$GRUB_DEFAULT\"" /flash/EFI/BOOT/grub.cfg 2>/dev/null; then + crnt_default="$(awk '/^set default/ {print substr($2,9,19)}' /flash/EFI/BOOT/grub.cfg)" + if [ ! "$crnt_default" = "\"$GRUB_DEFAULT\"" ]; then + progress "Updating /flash/EFI/BOOT/grub.cfg [$crnt_default -> \"$GRUB_DEFAULT\"]" + + mount -o remount,rw /flash + sed -e "s/^set default=.*/set default=\"$GRUB_DEFAULT\"/" -i /flash/EFI/BOOT/grub.cfg + rm -f /flash/grub.cfg + mount -o remount,ro /flash + fi + fi + fi +} + +check_out_of_space() { + if [ "$(df /storage | awk '/[0-9]%/{print $4}')" -eq "0" ]; then + echo "" + echo "The $1 is corrupt, or there is not enough" + echo "free space on /storage to complete the update!" + echo "" + echo "Please free up space on your /storage partition" + echo "by deleting unecessary files, then try again." + echo "" + return 0 + else + echo "" + echo "The $1 is corrupt/invalid!" + echo "" + return 1 + fi +} + +do_cleanup() { + StartProgress spinner "Cleaning up... " + + if mountpoint -q /storage/roms; then + umount /storage/roms &>/dev/null + fi + + if mountpoint -q /storage; then + umount /storage &>/dev/null + fi + + if mountpoint -q /update; then + umount /update &>/dev/null + fi + + if [ -d $UPDATE_ROOT/.tmp/mnt ]; then + if mountpoint -q $UPDATE_ROOT/.tmp/mnt ; then + # busybox umount deletes loop device automatically + umount $UPDATE_ROOT/.tmp/mnt &>/dev/null + fi + + [ -n $LOOP ] && losetup -d $LOOP &>/dev/null + fi + + [ -f "$UPDATE_TAR" ] && rm -f "$UPDATE_TAR" &>/dev/null + [ -f "$UPDATE_IMG_GZ" ] && rm -f "$UPDATE_IMG_GZ" &>/dev/null + [ -f "$UPDATE_IMG" ] && rm -f "$UPDATE_IMG" &>/dev/null + + rm -rf $UPDATE_ROOT/[0-9a-zA-Z]* &>/dev/null + rm -f $UPDATE_ROOT/* &>/dev/null + rm -f $UPDATE_ROOT/.nocheck $UPDATE_ROOT/.nocompat &>/dev/null + rm -rf $UPDATE_ROOT/.tmp &>/dev/null + + sync + + StopProgress "done" +} + +check_update() { + progress "Checking for updates" + UPDATE_TAR=$(ls -1 "$UPDATE_DIR"/*.tar 2>/dev/null | head -n 1) + UPDATE_IMG_GZ=$(ls -1 "$UPDATE_DIR"/*.img.gz 2>/dev/null | head -n 1) + UPDATE_IMG=$(ls -1 "$UPDATE_DIR"/*.img 2>/dev/null | head -n 1) + + if ! [ -f "$UPDATE_DIR/$UPDATE_KERNEL" -a -f "$UPDATE_DIR/$UPDATE_SYSTEM" ] && + ! [ -f "$UPDATE_TAR" -o -f "$UPDATE_IMG_GZ" -o -f "$UPDATE_IMG" ]; then + return 0 + fi + + echo "${UPDATE_TAR} ${UPDATE_IMG} ${UPDATE_IMG_GZ}" 2>&1 | grep JELOS 2>&1 >/dev/null + if [ "$?" -ne "0" ] + then + echo "Unsupported operating system update. Please only use JELOS update packages with this distribution." + do_cleanup + StartProgress countdown "Reboot in 5s... " 5 "now" + reboot + fi + + if [ "$UPDATE_DISABLED" = "yes" ]; then + echo "Updating is not supported on netboot" + do_cleanup + StartProgress countdown "Normal startup in 5s... " 5 "NOW" + return 0 + fi + + if [ -d $UPDATE_DIR/.tmp ]; then + # This isn't really a failed update, it's just a failure to clean up after updating. + #echo "Failed update detected - performing recovery." + #echo "" + do_cleanup + StartProgress countdown "Reboot in 5... " 5 "NOW" + sync + reboot + #return 0 + fi + + mkdir -p $UPDATE_DIR/.tmp &>/dev/null + sync + + clear >/dev/console + echo "UPDATE IN PROGRESS" + echo "" + echo "Please do not reboot or turn off your @DISTRONAME@ device!" + echo "" + + if [ -f "$UPDATE_TAR" ]; then + TARRESULT="0" + + echo "Found new .tar archive" + UPDATE_FILENAME="$UPDATE_TAR" + StartProgress spinner "Extracting contents of archive... " + tar -xf "$UPDATE_TAR" -C $UPDATE_DIR/.tmp 1>/dev/null 2>/tmp/tarresult.txt || TARRESULT="1" + + if [ "${TARRESULT}" -eq "0" ]; then + mv $UPDATE_DIR/.tmp/*/target/* $UPDATE_DIR &>/dev/null + sync + StopProgress "done" + else + StopProgress "FAILED" + + echo "Failed to extract contents of archive file!" + echo "tar result: '$(cat /tmp/tarresult.txt)'" + + check_out_of_space "archive" + + do_cleanup + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + return 0 + fi + elif [ -f "$UPDATE_IMG_GZ" -o -f "$UPDATE_IMG" ]; then + mkdir -p $UPDATE_DIR/.tmp/mnt &>/dev/null + IMG_FILE="$UPDATE_DIR/.tmp/update.img" + GZRESULT="0" + + if [ -f "$UPDATE_IMG_GZ" ]; then + echo "Found new compressed image file" + UPDATE_FILENAME="$UPDATE_IMG_GZ" + StartProgress spinner "Decompressing image file... " + gunzip -d -c "$UPDATE_IMG_GZ" 1>$IMG_FILE 2>/tmp/gzresult.txt || GZRESULT="1" + sync + [ "${GZRESULT}" -eq "0" ] && StopProgress "OK" || StopProgress "FAILED" + + if [ "${GZRESULT}" -eq "1" ]; then + echo "Failed to decompress image file!" + echo "gunzip result: '$(cat /tmp/gzresult.txt)'" + + check_out_of_space "compressed image" + + do_cleanup + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + return 0 + fi + else + echo "Found new image file" + UPDATE_FILENAME="$UPDATE_IMG" + mv "$UPDATE_IMG" $IMG_FILE + fi + + LOOP=$(losetup -f) + LOOP_NUM=$(echo $LOOP | sed 's|/dev/loop||') + mknod $LOOP b 7 $LOOP_NUM &>/dev/null + losetup $LOOP $IMG_FILE + + # check for MBR partititon + OFFSET=$(fdisk -u -l $LOOP 2>/dev/null | awk '/^[ ]*Device/{part=1; next}; part{if ($2 == "*") {print $5} else {print $4} ; exit}') + if [ -z "$OFFSET" ]; then + # check for GPT partititon + OFFSET=$(fdisk -u -l $LOOP 2>/dev/null | awk '/^Number/{part=1; next}; part{print $2; exit}') + if [ -z "$OFFSET" ]; then + echo "Could not find a valid system partition in image file!" + do_cleanup + StartProgress countdown "Normal startup in 5s... " 5 "NOW" + return 0 + fi + fi + + SECTOR_SIZE=$(cat /sys/devices/virtual/block/loop${LOOP_NUM}/queue/hw_sector_size) + losetup -d $LOOP + sync + + OFFSET=$(($OFFSET * $SECTOR_SIZE)) + + # use losetup because busybox mount does not support the -o offset option + echo "Mounting system partition..." + losetup -o $OFFSET $LOOP $IMG_FILE + mount -o ro,loop $LOOP $UPDATE_DIR/.tmp/mnt + + # don't make temporary files but instead copy + # directly from mountpoint to /flash + UPDATE_DIR=$UPDATE_ROOT/.tmp/mnt + UPDATE_KERNEL="@KERNEL_NAME@" + else + UPDATE_FILENAME="$UPDATE_DIR/$UPDATE_SYSTEM" + fi + + sync + + if [ ! -b "/$IMAGE_KERNEL" -a ! -f "/flash/$IMAGE_KERNEL" ] || [ ! -f "/flash/$IMAGE_SYSTEM" ]; then + echo "Missing (target) ${IMAGE_KERNEL} or ${IMAGE_SYSTEM}!" + do_cleanup + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + return 0 + fi + + if [ ! -f "$UPDATE_DIR/$UPDATE_KERNEL" -o ! -f "$UPDATE_DIR/$UPDATE_SYSTEM" ]; then + echo "Missing (source) ${UPDATE_KERNEL} or ${UPDATE_SYSTEM}!" + do_cleanup + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + return 0 + fi + + # check md5 sums if .nocheck doesn't exist + if [ ! -f "$UPDATE_ROOT/.nocheck" ]; then + if [ -f "$UPDATE_DIR/${UPDATE_KERNEL}.md5" -a -f "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" ]; then + # *.md5 size-check + if [ ! -s "$UPDATE_DIR/${UPDATE_KERNEL}.md5" -o ! -s "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" ]; then + echo "Zero-sized .md5 file!" + MD5_FAILED="1" + else + sed "s#target/KERNEL#$UPDATE_DIR/$UPDATE_KERNEL#g" "$UPDATE_DIR/${UPDATE_KERNEL}.md5" >"$UPDATE_ROOT/${UPDATE_KERNEL}.check.md5" + sed "s#target#$UPDATE_DIR#g" "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" >"$UPDATE_ROOT/${UPDATE_SYSTEM}.check.md5" + + StartProgress spinner "Checking ${UPDATE_KERNEL}.md5... " + if md5sum -sc "$UPDATE_ROOT/${UPDATE_KERNEL}.check.md5"; then + StopProgress "OK" + else + StopProgress "FAILED" + MD5_FAILED="1" + fi + + StartProgress spinner "Checking ${UPDATE_SYSTEM}.md5... " + if md5sum -sc "$UPDATE_ROOT/${UPDATE_SYSTEM}.check.md5"; then + StopProgress "OK" + else + StopProgress "FAILED" + MD5_FAILED="1" + fi + fi + else + echo "Missing ${UPDATE_KERNEL}.md5 or ${UPDATE_SYSTEM}.md5!" + MD5_FAILED="1" + fi + + if [ "$MD5_FAILED" -eq "1" ]; then + echo "md5 check failed!" + do_cleanup + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + return 0 + fi + fi + + mount_part "$UPDATE_DIR/$UPDATE_SYSTEM" "/update" "ro,loop" + + # Verify that the new update is compatible with the current system - this should avoid creating + # non-booting systems after (for example) an RPi tar is incorrectly applied to an RPi2 system. + if [ ! -f "$UPDATE_ROOT/.nocompat" ]; then + if ! check_is_compatible "$UPDATE_FILENAME"; then + do_cleanup + StartProgress countdown "Normal startup in 60s... " 60 "NOW" + return 0 + fi + fi + + # get sizes + FLASH_FREE=$(df /flash/ | awk '/[0-9]%/{print $4}') + FLASH_FREE=$(( $FLASH_FREE * 1024 )) + + # Disregard kernel size if it's a a block device + if [ ! -b "/$IMAGE_KERNEL" ]; then + OLD_KERNEL=$(stat -t "/flash/$IMAGE_KERNEL" | awk '{print $2}') + else + OLD_KERNEL="0" + fi + + OLD_SYSTEM=$(stat -t "/flash/$IMAGE_SYSTEM" | awk '{print $2}') + NEW_KERNEL=$(stat -t "$UPDATE_DIR/$UPDATE_KERNEL" | awk '{print $2}') + NEW_SYSTEM=$(stat -t "$UPDATE_DIR/$UPDATE_SYSTEM" | awk '{print $2}') + + # old KERNEL+SYSTEM+free space - new KERNEL+SYSTEM must be higher than 5MB + # at least 5MB free after update + + TMP_SIZE=$((OLD_KERNEL + OLD_SYSTEM + FLASH_FREE - NEW_KERNEL - NEW_SYSTEM)) + FLASH_FREE_MIN=$((FLASH_FREE_MIN * 1024 * 1024)) + + if [ $TMP_SIZE -ge $FLASH_FREE_MIN ]; then + echo "Checking size: OK" + else + echo "Checking size: FAILED" + echo "" + echo "Your System (FAT) partition is too small for this update," + echo "and there is not enough space for the update to be installed!" + echo "" + echo "You must re-install your system using the disk image of a" + echo "current release, or you must re-size your existing partitions" + echo "so that the System (FAT) partition is at least 512MB in size." + echo "" + do_cleanup + StartProgress countdown "Normal startup in 60s... " 60 "NOW" + return 0 + fi + + # all ok, update + display_versions + if [ -b "/$IMAGE_KERNEL" ]; then + update_partition "Kernel" "$UPDATE_KERNEL" "/$IMAGE_KERNEL" + else + update_file "Kernel" "$UPDATE_KERNEL" "/flash/$IMAGE_KERNEL" + fi + umount /sysroot &>/dev/null + update_file "System" "$UPDATE_SYSTEM" "/flash/$IMAGE_SYSTEM" + update_bootloader + sync + StartProgress countdown "Update complete. Reboot in 5s... " 5 "NOW" + do_cleanup + sync + do_reboot +} + +prepare_sysroot() { + progress "Preparing system" + + mount --move /flash /sysroot/flash + mount --move /storage /sysroot/storage + + if [ ! -d "/sysroot/usr/lib/kernel-overlays/base/lib/modules/$(uname -r)/" -a -f "/sysroot/usr/lib/systemd/systemd" ]; then + echo "" + echo "NEVER TOUCH boot= in syslinux.conf / cmdline.txt!" + echo "If you don't know what you are doing," + echo "your installation is now broken." + echo "" + StartProgress countdown "Normal startup in 60s... " 60 "NOW" + fi + + [ -f "/sysroot/usr/lib/systemd/systemd" ] || error "final_check" "Could not find systemd!" +} + +check_amlogic_dtb() { + if grep -q "amlogic" /proc/device-tree/compatible 2>/dev/null; then + if grep -q "official" /sysroot/etc/os-release 2>/dev/null; then + progress "Checking Amlogic DTB" + if [ "$(uname -r)" = "3.14.29" ]; then + DT_ID=$(cat /proc/device-tree/le-dt-id 2>/dev/null) + else + DT_ID=$(cat /proc/device-tree/coreelec-dt-id 2>/dev/null) + fi + DT_FILE=$(ls -1 /sysroot/usr/share/bootloader/device_trees/${DT_ID}.dtb 2>/dev/null | head -n 1) + + if [ -f "/proc/device-tree/coreelec" ] && + [ -n "${DT_ID}" ] && + [ -f "${DT_FILE}" ]; then + return 0 + fi + + echo "WARNING: Your device-tree is out-of-date!" + echo "" + echo "Please update it to resume normal startup." + echo "" + + StartProgress countdown "Normal startup in 30s... " 30 "NOW" + echo "" + fi + fi +} + +# create pipe and save original descriptors +create_output_pipe() { + # save original stdout and stderr descriptors + exec 4>&1 + exec 5>&2 + + # create pipe and use it with tee + mknod /tmp/output_pipe p + tee /tmp/output_pipe + exec 2>/tmp/output_pipe +} + +# restore original descriptors +redirect_output_to_screen() { + exec 1>&4 + exec 2>&5 +} + +# delete descriptor +delete_descriptors() { + exec 4>&- + exec 5>&- +} + +# Do init tasks to bring up system + +# set ondemand up_threshold +if [ -e /sys/devices/system/cpu/cpufreq/ondemand/up_threshold ]; then + echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold +else + for f in $(ls /sys/devices/system/cpu/cpufreq/policy*/ondemand/up_threshold 2>/dev/null) ; do + echo 50 > $f + done +fi + +# run platform_init script if exists +if [ -f "./platform_init" ]; then + ./platform_init +fi + +# clear screen and hide cursor +clear +hidecursor + +create_output_pipe +redirect_output_to_pipe + +# parse command line arguments +for arg in $(cat /proc/cmdline); do + case $arg in + BOOT_IMAGE=*) + IMAGE_KERNEL="${arg#*=}" + [ "${IMAGE_KERNEL:0:1}" = "/" ] && IMAGE_KERNEL="${IMAGE_KERNEL:1}" + ;; + SYSTEM_IMAGE=*) + IMAGE_SYSTEM="${arg#*=}" + [ "${IMAGE_SYSTEM:0:1}" = "/" ] && IMAGE_SYSTEM="${IMAGE_SYSTEM:1}" + ;; + boot=*) + boot="${arg#*=}" + case $boot in + ISCSI=*|NBD=*|NFS=*) + UPDATE_DISABLED=yes + FLASH_NETBOOT=yes + ;; + /dev/*|LABEL=*|UUID=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS $boot" + ;; + FOLDER=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS ${boot#*=}" + ;; + esac + ;; + disk=*) + disk="${arg#*=}" + case $disk in + ISCSI=*|NBD=*|NFS=*) + STORAGE_NETBOOT=yes + ;; + /dev/*|LABEL=*|UUID=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS $disk" + ;; + FOLDER=*) + RUN_FSCK_DISKS="$RUN_FSCK_DISKS ${disk#*=}" + ;; + esac + ;; + wol_mac=*) + wol_mac="${arg#*=}" + ;; + wol_wait=*) + wol_wait="${arg#*=}" + ;; + textmode) + INIT_UNIT="--unit=textmode.target" + ;; + installer) + INIT_UNIT="--unit=installer.target" + SYSLINUX_DEFAULT="installer" + ;; + debugging) + DEBUG=yes + ;; + nopkmute) + MUTE_PRINTK=no + ;; + progress) + PROGRESS=yes + INIT_ARGS="$INIT_ARGS --show-status=1" + ;; + nofsck) + RUN_FSCK=no + ;; + nosplash) + SPLASH=no + ;; + toram) + SYSTEM_TORAM=yes + ;; + live) + LIVE=yes + SYSLINUX_DEFAULT="live" + ;; + portable) + SYSLINUX_DEFAULT="run" + ;; + grub_live) + LIVE=yes + GRUB_DEFAULT="Live" + ;; + grub_portable) + GRUB_DEFAULT="Run" + ;; + overlay) + OVERLAY=yes + ;; + setfbres=*) + SWITCH_FRAMEBUFFER="${arg#*=}" + SWITCH_FRAMEBUFFER="${SWITCH_FRAMEBUFFER//,/ }" + ;; + break=*) + BREAK="${arg#*=}" + ;; + bigfont=*) + BIGFONT="${arg#*=}" + ;; + ip=*) + KERNEL_IPCONFIG="yes" + ;; + esac +done + +# hide kernel log messages on console +if [ ! "$MUTE_PRINTK" = "no" ]; then + echo '1 4 1 7' > /proc/sys/kernel/printk +fi + +if test "$DEBUG" = "yes"; then + exec 3>&1 +else + exec 3>/dev/null +fi +SILENT_OUT=3 + +# If the network is up (due to the use of the "ip" kernel parameter) and a DNS +# server is known, allow the libc resolver to use it +grep '^\(nameserver\|domain\) ' /proc/net/pnp 2>/dev/null | grep -v '^nameserver 0\.0\.0\.0$' > /etc/resolv.conf + +if [ "${boot%%=*}" = "FILE" ]; then + error "check arguments" "boot argument can't be FILE type..." +fi + +debug_msg "Unique identifier for this client: ${MACHINE_UID:-NOT AVAILABLE}" + +# main boot sequence +for BOOT_STEP in \ + load_modules \ + check_disks \ + mount_flash \ + set_consolefont \ + cleanup_flash \ + update_bootmenu \ + load_splash \ + mount_sysroot \ + mount_storage \ + mount_games \ + check_update \ + prepare_sysroot \ + check_amlogic_dtb; do + $BOOT_STEP + [ -n "$DEBUG" ] && break_after $BOOT_STEP +done + +BOOT_STEP=final + +# log if booting from usb / removable storage +STORAGE=$(cat /proc/mounts | grep " /sysroot/storage " 2>/dev/null | awk '{print $1}' | awk -F '/' '{print $3}') +FLASH=$(cat /proc/mounts | grep " /sysroot/flash " 2>/dev/null | awk '{print $1}' | awk -F '/' '{print $3}') +for i in $STORAGE $FLASH ; do + if [ -n "$i" ]; then + removable="/sys/class/block/*/$i/../removable" + if [ -e $removable ]; then + if [ "$(cat $removable 2>/dev/null)" = "1" ]; then + echo "### BIG FAT WARNING" > /dev/kmsg + echo "### $i is removable. suspend/resume may not work" > /dev/kmsg + fi + fi + fi +done +# move some special filesystems +/usr/bin/busybox mount --move /dev /sysroot/dev +/usr/bin/busybox mount --move /proc /sysroot/proc +/usr/bin/busybox mount --move /sys /sysroot/sys +/usr/bin/busybox rm -fr /tmp + +# tell OE settings addon to disable updates +if [ "$UPDATE_DISABLED" = "yes" ]; then + echo "" > /sysroot/dev/.update_disabled +fi + +if [ "$FLASH_NETBOOT" = "yes" ]; then + echo "" > /sysroot/dev/.flash_netboot +fi + +if [ "$KERNEL_IPCONFIG" = "yes" ]; then + echo "" > /sysroot/dev/.kernel_ipconfig +fi + +# swap can not be used over nfs.(see scripts/mount-swap) +if [ "$STORAGE_NETBOOT" = "yes" ]; then + echo "" > /sysroot/dev/.storage_netboot +fi + +BACKUP_FILE=$(ls -1 /sysroot/storage/.restore/??????????????.tar 2>/dev/null | head -n 1) + +if [ -f /sysroot/storage/.please_resize_me ]; then + INIT_UNIT="--unit=fs-resize.target" +elif [ -f /sysroot/storage/.cache/reset_oe -o -f /sysroot/storage/.cache/reset_xbmc ]; then + INIT_UNIT="--unit=factory-reset.target" +elif [ -f "$BACKUP_FILE" ]; then + INIT_UNIT="--unit=backup-restore.target" +elif [ -f /sysroot/storage/.rpi_flash_firmware ]; then + INIT_UNIT="--unit=rpi-flash-firmware.target" +fi + +# stop output redirection +[ -n "$TEE_PID" ] && kill $TEE_PID &>/dev/null +if [ -s /sysroot/dev/init.log ]; then + mv /sysroot/dev/init.log /sysroot/storage/init.log +else + rm -f /sysroot/dev/init.log + rm -f /sysroot/storage/init.log +fi + +# restore original descriptors and delete descriptors +redirect_output_to_screen +delete_descriptors + +# switch to new sysroot and start real init +exec /usr/bin/busybox switch_root /sysroot /usr/lib/systemd/systemd $INIT_ARGS $INIT_UNIT + +error "switch_root" "Error in initramfs. Could not switch to new root" diff --git a/packages/sysutils/busybox/scripts/lsb_release b/packages/sysutils/busybox/scripts/lsb_release new file mode 100755 index 000000000..4f0a0f584 --- /dev/null +++ b/packages/sysutils/busybox/scripts/lsb_release @@ -0,0 +1,7 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# show release information +. /etc/os-release diff --git a/packages/sysutils/busybox/scripts/pastebinit b/packages/sysutils/busybox/scripts/pastebinit new file mode 100755 index 000000000..6da8acfe7 --- /dev/null +++ b/packages/sysutils/busybox/scripts/pastebinit @@ -0,0 +1,8 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +cat "$@" | curl -F 'f:1=<-' https://paste.coreelec.org diff --git a/packages/sysutils/busybox/scripts/rpi-flash-firmware b/packages/sysutils/busybox/scripts/rpi-flash-firmware new file mode 100755 index 000000000..d519209f8 --- /dev/null +++ b/packages/sysutils/busybox/scripts/rpi-flash-firmware @@ -0,0 +1,42 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +FLAG_FILE="/storage/.rpi_flash_firmware" + +. /usr/lib/libreelec/functions + +hidecursor + +if [ -f "${FLAG_FILE}" ]; then + . ${FLAG_FILE} + rm -f "${FLAG_FILE}" + + if ! mount -o remount,rw /flash 2>/dev/null; then + echo "ERROR: Unable to mount /flash as a read/write file system." + echo + echo "Aborting Flash update process - please proceed with a manual update." + echo + + StartProgress countdown "Rebooting in 15s... " 15 "NOW" + reboot -f &>/dev/null + fi + + # Install new bootloader and/or USB3 firmware files to /flash + # Firmware flashing will occur during the next boot, after + # which the system will again reboot. + # Old firmware files will be automatically removed by init. + CMD_ARGS="" + [ "${BOOTLOADER}" = "yes" ] && CMD_ARGS="${CMD_ARGS} -A bootloader" + [ "${VL805}" = "yes" ] && CMD_ARGS="${CMD_ARGS} -A vl805" + + if [ -n "${CMD_ARGS}" ]; then + USE_FLASHROM=0 /usr/bin/.rpi-eeprom-update.real ${CMD_ARGS} + fi + + sync + mount -o remount,ro /flash +fi + +reboot -f &>/dev/null diff --git a/packages/sysutils/busybox/sleep.d.serial/99-suspend-modules.sh b/packages/sysutils/busybox/sleep.d.serial/99-suspend-modules.sh new file mode 100755 index 000000000..37545ee60 --- /dev/null +++ b/packages/sysutils/busybox/sleep.d.serial/99-suspend-modules.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +if [ -f /storage/.config/suspend-modules.conf ]; then + . /storage/.config/suspend-modules.conf + custom_modules="${SUSPEND_MODULES}" + SUSPEND_MODULES="" +fi + +. /etc/suspend-modules.conf + +if [ -n "${custom_modules}" ]; then + SUSPEND_MODULES="${SUSPEND_MODULES} ${custom_modules}" +fi + +modunload() +{ + local MOD D C USED MODS I + local UNL="$(echo $1 |tr - _)" RET=1 + + while read MOD D C USED D; do + [ "$MOD" = "$UNL" ] || continue + if [ "$USED" = "-" ]; then + # no dependent modules, just try to remove this one. + _rmmod "$MOD" $C + RET=$? + else + # modules depend on this one. try to remove them first. + MODS=",${USED%,}" + while [ -n "${MODS}" ]; do + # try to unload the last one first + MOD="${MODS##*,}" + modunload $MOD && RET=0 + # prune the last one from the list + MODS="${MODS%,*}" + done + # if we unloaded at least one module, then let's + # try again! + [ $RET -eq 0 ] && modunload $MOD + RET=$? + fi + return $RET + done < /proc/modules + # if we came this far, there was nothing to do, + # the module is no longer loaded. + return 0 +} + +_rmmod() +{ + if modprobe -r "$1"; then + touch "/run/libreelec/suspend/module:$1" + return 0 + else + logger -t suspend-modules "# could not unload '$1', usage count was $2" + return 1 + fi +} + +resume_modules() +{ + for x in /run/libreelec/suspend/module:* ; do + [ -O "${x}" ] || continue + modprobe "${x##*:}" &>/dev/null && \ + logger -t resume-modules "Reloaded module ${x##*:}." || \ + logger -t resume-modules "Could not reload module ${x##*:}." + done +} + +suspend_modules() +{ + [ -z "$SUSPEND_MODULES" ] && return 0 + # clean up + rm -rf /run/libreelec/suspend + mkdir -p /run/libreelec/suspend + for x in $SUSPEND_MODULES ; do + modunload $x && \ + logger -t suspend-modules "Unloading kernel module $x: Done" || \ + logger -t suspend-modules "Unloading kernel module $x: Failed" + done + return 0 +} + +case $1 in + pre) + suspend_modules + ;; + post) + resume_modules + ;; +esac diff --git a/packages/sysutils/busybox/sysctl.d/99-coredump.conf b/packages/sysutils/busybox/sysctl.d/99-coredump.conf new file mode 100644 index 000000000..aa33f5f59 --- /dev/null +++ b/packages/sysutils/busybox/sysctl.d/99-coredump.conf @@ -0,0 +1 @@ +kernel.core_pattern=/storage/.cache/cores/core.%E.%t.%p diff --git a/packages/sysutils/busybox/sysctl.d/cdrom.conf b/packages/sysutils/busybox/sysctl.d/cdrom.conf new file mode 100644 index 000000000..a9c22348a --- /dev/null +++ b/packages/sysutils/busybox/sysctl.d/cdrom.conf @@ -0,0 +1,2 @@ +dev.cdrom.lock=0 +dev.cdrom.autoclose=0 diff --git a/packages/sysutils/busybox/sysctl.d/memory.conf b/packages/sysutils/busybox/sysctl.d/memory.conf new file mode 100644 index 000000000..b2ccb5ba4 --- /dev/null +++ b/packages/sysutils/busybox/sysctl.d/memory.conf @@ -0,0 +1 @@ +vm.min_free_kbytes=16384 diff --git a/packages/sysutils/busybox/system.d.opt/cron-defaults.service b/packages/sysutils/busybox/system.d.opt/cron-defaults.service new file mode 100644 index 000000000..fdd14e95b --- /dev/null +++ b/packages/sysutils/busybox/system.d.opt/cron-defaults.service @@ -0,0 +1,11 @@ +[Unit] +Description=Cron defaults +After=local-fs.target + +ConditionPathExists=!/storage/.cache/services/crond.conf +ConditionPathExists=!/storage/.cache/services/crond.disabled + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /usr/share/services/crond.conf /storage/.cache/services/' +RemainAfterExit=yes diff --git a/packages/sysutils/busybox/system.d.opt/cron.service b/packages/sysutils/busybox/system.d.opt/cron.service new file mode 100644 index 000000000..0cf6a1e8c --- /dev/null +++ b/packages/sysutils/busybox/system.d.opt/cron.service @@ -0,0 +1,16 @@ +[Unit] +Description=Cron daemon +After=cron-defaults.service +Requires=cron-defaults.service + +ConditionPathExists=/storage/.cache/services/crond.conf + +[Service] +ExecStartPre=/bin/mkdir -p /storage/.cache/cron/crontabs +ExecStart=/sbin/crond -f -S +KillMode=process +TimeoutStopSec=1s + +[Install] +WantedBy=multi-user.target + diff --git a/packages/sysutils/busybox/system.d/fs-resize.service b/packages/sysutils/busybox/system.d/fs-resize.service new file mode 100644 index 000000000..50d202667 --- /dev/null +++ b/packages/sysutils/busybox/system.d/fs-resize.service @@ -0,0 +1,10 @@ +[Unit] +Description=FS Resize +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/coreelec/fs-resize +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/sysutils/busybox/system.d/fs-resize.target b/packages/sysutils/busybox/system.d/fs-resize.target new file mode 100644 index 000000000..838c57c29 --- /dev/null +++ b/packages/sysutils/busybox/system.d/fs-resize.target @@ -0,0 +1,5 @@ +[Unit] +Description=FS Resize target +Requires=fs-resize.service +After=fs-resize.service +AllowIsolate=yes diff --git a/packages/sysutils/busybox/system.d/rpi-flash-firmware.service b/packages/sysutils/busybox/system.d/rpi-flash-firmware.service new file mode 100644 index 000000000..c05ea654d --- /dev/null +++ b/packages/sysutils/busybox/system.d/rpi-flash-firmware.service @@ -0,0 +1,12 @@ +[Unit] +Description=RPi Flash Firmware +Requires=tmp.mount var.mount sys-kernel-config.mount kernel-overlays.service +After=tmp.mount var.mount sys-kernel-config.mount kernel-overlays.service +DefaultDependencies=no + +[Service] +Type=idle +ExecStart=/usr/lib/libreelec/rpi-flash-firmware +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit diff --git a/packages/sysutils/busybox/system.d/rpi-flash-firmware.target b/packages/sysutils/busybox/system.d/rpi-flash-firmware.target new file mode 100644 index 000000000..98480bca4 --- /dev/null +++ b/packages/sysutils/busybox/system.d/rpi-flash-firmware.target @@ -0,0 +1,5 @@ +[Unit] +Description=RPi Flash Firmware target +Requires=rpi-flash-firmware.service +After=rpi-flash-firmware.service +AllowIsolate=yes diff --git a/packages/sysutils/busybox/system.d/shell.service b/packages/sysutils/busybox/system.d/shell.service new file mode 100644 index 000000000..7b2a0da78 --- /dev/null +++ b/packages/sysutils/busybox/system.d/shell.service @@ -0,0 +1,23 @@ +[Unit] +Description=Textmode Shell +After=multi-user.target + +[Service] +Environment=TTY=1 +WorkingDirectory=/storage +ExecStartPre=/bin/sh -c 'echo -en "\033[?25h"' +ExecStart=/bin/sh -c 'clear; lsb_release; . /etc/profile; exec /bin/sh' + +Restart=always +RestartSec=0 +StandardInput=tty +TTYPath=/dev/tty1 +TTYReset=yes +TTYVHangup=yes +KillMode=process +IgnoreSIGPIPE=no +# bash ignores SIGTERM +KillSignal=SIGHUP + +[Install] +WantedBy=textmode.target diff --git a/packages/sysutils/busybox/system.d/show-version.service b/packages/sysutils/busybox/system.d/show-version.service new file mode 100644 index 000000000..cc29cbad9 --- /dev/null +++ b/packages/sysutils/busybox/system.d/show-version.service @@ -0,0 +1,13 @@ +[Unit] +Description=Show Version +DefaultDependencies=false +ConditionKernelCommandLine=!morequiet + +[Service] +Type=oneshot +ExecStart=/usr/bin/lsb_release +RemainAfterExit=yes +StandardOutput=tty + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/busybox/system.d/storage-log.service b/packages/sysutils/busybox/system.d/storage-log.service new file mode 100644 index 000000000..d27d0a31d --- /dev/null +++ b/packages/sysutils/busybox/system.d/storage-log.service @@ -0,0 +1,9 @@ +[Unit] +Description=Create Persistent Log Directory on /storage +DefaultDependencies=no +RequiresMountsFor=/storage + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/mkdir -p /storage/.cache/log/journal diff --git a/packages/sysutils/busybox/system.d/textmode.target b/packages/sysutils/busybox/system.d/textmode.target new file mode 100644 index 000000000..dad887aca --- /dev/null +++ b/packages/sysutils/busybox/system.d/textmode.target @@ -0,0 +1,6 @@ +[Unit] +Description=Textmode +Requires=multi-user.target +After=multi-user.target +Conflicts=rescue.target +AllowIsolate=yes diff --git a/packages/sysutils/busybox/system.d/var-log.mount b/packages/sysutils/busybox/system.d/var-log.mount new file mode 100644 index 000000000..3acdd0a6d --- /dev/null +++ b/packages/sysutils/busybox/system.d/var-log.mount @@ -0,0 +1,14 @@ +[Unit] +Description=Persistent Log Storage +RequiresMountsFor=/var /storage +Requires=storage-log.service +After=storage-log.service +ConditionKernelCommandLine=!installer +ConditionKernelCommandLine=|debugging +ConditionPathExists=|/storage/.cache/debug.libreelec + +[Mount] +What=/storage/.cache/log +Where=/var/log +Options=bind +LazyUnmount=yes diff --git a/packages/sysutils/busybox/system.d/var.mount b/packages/sysutils/busybox/system.d/var.mount new file mode 100644 index 000000000..1eea76fa0 --- /dev/null +++ b/packages/sysutils/busybox/system.d/var.mount @@ -0,0 +1,21 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Variable Directory +Documentation=man:hier(7) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems +DefaultDependencies=no +Before=local-fs.target umount.target + +[Mount] +What=tmpfs +Where=/var +Type=tmpfs + +[Install] +WantedBy=local-fs.target diff --git a/packages/sysutils/busybox/tmpfiles.d/z_01_busybox.conf b/packages/sysutils/busybox/tmpfiles.d/z_01_busybox.conf new file mode 100644 index 000000000..2bc468498 --- /dev/null +++ b/packages/sysutils/busybox/tmpfiles.d/z_01_busybox.conf @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /var/media 0755 root root - - + +d /storage/backup 0755 root root - - +d /storage/.update 0755 root root - - +d /storage/.cache/cores 0755 root root - - +d /storage/.cache/services 0755 root root - - +d /storage/.config 0755 root root - - diff --git a/packages/sysutils/dbus/package.mk b/packages/sysutils/dbus/package.mk new file mode 100644 index 000000000..a26f65f3b --- /dev/null +++ b/packages/sysutils/dbus/package.mk @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dbus" +PKG_VERSION="1.13.18" +PKG_SHA256="8078f5c25e34ab907ce06905d969dc8ef0ccbec367e1e1707c7ecf8460f4254e" +PKG_LICENSE="GPL" +PKG_SITE="https://dbus.freedesktop.org" +PKG_URL="https://dbus.freedesktop.org/releases/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain expat systemd" +PKG_LONGDESC="D-Bus is a message bus, used for sending messages between applications." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="export ac_cv_have_abstract_sockets=yes \ + --with-sysroot=$SYSROOT_PREFIX \ + --libexecdir=/usr/lib/dbus \ + --disable-verbose-mode \ + --disable-asserts \ + --enable-checks \ + --disable-tests \ + --disable-ansi \ + --disable-xml-docs \ + --disable-doxygen-docs \ + --disable-x11-autolaunch \ + --disable-selinux \ + --disable-libaudit \ + --enable-systemd \ + --enable-inotify \ + --without-valgrind \ + --without-x \ + --with-dbus-user=dbus \ + --runstatedir=/run \ + --with-system-socket=/run/dbus/system_bus_socket" + +post_makeinstall_target() { + rm -rf $INSTALL/etc/rc.d + rm -rf $INSTALL/usr/lib/dbus-1.0/include +} + +post_install() { + add_user dbus x 81 81 "System message bus" "/" "/bin/sh" + add_group dbus 81 + add_group netdev 497 + + echo "chmod 4750 $INSTALL/usr/lib/dbus/dbus-daemon-launch-helper" >> $FAKEROOT_SCRIPT + echo "chown 0:81 $INSTALL/usr/lib/dbus/dbus-daemon-launch-helper" >> $FAKEROOT_SCRIPT +} diff --git a/packages/sysutils/dbus/tmpfiles.d/z_02_dbus.conf b/packages/sysutils/dbus/tmpfiles.d/z_02_dbus.conf new file mode 100644 index 000000000..1f20d1ae4 --- /dev/null +++ b/packages/sysutils/dbus/tmpfiles.d/z_02_dbus.conf @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /var/lib/dbus 0755 root root - - +d /run/dbus 0755 root root - - + +L /var/lib/dbus/machine-id - - - - /etc/machine-id diff --git a/packages/sysutils/depends/efivar/package.mk b/packages/sysutils/depends/efivar/package.mk new file mode 100644 index 000000000..a52004169 --- /dev/null +++ b/packages/sysutils/depends/efivar/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="efivar" +PKG_VERSION="3e687d8072f3ed53ae727ec2cb99ae56dbcdf02b" +PKG_SHA256="810d386c9f4dafc160c721ef73e491c933c311e3df768e27eec50c28ac0f4d97" +PKG_ARCH="x86_64" +PKG_LICENSE="LGPL" +PKG_SITE="https://github.com/rhboot/efivar" +PKG_URL="https://github.com/rhboot/efivar/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain efivar:host" +PKG_LONGDESC="Tools and library to manipulate EFI variables." + +make_host() { + make -C src/ include/efivar/efivar-guids.h +} + +make_target() { + make -C src/ libefivar.a libefiboot.a efivar.h efivar +} + +makeinstall_host() { + : # noop +} + +makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/lib + cp -P src/libefivar.a src/libefiboot.a $SYSROOT_PREFIX/usr/lib/ + + mkdir -p $SYSROOT_PREFIX/usr/include/efivar + cp -P src/include/efivar/*.h $SYSROOT_PREFIX/usr/include/efivar +} diff --git a/packages/sysutils/depends/efivar/patches/efivar-01-static_lib.patch b/packages/sysutils/depends/efivar/patches/efivar-01-static_lib.patch new file mode 100644 index 000000000..5abebf959 --- /dev/null +++ b/packages/sysutils/depends/efivar/patches/efivar-01-static_lib.patch @@ -0,0 +1,11 @@ +--- a/src/Makefile 2018-10-01 21:30:06.000000000 +0200 ++++ b/src/Makefile 2018-10-17 14:16:46.000000000 +0200 +@@ -69,7 +69,7 @@ libefivar.so : | $(GENERATED_SOURCES) li + libefivar.so : LIBS=dl + libefivar.so : MAP=libefivar.map + +-efivar : efivar.c | libefivar.so ++efivar : efivar.c | libefivar.a + efivar : LIBS=efivar dl + + efivar-static : efivar.c $(patsubst %.o,%.static.o,$(LIBEFIVAR_OBJECTS)) diff --git a/packages/sysutils/depends/libmtp/package.mk b/packages/sysutils/depends/libmtp/package.mk new file mode 100644 index 000000000..3bba49e00 --- /dev/null +++ b/packages/sysutils/depends/libmtp/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmtp" +PKG_VERSION="1.1.13" +PKG_SHA256="494ee02fbfbc316aad75b93263dac00f02a4899f28cfda1decbbd6e26fda6d40" +PKG_LICENSE="GPL" +PKG_SITE="http://libmtp.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/project/$PKG_NAME/$PKG_NAME/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libusb" +PKG_LONGDESC="An Initiator implementation of the Media Transfer Protocol (MTP)." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + --disable-shared \ + --enable-static \ + --disable-mtpz" diff --git a/packages/sysutils/depends/libmtp/patches/libmtp-0001-dont-execute-compiled-tools.patch b/packages/sysutils/depends/libmtp/patches/libmtp-0001-dont-execute-compiled-tools.patch new file mode 100644 index 000000000..639b72f01 --- /dev/null +++ b/packages/sysutils/depends/libmtp/patches/libmtp-0001-dont-execute-compiled-tools.patch @@ -0,0 +1,99 @@ +diff -Naur a/Makefile.am b/Makefile.am +--- a/Makefile.am 2015-10-07 00:43:15.000000000 -0700 ++++ b/Makefile.am 2016-04-22 14:16:07.656866841 -0700 +@@ -11,21 +11,6 @@ + if USE_LINUX + udevrulesdir=@UDEV@/rules.d + hwdbdir=@UDEV@/hwdb.d +-udevrules_DATA=@UDEV_RULES@ +-hwdb_DATA=69-libmtp.hwdb +-noinst_DATA=libmtp.usermap libmtp.fdi +- +-libmtp.usermap: util/mtp-hotplug +- util/mtp-hotplug > libmtp.usermap +- +-@UDEV_RULES@: util/mtp-hotplug +- util/mtp-hotplug -u -p"@UDEV@" @UDEV_GROUP@ @UDEV_MODE@ > @UDEV_RULES@ +- +-libmtp.fdi: util/mtp-hotplug +- util/mtp-hotplug -H > libmtp.fdi +- +-$(hwdb_DATA): util/mtp-hotplug +- util/mtp-hotplug -w > $(hwdb_DATA) + + CLEANFILES = libmtp.usermap @UDEV_RULES@ libmtp.fdi libmtp.hwdb + endif +diff -Naur a/Makefile.in b/Makefile.in +--- a/Makefile.in 2016-02-10 12:17:34.000000000 -0800 ++++ b/Makefile.in 2016-04-22 14:14:22.638794537 -0700 +@@ -161,7 +161,7 @@ + } + am__installdirs = "$(DESTDIR)$(hwdbdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(udevrulesdir)" +-DATA = $(hwdb_DATA) $(noinst_DATA) $(pkgconfig_DATA) $(udevrules_DATA) ++DATA = $(pkgconfig_DATA) + RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive + am__recursive_targets = \ +@@ -452,21 +452,8 @@ + + distclean-libtool: + -rm -f libtool config.lt +-install-hwdbDATA: $(hwdb_DATA) +- @$(NORMAL_INSTALL) +- @list='$(hwdb_DATA)'; test -n "$(hwdbdir)" || list=; \ +- if test -n "$$list"; then \ +- echo " $(MKDIR_P) '$(DESTDIR)$(hwdbdir)'"; \ +- $(MKDIR_P) "$(DESTDIR)$(hwdbdir)" || exit 1; \ +- fi; \ +- for p in $$list; do \ +- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ +- echo "$$d$$p"; \ +- done | $(am__base_list) | \ +- while read files; do \ +- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(hwdbdir)'"; \ +- $(INSTALL_DATA) $$files "$(DESTDIR)$(hwdbdir)" || exit $$?; \ +- done ++install-hwdbDATA: ++ echo nope + + uninstall-hwdbDATA: + @$(NORMAL_UNINSTALL) +@@ -871,7 +858,7 @@ + + info-am: + +-install-data-am: install-hwdbDATA install-pkgconfigDATA \ ++install-data-am: install-pkgconfigDATA \ + install-udevrulesDATA + + install-dvi: install-dvi-recursive +@@ -932,7 +919,7 @@ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ +- install-html install-html-am install-hwdbDATA install-info \ ++ install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + install-udevrulesDATA installcheck installcheck-am installdirs \ +@@ -944,19 +931,6 @@ + + .PRECIOUS: Makefile + +- +-@USE_LINUX_TRUE@libmtp.usermap: util/mtp-hotplug +-@USE_LINUX_TRUE@ util/mtp-hotplug > libmtp.usermap +- +-@USE_LINUX_TRUE@@UDEV_RULES@: util/mtp-hotplug +-@USE_LINUX_TRUE@ util/mtp-hotplug -u -p"@UDEV@" @UDEV_GROUP@ @UDEV_MODE@ > @UDEV_RULES@ +- +-@USE_LINUX_TRUE@libmtp.fdi: util/mtp-hotplug +-@USE_LINUX_TRUE@ util/mtp-hotplug -H > libmtp.fdi +- +-@USE_LINUX_TRUE@$(hwdb_DATA): util/mtp-hotplug +-@USE_LINUX_TRUE@ util/mtp-hotplug -w > $(hwdb_DATA) +- + # Tell versions [3.59,3.63) of GNU make to not export all variables. + # Otherwise a system limit (for SysV at least) may be exceeded. + .NOEXPORT: diff --git a/packages/sysutils/depends/oniguruma/package.mk b/packages/sysutils/depends/oniguruma/package.mk new file mode 100644 index 000000000..84be0fc88 --- /dev/null +++ b/packages/sysutils/depends/oniguruma/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="oniguruma" +PKG_VERSION="6.9.1" +PKG_SHA256="c7c3feb7be45a5cc9f2dec239b4a317a422e6ffea299cf91ffab1b926633ea12" +PKG_LICENSE="BSD" +PKG_SITE="https://github.com/kkos/oniguruma" +PKG_URL="https://github.com/kkos/oniguruma/releases/download/v$PKG_VERSION/onig-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A regular expression library" diff --git a/packages/sysutils/diffutils/package.mk b/packages/sysutils/diffutils/package.mk new file mode 100644 index 000000000..8b48b779f --- /dev/null +++ b/packages/sysutils/diffutils/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="diffutils" +PKG_VERSION="3.6" +PKG_SHA256="d621e8bdd4b573918c8145f7ae61817d1be9deb4c8d2328a65cea8e11d783bd6" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/diffutils/" +PKG_URL="http://ftpmirror.gnu.org/diffutils/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A package of several programs related to finding differences between files." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-nls \ + --without-libsigsegv-prefix \ + --without-libiconv-prefix \ + --without-libintl-prefix" + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/diffutils/patches/diffutils-001-no-man.patch b/packages/sysutils/diffutils/patches/diffutils-001-no-man.patch new file mode 100644 index 000000000..297d01496 --- /dev/null +++ b/packages/sysutils/diffutils/patches/diffutils-001-no-man.patch @@ -0,0 +1,11 @@ +--- diffutils-3.5/Makefile.am.org 2017-05-24 18:54:09.404508347 +0200 ++++ diffutils-3.5/Makefile.am 2017-05-24 18:46:25.238456499 +0200 +@@ -19,7 +19,7 @@ + ALL_RECURSIVE_TARGETS = + + EXTRA_DIST = bootstrap exgettext ChangeLog-2008 cfg.mk dist-check.mk +-SUBDIRS = lib src tests doc man po gnulib-tests ++SUBDIRS = lib src tests doc po gnulib-tests + + ACLOCAL_AMFLAGS = -I m4 + AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) diff --git a/packages/sysutils/diffutils/patches/diffutils-002-explicitly-disable-replacing-getopt.patch b/packages/sysutils/diffutils/patches/diffutils-002-explicitly-disable-replacing-getopt.patch new file mode 100644 index 000000000..6e12ba86e --- /dev/null +++ b/packages/sysutils/diffutils/patches/diffutils-002-explicitly-disable-replacing-getopt.patch @@ -0,0 +1,26 @@ +http://cgit.openembedded.org/openembedded-core/tree/meta/recipes-extended/diffutils/diffutils-3.6 + +Subject: explicitly disable replacing getopt + +Explicitly disable replacing getopt to avoid compilation error like below. + + xstrtol-error.c:84:26: error: invalid use of undefined type 'struct rpl_option' + +diff --git a/m4/getopt.m4 b/m4/getopt.m4 +index 3ebc7b7..8934426 100644 +--- a/m4/getopt.m4 ++++ b/m4/getopt.m4 +@@ -22,8 +22,8 @@ AC_DEFUN([gl_FUNC_GETOPT_POSIX], + fi + ]) + if test $REPLACE_GETOPT = 1; then +- dnl Arrange for getopt.h to be created. +- gl_GETOPT_SUBSTITUTE_HEADER ++ dnl Explicitly disable replacing getopt ++ : + fi + ]) + +-- +2.11.0 + diff --git a/packages/sysutils/diskdev_cmds/package.mk b/packages/sysutils/diskdev_cmds/package.mk new file mode 100644 index 000000000..d02f6cf02 --- /dev/null +++ b/packages/sysutils/diskdev_cmds/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="diskdev_cmds" +PKG_VERSION="332.14" +PKG_SHA256="a46bec392661a02d9683355baf4442d494e2bcde0ffb094aacc1e57ddc03b3d4" +PKG_LICENSE="APSL" +PKG_SITE="http://src.gnu-darwin.org/DarwinSourceArchive/expanded/diskdev_cmds/" +PKG_URL="http://www.opensource.apple.com/tarballs/diskdev_cmds/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain openssl" +PKG_LONGDESC="The fsck and mkfs utliities for hfs and hfsplus filesystems." + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="-f Makefile.lnx CC=$CC" + + export CFLAGS="$TARGET_CFLAGS -g3 -Wall -I$PKG_BUILD/include -DDEBUG_BUILD=0 -D_FILE_OFFSET_BITS=64 -D LINUX=1 -D BSD=1" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/sbin + cp fsck_hfs.tproj/fsck_hfs $INSTALL/usr/sbin + ln -sf fsck_hfs $INSTALL/usr/sbin/fsck.hfs + ln -sf fsck_hfs $INSTALL/usr/sbin/fsck.hfsplus +} + +make_init() { + : # we reuse make_target() +} diff --git a/packages/sysutils/diskdev_cmds/patches/diskdev_cmds-332.14-main.patch b/packages/sysutils/diskdev_cmds/patches/diskdev_cmds-332.14-main.patch new file mode 100644 index 000000000..d94350f01 --- /dev/null +++ b/packages/sysutils/diskdev_cmds/patches/diskdev_cmds-332.14-main.patch @@ -0,0 +1,2713 @@ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/cache.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/cache.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/cache.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/cache.c 2008-07-01 22:30:11.000000000 +0200 +@@ -26,7 +26,11 @@ + #include + #include + #include ++#if LINUX ++#include "missing.h" ++#else + #include ++#endif /* __LINUX__ */ + #include + #include + #include +Files diskdev_cmds-332.14/fsck_hfs.tproj/cache.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/cache.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BlockCache.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BlockCache.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BlockCache.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BlockCache.c 2008-07-01 22:30:11.000000000 +0200 +@@ -20,6 +20,9 @@ + * @APPLE_LICENSE_HEADER_END@ + */ + ++#if LINUX ++#include "missing.h" ++#endif + #include "SRuntime.h" + #include "Scavenger.h" + #include "../cache.h" +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BlockCache.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BlockCache.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeAllocate.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeAllocate.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTree.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTree.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTree.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTree.c 2008-07-01 22:30:11.000000000 +0200 +@@ -1705,7 +1705,9 @@ + UInt16 version, + BTreeInfoRec *info ) + { ++#if !LINUX + #pragma unused (version) ++#endif + + BTreeControlBlockPtr btreePtr; + +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeMiscOps.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeMiscOps.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeNodeOps.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeNodeOps.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTree.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTree.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeScanner.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeScanner.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeTreeOps.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeTreeOps.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeTreeOps.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeTreeOps.c 2008-07-01 22:30:11.000000000 +0200 +@@ -223,7 +223,7 @@ + // + if (curNodeNum == 0) + { +-// Panic("\pSearchTree: curNodeNum is zero!"); ++ Panic("SearchTree: curNodeNum is zero!"); + err = fsBTInvalidNodeErr; + goto ErrorExit; + } +@@ -433,7 +433,7 @@ + M_ExitOnError (err); + + if ( DEBUG_BUILD && updateParent && newRoot ) +- DebugStr("\p InsertLevel: New root from primary key, update from secondary key..."); ++ DebugStr("InsertLevel: New root from primary key, update from secondary key..."); + } + + //////////////////////// Update Parent(s) /////////////////////////////// +@@ -448,7 +448,7 @@ + + secondaryKey = nil; + +- PanicIf ( (level == btreePtr->treeDepth), "\p InsertLevel: unfinished insert!?"); ++ PanicIf ( (level == btreePtr->treeDepth), "InsertLevel: unfinished insert!?"); + + ++level; + +@@ -456,7 +456,7 @@ + index = treePathTable [level].index; + parentNodeNum = treePathTable [level].node; + +- PanicIf ( parentNodeNum == 0, "\p InsertLevel: parent node is zero!?"); ++ PanicIf ( parentNodeNum == 0, "InsertLevel: parent node is zero!?"); + + err = GetNode (btreePtr, parentNodeNum, &parentNode); // released as target node in next level up + M_ExitOnError (err); +@@ -470,7 +470,7 @@ + { + //¥¥Êdebug: check if ptr == targetNodeNum + GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize); +- PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p InsertLevel: parent ptr doesn't match target node!"); ++ PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "InsertLevel: parent ptr doesn't match target node!"); + + // need to delete and re-insert this parent key/ptr + // we delete it here and it gets re-inserted in the +@@ -532,7 +532,7 @@ + (void) ReleaseNode (btreePtr, targetNode); + (void) ReleaseNode (btreePtr, &siblingNode); + +- Panic ("\p InsertLevel: an error occured!"); ++ Panic ("InsertLevel: an error occured!"); + + return err; + +@@ -566,7 +566,7 @@ + + *rootSplit = false; + +- PanicIf ( targetNode->buffer == siblingNode->buffer, "\p InsertNode: targetNode == siblingNode, huh?"); ++ PanicIf ( targetNode->buffer == siblingNode->buffer, "InsertNode: targetNode == siblingNode, huh?"); + + leftNodeNum = ((NodeDescPtr) targetNode->buffer)->bLink; + rightNodeNum = ((NodeDescPtr) targetNode->buffer)->fLink; +@@ -606,7 +606,7 @@ + + if ( leftNodeNum > 0 ) + { +- PanicIf ( siblingNode->buffer != nil, "\p InsertNode: siblingNode already aquired!"); ++ PanicIf ( siblingNode->buffer != nil, "InsertNode: siblingNode already aquired!"); + + if ( siblingNode->buffer == nil ) + { +@@ -614,7 +614,7 @@ + M_ExitOnError (err); + } + +- PanicIf ( ((NodeDescPtr) siblingNode->buffer)->fLink != nodeNum, "\p InsertNode, RotateLeft: invalid sibling link!" ); ++ PanicIf ( ((NodeDescPtr) siblingNode->buffer)->fLink != nodeNum, "InsertNode, RotateLeft: invalid sibling link!" ); + + if ( !key->skipRotate ) // are rotates allowed? + { +@@ -703,7 +703,7 @@ + + targetNodeNum = treePathTable[level].node; + targetNodePtr = targetNode->buffer; +- PanicIf (targetNodePtr == nil, "\pDeleteTree: targetNode has nil buffer!"); ++ PanicIf (targetNodePtr == nil, "DeleteTree: targetNode has nil buffer!"); + + DeleteRecord (btreePtr, targetNodePtr, index); + +@@ -797,7 +797,7 @@ + + //¥¥Êdebug: check if ptr == targetNodeNum + GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize); +- PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p DeleteTree: parent ptr doesn't match targetNodeNum!!"); ++ PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, " DeleteTree: parent ptr doesn't match targetNodeNum!!"); + + // need to delete and re-insert this parent key/ptr + DeleteRecord (btreePtr, parentNode.buffer, index); +@@ -1018,7 +1018,7 @@ + keyPtr, keyLength, recPtr, recSize); + if ( !didItFit ) + { +- Panic ("\pRotateLeft: InsertKeyRecord (left) returned false!"); ++ Panic ("RotateLeft: InsertKeyRecord (left) returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1031,7 +1031,7 @@ + didItFit = RotateRecordLeft (btreePtr, leftNode, rightNode); + if ( !didItFit ) + { +- Panic ("\pRotateLeft: RotateRecordLeft returned false!"); ++ Panic ("RotateLeft: RotateRecordLeft returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1048,7 +1048,7 @@ + keyPtr, keyLength, recPtr, recSize); + if ( !didItFit ) + { +- Panic ("\pRotateLeft: InsertKeyRecord (right) returned false!"); ++ Panic ("RotateLeft: InsertKeyRecord (right) returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1117,7 +1117,7 @@ + right = rightNode->buffer; + left = leftNode->buffer; + +- PanicIf ( right->bLink != 0 && left == 0, "\p SplitLeft: left sibling missing!?" ); ++ PanicIf ( right->bLink != 0 && left == 0, " SplitLeft: left sibling missing!?" ); + + //¥¥ type should be kLeafNode or kIndexNode + +@@ -1240,8 +1240,8 @@ + Boolean didItFit; + UInt16 keyLength; + +- PanicIf (leftNode == nil, "\pAddNewRootNode: leftNode == nil"); +- PanicIf (rightNode == nil, "\pAddNewRootNode: rightNode == nil"); ++ PanicIf (leftNode == nil, "AddNewRootNode: leftNode == nil"); ++ PanicIf (rightNode == nil, "AddNewRootNode: rightNode == nil"); + + + /////////////////////// Initialize New Root Node //////////////////////////// +@@ -1264,7 +1264,7 @@ + didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 0, keyPtr, keyLength, + (UInt8 *) &rightNode->bLink, 4 ); + +- PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for left index record"); ++ PanicIf ( !didItFit, "AddNewRootNode:InsertKeyRecord failed for left index record"); + + + //////////////////// Insert Right Node Index Record ///////////////////////// +@@ -1275,7 +1275,7 @@ + didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 1, keyPtr, keyLength, + (UInt8 *) &leftNode->fLink, 4 ); + +- PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for right index record"); ++ PanicIf ( !didItFit, "AddNewRootNode:InsertKeyRecord failed for right index record"); + + + #if DEBUG_TREEOPS +@@ -1355,7 +1355,7 @@ + } + rightPtr = rightNodePtr->buffer; + +- PanicIf ( leftPtr->fLink != 0 && rightPtr == 0, "\p SplitRight: right sibling missing!?" ); ++ PanicIf ( leftPtr->fLink != 0 && rightPtr == 0, "SplitRight: right sibling missing!?" ); + + //¥¥ type should be kLeafNode or kIndexNode + +@@ -1557,7 +1557,7 @@ + keyPtr, keyLength, recPtr, recSize); + if ( !didItFit ) + { +- Panic ("\pRotateRight: InsertKeyRecord (left) returned false!"); ++ Panic ("RotateRight: InsertKeyRecord (left) returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1572,7 +1572,7 @@ + didItFit = RotateRecordRight( btreePtr, leftNodePtr, rightNodePtr ); + if ( !didItFit ) + { +- Panic ("\pRotateRight: RotateRecordRight returned false!"); ++ Panic ("RotateRight: RotateRecordRight returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1583,7 +1583,7 @@ + keyPtr, keyLength, recPtr, recSize); + if ( !didItFit ) + { +- Panic ("\pRotateRight: InsertKeyRecord (left) returned false!"); ++ Panic ("RotateRight: InsertKeyRecord (left) returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +@@ -1607,7 +1607,7 @@ + keyPtr, keyLength, recPtr, recSize); + if ( !didItFit ) + { +- Panic ("\pRotateRight: InsertKeyRecord (right) returned false!"); ++ Panic ("RotateRight: InsertKeyRecord (right) returned false!"); + err = fsBTBadRotateErr; + goto ErrorExit; + } +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/BTreeTreeOps.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/BTreeTreeOps.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/CatalogCheck.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/CatalogCheck.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/HardLinkCheck.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/HardLinkCheck.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/hfs_endian.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/hfs_endian.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/hfs_endian.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/hfs_endian.c 2008-07-02 00:10:48.000000000 +0200 +@@ -31,7 +31,11 @@ + #include + #include + ++#if LINUX ++#include "missing.h" ++#else + #include ++#endif + #include + + #include "Scavenger.h" +@@ -194,7 +198,7 @@ + BTNodeDescriptor *srcDesc = src->buffer; + BTreeControlBlockPtr btcb = fcb->fcbBtree; + UInt16 *srcOffs = NULL; +- UInt32 i; ++ int i; + int error = 0; + + // WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum); +@@ -433,7 +437,7 @@ + BTNodeDescriptor *srcDesc = src->buffer; + UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16)))); + char *nextRecord; /* Points to start of record following current one */ +- UInt32 i; ++ int i; + UInt32 j; + + if (fileID == kHFSExtentsFileID) { +@@ -559,7 +563,7 @@ + /* Make sure name length is consistent with key length */ + if (keyLength < sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) + + srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0])) { +- if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%lu\n", ++ if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%i\n", + srcDesc->numRecords-i, keyLength, sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) + + srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0])); + WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum); +@@ -854,7 +858,7 @@ + UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16)))); + char *nextRecord; /* Points to start of record following current one */ + +- UInt32 i; ++ int i; + UInt32 j; + + if (fileID == kHFSExtentsFileID) { +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/hfs_endian.h diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/hfs_endian.h +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/hfs_endian.h 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/hfs_endian.h 2008-07-01 22:30:11.000000000 +0200 +@@ -27,9 +27,14 @@ + * + * This file prototypes endian swapping routines for the HFS/HFS Plus + * volume format. +- */ ++*/ + #include ++#if LINUX ++#include ++#include ++#else + #include ++#endif + #include "SRuntime.h" + + /*********************/ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/hfs_endian.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/hfs_endian.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/libdfa.a and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/libdfa.a differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/Makefile.lnx diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/Makefile.lnx +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/Makefile.lnx 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/Makefile.lnx 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,15 @@ ++CFILES = hfs_endian.c BlockCache.c\ ++ BTree.c BTreeAllocate.c BTreeMiscOps.c \ ++ BTreeNodeOps.c BTreeScanner.c BTreeTreeOps.c\ ++ CatalogCheck.c HardLinkCheck.c\ ++ SBTree.c SControl.c SVerify1.c SVerify2.c\ ++ SRepair.c SRebuildCatalogBTree.c\ ++ SUtils.c SKeyCompare.c SDevice.c SExtents.c SAllocate.c\ ++ SCatalog.c SStubs.c VolumeBitmapCheck.c ++OFILES = $(CFILES:.c=.o) ++ ++libdfa.a: $(OFILES) ++ $(AR) rc $@ $? ++ ++clean: ++ $(RM) $(OFILES) libdfa.a +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SAllocate.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SAllocate.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SBTree.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SBTree.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SBTree.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SBTree.c 2008-07-01 22:30:11.000000000 +0200 +@@ -93,7 +93,7 @@ + CopyMemory(&resultIterator->key, foundKey, CalcKeySize(btcb, &resultIterator->key)); //¥¥ warning, this could overflow user's buffer!!! + + if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) ) +- DebugStr("\pSearchBTreeRecord: bad record?"); ++ DebugStr("SearchBTreeRecord: bad record?"); + } + + ErrorExit: +@@ -190,7 +190,7 @@ + CopyMemory(&iterator->key, key, CalcKeySize(btcb, &iterator->key)); //¥¥ warning, this could overflow user's buffer!!! + + if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) ) +- DebugStr("\pGetBTreeRecord: bad record?"); ++ DebugStr("GetBTreeRecord: bad record?"); + + } + +@@ -222,7 +222,7 @@ + CopyMemory(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //¥¥ should we range check against maxkeylen? + + if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, dataSize) ) +- DebugStr("\pInsertBTreeRecord: bad record?"); ++ DebugStr("InsertBTreeRecord: bad record?"); + + result = BTInsertRecord( fcb, &iterator, &btRecord, dataSize ); + +@@ -284,7 +284,7 @@ + CopyMemory(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //¥¥ should we range check against maxkeylen? + + if ( DEBUG_BUILD && !ValidHFSRecord(newData, btcb, dataSize) ) +- DebugStr("\pReplaceBTreeRecord: bad record?"); ++ DebugStr("ReplaceBTreeRecord: bad record?"); + + result = BTReplaceRecord( fcb, &iterator, &btRecord, dataSize ); + +@@ -301,7 +301,9 @@ + OSStatus + SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF ) + { ++#if !LINUX + #pragma unused (maxEOF) ++#endif + + OSStatus result; + UInt32 actualSectorsAdded; +@@ -321,7 +323,7 @@ + else + { + if ( DEBUG_BUILD ) +- DebugStr("\pSetEndOfForkProc: minEOF is smaller than current size!"); ++ DebugStr("SetEndOfForkProc: minEOF is smaller than current size!"); + return -1; + } + +@@ -347,7 +349,7 @@ + // Make sure we got at least as much space as we needed + // + if (filePtr->fcbLogicalSize < minEOF) { +- Panic("\pSetEndOfForkProc: disk too full to extend B-tree file"); ++ Panic("SetEndOfForkProc: disk too full to extend B-tree file"); + return dskFulErr; + } + +@@ -419,7 +421,7 @@ + if ( (keyLen < 6) || (keyLen > btcb->maxKeyLength) ) + { + if ( DEBUG_BUILD ) +- DebugStr("\pCheckBTreeKey: bad key length!"); ++ DebugStr("CheckBTreeKey: bad key length!"); + return fsBTInvalidKeyLengthErr; + } + +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SBTree.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SBTree.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SCatalog.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SCatalog.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/Scavenger.h diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/Scavenger.h +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/Scavenger.h 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/Scavenger.h 2008-07-01 22:30:11.000000000 +0200 +@@ -35,11 +35,16 @@ + #include "BTreeScanner.h" + #include "hfs_endian.h" + ++#if LINUX ++#define XATTR_MAXNAMELEN 127 ++#include ++#else + #include + #include + #include +-#include + #include ++#endif ++#include + + #ifdef __cplusplus + extern "C" { +@@ -1434,4 +1439,8 @@ + }; + #endif + ++#if LINUX ++#undef XATTR_MAXNAMELEN ++#endif ++ + #endif /* __SCAVENGER__ */ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SControl.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SControl.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SControl.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SControl.c 2008-07-01 22:30:11.000000000 +0200 +@@ -739,7 +739,7 @@ + pointer = (ScavStaticStructures *) AllocateClearMemory( sizeof(ScavStaticStructures) ); + if ( pointer == nil ) { + if ( GPtr->logLevel >= kDebugLog ) { +- printf( "\t error %d - could not allocate %ld bytes of memory \n", ++ printf( "\t error %d - could not allocate %i bytes of memory \n", + R_NoMem, sizeof(ScavStaticStructures) ); + } + return( R_NoMem ); +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SControl.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SControl.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SDevice.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SDevice.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SDevice.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SDevice.c 2008-07-01 22:30:11.000000000 +0200 +@@ -28,24 +28,61 @@ + #include + #include + #include +- ++#if LINUX ++#include ++#include ++#else + #include +- ++#endif /* LINUX */ + #else +- + #include + #include + #include + +-#endif +- ++#endif + + OSErr GetDeviceSize(int driveRefNum, UInt64 *numBlocks, UInt32 *blockSize) + { + #if BSD + UInt64 devBlockCount = 0; + int devBlockSize = 0; ++#if LINUX ++ struct stat stbuf; ++ ++ devBlockSize = 512; + ++#ifndef BLKGETSIZE ++#define BLKGETSIZE _IO(0x12,96) ++#endif ++#ifndef BLKGETSIZE64 ++#define BLKGETSIZE64 _IOR(0x12,114,size_t) ++#endif ++ if (fstat(driveRefNum, &stbuf) < 0){ ++ printf("Error: %s\n", strerror(errno)); ++ return(-1); ++ } ++ ++ if (S_ISREG(stbuf.st_mode)) { ++ devBlockCount = stbuf.st_size / 512; ++ } ++ else if (S_ISBLK(stbuf.st_mode)) { ++ unsigned long size; ++ u_int64_t size64; ++ if (!ioctl(driveRefNum, BLKGETSIZE64, &size64)) ++ devBlockCount = size64 / 512; ++ else if (!ioctl(driveRefNum, BLKGETSIZE, &size)) ++ devBlockCount = size; ++ else{ ++ printf("Error: %s\n", strerror(errno)); ++ return(-1); ++ } ++ ++ } ++ else{ ++ printf("Device is not a block device"); ++ return(-1); ++ } ++#elif BSD + if (ioctl(driveRefNum, DKIOCGETBLOCKCOUNT, &devBlockCount) < 0) { + printf("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno)); + return (-1); +@@ -55,6 +92,7 @@ + printf("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno)); + return (-1); + } ++#endif /* BSD */ + + if (devBlockSize != 512) { + *numBlocks = (devBlockCount * (UInt64)devBlockSize) / 512; +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SDevice.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SDevice.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SExtents.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SExtents.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SKeyCompare.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SKeyCompare.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SKeyCompare.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SKeyCompare.c 2008-07-01 22:30:11.000000000 +0200 +@@ -454,7 +454,9 @@ + * The name portion of the key is compared using a 16-bit binary comparison. + * This is called from the b-tree code. + */ ++#if !LINUX + __private_extern__ ++#endif + SInt32 + CompareAttributeKeys(const AttributeKey *searchKey, const AttributeKey *trialKey) + { +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SKeyCompare.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SKeyCompare.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRebuildCatalogBTree.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRebuildCatalogBTree.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRepair.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRepair.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRepair.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRepair.c 2008-07-01 22:30:11.000000000 +0200 +@@ -1593,7 +1593,9 @@ + + static OSErr FixWrapperExtents( SGlobPtr GPtr, RepairOrderPtr p ) + { ++#if !LINUX + #pragma unused (p) ++#endif + + OSErr err; + HFSMasterDirectoryBlock *mdb; +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRepair.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRepair.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRuntime.h diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRuntime.h +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SRuntime.h 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SRuntime.h 2008-07-01 22:30:11.000000000 +0200 +@@ -27,8 +27,11 @@ + #define __SRUNTIME__ + + #if BSD +- ++#if LINUX ++#include "missing.h" ++#else + #include ++#endif + #include + #include + #include +@@ -91,10 +94,12 @@ + + typedef u_int32_t HFSCatalogNodeID; + ++#if !LINUX + enum { + false = 0, + true = 1 + }; ++#endif + + /* OS error codes */ + enum { +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SStubs.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SStubs.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SUtils.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SUtils.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SUtils.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SUtils.c 2008-07-01 22:30:11.000000000 +0200 +@@ -380,7 +380,8 @@ + // GPtr->realVCB Real in-memory vcb + //------------------------------------------------------------------------------ + +-#if !BSD ++#if BSD ++#if !LINUX + OSErr GetVolumeFeatures( SGlobPtr GPtr ) + { + OSErr err; +@@ -418,7 +419,7 @@ + return( noErr ); + } + #endif +- ++#endif + + + /*------------------------------------------------------------------------------- +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SUtils.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SUtils.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SVerify1.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SVerify1.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SVerify2.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SVerify2.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SVerify2.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SVerify2.c 2008-07-01 22:30:11.000000000 +0200 +@@ -32,7 +32,9 @@ + */ + + #include ++#if !LINUX + #include ++#endif + + #include "BTree.h" + #include "BTreePrivate.h" +@@ -1240,8 +1242,13 @@ + * clump size for read-only media is irrelevant we skip the clump size + * check to avoid non useful warnings. + */ ++#if LINUX ++ // FIXME ++ isWriteable = 1; ++#else + isWriteable = 0; + ioctl( GPtr->DrvNum, DKIOCISWRITABLE, &isWriteable ); ++#endif + if ( isWriteable != 0 && + volumeHeader->catalogFile.clumpSize != vcb->vcbCatalogFile->fcbClumpSize ) { + PrintError(GPtr, E_InvalidClumpSize, 0); +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/SVerify2.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/SVerify2.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/dfalib/VolumeBitmapCheck.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/dfalib/VolumeBitmapCheck.o differ +Files diskdev_cmds-332.14/fsck_hfs.tproj/fsck_hfs and diskdev_cmds-332.14-patched/fsck_hfs.tproj/fsck_hfs differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/fsck_hfs.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/fsck_hfs.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/fsck_hfs.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/fsck_hfs.c 2008-07-01 22:36:12.000000000 +0200 +@@ -24,10 +24,14 @@ + #include + #include + #include ++#if !LINUX + #include ++#endif + #include + #include ++#if !LINUX + #include ++#endif + + #include + +@@ -105,7 +109,7 @@ + else + progname = *argv; + +- while ((ch = getopt(argc, argv, "dfglm:npqruy")) != EOF) { ++ while ((ch = getopt(argc, argv, "dfglm:napqruy")) != EOF) { + switch (ch) { + case 'd': + debug++; +@@ -141,6 +145,7 @@ + yflag = 0; + break; + ++ case 'a': + case 'p': + preen++; + break; +@@ -170,10 +175,12 @@ + + if (guiControl) + debug = 0; /* debugging is for command line only */ +- ++#if LINUX ++// FIXME ++#else + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + (void)signal(SIGINT, catch); +- ++#endif + if (argc < 1) { + (void) fprintf(stderr, "%s: missing special-device\n", progname); + usage(); +@@ -194,7 +201,9 @@ + int chkLev, repLev, logLev; + int blockDevice_fd, canWrite; + char *unraw, *mntonname; ++#if !LINUX + struct statfs *fsinfo; ++#endif + int fs_fd=-1; // fd to the root-dir of the fs we're checking (only w/lfag == 1) + + flags = 0; +@@ -203,7 +212,9 @@ + canWrite = 0; + unraw = NULL; + mntonname = NULL; +- ++#if LINUX ++ // FIXME ++#else + if (lflag) { + result = getmntinfo(&fsinfo, MNT_NOWAIT); + +@@ -233,7 +244,7 @@ + } + } + } +- ++#endif + if (debug && preen) + pwarn("starting\n"); + +@@ -306,6 +317,9 @@ + } + } + } else { ++#if LINUX ++ // FIXME ++#else + struct statfs stfs_buf; + /* + * Check to see if root is mounted read-write. +@@ -315,18 +329,24 @@ + else + flags = 0; + ckfini(flags & MNT_RDONLY); ++#endif + } + + /* XXX free any allocated memory here */ + + if (hotroot && fsmodified) { ++#if !LINUX + struct hfs_mount_args args; ++#endif + /* + * We modified the root. Do a mount update on + * it, unless it is read-write, so we can continue. + */ + if (!preen) + printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); ++#if LINUX ++ // FIXME ++#else + if (flags & MNT_RDONLY) { + bzero(&args, sizeof(args)); + flags |= MNT_UPDATE | MNT_RELOAD; +@@ -335,6 +355,7 @@ + goto ExitThisRoutine; + } + } ++#endif + if (!preen) + printf("\n***** REBOOT NOW *****\n"); + sync(); +@@ -380,11 +401,13 @@ + printf("Can't stat %s: %s\n", dev, strerror(errno)); + return (0); + } ++#if !LINUX + if ((statb.st_mode & S_IFMT) != S_IFCHR) { + pfatal("%s is not a character device", dev); + if (reply("CONTINUE") == 0) + return (0); + } ++#endif + if ((fsreadfd = open(dev, O_RDONLY)) < 0) { + printf("Can't open %s: %s\n", dev, strerror(errno)); + return (0); +@@ -407,10 +430,14 @@ + printf("\n"); + + /* Get device block size to initialize cache */ ++#if LINUX ++ devBlockSize = 512; ++#else + if (ioctl(fsreadfd, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) { + pfatal ("Can't get device block size\n"); + return (0); + } ++#endif + /* Initialize the cache */ + if (CacheInit (&fscache, fsreadfd, fswritefd, devBlockSize, + CACHE_IOSIZE, CACHE_BLOCKS, CACHE_HASHSIZE) != EOK) { +@@ -431,11 +458,15 @@ + + static void getWriteAccess( char *dev, int *blockDevice_fdPtr, int *canWritePtr ) + { ++#if !LINUX + int i; + int myMountsCount; ++#endif + void * myPtr; + char * myCharPtr; ++#if !LINUX + struct statfs * myBufPtr; ++#endif + void * myNamePtr; + + myPtr = NULL; +@@ -456,18 +487,19 @@ + *canWritePtr = 1; + goto ExitThisRoutine; + } +- + // get count of mounts then get the info for each ++#if LINUX ++ // FIXME ++#else + myMountsCount = getfsstat( NULL, 0, MNT_NOWAIT ); + if ( myMountsCount < 0 ) + goto ExitThisRoutine; +- + myPtr = (void *) malloc( sizeof(struct statfs) * myMountsCount ); + if ( myPtr == NULL ) + goto ExitThisRoutine; + myMountsCount = getfsstat( myPtr, +- (sizeof(struct statfs) * myMountsCount), +- MNT_NOWAIT ); ++ (sizeof(struct statfs) * myMountsCount), ++ MNT_NOWAIT ); + if ( myMountsCount < 0 ) + goto ExitThisRoutine; + +@@ -481,8 +513,8 @@ + } + myBufPtr++; + } ++#endif + *canWritePtr = 1; // single user will get us here, f_mntfromname is not /dev/diskXXXX +- + ExitThisRoutine: + if ( myPtr != NULL ) + free( myPtr ); +@@ -504,7 +536,7 @@ + (void) fprintf(stderr, " l = live fsck (lock down and test-only)\n"); + (void) fprintf(stderr, " m arg = octal mode used when creating lost+found directory \n"); + (void) fprintf(stderr, " n = assume a no response \n"); +- (void) fprintf(stderr, " p = just fix normal inconsistencies \n"); ++ (void) fprintf(stderr, " p, a = just fix normal inconsistencies \n"); + (void) fprintf(stderr, " q = quick check returns clean, dirty, or failure \n"); + (void) fprintf(stderr, " r = rebuild catalog btree \n"); + (void) fprintf(stderr, " u = usage \n"); +Files diskdev_cmds-332.14/fsck_hfs.tproj/fsck_hfs.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/fsck_hfs.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/Makefile.lnx diskdev_cmds-332.14-patched/fsck_hfs.tproj/Makefile.lnx +--- diskdev_cmds-332.14/fsck_hfs.tproj/Makefile.lnx 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/Makefile.lnx 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,15 @@ ++CFILES = fsck_hfs.c strings.c utilities.c cache.c ++OFILES = $(CFILES:.c=.o) ++ ++all: fsck_hfs ++ ++fsck_hfs: $(OFILES) dfalib/libdfa.a ++ ++dfalib/libdfa.a: FORCE ++ $(MAKE) -C dfalib -f Makefile.lnx libdfa.a ++ ++clean: ++ $(RM) fsck_hfs $(OFILES) ++ $(MAKE) -C dfalib -f Makefile.lnx clean ++ ++.PHONY : FORCE clean +Files diskdev_cmds-332.14/fsck_hfs.tproj/strings.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/strings.o differ +diff -druN diskdev_cmds-332.14/fsck_hfs.tproj/utilities.c diskdev_cmds-332.14-patched/fsck_hfs.tproj/utilities.c +--- diskdev_cmds-332.14/fsck_hfs.tproj/utilities.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/fsck_hfs.tproj/utilities.c 2008-07-01 22:30:11.000000000 +0200 +@@ -183,12 +183,14 @@ + printf("Can't stat %s\n", raw); + return (origname); + } ++#if !LINUX + if ((stchar.st_mode & S_IFMT) == S_IFCHR) { + return (raw); + } else { + printf("%s is not a character device\n", raw); + return (origname); + } ++#endif + } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { + newname = unrawname(newname); + retried++; +@@ -214,7 +216,11 @@ + *dp = 0; + (void)strcpy(rawbuf, name); + *dp = '/'; +- (void)strcat(rawbuf, "/r"); ++#if LINUX ++ (void)strcat(rawbuf, "/"); ++#else ++ (void)strcat(rawbuf,"/r"); ++#endif + (void)strcat(rawbuf, &dp[1]); + + return (rawbuf); +Files diskdev_cmds-332.14/fsck_hfs.tproj/utilities.o and diskdev_cmds-332.14-patched/fsck_hfs.tproj/utilities.o differ +diff -druN diskdev_cmds-332.14/include/bitstring.h diskdev_cmds-332.14-patched/include/bitstring.h +--- diskdev_cmds-332.14/include/bitstring.h 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/include/bitstring.h 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,164 @@ ++/* ++ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ++ * ++ * @APPLE_LICENSE_HEADER_START@ ++ * ++ * The contents of this file constitute Original Code as defined in and ++ * are subject to the Apple Public Source License Version 1.1 (the ++ * "License"). You may not use this file except in compliance with the ++ * License. Please obtain a copy of the License at ++ * http://www.apple.com/publicsource and read it before using this file. ++ * ++ * This Original Code and all software distributed under the License are ++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ++ * License for the specific language governing rights and limitations ++ * under the License. ++ * ++ * @APPLE_LICENSE_HEADER_END@ ++ */ ++/* ++ * Copyright (c) 1989, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Paul Vixie. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93 ++ */ ++ ++#ifndef _BITSTRING_H_ ++#define _BITSTRING_H_ ++ ++typedef unsigned char bitstr_t; ++ ++/* internal macros */ ++ /* byte of the bitstring bit is in */ ++#define _bit_byte(bit) \ ++ ((bit) >> 3) ++ ++ /* mask for the bit within its byte */ ++#define _bit_mask(bit) \ ++ (1 << ((bit)&0x7)) ++ ++/* external macros */ ++ /* bytes in a bitstring of nbits bits */ ++#define bitstr_size(nbits) \ ++ ((((nbits) - 1) >> 3) + 1) ++ ++ /* allocate a bitstring */ ++#define bit_alloc(nbits) \ ++ (bitstr_t *)calloc(1, \ ++ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t)) ++ ++ /* allocate a bitstring on the stack */ ++#define bit_decl(name, nbits) \ ++ (name)[bitstr_size(nbits)] ++ ++ /* is bit N of bitstring name set? */ ++#define bit_test(name, bit) \ ++ ((name)[_bit_byte(bit)] & _bit_mask(bit)) ++ ++ /* set bit N of bitstring name */ ++#define bit_set(name, bit) \ ++ (name)[_bit_byte(bit)] |= _bit_mask(bit) ++ ++ /* clear bit N of bitstring name */ ++#define bit_clear(name, bit) \ ++ (name)[_bit_byte(bit)] &= ~_bit_mask(bit) ++ ++ /* clear bits start ... stop in bitstring */ ++#define bit_nclear(name, start, stop) { \ ++ register bitstr_t *_name = name; \ ++ register int _start = start, _stop = stop; \ ++ register int _startbyte = _bit_byte(_start); \ ++ register int _stopbyte = _bit_byte(_stop); \ ++ if (_startbyte == _stopbyte) { \ ++ _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ ++ (0xff << ((_stop&0x7) + 1))); \ ++ } else { \ ++ _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ ++ while (++_startbyte < _stopbyte) \ ++ _name[_startbyte] = 0; \ ++ _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ ++ } \ ++} ++ ++ /* set bits start ... stop in bitstring */ ++#define bit_nset(name, start, stop) { \ ++ register bitstr_t *_name = name; \ ++ register int _start = start, _stop = stop; \ ++ register int _startbyte = _bit_byte(_start); \ ++ register int _stopbyte = _bit_byte(_stop); \ ++ if (_startbyte == _stopbyte) { \ ++ _name[_startbyte] |= ((0xff << (_start&0x7)) & \ ++ (0xff >> (7 - (_stop&0x7)))); \ ++ } else { \ ++ _name[_startbyte] |= 0xff << ((_start)&0x7); \ ++ while (++_startbyte < _stopbyte) \ ++ _name[_startbyte] = 0xff; \ ++ _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ ++ } \ ++} ++ ++ /* find first bit clear in name */ ++#define bit_ffc(name, nbits, value) { \ ++ register bitstr_t *_name = name; \ ++ register int _byte, _nbits = nbits; \ ++ register int _stopbyte = _bit_byte(_nbits), _value = -1; \ ++ for (_byte = 0; _byte <= _stopbyte; ++_byte) \ ++ if (_name[_byte] != 0xff) { \ ++ _value = _byte << 3; \ ++ for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \ ++ ++_value, _stopbyte >>= 1); \ ++ break; \ ++ } \ ++ *(value) = _value; \ ++} ++ ++ /* find first bit set in name */ ++#define bit_ffs(name, nbits, value) { \ ++ register bitstr_t *_name = name; \ ++ register int _byte, _nbits = nbits; \ ++ register int _stopbyte = _bit_byte(_nbits), _value = -1; \ ++ for (_byte = 0; _byte <= _stopbyte; ++_byte) \ ++ if (_name[_byte]) { \ ++ _value = _byte << 3; \ ++ for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \ ++ ++_value, _stopbyte >>= 1); \ ++ break; \ ++ } \ ++ *(value) = _value; \ ++} ++ ++#endif /* !_BITSTRING_H_ */ +diff -druN diskdev_cmds-332.14/include/hfs/hfs_format.h diskdev_cmds-332.14-patched/include/hfs/hfs_format.h +--- diskdev_cmds-332.14/include/hfs/hfs_format.h 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/include/hfs/hfs_format.h 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,689 @@ ++/* ++ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. ++ * ++ * @APPLE_LICENSE_HEADER_START@ ++ * ++ * The contents of this file constitute Original Code as defined in and ++ * are subject to the Apple Public Source License Version 1.1 (the ++ * "License"). You may not use this file except in compliance with the ++ * License. Please obtain a copy of the License at ++ * http://www.apple.com/publicsource and read it before using this file. ++ * ++ * This Original Code and all software distributed under the License are ++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ++ * License for the specific language governing rights and limitations ++ * under the License. ++ * ++ * @APPLE_LICENSE_HEADER_END@ ++ */ ++#ifndef __HFS_FORMAT__ ++#define __HFS_FORMAT__ ++ ++#include "missing.h" ++ ++#include ++ ++/* ++ * hfs_format.c ++ * ++ * This file describes the on-disk format for HFS and HFS Plus volumes. ++ * The HFS Plus volume format is desciibed in detail in Apple Technote 1150. ++ * ++ * http://developer.apple.com/technotes/tn/tn1150.html ++ * ++ */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* some on-disk hfs structures have 68K alignment (misaligned) */ ++ ++#define PACKED_S __attribute__((packed)) ++ ++/* Signatures used to differentiate between HFS and HFS Plus volumes */ ++enum { ++ kHFSSigWord = 0x4244, /* 'BD' in ASCII */ ++ kHFSPlusSigWord = 0x482B, /* 'H+' in ASCII */ ++ kHFSXSigWord = 0x4858, /* 'HX' in ASCII */ ++ ++ kHFSPlusVersion = 0x0004, /* 'H+' volumes are version 4 only */ ++ kHFSXVersion = 0x0005, /* 'HX' volumes start with version 5 */ ++ ++ kHFSPlusMountVersion = 0x31302E30, /* '10.0' for Mac OS X */ ++ kHFSJMountVersion = 0x4846534a, /* 'HFSJ' for journaled HFS+ on OS X */ ++ kFSKMountVersion = 0x46534b21 /* 'FSK!' for failed journal replay */ ++}PACKED_S; ++ ++ ++#ifdef __APPLE_API_PRIVATE ++/* ++ * Mac OS X has a special directory for linked and unlinked files (HFS Plus only). ++ * This directory and its contents are never exported from the filesystem under ++ * Mac OS X. ++ * ++ * To make this folder name sort last, it has embedded null prefix. ++ * (0xC0, 0x80 in UTF-8) ++ */ ++#define HFSPLUSMETADATAFOLDER "\xC0\x80\xC0\x80\xC0\x80\xC0\x80HFS+ Private Data" ++ ++/* ++ * Files in the HFS Private Data folder have one of the following prefixes ++ * followed by a decimal number (no leading zeros). For indirect nodes this ++ * number is a 32 bit random number. For unlinked (deleted) files that are ++ * still open, the number is the file ID for that file. ++ * ++ * e.g. iNode7182000 and temp3296 ++ */ ++#define HFS_INODE_PREFIX "iNode" ++#define HFS_DELETE_PREFIX "temp" ++ ++#endif /* __APPLE_API_PRIVATE */ ++ ++/* ++ * Indirect link files (hard links) have the following type/creator. ++ */ ++enum { ++ kHardLinkFileType = 0x686C6E6B, /* 'hlnk' */ ++ kHFSPlusCreator = 0x6866732B /* 'hfs+' */ ++}PACKED_S; ++ ++ ++#ifndef _HFSUNISTR255_DEFINED_ ++#define _HFSUNISTR255_DEFINED_ ++/* Unicode strings are used for HFS Plus file and folder names */ ++struct HFSUniStr255 { ++ u_int16_t length; /* number of unicode characters */ ++ u_int16_t unicode[255]; /* unicode characters */ ++} PACKED_S; ++typedef struct HFSUniStr255 HFSUniStr255; ++typedef const HFSUniStr255 *ConstHFSUniStr255Param; ++#endif /* _HFSUNISTR255_DEFINED_ */ ++ ++enum { ++ kHFSMaxVolumeNameChars = 27, ++ kHFSMaxFileNameChars = 31, ++ kHFSPlusMaxFileNameChars = 255 ++}PACKED_S; ++ ++ ++/* Extent overflow file data structures */ ++ ++/* HFS Extent key */ ++struct HFSExtentKey { ++ u_int8_t keyLength; /* length of key, excluding this field */ ++ u_int8_t forkType; /* 0 = data fork, FF = resource fork */ ++ u_int32_t fileID; /* file ID */ ++ u_int16_t startBlock; /* first file allocation block number in this extent */ ++}PACKED_S; ++typedef struct HFSExtentKey HFSExtentKey; ++ ++/* HFS Plus Extent key */ ++struct HFSPlusExtentKey { ++ u_int16_t keyLength; /* length of key, excluding this field */ ++ u_int8_t forkType; /* 0 = data fork, FF = resource fork */ ++ u_int8_t pad; /* make the other fields align on 32-bit boundary */ ++ u_int32_t fileID; /* file ID */ ++ u_int32_t startBlock; /* first file allocation block number in this extent */ ++}PACKED_S; ++typedef struct HFSPlusExtentKey HFSPlusExtentKey; ++ ++/* Number of extent descriptors per extent record */ ++enum { ++ kHFSExtentDensity = 3, ++ kHFSPlusExtentDensity = 8 ++}PACKED_S; ++ ++/* HFS extent descriptor */ ++struct HFSExtentDescriptor { ++ u_int16_t startBlock; /* first allocation block */ ++ u_int16_t blockCount; /* number of allocation blocks */ ++}PACKED_S; ++typedef struct HFSExtentDescriptor HFSExtentDescriptor; ++ ++/* HFS Plus extent descriptor */ ++struct HFSPlusExtentDescriptor { ++ u_int32_t startBlock; /* first allocation block */ ++ u_int32_t blockCount; /* number of allocation blocks */ ++}PACKED_S; ++typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor; ++ ++/* HFS extent record */ ++typedef HFSExtentDescriptor HFSExtentRecord[3]; ++ ++/* HFS Plus extent record */ ++typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8]; ++ ++ ++/* Finder information */ ++struct FndrFileInfo { ++ u_int32_t fdType; /* file type */ ++ u_int32_t fdCreator; /* file creator */ ++ u_int16_t fdFlags; /* Finder flags */ ++ struct { ++ int16_t v; /* file's location */ ++ int16_t h; ++ } PACKED_S fdLocation; ++ int16_t opaque; ++}PACKED_S; ++typedef struct FndrFileInfo FndrFileInfo; ++ ++struct FndrDirInfo { ++ struct { /* folder's window rectangle */ ++ int16_t top; ++ int16_t left; ++ int16_t bottom; ++ int16_t right; ++ }PACKED_S frRect; ++ unsigned short frFlags; /* Finder flags */ ++ struct { ++ u_int16_t v; /* folder's location */ ++ u_int16_t h; ++ }PACKED_S frLocation; ++ int16_t opaque; ++}PACKED_S; ++typedef struct FndrDirInfo FndrDirInfo; ++ ++struct FndrOpaqueInfo { ++ int8_t opaque[16]; ++}PACKED_S; ++typedef struct FndrOpaqueInfo FndrOpaqueInfo; ++ ++ ++/* HFS Plus Fork data info - 80 bytes */ ++struct HFSPlusForkData { ++ u_int64_t logicalSize; /* fork's logical size in bytes */ ++ u_int32_t clumpSize; /* fork's clump size in bytes */ ++ u_int32_t totalBlocks; /* total blocks used by this fork */ ++ HFSPlusExtentRecord extents; /* initial set of extents */ ++}PACKED_S; ++typedef struct HFSPlusForkData HFSPlusForkData; ++ ++ ++/* Mac OS X has 16 bytes worth of "BSD" info. ++ * ++ * Note: Mac OS 9 implementations and applications ++ * should preserve, but not change, this information. ++ */ ++struct HFSPlusBSDInfo { ++ u_int32_t ownerID; /* user or group ID of file/folder owner */ ++ u_int32_t groupID; /* additional user of group ID */ ++ u_int8_t adminFlags; /* super-user changeable flags */ ++ u_int8_t ownerFlags; /* owner changeable flags */ ++ u_int16_t fileMode; /* file type and permission bits */ ++ union { ++ u_int32_t iNodeNum; /* indirect node number (hard links only) */ ++ u_int32_t linkCount; /* links that refer to this indirect node */ ++ u_int32_t rawDevice; /* special file device (FBLK and FCHR only) */ ++ }PACKED_S special; ++}PACKED_S; ++typedef struct HFSPlusBSDInfo HFSPlusBSDInfo; ++ ++ ++/* Catalog file data structures */ ++ ++enum { ++ kHFSRootParentID = 1, /* Parent ID of the root folder */ ++ kHFSRootFolderID = 2, /* Folder ID of the root folder */ ++ kHFSExtentsFileID = 3, /* File ID of the extents file */ ++ kHFSCatalogFileID = 4, /* File ID of the catalog file */ ++ kHFSBadBlockFileID = 5, /* File ID of the bad allocation block file */ ++ kHFSAllocationFileID = 6, /* File ID of the allocation file (HFS Plus only) */ ++ kHFSStartupFileID = 7, /* File ID of the startup file (HFS Plus only) */ ++ kHFSAttributesFileID = 8, /* File ID of the attribute file (HFS Plus only) */ ++ kHFSRepairCatalogFileID = 14, /* Used when rebuilding Catalog B-tree */ ++ kHFSBogusExtentFileID = 15, /* Used for exchanging extents in extents file */ ++ kHFSFirstUserCatalogNodeID = 16 ++}PACKED_S; ++ ++/* HFS catalog key */ ++struct HFSCatalogKey { ++ u_int8_t keyLength; /* key length (in bytes) */ ++ u_int8_t reserved; /* reserved (set to zero) */ ++ u_int32_t parentID; /* parent folder ID */ ++ u_int8_t nodeName[kHFSMaxFileNameChars + 1]; /* catalog node name */ ++}PACKED_S; ++typedef struct HFSCatalogKey HFSCatalogKey; ++ ++/* HFS Plus catalog key */ ++struct HFSPlusCatalogKey { ++ u_int16_t keyLength; /* key length (in bytes) */ ++ u_int32_t parentID; /* parent folder ID */ ++ HFSUniStr255 nodeName; /* catalog node name */ ++}PACKED_S; ++typedef struct HFSPlusCatalogKey HFSPlusCatalogKey; ++ ++/* Catalog record types */ ++enum { ++ /* HFS Catalog Records */ ++ kHFSFolderRecord = 0x0100, /* Folder record */ ++ kHFSFileRecord = 0x0200, /* File record */ ++ kHFSFolderThreadRecord = 0x0300, /* Folder thread record */ ++ kHFSFileThreadRecord = 0x0400, /* File thread record */ ++ ++ /* HFS Plus Catalog Records */ ++ kHFSPlusFolderRecord = 1, /* Folder record */ ++ kHFSPlusFileRecord = 2, /* File record */ ++ kHFSPlusFolderThreadRecord = 3, /* Folder thread record */ ++ kHFSPlusFileThreadRecord = 4 /* File thread record */ ++}PACKED_S; ++ ++ ++/* Catalog file record flags */ ++enum { ++ kHFSFileLockedBit = 0x0000, /* file is locked and cannot be written to */ ++ kHFSFileLockedMask = 0x0001, ++ ++ kHFSThreadExistsBit = 0x0001, /* a file thread record exists for this file */ ++ kHFSThreadExistsMask = 0x0002, ++ ++ kHFSHasAttributesBit = 0x0002, /* object has extended attributes */ ++ kHFSHasAttributesMask = 0x0004, ++ ++ kHFSHasSecurityBit = 0x0003, /* object has security data (ACLs) */ ++ kHFSHasSecurityMask = 0x0008 ++}PACKED_S; ++ ++ ++/* HFS catalog folder record - 70 bytes */ ++struct HFSCatalogFolder { ++ int16_t recordType; /* == kHFSFolderRecord */ ++ u_int16_t flags; /* folder flags */ ++ u_int16_t valence; /* folder valence */ ++ u_int32_t folderID; /* folder ID */ ++ u_int32_t createDate; /* date and time of creation */ ++ u_int32_t modifyDate; /* date and time of last modification */ ++ u_int32_t backupDate; /* date and time of last backup */ ++ FndrDirInfo userInfo; /* Finder information */ ++ FndrOpaqueInfo finderInfo; /* additional Finder information */ ++ u_int32_t reserved[4]; /* reserved - initialized as zero */ ++}PACKED_S; ++typedef struct HFSCatalogFolder HFSCatalogFolder; ++ ++/* HFS Plus catalog folder record - 88 bytes */ ++struct HFSPlusCatalogFolder { ++ int16_t recordType; /* == kHFSPlusFolderRecord */ ++ u_int16_t flags; /* file flags */ ++ u_int32_t valence; /* folder's valence (limited to 2^16 in Mac OS) */ ++ u_int32_t folderID; /* folder ID */ ++ u_int32_t createDate; /* date and time of creation */ ++ u_int32_t contentModDate; /* date and time of last content modification */ ++ u_int32_t attributeModDate; /* date and time of last attribute modification */ ++ u_int32_t accessDate; /* date and time of last access (MacOS X only) */ ++ u_int32_t backupDate; /* date and time of last backup */ ++ HFSPlusBSDInfo bsdInfo; /* permissions (for MacOS X) */ ++ FndrDirInfo userInfo; /* Finder information */ ++ FndrOpaqueInfo finderInfo; /* additional Finder information */ ++ u_int32_t textEncoding; /* hint for name conversions */ ++ u_int32_t attrBlocks; /* cached count of attribute data blocks */ ++}PACKED_S; ++typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder; ++ ++/* HFS catalog file record - 102 bytes */ ++struct HFSCatalogFile { ++ int16_t recordType; /* == kHFSFileRecord */ ++ u_int8_t flags; /* file flags */ ++ int8_t fileType; /* file type (unused ?) */ ++ FndrFileInfo userInfo; /* Finder information */ ++ u_int32_t fileID; /* file ID */ ++ u_int16_t dataStartBlock; /* not used - set to zero */ ++ int32_t dataLogicalSize; /* logical EOF of data fork */ ++ int32_t dataPhysicalSize; /* physical EOF of data fork */ ++ u_int16_t rsrcStartBlock; /* not used - set to zero */ ++ int32_t rsrcLogicalSize; /* logical EOF of resource fork */ ++ int32_t rsrcPhysicalSize; /* physical EOF of resource fork */ ++ u_int32_t createDate; /* date and time of creation */ ++ u_int32_t modifyDate; /* date and time of last modification */ ++ u_int32_t backupDate; /* date and time of last backup */ ++ FndrOpaqueInfo finderInfo; /* additional Finder information */ ++ u_int16_t clumpSize; /* file clump size (not used) */ ++ HFSExtentRecord dataExtents; /* first data fork extent record */ ++ HFSExtentRecord rsrcExtents; /* first resource fork extent record */ ++ u_int32_t reserved; /* reserved - initialized as zero */ ++}PACKED_S; ++typedef struct HFSCatalogFile HFSCatalogFile; ++ ++/* HFS Plus catalog file record - 248 bytes */ ++struct HFSPlusCatalogFile { ++ int16_t recordType; /* == kHFSPlusFileRecord */ ++ u_int16_t flags; /* file flags */ ++ u_int32_t reserved1; /* reserved - initialized as zero */ ++ u_int32_t fileID; /* file ID */ ++ u_int32_t createDate; /* date and time of creation */ ++ u_int32_t contentModDate; /* date and time of last content modification */ ++ u_int32_t attributeModDate; /* date and time of last attribute modification */ ++ u_int32_t accessDate; /* date and time of last access (MacOS X only) */ ++ u_int32_t backupDate; /* date and time of last backup */ ++ HFSPlusBSDInfo bsdInfo; /* permissions (for MacOS X) */ ++ FndrFileInfo userInfo; /* Finder information */ ++ FndrOpaqueInfo finderInfo; /* additional Finder information */ ++ u_int32_t textEncoding; /* hint for name conversions */ ++ u_int32_t attrBlocks; /* cached count of attribute data blocks */ ++ ++ /* Note: these start on double long (64 bit) boundry */ ++ HFSPlusForkData dataFork; /* size and block data for data fork */ ++ HFSPlusForkData resourceFork; /* size and block data for resource fork */ ++}PACKED_S; ++typedef struct HFSPlusCatalogFile HFSPlusCatalogFile; ++ ++/* HFS catalog thread record - 46 bytes */ ++struct HFSCatalogThread { ++ int16_t recordType; /* == kHFSFolderThreadRecord or kHFSFileThreadRecord */ ++ int32_t reserved[2]; /* reserved - initialized as zero */ ++ u_int32_t parentID; /* parent ID for this catalog node */ ++ u_int8_t nodeName[kHFSMaxFileNameChars + 1]; /* name of this catalog node */ ++}PACKED_S; ++typedef struct HFSCatalogThread HFSCatalogThread; ++ ++/* HFS Plus catalog thread record -- 264 bytes */ ++struct HFSPlusCatalogThread { ++ int16_t recordType; /* == kHFSPlusFolderThreadRecord or kHFSPlusFileThreadRecord */ ++ int16_t reserved; /* reserved - initialized as zero */ ++ u_int32_t parentID; /* parent ID for this catalog node */ ++ HFSUniStr255 nodeName; /* name of this catalog node (variable length) */ ++}PACKED_S; ++typedef struct HFSPlusCatalogThread HFSPlusCatalogThread; ++ ++#ifdef __APPLE_API_UNSTABLE ++/* ++ These are the types of records in the attribute B-tree. The values were ++ chosen so that they wouldn't conflict with the catalog record types. ++*/ ++enum { ++ kHFSPlusAttrInlineData = 0x10, /* if size < kAttrOverflowSize */ ++ kHFSPlusAttrForkData = 0x20, /* if size >= kAttrOverflowSize */ ++ kHFSPlusAttrExtents = 0x30 /* overflow extents for large attributes */ ++}PACKED_S; ++ ++ ++/* ++ HFSPlusAttrForkData ++ For larger attributes, whose value is stored in allocation blocks. ++ If the attribute has more than 8 extents, there will be additonal ++ records (of type HFSPlusAttrExtents) for this attribute. ++*/ ++struct HFSPlusAttrForkData { ++ u_int32_t recordType; /* == kHFSPlusAttrForkData*/ ++ u_int32_t reserved; ++ HFSPlusForkData theFork; /* size and first extents of value*/ ++}PACKED_S; ++typedef struct HFSPlusAttrForkData HFSPlusAttrForkData; ++ ++/* ++ HFSPlusAttrExtents ++ This record contains information about overflow extents for large, ++ fragmented attributes. ++*/ ++struct HFSPlusAttrExtents { ++ u_int32_t recordType; /* == kHFSPlusAttrExtents*/ ++ u_int32_t reserved; ++ HFSPlusExtentRecord extents; /* additional extents*/ ++}PACKED_S; ++typedef struct HFSPlusAttrExtents HFSPlusAttrExtents; ++ ++/* ++ * Atrributes B-tree Data Record ++ * ++ * For small attributes, whose entire value is stored ++ * within a single B-tree record. ++ */ ++struct HFSPlusAttrData { ++ u_int32_t recordType; /* == kHFSPlusAttrInlineData */ ++ u_int32_t reserved[2]; ++ u_int32_t attrSize; /* size of attribute data in bytes */ ++ u_int8_t attrData[2]; /* variable length */ ++}PACKED_S; ++typedef struct HFSPlusAttrData HFSPlusAttrData; ++ ++ ++/* HFSPlusAttrInlineData is obsolete use HFSPlusAttrData instead */ ++struct HFSPlusAttrInlineData { ++ u_int32_t recordType; ++ u_int32_t reserved; ++ u_int32_t logicalSize; ++ u_int8_t userData[2]; ++}PACKED_S; ++typedef struct HFSPlusAttrInlineData HFSPlusAttrInlineData; ++ ++ ++/* A generic Attribute Record*/ ++union HFSPlusAttrRecord { ++ u_int32_t recordType; ++ HFSPlusAttrInlineData inlineData; /* NOT USED */ ++ HFSPlusAttrData attrData; ++ HFSPlusAttrForkData forkData; ++ HFSPlusAttrExtents overflowExtents; ++}PACKED_S; ++typedef union HFSPlusAttrRecord HFSPlusAttrRecord; ++ ++/* Attribute key */ ++enum { kHFSMaxAttrNameLen = 127 }; ++struct HFSPlusAttrKey { ++ u_int16_t keyLength; /* key length (in bytes) */ ++ u_int16_t pad; /* set to zero */ ++ u_int32_t fileID; /* file associated with attribute */ ++ u_int32_t startBlock; /* first attribue allocation block number for extents */ ++ u_int16_t attrNameLen; /* number of unicode characters */ ++ u_int16_t attrName[127]; /* attribute name (Unicode) */ ++}PACKED_S; ++typedef struct HFSPlusAttrKey HFSPlusAttrKey; ++ ++#define kHFSPlusAttrKeyMaximumLength (sizeof(HFSPlusAttrKey) - sizeof(u_int16_t)) ++#define kHFSPlusAttrKeyMinimumLength (kHFSPlusAttrKeyMaximumLength - (127 * sizeof(u_int16_t))) ++ ++#endif /* __APPLE_API_UNSTABLE */ ++ ++ ++/* Key and node lengths */ ++enum { ++ kHFSPlusExtentKeyMaximumLength = sizeof(HFSPlusExtentKey) - sizeof(u_int16_t), ++ kHFSExtentKeyMaximumLength = sizeof(HFSExtentKey) - sizeof(u_int8_t), ++ kHFSPlusCatalogKeyMaximumLength = sizeof(HFSPlusCatalogKey) - sizeof(u_int16_t), ++ kHFSPlusCatalogKeyMinimumLength = kHFSPlusCatalogKeyMaximumLength - sizeof(HFSUniStr255) + sizeof(u_int16_t), ++ kHFSCatalogKeyMaximumLength = sizeof(HFSCatalogKey) - sizeof(u_int8_t), ++ kHFSCatalogKeyMinimumLength = kHFSCatalogKeyMaximumLength - (kHFSMaxFileNameChars + 1) + sizeof(u_int8_t), ++ kHFSPlusCatalogMinNodeSize = 4096, ++ kHFSPlusExtentMinNodeSize = 512, ++ kHFSPlusAttrMinNodeSize = 4096 ++}PACKED_S; ++ ++/* HFS and HFS Plus volume attribute bits */ ++enum { ++ /* Bits 0-6 are reserved (always cleared by MountVol call) */ ++ kHFSVolumeHardwareLockBit = 7, /* volume is locked by hardware */ ++ kHFSVolumeUnmountedBit = 8, /* volume was successfully unmounted */ ++ kHFSVolumeSparedBlocksBit = 9, /* volume has bad blocks spared */ ++ kHFSVolumeNoCacheRequiredBit = 10, /* don't cache volume blocks (i.e. RAM or ROM disk) */ ++ kHFSBootVolumeInconsistentBit = 11, /* boot volume is inconsistent (System 7.6 and later) */ ++ kHFSCatalogNodeIDsReusedBit = 12, ++ kHFSVolumeJournaledBit = 13, /* this volume has a journal on it */ ++ kHFSVolumeInconsistentBit = 14, /* serious inconsistencies detected at runtime */ ++ kHFSVolumeSoftwareLockBit = 15, /* volume is locked by software */ ++ ++ kHFSVolumeHardwareLockMask = 1 << kHFSVolumeHardwareLockBit, ++ kHFSVolumeUnmountedMask = 1 << kHFSVolumeUnmountedBit, ++ kHFSVolumeSparedBlocksMask = 1 << kHFSVolumeSparedBlocksBit, ++ kHFSVolumeNoCacheRequiredMask = 1 << kHFSVolumeNoCacheRequiredBit, ++ kHFSBootVolumeInconsistentMask = 1 << kHFSBootVolumeInconsistentBit, ++ kHFSCatalogNodeIDsReusedMask = 1 << kHFSCatalogNodeIDsReusedBit, ++ kHFSVolumeJournaledMask = 1 << kHFSVolumeJournaledBit, ++ kHFSVolumeInconsistentMask = 1 << kHFSVolumeInconsistentBit, ++ kHFSVolumeSoftwareLockMask = 1 << kHFSVolumeSoftwareLockBit, ++ kHFSMDBAttributesMask = 0x8380 ++}PACKED_S; ++ ++ ++/* HFS Master Directory Block - 162 bytes */ ++/* Stored at sector #2 (3rd sector) and second-to-last sector. */ ++struct HFSMasterDirectoryBlock { ++ u_int16_t drSigWord; /* == kHFSSigWord */ ++ u_int32_t drCrDate; /* date and time of volume creation */ ++ u_int32_t drLsMod; /* date and time of last modification */ ++ u_int16_t drAtrb; /* volume attributes */ ++ u_int16_t drNmFls; /* number of files in root folder */ ++ u_int16_t drVBMSt; /* first block of volume bitmap */ ++ u_int16_t drAllocPtr; /* start of next allocation search */ ++ u_int16_t drNmAlBlks; /* number of allocation blocks in volume */ ++ u_int32_t drAlBlkSiz; /* size (in bytes) of allocation blocks */ ++ u_int32_t drClpSiz; /* default clump size */ ++ u_int16_t drAlBlSt; /* first allocation block in volume */ ++ u_int32_t drNxtCNID; /* next unused catalog node ID */ ++ u_int16_t drFreeBks; /* number of unused allocation blocks */ ++ u_int8_t drVN[kHFSMaxVolumeNameChars + 1]; /* volume name */ ++ u_int32_t drVolBkUp; /* date and time of last backup */ ++ u_int16_t drVSeqNum; /* volume backup sequence number */ ++ u_int32_t drWrCnt; /* volume write count */ ++ u_int32_t drXTClpSiz; /* clump size for extents overflow file */ ++ u_int32_t drCTClpSiz; /* clump size for catalog file */ ++ u_int16_t drNmRtDirs; /* number of directories in root folder */ ++ u_int32_t drFilCnt; /* number of files in volume */ ++ u_int32_t drDirCnt; /* number of directories in volume */ ++ u_int32_t drFndrInfo[8]; /* information used by the Finder */ ++ u_int16_t drEmbedSigWord; /* embedded volume signature (formerly drVCSize) */ ++ HFSExtentDescriptor drEmbedExtent; /* embedded volume location and size (formerly drVBMCSize and drCtlCSize) */ ++ u_int32_t drXTFlSize; /* size of extents overflow file */ ++ HFSExtentRecord drXTExtRec; /* extent record for extents overflow file */ ++ u_int32_t drCTFlSize; /* size of catalog file */ ++ HFSExtentRecord drCTExtRec; /* extent record for catalog file */ ++}PACKED_S; ++typedef struct HFSMasterDirectoryBlock HFSMasterDirectoryBlock; ++ ++ ++#ifdef __APPLE_API_UNSTABLE ++#define SET_HFS_TEXT_ENCODING(hint) \ ++ (0x656e6300 | ((hint) & 0xff)) ++#define GET_HFS_TEXT_ENCODING(hint) \ ++ (((hint) & 0xffffff00) == 0x656e6300 ? (hint) & 0x000000ff : 0xffffffffU) ++#endif /* __APPLE_API_UNSTABLE */ ++ ++ ++/* HFS Plus Volume Header - 512 bytes */ ++/* Stored at sector #2 (3rd sector) and second-to-last sector. */ ++struct HFSPlusVolumeHeader { ++ u_int16_t signature; /* == kHFSPlusSigWord */ ++ u_int16_t version; /* == kHFSPlusVersion */ ++ u_int32_t attributes; /* volume attributes */ ++ u_int32_t lastMountedVersion; /* implementation version which last mounted volume */ ++ u_int32_t journalInfoBlock; /* block addr of journal info (if volume is journaled, zero otherwise) */ ++ ++ u_int32_t createDate; /* date and time of volume creation */ ++ u_int32_t modifyDate; /* date and time of last modification */ ++ u_int32_t backupDate; /* date and time of last backup */ ++ u_int32_t checkedDate; /* date and time of last disk check */ ++ ++ u_int32_t fileCount; /* number of files in volume */ ++ u_int32_t folderCount; /* number of directories in volume */ ++ ++ u_int32_t blockSize; /* size (in bytes) of allocation blocks */ ++ u_int32_t totalBlocks; /* number of allocation blocks in volume (includes this header and VBM*/ ++ u_int32_t freeBlocks; /* number of unused allocation blocks */ ++ ++ u_int32_t nextAllocation; /* start of next allocation search */ ++ u_int32_t rsrcClumpSize; /* default resource fork clump size */ ++ u_int32_t dataClumpSize; /* default data fork clump size */ ++ u_int32_t nextCatalogID; /* next unused catalog node ID */ ++ ++ u_int32_t writeCount; /* volume write count */ ++ u_int64_t encodingsBitmap; /* which encodings have been use on this volume */ ++ ++ u_int8_t finderInfo[32]; /* information used by the Finder */ ++ ++ HFSPlusForkData allocationFile; /* allocation bitmap file */ ++ HFSPlusForkData extentsFile; /* extents B-tree file */ ++ HFSPlusForkData catalogFile; /* catalog B-tree file */ ++ HFSPlusForkData attributesFile; /* extended attributes B-tree file */ ++ HFSPlusForkData startupFile; /* boot file (secondary loader) */ ++}PACKED_S; ++typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader; ++ ++ ++/* B-tree structures */ ++ ++enum BTreeKeyLimits{ ++ kMaxKeyLength = 520 ++}PACKED_S; ++ ++union BTreeKey{ ++ u_int8_t length8; ++ u_int16_t length16; ++ u_int8_t rawData [kMaxKeyLength+2]; ++}PACKED_S; ++typedef union BTreeKey BTreeKey; ++ ++/* BTNodeDescriptor -- Every B-tree node starts with these fields. */ ++struct BTNodeDescriptor { ++ u_int32_t fLink; /* next node at this level*/ ++ u_int32_t bLink; /* previous node at this level*/ ++ int8_t kind; /* kind of node (leaf, index, header, map)*/ ++ u_int8_t height; /* zero for header, map; child is one more than parent*/ ++ u_int16_t numRecords; /* number of records in this node*/ ++ u_int16_t reserved; /* reserved - initialized as zero */ ++}PACKED_S; ++typedef struct BTNodeDescriptor BTNodeDescriptor; ++ ++/* Constants for BTNodeDescriptor kind */ ++enum { ++ kBTLeafNode = -1, ++ kBTIndexNode = 0, ++ kBTHeaderNode = 1, ++ kBTMapNode = 2 ++}PACKED_S; ++ ++/* BTHeaderRec -- The first record of a B-tree header node */ ++struct BTHeaderRec { ++ u_int16_t treeDepth; /* maximum height (usually leaf nodes) */ ++ u_int32_t rootNode; /* node number of root node */ ++ u_int32_t leafRecords; /* number of leaf records in all leaf nodes */ ++ u_int32_t firstLeafNode; /* node number of first leaf node */ ++ u_int32_t lastLeafNode; /* node number of last leaf node */ ++ u_int16_t nodeSize; /* size of a node, in bytes */ ++ u_int16_t maxKeyLength; /* reserved */ ++ u_int32_t totalNodes; /* total number of nodes in tree */ ++ u_int32_t freeNodes; /* number of unused (free) nodes in tree */ ++ u_int16_t reserved1; /* unused */ ++ u_int32_t clumpSize; /* reserved */ ++ u_int8_t btreeType; /* reserved */ ++ u_int8_t keyCompareType; /* Key string Comparison Type */ ++ u_int32_t attributes; /* persistent attributes about the tree */ ++ u_int32_t reserved3[16]; /* reserved */ ++}PACKED_S; ++typedef struct BTHeaderRec BTHeaderRec; ++ ++/* Constants for BTHeaderRec attributes */ ++enum { ++ kBTBadCloseMask = 0x00000001, /* reserved */ ++ kBTBigKeysMask = 0x00000002, /* key length field is 16 bits */ ++ kBTVariableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length */ ++}PACKED_S; ++ ++ ++/* Catalog Key Name Comparison Type */ ++enum { ++ kHFSCaseFolding = 0xCF, /* case folding (case-insensitive) */ ++ kHFSBinaryCompare = 0xBC /* binary compare (case-sensitive) */ ++}PACKED_S; ++ ++/* JournalInfoBlock - Structure that describes where our journal lives */ ++struct JournalInfoBlock { ++ u_int32_t flags; ++ u_int32_t device_signature[8]; // signature used to locate our device. ++ u_int64_t offset; // byte offset to the journal on the device ++ u_int64_t size; // size in bytes of the journal ++ u_int32_t reserved[32]; ++}PACKED_S; ++typedef struct JournalInfoBlock JournalInfoBlock; ++ ++enum { ++ kJIJournalInFSMask = 0x00000001, ++ kJIJournalOnOtherDeviceMask = 0x00000002, ++ kJIJournalNeedInitMask = 0x00000004 ++}PACKED_S; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __HFS_FORMAT__ */ +diff -druN diskdev_cmds-332.14/include/hfs/hfs_mount.h diskdev_cmds-332.14-patched/include/hfs/hfs_mount.h +--- diskdev_cmds-332.14/include/hfs/hfs_mount.h 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/include/hfs/hfs_mount.h 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. ++ * ++ * @APPLE_LICENSE_HEADER_START@ ++ * ++ * The contents of this file constitute Original Code as defined in and ++ * are subject to the Apple Public Source License Version 1.1 (the ++ * "License"). You may not use this file except in compliance with the ++ * License. Please obtain a copy of the License at ++ * http://www.apple.com/publicsource and read it before using this file. ++ * ++ * This Original Code and all software distributed under the License are ++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ++ * License for the specific language governing rights and limitations ++ * under the License. ++ * ++ * @APPLE_LICENSE_HEADER_END@ ++ */ ++/* ++ * Copyright (c) 1997-2002 Apple Computer, Inc. All Rights Reserved ++ * ++ */ ++ ++#ifndef _HFS_MOUNT_H_ ++#define _HFS_MOUNT_H_ ++ ++#include ++ ++#include ++#include ++ ++/* ++ * Arguments to mount HFS-based filesystems ++ */ ++ ++#define OVERRIDE_UNKNOWN_PERMISSIONS 0 ++ ++#define UNKNOWNUID ((uid_t)99) ++#define UNKNOWNGID ((gid_t)99) ++#define UNKNOWNPERMISSIONS (S_IRWXU | S_IROTH | S_IXOTH) /* 705 */ ++ ++#ifdef __APPLE_API_UNSTABLE ++struct hfs_mount_args { ++#ifndef KERNEL ++ char *fspec; /* block special device to mount */ ++#endif ++ uid_t hfs_uid; /* uid that owns hfs files (standard HFS only) */ ++ gid_t hfs_gid; /* gid that owns hfs files (standard HFS only) */ ++ mode_t hfs_mask; /* mask to be applied for hfs perms (standard HFS only) */ ++ u_int32_t hfs_encoding; /* encoding for this volume (standard HFS only) */ ++ struct timezone hfs_timezone; /* user time zone info (standard HFS only) */ ++ int flags; /* mounting flags, see below */ ++ int journal_tbuffer_size; /* size in bytes of the journal transaction buffer */ ++ int journal_flags; /* flags to pass to journal_open/create */ ++ int journal_disable; /* don't use journaling (potentially dangerous) */ ++}; ++ ++#define HFSFSMNT_NOXONFILES 0x1 /* disable execute permissions for files */ ++#define HFSFSMNT_WRAPPER 0x2 /* mount HFS wrapper (if it exists) */ ++#define HFSFSMNT_EXTENDED_ARGS 0x4 /* indicates new fields after "flags" are valid */ ++ ++/* ++ * Sysctl values for HFS ++ */ ++#define HFS_ENCODINGBIAS 1 /* encoding matching CJK bias */ ++#define HFS_EXTEND_FS 2 ++#define HFS_ENCODINGHINT 3 /* guess encoding for string */ ++#define HFS_ENABLE_JOURNALING 0x082969 ++#define HFS_DISABLE_JOURNALING 0x031272 ++#define HFS_GET_JOURNAL_INFO 0x6a6e6c69 ++#define HFS_SET_PKG_EXTENSIONS 0x121031 ++ ++#endif /* __APPLE_API_UNSTABLE */ ++ ++#endif /* ! _HFS_MOUNT_H_ */ +diff -druN diskdev_cmds-332.14/include/missing.h diskdev_cmds-332.14-patched/include/missing.h +--- diskdev_cmds-332.14/include/missing.h 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/include/missing.h 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,113 @@ ++#ifndef _MISSING_H_ ++#define _MISSING_H_ ++ ++#include ++#include ++#include ++#include ++ ++#define MAXBSIZE (256 * 4096) ++ ++#ifndef true ++#define true 1 ++#endif ++#ifndef false ++#define false 0 ++#endif ++ ++/* Mac types */ ++ ++/* 8 Bit */ ++#ifndef UInt8 ++#define UInt8 uint8_t ++#endif ++#ifndef u_int8_t ++#define u_int8_t UInt8 ++#endif ++#ifndef SInt8 ++#define SInt8 int8_t ++#endif ++ ++/* 16 Bit */ ++#ifndef UInt16 ++#define UInt16 uint16_t ++#endif ++#ifndef u_int16_t ++#define u_int16_t UInt16 ++#endif ++#ifndef SInt16 ++#define SInt16 int16_t ++#endif ++ ++/* 32 Bit */ ++#ifndef UInt32 ++#define UInt32 uint32_t ++#endif ++#ifndef u_int32_t ++#define u_int32_t UInt32 ++#endif ++#ifndef SInt32 ++#define SInt32 int32_t ++#endif ++ ++/* 64 Bit */ ++#ifndef UInt64 ++#define UInt64 uint64_t ++#endif ++#ifndef u_int64_t ++#define u_int64_t UInt64 ++#endif ++#ifndef SInt64 ++#define SInt64 int64_t ++#endif ++ ++#define UniChar u_int16_t ++#define Boolean u_int8_t ++ ++#define UF_NODUMP 0x00000001 ++ ++/* syslimits.h */ ++#define NAME_MAX 255 ++ ++/* Byteswap stuff */ ++#define NXSwapHostLongToBig(x) cpu_to_be64(x) ++#define NXSwapBigShortToHost(x) be16_to_cpu(x) ++#define OSSwapBigToHostInt16(x) be16_to_cpu(x) ++#define NXSwapBigLongToHost(x) be32_to_cpu(x) ++#define OSSwapBigToHostInt32(x) be32_to_cpu(x) ++#define NXSwapBigLongLongToHost(x) be64_to_cpu(x) ++#define OSSwapBigToHostInt64(x) be64_to_cpu(x) ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++/* Big Endian Swaps */ ++#ifndef be16_to_cpu ++#define be16_to_cpu(x) bswap_16(x) ++#endif ++#ifndef be32_to_cpu ++#define be32_to_cpu(x) bswap_32(x) ++#endif ++#ifndef be64_to_cpu ++#define be64_to_cpu(x) bswap_64(x) ++#endif ++#ifndef cpu_to_be64 ++#define cpu_to_be64(x) bswap_64(x) ++#endif ++#elif __BYTE_ORDER == __BIG_ENDIAN ++/* Big endian doesn't swap */ ++#ifndef be16_to_cpu ++#define be16_to_cpu(x) (x) ++#endif ++#ifndef be32_to_cpu ++#define be32_to_cpu(x) (x) ++#endif ++#ifndef be64_to_cpu ++#define be64_to_cpu(x) (x) ++#endif ++#ifndef cpu_to_be64 ++#define cpu_to_be64(x) (x) ++#endif ++#endif ++ ++#define KAUTH_FILESEC_XATTR "com.apple.system.Security" ++ ++#endif +diff -druN diskdev_cmds-332.14/include/sys/appleapiopts.h diskdev_cmds-332.14-patched/include/sys/appleapiopts.h +--- diskdev_cmds-332.14/include/sys/appleapiopts.h 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/include/sys/appleapiopts.h 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. ++ * ++ * @APPLE_LICENSE_HEADER_START@ ++ * ++ * The contents of this file constitute Original Code as defined in and ++ * are subject to the Apple Public Source License Version 1.1 (the ++ * "License"). You may not use this file except in compliance with the ++ * License. Please obtain a copy of the License at ++ * http://www.apple.com/publicsource and read it before using this file. ++ * ++ * This Original Code and all software distributed under the License are ++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ++ * License for the specific language governing rights and limitations ++ * under the License. ++ * ++ * @APPLE_LICENSE_HEADER_END@ ++ */ ++ ++#ifndef __SYS_APPLEAPIOPTS_H__ ++#define __SYS_APPLEAPIOPTS_H__ ++ ++ ++#ifndef __APPLE_API_STANDARD ++#define __APPLE_API_STANDARD ++#endif /* __APPLE_API_STANDARD */ ++ ++#ifndef __APPLE_API_STABLE ++#define __APPLE_API_STABLE ++#endif /* __APPLE_API_STABLE */ ++ ++#ifndef __APPLE_API_STRICT_CONFORMANCE ++ ++#ifndef __APPLE_API_EVOLVING ++#define __APPLE_API_EVOLVING ++#endif /* __APPLE_API_EVOLVING */ ++ ++#ifndef __APPLE_API_UNSTABLE ++#define __APPLE_API_UNSTABLE ++#endif /* __APPLE_API_UNSTABLE */ ++ ++#ifndef __APPLE_API_PRIVATE ++#define __APPLE_API_PRIVATE ++#endif /* __APPLE_API_PRIVATE */ ++ ++#ifndef __APPLE_API_OBSOLETE ++#define __APPLE_API_OBSOLETE ++#endif /* __APPLE_API_OBSOLETE */ ++ ++#endif /* __APPLE_API_STRICT_CONFORMANCE */ ++ ++#endif /* __SYS_APPLEAPIOPTS_H__ */ ++ +diff -druN diskdev_cmds-332.14/Makefile.lnx diskdev_cmds-332.14-patched/Makefile.lnx +--- diskdev_cmds-332.14/Makefile.lnx 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/Makefile.lnx 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,8 @@ ++CC := gcc ++CFLAGS := -g3 -Wall -I$(PWD)/include -DDEBUG_BUILD=0 -D_FILE_OFFSET_BITS=64 -D LINUX=1 -D BSD=1 ++SUBDIRS := newfs_hfs.tproj fsck_hfs.tproj ++ ++all clean: ++ for d in $(SUBDIRS); do $(MAKE) -C $$d -f Makefile.lnx $@; done ++ ++export CC CFLAGS +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/hfs_endian.c diskdev_cmds-332.14-patched/newfs_hfs.tproj/hfs_endian.c +--- diskdev_cmds-332.14/newfs_hfs.tproj/hfs_endian.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/hfs_endian.c 2008-07-01 22:30:11.000000000 +0200 +@@ -30,7 +30,12 @@ + #include + #include + ++#if LINUX ++#include "missing.h" ++#else + #include ++#endif ++ + #include + + #include "hfs_endian.h" +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/hfs_endian.h diskdev_cmds-332.14-patched/newfs_hfs.tproj/hfs_endian.h +--- diskdev_cmds-332.14/newfs_hfs.tproj/hfs_endian.h 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/hfs_endian.h 2008-07-01 22:30:11.000000000 +0200 +@@ -29,7 +29,12 @@ + * volume format. + */ + #include ++#if LINUX ++#include ++#include ++#else + #include ++#endif + + /*********************/ + /* BIG ENDIAN Macros */ +Files diskdev_cmds-332.14/newfs_hfs.tproj/hfs_endian.o and diskdev_cmds-332.14-patched/newfs_hfs.tproj/hfs_endian.o differ +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/Makefile.lnx diskdev_cmds-332.14-patched/newfs_hfs.tproj/Makefile.lnx +--- diskdev_cmds-332.14/newfs_hfs.tproj/Makefile.lnx 1970-01-01 01:00:00.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/Makefile.lnx 2008-07-01 22:30:11.000000000 +0200 +@@ -0,0 +1,12 @@ ++CFILES = hfs_endian.c makehfs.c newfs_hfs.c ++OFILES = $(CFILES:.c=.o) ++ ++all: newfs_hfs ++ ++newfs_hfs: $(OFILES) ++ ${CC} ${CFLAGS} -o newfs_hfs ${OFILES} -lcrypto ++ ++clean: ++ $(RM) newfs_hfs $(OFILES) ++ ++.PHONY : FORCE clean +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/makehfs.c diskdev_cmds-332.14-patched/newfs_hfs.tproj/makehfs.c +--- diskdev_cmds-332.14/newfs_hfs.tproj/makehfs.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/makehfs.c 2008-07-01 22:36:05.000000000 +0200 +@@ -31,10 +31,16 @@ + #include + #include + #include ++#if LINUX ++#include ++#include "missing.h" ++#endif + #include + #include + #include ++#if !LINUX + #include ++#endif + + #include + #include +@@ -47,13 +53,14 @@ + + #include + ++#if !LINUX + #include + + #include + #include + + extern Boolean _CFStringGetFileSystemRepresentation(CFStringRef string, UInt8 *buffer, CFIndex maxBufLen); +- ++#endif + + #include + #include +@@ -63,7 +70,7 @@ + #include "readme.h" + + +-#define HFS_BOOT_DATA "/usr/share/misc/hfsbootdata" ++#define HFS_BOOT_DATA "/usr/share/hfsprogs/hfsbootdata" + + #define HFS_JOURNAL_FILE ".journal" + #define HFS_JOURNAL_INFO ".journal_info_block" +@@ -129,7 +136,9 @@ + static void MarkBitInAllocationBuffer __P((HFSPlusVolumeHeader *header, + UInt32 allocationBlock, void* sectorBuffer, UInt32 *sector)); + ++#if !LINUX + static UInt32 GetDefaultEncoding(); ++#endif + + static UInt32 UTCToLocal __P((UInt32 utcTime)); + +@@ -158,11 +167,14 @@ + + #define ROUNDUP(x, u) (((x) % (u) == 0) ? (x) : ((x)/(u) + 1) * (u)) + +-#define ENCODING_TO_BIT(e) \ ++#if LINUX ++#define ENCODING_TO_BIT(e) (e) ++#else ++#define ENCODING_TO_BIT(e) + ((e) < 48 ? (e) : \ + ((e) == kCFStringEncodingMacUkrainian ? 48 : \ + ((e) == kCFStringEncodingMacFarsi ? 49 : 0))) +- ++#endif + /* + * make_hfs + * +@@ -528,6 +540,7 @@ + * Map UTF-8 input into a Mac encoding. + * On conversion errors "untitled" is used as a fallback. + */ ++#if !LINUX + { + UniChar unibuf[kHFSMaxVolumeNameChars]; + CFStringRef cfstr; +@@ -553,7 +566,11 @@ + bcopy(&mdbp->drVN[1], defaults->volumeName, mdbp->drVN[0]); + defaults->volumeName[mdbp->drVN[0]] = '\0'; + } ++#endif + /* Save the encoding hint in the Finder Info (field 4). */ ++ mdbp->drVN[0] = strlen(defaults->volumeName); ++ bcopy(defaults->volumeName,&mdbp->drVN[1],mdbp->drVN[0]); ++ + mdbp->drFndrInfo[4] = SET_HFS_TEXT_ENCODING(defaults->encodingHint); + + mdbp->drWrCnt = kWriteSeqNum; +@@ -1100,9 +1117,11 @@ + UInt16 nodeSize; + SInt16 offset; + UInt32 unicodeBytes; ++#if !LINUX + UInt8 canonicalName[256]; + CFStringRef cfstr; + Boolean cfOK; ++#endif + int index = 0; + + nodeSize = dp->catalogNodeSize; +@@ -1122,7 +1141,9 @@ + * First record is always the root directory... + */ + ckp = (HFSPlusCatalogKey *)((UInt8 *)buffer + offset); +- ++#if LINUX ++ ConvertUTF8toUnicode(dp->volumeName, sizeof(ckp->nodeName.unicode), ckp->nodeName.unicode, &ckp->nodeName.length); ++#else + /* Use CFString functions to get a HFSPlus Canonical name */ + cfstr = CFStringCreateWithCString(kCFAllocatorDefault, (char *)dp->volumeName, kCFStringEncodingUTF8); + cfOK = _CFStringGetFileSystemRepresentation(cfstr, canonicalName, sizeof(canonicalName)); +@@ -1139,6 +1160,7 @@ + dp->volumeName, kDefaultVolumeNameStr); + } + CFRelease(cfstr); ++#endif + ckp->nodeName.length = SWAP_BE16 (ckp->nodeName.length); + + unicodeBytes = sizeof(UniChar) * SWAP_BE16 (ckp->nodeName.length); +@@ -1821,15 +1843,15 @@ + off_t sector; + + if ((byteCount % driveInfo->sectorSize) != 0) +- errx(1, "WriteBuffer: byte count %ld is not sector size multiple", byteCount); ++ errx(1, "WriteBuffer: byte count %i is not sector size multiple", byteCount); + + sector = driveInfo->sectorOffset + startingSector; + + if (lseek(driveInfo->fd, sector * driveInfo->sectorSize, SEEK_SET) < 0) +- err(1, "seek (sector %qd)", sector); ++ err(1, "seek (sector %lld)", sector); + + if (write(driveInfo->fd, buffer, byteCount) != byteCount) +- err(1, "write (sector %qd, %ld bytes)", sector, byteCount); ++ err(1, "write (sector %lld, %i bytes)", sector, byteCount); + } + + +@@ -1913,7 +1935,7 @@ + return quotient; + } + +- ++#if !LINUX + #define __kCFUserEncodingFileName ("/.CFUserTextEncoding") + + static UInt32 +@@ -1939,7 +1961,7 @@ + } + return 0; + } +- ++#endif + + static int + ConvertUTF8toUnicode(const UInt8* source, UInt32 bufsize, UniChar* unibuf, +@@ -2006,6 +2028,9 @@ + static int + getencodinghint(unsigned char *name) + { ++#if LINUX ++ return(0); ++#else + int mib[3]; + size_t buflen = sizeof(int); + struct vfsconf vfc; +@@ -2023,7 +2048,8 @@ + return (hint); + error: + hint = GetDefaultEncoding(); +- return (hint); ++ return (0); ++#endif + } + + +@@ -2034,12 +2060,14 @@ + unsigned char digest[20]; + time_t now; + clock_t uptime; +- int mib[2]; +- int sysdata; +- char sysctlstring[128]; + size_t datalen; + double sysloadavg[3]; ++#if !LINUX ++ int sysdata; ++ int mib[2]; ++ char sysctlstring[128]; + struct vmtotal sysvmtotal; ++#endif + + do { + /* Initialize the SHA-1 context for processing: */ +@@ -2052,52 +2080,58 @@ + SHA1_Update(&context, &uptime, sizeof(uptime)); + + /* The kernel's boot time: */ ++#if !LINUX + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + datalen = sizeof(sysdata); + sysctl(mib, 2, &sysdata, &datalen, NULL, 0); + SHA1_Update(&context, &sysdata, datalen); +- ++#endif + /* The system's host id: */ ++#if !LINUX + mib[0] = CTL_KERN; + mib[1] = KERN_HOSTID; + datalen = sizeof(sysdata); + sysctl(mib, 2, &sysdata, &datalen, NULL, 0); + SHA1_Update(&context, &sysdata, datalen); +- ++#endif + /* The system's host name: */ ++#if !LINUX + mib[0] = CTL_KERN; + mib[1] = KERN_HOSTNAME; + datalen = sizeof(sysctlstring); + sysctl(mib, 2, sysctlstring, &datalen, NULL, 0); + SHA1_Update(&context, sysctlstring, datalen); +- ++#endif + /* The running kernel's OS release string: */ ++#if !LINUX + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + datalen = sizeof(sysctlstring); + sysctl(mib, 2, sysctlstring, &datalen, NULL, 0); + SHA1_Update(&context, sysctlstring, datalen); +- ++#endif + /* The running kernel's version string: */ ++#if !LINUX + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + datalen = sizeof(sysctlstring); + sysctl(mib, 2, sysctlstring, &datalen, NULL, 0); + SHA1_Update(&context, sysctlstring, datalen); +- ++#endif + /* The system's load average: */ + datalen = sizeof(sysloadavg); + getloadavg(sysloadavg, 3); + SHA1_Update(&context, &sysloadavg, datalen); + + /* The system's VM statistics: */ ++#if !LINUX + mib[0] = CTL_VM; + mib[1] = VM_METER; + datalen = sizeof(sysvmtotal); + sysctl(mib, 2, &sysvmtotal, &datalen, NULL, 0); + SHA1_Update(&context, &sysvmtotal, datalen); +- ++#endif + /* The current GMT (26 ASCII characters): */ + time(&now); + strncpy(randomInputBuffer, asctime(gmtime(&now)), 26); /* "Mon Mar 27 13:46:26 2000" */ +Files diskdev_cmds-332.14/newfs_hfs.tproj/makehfs.o and diskdev_cmds-332.14-patched/newfs_hfs.tproj/makehfs.o differ +Files diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs and diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs differ +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.8 diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.8 +--- diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.8 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.8 2008-07-01 22:35:53.000000000 +0200 +@@ -93,7 +93,7 @@ + option followed by a comma + separated list of the form arg=blocks. + .Pp +-Example: -c c=5000,e=500 ++Example: \-c c=5000,e=500 + .Bl -tag -width Fl + .It Em a=blocks + Set the attribute file clump size. +@@ -126,7 +126,7 @@ + size must be a power of two and no larger than + 32768 bytes. + .Pp +-Example: -n c=8192,e=4096 ++Example: \-n c=8192,e=4096 + .Bl -tag -width Fl + .It Em a=bytes + Set the attribute b-tree node size. +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.c diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.c +--- diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.c 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.c 2008-07-01 22:30:11.000000000 +0200 +@@ -38,8 +38,13 @@ + #include + #include + #include ++#if LINUX ++#include ++#endif + ++#if !LINUX + #include ++#endif + + #include + #include "newfs_hfs.h" +@@ -73,7 +78,9 @@ + + char *progname; + char gVolumeName[kHFSPlusMaxFileNameChars + 1] = {kDefaultVolumeNameStr}; +-char rawdevice[MAXPATHLEN]; ++#if !LINUX ++char rawdevice[MAXPATHLEN]; ++#endif + char blkdevice[MAXPATHLEN]; + UInt32 gBlockSize = 0; + UInt32 gNextCNID = kHFSFirstUserCatalogNodeID; +@@ -137,8 +144,10 @@ + extern int optind; + int ch; + int forceHFS; ++#if !LINUX + char *cp, *special; + struct statfs *mp; ++#endif + int n; + + if ((progname = strrchr(*argv, '/'))) +@@ -238,7 +247,9 @@ + + if (argc != 1) + usage(); +- ++#if LINUX ++ (void) sprintf(blkdevice, "%s", argv[0]); ++#else + special = argv[0]; + cp = strrchr(special, '/'); + if (cp != 0) +@@ -247,6 +258,7 @@ + special++; + (void) sprintf(rawdevice, "%sr%s", _PATH_DEV, special); + (void) sprintf(blkdevice, "%s%s", _PATH_DEV, special); ++#endif + + if (forceHFS && gJournaled) { + fprintf(stderr, "-h -J: incompatible options specified\n"); +@@ -268,6 +280,9 @@ + /* + * Check if target device is aready mounted + */ ++#if LINUX ++ // FIXME ++#else + n = getmntinfo(&mp, MNT_NOWAIT); + if (n == 0) + fatal("%s: getmntinfo: %s", blkdevice, strerror(errno)); +@@ -277,14 +292,19 @@ + fatal("%s is mounted on %s", blkdevice, mp->f_mntonname); + ++mp; + } ++#endif + +- if (hfs_newfs(rawdevice, forceHFS, true) < 0) { ++ if (hfs_newfs(blkdevice, forceHFS, true) < 0) { ++#if LINUX ++ err(1, NULL); ++#else + /* On ENXIO error use the block device (to get de-blocking) */ + if (errno == ENXIO) { + if (hfs_newfs(blkdevice, forceHFS, false) < 0) + err(1, NULL); + } else + err(1, NULL); ++#endif + } + + exit(0); +@@ -458,7 +478,7 @@ + fatal("%s: block size is too small for %lld sectors", optarg, gBlockSize, sectorCount); + + if (gBlockSize < HFSOPTIMALBLKSIZE) +- warnx("Warning: %ld is a non-optimal block size (4096 would be a better choice)", gBlockSize); ++ warnx("Warning: %i is a non-optimal block size (4096 would be a better choice)", gBlockSize); + } + } + +@@ -472,7 +492,9 @@ + int fso = 0; + int retval = 0; + hfsparams_t defaults = {0}; ++#if !LINUX + u_int64_t maxSectorsPerIO; ++#endif + + if (gNoCreate) { + fso = open( device, O_RDONLY | O_NDELAY, 0 ); +@@ -485,7 +507,33 @@ + + if (fstat( fso, &stbuf) < 0) + fatal("%s: %s", device, strerror(errno)); ++#if LINUX ++ dip.sectorSize = 512; ++ dip.sectorsPerIO = 256; + ++#ifndef BLKGETSIZE ++#define BLKGETSIZE _IO(0x12,96) ++#endif ++#ifndef BLKGETSIZE64 ++#define BLKGETSIZE64 _IOR(0x12,114,size_t) ++#endif ++ ++ if (S_ISREG(stbuf.st_mode)) { ++ dip.totalSectors = stbuf.st_size / 512; ++ } ++ else if (S_ISBLK(stbuf.st_mode)) { ++ unsigned long size; ++ u_int64_t size64; ++ if (!ioctl(fso, BLKGETSIZE64, &size64)) ++ dip.totalSectors = size64 / 512; ++ else if (!ioctl(fso, BLKGETSIZE, &size)) ++ dip.totalSectors = size; ++ else ++ fatal("%s: %s", device, strerror(errno)); ++ } ++ else ++ fatal("%s: is not a block device", device); ++#else + if (ioctl(fso, DKIOCGETBLOCKCOUNT, &dip.totalSectors) < 0) + fatal("%s: %s", device, strerror(errno)); + +@@ -493,14 +541,17 @@ + fatal("%s: %s", device, strerror(errno)); + + if (ioctl(fso, DKIOCGETMAXBLOCKCOUNTWRITE, &maxSectorsPerIO) < 0) +- dip.sectorsPerIO = (128 * 1024) / dip.sectorSize; /* use 128K as default */ ++ dip.sectorsPerIO = (128 * 1024) / dip.sectorSize; /* use 128K as default */ + else + dip.sectorsPerIO = MIN(maxSectorsPerIO, (1024 * 1024) / dip.sectorSize); ++#endif ++ + /* +- * The make_hfs code currentlydoes 512 byte sized I/O. ++ * The make_hfs code currently does 512 byte sized I/O. + * If the sector size is bigger than 512, start over + * using the block device (to get de-blocking). + */ ++#if !LINUX + if (dip.sectorSize != kBytesPerSector) { + if (isRaw) { + close(fso); +@@ -515,7 +566,8 @@ + dip.sectorSize = kBytesPerSector; + } + } +- ++#endif ++ + dip.fd = fso; + dip.sectorOffset = 0; + time(&createtime); +@@ -693,7 +745,7 @@ + defaults->catalogClumpSize = clumpSize; + defaults->catalogNodeSize = catnodesiz; + if (gBlockSize < 4096 && gBlockSize < catnodesiz) +- warnx("Warning: block size %ld is less than catalog b-tree node size %ld", gBlockSize, catnodesiz); ++ warnx("Warning: block size %i is less than catalog b-tree node size %i", gBlockSize, catnodesiz); + + if (extclumpblks == 0) { + clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, extnodesiz, sectorCount, FALSE); +@@ -706,7 +758,7 @@ + defaults->extentsClumpSize = clumpSize; + defaults->extentsNodeSize = extnodesiz; + if (gBlockSize < extnodesiz) +- warnx("Warning: block size %ld is less than extents b-tree node size %ld", gBlockSize, extnodesiz); ++ warnx("Warning: block size %i is less than extents b-tree node size %i", gBlockSize, extnodesiz); + + if (atrclumpblks == 0) { + clumpSize = 0; +@@ -754,22 +806,22 @@ + + if (gNoCreate) { + if (!gWrapper) +- printf("%qd sectors (%lu bytes per sector)\n", sectorCount, sectorSize); ++ printf("%lld sectors (%u bytes per sector)\n", sectorCount, sectorSize); + printf("HFS Plus format parameters:\n"); + printf("\tvolume name: \"%s\"\n", gVolumeName); +- printf("\tblock-size: %lu\n", defaults->blockSize); +- printf("\ttotal blocks: %lu\n", totalBlocks); ++ printf("\tblock-size: %u\n", defaults->blockSize); ++ printf("\ttotal blocks: %u\n", totalBlocks); + if (gJournaled) + printf("\tjournal-size: %dk\n", (int)defaults->journalSize/1024); +- printf("\tfirst free catalog node id: %lu\n", defaults->nextFreeFileID); +- printf("\tcatalog b-tree node size: %lu\n", defaults->catalogNodeSize); +- printf("\tinitial catalog file size: %lu\n", defaults->catalogClumpSize); +- printf("\textents b-tree node size: %lu\n", defaults->extentsNodeSize); +- printf("\tinitial extents file size: %lu\n", defaults->extentsClumpSize); +- printf("\tinitial allocation file size: %lu (%lu blocks)\n", ++ printf("\tfirst free catalog node id: %u\n", defaults->nextFreeFileID); ++ printf("\tcatalog b-tree node size: %u\n", defaults->catalogNodeSize); ++ printf("\tinitial catalog file size: %u\n", defaults->catalogClumpSize); ++ printf("\textents b-tree node size: %u\n", defaults->extentsNodeSize); ++ printf("\tinitial extents file size: %u\n", defaults->extentsClumpSize); ++ printf("\tinitial allocation file size: %u (%u blocks)\n", + defaults->allocationClumpSize, defaults->allocationClumpSize / gBlockSize); +- printf("\tdata fork clump size: %lu\n", defaults->dataClumpSize); +- printf("\tresource fork clump size: %lu\n", defaults->rsrcClumpSize); ++ printf("\tdata fork clump size: %u\n", defaults->dataClumpSize); ++ printf("\tresource fork clump size: %u\n", defaults->rsrcClumpSize); + if (defaults->flags & kUseAccessPerms) { + printf("\tuser ID: %d\n", (int)defaults->owner); + printf("\tgroup ID: %d\n", (int)defaults->group); +@@ -844,17 +896,17 @@ + } + + if (gNoCreate) { +- printf("%ld sectors at %ld bytes per sector\n", sectorCount, sectorSize); ++ printf("%i sectors at %i bytes per sector\n", sectorCount, sectorSize); + printf("%s format parameters:\n", gWrapper ? "HFS Wrapper" : "HFS"); + printf("\tvolume name: \"%s\"\n", gVolumeName); +- printf("\tblock-size: %ld\n", defaults->blockSize); +- printf("\ttotal blocks: %ld\n", sectorCount / (alBlkSize / sectorSize) ); +- printf("\tfirst free catalog node id: %ld\n", defaults->nextFreeFileID); +- printf("\tinitial catalog file size: %ld\n", defaults->catalogClumpSize); +- printf("\tinitial extents file size: %ld\n", defaults->extentsClumpSize); +- printf("\tfile clump size: %ld\n", defaults->dataClumpSize); ++ printf("\tblock-size: %i\n", defaults->blockSize); ++ printf("\ttotal blocks: %i\n", sectorCount / (alBlkSize / sectorSize) ); ++ printf("\tfirst free catalog node id: %i\n", defaults->nextFreeFileID); ++ printf("\tinitial catalog file size: %i\n", defaults->catalogClumpSize); ++ printf("\tinitial extents file size: %i\n", defaults->extentsClumpSize); ++ printf("\tfile clump size: %i\n", defaults->dataClumpSize); + if (hfsgrowblks) +- printf("\twrapper growable from %ld to %ld sectors\n", sectorCount, hfsgrowblks); ++ printf("\twrapper growable from %i to %i sectors\n", sectorCount, hfsgrowblks); + } + } + +diff -druN diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.h diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.h +--- diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.h 2006-02-20 22:45:15.000000000 +0100 ++++ diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.h 2008-07-01 22:30:11.000000000 +0200 +@@ -19,8 +19,12 @@ + * + * @APPLE_LICENSE_HEADER_END@ + */ +- +-#include ++ ++#if LINUX ++#include "missing.h" ++#else ++#include */ ++#endif + + /* + * Mac OS Finder flags +@@ -122,33 +126,33 @@ + #define kDTDF_FileID 16 + #define kDTDF_Name "Desktop DF" + #define kDTDF_Chars 10 +-#define kDTDF_Type 'DTFL' +-#define kDTDF_Creator 'DMGR' ++#define kDTDF_Type 0x4454464C /* 'DTFL' */ ++#define kDTDF_Creator 0x444D4752 /* 'DMGR' */ + + #define kDTDB_FileID 17 + #define kDTDB_Name "Desktop DB" + #define kDTDB_Chars 10 +-#define kDTDB_Type 'BTFL' +-#define kDTDB_Creator 'DMGR' ++#define kDTDB_Type 0x4254464C /* 'BTFL' */ ++#define kDTDB_Creator 0x444D4752 /* 'DMGR' */ + #define kDTDB_Size 1024 + + #define kReadMe_FileID 18 + #define kReadMe_Name "ReadMe" + #define kReadMe_Chars 6 +-#define kReadMe_Type 'ttro' +-#define kReadMe_Creator 'ttxt' ++#define kReadMe_Type 0x7474726F /* 'ttro' */ ++#define kReadMe_Creator 0x74747974 /* 'ttxt' */ + + #define kFinder_FileID 19 + #define kFinder_Name "Finder" + #define kFinder_Chars 6 +-#define kFinder_Type 'FNDR' +-#define kFinder_Creator 'MACS' ++#define kFinder_Type 0x464E4452 /* 'FNDR' */ ++#define kFinder_Creator 0x4D414353 /* 'MACS' */ + + #define kSystem_FileID 20 + #define kSystem_Name "System" + #define kSystem_Chars 6 +-#define kSystem_Type 'zsys' +-#define kSystem_Creator 'MACS' ++#define kSystem_Type 0x7A737973 /* 'zsys' */ ++#define kSystem_Creator 0x4D414353 /* 'MACS' */ + + + +Files diskdev_cmds-332.14/newfs_hfs.tproj/newfs_hfs.o and diskdev_cmds-332.14-patched/newfs_hfs.tproj/newfs_hfs.o differ diff --git a/packages/sysutils/dosfstools/package.mk b/packages/sysutils/dosfstools/package.mk new file mode 100644 index 000000000..5298277a5 --- /dev/null +++ b/packages/sysutils/dosfstools/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dosfstools" +PKG_VERSION="4.1" +PKG_SHA256="e6b2aca70ccc3fe3687365009dd94a2e18e82b688ed4e260e04b7412471cc173" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/dosfstools/dosfstools" +PKG_URL="https://github.com/dosfstools/dosfstools/releases/download/v${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_INIT="toolchain dosfstools" +PKG_LONGDESC="dosfstools contains utilities for making and checking MS-DOS FAT filesystems." + +PKG_CONFIGURE_OPTS_TARGET="--enable-compat-symlinks" +PKG_MAKE_OPTS_TARGET="PREFIX=/usr" +PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr" + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/sbin + cp ../.install_pkg/usr/sbin/fsck.fat ${INSTALL}/usr/sbin + ln -sf fsck.fat ${INSTALL}/usr/sbin/fsck.msdos + ln -sf fsck.fat ${INSTALL}/usr/sbin/fsck.vfat +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/sbin + cp src/mkfs.fat ${TOOLCHAIN}/sbin + ln -sf mkfs.fat ${TOOLCHAIN}/sbin/mkfs.vfat + cp src/fsck.fat ${TOOLCHAIN}/sbin + ln -sf fsck.fat ${TOOLCHAIN}/sbin/fsck.vfat + cp src/fatlabel ${TOOLCHAIN}/sbin +} diff --git a/packages/sysutils/dosfstools/patches/dosfstools-01-silence_backup_boot_sector_diff.patch b/packages/sysutils/dosfstools/patches/dosfstools-01-silence_backup_boot_sector_diff.patch new file mode 100644 index 000000000..2fe329dc5 --- /dev/null +++ b/packages/sysutils/dosfstools/patches/dosfstools-01-silence_backup_boot_sector_diff.patch @@ -0,0 +1,23 @@ + +Do not print backup boot sector diff in non interactive mode to avoid log spam. + +--- a/src/boot.c 2017-01-23 02:16:58.000000000 +0100 ++++ a/src/boot.c 2020-02-05 18:32:16.000000000 +0100 +@@ -174,6 +174,9 @@ static void check_backup_boot(DOS_FS * f + char buf[20]; + + printf("There are differences between boot sector and its backup.\n"); ++ if (!interactive) ++ printf("This is mostly harmless.\n"); ++ else { + printf("This is mostly harmless. Differences: (offset:original/backup)\n "); + pos = 2; + for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2); +@@ -188,6 +191,7 @@ static void check_backup_boot(DOS_FS * f + first = 0; + } + } ++ } + printf("\n"); + + if (interactive) diff --git a/packages/sysutils/dstat/package.mk b/packages/sysutils/dstat/package.mk new file mode 100644 index 000000000..1faa9abad --- /dev/null +++ b/packages/sysutils/dstat/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dstat" +PKG_VERSION="77e9347" +PKG_SHA256="2b2f4ef3a0d1dc6d0a4bc2f54a57ba6f1e278333881a07df7e55aec502a48c7c" +PKG_LICENSE="GPL" +PKG_SITE="http://dag.wiee.rs/home-made/dstat" +PKG_URL="https://github.com/dagwieers/dstat/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python2" +PKG_LONGDESC="Versatile resource statistics tool." +PKG_TOOLCHAIN="manual" + +post_unpack() { +rm $PKG_BUILD/Makefile +} diff --git a/packages/sysutils/dtach/package.mk b/packages/sysutils/dtach/package.mk new file mode 100644 index 000000000..80361d0ab --- /dev/null +++ b/packages/sysutils/dtach/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dtach" +PKG_VERSION="0.9" +PKG_SHA256="5f7e8c835ee49a9e6dcf89f4e8ccbe724b061c0fc8565b504dd8b3e67ab79f82" +PKG_LICENSE="GPL" +PKG_SITE="http://dtach.sourceforge.net" +PKG_URL="https://github.com/crigler/dtach/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A program that emulates the detach feature of screen." + +makeinstall_target() { + : +} diff --git a/packages/sysutils/e2fsprogs/package.mk b/packages/sysutils/e2fsprogs/package.mk new file mode 100644 index 000000000..5fab785b0 --- /dev/null +++ b/packages/sysutils/e2fsprogs/package.mk @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="e2fsprogs" +PKG_VERSION="1.45.3" +PKG_SHA256="90d10066b815e27b0b4875f0d5e396c663e0bf55aa3ca10868978d10c6ffe595" +PKG_LICENSE="GPL" +PKG_SITE="http://e2fsprogs.sourceforge.net/" +PKG_URL="https://www.kernel.org/pub/linux/kernel/people/tytso/$PKG_NAME/v$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="gcc:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_INIT="toolchain" +PKG_LONGDESC="The filesystem utilities for the EXT2 filesystem, including e2fsck, mke2fs, dumpe2fs, fsck, and others." +PKG_BUILD_FLAGS="-parallel" + +if [ "$HFSTOOLS" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET diskdev_cmds" +fi + +PKG_CONFIGURE_OPTS_HOST="--prefix=$TOOLCHAIN/ \ + --bindir=$TOOLCHAIN/bin \ + --with-udev-rules-dir=no \ + --with-crond-dir=no \ + --with-systemd-unit-dir=no \ + --sbindir=$TOOLCHAIN/sbin \ + --enable-verbose-makecmds \ + --disable-symlink-install \ + --disable-symlink-build \ + --disable-subset \ + --disable-debugfs \ + --disable-imager \ + --disable-resizer \ + --disable-defrag \ + --disable-fsck \ + --disable-e2initrd-helper \ + --enable-tls \ + --disable-uuidd \ + --disable-nls \ + --disable-rpath \ + --disable-fuse2fs \ + --with-gnu-ld" + +pre_configure() { + PKG_CONFIGURE_OPTS_INIT="BUILD_CC=$HOST_CC \ + --with-udev-rules-dir=no \ + --with-crond-dir=no \ + --with-systemd-unit-dir=no \ + --enable-verbose-makecmds \ + --enable-symlink-install \ + --enable-symlink-build \ + --disable-subset \ + --disable-elf-shlibs \ + --disable-bsd-shlibs \ + --disable-profile \ + --disable-jbd-debug \ + --disable-blkid-debug \ + --disable-testio-debug \ + --enable-libuuid \ + --enable-libblkid \ + --disable-debugfs \ + --disable-imager \ + --enable-resizer \ + --enable-fsck \ + --disable-e2initrd-helper \ + --enable-tls \ + --disable-uuidd \ + --disable-nls \ + --disable-rpath \ + --disable-fuse2fs \ + --with-gnu-ld" + + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_INIT" +} + +post_makeinstall_target() { + make -C lib/et LIBMODE=644 DESTDIR=$SYSROOT_PREFIX install + + rm -rf $INSTALL/usr/sbin/badblocks + rm -rf $INSTALL/usr/sbin/blkid + rm -rf $INSTALL/usr/sbin/dumpe2fs + rm -rf $INSTALL/usr/sbin/e2freefrag + rm -rf $INSTALL/usr/sbin/e2undo + rm -rf $INSTALL/usr/sbin/e4defrag + rm -rf $INSTALL/usr/sbin/filefrag + rm -rf $INSTALL/usr/sbin/fsck + rm -rf $INSTALL/usr/sbin/logsave + rm -rf $INSTALL/usr/sbin/mklost+found +} + +makeinstall_init() { + mkdir -p $INSTALL/usr/sbin + cp e2fsck/e2fsck $INSTALL/usr/sbin + ln -sf e2fsck $INSTALL/usr/sbin/fsck.ext2 + ln -sf e2fsck $INSTALL/usr/sbin/fsck.ext3 + ln -sf e2fsck $INSTALL/usr/sbin/fsck.ext4 + ln -sf e2fsck $INSTALL/usr/sbin/fsck.ext4dev + + if [ $INITRAMFS_PARTED_SUPPORT = "yes" ]; then + cp misc/mke2fs $INSTALL/usr/sbin + ln -sf mke2fs $INSTALL/usr/sbin/mkfs.ext2 + ln -sf mke2fs $INSTALL/usr/sbin/mkfs.ext3 + ln -sf mke2fs $INSTALL/usr/sbin/mkfs.ext4 + ln -sf mke2fs $INSTALL/usr/sbin/mkfs.ext4dev + fi +} + +makeinstall_host() { + make -C lib/et LIBMODE=644 install + make -C lib/ext2fs LIBMODE=644 install + mkdir -p $TOOLCHAIN/sbin + cp e2fsck/e2fsck $TOOLCHAIN/sbin + cp misc/mke2fs $TOOLCHAIN/sbin + cp misc/tune2fs $TOOLCHAIN/sbin + mkdir -p $TOOLCHAIN/etc + cp misc/mke2fs.conf $TOOLCHAIN/etc +} diff --git a/packages/sysutils/e2fsprogs/patches/e2fsprogs-0001-remove-64bit-from-default-ext4-config.patch b/packages/sysutils/e2fsprogs/patches/e2fsprogs-0001-remove-64bit-from-default-ext4-config.patch new file mode 100644 index 000000000..5fa741d2c --- /dev/null +++ b/packages/sysutils/e2fsprogs/patches/e2fsprogs-0001-remove-64bit-from-default-ext4-config.patch @@ -0,0 +1,11 @@ +--- a/misc/mke2fs.conf.in ++++ b/misc/mke2fs.conf.in +@@ -11,7 +11,7 @@ + features = has_journal + } + ext4 = { +- features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize ++ features = has_journal,extent,huge_file,flex_bg,metadata_csum,dir_nlink,extra_isize + inode_size = 256 + } + small = { diff --git a/packages/sysutils/efibootmgr/package.mk b/packages/sysutils/efibootmgr/package.mk new file mode 100644 index 000000000..0c64c2ef6 --- /dev/null +++ b/packages/sysutils/efibootmgr/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="efibootmgr" +PKG_VERSION="99b578501643377e0b1994b2a068b790d189d5ad" +PKG_SHA256="04bc45dc8a841985d78d8df87b3475eb6e1122f993fae975197bf3adbc6e3341" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/rhboot/efibootmgr" +PKG_URL="https://github.com/rhboot/efibootmgr/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain efivar pciutils zlib" +PKG_LONGDESC="Tool to modify UEFI Firmware Boot Manager Variables." + +make_target() { + export CFLAGS="$CFLAGS -I$SYSROOT_PREFIX/usr/include -I$SYSROOT_PREFIX/usr/include/efivar -fgnu89-inline" + export LDFLAGS="$LDFLAGS -L$SYSROOT_PREFIX/usr/lib -ludev -ldl" + + make EFIDIR=BOOT EFI_LOADER=bootx64.efi PKG_CONFIG=true \ + LDLIBS="-lefiboot -lefivar" \ + efibootmgr +} + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/encfs/package.mk b/packages/sysutils/encfs/package.mk new file mode 100644 index 000000000..235710fad --- /dev/null +++ b/packages/sysutils/encfs/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="encfs" +PKG_VERSION="1.9.5" +PKG_SHA256="4709f05395ccbad6c0a5b40a4619d60aafe3473b1a79bafb3aa700b1f756fd63" +PKG_LICENSE="LGPL" +PKG_SITE="https://vgough.github.io/encfs/" +PKG_URL="https://github.com/vgough/encfs/releases/download/v$PKG_VERSION/encfs-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain fuse openssl" +PKG_LONGDESC="A Encrypted Filesystem for FUSE." + +PKG_CMAKE_OPTS_TARGET="-DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=$SYSROOT_PREFIX/usr/include \ + -DBUILD_UNIT_TESTS=OFF" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/entropy/package.mk b/packages/sysutils/entropy/package.mk new file mode 100644 index 000000000..53eb0a735 --- /dev/null +++ b/packages/sysutils/entropy/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="entropy" +PKG_VERSION="0" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A simple way to add entropy at boot" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/lib/entropy + cp add-entropy $INSTALL/usr/lib/entropy + cp add-random-at-shutdown $INSTALL/usr/lib/entropy + + chmod +x $INSTALL/usr/lib/entropy/* +} + +post_install() { + enable_service add-entropy.service + enable_service add-random-at-shutdown.service +} diff --git a/packages/sysutils/entropy/sources/add-entropy b/packages/sysutils/entropy/sources/add-entropy new file mode 100644 index 000000000..e3af8fab4 --- /dev/null +++ b/packages/sysutils/entropy/sources/add-entropy @@ -0,0 +1,24 @@ +#!/usr/bin/python + +import os +import struct + +RNDADDENTROPY = 0x40085203 +import fcntl + +def add_entropy(fd, data): + add = struct.pack('ii', len(data)*8, len(data)) + data + fcntl.ioctl(fd, RNDADDENTROPY, add) + +if not os.path.isfile("/storage/.cache/random.data"): + os.system("dd if=/dev/urandom of=/storage/.cache/random.data count=4 >/dev/null") + +cache=os.open("/storage/.cache/random.data", os.O_RDONLY) + +rnd=os.open("/dev/random", os.O_RDWR) + +while True: + data=os.read(cache, 512) + if len(data) == 0: + break + add_entropy(rnd, data) diff --git a/packages/sysutils/entropy/sources/add-random-at-shutdown b/packages/sysutils/entropy/sources/add-random-at-shutdown new file mode 100644 index 000000000..967712e5a --- /dev/null +++ b/packages/sysutils/entropy/sources/add-random-at-shutdown @@ -0,0 +1,2 @@ +#!/bin/sh +dd if=/dev/urandom of=/storage/.cache/random.data count=4 diff --git a/packages/sysutils/entropy/system.d/add-entropy.service b/packages/sysutils/entropy/system.d/add-entropy.service new file mode 100644 index 000000000..ddfb1bec3 --- /dev/null +++ b/packages/sysutils/entropy/system.d/add-entropy.service @@ -0,0 +1,13 @@ +[Unit] +Description=Add random entropy from file +DefaultDependencies=no +After=systemd-tmpfiles-setup.service +Before=systemd-udevd.service + +[Service] +Type=oneshot +ExecStart=/usr/lib/entropy/add-entropy +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/entropy/system.d/add-random-at-shutdown.service b/packages/sysutils/entropy/system.d/add-random-at-shutdown.service new file mode 100644 index 000000000..61ab2f724 --- /dev/null +++ b/packages/sysutils/entropy/system.d/add-random-at-shutdown.service @@ -0,0 +1,12 @@ +[Unit] +Description=Save random entropy at shutdown +DefaultDependencies=no +Before=systemd-poweroff.service systemd-reboot.service systemd-halt.service + +[Service] +Type=oneshot +ExecStart=/usr/lib/entropy/add-random-at-shutdown +RemainAfterExit=yes + +[Install] +WantedBy=poweroff.target reboot.target halt.target diff --git a/packages/sysutils/ethmactool/package.mk b/packages/sysutils/ethmactool/package.mk new file mode 100644 index 000000000..9edc7d01b --- /dev/null +++ b/packages/sysutils/ethmactool/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="ethmactool" +PKG_VERSION="1.0" +PKG_LICENSE="GPLv2" +PKG_LONGDESC="ethmactool: udev rule for obtaining real MAC address or creating a persistent MAC from the CPU serial" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/ethmactool-config $INSTALL/usr/bin +} + +post_install() { + enable_service ethmactool-config.service +} diff --git a/packages/sysutils/ethmactool/scripts/ethmactool-config b/packages/sysutils/ethmactool/scripts/ethmactool-config new file mode 100755 index 000000000..e704f3262 --- /dev/null +++ b/packages/sysutils/ethmactool/scripts/ethmactool-config @@ -0,0 +1,73 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +COMPATIBLE=$(/usr/bin/dtsoc) +MAC_STEP="" + +validate_mac() { + [ ${#MAC} -eq 12 -a "${MAC}" != "000000000000" ] +} + +fixup_self_mac() { + # clear multicast bit and set local assignment bit (IEEE802) + MAC=$(printf '%012X' "$(( (0x$MAC & 0xFEFFFFFFFFFF) | 0x020000000000 ))") +} + +from_cmdline() { + for arg in $(cat /proc/cmdline | tr -d ':'); do + case ${arg} in + mac=*) + MAC=${arg#*=} + ;; + esac + done +} + +aml_from_efuse_gxbb() { + if [ -e /sys/devices/platform/efuse/efuse0/nvmem ] ; then + MAC=$(od -x -A n -j 0x34 -N 6 /sys/bus/nvmem/devices/efuse0/nvmem | tr -d ' ') + MAC=${MAC:2:2}${MAC:0:2}${MAC:6:2}${MAC:4:2}${MAC:10:2}${MAC:8:2} + fi +} + +aml_from_efuse_gxl() { + if [ -e /sys/devices/platform/efuse/efuse0/nvmem ] ; then + MAC=$(cat /sys/devices/platform/efuse/efuse0/nvmem) + fi +} + +aml_from_cpu_sn() { + if [ -e /sys/bus/platform/devices/firmware\:secure-monitor/serial ] ; then + MAC=$(cat /sys/bus/platform/devices/firmware\:secure-monitor/serial 2>/dev/null | cut -b-12) + fixup_self_mac + fi +} + +from_cpu_sn() { + MAC=$(cat /proc/cpuinfo 2>/dev/null | awk '/Serial/ {print substr($3,1,12)}') + fixup_self_mac +} + +case $COMPATIBLE in + amlogic*) + MAC_STEPS="from_cmdline aml_from_efuse_gxbb aml_from_efuse_gxl aml_from_cpu_sn" + ;; + *) + MAC_STEPS="from_cpu_sn" + ;; +esac + +for MAC_STEP in $MAC_STEPS ; do + $MAC_STEP + validate_mac && break +done + +if validate_mac ; then + MAC=$(echo "$MAC" | sed 's/\(..\)/\1:/g' | cut -b-17) + echo "MAC=${MAC}" > /run/libreelec/ethmactool-$1 + /usr/sbin/ip link set dev $1 down + /usr/sbin/ip link set dev $1 address $MAC + /usr/sbin/ip link set dev $1 up +fi diff --git a/packages/sysutils/ethmactool/system.d/ethmactool-config.service b/packages/sysutils/ethmactool/system.d/ethmactool-config.service new file mode 100644 index 000000000..e11180b46 --- /dev/null +++ b/packages/sysutils/ethmactool/system.d/ethmactool-config.service @@ -0,0 +1,13 @@ +[Unit] +Description=Configure eth0 MAC address +BindsTo=sys-subsystem-net-devices-eth0.device +After=sys-subsystem-net-devices-eth0.device +Before=connman.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/ethmactool-config eth0 + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/eventlircd/evmap/03_03eb_0002.evmap b/packages/sysutils/eventlircd/evmap/03_03eb_0002.evmap new file mode 100644 index 000000000..6da7459e5 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_03eb_0002.evmap @@ -0,0 +1,8 @@ +KEY_VOLDOWN = KEY_VOLUMEDOWN # Volume Down +KEY_VOLUP = KEY_VOLUMEUP # Volume Up +KEY_CHDOWN = KEY_CHANNELDOWN # Channel Down +KEY_CHUP = KEY_CHANNELUP # Channel Up +KEY_OK = KEY_ENTER # Direction OK (also used for Enter) +KEY_FFORWARD = KEY_FASTFORWARD # Forward +KEY_GUIDE = KEY_EPG # EPG + diff --git a/packages/sysutils/eventlircd/evmap/03_0419_0001.evmap b/packages/sysutils/eventlircd/evmap/03_0419_0001.evmap new file mode 100644 index 000000000..a1eaeaf53 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_0419_0001.evmap @@ -0,0 +1,17 @@ + ctrl+shift+alt+KEY_2 = KEY_PVR # TV/DVR + ctrl+shift+alt+KEY_H = KEY_PRINT # Print + alt+KEY_F4 = KEY_CLOSE # Close + ctrl+shift+alt+KEY_3 = KEY_MP3 # Music + ctrl+shift+alt+KEY_4 = KEY_MEDIA # Pictures + ctrl+shift+alt+KEY_5 = KEY_VIDEO # Videos + ctrl+shift+alt+KEY_1 = KEY_CONTEXT_MENU # DVD/Menu + ctrl+KEY_B = KEY_PREVIOUS # Previous + ctrl+KEY_P = KEY_PLAYPAUSE # Play/Pause + ctrl+KEY_F = KEY_NEXT # Next + ctrl+shift+KEY_B = KEY_REWIND # Rew + ctrl+KEY_S = KEY_STOP # Stop + ctrl+shift+KEY_F = KEY_FORWARD # Fwd + ctrl+shift+alt+KEY_HOME = KEY_MENU # Home + ctrl+KEY_R = KEY_RECORD # Record + ctrl+shift+alt+KEY_F = KEY_SHUFFLE # Shuffle + ctrl+shift+alt+KEY_B = KEY_MEDIA_REPEAT # Repeat diff --git a/packages/sysutils/eventlircd/evmap/03_046d_c101.evmap b/packages/sysutils/eventlircd/evmap/03_046d_c101.evmap new file mode 100644 index 000000000..bb6da67c6 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_046d_c101.evmap @@ -0,0 +1,14 @@ +# Logitech, Inc. UltraX Media Remote +# Bus=001 Device=009 Product=046d Version=c101 + + KEY_KPENTER = KEY_ENTER # Enter/OK + KEY_STOPCD = KEY_STOP # Stop + + KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev + KEY_NEXTSONG = KEY_NEXT # Next + KEY_PLAYPAUSE = KEY_PLAY # Play/Pause + KEY_FASTFORWARD = KEY_FASTFORWARD # Fwd + + KEY_BACK = KEY_EXIT # Back + KEY_AGAIN = KEY_MEDIA_REPEAT # Repeat + KEY_PROPS = KEY_INFO # Info/EPG diff --git a/packages/sysutils/eventlircd/evmap/03_05a4_9881.evmap b/packages/sysutils/eventlircd/evmap/03_05a4_9881.evmap new file mode 100644 index 000000000..fcd08f468 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_05a4_9881.evmap @@ -0,0 +1,57 @@ + KEY_HOMEPAGE = KEY_WWW # WWW + KEY_SLEEP = KEY_POWER # Sleep + ctrl+shift+KEY_T = KEY_VCR # My TV + ctrl+KEY_M = KEY_AUDIO # My Music + ctrl+KEY_I = KEY_CAMERA # My Pictures + ctrl+KEY_E = KEY_VIDEO # My Videos + ctrl+KEY_O = KEY_TUNER # Record TV + ctrl+KEY_G = KEY_EPG # Guide + ctrl+KEY_T = KEY_TV # Live TV + ctrl+shift+KEY_M = KEY_DVD # DVD Menu + KEY_PLAYPAUSE = KEY_PLAY # Play (also used for Pause) +#KEY_PLAYPAUSE = KEY_PAUSE # Pause (also used for Play) + ctrl+shift+KEY_B = KEY_REWIND # Reverse + ctrl+shift+KEY_F = KEY_FASTFORWARD # Forward + KEY_PREVIOUSSONG = KEY_PREVIOUS # Pre-track + KEY_NEXTSONG = KEY_NEXT # Next track + KEY_STOPCD = KEY_STOP # Stop + ctrl+KEY_R = KEY_RECORD # Record + KEY_BACKSPACE = KEY_EXIT # Back + BTN_RIGHT = KEY_INFO # Information (also used for Mouse Right) + KEY_UP = KEY_UP # Direction Up + KEY_DOWN = KEY_DOWN # Direction Down + KEY_LEFT = KEY_LEFT # Direction Left + KEY_RIGHT = KEY_RIGHT # Direction Right + KEY_ENTER = KEY_ENTER # Direction OK (also used for Enter) + BTN_MOUSE = BTN_LEFT # Mouse Left +#BTN_RIGHT = KEY_INFO # Mouse Right (also used for Information) + KEY_VOLUMEUP = KEY_VOLUMEUP # Volume Up + KEY_VOLUMEDOWN = KEY_VOLUMEDOWN # Volume Down + KEY_PAGEDOWN = KEY_CHANNELDOWN # Channel Up + KEY_PAGEUP = KEY_CHANNELUP # Channel Down + KEY_MUTE = KEY_MUTE # Mute + alt+meta+KEY_ENTER = KEY_MEDIA # Start Key + alt+KEY_F4 = KEY_SUBTITLE # Close (used here for Subtitles) + KEY_ESC = KEY_DELETE # Clear +#KEY_ENTER = KEY_ENTER # Enter (also used for Direction OK) + numlock+KEY_KP0 = KEY_NUMERIC_0 # 0 + numlock+KEY_KP1 = KEY_NUMERIC_1 # 1 + numlock+KEY_KP2 = KEY_NUMERIC_2 # 2 + numlock+KEY_KP3 = KEY_NUMERIC_3 # 3 + numlock+KEY_KP4 = KEY_NUMERIC_4 # 4 + numlock+KEY_KP5 = KEY_NUMERIC_5 # 5 + numlock+KEY_KP6 = KEY_NUMERIC_6 # 6 + numlock+KEY_KP7 = KEY_NUMERIC_7 # 7 + numlock+KEY_KP8 = KEY_NUMERIC_8 # 8 + numlock+KEY_KP9 = KEY_NUMERIC_9 # 9 + KEY_KPASTERISK = KEY_ZOOM # * + numlock+alt+KEY_KP3 = KEY_TEXT # # + numlock+alt+KEY_KP5 = NULL # Sent as part #, and we ignore it + +#The USB interface advertises these events but none of the remote control's +#buttons appear to generate them. Therefore, they are set to NULL so that +#eventlircd does not advertise them as part of its mouse/joystick device. + BTN_MIDDLE = NULL + BTN_SIDE = NULL + BTN_EXTRA = NULL + REL_WHEEL = NULL diff --git a/packages/sysutils/eventlircd/evmap/03_05ac_8241.evmap b/packages/sysutils/eventlircd/evmap/03_05ac_8241.evmap new file mode 100644 index 000000000..9cb59bbfe --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_05ac_8241.evmap @@ -0,0 +1,4 @@ +# Apple Infrared Remote Controller + + KEY_FORWARD = KEY_NEXT # Next + KEY_BACK = KEY_PREVIOUS # Prev diff --git a/packages/sysutils/eventlircd/evmap/03_0709_9137.evmap b/packages/sysutils/eventlircd/evmap/03_0709_9137.evmap new file mode 100644 index 000000000..ac672550a --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_0709_9137.evmap @@ -0,0 +1,17 @@ +# Giada N20 Remote +# Bus=0003 Vendor=0709 Product=9137 Version=0111 + + KEY_BACK = KEY_EXIT # Back + KEY_ESC = KEY_CLEAR # Clear + + KEY_STOPCD = KEY_STOP # Stop + KEY_NEXTSONG = KEY_NEXT # Next + KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev + KEY_REWIND = KEY_REWIND # Rev + KEY_FASTFORWARD = KEY_FASTFORWARD # Fwd + + KEY_COMPOSE = KEY_INFO # Info/EPG + KEY_G = KEY_EPG # Guide + + shift+KEY_3 = KEY_NUMERIC_POUND # Hash (#) + shift+KEY_8 = KEY_NUMERIC_STAR # Star (*) diff --git a/packages/sysutils/eventlircd/evmap/03_0755_2626.evmap b/packages/sysutils/eventlircd/evmap/03_0755_2626.evmap new file mode 100644 index 000000000..e5e57c902 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_0755_2626.evmap @@ -0,0 +1,56 @@ +# Remote 0755:2626 Aureal Semiconductor (iRF Media Technology W-01RN USB_V3.1) + + shift+KEY_8 = KEY_NUMERIC_STAR # * + shift+KEY_3 = KEY_NUMERIC_POUND # # + + ctrl+shift+KEY_B = KEY_REWIND # Rewind + ctrl+KEY_LEFT = NULL # Rew (Hide) + ctrl+shift+KEY_LEFT = NULL # Rew + + ctrl+shift+KEY_F = NULL # Fwd (Hide) + ctrl+KEY_RIGHT = NULL # Fwd (Hide) + ctrl+shift+KEY_RIGHT = NULL # Fwd + + alt+KEY_LEFT = NULL # Prev + ctrl+KEY_PAGEUP = NULL # Prev + KEY_PREVIOUSSONG = KEY_PREVIOUS # Replay + + alt+KEY_DOWN = NULL # Next + ctrl+KEY_PAGEDOWN = NULL # Next + KEY_NEXTSONG = KEY_NEXT # Skip + + KEY_SPACE = NULL # Play/Pause + KEY_PLAYPAUSE = KEY_PLAY # Play/Pause + + KEY_DOT = NULL # Stop + ctrl+KEY_U = NULL # Stop + alt+KEY_U = NULL # Stop + KEY_STOPCD = KEY_STOP # Stop + + KEY_PAGEUP = KEY_CHANNELUP # CH/PG up + KEY_PAGEDOWN = KEY_CHANNELDOWN # CH/PG down + + KEY_HOMEPAGE = KEY_GREEN # Green Key + KEY_MAIL = KEY_YELLOW # Yellow Key + + alt+meta+KEY_ENTER = KEY_MEDIA # Home + ctrl+KEY_M = KEY_AUDIO # Music + ctrl+KEY_I = KEY_CAMERA # Pictures + ctrl+shift+KEY_M = KEY_DVD # DVD/VCD + ctrl+KEY_E = KEY_VIDEO # Videos + ctrl+KEY_A = KEY_RADIO # Radio + ctrl+shift+KEY_T = KEY_TUNER # Tuner + KEY_PVR = KEY_TV # PVR + + meta+KEY_EQUAL = KEY_INFO # Zoom + ctrl+KEY_ENTER = NULL # Full Screen (Hide) + alt+KEY_ENTER = KEY_ZOOM # Full Screen + + KEY_OK = KEY_ENTER # Ok + KEY_BACKSPACE = KEY_EXIT # BACK + + alt+KEY_F4 = KEY_CLOSE # Close + meta+KEY_D = KEY_INFO # Desktop, remapped to Info in XBMC + KEY_COMPOSE = KEY_EPG # More, remapped to Context Menu in XBMC + ctrl+KEY_R = KEY_RECORD # Record + KEY_ESC = KEY_DELETE # Clear diff --git a/packages/sysutils/eventlircd/evmap/03_0bc7_0006.evmap b/packages/sysutils/eventlircd/evmap/03_0bc7_0006.evmap new file mode 100644 index 000000000..484df5657 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_0bc7_0006.evmap @@ -0,0 +1,13 @@ +# X10 Remote + + KEY_OK = KEY_ENTER # Direction OK (also used for Enter) + KEY_STOPCD = KEY_STOP # Stop + + KEY_FASTFORWARD = KEY_FORWARD # Forward + + KEY_IMAGES = KEY_CAMERA # My Pictures + KEY_TV = KEY_TUNER # My TV + + KEY_SELECT = KEY_MEDIA # Start Key/Select Key + KEY_BACK = KEY_EXIT # Back + diff --git a/packages/sysutils/eventlircd/evmap/03_1241_e000.evmap b/packages/sysutils/eventlircd/evmap/03_1241_e000.evmap new file mode 100644 index 000000000..9a8973638 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_1241_e000.evmap @@ -0,0 +1,47 @@ +# 1241:e000 HOLTEK USB receiver +# mode 1, keyboard red # keyboard on +# mode 2, mouse blue # mouse on + + shift+KEY_8 = KEY_NUMERIC_STAR # * + BTN_LEFT = KEY_NUMERIC_POUND # # + + alt+KEY_F4 = KEY_POWER # Power + + ctrl+KEY_R = KEY_RECORD # Record + ctrl+KEY_P = KEY_PAUSE # Pause + ctrl+shift+KEY_S = KEY_STOP # Stop + ctrl+shift+KEY_B = KEY_REWIND # Rev + ctrl+shift+KEY_P = KEY_PLAY # Play + ctrl+shift+KEY_F = KEY_FASTFORWARD # Fwd + KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev + KEY_KPASTERISK = KEY_PREVIOUS # Prev + KEY_NEXTSONG = KEY_NEXT # Next + ctrl+KEY_F = KEY_NEXT # Next + + KEY_BACKSPACE = KEY_EXIT # BACK/Clear + ctrl+KEY_B = KEY_BACK # BACK/Clear + BTN_RIGHT = KEY_INFO # Info/EPG + KEY_F1 = KEY_INFO # Info/EPG + KEY_COMPOSE = KEY_INFO # Info/EPG + alt+meta+KEY_ENTER = KEY_MEDIA # Media + + KEY_F10 = KEY_VOLUMEUP # Vol + + KEY_F9 = KEY_VOLUMEDOWN # Vol - + KEY_PAGEUP = KEY_CHANNELUP # CH/PG up + KEY_PAGEDOWN = KEY_CHANNELDOWN # CH/PG down + KEY_F8 = KEY_MUTE # Mute + + ctrl+shift+KEY_T = KEY_SUBTITLE # Teletext + ctrl+shift+KEY_C = KEY_SUBTITLE # Teletext + ctrl+KEY_U = KEY_SUBTITLE # Subtitles + ctrl+KEY_G = KEY_EPG # Program # remapped to EPG (Contextmenu) + + ctrl+shift+KEY_M = KEY_DVD # DVD + KEY_MP3 = KEY_AUDIO # Music + ctrl+KEY_M = KEY_AUDIO # Audio + ctrl+KEY_T = KEY_TUNER # LiveTV + ctrl+KEY_E = KEY_TUNER # TV + ctrl+KEY_O = KEY_PVR # RecordedTV + + ctrl+KEY_I = KEY_GREEN # Green + alt+KEY_TAB = KEY_YELLOW # Yellow diff --git a/packages/sysutils/eventlircd/evmap/03_13ec_0006.evmap b/packages/sysutils/eventlircd/evmap/03_13ec_0006.evmap new file mode 100644 index 000000000..0bb87989e --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_13ec_0006.evmap @@ -0,0 +1,16 @@ +# Remote 13ec:0006 + + KEY_SLEEP = KEY_POWER # Power + + KEY_BACKSPACE = KEY_EXIT # Backspace + + KEY_PLAYPAUSE = KEY_PLAY # Play/Pause + KEY_STOPCD = KEY_STOP # Stop + KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev + KEY_NEXTSONG = KEY_NEXT # Next + + KEY_PVR = KEY_MEDIA # Home + KEY_AUX = KEY_CAMERA # Photo + + KEY_MENU = KEY_EPG # Menu (used for XBMC's context menu) + KEY_K = KEY_EPG # Title (used for XBMC's context menu) diff --git a/packages/sysutils/eventlircd/evmap/03_147a_e02d.evmap b/packages/sysutils/eventlircd/evmap/03_147a_e02d.evmap new file mode 100644 index 000000000..9358a9f62 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_147a_e02d.evmap @@ -0,0 +1,15 @@ + KEY_M = KEY_MUTE + KEY_R = KEY_VOLUMEDOWN # -/-- key + KEY_S = KEY_VOLUMEUP # A/B key + KEY_F5 = KEY_RECORD # KEY_RED + KEY_F6 = KEY_PREVIOUS # KEY_GREEN + KEY_F7 = KEY_NEXT # KEY_YELLOW + KEY_F8 = KEY_BLUE + KEY_E = KEY_PROGRAM + KEY_F = KEY_EXIT + KEY_I = KEY_INFO + KEY_F9 = KEY_TV + KEY_F2 = KEY_MENU + KEY_T = KEY_TEXT + KEY_P = KEY_PAUSE + KEY_V = KEY_ZOOM # EXT diff --git a/packages/sysutils/eventlircd/evmap/03_18b1_0037.evmap b/packages/sysutils/eventlircd/evmap/03_18b1_0037.evmap new file mode 100644 index 000000000..f97c6130c --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_18b1_0037.evmap @@ -0,0 +1,24 @@ +# Remote 18b1:0037 Petalynx Maxter + + KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev + KEY_NEXTSONG = KEY_NEXT # Next + + KEY_NEXT = KEY_MENU + + KEY_PROGRAM = KEY_HOME + + KEY_PLAYPAUSE = KEY_PLAY # Play/Pause + KEY_STOPCD = KEY_STOP # Stop + + KEY_PAGEUP = KEY_CHANNELUP # CH/PG up + KEY_PAGEDOWN = KEY_CHANNELDOWN # CH/PG down + + KEY_PVR = KEY_TV # PVR + + KEY_OK = KEY_ENTER # Ok + KEY_EXIT = KEY_EXIT # BACK + + KEY_SLEEP = KEY_POWER # Power + KEY_ESC = KEY_ESC # Escape + KEY_BACK = KEY_EXIT # Back + diff --git a/packages/sysutils/eventlircd/evmap/03_1d57_ac01.evmap b/packages/sysutils/eventlircd/evmap/03_1d57_ac01.evmap new file mode 100644 index 000000000..eb8ec8373 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/03_1d57_ac01.evmap @@ -0,0 +1,27 @@ +# 1d57:ac01 MS-Tech + + shift+KEY_8 = KEY_NUMERIC_STAR # * + shift+KEY_3 = KEY_NUMERIC_POUND # # + + KEY_PAGEUP = KEY_CHANNELUP # CH/PG up + KEY_PAGEDOWN = KEY_CHANNELDOWN # CH/PG down + ctrl+KEY_F = KEY_NEXT # Next + ctrl+KEY_B = KEY_PREVIOUS # Prev + + alt+KEY_F4 = KEY_EXIT # Exit + KEY_BACKSPACE = KEY_EXIT # Back + + KEY_COMPOSE = KEY_INFO # Info + ctrl+KEY_R = KEY_RECORD # Record + ctrl+KEY_P = KEY_PAUSE # Pause + ctrl+shift+KEY_S = KEY_STOP # Stop + ctrl+shift+KEY_B = KEY_REWIND # Rev + ctrl+shift+KEY_P = KEY_PLAY # Play + ctrl+shift+KEY_F = KEY_FASTFORWARD # Fwd + + ctrl+shift+KEY_M = KEY_DVD # DVD + ctrl+shift+KEY_A = KEY_AUDIO # Audio + ctrl+shift+KEY_T = KEY_TUNER # LiveTV + ctrl+KEY_U = KEY_SUBTITLE # Subtitles + ctrl+KEY_G = KEY_EPG # Guide # remapped to EPG (Contextmenu) + alt+KEY_ENTER = KEY_MEDIA # Media/Switch Windows diff --git a/packages/sysutils/eventlircd/evmap/aboxwireless.evmap b/packages/sysutils/eventlircd/evmap/aboxwireless.evmap new file mode 100644 index 000000000..4e049af6e --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/aboxwireless.evmap @@ -0,0 +1,6 @@ +KEY_POWER = KEY_TITLE +KEY_MUTE = KEY_MUTE +KEY_HOMEPAGE = KEY_HOME +KEY_BACK = KEY_EXIT +KEY_COMPOSE = KEY_CONTEXT_MENU +KEY_SEARCH = KEY_PLAYPAUSE diff --git a/packages/sysutils/eventlircd/evmap/aftvsremote.evmap b/packages/sysutils/eventlircd/evmap/aftvsremote.evmap new file mode 100644 index 000000000..917781622 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/aftvsremote.evmap @@ -0,0 +1,11 @@ +KEY_KPENTER = KEY_OK +KEY_UP = KEY_UP +KEY_LEFT = KEY_LEFT +KEY_RIGHT = KEY_RIGHT +KEY_DOWN = KEY_DOWN +KEY_MENU = KEY_TITLE +KEY_BACK = KEY_BACK +KEY_PLAYPAUSE = KEY_PLAY +KEY_REWIND = KEY_REWIND +KEY_HOMEPAGE = KEY_HOME +KEY_FASTFORWARD = KEY_FASTFORWARD diff --git a/packages/sysutils/eventlircd/evmap/bdremoteng.evmap b/packages/sysutils/eventlircd/evmap/bdremoteng.evmap new file mode 100644 index 000000000..9a4cc1785 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/bdremoteng.evmap @@ -0,0 +1,7 @@ +BTN_A = KEY_F1 +BTN_B = KEY_F2 +BTN_C = KEY_F3 +BTN_X = KEY_F4 +BNT_Y = KEY_F5 +BTN_Z = KEY_F6 +BTN_START = KEY_ENTER diff --git a/packages/sysutils/eventlircd/evmap/cypress.evmap b/packages/sysutils/eventlircd/evmap/cypress.evmap new file mode 100644 index 000000000..86f5fb7ae --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/cypress.evmap @@ -0,0 +1,40 @@ +# Cypress Receiver support +# Bus=0003 Vendor=04b4 Product=0101 Version=0100 +# N: Name="Cypress Cypress USB Keyboard / PS2 Mouse" +# Bus=0003 Vendor=04b4 Product=0100 Version=0001 +# N: Name="Cyp Se WitheHome" + + alt+meta+KEY_ENTER = KEY_MEDIA # Start Key + ctrl+shift+KEY_P = KEY_PLAY # Play + ctrl+KEY_R = KEY_RECORD # Record + ctrl+KEY_P = KEY_PAUSE # Pause + ctrl+KEY_S = KEY_STOP # Stop + ctrl+shift+KEY_S = KEY_STOP # Stop + + ctrl+shift+KEY_F = KEY_FASTFORWARD # Forward + ctrl+shift+KEY_B = KEY_REWIND # Reverse + ctrl+shift+KEY_R = KEY_MEDIA_REPEAT # Repeat + ctrl+KEY_F = KEY_NEXT # Next track + ctrl+KEY_B = KEY_PREVIOUS # Pre-track + KEY_PAGEDOWN = KEY_CHANNELDOWN # Channel Up + KEY_PAGEUP = KEY_CHANNELUP # Channel Down + + KEY_KPASTERISK = KEY_NUMERIC_STAR # * + shift+KEY_3 = KEY_NUMERIC_POUND # # + + KEY_BACKSPACE = KEY_EXIT # Back + + ctrl+KEY_V = KEY_MENU # Menu + ctrl+shift+KEY_M = KEY_MENU # Menu + KEY_COMPOSE = KEY_INFO # Information (also used for Mouse Right) + KEY_F1 = KEY_EPG # Guide (also contextmenu) + alt+KEY_ENTER = KEY_ZOOM # Zoom + + ctrl+KEY_E = KEY_VIDEO # My Videos + ctrl+KEY_M = KEY_AUDIO # My Music + ctrl+KEY_I = KEY_CAMERA # My Pictures + ctrl+KEY_T = KEY_TV # My TV + ctrl+shift+KEY_T = KEY_TV # My TV + ctrl+KEY_A = KEY_RADIO # Radio + ctrl+KEY_O = KEY_TUNER # Record TV + ctrl+KEY_N = KEY_DVD # DVD diff --git a/packages/sysutils/eventlircd/evmap/default.evmap b/packages/sysutils/eventlircd/evmap/default.evmap new file mode 100644 index 000000000..1e502ed1d --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/default.evmap @@ -0,0 +1 @@ +# nothing to remap \ No newline at end of file diff --git a/packages/sysutils/eventlircd/evmap/mcekbd.evmap b/packages/sysutils/eventlircd/evmap/mcekbd.evmap new file mode 100644 index 000000000..c453edacb --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/mcekbd.evmap @@ -0,0 +1,28 @@ +alt+meta+KEY_ENTER = KEY_MENU +KEY_BACKSPACE = KEY_BACK +KEY_EQUAL = KEY_CHANNELUP +ctrl+KEY_EQUAL = KEY_CHANNELUP +KEY_MINUS = KEY_CHANNELDOWN +ctrl+KEY_MINUS = KEY_CHANNELDOWN +ctrl+shift+KEY_T = KEY_TV +ctrl+KEY_M = KEY_MP3 +ctrl+KEY_E = KEY_VIDEO +ctrl+KEY_I = KEY_MEDIA +ctrl+KEY_G = KEY_PROGRAM +ctrl+KEY_R = KEY_RECORD +ctrl+KEY_D = KEY_MENU +ctrl+shift+KEY_M = KEY_DVD +ctrl+KEY_O = KEY_VCR +ctrl+KEY_A = KEY_RADIO +ctrl+KEY_U = KEY_SUBTITLE +ctrl+KEY_P = KEY_PAUSE +ctrl+shift+KEY_P = KEY_PLAY +ctrl+shift+KEY_S = KEY_STOP +ctrl+KEY_B = KEY_PREVIOUS +ctrl+KEY_F = KEY_NEXT +ctrl+shift+KEY_B = KEY_REWIND +ctrl+shift+KEY_F = KEY_FORWARD +KEY_F8 = KEY_MUTE +KEY_F9 = KEY_VOLUMEDOWN +KEY_F10 = KEY_VOLUMEUP +ctrl+shift+KEY_C = KEY_TEXT diff --git a/packages/sysutils/eventlircd/evmap/osmc_rf.evmap b/packages/sysutils/eventlircd/evmap/osmc_rf.evmap new file mode 100644 index 000000000..6f179cf33 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/osmc_rf.evmap @@ -0,0 +1,13 @@ +#KEY_HOME = KEY_HOME +#KEY_INFO = KEY_INFO +#KEY_UP = KEY_UP +#KEY_DOWN = KEY_DOWN +#KEY_LEFT = KEY_LEFT +#KEY_RIGHT = KEY_RIGHT +KEY_ENTER = KEY_OK +#KEY_BACK = KEY_BACK +#KEY_CONTEXT_MENU = KEY_CONTEXT_MENU +#KEY_PLAYPAUSE = KEY_PLAYPAUSE +#KEY_STOP = KEY_STOP +#KEY_REWIND = KEY_REWIND +#KEY_FASTFORWARD = KEY_FASTFORWARD diff --git a/packages/sysutils/eventlircd/evmap/osmc_rf2.evmap b/packages/sysutils/eventlircd/evmap/osmc_rf2.evmap new file mode 100644 index 000000000..6881826b9 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/osmc_rf2.evmap @@ -0,0 +1,13 @@ +#KEY_HOME = KEY_HOME +KEY_I = KEY_INFO +#KEY_UP = KEY_UP +#KEY_DOWN = KEY_DOWN +#KEY_LEFT = KEY_LEFT +#KEY_RIGHT = KEY_RIGHT +KEY_ENTER = KEY_OK +#KEY_BACK = KEY_BACK +KEY_C = KEY_CONTEXT_MENU +#KEY_PLAYPAUSE = KEY_PLAYPAUSE +#KEY_STOP = KEY_STOP +KEY_MINUS = KEY_VOLUMEDOWN +KEY_EQUAL = KEY_VOLUMEUP diff --git a/packages/sysutils/eventlircd/evmap/ps3remote.evmap b/packages/sysutils/eventlircd/evmap/ps3remote.evmap new file mode 100644 index 000000000..bc391f5e8 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/ps3remote.evmap @@ -0,0 +1,29 @@ +# PS3 Bluetooth remote + +KEY_EJECTCD = KEY_EJECT # Eject + +KEY_AUDIO = KEY_LANGUAGE # Audio +KEY_ANGLE = KEY_ZOOM # Angle +KEY_CLEAR = KEY_DELETE # Clear + +KEY_CONTEXT_MENU = KEY_EPG # Pop UP/MENU +KEY_ESC = KEY_EXIT # Return + +KEY_BACK = KEY_EXIT # Back +KEY_OPTION = KEY_OPTION # Options +KEY_SCREEN = KEY_SCREEN # View +BTN_0 = KEY_EXIT # X + +BTN_TL = KEY_VOLUMEUP # L1 -> Volume Upn +BTN_TL2 = KEY_VOLUMEDOWN # L2 -> Volume down +BTN_THUMBL = KEY_MUTE # L3 -> Mute + +KEY_HOMEPAGE = KEY_MEDIA # PS3 Menu +KEY_SELECT = KEY_RECORD # Select +BTN_START = KEY_ENTER # Start + +BTN_TR = KEY_CHANNELUP # R1 -> Channel Up +BTN_TR2 = KEY_CHANNELDOWN # R2 -> Channel down +BTN_THUMBR = KEY_PREVIOUS # R3 -> Previous Channel + +KEY_FORWARD = KEY_FASTFORWARD # Forward diff --git a/packages/sysutils/eventlircd/evmap/spinelplus.evmap b/packages/sysutils/eventlircd/evmap/spinelplus.evmap new file mode 100644 index 000000000..de59d094e --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/spinelplus.evmap @@ -0,0 +1,19 @@ +# 0471:0613 PHILIPS MCE USB IR Receiver- Spinel plus +# 0471:206c PHILIPS MCE USB IR Receiver- Spinel plus +# 0471:20cc PHILIPS MCE USB IR Receiver- Spinel plus + +shift+KEY_8 = KEY_NUMERIC_STAR # * +shift+KEY_3 = KEY_NUMERIC_POUND # # + +KEY_SLEEP = KEY_POWER # Sleep # remapped to Power +KEY_WAKEUP = KEY_POWER # WakeUp # remapped to Power +KEY_STOPCD = KEY_STOP # Stop +KEY_PLAYPAUSE = KEY_PLAY # Play/Pause +KEY_PREVIOUSSONG = KEY_PREVIOUS # Prev +KEY_NEXTSONG = KEY_NEXT # Next +KEY_BACK = KEY_EXIT # BACK +KEY_PROPS = KEY_INFO # Info/EPG +KEY_PROGRAM = KEY_EPG # Program # remapped to EPG (Contextmenu) +KEY_ESC = KEY_DELETE # Delete/Clear +KEY_HOME = KEY_DELETE # Delete/Clear +KEY_MP3 = KEY_AUDIO # Music diff --git a/packages/sysutils/eventlircd/evmap/tevii_s660.evmap b/packages/sysutils/eventlircd/evmap/tevii_s660.evmap new file mode 100644 index 000000000..35bc514b5 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/tevii_s660.evmap @@ -0,0 +1,26 @@ +# TiVii S660 Remote +# Bus=0003 Vendor=9022 Product=d660 Version=0000 + + KEY_OK = KEY_ENTER # Ok + KEY_F5 = KEY_ENTER # Enter + + KEY_PLAYPAUSE = KEY_PLAY # Play/Pause + KEY_EPG = KEY_STOP # remap EPG to STOP, because there is no STOP button + KEY_OPEN = KEY_NEXT # Next + KEY_TIME = KEY_PREVIOUS # Prev + + KEY_F6 = KEY_MEDIA # HOME + KEY_AUDIO = KEY_NUMERIC_POUND # Audio + KEY_SUBTITLE = KEY_NUMERIC_STAR # Subtitle + + KEY_MENU = KEY_EXIT # Menu + KEY_BACK = KEY_DELETE # Back + + KEY_SWITCHVIDEOMODE = KEY_ZOOM # Switch Video Mode (Zoom) + + KEY_F1 = KEY_VIDEO # Videos + KEY_F2 = KEY_AUDIO # Music + KEY_F3 = KEY_RADIO # Radio + KEY_F4 = KEY_CAMERA # Pictures + KEY_TUNER = KEY_TV # Live + KEY_PVR = KEY_EPG # Play (EPG/PVR) diff --git a/packages/sysutils/eventlircd/evmap/topseed.evmap b/packages/sysutils/eventlircd/evmap/topseed.evmap new file mode 100644 index 000000000..244a1296b --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/topseed.evmap @@ -0,0 +1,25 @@ +# Emprex BTX remote control +# 046e:5577 BTC Emprex 2 +# 046e:5578 BTC Emprex +# 04f2:0618 Chicony Wireless +# 0766:0204 Topseed Cyberlink +# 1784:0004 Topseed 2 RF Combo + + shift+KEY_8 = KEY_NUMERIC_STAR # * + shift+KEY_3 = KEY_NUMERIC_POUND # # + + KEY_BACK = KEY_EXIT # BACK + KEY_ESC = KEY_DELETE # Delete/Clear + + KEY_SLEEP = KEY_POWER # Power + + KEY_STOPCD = KEY_STOP # Stop + KEY_NEXTSONG = KEY_NEXT # Next + + KEY_MP3 = KEY_AUDIO # Music + KEY_RADIO = KEY_ZOOM # Radio # Remap because we need the zoom key + KEY_TV2 = KEY_EPG # EPG + + KEY_PROGRAM = KEY_SUBTITLE # Program # remapped to Subtitle + + KEY_PROPS = KEY_INFO # Info/EPG diff --git a/packages/sysutils/eventlircd/evmap/wiimote.evmap b/packages/sysutils/eventlircd/evmap/wiimote.evmap new file mode 100644 index 000000000..16d199968 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/wiimote.evmap @@ -0,0 +1,9 @@ +BTN_A = KEY_ENTER # Ok +BTN_B = KEY_EXIT # Back/Exit + +KEY_PREVIOUS = KEY_VOLUMEDOWN # Vol- +KEY_NEXT = KEY_VOLUMEUP # Vol+ + +BTN_MODE = KEY_MEDIA # Home +BTN_1 = KEY_CHANNELUP # Channel Up +BTN_2 = KEY_CHANNELDOWN # Channel Down diff --git a/packages/sysutils/eventlircd/evmap/xiaomibtremote.evmap b/packages/sysutils/eventlircd/evmap/xiaomibtremote.evmap new file mode 100644 index 000000000..807ff6155 --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/xiaomibtremote.evmap @@ -0,0 +1,4 @@ +KEY_POWER = KEY_MUTE +KEY_F5 = KEY_PLAYPAUSE +KEY_HOME = KEY_CONTEXT_MENU +KEY_BACK = KEY_EXIT diff --git a/packages/sysutils/eventlircd/evmap/xiaomibtremoteAM.evmap b/packages/sysutils/eventlircd/evmap/xiaomibtremoteAM.evmap new file mode 100644 index 000000000..eec64bd1f --- /dev/null +++ b/packages/sysutils/eventlircd/evmap/xiaomibtremoteAM.evmap @@ -0,0 +1,4 @@ +KEY_POWER = KEY_MUTE +KEY_COMPOSE = KEY_PLAYPAUSE +KEY_BACK = KEY_EXIT +KEY_HOME = KEY_CONTEXT_MENU diff --git a/packages/sysutils/eventlircd/package.mk b/packages/sysutils/eventlircd/package.mk new file mode 100644 index 000000000..188d11b18 --- /dev/null +++ b/packages/sysutils/eventlircd/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="eventlircd" +PKG_VERSION="3b753e9" +PKG_SHA256="4eca52d0570fa568b3296a2c9bc2af252423e25c1a67654bd79680fc5a93092a" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/LibreELEC/eventlircd" +PKG_URL="https://github.com/LibreELEC/eventlircd/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd lirc" +PKG_LONGDESC="The eventlircd daemon provides four functions for LIRC devices" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--with-udev-dir=/usr/lib/udev \ + --with-lircd-socket=/run/lirc/lircd" + +post_makeinstall_target() { +# install our own evmap files and udev rules + rm -rf $INSTALL/etc/eventlircd.d + rm -rf $INSTALL/usr/lib/udev/rules.d + rm -rf $INSTALL/usr/lib/udev/lircd_helper + + mkdir -p $INSTALL/etc/eventlircd.d + cp $PKG_DIR/evmap/*.evmap $INSTALL/etc/eventlircd.d +} + +post_install() { + enable_service eventlircd.service +} diff --git a/packages/sysutils/eventlircd/system.d/eventlircd.service b/packages/sysutils/eventlircd/system.d/eventlircd.service new file mode 100644 index 000000000..15b607831 --- /dev/null +++ b/packages/sysutils/eventlircd/system.d/eventlircd.service @@ -0,0 +1,11 @@ +[Unit] +Description=Eventlirc server daemon + +[Service] +ExecStart=/usr/sbin/eventlircd -f --evmap=/etc/eventlircd.d --socket=/run/lirc/lircd +KillMode=process +TimeoutStopSec=1s + +[Install] +WantedBy=multi-user.target + diff --git a/packages/sysutils/eventlircd/tmpfiles.d/z_62_eventlircd.conf b/packages/sysutils/eventlircd/tmpfiles.d/z_62_eventlircd.conf new file mode 100644 index 000000000..be3a0035d --- /dev/null +++ b/packages/sysutils/eventlircd/tmpfiles.d/z_62_eventlircd.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /run/lirc 0755 root root - - diff --git a/packages/sysutils/eventlircd/udev.d/98-eventlircd.rules b/packages/sysutils/eventlircd/udev.d/98-eventlircd.rules new file mode 100644 index 000000000..d0861ca03 --- /dev/null +++ b/packages/sysutils/eventlircd/udev.d/98-eventlircd.rules @@ -0,0 +1,240 @@ +################################################################################ +# An example udev rules file for eventlircd. +# +# This rules file does not start eventlircd. Many applications only check for +# the lircd socket at application lauch. Therefore, it is better to start +# eventlircd in an init script so that eventlircd creates the lircd socket +# before any applications that use LIRC launch. +################################################################################ + +# eventlircd only does something for "add" and "remove" actions. +ACTION!="add|remove", GOTO="end" + +# eventlircd only does something "input" subsystem devices. +SUBSYSTEM!="input", GOTO="end" + +# eventlircd can only handle event devices. +KERNEL!="event[0-9]*", GOTO="end" + +# eventlircd ignores devices created by eventlircd. +ATTRS{name}=="eventlircd", GOTO="end" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle input event devices created by lircd. For this to +# work, lircd must be configured to output Linux input events and must be +# configured to output key names that conform to the LIRC namespace derived from +# the Linux key/button event names. This rule assumes that lircd performs all +# key mappings, so the rule does not provide a value for "eventlircd_evmap". +# For more information on lircd, see . +#------------------------------------------------------------------------------- +ATTRS{name}=="lircd", \ + ENV{eventlircd_enable}="true" + +ATTRS{name}=="lircd-uinput", \ + ENV{eventlircd_enable}="true" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle input event devices created by bdremoteng. For this +# to work, bdremoteng must be configured to output Linux input events and must +# be configured to output key names that conform to LIRC namespace derived +# from the Linux key/button event names. For more information on bdremoteng, +# see . +#------------------------------------------------------------------------------- +ATTRS{name}=="bdremoteng", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="bdremoteng.evmap" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle input event devices created by wminput. This rule +# assumes that wminput performs all key mappings, so the rule does not provide a +# value for "eventlircd_evmap" For more information on wminput, see +# . +#------------------------------------------------------------------------------- +ATTRS{name}=="bdremoteng", \ + ENV{eventlircd_enable}="true" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle input event devices created by ir-core (kernel). +#------------------------------------------------------------------------------- +SUBSYSTEMS=="rc", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="default.evmap" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle input event devices. +#------------------------------------------------------------------------------- + +# Xiaomi Mi Box USA remote +SUBSYSTEMS=="input", ATTRS{name}=="Xiaomi Remote", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="xiaomibtremote.evmap" + +# Xiaomi Mi Box aftermarket remote +SUBSYSTEMS=="input", ATTRS{name}=="å°ç±³è“牙é¥æŽ§å™¨", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="xiaomibtremoteAM.evmap" + + # iMON Ultrabay Front Panel +SUBSYSTEMS=="input", ATTRS{name}=="iMON Panel, Knob and Mouse(15c2:ffdc)", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="default.evmap" + +# ABOX Wireless Remote +SUBSYSTEMS=="input", ATTRS{name}=="Hotack_RC", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="aboxwireless.evmap" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle USB HID devices that show up as event devices and are +# known to be remote controls. For simplicity, the event map file names have the +# format __.evmap. +#------------------------------------------------------------------------------- +SUBSYSTEMS=="usb", GOTO="begin-usb" +GOTO="end-usb" +LABEL="begin-usb" + +ENV{ID_USB_INTERFACES}=="", IMPORT{builtin}="usb_id" + +ENV{ID_VENDOR_ID}=="0bc7", ENV{ID_MODEL_ID}=="0006", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="0419", ENV{ID_MODEL_ID}=="0001", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="046d", ENV{ID_MODEL_ID}=="c101", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="046e", ENV{ID_MODEL_ID}=="5577", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="topseed.evmap" + +ENV{ID_VENDOR_ID}=="046e", ENV{ID_MODEL_ID}=="5578", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="topseed.evmap" + +ENV{ID_VENDOR_ID}=="04b4", ENV{ID_MODEL_ID}=="0100", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="cypress.evmap" + +ENV{ID_VENDOR_ID}=="04b4", ENV{ID_MODEL_ID}=="0101", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="cypress.evmap" + +ENV{ID_VENDOR_ID}=="04f2", ENV{ID_MODEL_ID}=="0618", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="topseed.evmap" + +ENV{ID_VENDOR_ID}=="0766", ENV{ID_MODEL_ID}=="0204", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="topseed.evmap" + +ENV{ID_VENDOR_ID}=="1784", ENV{ID_MODEL_ID}=="0004", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="topseed.evmap" + +ENV{ID_VENDOR_ID}=="03eb", ENV{ID_MODEL_ID}=="0002", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="05a4", ENV{ID_MODEL_ID}=="9881", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +# ENV{ID_VENDOR_ID}=="05ac", ENV{ID_MODEL_ID}=="8241", \ +# ENV{eventlircd_enable}="true", \ +# ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="0709", ENV{ID_MODEL_ID}=="9137", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="0755", ENV{ID_MODEL_ID}=="2626", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="1241", ENV{ID_MODEL_ID}=="e000", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="13ec", ENV{ID_MODEL_ID}=="0006", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="147a", ENV{ID_MODEL_ID}=="e02d", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="18b1", ENV{ID_MODEL_ID}=="0037", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +ENV{ID_VENDOR_ID}=="1d57", ENV{ID_MODEL_ID}=="ac01", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="03_$env{ID_VENDOR_ID}_$env{ID_MODEL_ID}.evmap" + +#ENV{ID_VENDOR_ID}=="9022", ENV{ID_MODEL_ID}=="d660", \ +ATTRS{idVendor}=="9022", ATTRS{idProduct}=="d660", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="tevii_s660.evmap" + +ENV{ID_VENDOR_ID}=="0471", ENV{ID_MODEL_ID}=="0613", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="spinelplus.evmap" + +ENV{ID_VENDOR_ID}=="0471", ENV{ID_MODEL_ID}=="206c", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="spinelplus.evmap" + +ENV{ID_VENDOR_ID}=="0471", ENV{ID_MODEL_ID}=="20cc", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="spinelplus.evmap" + +ENV{ID_VENDOR_ID}=="2252", ENV{ID_MODEL_ID}=="1037", \ +ENV{eventlircd_enable}="true", \ +ENV{eventlircd_evmap}="osmc_rf.evmap" + +ENV{ID_VENDOR_ID}=="2017", ENV{ID_MODEL_ID}=="1688", \ +ENV{eventlircd_enable}="true", \ +ENV{eventlircd_evmap}="osmc_rf2.evmap" + +# Enable wake-on-usb for the USB remotes. + RUN+="wakeup_enable" + +LABEL="end-usb" + +#------------------------------------------------------------------------------- +# Ask eventlircd to handle Bluetooth HID devices that show up as event devices +# and are known to be remote controls. For simplicity, the event map file names +# have the format __.evmap. +#------------------------------------------------------------------------------- +SUBSYSTEMS=="bluetooth", GOTO="begin-bluetooth" +GOTO="end-bluetooth" +LABEL="begin-bluetooth" + +ATTRS{name}=="Nintendo Wii Remote", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="wiimote.evmap" + +ATTRS{name}=="BD Remote Control", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="ps3remote.evmap" + +#PS3 BD Remote Version 2 (Bluetooth AND infrared 3 in 1 remote) +ATTRS{name}=="Sony Computer Entertainment Inc BD Remote Control", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="ps3remote.evmap" + +# Amazon Fire TV stick remote +ATTRS{name}=="Amazon Fire TV Remote", \ + ENV{eventlircd_enable}="true", \ + ENV{eventlircd_evmap}="aftvsremote.evmap" + +LABEL="end-bluetooth" + +# tell libinput to ignore devices handled by eventlircd +ENV{eventlircd_enable}=="true", ENV{LIBINPUT_IGNORE_DEVICE}="1" + +LABEL="end" diff --git a/packages/sysutils/evtest/package.mk b/packages/sysutils/evtest/package.mk new file mode 100644 index 000000000..50545ec89 --- /dev/null +++ b/packages/sysutils/evtest/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="evtest" +PKG_VERSION="1.33" +PKG_SHA256="5037d1162f4c407053cd97e85763ba03150a0c35f929ee9bf9a360abd32ef1c1" +PKG_LICENSE="GPL" +PKG_SITE="http://cgit.freedesktop.org/evtest/" +PKG_URL="http://cgit.freedesktop.org/evtest/snapshot/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libxml2" +PKG_LONGDESC="A simple tool for input event debugging." +PKG_TOOLCHAIN="autotools" + +#makeinstall_target() { +# : # nop +#} diff --git a/packages/sysutils/exfat/package.mk b/packages/sysutils/exfat/package.mk new file mode 100644 index 000000000..978881beb --- /dev/null +++ b/packages/sysutils/exfat/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="exfat" +PKG_VERSION="66747e2df0771b23ea30cbef3767f2b72488e914" +PKG_SHA256="c83fedc3deaefde0d9549deb73ffc4b610d29ff23d39e5628114f67d267d0e82" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/relan/exfat" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_INIT="toolchain exfat" +PKG_LONGDESC="This project aims to provide a full-featured exFAT file system implementation for GNU/Linux other Unix-like systems as a FUSE module." +PKG_TOOLCHAIN="autotools" + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + mkdir -p $INSTALL/usr/sbin + cp ../.install_pkg/usr/sbin/exfatfsck $INSTALL/usr/sbin + ln -sf exfatfsck $INSTALL/usr/sbin/fsck.exfat +} diff --git a/packages/sysutils/exfat/patches/01-no-fuse.patch b/packages/sysutils/exfat/patches/01-no-fuse.patch new file mode 100644 index 000000000..fa2b3cd06 --- /dev/null +++ b/packages/sysutils/exfat/patches/01-no-fuse.patch @@ -0,0 +1,119 @@ +diff -rupN exfat.orig/configure.ac exfat.new/configure.ac +--- exfat.orig/configure.ac 2021-01-04 18:18:34.766169964 -0500 ++++ exfat.new/configure.ac 2021-01-04 18:20:48.674744092 -0500 +@@ -38,7 +38,6 @@ PKG_CHECK_MODULES([UBLIO], [libublio], [ + AC_DEFINE([USE_UBLIO], [1], + [Define if block devices are not supported.]) + ], [:]) +-PKG_CHECK_MODULES([FUSE], [fuse]) + case "$host_os" in + *-gnu) + AC_DEFINE([_XOPEN_SOURCE], [500], [Enable pread() and pwrite().]) +@@ -50,7 +49,6 @@ AC_CONFIG_FILES([ + libexfat/Makefile + dump/Makefile + fsck/Makefile +- fuse/Makefile + label/Makefile + mkfs/Makefile + Makefile]) +diff -rupN exfat.orig/configure.ac.orig exfat.new/configure.ac.orig +--- exfat.orig/configure.ac.orig 1969-12-31 19:00:00.000000000 -0500 ++++ exfat.new/configure.ac.orig 2021-01-04 18:19:10.778324347 -0500 +@@ -0,0 +1,57 @@ ++# ++# configure.ac (30.03.15) ++# Autoconf source. ++# ++# Free exFAT implementation. ++# Copyright (C) 2010-2018 Andrew Nayenko ++# ++# This program 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 2 of the License, or ++# (at your option) any later version. ++# ++# This program 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 this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++AC_INIT([Free exFAT implementation], ++ [1.3.0], ++ [relan@users.noreply.github.com], ++ [exfat], ++ [https://github.com/relan/exfat]) ++AM_INIT_AUTOMAKE([1.11.2 -Wall -Werror foreign subdir-objects]) ++AC_PROG_CC ++AC_PROG_CC_C99 ++AC_PROG_RANLIB ++AM_PROG_AR ++AC_SYS_LARGEFILE ++AC_CANONICAL_HOST ++PKG_CHECK_MODULES([UBLIO], [libublio], [ ++ CFLAGS="$CFLAGS $UBLIO_CFLAGS" ++ LIBS="$LIBS $UBLIO_LIBS" ++ AC_DEFINE([USE_UBLIO], [1], ++ [Define if block devices are not supported.]) ++], [:]) ++PKG_CHECK_MODULES([FUSE], [fuse]) ++case "$host_os" in ++ *-gnu) ++ AC_DEFINE([_XOPEN_SOURCE], [500], [Enable pread() and pwrite().]) ++ AC_DEFINE([_DEFAULT_SOURCE], [], [Enable vsyslog().]) ++ ;; ++esac ++AC_CONFIG_HEADERS([libexfat/config.h]) ++AC_CONFIG_FILES([ ++ libexfat/Makefile ++ dump/Makefile ++ fsck/Makefile ++ fuse/Makefile ++ label/Makefile ++ mkfs/Makefile ++ Makefile]) ++AC_OUTPUT +diff -rupN exfat.orig/Makefile.am exfat.new/Makefile.am +--- exfat.orig/Makefile.am 2021-01-04 18:18:34.766169964 -0500 ++++ exfat.new/Makefile.am 2021-01-04 18:19:10.778324347 -0500 +@@ -20,4 +20,4 @@ + # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + # + +-SUBDIRS = libexfat dump fsck fuse label mkfs ++SUBDIRS = libexfat dump fsck label mkfs +diff -rupN exfat.orig/patch exfat.new/patch +--- exfat.orig/patch 1969-12-31 19:00:00.000000000 -0500 ++++ exfat.new/patch 2021-01-04 18:18:55.522258946 -0500 +@@ -0,0 +1,26 @@ ++diff --git configure.ac configure.ac ++--- configure.ac 2018-09-15 07:03:24.000000000 +0200 +++++ configure.ac 2019-10-28 18:02:19.792588993 +0100 ++@@ -37,13 +37,11 @@ ++ AC_DEFINE([USE_UBLIO], [1], ++ [Define if block devices are not supported.]) ++ ], [:]) ++-PKG_CHECK_MODULES([FUSE], [fuse]) ++ AC_CONFIG_HEADERS([libexfat/config.h]) ++ AC_CONFIG_FILES([ ++ libexfat/Makefile ++ dump/Makefile ++ fsck/Makefile ++- fuse/Makefile ++ label/Makefile ++ mkfs/Makefile ++ Makefile]) ++diff --git Makefile.am Makefile.am ++--- Makefile.am 2018-09-15 07:03:24.000000000 +0200 +++++ Makefile.am 2019-10-28 18:02:19.785922319 +0100 ++@@ -20,4 +20,4 @@ ++ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ # ++ ++-SUBDIRS = libexfat dump fsck fuse label mkfs +++SUBDIRS = libexfat dump fsck label mkfs diff --git a/packages/sysutils/exfatprogs/package.mk b/packages/sysutils/exfatprogs/package.mk new file mode 100644 index 000000000..09de2f261 --- /dev/null +++ b/packages/sysutils/exfatprogs/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="exfatprogs" +PKG_VERSION="7c3b61769bb04eaafedf245db396813bbcfb2b0a" +PKG_SHA256="17f8ca2b3729a82b2afa8e6f50f3506e61d691763365d0da477c88642787e5cf" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/exfatprogs/exfatprogs" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_LONGDESC="Userspace utilities for exfat" +PKG_TOOLCHAIN="autotools" diff --git a/packages/sysutils/fdupes/package.mk b/packages/sysutils/fdupes/package.mk new file mode 100644 index 000000000..95694166c --- /dev/null +++ b/packages/sysutils/fdupes/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fdupes" +PKG_VERSION="1.6.1" +PKG_SHA256="9d6b6fdb0b8419815b4df3bdfd0aebc135b8276c90bbbe78ebe6af0b88ba49ea" +PKG_LICENSE="GPL" +PKG_SITE="http://premium.caribe.net/~adrian2/fdupes.html" +PKG_URL="https://github.com/adrianlopezroche/fdupes/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A program for identifying or deleting duplicate files residing within specified directories." + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/file/package.mk b/packages/sysutils/file/package.mk new file mode 100644 index 000000000..56ca36825 --- /dev/null +++ b/packages/sysutils/file/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="file" +PKG_VERSION="d1ff3af7a2c6b38bdbdde7af26b59e3c50a48fff" +PKG_SHA256="acc16f878576ad0bb29bbb7c724e29d2827f14ddb39fe94d76c3a859d4a3d0d9" +PKG_LICENSE="BSD" +PKG_SITE="http://www.darwinsys.com/file/" +PKG_URL="https://github.com/file/file/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_TARGET="toolchain file:host zlib" +PKG_LONGDESC="The file utility is used to determine the types of various files." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_HOST="--enable-fsect-man5 --enable-static --disable-shared" +PKG_CONFIGURE_OPTS_TARGET="--enable-fsect-man5 --enable-static --disable-shared" diff --git a/packages/sysutils/file/patches/file-move-magic.mgc-to-addon-data.patch b/packages/sysutils/file/patches/file-move-magic.mgc-to-addon-data.patch new file mode 100644 index 000000000..d0a72d761 --- /dev/null +++ b/packages/sysutils/file/patches/file-move-magic.mgc-to-addon-data.patch @@ -0,0 +1,25 @@ +From 1191268f518d298c8617a4a74644ee1bb627f614 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Mon, 25 Aug 2014 15:35:14 +0300 +Subject: [PATCH] move magic.mgc to addon/data + +--- + src/magic.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/magic.c b/src/magic.c +index e4bd12b..59c1456 100644 +--- a/src/magic.c ++++ b/src/magic.c +@@ -100,7 +100,7 @@ get_default_magic(void) + if ((home = getenv("HOME")) == NULL) + return MAGIC; + +- if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0) ++ if (asprintf(&hmagicpath, "%s/.kodi/addons/virtual.system-tools/data/magic.mgc", home) < 0) + return MAGIC; + if (stat(hmagicpath, &st) == -1) { + free(hmagicpath); +-- +1.7.2.5 + diff --git a/packages/sysutils/fuse-exfat/package.mk b/packages/sysutils/fuse-exfat/package.mk new file mode 100644 index 000000000..c51855029 --- /dev/null +++ b/packages/sysutils/fuse-exfat/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fuse-exfat" +PKG_VERSION="66747e2df0771b23ea30cbef3767f2b72488e914" +PKG_SHA256="c83fedc3deaefde0d9549deb73ffc4b610d29ff23d39e5628114f67d267d0e82" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/relan/exfat" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain fuse" +PKG_LONGDESC="This project aims to provide a full-featured exFAT file system implementation for GNU/Linux other Unix-like systems as a FUSE module." +PKG_TOOLCHAIN="autotools" diff --git a/packages/sysutils/fuse/package.mk b/packages/sysutils/fuse/package.mk new file mode 100644 index 000000000..c5d417aff --- /dev/null +++ b/packages/sysutils/fuse/package.mk @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="fuse" +PKG_VERSION="2.9.9" +PKG_SHA256="d0e69d5d608cc22ff4843791ad097f554dd32540ddc9bed7638cc6fea7c1b4b5" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/libfuse/libfuse/" +PKG_URL="https://github.com/libfuse/libfuse/releases/download/$PKG_NAME-$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="FUSE provides a simple interface for userspace programs to export a virtual filesystem to the Linux kernel." +# fuse fails to build with GOLD linker on gcc-4.9 +PKG_BUILD_FLAGS="-gold" + +PKG_CONFIGURE_OPTS_TARGET="MOUNT_FUSE_PATH=/usr/sbin \ + --enable-lib \ + --enable-util \ + --disable-example \ + --enable-mtab \ + --disable-rpath \ + --with-gnu-ld" + +post_makeinstall_target() { + rm -rf $INSTALL/etc/init.d + rm -rf $INSTALL/etc/udev +} diff --git a/packages/sysutils/fuse/patches/fuse-0001_aarch64-support.patch b/packages/sysutils/fuse/patches/fuse-0001_aarch64-support.patch new file mode 100644 index 000000000..050d1146a --- /dev/null +++ b/packages/sysutils/fuse/patches/fuse-0001_aarch64-support.patch @@ -0,0 +1,33 @@ +fuse: add aarch64 support + +u64/u32 is not defined in sys/types.h, include linux/types.h like +the kernel version of fuse.h does. Patch sent to upstream mailing list. + +Upstream-Status: Submitted +Signed-off-by: Riku Voipio +Signed-off-by: Hongxu Jia +--- + include/fuse_kernel.h | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h +index c632b58..e804278 100644 +--- a/include/fuse_kernel.h ++++ b/include/fuse_kernel.h +@@ -88,12 +88,7 @@ + #ifndef _LINUX_FUSE_H + #define _LINUX_FUSE_H + +-#include +-#define __u64 uint64_t +-#define __s64 int64_t +-#define __u32 uint32_t +-#define __s32 int32_t +-#define __u16 uint16_t ++#include + + /* + * Version negotiation: +-- +1.8.1.2 + diff --git a/packages/sysutils/fuse/patches/fuse-0002-dont-run-update-rc.d.patch b/packages/sysutils/fuse/patches/fuse-0002-dont-run-update-rc.d.patch new file mode 100644 index 000000000..d89103eca --- /dev/null +++ b/packages/sysutils/fuse/patches/fuse-0002-dont-run-update-rc.d.patch @@ -0,0 +1,13 @@ +--- a/util/Makefile.in 2017-06-23 22:47:36.762827097 +0200 ++++ b/util/Makefile.in 2017-06-23 22:47:47.358852950 +0200 +@@ -734,10 +734,6 @@ + $(INSTALL_PROGRAM) $(builddir)/mount.fuse $(DESTDIR)$(MOUNT_FUSE_PATH)/mount.fuse + $(MKDIR_P) $(DESTDIR)$(INIT_D_PATH) + $(INSTALL_SCRIPT) $(srcdir)/init_script $(DESTDIR)$(INIT_D_PATH)/fuse +- @if test -x /usr/sbin/update-rc.d; then \ +- echo "/usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true"; \ +- /usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true; \ +- fi + + install-data-local: + $(MKDIR_P) $(DESTDIR)$(UDEV_RULES_PATH) diff --git a/packages/sysutils/getscancodes/package.mk b/packages/sysutils/getscancodes/package.mk new file mode 100644 index 000000000..de8e7fc80 --- /dev/null +++ b/packages/sysutils/getscancodes/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="getscancodes" +PKG_VERSION="1.0" +PKG_SHA256="5f4e2ab22dc3890392ab8870fb79bbebdfd39b34dcd5bafcb51edee554855d34" +PKG_LICENSE="GPL" +PKG_SITE="http://keytouch.sourceforge.net" +PKG_URL="$SOURCEFORGE_SRC/keytouch/getscancodes-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Shows the scancode of the pressed or released key." + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="CC=$CC" +} + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/gptfdisk/package.mk b/packages/sysutils/gptfdisk/package.mk new file mode 100644 index 000000000..c23b89d6a --- /dev/null +++ b/packages/sysutils/gptfdisk/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="gptfdisk" +PKG_VERSION="1.0.4" +PKG_SHA256="b663391a6876f19a3cd901d862423a16e2b5ceaa2f4a3b9bb681e64b9c7ba78d" +PKG_LICENSE="GPL" +PKG_SITE="http://www.rodsbooks.com/gdisk/" +PKG_URL="https://downloads.sourceforge.net/project/$PKG_NAME/$PKG_NAME/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain popt crossguid" +PKG_LONGDESC="GPT text-mode partitioning tools" + +make_target() { + make sgdisk "CC=$CC" "CXX=$CXX" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/sbin/ + cp -p sgdisk $INSTALL/usr/sbin/ +} diff --git a/packages/sysutils/grep/package.mk b/packages/sysutils/grep/package.mk new file mode 100644 index 000000000..b9c048edf --- /dev/null +++ b/packages/sysutils/grep/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="grep" +PKG_VERSION="3.7" +PKG_SHA256="5c10da312460aec721984d5d83246d24520ec438dd48d7ab5a05dbc0d6d6823c" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/grep/" +PKG_URL="http://ftpmirror.gnu.org/grep/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="Grep searches one or more input files for lines containing a match to a specified pattern. By default, Grep outputs the matching lines." + +PKG_CONFIGURE_OPTS_HOST="--disable-nls --disable-acl --without-selinux" diff --git a/packages/sysutils/hd-idle/package.mk b/packages/sysutils/hd-idle/package.mk new file mode 100644 index 000000000..b955f7061 --- /dev/null +++ b/packages/sysutils/hd-idle/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hd-idle" +PKG_VERSION="1.05" +PKG_SHA256="4efefe79d145b50e055582730d9d685e485da3df3dad90fef030036d52aa3a0c" +PKG_LICENSE="GPL" +PKG_SITE="http://hd-idle.sourceforge.net/" +PKG_URL="http://downloads.sourceforge.net/project/hd-idle/${PKG_NAME}-${PKG_VERSION}.tgz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A utility for spinning-down external disks after a period of idle time." + +makeinstall_target() { + mkdir -p $INSTALL/usr/sbin + cp -a $PKG_BUILD/hd-idle $INSTALL/usr/sbin +} \ No newline at end of file diff --git a/packages/sysutils/hd-idle/patches/hd-idle-makefile.patch b/packages/sysutils/hd-idle/patches/hd-idle-makefile.patch new file mode 100644 index 000000000..5c23437d5 --- /dev/null +++ b/packages/sysutils/hd-idle/patches/hd-idle-makefile.patch @@ -0,0 +1,15 @@ +diff --git a/Makefile b/Makefile +index 130afd8..480032e 100644 +--- a/Makefile ++++ b/Makefile +@@ -43,8 +43,8 @@ clean: + rm -f $(OBJS) $(TARGET) + + install: $(TARGET) +- install -D -g root -o root $(TARGET) $(TARGET_DIR)/sbin/$(TARGET) +- install -D -g root -o root $(TARGET).1 $(TARGET_DIR)/share/man/man1/$(TARGET).1 ++ install -D $(TARGET) $(TARGET_DIR)/sbin/$(TARGET) ++ install -D $(TARGET).1 $(TARGET_DIR)/share/man/man1/$(TARGET).1 + + hd-idle.o: hd-idle.c + diff --git a/packages/sysutils/hddtemp/db/hddtemp.db b/packages/sysutils/hddtemp/db/hddtemp.db new file mode 100644 index 000000000..4a061cfcb --- /dev/null +++ b/packages/sysutils/hddtemp/db/hddtemp.db @@ -0,0 +1,523 @@ +# +# Insert a regular expression for support of the model or the serie of your hard drive. +# If you don't know what to put in the second field, put the number +# that appears most often for your brand :o) +# A value of zero meens that we know that the drive doesn't have +# a temperature sensor (you can set the unit to C or F). +# +############################################################################ +# The following list was found at (http://www.almico.com/forumharddisks.php) +# If your drive is in the list send me a mail. +# +# Manufacturer Model Size Notes +# FUJITSU FUJITSU MPF3102AH 10.0GB +# FUJITSU FUJITSU MPG3204AH E 20.0GB +# FUJITSU FUJITSU MPG3307AT 30.0GB +# FUJITSU FUJITSU MPG3409AH 40.0GB +# FUJITSU FUJITSU MPG3409AH EF 40.0GB +# HITACHI HITACHI_DK23CA-10 9.8GB +# HITACHI HITACHI_DK23CA-15 14.7GB +# SAMSUNG SAMSUNG SV3012H 29.4GB +# SEAGATE ST310210A 10.0GB +# SEAGATE ST310211A 9.8GB +# SEAGATE ST310215A 10.0GB +# SEAGATE ST315320A 14.9GB +# SEAGATE ST320410A 19.6GB +# SEAGATE ST320413A 19.6GB +# SEAGATE ST320420A 19.9GB +# SEAGATE ST330610A 29.3GB +# SEAGATE ST330620A 29.3GB +# SEAGATE ST330621A 29.3GB +# SEAGATE ST330630A 29.9GB +# SEAGATE ST340016A 39.1GB +# SEAGATE ST340810ACE 39.1GB +# SEAGATE ST380020ACE 78.2GB +# WESTERN DIGITAL WDC AC210200D 10.0GB +# WESTERN DIGITAL WDC AC29100D 8.9GB +# WESTERN DIGITAL WDC AC420400D 19.9GB +# WESTERN DIGITAL WDC WD102AA 10.0GB +# +################################################# + +######################################## +############# ExcelStor drives +######################################## +# "ExcelStor Technology CT215" ??? ? "ExcelStor CT215" +"ExcelStor Technology J3.0" 194 C "ExcelStor Technology 3xy (xy GB)" +"ExcelStor Technology J6.0" 194 C "ExcelStor Technology 6xy (xy GB)" +"ExcelStor Technology J680" 194 C "ExcelStor Technology J680 (80 GB)" +"ExcelStor Technology J860" 194 C "ExcelStor Technology J860 (60 GB)" +"ExcelStor Technology J880" 194 C "ExcelStor Technology J880 (80 GB)" + + + +######################################## +############# Fujitsu drives +######################################## +"FUJITSU MHM2100AT" 0 C "Fujitsu MHM2100AT" + +"FUJITSU MHN2150AT" 194 C "Fujitsu MHN2150AT" +"FUJITSU MHN2200AT" 194 C "Fujitsu MHN2200AT" +"FUJITSU MHN2300AT" 194 C "Fujitsu MHN2300AT" + +"FUJITSU MHR2020AT" 194 C "Fujitsu MHR2020AT" +"FUJITSU MHR2030AT" 194 C "Fujitsu MHR2030AT" + +"FUJITSU MHS2030AT" 194 C "Fujitsu MHS2030AT" +"FUJITSU MHS2040AT" 194 C "Fujitsu MHS2040AT" +"FUJITSU MHS2060AT" 194 C "Fujitsu MHS2060AT (Apple PowerBook G4)" + +"FUJITSU MHT2030AC" 194 C "Fujitsu Mobile 30GB, 2MB, 4200RPM (automotive)" + +"FUJITSU MHT2030AT" 194 C "Fujitsu MHT2030AT" +"FUJITSU MHT2040AH" 194 C "Fujitsu MHT2040AH" +"FUJITSU MHT2040AT" 194 C "Fujitsu MHT2040AT" +"FUJITSU MHT2060AH" 194 C "Fujitsu MHT2060AH" +"FUJITSU MHT2060AT" 194 C "Fujitsu MHT2060AT" +"FUJITSU MHT2080AH" 194 C "Fujitsu MHT2080AH" + +"FUJITSU MHU2100AT" 194 C "Fujitsu MHU2100AT 100GB, 8MB (4200RPM)" + +"FUJITSU MHV2100AH" 194 C "FUJITSU MHV2100AH" +"FUJITSU MHV2100AT" 194 C "FUJITSU MHV2100AT" +"FUJITSU MHV2080[AB]H" 194 C "FUJITSU MHV2080AH" + +"FUJITSU MPF3204AH" 194 C "Fujitsu MPF3204AH" + +"FUJITSU MPG3204AT.*" 194 C "Fujitsu MPG3204AT" +"FUJITSU MPG3307AT" 194 C "Fujitsu MPG3307AT" +"FUJITSU MPG3409AT.*" 194 C "Fujitsu MPG3409AT E" +"FUJITSU MPG3409AH.*" 194 C "Fujitsu MPG3409AH E" +"FUJITSU MPG3204AH" 194 C "Fujitsu MPG3204AH" +"FUJITSU MPG3102AT E" 194 C "FUJITSU MPG3102AT E" + + + +######################################## +############# Hitachi drives +######################################## +"HITACHI_DK13FA-40B" 194 C "Hitachi DK13FA-40B" +"HITACHI_DK228A-65" 0 C "Hitachi DK228A-65" +"HITACHI_DK23CA-(15|20|30|30B|75)" 194 C "Hitachi DK23CA series" +"HITACHI_DK23DA-[234]0" 194 C "Hitachi DK23DA series" +"HITACHI_DK23EA-[2346]0" 194 C "Hitachi DK23EA series" +"HITACHI_DK23EB-40" 194 C "Hitachi DK23EB series" +"HITACHI_DK23FA-[468]0" 194 C "Hitachi DK23FA series" +"HITACHI_DK23FB-[46]0" 194 C "Hitachi DK23FB series" + +"HDS722516VLAT[28]0" 194 C "Hitachi Deskstar 7K250 160GB 2/8MB cache" +"HDS722525VLAT80" 194 C "Hitachi Deskstar 7K250 200/250GB, 7200RPM, 8MB, Parallel-ATA" +"HDS722512VLAT80" 194 C "Hitachi Deskstar 7K250 80GB" +"HDS722540VLAT20" 194 C "Hitachi Deskstar 7K250, 40GB, 7200RPM, 2MB cache" +"HDS722580VLAT20" 194 C "Deskstar 7K250 60GB" +"HDS724040KLSA80" 194 C "Hitachi Deskstar 7K250 400GB, 7200RPM, 8MB, Serial-ATA" +"HDS728080PLAT20" 194 C "Hitachi Deskstar 7K80 80GB" + +"HDS722525VLSA80" 194 C "Hitachi Deskstar 7K250 250GB, 7200RPM, 8MB, SATA" +"HDS722516VLSA80" 194 C "Hitachi Deskstar 7K250 160GB 8Mo cache SATA" +"HDS722580VLSA80" 194 C "Hitachi Deskstar 7K250 80GB SATA" +"HDS728040PLAT20" 194 C "Hitachi Deskstar 7K80 40GB" + +"HDS724040KLAT80" 194 C "Hitachi Deskstar 7K400 400GB 8Mo cache PATA" + +"HDT7225(16|25)DLAT80" 194 C "Hitachi Deskstar T7K250 series, 7200RPM, 8MB, PATA" +"HDT722516DLA380 V43O" 194 C "Hitachi T7K250 SATA" +"HDT722525DLA380" 194 C "Hitachi Deskstar T7K250 250GB 8Mo cache SATAII" +"HDT725050VLA360" 194 C "Hitachi Deskstar T7K500 500GB, 7200RPM, 16MB, SATA II" + +"HTE721010G9AT00" 194 C "Hitachi Travelstar 100GB (7200RPM)" +"HTE726060M9AT00" 194 C "Hitachi Travelstar 60GB (7200RPM)" +"HTS424030M9AT00" 194 C "Hitachi Travelstar 30GB (4200RPM)" +"HTS424040M9AT00" 194 C "Hitachi Travelstar 4K40 40GB 2MB cache (4200RPM)" +"HTS541010G9SA00" 194 C "Hitachi Travelstar 100GB SATA" +"HTS541040G9AT00" 194 C "Hitachi Travelstar 40GB (5400RPM)" +"HTS541080G9AT00" 194 C "Hitachi Travelstar 80GB (5400RPM)" +"HTS548020M9AT00" 194 C "Hitachi Travelstar 20GB (5400RPM)" +"HTS548030M9AT00" 194 C "Hitachi Travelstar 30GB (5400RPM)" +"HTS548040M9AT00" 194 C "Hitachi Travelstar 40GB (5400RPM)" +"HTS548060M9AT00" 194 C "Hitachi Travelstar 60GB (5400RPM)" +"HTS548080M9AT00" 194 C "Hitachi Travelstar 80GB (5400RPM)" +"HTS721080G9AT00" 194 C "Hitachi Travelstar 7K100 80GB (7200RPM)" +"HTS726060M9AT00" 194 C "Hitachi Travelstar 60GB" + + +######################################## +############# IBM drives +######################################## + +# DJSA serie is using F0h command to report temperature and also have +# SMART capabilties but it was reported not to work. +# "DJSA-2(30|32|10|20|05)" 0 C "IBM Travelstar 20GN, 32GH, 30GT series" + +"IBM-DARA-212000" 0 C "IBM Travelstar 12GN" +"IBM-DTTA-35*" 0 C "IBM Deskstar 16GP serie" + +# according to specifications they do not seems to have sensor +# but I prefer waiting for a report +#"IBM-DTTA-37*" 0 C "IBM Deskstar 14GXP serie" + +"IBM-DJNA-35.*" 231 C "IBM Deskstar 25 GP serie" +"IBM-DJNA-37.*" 231 C "IBM Deskstar 22 GXP serie" +"IBM-DHEA-(34330|36480)" 0 C "IBM Deskstar 5 serie" +"IBM-DHEA-(34331|36481|38451)" 0 C "IBM Deskstar 8 serie" +"IBM-DPTA-37.*" 231 C "IBM Deskstar 34GXP serie" +"IBM-DPTA-35.*" 231 C "IBM Deskstar 37GP serie" +"IBM-DTLA-30[57]0[123467][05]" 194 C "IBM Deskstar 40GV & 75GXP series" +"IC25N0[1234]0ATCS04-0" 194 C "IBM Travelstar 40GN serie" +"IC25N0[24]0ATC[SX]05-0" 194 C "IBM Travelstar 40GNX serie" +"IC25N0(10|15|20|30)ATDA04-0" 194 C "IBM Travelstar 30GN serie" +"IC25N0[23468]0ATMR04*" 194 C "Hitachi Travelstar 80GN" +"IC25T048ATDA05-0" 194 C "IBM Travelstar 48GH serie" +"IC25T060ATC[SX]05-0" 194 C "IBM Travelstar 60GH serie" +"IC35L0[12346]0AVER07" 194 C "IBM Deskstar 60GXP serie" +"IC35L[01][02468]0AVV[AN]07*" 194 C "IBM Deskstar 120GXP serie" +"IC35L[01][23689]0AVV207*" 194 C "IBM Deskstar 180GXP serie" + +######################################## +############# Maxtor drives +######################################## +#"Maxtor 2B0[012][04568]H1" ??? C "Maxtor Fireball 541DX" +"Maxtor 2F0[234]0[LJ]0" 194 C "Maxtor Fireball 3" +# which one must I trust ? +#"Maxtor 4D040H2" 9 C "Maxtor DiamondMax D540X-4D" +#"Maxtor 4D040H2" 0 C "Maxtor 4D040H2" +#"Maxtor 4D080H4" 12 C "Maxtor DiamondMax D540X-4D" +#"Maxtor 4D060H3" 12 C "Maxtor DiamondMax D540X-4D" +#"Maxtor 4D080H4" 9 C "Maxtor DiamondMax D540X-4D" +"MAXTOR 4K0[468]0H[234]" 194 C "Maxtor DiamondMax D540X serie" +"MAXTOR 4K020H1" 194 C "Maxtor 4K020H1" +"Maxtor 4A300J0" 194 C "Maxtor MaxLine II 300GB 5400RPM" +"Maxtor 4[RA](25|16|12|08|06)0[LJ]0" 194 C "Maxtor DiamondMax 16" +"Maxtor 5(1024|1369|2049|2732|3073|4098)U(2|3|4|6|8)" 0 C "Maxtor DiamondMax Plus 40" +"Maxtor 5A250J0" 194 C "Maxtor MaXline II 250GB 5400RPM" +"Maxtor 5A300J0" 194 C "Maxtor 5A300J0" +"Maxtor 5T0[24]0H[24]" 0 C "Maxtor DiamondMax Plus 60" +"Maxtor 6E0[234]0L0" 194 C "Maxtor DiamondMax Plus 8" +"MAXTOR 6L0[2468]0[LJ][1234]" 194 C "Maxtor DiamondMax Plus D740X family" +"Maxtor 6V320F0" 194 C "Maxtor Diamond Max 10 SATA II 320 GB" +"Maxtor 6Y(06|08|12|16|20|25)0[LPM]0" 194 C "Maxtor DiamondMax Plus 9" +"Maxtor 7L300[RS]0" 194 C "Maxtor 7L300R0 MaxLine+III 300GB 7200rpm" +"Maxtor 7Y250[PM]0" 194 C "Maxtor MaXLine Plus II 250GB 7200RPM" +"Maxtor 94098U8" 11 C "Maxtor DiamondMax 40 94098U8" + +#"Maxtor 6(B|L)(08|12|16|20|25|30)0[RSPM]0" 194 C "Maxtor DiamondMax Plus 10" +"Maxtor 6B080M0" 194 C "Maxtor DiamondMax 10 80GB 8MB SATA" +"Maxtor 6B120M0" 194 C "Maxtor DiamondMax 10 120GB 8MB SATA" +"Maxtor 6B160M0" 194 C "Maxtor DiamondMax 10 160GB 8MB SATA" +"Maxtor 6B160P0" 194 C "Maxtor DiamondMax 10 160GB 8MB ATA/133" +"Maxtor 6B200M0" 194 C "Maxtor DiamondMax 10 200GB 8MB SATA" +"Maxtor 6B200P0" 194 C "Maxtor DiamondMax 10 200GB 8MB ATA/133" +"Maxtor 6B250R0" 194 C "Maxtor DiamondMax 10 250GB 16MB ATA/133" +"Maxtor 6B250S0" 194 C "Maxtor DiamondMax 10 250GB 16MB SATA" +"Maxtor 6B300R0" 194 C "Maxtor DiamondMax 10 300GB 16MB ATA/133" +"Maxtor 6B300S0" 194 C "Maxtor DiamondMax 10 300GB 16MB SATA" +"Maxtor 6L080L0" 194 C "Maxtor DiamondMax 10 80GB 2MB ATA/133 RoHS" +"Maxtor 6L080M0" 194 C "Maxtor DiamondMax 10 80GB 8MB SATA RoHS" +"Maxtor 6L080P0" 194 C "Maxtor DiamondMax 10 80GB 8MB ATA/133 RoHS" +"Maxtor 6L120M0" 194 C "Maxtor DiamondMax 10 120GB 8MB SATA RoHS" +"Maxtor 6L120P0" 194 C "Maxtor DiamondMax 10 120GB 8MB ATA/133 RoHS" +"Maxtor 6L160M0" 194 C "Maxtor DiamondMax 10 160GB 8MB SATA RoHS" +"Maxtor 6L160P0" 194 C "Maxtor DiamondMax 10 160GB 8MB ATA/133 RoHS" +"Maxtor 6L200M0" 194 C "Maxtor DiamondMax 10 200GB 8MB SATA RoHS" +"Maxtor 6L200P0" 194 C "Maxtor DiamondMax 10 200GB 8MB ATA/133 RoHS" +"Maxtor 6L250R0" 194 C "Maxtor DiamondMax 10 250GB 16MB ATA/133 RoHS" +"Maxtor 6L250S0" 194 C "Maxtor DiamondMax 10 250GB 16MB SATA RoHS" +"Maxtor 6L300R0" 194 C "Maxtor DiamondMax 10 300GB 16MB ATA/133 RoHS" +"Maxtor 6L300S0" 194 C "Maxtor DiamondMax 10 300GB 16MB SATA RoHS" +"Maxtor 6V080E0" 194 C "Maxtor DiamondMax 10 80GB 8MB SATAII RoHS" +"Maxtor 6V160E0" 194 C "Maxtor DiamondMax 10 160GB 8MB SATAII RoHS" +"Maxtor 6V200E0" 194 C "Maxtor DiamondMax 10 200GB 8MB SATAII RoHS" +"Maxtor 6V250F0" 194 C "Maxtor DiamondMax 10 250GB 16MB SATAII RoHS" +"Maxtor 6V300F0" 194 C "Maxtor DiamondMax 10 300GB 16MB SATAII RoHS" + + + +######################################## +############# Quantum drives +######################################## +"QUANTUM FIREBALLP AS40.0" 0 C "Quantum Fireball AS40" +"QUANTUM FIREBALL CX10.2A" 0 C "Quantum Fireball CX10.2A" +#"QUANTUM FIREBALLlct10 20" 4 C "Quantum Fireball CT10 20GB" +# I suspect the QUANTUM FIREBALL_TM2110A to have a sensor in field 9... +# "QUANTUM FIREBALL_TM2110A" 9 C "Quantum Fireball TM2110A" + + + +######################################## +############# Samsung drives +######################################## +# somenone reported a problem with the SP8004H which reports a temperature +# 10°C below the ambient temperature +"SAMSUNG HA(200|250)JC" 194 C "Samsung SpinPoint V120CE series" +"SAMSUNG HD160JJ" 194 C "Samsung 160GB, 7200RPM, 8MB cache, SATA" +"SAMSUNG HD160JJ/P" 194 C "Samsung SpinPoint P80 SD 160GB (7200RPM, 8MB cache)" +"SAMSUNG HD[30|32|40][01]L[DJ]" 194 C "Samsung SpinPoint T133 series (300-400MB)" +"SAMSUNG HD250KD" 194 C "Samsung SpinPoint T133 series (250 MB PATA)" +"SAMSUNG HD321KJ" 194 C "Samsung Spinpoint T166 (7200RPM, 16MB cache) - SATA" +"SAMSUNG HD501LJ" 194 C "Samsung HD501LJ" +"SAMSUNG MP0(302|402|603|804)H" 194 C "Samsung SpinPoint M40 2.5inch" +"SAMSUNG SW0434A" 0 C "Samsung SW0434A" +"SAMSUNG SP(2001|4002|6003|8004|40A2)H" 194 C "Samsung SpinPoint P40 serie" +"SAMSUNG SP(0612|0802|1203|1604|0812|1213|1614)N" 194 C "Samsung SpinPoint P80 serie" +"SAMSUNG SP(0612|0802|1203|1604|0812|1213|1614)C" 194 C "Samsung SpinPoint P80 series - SATA" +"SAMSUNG SP0411N" 194 C "Samsung SpinPoint PL40 serie" +"SAMSUNG SP0822N" 194 C "Samsung SP0822N" +"SAMSUNG SP(0812|1213|1614)C" 194 C "Samsung Spinpoint 160G SATA" +"SAMSUNG SP2[05]14N" 194 C "Samsung SpinPoint P120 series (7200RPM, 8MB cache)" +"SAMSUNG SP2[05]04C" 194 C "Samsung SpinPoint P120 series - SATA" +"SAMSUNG SV0432A" 0 C "Samsung SV0432A" +"SAMSUNG SV3002H" 0 C "Samsung SpinPoint V30 serie" +"SAMSUNG SV(2001|4002|4012|6003|8004)H" 194 C "Samsung SpinPoint V40 serie" +#"SAMSUNG SV(0221|0602|0813|1204)H" 9 C "Samsung SpinPoint V60 serie" +#"SAMSUNG SV1204H" 194 C "Samsung 120G" +"SAMSUNG SV(0401|0802|1203|1604)N" 194 C "Samsung SpinPoint V80 serie" +"SAMSUNG SV4012H" 194 C "Samsung 40GB, 5400RPM, 2MB cache" + +######################################## +############# Seagate drives +######################################## +"Seagate Technology 1275MB - ST31276A" 0 C "Seagate ST31276A" +"ST3412A" 0 C "Seagate ST3412A" +"ST38641A" 0 C "Seagate ST38641A" +"ST310014A" 194 C "Seagate ST310014A" +"ST310210A" 0 C "Seagate ST310210A" +"ST310211A" 194 C "Seagate ST310211A" +"ST310220A" 0 C "Seagate ST310220A" +# SEAGATE ST313021A 13.0GB +"ST313021A" 0 C "Seagate U8 ST313021A" +"ST310240A" 0 C "Seagate Medalist 10240 Ultra ATA-3" +"ST315320A" 194 C "Seagate ST315320A" +"ST320423A" 0 C "Seagate U10 20423, Ultra ATA/66" +"ST320011A" 194 C "Seagate ST320011A" +"ST320014A" 194 C "Seagate ST320014A (5400 rpm, 20Gb)" +"ST320410A" 194 C "Seagate ST320410A" +"ST320413A" 194 C "Seagate ST320413A" +"ST320414A" 194 C "Seagate ST320414A" +"ST320420A" 194 C "Seagate Barracuda II ST320420A" +"ST330013A" 194 C "Seagate ST330013A Barracuda ATA V 30GB, 7200 rpm" +"ST330620A" 194 C "Seagate ST330620A" +"ST330621A" 194 C "Seagate ST330621A" +"ST330630A" 194 C "Seagate Barracuda ST330630A" +"ST340014A" 194 C "Seagate Barracuda 7200.7 40Gb" +"ST340015A" 194 C "Seagate Barracuda 5400.1 40GB" +"ST340016A" 194 C "Seagate ST340016A" +"ST340810A" 194 C "Seagate U Series 40810 (40Gb, Ultra ATA/100, 5400 rpm)" +"ST340823A" 194 C "Seagate U Series 5 40823" +"ST340824A" 194 C "Seagate Barracuda III" +"ST360015A" 194 C "Seagate Barracuda V ST360015A" +"ST360020A" 194 C "Seagate U Series 60020" +"ST360021A" 194 C "Seagate Barracuda IV ST360021A" +"ST380011A" 194 C "Seagate Barracuda 7200.7 80GB" +"ST380012A" 194 C "Seagate ST380012A 80GB" +"ST380013A" 194 C "Seagate Barracuda 7200.7 80GB" +"ST380013AS" 194 C "Seagate Barracuda 7200.7 80GB (Serial ATA)" +"ST380020A" 194 C "Seagate U Series 80020 (80Gb, Ultra ATA/100, 5400 rpm)" +"ST380021A" 194 C "Seagate Barracuda IV ST380021A" +"ST380022A" 194 C "Seagate Barracuda U7 80022, Ultra ATA/100" +"ST380023A" 194 C "Seagate Barracuda V ST380023A" +"ST380817AS" 194 C "Seagate Barracuda 7200.7 80GB - SATA" +"ST39111A" 194 C "Seagate ST39111A (from Sun Ultra)" +"ST3120020A" 194 C "Seagate ST3120020A" +"ST3120022A" 194 C "Seagate Baraccuda 7200.7 120GB" +"ST3120023A" 194 C "Seagate Barracuda V ST3120023A" +"ST3120024A" 194 C "Seagate Barracuda V ST3120024A" +"ST3120025ACE" 194 C "Seagate Barracuda V ST3120025ACE" +"ST3120026A" 194 C "Seagate Barracuda V ST3120026A" +"ST3160021A" 194 C "Seagate Barracuda 7200.7 - ST3160021A" +"ST3160023(A|AS)" 194 C "Seagate Barracuda V ST3160023A and AS (160Gb, ATA100 or Serial ATA)" +"ST3160827AS" 194 C "Seagate Barracuda 7200.7 160GB (Serial ATA)" +"ST3200021A" 194 C "Seagate Barracuda 7200.7 Plus 200GB" +"ST3200822(A|AS)" 194 C "Seagate Barracuda 7200.7 Plus 200GB (PATA or SATA)" +"ST3200826A" 194 C "Seagate Barracuda 7200.8 200Gb" +"ST3250623A" 194 C "Seagate Barracuda 7200.16 250GB" +"ST3250823A" 194 C "Seagate Barracuda 7200.8 250GB" +"ST3250823A" 194 C "Seagate Barracuda 7200.7 Plus 250GB" +"ST3250823NS" 194 C "Seagate NL35 SATA (RAID-Edition) 7200 250GB" +"ST3300831A" 194 C "Seagate 300GB ST3300831A" +"ST3400832A" 194 C "Seagate Barracuda 7200.8 Plus 400GB" +"ST3400633(A|AS)" 194 C "Seagate Barracuda 7200.7 400 GB" +"ST3500630NS" 194 C "Seagate" +"ST3400632NS" 194 C "Seagate" +"ST3320620AS" 194 C "Seagate Barracuda 7200.7 320 GB" +"ST3500630AS" 194 C "Seagate Barracuda 7200.7 500 GB" +"ST3802110A" 194 C "Seagate Barracuda 7200.9 80 GB" +"ST910021A" 194 C "Seagate Momentus 7200.1 100GB" +"ST910082[35]A" 194 C "Seagate Momentus 5400.2 100GB" +"ST9120821A" 194 C "Seagate Momentus 5400.2 120GB" +"ST94019A" 194 C "Seagate ST94019A" +"ST94813A" 194 C "Seagate Momentus 5400.2 40GB" +"ST94[08]11A" 194 C "Seagate ST94011A" +"ST960821A" 194 C "Seagate ST960821A" +"ST960822A" 194 C "Seagate Momentus 5400.2 60GB" +"ST96812AS" 194 C "Seagate Momentus 5400.2 60GB SATA" +"ST9808211A" 194 C "Seagate Momentus 5400.2 80GB" + +######################################## +############# TOSHIBA Laptops +######################################## +"MK4313MAT" 220 C "Toshiba MK4313MAT" +"TOSHIBA MK1032GAX" 194 C "Toshiba MK1032GAX" +"TOSHIBA MK1517GAP" 0 C "Toshiba MK1517GAP" +"TOSHIBA MK2018GAS" 226 F "Toshiba MK2018GAS" +"TOSHIBA MK2023GAS" 194 C "Toshiba MK2023GAS" + +"TOSHIBA MK3017GAP" 0 C "Toshiba MK3017GAP" +"TOSHIBA MK3021GAS" 194 C "Toshiba MK3021GAS" +"TOSHIBA MK3025GAS" 194 C "Toshiba MK3025GAS" + +#"TOSHIBA MK4019GAX" 222 C "Toshiba MK4019GAX" +"TOSHIBA MK4021GAS" 194 C "Toshiba MK4021GAS" +"TOSHIBA MK4025GAS" 194 C "Toshiba MK4025GAS 40 Go" +"TOSHIBA MK4026GAS" 194 C "Toshiba MK4026GAS 40 Go" +"TOSHIBA MK4032GAX" 194 C "Toshiba MK4032GAX" + +"TOSHIBA MK6021GAS" 194 C "Toshiba MK6021GAS" +"TOSHIBA MK6022GAX" 194 C "Toshiba MK6022GAX" +"TOSHIBA MK6025GAS" 194 C "Toshiba MK6025GAS" +"TOSHIBA MK6026GAX" 194 C "Toshiba MK6026GAX" +"TOSHIBA MK8025GAS" 194 C "Toshiba MK8025GAS" +"TOSHIBA MK8026GAX" 194 C "Toshiba MK8026GAX" + +"MK4025GAS" 194 C "Toshiba MK4025GAS" + + +######################################## +############# Western Digital drives +######################################## +# WDC AC310100B and WDC AC2850F are reported not working +# no more informations were given +"WDC AC22000L" 0 C "Western Digital Caviar AC22000" +"WDC AC420400D" 231 C "Western Digital Caviar AC420400D" +"WDC AC418000D" 231 C "Western Digital AC418000D" +"WDC WD135BA" 231 C "Western Digital WD135BA" + +"WDC WD100EB-00BHF0" 0 C "Western Digital 100EB-00BHF0" +"WDC WD200BB-00AUA1" 0 C "Western Digital Caviar WD200BB" +#"WDC WD200BB-60DGA0" 0 C "Western Digital Caviar WD200BB" +"WDC WD300BB-00CAA0" 0 C "Western Digital WD300BB" +"WDC WD360GD-00FNA0" 194 C "Western Digital SATA Raptor 36.7GB" +"WDC WD400BB-00CAA0" 0 C "Western Digital 400BB-00CAA0" +"WDC WD400BB-00J[KH]A0" 194 C "Western Digital Caviar WD400BB" +"WDC WD400BB-23JHC0" 194 C "Western Digital 23JHC0" +#"WDC WD400BB-00GFA0" 0 C "" +"WDC WD400BB-55HEA0" 194 C "Western Digital Caviar WD400BB" +"WDC WD400BB-(18CA|00DE)A0" 0 C "Western Digital Caviar WD400BB" +"WDC WD400BB-75FJA1" 194 C "Western Digital Caviar WD400BB" +"WDC WD400EB-00CPF0" 0 C "Western Digital 400EB-00CPF0" +"WDC WD400JB-00(JJ|FM|FS)A0" 194 C "Western Digital Caviar 40GB Special Edition 8MB" +"WDC WD400JB-00ETA0" 194 C "Western Digital 400JB-00ETA0" +"WDC WD400JB-00JJC0" 194 C "Western Digital 400JB-00JJC0 40GB" +"WDC WD400LB-00DNA0" 194 C "Western Digital 400LB-00DNA0" +"WDC WD400UE-22HCT0" 194 C "Western Digital 40GB Notebook HDD" +"WDC WD400VE-75HDT1" 194 C "Western Digital Scorpio 40GB" +"WDC WD600BB-32BSA0" 0 C "Western Digital 600BB-32BSA0" +"WDC WD600JB-00ETA0" 194 C "Western Digital 600JB-00ETA0" +"WDC WD600LB-00DNA0" 194 C "Western Digital 60GB" +"WDC WD600VE-75HDT0" 194 C "Western Digital 600VE-75HDT0" +"WDC WD600VE-00HDT0" 194 C "Western Digital 600VE-00HDT0" +"WDC WD740GD-00FL21.0" 194 C "Western Digital SATA Raptor" +"WDC WD740GD-([05]0FL[AC]0|75FLA1)" 194 C "Western Digital SATA Raptor 74GB 8MB" +"WDC WD800BB-00CAA1" 0 C "Western Digital WD800BB-00CAA1" +"WDC WD800BB-(00|22)DKA0" 194 C "Western Digital WD800BB 80 Go" +"WDC WD800BB-32CCB0" 194 C "Western Digital 800BB-32CCB0" +"WDC WD800BB-55HEA0" 194 C "Western Digital 800BB-55HEA0" +"WDC WD800BB-00JHA0" 194 C "Western Digital 800BB-00JHA0" +"WDC WD800BB-00JKA0" 194 C "Western Digital 800BB-00JKA0" +"WDC WD800BB-55JKA0" 194 C "Western Digital 800BB-55JKA0" +"WDC WD800BB-75FRA0" 194 C "Western Digital Caviar WD800BB" +"WDC WD800JB-00CRA1" 0 C "Western Digital Caviar WD800JB" +"WDC WD800JB-00(ET|FM|FS)A0" 194 C "Western Digital Caviar 80GB Special Edition 8MB" +"WDC WD800JB-00JJ[AC]0" 194 C "Western Digital WD800JB" +"WDC WD800JD-(00|55)(HK|JR)A0" 194 C "Western Digital SATA 80GB, 8MB Cache" +"WDC WD800JD-00(HK|JN)A0" 194 C "Western Digital SATA 80GB, 8MB Cache" +"WDC WD800LB-(00|55)DNA0" 194 C "Western Digital Caviar WD800LB 80 Go ATA-100" +"WDC WD800VE-07HDT0" 194 C "Western Digital 800VE-07HDT0" +"WDC WD1200BB-00(FTA|GUA)0" 194 C "Western Digital Caviar EIDE 2MB Cache" +"WDC WD1200JB-00(EV|FU|GV)A0" 194 C "Western Digital Caviar 120GB Special Edition 8MB" +"WDC WD1200JB-22GVA0" 194 C "Western Digital Caviar 120GB" +"WDC WD1200JD-00(GBB|HBC)0" 194 C "Western Digital WD1200JD" +"WDC WD1200LB-55EDA0" 194 C "Western Digital WD1220LB" +"WDC WD1200SB-01KB[AC]0" 194 C "Western Digital Caviar RE (Raid Edition) 120 GB" +"WDC WD1600BB-00DWA0" 194 C "Western Digital Caviar WD1600BB" +"WDC WD1600JB-(00EV|00FU|00GV|22GV|75GV)A0" 194 C "Western Digital Caviar 160GB Special Edition 8MB" +"WDC WD2000BB-00FTA0" 194 C "Western Digital WD2000BB" +"WDC WD2000JB-(00EV|32EV|34EV|00FU|00GV|55GV|98GV|00KF)A0" 194 C "Western Digital Caviar 200GB Special Edition 8MB" +"WDC WD2000JB-00GVC0" 194 C "Western Digital WD2000JB" +"WDC WD2000JS-00MHB1" 194 C "Western Digital SATA 200GB" +"WDC WD2500JB-(00RE|00EV|00FU|32FU|00GV|55GV)A0" 194 C "Western Digital Caviar 250GB Special Edition 8MB" +"WDC WD2500JB-00GVC0" 194 C "Western Digital 250GB" +"WDC WD2500JD-(00G|32H)BB0" 194 C "Western Digital SATA Caviar 250GB Special Edition 8MB" +"WDC WD2500JD-40HBC0" 194 C "Western Digital WD2500JD-40HBC0" +"WDC WD2500PB-98FBA0" 194 C "Western Digital Caviar 250GB Special Edition 8MB" +"WDC WD2500PD-00FZB1" 194 C "Western Digital WD2500PD-00FZB1" +"WDC WD2500SD-01KCB0" 194 C "Western Digital Caviar RE 250GB 8MB" +"WDC WD3000JB-00KFA0" 194 C "Western Digital WD3000JB" +"WDC WD3200JB-00KFA0" 194 C "Western Digital Caviar 320GB 8MB" +"WDC WD4000KD-00NAB0" 194 C "Western Digital Caviar SE16 400GB 16MB" +"WDC WD4000YR-01PLB0" 194 C "Western Digital Caviar RE2 400GB 16MB" +"WD4000YS-01MPB0" 194 C "Western Digital RE2 7200 SATA II 400 GB" + +# not sure for next +# "WDC WD1200JB-00CRA1" 9 C "Western Digital 1200JB-00CRA1" +# "WDC WD273BA" 9 C "Western Digital WD273BA" + + + + +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## +######################################################################################################################## + +"ST3750640AS" 194 C "Seagate Barracuda 7200.10 SATA 750GB" +"ST3750840AS" 194 C "Seagate Barracuda 7200.10 SATA 750GB" +"ST3500630AS" 194 C "Seagate Barracuda 7200.10 SATA 500GB" +"ST3500830AS" 194 C "Seagate Barracuda 7200.10 SATA 500GB" +"ST3400620AS" 194 C "Seagate Barracuda 7200.10 SATA 400GB" +"ST3400620A" 194 C "Seagate Barracuda 7200.10 400GB" +"ST3400820AS" 194 C "Seagate Barracuda 7200.10 SATA 400GB" +"ST3320620AS" 194 C "Seagate Barracuda 7200.10 SATA 320GB" +"ST3320820AS" 194 C "Seagate Barracuda 7200.10 SATA 320GB" +"ST3300620AS" 194 C "Seagate Barracuda 7200.10 SATA 300GB" +"ST3300820AS" 194 C "Seagate Barracuda 7200.10 SATA 300GB" +"ST3250620AS" 194 C "Seagate Barracuda 7200.10 SATA 250GB" +"ST3250820AS" 194 C "Seagate Barracuda 7200.10 SATA 250GB" +"ST3250410AS" 194 C "Seagate Barracuda 7200.10 SATA 250GB" +"ST3250310AS" 194 C "Seagate Barracuda 7200.10 SATA 250GB" +"ST3200820AS" 194 C "Seagate Barracuda 7200.10 SATA 200GB" +"ST3160815AS" 194 C "Seagate Barracuda 7200.10 SATA 160GB" +"ST3160215AS" 194 C "Seagate Barracuda 7200.10 SATA 160GB" +"ST3120815AS" 194 C "Seagate Barracuda 7200.10 SATA 120GB" +"ST3120215AS" 194 C "Seagate Barracuda 7200.10 SATA 120GB" +"ST380815AS" 194 C "Seagate Barracuda 7200.10 SATA 80GB" +"ST380215AS" 194 C "Seagate Barracuda 7200.10 SATA 80GB" +"ST340815AS" 194 C "Seagate Barracuda 7200.10 SATA 40GB" +"ST340215AS" 194 C "Seagate Barracuda 7200.10 SATA 40GB" +"ST3300622AS" 194 C "Seagate Barracuda 7200.9 SATA2.5 300GB" +"ST3300831A" 194 C "Seagate Barracuda 7200.8 PATA 300GB" + +"Maxtor 7(L|V)250(F|R|S)0" 194 C "Maxtor MaXLine III 250GB 7200rpm" +"Maxtor 7(L|V)300(F|R|S)0" 194 C "Maxtor MaXLine III 300GB 7200rpm" +"MAXTOR STM3320620AS" 194 C "" + +"WDC WD1500ADFD-00NLR1" 194 C "Western Digital Raptor 150GB" +"WDC WD1600JS-00NCB1" 194 C "Western Digital Caviar 1600JS 160GB Sata" +"WDC WD1600SD-01KCC0" 194 C "Western Digital Caviar RE Serial ATA series" +"WDC WD2500JD-57HBC0" 194 C "Western Digital Caviar SE (Serial ATA) 250 GB" +"WDC WD2500JS" 194 C "Western Digital WD2500JS" +"WDC WD2500JS-41MVB1" 194 C "Western Digital SATAII Caviar 250GB Special Edition 8MB" +"WDC WD2500JD-00HBB0" 194 C "Western Digital SATA 250GB" +"WDC WD2500KS-00MJB0" 194 C "Western Digital SATA-II Caviar 250GB Special Edition 16MB" +"WDC WD3000JS-00PDB0" 194 C "Western Digital WD3000JS" +"WDC WD3200KS-00PFB0" 194 C "" +"WDC WD3200JD-22KLB0" 194 C "Western Digital Caviar SE 320GB 8MB" diff --git a/packages/sysutils/hddtemp/package.mk b/packages/sysutils/hddtemp/package.mk new file mode 100644 index 000000000..d7e6a1782 --- /dev/null +++ b/packages/sysutils/hddtemp/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hddtemp" +PKG_VERSION="e16aed6" +PKG_SHA256="5d5af74ba7449b6e56a8f872a0e10d654a512ed65d62beaef1575b0c1826d9f3" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.nongnu.org/projects/hddtemp" +PKG_URL="https://github.com/guzu/hddtemp/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A utility that gives you the temperature of your hard drive by reading S.M.A.R.T.." + +PKG_CONFIGURE_OPTS_TARGET="--with-db-path=/storage/.kodi/addons/virtual.system-tools/data/hddtemp.db" + +post_unpack() { + cp $PKG_DIR/db/* $PKG_BUILD +} + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/hid_mapper/package.mk b/packages/sysutils/hid_mapper/package.mk new file mode 100644 index 000000000..3e3ae4642 --- /dev/null +++ b/packages/sysutils/hid_mapper/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hid_mapper" +PKG_VERSION="2.1.0" +PKG_SHA256="e740c1f3a99f260f015ea7d415f0419e27171356e2eddff1781fc5d936cc86cd" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/s-leroux/hid_mapper" +PKG_URL="https://github.com/s-leroux/hid_mapper/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A Generic HID mapper." + +makeinstall_target() { + : # nope +} diff --git a/packages/sysutils/hid_mapper/patches/hid_mapper-01_crosscompile.patch b/packages/sysutils/hid_mapper/patches/hid_mapper-01_crosscompile.patch new file mode 100644 index 000000000..9843d7b94 --- /dev/null +++ b/packages/sysutils/hid_mapper/patches/hid_mapper-01_crosscompile.patch @@ -0,0 +1,21 @@ +diff --git a/Makefile b/Makefile +index f98abbd..9d1d524 100755 +--- a/Makefile ++++ b/Makefile +@@ -9,13 +9,13 @@ EXEC=hid_mapper + VERSION=1.0 + + all: $(OBJS) +- g++ $(LDFLAGS) $(OBJS) -o $(EXEC) ++ ${CXX} $(LDFLAGS) $(OBJS) -o $(EXEC) + + %.o: %.cpp +- g++ -c $(CPPFLAGS) $< ++ ${CXX} -c $(CPPFLAGS) $< + + %.o: %.c +- gcc -c $(CFLAGS) $< ++ ${CC} -c $(CFLAGS) $< + + deb: + cp $(EXEC) package/usr/bin diff --git a/packages/sysutils/hid_mapper/patches/hid_mapper-02_include-sys-time.patch b/packages/sysutils/hid_mapper/patches/hid_mapper-02_include-sys-time.patch new file mode 100644 index 000000000..2dba3d84a --- /dev/null +++ b/packages/sysutils/hid_mapper/patches/hid_mapper-02_include-sys-time.patch @@ -0,0 +1,12 @@ +diff --git a/hid.c b/hid.c +index 2830b58..a652222 100644 +--- a/hid.c ++++ b/hid.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #define SYSFS_HIDRAW_CLASS_PATH "/sys/class/hidraw" + diff --git a/packages/sysutils/hid_mapper/patches/hid_mapper-03_fix-parser.patch b/packages/sysutils/hid_mapper/patches/hid_mapper-03_fix-parser.patch new file mode 100644 index 000000000..c2bb51c12 --- /dev/null +++ b/packages/sysutils/hid_mapper/patches/hid_mapper-03_fix-parser.patch @@ -0,0 +1,14 @@ +--- a/MapReader.cpp ++++ b/MapReader.cpp +@@ -106,7 +106,10 @@ + i = 0; + + while(i "Not supported" # +# # +# config.ini parameter are auto generated from package bl301: # +# # +# [config variable name] # +# config_id = [unique unsigned int ID for variable] # +# config_name = [unique matching config.ini key name] # +# # +# This config parameter value is filled automatic by package.mk. # +# Multiple sections are possible. Do not edit! # +#################################################################### + +[BL301] +odroid= +lepotato= +lafrite= +gxl_p212_2g_kvim=Khadas_VIM1 +khadas_vim3=Khadas_VIM3 diff --git a/packages/sysutils/inject_bl301/package.mk b/packages/sysutils/inject_bl301/package.mk new file mode 100644 index 000000000..e82e2ba36 --- /dev/null +++ b/packages/sysutils/inject_bl301/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="inject_bl301" +PKG_VERSION="6af46f6a7defbbba360a6bbcd5db2b11925f7315" +PKG_SHA256="bb02545eb80c0a1372f91990cb21572b201251d47523c9f4424fea72a16426ab" +PKG_LICENSE="proprietary" +PKG_SITE="https://coreelec.org" +PKG_URL="https://sources.coreelec.org/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain bl301" +PKG_LONGDESC="Tool to inject bootloader blob BL301.bin on internal eMMC" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + cp -av ${PKG_DIR}/config/bl301.conf ${PKG_BUILD}/bl301.conf + for f in $(find $(get_build_dir bl301) -mindepth 1 -name 'coreelec_config.c'); do + cat ${f} | awk -F'[(),"]' '/.config_id_a\s*=\s*HASH/ {printf("%s %s\n", $2, $3)}' | \ + while read id name; do + if ! grep -Fwq "${id}" ${PKG_BUILD}/bl301.conf; then + echo -e '\n['${id}']' >> ${PKG_BUILD}/bl301.conf; + cat ${f%.*}.h | awk -v id="HASHSTR_${id} " '$0 ~ id {printf("config_id=%s\n", $3)}' >> ${PKG_BUILD}/bl301.conf; + echo -e "config_name=${name}" >> ${PKG_BUILD}/bl301.conf; + fi + done + done +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/sbin + mkdir -p ${INSTALL}/usr/lib/coreelec + mkdir -p ${INSTALL}/etc/inject_bl301 + install -m 0755 inject_bl301 ${INSTALL}/usr/sbin/inject_bl301 + install -m 0755 ${PKG_DIR}/scripts/check-bl301.sh ${INSTALL}/usr/lib/coreelec/check-bl301 + install -m 0755 ${PKG_DIR}/scripts/update-bl301.sh ${INSTALL}/usr/lib/coreelec/update-bl301 + install -m 0644 ${PKG_BUILD}/bl301.conf ${INSTALL}/etc/inject_bl301/bl301.conf +} + +post_install() { + enable_service update-bl301.service +} diff --git a/packages/sysutils/inject_bl301/scripts/check-bl301.sh b/packages/sysutils/inject_bl301/scripts/check-bl301.sh new file mode 100755 index 000000000..dc4a32a5a --- /dev/null +++ b/packages/sysutils/inject_bl301/scripts/check-bl301.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) +# +# Detect BL301 injection +# +##################################################### +# +# Comand Line Arguments +# -v = Show verbose output +# +##################################################### + +VERBOSE=0 +INSTALLED=0 + +if [ "$1" = "-v" ]; then + VERBOSE=1 +fi + +if [ -e /usr/sbin/inject_bl301 ]; then + inject_bl301 -i + if [ ${?} = 1 ]; then + INSTALLED=1 + fi +fi + +if [ "$VERBOSE" = 1 ]; then + if [ "$INSTALLED" = 1 ]; then + echo "CoreELEC BL301 Installed" + else + echo "CoreELEC BL301 Not found" + fi +fi +exit $INSTALLED diff --git a/packages/sysutils/inject_bl301/scripts/update-bl301.sh b/packages/sysutils/inject_bl301/scripts/update-bl301.sh new file mode 100755 index 000000000..5fb1d3c17 --- /dev/null +++ b/packages/sysutils/inject_bl301/scripts/update-bl301.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) +# +# Update BL301 injection +# +##################################################### +# +# Comand Line Arguments +# -v = Show verbose output +# +##################################################### + +VERBOSE=0 +INSTALLED=0 +UPDATE=1 +RET=0 + +if [ "$1" = "-v" ]; then + VERBOSE=1 +fi + +if [ -e /usr/lib/coreelec/check-bl301 ]; then + /usr/lib/coreelec/check-bl301 + INSTALLED=${?} + if [ "$INSTALLED" = 1 ]; then + touch /run/bl301_injected + fi +fi + +if [ -e /usr/sbin/inject_bl301 ] && [ "$INSTALLED" = 1 ]; then + inject_bl301 -Y > /storage/update-bl301.log + UPDATE=${?} +fi + +if [ "$VERBOSE" = 1 ]; then + if [ "$INSTALLED" = 1 ] && [ "$UPDATE" = 0 ]; then + echo "CoreELEC BL301 got updated" + elif [ "$INSTALLED" = 1 ] && [ "$UPDATE" = 1 ]; then + echo "CoreELEC BL301 installed but no update needed" + elif [ "$INSTALLED" = 1 ]; then + echo "CoreELEC BL301 installed but error on update: " $UPDATE + RET=$UPDATE + elif [ "$INSTALLED" = 0 ]; then + echo "CoreELEC BL301 not installed" + fi +fi + +if [ "$INSTALLED" = 1 ] && [ "$UPDATE" = 0 ]; then + sync && reboot +fi + +exit $RET diff --git a/packages/sysutils/inject_bl301/system.d/update-bl301.service b/packages/sysutils/inject_bl301/system.d/update-bl301.service new file mode 100644 index 000000000..61033aa30 --- /dev/null +++ b/packages/sysutils/inject_bl301/system.d/update-bl301.service @@ -0,0 +1,10 @@ +[Unit] +Description=CoreELEC BL301 Update Service + +[Service] +Type=oneshot +ExecStart=/usr/lib/coreelec/update-bl301 -v +RemainAfterExit=no + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/inotify-tools/package.mk b/packages/sysutils/inotify-tools/package.mk new file mode 100644 index 000000000..ff77b5f88 --- /dev/null +++ b/packages/sysutils/inotify-tools/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="inotify-tools" +PKG_VERSION="3.20.1" +PKG_SHA256="a433cc1dedba851078276db69b0e97f9fe41e4ba3336d2971adfca4b3a6242ac" +PKG_LICENSE="GPLv2" +PKG_SITE="http://wiki.github.com/rvoicilas/inotify-tools/" +PKG_URL="https://github.com/rvoicilas/inotify-tools/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A C library and a set of command-line programs for Linux providing a simple interface to inotify." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --disable-doxygen" + +pre_configure_target() { + CFLAGS="$CFLAGS -Wno-error=misleading-indentation" +} + +makeinstall_target() { + : +} diff --git a/packages/sysutils/irqbalanced/package.mk b/packages/sysutils/irqbalanced/package.mk new file mode 100644 index 000000000..86f1e42ab --- /dev/null +++ b/packages/sysutils/irqbalanced/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="irqbalanced" +PKG_VERSION="7f31046" +PKG_SHA256="e9f533bc2186fcef8456b78fb404ac981836d19f4b6ff10fede830b1df421717" +PKG_ARCH="arm" +PKG_LICENSE="other" +PKG_SITE="http://www.freescale.com" +PKG_URL="https://github.com/dv1/irqbalanced/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain systemd glib" +PKG_LONGDESC="irqbalanced: distribute hardware interrupts across processors on a multiprocessor system." +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + sh -c ./autogen.sh +} + +post_install() { + enable_service irqbalance.service +} diff --git a/packages/sysutils/irqbalanced/system.d/irqbalance.service b/packages/sysutils/irqbalanced/system.d/irqbalance.service new file mode 100644 index 000000000..a9d97d14b --- /dev/null +++ b/packages/sysutils/irqbalanced/system.d/irqbalance.service @@ -0,0 +1,10 @@ +[Unit] +Description=irqbalance +After=proc.mount + +[Service] +ExecStart=/usr/sbin/irqbalance +Type=forking + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/jq/package.mk b/packages/sysutils/jq/package.mk new file mode 100644 index 000000000..75c17fbec --- /dev/null +++ b/packages/sysutils/jq/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="jq" +PKG_VERSION="1.6" +PKG_SHA256="5de8c8e29aaa3fb9cc6b47bb27299f271354ebb72514e3accadc7d38b5bbaa72" +PKG_LICENSE="MIT" +PKG_SITE="http://stedolan.github.io/jq/" +PKG_URL="https://github.com/stedolan/jq/releases/download/$PKG_NAME-$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain oniguruma" +PKG_LONGDESC="A like sed for JSON data." + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --disable-docs \ + --disable-maintainer-mode \ + --disable-valgrind" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/kbd/package.mk b/packages/sysutils/kbd/package.mk new file mode 100644 index 000000000..72de6c6bb --- /dev/null +++ b/packages/sysutils/kbd/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="kbd" +PKG_VERSION="2.4.0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/legionus/kbd" +PKG_URL="https://github.com/legionus/kbd/archive/refs/tags/v$PKG_VERSION.tar.gz" +PKG_DEPENDS="toolchain" +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + cd . + ./autogen.sh +} + +configure_target() { + ./configure --disable-vlock --prefix=/usr --host=aarch64 +} diff --git a/packages/sysutils/keyutils/package.mk b/packages/sysutils/keyutils/package.mk new file mode 100644 index 000000000..e8a2160da --- /dev/null +++ b/packages/sysutils/keyutils/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="keyutils" +PKG_VERSION="1.6" +PKG_SHA256="d3aef20cec0005c0fa6b4be40079885567473185b1a57b629b030e67942c7115" +PKG_LICENSE="GPL" +PKG_SITE="http://people.redhat.com/~dhowells/keyutils/" +PKG_URL="http://people.redhat.com/~dhowells/keyutils/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Keyutils is a set of utilities for managing the key retention facility in the kernel." +PKG_BUILD_FLAGS="+pic" + +PKG_MAKE_OPTS_TARGET="NO_ARLIB=0 NO_SOLIB=1 BINDIR=/usr/bin SBINDIR=/usr/sbin LIBDIR=/usr/lib USRLIBDIR=/usr/lib" +PKG_MAKEINSTALL_OPTS_TARGET="$PKG_MAKE_OPTS_TARGET" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/share + rmdir $INSTALL/etc/request-key.d + ln -sf /storage/.config/request-key.d $INSTALL/etc/request-key.d +} diff --git a/packages/sysutils/keyutils/patches/keyutils-02-cflags.patch b/packages/sysutils/keyutils/patches/keyutils-02-cflags.patch new file mode 100644 index 000000000..508b3d437 --- /dev/null +++ b/packages/sysutils/keyutils/patches/keyutils-02-cflags.patch @@ -0,0 +1,23 @@ +From d8f15e55b4d357ac0a2b384888080b120600d09d Mon Sep 17 00:00:00 2001 +From: vpeter4 +Date: Wed, 8 Apr 2015 18:27:06 +0200 +Subject: [PATCH] cflags + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index c904eaf..df0fe3e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,5 +1,5 @@ + CPPFLAGS := -I. +-CFLAGS := -g -Wall -Werror ++CFLAGS += -g -Wall -Werror + INSTALL := install + DESTDIR := + SPECFILE := keyutils.spec +-- +1.8.1.2 + diff --git a/packages/sysutils/kmod/modprobe.d/aliases.conf b/packages/sysutils/kmod/modprobe.d/aliases.conf new file mode 100644 index 000000000..f7f20aa5b --- /dev/null +++ b/packages/sysutils/kmod/modprobe.d/aliases.conf @@ -0,0 +1,172 @@ +# These are the standard aliases for devices and kernel drivers. +# This file does not need to be modified. +# +# Please file a bug against module-init-tools if a package needs a entry +# in this file. + +# network protocols ########################################################## +alias net-pf-1 unix +alias net-pf-2 ipv4 +alias net-pf-3 ax25 +alias net-pf-4 ipx +alias net-pf-5 appletalk +alias net-pf-6 netrom +alias net-pf-7 bridge +alias net-pf-8 atm +alias net-pf-9 x25 +alias net-pf-10 ipv6 +alias net-pf-11 rose +alias net-pf-12 decnet +# 13 NETBEUI +alias net-pf-15 af_key +alias net-pf-16 af_netlink +alias net-pf-17 af_packet +# 18 ASH +alias net-pf-19 af_econet +alias net-pf-20 atm +# 22 SNA +alias net-pf-23 irda +alias net-pf-24 pppoe +alias net-pf-25 wanrouter +alias net-pf-26 llc +alias net-pf-31 bluetooth + +alias net-pf-16-proto-1 wire +alias net-pf-16-proto-3 ip_queue +alias net-pf-16-proto-4 tcp_diag +alias net-pf-16-proto-8 scsi_transport_iscsi +alias net-pf-16-proto-9 audit +alias net-pf-16-proto-11 cn +alias net-pf-16-proto-13 ip6_queue + +# executables formats ######################################################## +install binfmt-0000 /bin/true +alias binfmt-204 binfmt_aout +alias binfmt-263 binfmt_aout +alias binfmt-264 binfmt_aout +alias binfmt-267 binfmt_aout +alias binfmt-387 binfmt_aout + +# block devices ############################################################## +alias block-major-3-* ide_generic +alias block-major-8-* sd_mod +alias block-major-9-* md +alias block-major-11-* sr_mod +alias block-major-22-* ide_generic +alias block-major-33-* ide_generic +alias block-major-34-* ide_generic +alias block-major-37-* ide_tape +alias block-major-44-* ftl +alias block-major-46-* pcd +alias block-major-47-* pf +alias block-major-56-* ide_generic +alias block-major-57-* ide_generic +alias block-major-58-* lvm_mod +alias block-major-88-* ide_generic +alias block-major-89-* ide_generic +alias block-major-90-* ide_generic +alias block-major-91-* ide_generic +alias block-major-93-* nftl +alias block-major-97-* pg + +# character devices ########################################################## +alias char-major-9-* st +alias char-major-10-1 psmouse +alias char-major-10-139 openprom +alias char-major-10-157 applicom +alias char-major-10-181 toshiba +alias char-major-10-183 hw_random +alias char-major-10-187 irnet +alias char-major-10-189 ussp +alias char-major-10-250 hci_vhci +alias char-major-13-0 joydev +alias char-major-13-1 joydev +alias char-major-13-2 joydev +alias char-major-13-3 joydev +alias char-major-13-32 mousedev +alias char-major-13-33 mousedev +alias char-major-13-34 mousedev +alias char-major-13-35 mousedev +alias char-major-13-63 mousedev +alias char-major-13-64 evdev +alias char-major-13-65 evdev +alias char-major-13-66 evdev +alias char-major-13-67 evdev +alias char-major-19-* cyclades +alias char-major-20-* cyclades +alias char-major-22-* pcxx +alias char-major-23-* pcxx +alias char-major-27-* ftape +alias char-major-34-* scc +alias char-major-35-* tclmidi +alias char-major-48-* riscom8 +alias char-major-49-* riscom8 +alias char-major-57-* esp +alias char-major-58-* esp +alias char-major-63-* kdebug +alias char-major-67-* coda +alias char-major-75-* specialix +alias char-major-76-* specialix +alias char-major-81-* videodev +alias char-major-83-* vtx +alias char-major-89-* i2c_dev +alias char-major-90-* mtdchar +alias char-major-96-* pt +alias char-major-97-* pg +alias char-major-107-* 3dfx +alias char-major-109-* lvm_mod +alias char-major-166-* cdc_acm +alias char-major-171-0 raw1394 +alias char-major-171-1 video1394 +alias char-major-171-2 dv1394 +alias char-major-171-3 amdtp +alias char-major-180-* usbcore +alias char-major-195-* nvidia +alias char-major-200-* vxspec +alias char-major-202-* msr +alias char-major-203-* cpuid +alias char-major-206-* osst +alias char-major-208-* ussp +alias char-major-227-* tub3270 +#alias char-major-240-* usb-serial +#alias char-major-240-* hsfserial +#alias char-major-241-* hsfserial + +# misc ####################################################################### +alias xfrm-type-2-4 xfrm4_tunnel +alias xfrm-type-2-50 esp4 +alias xfrm-type-2-51 ah4 +alias xfrm-type-2-108 ipcomp +alias xfrm-type-10-41 xfrm6_tunnel +alias xfrm-type-10-50 esp6 +alias xfrm-type-10-51 ah6 +alias xfrm-type-10-108 ipcomp6 + +alias bt-proto-0 l2cap +alias bt-proto-2 sco +alias bt-proto-3 rfcomm +alias bt-proto-4 bnep +alias bt-proto-5 cmtp +alias bt-proto-6 hidp +alias bt-proto-7 avdtp + +alias cipcb0 cipcb +alias cipcb1 cipcb +alias cipcb2 cipcb +alias cipcb3 cipcb +alias dummy0 dummy +alias dummy1 dummy +alias plip0 plip +alias plip1 plip +alias slip0 slip +alias slip1 slip +alias tunl0 ipip +alias gre0 ip_gre + +alias usbdevfs usbcore + +# work around other kernel issues ############################################ +# The EHCI driver should be loaded before the ones for low speed controllers +# or some devices may be confused when they are disconnected and reconnected. +softdep uhci-hcd pre: ehci-hcd +softdep ohci-hcd pre: ehci-hcd diff --git a/packages/sysutils/kmod/modprobe.d/i2c.conf b/packages/sysutils/kmod/modprobe.d/i2c.conf new file mode 100644 index 000000000..2a7da1c9c --- /dev/null +++ b/packages/sysutils/kmod/modprobe.d/i2c.conf @@ -0,0 +1 @@ +alias char-major-89 i2c-dev diff --git a/packages/sysutils/kmod/package.mk b/packages/sysutils/kmod/package.mk new file mode 100644 index 000000000..0cc005aeb --- /dev/null +++ b/packages/sysutils/kmod/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="kmod" +PKG_VERSION="24" +PKG_SHA256="610b8d1df172acc39a4fdf1eaa47a57b04873c82f32152e7a62e29b6ff9cb397" +PKG_LICENSE="GPL" +PKG_SITE="http://git.profusion.mobi/cgit.cgi/kmod.git/" +PKG_URL="https://www.kernel.org/pub/linux/utils/kernel/kmod/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="toolchain" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="kmod offers the needed flexibility and fine grained control over insertion, removal, configuration and listing of kernel modules." + +PKG_CONFIGURE_OPTS_HOST="--enable-tools \ + --disable-logging \ + --disable-debug \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-manpages \ + --with-gnu-ld \ + --without-xz \ + --without-zlib" + +PKG_CONFIGURE_OPTS_TARGET="--enable-tools \ + --enable-logging \ + --disable-debug \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-manpages \ + --with-gnu-ld \ + --without-xz \ + --without-zlib" + +post_makeinstall_host() { + ln -sf kmod $TOOLCHAIN/bin/depmod +} + +post_makeinstall_target() { +# make symlinks for compatibility + mkdir -p $INSTALL/usr/sbin + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/lsmod + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/insmod + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/rmmod + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/modinfo + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/modprobe + ln -sf /usr/bin/kmod $INSTALL/usr/sbin/depmod + + mkdir -p $INSTALL/etc + ln -sf /storage/.config/modprobe.d $INSTALL/etc/modprobe.d + +# add user modprobe.d dir + mkdir -p $INSTALL/usr/config/modprobe.d +} diff --git a/packages/sysutils/kmod/patches/kmod-02_fix-pkgconf.patch b/packages/sysutils/kmod/patches/kmod-02_fix-pkgconf.patch new file mode 100644 index 000000000..8614e475c --- /dev/null +++ b/packages/sysutils/kmod/patches/kmod-02_fix-pkgconf.patch @@ -0,0 +1,27 @@ +From 19b848e18e0eaaec75d3d840b5831b82f7c6b5b5 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 16 Aug 2014 13:39:55 +0300 +Subject: [PATCH] fix pkgconf + +--- + libkmod/libkmod.pc.in | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libkmod/libkmod.pc.in b/libkmod/libkmod.pc.in +index e4fdf21..c4f1465 100644 +--- a/libkmod/libkmod.pc.in ++++ b/libkmod/libkmod.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@libdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: libkmod + Description: Library to deal with kernel modules +-- +1.7.2.5 + diff --git a/packages/sysutils/libevdev/package.mk b/packages/sysutils/libevdev/package.mk new file mode 100644 index 000000000..7a9152613 --- /dev/null +++ b/packages/sysutils/libevdev/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libevdev" +PKG_VERSION="1.11.0" +#PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freedesktop.org/wiki/Software/libevdev/" +PKG_URL="http://www.freedesktop.org/software/libevdev/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libevdev is a wrapper library for evdev devices." +PKG_BUILD_FLAGS="+pic" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-shared --disable-static" +PKG_CMAKE_OPTS_TARGET="-Dtests=disabled" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin +} diff --git a/packages/sysutils/libhid/package.mk b/packages/sysutils/libhid/package.mk new file mode 100644 index 000000000..dc5fab9aa --- /dev/null +++ b/packages/sysutils/libhid/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libhid" +PKG_VERSION="0.2.16" +PKG_SHA256="f6809ab3b9c907cbb05ceba9ee6ca23a705f85fd71588518e14b3a7d9f2550e5" +PKG_LICENSE="GPL" +PKG_SITE="http://libhid.alioth.debian.org/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libusb-compat libusb" +PKG_LONGDESC="libhid provides a generic and flexible way to access and interact with USB HID devices." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --disable-werror \ + --disable-swig" + +post_makeinstall_target() { + rm -rf $INSTALL/usr +} diff --git a/packages/sysutils/libhid/patches/libhid-0.2.16-automake-1.13.patch b/packages/sysutils/libhid/patches/libhid-0.2.16-automake-1.13.patch new file mode 100644 index 000000000..eb2b2245c --- /dev/null +++ b/packages/sysutils/libhid/patches/libhid-0.2.16-automake-1.13.patch @@ -0,0 +1,12 @@ +diff -Naur libhid-0.2.16/configure.ac libhid-0.2.16.patch/configure.ac +--- libhid-0.2.16/configure.ac 2007-04-01 22:32:10.000000000 +0200 ++++ libhid-0.2.16.patch/configure.ac 2013-01-12 17:23:25.129691249 +0100 +@@ -21,7 +21,7 @@ + + AC_INIT(MD_INIT_NAME, MD_INIT_VERSION, MD_INIT_ADDRESS) + +-AM_CONFIG_HEADER([config.h]) ++AC_CONFIG_HEADERS([config.h]) + AC_CONFIG_SRCDIR([include/hid.h]) + AC_CONFIG_AUX_DIR([.]) + diff --git a/packages/sysutils/libhid/patches/libhid-0.2.16-autoreconf.patch b/packages/sysutils/libhid/patches/libhid-0.2.16-autoreconf.patch new file mode 100644 index 000000000..db5901408 --- /dev/null +++ b/packages/sysutils/libhid/patches/libhid-0.2.16-autoreconf.patch @@ -0,0 +1,531 @@ +diff -Naur libhid-0.2.16/configure.ac libhid-0.2.16.patch/configure.ac +--- libhid-0.2.16/configure.ac 2007-04-01 22:32:10.000000000 +0200 ++++ libhid-0.2.16.patch/configure.ac 2012-06-29 21:43:13.483730717 +0200 +@@ -88,11 +88,11 @@ + if test "${ac_cv_enable_swig}" = "no" ; then + AM_CONDITIONAL(HAVE_SWIG, false) + else +- AC_PROG_SWIG(1.3) ++ AX_PKG_SWIG(1.3) + AM_CONDITIONAL(HAVE_SWIG, "$SWIG" -version) + if test -z "${HAVE_SWIG_TRUE}" ; then + AM_PATH_PYTHON +- SWIG_PYTHON ++ AX_SWIG_PYTHON + fi + fi + +diff -Naur libhid-0.2.16/m4/ac_pkg_swig.m4 libhid-0.2.16.patch/m4/ac_pkg_swig.m4 +--- libhid-0.2.16/m4/ac_pkg_swig.m4 2007-04-01 22:32:10.000000000 +0200 ++++ libhid-0.2.16.patch/m4/ac_pkg_swig.m4 1970-01-01 01:00:00.000000000 +0100 +@@ -1,167 +0,0 @@ +-##### http://autoconf-archive.cryp.to/ac_pkg_swig.html +-# +-# SYNOPSIS +-# +-# AC_PROG_SWIG([major.minor.micro]) +-# +-# DESCRIPTION +-# +-# This macro searches for a SWIG installation on your system. If +-# found you should call SWIG via $(SWIG). You can use the optional +-# first argument to check if the version of the available SWIG is +-# greater than or equal to the value of the argument. It should have +-# the format: N[.N[.N]] (N is a number between 0 and 999. Only the +-# first N is mandatory.) +-# +-# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks +-# that the swig package is this version number or higher. +-# +-# In configure.in, use as: +-# +-# AC_PROG_SWIG(1.3.17) +-# SWIG_ENABLE_CXX +-# SWIG_MULTI_MODULE_SUPPORT +-# SWIG_PYTHON +-# +-# LAST MODIFICATION +-# +-# 2006-10-22 +-# +-# COPYLEFT +-# +-# Copyright (c) 2006 Sebastian Huber +-# Copyright (c) 2006 Alan W. Irwin +-# Copyright (c) 2006 Rafael Laboissiere +-# Copyright (c) 2006 Andrew Collier +-# +-# This program 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 2 of the +-# License, or (at your option) any later version. +-# +-# This program 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 this program; if not, write to the Free Software +-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-# 02111-1307, USA. +-# +-# As a special exception, the respective Autoconf Macro's copyright +-# owner gives unlimited permission to copy, distribute and modify the +-# configure scripts that are the output of Autoconf when processing +-# the Macro. You need not follow the terms of the GNU General Public +-# License when using or distributing such scripts, even though +-# portions of the text of the Macro appear in them. The GNU General +-# Public License (GPL) does govern all other use of the material that +-# constitutes the Autoconf Macro. +-# +-# This special exception to the GPL applies to versions of the +-# Autoconf Macro released by the Autoconf Macro Archive. When you +-# make and distribute a modified version of the Autoconf Macro, you +-# may extend this special exception to the GPL to apply to your +-# modified version as well. +- +-AC_DEFUN([AC_PROG_SWIG],[ +- AC_PATH_PROG([SWIG],[swig]) +- if test -z "$SWIG" ; then +- AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org]) +- SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false' +- elif test -n "$1" ; then +- AC_MSG_CHECKING([for SWIG version]) +- [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] +- AC_MSG_RESULT([$swig_version]) +- if test -n "$swig_version" ; then +- # Calculate the required version number components +- [required=$1] +- [required_major=`echo $required | sed 's/[^0-9].*//'`] +- if test -z "$required_major" ; then +- [required_major=0] +- fi +- [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] +- [required_minor=`echo $required | sed 's/[^0-9].*//'`] +- if test -z "$required_minor" ; then +- [required_minor=0] +- fi +- [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] +- [required_patch=`echo $required | sed 's/[^0-9].*//'`] +- if test -z "$required_patch" ; then +- [required_patch=0] +- fi +- # Calculate the available version number components +- [available=$swig_version] +- [available_major=`echo $available | sed 's/[^0-9].*//'`] +- if test -z "$available_major" ; then +- [available_major=0] +- fi +- [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] +- [available_minor=`echo $available | sed 's/[^0-9].*//'`] +- if test -z "$available_minor" ; then +- [available_minor=0] +- fi +- [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] +- [available_patch=`echo $available | sed 's/[^0-9].*//'`] +- if test -z "$available_patch" ; then +- [available_patch=0] +- fi +- if test $available_major -ne $required_major \ +- -o $available_minor -ne $required_minor \ +- -o $available_patch -lt $required_patch ; then +- AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org]) +- SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' +- else +- AC_MSG_NOTICE([SWIG executable is '$SWIG']) +- SWIG_LIB=`$SWIG -swiglib` +- AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB']) +- fi +- else +- AC_MSG_WARN([cannot determine SWIG version]) +- SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' +- fi +- fi +- AC_SUBST([SWIG_LIB]) +-]) +- +- +-# SWIG_ENABLE_CXX() +-# +-# Enable SWIG C++ support. This affects all invocations of $(SWIG). +-AC_DEFUN([SWIG_ENABLE_CXX],[ +- AC_REQUIRE([AC_PROG_SWIG]) +- AC_REQUIRE([AC_PROG_CXX]) +- SWIG="$SWIG -c++" +-]) +- +-# SWIG_MULTI_MODULE_SUPPORT() +-# +-# Enable support for multiple modules. This effects all invocations +-# of $(SWIG). You have to link all generated modules against the +-# appropriate SWIG runtime library. If you want to build Python +-# modules for example, use the SWIG_PYTHON() macro and link the +-# modules against $(SWIG_PYTHON_LIBS). +-AC_DEFUN([SWIG_MULTI_MODULE_SUPPORT],[ +- AC_REQUIRE([AC_PROG_SWIG]) +- SWIG="$SWIG -c" +-]) +- +-# SWIG_PYTHON([use-shadow-classes = {no, yes}]) +-# +-# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS), +-# $(SWIG_PYTHON_LIBS) and $(SWIG_PYTHON_OPT) output variables. +-# $(SWIG_PYTHON_OPT) contains all necessary SWIG options to generate +-# code for Python. Shadow classes are enabled unless the value of the +-# optional first argument is exactly 'no'. If you need multi module +-# support (provided by the SWIG_MULTI_MODULE_SUPPORT() macro) use +-# $(SWIG_PYTHON_LIBS) to link against the appropriate library. It +-# contains the SWIG Python runtime library that is needed by the type +-# check system for example. +-AC_DEFUN([SWIG_PYTHON],[ +- AC_REQUIRE([AC_PROG_SWIG]) +- AC_REQUIRE([AC_PYTHON_DEVEL]) +- test "x$1" != "xno" || swig_shadow=" -noproxy" +- AC_SUBST([SWIG_PYTHON_OPT],[-python$swig_shadow]) +- AC_SUBST([SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +- AC_SUBST([SWIG_PYTHON_LIBS],["-L$SWIG_LIB -lswigpy"]) +-]) +diff -Naur libhid-0.2.16/m4/ac_python_devel.m4 libhid-0.2.16.patch/m4/ac_python_devel.m4 +--- libhid-0.2.16/m4/ac_python_devel.m4 2007-04-01 22:32:10.000000000 +0200 ++++ libhid-0.2.16.patch/m4/ac_python_devel.m4 1970-01-01 01:00:00.000000000 +0100 +@@ -1,268 +0,0 @@ +-##### http://autoconf-archive.cryp.to/ac_python_devel.html +-# +-# SYNOPSIS +-# +-# AC_PYTHON_DEVEL([version]) +-# +-# DESCRIPTION +-# +-# Note: Defines as a precious variable "PYTHON_VERSION". Don't +-# override it in your configure.ac. +-# +-# This macro checks for Python and tries to get the include path to +-# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and +-# $(PYTHON_LDFLAGS) output variables. It also exports +-# $(PYTHON_EXTRA_LIBS) and $(PYTHON_EXTRA_LDFLAGS) for embedding +-# Python in your code. +-# +-# You can search for some particular version of Python by passing a +-# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". +-# Please note that you *have* to pass also an operator along with the +-# version to match, and pay special attention to the single quotes +-# surrounding the version number. Don't use "PYTHON_VERSION" for +-# this: that environment variable is declared as precious and thus +-# reserved for the end-user. +-# +-# This macro should work for all versions of Python >= 2.1.0. As an +-# end user, you can disable the check for the python version by +-# setting the PYTHON_NOVERSIONCHECK environment variable to something +-# else than the empty string. +-# +-# If you need to use this macro for an older Python version, please +-# contact the authors. We're always open for feedback. +-# +-# LAST MODIFICATION +-# +-# 2006-10-22 +-# +-# COPYLEFT +-# +-# Copyright (c) 2006 Sebastian Huber +-# Copyright (c) 2006 Alan W. Irwin +-# Copyright (c) 2006 Rafael Laboissiere +-# Copyright (c) 2006 Andrew Collier +-# Copyright (c) 2006 Matteo Settenvini +-# Copyright (c) 2006 Horst Knorr +-# +-# This program 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 2 of the +-# License, or (at your option) any later version. +-# +-# This program 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 this program; if not, write to the Free Software +-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-# 02111-1307, USA. +-# +-# As a special exception, the respective Autoconf Macro's copyright +-# owner gives unlimited permission to copy, distribute and modify the +-# configure scripts that are the output of Autoconf when processing +-# the Macro. You need not follow the terms of the GNU General Public +-# License when using or distributing such scripts, even though +-# portions of the text of the Macro appear in them. The GNU General +-# Public License (GPL) does govern all other use of the material that +-# constitutes the Autoconf Macro. +-# +-# This special exception to the GPL applies to versions of the +-# Autoconf Macro released by the Autoconf Macro Archive. When you +-# make and distribute a modified version of the Autoconf Macro, you +-# may extend this special exception to the GPL to apply to your +-# modified version as well. +- +-AC_DEFUN([AC_PYTHON_DEVEL],[ +- # +- # Allow the use of a (user set) custom python version +- # +- AC_ARG_VAR([PYTHON_VERSION],[The installed Python +- version to use, for example '2.3'. This string +- will be appended to the Python interpreter +- canonical name.]) +- +- AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) +- if test -z "$PYTHON"; then +- AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) +- PYTHON_VERSION="" +- fi +- +- # +- # Check for a version of Python >= 2.1.0 +- # +- AC_MSG_CHECKING([for a version of Python >= '2.1.0']) +- ac_supports_python_ver=`$PYTHON -c "import sys, string; \ +- ver = string.split(sys.version)[[0]]; \ +- print ver >= '2.1.0'"` +- if test "$ac_supports_python_ver" != "True"; then +- if test -z "$PYTHON_NOVERSIONCHECK"; then +- AC_MSG_RESULT([no]) +- AC_MSG_FAILURE([ +-This version of the AC@&t@_PYTHON_DEVEL macro +-doesn't work properly with versions of Python before +-2.1.0. You may need to re-run configure, setting the +-variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +-PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +-Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +-to something else than an empty string. +-]) +- else +- AC_MSG_RESULT([skip at user request]) +- fi +- else +- AC_MSG_RESULT([yes]) +- fi +- +- # +- # if the macro parameter ``version'' is set, honour it +- # +- if test -n "$1"; then +- AC_MSG_CHECKING([for a version of Python $1]) +- ac_supports_python_ver=`$PYTHON -c "import sys, string; \ +- ver = string.split(sys.version)[[0]]; \ +- print ver $1"` +- if test "$ac_supports_python_ver" = "True"; then +- AC_MSG_RESULT([yes]) +- else +- AC_MSG_RESULT([no]) +- AC_MSG_ERROR([this package requires Python $1. +-If you have it installed, but it isn't the default Python +-interpreter in your system path, please pass the PYTHON_VERSION +-variable to configure. See ``configure --help'' for reference. +-]) +- PYTHON_VERSION="" +- fi +- fi +- +- # +- # Check if you have distutils, else fail +- # +- AC_MSG_CHECKING([for the distutils Python package]) +- ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` +- if test -z "$ac_distutils_result"; then +- AC_MSG_RESULT([yes]) +- else +- AC_MSG_RESULT([no]) +- AC_MSG_ERROR([cannot import Python module "distutils". +-Please check your Python installation. The error was: +-$ac_distutils_result]) +- PYTHON_VERSION="" +- fi +- +- # +- # Check for Python include path +- # +- AC_MSG_CHECKING([for Python include path]) +- if test -z "$PYTHON_CPPFLAGS"; then +- python_path=`$PYTHON -c "import distutils.sysconfig; \ +- print distutils.sysconfig.get_python_inc();"` +- if test -n "${python_path}"; then +- python_path="-I$python_path" +- fi +- PYTHON_CPPFLAGS=$python_path +- fi +- AC_MSG_RESULT([$PYTHON_CPPFLAGS]) +- AC_SUBST([PYTHON_CPPFLAGS]) +- +- # +- # Check for Python library path +- # +- AC_MSG_CHECKING([for Python library path]) +- if test -z "$PYTHON_LDFLAGS"; then +- # (makes two attempts to ensure we've got a version number +- # from the interpreter) +- py_version=`$PYTHON -c "from distutils.sysconfig import *; \ +- from string import join; \ +- print join(get_config_vars('VERSION'))"` +- if test "$py_version" == "[None]"; then +- if test -n "$PYTHON_VERSION"; then +- py_version=$PYTHON_VERSION +- else +- py_version=`$PYTHON -c "import sys; \ +- print sys.version[[:3]]"` +- fi +- fi +- +- PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ +- import os; \ +- print apply(os.path.join, get_config_vars('LIBPL', 'LDLIBRARY'))"` +- fi +- AC_MSG_RESULT([$PYTHON_LDFLAGS]) +- AC_SUBST([PYTHON_LDFLAGS]) +- +- # +- # Check for site packages +- # +- AC_MSG_CHECKING([for Python site-packages path]) +- if test -z "$PYTHON_SITE_PKG"; then +- PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ +- print distutils.sysconfig.get_python_lib(0,0);"` +- fi +- AC_MSG_RESULT([$PYTHON_SITE_PKG]) +- AC_SUBST([PYTHON_SITE_PKG]) +- +- # +- # libraries which must be linked in when embedding +- # +- AC_MSG_CHECKING(python extra libraries) +- if test -z "$PYTHON_EXTRA_LIBS"; then +- PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ +- conf = distutils.sysconfig.get_config_var; \ +- print conf('LOCALMODLIBS'), conf('LIBS')"` +- fi +- AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) +- AC_SUBST(PYTHON_EXTRA_LIBS) +- +- # +- # linking flags needed when embedding +- # +- AC_MSG_CHECKING(python extra linking flags) +- if test -z "$PYTHON_EXTRA_LDFLAGS"; then +- PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ +- conf = distutils.sysconfig.get_config_var; \ +- print conf('LINKFORSHARED')"` +- fi +- AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) +- AC_SUBST(PYTHON_EXTRA_LDFLAGS) +- +- # +- # final check to see if everything compiles alright +- # +- AC_MSG_CHECKING([consistency of all components of python development environment]) +- AC_LANG_PUSH([C]) +- # save current global flags +- LIBS="$ac_save_LIBS $PYTHON_LDFLAGS" +- CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" +- AC_TRY_LINK([ +- #include +- ],[ +- Py_Initialize(); +- ],[pythonexists=yes],[pythonexists=no]) +- +- AC_MSG_RESULT([$pythonexists]) +- +- if test ! "$pythonexists" = "yes"; then +- AC_MSG_ERROR([ +- Could not link test program to Python. Maybe the main Python library has been +- installed in some non-standard library path. If so, pass it to configure, +- via the LDFLAGS environment variable. +- Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" +- ============================================================================ +- ERROR! +- You probably have to install the development version of the Python package +- for your distribution. The exact name of this package varies among them. +- ============================================================================ +- ]) +- PYTHON_VERSION="" +- fi +- AC_LANG_POP +- # turn back to default flags +- CPPFLAGS="$ac_save_CPPFLAGS" +- LIBS="$ac_save_LIBS" +- +- # +- # all done! +- # +-]) +diff -Naur libhid-0.2.16/m4/swig_python.m4 libhid-0.2.16.patch/m4/swig_python.m4 +--- libhid-0.2.16/m4/swig_python.m4 2007-04-01 22:32:10.000000000 +0200 ++++ libhid-0.2.16.patch/m4/swig_python.m4 1970-01-01 01:00:00.000000000 +0100 +@@ -1,67 +0,0 @@ +-##### http://autoconf-archive.cryp.to/swig_python.html +-# +-# SYNOPSIS +-# +-# SWIG_PYTHON([use-shadow-classes = {no, yes}]) +-# +-# DESCRIPTION +-# +-# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS), and +-# $(SWIG_PYTHON_OPT) output variables. +-# +-# $(SWIG_PYTHON_OPT) contains all necessary SWIG options to generate +-# code for Python. Shadow classes are enabled unless the value of the +-# optional first argument is exactly 'no'. If you need multi module +-# support (provided by the SWIG_MULTI_MODULE_SUPPORT macro) use +-# $(SWIG_PYTHON_LIBS) to link against the appropriate library. It +-# contains the SWIG Python runtime library that is needed by the type +-# check system for example. +-# +-# LAST MODIFICATION +-# +-# 2006-10-22 +-# +-# COPYLEFT +-# +-# Copyright (c) 2006 Sebastian Huber +-# Copyright (c) 2006 Alan W. Irwin +-# Copyright (c) 2006 Rafael Laboissiere +-# Copyright (c) 2006 Andrew Collier +-# +-# This program 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 2 of the +-# License, or (at your option) any later version. +-# +-# This program 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 this program; if not, write to the Free Software +-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-# 02111-1307, USA. +-# +-# As a special exception, the respective Autoconf Macro's copyright +-# owner gives unlimited permission to copy, distribute and modify the +-# configure scripts that are the output of Autoconf when processing +-# the Macro. You need not follow the terms of the GNU General Public +-# License when using or distributing such scripts, even though +-# portions of the text of the Macro appear in them. The GNU General +-# Public License (GPL) does govern all other use of the material that +-# constitutes the Autoconf Macro. +-# +-# This special exception to the GPL applies to versions of the +-# Autoconf Macro released by the Autoconf Macro Archive. When you +-# make and distribute a modified version of the Autoconf Macro, you +-# may extend this special exception to the GPL to apply to your +-# modified version as well. +- +-AC_DEFUN([SWIG_PYTHON],[ +- AC_REQUIRE([AC_PROG_SWIG]) +- AC_REQUIRE([AC_PYTHON_DEVEL]) +- test "x$1" != "xno" || swig_shadow=" -noproxy" +- AC_SUBST([SWIG_PYTHON_OPT],[-python$swig_shadow]) +- AC_SUBST([SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +-]) diff --git a/packages/sysutils/libhid/patches/libhid-use_pkgconfig.patch b/packages/sysutils/libhid/patches/libhid-use_pkgconfig.patch new file mode 100644 index 000000000..0d3805768 --- /dev/null +++ b/packages/sysutils/libhid/patches/libhid-use_pkgconfig.patch @@ -0,0 +1,14 @@ +diff -Naur libhid-0.2.16/m4/md_check_libusb018b.m4 libhid-0.2.16.patch/m4/md_check_libusb018b.m4 +--- libhid-0.2.16/m4/md_check_libusb018b.m4 2004-05-26 02:37:41.000000000 +0200 ++++ libhid-0.2.16.patch/m4/md_check_libusb018b.m4 2016-01-10 00:07:24.000000000 +0100 +@@ -2,8 +2,8 @@ + [ + AC_CHECK_HEADERS([usb.h]) + +- LIBUSB_CFLAGS="`libusb-config --cflags`" +- LIBUSB_LIBS="`libusb-config --libs`" ++ LIBUSB_CFLAGS="`pkg-config --cflags libusb`" ++ LIBUSB_LIBS="`pkg-config --libs libusb`" + + AC_SUBST(LIBUSB_CFLAGS) + AC_SUBST(LIBUSB_LIBS) diff --git a/packages/sysutils/libusb-compat/package.mk b/packages/sysutils/libusb-compat/package.mk new file mode 100644 index 000000000..742fb3e88 --- /dev/null +++ b/packages/sysutils/libusb-compat/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libusb-compat" +PKG_VERSION="0.1.5" +PKG_SHA256="404ef4b6b324be79ac1bfb3d839eac860fbc929e6acb1ef88793a6ea328bc55a" +PKG_LICENSE="GPL" +PKG_SITE="http://libusb.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/libusb/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libusb" +PKG_LONGDESC="The libusb project's aim is to create a Library for use by user level applications to USB devices." + +PKG_CONFIGURE_OPTS_TARGET="--disable-log --disable-debug-log --disable-examples-build" + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin + sed -e "s:\(['= ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/bin/libusb-config +} diff --git a/packages/sysutils/libusb/package.mk b/packages/sysutils/libusb/package.mk new file mode 100644 index 000000000..c7f88df51 --- /dev/null +++ b/packages/sysutils/libusb/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libusb" +PKG_VERSION="1.0.22" +PKG_SHA256="75aeb9d59a4fdb800d329a545c2e6799f732362193b465ea198f2aa275518157" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="http://libusb.info/" +PKG_URL="$SOURCEFORGE_SRC/libusb/files/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain systemd" +PKG_LONGDESC="The libusb project's aim is to create a Library for use by user level applications to USB devices." +#libusb sometimes fails to build if building paralell +PKG_BUILD_FLAGS="-parallel" + +PKG_CONFIGURE_OPTS_TARGET="--enable-shared \ + --enable-static \ + --disable-log \ + --disable-debug-log \ + --enable-udev \ + --disable-examples-build" diff --git a/packages/sysutils/lirc/config/lirc_options.conf b/packages/sysutils/lirc/config/lirc_options.conf new file mode 100644 index 000000000..3fb2bf94f --- /dev/null +++ b/packages/sysutils/lirc/config/lirc_options.conf @@ -0,0 +1,43 @@ +# These are the default options to lircd, if installed as +# /etc/lirc/lirc_options.conf. See the lircd(8) and lircmd(8) +# manpages for info on the different options. +# +# Some tools including mode2 and irw uses values such as +# driver, device, plugindir and loglevel as fallback values +# in not defined elsewhere. + +[lircd] +nodaemon = False +driver = default +device = /dev/lirc0 +output = /run/lirc/lircd.socket +pidfile = /run/lirc/lircd.pid +plugindir = /usr/lib/lirc/plugins +permission = 666 +allow-simulate = No +repeat-max = 600 +#effective-user = +#listen = [address:]port +#connect = host[:port] +#loglevel = 6 +#release = true +#release_suffix = _EVUP + +#logfile = ... + +[lircmd] +uinput = False +nodaemon = False + +# modinit is not supported in LibreELEC + +# [modinit] +# code = /usr/sbin/modprobe lirc_serial +# code1 = /usr/bin/setfacl -m g:lirc:rw /dev/uinput +# code2 = ... + + +# [lircd-uinput] +# add-release-events = False +# release-timeout = 200 +# release-suffix = _EVUP diff --git a/packages/sysutils/lirc/default.d/lircd.conf b/packages/sysutils/lirc/default.d/lircd.conf new file mode 100644 index 000000000..e69de29bb diff --git a/packages/sysutils/lirc/package.mk b/packages/sysutils/lirc/package.mk new file mode 100644 index 000000000..e67538c9b --- /dev/null +++ b/packages/sysutils/lirc/package.mk @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lirc" +PKG_VERSION="0.10.1" +PKG_SHA256="8b753c60df2a7f5dcda2db72c38e448ca300c3b4f6000c1501fcb0bd5df414f2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.lirc.org" +PKG_URL="https://sourceforge.net/projects/lirc/files/LIRC/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libftdi1 libusb-compat libxslt alsa-lib" +PKG_LONGDESC="LIRC is a package that allows you to decode and send infra-red signals." +PKG_TOOLCHAIN="autotools" + +PKG_PYTHON_WANTED=Python2 + +PKG_CONFIGURE_OPTS_TARGET="--enable-devinput \ + --enable-uinput \ + --with-gnu-ld \ + --without-x \ + --runstatedir=/run" + +pre_configure_target() { + export HAVE_WORKING_POLL=yes + export HAVE_UINPUT=yes + export PYTHON=: + export PYTHON_VERSION=${PKG_PYTHON_VERSION#python} + if [ -e ${SYSROOT_PREFIX}/usr/include/linux/input-event-codes.h ] ; then + export DEVINPUT_HEADER=${SYSROOT_PREFIX}/usr/include/linux/input-event-codes.h + else + export DEVINPUT_HEADER=${SYSROOT_PREFIX}/usr/include/linux/input.h + fi +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/lib/systemd + rm -rf $INSTALL/lib + rm -rf $INSTALL/usr/share + rm -rf $INSTALL/etc + + mkdir -p $INSTALL/etc/lirc + cp -r $PKG_DIR/config/lirc_options.conf $INSTALL/etc/lirc + ln -s /storage/.config/lircd.conf $INSTALL/etc/lirc/lircd.conf + + mkdir -p $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/lircd_helper $INSTALL/usr/lib/coreelec + cp $PKG_DIR/scripts/lircd_uinput_helper $INSTALL/usr/lib/coreelec + + mkdir -p $INSTALL/usr/share/services + cp -P $PKG_DIR/default.d/*.conf $INSTALL/usr/share/services +} + +post_install() { + enable_service lircd.socket + enable_service lircd.service + enable_service lircd-uinput.service +} diff --git a/packages/sysutils/lirc/patches/lirc-0001-fix-zotac-poll.patch b/packages/sysutils/lirc/patches/lirc-0001-fix-zotac-poll.patch new file mode 100644 index 000000000..1c0be1f0e --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0001-fix-zotac-poll.patch @@ -0,0 +1,29 @@ +From 79e2494e4880d0446bf837c8bbca0b01baac4ed4 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Wed, 8 Apr 2020 11:27:11 +0200 +Subject: [PATCH] plugins/zotac: fix poll timeout + +poll requires a negative timeout value for infinite waits. +See https://sourceforge.net/p/lirc/tickets/327/ + +Signed-off-by: Matthias Reichl +--- + plugins/zotac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/plugins/zotac.c b/plugins/zotac.c +index ac528c67..4a66acf5 100644 +--- a/plugins/zotac.c ++++ b/plugins/zotac.c +@@ -352,7 +352,7 @@ static void* zotac_repeat(void* arg) + if (pressed) + sel = curl_poll(&pfd, 1, delay_ms); + else +- sel = curl_poll(&pfd, 1, 0); ++ sel = curl_poll(&pfd, 1, -1); + switch (sel) { + case 1: + // Data ready in device's file +-- +2.20.1 + diff --git a/packages/sysutils/lirc/patches/lirc-0003-logging-Don-t-use-broken-LOG_CONS-syslog-flag.patch b/packages/sysutils/lirc/patches/lirc-0003-logging-Don-t-use-broken-LOG_CONS-syslog-flag.patch new file mode 100644 index 000000000..5cf3e2a64 --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0003-logging-Don-t-use-broken-LOG_CONS-syslog-flag.patch @@ -0,0 +1,24 @@ +From: Alec Leamas +Date: Fri, 23 Nov 2018 23:04:35 -0500 +Subject: [PATCH] logging: Don't use broken LOG_CONS syslog flag. + +--- + lib/lirc_log.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/lirc_log.c b/lib/lirc_log.c +index bea357b..900beb3 100644 +--- a/lib/lirc_log.c ++++ b/lib/lirc_log.c +@@ -102,9 +102,9 @@ int lirc_log_open(const char* _progname, int _nodaemon, loglevel_t level) + + if (use_syslog) { + if (nodaemon) +- openlog(syslogident, LOG_CONS | LOG_PID | LOG_PERROR, LOG_LOCAL0); ++ openlog(syslogident, LOG_PID | LOG_PERROR, LOG_LOCAL0); + else +- openlog(syslogident, LOG_CONS | LOG_PID, LOG_LOCAL0); ++ openlog(syslogident, LOG_PID, LOG_LOCAL0); + } else { + lf = fopen(logfile, "a"); + if (lf == NULL) { diff --git a/packages/sysutils/lirc/patches/lirc-0004-lircd-Fix-connect-option-parsing-error-343.patch b/packages/sysutils/lirc/patches/lirc-0004-lircd-Fix-connect-option-parsing-error-343.patch new file mode 100644 index 000000000..e498661f9 --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0004-lircd-Fix-connect-option-parsing-error-343.patch @@ -0,0 +1,22 @@ +From: Alec Leamas +Date: Sun, 30 Dec 2018 21:26:15 +0100 +Subject: [PATCH] lircd: Fix --connect option parsing error (#343). + +Bug: https://sourceforge.net/p/lirc/tickets/343/ +--- + daemons/lircd.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemons/lircd.cpp b/daemons/lircd.cpp +index d5be708..ad8dde9 100644 +--- a/daemons/lircd.cpp ++++ b/daemons/lircd.cpp +@@ -790,7 +790,7 @@ int add_peer_connection(const char* server_arg) + struct servent* service; + char server[strlen(server_arg) + 1]; + +- strncpy(server, server_arg, sizeof(server) - 1); ++ strncpy(server, server_arg, sizeof(server)); + + if (peern < MAX_PEERS) { + peers[peern] = (struct peer_connection*) malloc(sizeof( diff --git a/packages/sysutils/lirc/patches/lirc-0005-systemd-support-Notify-systemd-on-successful-startup.patch b/packages/sysutils/lirc/patches/lirc-0005-systemd-support-Notify-systemd-on-successful-startup.patch new file mode 100644 index 000000000..ffe479817 --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0005-systemd-support-Notify-systemd-on-successful-startup.patch @@ -0,0 +1,43 @@ +From: William Manley +Date: Thu, 9 Aug 2018 18:26:44 +0100 +Subject: [PATCH] systemd support: Notify systemd on successful startup + +This allows systemd to detect the case where we've failed to startup +due to a failure to parse our config files. + +Origin: upstream, https://sourceforge.net/p/lirc/git/ci/b78df9b2950cf4 +Applied-Upstream: 0.11.0 +--- + daemons/lircd.cpp | 5 +++++ + systemd/lircd.service | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/daemons/lircd.cpp b/daemons/lircd.cpp +index ad8dde9..f559b62 100644 +--- a/daemons/lircd.cpp ++++ b/daemons/lircd.cpp +@@ -2469,6 +2469,11 @@ int main(int argc, char** argv) + if (!nodaemon) + daemonize(); + ++#ifdef HAVE_SYSTEMD ++ /* Tell systemd that we started up correctly */ ++ sd_notify(0, "READY=1"); ++#endif ++ + loop(); + + /* never reached */ +diff --git a/systemd/lircd.service b/systemd/lircd.service +index 7f75805..6af049b 100644 +--- a/systemd/lircd.service ++++ b/systemd/lircd.service +@@ -6,7 +6,7 @@ Wants=lircd-setup.service + After=network.target lircd-setup.service + + [Service] +-Type=simple ++Type=notify + ExecStart=/usr/sbin/lircd --nodaemon + ; User=lirc + ; Group=lirc diff --git a/packages/sysutils/lirc/patches/lirc-0100-disable-python.patch b/packages/sysutils/lirc/patches/lirc-0100-disable-python.patch new file mode 100644 index 000000000..d91175f11 --- /dev/null +++ b/packages/sysutils/lirc/patches/lirc-0100-disable-python.patch @@ -0,0 +1,128 @@ +diff --git a/Makefile.am b/Makefile.am +index 9f3dd143..9619a6eb 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -5,7 +5,9 @@ ACLOCAL_AMFLAGS = -I m4 + AUTOMAKE_OPTIONS = 1.5 check-news dist-bzip2 -Wno-portability \ + subdir-objects + ++if HAVE_PYTHON + include pylint.mak ++endif + + GIT_COMMIT = $(shell git log -1 --pretty=format:%h || echo UNKNOWN) + GIT_DATE = $(shell git log -1 --pretty=format:%cd || echo UNKNOWN) +@@ -34,13 +36,17 @@ MANTAINERCLEANFILES = config.sub install-sh depcomp py-compile \ + AM_DISTCHECK_CONFIGURE_FLAGS = \ + --with-systemdsystemunitdir=$${dc_install_base}/lib/systemd/system + ++if HAVE_PYTHON + BUILT_SOURCES = paths.h python-pkg/lirc/config.py python-pkg/VERSION ++else ++BUILT_SOURCES = paths.h ++endif + + if WITH_SYSTEMDSYSTEMUNITDIR + SYSTEMD_DIR = systemd + endif + +-SUBDIRS = lib daemons tools plugins configs doc $(SYSTEMD_DIR) ++SUBDIRS = lib daemons tools plugins $(SYSTEMD_DIR) + + if INSTALL_ETC + +@@ -61,7 +67,9 @@ endif + + dist_doc_DATA = VERSION + ++if HAVE_PYTHON + nodist_pkgdata_DATA = $(PYTHON_TARBALL) ++endif + + pkgconfigdir = $(libdir)/pkgconfig + dist_pkgconfig_DATA = lirc.pc lirc-driver.pc +@@ -71,6 +79,7 @@ nobase_header_HEADERS = include/media/lirc.h \ + include/linux/input-event-codes.h + header_HEADERS = drivers/irpipe/irpipe.h + ++if HAVE_PYTHON + py_pkgdir = $(pkgdatadir)/python-pkg + dist_py_pkg_DATA = python-pkg/setup.py \ + python-pkg/README.rst +@@ -134,6 +143,8 @@ all-local: + $(if $(VERBOSE),,-q) build + endif + ++endif ++ + install-data-hook: + $(SED) -i -e '/^plugindir/s|/usr/lib|$(libdir)|' \ + $(DESTDIR)$(lirc_confdir)/lirc_options.conf +@@ -170,6 +181,7 @@ fix-version: .phony + $(SED) -i '/DATE/s/=.*/="$(GIT_DATE)"/' $(distdir)/VERSION + $(SED) -i '/REFS/s|=.*|="$(GIT_REFS)"|' $(distdir)/VERSION + ++if HAVE_PYTHON + $(abs_builddir)/python-pkg/setup.py: + cp -ar $(top_srcdir)/python-pkg $(abs_builddir) + chmod -R u+w python-pkg +@@ -193,6 +205,7 @@ python-pkg/lirc/config.py: Makefile $(abs_builddir)/python-pkg/setup.py + @echo 'DOCDIR = "$(docdir)"' >>$@ + @echo 'MODINFO = "$(MODINFO)"' >>$@ + @echo 'VERSION = "$(VERSION)"' >>$@ ++endif + + paths.h: Makefile + @echo "#ifndef PATHS_H" >paths.h +diff --git a/configure.ac b/configure.ac +index 58347d88..48ce5629 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -43,7 +43,8 @@ AC_CHECK_PROG([DOXYGEN],[doxygen],[yes],[no]) + AM_CONDITIONAL(HAVE_DOXYGEN, test x$DOXYGEN = xyes) + LT_INIT([disable-static]) + +-AM_PATH_PYTHON([3.1],,) ++AM_PATH_PYTHON([3.1],,[:]) ++AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) + PKG_CHECK_MODULES([PYTHON],[python-${PYTHON_VERSION}m],,[true]) + test -z "$PYTHON_LIBS" && \ + PKG_CHECK_MODULES([PYTHON], [python-$PYTHON_VERSION],,[true]) +@@ -580,6 +581,7 @@ AX_REPORT_CONDITIONAL([DEVEL]) + AX_REPORT_CONDITIONAL([LINUX_KERNEL]) + AX_REPORT_CONDITIONAL([HAVE_DEVINPUT]) + AX_REPORT_CONDITIONAL([WITH_SYSTEMDSYSTEMUNITDIR]) ++AX_REPORT_CONDITIONAL([HAVE_PYTHON]) + AX_REPORT_CONDITIONAL([HAVE_PYTHON35]) + + echo +diff --git a/tools/Makefile.am b/tools/Makefile.am +index abfb9911..8aff1cff 100644 +--- a/tools/Makefile.am ++++ b/tools/Makefile.am +@@ -71,12 +71,17 @@ xmode2_SOURCES = xmode2.cpp + xmode2_LDADD = @X_LIBS@ @X_PRE_LIBS@ -lX11 @X_EXTRA_LIBS@ \ + $(LIRC_LIBS) + ++if HAVE_PYTHON + dist_bin_SCRIPTS = lirc-config-tool lirc-init-db ++else ++dist_bin_SCRIPTS = ++endif + + if HAVE_DEVINPUT + dist_bin_SCRIPTS += lirc-make-devinput + endif + ++if HAVE_PYTHON + dist_bin_SCRIPTS += pronto2lirc irdb-get irtext2udp + dist_sbin_SCRIPTS = lircd-setup + dist_noinst_SCRIPTS = make_rel_symlink.py check_configs.py +@@ -121,6 +126,7 @@ install-data-hook: + $(PYTHON) $(srcdir)/make_rel_symlink.py \ + $(DESTDIR)/$(pkgdatadir)/configs \ + $(DESTDIR)/$(setupdir)/configs ++endif + + uninstall-hook: + rm -f $(DESTDIR)/$(bindir)/lirc-setup \ diff --git a/packages/sysutils/lirc/scripts/lircd_helper b/packages/sysutils/lirc/scripts/lircd_helper new file mode 100755 index 000000000..8430b4a37 --- /dev/null +++ b/packages/sysutils/lirc/scripts/lircd_helper @@ -0,0 +1,10 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Matthias Reichl (hias@horus.com) + +if [ -e "/storage/.config/lirc_options.conf" ] ; then + LIRCD_OPTIONS="-O /storage/.config/lirc_options.conf" +fi + +exec /usr/sbin/lircd $LIRCD_OPTIONS "$@" /storage/.config/lircd.conf diff --git a/packages/sysutils/lirc/scripts/lircd_uinput_helper b/packages/sysutils/lirc/scripts/lircd_uinput_helper new file mode 100755 index 000000000..46685cd4f --- /dev/null +++ b/packages/sysutils/lirc/scripts/lircd_uinput_helper @@ -0,0 +1,10 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017 Matthias Reichl (hias@horus.com) + +if [ -e "/storage/.config/lirc_options.conf" ] ; then + LIRCD_OPTIONS="-O /storage/.config/lirc_options.conf" +fi + +exec /usr/sbin/lircd-uinput $LIRCD_OPTIONS "$@" diff --git a/packages/sysutils/lirc/system.d/lircd-uinput.service b/packages/sysutils/lirc/system.d/lircd-uinput.service new file mode 100644 index 000000000..feb4a2ea8 --- /dev/null +++ b/packages/sysutils/lirc/system.d/lircd-uinput.service @@ -0,0 +1,12 @@ +[Unit] +Documentation=http://lirc.org/html/configure.html +Description=Forward LIRC button presses as uinput events +ConditionPathExists=/storage/.config/lircd.conf +After=lircd.service + +[Service] +Type=simple +ExecStart=/usr/lib/coreelec/lircd_uinput_helper --add-release-events + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/lirc/system.d/lircd.service b/packages/sysutils/lirc/system.d/lircd.service new file mode 100644 index 000000000..0d12b3478 --- /dev/null +++ b/packages/sysutils/lirc/system.d/lircd.service @@ -0,0 +1,12 @@ +[Unit] +Documentation=http://lirc.org/html/configure.html +Description=Flexible IR remote input/output application support +ConditionPathExists=/storage/.config/lircd.conf +After=network.target + +[Service] +Type=simple +ExecStart=/usr/lib/coreelec/lircd_helper --nodaemon + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/lirc/system.d/lircd.socket b/packages/sysutils/lirc/system.d/lircd.socket new file mode 100644 index 000000000..03a5c1bd5 --- /dev/null +++ b/packages/sysutils/lirc/system.d/lircd.socket @@ -0,0 +1,6 @@ +[Socket] +ListenStream=/run/lirc/lircd.socket + +[Install] +WantedBy=sockets.target +Also=lircd.service diff --git a/packages/sysutils/lirc/tmpfiles.d/z_61_lirc.conf b/packages/sysutils/lirc/tmpfiles.d/z_61_lirc.conf new file mode 100644 index 000000000..d1f150c68 --- /dev/null +++ b/packages/sysutils/lirc/tmpfiles.d/z_61_lirc.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /run/lirc 0755 root root - - diff --git a/packages/sysutils/lm_sensors/package.mk b/packages/sysutils/lm_sensors/package.mk new file mode 100644 index 000000000..9f7a42a05 --- /dev/null +++ b/packages/sysutils/lm_sensors/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lm_sensors" +PKG_VERSION="e8afbda10fba571c816abddcb5c8180afc435bba" +PKG_SHA256="255b9a9b30c7969b3df0460392a807239c18b15baac1ff33ff5fef3b1cc1169d" +PKG_ARCH="arm x86_64" +PKG_LICENSE="GPL" +PKG_SITE="http://secure.netroedge.com/~lm78/" +PKG_URL="https://github.com/groeck/lm-sensors/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Provides user-space support for the hardware monitoring drivers." + +PKG_MAKEINSTALL_OPTS_TARGET="PREFIX=/usr" + +pre_make_target() { + PKG_MAKE_OPTS_TARGET="PREFIX=/usr CC=$CC AR=$AR" + + export CFLAGS="$TARGET_CFLAGS" + export CPPFLAGS="$TARGET_CPPFLAGS" +} + +makeinstall_target() { + : +} diff --git a/packages/sysutils/lm_sensors/patches/lm_sensors-01_link-static.patch b/packages/sysutils/lm_sensors/patches/lm_sensors-01_link-static.patch new file mode 100644 index 000000000..8535cbb4f --- /dev/null +++ b/packages/sysutils/lm_sensors/patches/lm_sensors-01_link-static.patch @@ -0,0 +1,25 @@ +From 0b2b2e26bbae3d06580080a66a85e5e0d90ea9f6 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sun, 10 Aug 2014 14:21:19 +0300 +Subject: [PATCH] link static + +--- + prog/sensors/Module.mk | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/prog/sensors/Module.mk b/prog/sensors/Module.mk +index b656441..ad59874 100644 +--- a/prog/sensors/Module.mk ++++ b/prog/sensors/Module.mk +@@ -40,7 +40,7 @@ REMOVESENSORSMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGSENSORSMAN1DIR)/% + LIBICONV := $(shell if /sbin/ldconfig -p | grep -q '/libiconv\.so$$' ; then echo \-liconv; else echo; fi) + + $(PROGSENSORSTARGETS): $(PROGSENSORSSOURCES:.c=.ro) lib/$(LIBSHBASENAME) +- $(CC) $(EXLDFLAGS) -o $@ $(PROGSENSORSSOURCES:.c=.ro) $(LIBICONV) -Llib -lsensors ++ $(CC) $(EXLDFLAGS) -o $@ $(PROGSENSORSSOURCES:.c=.ro) $(LIBICONV) -Llib -Wl,-Bstatic -lsensors -Wl,-Bdynamic -lm + + all-prog-sensors: $(PROGSENSORSTARGETS) + user :: all-prog-sensors +-- +1.7.2.5 + diff --git a/packages/sysutils/lshw/package.mk b/packages/sysutils/lshw/package.mk new file mode 100644 index 000000000..7cd3e40eb --- /dev/null +++ b/packages/sysutils/lshw/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="lshw" +PKG_VERSION="B.02.18" +PKG_SHA256="ae22ef11c934364be4fd2a0a1a7aadf4495a0251ec6979da280d342a89ca3c2f" +PKG_LICENSE="GPL" +PKG_SITE="http://ezix.org/project/wiki/HardwareLiSter" +PKG_URL="http://ezix.org/software/files/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small tool to provide detailed information on the hardware configuration of the machine." + +make_target() { + make CXX=$CXX -C src/ +} + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/mc/package.mk b/packages/sysutils/mc/package.mk new file mode 100644 index 000000000..c5d1c884c --- /dev/null +++ b/packages/sysutils/mc/package.mk @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mc" +PKG_VERSION="4.8.21" +PKG_SHA256="8f37e546ac7c31c9c203a03b1c1d6cb2d2f623a300b86badfd367e5559fe148c" +PKG_LICENSE="GPL" +PKG_SITE="http://www.midnight-commander.org" +PKG_URL="http://ftp.midnight-commander.org/mc-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain gettext:host glib libssh2 libtool:host ncurses pcre" +PKG_LONGDESC="Midnight Commander is a text based filemanager that emulates Norton Commander." + +PKG_CONFIGURE_OPTS_TARGET=" \ + --datadir=/storage/.kodi/addons/virtual.system-tools/data \ + --libexecdir=/storage/.kodi/addons/virtual.system-tools/mclib \ + --with-homedir=/storage/.kodi/userdata/addon_data/virtual.system-tools \ + --sysconfdir=/storage/.kodi/addons/virtual.system-tools/etc \ + --with-screen=ncurses \ + --with-sysroot=$SYSROOT_PREFIX \ + --disable-aspell \ + --without-diff-viewer \ + --disable-doxygen-doc \ + --disable-doxygen-dot \ + --disable-doxygen-html \ + --with-gnu-ld \ + --without-libiconv-prefix \ + --without-libintl-prefix \ + --with-internal-edit \ + --disable-mclib \ + --with-subshell \ + --enable-vfs-extfs \ + --enable-vfs-ftp \ + --enable-vfs-sftp \ + --enable-vfs-tar \ + --without-x" + +pre_configure_target() { + LDFLAGS="$LDFLAGS -lcrypto -lssl" +} + +post_makeinstall_target() { + rm -rf $INSTALL/storage/.kodi/addons/virtual.system-tools/data/locale + rm -rf $INSTALL/storage/.kodi/addons/virtual.system-tools/data/mc/help/mc.hlp.* + mv $INSTALL/usr/bin/mc $INSTALL/usr/bin/mc-bin + rm -f $INSTALL/usr/bin/{mcedit,mcview} + cp $PKG_DIR/wrapper/* $INSTALL/usr/bin +} diff --git a/packages/sysutils/mc/wrapper/mc b/packages/sysutils/mc/wrapper/mc new file mode 100644 index 000000000..c006477eb --- /dev/null +++ b/packages/sysutils/mc/wrapper/mc @@ -0,0 +1,4 @@ +#!/bin/sh +HISTFILE="/run/mc_histfile" +export HISTFILE +exec mc-bin "$@" diff --git a/packages/sysutils/mc/wrapper/mcedit b/packages/sysutils/mc/wrapper/mcedit new file mode 100644 index 000000000..43b7815f4 --- /dev/null +++ b/packages/sysutils/mc/wrapper/mcedit @@ -0,0 +1,4 @@ +#!/bin/sh +HISTFILE="/run/mc_histfile" +export HISTFILE +exec mc-bin -e "$@" diff --git a/packages/sysutils/mc/wrapper/mcview b/packages/sysutils/mc/wrapper/mcview new file mode 100644 index 000000000..7aec5c875 --- /dev/null +++ b/packages/sysutils/mc/wrapper/mcview @@ -0,0 +1,4 @@ +#!/bin/sh +HISTFILE="/run/mc_histfile" +export HISTFILE +exec mc-bin -v "$@" diff --git a/packages/sysutils/mrxvt/package.mk b/packages/sysutils/mrxvt/package.mk new file mode 100644 index 000000000..cbd9caa1c --- /dev/null +++ b/packages/sysutils/mrxvt/package.mk @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mrxvt" +PKG_VERSION="0.5.4" +PKG_SHA256="f403ad5a908fcd38a55ed0a7e1b85584cb77be8781199653a39b8af1a9ad10d7" +PKG_ARCH="i386 x86_64" +PKG_LICENSE="GPL" +PKG_SITE="http://materm.sourceforge.net/" +PKG_URL="$SOURCEFORGE_SRC/materm/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libX11" +PKG_LONGDESC="A lightweight and powerful multi-tabbed X terminal emulator based on the popular rxvt and aterm." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_setpgrp_void=no \ + --enable-minimal \ + --disable-frills \ + --enable-keepscrolling \ + --disable-selectionscrolling \ + --enable-mousewheel \ + --disable-mouseslipwheel \ + --enable-rxvt-scroll \ + --disable-half-shadow \ + --enable-lastlog \ + --enable-sessionmgr \ + --enable-linespace \ + --enable-24bits \ + --enable-256colors \ + --enable-cursor-blink \ + --enable-pointer-blank \ + --disable-text-shadow \ + --disable-menubar \ + --disable-transparency \ + --disable-tinting \ + --disable-xrender \ + --disable-xpm \ + --disable-jpeg \ + --disable-png \ + --disable-xft \ + --enable-ttygid \ + --enable-backspace-key \ + --enable-delete-key \ + --disable-resources \ + --disable-swapscreen \ + --disable-use-fifo \ + --disable-greek \ + --disable-xim \ + --disable-utempter\ + --with-term=xterm" + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/mrxvt/patches/mrxvt-01_xterm.patch b/packages/sysutils/mrxvt/patches/mrxvt-01_xterm.patch new file mode 100644 index 000000000..3418f7c70 --- /dev/null +++ b/packages/sysutils/mrxvt/patches/mrxvt-01_xterm.patch @@ -0,0 +1,11 @@ +--- mrxvt-0.5.4/src/rxvt.h.org 2008-08-04 09:41:35.000000000 +0200 ++++ mrxvt-0.5.4/src/rxvt.h 2016-05-24 19:23:28.000000000 +0200 +@@ -631,7 +631,7 @@ + #define APL_NAME "mrxvt" /* normal name */ + + /* COLORTERM, TERM environment variables */ +-#define COLORTERMENV "rxvt" ++#define COLORTERMENV "xterm" + #ifdef BACKGROUND_IMAGE + # define COLORTERMENVFULL COLORTERMENV "-xpm" + #else diff --git a/packages/sysutils/mtpfs/package.mk b/packages/sysutils/mtpfs/package.mk new file mode 100644 index 000000000..e1e3c0ecb --- /dev/null +++ b/packages/sysutils/mtpfs/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mtpfs" +PKG_VERSION="fd3864dd6f0e8183fa2598d4cf890401d3a1e09a" +PKG_SHA256="f004136a82452d13362581277eb2496033aa13a6c3f35d0501327248f3120456" +PKG_LICENSE="GPL" +PKG_SITE="http://www.adebenham.com/mtpfs/" +PKG_URL="https://github.com/cjd/mtpfs/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain fuse glib libmtp" +PKG_LONGDESC="MTPfs is a FUSE filesystem that supports reading and writing from any MTP device." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-mad" + +# TODO: mtpfs runs host utils while building, fix and set +pre_configure_target() { + export LIBS="-lusb-1.0 -ludev" +} + +makeinstall_target() { + : # nop +} diff --git a/packages/sysutils/nmon/package.mk b/packages/sysutils/nmon/package.mk new file mode 100644 index 000000000..a8c4273ff --- /dev/null +++ b/packages/sysutils/nmon/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nmon" +PKG_VERSION="411b08f1c98bca8b24670fc2d9ee6325b4fcb3d2" +PKG_SHA256="aa88257728e820db10b1f04792dfcc1b8a483de51bfda70db016da016a4879a2" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/axibase/nmon" +PKG_URL="https://github.com/axibase/nmon/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Systems administrator, tuner, benchmark tool gives you a huge amount of important performance information in one go." +PKG_TOOLCHAIN="manual" + +make_target() { + case $ARCH in + x86_64) + arch="X86" + ;; + *) + arch="arm" + ;; + esac + CFLAGS="$CFLAGS -g -O3 -Wall -D JFS -D GETUSER -D LARGEMEM" + LDFLAGS="$LDFLAGS -lncurses -lm -g" + $CC -o nmon lmon*.c $CFLAGS $LDFLAGS -D $arch -D KERNEL_2_6_18 +} diff --git a/packages/sysutils/ntfs-3g_ntfsprogs/package.mk b/packages/sysutils/ntfs-3g_ntfsprogs/package.mk new file mode 100644 index 000000000..4961fe457 --- /dev/null +++ b/packages/sysutils/ntfs-3g_ntfsprogs/package.mk @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="ntfs-3g_ntfsprogs" +PKG_VERSION="2017.3.23" +PKG_SHA256="3e5a021d7b761261836dcb305370af299793eedbded731df3d6943802e1262d5" +PKG_LICENSE="GPL" +PKG_SITE="http://www.ntfs-3g.org/" +PKG_URL="http://tuxera.com/opensource/$PKG_NAME-$PKG_VERSION.tgz" +PKG_DEPENDS_TARGET="toolchain fuse libgcrypt" +PKG_LONGDESC="A NTFS driver with read and write support." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+lto" + +PKG_CONFIGURE_OPTS_TARGET="--exec-prefix=/usr/ \ + --disable-dependency-tracking \ + --disable-library \ + --enable-posix-acls \ + --enable-mtab \ + --enable-ntfsprogs \ + --disable-crypto \ + --with-fuse=external \ + --with-uuid" + +post_makeinstall_target() { + # dont include ntfsprogs. + for i in $INSTALL/usr/bin/*; do + if [ "$(basename $i)" != "ntfs-3g" ]; then + rm $i + fi + done + + rm -rf $INSTALL/sbin + rm -rf $INSTALL/usr/sbin/ntfsclone + rm -rf $INSTALL/usr/sbin/ntfscp + rm -rf $INSTALL/usr/sbin/ntfsundelete + + mkdir -p $INSTALL/usr/sbin + ln -sf /usr/bin/ntfs-3g $INSTALL/usr/sbin/mount.ntfs + ln -sf /usr/sbin/mkntfs $INSTALL/usr/sbin/mkfs.ntfs +} diff --git a/packages/sysutils/ntfs-3g_ntfsprogs/patches/ntfs-3g_ntfsprogs-001-fix-mounting-after-Win10-Creators-Update.patch b/packages/sysutils/ntfs-3g_ntfsprogs/patches/ntfs-3g_ntfsprogs-001-fix-mounting-after-Win10-Creators-Update.patch new file mode 100644 index 000000000..a5f76321a --- /dev/null +++ b/packages/sysutils/ntfs-3g_ntfsprogs/patches/ntfs-3g_ntfsprogs-001-fix-mounting-after-Win10-Creators-Update.patch @@ -0,0 +1,28 @@ +From 801c894b3723ed6345982e0105b342ec119f81ee Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sat, 16 Jun 2018 15:38:06 +0100 +Subject: [PATCH] Fix for NTFS partitions mounted with Windows 10 Creators + Update + +See: https://bugzilla.redhat.com/show_bug.cgi?id=1527231 +--- + libntfs-3g/volume.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c +index 68b8ee1..d36c7d5 100644 +--- a/libntfs-3g/volume.c ++++ b/libntfs-3g/volume.c +@@ -959,7 +959,8 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) + vol->mftmirr_size = l; + } + ntfs_log_debug("Comparing $MFTMirr to $MFT...\n"); +- for (i = 0; i < vol->mftmirr_size; ++i) { ++ /* Windows 10 does not update the full $MFTMirr any more */ ++ for (i = 0; (i < vol->mftmirr_size) && (i < FILE_first_user); ++i) { + MFT_RECORD *mrec, *mrec2; + const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", + "$Volume", "$AttrDef", "root directory", "$Bitmap", +-- +2.14.1 + diff --git a/packages/sysutils/open-iscsi/package.mk b/packages/sysutils/open-iscsi/package.mk new file mode 100644 index 000000000..161d9cde8 --- /dev/null +++ b/packages/sysutils/open-iscsi/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2012 Yann Cézard (eesprit@free.fr) +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="open-iscsi" +PKG_VERSION="bf39941" +PKG_SHA256="92b9f0a27a9a373b14eab7b12f1bfff5d4857695a688dc4434df8e7623354588" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/mikechristie/open-iscsi" +PKG_URL="https://github.com/mikechristie/open-iscsi/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_INIT="toolchain util-linux" +PKG_LONGDESC="The open-iscsi package allows you to mount iSCSI targets." +PKG_TOOLCHAIN="configure" + +PKG_MAKE_OPTS_INIT="user" + +pre_configure_init() { + export OPTFLAGS="$CFLAGS $LDFLAGS" +} + +configure_init() { + cd utils/open-isns + ./configure --host=$TARGET_NAME \ + --build=$HOST_NAME \ + --with-security=no + cd ../.. +} + +makeinstall_init() { + mkdir -p $INSTALL/usr/sbin + cp -P $PKG_BUILD/usr/iscsistart $INSTALL/usr/sbin +} diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-01_dynamic_linked_iscsistart.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-01_dynamic_linked_iscsistart.patch new file mode 100644 index 000000000..27d30311b --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-01_dynamic_linked_iscsistart.patch @@ -0,0 +1,11 @@ +--- a/usr/Makefile 2011-08-05 11:54:52.000000000 +0200 ++++ b/usr/Makefile 2011-08-05 11:55:06.000000000 +0200 +@@ -63,7 +63,7 @@ + + iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \ + iscsistart.o statics.o +- $(CC) $(CFLAGS) -static $^ -o $@ ++ $(CC) $(CFLAGS) $^ -o $@ + clean: + rm -f *.o $(PROGRAMS) .depend $(LIBSYS) + diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-02-cross_compile.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-02-cross_compile.patch new file mode 100644 index 000000000..38e82d7ea --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-02-cross_compile.patch @@ -0,0 +1,64 @@ +diff --git a/usr/Makefile b/usr/Makefile +index fd14a10..41b7140 100644 +--- a/usr/Makefile ++++ b/usr/Makefile +@@ -66,6 +66,6 @@ clean: + rm -f *.o $(PROGRAMS) .depend $(LIBSYS) + + depend: +- gcc $(CFLAGS) -M `ls *.c` > .depend ++ $(CC) $(CFLAGS) -M `ls *.c` > .depend + + -include .depend +diff --git a/utils/Makefile b/utils/Makefile +index 2c7e891..440e24e 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -12,6 +12,6 @@ clean: + rm -f *.o $(PROGRAMS) .depend + + depend: +- gcc $(CFLAGS) -M `ls *.c` > .depend ++ $(CC) $(CFLAGS) -M `ls *.c` > .depend + + -include .depend +diff --git a/utils/fwparam_ibft/Makefile b/utils/fwparam_ibft/Makefile +index c72bb7f..3d2c2a5 100644 +--- a/utils/fwparam_ibft/Makefile ++++ b/utils/fwparam_ibft/Makefile +@@ -38,6 +38,6 @@ clean: + $(OBJS): prom_parse.tab.h prom_parse.h fwparam_ibft.h + + depend: +- gcc $(CFLAGS) -M `ls *.c` > .depend ++ $(CC) $(CFLAGS) -M `ls *.c` > .depend + + -include .depend +diff --git a/utils/open-isns/Makefile.in b/utils/open-isns/Makefile.in +index a27199c..a76649f 100644 +--- a/utils/open-isns/Makefile.in ++++ b/utils/open-isns/Makefile.in +@@ -73,9 +73,9 @@ distclean:: + rm -rf autom4te.cache + + $(LIB): $(LIBOBJS) +- ar cr $@ $(LIBOBJS) ++ $(AR) cr $@ $(LIBOBJS) + + depend: +- gcc $(CFLAGS) -M `ls *.c` > .depend ++ $(CC) $(CFLAGS) -M `ls *.c` > .depend + + -include .depend +diff --git a/utils/sysdeps/Makefile b/utils/sysdeps/Makefile +index 53c10e5..effe013 100644 +--- a/utils/sysdeps/Makefile ++++ b/utils/sysdeps/Makefile +@@ -10,6 +10,6 @@ clean: + rm -f *.o .depend + + depend: +- gcc $(CFLAGS) -M `ls *.c` > .depend ++ $(CC) $(CFLAGS) -M `ls *.c` > .depend + + -include .depend diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-03_enable-multicast.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-03_enable-multicast.patch new file mode 100644 index 000000000..10ca6e23e --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-03_enable-multicast.patch @@ -0,0 +1,26 @@ +From d5b4400d2c50190474a6000d60f05deb95f97e0b Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Thu, 8 Aug 2013 18:08:44 +0300 +Subject: [PATCH] enable multicast + +source: https://groups.google.com/forum/#!msg/open-iscsi/nuLFqxgsHAA/53-JE3gNNjEJ +--- + usr/iscsi_net_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/usr/iscsi_net_util.c b/usr/iscsi_net_util.c +index 6d0ebf9..3801ac7 100644 +--- a/usr/iscsi_net_util.c ++++ b/usr/iscsi_net_util.c +@@ -229,7 +229,7 @@ int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway, + /* Bring up interface */ + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, netdev, IFNAMSIZ); +- ifr.ifr_flags = IFF_UP | IFF_RUNNING; ++ ifr.ifr_flags = IFF_UP | IFF_RUNNING | IFF_MULTICAST; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { + log_error("Could not bring up netdev %s (err %d - %s)", + netdev, errno, strerror(errno)); +-- +1.8.1.2 + diff --git a/packages/sysutils/open-iscsi/patches/open-iscsi-04-no_iscsiuio.patch b/packages/sysutils/open-iscsi/patches/open-iscsi-04-no_iscsiuio.patch new file mode 100644 index 000000000..106e84a9e --- /dev/null +++ b/packages/sysutils/open-iscsi/patches/open-iscsi-04-no_iscsiuio.patch @@ -0,0 +1,25 @@ +diff -Naur open-iscsi-bf39941/Makefile open-iscsi-bf39941.patch/Makefile +--- open-iscsi-bf39941/Makefile 2013-08-08 17:06:46.000000000 +0200 ++++ open-iscsi-bf39941.patch/Makefile 2013-08-08 18:02:13.009068581 +0200 +@@ -26,20 +26,18 @@ + + all: user + +-user: utils/open-isns/Makefile iscsiuio/Makefile ++user: utils/open-isns/Makefile + $(MAKE) -C utils/open-isns + $(MAKE) -C utils/sysdeps + $(MAKE) -C utils/fwparam_ibft + $(MAKE) -C usr + $(MAKE) -C utils +- $(MAKE) -C iscsiuio + @echo + @echo "Compilation complete Output file" + @echo "----------------------------------- ----------------" + @echo "Built iSCSI daemon: usr/iscsid" + @echo "Built management application: usr/iscsiadm" + @echo "Built boot tool: usr/iscsistart" +- @echo "Built iscsiuio daemon: iscsiuio/src/unix/iscsiuio" + @echo + @echo "Read README file for detailed information." + diff --git a/packages/sysutils/open-vm-tools/package.mk b/packages/sysutils/open-vm-tools/package.mk new file mode 100644 index 000000000..b5be36883 --- /dev/null +++ b/packages/sysutils/open-vm-tools/package.mk @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2011 Anthony Nash (nash.ant@gmail.com) +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="open-vm-tools" +PKG_VERSION="stable-10.3.10" +PKG_SHA256="6e39e643edcd85bae04ba8db608bd500d14ff3771e6e89b171ffb31020fed945" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/vmware/open-vm-tools" +PKG_URL="https://github.com/vmware/open-vm-tools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain fuse glib:host glib libdnet libtirpc" +PKG_LONGDESC="open-vm-tools: open source implementation of VMware Tools" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-docs \ + --disable-tests \ + --disable-deploypkg \ + --without-pam \ + --without-gtk2 \ + --without-gtkmm \ + --without-ssl \ + --without-x \ + --without-xerces \ + --without-icu \ + --without-kernel-modules \ + --with-udev-rules-dir=/usr/lib/udev/rules.d/ \ + --with-sysroot=$SYSROOT_PREFIX" + +post_unpack() { + mv $PKG_BUILD/$PKG_NAME/* $PKG_BUILD/ + + sed -i -e 's|.*common-agent/etc/config/Makefile.*||' $PKG_BUILD/configure.ac + mkdir -p $PKG_BUILD/common-agent/etc/config +} + +pre_configure_target() { + export LIBS="-ldnet -ltirpc" +} + +post_makeinstall_target() { + rm -rf $INSTALL/sbin + rm -rf $INSTALL/usr/share + rm -rf $INSTALL/etc/vmware-tools/scripts/vmware/network + + find $INSTALL/etc/vmware-tools/ -type f | xargs sed -i '/.*expr.*/d' +} + +post_install() { + enable_service vmtoolsd.service + enable_service vmware-vmblock-fuse.service +} diff --git a/packages/sysutils/open-vm-tools/system.d/vmtoolsd.service b/packages/sysutils/open-vm-tools/system.d/vmtoolsd.service new file mode 100644 index 000000000..1b9924c1f --- /dev/null +++ b/packages/sysutils/open-vm-tools/system.d/vmtoolsd.service @@ -0,0 +1,9 @@ +[Unit] +Description=Open Virtual Machine Tools (VMware Tools) +ConditionVirtualization=vmware + +[Service] +ExecStart=/usr/bin/vmtoolsd + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/open-vm-tools/system.d/vmware-vmblock-fuse.service b/packages/sysutils/open-vm-tools/system.d/vmware-vmblock-fuse.service new file mode 100644 index 000000000..9e4d2a312 --- /dev/null +++ b/packages/sysutils/open-vm-tools/system.d/vmware-vmblock-fuse.service @@ -0,0 +1,12 @@ +[Unit] +Description=Open Virtual Machine Tools (vmware-vmblock-fuse) +ConditionVirtualization=vmware + +[Service] +Type=simple +RuntimeDirectory=vmblock-fuse +RuntimeDirectoryMode=755 +ExecStart=/usr/bin/vmware-vmblock-fuse -d -f -o subtype=vmware-vmblock,default_permissions,allow_other /run/vmblock-fuse + +[Install] +WantedBy=multi-user.target diff --git a/packages/sysutils/parted/package.mk b/packages/sysutils/parted/package.mk new file mode 100644 index 000000000..818ab3cf0 --- /dev/null +++ b/packages/sysutils/parted/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="parted" +PKG_VERSION="3.2" +PKG_SHA256="858b589c22297cacdf437f3baff6f04b333087521ab274f7ab677cb8c6bb78e4" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/parted/" +PKG_URL="http://ftpmirror.gnu.org/parted/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="toolchain util-linux:host" +PKG_DEPENDS_TARGET="toolchain util-linux parted:host" +PKG_DEPENDS_INIT="toolchain util-linux:init parted" +PKG_LONGDESC="GNU Parted is a program for creating, destroying, resizing, checking and copying partitions." + +PKG_CONFIGURE_OPTS_TARGET="--disable-device-mapper \ + --disable-shared \ + --without-readline \ + --disable-rpath \ + --with-gnu-ld" + +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_TARGET" + +configure_init() { + : # reuse configure_target() +} + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + mkdir -p $INSTALL/sbin + cp ../.$TARGET_NAME/parted/parted $INSTALL/sbin + cp ../.$TARGET_NAME/partprobe/partprobe $INSTALL/sbin +} diff --git a/packages/sysutils/parted/patches/parted-0001-buildfix.patch b/packages/sysutils/parted/patches/parted-0001-buildfix.patch new file mode 100644 index 000000000..88b2ada7e --- /dev/null +++ b/packages/sysutils/parted/patches/parted-0001-buildfix.patch @@ -0,0 +1,45 @@ +diff -Naur parted-3.2/libparted/arch/linux.c parted-3.2.patch/libparted/arch/linux.c +--- parted-3.2/libparted/arch/linux.c 2014-06-15 21:15:54.000000000 +0200 ++++ parted-3.2.patch/libparted/arch/linux.c 2014-08-04 01:57:47.626611437 +0200 +@@ -2307,6 +2307,7 @@ + static char * + dm_canonical_path (PedDevice const *dev) + { ++#ifdef ENABLE_DEVICE_MAPPER + LinuxSpecific const *arch_specific = LINUX_SPECIFIC (dev); + + /* Get map name from devicemapper */ +@@ -2324,6 +2325,7 @@ + dm_task_destroy (task); + return dev_name; + err: ++#endif + return NULL; + } + +@@ -2944,13 +2946,14 @@ + unsigned long long *start, + unsigned long long *length); + +- ++#ifdef ENABLE_DEVICE_MAPPER + if (disk->dev->type == PED_DEVICE_DM) { + add_partition = _dm_add_partition; + remove_partition = _dm_remove_partition; + resize_partition = _dm_resize_partition; + get_partition_start_and_length = _dm_get_partition_start_and_length; + } else { ++#endif + add_partition = _blkpg_add_partition; + remove_partition = _blkpg_remove_partition; + #ifdef BLKPG_RESIZE_PARTITION +@@ -2959,7 +2962,9 @@ + resize_partition = NULL; + #endif + get_partition_start_and_length = _kernel_get_partition_start_and_length; ++#ifdef ENABLE_DEVICE_MAPPER + } ++#endif + + /* lpn = largest partition number. + * for remove pass, use greater of device or label limit */ diff --git a/packages/sysutils/parted/patches/parted-0002-buildfix-glibc-2.28.patch b/packages/sysutils/parted/patches/parted-0002-buildfix-glibc-2.28.patch new file mode 100644 index 000000000..8e77a9600 --- /dev/null +++ b/packages/sysutils/parted/patches/parted-0002-buildfix-glibc-2.28.patch @@ -0,0 +1,29 @@ +From b79bdebf285575ec2c3e8944d951655ef8c97a23 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Tue, 21 Jun 2016 15:01:08 -0400 +Subject: [PATCH] include sysmacros.h for major/minor/makedev + +Linux C libs are moving away from including this header implicitly via +sys/types.h, so include it explicitly. + +Upstream-Status: Pending +Signed-off-by: Martin Jansa +--- + libparted/arch/linux.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index 0f18904..b302d63 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include /* for uname() */ + #include +-- +2.14.1 + diff --git a/packages/sysutils/patch/package.mk b/packages/sysutils/patch/package.mk new file mode 100644 index 000000000..9d93d0373 --- /dev/null +++ b/packages/sysutils/patch/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="patch" +PKG_VERSION="2.7.6" +PKG_SHA256="ac610bda97abe0d9f6b7c963255a11dcb196c25e337c61f94e4778d632f1d8fd" +PKG_LICENSE="GPL" +PKG_SITE="http://savannah.gnu.org/projects/patch/" +PKG_URL="http://ftpmirror.gnu.org/patch/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Patch takes a patch file containing a difference listing produced by the diff." + +PKG_CONFIGURE_OPTS_TARGET="--disable-xattr" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/pciutils/package.mk b/packages/sysutils/pciutils/package.mk new file mode 100644 index 000000000..019fd8cd3 --- /dev/null +++ b/packages/sysutils/pciutils/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pciutils" +PKG_VERSION="3.6.2" +PKG_SHA256="db452ec986edefd88af0d222d22f6102f8030a8633fdfe846c3ae4bde9bb93f3" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="http://mj.ucw.cz/pciutils.shtml" +PKG_URL="http://www.kernel.org/pub/software/utils/pciutils/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain kmod systemd" +PKG_LONGDESC="Utilities for inspecting devices connected to the PCI bus and the PCI vendor/product ID database." + +PKG_MAKE_OPTS="PREFIX=/usr SHARED=no STRIP= IDSDIR=/usr/share" + +make_target() { + make OPT="$CFLAGS" \ + CROSS_COMPILE=${TARGET_PREFIX} \ + HOST=$TARGET_ARCH-linux \ + $PKG_MAKE_OPTS \ + ZLIB=no DNS=no LIBKMOD=yes HWDB=yes +} + +makeinstall_target() { + make $PKG_MAKE_OPTS DESTDIR=$SYSROOT_PREFIX install + make $PKG_MAKE_OPTS DESTDIR=$SYSROOT_PREFIX install-lib + make $PKG_MAKE_OPTS DESTDIR=$INSTALL install-lib + if [ "$TARGET_ARCH" = x86_64 ]; then + make $PKG_MAKE_OPTS DESTDIR=$INSTALL install + fi +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/sbin/setpci + rm -rf $INSTALL/usr/sbin/update-pciids + rm -rf $INSTALL/usr/share +} diff --git a/packages/sysutils/pciutils/patches/pciutils-01-fix-pkgconf.patch b/packages/sysutils/pciutils/patches/pciutils-01-fix-pkgconf.patch new file mode 100644 index 000000000..cee1da509 --- /dev/null +++ b/packages/sysutils/pciutils/patches/pciutils-01-fix-pkgconf.patch @@ -0,0 +1,27 @@ +From 4dd9a1b445269aa24626b1cfb85d3c22bc0e64bb Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 16 Aug 2014 14:25:18 +0300 +Subject: [PATCH] fix pkgconf + +--- + lib/libpci.pc.in | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/libpci.pc.in b/lib/libpci.pc.in +index 9d7e8a0..38827ba 100644 +--- a/lib/libpci.pc.in ++++ b/lib/libpci.pc.in +@@ -1,7 +1,7 @@ + prefix=@PREFIX@ +-includedir=@INCDIR@ +-libdir=@LIBDIR@ +-idsdir=@IDSDIR@ ++includedir=${prefix}/include ++libdir=${prefix}/lib ++idsdir=${prefix}/share + + Name: libpci + Description: libpci +-- +1.7.2.5 + diff --git a/packages/sysutils/pv/package.mk b/packages/sysutils/pv/package.mk new file mode 100644 index 000000000..294027bf0 --- /dev/null +++ b/packages/sysutils/pv/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pv" +PKG_VERSION="1.6.6" +PKG_SHA256="608ef935f7a377e1439c181c4fc188d247da10d51a19ef79bcdee5043b0973f1" +PKG_LICENSE="GNU" +PKG_SITE="http://www.ivarch.com/programs/pv.shtml" +PKG_URL="http://www.ivarch.com/programs/sources/pv-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Pipe Viwer can be inserted into any normal pipeline between two processes." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static-nls" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/rclone/cloud-sync-rules.conf b/packages/sysutils/rclone/cloud-sync-rules.conf new file mode 100644 index 000000000..17be05878 --- /dev/null +++ b/packages/sysutils/rclone/cloud-sync-rules.conf @@ -0,0 +1,32 @@ +# Exclude mac folders +- .Trashes/** +- .Spotlight-V100/** + +# Main dir is /storage/roms +# COMMONS ++ *.sav ++ *.srm ++ *.state* ++ *.auto +# LZDOOM ++ *.zds +# PPSSPP ++ gamedata/ppsspp/PSP/** +# MS-DOS ++ pc/*.zip +# POKEMINI ++ *.eep +# SCREENSHOTS ++ screenshots/** +# JELOS Backups ++ JELOS_BACKUP.zip +# VARIOUS ++ *.ec ++ *.nv ++ *.hi ++ *.hs ++ *.fs + +# exclude everything +- bios/** +- * diff --git a/packages/sysutils/rclone/cloud-sync.conf b/packages/sysutils/rclone/cloud-sync.conf new file mode 100644 index 000000000..c51f59ed1 --- /dev/null +++ b/packages/sysutils/rclone/cloud-sync.conf @@ -0,0 +1,5 @@ +# CLOUD_SYNC_PATH is where files on the remote go. For S3 this includes the bucket name. +CLOUD_SYNC_PATH="/351backup/" + +# CLOUD_SYNC_REMOTE must match the remote name in rclone.conf +CLOUD_SYNC_REMOTE="351remote" diff --git a/packages/sysutils/rclone/package.mk b/packages/sysutils/rclone/package.mk new file mode 100644 index 000000000..0c6c9450b --- /dev/null +++ b/packages/sysutils/rclone/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Xargon (https://github.com/XargonWan) + +PKG_NAME="rclone" +PKG_VERSION="1.57.0" +PKG_ARCH="aarch64" +PKG_URL="https://downloads.rclone.org/v$PKG_VERSION/rclone-v$PKG_VERSION-linux-arm64.zip" +PKG_SECTION="tools" +PKG_SHORTDESC="rsync for cloud storage" +PKG_TOOLCHAIN="manual" + +pre_unpack() { + unzip sources/rclone/rclone-$PKG_VERSION.zip -d $PKG_BUILD/ +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin/ + mkdir -p $INSTALL/usr/config/ + cp $PKG_BUILD/rclone-v$PKG_VERSION-linux-arm64/rclone $INSTALL/usr/bin/ + cp $PKG_DIR/cloud-sync-rules.conf $INSTALL/usr/config/ + cp $PKG_DIR/cloud-sync.conf $INSTALL/usr/config/ + chmod 755 $INSTALL/usr/bin/rclone +} \ No newline at end of file diff --git a/packages/sysutils/screen/package.mk b/packages/sysutils/screen/package.mk new file mode 100644 index 000000000..4231f75b9 --- /dev/null +++ b/packages/sysutils/screen/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="screen" +PKG_VERSION="4.6.2" +PKG_SHA256="1b6922520e6a0ce5e28768d620b0f640a6631397f95ccb043b70b91bb503fa3a" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/screen/" +PKG_URL="http://ftpmirror.gnu.org/screen/$PKG_NAME-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Screen is a window manager that multiplexes a physical terminal between several processes" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_utempter_h=no \ + --enable-colors256 \ + --disable-pam \ + --disable-use-locale \ + --disable-telnet \ + --disable-socket-dir" + +pre_configure_target() { + CFLAGS="$CFLAGS -DTERMINFO" + export LDFLAGS=`echo $LDFLAGS | sed -e "s|-Wl,--as-needed||"` + +# screen fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME +} + +makeinstall_target() { + : +} diff --git a/packages/sysutils/screen/patches/screen-cross-compile.patch b/packages/sysutils/screen/patches/screen-cross-compile.patch new file mode 100644 index 000000000..b4bc30797 --- /dev/null +++ b/packages/sysutils/screen/patches/screen-cross-compile.patch @@ -0,0 +1,64 @@ +--- a/configure ++++ b/configure +@@ -414,7 +414,7 @@ as_fn_error () + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 +- as_fn_exit $as_status ++ # as_fn_exit $as_status + } # as_fn_error + + if expr a : '\(a\)' >/dev/null 2>&1 && +@@ -5941,8 +5941,6 @@ else + fi + rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +-test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" +-test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" + oldlibs="$LIBS" + LIBS="$LIBS -lsun" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking IRIX sun library..." >&5 +@@ -7023,7 +7021,7 @@ as_fn_error () + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 +- as_fn_exit $as_status ++ # as_fn_exit $as_status + } # as_fn_error + + +--- a/pty.c ++++ b/pty.c +@@ -39,9 +39,9 @@ + #endif + + /* for solaris 2.1, Unixware (SVR4.2) and possibly others */ +-#ifdef HAVE_STROPTS_H +-# include +-#endif ++//#ifdef HAVE_STROPTS_H ++//# include ++//#endif + + #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL) + # include +--- a/sched.h ++++ b/sched.h +@@ -27,6 +27,11 @@ + * $Id$ GNU + */ + ++#ifndef __SCHED_H ++#define __SCHED_H ++ ++#include ++ + struct event + { + struct event *next; +@@ -46,3 +51,5 @@ struct event + #define EV_READ 1 + #define EV_WRITE 2 + #define EV_ALWAYS 3 ++ ++#endif diff --git a/packages/sysutils/screen/patches/screen-dont_link_against_libelf.patch b/packages/sysutils/screen/patches/screen-dont_link_against_libelf.patch new file mode 100644 index 000000000..496246a3e --- /dev/null +++ b/packages/sysutils/screen/patches/screen-dont_link_against_libelf.patch @@ -0,0 +1,22 @@ +diff -Naur screen-4.3.1/configure screen-4.3.1.patch/configure +--- screen-4.3.1/configure 2015-06-28 23:42:40.000000000 +0200 ++++ screen-4.3.1.patch/configure 2016-03-26 17:52:12.807054501 +0100 +@@ -4156,7 +4156,6 @@ + + + oldlibs="$LIBS" +-LIBS="$LIBS -lelf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SVR4..." >&5 + $as_echo "$as_me: checking SVR4..." >&6;} + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +diff -Naur screen-4.3.1/configure.ac screen-4.3.1.patch/configure.ac +--- screen-4.3.1/configure.ac 2015-06-28 23:22:55.000000000 +0200 ++++ screen-4.3.1.patch/configure.ac 2016-03-26 17:52:03.538036990 +0100 +@@ -203,7 +203,6 @@ + ], LIBS="$LIBS -lsocket -linet";seqptx=1) + + oldlibs="$LIBS" +-LIBS="$LIBS -lelf" + AC_CHECKING(SVR4) + AC_TRY_LINK([#include + ],, diff --git a/packages/sysutils/sed/package.mk b/packages/sysutils/sed/package.mk new file mode 100644 index 000000000..714a26250 --- /dev/null +++ b/packages/sysutils/sed/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="sed" +PKG_VERSION="4.7" +PKG_SHA256="2885768cd0a29ff8d58a6280a270ff161f6a3deb5690b2be6c49f46d4c67bd6a" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/sed/" +PKG_URL="http://ftpmirror.gnu.org/sed/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="The sed (Stream EDitor) editor is a stream or batch (non-interactive) editor." + +PKG_CONFIGURE_OPTS_HOST="--disable-nls --disable-acl --without-selinux" diff --git a/packages/sysutils/smartmontools/package.mk b/packages/sysutils/smartmontools/package.mk new file mode 100644 index 000000000..b0ff05e86 --- /dev/null +++ b/packages/sysutils/smartmontools/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="smartmontools" +PKG_VERSION="7.0" +PKG_SHA256="e5e1ac2786bc87fdbd6f92d0ee751b799fbb3e1a09c0a6a379f9eb64b3e8f61c" +PKG_LICENSE="GPL" +PKG_SITE="https://www.smartmontools.org" +PKG_URL="https://downloads.sourceforge.net/sourceforge/smartmontools/smartmontools-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Control and monitor storage systems using S.M.A.R.T." + +PKG_CONFIGURE_OPTS_TARGET="--prefix=/usr \ + --without-initscriptdir \ + --without-nvme-devicescan \ + --without-systemdenvfile \ + --without-systemdsystemunitdir \ + --without-systemdenvfile \ + --without-systemdsystemunitdir" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/squashfs-tools/package.mk b/packages/sysutils/squashfs-tools/package.mk new file mode 100644 index 000000000..11d0df2c7 --- /dev/null +++ b/packages/sysutils/squashfs-tools/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="squashfs-tools" +PKG_VERSION="4.5" +PKG_SHA256="b9e16188e6dc1857fe312633920f7d71cc36b0162eb50f3ecb1f0040f02edddd" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/plougher/squashfs-tools" +PKG_URL="https://github.com/plougher/squashfs-tools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="ccache:host zlib:host lzo:host xz:host zstd:host" +PKG_NEED_UNPACK="$(get_pkg_directory zlib) $(get_pkg_directory lzo) $(get_pkg_directory xz) $(get_pkg_directory zstd)" +PKG_LONGDESC="Tools for squashfs, a highly compressed read-only filesystem for Linux." +PKG_TOOLCHAIN="manual" + +make_host() { + make -C squashfs-tools \ + mksquashfs \ + XZ_SUPPORT=1 \ + LZO_SUPPORT=1 \ + ZSTD_SUPPORT=1 \ + XATTR_SUPPORT=0 \ + XATTR_DEFAULT=0 \ + INCLUDEDIR="-I. -I${TOOLCHAIN}/include" +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp squashfs-tools/mksquashfs ${TOOLCHAIN}/bin +} \ No newline at end of file diff --git a/packages/sysutils/strace/package.mk b/packages/sysutils/strace/package.mk new file mode 100644 index 000000000..9e824735c --- /dev/null +++ b/packages/sysutils/strace/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="strace" +PKG_VERSION="5.10" +PKG_SHA256="fe3982ea4cd9aeb3b4ba35f6279f0b577a37175d3282be24b9a5537b56b8f01c" +PKG_LICENSE="BSD" +PKG_SITE="https://strace.io/" +PKG_URL="https://strace.io/files/${PKG_VERSION}/strace-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="strace is a diagnostic, debugging and instructional userspace utility" +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="-sysroot" +PKG_CONFIGURE_OPTS_TARGET=" --enable-mpers=check" diff --git a/packages/sysutils/strace/patches/strace-0001-autoreconf.patch b/packages/sysutils/strace/patches/strace-0001-autoreconf.patch new file mode 100644 index 000000000..830708ee9 --- /dev/null +++ b/packages/sysutils/strace/patches/strace-0001-autoreconf.patch @@ -0,0 +1,17 @@ +diff --git a/configure.ac b/configure.ac +index 4e7bc2a89..3b762c94c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -11,11 +11,7 @@ + # SPDX-License-Identifier: LGPL-2.1-or-later + + AC_PREREQ(2.57) +-AC_INIT([strace], +- st_esyscmd_s([./git-version-gen .tarball-version]), +- [strace-devel@lists.strace.io], +- [strace], +- [https://strace.io]) ++AC_INIT([strace],[5.10]) + m4_define([copyright_year], st_esyscmd_s([./copyright-year-gen .year])) + m4_define([manpage_date], st_esyscmd_s([./file-date-gen strace.1.in])) + AC_COPYRIGHT([Copyright (c) 1999-]copyright_year[ The strace developers.]) diff --git a/packages/sysutils/strace/patches/strace-0002-fix-autoconf-archive.patch b/packages/sysutils/strace/patches/strace-0002-fix-autoconf-archive.patch new file mode 100644 index 000000000..4e0927da6 --- /dev/null +++ b/packages/sysutils/strace/patches/strace-0002-fix-autoconf-archive.patch @@ -0,0 +1,39 @@ +From ba71a5f3778df1bb19ba593f6a5550c01f5349ad Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Tue, 28 Jan 2020 03:17:14 +0000 +Subject: [PATCH] fix API change since autoconf-archive-2019.01.06 + +--- + Makefile.am | 2 +- + Makefile.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 723460f2e..a6a0f5f9c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -408,7 +408,7 @@ strace_LDADD += $(libiberty_LIBS) + endif + endif + +-@CODE_COVERAGE_RULES@ ++include $(top_srcdir)/aminclude_static.am + CODE_COVERAGE_BRANCH_COVERAGE = 1 + CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ + --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) +diff --git a/Makefile.in b/Makefile.in +index b0ec9f686..9b4b93d8b 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -10351,7 +10351,7 @@ $(top_srcdir)/xlat/xfs_dqblk_flags.h: $(top_srcdir)/xlat/xfs_dqblk_flags.in $(to + $(top_srcdir)/xlat/xfs_quota_flags.h: $(top_srcdir)/xlat/xfs_quota_flags.in $(top_srcdir)/xlat/gen.sh + $(AM_V_GEN)$(top_srcdir)/xlat/gen.sh $< $@ + +-@CODE_COVERAGE_RULES@ ++include $(top_srcdir)/aminclude_static.am + + .PHONY: check-valgrind-local + check-valgrind-local: +-- +2.7.4 + diff --git a/packages/sysutils/stress-ng/package.mk b/packages/sysutils/stress-ng/package.mk new file mode 100644 index 000000000..bca940839 --- /dev/null +++ b/packages/sysutils/stress-ng/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="stress-ng" +PKG_VERSION="0.09.50" +PKG_SHA256="b07290495794092cdf2f8d51ac631f28b8cec9455a16552d8ca48bc1f376c634" +PKG_LICENSE="GPLv2" +PKG_SITE="http://kernel.ubuntu.com/~cking/stress-ng/" +PKG_URL="http://kernel.ubuntu.com/~cking/tarballs/stress-ng/stress-ng-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain attr keyutils libaio libcap zlib" +PKG_LONGDESC="stress-ng will stress test a computer system in various selectable ways" diff --git a/packages/sysutils/systemd/config/hosts.conf b/packages/sysutils/systemd/config/hosts.conf new file mode 100644 index 000000000..82ec2eea7 --- /dev/null +++ b/packages/sysutils/systemd/config/hosts.conf @@ -0,0 +1,10 @@ +# hosts.conf + +# This configuration file allows you to manually map hostnames to +# IP addresses + +# Format: +# Example: 192.168.0.3 libreelec libreelec.mynetwork + +# NOTE: do not edit /etc/hosts directly +# edit /storage/.config/hosts.conf then reboot diff --git a/packages/sysutils/systemd/config/hwdb.d/README b/packages/sysutils/systemd/config/hwdb.d/README new file mode 100644 index 000000000..6f31f02ec --- /dev/null +++ b/packages/sysutils/systemd/config/hwdb.d/README @@ -0,0 +1,10 @@ +Hardware Database Files + +The hwdb files are read from the files located in the system hwdb directory +/usr/lib/udev/hwdb.d and the user runtime directory /storage/.config/hwdb.d +All hwdb files are collectively sorted and processed in lexical order, regardless of +the directories in which they live. However, files with identical filenames +replace each other. /usr/lib/udev/hwdb.d/* takes precedence over /storage/.config/hwdb.d/* + +your files must be named 99-xxxxx.hwdb + diff --git a/packages/sysutils/systemd/config/logind.conf.d/README b/packages/sysutils/systemd/config/logind.conf.d/README new file mode 100644 index 000000000..ea24105a8 --- /dev/null +++ b/packages/sysutils/systemd/config/logind.conf.d/README @@ -0,0 +1,233 @@ +LOGIND.CONF(5) logind.conf LOGIND.CONF(5) + +NAME + logind.conf, logind.conf.d - Login manager configuration files + +SYNOPSIS + /etc/systemd/logind.conf + + /etc/systemd/logind.conf.d/*.conf + + /run/systemd/logind.conf.d/*.conf + + /usr/lib/systemd/logind.conf.d/*.conf + +DESCRIPTION + These files configure various parameters of the systemd login manager, + systemd-logind.service(8). + +CONFIGURATION DIRECTORIES AND PRECEDENCE + The default configuration is defined during compilation, so a + configuration file is only needed when it is necessary to deviate from + those defaults. By default, the configuration file in /etc/systemd/ + contains commented out entries showing the defaults as a guide to the + administrator. This file can be edited to create local overrides. + + When packages need to customize the configuration, they can install + configuration snippets in /usr/lib/systemd/*.conf.d/. Files in /etc/ + are reserved for the local administrator, who may use this logic to + override the configuration files installed by vendor packages. The main + configuration file is read before any of the configuration directories, + and has the lowest precedence; entries in a file in any configuration + directory override entries in the single configuration file. Files in + the *.conf.d/ configuration subdirectories are sorted by their filename + in lexicographic order, regardless of which of the subdirectories they + reside in. When multiple files specify the same option, for options + which accept just a single value, the entry in the file with the + lexicographically latest name takes precedence. For options which + accept a list of values, entries are collected as they occur in files + sorted lexicographically. It is recommended to prefix all filenames in + those subdirectories with a two-digit number and a dash, to simplify + the ordering of the files. + + To disable a configuration file supplied by the vendor, the recommended + way is to place a symlink to /dev/null in the configuration directory + in /etc/, with the same filename as the vendor configuration file. + +OPTIONS + All options are configured in the "[Login]" section: + + NAutoVTs= + Takes a positive integer. Configures how many virtual terminals + (VTs) to allocate by default that, when switched to and are + previously unused, "autovt" services are automatically spawned on. + These services are instantiated from the template unit + autovt@.service for the respective VT TTY name, for example, + autovt@tty4.service. By default, autovt@.service is linked to + getty@.service. In other words, login prompts are started + dynamically as the user switches to unused virtual terminals. + Hence, this parameter controls how many login "gettys" are + available on the VTs. If a VT is already used by some other + subsystem (for example, a graphical login), this kind of activation + will not be attempted. Note that the VT configured in ReserveVT= is + always subject to this kind of activation, even if it is not one of + the VTs configured with the NAutoVTs= directive. Defaults to 6. + When set to 0, automatic spawning of "autovt" services is disabled. + + ReserveVT= + Takes a positive integer. Identifies one virtual terminal that + shall unconditionally be reserved for autovt@.service activation + (see above). The VT selected with this option will be marked busy + unconditionally, so that no other subsystem will allocate it. This + functionality is useful to ensure that, regardless of how many VTs + are allocated by other subsystems, one login "getty" is always + available. Defaults to 6 (in other words, there will always be a + "getty" available on Alt-F6.). When set to 0, VT reservation is + disabled. + + KillUserProcesses= + Takes a boolean argument. Configures whether the processes of a + user should be killed when the user logs out. If true, the scope + unit corresponding to the session and all processes inside that + scope will be terminated. If false, the scope is "abandoned", see + systemd.scope(5), and processes are not killed. Defaults to "yes", + but see the options KillOnlyUsers= and KillExcludeUsers= below. + + In addition to session processes, user process may run under the + user manager unit user@.service. Depending on the linger settings, + this may allow users to run processes independent of their login + sessions. See the description of enable-linger in loginctl(1). + + Note that setting KillUserProcesses=yes will break tools like + screen(1) and tmux(1), unless they are moved out of the session + scope. See example in systemd-run(1). + + KillOnlyUsers=, KillExcludeUsers= + These settings take space-separated lists of usernames that + override the KillUserProcesses= setting. A user name may be added + to KillExcludeUsers= to exclude the processes in the session scopes + of that user from being killed even if KillUserProcesses=yes is + set. If KillExcludeUsers= is not set, the "root" user is excluded + by default. KillExcludeUsers= may be set to an empty value to + override this default. If a user is not excluded, KillOnlyUsers= is + checked next. If this setting is specified, only the session scopes + of those users will be killed. Otherwise, users are subject to the + KillUserProcesses=yes setting. + + IdleAction= + Configures the action to take when the system is idle. Takes one of + "ignore", "poweroff", "reboot", "halt", "kexec", "suspend", + "hibernate", "hybrid-sleep", and "lock". Defaults to "ignore". + + Note that this requires that user sessions correctly report the + idle status to the system. The system will execute the action after + all sessions report that they are idle, no idle inhibitor lock is + active, and subsequently, the time configured with IdleActionSec= + (see below) has expired. + + IdleActionSec= + Configures the delay after which the action configured in + IdleAction= (see above) is taken after the system is idle. + + InhibitDelayMaxSec= + Specifies the maximum time a system shutdown or sleep request is + delayed due to an inhibitor lock of type "delay" being active + before the inhibitor is ignored and the operation executes anyway. + Defaults to 5. + + HandlePowerKey=, HandleSuspendKey=, HandleHibernateKey=, + HandleLidSwitch=, HandleLidSwitchExternalPower=, HandleLidSwitchDocked= + Controls how logind shall handle the system power and sleep keys + and the lid switch to trigger actions such as system power-off or + suspend. Can be one of "ignore", "poweroff", "reboot", "halt", + "kexec", "suspend", "hibernate", "hybrid-sleep", and "lock". If + "ignore", logind will never handle these keys. If "lock", all + running sessions will be screen-locked; otherwise, the specified + action will be taken in the respective event. Only input devices + with the "power-switch" udev tag will be watched for key/lid switch + events. HandlePowerKey= defaults to "poweroff". HandleSuspendKey= + and HandleLidSwitch= default to "suspend". + HandleLidSwitchExternalPower= is completely ignored by default (for + backwards compatibility) — an explicit value must be set before it + will be used to determine behaviour. HandleLidSwitchDocked= + defaults to "ignore". HandleHibernateKey= defaults to "hibernate". + If the system is inserted in a docking station, or if more than one + display is connected, the action specified by + HandleLidSwitchDocked= occurs; if the system is on external power + the action (if any) specified by HandleLidSwitchExternalPower= + occurs; otherwise the HandleLidSwitch= action occurs. + + A different application may disable logind's handling of system + power and sleep keys and the lid switch by taking a low-level + inhibitor lock ("handle-power-key", "handle-suspend-key", + "handle-hibernate-key", "handle-lid-switch"). This is most commonly + used by graphical desktop environments to take over suspend and + hibernation handling, and to use their own configuration + mechanisms. If a low-level inhibitor lock is taken, logind will not + take any action when that key or switch is triggered and the + Handle*= settings are irrelevant. + + PowerKeyIgnoreInhibited=, SuspendKeyIgnoreInhibited=, + HibernateKeyIgnoreInhibited=, LidSwitchIgnoreInhibited= + Controls whether actions that systemd-logind takes when the power + and sleep keys and the lid switch are triggered are subject to + high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level + inhibitor locks ("handle-power-key", "handle-suspend-key", + "handle-hibernate-key", "handle-lid-switch"), are always honored, + irrespective of this setting. + + These settings take boolean arguments. If "no", the inhibitor locks + taken by applications are respected. If "yes", "shutdown", "sleep", + and "idle" inhibitor locks are ignored. PowerKeyIgnoreInhibited=, + SuspendKeyIgnoreInhibited=, and HibernateKeyIgnoreInhibited= + default to "no". LidSwitchIgnoreInhibited= defaults to "yes". This + means that when systemd-logind is handling events by itself (no low + level inhibitor locks are taken by another application), the lid + switch does not respect suspend blockers by default, but the power + and sleep keys do. + + HoldoffTimeoutSec= + Specifies the timeout after system startup or system resume in + which systemd will hold off on reacting to lid events. This is + required for the system to properly detect any hotplugged devices + so systemd can ignore lid events if external monitors, or docks, + are connected. If set to 0, systemd will always react immediately, + possibly before the kernel fully probed all hotplugged devices. + This is safe, as long as you do not care for systemd to account for + devices that have been plugged or unplugged while the system was + off. Defaults to 30s. + + RuntimeDirectorySize= + Sets the size limit on the $XDG_RUNTIME_DIR runtime directory for + each user who logs in. Takes a size in bytes, optionally suffixed + with the usual K, G, M, and T suffixes, to the base 1024 (IEC). + Alternatively, a numerical percentage suffixed by "%" may be + specified, which sets the size limit relative to the amount of + physical RAM. Defaults to 10%. Note that this size is a safety + limit only. As each runtime directory is a tmpfs file system, it + will only consume as much memory as is needed. + + InhibitorsMax= + Controls the maximum number of concurrent inhibitors to permit. + Defaults to 8192 (8K). + + SessionsMax= + Controls the maximum number of concurrent user sessions to manage. + Defaults to 8192 (8K). Depending on how the pam_systemd.so module + is included in the PAM stack configuration, further login sessions + will either be refused, or permitted but not tracked by + systemd-logind. + + UserTasksMax= + Sets the maximum number of OS tasks each user may run concurrently. + This controls the TasksMax= setting of the per-user slice unit, see + systemd.resource-control(5) for details. If assigned the special + value "infinity", no tasks limit is applied. Defaults to 33%, which + equals 10813 with the kernel's defaults on the host, but might be + smaller in OS containers. + + RemoveIPC= + Controls whether System V and POSIX IPC objects belonging to the + user shall be removed when the user fully logs out. Takes a boolean + argument. If enabled, the user may not consume IPC resources after + the last of the user's sessions terminated. This covers System V + semaphores, shared memory and message queues, as well as POSIX + shared memory and message queues. Note that IPC objects of the root + user and other system users are excluded from the effect of this + setting. Defaults to "yes". + +SEE ALSO + systemd(1), systemd-logind.service(8), loginctl(1), systemd- + system.conf(5) + +systemd 238 LOGIND.CONF(5) diff --git a/packages/sysutils/systemd/config/modules-load.d/README b/packages/sysutils/systemd/config/modules-load.d/README new file mode 100644 index 000000000..e781928e9 --- /dev/null +++ b/packages/sysutils/systemd/config/modules-load.d/README @@ -0,0 +1,33 @@ +Name + +modules-load.d — Configure kernel modules to load at boot + +Synopsis + +/etc/modules-load.d/*.conf + +/run/modules-load.d/*.conf + +/usr/lib/modules-load.d/*.conf + +Description + +systemd-modules-load.service(8) reads files from the above directories which contain kernel modules to load during boot in a static list. Each configuration file is named in the style of /etc/modules-load.d/program.conf. Note that it is usually a better idea to rely on the automatic module loading by PCI IDs, USB IDs, DMI IDs or similar triggers encoded in the kernel modules themselves instead of static configuration like this. In fact, most modern kernel modules are prepared for automatic loading already. +Configuration Format + +The configuration files should simply contain a list of kernel module names to load, separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored. + +Each configuration file shall be named in the style of program.conf. Files in /etc/ override files with the same name in /usr/lib/ and /run/. Files in /run/ override files with the same name in /usr/lib/. Packages should install their configuration files in /usr/lib/, files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed from vendor packages. + +If the administrator wants to disable a configuration file supplied by the vendor the recommended way is to place a symlink to /dev/null in /etc/modules-load.d/ bearing the same filename. +Example + +Example 1. /etc/modules-load.d/virtio-net.conf example: + +# Load virtio-net.ko at boot +virtio-net + + +See Also + +systemd(1), systemd-modules-load.service(8), systemd-delta(1), modprobe(8) diff --git a/packages/sysutils/systemd/config/sleep.conf.d/README b/packages/sysutils/systemd/config/sleep.conf.d/README new file mode 100644 index 000000000..403b99f7b --- /dev/null +++ b/packages/sysutils/systemd/config/sleep.conf.d/README @@ -0,0 +1,59 @@ +NAME + systemd-sleep.conf, sleep.conf.d - Suspend and hibernation configuration file + +SYNOPSIS + /etc/systemd/sleep.conf + + /etc/systemd/sleep.conf.d/*.conf + + /run/systemd/sleep.conf.d/*.conf + + /usr/lib/systemd/sleep.conf.d/*.conf + +DESCRIPTION + systemd supports three general power-saving modes: + + suspend + a low-power state where execution of the OS is paused, and complete power loss might result in lost data, and which is fast to enter and exit. This corresponds to suspend, standby, or freeze states as understood by the + kernel. + + hibernate + a low-power state where execution of the OS is paused, and complete power loss does not result in lost data, and which might be slow to enter and exit. This corresponds to the hibernation as understood by the kernel. + + hybrid-sleep + a low-power state where execution of the OS is paused, which might be slow to enter, and on complete power loss does not result in lost data but might be slower to exit in that case. This mode is called suspend-to-both + by the kernel. + + Settings in these files determine what strings will be written to /sys/power/disk and /sys/power/state by systemd-sleep(8) when systemd(1) attempts to suspend or hibernate the machine. + +CONFIGURATION DIRECTORIES AND PRECEDENCE + The default configuration is defined during compilation, so a configuration file is only needed when it is necessary to deviate from those defaults. By default, the configuration file in /etc/systemd/ contains commented out + entries showing the defaults as a guide to the administrator. This file can be edited to create local overrides. + + When packages need to customize the configuration, they can install configuration snippets in /usr/lib/systemd/*.conf.d/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the + configuration files installed by vendor packages. The main configuration file is read before any of the configuration directories, and has the lowest precedence; entries in a file in any configuration directory override + entries in the single configuration file. Files in the *.conf.d/ configuration subdirectories are sorted by their filename in lexicographic order, regardless of which of the subdirectories they reside in. If multiple files + specify the same option, the entry in the file with the lexicographically latest name takes precedence. It is recommended to prefix all filenames in those subdirectories with a two-digit number and a dash, to simplify the + ordering of the files. + + To disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in the configuration directory in /etc/, with the same filename as the vendor configuration file. + +OPTIONS + The following options can be configured in the "[Sleep]" section of /etc/systemd/sleep.conf or a sleep.conf.d file: + + SuspendMode=, HibernateMode=, HybridSleepMode= + The string to be written to /sys/power/disk by, respectively, systemd-suspend.service(8), systemd-hibernate.service(8), or systemd-hybrid-sleep.service(8). More than one value can be specified by separating multiple + values with whitespace. They will be tried in turn, until one is written without error. If neither succeeds, the operation will be aborted. + + SuspendState=, HibernateState=, HybridSleepState= + The string to be written to /sys/power/state by, respectively, systemd-suspend.service(8), systemd-hibernate.service(8), or systemd-hybrid-sleep.service(8). More than one value can be specified by separating multiple + values with whitespace. They will be tried in turn, until one is written without error. If neither succeeds, the operation will be aborted. + +EXAMPLE: FREEZE + Example: to exploit the “freeze†mode added in Linux 3.9, one can use systemctl suspend with + + [Sleep] + SuspendState=freeze + +SEE ALSO + systemd-sleep(8), systemd-suspend.service(8), systemd-hibernate.service(8), systemd-hybrid-sleep.service(8), systemd(1), systemd.directives(7) diff --git a/packages/sysutils/systemd/config/sleep.conf.d/sleep.conf.sample b/packages/sysutils/systemd/config/sleep.conf.d/sleep.conf.sample new file mode 100644 index 000000000..4ca7168be --- /dev/null +++ b/packages/sysutils/systemd/config/sleep.conf.d/sleep.conf.sample @@ -0,0 +1,3 @@ +[Sleep] +SuspendMode=false +HibernateMode=false diff --git a/packages/sysutils/systemd/config/sysctl.d/README b/packages/sysutils/systemd/config/sysctl.d/README new file mode 100644 index 000000000..fd6998447 --- /dev/null +++ b/packages/sysutils/systemd/config/sysctl.d/README @@ -0,0 +1,35 @@ +Name + +sysctl.d — Configure kernel parameters at boot + +Synopsis + +/etc/sysctl.d/*.conf + +/run/sysctl.d/*.conf + +/usr/lib/sysctl.d/*.conf + +Description + +At boot, systemd-sysctl.service(8) reads configuration files from the above directories to configure sysctl(8) kernel parameters. +Configuration Format + +The configuration files contain a list of variable assignments, separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored. + +Note that both / and . are accepted as label separators within sysctl variable names. "kernel.domainname=foo" and "kernel/domainname=foo" hence are entirely equivalent. + +Each configuration file shall be named in the style of program.conf. Files in /etc/ override files with the same name in /usr/lib/ and /run/. Files in /run/ override files with the same name in /usr/lib/. Packages should install their configuration files in /usr/lib/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. All configuration files are sorted by their filename in alphabetical order, regardless in which of the directories they reside, to guarantee that a specific configuration file takes precedence over another file with an alphabetically later name, if both files contain the same variable setting. + +If the administrator wants to disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in /etc/sysctl.d/ bearing the same filename. +Example + +Example 1. /etc/sysctl.d/domain-name.conf example: + +# Set kernel YP domain name +kernel.domainname=example.com + + +See Also + +systemd(1), systemd-sysctl.service(8), systemd-delta(1), sysctl(8), sysctl.conf(5) diff --git a/packages/sysutils/systemd/config/system.d/README b/packages/sysutils/systemd/config/system.d/README new file mode 100644 index 000000000..4546cb522 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/README @@ -0,0 +1,232 @@ +Name + +systemd.unit — Unit configuration + +Synopsis + +service.service, socket.socket, device.device, mount.mount, automount.automount, swap.swap, target.target, path.path, timer.timer, snapshot.snapshot, slice.slice, scope.scope + +/etc/systemd/system/* +/run/systemd/system/* +/usr/lib/systemd/system/* +... + + +$HOME/.config/systemd/user/* +/etc/systemd/user/* +/run/systemd/user/* +/usr/lib/systemd/user/* +... + +Description + +A unit configuration file encodes information about a service, a socket, a device, a mount point, an automount point, a swap file or partition, a start-up target, a watched file system path, a timer controlled and supervised by systemd(1), a temporary system state snapshot, a resource management slice or a group of externally created processes. The syntax is inspired by XDG Desktop Entry Specification .desktop files, which are in turn inspired by Microsoft Windows .ini files. + +This man page lists the common configuration options of all the unit types. These options need to be configured in the [Unit] or [Install] sections of the unit files. + +In addition to the generic [Unit] and [Install] sections described here, each unit may have a type-specific section, e.g. [Service] for a service unit. See the respective man pages for more information: systemd.service(5), systemd.socket(5), systemd.device(5), systemd.mount(5), systemd.automount(5), systemd.swap(5), systemd.target(5), systemd.path(5), systemd.timer(5), systemd.snapshot(5). systemd.slice(5). systemd.scope(5). + +Unit files are loaded from a set of paths determined during compilation, described in the next section. + +Unit files may contain additional options on top of those listed here. If systemd encounters an unknown option it will write a warning log message but continue loading the unit. If an option is prefixed with X- it is ignored completely by systemd. Applications may use this to include additional information in the unit files. + +Boolean arguments used in unit files can be written in various formats. For positive settings the strings 1, yes, true and on are equivalent. For negative settings the strings 0, no, false and off are equivalent. + +Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a time in seconds. If suffixed with a time unit, the unit is honored. A concatenation of multiple values with units is supported, in which case the values are added up. Example: "50" refers to 50 seconds; "2min 200ms" refers to 2 minutes plus 200 milliseconds, i.e. 120200ms. The following time units are understood: s, min, h, d, w, ms, us. For details see systemd.time(7). + +Empty lines and lines starting with # or ; are ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the backslash is replaced by a space character. This may be used to wrap long lines. + +Along with a unit file foo.service the directory foo.service.wants/ may exist. All unit files symlinked from such a directory are implicitly added as dependencies of type Wanted= to the unit. This is useful to hook units into the start-up of other units, without having to modify their unit files. For details about the semantics of Wanted= see below. The preferred way to create symlinks in the .wants/ directory of a unit file is with the enable command of the systemctl(1) tool which reads information from the [Install] section of unit files (see below). A similar functionality exists for Requires= type dependencies as well, the directory suffix is .requires/ in this case. + +Along with a unit file foo.service a directory foo.service.d/ may exist. All files with the suffix ".conf" from this directory will be parsed after the file itself is parsed. This is useful to alter or add configuration settings to a unit, without having to modify their unit files. Make sure that the file that is included has the appropriate section headers before any directive. + +If a line starts with .include followed by a filename, the specified file will be parsed at this point. Make sure that the file that is included has the appropriate section headers before any directives. + +Note that while systemd offers a flexible dependency system between units it is recommended to use this functionality only sparingly and instead rely on techniques such as bus-based or socket-based activation which make dependencies implicit, resulting in a both simpler and more flexible system. + +Some unit names reflect paths existing in the file system namespace. Example: a device unit dev-sda.device refers to a device with the device node /dev/sda in the file system namespace. If this applies a special way to escape the path name is used, so that the result is usable as part of a filename. Basically, given a path, "/" is replaced by "-", and all unprintable characters and the "-" are replaced by C-style "\x20" escapes. The root directory "/" is encoded as single dash, while otherwise the initial and ending "/" is removed from all paths during transformation. This escaping is reversible. + +Optionally, units may be instantiated from a template file at runtime. This allows creation of multiple units from a single configuration file. If systemd looks for a unit configuration file it will first search for the literal unit name in the filesystem. If that yields no success and the unit name contains an "@" character, systemd will look for a unit template that shares the same name but with the instance string (i.e. the part between the "@" character and the suffix) removed. Example: if a service getty@tty3.service is requested and no file by that name is found, systemd will look for getty@.service and instantiate a service from that configuration file if it is found. + +To refer to the instance string from within the configuration file you may use the special "%i" specifier in many of the configuration options. See below for details. + +If a unit file is empty (i.e. has the file size 0) or is symlinked to /dev/null its configuration will not be loaded and it appears with a load state of "masked", and cannot be activated. Use this as an effective way to fully disable a unit, making it impossible to start it even manually. + +The unit file format is covered by the Interface Stability Promise. +Unit Load Path + +Unit files are loaded from a set of paths determined during compilation, described in the two tables below. Unit files found in directories listed earlier override files with the same name in directories lower in the list. + +When systemd is running in user mode (--user) and the variable $SYSTEMD_UNIT_PATH is set, this contents of this variable overrides the unit load path. + +Table 1. Load path when running in system mode (--system). +Path Description +/etc/systemd/system Local configuration +/run/systemd/systemd Runtime units +/usr/lib/systemd/system Units of installed packages + +Table 2. Load path when running in user mode (--user). +Path Description +$HOME/.config/systemd/user User configuration +/etc/systemd/user Local configuration +/run/systemd/user Runtime units +/usr/lib/systemd/user Units of installed packages + +Additional units might be loaded into systemd ("linked") from directories not on the unit load path. See the link command for systemctl(1). Also, some units are dynamically created via generators Generators. +Options + +Unit file may include a [Unit] section, which carries generic information about the unit that is not dependent on the type of unit: + +Description= + A free-form string describing the unit. This is intended for use in UIs to show descriptive information along with the unit name. + +Documentation= + A space-separated list of URIs referencing documentation for this unit or its configuration. Accepted are only URIs of the types "http://", "https://", "file:", "info:", "man:". For more information about the syntax of these URIs, see uri(7). The URIs should be listed in order of relevance, starting with the most relevant. It is a good idea to first reference documentation that explains what the unit's purpose is, followed by how it is configured, followed by any other related documentation. This option may be specified more than once in which case the specified list of URIs is merged. If the empty string is assigned to this option, the list is reset and all prior assignments will have no effect. +Requires= + + Configures requirement dependencies on other units. If this unit gets activated, the units listed here will be activated as well. If one of the other units gets deactivated or its activation fails, this unit will be deactivated. This option may be specified more than once, in which case requirement dependencies for all listed names are created. Note that requirement dependencies do not influence the order in which services are started or stopped. This has to be configured independently with the After= or Before= options. If a unit foo.service requires a unit bar.service as configured with Requires= and no ordering is configured with After= or Before=, then both units will be started simultaneously and without any delay between them if foo.service is activated. Often it is a better choice to use Wants= instead of Requires= in order to achieve a system that is more robust when dealing with failing services. + + Note that dependencies of this type may also be configured outside of the unit configuration file by adding a symlink to a .requires/ directory accompanying the unit file. For details see above. + +RequiresOverridable= + Similar to Requires=. Dependencies listed in RequiresOverridable= which cannot be fulfilled or fail to start are ignored if the startup was explicitly requested by the user. If the start-up was pulled in indirectly by some dependency or automatic start-up of units that is not requested by the user this dependency must be fulfilled and otherwise the transaction fails. Hence, this option may be used to configure dependencies that are normally honored unless the user explicitly starts up the unit, in which case whether they failed or not is irrelevant. + +Requisite=, RequisiteOverridable= + Similar to Requires= and RequiresOverridable=, respectively. However, if a unit listed here is not started already it will not be started and the transaction fails immediately. + +Wants= + A weaker version of Requires=. A unit listed in this option will be started if the configuring unit is. However, if the listed unit fails to start up or cannot be added to the transaction this has no impact on the validity of the transaction as a whole. This is the recommended way to hook start-up of one unit to the start-up of another unit. + + Note that dependencies of this type may also be configured outside of the unit configuration file by adding a symlink to a .wants/ directory accompanying the unit file. For details see above. + +BindsTo= + Configures requirement dependencies, very similar in style to Requires=, however in addition to this behavior it also declares that this unit is stopped when any of the units listed suddenly disappears. Units can suddenly, unexpectedly disappear if a service terminates on its own choice, a device is unplugged or a mount point unmounted without involvement of systemd. + +PartOf= + Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or restarts the units listed here, the action is propagated to this unit. Note that this is a one way dependency - changes to this unit do not affect the listed units. + +Conflicts= + Configures negative requirement dependencies. If a unit has a Conflicts= setting on another unit, starting the former will stop the latter and vice versa. Note that this setting is independent of and orthogonal to the After= and Before= ordering dependencies. + + If a unit A that conflicts with a unit B is scheduled to be started at the same time as B, the transaction will either fail (in case both are required part of the transaction) or be modified to be fixed (in case one or both jobs are not a required part of the transaction). In the latter case the job that is not the required will be removed, or in case both are not required the unit that conflicts will be started and the unit that is conflicted is stopped. + +Before=, After= + Configures ordering dependencies between units. If a unit foo.service contains a setting Before=bar.service and both units are being started, bar.service's start-up is delayed until foo.service is started up. Note that this setting is independent of and orthogonal to the requirement dependencies as configured by Requires=. It is a common pattern to include a unit name in both the After= and Requires= option in which case the unit listed will be started before the unit that is configured with these options. This option may be specified more than once, in which case ordering dependencies for all listed names are created. After= is the inverse of Before=, i.e. while After= ensures that the configured unit is started after the listed unit finished starting up, Before= ensures the opposite, i.e. that the configured unit is fully started up before the listed unit is started. Note that when two units with an ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is configured with After= on another unit, the former is stopped before the latter if both are shut down. If one unit with an ordering dependency on another unit is shut down while the latter is started up, the shut down is ordered before the start-up regardless whether the ordering dependency is actually of type After= or Before=. If two units have no ordering dependencies between them they are shut down or started up simultaneously, and no ordering takes place. + +OnFailure= + Lists one or more units that are activated when this unit enters the "failed" state. + +PropagatesReloadTo=, ReloadPropagatedFrom= + Lists one or more units where reload requests on the unit will be propagated to/on the other unit will be propagated from. Issuing a reload request on a unit will automatically also enqueue a reload request on all units that the reload request shall be propagated to via these two settings. + +RequiresMountsFor= + Takes a space-separated list of absolute paths. Automatically adds dependencies of type Requires= and After= for all mount units required to access the specified path. + +OnFailureIsolate= + Takes a boolean argument. If true the unit listed in OnFailure= will be enqueued in isolation mode, i.e. all units that are not its dependency will be stopped. If this is set only a single unit may be listed in OnFailure=. Defaults to false. + +IgnoreOnIsolate= + Takes a boolean argument. If true this unit will not be stopped when isolating another unit. Defaults to false. + +IgnoreOnSnapshot= + Takes a boolean argument. If true this unit will not be included in snapshots. Defaults to true for device and snapshot units, false for the others. + +StopWhenUnneeded= + Takes a boolean argument. If true this unit will be stopped when it is no longer used. Note that in order to minimize the work to be executed, systemd will not stop units by default unless they are conflicting with other units, or the user explicitly requested their shut down. If this option is set, a unit will be automatically cleaned up if no other active unit requires it. Defaults to false. + +RefuseManualStart=, RefuseManualStop= + Takes a boolean argument. If true this unit can only be activated or deactivated indirectly. In this case explicit start-up or termination requested by the user is denied, however if it is started or stopped as a dependency of another unit, start-up or termination will succeed. This is mostly a safety feature to ensure that the user does not accidentally activate units that are not intended to be activated explicitly, and not accidentally deactivate units that are not intended to be deactivated. These options default to false. + +AllowIsolate= + Takes a boolean argument. If true this unit may be used with the systemctl isolate command. Otherwise this will be refused. It probably is a good idea to leave this disabled except for target units that shall be used similar to runlevels in SysV init systems, just as a precaution to avoid unusable system states. This option defaults to false. + +DefaultDependencies= + Takes a boolean argument. If true (the default), a few default dependencies will implicitly be created for the unit. The actual dependencies created depend on the unit type. For example, for service units, these dependencies ensure that the service is started only after basic system initialization is completed and is properly terminated on system shutdown. See the respective man pages for details. Generally, only services involved with early boot or late shutdown should set this option to false. It is highly recommended to leave this option enabled for the majority of common units. If set to false, this option does not disable all implicit dependencies, just non-essential ones. + +JobTimeoutSec= + When clients are waiting for a job of this unit to complete, time out after the specified time. If this time limit is reached the job will be cancelled, the unit however will not change state or even enter the "failed" mode. This value defaults to 0 (job timeouts disabled), except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the timeout set with Timeout= in service units) as the job timeout has no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however is useful to abort only the job waiting for the unit state to change. + +ConditionPathExists=, ConditionPathExistsGlob=, ConditionPathIsDirectory=, ConditionPathIsSymbolicLink=, ConditionPathIsMountPoint=, ConditionPathIsReadWrite=, ConditionDirectoryNotEmpty=, ConditionFileNotEmpty=, ConditionFileIsExecutable=, ConditionKernelCommandLine=, ConditionVirtualization=, ConditionSecurity=, ConditionCapability=, ConditionHost=, ConditionACPower=, ConditionNull= + Before starting a unit verify that the specified condition is true. If it is not true the starting of the unit will be skipped, however all ordering dependencies of it are still respected. A failing condition will not result in the unit being moved into a failure state. The condition is checked at the time the queued start job is to be executed. + + With ConditionPathExists= a file existence condition is checked before a unit is started. If the specified absolute path name does not exist the condition will fail. If the absolute path name passed to ConditionPathExists= is prefixed with an exclamation mark ("!"), the test is negated, and the unit is only started if the path does not exist. + + ConditionPathExistsGlob= is similar to ConditionPathExists=, but checks for the existence of at least one file or directory matching the specified globbing pattern. + + ConditionPathIsDirectory= is similar to ConditionPathExists= but verifies whether a certain path exists and is a directory. + + ConditionPathIsSymbolicLink= is similar to ConditionPathExists= but verifies whether a certain path exists and is a symbolic link. + + ConditionPathIsMountPoint= is similar to ConditionPathExists= but verifies whether a certain path exists and is a mount point. + + ConditionPathIsReadWrite= is similar to ConditionPathExists= but verifies whether the underlying file system is readable and writable (i.e. not mounted read-only). + + ConditionDirectoryNotEmpty= is similar to ConditionPathExists= but verifies whether a certain path exists and is a non-empty directory. + + ConditionFileNotEmpty= is similar to ConditionPathExists= but verifies whether a certain path exists and refers to a regular file with a non-zero size. + + ConditionFileIsExecutable= is similar to ConditionPathExists= but verifies whether a certain path exists, is a regular file and marked executable. + + Similar, ConditionKernelCommandLine= may be used to check whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). The argument must either be a single word, or an assignment (i.e. two words, separated "="). In the former case the kernel command line is searched for the word appearing as is, or as left hand side of an assignment. In the latter case the exact assignment is looked for with right and left hand side matching. + + ConditionVirtualization= may be used to check whether the system is executed in a virtualized environment and optionally test whether it is a specific implementation. Takes either boolean value to check if being executed in any virtualized environment, or one of vm and container to test against a generic type of virtualization solution, or one of qemu, kvm, vmware, microsoft, oracle, xen, bochs, chroot, uml, openvz, lxc, lxc-libvirt, systemd-nspawn to test against a specific implementation. If multiple virtualization technologies are nested only the innermost is considered. The test may be negated by prepending an exclamation mark. + + ConditionSecurity= may be used to check whether the given security module is enabled on the system. Currently the recognized values values are selinux, apparmor, ima and smack. The test may be negated by prepending an exclamation mark. + + ConditionCapability= may be used to check whether the given capability exists in the capability bounding set of the service manager (i.e. this does not check whether capability is actually available in the permitted or effective sets, see capabilities(7) for details). Pass a capability name such as "CAP_MKNOD", possibly prefixed with an exclamation mark to negate the check. + + ConditionHost= may be used to match against the hostname or machine ID of the host. This either takes a hostname string (optionally with shell style globs) which is tested against the locally set hostname as returned by gethostname(2), or a machine ID formatted as string (see machine-id(5)). The test may be negated by prepending an exclamation mark. + + ConditionACPower= may be used to check whether the system has AC power, or is exclusively battery powered at the time of activation of the unit. This takes a boolean argument. If set to true the condition will hold only if at least one AC connector of the system is connected to a power source, or if no AC connectors are known. Conversely, if set to false the condition will hold only if there is at least one AC connector known and all AC connectors are disconnected from a power source. + + Finally, ConditionNull= may be used to add a constant condition check value to the unit. It takes a boolean argument. If set to false the condition will always fail, otherwise succeed. + + If multiple conditions are specified the unit will be executed if all of them apply (i.e. a logical AND is applied). Condition checks can be prefixed with a pipe symbol (|) in which case a condition becomes a triggering condition. If at least one triggering condition is defined for a unit then the unit will be executed if at least one of the triggering conditions apply and all of the non-triggering conditions. If you prefix an argument with the pipe symbol and an exclamation mark the pipe symbol must be passed first, the exclamation second. Except for ConditionPathIsSymbolicLink=, all path checks follow symlinks. If any of these options is assigned the empty string the list of conditions is reset completely, all previous condition settings (of any kind) will have no effect. + +SourcePath= + A path to a configuration file this unit has been generated from. This is primarily useful for implementation of generator tools that convert configuration from an external configuration file format into native unit files. Thus functionality should not be used in normal units. + +Unit file may include a [Install] section, which carries installation information for the unit. This section is not interpreted by systemd(1) during runtime. It is used exclusively by the enable and disable commands of the systemctl(1) tool during installation of a unit: + +Alias= + Additional names this unit shall be installed under. The names listed here must have the same suffix (i.e. type) as the unit file name. This option may be specified more than once, in which case all listed names are used. At installation time, systemctl enable will create symlinks from these names to the unit filename. + +WantedBy=, RequiredBy= + A symbolic link is created in the .wants/ or .requires/ directory of the listed unit when this unit is activated by systemctl enable. This has the effect that a dependency of type Wants= or Requires= is added from the listed unit to the current unit. The primary result is that the current unit will be started when the listed unit is started. See the description of Wants= and Requires= in the [Unit] section for details. + + WantedBy=foo.service in a service bar.service is mostly equivalent to Alias=foo.service.wants/bar.service in the same file. In case of template units, systemctl enable must be called with an instance name, and this instance will be added to the .wants/ or .requires/ list of the listed unit. E.g. WantedBy=getty.target in a service getty@.service will result in systemctl enable getty@tty2.service creating a getty.target.wants/getty@tty2.service link to getty@.service. + +Also= + Additional units to install/deinstall when this unit is installed/deinstalled. If the user requests installation/deinstallation of a unit with this option configured, systemctl enable and systemctl disable will automatically install/uninstall units listed in this option as well. + +The following specifiers are interpreted in the Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b, %v. For their meaning see the next section. +Specifiers + +Many settings resolve specifiers which may be used to write generic unit files referring to runtime or unit parameters that are replaced when the unit files are loaded. The following specifiers are understood: + +Table 3. Specifiers available in unit files +Specifier Meaning Details +"%n" Full unit name +"%N" Unescaped full unit name +"%p" Prefix name For instantiated units this refers to the string before the @. For non-instantiated units this refers to to the name of the unit with the type suffix removed. +"%P" Unescaped prefix name +"%i" Instance name For instantiated units: this is the string between the "@" character and the suffix. +"%I" Unescaped instance name +"%f" Unescaped filename This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the prefix name similarly prepended with /. +"%c" Control group path of the unit +"%r" Root control group path where units are placed. For system instances this usually resolves to /system, except in containers, where the path might be prefixed with the container's root control group. +"%R" Parent directory of the control group path where units are placed. For system instances this usually resolves to /, except in containers, where this resolves to the container's root directory. This specifier is particularly useful in the ControlGroup= setting (see systemd.exec(5)). +"%t" Runtime socket dir This is either /run (for the system manager) or "$XDG_RUNTIME_DIR" (for user managers). +"%u" User name This is the name of the configured user of the unit, or (if none is set) the user running the systemd instance. +"%U" User UID This is the UID of the configured user of the unit, or (if none is set) the user running the systemd instance. +"%h" User home directory This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd instance. +"%s" User shell This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance. If the user is "root" (UID equal to 0), the shell configured in account database is ignored and /bin/sh is always used. +"%m" Machine ID The machine ID of the running system, formatted as string. See machine-id(5) for more information. +"%b" Boot ID The boot ID of the running system, formatted as string. See random(4) for more information. +"%H" Host name The hostname of the running system. +"%v" Kernel release Identical to uname -r output. +"%%" Escaped % Single percent sign. + +See Also + +systemd(1), systemctl(8), systemd.special(7), systemd.service(5), systemd.socket(5), systemd.device(5), systemd.mount(5), systemd.automount(5), systemd.swap(5), systemd.target(5), systemd.path(5), systemd.timer(5), systemd.snapshot(5), systemd.scope(5), systemd.slice(5), systemd.time(7), capabilities(7), systemd.directives(7), uname(1) diff --git a/packages/sysutils/systemd/config/system.d/cifs.mount.sample b/packages/sysutils/systemd/config/system.d/cifs.mount.sample new file mode 100644 index 000000000..eb0d08596 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/cifs.mount.sample @@ -0,0 +1,50 @@ +# This is a sample service script to mount CIFS/SAMBA shares. +# Please read carefully the comments in this file. For production usage +# you can remove all comments (lines beginning with "#") from this file. + + +[Unit] +# The description should be used to explain what this servicefile is for +Description=test cifs mount script + +# if we do network mounts like here we *require* 'network-online.service' +# which checks if the network is online +Requires=network-online.service + +# our scripts must start *after* 'network-online.service', on timeout and if +# 'network-online.service' fails we can not mount and this scripts fails too +After=network-online.service + +# usually we mount networks shares because we want they avaible *before* XBMC starts. +# so XBMC has access to this mounts from beginning. Note: this slows down the boot! +Before=kodi.service + + +[Mount] +# The share we want mount +What=//192.168.0.31/Music + +# Where we want mount this share +Where=/storage/music2 + +# Any options you usually use with the "-o" parameter in the mount command +Options=username=myusername,password=mypassword + +# filesystem type +Type=cifs + + +[Install] +# The target is used by 'systemctl enable ' to link +# this service to a runlevel for starting on boot. usually 'multi-user.target' +# is ok here. +WantedBy=multi-user.target + +# Important: +# this file must be renamed to .mount where , is the FULL path +# where the share will be mounted but slashes "/" MUST BE REPLACED with dashes "-" with .mount +# as extension. +# This means, if we want mount to "/storage/music2" (see above "Where=/storage/music2") +# then this file must be renamed to 'storage-music2.mount' and can be enabled via ssh with the +# command 'systemctl enable storage-music2.mount' + diff --git a/packages/sysutils/systemd/config/system.d/nfs.mount.sample b/packages/sysutils/systemd/config/system.d/nfs.mount.sample new file mode 100644 index 000000000..20ad18b65 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/nfs.mount.sample @@ -0,0 +1,50 @@ +# This is a sample service script to mount NFS shares. +# Please read carefully the comments in this file. For production usage +# you can remove all comments (lines beginning with "#") from this file. + + +[Unit] +# The description should be used to explain what this servicefile is for +Description=test nfs mount script + +# if we do network mounts like here we *require* 'network-online.service' +# which checks if the network is online +Requires=network-online.service + +# our scripts must start *after* 'network-online.service', on timeout and if +# 'network-online.service' fails we can not mount and this scripts fails too +After=network-online.service + +# usually we mount networks shares because we want they avaible *before* XBMC starts. +# so XBMC has access to this mounts from beginning. Note: this slows down the boot! +Before=kodi.service + + +[Mount] +# The share we want mount +What=192.168.0.31:/movies + +# Where we want mount this share +Where=/storage/movies2 + +# Any options you usually use with the "-o" parameter in the mount command +Options= + +# filesystem type +Type=nfs + + +[Install] +# The target is used by 'systemctl enable ' to link +# this service to a runlevel for starting on boot. usually 'multi-user.target' +# is ok here. +WantedBy=multi-user.target + +# Important: +# this file must be renamed to .mount where , is the FULL path +# where the share will be mounted but slashes "/" MUST BE REPLACED with dashes "-" with .mount +# as extension. +# This means, if we want mount to "/storage/movies2" (see above "Where=/storage/movies2") +# then this file must be renamed to 'storage-movies2.mount' and can be enabled via ssh with the +# command 'systemctl enable storage-movies2.mount' + diff --git a/packages/sysutils/systemd/config/system.d/openvpn.service.sample b/packages/sysutils/systemd/config/system.d/openvpn.service.sample new file mode 100644 index 000000000..d6f0ac445 --- /dev/null +++ b/packages/sysutils/systemd/config/system.d/openvpn.service.sample @@ -0,0 +1,44 @@ +[Unit] +Description=OpenVPN Autorun Service + +[Service] +Type=forking +Requires=network-online.service +After=network-online.service +ExecStart=/usr/sbin/openvpn --daemon --config /storage/.config/openvpn.config +Restart=always +RestartSec=15 + +[Install] +WantedBy=kodi.target + +# NOTES: +# +# 1) Edit /storage/.config/openvpn.config to the .config/.conf/.ovpn file +# from your VPN service provider and test it works first by connecting at +# the console: +# +# /usr/sbin/openvpn --daemon --config /storage/.config/openvpn.config +# +# 2) The openvpn.service file must be addeded to the active systemd config +# before it will work. This is done by running: +# +# systemctl enable openvpn.service +# +# 3) If you suspend/resume your LibreELEC system you will need to stop and +# restart the connection with a systemd *.power script, e.g. +# +# mkdir -p /storage/.config/sleep.d +# nano /storage/.config/sleep.d/01-openvpn.power +# +# Copy the sample script below. Remove # marks except for #!/bin/bash +# +# #!/bin/sh +# case "$1" in +# pre) +# systemctl stop openvpn.service +# ;; +# post) +# systemctl start openvpn.service +# ;; +# esac diff --git a/packages/sysutils/systemd/config/timesyncd.conf.d/README b/packages/sysutils/systemd/config/timesyncd.conf.d/README new file mode 100644 index 000000000..17537eb0c --- /dev/null +++ b/packages/sysutils/systemd/config/timesyncd.conf.d/README @@ -0,0 +1,86 @@ +TIMESYNCD.CONF(5) timesyncd.conf TIMESYNCD.CONF(5) + +NAME + timesyncd.conf, timesyncd.conf.d - Network Time Synchronization + configuration files + +SYNOPSIS + /etc/systemd/timesyncd.conf + + /etc/systemd/timesyncd.conf.d/*.conf + + /run/systemd/timesyncd.conf.d/*.conf + + /usr/lib/systemd/timesyncd.conf.d/*.conf + +DESCRIPTION + These configuration files control NTP network time synchronization. See + systemd.syntax(5) for a general description of the syntax. + +CONFIGURATION DIRECTORIES AND PRECEDENCE + The default configuration is defined during compilation, so a + configuration file is only needed when it is necessary to deviate from + those defaults. By default, the configuration file in /etc/systemd/ + contains commented out entries showing the defaults as a guide to the + administrator. This file can be edited to create local overrides. + + When packages need to customize the configuration, they can install + configuration snippets in /usr/lib/systemd/*.conf.d/. Files in /etc/ + are reserved for the local administrator, who may use this logic to + override the configuration files installed by vendor packages. The main + configuration file is read before any of the configuration directories, + and has the lowest precedence; entries in a file in any configuration + directory override entries in the single configuration file. Files in + the *.conf.d/ configuration subdirectories are sorted by their filename + in lexicographic order, regardless of which of the subdirectories they + reside in. When multiple files specify the same option, for options + which accept just a single value, the entry in the file with the + lexicographically latest name takes precedence. For options which + accept a list of values, entries are collected as they occur in files + sorted lexicographically. It is recommended to prefix all filenames in + those subdirectories with a two-digit number and a dash, to simplify + the ordering of the files. + + To disable a configuration file supplied by the vendor, the recommended + way is to place a symlink to /dev/null in the configuration directory + in /etc/, with the same filename as the vendor configuration file. + +OPTIONS + The following settings are configured in the "[Time]" section: + + NTP= + A space-separated list of NTP server host names or IP addresses. + During runtime this list is combined with any per-interface NTP + servers acquired from systemd-networkd.service(8). + systemd-timesyncd will contact all configured system or + per-interface servers in turn until one is found that responds. + When the empty string is assigned, the list of NTP servers is + reset, and all assignments prior to this one will have no effect. + This setting defaults to an empty list. + + FallbackNTP= + A space-separated list of NTP server host names or IP addresses to + be used as the fallback NTP servers. Any per-interface NTP servers + obtained from systemd-networkd.service(8) take precedence over this + setting, as do any servers set via NTP= above. This setting is + hence only used if no other NTP server information is known. When + the empty string is assigned, the list of NTP servers is reset, and + all assignments prior to this one will have no effect. If this + option is not given, a compiled-in list of NTP servers is used + instead. + + RootDistanceMaxSec= + Maximum acceptable root distance. Takes a time value (in seconds). + Defaults to 5 seconds. + + PollIntervalMinSec=, PollIntervalMaxSec= + The minimum and maximum poll intervals for NTP messages. Each + setting takes a time value (in seconds). PollIntervalMinSec= must + not be smaller than 16 seconds. PollIntervalMaxSec= must be larger + than PollIntervalMinSec=. PollIntervalMinSec= defaults to 32 + seconds, and PollIntervalMaxSec= defaults to 2048 seconds. + +SEE ALSO + systemd(1), systemd-timesyncd.service(8), systemd-networkd.service(8) + +systemd 241 TIMESYNCD.CONF(5) diff --git a/packages/sysutils/systemd/config/tmpfiles.d/README b/packages/sysutils/systemd/config/tmpfiles.d/README new file mode 100644 index 000000000..5ae2a9397 --- /dev/null +++ b/packages/sysutils/systemd/config/tmpfiles.d/README @@ -0,0 +1,109 @@ +Name + +tmpfiles.d — Configuration for creation, deletion and cleaning of volatile and temporary files + +Synopsis + +/etc/tmpfiles.d/*.conf + +/run/tmpfiles.d/*.conf + +/usr/lib/tmpfiles.d/*.conf + +Description + +systemd-tmpfiles uses the configuration files from the above directories to describe the creation, cleaning and removal of volatile and temporary files and directories which usually reside in directories such as /run or /tmp. +Configuration Format + +Each configuration file shall be named in the style of .conf. Files in /etc/ override files with the same name in /usr/lib/ and /run/. Files in /run/ override files with the same name in /usr/lib/. Packages should install their configuration files in /usr/lib/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. All configuration files are sorted by their filename in alphabetical order, regardless in which of the directories they reside, to guarantee that a specific configuration file takes precedence over another file with an alphabetically later name. + +If the administrator wants to disable a configuration file supplied by the vendor the recommended way is to place a symlink to /dev/null in /etc/tmpfiles.d/ bearing the same filename. + +The configuration format is one line per path containing action, path, mode, ownership, age and argument fields: + +Type Path Mode UID GID Age Argument +d /run/user 0755 root root 10d - +L /tmp/foobar - - - - /dev/null + +Type + +f + Create a file if it doesn't exist yet (optionally writing a short string into it, if the argument parameter is passed) + +F + Create or truncate a file (optionally writing a short string into it, if the argument parameter is passed) + +w + Write the argument parameter to a file, if the file exists. Lines of this type accept shell-style globs in place of normal path names. The argument parameter will be written without a trailing newline. C-style backslash escapes are interpreted. + +d + Create a directory if it doesn't exist yet + +D + Create or empty a directory + +p + Create a named pipe (FIFO) if it doesn't exist yet + +L + Create a symlink if it doesn't exist yet + +c + Create a character device node if it doesn't exist yet + +b + Create a block device node if it doesn't exist yet + +x + Ignore a path during cleaning. Use this type to exclude paths from clean-up as controlled with the Age parameter. Note that lines of this type do not influence the effect of r or R lines. Lines of this type accept shell-style globs in place of normal path names. + +X + Ignore a path during cleanup. Use this type to prevent path removal as controlled with the Age parameter. Note that if path is a directory, content of a directory is not excluded from clean-up, only directory itself. Lines of this type accept shell-style globs in place of normal path names. + +r + Remove a file or directory if it exists. This may not be used to remove non-empty directories, use R for that. Lines of this type accept shell-style globs in place of normal path names. + +R + Recursively remove a path and all its subdirectories (if it is a directory). Lines of this type accept shell-style globs in place of normal path names. + +z + Restore SELinux security context label and set ownership and access mode of a file or directory if it exists. Lines of this type accept shell-style globs in place of normal path names. + +Z + Recursively restore SELinux security context label and set ownership and access mode of a path and all its subdirectories (if it is a directory). Lines of this type accept shell-style globs in place of normal path names. + +Mode + +The file access mode to use when creating this file or directory. If omitted or when set to - the default is used: 0755 for directories, 0644 for all other file objects. For z, Z lines if omitted or when set to - the file access mode will not be modified. This parameter is ignored for x, r, R, L lines. +UID, GID + +The user and group to use for this file or directory. This may either be a numeric user/group ID or a user or group name. If omitted or when set to - the default 0 (root) is used. For z, Z lines when omitted or when set to - the file ownership will not be modified. These parameters are ignored for x, r, R, L lines. +Age + +The date field, when set, is used to decide what files to delete when cleaning. If a file or directory is older than the current time minus the age field it is deleted. The field format is a series of integers each followed by one of the following postfixes for the respective time units: + +s, min, h, d, w, ms, m, us + +If multiple integers and units are specified the time values are summed up. If an integer is given without a unit, s is assumed. + +When the age is set to zero, the files are cleaned unconditionally. + +The age field only applies to lines starting with d, D and x. If omitted or set to - no automatic clean-up is done. + +If the age field starts with a tilde character (~) the clean-up is only applied to files and directories one level inside the directory specified, but not the files and directories immediately inside it. +Argument + +For L lines determines the destination path of the symlink. For c, b determines the major/minor of the device node, with major and minor formatted as integers, separated by :, e.g. "1:3". For f, F, w may be used to specify a short string that is written to the file, suffixed by a newline. Ignored for all other lines. +Example + +Example 1. /etc/tmpfiles.d/screen.conf example + +screen needs two directories created at boot with specific modes and ownership. + +d /var/run/screens 1777 root root 10d +d /var/run/uscreens 0755 root root 10d12h + + +See Also + +systemd(1), systemd-tmpfiles(8), systemd-delta(1) diff --git a/packages/sysutils/systemd/config/udev.rules.d/README b/packages/sysutils/systemd/config/udev.rules.d/README new file mode 100644 index 000000000..d6d921203 --- /dev/null +++ b/packages/sysutils/systemd/config/udev.rules.d/README @@ -0,0 +1,25 @@ +The files in this directory are read by udev(7) and used when events +are performed by the kernel. The udev daemon watches this directory +with inotify so that changes to these files are automatically picked +up, for this reason they must be files and not symlinks to another +location as in the case in Debian. + +Packages do not generally install rules here, this directory is for +local rules. If you want to override behaviour of package-supplied +rules, which can be found in /usr/lib/udev/rules.d, you can do one of +two things: + + 1) Write your own rules in this directory that assign the name, + symlinks, permissions, etc. that you want. Pick a number higher + than the rules you want to override, and yours will be used. + + 2) Copy the file from /usr/lib/udev/rules.d and edit it here; you + should generally only do this if you want to prevent a program + from being run. + + +If the ordering of files in this directory are not important to you, +it's recommended that you simply name your files "descriptive-name.rules" +such that they are processed AFTER all numbered rules in both this +directory and /usr/lib/udev/rules.d and thus override anything set there. + diff --git a/packages/sysutils/systemd/hwdb.d/70-local-keyboard.hwdb b/packages/sysutils/systemd/hwdb.d/70-local-keyboard.hwdb new file mode 100644 index 000000000..6b3397d21 --- /dev/null +++ b/packages/sysutils/systemd/hwdb.d/70-local-keyboard.hwdb @@ -0,0 +1,3 @@ +# o2.cz bluetooth remote +evdev:input:b0005v0217p0000e0110* + KEYBOARD_KEY_c0041=enter # OK button diff --git a/packages/sysutils/systemd/package.mk b/packages/sysutils/systemd/package.mk new file mode 100644 index 000000000..e63d22ef6 --- /dev/null +++ b/packages/sysutils/systemd/package.mk @@ -0,0 +1,292 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="systemd" +PKG_VERSION="247" +PKG_SHA256="77146f7b27334aa69ef6692bed92c3c893685150f481e7254b81d4ea0f66c640" +PKG_LICENSE="LGPL2.1+" +PKG_SITE="http://www.freedesktop.org/wiki/Software/systemd" +PKG_URL="https://github.com/systemd/systemd/archive/v$PKG_VERSION.tar.gz" +#PKG_DEPENDS_TARGET="toolchain libcap kmod util-linux entropy libidn2 wait-time-sync" +PKG_DEPENDS_TARGET="toolchain libcap kmod util-linux entropy libidn2" +PKG_LONGDESC="A system and session manager for Linux, compatible with SysV and LSB init scripts." + +if [ "$PROJECT" = "Amlogic" ]; then + PKG_PATCH_DIRS="amlogic" +fi + +PKG_MESON_OPTS_TARGET="--libdir=/usr/lib \ + -Drootprefix=/usr \ + -Dsplit-usr=false \ + -Dsplit-bin=true \ + -Ddefault-hierarchy=hybrid \ + -Dtty-gid=5 \ + -Dtests=false \ + -Dseccomp=false \ + -Dselinux=false \ + -Dapparmor=false \ + -Dpolkit=false \ + -Dacl=false \ + -Daudit=false \ + -Dblkid=true \ + -Dkmod=true \ + -Dpam=false \ + -Dmicrohttpd=false \ + -Dlibcryptsetup=false \ + -Dlibcurl=false \ + -Dlibidn=false \ + -Dlibidn2=true \ + -Dlibiptc=false \ + -Dqrencode=false \ + -Dgcrypt=false \ + -Dgnutls=false \ + -Dopenssl=false \ + -Delfutils=false \ + -Dzlib=false \ + -Dbzip2=false \ + -Dxz=false \ + -Dlz4=false \ + -Dxkbcommon=false \ + -Dpcre2=false \ + -Dglib=false \ + -Ddbus=false \ + -Ddefault-dnssec=no \ + -Dimportd=false \ + -Dremote=false \ + -Dutmp=false \ + -Dhibernate=false \ + -Denvironment-d=false \ + -Dbinfmt=false \ + -Dcoredump=false \ + -Dresolve=false \ + -Dlogind=true \ + -Dhostnamed=true \ + -Dlocaled=false \ + -Dmachined=false \ + -Dnetworkd=false \ + -Dtimedated=false \ + -Dtimesyncd=true \ + -Dfirstboot=false \ + -Drandomseed=false \ + -Dbacklight=false \ + -Dvconsole=false \ + -Dquotacheck=false \ + -Dsysusers=false \ + -Dtmpfiles=true \ + -Dhwdb=true \ + -Drfkill=false \ + -Dldconfig=false \ + -Defi=false \ + -Dtpm=false \ + -Dima=false \ + -Dsmack=false \ + -Dgshadow=false \ + -Didn=false \ + -Dnss-myhostname=false \ + -Dnss-mymachines=false \ + -Dnss-resolve=false \ + -Dnss-systemd=false \ + -Dman=false \ + -Dhtml=false \ + -Dbashcompletiondir=no \ + -Dzshcompletiondir=no \ + -Dkmod-path=/usr/bin/kmod \ + -Dmount-path=/usr/bin/mount \ + -Dumount-path=/usr/bin/umount \ + -Ddebug-tty=$DEBUG_TTY \ + -Dversion-tag=${PKG_VERSION}" + +pre_configure_target() { + export CFLAGS="$CFLAGS -fno-schedule-insns -fno-schedule-insns2 -Wno-format-truncation" + export LC_ALL=en_US.UTF-8 +} + +post_makeinstall_target() { + # remove unneeded stuff + safe_remove $INSTALL/etc/init.d + safe_remove $INSTALL/etc/pam.d + safe_remove $INSTALL/etc/systemd/system + safe_remove $INSTALL/etc/xdg + safe_remove $INSTALL/etc/X11 + safe_remove $INSTALL/usr/bin/kernel-install + safe_remove $INSTALL/usr/lib/kernel/install.d + safe_remove $INSTALL/usr/lib/rpm + safe_remove $INSTALL/usr/lib/systemd/user + safe_remove $INSTALL/usr/lib/tmpfiles.d/etc.conf + safe_remove $INSTALL/usr/lib/tmpfiles.d/home.conf + safe_remove $INSTALL/usr/share/factory + safe_remove $INSTALL/usr/share/zsh + + # clean up hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-OUI.hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-acpi-vendor.hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-bluetooth-vendor-product.hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-net-ifname.hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-sdio-classes.hwdb + safe_remove $INSTALL/usr/lib/udev/hwdb.d/20-sdio-vendor-model.hwdb + + # remove Network adaper renaming rule, this is confusing + safe_remove $INSTALL/usr/lib/udev/rules.d/80-net-setup-link.rules + + # remove the uaccess rules as we don't build systemd with ACL (see https://github.com/systemd/systemd/issues/4107) + safe_remove $INSTALL/usr/lib/udev/rules.d/70-uaccess.rules + safe_remove $INSTALL/usr/lib/udev/rules.d/71-seat.rules + safe_remove $INSTALL/usr/lib/udev/rules.d/73-seat-late.rules + + # remove getty units, we dont want a console + safe_remove $INSTALL/usr/lib/systemd/system/autovt@.service + safe_remove $INSTALL/usr/lib/systemd/system/console-getty.service + safe_remove $INSTALL/usr/lib/systemd/system/console-shell.service + safe_remove $INSTALL/usr/lib/systemd/system/container-getty@.service + safe_remove $INSTALL/usr/lib/systemd/system/getty.target + safe_remove $INSTALL/usr/lib/systemd/system/getty@.service + safe_remove $INSTALL/usr/lib/systemd/system/serial-getty@.service + safe_remove $INSTALL/usr/lib/systemd/system/*.target.wants/getty.target + + # remove other notused or nonsense stuff (our /etc is ro) + safe_remove $INSTALL/usr/lib/systemd/systemd-update-done + safe_remove $INSTALL/usr/lib/systemd/system/systemd-update-done.service + safe_remove $INSTALL/usr/lib/systemd/system/*.target.wants/systemd-update-done.service + + # remove systemd-udev-hwdb-update. we have own hwdb.service + safe_remove $INSTALL/usr/lib/systemd/system/systemd-udev-hwdb-update.service + safe_remove $INSTALL/usr/lib/systemd/system/*.target.wants/systemd-udev-hwdb-update.service + + # remove systemd-user-sessions + safe_remove $INSTALL/usr/lib/systemd/system/systemd-user-sessions.service + safe_remove $INSTALL/usr/lib/systemd/system/*.target.wants/systemd-user-sessions.service + + # remove nspawn + safe_remove $INSTALL/usr/bin/systemd-nspawn + safe_remove $INSTALL/usr/lib/systemd/system/systemd-nspawn@.service + + # remove unneeded generators + for gen in $INSTALL/usr/lib/systemd/system-generators/*; do + case "$gen" in + */systemd-debug-generator) + # keep it + ;; + *) + safe_remove "$gen" + ;; + esac + done + + # remove catalog + safe_remove $INSTALL/usr/lib/systemd/catalog + + # remove partition + safe_remove $INSTALL/usr/lib/systemd/systemd-growfs + safe_remove $INSTALL/usr/lib/systemd/systemd-makefs + + # distro preset policy + safe_remove $INSTALL/usr/lib/systemd/system-preset/* + echo "disable *" > $INSTALL/usr/lib/systemd/system-preset/99-default.preset + + safe_remove $INSTALL/usr/lib/systemd/user-preset/* + echo "disable *" > $INSTALL/usr/lib/systemd/user-preset/90-systemd.preset + + # remove networkd + safe_remove $INSTALL/usr/lib/systemd/network + + # remove systemd-time-wait-sync (not detecting slew time updates, using package wait-time-sync) + safe_remove $INSTALL/usr/lib/systemd/system/systemd-time-wait-sync.service + safe_remove $INSTALL/usr/lib/systemd/systemd-time-wait-sync + + # tune journald.conf + sed -e "s,^.*Compress=.*$,Compress=no,g" -i $INSTALL/etc/systemd/journald.conf + sed -e "s,^.*SplitMode=.*$,SplitMode=none,g" -i $INSTALL/etc/systemd/journald.conf + sed -e "s,^.*RuntimeMaxUse=.*$,RuntimeMaxUse=2M,g" -i $INSTALL/etc/systemd/journald.conf + sed -e "s,^.*RuntimeMaxFileSize=.*$,RuntimeMaxFileSize=128K,g" -i $INSTALL/etc/systemd/journald.conf + sed -e "s,^.*SystemMaxUse=.*$,SystemMaxUse=10M,g" -i $INSTALL/etc/systemd/journald.conf + + # tune logind.conf + sed -e "s,^.*HandleLidSwitch=.*$,HandleLidSwitch=ignore,g" -i $INSTALL/etc/systemd/logind.conf + sed -e "s,^.*HandlePowerKey=.*$,HandlePowerKey=suspend,g" -i $INSTALL/etc/systemd/logind.conf + + # replace systemd-machine-id-setup with ours + safe_remove $INSTALL/usr/lib/systemd/systemd-machine-id-commit + safe_remove $INSTALL/usr/lib/systemd/system/systemd-machine-id-commit.service + safe_remove $INSTALL/usr/lib/systemd/system/*.target.wants/systemd-machine-id-commit.service + safe_remove $INSTALL/usr/bin/systemd-machine-id-setup + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/systemd-machine-id-setup $INSTALL/usr/bin + cp $PKG_DIR/scripts/userconfig-setup $INSTALL/usr/bin + cp $PKG_DIR/scripts/usercache-setup $INSTALL/usr/bin + + mkdir -p $INSTALL/usr/sbin + cp $PKG_DIR/scripts/kernel-overlays-setup $INSTALL/usr/sbin + cp $PKG_DIR/scripts/network-base-setup $INSTALL/usr/sbin + cp $PKG_DIR/scripts/systemd-timesyncd-setup $INSTALL/usr/sbin + + # /etc/resolv.conf and /etc/hosts must be writable + ln -sf /run/libreelec/resolv.conf $INSTALL/etc/resolv.conf + ln -sf /run/libreelec/hosts $INSTALL/etc/hosts + + # provide 'halt', 'shutdown', 'reboot' & co. + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/halt + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/poweroff + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/reboot + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/runlevel + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/shutdown + ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/telinit + + # strip + debug_strip $INSTALL/usr + + # defaults + mkdir -p $INSTALL/usr/config + cp -PR $PKG_DIR/config/* $INSTALL/usr/config + + safe_remove $INSTALL/etc/modules-load.d + ln -sf /storage/.config/modules-load.d $INSTALL/etc/modules-load.d + safe_remove $INSTALL/etc/systemd/logind.conf.d + ln -sf /storage/.config/logind.conf.d $INSTALL/etc/systemd/logind.conf.d + safe_remove $INSTALL/etc/systemd/sleep.conf.d + ln -sf /storage/.config/sleep.conf.d $INSTALL/etc/systemd/sleep.conf.d + ln -sf /storage/.config/timesyncd.conf.d $INSTALL/etc/systemd/timesyncd.conf.d + safe_remove $INSTALL/etc/sysctl.d + ln -sf /storage/.config/sysctl.d $INSTALL/etc/sysctl.d + safe_remove $INSTALL/etc/tmpfiles.d + ln -sf /storage/.config/tmpfiles.d $INSTALL/etc/tmpfiles.d + safe_remove $INSTALL/etc/udev/hwdb.d + ln -sf /storage/.config/hwdb.d $INSTALL/etc/udev/hwdb.d + safe_remove $INSTALL/etc/udev/rules.d + ln -sf /storage/.config/udev.rules.d $INSTALL/etc/udev/rules.d +} + +post_install() { + add_group systemd-journal 190 + + add_group systemd-timesync 191 + add_user systemd-timesync x 191 191 "systemd-timesync" "/" "/bin/false" + + add_group systemd-network 193 + add_user systemd-network x 193 193 "systemd-network" "/" "/bin/sh" + + add_group audio 63 + add_group cdrom 11 + add_group dialout 18 + add_group disk 6 + add_group floppy 19 + add_group kmem 9 + add_group lp 7 + add_group tape 33 + add_group tty 5 + add_group video 39 + add_group utmp 22 + add_group input 199 + + enable_service machine-id.service + enable_service debugconfig.service + enable_service userconfig.service + enable_service usercache.service + enable_service kernel-overlays.service + enable_service hwdb.service + enable_service network-base.service + enable_service systemd-timesyncd.service + enable_service systemd-timesyncd-setup.service + enable_service debug-shell.service +} diff --git a/packages/sysutils/systemd/patches/amlogic/systemd-0203-syscall_397_doesnt_exists_on_3.14.patch b/packages/sysutils/systemd/patches/amlogic/systemd-0203-syscall_397_doesnt_exists_on_3.14.patch new file mode 100644 index 000000000..7284b282d --- /dev/null +++ b/packages/sysutils/systemd/patches/amlogic/systemd-0203-syscall_397_doesnt_exists_on_3.14.patch @@ -0,0 +1,42 @@ +--- a/src/basic/missing_syscall.h 2018-05-22 17:52:31.996229634 +0200 ++++ b/src/basic/missing_syscall.h 2018-05-23 00:23:03.774696689 +0200 +@@ -414,37 +414,14 @@ + + /* ======================================================================= */ + +-#if !HAVE_STATX +-# ifndef __NR_statx +-# if defined __aarch64__ || defined __arm__ +-# define __NR_statx 397 +-# elif defined __alpha__ +-# define __NR_statx 522 +-# elif defined __i386__ || defined __powerpc64__ +-# define __NR_statx 383 +-# elif defined __sparc__ +-# define __NR_statx 360 +-# elif defined __x86_64__ +-# define __NR_statx 332 +-# else +-# warning "__NR_statx not defined for your architecture" +-# endif +-# endif +- +-struct statx; +-#endif +- + /* This typedef is supposed to be always defined. */ + typedef struct statx struct_statx; + + #if !HAVE_STATX ++struct statx; + static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { +-# ifdef __NR_statx +- return syscall(__NR_statx, dfd, filename, flags, mask, buffer); +-# else + errno = ENOSYS; + return -1; +-# endif + } + + # define statx missing_statx + diff --git a/packages/sysutils/systemd/patches/amlogic/systemd-9999.1-backport.patch b/packages/sysutils/systemd/patches/amlogic/systemd-9999.1-backport.patch new file mode 100644 index 000000000..c2d3a4d24 --- /dev/null +++ b/packages/sysutils/systemd/patches/amlogic/systemd-9999.1-backport.patch @@ -0,0 +1,14185 @@ +From c7af754aa65eb84b6bb5018bda355891fa8183bd Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 10 Apr 2019 19:55:53 +0900 +Subject: [PATCH] tree-wide: drop several missing_*.h and import relevant + headers from kernel-5.0 + +--- + meson.build | 93 - + src/basic/arphrd-list.c | 3 +- + src/basic/btrfs-util.c | 3 +- + src/basic/generate-arphrd-list.sh | 2 +- + src/basic/linux/README | 3 + + src/basic/linux/btrfs.h | 945 +++++ + src/basic/linux/btrfs_tree.h | 974 +++++ + src/basic/linux/can/vxcan.h | 13 + + src/basic/linux/fib_rules.h | 90 + + src/basic/linux/fou.h | 42 + + src/basic/linux/if.h | 294 ++ + src/basic/linux/if_addr.h | 72 + + src/basic/linux/if_arp.h | 164 + + src/basic/linux/if_bonding.h | 131 + + src/basic/linux/if_bridge.h | 316 ++ + src/basic/linux/if_link.h | 1024 ++++++ + src/basic/linux/if_tun.h | 113 + + src/basic/linux/if_tunnel.h | 183 + + src/basic/linux/libc-compat.h | 267 ++ + src/basic/linux/netlink.h | 252 ++ + src/basic/linux/rtnetlink.h | 751 ++++ + src/basic/linux/wireguard.h | 190 + + src/basic/meson.build | 29 +- + src/basic/missing.h | 1 - + src/basic/missing_btrfs.h | 22 - + src/basic/missing_btrfs_tree.h | 109 - + src/basic/missing_ethtool.h | 131 - + src/basic/missing_fib_rules.h | 45 - + src/basic/missing_fou.h | 55 - + src/basic/missing_if_bridge.h | 21 - + src/basic/missing_if_link.h | 393 --- + src/basic/missing_if_tunnel.h | 59 - + src/basic/missing_network.h | 144 +- + src/basic/missing_vxcan.h | 12 - + src/core/bpf-devices.c | 2 +- + src/core/bpf-firewall.c | 2 +- + src/libsystemd/sd-netlink/netlink-types.c | 12 +- + src/network/netdev/fou-tunnel.h | 3 - + src/network/netdev/ipvlan.h | 1 - + src/network/netdev/tunnel.c | 6 +- + src/network/netdev/vxcan.c | 3 - + src/network/netdev/wireguard.c | 1 - + src/network/netdev/wireguard.h | 3 +- + src/network/networkd-brvlan.c | 1 - + src/network/networkd-network.c | 4 +- + src/network/networkd-routing-policy-rule.h | 1 - + src/partition/growfs.c | 1 + + src/resolve/resolved-link.c | 3 +- + src/shared/dissect-image.c | 3 +- + src/shared/linux/README | 8 + + src/shared/linux/auto_dev-ioctl.h | 33 +- + src/shared/linux/bpf.h | 3536 ++++++++++++++----- + src/shared/linux/bpf_common.h | 14 +- + src/shared/linux/bpf_insn.h | 205 ++ + src/shared/{linux-3.13 => linux}/dm-ioctl.h | 12 +- + src/shared/linux/ethtool.h | 1843 ++++++++++ + src/shared/linux/libbpf.h | 207 -- + src/shared/linux/netdevice.h | 66 + + src/shared/meson.build | 8 +- + src/shared/wireguard-netlink.h | 179 - + src/shutdown/umount.c | 2 +- + src/test/test-arphrd-list.c | 3 +- + src/test/test-bpf.c | 2 +- + src/test/test-netlink-manual.c | 3 +- + src/udev/net/ethtool-util.h | 1 - + src/udev/net/link-config.c | 2 +- + src/udev/udev-builtin-btrfs.c | 2 +- + 67 files changed, 10771 insertions(+), 2347 deletions(-) + create mode 100644 src/basic/linux/README + create mode 100644 src/basic/linux/btrfs.h + create mode 100644 src/basic/linux/btrfs_tree.h + create mode 100644 src/basic/linux/can/vxcan.h + create mode 100644 src/basic/linux/fib_rules.h + create mode 100644 src/basic/linux/fou.h + create mode 100644 src/basic/linux/if.h + create mode 100644 src/basic/linux/if_addr.h + create mode 100644 src/basic/linux/if_arp.h + create mode 100644 src/basic/linux/if_bonding.h + create mode 100644 src/basic/linux/if_bridge.h + create mode 100644 src/basic/linux/if_link.h + create mode 100644 src/basic/linux/if_tun.h + create mode 100644 src/basic/linux/if_tunnel.h + create mode 100644 src/basic/linux/libc-compat.h + create mode 100644 src/basic/linux/netlink.h + create mode 100644 src/basic/linux/rtnetlink.h + create mode 100644 src/basic/linux/wireguard.h + delete mode 100644 src/basic/missing_btrfs.h + delete mode 100644 src/basic/missing_btrfs_tree.h + delete mode 100644 src/basic/missing_ethtool.h + delete mode 100644 src/basic/missing_fib_rules.h + delete mode 100644 src/basic/missing_fou.h + delete mode 100644 src/basic/missing_if_bridge.h + delete mode 100644 src/basic/missing_if_link.h + delete mode 100644 src/basic/missing_if_tunnel.h + delete mode 100644 src/basic/missing_vxcan.h + create mode 100644 src/shared/linux/README + create mode 100644 src/shared/linux/bpf_insn.h + rename src/shared/{linux-3.13 => linux}/dm-ioctl.h (96%) + create mode 100644 src/shared/linux/ethtool.h + delete mode 100644 src/shared/linux/libbpf.h + create mode 100644 src/shared/linux/netdevice.h + delete mode 100644 src/shared/wireguard-netlink.h + +diff --git a/meson.build b/meson.build +index 79195c97484..15e3394b91d 100644 +--- a/meson.build ++++ b/meson.build +@@ -454,96 +454,6 @@ endforeach + + conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h) + +-foreach decl : [['ETHTOOL_LINK_MODE_10baseT_Half_BIT', 'linux/ethtool.h'], +- ['ETHTOOL_LINK_MODE_25000baseCR_Full_BIT', 'linux/ethtool.h'], +- ['ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT', 'linux/ethtool.h'], +- ['ETHTOOL_LINK_MODE_1000baseX_Full_BIT', 'linux/ethtool.h'], +- ['ETHTOOL_LINK_MODE_2500baseT_Full_BIT', 'linux/ethtool.h'], +- ['ETHTOOL_LINK_MODE_FEC_NONE_BIT', 'linux/ethtool.h'], +- ['FRA_TUN_ID', 'linux/fib_rules.h'], +- ['FRA_SUPPRESS_PREFIXLEN', 'linux/fib_rules.h'], +- ['FRA_PAD', 'linux/fib_rules.h'], +- ['FRA_L3MDEV', 'linux/fib_rules.h'], +- ['FRA_UID_RANGE', 'linux/fib_rules.h'], +- ['FRA_DPORT_RANGE', 'linux/fib_rules.h'], +- ['FOU_ATTR_REMCSUM_NOPARTIAL', 'linux/fou.h'], +- ['FOU_CMD_GET', 'linux/fou.h'], +- ['IFA_FLAGS', 'linux/if_addr.h'], +- ['IFLA_BRIDGE_VLAN_TUNNEL_INFO', 'linux/if_bridge.h'], +- ['IFLA_INET6_ADDR_GEN_MODE', 'linux/if_link.h'], +- ['IN6_ADDR_GEN_MODE_STABLE_PRIVACY', 'linux/if_link.h'], +- ['IN6_ADDR_GEN_MODE_RANDOM', 'linux/if_link.h'], +- ['IFLA_IPVLAN_MODE', 'linux/if_link.h'], +- ['IPVLAN_MODE_L3S', 'linux/if_link.h'], +- ['IFLA_IPVLAN_FLAGS', 'linux/if_link.h'], +- ['IFLA_PHYS_PORT_ID', 'linux/if_link.h'], +- ['IFLA_CARRIER_CHANGES', 'linux/if_link.h'], +- ['IFLA_PHYS_SWITCH_ID', 'linux/if_link.h'], +- ['IFLA_LINK_NETNSID', 'linux/if_link.h'], +- ['IFLA_PHYS_PORT_NAME', 'linux/if_link.h'], +- ['IFLA_PROTO_DOWN', 'linux/if_link.h'], +- ['IFLA_GSO_MAX_SIZE', 'linux/if_link.h'], +- ['IFLA_PAD', 'linux/if_link.h'], +- ['IFLA_XDP', 'linux/if_link.h'], +- ['IFLA_EVENT', 'linux/if_link.h'], +- ['IFLA_IF_NETNSID', 'linux/if_link.h'], +- ['IFLA_TARGET_NETNSID', 'linux/if_link.h'], +- ['IFLA_NEW_IFINDEX', 'linux/if_link.h'], +- ['IFLA_MAX_MTU', 'linux/if_link.h'], +- ['IFLA_BOND_MODE', 'linux/if_link.h'], +- ['IFLA_BOND_ACTIVE_SLAVE', 'linux/if_link.h'], +- ['IFLA_BOND_AD_INFO', 'linux/if_link.h'], +- ['IFLA_BOND_AD_ACTOR_SYSTEM', 'linux/if_link.h'], +- ['IFLA_BOND_TLB_DYNAMIC_LB', 'linux/if_link.h'], +- ['IFLA_VXLAN_UDP_ZERO_CSUM6_RX', 'linux/if_link.h'], +- ['IFLA_VXLAN_REMCSUM_NOPARTIAL', 'linux/if_link.h'], +- ['IFLA_VXLAN_COLLECT_METADATA', 'linux/if_link.h'], +- ['IFLA_VXLAN_LABEL', 'linux/if_link.h'], +- ['IFLA_VXLAN_GPE', 'linux/if_link.h'], +- ['IFLA_VXLAN_TTL_INHERIT', 'linux/if_link.h'], +- ['IFLA_GENEVE_TOS', 'linux/if_link.h'], +- ['IFLA_GENEVE_COLLECT_METADATA', 'linux/if_link.h'], +- ['IFLA_GENEVE_REMOTE6', 'linux/if_link.h'], +- ['IFLA_GENEVE_UDP_ZERO_CSUM6_RX', 'linux/if_link.h'], +- ['IFLA_GENEVE_LABEL', 'linux/if_link.h'], +- ['IFLA_GENEVE_TTL_INHERIT', 'linux/if_link.h'], +- ['IFLA_BR_MAX_AGE', 'linux/if_link.h'], +- ['IFLA_BR_PRIORITY', 'linux/if_link.h'], +- ['IFLA_BR_VLAN_PROTOCOL', 'linux/if_link.h'], +- ['IFLA_BR_VLAN_DEFAULT_PVID', 'linux/if_link.h'], +- ['IFLA_BR_VLAN_STATS_ENABLED', 'linux/if_link.h'], +- ['IFLA_BR_MCAST_STATS_ENABLED', 'linux/if_link.h'], +- ['IFLA_BR_MCAST_MLD_VERSION', 'linux/if_link.h'], +- ['IFLA_BR_VLAN_STATS_PER_PORT', 'linux/if_link.h'], +- ['IFLA_BRPORT_LEARNING_SYNC', 'linux/if_link.h'], +- ['IFLA_BRPORT_PROXYARP_WIFI', 'linux/if_link.h'], +- ['IFLA_BRPORT_MULTICAST_ROUTER', 'linux/if_link.h'], +- ['IFLA_BRPORT_PAD', 'linux/if_link.h'], +- ['IFLA_BRPORT_MCAST_FLOOD', 'linux/if_link.h'], +- ['IFLA_BRPORT_VLAN_TUNNEL', 'linux/if_link.h'], +- ['IFLA_BRPORT_BCAST_FLOOD', 'linux/if_link.h'], +- ['IFLA_BRPORT_NEIGH_SUPPRESS', 'linux/if_link.h'], +- ['IFLA_BRPORT_ISOLATED', 'linux/if_link.h'], +- ['IFLA_BRPORT_BACKUP_PORT', 'linux/if_link.h'], +- ['IFLA_VRF_TABLE', 'linux/if_link.h'], +- # if_tunnel.h is buggy and cannot be included on its own +- ['IFLA_VTI_FWMARK', 'linux/if_tunnel.h', '#include '], +- ['IFLA_IPTUN_ENCAP_DPORT', 'linux/if_tunnel.h', '#include '], +- ['IFLA_IPTUN_COLLECT_METADATA', 'linux/if_tunnel.h', '#include '], +- ['IFLA_IPTUN_FWMARK', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_ENCAP_DPORT', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_COLLECT_METADATA', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_IGNORE_DF', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_FWMARK', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_ERSPAN_INDEX', 'linux/if_tunnel.h', '#include '], +- ['IFLA_GRE_ERSPAN_HWID', 'linux/if_tunnel.h', '#include '], +- ['LO_FLAGS_PARTSCAN', 'linux/loop.h'], +- ] +- prefix = decl.length() > 2 ? decl[2] : '' +- have = cc.has_header_symbol(decl[1], decl[0], prefix : prefix) +- conf.set10('HAVE_' + decl[0], have) +-endforeach +- + foreach ident : ['secure_getenv', '__secure_getenv'] + conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident)) + endforeach +@@ -680,11 +590,8 @@ if not cc.has_header('sys/capability.h') + error('POSIX caps headers not found') + endif + foreach header : ['crypt.h', +- 'linux/btrfs_tree.h', +- 'linux/fou.h', + 'linux/memfd.h', + 'linux/vm_sockets.h', +- 'linux/can/vxcan.h', + 'sys/auxv.h', + 'valgrind/memcheck.h', + 'valgrind/valgrind.h', +diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c +index b6e2486b67b..b9a9cb7ed41 100644 +--- a/src/basic/arphrd-list.c ++++ b/src/basic/arphrd-list.c +@@ -1,12 +1,11 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include +-#include ++#include + #include + + #include "arphrd-list.h" + #include "macro.h" +-#include "missing_network.h" + + static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len); + +diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c +index b1519cc4eb4..db6c0c3f1e4 100644 +--- a/src/basic/btrfs-util.c ++++ b/src/basic/btrfs-util.c +@@ -3,8 +3,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + #include + #include +@@ -26,7 +28,6 @@ + #include "fs-util.h" + #include "io-util.h" + #include "macro.h" +-#include "missing.h" + #include "path-util.h" + #include "rm-rf.h" + #include "smack-util.h" +diff --git a/src/basic/generate-arphrd-list.sh b/src/basic/generate-arphrd-list.sh +index e6e874a8fd0..6db931c52b5 100755 +--- a/src/basic/generate-arphrd-list.sh ++++ b/src/basic/generate-arphrd-list.sh +@@ -1,6 +1,6 @@ + #!/bin/sh + set -eu + +-$1 -dM -include net/if_arp.h -include "$2" -include "$3" - ' and '__user' attributes +diff --git a/src/basic/linux/btrfs.h b/src/basic/linux/btrfs.h +new file mode 100644 +index 00000000000..22455c4cd79 +--- /dev/null ++++ b/src/basic/linux/btrfs.h +@@ -0,0 +1,945 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Copyright (C) 2007 Oracle. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public ++ * License v2 as published by the Free Software Foundation. ++ * ++ * This program 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 this program; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 021110-1307, USA. ++ */ ++ ++#ifndef _UAPI_LINUX_BTRFS_H ++#define _UAPI_LINUX_BTRFS_H ++#include ++#include ++ ++#define BTRFS_IOCTL_MAGIC 0x94 ++#define BTRFS_VOL_NAME_MAX 255 ++#define BTRFS_LABEL_SIZE 256 ++ ++/* this should be 4k */ ++#define BTRFS_PATH_NAME_MAX 4087 ++struct btrfs_ioctl_vol_args { ++ __s64 fd; ++ char name[BTRFS_PATH_NAME_MAX + 1]; ++}; ++ ++#define BTRFS_DEVICE_PATH_NAME_MAX 1024 ++#define BTRFS_SUBVOL_NAME_MAX 4039 ++ ++#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) ++#define BTRFS_SUBVOL_RDONLY (1ULL << 1) ++#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) ++ ++#define BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) ++ ++#define BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED \ ++ (BTRFS_SUBVOL_CREATE_ASYNC | \ ++ BTRFS_SUBVOL_RDONLY | \ ++ BTRFS_SUBVOL_QGROUP_INHERIT | \ ++ BTRFS_DEVICE_SPEC_BY_ID) ++ ++#define BTRFS_FSID_SIZE 16 ++#define BTRFS_UUID_SIZE 16 ++#define BTRFS_UUID_UNPARSED_SIZE 37 ++ ++/* ++ * flags definition for qgroup limits ++ * ++ * Used by: ++ * struct btrfs_qgroup_limit.flags ++ * struct btrfs_qgroup_limit_item.flags ++ */ ++#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) ++#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) ++#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) ++#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) ++#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) ++#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) ++ ++struct btrfs_qgroup_limit { ++ __u64 flags; ++ __u64 max_rfer; ++ __u64 max_excl; ++ __u64 rsv_rfer; ++ __u64 rsv_excl; ++}; ++ ++/* ++ * flags definition for qgroup inheritance ++ * ++ * Used by: ++ * struct btrfs_qgroup_inherit.flags ++ */ ++#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) ++ ++struct btrfs_qgroup_inherit { ++ __u64 flags; ++ __u64 num_qgroups; ++ __u64 num_ref_copies; ++ __u64 num_excl_copies; ++ struct btrfs_qgroup_limit lim; ++ __u64 qgroups[0]; ++}; ++ ++struct btrfs_ioctl_qgroup_limit_args { ++ __u64 qgroupid; ++ struct btrfs_qgroup_limit lim; ++}; ++ ++/* ++ * flags for subvolumes ++ * ++ * Used by: ++ * struct btrfs_ioctl_vol_args_v2.flags ++ * ++ * BTRFS_SUBVOL_RDONLY is also provided/consumed by the following ioctls: ++ * - BTRFS_IOC_SUBVOL_GETFLAGS ++ * - BTRFS_IOC_SUBVOL_SETFLAGS ++ */ ++ ++struct btrfs_ioctl_vol_args_v2 { ++ __s64 fd; ++ __u64 transid; ++ __u64 flags; ++ union { ++ struct { ++ __u64 size; ++ struct btrfs_qgroup_inherit *qgroup_inherit; ++ }; ++ __u64 unused[4]; ++ }; ++ union { ++ char name[BTRFS_SUBVOL_NAME_MAX + 1]; ++ __u64 devid; ++ }; ++}; ++ ++/* ++ * structure to report errors and progress to userspace, either as a ++ * result of a finished scrub, a canceled scrub or a progress inquiry ++ */ ++struct btrfs_scrub_progress { ++ __u64 data_extents_scrubbed; /* # of data extents scrubbed */ ++ __u64 tree_extents_scrubbed; /* # of tree extents scrubbed */ ++ __u64 data_bytes_scrubbed; /* # of data bytes scrubbed */ ++ __u64 tree_bytes_scrubbed; /* # of tree bytes scrubbed */ ++ __u64 read_errors; /* # of read errors encountered (EIO) */ ++ __u64 csum_errors; /* # of failed csum checks */ ++ __u64 verify_errors; /* # of occurences, where the metadata ++ * of a tree block did not match the ++ * expected values, like generation or ++ * logical */ ++ __u64 no_csum; /* # of 4k data block for which no csum ++ * is present, probably the result of ++ * data written with nodatasum */ ++ __u64 csum_discards; /* # of csum for which no data was found ++ * in the extent tree. */ ++ __u64 super_errors; /* # of bad super blocks encountered */ ++ __u64 malloc_errors; /* # of internal kmalloc errors. These ++ * will likely cause an incomplete ++ * scrub */ ++ __u64 uncorrectable_errors; /* # of errors where either no intact ++ * copy was found or the writeback ++ * failed */ ++ __u64 corrected_errors; /* # of errors corrected */ ++ __u64 last_physical; /* last physical address scrubbed. In ++ * case a scrub was aborted, this can ++ * be used to restart the scrub */ ++ __u64 unverified_errors; /* # of occurences where a read for a ++ * full (64k) bio failed, but the re- ++ * check succeeded for each 4k piece. ++ * Intermittent error. */ ++}; ++ ++#define BTRFS_SCRUB_READONLY 1 ++struct btrfs_ioctl_scrub_args { ++ __u64 devid; /* in */ ++ __u64 start; /* in */ ++ __u64 end; /* in */ ++ __u64 flags; /* in */ ++ struct btrfs_scrub_progress progress; /* out */ ++ /* pad to 1k */ ++ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; ++}; ++ ++#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 ++#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 ++struct btrfs_ioctl_dev_replace_start_params { ++ __u64 srcdevid; /* in, if 0, use srcdev_name instead */ ++ __u64 cont_reading_from_srcdev_mode; /* in, see #define ++ * above */ ++ __u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ ++ __u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ ++}; ++ ++#define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 ++#define BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED 1 ++#define BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED 2 ++#define BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED 3 ++#define BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED 4 ++struct btrfs_ioctl_dev_replace_status_params { ++ __u64 replace_state; /* out, see #define above */ ++ __u64 progress_1000; /* out, 0 <= x <= 1000 */ ++ __u64 time_started; /* out, seconds since 1-Jan-1970 */ ++ __u64 time_stopped; /* out, seconds since 1-Jan-1970 */ ++ __u64 num_write_errors; /* out */ ++ __u64 num_uncorrectable_read_errors; /* out */ ++}; ++ ++#define BTRFS_IOCTL_DEV_REPLACE_CMD_START 0 ++#define BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS 1 ++#define BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL 2 ++#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR 0 ++#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED 1 ++#define BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED 2 ++#define BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS 3 ++struct btrfs_ioctl_dev_replace_args { ++ __u64 cmd; /* in */ ++ __u64 result; /* out */ ++ ++ union { ++ struct btrfs_ioctl_dev_replace_start_params start; ++ struct btrfs_ioctl_dev_replace_status_params status; ++ }; /* in/out */ ++ ++ __u64 spare[64]; ++}; ++ ++struct btrfs_ioctl_dev_info_args { ++ __u64 devid; /* in/out */ ++ __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ ++ __u64 bytes_used; /* out */ ++ __u64 total_bytes; /* out */ ++ __u64 unused[379]; /* pad to 4k */ ++ __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ ++}; ++ ++struct btrfs_ioctl_fs_info_args { ++ __u64 max_id; /* out */ ++ __u64 num_devices; /* out */ ++ __u8 fsid[BTRFS_FSID_SIZE]; /* out */ ++ __u32 nodesize; /* out */ ++ __u32 sectorsize; /* out */ ++ __u32 clone_alignment; /* out */ ++ __u32 reserved32; ++ __u64 reserved[122]; /* pad to 1k */ ++}; ++ ++/* ++ * feature flags ++ * ++ * Used by: ++ * struct btrfs_ioctl_feature_flags ++ */ ++#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) ++/* ++ * Older kernels (< 4.9) on big-endian systems produced broken free space tree ++ * bitmaps, and btrfs-progs also used to corrupt the free space tree (versions ++ * < 4.7.3). If this bit is clear, then the free space tree cannot be trusted. ++ * btrfs-progs can also intentionally clear this bit to ask the kernel to ++ * rebuild the free space tree, however this might not work on older kernels ++ * that do not know about this bit. If not sure, clear the cache manually on ++ * first mount when booting older kernel versions. ++ */ ++#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) ++ ++#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) ++#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) ++#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) ++#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) ++#define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4) ++ ++/* ++ * older kernels tried to do bigger metadata blocks, but the ++ * code was pretty buggy. Lets not let them try anymore. ++ */ ++#define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) ++ ++#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) ++#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) ++#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) ++#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) ++#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10) ++ ++struct btrfs_ioctl_feature_flags { ++ __u64 compat_flags; ++ __u64 compat_ro_flags; ++ __u64 incompat_flags; ++}; ++ ++/* balance control ioctl modes */ ++#define BTRFS_BALANCE_CTL_PAUSE 1 ++#define BTRFS_BALANCE_CTL_CANCEL 2 ++ ++/* ++ * this is packed, because it should be exactly the same as its disk ++ * byte order counterpart (struct btrfs_disk_balance_args) ++ */ ++struct btrfs_balance_args { ++ __u64 profiles; ++ union { ++ __u64 usage; ++ struct { ++ __u32 usage_min; ++ __u32 usage_max; ++ }; ++ }; ++ __u64 devid; ++ __u64 pstart; ++ __u64 pend; ++ __u64 vstart; ++ __u64 vend; ++ ++ __u64 target; ++ ++ __u64 flags; ++ ++ /* ++ * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' ++ * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum ++ * and maximum ++ */ ++ union { ++ __u64 limit; /* limit number of processed chunks */ ++ struct { ++ __u32 limit_min; ++ __u32 limit_max; ++ }; ++ }; ++ ++ /* ++ * Process chunks that cross stripes_min..stripes_max devices, ++ * BTRFS_BALANCE_ARGS_STRIPES_RANGE ++ */ ++ __u32 stripes_min; ++ __u32 stripes_max; ++ ++ __u64 unused[6]; ++} __attribute__ ((__packed__)); ++ ++/* report balance progress to userspace */ ++struct btrfs_balance_progress { ++ __u64 expected; /* estimated # of chunks that will be ++ * relocated to fulfill the request */ ++ __u64 considered; /* # of chunks we have considered so far */ ++ __u64 completed; /* # of chunks relocated so far */ ++}; ++ ++/* ++ * flags definition for balance ++ * ++ * Restriper's general type filter ++ * ++ * Used by: ++ * btrfs_ioctl_balance_args.flags ++ * btrfs_balance_control.flags (internal) ++ */ ++#define BTRFS_BALANCE_DATA (1ULL << 0) ++#define BTRFS_BALANCE_SYSTEM (1ULL << 1) ++#define BTRFS_BALANCE_METADATA (1ULL << 2) ++ ++#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ ++ BTRFS_BALANCE_SYSTEM | \ ++ BTRFS_BALANCE_METADATA) ++ ++#define BTRFS_BALANCE_FORCE (1ULL << 3) ++#define BTRFS_BALANCE_RESUME (1ULL << 4) ++ ++/* ++ * flags definitions for per-type balance args ++ * ++ * Balance filters ++ * ++ * Used by: ++ * struct btrfs_balance_args ++ */ ++#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0) ++#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1) ++#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2) ++#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) ++#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) ++#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) ++#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) ++#define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7) ++#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10) ++ ++#define BTRFS_BALANCE_ARGS_MASK \ ++ (BTRFS_BALANCE_ARGS_PROFILES | \ ++ BTRFS_BALANCE_ARGS_USAGE | \ ++ BTRFS_BALANCE_ARGS_DEVID | \ ++ BTRFS_BALANCE_ARGS_DRANGE | \ ++ BTRFS_BALANCE_ARGS_VRANGE | \ ++ BTRFS_BALANCE_ARGS_LIMIT | \ ++ BTRFS_BALANCE_ARGS_LIMIT_RANGE | \ ++ BTRFS_BALANCE_ARGS_STRIPES_RANGE | \ ++ BTRFS_BALANCE_ARGS_USAGE_RANGE) ++ ++/* ++ * Profile changing flags. When SOFT is set we won't relocate chunk if ++ * it already has the target profile (even though it may be ++ * half-filled). ++ */ ++#define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8) ++#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9) ++ ++ ++/* ++ * flags definition for balance state ++ * ++ * Used by: ++ * struct btrfs_ioctl_balance_args.state ++ */ ++#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) ++#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) ++#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2) ++ ++struct btrfs_ioctl_balance_args { ++ __u64 flags; /* in/out */ ++ __u64 state; /* out */ ++ ++ struct btrfs_balance_args data; /* in/out */ ++ struct btrfs_balance_args meta; /* in/out */ ++ struct btrfs_balance_args sys; /* in/out */ ++ ++ struct btrfs_balance_progress stat; /* out */ ++ ++ __u64 unused[72]; /* pad to 1k */ ++}; ++ ++#define BTRFS_INO_LOOKUP_PATH_MAX 4080 ++struct btrfs_ioctl_ino_lookup_args { ++ __u64 treeid; ++ __u64 objectid; ++ char name[BTRFS_INO_LOOKUP_PATH_MAX]; ++}; ++ ++#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1) ++struct btrfs_ioctl_ino_lookup_user_args { ++ /* in, inode number containing the subvolume of 'subvolid' */ ++ __u64 dirid; ++ /* in */ ++ __u64 treeid; ++ /* out, name of the subvolume of 'treeid' */ ++ char name[BTRFS_VOL_NAME_MAX + 1]; ++ /* ++ * out, constructed path from the directory with which the ioctl is ++ * called to dirid ++ */ ++ char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; ++}; ++ ++/* Search criteria for the btrfs SEARCH ioctl family. */ ++struct btrfs_ioctl_search_key { ++ /* ++ * The tree we're searching in. 1 is the tree of tree roots, 2 is the ++ * extent tree, etc... ++ * ++ * A special tree_id value of 0 will cause a search in the subvolume ++ * tree that the inode which is passed to the ioctl is part of. ++ */ ++ __u64 tree_id; /* in */ ++ ++ /* ++ * When doing a tree search, we're actually taking a slice from a ++ * linear search space of 136-bit keys. ++ * ++ * A full 136-bit tree key is composed as: ++ * (objectid << 72) + (type << 64) + offset ++ * ++ * The individual min and max values for objectid, type and offset ++ * define the min_key and max_key values for the search range. All ++ * metadata items with a key in the interval [min_key, max_key] will be ++ * returned. ++ * ++ * Additionally, we can filter the items returned on transaction id of ++ * the metadata block they're stored in by specifying a transid range. ++ * Be aware that this transaction id only denotes when the metadata ++ * page that currently contains the item got written the last time as ++ * result of a COW operation. The number does not have any meaning ++ * related to the transaction in which an individual item that is being ++ * returned was created or changed. ++ */ ++ __u64 min_objectid; /* in */ ++ __u64 max_objectid; /* in */ ++ __u64 min_offset; /* in */ ++ __u64 max_offset; /* in */ ++ __u64 min_transid; /* in */ ++ __u64 max_transid; /* in */ ++ __u32 min_type; /* in */ ++ __u32 max_type; /* in */ ++ ++ /* ++ * input: The maximum amount of results desired. ++ * output: The actual amount of items returned, restricted by any of: ++ * - reaching the upper bound of the search range ++ * - reaching the input nr_items amount of items ++ * - completely filling the supplied memory buffer ++ */ ++ __u32 nr_items; /* in/out */ ++ ++ /* align to 64 bits */ ++ __u32 unused; ++ ++ /* some extra for later */ ++ __u64 unused1; ++ __u64 unused2; ++ __u64 unused3; ++ __u64 unused4; ++}; ++ ++struct btrfs_ioctl_search_header { ++ __u64 transid; ++ __u64 objectid; ++ __u64 offset; ++ __u32 type; ++ __u32 len; ++}; ++ ++#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key)) ++/* ++ * the buf is an array of search headers where ++ * each header is followed by the actual item ++ * the type field is expanded to 32 bits for alignment ++ */ ++struct btrfs_ioctl_search_args { ++ struct btrfs_ioctl_search_key key; ++ char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; ++}; ++ ++struct btrfs_ioctl_search_args_v2 { ++ struct btrfs_ioctl_search_key key; /* in/out - search parameters */ ++ __u64 buf_size; /* in - size of buffer ++ * out - on EOVERFLOW: needed size ++ * to store item */ ++ __u64 buf[0]; /* out - found items */ ++}; ++ ++struct btrfs_ioctl_clone_range_args { ++ __s64 src_fd; ++ __u64 src_offset, src_length; ++ __u64 dest_offset; ++}; ++ ++/* ++ * flags definition for the defrag range ioctl ++ * ++ * Used by: ++ * struct btrfs_ioctl_defrag_range_args.flags ++ */ ++#define BTRFS_DEFRAG_RANGE_COMPRESS 1 ++#define BTRFS_DEFRAG_RANGE_START_IO 2 ++struct btrfs_ioctl_defrag_range_args { ++ /* start of the defrag operation */ ++ __u64 start; ++ ++ /* number of bytes to defrag, use (u64)-1 to say all */ ++ __u64 len; ++ ++ /* ++ * flags for the operation, which can include turning ++ * on compression for this one defrag ++ */ ++ __u64 flags; ++ ++ /* ++ * any extent bigger than this will be considered ++ * already defragged. Use 0 to take the kernel default ++ * Use 1 to say every single extent must be rewritten ++ */ ++ __u32 extent_thresh; ++ ++ /* ++ * which compression method to use if turning on compression ++ * for this defrag operation. If unspecified, zlib will ++ * be used ++ */ ++ __u32 compress_type; ++ ++ /* spare for later */ ++ __u32 unused[4]; ++}; ++ ++ ++#define BTRFS_SAME_DATA_DIFFERS 1 ++/* For extent-same ioctl */ ++struct btrfs_ioctl_same_extent_info { ++ __s64 fd; /* in - destination file */ ++ __u64 logical_offset; /* in - start of extent in destination */ ++ __u64 bytes_deduped; /* out - total # of bytes we were able ++ * to dedupe from this file */ ++ /* status of this dedupe operation: ++ * 0 if dedup succeeds ++ * < 0 for error ++ * == BTRFS_SAME_DATA_DIFFERS if data differs ++ */ ++ __s32 status; /* out - see above description */ ++ __u32 reserved; ++}; ++ ++struct btrfs_ioctl_same_args { ++ __u64 logical_offset; /* in - start of extent in source */ ++ __u64 length; /* in - length of extent */ ++ __u16 dest_count; /* in - total elements in info array */ ++ __u16 reserved1; ++ __u32 reserved2; ++ struct btrfs_ioctl_same_extent_info info[0]; ++}; ++ ++struct btrfs_ioctl_space_info { ++ __u64 flags; ++ __u64 total_bytes; ++ __u64 used_bytes; ++}; ++ ++struct btrfs_ioctl_space_args { ++ __u64 space_slots; ++ __u64 total_spaces; ++ struct btrfs_ioctl_space_info spaces[0]; ++}; ++ ++struct btrfs_data_container { ++ __u32 bytes_left; /* out -- bytes not needed to deliver output */ ++ __u32 bytes_missing; /* out -- additional bytes needed for result */ ++ __u32 elem_cnt; /* out */ ++ __u32 elem_missed; /* out */ ++ __u64 val[0]; /* out */ ++}; ++ ++struct btrfs_ioctl_ino_path_args { ++ __u64 inum; /* in */ ++ __u64 size; /* in */ ++ __u64 reserved[4]; ++ /* struct btrfs_data_container *fspath; out */ ++ __u64 fspath; /* out */ ++}; ++ ++struct btrfs_ioctl_logical_ino_args { ++ __u64 logical; /* in */ ++ __u64 size; /* in */ ++ __u64 reserved[3]; /* must be 0 for now */ ++ __u64 flags; /* in, v2 only */ ++ /* struct btrfs_data_container *inodes; out */ ++ __u64 inodes; ++}; ++/* Return every ref to the extent, not just those containing logical block. ++ * Requires logical == extent bytenr. */ ++#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET (1ULL << 0) ++ ++enum btrfs_dev_stat_values { ++ /* disk I/O failure stats */ ++ BTRFS_DEV_STAT_WRITE_ERRS, /* EIO or EREMOTEIO from lower layers */ ++ BTRFS_DEV_STAT_READ_ERRS, /* EIO or EREMOTEIO from lower layers */ ++ BTRFS_DEV_STAT_FLUSH_ERRS, /* EIO or EREMOTEIO from lower layers */ ++ ++ /* stats for indirect indications for I/O failures */ ++ BTRFS_DEV_STAT_CORRUPTION_ERRS, /* checksum error, bytenr error or ++ * contents is illegal: this is an ++ * indication that the block was damaged ++ * during read or write, or written to ++ * wrong location or read from wrong ++ * location */ ++ BTRFS_DEV_STAT_GENERATION_ERRS, /* an indication that blocks have not ++ * been written */ ++ ++ BTRFS_DEV_STAT_VALUES_MAX ++}; ++ ++/* Reset statistics after reading; needs SYS_ADMIN capability */ ++#define BTRFS_DEV_STATS_RESET (1ULL << 0) ++ ++struct btrfs_ioctl_get_dev_stats { ++ __u64 devid; /* in */ ++ __u64 nr_items; /* in/out */ ++ __u64 flags; /* in/out */ ++ ++ /* out values: */ ++ __u64 values[BTRFS_DEV_STAT_VALUES_MAX]; ++ ++ __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ ++}; ++ ++#define BTRFS_QUOTA_CTL_ENABLE 1 ++#define BTRFS_QUOTA_CTL_DISABLE 2 ++#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 ++struct btrfs_ioctl_quota_ctl_args { ++ __u64 cmd; ++ __u64 status; ++}; ++ ++struct btrfs_ioctl_quota_rescan_args { ++ __u64 flags; ++ __u64 progress; ++ __u64 reserved[6]; ++}; ++ ++struct btrfs_ioctl_qgroup_assign_args { ++ __u64 assign; ++ __u64 src; ++ __u64 dst; ++}; ++ ++struct btrfs_ioctl_qgroup_create_args { ++ __u64 create; ++ __u64 qgroupid; ++}; ++struct btrfs_ioctl_timespec { ++ __u64 sec; ++ __u32 nsec; ++}; ++ ++struct btrfs_ioctl_received_subvol_args { ++ char uuid[BTRFS_UUID_SIZE]; /* in */ ++ __u64 stransid; /* in */ ++ __u64 rtransid; /* out */ ++ struct btrfs_ioctl_timespec stime; /* in */ ++ struct btrfs_ioctl_timespec rtime; /* out */ ++ __u64 flags; /* in */ ++ __u64 reserved[16]; /* in */ ++}; ++ ++/* ++ * Caller doesn't want file data in the send stream, even if the ++ * search of clone sources doesn't find an extent. UPDATE_EXTENT ++ * commands will be sent instead of WRITE commands. ++ */ ++#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1 ++ ++/* ++ * Do not add the leading stream header. Used when multiple snapshots ++ * are sent back to back. ++ */ ++#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2 ++ ++/* ++ * Omit the command at the end of the stream that indicated the end ++ * of the stream. This option is used when multiple snapshots are ++ * sent back to back. ++ */ ++#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4 ++ ++#define BTRFS_SEND_FLAG_MASK \ ++ (BTRFS_SEND_FLAG_NO_FILE_DATA | \ ++ BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \ ++ BTRFS_SEND_FLAG_OMIT_END_CMD) ++ ++struct btrfs_ioctl_send_args { ++ __s64 send_fd; /* in */ ++ __u64 clone_sources_count; /* in */ ++ __u64 *clone_sources; /* in */ ++ __u64 parent_root; /* in */ ++ __u64 flags; /* in */ ++ __u64 reserved[4]; /* in */ ++}; ++ ++/* ++ * Information about a fs tree root. ++ * ++ * All items are filled by the ioctl ++ */ ++struct btrfs_ioctl_get_subvol_info_args { ++ /* Id of this subvolume */ ++ __u64 treeid; ++ ++ /* Name of this subvolume, used to get the real name at mount point */ ++ char name[BTRFS_VOL_NAME_MAX + 1]; ++ ++ /* ++ * Id of the subvolume which contains this subvolume. ++ * Zero for top-level subvolume or a deleted subvolume. ++ */ ++ __u64 parent_id; ++ ++ /* ++ * Inode number of the directory which contains this subvolume. ++ * Zero for top-level subvolume or a deleted subvolume ++ */ ++ __u64 dirid; ++ ++ /* Latest transaction id of this subvolume */ ++ __u64 generation; ++ ++ /* Flags of this subvolume */ ++ __u64 flags; ++ ++ /* UUID of this subvolume */ ++ __u8 uuid[BTRFS_UUID_SIZE]; ++ ++ /* ++ * UUID of the subvolume of which this subvolume is a snapshot. ++ * All zero for a non-snapshot subvolume. ++ */ ++ __u8 parent_uuid[BTRFS_UUID_SIZE]; ++ ++ /* ++ * UUID of the subvolume from which this subvolume was received. ++ * All zero for non-received subvolume. ++ */ ++ __u8 received_uuid[BTRFS_UUID_SIZE]; ++ ++ /* Transaction id indicating when change/create/send/receive happened */ ++ __u64 ctransid; ++ __u64 otransid; ++ __u64 stransid; ++ __u64 rtransid; ++ /* Time corresponding to c/o/s/rtransid */ ++ struct btrfs_ioctl_timespec ctime; ++ struct btrfs_ioctl_timespec otime; ++ struct btrfs_ioctl_timespec stime; ++ struct btrfs_ioctl_timespec rtime; ++ ++ /* Must be zero */ ++ __u64 reserved[8]; ++}; ++ ++#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255 ++struct btrfs_ioctl_get_subvol_rootref_args { ++ /* in/out, minimum id of rootref's treeid to be searched */ ++ __u64 min_treeid; ++ ++ /* out */ ++ struct { ++ __u64 treeid; ++ __u64 dirid; ++ } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; ++ ++ /* out, number of found items */ ++ __u8 num_items; ++ __u8 align[7]; ++}; ++ ++/* Error codes as returned by the kernel */ ++enum btrfs_err_code { ++ BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1, ++ BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET, ++ BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET, ++ BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET, ++ BTRFS_ERROR_DEV_TGT_REPLACE, ++ BTRFS_ERROR_DEV_MISSING_NOT_FOUND, ++ BTRFS_ERROR_DEV_ONLY_WRITABLE, ++ BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS ++}; ++ ++#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ ++ struct btrfs_ioctl_vol_args) ++/* trans start and trans end are dangerous, and only for ++ * use by applications that know how to avoid the ++ * resulting deadlocks ++ */ ++#define BTRFS_IOC_TRANS_START _IO(BTRFS_IOCTL_MAGIC, 6) ++#define BTRFS_IOC_TRANS_END _IO(BTRFS_IOCTL_MAGIC, 7) ++#define BTRFS_IOC_SYNC _IO(BTRFS_IOCTL_MAGIC, 8) ++ ++#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int) ++#define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_RM_DEV _IOW(BTRFS_IOCTL_MAGIC, 11, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ ++ struct btrfs_ioctl_vol_args) ++ ++#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ ++ struct btrfs_ioctl_clone_range_args) ++ ++#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_DEFRAG_RANGE _IOW(BTRFS_IOCTL_MAGIC, 16, \ ++ struct btrfs_ioctl_defrag_range_args) ++#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ ++ struct btrfs_ioctl_search_args) ++#define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \ ++ struct btrfs_ioctl_search_args_v2) ++#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ ++ struct btrfs_ioctl_ino_lookup_args) ++#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64) ++#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ ++ struct btrfs_ioctl_space_args) ++#define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64) ++#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) ++#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ ++ struct btrfs_ioctl_vol_args_v2) ++#define BTRFS_IOC_SUBVOL_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 24, \ ++ struct btrfs_ioctl_vol_args_v2) ++#define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) ++#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64) ++#define BTRFS_IOC_SCRUB _IOWR(BTRFS_IOCTL_MAGIC, 27, \ ++ struct btrfs_ioctl_scrub_args) ++#define BTRFS_IOC_SCRUB_CANCEL _IO(BTRFS_IOCTL_MAGIC, 28) ++#define BTRFS_IOC_SCRUB_PROGRESS _IOWR(BTRFS_IOCTL_MAGIC, 29, \ ++ struct btrfs_ioctl_scrub_args) ++#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \ ++ struct btrfs_ioctl_dev_info_args) ++#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ ++ struct btrfs_ioctl_fs_info_args) ++#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \ ++ struct btrfs_ioctl_balance_args) ++#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int) ++#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \ ++ struct btrfs_ioctl_balance_args) ++#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \ ++ struct btrfs_ioctl_ino_path_args) ++#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ ++ struct btrfs_ioctl_logical_ino_args) ++#define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \ ++ struct btrfs_ioctl_received_subvol_args) ++#define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args) ++#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \ ++ struct btrfs_ioctl_vol_args) ++#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ ++ struct btrfs_ioctl_quota_ctl_args) ++#define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \ ++ struct btrfs_ioctl_qgroup_assign_args) ++#define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \ ++ struct btrfs_ioctl_qgroup_create_args) ++#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ ++ struct btrfs_ioctl_qgroup_limit_args) ++#define BTRFS_IOC_QUOTA_RESCAN _IOW(BTRFS_IOCTL_MAGIC, 44, \ ++ struct btrfs_ioctl_quota_rescan_args) ++#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \ ++ struct btrfs_ioctl_quota_rescan_args) ++#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46) ++#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \ ++ char[BTRFS_LABEL_SIZE]) ++#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \ ++ char[BTRFS_LABEL_SIZE]) ++#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \ ++ struct btrfs_ioctl_get_dev_stats) ++#define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \ ++ struct btrfs_ioctl_dev_replace_args) ++#define BTRFS_IOC_FILE_EXTENT_SAME _IOWR(BTRFS_IOCTL_MAGIC, 54, \ ++ struct btrfs_ioctl_same_args) ++#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ ++ struct btrfs_ioctl_feature_flags) ++#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \ ++ struct btrfs_ioctl_feature_flags[2]) ++#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ ++ struct btrfs_ioctl_feature_flags[3]) ++#define BTRFS_IOC_RM_DEV_V2 _IOW(BTRFS_IOCTL_MAGIC, 58, \ ++ struct btrfs_ioctl_vol_args_v2) ++#define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, \ ++ struct btrfs_ioctl_logical_ino_args) ++#define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, \ ++ struct btrfs_ioctl_get_subvol_info_args) ++#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, \ ++ struct btrfs_ioctl_get_subvol_rootref_args) ++#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, \ ++ struct btrfs_ioctl_ino_lookup_user_args) ++ ++#endif /* _UAPI_LINUX_BTRFS_H */ +diff --git a/src/basic/linux/btrfs_tree.h b/src/basic/linux/btrfs_tree.h +new file mode 100644 +index 00000000000..e974f4bb537 +--- /dev/null ++++ b/src/basic/linux/btrfs_tree.h +@@ -0,0 +1,974 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _BTRFS_CTREE_H_ ++#define _BTRFS_CTREE_H_ ++ ++#include ++#include ++ ++/* ++ * This header contains the structure definitions and constants used ++ * by file system objects that can be retrieved using ++ * the BTRFS_IOC_SEARCH_TREE ioctl. That means basically anything that ++ * is needed to describe a leaf node's key or item contents. ++ */ ++ ++/* holds pointers to all of the tree roots */ ++#define BTRFS_ROOT_TREE_OBJECTID 1ULL ++ ++/* stores information about which extents are in use, and reference counts */ ++#define BTRFS_EXTENT_TREE_OBJECTID 2ULL ++ ++/* ++ * chunk tree stores translations from logical -> physical block numbering ++ * the super block points to the chunk tree ++ */ ++#define BTRFS_CHUNK_TREE_OBJECTID 3ULL ++ ++/* ++ * stores information about which areas of a given device are in use. ++ * one per device. The tree of tree roots points to the device tree ++ */ ++#define BTRFS_DEV_TREE_OBJECTID 4ULL ++ ++/* one per subvolume, storing files and directories */ ++#define BTRFS_FS_TREE_OBJECTID 5ULL ++ ++/* directory objectid inside the root tree */ ++#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL ++ ++/* holds checksums of all the data extents */ ++#define BTRFS_CSUM_TREE_OBJECTID 7ULL ++ ++/* holds quota configuration and tracking */ ++#define BTRFS_QUOTA_TREE_OBJECTID 8ULL ++ ++/* for storing items that use the BTRFS_UUID_KEY* types */ ++#define BTRFS_UUID_TREE_OBJECTID 9ULL ++ ++/* tracks free space in block groups. */ ++#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL ++ ++/* device stats in the device tree */ ++#define BTRFS_DEV_STATS_OBJECTID 0ULL ++ ++/* for storing balance parameters in the root tree */ ++#define BTRFS_BALANCE_OBJECTID -4ULL ++ ++/* orhpan objectid for tracking unlinked/truncated files */ ++#define BTRFS_ORPHAN_OBJECTID -5ULL ++ ++/* does write ahead logging to speed up fsyncs */ ++#define BTRFS_TREE_LOG_OBJECTID -6ULL ++#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL ++ ++/* for space balancing */ ++#define BTRFS_TREE_RELOC_OBJECTID -8ULL ++#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL ++ ++/* ++ * extent checksums all have this objectid ++ * this allows them to share the logging tree ++ * for fsyncs ++ */ ++#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL ++ ++/* For storing free space cache */ ++#define BTRFS_FREE_SPACE_OBJECTID -11ULL ++ ++/* ++ * The inode number assigned to the special inode for storing ++ * free ino cache ++ */ ++#define BTRFS_FREE_INO_OBJECTID -12ULL ++ ++/* dummy objectid represents multiple objectids */ ++#define BTRFS_MULTIPLE_OBJECTIDS -255ULL ++ ++/* ++ * All files have objectids in this range. ++ */ ++#define BTRFS_FIRST_FREE_OBJECTID 256ULL ++#define BTRFS_LAST_FREE_OBJECTID -256ULL ++#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL ++ ++ ++/* ++ * the device items go into the chunk tree. The key is in the form ++ * [ 1 BTRFS_DEV_ITEM_KEY device_id ] ++ */ ++#define BTRFS_DEV_ITEMS_OBJECTID 1ULL ++ ++#define BTRFS_BTREE_INODE_OBJECTID 1 ++ ++#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2 ++ ++#define BTRFS_DEV_REPLACE_DEVID 0ULL ++ ++/* ++ * inode items have the data typically returned from stat and store other ++ * info about object characteristics. There is one for every file and dir in ++ * the FS ++ */ ++#define BTRFS_INODE_ITEM_KEY 1 ++#define BTRFS_INODE_REF_KEY 12 ++#define BTRFS_INODE_EXTREF_KEY 13 ++#define BTRFS_XATTR_ITEM_KEY 24 ++#define BTRFS_ORPHAN_ITEM_KEY 48 ++/* reserve 2-15 close to the inode for later flexibility */ ++ ++/* ++ * dir items are the name -> inode pointers in a directory. There is one ++ * for every name in a directory. ++ */ ++#define BTRFS_DIR_LOG_ITEM_KEY 60 ++#define BTRFS_DIR_LOG_INDEX_KEY 72 ++#define BTRFS_DIR_ITEM_KEY 84 ++#define BTRFS_DIR_INDEX_KEY 96 ++/* ++ * extent data is for file data ++ */ ++#define BTRFS_EXTENT_DATA_KEY 108 ++ ++/* ++ * extent csums are stored in a separate tree and hold csums for ++ * an entire extent on disk. ++ */ ++#define BTRFS_EXTENT_CSUM_KEY 128 ++ ++/* ++ * root items point to tree roots. They are typically in the root ++ * tree used by the super block to find all the other trees ++ */ ++#define BTRFS_ROOT_ITEM_KEY 132 ++ ++/* ++ * root backrefs tie subvols and snapshots to the directory entries that ++ * reference them ++ */ ++#define BTRFS_ROOT_BACKREF_KEY 144 ++ ++/* ++ * root refs make a fast index for listing all of the snapshots and ++ * subvolumes referenced by a given root. They point directly to the ++ * directory item in the root that references the subvol ++ */ ++#define BTRFS_ROOT_REF_KEY 156 ++ ++/* ++ * extent items are in the extent map tree. These record which blocks ++ * are used, and how many references there are to each block ++ */ ++#define BTRFS_EXTENT_ITEM_KEY 168 ++ ++/* ++ * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know ++ * the length, so we save the level in key->offset instead of the length. ++ */ ++#define BTRFS_METADATA_ITEM_KEY 169 ++ ++#define BTRFS_TREE_BLOCK_REF_KEY 176 ++ ++#define BTRFS_EXTENT_DATA_REF_KEY 178 ++ ++#define BTRFS_EXTENT_REF_V0_KEY 180 ++ ++#define BTRFS_SHARED_BLOCK_REF_KEY 182 ++ ++#define BTRFS_SHARED_DATA_REF_KEY 184 ++ ++/* ++ * block groups give us hints into the extent allocation trees. Which ++ * blocks are free etc etc ++ */ ++#define BTRFS_BLOCK_GROUP_ITEM_KEY 192 ++ ++/* ++ * Every block group is represented in the free space tree by a free space info ++ * item, which stores some accounting information. It is keyed on ++ * (block_group_start, FREE_SPACE_INFO, block_group_length). ++ */ ++#define BTRFS_FREE_SPACE_INFO_KEY 198 ++ ++/* ++ * A free space extent tracks an extent of space that is free in a block group. ++ * It is keyed on (start, FREE_SPACE_EXTENT, length). ++ */ ++#define BTRFS_FREE_SPACE_EXTENT_KEY 199 ++ ++/* ++ * When a block group becomes very fragmented, we convert it to use bitmaps ++ * instead of extents. A free space bitmap is keyed on ++ * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with ++ * (length / sectorsize) bits. ++ */ ++#define BTRFS_FREE_SPACE_BITMAP_KEY 200 ++ ++#define BTRFS_DEV_EXTENT_KEY 204 ++#define BTRFS_DEV_ITEM_KEY 216 ++#define BTRFS_CHUNK_ITEM_KEY 228 ++ ++/* ++ * Records the overall state of the qgroups. ++ * There's only one instance of this key present, ++ * (0, BTRFS_QGROUP_STATUS_KEY, 0) ++ */ ++#define BTRFS_QGROUP_STATUS_KEY 240 ++/* ++ * Records the currently used space of the qgroup. ++ * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid). ++ */ ++#define BTRFS_QGROUP_INFO_KEY 242 ++/* ++ * Contains the user configured limits for the qgroup. ++ * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid). ++ */ ++#define BTRFS_QGROUP_LIMIT_KEY 244 ++/* ++ * Records the child-parent relationship of qgroups. For ++ * each relation, 2 keys are present: ++ * (childid, BTRFS_QGROUP_RELATION_KEY, parentid) ++ * (parentid, BTRFS_QGROUP_RELATION_KEY, childid) ++ */ ++#define BTRFS_QGROUP_RELATION_KEY 246 ++ ++/* ++ * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY. ++ */ ++#define BTRFS_BALANCE_ITEM_KEY 248 ++ ++/* ++ * The key type for tree items that are stored persistently, but do not need to ++ * exist for extended period of time. The items can exist in any tree. ++ * ++ * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data] ++ * ++ * Existing items: ++ * ++ * - balance status item ++ * (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0) ++ */ ++#define BTRFS_TEMPORARY_ITEM_KEY 248 ++ ++/* ++ * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY ++ */ ++#define BTRFS_DEV_STATS_KEY 249 ++ ++/* ++ * The key type for tree items that are stored persistently and usually exist ++ * for a long period, eg. filesystem lifetime. The item kinds can be status ++ * information, stats or preference values. The item can exist in any tree. ++ * ++ * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data] ++ * ++ * Existing items: ++ * ++ * - device statistics, store IO stats in the device tree, one key for all ++ * stats ++ * (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0) ++ */ ++#define BTRFS_PERSISTENT_ITEM_KEY 249 ++ ++/* ++ * Persistantly stores the device replace state in the device tree. ++ * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0). ++ */ ++#define BTRFS_DEV_REPLACE_KEY 250 ++ ++/* ++ * Stores items that allow to quickly map UUIDs to something else. ++ * These items are part of the filesystem UUID tree. ++ * The key is built like this: ++ * (UUID_upper_64_bits, BTRFS_UUID_KEY*, UUID_lower_64_bits). ++ */ ++#if BTRFS_UUID_SIZE != 16 ++#error "UUID items require BTRFS_UUID_SIZE == 16!" ++#endif ++#define BTRFS_UUID_KEY_SUBVOL 251 /* for UUIDs assigned to subvols */ ++#define BTRFS_UUID_KEY_RECEIVED_SUBVOL 252 /* for UUIDs assigned to ++ * received subvols */ ++ ++/* ++ * string items are for debugging. They just store a short string of ++ * data in the FS ++ */ ++#define BTRFS_STRING_ITEM_KEY 253 ++ ++ ++ ++/* 32 bytes in various csum fields */ ++#define BTRFS_CSUM_SIZE 32 ++ ++/* csum types */ ++#define BTRFS_CSUM_TYPE_CRC32 0 ++ ++/* ++ * flags definitions for directory entry item type ++ * ++ * Used by: ++ * struct btrfs_dir_item.type ++ */ ++#define BTRFS_FT_UNKNOWN 0 ++#define BTRFS_FT_REG_FILE 1 ++#define BTRFS_FT_DIR 2 ++#define BTRFS_FT_CHRDEV 3 ++#define BTRFS_FT_BLKDEV 4 ++#define BTRFS_FT_FIFO 5 ++#define BTRFS_FT_SOCK 6 ++#define BTRFS_FT_SYMLINK 7 ++#define BTRFS_FT_XATTR 8 ++#define BTRFS_FT_MAX 9 ++ ++/* ++ * The key defines the order in the tree, and so it also defines (optimal) ++ * block layout. ++ * ++ * objectid corresponds to the inode number. ++ * ++ * type tells us things about the object, and is a kind of stream selector. ++ * so for a given inode, keys with type of 1 might refer to the inode data, ++ * type of 2 may point to file data in the btree and type == 3 may point to ++ * extents. ++ * ++ * offset is the starting byte offset for this key in the stream. ++ * ++ * btrfs_disk_key is in disk byte order. struct btrfs_key is always ++ * in cpu native order. Otherwise they are identical and their sizes ++ * should be the same (ie both packed) ++ */ ++struct btrfs_disk_key { ++ __le64 objectid; ++ __u8 type; ++ __le64 offset; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_key { ++ __u64 objectid; ++ __u8 type; ++ __u64 offset; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_dev_item { ++ /* the internal btrfs device id */ ++ __le64 devid; ++ ++ /* size of the device */ ++ __le64 total_bytes; ++ ++ /* bytes used */ ++ __le64 bytes_used; ++ ++ /* optimal io alignment for this device */ ++ __le32 io_align; ++ ++ /* optimal io width for this device */ ++ __le32 io_width; ++ ++ /* minimal io size for this device */ ++ __le32 sector_size; ++ ++ /* type and info about this device */ ++ __le64 type; ++ ++ /* expected generation for this device */ ++ __le64 generation; ++ ++ /* ++ * starting byte of this partition on the device, ++ * to allow for stripe alignment in the future ++ */ ++ __le64 start_offset; ++ ++ /* grouping information for allocation decisions */ ++ __le32 dev_group; ++ ++ /* seek speed 0-100 where 100 is fastest */ ++ __u8 seek_speed; ++ ++ /* bandwidth 0-100 where 100 is fastest */ ++ __u8 bandwidth; ++ ++ /* btrfs generated uuid for this device */ ++ __u8 uuid[BTRFS_UUID_SIZE]; ++ ++ /* uuid of FS who owns this device */ ++ __u8 fsid[BTRFS_UUID_SIZE]; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_stripe { ++ __le64 devid; ++ __le64 offset; ++ __u8 dev_uuid[BTRFS_UUID_SIZE]; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_chunk { ++ /* size of this chunk in bytes */ ++ __le64 length; ++ ++ /* objectid of the root referencing this chunk */ ++ __le64 owner; ++ ++ __le64 stripe_len; ++ __le64 type; ++ ++ /* optimal io alignment for this chunk */ ++ __le32 io_align; ++ ++ /* optimal io width for this chunk */ ++ __le32 io_width; ++ ++ /* minimal io size for this chunk */ ++ __le32 sector_size; ++ ++ /* 2^16 stripes is quite a lot, a second limit is the size of a single ++ * item in the btree ++ */ ++ __le16 num_stripes; ++ ++ /* sub stripes only matter for raid10 */ ++ __le16 sub_stripes; ++ struct btrfs_stripe stripe; ++ /* additional stripes go here */ ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_FREE_SPACE_EXTENT 1 ++#define BTRFS_FREE_SPACE_BITMAP 2 ++ ++struct btrfs_free_space_entry { ++ __le64 offset; ++ __le64 bytes; ++ __u8 type; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_free_space_header { ++ struct btrfs_disk_key location; ++ __le64 generation; ++ __le64 num_entries; ++ __le64 num_bitmaps; ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0) ++#define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) ++ ++/* Super block flags */ ++/* Errors detected */ ++#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2) ++ ++#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) ++#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) ++#define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34) ++#define BTRFS_SUPER_FLAG_CHANGING_FSID (1ULL << 35) ++#define BTRFS_SUPER_FLAG_CHANGING_FSID_V2 (1ULL << 36) ++ ++ ++/* ++ * items in the extent btree are used to record the objectid of the ++ * owner of the block and the number of references ++ */ ++ ++struct btrfs_extent_item { ++ __le64 refs; ++ __le64 generation; ++ __le64 flags; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_extent_item_v0 { ++ __le32 refs; ++} __attribute__ ((__packed__)); ++ ++ ++#define BTRFS_EXTENT_FLAG_DATA (1ULL << 0) ++#define BTRFS_EXTENT_FLAG_TREE_BLOCK (1ULL << 1) ++ ++/* following flags only apply to tree blocks */ ++ ++/* use full backrefs for extent pointers in the block */ ++#define BTRFS_BLOCK_FLAG_FULL_BACKREF (1ULL << 8) ++ ++/* ++ * this flag is only used internally by scrub and may be changed at any time ++ * it is only declared here to avoid collisions ++ */ ++#define BTRFS_EXTENT_FLAG_SUPER (1ULL << 48) ++ ++struct btrfs_tree_block_info { ++ struct btrfs_disk_key key; ++ __u8 level; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_extent_data_ref { ++ __le64 root; ++ __le64 objectid; ++ __le64 offset; ++ __le32 count; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_shared_data_ref { ++ __le32 count; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_extent_inline_ref { ++ __u8 type; ++ __le64 offset; ++} __attribute__ ((__packed__)); ++ ++/* old style backrefs item */ ++struct btrfs_extent_ref_v0 { ++ __le64 root; ++ __le64 generation; ++ __le64 objectid; ++ __le32 count; ++} __attribute__ ((__packed__)); ++ ++ ++/* dev extents record free space on individual devices. The owner ++ * field points back to the chunk allocation mapping tree that allocated ++ * the extent. The chunk tree uuid field is a way to double check the owner ++ */ ++struct btrfs_dev_extent { ++ __le64 chunk_tree; ++ __le64 chunk_objectid; ++ __le64 chunk_offset; ++ __le64 length; ++ __u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_inode_ref { ++ __le64 index; ++ __le16 name_len; ++ /* name goes here */ ++} __attribute__ ((__packed__)); ++ ++struct btrfs_inode_extref { ++ __le64 parent_objectid; ++ __le64 index; ++ __le16 name_len; ++ __u8 name[0]; ++ /* name goes here */ ++} __attribute__ ((__packed__)); ++ ++struct btrfs_timespec { ++ __le64 sec; ++ __le32 nsec; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_inode_item { ++ /* nfs style generation number */ ++ __le64 generation; ++ /* transid that last touched this inode */ ++ __le64 transid; ++ __le64 size; ++ __le64 nbytes; ++ __le64 block_group; ++ __le32 nlink; ++ __le32 uid; ++ __le32 gid; ++ __le32 mode; ++ __le64 rdev; ++ __le64 flags; ++ ++ /* modification sequence number for NFS */ ++ __le64 sequence; ++ ++ /* ++ * a little future expansion, for more than this we can ++ * just grow the inode item and version it ++ */ ++ __le64 reserved[4]; ++ struct btrfs_timespec atime; ++ struct btrfs_timespec ctime; ++ struct btrfs_timespec mtime; ++ struct btrfs_timespec otime; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_dir_log_item { ++ __le64 end; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_dir_item { ++ struct btrfs_disk_key location; ++ __le64 transid; ++ __le16 data_len; ++ __le16 name_len; ++ __u8 type; ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) ++ ++/* ++ * Internal in-memory flag that a subvolume has been marked for deletion but ++ * still visible as a directory ++ */ ++#define BTRFS_ROOT_SUBVOL_DEAD (1ULL << 48) ++ ++struct btrfs_root_item { ++ struct btrfs_inode_item inode; ++ __le64 generation; ++ __le64 root_dirid; ++ __le64 bytenr; ++ __le64 byte_limit; ++ __le64 bytes_used; ++ __le64 last_snapshot; ++ __le64 flags; ++ __le32 refs; ++ struct btrfs_disk_key drop_progress; ++ __u8 drop_level; ++ __u8 level; ++ ++ /* ++ * The following fields appear after subvol_uuids+subvol_times ++ * were introduced. ++ */ ++ ++ /* ++ * This generation number is used to test if the new fields are valid ++ * and up to date while reading the root item. Every time the root item ++ * is written out, the "generation" field is copied into this field. If ++ * anyone ever mounted the fs with an older kernel, we will have ++ * mismatching generation values here and thus must invalidate the ++ * new fields. See btrfs_update_root and btrfs_find_last_root for ++ * details. ++ * the offset of generation_v2 is also used as the start for the memset ++ * when invalidating the fields. ++ */ ++ __le64 generation_v2; ++ __u8 uuid[BTRFS_UUID_SIZE]; ++ __u8 parent_uuid[BTRFS_UUID_SIZE]; ++ __u8 received_uuid[BTRFS_UUID_SIZE]; ++ __le64 ctransid; /* updated when an inode changes */ ++ __le64 otransid; /* trans when created */ ++ __le64 stransid; /* trans when sent. non-zero for received subvol */ ++ __le64 rtransid; /* trans when received. non-zero for received subvol */ ++ struct btrfs_timespec ctime; ++ struct btrfs_timespec otime; ++ struct btrfs_timespec stime; ++ struct btrfs_timespec rtime; ++ __le64 reserved[8]; /* for future */ ++} __attribute__ ((__packed__)); ++ ++/* ++ * this is used for both forward and backward root refs ++ */ ++struct btrfs_root_ref { ++ __le64 dirid; ++ __le64 sequence; ++ __le16 name_len; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_disk_balance_args { ++ /* ++ * profiles to operate on, single is denoted by ++ * BTRFS_AVAIL_ALLOC_BIT_SINGLE ++ */ ++ __le64 profiles; ++ ++ /* ++ * usage filter ++ * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N' ++ * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max ++ */ ++ union { ++ __le64 usage; ++ struct { ++ __le32 usage_min; ++ __le32 usage_max; ++ }; ++ }; ++ ++ /* devid filter */ ++ __le64 devid; ++ ++ /* devid subset filter [pstart..pend) */ ++ __le64 pstart; ++ __le64 pend; ++ ++ /* btrfs virtual address space subset filter [vstart..vend) */ ++ __le64 vstart; ++ __le64 vend; ++ ++ /* ++ * profile to convert to, single is denoted by ++ * BTRFS_AVAIL_ALLOC_BIT_SINGLE ++ */ ++ __le64 target; ++ ++ /* BTRFS_BALANCE_ARGS_* */ ++ __le64 flags; ++ ++ /* ++ * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' ++ * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum ++ * and maximum ++ */ ++ union { ++ __le64 limit; ++ struct { ++ __le32 limit_min; ++ __le32 limit_max; ++ }; ++ }; ++ ++ /* ++ * Process chunks that cross stripes_min..stripes_max devices, ++ * BTRFS_BALANCE_ARGS_STRIPES_RANGE ++ */ ++ __le32 stripes_min; ++ __le32 stripes_max; ++ ++ __le64 unused[6]; ++} __attribute__ ((__packed__)); ++ ++/* ++ * store balance parameters to disk so that balance can be properly ++ * resumed after crash or unmount ++ */ ++struct btrfs_balance_item { ++ /* BTRFS_BALANCE_* */ ++ __le64 flags; ++ ++ struct btrfs_disk_balance_args data; ++ struct btrfs_disk_balance_args meta; ++ struct btrfs_disk_balance_args sys; ++ ++ __le64 unused[4]; ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_FILE_EXTENT_INLINE 0 ++#define BTRFS_FILE_EXTENT_REG 1 ++#define BTRFS_FILE_EXTENT_PREALLOC 2 ++#define BTRFS_FILE_EXTENT_TYPES 2 ++ ++struct btrfs_file_extent_item { ++ /* ++ * transaction id that created this extent ++ */ ++ __le64 generation; ++ /* ++ * max number of bytes to hold this extent in ram ++ * when we split a compressed extent we can't know how big ++ * each of the resulting pieces will be. So, this is ++ * an upper limit on the size of the extent in ram instead of ++ * an exact limit. ++ */ ++ __le64 ram_bytes; ++ ++ /* ++ * 32 bits for the various ways we might encode the data, ++ * including compression and encryption. If any of these ++ * are set to something a given disk format doesn't understand ++ * it is treated like an incompat flag for reading and writing, ++ * but not for stat. ++ */ ++ __u8 compression; ++ __u8 encryption; ++ __le16 other_encoding; /* spare for later use */ ++ ++ /* are we inline data or a real extent? */ ++ __u8 type; ++ ++ /* ++ * disk space consumed by the extent, checksum blocks are included ++ * in these numbers ++ * ++ * At this offset in the structure, the inline extent data start. ++ */ ++ __le64 disk_bytenr; ++ __le64 disk_num_bytes; ++ /* ++ * the logical offset in file blocks (no csums) ++ * this extent record is for. This allows a file extent to point ++ * into the middle of an existing extent on disk, sharing it ++ * between two snapshots (useful if some bytes in the middle of the ++ * extent have changed ++ */ ++ __le64 offset; ++ /* ++ * the logical number of file blocks (no csums included). This ++ * always reflects the size uncompressed and without encoding. ++ */ ++ __le64 num_bytes; ++ ++} __attribute__ ((__packed__)); ++ ++struct btrfs_csum_item { ++ __u8 csum; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_dev_stats_item { ++ /* ++ * grow this item struct at the end for future enhancements and keep ++ * the existing values unchanged ++ */ ++ __le64 values[BTRFS_DEV_STAT_VALUES_MAX]; ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 ++#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 ++#define BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED 0 ++#define BTRFS_DEV_REPLACE_ITEM_STATE_STARTED 1 ++#define BTRFS_DEV_REPLACE_ITEM_STATE_SUSPENDED 2 ++#define BTRFS_DEV_REPLACE_ITEM_STATE_FINISHED 3 ++#define BTRFS_DEV_REPLACE_ITEM_STATE_CANCELED 4 ++ ++struct btrfs_dev_replace_item { ++ /* ++ * grow this item struct at the end for future enhancements and keep ++ * the existing values unchanged ++ */ ++ __le64 src_devid; ++ __le64 cursor_left; ++ __le64 cursor_right; ++ __le64 cont_reading_from_srcdev_mode; ++ ++ __le64 replace_state; ++ __le64 time_started; ++ __le64 time_stopped; ++ __le64 num_write_errors; ++ __le64 num_uncorrectable_read_errors; ++} __attribute__ ((__packed__)); ++ ++/* different types of block groups (and chunks) */ ++#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) ++#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) ++#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) ++#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) ++#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) ++#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) ++#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) ++#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) ++#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) ++#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ ++ BTRFS_SPACE_INFO_GLOBAL_RSV) ++ ++enum btrfs_raid_types { ++ BTRFS_RAID_RAID10, ++ BTRFS_RAID_RAID1, ++ BTRFS_RAID_DUP, ++ BTRFS_RAID_RAID0, ++ BTRFS_RAID_SINGLE, ++ BTRFS_RAID_RAID5, ++ BTRFS_RAID_RAID6, ++ BTRFS_NR_RAID_TYPES ++}; ++ ++#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ ++ BTRFS_BLOCK_GROUP_SYSTEM | \ ++ BTRFS_BLOCK_GROUP_METADATA) ++ ++#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ ++ BTRFS_BLOCK_GROUP_RAID1 | \ ++ BTRFS_BLOCK_GROUP_RAID5 | \ ++ BTRFS_BLOCK_GROUP_RAID6 | \ ++ BTRFS_BLOCK_GROUP_DUP | \ ++ BTRFS_BLOCK_GROUP_RAID10) ++#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \ ++ BTRFS_BLOCK_GROUP_RAID6) ++ ++/* ++ * We need a bit for restriper to be able to tell when chunks of type ++ * SINGLE are available. This "extended" profile format is used in ++ * fs_info->avail_*_alloc_bits (in-memory) and balance item fields ++ * (on-disk). The corresponding on-disk bit in chunk.type is reserved ++ * to avoid remappings between two formats in future. ++ */ ++#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) ++ ++/* ++ * A fake block group type that is used to communicate global block reserve ++ * size to userspace via the SPACE_INFO ioctl. ++ */ ++#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) ++ ++#define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ ++ BTRFS_AVAIL_ALLOC_BIT_SINGLE) ++ ++static inline __u64 chunk_to_extended(__u64 flags) ++{ ++ if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0) ++ flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE; ++ ++ return flags; ++} ++static inline __u64 extended_to_chunk(__u64 flags) ++{ ++ return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; ++} ++ ++struct btrfs_block_group_item { ++ __le64 used; ++ __le64 chunk_objectid; ++ __le64 flags; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_free_space_info { ++ __le32 extent_count; ++ __le32 flags; ++} __attribute__ ((__packed__)); ++ ++#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) ++ ++#define BTRFS_QGROUP_LEVEL_SHIFT 48 ++static inline __u64 btrfs_qgroup_level(__u64 qgroupid) ++{ ++ return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; ++} ++ ++/* ++ * is subvolume quota turned on? ++ */ ++#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0) ++/* ++ * RESCAN is set during the initialization phase ++ */ ++#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1) ++/* ++ * Some qgroup entries are known to be out of date, ++ * either because the configuration has changed in a way that ++ * makes a rescan necessary, or because the fs has been mounted ++ * with a non-qgroup-aware version. ++ * Turning qouta off and on again makes it inconsistent, too. ++ */ ++#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) ++ ++#define BTRFS_QGROUP_STATUS_VERSION 1 ++ ++struct btrfs_qgroup_status_item { ++ __le64 version; ++ /* ++ * the generation is updated during every commit. As older ++ * versions of btrfs are not aware of qgroups, it will be ++ * possible to detect inconsistencies by checking the ++ * generation on mount time ++ */ ++ __le64 generation; ++ ++ /* flag definitions see above */ ++ __le64 flags; ++ ++ /* ++ * only used during scanning to record the progress ++ * of the scan. It contains a logical address ++ */ ++ __le64 rescan; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_qgroup_info_item { ++ __le64 generation; ++ __le64 rfer; ++ __le64 rfer_cmpr; ++ __le64 excl; ++ __le64 excl_cmpr; ++} __attribute__ ((__packed__)); ++ ++struct btrfs_qgroup_limit_item { ++ /* ++ * only updated when any of the other values change ++ */ ++ __le64 flags; ++ __le64 max_rfer; ++ __le64 max_excl; ++ __le64 rsv_rfer; ++ __le64 rsv_excl; ++} __attribute__ ((__packed__)); ++ ++#endif /* _BTRFS_CTREE_H_ */ +diff --git a/src/basic/linux/can/vxcan.h b/src/basic/linux/can/vxcan.h +new file mode 100644 +index 00000000000..066812d118a +--- /dev/null ++++ b/src/basic/linux/can/vxcan.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI_CAN_VXCAN_H ++#define _UAPI_CAN_VXCAN_H ++ ++enum { ++ VXCAN_INFO_UNSPEC, ++ VXCAN_INFO_PEER, ++ ++ __VXCAN_INFO_MAX ++#define VXCAN_INFO_MAX (__VXCAN_INFO_MAX - 1) ++}; ++ ++#endif +diff --git a/src/basic/linux/fib_rules.h b/src/basic/linux/fib_rules.h +new file mode 100644 +index 00000000000..232df14e128 +--- /dev/null ++++ b/src/basic/linux/fib_rules.h +@@ -0,0 +1,90 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef __LINUX_FIB_RULES_H ++#define __LINUX_FIB_RULES_H ++ ++#include ++#include ++ ++/* rule is permanent, and cannot be deleted */ ++#define FIB_RULE_PERMANENT 0x00000001 ++#define FIB_RULE_INVERT 0x00000002 ++#define FIB_RULE_UNRESOLVED 0x00000004 ++#define FIB_RULE_IIF_DETACHED 0x00000008 ++#define FIB_RULE_DEV_DETACHED FIB_RULE_IIF_DETACHED ++#define FIB_RULE_OIF_DETACHED 0x00000010 ++ ++/* try to find source address in routing lookups */ ++#define FIB_RULE_FIND_SADDR 0x00010000 ++ ++struct fib_rule_hdr { ++ __u8 family; ++ __u8 dst_len; ++ __u8 src_len; ++ __u8 tos; ++ ++ __u8 table; ++ __u8 res1; /* reserved */ ++ __u8 res2; /* reserved */ ++ __u8 action; ++ ++ __u32 flags; ++}; ++ ++struct fib_rule_uid_range { ++ __u32 start; ++ __u32 end; ++}; ++ ++struct fib_rule_port_range { ++ __u16 start; ++ __u16 end; ++}; ++ ++enum { ++ FRA_UNSPEC, ++ FRA_DST, /* destination address */ ++ FRA_SRC, /* source address */ ++ FRA_IIFNAME, /* interface name */ ++#define FRA_IFNAME FRA_IIFNAME ++ FRA_GOTO, /* target to jump to (FR_ACT_GOTO) */ ++ FRA_UNUSED2, ++ FRA_PRIORITY, /* priority/preference */ ++ FRA_UNUSED3, ++ FRA_UNUSED4, ++ FRA_UNUSED5, ++ FRA_FWMARK, /* mark */ ++ FRA_FLOW, /* flow/class id */ ++ FRA_TUN_ID, ++ FRA_SUPPRESS_IFGROUP, ++ FRA_SUPPRESS_PREFIXLEN, ++ FRA_TABLE, /* Extended table id */ ++ FRA_FWMASK, /* mask for netfilter mark */ ++ FRA_OIFNAME, ++ FRA_PAD, ++ FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ ++ FRA_UID_RANGE, /* UID range */ ++ FRA_PROTOCOL, /* Originator of the rule */ ++ FRA_IP_PROTO, /* ip proto */ ++ FRA_SPORT_RANGE, /* sport */ ++ FRA_DPORT_RANGE, /* dport */ ++ __FRA_MAX ++}; ++ ++#define FRA_MAX (__FRA_MAX - 1) ++ ++enum { ++ FR_ACT_UNSPEC, ++ FR_ACT_TO_TBL, /* Pass to fixed table */ ++ FR_ACT_GOTO, /* Jump to another rule */ ++ FR_ACT_NOP, /* No operation */ ++ FR_ACT_RES3, ++ FR_ACT_RES4, ++ FR_ACT_BLACKHOLE, /* Drop without notification */ ++ FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ ++ FR_ACT_PROHIBIT, /* Drop with EACCES */ ++ __FR_ACT_MAX, ++}; ++ ++#define FR_ACT_MAX (__FR_ACT_MAX - 1) ++ ++#endif +diff --git a/src/basic/linux/fou.h b/src/basic/linux/fou.h +new file mode 100644 +index 00000000000..f2ea833a281 +--- /dev/null ++++ b/src/basic/linux/fou.h +@@ -0,0 +1,42 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* fou.h - FOU Interface */ ++ ++#ifndef _UAPI_LINUX_FOU_H ++#define _UAPI_LINUX_FOU_H ++ ++/* NETLINK_GENERIC related info ++ */ ++#define FOU_GENL_NAME "fou" ++#define FOU_GENL_VERSION 0x1 ++ ++enum { ++ FOU_ATTR_UNSPEC, ++ FOU_ATTR_PORT, /* u16 */ ++ FOU_ATTR_AF, /* u8 */ ++ FOU_ATTR_IPPROTO, /* u8 */ ++ FOU_ATTR_TYPE, /* u8 */ ++ FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ ++ ++ __FOU_ATTR_MAX, ++}; ++ ++#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1) ++ ++enum { ++ FOU_CMD_UNSPEC, ++ FOU_CMD_ADD, ++ FOU_CMD_DEL, ++ FOU_CMD_GET, ++ ++ __FOU_CMD_MAX, ++}; ++ ++enum { ++ FOU_ENCAP_UNSPEC, ++ FOU_ENCAP_DIRECT, ++ FOU_ENCAP_GUE, ++}; ++ ++#define FOU_CMD_MAX (__FOU_CMD_MAX - 1) ++ ++#endif /* _UAPI_LINUX_FOU_H */ +diff --git a/src/basic/linux/if.h b/src/basic/linux/if.h +new file mode 100644 +index 00000000000..cbabdde8f9d +--- /dev/null ++++ b/src/basic/linux/if.h +@@ -0,0 +1,294 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Global definitions for the INET interface module. ++ * ++ * Version: @(#)if.h 1.0.2 04/18/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 ++ * Ross Biro ++ * Fred N. van Kempen, ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ */ ++#ifndef _LINUX_IF_H ++#define _LINUX_IF_H ++ ++#include /* for compatibility with glibc */ ++#include /* for "__kernel_caddr_t" et al */ ++#include /* for "struct sockaddr" et al */ ++ ++#ifndef __KERNEL__ ++#include /* for struct sockaddr. */ ++#endif ++ ++#if __UAPI_DEF_IF_IFNAMSIZ ++#define IFNAMSIZ 16 ++#endif /* __UAPI_DEF_IF_IFNAMSIZ */ ++#define IFALIASZ 256 ++#include ++ ++/* For glibc compatibility. An empty enum does not compile. */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || \ ++ __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 ++/** ++ * enum net_device_flags - &struct net_device flags ++ * ++ * These are the &struct net_device flags, they can be set by drivers, the ++ * kernel and some can be triggered by userspace. Userspace can query and ++ * set these flags using userspace utilities but there is also a sysfs ++ * entry available for all dev flags which can be queried and set. These flags ++ * are shared for all types of net_devices. The sysfs entries are available ++ * via /sys/class/net//flags. Flags which can be toggled through sysfs ++ * are annotated below, note that only a few flags can be toggled and some ++ * other flags are always preserved from the original net_device flags ++ * even if you try to set them via sysfs. Flags which are always preserved ++ * are kept under the flag grouping @IFF_VOLATILE. Flags which are volatile ++ * are annotated below as such. ++ * ++ * You should have a pretty good reason to be extending these flags. ++ * ++ * @IFF_UP: interface is up. Can be toggled through sysfs. ++ * @IFF_BROADCAST: broadcast address valid. Volatile. ++ * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs. ++ * @IFF_LOOPBACK: is a loopback net. Volatile. ++ * @IFF_POINTOPOINT: interface is has p-p link. Volatile. ++ * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs. ++ * Volatile. ++ * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile. ++ * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile. ++ * @IFF_PROMISC: receive all packets. Can be toggled through sysfs. ++ * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through ++ * sysfs. ++ * @IFF_MASTER: master of a load balancer. Volatile. ++ * @IFF_SLAVE: slave of a load balancer. Volatile. ++ * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs. ++ * @IFF_PORTSEL: can set media type. Can be toggled through sysfs. ++ * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs. ++ * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled ++ * through sysfs. ++ * @IFF_LOWER_UP: driver signals L1 up. Volatile. ++ * @IFF_DORMANT: driver signals dormant. Volatile. ++ * @IFF_ECHO: echo sent packets. Volatile. ++ */ ++enum net_device_flags { ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS ++ IFF_UP = 1<<0, /* sysfs */ ++ IFF_BROADCAST = 1<<1, /* volatile */ ++ IFF_DEBUG = 1<<2, /* sysfs */ ++ IFF_LOOPBACK = 1<<3, /* volatile */ ++ IFF_POINTOPOINT = 1<<4, /* volatile */ ++ IFF_NOTRAILERS = 1<<5, /* sysfs */ ++ IFF_RUNNING = 1<<6, /* volatile */ ++ IFF_NOARP = 1<<7, /* sysfs */ ++ IFF_PROMISC = 1<<8, /* sysfs */ ++ IFF_ALLMULTI = 1<<9, /* sysfs */ ++ IFF_MASTER = 1<<10, /* volatile */ ++ IFF_SLAVE = 1<<11, /* volatile */ ++ IFF_MULTICAST = 1<<12, /* sysfs */ ++ IFF_PORTSEL = 1<<13, /* sysfs */ ++ IFF_AUTOMEDIA = 1<<14, /* sysfs */ ++ IFF_DYNAMIC = 1<<15, /* sysfs */ ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO ++ IFF_LOWER_UP = 1<<16, /* volatile */ ++ IFF_DORMANT = 1<<17, /* volatile */ ++ IFF_ECHO = 1<<18, /* volatile */ ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ ++}; ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */ ++ ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS ++#define IFF_UP IFF_UP ++#define IFF_BROADCAST IFF_BROADCAST ++#define IFF_DEBUG IFF_DEBUG ++#define IFF_LOOPBACK IFF_LOOPBACK ++#define IFF_POINTOPOINT IFF_POINTOPOINT ++#define IFF_NOTRAILERS IFF_NOTRAILERS ++#define IFF_RUNNING IFF_RUNNING ++#define IFF_NOARP IFF_NOARP ++#define IFF_PROMISC IFF_PROMISC ++#define IFF_ALLMULTI IFF_ALLMULTI ++#define IFF_MASTER IFF_MASTER ++#define IFF_SLAVE IFF_SLAVE ++#define IFF_MULTICAST IFF_MULTICAST ++#define IFF_PORTSEL IFF_PORTSEL ++#define IFF_AUTOMEDIA IFF_AUTOMEDIA ++#define IFF_DYNAMIC IFF_DYNAMIC ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ ++ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO ++#define IFF_LOWER_UP IFF_LOWER_UP ++#define IFF_DORMANT IFF_DORMANT ++#define IFF_ECHO IFF_ECHO ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ ++ ++#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ ++ IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) ++ ++#define IF_GET_IFACE 0x0001 /* for querying only */ ++#define IF_GET_PROTO 0x0002 ++ ++/* For definitions see hdlc.h */ ++#define IF_IFACE_V35 0x1000 /* V.35 serial interface */ ++#define IF_IFACE_V24 0x1001 /* V.24 serial interface */ ++#define IF_IFACE_X21 0x1002 /* X.21 serial interface */ ++#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ ++#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ ++#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ ++#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */ ++ ++/* For definitions see hdlc.h */ ++#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ ++#define IF_PROTO_PPP 0x2001 /* PPP protocol */ ++#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */ ++#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */ ++#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ ++#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ ++#define IF_PROTO_X25 0x2006 /* X.25 */ ++#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ ++#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ ++#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ ++#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ ++#define IF_PROTO_FR_ETH_PVC 0x200B ++#define IF_PROTO_RAW 0x200C /* RAW Socket */ ++ ++/* RFC 2863 operational status */ ++enum { ++ IF_OPER_UNKNOWN, ++ IF_OPER_NOTPRESENT, ++ IF_OPER_DOWN, ++ IF_OPER_LOWERLAYERDOWN, ++ IF_OPER_TESTING, ++ IF_OPER_DORMANT, ++ IF_OPER_UP, ++}; ++ ++/* link modes */ ++enum { ++ IF_LINK_MODE_DEFAULT, ++ IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ ++}; ++ ++/* ++ * Device mapping structure. I'd just gone off and designed a ++ * beautiful scheme using only loadable modules with arguments ++ * for driver options and along come the PCMCIA people 8) ++ * ++ * Ah well. The get() side of this is good for WDSETUP, and it'll ++ * be handy for debugging things. The set side is fine for now and ++ * being very small might be worth keeping for clean configuration. ++ */ ++ ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFMAP ++struct ifmap { ++ unsigned long mem_start; ++ unsigned long mem_end; ++ unsigned short base_addr; ++ unsigned char irq; ++ unsigned char dma; ++ unsigned char port; ++ /* 3 bytes spare */ ++}; ++#endif /* __UAPI_DEF_IF_IFMAP */ ++ ++struct if_settings { ++ unsigned int type; /* Type of physical device or protocol */ ++ unsigned int size; /* Size of the data allocated by the caller */ ++ union { ++ /* {atm/eth/dsl}_settings anyone ? */ ++ raw_hdlc_proto *raw_hdlc; ++ cisco_proto *cisco; ++ fr_proto *fr; ++ fr_proto_pvc *fr_pvc; ++ fr_proto_pvc_info *fr_pvc_info; ++ ++ /* interface settings */ ++ sync_serial_settings *sync; ++ te1_settings *te1; ++ } ifs_ifsu; ++}; ++ ++/* ++ * Interface request structure used for socket ++ * ioctl's. All interface ioctl's must have parameter ++ * definitions which begin with ifr_name. The ++ * remainder may be interface specific. ++ */ ++ ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFREQ ++struct ifreq { ++#define IFHWADDRLEN 6 ++ union ++ { ++ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ ++ } ifr_ifrn; ++ ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ struct sockaddr ifru_hwaddr; ++ short ifru_flags; ++ int ifru_ivalue; ++ int ifru_mtu; ++ struct ifmap ifru_map; ++ char ifru_slave[IFNAMSIZ]; /* Just fits the size */ ++ char ifru_newname[IFNAMSIZ]; ++ void * ifru_data; ++ struct if_settings ifru_settings; ++ } ifr_ifru; ++}; ++#endif /* __UAPI_DEF_IF_IFREQ */ ++ ++#define ifr_name ifr_ifrn.ifrn_name /* interface name */ ++#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ ++#define ifr_addr ifr_ifru.ifru_addr /* address */ ++#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ ++#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ ++#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ ++#define ifr_flags ifr_ifru.ifru_flags /* flags */ ++#define ifr_metric ifr_ifru.ifru_ivalue /* metric */ ++#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ ++#define ifr_map ifr_ifru.ifru_map /* device map */ ++#define ifr_slave ifr_ifru.ifru_slave /* slave device */ ++#define ifr_data ifr_ifru.ifru_data /* for use by interface */ ++#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ ++#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ ++#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ ++#define ifr_newname ifr_ifru.ifru_newname /* New name */ ++#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ ++ ++/* ++ * Structure used in SIOCGIFCONF request. ++ * Used to retrieve interface configuration ++ * for machine (useful for programs which ++ * must know all networks accessible). ++ */ ++ ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFCONF ++struct ifconf { ++ int ifc_len; /* size of buffer */ ++ union { ++ char *ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++}; ++#endif /* __UAPI_DEF_IF_IFCONF */ ++ ++#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ ++#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ ++ ++#endif /* _LINUX_IF_H */ +diff --git a/src/basic/linux/if_addr.h b/src/basic/linux/if_addr.h +new file mode 100644 +index 00000000000..dfcf3ce0097 +--- /dev/null ++++ b/src/basic/linux/if_addr.h +@@ -0,0 +1,72 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef __LINUX_IF_ADDR_H ++#define __LINUX_IF_ADDR_H ++ ++#include ++#include ++ ++struct ifaddrmsg { ++ __u8 ifa_family; ++ __u8 ifa_prefixlen; /* The prefix length */ ++ __u8 ifa_flags; /* Flags */ ++ __u8 ifa_scope; /* Address scope */ ++ __u32 ifa_index; /* Link index */ ++}; ++ ++/* ++ * Important comment: ++ * IFA_ADDRESS is prefix address, rather than local interface address. ++ * It makes no difference for normally configured broadcast interfaces, ++ * but for point-to-point IFA_ADDRESS is DESTINATION address, ++ * local address is supplied in IFA_LOCAL attribute. ++ * ++ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags. ++ * If present, the value from struct ifaddrmsg will be ignored. ++ */ ++enum { ++ IFA_UNSPEC, ++ IFA_ADDRESS, ++ IFA_LOCAL, ++ IFA_LABEL, ++ IFA_BROADCAST, ++ IFA_ANYCAST, ++ IFA_CACHEINFO, ++ IFA_MULTICAST, ++ IFA_FLAGS, ++ IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ ++ IFA_TARGET_NETNSID, ++ __IFA_MAX, ++}; ++ ++#define IFA_MAX (__IFA_MAX - 1) ++ ++/* ifa_flags */ ++#define IFA_F_SECONDARY 0x01 ++#define IFA_F_TEMPORARY IFA_F_SECONDARY ++ ++#define IFA_F_NODAD 0x02 ++#define IFA_F_OPTIMISTIC 0x04 ++#define IFA_F_DADFAILED 0x08 ++#define IFA_F_HOMEADDRESS 0x10 ++#define IFA_F_DEPRECATED 0x20 ++#define IFA_F_TENTATIVE 0x40 ++#define IFA_F_PERMANENT 0x80 ++#define IFA_F_MANAGETEMPADDR 0x100 ++#define IFA_F_NOPREFIXROUTE 0x200 ++#define IFA_F_MCAUTOJOIN 0x400 ++#define IFA_F_STABLE_PRIVACY 0x800 ++ ++struct ifa_cacheinfo { ++ __u32 ifa_prefered; ++ __u32 ifa_valid; ++ __u32 cstamp; /* created timestamp, hundredths of seconds */ ++ __u32 tstamp; /* updated timestamp, hundredths of seconds */ ++}; ++ ++/* backwards compatibility for userspace */ ++#ifndef __KERNEL__ ++#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) ++#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) ++#endif ++ ++#endif +diff --git a/src/basic/linux/if_arp.h b/src/basic/linux/if_arp.h +new file mode 100644 +index 00000000000..c3cc5a9e5ea +--- /dev/null ++++ b/src/basic/linux/if_arp.h +@@ -0,0 +1,164 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Global definitions for the ARP (RFC 826) protocol. ++ * ++ * Version: @(#)if_arp.h 1.0.1 04/16/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 ++ * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. ++ * Ross Biro ++ * Fred N. van Kempen, ++ * Florian La Roche, ++ * Jonathan Layes ++ * Arnaldo Carvalho de Melo ARPHRD_HWX25 ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ */ ++#ifndef _UAPI_LINUX_IF_ARP_H ++#define _UAPI_LINUX_IF_ARP_H ++ ++#include ++ ++/* ARP protocol HARDWARE identifiers. */ ++#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ ++#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ ++#define ARPHRD_EETHER 2 /* Experimental Ethernet */ ++#define ARPHRD_AX25 3 /* AX.25 Level 2 */ ++#define ARPHRD_PRONET 4 /* PROnet token ring */ ++#define ARPHRD_CHAOS 5 /* Chaosnet */ ++#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */ ++#define ARPHRD_ARCNET 7 /* ARCnet */ ++#define ARPHRD_APPLETLK 8 /* APPLEtalk */ ++#define ARPHRD_DLCI 15 /* Frame Relay DLCI */ ++#define ARPHRD_ATM 19 /* ATM */ ++#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */ ++#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */ ++#define ARPHRD_EUI64 27 /* EUI-64 */ ++#define ARPHRD_INFINIBAND 32 /* InfiniBand */ ++ ++/* Dummy types for non ARP hardware */ ++#define ARPHRD_SLIP 256 ++#define ARPHRD_CSLIP 257 ++#define ARPHRD_SLIP6 258 ++#define ARPHRD_CSLIP6 259 ++#define ARPHRD_RSRVD 260 /* Notional KISS type */ ++#define ARPHRD_ADAPT 264 ++#define ARPHRD_ROSE 270 ++#define ARPHRD_X25 271 /* CCITT X.25 */ ++#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */ ++#define ARPHRD_CAN 280 /* Controller Area Network */ ++#define ARPHRD_PPP 512 ++#define ARPHRD_CISCO 513 /* Cisco HDLC */ ++#define ARPHRD_HDLC ARPHRD_CISCO ++#define ARPHRD_LAPB 516 /* LAPB */ ++#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */ ++#define ARPHRD_RAWHDLC 518 /* Raw HDLC */ ++#define ARPHRD_RAWIP 519 /* Raw IP */ ++ ++#define ARPHRD_TUNNEL 768 /* IPIP tunnel */ ++#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */ ++#define ARPHRD_FRAD 770 /* Frame Relay Access Device */ ++#define ARPHRD_SKIP 771 /* SKIP vif */ ++#define ARPHRD_LOOPBACK 772 /* Loopback device */ ++#define ARPHRD_LOCALTLK 773 /* Localtalk device */ ++#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface */ ++#define ARPHRD_BIF 775 /* AP1000 BIF */ ++#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4 */ ++#define ARPHRD_IPDDP 777 /* IP over DDP tunneller */ ++#define ARPHRD_IPGRE 778 /* GRE over IP */ ++#define ARPHRD_PIMREG 779 /* PIMSM register interface */ ++#define ARPHRD_HIPPI 780 /* High Performance Parallel Interface */ ++#define ARPHRD_ASH 781 /* Nexus 64Mbps Ash */ ++#define ARPHRD_ECONET 782 /* Acorn Econet */ ++#define ARPHRD_IRDA 783 /* Linux-IrDA */ ++/* ARP works differently on different FC media .. so */ ++#define ARPHRD_FCPP 784 /* Point to point fibrechannel */ ++#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */ ++#define ARPHRD_FCPL 786 /* Fibrechannel public loop */ ++#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */ ++ /* 787->799 reserved for fibrechannel media types */ ++#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */ ++#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ ++#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ ++#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ ++#define ARPHRD_IEEE802154 804 ++#define ARPHRD_IEEE802154_MONITOR 805 /* IEEE 802.15.4 network monitor */ ++ ++#define ARPHRD_PHONET 820 /* PhoNet media type */ ++#define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ ++#define ARPHRD_CAIF 822 /* CAIF media type */ ++#define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ ++#define ARPHRD_NETLINK 824 /* Netlink header */ ++#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ ++#define ARPHRD_VSOCKMON 826 /* Vsock monitor header */ ++ ++#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ ++#define ARPHRD_NONE 0xFFFE /* zero header length */ ++ ++/* ARP protocol opcodes. */ ++#define ARPOP_REQUEST 1 /* ARP request */ ++#define ARPOP_REPLY 2 /* ARP reply */ ++#define ARPOP_RREQUEST 3 /* RARP request */ ++#define ARPOP_RREPLY 4 /* RARP reply */ ++#define ARPOP_InREQUEST 8 /* InARP request */ ++#define ARPOP_InREPLY 9 /* InARP reply */ ++#define ARPOP_NAK 10 /* (ATM)ARP NAK */ ++ ++ ++/* ARP ioctl request. */ ++struct arpreq { ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ ++ char arp_dev[IFNAMSIZ]; ++}; ++ ++struct arpreq_old { ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ ++}; ++ ++/* ARP Flag values. */ ++#define ATF_COM 0x02 /* completed entry (ha valid) */ ++#define ATF_PERM 0x04 /* permanent entry */ ++#define ATF_PUBL 0x08 /* publish entry */ ++#define ATF_USETRAILERS 0x10 /* has requested trailers */ ++#define ATF_NETMASK 0x20 /* want to use a netmask (only ++ for proxy entries) */ ++#define ATF_DONTPUB 0x40 /* don't answer this addresses */ ++ ++/* ++ * This structure defines an ethernet arp header. ++ */ ++ ++struct arphdr { ++ __be16 ar_hrd; /* format of hardware address */ ++ __be16 ar_pro; /* format of protocol address */ ++ unsigned char ar_hln; /* length of hardware address */ ++ unsigned char ar_pln; /* length of protocol address */ ++ __be16 ar_op; /* ARP opcode (command) */ ++ ++#if 0 ++ /* ++ * Ethernet looks like this : This bit is variable sized however... ++ */ ++ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ ++ unsigned char ar_sip[4]; /* sender IP address */ ++ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ ++ unsigned char ar_tip[4]; /* target IP address */ ++#endif ++ ++}; ++ ++ ++#endif /* _UAPI_LINUX_IF_ARP_H */ +diff --git a/src/basic/linux/if_bonding.h b/src/basic/linux/if_bonding.h +new file mode 100644 +index 00000000000..61a1bf6e865 +--- /dev/null ++++ b/src/basic/linux/if_bonding.h +@@ -0,0 +1,131 @@ ++/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */ ++/* ++ * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'. ++ * ++ * ++ * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes ++ * NCM: Network and Communications Management, Inc. ++ * ++ * BUT, I'm the one who modified it for ethernet, so: ++ * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov ++ * ++ * This software may be used and distributed according to the terms ++ * of the GNU Public License, incorporated herein by reference. ++ * ++ * 2003/03/18 - Amir Noam ++ * - Added support for getting slave's speed and duplex via ethtool. ++ * Needed for 802.3ad and other future modes. ++ * ++ * 2003/03/18 - Tsippy Mendelson and ++ * Shmulik Hen ++ * - Enable support of modes that need to use the unique mac address of ++ * each slave. ++ * ++ * 2003/03/18 - Tsippy Mendelson and ++ * Amir Noam ++ * - Moved driver's private data types to bonding.h ++ * ++ * 2003/03/18 - Amir Noam , ++ * Tsippy Mendelson and ++ * Shmulik Hen ++ * - Added support for IEEE 802.3ad Dynamic link aggregation mode. ++ * ++ * 2003/05/01 - Amir Noam ++ * - Added ABI version control to restore compatibility between ++ * new/old ifenslave and new/old bonding. ++ * ++ * 2003/12/01 - Shmulik Hen ++ * - Code cleanup and style changes ++ * ++ * 2005/05/05 - Jason Gabler ++ * - added definitions for various XOR hashing policies ++ */ ++ ++#ifndef _LINUX_IF_BONDING_H ++#define _LINUX_IF_BONDING_H ++ ++#include ++#include ++#include ++ ++/* userland - kernel ABI version (2003/05/08) */ ++#define BOND_ABI_VERSION 2 ++ ++/* ++ * We can remove these ioctl definitions in 2.5. People should use the ++ * SIOC*** versions of them instead ++ */ ++#define BOND_ENSLAVE_OLD (SIOCDEVPRIVATE) ++#define BOND_RELEASE_OLD (SIOCDEVPRIVATE + 1) ++#define BOND_SETHWADDR_OLD (SIOCDEVPRIVATE + 2) ++#define BOND_SLAVE_INFO_QUERY_OLD (SIOCDEVPRIVATE + 11) ++#define BOND_INFO_QUERY_OLD (SIOCDEVPRIVATE + 12) ++#define BOND_CHANGE_ACTIVE_OLD (SIOCDEVPRIVATE + 13) ++ ++#define BOND_CHECK_MII_STATUS (SIOCGMIIPHY) ++ ++#define BOND_MODE_ROUNDROBIN 0 ++#define BOND_MODE_ACTIVEBACKUP 1 ++#define BOND_MODE_XOR 2 ++#define BOND_MODE_BROADCAST 3 ++#define BOND_MODE_8023AD 4 ++#define BOND_MODE_TLB 5 ++#define BOND_MODE_ALB 6 /* TLB + RLB (receive load balancing) */ ++ ++/* each slave's link has 4 states */ ++#define BOND_LINK_UP 0 /* link is up and running */ ++#define BOND_LINK_FAIL 1 /* link has just gone down */ ++#define BOND_LINK_DOWN 2 /* link has been down for too long time */ ++#define BOND_LINK_BACK 3 /* link is going back */ ++ ++/* each slave has several states */ ++#define BOND_STATE_ACTIVE 0 /* link is active */ ++#define BOND_STATE_BACKUP 1 /* link is backup */ ++ ++#define BOND_DEFAULT_MAX_BONDS 1 /* Default maximum number of devices to support */ ++ ++#define BOND_DEFAULT_TX_QUEUES 16 /* Default number of tx queues per device */ ++ ++#define BOND_DEFAULT_RESEND_IGMP 1 /* Default number of IGMP membership reports */ ++ ++/* hashing types */ ++#define BOND_XMIT_POLICY_LAYER2 0 /* layer 2 (MAC only), default */ ++#define BOND_XMIT_POLICY_LAYER34 1 /* layer 3+4 (IP ^ (TCP || UDP)) */ ++#define BOND_XMIT_POLICY_LAYER23 2 /* layer 2+3 (IP ^ MAC) */ ++#define BOND_XMIT_POLICY_ENCAP23 3 /* encapsulated layer 2+3 */ ++#define BOND_XMIT_POLICY_ENCAP34 4 /* encapsulated layer 3+4 */ ++ ++typedef struct ifbond { ++ __s32 bond_mode; ++ __s32 num_slaves; ++ __s32 miimon; ++} ifbond; ++ ++typedef struct ifslave { ++ __s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */ ++ char slave_name[IFNAMSIZ]; ++ __s8 link; ++ __s8 state; ++ __u32 link_failure_count; ++} ifslave; ++ ++struct ad_info { ++ __u16 aggregator_id; ++ __u16 ports; ++ __u16 actor_key; ++ __u16 partner_key; ++ __u8 partner_system[ETH_ALEN]; ++}; ++ ++#endif /* _LINUX_IF_BONDING_H */ ++ ++/* ++ * Local variables: ++ * version-control: t ++ * kept-new-versions: 5 ++ * c-indent-level: 8 ++ * c-basic-offset: 8 ++ * tab-width: 8 ++ * End: ++ */ ++ +diff --git a/src/basic/linux/if_bridge.h b/src/basic/linux/if_bridge.h +new file mode 100644 +index 00000000000..773e476a8e5 +--- /dev/null ++++ b/src/basic/linux/if_bridge.h +@@ -0,0 +1,316 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Linux ethernet bridge ++ * ++ * Authors: ++ * Lennert Buytenhek ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#ifndef _UAPI_LINUX_IF_BRIDGE_H ++#define _UAPI_LINUX_IF_BRIDGE_H ++ ++#include ++#include ++#include ++ ++#define SYSFS_BRIDGE_ATTR "bridge" ++#define SYSFS_BRIDGE_FDB "brforward" ++#define SYSFS_BRIDGE_PORT_SUBDIR "brif" ++#define SYSFS_BRIDGE_PORT_ATTR "brport" ++#define SYSFS_BRIDGE_PORT_LINK "bridge" ++ ++#define BRCTL_VERSION 1 ++ ++#define BRCTL_GET_VERSION 0 ++#define BRCTL_GET_BRIDGES 1 ++#define BRCTL_ADD_BRIDGE 2 ++#define BRCTL_DEL_BRIDGE 3 ++#define BRCTL_ADD_IF 4 ++#define BRCTL_DEL_IF 5 ++#define BRCTL_GET_BRIDGE_INFO 6 ++#define BRCTL_GET_PORT_LIST 7 ++#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 ++#define BRCTL_SET_BRIDGE_HELLO_TIME 9 ++#define BRCTL_SET_BRIDGE_MAX_AGE 10 ++#define BRCTL_SET_AGEING_TIME 11 ++#define BRCTL_SET_GC_INTERVAL 12 ++#define BRCTL_GET_PORT_INFO 13 ++#define BRCTL_SET_BRIDGE_STP_STATE 14 ++#define BRCTL_SET_BRIDGE_PRIORITY 15 ++#define BRCTL_SET_PORT_PRIORITY 16 ++#define BRCTL_SET_PATH_COST 17 ++#define BRCTL_GET_FDB_ENTRIES 18 ++ ++#define BR_STATE_DISABLED 0 ++#define BR_STATE_LISTENING 1 ++#define BR_STATE_LEARNING 2 ++#define BR_STATE_FORWARDING 3 ++#define BR_STATE_BLOCKING 4 ++ ++struct __bridge_info { ++ __u64 designated_root; ++ __u64 bridge_id; ++ __u32 root_path_cost; ++ __u32 max_age; ++ __u32 hello_time; ++ __u32 forward_delay; ++ __u32 bridge_max_age; ++ __u32 bridge_hello_time; ++ __u32 bridge_forward_delay; ++ __u8 topology_change; ++ __u8 topology_change_detected; ++ __u8 root_port; ++ __u8 stp_enabled; ++ __u32 ageing_time; ++ __u32 gc_interval; ++ __u32 hello_timer_value; ++ __u32 tcn_timer_value; ++ __u32 topology_change_timer_value; ++ __u32 gc_timer_value; ++}; ++ ++struct __port_info { ++ __u64 designated_root; ++ __u64 designated_bridge; ++ __u16 port_id; ++ __u16 designated_port; ++ __u32 path_cost; ++ __u32 designated_cost; ++ __u8 state; ++ __u8 top_change_ack; ++ __u8 config_pending; ++ __u8 unused0; ++ __u32 message_age_timer_value; ++ __u32 forward_delay_timer_value; ++ __u32 hold_timer_value; ++}; ++ ++struct __fdb_entry { ++ __u8 mac_addr[ETH_ALEN]; ++ __u8 port_no; ++ __u8 is_local; ++ __u32 ageing_timer_value; ++ __u8 port_hi; ++ __u8 pad0; ++ __u16 unused; ++}; ++ ++/* Bridge Flags */ ++#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ ++#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ ++ ++#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ ++#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ ++#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */ ++ ++/* Bridge management nested attributes ++ * [IFLA_AF_SPEC] = { ++ * [IFLA_BRIDGE_FLAGS] ++ * [IFLA_BRIDGE_MODE] ++ * [IFLA_BRIDGE_VLAN_INFO] ++ * } ++ */ ++enum { ++ IFLA_BRIDGE_FLAGS, ++ IFLA_BRIDGE_MODE, ++ IFLA_BRIDGE_VLAN_INFO, ++ IFLA_BRIDGE_VLAN_TUNNEL_INFO, ++ __IFLA_BRIDGE_MAX, ++}; ++#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) ++ ++#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ ++#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ ++#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ ++#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ ++#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ ++#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */ ++ ++struct bridge_vlan_info { ++ __u16 flags; ++ __u16 vid; ++}; ++ ++enum { ++ IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC, ++ IFLA_BRIDGE_VLAN_TUNNEL_ID, ++ IFLA_BRIDGE_VLAN_TUNNEL_VID, ++ IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, ++ __IFLA_BRIDGE_VLAN_TUNNEL_MAX, ++}; ++ ++#define IFLA_BRIDGE_VLAN_TUNNEL_MAX (__IFLA_BRIDGE_VLAN_TUNNEL_MAX - 1) ++ ++struct bridge_vlan_xstats { ++ __u64 rx_bytes; ++ __u64 rx_packets; ++ __u64 tx_bytes; ++ __u64 tx_packets; ++ __u16 vid; ++ __u16 flags; ++ __u32 pad2; ++}; ++ ++/* Bridge multicast database attributes ++ * [MDBA_MDB] = { ++ * [MDBA_MDB_ENTRY] = { ++ * [MDBA_MDB_ENTRY_INFO] { ++ * struct br_mdb_entry ++ * [MDBA_MDB_EATTR attributes] ++ * } ++ * } ++ * } ++ * [MDBA_ROUTER] = { ++ * [MDBA_ROUTER_PORT] = { ++ * u32 ifindex ++ * [MDBA_ROUTER_PATTR attributes] ++ * } ++ * } ++ */ ++enum { ++ MDBA_UNSPEC, ++ MDBA_MDB, ++ MDBA_ROUTER, ++ __MDBA_MAX, ++}; ++#define MDBA_MAX (__MDBA_MAX - 1) ++ ++enum { ++ MDBA_MDB_UNSPEC, ++ MDBA_MDB_ENTRY, ++ __MDBA_MDB_MAX, ++}; ++#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) ++ ++enum { ++ MDBA_MDB_ENTRY_UNSPEC, ++ MDBA_MDB_ENTRY_INFO, ++ __MDBA_MDB_ENTRY_MAX, ++}; ++#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) ++ ++/* per mdb entry additional attributes */ ++enum { ++ MDBA_MDB_EATTR_UNSPEC, ++ MDBA_MDB_EATTR_TIMER, ++ __MDBA_MDB_EATTR_MAX ++}; ++#define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) ++ ++/* multicast router types */ ++enum { ++ MDB_RTR_TYPE_DISABLED, ++ MDB_RTR_TYPE_TEMP_QUERY, ++ MDB_RTR_TYPE_PERM, ++ MDB_RTR_TYPE_TEMP ++}; ++ ++enum { ++ MDBA_ROUTER_UNSPEC, ++ MDBA_ROUTER_PORT, ++ __MDBA_ROUTER_MAX, ++}; ++#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) ++ ++/* router port attributes */ ++enum { ++ MDBA_ROUTER_PATTR_UNSPEC, ++ MDBA_ROUTER_PATTR_TIMER, ++ MDBA_ROUTER_PATTR_TYPE, ++ __MDBA_ROUTER_PATTR_MAX ++}; ++#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) ++ ++struct br_port_msg { ++ __u8 family; ++ __u32 ifindex; ++}; ++ ++struct br_mdb_entry { ++ __u32 ifindex; ++#define MDB_TEMPORARY 0 ++#define MDB_PERMANENT 1 ++ __u8 state; ++#define MDB_FLAGS_OFFLOAD (1 << 0) ++ __u8 flags; ++ __u16 vid; ++ struct { ++ union { ++ __be32 ip4; ++ struct in6_addr ip6; ++ } u; ++ __be16 proto; ++ } addr; ++}; ++ ++enum { ++ MDBA_SET_ENTRY_UNSPEC, ++ MDBA_SET_ENTRY, ++ __MDBA_SET_ENTRY_MAX, ++}; ++#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) ++ ++/* Embedded inside LINK_XSTATS_TYPE_BRIDGE */ ++enum { ++ BRIDGE_XSTATS_UNSPEC, ++ BRIDGE_XSTATS_VLAN, ++ BRIDGE_XSTATS_MCAST, ++ BRIDGE_XSTATS_PAD, ++ __BRIDGE_XSTATS_MAX ++}; ++#define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1) ++ ++enum { ++ BR_MCAST_DIR_RX, ++ BR_MCAST_DIR_TX, ++ BR_MCAST_DIR_SIZE ++}; ++ ++/* IGMP/MLD statistics */ ++struct br_mcast_stats { ++ __u64 igmp_v1queries[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_v2queries[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_v3queries[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_leaves[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_v1reports[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_v2reports[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_v3reports[BR_MCAST_DIR_SIZE]; ++ __u64 igmp_parse_errors; ++ ++ __u64 mld_v1queries[BR_MCAST_DIR_SIZE]; ++ __u64 mld_v2queries[BR_MCAST_DIR_SIZE]; ++ __u64 mld_leaves[BR_MCAST_DIR_SIZE]; ++ __u64 mld_v1reports[BR_MCAST_DIR_SIZE]; ++ __u64 mld_v2reports[BR_MCAST_DIR_SIZE]; ++ __u64 mld_parse_errors; ++ ++ __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; ++ __u64 mcast_packets[BR_MCAST_DIR_SIZE]; ++}; ++ ++/* bridge boolean options ++ * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets ++ * ++ * IMPORTANT: if adding a new option do not forget to handle ++ * it in br_boolopt_toggle/get and bridge sysfs ++ */ ++enum br_boolopt_id { ++ BR_BOOLOPT_NO_LL_LEARN, ++ BR_BOOLOPT_MAX ++}; ++ ++/* struct br_boolopt_multi - change multiple bridge boolean options ++ * ++ * @optval: new option values (bit per option) ++ * @optmask: options to change (bit per option) ++ */ ++struct br_boolopt_multi { ++ __u32 optval; ++ __u32 optmask; ++}; ++#endif /* _UAPI_LINUX_IF_BRIDGE_H */ +diff --git a/src/basic/linux/if_link.h b/src/basic/linux/if_link.h +new file mode 100644 +index 00000000000..d6533828123 +--- /dev/null ++++ b/src/basic/linux/if_link.h +@@ -0,0 +1,1024 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI_LINUX_IF_LINK_H ++#define _UAPI_LINUX_IF_LINK_H ++ ++#include ++#include ++ ++/* This struct should be in sync with struct rtnl_link_stats64 */ ++struct rtnl_link_stats { ++ __u32 rx_packets; /* total packets received */ ++ __u32 tx_packets; /* total packets transmitted */ ++ __u32 rx_bytes; /* total bytes received */ ++ __u32 tx_bytes; /* total bytes transmitted */ ++ __u32 rx_errors; /* bad packets received */ ++ __u32 tx_errors; /* packet transmit problems */ ++ __u32 rx_dropped; /* no space in linux buffers */ ++ __u32 tx_dropped; /* no space available in linux */ ++ __u32 multicast; /* multicast packets received */ ++ __u32 collisions; ++ ++ /* detailed rx_errors: */ ++ __u32 rx_length_errors; ++ __u32 rx_over_errors; /* receiver ring buff overflow */ ++ __u32 rx_crc_errors; /* recved pkt with crc error */ ++ __u32 rx_frame_errors; /* recv'd frame alignment error */ ++ __u32 rx_fifo_errors; /* recv'r fifo overrun */ ++ __u32 rx_missed_errors; /* receiver missed packet */ ++ ++ /* detailed tx_errors */ ++ __u32 tx_aborted_errors; ++ __u32 tx_carrier_errors; ++ __u32 tx_fifo_errors; ++ __u32 tx_heartbeat_errors; ++ __u32 tx_window_errors; ++ ++ /* for cslip etc */ ++ __u32 rx_compressed; ++ __u32 tx_compressed; ++ ++ __u32 rx_nohandler; /* dropped, no handler found */ ++}; ++ ++/* The main device statistics structure */ ++struct rtnl_link_stats64 { ++ __u64 rx_packets; /* total packets received */ ++ __u64 tx_packets; /* total packets transmitted */ ++ __u64 rx_bytes; /* total bytes received */ ++ __u64 tx_bytes; /* total bytes transmitted */ ++ __u64 rx_errors; /* bad packets received */ ++ __u64 tx_errors; /* packet transmit problems */ ++ __u64 rx_dropped; /* no space in linux buffers */ ++ __u64 tx_dropped; /* no space available in linux */ ++ __u64 multicast; /* multicast packets received */ ++ __u64 collisions; ++ ++ /* detailed rx_errors: */ ++ __u64 rx_length_errors; ++ __u64 rx_over_errors; /* receiver ring buff overflow */ ++ __u64 rx_crc_errors; /* recved pkt with crc error */ ++ __u64 rx_frame_errors; /* recv'd frame alignment error */ ++ __u64 rx_fifo_errors; /* recv'r fifo overrun */ ++ __u64 rx_missed_errors; /* receiver missed packet */ ++ ++ /* detailed tx_errors */ ++ __u64 tx_aborted_errors; ++ __u64 tx_carrier_errors; ++ __u64 tx_fifo_errors; ++ __u64 tx_heartbeat_errors; ++ __u64 tx_window_errors; ++ ++ /* for cslip etc */ ++ __u64 rx_compressed; ++ __u64 tx_compressed; ++ ++ __u64 rx_nohandler; /* dropped, no handler found */ ++}; ++ ++/* The struct should be in sync with struct ifmap */ ++struct rtnl_link_ifmap { ++ __u64 mem_start; ++ __u64 mem_end; ++ __u64 base_addr; ++ __u16 irq; ++ __u8 dma; ++ __u8 port; ++}; ++ ++/* ++ * IFLA_AF_SPEC ++ * Contains nested attributes for address family specific attributes. ++ * Each address family may create a attribute with the address family ++ * number as type and create its own attribute structure in it. ++ * ++ * Example: ++ * [IFLA_AF_SPEC] = { ++ * [AF_INET] = { ++ * [IFLA_INET_CONF] = ..., ++ * }, ++ * [AF_INET6] = { ++ * [IFLA_INET6_FLAGS] = ..., ++ * [IFLA_INET6_CONF] = ..., ++ * } ++ * } ++ */ ++ ++enum { ++ IFLA_UNSPEC, ++ IFLA_ADDRESS, ++ IFLA_BROADCAST, ++ IFLA_IFNAME, ++ IFLA_MTU, ++ IFLA_LINK, ++ IFLA_QDISC, ++ IFLA_STATS, ++ IFLA_COST, ++#define IFLA_COST IFLA_COST ++ IFLA_PRIORITY, ++#define IFLA_PRIORITY IFLA_PRIORITY ++ IFLA_MASTER, ++#define IFLA_MASTER IFLA_MASTER ++ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ ++#define IFLA_WIRELESS IFLA_WIRELESS ++ IFLA_PROTINFO, /* Protocol specific information for a link */ ++#define IFLA_PROTINFO IFLA_PROTINFO ++ IFLA_TXQLEN, ++#define IFLA_TXQLEN IFLA_TXQLEN ++ IFLA_MAP, ++#define IFLA_MAP IFLA_MAP ++ IFLA_WEIGHT, ++#define IFLA_WEIGHT IFLA_WEIGHT ++ IFLA_OPERSTATE, ++ IFLA_LINKMODE, ++ IFLA_LINKINFO, ++#define IFLA_LINKINFO IFLA_LINKINFO ++ IFLA_NET_NS_PID, ++ IFLA_IFALIAS, ++ IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ ++ IFLA_VFINFO_LIST, ++ IFLA_STATS64, ++ IFLA_VF_PORTS, ++ IFLA_PORT_SELF, ++ IFLA_AF_SPEC, ++ IFLA_GROUP, /* Group the device belongs to */ ++ IFLA_NET_NS_FD, ++ IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ ++ IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ ++#define IFLA_PROMISCUITY IFLA_PROMISCUITY ++ IFLA_NUM_TX_QUEUES, ++ IFLA_NUM_RX_QUEUES, ++ IFLA_CARRIER, ++ IFLA_PHYS_PORT_ID, ++ IFLA_CARRIER_CHANGES, ++ IFLA_PHYS_SWITCH_ID, ++ IFLA_LINK_NETNSID, ++ IFLA_PHYS_PORT_NAME, ++ IFLA_PROTO_DOWN, ++ IFLA_GSO_MAX_SEGS, ++ IFLA_GSO_MAX_SIZE, ++ IFLA_PAD, ++ IFLA_XDP, ++ IFLA_EVENT, ++ IFLA_NEW_NETNSID, ++ IFLA_IF_NETNSID, ++ IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ ++ IFLA_CARRIER_UP_COUNT, ++ IFLA_CARRIER_DOWN_COUNT, ++ IFLA_NEW_IFINDEX, ++ IFLA_MIN_MTU, ++ IFLA_MAX_MTU, ++ __IFLA_MAX ++}; ++ ++ ++#define IFLA_MAX (__IFLA_MAX - 1) ++ ++/* backwards compatibility for userspace */ ++#ifndef __KERNEL__ ++#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) ++#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) ++#endif ++ ++enum { ++ IFLA_INET_UNSPEC, ++ IFLA_INET_CONF, ++ __IFLA_INET_MAX, ++}; ++ ++#define IFLA_INET_MAX (__IFLA_INET_MAX - 1) ++ ++/* ifi_flags. ++ ++ IFF_* flags. ++ ++ The only change is: ++ IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are ++ more not changeable by user. They describe link media ++ characteristics and set by device driver. ++ ++ Comments: ++ - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid ++ - If neither of these three flags are set; ++ the interface is NBMA. ++ ++ - IFF_MULTICAST does not mean anything special: ++ multicasts can be used on all not-NBMA links. ++ IFF_MULTICAST means that this media uses special encapsulation ++ for multicast frames. Apparently, all IFF_POINTOPOINT and ++ IFF_BROADCAST devices are able to use multicasts too. ++ */ ++ ++/* IFLA_LINK. ++ For usual devices it is equal ifi_index. ++ If it is a "virtual interface" (f.e. tunnel), ifi_link ++ can point to real physical interface (f.e. for bandwidth calculations), ++ or maybe 0, what means, that real media is unknown (usual ++ for IPIP tunnels, when route to endpoint is allowed to change) ++ */ ++ ++/* Subtype attributes for IFLA_PROTINFO */ ++enum { ++ IFLA_INET6_UNSPEC, ++ IFLA_INET6_FLAGS, /* link flags */ ++ IFLA_INET6_CONF, /* sysctl parameters */ ++ IFLA_INET6_STATS, /* statistics */ ++ IFLA_INET6_MCAST, /* MC things. What of them? */ ++ IFLA_INET6_CACHEINFO, /* time values and max reasm size */ ++ IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ ++ IFLA_INET6_TOKEN, /* device token */ ++ IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ ++ __IFLA_INET6_MAX ++}; ++ ++#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) ++ ++enum in6_addr_gen_mode { ++ IN6_ADDR_GEN_MODE_EUI64, ++ IN6_ADDR_GEN_MODE_NONE, ++ IN6_ADDR_GEN_MODE_STABLE_PRIVACY, ++ IN6_ADDR_GEN_MODE_RANDOM, ++}; ++ ++/* Bridge section */ ++ ++enum { ++ IFLA_BR_UNSPEC, ++ IFLA_BR_FORWARD_DELAY, ++ IFLA_BR_HELLO_TIME, ++ IFLA_BR_MAX_AGE, ++ IFLA_BR_AGEING_TIME, ++ IFLA_BR_STP_STATE, ++ IFLA_BR_PRIORITY, ++ IFLA_BR_VLAN_FILTERING, ++ IFLA_BR_VLAN_PROTOCOL, ++ IFLA_BR_GROUP_FWD_MASK, ++ IFLA_BR_ROOT_ID, ++ IFLA_BR_BRIDGE_ID, ++ IFLA_BR_ROOT_PORT, ++ IFLA_BR_ROOT_PATH_COST, ++ IFLA_BR_TOPOLOGY_CHANGE, ++ IFLA_BR_TOPOLOGY_CHANGE_DETECTED, ++ IFLA_BR_HELLO_TIMER, ++ IFLA_BR_TCN_TIMER, ++ IFLA_BR_TOPOLOGY_CHANGE_TIMER, ++ IFLA_BR_GC_TIMER, ++ IFLA_BR_GROUP_ADDR, ++ IFLA_BR_FDB_FLUSH, ++ IFLA_BR_MCAST_ROUTER, ++ IFLA_BR_MCAST_SNOOPING, ++ IFLA_BR_MCAST_QUERY_USE_IFADDR, ++ IFLA_BR_MCAST_QUERIER, ++ IFLA_BR_MCAST_HASH_ELASTICITY, ++ IFLA_BR_MCAST_HASH_MAX, ++ IFLA_BR_MCAST_LAST_MEMBER_CNT, ++ IFLA_BR_MCAST_STARTUP_QUERY_CNT, ++ IFLA_BR_MCAST_LAST_MEMBER_INTVL, ++ IFLA_BR_MCAST_MEMBERSHIP_INTVL, ++ IFLA_BR_MCAST_QUERIER_INTVL, ++ IFLA_BR_MCAST_QUERY_INTVL, ++ IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, ++ IFLA_BR_MCAST_STARTUP_QUERY_INTVL, ++ IFLA_BR_NF_CALL_IPTABLES, ++ IFLA_BR_NF_CALL_IP6TABLES, ++ IFLA_BR_NF_CALL_ARPTABLES, ++ IFLA_BR_VLAN_DEFAULT_PVID, ++ IFLA_BR_PAD, ++ IFLA_BR_VLAN_STATS_ENABLED, ++ IFLA_BR_MCAST_STATS_ENABLED, ++ IFLA_BR_MCAST_IGMP_VERSION, ++ IFLA_BR_MCAST_MLD_VERSION, ++ IFLA_BR_VLAN_STATS_PER_PORT, ++ IFLA_BR_MULTI_BOOLOPT, ++ __IFLA_BR_MAX, ++}; ++ ++#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) ++ ++struct ifla_bridge_id { ++ __u8 prio[2]; ++ __u8 addr[6]; /* ETH_ALEN */ ++}; ++ ++enum { ++ BRIDGE_MODE_UNSPEC, ++ BRIDGE_MODE_HAIRPIN, ++}; ++ ++enum { ++ IFLA_BRPORT_UNSPEC, ++ IFLA_BRPORT_STATE, /* Spanning tree state */ ++ IFLA_BRPORT_PRIORITY, /* " priority */ ++ IFLA_BRPORT_COST, /* " cost */ ++ IFLA_BRPORT_MODE, /* mode (hairpin) */ ++ IFLA_BRPORT_GUARD, /* bpdu guard */ ++ IFLA_BRPORT_PROTECT, /* root port protection */ ++ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ ++ IFLA_BRPORT_LEARNING, /* mac learning */ ++ IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ ++ IFLA_BRPORT_PROXYARP, /* proxy ARP */ ++ IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */ ++ IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */ ++ IFLA_BRPORT_ROOT_ID, /* designated root */ ++ IFLA_BRPORT_BRIDGE_ID, /* designated bridge */ ++ IFLA_BRPORT_DESIGNATED_PORT, ++ IFLA_BRPORT_DESIGNATED_COST, ++ IFLA_BRPORT_ID, ++ IFLA_BRPORT_NO, ++ IFLA_BRPORT_TOPOLOGY_CHANGE_ACK, ++ IFLA_BRPORT_CONFIG_PENDING, ++ IFLA_BRPORT_MESSAGE_AGE_TIMER, ++ IFLA_BRPORT_FORWARD_DELAY_TIMER, ++ IFLA_BRPORT_HOLD_TIMER, ++ IFLA_BRPORT_FLUSH, ++ IFLA_BRPORT_MULTICAST_ROUTER, ++ IFLA_BRPORT_PAD, ++ IFLA_BRPORT_MCAST_FLOOD, ++ IFLA_BRPORT_MCAST_TO_UCAST, ++ IFLA_BRPORT_VLAN_TUNNEL, ++ IFLA_BRPORT_BCAST_FLOOD, ++ IFLA_BRPORT_GROUP_FWD_MASK, ++ IFLA_BRPORT_NEIGH_SUPPRESS, ++ IFLA_BRPORT_ISOLATED, ++ IFLA_BRPORT_BACKUP_PORT, ++ __IFLA_BRPORT_MAX ++}; ++#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) ++ ++struct ifla_cacheinfo { ++ __u32 max_reasm_len; ++ __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ ++ __u32 reachable_time; ++ __u32 retrans_time; ++}; ++ ++enum { ++ IFLA_INFO_UNSPEC, ++ IFLA_INFO_KIND, ++ IFLA_INFO_DATA, ++ IFLA_INFO_XSTATS, ++ IFLA_INFO_SLAVE_KIND, ++ IFLA_INFO_SLAVE_DATA, ++ __IFLA_INFO_MAX, ++}; ++ ++#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) ++ ++/* VLAN section */ ++ ++enum { ++ IFLA_VLAN_UNSPEC, ++ IFLA_VLAN_ID, ++ IFLA_VLAN_FLAGS, ++ IFLA_VLAN_EGRESS_QOS, ++ IFLA_VLAN_INGRESS_QOS, ++ IFLA_VLAN_PROTOCOL, ++ __IFLA_VLAN_MAX, ++}; ++ ++#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) ++ ++struct ifla_vlan_flags { ++ __u32 flags; ++ __u32 mask; ++}; ++ ++enum { ++ IFLA_VLAN_QOS_UNSPEC, ++ IFLA_VLAN_QOS_MAPPING, ++ __IFLA_VLAN_QOS_MAX ++}; ++ ++#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1) ++ ++struct ifla_vlan_qos_mapping { ++ __u32 from; ++ __u32 to; ++}; ++ ++/* MACVLAN section */ ++enum { ++ IFLA_MACVLAN_UNSPEC, ++ IFLA_MACVLAN_MODE, ++ IFLA_MACVLAN_FLAGS, ++ IFLA_MACVLAN_MACADDR_MODE, ++ IFLA_MACVLAN_MACADDR, ++ IFLA_MACVLAN_MACADDR_DATA, ++ IFLA_MACVLAN_MACADDR_COUNT, ++ __IFLA_MACVLAN_MAX, ++}; ++ ++#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) ++ ++enum macvlan_mode { ++ MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ ++ MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ ++ MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ ++ MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ ++ MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */ ++}; ++ ++enum macvlan_macaddr_mode { ++ MACVLAN_MACADDR_ADD, ++ MACVLAN_MACADDR_DEL, ++ MACVLAN_MACADDR_FLUSH, ++ MACVLAN_MACADDR_SET, ++}; ++ ++#define MACVLAN_FLAG_NOPROMISC 1 ++ ++/* VRF section */ ++enum { ++ IFLA_VRF_UNSPEC, ++ IFLA_VRF_TABLE, ++ __IFLA_VRF_MAX ++}; ++ ++#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) ++ ++enum { ++ IFLA_VRF_PORT_UNSPEC, ++ IFLA_VRF_PORT_TABLE, ++ __IFLA_VRF_PORT_MAX ++}; ++ ++#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) ++ ++/* MACSEC section */ ++enum { ++ IFLA_MACSEC_UNSPEC, ++ IFLA_MACSEC_SCI, ++ IFLA_MACSEC_PORT, ++ IFLA_MACSEC_ICV_LEN, ++ IFLA_MACSEC_CIPHER_SUITE, ++ IFLA_MACSEC_WINDOW, ++ IFLA_MACSEC_ENCODING_SA, ++ IFLA_MACSEC_ENCRYPT, ++ IFLA_MACSEC_PROTECT, ++ IFLA_MACSEC_INC_SCI, ++ IFLA_MACSEC_ES, ++ IFLA_MACSEC_SCB, ++ IFLA_MACSEC_REPLAY_PROTECT, ++ IFLA_MACSEC_VALIDATION, ++ IFLA_MACSEC_PAD, ++ __IFLA_MACSEC_MAX, ++}; ++ ++#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) ++ ++/* XFRM section */ ++enum { ++ IFLA_XFRM_UNSPEC, ++ IFLA_XFRM_LINK, ++ IFLA_XFRM_IF_ID, ++ __IFLA_XFRM_MAX ++}; ++ ++#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) ++ ++enum macsec_validation_type { ++ MACSEC_VALIDATE_DISABLED = 0, ++ MACSEC_VALIDATE_CHECK = 1, ++ MACSEC_VALIDATE_STRICT = 2, ++ __MACSEC_VALIDATE_END, ++ MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1, ++}; ++ ++/* IPVLAN section */ ++enum { ++ IFLA_IPVLAN_UNSPEC, ++ IFLA_IPVLAN_MODE, ++ IFLA_IPVLAN_FLAGS, ++ __IFLA_IPVLAN_MAX ++}; ++ ++#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) ++ ++enum ipvlan_mode { ++ IPVLAN_MODE_L2 = 0, ++ IPVLAN_MODE_L3, ++ IPVLAN_MODE_L3S, ++ IPVLAN_MODE_MAX ++}; ++ ++#define IPVLAN_F_PRIVATE 0x01 ++#define IPVLAN_F_VEPA 0x02 ++ ++/* VXLAN section */ ++enum { ++ IFLA_VXLAN_UNSPEC, ++ IFLA_VXLAN_ID, ++ IFLA_VXLAN_GROUP, /* group or remote address */ ++ IFLA_VXLAN_LINK, ++ IFLA_VXLAN_LOCAL, ++ IFLA_VXLAN_TTL, ++ IFLA_VXLAN_TOS, ++ IFLA_VXLAN_LEARNING, ++ IFLA_VXLAN_AGEING, ++ IFLA_VXLAN_LIMIT, ++ IFLA_VXLAN_PORT_RANGE, /* source port */ ++ IFLA_VXLAN_PROXY, ++ IFLA_VXLAN_RSC, ++ IFLA_VXLAN_L2MISS, ++ IFLA_VXLAN_L3MISS, ++ IFLA_VXLAN_PORT, /* destination port */ ++ IFLA_VXLAN_GROUP6, ++ IFLA_VXLAN_LOCAL6, ++ IFLA_VXLAN_UDP_CSUM, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_TX, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_RX, ++ IFLA_VXLAN_REMCSUM_TX, ++ IFLA_VXLAN_REMCSUM_RX, ++ IFLA_VXLAN_GBP, ++ IFLA_VXLAN_REMCSUM_NOPARTIAL, ++ IFLA_VXLAN_COLLECT_METADATA, ++ IFLA_VXLAN_LABEL, ++ IFLA_VXLAN_GPE, ++ IFLA_VXLAN_TTL_INHERIT, ++ IFLA_VXLAN_DF, ++ __IFLA_VXLAN_MAX ++}; ++#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) ++ ++struct ifla_vxlan_port_range { ++ __be16 low; ++ __be16 high; ++}; ++ ++enum ifla_vxlan_df { ++ VXLAN_DF_UNSET = 0, ++ VXLAN_DF_SET, ++ VXLAN_DF_INHERIT, ++ __VXLAN_DF_END, ++ VXLAN_DF_MAX = __VXLAN_DF_END - 1, ++}; ++ ++/* GENEVE section */ ++enum { ++ IFLA_GENEVE_UNSPEC, ++ IFLA_GENEVE_ID, ++ IFLA_GENEVE_REMOTE, ++ IFLA_GENEVE_TTL, ++ IFLA_GENEVE_TOS, ++ IFLA_GENEVE_PORT, /* destination port */ ++ IFLA_GENEVE_COLLECT_METADATA, ++ IFLA_GENEVE_REMOTE6, ++ IFLA_GENEVE_UDP_CSUM, ++ IFLA_GENEVE_UDP_ZERO_CSUM6_TX, ++ IFLA_GENEVE_UDP_ZERO_CSUM6_RX, ++ IFLA_GENEVE_LABEL, ++ IFLA_GENEVE_TTL_INHERIT, ++ IFLA_GENEVE_DF, ++ __IFLA_GENEVE_MAX ++}; ++#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) ++ ++enum ifla_geneve_df { ++ GENEVE_DF_UNSET = 0, ++ GENEVE_DF_SET, ++ GENEVE_DF_INHERIT, ++ __GENEVE_DF_END, ++ GENEVE_DF_MAX = __GENEVE_DF_END - 1, ++}; ++ ++/* PPP section */ ++enum { ++ IFLA_PPP_UNSPEC, ++ IFLA_PPP_DEV_FD, ++ __IFLA_PPP_MAX ++}; ++#define IFLA_PPP_MAX (__IFLA_PPP_MAX - 1) ++ ++/* GTP section */ ++ ++enum ifla_gtp_role { ++ GTP_ROLE_GGSN = 0, ++ GTP_ROLE_SGSN, ++}; ++ ++enum { ++ IFLA_GTP_UNSPEC, ++ IFLA_GTP_FD0, ++ IFLA_GTP_FD1, ++ IFLA_GTP_PDP_HASHSIZE, ++ IFLA_GTP_ROLE, ++ __IFLA_GTP_MAX, ++}; ++#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) ++ ++/* Bonding section */ ++ ++enum { ++ IFLA_BOND_UNSPEC, ++ IFLA_BOND_MODE, ++ IFLA_BOND_ACTIVE_SLAVE, ++ IFLA_BOND_MIIMON, ++ IFLA_BOND_UPDELAY, ++ IFLA_BOND_DOWNDELAY, ++ IFLA_BOND_USE_CARRIER, ++ IFLA_BOND_ARP_INTERVAL, ++ IFLA_BOND_ARP_IP_TARGET, ++ IFLA_BOND_ARP_VALIDATE, ++ IFLA_BOND_ARP_ALL_TARGETS, ++ IFLA_BOND_PRIMARY, ++ IFLA_BOND_PRIMARY_RESELECT, ++ IFLA_BOND_FAIL_OVER_MAC, ++ IFLA_BOND_XMIT_HASH_POLICY, ++ IFLA_BOND_RESEND_IGMP, ++ IFLA_BOND_NUM_PEER_NOTIF, ++ IFLA_BOND_ALL_SLAVES_ACTIVE, ++ IFLA_BOND_MIN_LINKS, ++ IFLA_BOND_LP_INTERVAL, ++ IFLA_BOND_PACKETS_PER_SLAVE, ++ IFLA_BOND_AD_LACP_RATE, ++ IFLA_BOND_AD_SELECT, ++ IFLA_BOND_AD_INFO, ++ IFLA_BOND_AD_ACTOR_SYS_PRIO, ++ IFLA_BOND_AD_USER_PORT_KEY, ++ IFLA_BOND_AD_ACTOR_SYSTEM, ++ IFLA_BOND_TLB_DYNAMIC_LB, ++ __IFLA_BOND_MAX, ++}; ++ ++#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) ++ ++enum { ++ IFLA_BOND_AD_INFO_UNSPEC, ++ IFLA_BOND_AD_INFO_AGGREGATOR, ++ IFLA_BOND_AD_INFO_NUM_PORTS, ++ IFLA_BOND_AD_INFO_ACTOR_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_MAC, ++ __IFLA_BOND_AD_INFO_MAX, ++}; ++ ++#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) ++ ++enum { ++ IFLA_BOND_SLAVE_UNSPEC, ++ IFLA_BOND_SLAVE_STATE, ++ IFLA_BOND_SLAVE_MII_STATUS, ++ IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, ++ IFLA_BOND_SLAVE_PERM_HWADDR, ++ IFLA_BOND_SLAVE_QUEUE_ID, ++ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, ++ IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, ++ IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, ++ __IFLA_BOND_SLAVE_MAX, ++}; ++ ++#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) ++ ++/* SR-IOV virtual function management section */ ++ ++enum { ++ IFLA_VF_INFO_UNSPEC, ++ IFLA_VF_INFO, ++ __IFLA_VF_INFO_MAX, ++}; ++ ++#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) ++ ++enum { ++ IFLA_VF_UNSPEC, ++ IFLA_VF_MAC, /* Hardware queue specific attributes */ ++ IFLA_VF_VLAN, /* VLAN ID and QoS */ ++ IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */ ++ IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ ++ IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ ++ IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */ ++ IFLA_VF_RSS_QUERY_EN, /* RSS Redirection Table and Hash Key query ++ * on/off switch ++ */ ++ IFLA_VF_STATS, /* network device statistics */ ++ IFLA_VF_TRUST, /* Trust VF */ ++ IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */ ++ IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */ ++ IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */ ++ __IFLA_VF_MAX, ++}; ++ ++#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) ++ ++struct ifla_vf_mac { ++ __u32 vf; ++ __u8 mac[32]; /* MAX_ADDR_LEN */ ++}; ++ ++struct ifla_vf_vlan { ++ __u32 vf; ++ __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ ++ __u32 qos; ++}; ++ ++enum { ++ IFLA_VF_VLAN_INFO_UNSPEC, ++ IFLA_VF_VLAN_INFO, /* VLAN ID, QoS and VLAN protocol */ ++ __IFLA_VF_VLAN_INFO_MAX, ++}; ++ ++#define IFLA_VF_VLAN_INFO_MAX (__IFLA_VF_VLAN_INFO_MAX - 1) ++#define MAX_VLAN_LIST_LEN 1 ++ ++struct ifla_vf_vlan_info { ++ __u32 vf; ++ __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ ++ __u32 qos; ++ __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */ ++}; ++ ++struct ifla_vf_tx_rate { ++ __u32 vf; ++ __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ ++}; ++ ++struct ifla_vf_rate { ++ __u32 vf; ++ __u32 min_tx_rate; /* Min Bandwidth in Mbps */ ++ __u32 max_tx_rate; /* Max Bandwidth in Mbps */ ++}; ++ ++struct ifla_vf_spoofchk { ++ __u32 vf; ++ __u32 setting; ++}; ++ ++struct ifla_vf_guid { ++ __u32 vf; ++ __u64 guid; ++}; ++ ++enum { ++ IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ ++ IFLA_VF_LINK_STATE_ENABLE, /* link always up */ ++ IFLA_VF_LINK_STATE_DISABLE, /* link always down */ ++ __IFLA_VF_LINK_STATE_MAX, ++}; ++ ++struct ifla_vf_link_state { ++ __u32 vf; ++ __u32 link_state; ++}; ++ ++struct ifla_vf_rss_query_en { ++ __u32 vf; ++ __u32 setting; ++}; ++ ++enum { ++ IFLA_VF_STATS_RX_PACKETS, ++ IFLA_VF_STATS_TX_PACKETS, ++ IFLA_VF_STATS_RX_BYTES, ++ IFLA_VF_STATS_TX_BYTES, ++ IFLA_VF_STATS_BROADCAST, ++ IFLA_VF_STATS_MULTICAST, ++ IFLA_VF_STATS_PAD, ++ IFLA_VF_STATS_RX_DROPPED, ++ IFLA_VF_STATS_TX_DROPPED, ++ __IFLA_VF_STATS_MAX, ++}; ++ ++#define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1) ++ ++struct ifla_vf_trust { ++ __u32 vf; ++ __u32 setting; ++}; ++ ++/* VF ports management section ++ * ++ * Nested layout of set/get msg is: ++ * ++ * [IFLA_NUM_VF] ++ * [IFLA_VF_PORTS] ++ * [IFLA_VF_PORT] ++ * [IFLA_PORT_*], ... ++ * [IFLA_VF_PORT] ++ * [IFLA_PORT_*], ... ++ * ... ++ * [IFLA_PORT_SELF] ++ * [IFLA_PORT_*], ... ++ */ ++ ++enum { ++ IFLA_VF_PORT_UNSPEC, ++ IFLA_VF_PORT, /* nest */ ++ __IFLA_VF_PORT_MAX, ++}; ++ ++#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) ++ ++enum { ++ IFLA_PORT_UNSPEC, ++ IFLA_PORT_VF, /* __u32 */ ++ IFLA_PORT_PROFILE, /* string */ ++ IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ ++ IFLA_PORT_INSTANCE_UUID, /* binary UUID */ ++ IFLA_PORT_HOST_UUID, /* binary UUID */ ++ IFLA_PORT_REQUEST, /* __u8 */ ++ IFLA_PORT_RESPONSE, /* __u16, output only */ ++ __IFLA_PORT_MAX, ++}; ++ ++#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) ++ ++#define PORT_PROFILE_MAX 40 ++#define PORT_UUID_MAX 16 ++#define PORT_SELF_VF -1 ++ ++enum { ++ PORT_REQUEST_PREASSOCIATE = 0, ++ PORT_REQUEST_PREASSOCIATE_RR, ++ PORT_REQUEST_ASSOCIATE, ++ PORT_REQUEST_DISASSOCIATE, ++}; ++ ++enum { ++ PORT_VDP_RESPONSE_SUCCESS = 0, ++ PORT_VDP_RESPONSE_INVALID_FORMAT, ++ PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, ++ PORT_VDP_RESPONSE_UNUSED_VTID, ++ PORT_VDP_RESPONSE_VTID_VIOLATION, ++ PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, ++ PORT_VDP_RESPONSE_OUT_OF_SYNC, ++ /* 0x08-0xFF reserved for future VDP use */ ++ PORT_PROFILE_RESPONSE_SUCCESS = 0x100, ++ PORT_PROFILE_RESPONSE_INPROGRESS, ++ PORT_PROFILE_RESPONSE_INVALID, ++ PORT_PROFILE_RESPONSE_BADSTATE, ++ PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, ++ PORT_PROFILE_RESPONSE_ERROR, ++}; ++ ++struct ifla_port_vsi { ++ __u8 vsi_mgr_id; ++ __u8 vsi_type_id[3]; ++ __u8 vsi_type_version; ++ __u8 pad[3]; ++}; ++ ++ ++/* IPoIB section */ ++ ++enum { ++ IFLA_IPOIB_UNSPEC, ++ IFLA_IPOIB_PKEY, ++ IFLA_IPOIB_MODE, ++ IFLA_IPOIB_UMCAST, ++ __IFLA_IPOIB_MAX ++}; ++ ++enum { ++ IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ ++ IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ ++}; ++ ++#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) ++ ++ ++/* HSR section */ ++ ++enum { ++ IFLA_HSR_UNSPEC, ++ IFLA_HSR_SLAVE1, ++ IFLA_HSR_SLAVE2, ++ IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ ++ IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ ++ IFLA_HSR_SEQ_NR, ++ IFLA_HSR_VERSION, /* HSR version */ ++ __IFLA_HSR_MAX, ++}; ++ ++#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) ++ ++/* STATS section */ ++ ++struct if_stats_msg { ++ __u8 family; ++ __u8 pad1; ++ __u16 pad2; ++ __u32 ifindex; ++ __u32 filter_mask; ++}; ++ ++/* A stats attribute can be netdev specific or a global stat. ++ * For netdev stats, lets use the prefix IFLA_STATS_LINK_* ++ */ ++enum { ++ IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */ ++ IFLA_STATS_LINK_64, ++ IFLA_STATS_LINK_XSTATS, ++ IFLA_STATS_LINK_XSTATS_SLAVE, ++ IFLA_STATS_LINK_OFFLOAD_XSTATS, ++ IFLA_STATS_AF_SPEC, ++ __IFLA_STATS_MAX, ++}; ++ ++#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1) ++ ++#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1)) ++ ++/* These are embedded into IFLA_STATS_LINK_XSTATS: ++ * [IFLA_STATS_LINK_XSTATS] ++ * -> [LINK_XSTATS_TYPE_xxx] ++ * -> [rtnl link type specific attributes] ++ */ ++enum { ++ LINK_XSTATS_TYPE_UNSPEC, ++ LINK_XSTATS_TYPE_BRIDGE, ++ __LINK_XSTATS_TYPE_MAX ++}; ++#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) ++ ++/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */ ++enum { ++ IFLA_OFFLOAD_XSTATS_UNSPEC, ++ IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */ ++ __IFLA_OFFLOAD_XSTATS_MAX ++}; ++#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1) ++ ++/* XDP section */ ++ ++#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0) ++#define XDP_FLAGS_SKB_MODE (1U << 1) ++#define XDP_FLAGS_DRV_MODE (1U << 2) ++#define XDP_FLAGS_HW_MODE (1U << 3) ++#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \ ++ XDP_FLAGS_DRV_MODE | \ ++ XDP_FLAGS_HW_MODE) ++#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ ++ XDP_FLAGS_MODES) ++ ++/* These are stored into IFLA_XDP_ATTACHED on dump. */ ++enum { ++ XDP_ATTACHED_NONE = 0, ++ XDP_ATTACHED_DRV, ++ XDP_ATTACHED_SKB, ++ XDP_ATTACHED_HW, ++ XDP_ATTACHED_MULTI, ++}; ++ ++enum { ++ IFLA_XDP_UNSPEC, ++ IFLA_XDP_FD, ++ IFLA_XDP_ATTACHED, ++ IFLA_XDP_FLAGS, ++ IFLA_XDP_PROG_ID, ++ IFLA_XDP_DRV_PROG_ID, ++ IFLA_XDP_SKB_PROG_ID, ++ IFLA_XDP_HW_PROG_ID, ++ __IFLA_XDP_MAX, ++}; ++ ++#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1) ++ ++enum { ++ IFLA_EVENT_NONE, ++ IFLA_EVENT_REBOOT, /* internal reset / reboot */ ++ IFLA_EVENT_FEATURES, /* change in offload features */ ++ IFLA_EVENT_BONDING_FAILOVER, /* change in active slave */ ++ IFLA_EVENT_NOTIFY_PEERS, /* re-sent grat. arp/ndisc */ ++ IFLA_EVENT_IGMP_RESEND, /* re-sent IGMP JOIN */ ++ IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ ++}; ++ ++/* tun section */ ++ ++enum { ++ IFLA_TUN_UNSPEC, ++ IFLA_TUN_OWNER, ++ IFLA_TUN_GROUP, ++ IFLA_TUN_TYPE, ++ IFLA_TUN_PI, ++ IFLA_TUN_VNET_HDR, ++ IFLA_TUN_PERSIST, ++ IFLA_TUN_MULTI_QUEUE, ++ IFLA_TUN_NUM_QUEUES, ++ IFLA_TUN_NUM_DISABLED_QUEUES, ++ __IFLA_TUN_MAX, ++}; ++ ++#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) ++ ++/* rmnet section */ ++ ++#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) ++#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) ++#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) ++#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) ++ ++enum { ++ IFLA_RMNET_UNSPEC, ++ IFLA_RMNET_MUX_ID, ++ IFLA_RMNET_FLAGS, ++ __IFLA_RMNET_MAX, ++}; ++ ++#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1) ++ ++struct ifla_rmnet_flags { ++ __u32 flags; ++ __u32 mask; ++}; ++ ++#endif /* _UAPI_LINUX_IF_LINK_H */ +diff --git a/src/basic/linux/if_tun.h b/src/basic/linux/if_tun.h +new file mode 100644 +index 00000000000..23a6753b37d +--- /dev/null ++++ b/src/basic/linux/if_tun.h +@@ -0,0 +1,113 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Universal TUN/TAP device driver. ++ * Copyright (C) 1999-2000 Maxim Krasnyansky ++ * ++ * This program 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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. ++ */ ++ ++#ifndef _UAPI__IF_TUN_H ++#define _UAPI__IF_TUN_H ++ ++#include ++#include ++#include ++ ++/* Read queue size */ ++#define TUN_READQ_SIZE 500 ++/* TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. */ ++#define TUN_TUN_DEV IFF_TUN ++#define TUN_TAP_DEV IFF_TAP ++#define TUN_TYPE_MASK 0x000f ++ ++/* Ioctl defines */ ++#define TUNSETNOCSUM _IOW('T', 200, int) ++#define TUNSETDEBUG _IOW('T', 201, int) ++#define TUNSETIFF _IOW('T', 202, int) ++#define TUNSETPERSIST _IOW('T', 203, int) ++#define TUNSETOWNER _IOW('T', 204, int) ++#define TUNSETLINK _IOW('T', 205, int) ++#define TUNSETGROUP _IOW('T', 206, int) ++#define TUNGETFEATURES _IOR('T', 207, unsigned int) ++#define TUNSETOFFLOAD _IOW('T', 208, unsigned int) ++#define TUNSETTXFILTER _IOW('T', 209, unsigned int) ++#define TUNGETIFF _IOR('T', 210, unsigned int) ++#define TUNGETSNDBUF _IOR('T', 211, int) ++#define TUNSETSNDBUF _IOW('T', 212, int) ++#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) ++#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) ++#define TUNGETVNETHDRSZ _IOR('T', 215, int) ++#define TUNSETVNETHDRSZ _IOW('T', 216, int) ++#define TUNSETQUEUE _IOW('T', 217, int) ++#define TUNSETIFINDEX _IOW('T', 218, unsigned int) ++#define TUNGETFILTER _IOR('T', 219, struct sock_fprog) ++#define TUNSETVNETLE _IOW('T', 220, int) ++#define TUNGETVNETLE _IOR('T', 221, int) ++/* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on ++ * little-endian hosts. Not all kernel configurations support them, but all ++ * configurations that support SET also support GET. ++ */ ++#define TUNSETVNETBE _IOW('T', 222, int) ++#define TUNGETVNETBE _IOR('T', 223, int) ++#define TUNSETSTEERINGEBPF _IOR('T', 224, int) ++#define TUNSETFILTEREBPF _IOR('T', 225, int) ++#define TUNSETCARRIER _IOW('T', 226, int) ++ ++/* TUNSETIFF ifr flags */ ++#define IFF_TUN 0x0001 ++#define IFF_TAP 0x0002 ++#define IFF_NAPI 0x0010 ++#define IFF_NAPI_FRAGS 0x0020 ++#define IFF_NO_PI 0x1000 ++/* This flag has no real effect */ ++#define IFF_ONE_QUEUE 0x2000 ++#define IFF_VNET_HDR 0x4000 ++#define IFF_TUN_EXCL 0x8000 ++#define IFF_MULTI_QUEUE 0x0100 ++#define IFF_ATTACH_QUEUE 0x0200 ++#define IFF_DETACH_QUEUE 0x0400 ++/* read-only flag */ ++#define IFF_PERSIST 0x0800 ++#define IFF_NOFILTER 0x1000 ++ ++/* Socket options */ ++#define TUN_TX_TIMESTAMP 1 ++ ++/* Features for GSO (TUNSETOFFLOAD). */ ++#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ ++#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */ ++#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ ++#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ ++#define TUN_F_UFO 0x10 /* I can handle UFO packets */ ++ ++/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ ++#define TUN_PKT_STRIP 0x0001 ++struct tun_pi { ++ __u16 flags; ++ __be16 proto; ++}; ++ ++/* ++ * Filter spec (used for SETXXFILTER ioctls) ++ * This stuff is applicable only to the TAP (Ethernet) devices. ++ * If the count is zero the filter is disabled and the driver accepts ++ * all packets (promisc mode). ++ * If the filter is enabled in order to accept broadcast packets ++ * broadcast addr must be explicitly included in the addr list. ++ */ ++#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */ ++struct tun_filter { ++ __u16 flags; /* TUN_FLT_ flags see above */ ++ __u16 count; /* Number of addresses */ ++ __u8 addr[0][ETH_ALEN]; ++}; ++ ++#endif /* _UAPI__IF_TUN_H */ +diff --git a/src/basic/linux/if_tunnel.h b/src/basic/linux/if_tunnel.h +new file mode 100644 +index 00000000000..7d9105533c7 +--- /dev/null ++++ b/src/basic/linux/if_tunnel.h +@@ -0,0 +1,183 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI_IF_TUNNEL_H_ ++#define _UAPI_IF_TUNNEL_H_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) ++#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) ++#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2) ++#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3) ++#define SIOCGETPRL (SIOCDEVPRIVATE + 4) ++#define SIOCADDPRL (SIOCDEVPRIVATE + 5) ++#define SIOCDELPRL (SIOCDEVPRIVATE + 6) ++#define SIOCCHGPRL (SIOCDEVPRIVATE + 7) ++#define SIOCGET6RD (SIOCDEVPRIVATE + 8) ++#define SIOCADD6RD (SIOCDEVPRIVATE + 9) ++#define SIOCDEL6RD (SIOCDEVPRIVATE + 10) ++#define SIOCCHG6RD (SIOCDEVPRIVATE + 11) ++ ++#define GRE_CSUM __cpu_to_be16(0x8000) ++#define GRE_ROUTING __cpu_to_be16(0x4000) ++#define GRE_KEY __cpu_to_be16(0x2000) ++#define GRE_SEQ __cpu_to_be16(0x1000) ++#define GRE_STRICT __cpu_to_be16(0x0800) ++#define GRE_REC __cpu_to_be16(0x0700) ++#define GRE_ACK __cpu_to_be16(0x0080) ++#define GRE_FLAGS __cpu_to_be16(0x0078) ++#define GRE_VERSION __cpu_to_be16(0x0007) ++ ++#define GRE_IS_CSUM(f) ((f) & GRE_CSUM) ++#define GRE_IS_ROUTING(f) ((f) & GRE_ROUTING) ++#define GRE_IS_KEY(f) ((f) & GRE_KEY) ++#define GRE_IS_SEQ(f) ((f) & GRE_SEQ) ++#define GRE_IS_STRICT(f) ((f) & GRE_STRICT) ++#define GRE_IS_REC(f) ((f) & GRE_REC) ++#define GRE_IS_ACK(f) ((f) & GRE_ACK) ++ ++#define GRE_VERSION_0 __cpu_to_be16(0x0000) ++#define GRE_VERSION_1 __cpu_to_be16(0x0001) ++#define GRE_PROTO_PPP __cpu_to_be16(0x880b) ++#define GRE_PPTP_KEY_MASK __cpu_to_be32(0xffff) ++ ++struct ip_tunnel_parm { ++ char name[IFNAMSIZ]; ++ int link; ++ __be16 i_flags; ++ __be16 o_flags; ++ __be32 i_key; ++ __be32 o_key; ++ struct iphdr iph; ++}; ++ ++enum { ++ IFLA_IPTUN_UNSPEC, ++ IFLA_IPTUN_LINK, ++ IFLA_IPTUN_LOCAL, ++ IFLA_IPTUN_REMOTE, ++ IFLA_IPTUN_TTL, ++ IFLA_IPTUN_TOS, ++ IFLA_IPTUN_ENCAP_LIMIT, ++ IFLA_IPTUN_FLOWINFO, ++ IFLA_IPTUN_FLAGS, ++ IFLA_IPTUN_PROTO, ++ IFLA_IPTUN_PMTUDISC, ++ IFLA_IPTUN_6RD_PREFIX, ++ IFLA_IPTUN_6RD_RELAY_PREFIX, ++ IFLA_IPTUN_6RD_PREFIXLEN, ++ IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ++ IFLA_IPTUN_ENCAP_TYPE, ++ IFLA_IPTUN_ENCAP_FLAGS, ++ IFLA_IPTUN_ENCAP_SPORT, ++ IFLA_IPTUN_ENCAP_DPORT, ++ IFLA_IPTUN_COLLECT_METADATA, ++ IFLA_IPTUN_FWMARK, ++ __IFLA_IPTUN_MAX, ++}; ++#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) ++ ++enum tunnel_encap_types { ++ TUNNEL_ENCAP_NONE, ++ TUNNEL_ENCAP_FOU, ++ TUNNEL_ENCAP_GUE, ++ TUNNEL_ENCAP_MPLS, ++}; ++ ++#define TUNNEL_ENCAP_FLAG_CSUM (1<<0) ++#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1) ++#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2) ++ ++/* SIT-mode i_flags */ ++#define SIT_ISATAP 0x0001 ++ ++struct ip_tunnel_prl { ++ __be32 addr; ++ __u16 flags; ++ __u16 __reserved; ++ __u32 datalen; ++ __u32 __reserved2; ++ /* data follows */ ++}; ++ ++/* PRL flags */ ++#define PRL_DEFAULT 0x0001 ++ ++struct ip_tunnel_6rd { ++ struct in6_addr prefix; ++ __be32 relay_prefix; ++ __u16 prefixlen; ++ __u16 relay_prefixlen; ++}; ++ ++enum { ++ IFLA_GRE_UNSPEC, ++ IFLA_GRE_LINK, ++ IFLA_GRE_IFLAGS, ++ IFLA_GRE_OFLAGS, ++ IFLA_GRE_IKEY, ++ IFLA_GRE_OKEY, ++ IFLA_GRE_LOCAL, ++ IFLA_GRE_REMOTE, ++ IFLA_GRE_TTL, ++ IFLA_GRE_TOS, ++ IFLA_GRE_PMTUDISC, ++ IFLA_GRE_ENCAP_LIMIT, ++ IFLA_GRE_FLOWINFO, ++ IFLA_GRE_FLAGS, ++ IFLA_GRE_ENCAP_TYPE, ++ IFLA_GRE_ENCAP_FLAGS, ++ IFLA_GRE_ENCAP_SPORT, ++ IFLA_GRE_ENCAP_DPORT, ++ IFLA_GRE_COLLECT_METADATA, ++ IFLA_GRE_IGNORE_DF, ++ IFLA_GRE_FWMARK, ++ IFLA_GRE_ERSPAN_INDEX, ++ IFLA_GRE_ERSPAN_VER, ++ IFLA_GRE_ERSPAN_DIR, ++ IFLA_GRE_ERSPAN_HWID, ++ __IFLA_GRE_MAX, ++}; ++ ++#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) ++ ++/* VTI-mode i_flags */ ++#define VTI_ISVTI ((__force __be16)0x0001) ++ ++enum { ++ IFLA_VTI_UNSPEC, ++ IFLA_VTI_LINK, ++ IFLA_VTI_IKEY, ++ IFLA_VTI_OKEY, ++ IFLA_VTI_LOCAL, ++ IFLA_VTI_REMOTE, ++ IFLA_VTI_FWMARK, ++ __IFLA_VTI_MAX, ++}; ++ ++#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) ++ ++#define TUNNEL_CSUM __cpu_to_be16(0x01) ++#define TUNNEL_ROUTING __cpu_to_be16(0x02) ++#define TUNNEL_KEY __cpu_to_be16(0x04) ++#define TUNNEL_SEQ __cpu_to_be16(0x08) ++#define TUNNEL_STRICT __cpu_to_be16(0x10) ++#define TUNNEL_REC __cpu_to_be16(0x20) ++#define TUNNEL_VERSION __cpu_to_be16(0x40) ++#define TUNNEL_NO_KEY __cpu_to_be16(0x80) ++#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) ++#define TUNNEL_OAM __cpu_to_be16(0x0200) ++#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400) ++#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800) ++#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) ++#define TUNNEL_NOCACHE __cpu_to_be16(0x2000) ++#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) ++ ++#define TUNNEL_OPTIONS_PRESENT \ ++ (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT) ++ ++#endif /* _UAPI_IF_TUNNEL_H_ */ +diff --git a/src/basic/linux/libc-compat.h b/src/basic/linux/libc-compat.h +new file mode 100644 +index 00000000000..8254c937c9f +--- /dev/null ++++ b/src/basic/linux/libc-compat.h +@@ -0,0 +1,267 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Compatibility interface for userspace libc header coordination: ++ * ++ * Define compatibility macros that are used to control the inclusion or ++ * exclusion of UAPI structures and definitions in coordination with another ++ * userspace C library. ++ * ++ * This header is intended to solve the problem of UAPI definitions that ++ * conflict with userspace definitions. If a UAPI header has such conflicting ++ * definitions then the solution is as follows: ++ * ++ * * Synchronize the UAPI header and the libc headers so either one can be ++ * used and such that the ABI is preserved. If this is not possible then ++ * no simple compatibility interface exists (you need to write translating ++ * wrappers and rename things) and you can't use this interface. ++ * ++ * Then follow this process: ++ * ++ * (a) Include libc-compat.h in the UAPI header. ++ * e.g. #include ++ * This include must be as early as possible. ++ * ++ * (b) In libc-compat.h add enough code to detect that the comflicting ++ * userspace libc header has been included first. ++ * ++ * (c) If the userspace libc header has been included first define a set of ++ * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else ++ * set their values to 0. ++ * ++ * (d) Back in the UAPI header with the conflicting definitions, guard the ++ * definitions with: ++ * #if __UAPI_DEF_FOO ++ * ... ++ * #endif ++ * ++ * This fixes the situation where the linux headers are included *after* the ++ * libc headers. To fix the problem with the inclusion in the other order the ++ * userspace libc headers must be fixed like this: ++ * ++ * * For all definitions that conflict with kernel definitions wrap those ++ * defines in the following: ++ * #if !__UAPI_DEF_FOO ++ * ... ++ * #endif ++ * ++ * This prevents the redefinition of a construct already defined by the kernel. ++ */ ++#ifndef _UAPI_LIBC_COMPAT_H ++#define _UAPI_LIBC_COMPAT_H ++ ++/* We have included glibc headers... */ ++#if defined(__GLIBC__) ++ ++/* Coordinate with glibc net/if.h header. */ ++#if defined(_NET_IF_H) && defined(__USE_MISC) ++ ++/* GLIBC headers included first so don't define anything ++ * that would already be defined. */ ++ ++#define __UAPI_DEF_IF_IFCONF 0 ++#define __UAPI_DEF_IF_IFMAP 0 ++#define __UAPI_DEF_IF_IFNAMSIZ 0 ++#define __UAPI_DEF_IF_IFREQ 0 ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ ++ ++#else /* _NET_IF_H */ ++ ++/* Linux headers included first, and we must define everything ++ * we need. The expectation is that glibc will check the ++ * __UAPI_DEF_* defines and adjust appropriately. */ ++ ++#define __UAPI_DEF_IF_IFCONF 1 ++#define __UAPI_DEF_IF_IFMAP 1 ++#define __UAPI_DEF_IF_IFNAMSIZ 1 ++#define __UAPI_DEF_IF_IFREQ 1 ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++ ++#endif /* _NET_IF_H */ ++ ++/* Coordinate with glibc netinet/in.h header. */ ++#if defined(_NETINET_IN_H) ++ ++/* GLIBC headers included first so don't define anything ++ * that would already be defined. */ ++#define __UAPI_DEF_IN_ADDR 0 ++#define __UAPI_DEF_IN_IPPROTO 0 ++#define __UAPI_DEF_IN_PKTINFO 0 ++#define __UAPI_DEF_IP_MREQ 0 ++#define __UAPI_DEF_SOCKADDR_IN 0 ++#define __UAPI_DEF_IN_CLASS 0 ++ ++#define __UAPI_DEF_IN6_ADDR 0 ++/* The exception is the in6_addr macros which must be defined ++ * if the glibc code didn't define them. This guard matches ++ * the guard in glibc/inet/netinet/in.h which defines the ++ * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ ++#if defined(__USE_MISC) || defined (__USE_GNU) ++#define __UAPI_DEF_IN6_ADDR_ALT 0 ++#else ++#define __UAPI_DEF_IN6_ADDR_ALT 1 ++#endif ++#define __UAPI_DEF_SOCKADDR_IN6 0 ++#define __UAPI_DEF_IPV6_MREQ 0 ++#define __UAPI_DEF_IPPROTO_V6 0 ++#define __UAPI_DEF_IPV6_OPTIONS 0 ++#define __UAPI_DEF_IN6_PKTINFO 0 ++#define __UAPI_DEF_IP6_MTUINFO 0 ++ ++#else ++ ++/* Linux headers included first, and we must define everything ++ * we need. The expectation is that glibc will check the ++ * __UAPI_DEF_* defines and adjust appropriately. */ ++#define __UAPI_DEF_IN_ADDR 1 ++#define __UAPI_DEF_IN_IPPROTO 1 ++#define __UAPI_DEF_IN_PKTINFO 1 ++#define __UAPI_DEF_IP_MREQ 1 ++#define __UAPI_DEF_SOCKADDR_IN 1 ++#define __UAPI_DEF_IN_CLASS 1 ++ ++#define __UAPI_DEF_IN6_ADDR 1 ++/* We unconditionally define the in6_addr macros and glibc must ++ * coordinate. */ ++#define __UAPI_DEF_IN6_ADDR_ALT 1 ++#define __UAPI_DEF_SOCKADDR_IN6 1 ++#define __UAPI_DEF_IPV6_MREQ 1 ++#define __UAPI_DEF_IPPROTO_V6 1 ++#define __UAPI_DEF_IPV6_OPTIONS 1 ++#define __UAPI_DEF_IN6_PKTINFO 1 ++#define __UAPI_DEF_IP6_MTUINFO 1 ++ ++#endif /* _NETINET_IN_H */ ++ ++/* Coordinate with glibc netipx/ipx.h header. */ ++#if defined(__NETIPX_IPX_H) ++ ++#define __UAPI_DEF_SOCKADDR_IPX 0 ++#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0 ++#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0 ++#define __UAPI_DEF_IPX_CONFIG_DATA 0 ++#define __UAPI_DEF_IPX_ROUTE_DEF 0 ++ ++#else /* defined(__NETIPX_IPX_H) */ ++ ++#define __UAPI_DEF_SOCKADDR_IPX 1 ++#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 ++#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 ++#define __UAPI_DEF_IPX_CONFIG_DATA 1 ++#define __UAPI_DEF_IPX_ROUTE_DEF 1 ++ ++#endif /* defined(__NETIPX_IPX_H) */ ++ ++/* Definitions for xattr.h */ ++#if defined(_SYS_XATTR_H) ++#define __UAPI_DEF_XATTR 0 ++#else ++#define __UAPI_DEF_XATTR 1 ++#endif ++ ++/* If we did not see any headers from any supported C libraries, ++ * or we are being included in the kernel, then define everything ++ * that we need. Check for previous __UAPI_* definitions to give ++ * unsupported C libraries a way to opt out of any kernel definition. */ ++#else /* !defined(__GLIBC__) */ ++ ++/* Definitions for if.h */ ++#ifndef __UAPI_DEF_IF_IFCONF ++#define __UAPI_DEF_IF_IFCONF 1 ++#endif ++#ifndef __UAPI_DEF_IF_IFMAP ++#define __UAPI_DEF_IF_IFMAP 1 ++#endif ++#ifndef __UAPI_DEF_IF_IFNAMSIZ ++#define __UAPI_DEF_IF_IFNAMSIZ 1 ++#endif ++#ifndef __UAPI_DEF_IF_IFREQ ++#define __UAPI_DEF_IF_IFREQ 1 ++#endif ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 ++#endif ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++#endif ++ ++/* Definitions for in.h */ ++#ifndef __UAPI_DEF_IN_ADDR ++#define __UAPI_DEF_IN_ADDR 1 ++#endif ++#ifndef __UAPI_DEF_IN_IPPROTO ++#define __UAPI_DEF_IN_IPPROTO 1 ++#endif ++#ifndef __UAPI_DEF_IN_PKTINFO ++#define __UAPI_DEF_IN_PKTINFO 1 ++#endif ++#ifndef __UAPI_DEF_IP_MREQ ++#define __UAPI_DEF_IP_MREQ 1 ++#endif ++#ifndef __UAPI_DEF_SOCKADDR_IN ++#define __UAPI_DEF_SOCKADDR_IN 1 ++#endif ++#ifndef __UAPI_DEF_IN_CLASS ++#define __UAPI_DEF_IN_CLASS 1 ++#endif ++ ++/* Definitions for in6.h */ ++#ifndef __UAPI_DEF_IN6_ADDR ++#define __UAPI_DEF_IN6_ADDR 1 ++#endif ++#ifndef __UAPI_DEF_IN6_ADDR_ALT ++#define __UAPI_DEF_IN6_ADDR_ALT 1 ++#endif ++#ifndef __UAPI_DEF_SOCKADDR_IN6 ++#define __UAPI_DEF_SOCKADDR_IN6 1 ++#endif ++#ifndef __UAPI_DEF_IPV6_MREQ ++#define __UAPI_DEF_IPV6_MREQ 1 ++#endif ++#ifndef __UAPI_DEF_IPPROTO_V6 ++#define __UAPI_DEF_IPPROTO_V6 1 ++#endif ++#ifndef __UAPI_DEF_IPV6_OPTIONS ++#define __UAPI_DEF_IPV6_OPTIONS 1 ++#endif ++#ifndef __UAPI_DEF_IN6_PKTINFO ++#define __UAPI_DEF_IN6_PKTINFO 1 ++#endif ++#ifndef __UAPI_DEF_IP6_MTUINFO ++#define __UAPI_DEF_IP6_MTUINFO 1 ++#endif ++ ++/* Definitions for ipx.h */ ++#ifndef __UAPI_DEF_SOCKADDR_IPX ++#define __UAPI_DEF_SOCKADDR_IPX 1 ++#endif ++#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION ++#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 ++#endif ++#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION ++#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 ++#endif ++#ifndef __UAPI_DEF_IPX_CONFIG_DATA ++#define __UAPI_DEF_IPX_CONFIG_DATA 1 ++#endif ++#ifndef __UAPI_DEF_IPX_ROUTE_DEF ++#define __UAPI_DEF_IPX_ROUTE_DEF 1 ++#endif ++ ++/* Definitions for xattr.h */ ++#ifndef __UAPI_DEF_XATTR ++#define __UAPI_DEF_XATTR 1 ++#endif ++ ++#endif /* __GLIBC__ */ ++ ++#endif /* _UAPI_LIBC_COMPAT_H */ +diff --git a/src/basic/linux/netlink.h b/src/basic/linux/netlink.h +new file mode 100644 +index 00000000000..0a4d7331775 +--- /dev/null ++++ b/src/basic/linux/netlink.h +@@ -0,0 +1,252 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI__LINUX_NETLINK_H ++#define _UAPI__LINUX_NETLINK_H ++ ++#include ++#include /* for __kernel_sa_family_t */ ++#include ++ ++#define NETLINK_ROUTE 0 /* Routing/device hook */ ++#define NETLINK_UNUSED 1 /* Unused number */ ++#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ ++#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ ++#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ ++#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ ++#define NETLINK_XFRM 6 /* ipsec */ ++#define NETLINK_SELINUX 7 /* SELinux event notifications */ ++#define NETLINK_ISCSI 8 /* Open-iSCSI */ ++#define NETLINK_AUDIT 9 /* auditing */ ++#define NETLINK_FIB_LOOKUP 10 ++#define NETLINK_CONNECTOR 11 ++#define NETLINK_NETFILTER 12 /* netfilter subsystem */ ++#define NETLINK_IP6_FW 13 ++#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ ++#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ ++#define NETLINK_GENERIC 16 ++/* leave room for NETLINK_DM (DM Events) */ ++#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ ++#define NETLINK_ECRYPTFS 19 ++#define NETLINK_RDMA 20 ++#define NETLINK_CRYPTO 21 /* Crypto layer */ ++#define NETLINK_SMC 22 /* SMC monitoring */ ++ ++#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG ++ ++#define MAX_LINKS 32 ++ ++struct sockaddr_nl { ++ __kernel_sa_family_t nl_family; /* AF_NETLINK */ ++ unsigned short nl_pad; /* zero */ ++ __u32 nl_pid; /* port ID */ ++ __u32 nl_groups; /* multicast groups mask */ ++}; ++ ++struct nlmsghdr { ++ __u32 nlmsg_len; /* Length of message including header */ ++ __u16 nlmsg_type; /* Message content */ ++ __u16 nlmsg_flags; /* Additional flags */ ++ __u32 nlmsg_seq; /* Sequence number */ ++ __u32 nlmsg_pid; /* Sending process port ID */ ++}; ++ ++/* Flags values */ ++ ++#define NLM_F_REQUEST 0x01 /* It is request message. */ ++#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */ ++#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */ ++#define NLM_F_ECHO 0x08 /* Echo this request */ ++#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */ ++#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ ++ ++/* Modifiers to GET request */ ++#define NLM_F_ROOT 0x100 /* specify tree root */ ++#define NLM_F_MATCH 0x200 /* return all matching */ ++#define NLM_F_ATOMIC 0x400 /* atomic GET */ ++#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) ++ ++/* Modifiers to NEW request */ ++#define NLM_F_REPLACE 0x100 /* Override existing */ ++#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ ++#define NLM_F_CREATE 0x400 /* Create, if it does not exist */ ++#define NLM_F_APPEND 0x800 /* Add to end of list */ ++ ++/* Modifiers to DELETE request */ ++#define NLM_F_NONREC 0x100 /* Do not delete recursively */ ++ ++/* Flags for ACK message */ ++#define NLM_F_CAPPED 0x100 /* request was capped */ ++#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ ++ ++/* ++ 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL ++ 4.4BSD CHANGE NLM_F_REPLACE ++ ++ True CHANGE NLM_F_CREATE|NLM_F_REPLACE ++ Append NLM_F_CREATE ++ Check NLM_F_EXCL ++ */ ++ ++#define NLMSG_ALIGNTO 4U ++#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) ++#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) ++#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN) ++#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) ++#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) ++#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ ++ (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) ++#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ ++ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ ++ (nlh)->nlmsg_len <= (len)) ++#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) ++ ++#define NLMSG_NOOP 0x1 /* Nothing. */ ++#define NLMSG_ERROR 0x2 /* Error */ ++#define NLMSG_DONE 0x3 /* End of a dump */ ++#define NLMSG_OVERRUN 0x4 /* Data lost */ ++ ++#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ ++ ++struct nlmsgerr { ++ int error; ++ struct nlmsghdr msg; ++ /* ++ * followed by the message contents unless NETLINK_CAP_ACK was set ++ * or the ACK indicates success (error == 0) ++ * message length is aligned with NLMSG_ALIGN() ++ */ ++ /* ++ * followed by TLVs defined in enum nlmsgerr_attrs ++ * if NETLINK_EXT_ACK was set ++ */ ++}; ++ ++/** ++ * enum nlmsgerr_attrs - nlmsgerr attributes ++ * @NLMSGERR_ATTR_UNUSED: unused ++ * @NLMSGERR_ATTR_MSG: error message string (string) ++ * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original ++ * message, counting from the beginning of the header (u32) ++ * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to ++ * be used - in the success case - to identify a created ++ * object or operation or similar (binary) ++ * @__NLMSGERR_ATTR_MAX: number of attributes ++ * @NLMSGERR_ATTR_MAX: highest attribute number ++ */ ++enum nlmsgerr_attrs { ++ NLMSGERR_ATTR_UNUSED, ++ NLMSGERR_ATTR_MSG, ++ NLMSGERR_ATTR_OFFS, ++ NLMSGERR_ATTR_COOKIE, ++ ++ __NLMSGERR_ATTR_MAX, ++ NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 ++}; ++ ++#define NETLINK_ADD_MEMBERSHIP 1 ++#define NETLINK_DROP_MEMBERSHIP 2 ++#define NETLINK_PKTINFO 3 ++#define NETLINK_BROADCAST_ERROR 4 ++#define NETLINK_NO_ENOBUFS 5 ++#ifndef __KERNEL__ ++#define NETLINK_RX_RING 6 ++#define NETLINK_TX_RING 7 ++#endif ++#define NETLINK_LISTEN_ALL_NSID 8 ++#define NETLINK_LIST_MEMBERSHIPS 9 ++#define NETLINK_CAP_ACK 10 ++#define NETLINK_EXT_ACK 11 ++#define NETLINK_GET_STRICT_CHK 12 ++ ++struct nl_pktinfo { ++ __u32 group; ++}; ++ ++struct nl_mmap_req { ++ unsigned int nm_block_size; ++ unsigned int nm_block_nr; ++ unsigned int nm_frame_size; ++ unsigned int nm_frame_nr; ++}; ++ ++struct nl_mmap_hdr { ++ unsigned int nm_status; ++ unsigned int nm_len; ++ __u32 nm_group; ++ /* credentials */ ++ __u32 nm_pid; ++ __u32 nm_uid; ++ __u32 nm_gid; ++}; ++ ++#ifndef __KERNEL__ ++enum nl_mmap_status { ++ NL_MMAP_STATUS_UNUSED, ++ NL_MMAP_STATUS_RESERVED, ++ NL_MMAP_STATUS_VALID, ++ NL_MMAP_STATUS_COPY, ++ NL_MMAP_STATUS_SKIP, ++}; ++ ++#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO ++#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) ++#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) ++#endif ++ ++#define NET_MAJOR 36 /* Major 36 is reserved for networking */ ++ ++enum { ++ NETLINK_UNCONNECTED = 0, ++ NETLINK_CONNECTED, ++}; ++ ++/* ++ * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> ++ * +---------------------+- - -+- - - - - - - - - -+- - -+ ++ * | Header | Pad | Payload | Pad | ++ * | (struct nlattr) | ing | | ing | ++ * +---------------------+- - -+- - - - - - - - - -+- - -+ ++ * <-------------- nlattr->nla_len --------------> ++ */ ++ ++struct nlattr { ++ __u16 nla_len; ++ __u16 nla_type; ++}; ++ ++/* ++ * nla_type (16 bits) ++ * +---+---+-------------------------------+ ++ * | N | O | Attribute Type | ++ * +---+---+-------------------------------+ ++ * N := Carries nested attributes ++ * O := Payload stored in network byte order ++ * ++ * Note: The N and O flag are mutually exclusive. ++ */ ++#define NLA_F_NESTED (1 << 15) ++#define NLA_F_NET_BYTEORDER (1 << 14) ++#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) ++ ++#define NLA_ALIGNTO 4 ++#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) ++#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) ++ ++/* Generic 32 bitflags attribute content sent to the kernel. ++ * ++ * The value is a bitmap that defines the values being set ++ * The selector is a bitmask that defines which value is legit ++ * ++ * Examples: ++ * value = 0x0, and selector = 0x1 ++ * implies we are selecting bit 1 and we want to set its value to 0. ++ * ++ * value = 0x2, and selector = 0x2 ++ * implies we are selecting bit 2 and we want to set its value to 1. ++ * ++ */ ++struct nla_bitfield32 { ++ __u32 value; ++ __u32 selector; ++}; ++ ++#endif /* _UAPI__LINUX_NETLINK_H */ +diff --git a/src/basic/linux/rtnetlink.h b/src/basic/linux/rtnetlink.h +new file mode 100644 +index 00000000000..46399367627 +--- /dev/null ++++ b/src/basic/linux/rtnetlink.h +@@ -0,0 +1,751 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI__LINUX_RTNETLINK_H ++#define _UAPI__LINUX_RTNETLINK_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* rtnetlink families. Values up to 127 are reserved for real address ++ * families, values above 128 may be used arbitrarily. ++ */ ++#define RTNL_FAMILY_IPMR 128 ++#define RTNL_FAMILY_IP6MR 129 ++#define RTNL_FAMILY_MAX 129 ++ ++/**** ++ * Routing/neighbour discovery messages. ++ ****/ ++ ++/* Types of messages */ ++ ++enum { ++ RTM_BASE = 16, ++#define RTM_BASE RTM_BASE ++ ++ RTM_NEWLINK = 16, ++#define RTM_NEWLINK RTM_NEWLINK ++ RTM_DELLINK, ++#define RTM_DELLINK RTM_DELLINK ++ RTM_GETLINK, ++#define RTM_GETLINK RTM_GETLINK ++ RTM_SETLINK, ++#define RTM_SETLINK RTM_SETLINK ++ ++ RTM_NEWADDR = 20, ++#define RTM_NEWADDR RTM_NEWADDR ++ RTM_DELADDR, ++#define RTM_DELADDR RTM_DELADDR ++ RTM_GETADDR, ++#define RTM_GETADDR RTM_GETADDR ++ ++ RTM_NEWROUTE = 24, ++#define RTM_NEWROUTE RTM_NEWROUTE ++ RTM_DELROUTE, ++#define RTM_DELROUTE RTM_DELROUTE ++ RTM_GETROUTE, ++#define RTM_GETROUTE RTM_GETROUTE ++ ++ RTM_NEWNEIGH = 28, ++#define RTM_NEWNEIGH RTM_NEWNEIGH ++ RTM_DELNEIGH, ++#define RTM_DELNEIGH RTM_DELNEIGH ++ RTM_GETNEIGH, ++#define RTM_GETNEIGH RTM_GETNEIGH ++ ++ RTM_NEWRULE = 32, ++#define RTM_NEWRULE RTM_NEWRULE ++ RTM_DELRULE, ++#define RTM_DELRULE RTM_DELRULE ++ RTM_GETRULE, ++#define RTM_GETRULE RTM_GETRULE ++ ++ RTM_NEWQDISC = 36, ++#define RTM_NEWQDISC RTM_NEWQDISC ++ RTM_DELQDISC, ++#define RTM_DELQDISC RTM_DELQDISC ++ RTM_GETQDISC, ++#define RTM_GETQDISC RTM_GETQDISC ++ ++ RTM_NEWTCLASS = 40, ++#define RTM_NEWTCLASS RTM_NEWTCLASS ++ RTM_DELTCLASS, ++#define RTM_DELTCLASS RTM_DELTCLASS ++ RTM_GETTCLASS, ++#define RTM_GETTCLASS RTM_GETTCLASS ++ ++ RTM_NEWTFILTER = 44, ++#define RTM_NEWTFILTER RTM_NEWTFILTER ++ RTM_DELTFILTER, ++#define RTM_DELTFILTER RTM_DELTFILTER ++ RTM_GETTFILTER, ++#define RTM_GETTFILTER RTM_GETTFILTER ++ ++ RTM_NEWACTION = 48, ++#define RTM_NEWACTION RTM_NEWACTION ++ RTM_DELACTION, ++#define RTM_DELACTION RTM_DELACTION ++ RTM_GETACTION, ++#define RTM_GETACTION RTM_GETACTION ++ ++ RTM_NEWPREFIX = 52, ++#define RTM_NEWPREFIX RTM_NEWPREFIX ++ ++ RTM_GETMULTICAST = 58, ++#define RTM_GETMULTICAST RTM_GETMULTICAST ++ ++ RTM_GETANYCAST = 62, ++#define RTM_GETANYCAST RTM_GETANYCAST ++ ++ RTM_NEWNEIGHTBL = 64, ++#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL ++ RTM_GETNEIGHTBL = 66, ++#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL ++ RTM_SETNEIGHTBL, ++#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL ++ ++ RTM_NEWNDUSEROPT = 68, ++#define RTM_NEWNDUSEROPT RTM_NEWNDUSEROPT ++ ++ RTM_NEWADDRLABEL = 72, ++#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL ++ RTM_DELADDRLABEL, ++#define RTM_DELADDRLABEL RTM_DELADDRLABEL ++ RTM_GETADDRLABEL, ++#define RTM_GETADDRLABEL RTM_GETADDRLABEL ++ ++ RTM_GETDCB = 78, ++#define RTM_GETDCB RTM_GETDCB ++ RTM_SETDCB, ++#define RTM_SETDCB RTM_SETDCB ++ ++ RTM_NEWNETCONF = 80, ++#define RTM_NEWNETCONF RTM_NEWNETCONF ++ RTM_DELNETCONF, ++#define RTM_DELNETCONF RTM_DELNETCONF ++ RTM_GETNETCONF = 82, ++#define RTM_GETNETCONF RTM_GETNETCONF ++ ++ RTM_NEWMDB = 84, ++#define RTM_NEWMDB RTM_NEWMDB ++ RTM_DELMDB = 85, ++#define RTM_DELMDB RTM_DELMDB ++ RTM_GETMDB = 86, ++#define RTM_GETMDB RTM_GETMDB ++ ++ RTM_NEWNSID = 88, ++#define RTM_NEWNSID RTM_NEWNSID ++ RTM_DELNSID = 89, ++#define RTM_DELNSID RTM_DELNSID ++ RTM_GETNSID = 90, ++#define RTM_GETNSID RTM_GETNSID ++ ++ RTM_NEWSTATS = 92, ++#define RTM_NEWSTATS RTM_NEWSTATS ++ RTM_GETSTATS = 94, ++#define RTM_GETSTATS RTM_GETSTATS ++ ++ RTM_NEWCACHEREPORT = 96, ++#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT ++ ++ RTM_NEWCHAIN = 100, ++#define RTM_NEWCHAIN RTM_NEWCHAIN ++ RTM_DELCHAIN, ++#define RTM_DELCHAIN RTM_DELCHAIN ++ RTM_GETCHAIN, ++#define RTM_GETCHAIN RTM_GETCHAIN ++ ++ __RTM_MAX, ++#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) ++}; ++ ++#define RTM_NR_MSGTYPES (RTM_MAX + 1 - RTM_BASE) ++#define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2) ++#define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2) ++ ++/* ++ Generic structure for encapsulation of optional route information. ++ It is reminiscent of sockaddr, but with sa_family replaced ++ with attribute type. ++ */ ++ ++struct rtattr { ++ unsigned short rta_len; ++ unsigned short rta_type; ++}; ++ ++/* Macros to handle rtattributes */ ++ ++#define RTA_ALIGNTO 4U ++#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) ) ++#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \ ++ (rta)->rta_len >= sizeof(struct rtattr) && \ ++ (rta)->rta_len <= (len)) ++#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \ ++ (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len))) ++#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) ++#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len)) ++#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0))) ++#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) ++ ++ ++ ++ ++/****************************************************************************** ++ * Definitions used in routing table administration. ++ ****/ ++ ++struct rtmsg { ++ unsigned char rtm_family; ++ unsigned char rtm_dst_len; ++ unsigned char rtm_src_len; ++ unsigned char rtm_tos; ++ ++ unsigned char rtm_table; /* Routing table id */ ++ unsigned char rtm_protocol; /* Routing protocol; see below */ ++ unsigned char rtm_scope; /* See below */ ++ unsigned char rtm_type; /* See below */ ++ ++ unsigned rtm_flags; ++}; ++ ++/* rtm_type */ ++ ++enum { ++ RTN_UNSPEC, ++ RTN_UNICAST, /* Gateway or direct route */ ++ RTN_LOCAL, /* Accept locally */ ++ RTN_BROADCAST, /* Accept locally as broadcast, ++ send as broadcast */ ++ RTN_ANYCAST, /* Accept locally as broadcast, ++ but send as unicast */ ++ RTN_MULTICAST, /* Multicast route */ ++ RTN_BLACKHOLE, /* Drop */ ++ RTN_UNREACHABLE, /* Destination is unreachable */ ++ RTN_PROHIBIT, /* Administratively prohibited */ ++ RTN_THROW, /* Not in this table */ ++ RTN_NAT, /* Translate this address */ ++ RTN_XRESOLVE, /* Use external resolver */ ++ __RTN_MAX ++}; ++ ++#define RTN_MAX (__RTN_MAX - 1) ++ ++ ++/* rtm_protocol */ ++ ++#define RTPROT_UNSPEC 0 ++#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; ++ not used by current IPv4 */ ++#define RTPROT_KERNEL 2 /* Route installed by kernel */ ++#define RTPROT_BOOT 3 /* Route installed during boot */ ++#define RTPROT_STATIC 4 /* Route installed by administrator */ ++ ++/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; ++ they are just passed from user and back as is. ++ It will be used by hypothetical multiple routing daemons. ++ Note that protocol values should be standardized in order to ++ avoid conflicts. ++ */ ++ ++#define RTPROT_GATED 8 /* Apparently, GateD */ ++#define RTPROT_RA 9 /* RDISC/ND router advertisements */ ++#define RTPROT_MRT 10 /* Merit MRT */ ++#define RTPROT_ZEBRA 11 /* Zebra */ ++#define RTPROT_BIRD 12 /* BIRD */ ++#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ ++#define RTPROT_XORP 14 /* XORP */ ++#define RTPROT_NTK 15 /* Netsukuku */ ++#define RTPROT_DHCP 16 /* DHCP client */ ++#define RTPROT_MROUTED 17 /* Multicast daemon */ ++#define RTPROT_BABEL 42 /* Babel daemon */ ++#define RTPROT_BGP 186 /* BGP Routes */ ++#define RTPROT_ISIS 187 /* ISIS Routes */ ++#define RTPROT_OSPF 188 /* OSPF Routes */ ++#define RTPROT_RIP 189 /* RIP Routes */ ++#define RTPROT_EIGRP 192 /* EIGRP Routes */ ++ ++/* rtm_scope ++ ++ Really it is not scope, but sort of distance to the destination. ++ NOWHERE are reserved for not existing destinations, HOST is our ++ local addresses, LINK are destinations, located on directly attached ++ link and UNIVERSE is everywhere in the Universe. ++ ++ Intermediate values are also possible f.e. interior routes ++ could be assigned a value between UNIVERSE and LINK. ++*/ ++ ++enum rt_scope_t { ++ RT_SCOPE_UNIVERSE=0, ++/* User defined values */ ++ RT_SCOPE_SITE=200, ++ RT_SCOPE_LINK=253, ++ RT_SCOPE_HOST=254, ++ RT_SCOPE_NOWHERE=255 ++}; ++ ++/* rtm_flags */ ++ ++#define RTM_F_NOTIFY 0x100 /* Notify user of route change */ ++#define RTM_F_CLONED 0x200 /* This route is cloned */ ++#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ ++#define RTM_F_PREFIX 0x800 /* Prefix addresses */ ++#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ ++#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */ ++ ++/* Reserved table identifiers */ ++ ++enum rt_class_t { ++ RT_TABLE_UNSPEC=0, ++/* User defined values */ ++ RT_TABLE_COMPAT=252, ++ RT_TABLE_DEFAULT=253, ++ RT_TABLE_MAIN=254, ++ RT_TABLE_LOCAL=255, ++ RT_TABLE_MAX=0xFFFFFFFF ++}; ++ ++ ++/* Routing message attributes */ ++ ++enum rtattr_type_t { ++ RTA_UNSPEC, ++ RTA_DST, ++ RTA_SRC, ++ RTA_IIF, ++ RTA_OIF, ++ RTA_GATEWAY, ++ RTA_PRIORITY, ++ RTA_PREFSRC, ++ RTA_METRICS, ++ RTA_MULTIPATH, ++ RTA_PROTOINFO, /* no longer used */ ++ RTA_FLOW, ++ RTA_CACHEINFO, ++ RTA_SESSION, /* no longer used */ ++ RTA_MP_ALGO, /* no longer used */ ++ RTA_TABLE, ++ RTA_MARK, ++ RTA_MFC_STATS, ++ RTA_VIA, ++ RTA_NEWDST, ++ RTA_PREF, ++ RTA_ENCAP_TYPE, ++ RTA_ENCAP, ++ RTA_EXPIRES, ++ RTA_PAD, ++ RTA_UID, ++ RTA_TTL_PROPAGATE, ++ RTA_IP_PROTO, ++ RTA_SPORT, ++ RTA_DPORT, ++ __RTA_MAX ++}; ++ ++#define RTA_MAX (__RTA_MAX - 1) ++ ++#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg)))) ++#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg)) ++ ++/* RTM_MULTIPATH --- array of struct rtnexthop. ++ * ++ * "struct rtnexthop" describes all necessary nexthop information, ++ * i.e. parameters of path to a destination via this nexthop. ++ * ++ * At the moment it is impossible to set different prefsrc, mtu, window ++ * and rtt for different paths from multipath. ++ */ ++ ++struct rtnexthop { ++ unsigned short rtnh_len; ++ unsigned char rtnh_flags; ++ unsigned char rtnh_hops; ++ int rtnh_ifindex; ++}; ++ ++/* rtnh_flags */ ++ ++#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */ ++#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */ ++#define RTNH_F_ONLINK 4 /* Gateway is forced on link */ ++#define RTNH_F_OFFLOAD 8 /* offloaded route */ ++#define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */ ++#define RTNH_F_UNRESOLVED 32 /* The entry is unresolved (ipmr) */ ++ ++#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD) ++ ++/* Macros to handle hexthops */ ++ ++#define RTNH_ALIGNTO 4 ++#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) ) ++#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \ ++ ((int)(rtnh)->rtnh_len) <= (len)) ++#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len))) ++#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len)) ++#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len)) ++#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) ++ ++/* RTA_VIA */ ++struct rtvia { ++ __kernel_sa_family_t rtvia_family; ++ __u8 rtvia_addr[0]; ++}; ++ ++/* RTM_CACHEINFO */ ++ ++struct rta_cacheinfo { ++ __u32 rta_clntref; ++ __u32 rta_lastuse; ++ __s32 rta_expires; ++ __u32 rta_error; ++ __u32 rta_used; ++ ++#define RTNETLINK_HAVE_PEERINFO 1 ++ __u32 rta_id; ++ __u32 rta_ts; ++ __u32 rta_tsage; ++}; ++ ++/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */ ++ ++enum { ++ RTAX_UNSPEC, ++#define RTAX_UNSPEC RTAX_UNSPEC ++ RTAX_LOCK, ++#define RTAX_LOCK RTAX_LOCK ++ RTAX_MTU, ++#define RTAX_MTU RTAX_MTU ++ RTAX_WINDOW, ++#define RTAX_WINDOW RTAX_WINDOW ++ RTAX_RTT, ++#define RTAX_RTT RTAX_RTT ++ RTAX_RTTVAR, ++#define RTAX_RTTVAR RTAX_RTTVAR ++ RTAX_SSTHRESH, ++#define RTAX_SSTHRESH RTAX_SSTHRESH ++ RTAX_CWND, ++#define RTAX_CWND RTAX_CWND ++ RTAX_ADVMSS, ++#define RTAX_ADVMSS RTAX_ADVMSS ++ RTAX_REORDERING, ++#define RTAX_REORDERING RTAX_REORDERING ++ RTAX_HOPLIMIT, ++#define RTAX_HOPLIMIT RTAX_HOPLIMIT ++ RTAX_INITCWND, ++#define RTAX_INITCWND RTAX_INITCWND ++ RTAX_FEATURES, ++#define RTAX_FEATURES RTAX_FEATURES ++ RTAX_RTO_MIN, ++#define RTAX_RTO_MIN RTAX_RTO_MIN ++ RTAX_INITRWND, ++#define RTAX_INITRWND RTAX_INITRWND ++ RTAX_QUICKACK, ++#define RTAX_QUICKACK RTAX_QUICKACK ++ RTAX_CC_ALGO, ++#define RTAX_CC_ALGO RTAX_CC_ALGO ++ RTAX_FASTOPEN_NO_COOKIE, ++#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE ++ __RTAX_MAX ++}; ++ ++#define RTAX_MAX (__RTAX_MAX - 1) ++ ++#define RTAX_FEATURE_ECN (1 << 0) ++#define RTAX_FEATURE_SACK (1 << 1) ++#define RTAX_FEATURE_TIMESTAMP (1 << 2) ++#define RTAX_FEATURE_ALLFRAG (1 << 3) ++ ++#define RTAX_FEATURE_MASK (RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | \ ++ RTAX_FEATURE_TIMESTAMP | RTAX_FEATURE_ALLFRAG) ++ ++struct rta_session { ++ __u8 proto; ++ __u8 pad1; ++ __u16 pad2; ++ ++ union { ++ struct { ++ __u16 sport; ++ __u16 dport; ++ } ports; ++ ++ struct { ++ __u8 type; ++ __u8 code; ++ __u16 ident; ++ } icmpt; ++ ++ __u32 spi; ++ } u; ++}; ++ ++struct rta_mfc_stats { ++ __u64 mfcs_packets; ++ __u64 mfcs_bytes; ++ __u64 mfcs_wrong_if; ++}; ++ ++/**** ++ * General form of address family dependent message. ++ ****/ ++ ++struct rtgenmsg { ++ unsigned char rtgen_family; ++}; ++ ++/***************************************************************** ++ * Link layer specific messages. ++ ****/ ++ ++/* struct ifinfomsg ++ * passes link level specific information, not dependent ++ * on network protocol. ++ */ ++ ++struct ifinfomsg { ++ unsigned char ifi_family; ++ unsigned char __ifi_pad; ++ unsigned short ifi_type; /* ARPHRD_* */ ++ int ifi_index; /* Link index */ ++ unsigned ifi_flags; /* IFF_* flags */ ++ unsigned ifi_change; /* IFF_* change mask */ ++}; ++ ++/******************************************************************** ++ * prefix information ++ ****/ ++ ++struct prefixmsg { ++ unsigned char prefix_family; ++ unsigned char prefix_pad1; ++ unsigned short prefix_pad2; ++ int prefix_ifindex; ++ unsigned char prefix_type; ++ unsigned char prefix_len; ++ unsigned char prefix_flags; ++ unsigned char prefix_pad3; ++}; ++ ++enum ++{ ++ PREFIX_UNSPEC, ++ PREFIX_ADDRESS, ++ PREFIX_CACHEINFO, ++ __PREFIX_MAX ++}; ++ ++#define PREFIX_MAX (__PREFIX_MAX - 1) ++ ++struct prefix_cacheinfo { ++ __u32 preferred_time; ++ __u32 valid_time; ++}; ++ ++ ++/***************************************************************** ++ * Traffic control messages. ++ ****/ ++ ++struct tcmsg { ++ unsigned char tcm_family; ++ unsigned char tcm__pad1; ++ unsigned short tcm__pad2; ++ int tcm_ifindex; ++ __u32 tcm_handle; ++ __u32 tcm_parent; ++/* tcm_block_index is used instead of tcm_parent ++ * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK ++ */ ++#define tcm_block_index tcm_parent ++ __u32 tcm_info; ++}; ++ ++/* For manipulation of filters in shared block, tcm_ifindex is set to ++ * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index ++ * which is the block index. ++ */ ++#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU) ++ ++enum { ++ TCA_UNSPEC, ++ TCA_KIND, ++ TCA_OPTIONS, ++ TCA_STATS, ++ TCA_XSTATS, ++ TCA_RATE, ++ TCA_FCNT, ++ TCA_STATS2, ++ TCA_STAB, ++ TCA_PAD, ++ TCA_DUMP_INVISIBLE, ++ TCA_CHAIN, ++ TCA_HW_OFFLOAD, ++ TCA_INGRESS_BLOCK, ++ TCA_EGRESS_BLOCK, ++ __TCA_MAX ++}; ++ ++#define TCA_MAX (__TCA_MAX - 1) ++ ++#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) ++#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) ++ ++/******************************************************************** ++ * Neighbor Discovery userland options ++ ****/ ++ ++struct nduseroptmsg { ++ unsigned char nduseropt_family; ++ unsigned char nduseropt_pad1; ++ unsigned short nduseropt_opts_len; /* Total length of options */ ++ int nduseropt_ifindex; ++ __u8 nduseropt_icmp_type; ++ __u8 nduseropt_icmp_code; ++ unsigned short nduseropt_pad2; ++ unsigned int nduseropt_pad3; ++ /* Followed by one or more ND options */ ++}; ++ ++enum { ++ NDUSEROPT_UNSPEC, ++ NDUSEROPT_SRCADDR, ++ __NDUSEROPT_MAX ++}; ++ ++#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1) ++ ++#ifndef __KERNEL__ ++/* RTnetlink multicast groups - backwards compatibility for userspace */ ++#define RTMGRP_LINK 1 ++#define RTMGRP_NOTIFY 2 ++#define RTMGRP_NEIGH 4 ++#define RTMGRP_TC 8 ++ ++#define RTMGRP_IPV4_IFADDR 0x10 ++#define RTMGRP_IPV4_MROUTE 0x20 ++#define RTMGRP_IPV4_ROUTE 0x40 ++#define RTMGRP_IPV4_RULE 0x80 ++ ++#define RTMGRP_IPV6_IFADDR 0x100 ++#define RTMGRP_IPV6_MROUTE 0x200 ++#define RTMGRP_IPV6_ROUTE 0x400 ++#define RTMGRP_IPV6_IFINFO 0x800 ++ ++#define RTMGRP_DECnet_IFADDR 0x1000 ++#define RTMGRP_DECnet_ROUTE 0x4000 ++ ++#define RTMGRP_IPV6_PREFIX 0x20000 ++#endif ++ ++/* RTnetlink multicast groups */ ++enum rtnetlink_groups { ++ RTNLGRP_NONE, ++#define RTNLGRP_NONE RTNLGRP_NONE ++ RTNLGRP_LINK, ++#define RTNLGRP_LINK RTNLGRP_LINK ++ RTNLGRP_NOTIFY, ++#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY ++ RTNLGRP_NEIGH, ++#define RTNLGRP_NEIGH RTNLGRP_NEIGH ++ RTNLGRP_TC, ++#define RTNLGRP_TC RTNLGRP_TC ++ RTNLGRP_IPV4_IFADDR, ++#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR ++ RTNLGRP_IPV4_MROUTE, ++#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE ++ RTNLGRP_IPV4_ROUTE, ++#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE ++ RTNLGRP_IPV4_RULE, ++#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE ++ RTNLGRP_IPV6_IFADDR, ++#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR ++ RTNLGRP_IPV6_MROUTE, ++#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE ++ RTNLGRP_IPV6_ROUTE, ++#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE ++ RTNLGRP_IPV6_IFINFO, ++#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO ++ RTNLGRP_DECnet_IFADDR, ++#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR ++ RTNLGRP_NOP2, ++ RTNLGRP_DECnet_ROUTE, ++#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE ++ RTNLGRP_DECnet_RULE, ++#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE ++ RTNLGRP_NOP4, ++ RTNLGRP_IPV6_PREFIX, ++#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX ++ RTNLGRP_IPV6_RULE, ++#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE ++ RTNLGRP_ND_USEROPT, ++#define RTNLGRP_ND_USEROPT RTNLGRP_ND_USEROPT ++ RTNLGRP_PHONET_IFADDR, ++#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR ++ RTNLGRP_PHONET_ROUTE, ++#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE ++ RTNLGRP_DCB, ++#define RTNLGRP_DCB RTNLGRP_DCB ++ RTNLGRP_IPV4_NETCONF, ++#define RTNLGRP_IPV4_NETCONF RTNLGRP_IPV4_NETCONF ++ RTNLGRP_IPV6_NETCONF, ++#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF ++ RTNLGRP_MDB, ++#define RTNLGRP_MDB RTNLGRP_MDB ++ RTNLGRP_MPLS_ROUTE, ++#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE ++ RTNLGRP_NSID, ++#define RTNLGRP_NSID RTNLGRP_NSID ++ RTNLGRP_MPLS_NETCONF, ++#define RTNLGRP_MPLS_NETCONF RTNLGRP_MPLS_NETCONF ++ RTNLGRP_IPV4_MROUTE_R, ++#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R ++ RTNLGRP_IPV6_MROUTE_R, ++#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R ++ __RTNLGRP_MAX ++}; ++#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) ++ ++/* TC action piece */ ++struct tcamsg { ++ unsigned char tca_family; ++ unsigned char tca__pad1; ++ unsigned short tca__pad2; ++}; ++ ++enum { ++ TCA_ROOT_UNSPEC, ++ TCA_ROOT_TAB, ++#define TCA_ACT_TAB TCA_ROOT_TAB ++#define TCAA_MAX TCA_ROOT_TAB ++ TCA_ROOT_FLAGS, ++ TCA_ROOT_COUNT, ++ TCA_ROOT_TIME_DELTA, /* in msecs */ ++ __TCA_ROOT_MAX, ++#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) ++}; ++ ++#define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) ++#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) ++/* tcamsg flags stored in attribute TCA_ROOT_FLAGS ++ * ++ * TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO ++ * actions in a dump. All dump responses will contain the number of actions ++ * being dumped stored in for user app's consumption in TCA_ROOT_COUNT ++ * ++ */ ++#define TCA_FLAG_LARGE_DUMP_ON (1 << 0) ++ ++/* New extended info filters for IFLA_EXT_MASK */ ++#define RTEXT_FILTER_VF (1 << 0) ++#define RTEXT_FILTER_BRVLAN (1 << 1) ++#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) ++#define RTEXT_FILTER_SKIP_STATS (1 << 3) ++ ++/* End of information exported to user level */ ++ ++ ++ ++#endif /* _UAPI__LINUX_RTNETLINK_H */ +diff --git a/src/basic/linux/wireguard.h b/src/basic/linux/wireguard.h +new file mode 100644 +index 00000000000..071ce4167f5 +--- /dev/null ++++ b/src/basic/linux/wireguard.h +@@ -0,0 +1,190 @@ ++/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */ ++/* ++ * Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved. ++ * ++ * Documentation ++ * ============= ++ * ++ * The below enums and macros are for interfacing with WireGuard, using generic ++ * netlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two ++ * methods: get and set. Note that while they share many common attributes, ++ * these two functions actually accept a slightly different set of inputs and ++ * outputs. ++ * ++ * WG_CMD_GET_DEVICE ++ * ----------------- ++ * ++ * May only be called via NLM_F_REQUEST | NLM_F_DUMP. The command should contain ++ * one but not both of: ++ * ++ * WGDEVICE_A_IFINDEX: NLA_U32 ++ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 ++ * ++ * The kernel will then return several messages (NLM_F_MULTI) containing the ++ * following tree of nested items: ++ * ++ * WGDEVICE_A_IFINDEX: NLA_U32 ++ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 ++ * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN ++ * WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN ++ * WGDEVICE_A_LISTEN_PORT: NLA_U16 ++ * WGDEVICE_A_FWMARK: NLA_U32 ++ * WGDEVICE_A_PEERS: NLA_NESTED ++ * 0: NLA_NESTED ++ * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN ++ * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN ++ * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 ++ * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16 ++ * WGPEER_A_LAST_HANDSHAKE_TIME: struct __kernel_timespec ++ * WGPEER_A_RX_BYTES: NLA_U64 ++ * WGPEER_A_TX_BYTES: NLA_U64 ++ * WGPEER_A_ALLOWEDIPS: NLA_NESTED ++ * 0: NLA_NESTED ++ * WGALLOWEDIP_A_FAMILY: NLA_U16 ++ * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr ++ * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 ++ * 0: NLA_NESTED ++ * ... ++ * 0: NLA_NESTED ++ * ... ++ * ... ++ * WGPEER_A_PROTOCOL_VERSION: NLA_U32 ++ * 0: NLA_NESTED ++ * ... ++ * ... ++ * ++ * It is possible that all of the allowed IPs of a single peer will not ++ * fit within a single netlink message. In that case, the same peer will ++ * be written in the following message, except it will only contain ++ * WGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several ++ * times in a row for the same peer. It is then up to the receiver to ++ * coalesce adjacent peers. Likewise, it is possible that all peers will ++ * not fit within a single message. So, subsequent peers will be sent ++ * in following messages, except those will only contain WGDEVICE_A_IFNAME ++ * and WGDEVICE_A_PEERS. It is then up to the receiver to coalesce these ++ * messages to form the complete list of peers. ++ * ++ * Since this is an NLA_F_DUMP command, the final message will always be ++ * NLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message ++ * contains an integer error code. It is either zero or a negative error ++ * code corresponding to the errno. ++ * ++ * WG_CMD_SET_DEVICE ++ * ----------------- ++ * ++ * May only be called via NLM_F_REQUEST. The command should contain the ++ * following tree of nested items, containing one but not both of ++ * WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME: ++ * ++ * WGDEVICE_A_IFINDEX: NLA_U32 ++ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 ++ * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current ++ * peers should be removed prior to adding the list below. ++ * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove ++ * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly ++ * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable ++ * WGDEVICE_A_PEERS: NLA_NESTED ++ * 0: NLA_NESTED ++ * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN ++ * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the ++ * specified peer should be removed rather than ++ * added/updated and/or WGPEER_F_REPLACE_ALLOWEDIPS ++ * if all current allowed IPs of this peer should be ++ * removed prior to adding the list below. ++ * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove ++ * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 ++ * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable ++ * WGPEER_A_ALLOWEDIPS: NLA_NESTED ++ * 0: NLA_NESTED ++ * WGALLOWEDIP_A_FAMILY: NLA_U16 ++ * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr ++ * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 ++ * 0: NLA_NESTED ++ * ... ++ * 0: NLA_NESTED ++ * ... ++ * ... ++ * WGPEER_A_PROTOCOL_VERSION: NLA_U32, should not be set or used at ++ * all by most users of this API, as the ++ * most recent protocol will be used when ++ * this is unset. Otherwise, must be set ++ * to 1. ++ * 0: NLA_NESTED ++ * ... ++ * ... ++ * ++ * It is possible that the amount of configuration data exceeds that of ++ * the maximum message length accepted by the kernel. In that case, several ++ * messages should be sent one after another, with each successive one ++ * filling in information not contained in the prior. Note that if ++ * WGDEVICE_F_REPLACE_PEERS is specified in the first message, it probably ++ * should not be specified in fragments that come after, so that the list ++ * of peers is only cleared the first time but appened after. Likewise for ++ * peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the first message ++ * of a peer, it likely should not be specified in subsequent fragments. ++ * ++ * If an error occurs, NLMSG_ERROR will reply containing an errno. ++ */ ++ ++#ifndef _WG_UAPI_WIREGUARD_H ++#define _WG_UAPI_WIREGUARD_H ++ ++#define WG_GENL_NAME "wireguard" ++#define WG_GENL_VERSION 1 ++ ++#define WG_KEY_LEN 32 ++ ++enum wg_cmd { ++ WG_CMD_GET_DEVICE, ++ WG_CMD_SET_DEVICE, ++ __WG_CMD_MAX ++}; ++#define WG_CMD_MAX (__WG_CMD_MAX - 1) ++ ++enum wgdevice_flag { ++ WGDEVICE_F_REPLACE_PEERS = 1U << 0 ++}; ++enum wgdevice_attribute { ++ WGDEVICE_A_UNSPEC, ++ WGDEVICE_A_IFINDEX, ++ WGDEVICE_A_IFNAME, ++ WGDEVICE_A_PRIVATE_KEY, ++ WGDEVICE_A_PUBLIC_KEY, ++ WGDEVICE_A_FLAGS, ++ WGDEVICE_A_LISTEN_PORT, ++ WGDEVICE_A_FWMARK, ++ WGDEVICE_A_PEERS, ++ __WGDEVICE_A_LAST ++}; ++#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1) ++ ++enum wgpeer_flag { ++ WGPEER_F_REMOVE_ME = 1U << 0, ++ WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1 ++}; ++enum wgpeer_attribute { ++ WGPEER_A_UNSPEC, ++ WGPEER_A_PUBLIC_KEY, ++ WGPEER_A_PRESHARED_KEY, ++ WGPEER_A_FLAGS, ++ WGPEER_A_ENDPOINT, ++ WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, ++ WGPEER_A_LAST_HANDSHAKE_TIME, ++ WGPEER_A_RX_BYTES, ++ WGPEER_A_TX_BYTES, ++ WGPEER_A_ALLOWEDIPS, ++ WGPEER_A_PROTOCOL_VERSION, ++ __WGPEER_A_LAST ++}; ++#define WGPEER_A_MAX (__WGPEER_A_LAST - 1) ++ ++enum wgallowedip_attribute { ++ WGALLOWEDIP_A_UNSPEC, ++ WGALLOWEDIP_A_FAMILY, ++ WGALLOWEDIP_A_IPADDR, ++ WGALLOWEDIP_A_CIDR_MASK, ++ __WGALLOWEDIP_A_LAST ++}; ++#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) ++ ++#endif /* _WG_UAPI_WIREGUARD_H */ +diff --git a/src/basic/meson.build b/src/basic/meson.build +index 91e0df3d2f7..de1e42013de 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -84,6 +84,23 @@ basic_sources = files(''' + label.h + limits-util.c + limits-util.h ++ linux/btrfs.h ++ linux/btrfs_tree.h ++ linux/can/vxcan.h ++ linux/fib_rules.h ++ linux/fou.h ++ linux/if.h ++ linux/if_addr.h ++ linux/if_arp.h ++ linux/if_bonding.h ++ linux/if_bridge.h ++ linux/if_link.h ++ linux/if_tun.h ++ linux/if_tunnel.h ++ linux/libc-compat.h ++ linux/netlink.h ++ linux/rtnetlink.h ++ linux/wireguard.h + list.h + locale-util.c + locale-util.h +@@ -100,18 +117,10 @@ basic_sources = files(''' + mempool.h + missing.h + missing_audit.h +- missing_btrfs.h +- missing_btrfs_tree.h + missing_capability.h + missing_drm.h +- missing_ethtool.h + missing_fcntl.h +- missing_fib_rules.h +- missing_fou.h + missing_fs.h +- missing_if_bridge.h +- missing_if_link.h +- missing_if_tunnel.h + missing_input.h + missing_keyctl.h + missing_magic.h +@@ -128,7 +137,6 @@ basic_sources = files(''' + missing_syscall.h + missing_timerfd.h + missing_type.h +- missing_vxcan.h + mkdir-label.c + mkdir.c + mkdir.h +@@ -227,7 +235,6 @@ basic_sources = files(''' + + missing_audit_h = files('missing_audit.h') + missing_capability_h = files('missing_capability.h') +-missing_network_h = files('missing_network.h') + missing_socket_h = files('missing_socket.h') + + generate_af_list = find_program('generate-af-list.sh') +@@ -241,7 +248,7 @@ generate_arphrd_list = find_program('generate-arphrd-list.sh') + arphrd_list_txt = custom_target( + 'arphrd-list.txt', + output : 'arphrd-list.txt', +- command : [generate_arphrd_list, cpp, config_h, missing_network_h], ++ command : [generate_arphrd_list, cpp, config_h], + capture : true) + + generate_cap_list = find_program('generate-cap-list.sh') +diff --git a/src/basic/missing.h b/src/basic/missing.h +index 5067c8fd009..9ea4d9467cb 100644 +--- a/src/basic/missing.h ++++ b/src/basic/missing.h +@@ -4,7 +4,6 @@ + /* Missing glibc definitions to access certain kernel APIs */ + + #include "missing_audit.h" +-#include "missing_btrfs_tree.h" + #include "missing_capability.h" + #include "missing_drm.h" + #include "missing_fcntl.h" +diff --git a/src/basic/missing_btrfs.h b/src/basic/missing_btrfs.h +deleted file mode 100644 +index 34c382ff0b5..00000000000 +--- a/src/basic/missing_btrfs.h ++++ /dev/null +@@ -1,22 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-/* Old btrfs.h requires stddef.h to be included before btrfs.h */ +-#include +- +-#include +- +-/* linux@57254b6ebce4ceca02d9c8b615f6059c56c19238 (3.11) */ +-#ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT +-#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46) +-#endif +- +-/* linux@83288b60bf6668933689078973136e0c9d387b38 (4.7) */ +-#ifndef BTRFS_QGROUP_LIMIT_MAX_RFER +-#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) +-#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) +-#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) +-#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) +-#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) +-#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) +-#endif +diff --git a/src/basic/missing_btrfs_tree.h b/src/basic/missing_btrfs_tree.h +deleted file mode 100644 +index 555f90fe1b5..00000000000 +--- a/src/basic/missing_btrfs_tree.h ++++ /dev/null +@@ -1,109 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#include +- +-#include "missing_btrfs.h" +- +-/* linux@db6711600e27c885aed89751f04e727f3af26715 (4.7) */ +-#if HAVE_LINUX_BTRFS_TREE_H +-#include +-#else +-#define BTRFS_ROOT_TREE_OBJECTID 1 +-#define BTRFS_QUOTA_TREE_OBJECTID 8 +-#define BTRFS_FIRST_FREE_OBJECTID 256 +-#define BTRFS_LAST_FREE_OBJECTID -256ULL +- +-#define BTRFS_ROOT_ITEM_KEY 132 +-#define BTRFS_ROOT_BACKREF_KEY 144 +-#define BTRFS_QGROUP_STATUS_KEY 240 +-#define BTRFS_QGROUP_INFO_KEY 242 +-#define BTRFS_QGROUP_LIMIT_KEY 244 +-#define BTRFS_QGROUP_RELATION_KEY 246 +- +-struct btrfs_disk_key { +- __le64 objectid; +- __u8 type; +- __le64 offset; +-} __attribute__ ((__packed__)); +- +-struct btrfs_timespec { +- __le64 sec; +- __le32 nsec; +-} __attribute__ ((__packed__)); +- +-struct btrfs_inode_item { +- __le64 generation; +- __le64 transid; +- __le64 size; +- __le64 nbytes; +- __le64 block_group; +- __le32 nlink; +- __le32 uid; +- __le32 gid; +- __le32 mode; +- __le64 rdev; +- __le64 flags; +- __le64 sequence; +- __le64 reserved[4]; +- struct btrfs_timespec atime; +- struct btrfs_timespec ctime; +- struct btrfs_timespec mtime; +- struct btrfs_timespec otime; +-} __attribute__ ((__packed__)); +- +-#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) +- +-struct btrfs_root_item { +- struct btrfs_inode_item inode; +- __le64 generation; +- __le64 root_dirid; +- __le64 bytenr; +- __le64 byte_limit; +- __le64 bytes_used; +- __le64 last_snapshot; +- __le64 flags; +- __le32 refs; +- struct btrfs_disk_key drop_progress; +- __u8 drop_level; +- __u8 level; +- +- __le64 generation_v2; +- __u8 uuid[BTRFS_UUID_SIZE]; +- __u8 parent_uuid[BTRFS_UUID_SIZE]; +- __u8 received_uuid[BTRFS_UUID_SIZE]; +- __le64 ctransid; /* updated when an inode changes */ +- __le64 otransid; /* trans when created */ +- __le64 stransid; /* trans when sent. non-zero for received subvol */ +- __le64 rtransid; /* trans when received. non-zero for received subvol */ +- struct btrfs_timespec ctime; +- struct btrfs_timespec otime; +- struct btrfs_timespec stime; +- struct btrfs_timespec rtime; +- __le64 reserved[8]; /* for future */ +-} __attribute__ ((__packed__)); +- +-struct btrfs_root_ref { +- __le64 dirid; +- __le64 sequence; +- __le16 name_len; +-} __attribute__ ((__packed__)); +- +-#define BTRFS_QGROUP_LEVEL_SHIFT 48 +- +-struct btrfs_qgroup_info_item { +- __le64 generation; +- __le64 rfer; +- __le64 rfer_cmpr; +- __le64 excl; +- __le64 excl_cmpr; +-} __attribute__ ((__packed__)); +- +-struct btrfs_qgroup_limit_item { +- __le64 flags; +- __le64 max_rfer; +- __le64 max_excl; +- __le64 rsv_rfer; +- __le64 rsv_excl; +-} __attribute__ ((__packed__)); +-#endif +diff --git a/src/basic/missing_ethtool.h b/src/basic/missing_ethtool.h +deleted file mode 100644 +index 9ba929c6329..00000000000 +--- a/src/basic/missing_ethtool.h ++++ /dev/null +@@ -1,131 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#include +- +-/* Missing definitions in ethtool.h */ +- +-#if !HAVE_ETHTOOL_LINK_MODE_10baseT_Half_BIT /* linux@3f1ac7a700d039c61d8d8b99f28d605d489a60cf (4.6) */ +- +-#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */ +-#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */ +- +-struct ethtool_link_settings { +- __u32 cmd; +- __u32 speed; +- __u8 duplex; +- __u8 port; +- __u8 phy_address; +- __u8 autoneg; +- __u8 mdio_support; +- __u8 eth_tp_mdix; +- __u8 eth_tp_mdix_ctrl; +- __s8 link_mode_masks_nwords; +- __u8 transceiver; +- __u8 reserved1[3]; +- __u32 reserved[7]; +- __u32 link_mode_masks[0]; +- /* layout of link_mode_masks fields: +- * __u32 map_supported[link_mode_masks_nwords]; +- * __u32 map_advertising[link_mode_masks_nwords]; +- * __u32 map_lp_advertising[link_mode_masks_nwords]; +- */ +-}; +- +-enum ethtool_link_mode_bit_indices { +- ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, +- ETHTOOL_LINK_MODE_10baseT_Full_BIT = 1, +- ETHTOOL_LINK_MODE_100baseT_Half_BIT = 2, +- ETHTOOL_LINK_MODE_100baseT_Full_BIT = 3, +- ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 4, +- ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 5, +- ETHTOOL_LINK_MODE_Autoneg_BIT = 6, +- ETHTOOL_LINK_MODE_TP_BIT = 7, +- ETHTOOL_LINK_MODE_AUI_BIT = 8, +- ETHTOOL_LINK_MODE_MII_BIT = 9, +- ETHTOOL_LINK_MODE_FIBRE_BIT = 10, +- ETHTOOL_LINK_MODE_BNC_BIT = 11, +- ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 12, +- ETHTOOL_LINK_MODE_Pause_BIT = 13, +- ETHTOOL_LINK_MODE_Asym_Pause_BIT = 14, +- ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 15, +- ETHTOOL_LINK_MODE_Backplane_BIT = 16, +- ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 17, +- ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 18, +- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 19, +- ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 20, +- ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21, +- ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 22, +- ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 23, +- ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 24, +- ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 25, +- ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 26, +- ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 27, +- ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28, +- ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29, +- ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30, +- ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 31, +- ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 32, +- ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 33, +- ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34, +- ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35, +- ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 36, +- ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 37, +- ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 38, +- ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39, +- ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40, +- ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41, +- ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42, +- ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43, +- ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44, +- ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45, +- ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46, +- ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47, +- ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48, +- +- ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49, +- ETHTOOL_LINK_MODE_FEC_RS_BIT = 50, +- ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51, +- +- /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit +- * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_* +- * macro for bits > 31. The only way to use indices > 31 is to +- * use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. +- */ +- +- __ETHTOOL_LINK_MODE_LAST +- = ETHTOOL_LINK_MODE_FEC_BASER_BIT, +-}; +-#else +-#if !HAVE_ETHTOOL_LINK_MODE_25000baseCR_Full_BIT /* linux@3851112e4737cd52aaeda0ce8d084be9ee128106 (4.7) */ +-#define ETHTOOL_LINK_MODE_25000baseCR_Full_BIT 31 +-#define ETHTOOL_LINK_MODE_25000baseKR_Full_BIT 32 +-#define ETHTOOL_LINK_MODE_25000baseSR_Full_BIT 33 +-#define ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT 34 +-#define ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT 35 +-#define ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT 36 +-#define ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT 37 +-#define ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT 38 +-#define ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT 39 +-#endif +-#if !HAVE_ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT /* linux@89da45b8b5b2187734a11038b8593714f964ffd1 (4.8) */ +-#define ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT 40 +-#endif +-#if !HAVE_ETHTOOL_LINK_MODE_1000baseX_Full_BIT /* linux@5711a98221443aec54c4c81ee98c6ae46acccb65 (4.9) */ +-#define ETHTOOL_LINK_MODE_1000baseX_Full_BIT 41 +-#define ETHTOOL_LINK_MODE_10000baseCR_Full_BIT 42 +-#define ETHTOOL_LINK_MODE_10000baseSR_Full_BIT 43 +-#define ETHTOOL_LINK_MODE_10000baseLR_Full_BIT 44 +-#define ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT 45 +-#define ETHTOOL_LINK_MODE_10000baseER_Full_BIT 46 +-#endif +-#if !HAVE_ETHTOOL_LINK_MODE_2500baseT_Full_BIT /* linux@94842b4fc4d6b1691cfc86c6f5251f299d27f4ba (4.10) */ +-#define ETHTOOL_LINK_MODE_2500baseT_Full_BIT 47 +-#define ETHTOOL_LINK_MODE_5000baseT_Full_BIT 48 +-#endif +-#if !HAVE_ETHTOOL_LINK_MODE_FEC_NONE_BIT /* linux@1a5f3da20bd966220931239fbd31e6ac6ff42251 (4.14) */ +-#define ETHTOOL_LINK_MODE_FEC_NONE_BIT 49 +-#define ETHTOOL_LINK_MODE_FEC_RS_BIT 50 +-#define ETHTOOL_LINK_MODE_FEC_BASER_BIT 51 +-#endif +-#endif +diff --git a/src/basic/missing_fib_rules.h b/src/basic/missing_fib_rules.h +deleted file mode 100644 +index df120d7bcda..00000000000 +--- a/src/basic/missing_fib_rules.h ++++ /dev/null +@@ -1,45 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#include +- +-#if !HAVE_FRA_TUN_ID /* linux@e7030878fc8448492b6e5cecd574043f63271298 (4.3) */ +-#define FRA_TUN_ID 12 +-#endif +- +-#if !HAVE_FRA_SUPPRESS_PREFIXLEN /* linux@6ef94cfafba159d6b1a902ccb3349ac6a34ff6ad, 73f5698e77219bfc3ea1903759fe8e20ab5b285e (3.12) */ +-#define FRA_SUPPRESS_IFGROUP 13 +-#define FRA_SUPPRESS_PREFIXLEN 14 +-#endif +- +-#if !HAVE_FRA_PAD /* linux@b46f6ded906ef0be52a4881ba50a084aeca64d7e (4.7) */ +-#define FRA_PAD 18 +-#endif +- +-#if !HAVE_FRA_L3MDEV /* linux@96c63fa7393d0a346acfe5a91e0c7d4c7782641b (4.8) */ +-#define FRA_L3MDEV 19 +-#endif +- +-#if !HAVE_FRA_UID_RANGE /* linux@622ec2c9d52405973c9f1ca5116eb1c393adfc7d (4.10) */ +-#define FRA_UID_RANGE 20 +- +-struct fib_rule_uid_range { +- __u32 start; +- __u32 end; +-}; +-#endif +- +-#if !HAVE_FRA_DPORT_RANGE /* linux@1b71af6053af1bd2f849e9fda4f71c1e3f145dcf, bfff4862653bb96001ab57c1edd6d03f48e5f035 (4.17) */ +-#define FRA_PROTOCOL 21 +-#define FRA_IP_PROTO 22 +-#define FRA_SPORT_RANGE 23 +-#define FRA_DPORT_RANGE 24 +- +-#undef FRA_MAX +-#define FRA_MAX 24 +- +-struct fib_rule_port_range { +- __u16 start; +- __u16 end; +-}; +-#endif +diff --git a/src/basic/missing_fou.h b/src/basic/missing_fou.h +deleted file mode 100644 +index d8c743577cd..00000000000 +--- a/src/basic/missing_fou.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#if !HAVE_LINUX_FOU_H /* linux@23461551c00628c3f3fe9cf837bf53cf8f212b63 (3.18) */ +- +-#define FOU_GENL_NAME "fou" +-#define FOU_GENL_VERSION 0x1 +- +-enum { +- FOU_ATTR_UNSPEC, +- FOU_ATTR_PORT, /* u16 */ +- FOU_ATTR_AF, /* u8 */ +- FOU_ATTR_IPPROTO, /* u8 */ +- FOU_ATTR_TYPE, /* u8 */ +- FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ +- +- __FOU_ATTR_MAX, +-}; +- +-#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1) +- +-enum { +- FOU_CMD_UNSPEC, +- FOU_CMD_ADD, +- FOU_CMD_DEL, +- FOU_CMD_GET, +- +- __FOU_CMD_MAX, +-}; +- +-enum { +- FOU_ENCAP_UNSPEC, +- FOU_ENCAP_DIRECT, +- FOU_ENCAP_GUE, +-}; +- +-#define FOU_CMD_MAX (__FOU_CMD_MAX - 1) +- +-#else +- +-#if !HAVE_FOU_ATTR_REMCSUM_NOPARTIAL /* linux@fe881ef11cf0220f118816181930494d484c4883 (4.0) */ +-#define FOU_ATTR_REMCSUM_NOPARTIAL 5 +- +-#undef FOU_ATTR_MAX +-#define FOU_ATTR_MAX 5 +-#endif +- +-#if !HAVE_FOU_CMD_GET /* linux@7a6c8c34e5b71ac50e39588e20b39494a9e1d8e5 (4.1) */ +-#define FOU_CMD_GET 3 +- +-#undef FOU_CMD_MAX +-#define FOU_CMD_MAX 3 +-#endif +- +-#endif +diff --git a/src/basic/missing_if_bridge.h b/src/basic/missing_if_bridge.h +deleted file mode 100644 +index 9306062fc2c..00000000000 +--- a/src/basic/missing_if_bridge.h ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#if !HAVE_IFLA_BRIDGE_VLAN_TUNNEL_INFO /* linux@b3c7ef0adadc5768e0baa786213c6bd1ce521a77 (4.11) */ +-#define IFLA_BRIDGE_VLAN_TUNNEL_INFO 3 +- +-#undef IFLA_BRIDGE_MAX +-#define IFLA_BRIDGE_MAX 3 +-#endif +- +-#ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN +-#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ +-#endif +- +-#ifndef BRIDGE_VLAN_INFO_RANGE_END +-#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ +-#endif +- +-#ifndef BRIDGE_VLAN_INFO_BRENTRY +-#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */ +-#endif +diff --git a/src/basic/missing_if_link.h b/src/basic/missing_if_link.h +deleted file mode 100644 +index 761797f56a4..00000000000 +--- a/src/basic/missing_if_link.h ++++ /dev/null +@@ -1,393 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#if !HAVE_IFLA_INET6_ADDR_GEN_MODE /* linux@bc91b0f07ada5535427373a4e2050877bcc12218 (3.17) */ +-#define IFLA_INET6_ADDR_GEN_MODE 8 +- +-#undef IFLA_INET6_MAX +-#define IFLA_INET6_MAX 8 +- +-enum in6_addr_gen_mode { +- IN6_ADDR_GEN_MODE_EUI64, +- IN6_ADDR_GEN_MODE_NONE, +- IN6_ADDR_GEN_MODE_STABLE_PRIVACY, +- IN6_ADDR_GEN_MODE_RANDOM, +-}; +-#else +-#if !HAVE_IN6_ADDR_GEN_MODE_STABLE_PRIVACY /* linux@622c81d57b392cc9be836670eb464a4dfaa9adfe (4.1) */ +-#define IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 +-#endif +-#if !HAVE_IN6_ADDR_GEN_MODE_RANDOM /* linux@cc9da6cc4f56e05cc9e591459fe0192727ff58b3 (4.5) */ +-#define IN6_ADDR_GEN_MODE_RANDOM 3 +-#endif +-#endif /* !HAVE_IFLA_INET6_ADDR_GEN_MODE */ +- +-#if !HAVE_IFLA_IPVLAN_MODE /* linux@2ad7bf3638411cb547f2823df08166c13ab04269 (3.19) */ +-enum { +- IFLA_IPVLAN_UNSPEC, +- IFLA_IPVLAN_MODE, +- IFLA_IPVLAN_FLAGS, +- __IFLA_IPVLAN_MAX +-}; +-#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) +-enum ipvlan_mode { +- IPVLAN_MODE_L2 = 0, +- IPVLAN_MODE_L3, +- IPVLAN_MODE_L3S, +- IPVLAN_MODE_MAX +-}; +-#else +-#if !HAVE_IPVLAN_MODE_L3S /* linux@4fbae7d83c98c30efcf0a2a2ac55fbb75ef5a1a5 (4.9) */ +-#define IPVLAN_MODE_L3S 2 +-#define IPVLAN_MODE_MAX 3 +-#endif +-#if !HAVE_IFLA_IPVLAN_FLAGS /* linux@a190d04db93710ae166749055b6985397c6d13f5 (4.15) */ +-#define IFLA_IPVLAN_FLAGS 2 +- +-#undef IFLA_IPVLAN_MAX +-#define IFLA_IPVLAN_MAX 2 +-#endif +-#endif /* !HAVE_IFLA_IPVLAN_MODE */ +- +-/* linux@a190d04db93710ae166749055b6985397c6d13f5 (4.15) */ +-#ifndef IPVLAN_F_PRIVATE +-#define IPVLAN_F_PRIVATE 0x01 +-#endif +- +-/* linux@fe89aa6b250c1011ccf425fbb7998e96bd54263f (4.15) */ +-#ifndef IPVLAN_F_VEPA +-#define IPVLAN_F_VEPA 0x02 +-#endif +- +-#if !HAVE_IFLA_PHYS_PORT_ID /* linux@66cae9ed6bc46b8cc57a9693f99f69926f3cc7ef (3.12) */ +-#define IFLA_PHYS_PORT_ID 34 +-#endif +-#if !HAVE_IFLA_CARRIER_CHANGES /* linux@2d3b479df41a10e2f41f9259fcba775bd34de6e4 (3.15) */ +-#define IFLA_CARRIER_CHANGES 35 +-#endif +-#if !HAVE_IFLA_PHYS_SWITCH_ID /* linux@82f2841291cfaf4d225aa1766424280254d3e3b2 (3.19) */ +-#define IFLA_PHYS_SWITCH_ID 36 +-#endif +-#if !HAVE_IFLA_LINK_NETNSID /* linux@d37512a277dfb2cef8a578e25a3246f61399a55a (4.0) */ +-#define IFLA_LINK_NETNSID 37 +-#endif +-#if !HAVE_IFLA_PHYS_PORT_NAME /* linux@db24a9044ee191c397dcd1c6574f56d67d7c8df5 (4.1) */ +-#define IFLA_PHYS_PORT_NAME 38 +-#endif +-#if !HAVE_IFLA_PROTO_DOWN /* linux@88d6378bd6c096cb8440face3ae3f33d55a2e6e4 (4.3) */ +-#define IFLA_PROTO_DOWN 39 +-#endif +-#if !HAVE_IFLA_GSO_MAX_SIZE /* linux@c70ce028e834f8e51306217dbdbd441d851c64d3 (4.6) */ +-#define IFLA_GSO_MAX_SEGS 40 +-#define IFLA_GSO_MAX_SIZE 41 +-#endif +-#if !HAVE_IFLA_PAD /* linux@18402843bf88c2e9674e1a3a05c73b7d9b09ee05 (4.7) */ +-#define IFLA_PAD 42 +-#endif +-#if !HAVE_IFLA_XDP /* linux@d1fdd9138682e0f272beee0cb08b6328c5478b26 (4.8) */ +-#define IFLA_XDP 43 +-#endif +-#if !HAVE_IFLA_EVENT /* linux@3d3ea5af5c0b382bc9d9aed378fd814fb5d4a011 (4.13) */ +-#define IFLA_EVENT 44 +-#endif +-#if !HAVE_IFLA_IF_NETNSID /* linux@6621dd29eb9b5e6774ec7a9a75161352fdea47fc, 79e1ad148c844f5c8b9d76b36b26e3886dca95ae (4.15) */ +-#define IFLA_IF_NETNSID 45 +-#define IFLA_NEW_NETNSID 46 +-#endif +-#if !HAVE_IFLA_TARGET_NETNSID /* linux@19d8f1ad12fd746e60707a58d954980013c7a35a (4.20) */ +-#define IFLA_TARGET_NETNSID IFLA_IF_NETNSID +-#endif +-#if !HAVE_IFLA_NEW_IFINDEX /* linux@b2d3bcfa26a7a8de41f358a6cae8b848673b3c6e, 38e01b30563a5b5ade7b54e5d739d16a2b02fe82 (4.16) */ +-#define IFLA_CARRIER_UP_COUNT 47 +-#define IFLA_CARRIER_DOWN_COUNT 48 +-#define IFLA_NEW_IFINDEX 49 +-#endif +-#if !HAVE_IFLA_MAX_MTU /* linux@3e7a50ceb11ea75c27e944f1a01e478fd62a2d8d (4.19) */ +-#define IFLA_MIN_MTU 50 +-#define IFLA_MAX_MTU 51 +- +-#undef IFLA_MAX +-#define IFLA_MAX 51 +-#endif +- +-#if !HAVE_IFLA_BOND_MODE /* linux@90af231106c0b8d223c27d35464af95cb3d9cacf (3.13) */ +-#define IFLA_BOND_MODE 1 +-#endif +-#if !HAVE_IFLA_BOND_ACTIVE_SLAVE /* linux@ec76aa49855f6d6fea5e01de179fb57dd47c619d (3.13) */ +-#define IFLA_BOND_ACTIVE_SLAVE 2 +-#endif +-#if !HAVE_IFLA_BOND_AD_INFO /* linux@4ee7ac7526d4a9413cafa733d824edfe49fdcc46 (3.14) */ +-#define IFLA_BOND_MIIMON 3 +-#define IFLA_BOND_UPDELAY 4 +-#define IFLA_BOND_DOWNDELAY 5 +-#define IFLA_BOND_USE_CARRIER 6 +-#define IFLA_BOND_ARP_INTERVAL 7 +-#define IFLA_BOND_ARP_IP_TARGET 8 +-#define IFLA_BOND_ARP_VALIDATE 9 +-#define IFLA_BOND_ARP_ALL_TARGETS 10 +-#define IFLA_BOND_PRIMARY 11 +-#define IFLA_BOND_PRIMARY_RESELECT 12 +-#define IFLA_BOND_FAIL_OVER_MAC 13 +-#define IFLA_BOND_XMIT_HASH_POLICY 14 +-#define IFLA_BOND_RESEND_IGMP 15 +-#define IFLA_BOND_NUM_PEER_NOTIF 16 +-#define IFLA_BOND_ALL_SLAVES_ACTIVE 17 +-#define IFLA_BOND_MIN_LINKS 18 +-#define IFLA_BOND_LP_INTERVAL 19 +-#define IFLA_BOND_PACKETS_PER_SLAVE 20 +-#define IFLA_BOND_AD_LACP_RATE 21 +-#define IFLA_BOND_AD_SELECT 22 +-#define IFLA_BOND_AD_INFO 23 +-#endif +-#if !HAVE_IFLA_BOND_AD_ACTOR_SYSTEM /* linux@171a42c38c6e1a5a076d6276e94e55a0b5b7868c (4.2) */ +-#define IFLA_BOND_AD_ACTOR_SYS_PRIO 24 +-#define IFLA_BOND_AD_USER_PORT_KEY 25 +-#define IFLA_BOND_AD_ACTOR_SYSTEM 26 +-#endif +-#if !HAVE_IFLA_BOND_TLB_DYNAMIC_LB /* linux@0f7bffd9e512b77279bbce704fad3cb1d6887958 (4.3) */ +-#define IFLA_BOND_TLB_DYNAMIC_LB 27 +- +-#undef IFLA_BOND_MAX +-#define IFLA_BOND_MAX 27 +-#endif +- +-#if !HAVE_IFLA_VXLAN_UDP_ZERO_CSUM6_RX /* linux@359a0ea9875ef4f32c8425bbe1ae348e1fd2ed2a (3.16) */ +-#define IFLA_VXLAN_UDP_CSUM 18 +-#define IFLA_VXLAN_UDP_ZERO_CSUM6_TX 19 +-#define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20 +-#endif +-#if !HAVE_IFLA_VXLAN_REMCSUM_NOPARTIAL /* linux@dfd8645ea1bd91277f841e74c33e1f4dbbede808..0ace2ca89cbd6bcdf2b9d2df1fa0fa24ea9d1653 (4.0) */ +-#define IFLA_VXLAN_REMCSUM_TX 21 +-#define IFLA_VXLAN_REMCSUM_RX 22 +-#define IFLA_VXLAN_GBP 23 +-#define IFLA_VXLAN_REMCSUM_NOPARTIAL 24 +-#endif +-#if !HAVE_IFLA_VXLAN_COLLECT_METADATA /* linux@f8a9b1bc1b238eed9987da747a0e52f5bb009980 (4.3) */ +-#define IFLA_VXLAN_COLLECT_METADATA 25 +-#endif +-#if !HAVE_IFLA_VXLAN_LABEL /* linux@e7f70af111f086a20800ad2e17f544b2e3e0f375 (4.6) */ +-#define IFLA_VXLAN_LABEL 26 +-#endif +-#if !HAVE_IFLA_VXLAN_GPE /* linux@e1e5314de08ba6003b358125eafc9ad9e75a950c (4.7) */ +-#define IFLA_VXLAN_GPE 27 +-#endif +-#if !HAVE_IFLA_VXLAN_TTL_INHERIT /* linux@72f6d71e491e6ce269b564865b21fab0a4402dd3 (4.18) */ +-#define IFLA_VXLAN_TTL_INHERIT 28 +- +-#undef IFLA_VXLAN_MAX +-#define IFLA_VXLAN_MAX 28 +-#endif +- +-#if !HAVE_IFLA_GENEVE_TOS /* linux@2d07dc79fe04a43d82a346ced6bbf07bdb523f1b..d89511251f6519599b109dc6cda87a6ab314ed8c (4.2) */ +-enum { +- IFLA_GENEVE_UNSPEC, +- IFLA_GENEVE_ID, +- IFLA_GENEVE_REMOTE, +- IFLA_GENEVE_TTL, +- IFLA_GENEVE_TOS, +- IFLA_GENEVE_PORT, /* destination port */ +- IFLA_GENEVE_COLLECT_METADATA, +- IFLA_GENEVE_REMOTE6, +- IFLA_GENEVE_UDP_CSUM, +- IFLA_GENEVE_UDP_ZERO_CSUM6_TX, +- IFLA_GENEVE_UDP_ZERO_CSUM6_RX, +- IFLA_GENEVE_LABEL, +- IFLA_GENEVE_TTL_INHERIT, +- __IFLA_GENEVE_MAX +-}; +-#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) +-#else +-#if !HAVE_IFLA_GENEVE_COLLECT_METADATA /* linux@e305ac6cf5a1e1386aedce7ef9cb773635d5845c (4.3) */ +-#define IFLA_GENEVE_PORT 5 +-#define IFLA_GENEVE_COLLECT_METADATA 6 +-#endif +-#if !HAVE_IFLA_GENEVE_REMOTE6 /* linux@8ed66f0e8235118a31720acdab3bbbe9debd0f6a (4.4) */ +-#define IFLA_GENEVE_REMOTE6 7 +-#endif +-#if !HAVE_IFLA_GENEVE_UDP_ZERO_CSUM6_RX /* linux@abe492b4f50c3ae2ebcfaa2f5c16176aebaa1c68 (4.5) */ +-#define IFLA_GENEVE_UDP_CSUM 8 +-#define IFLA_GENEVE_UDP_ZERO_CSUM6_TX 9 +-#define IFLA_GENEVE_UDP_ZERO_CSUM6_RX 10 +-#endif +-#if !HAVE_IFLA_GENEVE_LABEL /* linux@8eb3b99554b82da968d1fbc00df9f3156c5e2d63 (4.6) */ +-#define IFLA_GENEVE_LABEL 11 +-#endif +-#if !HAVE_IFLA_GENEVE_TTL_INHERIT /* linux@52d0d404d39dd9eac71a181615d6ca15e23d8e38 (4.20) */ +-#define IFLA_GENEVE_TTL_INHERIT 12 +- +-#undef IFLA_GENEVE_MAX +-#define IFLA_GENEVE_MAX 12 +-#endif +-#endif +- +-#if !HAVE_IFLA_BR_MAX_AGE /* linux@e5c3ea5c668033b303e7ac835d7d91da32d97958 (3.18) */ +-enum { +- IFLA_BR_UNSPEC, +- IFLA_BR_FORWARD_DELAY, +- IFLA_BR_HELLO_TIME, +- IFLA_BR_MAX_AGE, +- IFLA_BR_AGEING_TIME, +- IFLA_BR_STP_STATE, +- IFLA_BR_PRIORITY, +- IFLA_BR_VLAN_FILTERING, +- IFLA_BR_VLAN_PROTOCOL, +- IFLA_BR_GROUP_FWD_MASK, +- IFLA_BR_ROOT_ID, +- IFLA_BR_BRIDGE_ID, +- IFLA_BR_ROOT_PORT, +- IFLA_BR_ROOT_PATH_COST, +- IFLA_BR_TOPOLOGY_CHANGE, +- IFLA_BR_TOPOLOGY_CHANGE_DETECTED, +- IFLA_BR_HELLO_TIMER, +- IFLA_BR_TCN_TIMER, +- IFLA_BR_TOPOLOGY_CHANGE_TIMER, +- IFLA_BR_GC_TIMER, +- IFLA_BR_GROUP_ADDR, +- IFLA_BR_FDB_FLUSH, +- IFLA_BR_MCAST_ROUTER, +- IFLA_BR_MCAST_SNOOPING, +- IFLA_BR_MCAST_QUERY_USE_IFADDR, +- IFLA_BR_MCAST_QUERIER, +- IFLA_BR_MCAST_HASH_ELASTICITY, +- IFLA_BR_MCAST_HASH_MAX, +- IFLA_BR_MCAST_LAST_MEMBER_CNT, +- IFLA_BR_MCAST_STARTUP_QUERY_CNT, +- IFLA_BR_MCAST_LAST_MEMBER_INTVL, +- IFLA_BR_MCAST_MEMBERSHIP_INTVL, +- IFLA_BR_MCAST_QUERIER_INTVL, +- IFLA_BR_MCAST_QUERY_INTVL, +- IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, +- IFLA_BR_MCAST_STARTUP_QUERY_INTVL, +- IFLA_BR_NF_CALL_IPTABLES, +- IFLA_BR_NF_CALL_IP6TABLES, +- IFLA_BR_NF_CALL_ARPTABLES, +- IFLA_BR_VLAN_DEFAULT_PVID, +- IFLA_BR_PAD, +- IFLA_BR_VLAN_STATS_ENABLED, +- IFLA_BR_MCAST_STATS_ENABLED, +- IFLA_BR_MCAST_IGMP_VERSION, +- IFLA_BR_MCAST_MLD_VERSION, +- IFLA_BR_VLAN_STATS_PER_PORT, +- __IFLA_BR_MAX, +-}; +- +-#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) +-#else +-#if !HAVE_IFLA_BR_PRIORITY /* linux@af615762e972be0c66cf1d156ca4fac13b93c0b0 (4.1) */ +-#define IFLA_BR_AGEING_TIME 4 +-#define IFLA_BR_STP_STATE 5 +-#define IFLA_BR_PRIORITY 6 +-#endif +-#if !HAVE_IFLA_BR_VLAN_PROTOCOL /* linux@a7854037da006a7472c48773e3190db55217ec9b, d2d427b3927bd7a0348fc7f323d0e291f79a2779 (4.3) */ +-#define IFLA_BR_VLAN_FILTERING 7 +-#define IFLA_BR_VLAN_PROTOCOL 8 +-#endif +-#if !HAVE_IFLA_BR_VLAN_DEFAULT_PVID /* linux@7910228b6bb35f3c8e0bc72a8d84c29616cb1b90..0f963b7592ef9e054974b6672b86ec1edd84b4bc (4.4) */ +-#define IFLA_BR_GROUP_FWD_MASK 9 +-#define IFLA_BR_ROOT_ID 10 +-#define IFLA_BR_BRIDGE_ID 11 +-#define IFLA_BR_ROOT_PORT 12 +-#define IFLA_BR_ROOT_PATH_COST 13 +-#define IFLA_BR_TOPOLOGY_CHANGE 14 +-#define IFLA_BR_TOPOLOGY_CHANGE_DETECTED 15 +-#define IFLA_BR_HELLO_TIMER 16 +-#define IFLA_BR_TCN_TIMER 17 +-#define IFLA_BR_TOPOLOGY_CHANGE_TIMER 18 +-#define IFLA_BR_GC_TIMER 19 +-#define IFLA_BR_GROUP_ADDR 20 +-#define IFLA_BR_FDB_FLUSH 21 +-#define IFLA_BR_MCAST_ROUTER 22 +-#define IFLA_BR_MCAST_SNOOPING 23 +-#define IFLA_BR_MCAST_QUERY_USE_IFADDR 24 +-#define IFLA_BR_MCAST_QUERIER 25 +-#define IFLA_BR_MCAST_HASH_ELASTICITY 26 +-#define IFLA_BR_MCAST_HASH_MAX 27 +-#define IFLA_BR_MCAST_LAST_MEMBER_CNT 28 +-#define IFLA_BR_MCAST_STARTUP_QUERY_CNT 29 +-#define IFLA_BR_MCAST_LAST_MEMBER_INTVL 30 +-#define IFLA_BR_MCAST_MEMBERSHIP_INTVL 31 +-#define IFLA_BR_MCAST_QUERIER_INTVL 32 +-#define IFLA_BR_MCAST_QUERY_INTVL 33 +-#define IFLA_BR_MCAST_QUERY_RESPONSE_INTVL 34 +-#define IFLA_BR_MCAST_STARTUP_QUERY_INTVL 35 +-#define IFLA_BR_NF_CALL_IPTABLES 36 +-#define IFLA_BR_NF_CALL_IP6TABLES 37 +-#define IFLA_BR_NF_CALL_ARPTABLES 38 +-#define IFLA_BR_VLAN_DEFAULT_PVID 39 +-#endif +-#if !HAVE_IFLA_BR_VLAN_STATS_ENABLED /* linux@12a0faa3bd76157b9dc096758d6818ff535e4586, 6dada9b10a0818ba72c249526a742c8c41274a73 (4.7) */ +-#define IFLA_BR_PAD 40 +-#define IFLA_BR_VLAN_STATS_ENABLED 41 +-#endif +-#if !HAVE_IFLA_BR_MCAST_STATS_ENABLED /* linux@1080ab95e3c7bdd77870e209aff83c763fdcf439 (4.8) */ +-#define IFLA_BR_MCAST_STATS_ENABLED 42 +-#endif +-#if !HAVE_IFLA_BR_MCAST_MLD_VERSION /* linux@5e9235853d652a295d5f56cb8652950b6b5bf56b, aa2ae3e71c74cc00ec22f133dc900b3817415785 (4.10) */ +-#define IFLA_BR_MCAST_IGMP_VERSION 43 +-#define IFLA_BR_MCAST_MLD_VERSION 44 +-#endif +-#if !HAVE_IFLA_BR_VLAN_STATS_PER_PORT /* linux@9163a0fc1f0c0980f117cc25f4fa6ba9b0750a36 (4.20) */ +-#define IFLA_BR_VLAN_STATS_PER_PORT 45 +- +-#undef IFLA_BR_MAX +-#define IFLA_BR_MAX 45 +-#endif +-#endif +- +-#if !HAVE_IFLA_BRPORT_LEARNING_SYNC /* linux@958501163ddd6ea22a98f94fa0e7ce6d4734e5c4, efacacdaf7cb5a0592ed772e3731636b2742e34a (3.19)*/ +-#define IFLA_BRPORT_PROXYARP 10 +-#define IFLA_BRPORT_LEARNING_SYNC 11 +-#endif +-#if !HAVE_IFLA_BRPORT_PROXYARP_WIFI /* linux@842a9ae08a25671db3d4f689eed68b4d64be15b5 (4.1) */ +-#define IFLA_BRPORT_PROXYARP_WIFI 12 +-#endif +-#if !HAVE_IFLA_BRPORT_MULTICAST_ROUTER /* linux@4ebc7660ab4559cad10b6595e05f70562bb26dc5..5d6ae479ab7ddf77bb22bdf739268581453ff886 (4.4) */ +-#define IFLA_BRPORT_ROOT_ID 13 +-#define IFLA_BRPORT_BRIDGE_ID 14 +-#define IFLA_BRPORT_DESIGNATED_PORT 15 +-#define IFLA_BRPORT_DESIGNATED_COST 16 +-#define IFLA_BRPORT_ID 17 +-#define IFLA_BRPORT_NO 18 +-#define IFLA_BRPORT_TOPOLOGY_CHANGE_ACK 19 +-#define IFLA_BRPORT_CONFIG_PENDING 20 +-#define IFLA_BRPORT_MESSAGE_AGE_TIMER 21 +-#define IFLA_BRPORT_FORWARD_DELAY_TIMER 22 +-#define IFLA_BRPORT_HOLD_TIMER 23 +-#define IFLA_BRPORT_FLUSH 24 +-#define IFLA_BRPORT_MULTICAST_ROUTER 25 +-#endif +-#if !HAVE_IFLA_BRPORT_PAD /* linux@12a0faa3bd76157b9dc096758d6818ff535e4586 (4.7) */ +-#define IFLA_BRPORT_PAD 26 +-#endif +-#if !HAVE_IFLA_BRPORT_MCAST_FLOOD /* linux@b6cb5ac8331b6bcfe9ce38c7f7f58db6e1d6270a (4.9) */ +-#define IFLA_BRPORT_MCAST_FLOOD 27 +-#endif +-#if !HAVE_IFLA_BRPORT_VLAN_TUNNEL /* linux@6db6f0eae6052b70885562e1733896647ec1d807, b3c7ef0adadc5768e0baa786213c6bd1ce521a77 (4.11) */ +-#define IFLA_BRPORT_MCAST_TO_UCAST 28 +-#define IFLA_BRPORT_VLAN_TUNNEL 29 +-#endif +-#if !HAVE_IFLA_BRPORT_BCAST_FLOOD /* linux@99f906e9ad7b6e79ffeda30f45906a8448b9d6a2 (4.12) */ +-#define IFLA_BRPORT_BCAST_FLOOD 30 +-#endif +-#if !HAVE_IFLA_BRPORT_NEIGH_SUPPRESS /* linux@5af48b59f35cf712793badabe1a574a0d0ce3bd3, 821f1b21cabb46827ce39ddf82e2789680b5042a (4.15) */ +-#define IFLA_BRPORT_GROUP_FWD_MASK 31 +-#define IFLA_BRPORT_NEIGH_SUPPRESS 32 +-#endif +-#if !HAVE_IFLA_BRPORT_ISOLATED /* linux@7d850abd5f4edb1b1ca4b4141a4453305736f564 (4.18) */ +-#define IFLA_BRPORT_ISOLATED 33 +-#endif +-#if !HAVE_IFLA_BRPORT_BACKUP_PORT /* linux@2756f68c314917d03eb348084edb08bb929139d9 (4.19) */ +-#define IFLA_BRPORT_BACKUP_PORT 34 +- +-#undef IFLA_BRPORT_MAX +-#define IFLA_BRPORT_MAX 34 +-#endif +- +-#if !HAVE_IFLA_VRF_TABLE /* linux@4e3c89920cd3a6cfce22c6f537690747c26128dd (4.3) */ +-enum { +- IFLA_VRF_UNSPEC, +- IFLA_VRF_TABLE, +- __IFLA_VRF_MAX +-}; +-#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) +-#endif +diff --git a/src/basic/missing_if_tunnel.h b/src/basic/missing_if_tunnel.h +deleted file mode 100644 +index f51fdd1ed78..00000000000 +--- a/src/basic/missing_if_tunnel.h ++++ /dev/null +@@ -1,59 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#if !HAVE_IFLA_VTI_FWMARK /* linux@0a473b82cb23e7a35c4be6e9765c8487a65e8f55 (4.12) */ +-#define IFLA_VTI_FWMARK 6 +- +-#undef IFLA_VTI_MAX +-#define IFLA_VTI_MAX 6 +-#endif +- +-#if !HAVE_IFLA_IPTUN_ENCAP_DPORT /* linux@56328486539ddd07cbaafec7a542a2c8a3043623 (3.18)*/ +-#define IFLA_IPTUN_ENCAP_TYPE 15 +-#define IFLA_IPTUN_ENCAP_FLAGS 16 +-#define IFLA_IPTUN_ENCAP_SPORT 17 +-#define IFLA_IPTUN_ENCAP_DPORT 18 +-#endif +- +-#if !HAVE_IFLA_IPTUN_COLLECT_METADATA /* linux@cfc7381b3002756b1dcada32979e942aa3126e31 (4.9) */ +-#define IFLA_IPTUN_COLLECT_METADATA 19 +-#endif +- +-#if !HAVE_IFLA_IPTUN_FWMARK /* linux@0a473b82cb23e7a35c4be6e9765c8487a65e8f55 (4.12) */ +-#define IFLA_IPTUN_FWMARK 20 +- +-#undef IFLA_IPTUN_MAX +-#define IFLA_IPTUN_MAX 20 +-#endif +- +-#if !HAVE_IFLA_GRE_ENCAP_DPORT /* linux@4565e9919cda747815547e2e5d7b78f15efbffdf (3.18) */ +-#define IFLA_GRE_ENCAP_TYPE 14 +-#define IFLA_GRE_ENCAP_FLAGS 15 +-#define IFLA_GRE_ENCAP_SPORT 16 +-#define IFLA_GRE_ENCAP_DPORT 17 +-#endif +- +-#if !HAVE_IFLA_GRE_COLLECT_METADATA /* linux@2e15ea390e6f4466655066d97e22ec66870a042c (4.3) */ +-#define IFLA_GRE_COLLECT_METADATA 18 +-#endif +- +-#if !HAVE_IFLA_GRE_IGNORE_DF /* linux@22a59be8b7693eb2d0897a9638f5991f2f8e4ddd (4.8) */ +-#define IFLA_GRE_IGNORE_DF 19 +-#endif +- +-#if !HAVE_IFLA_GRE_FWMARK /* linux@0a473b82cb23e7a35c4be6e9765c8487a65e8f55 (4.12) */ +-#define IFLA_GRE_FWMARK 20 +-#endif +- +-#if !HAVE_IFLA_GRE_ERSPAN_INDEX /* linux@84e54fe0a5eaed696dee4019c396f8396f5a908b (4.14) */ +-#define IFLA_GRE_ERSPAN_INDEX 21 +-#endif +- +-#if !HAVE_IFLA_GRE_ERSPAN_HWID /* linux@f551c91de262ba36b20c3ac19538afb4f4507441 (4.16) */ +-#define IFLA_GRE_ERSPAN_VER 22 +-#define IFLA_GRE_ERSPAN_DIR 23 +-#define IFLA_GRE_ERSPAN_HWID 24 +- +-#undef IFLA_GRE_MAX +-#define IFLA_GRE_MAX 24 +-#endif +diff --git a/src/basic/missing_network.h b/src/basic/missing_network.h +index 80ef13fd3ea..257879405c9 100644 +--- a/src/basic/missing_network.h ++++ b/src/basic/missing_network.h +@@ -1,158 +1,22 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + #pragma once + +-#include +-#include +-#include +- +-#include "missing_ethtool.h" +-#include "missing_fib_rules.h" +-#include "missing_fou.h" +-#include "missing_if_bridge.h" +-#include "missing_if_link.h" +-#include "missing_if_tunnel.h" +-#include "missing_vxcan.h" +- +-/* if.h */ +-/* The following two defines are actually available in the kernel headers for longer, but we define them here anyway, +- * since that makes it easier to use them in conjunction with the glibc net/if.h header which conflicts with +- * linux/if.h. */ +-#ifndef IF_OPER_UNKNOWN +-#define IF_OPER_UNKNOWN 0 +-#endif +- +-#ifndef IF_OPER_UP +-#define IF_OPER_UP 6 +-#endif +- +-#ifndef IFF_LOWER_UP +-#define IFF_LOWER_UP 0x10000 +-#endif +- +-#ifndef IFF_DORMANT +-#define IFF_DORMANT 0x20000 +-#endif +- +-/* if_addr.h */ +-#if !HAVE_IFA_FLAGS +-#define IFA_FLAGS 8 +-#endif +- +-#ifndef IFA_F_MANAGETEMPADDR +-#define IFA_F_MANAGETEMPADDR 0x100 +-#endif +- +-#ifndef IFA_F_NOPREFIXROUTE +-#define IFA_F_NOPREFIXROUTE 0x200 +-#endif +- +-#ifndef IFA_F_MCAUTOJOIN +-#define IFA_F_MCAUTOJOIN 0x400 +-#endif +- +-/* if_arp.h */ +-#ifndef ARPHRD_IP6GRE +-#define ARPHRD_IP6GRE 823 +-#endif +- +-/* if_bonding.h */ +-#ifndef BOND_XMIT_POLICY_ENCAP23 +-#define BOND_XMIT_POLICY_ENCAP23 3 +-#endif +- +-#ifndef BOND_XMIT_POLICY_ENCAP34 +-#define BOND_XMIT_POLICY_ENCAP34 4 +-#endif +- +-/* if_tun.h */ +-#ifndef IFF_MULTI_QUEUE +-#define IFF_MULTI_QUEUE 0x100 +-#endif +- +-/* in6.h */ ++/* linux/in6.h or netinet/in.h */ + #ifndef IPV6_UNICAST_IF + #define IPV6_UNICAST_IF 76 + #endif + +-/* ip.h */ ++/* Not exposed but defined at include/net/ip.h */ + #ifndef IPV4_MIN_MTU + #define IPV4_MIN_MTU 68 + #endif + +-/* ipv6.h */ ++/* linux/ipv6.h */ + #ifndef IPV6_MIN_MTU + #define IPV6_MIN_MTU 1280 + #endif + +-/* loop.h */ +-#if !HAVE_LO_FLAGS_PARTSCAN +-#define LO_FLAGS_PARTSCAN 8 +-#endif +- +-#ifndef LOOP_CTL_REMOVE +-#define LOOP_CTL_REMOVE 0x4C81 +-#endif +- +-#ifndef LOOP_CTL_GET_FREE +-#define LOOP_CTL_GET_FREE 0x4C82 +-#endif +- +-/* netdevice.h */ +-#ifndef NET_ADDR_PERM +-#define NET_ADDR_PERM 0 +-#endif +- +-#ifndef NET_ADDR_RANDOM +-#define NET_ADDR_RANDOM 1 +-#endif +- +-#ifndef NET_ADDR_STOLEN +-#define NET_ADDR_STOLEN 2 +-#endif +- +-#ifndef NET_ADDR_SET +-#define NET_ADDR_SET 3 +-#endif +- +-#ifndef NET_NAME_UNKNOWN +-#define NET_NAME_UNKNOWN 0 +-#endif +- +-#ifndef NET_NAME_ENUM +-#define NET_NAME_ENUM 1 +-#endif +- +-#ifndef NET_NAME_PREDICTABLE +-#define NET_NAME_PREDICTABLE 2 +-#endif +- +-#ifndef NET_NAME_USER +-#define NET_NAME_USER 3 +-#endif +- +-#ifndef NET_NAME_RENAMED +-#define NET_NAME_RENAMED 4 +-#endif +- +-/* netlink.h */ +-#ifndef NETLINK_LIST_MEMBERSHIPS /* b42be38b2778eda2237fc759e55e3b698b05b315 (4.2) */ +-#define NETLINK_LIST_MEMBERSHIPS 9 +-#endif +- +-/* rtnetlink.h */ +-#ifndef RTA_PREF +-#define RTA_PREF 20 +-#endif +- +-#ifndef RTAX_QUICKACK +-#define RTAX_QUICKACK 15 +-#endif +- +-#ifndef RTA_EXPIRES +-#define RTA_EXPIRES 23 +-#endif +- +-/* Note that LOOPBACK_IFINDEX is currently not exported by the ++/* Note that LOOPBACK_IFINDEX is currently not exposed by the + * kernel/glibc, but hardcoded internally by the kernel. However, as + * it is exported to userspace indirectly via rtnetlink and the + * ioctls, and made use of widely we define it here too, in a way that +diff --git a/src/basic/missing_vxcan.h b/src/basic/missing_vxcan.h +deleted file mode 100644 +index be430f708dd..00000000000 +--- a/src/basic/missing_vxcan.h ++++ /dev/null +@@ -1,12 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +-#pragma once +- +-#if !HAVE_LINUX_CAN_VXCAN_H /* linux@a8f820a380a2a06fc4fe1a54159067958f800929 (4.12) */ +-enum { +- VXCAN_INFO_UNSPEC, +- VXCAN_INFO_PEER, +- +- __VXCAN_INFO_MAX +-#define VXCAN_INFO_MAX (__VXCAN_INFO_MAX - 1) +-}; +-#endif +diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c +index 81e91fcb362..9750c4c6827 100644 +--- a/src/core/bpf-devices.c ++++ b/src/core/bpf-devices.c +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ +-#include ++#include + + #include "bpf-devices.h" + #include "bpf-program.h" +diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c +index 2ecce300da1..723c7b4b4e1 100644 +--- a/src/core/bpf-firewall.c ++++ b/src/core/bpf-firewall.c +@@ -4,7 +4,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c +index 8248ac0f5a5..0c67d1c68f5 100644 +--- a/src/libsystemd/sd-netlink/netlink-types.c ++++ b/src/libsystemd/sd-netlink/netlink-types.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -10,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -17,14 +19,7 @@ + #include + #include + #include +- +-#if HAVE_LINUX_FOU_H +-#include +-#endif +- +-#if HAVE_LINUX_CAN_VXCAN_H +-#include +-#endif ++#include + + #include "macro.h" + #include "missing.h" +@@ -32,7 +27,6 @@ + #include "sd-netlink.h" + #include "string-table.h" + #include "util.h" +-#include "wireguard-netlink.h" + + /* Maximum ARP IP target defined in kernel */ + #define BOND_MAX_ARP_TARGETS 16 +diff --git a/src/network/netdev/fou-tunnel.h b/src/network/netdev/fou-tunnel.h +index 0e3fd7dd766..51eeac41bd2 100644 +--- a/src/network/netdev/fou-tunnel.h ++++ b/src/network/netdev/fou-tunnel.h +@@ -1,12 +1,9 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + #pragma once + +-#if HAVE_LINUX_FOU_H + #include +-#endif + + #include "in-addr-util.h" +-#include "missing_fou.h" + #include "netdev/netdev.h" + + typedef enum FooOverUDPEncapType { +diff --git a/src/network/netdev/ipvlan.h b/src/network/netdev/ipvlan.h +index fb426d37e5d..78f09dbb2d5 100644 +--- a/src/network/netdev/ipvlan.h ++++ b/src/network/netdev/ipvlan.h +@@ -3,7 +3,6 @@ + + #include + +-#include "missing_if_link.h" + #include "netdev/netdev.h" + + typedef enum IPVlanMode { +diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c +index 719b5e4add5..84f6af8578f 100644 +--- a/src/network/netdev/tunnel.c ++++ b/src/network/netdev/tunnel.c +@@ -1,15 +1,11 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include +-#include ++#include + #include + #include + #include + +-#if HAVE_LINUX_FOU_H +-#include +-#endif +- + #include "sd-netlink.h" + + #include "conf-parser.h" +diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c +index e8ea70a1edc..c5dd5df51c5 100644 +--- a/src/network/netdev/vxcan.c ++++ b/src/network/netdev/vxcan.c +@@ -1,10 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#if HAVE_LINUX_CAN_VXCAN_H + #include +-#endif + +-#include "missing.h" + #include "netdev/vxcan.h" + + static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { +diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c +index 5aa10fc4dea..aa7d7be16e2 100644 +--- a/src/network/netdev/wireguard.c ++++ b/src/network/netdev/wireguard.c +@@ -23,7 +23,6 @@ + #include "resolve-private.h" + #include "string-util.h" + #include "strv.h" +-#include "wireguard-netlink.h" + #include "wireguard.h" + + static void resolve_endpoints(NetDev *netdev); +diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h +index 4ae520c52ba..862f2a99c4c 100644 +--- a/src/network/netdev/wireguard.h ++++ b/src/network/netdev/wireguard.h +@@ -2,10 +2,11 @@ + + typedef struct Wireguard Wireguard; + ++#include ++ + #include "in-addr-util.h" + #include "netdev.h" + #include "socket-util.h" +-#include "wireguard-netlink.h" + + typedef struct WireguardIPmask { + uint16_t family; +diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c +index 8377623da48..8f9103f1466 100644 +--- a/src/network/networkd-brvlan.c ++++ b/src/network/networkd-brvlan.c +@@ -9,7 +9,6 @@ + + #include "alloc-util.h" + #include "conf-parser.h" +-#include "missing_if_bridge.h" + #include "netlink-util.h" + #include "networkd-brvlan.h" + #include "networkd-link.h" +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 836776ae849..2c8896530a0 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -1,7 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include +-#include ++#include + + #include "alloc-util.h" + #include "conf-files.h" +@@ -10,7 +9,6 @@ + #include "fd-util.h" + #include "hostname-util.h" + #include "in-addr-util.h" +-#include "missing_network.h" + #include "network-internal.h" + #include "networkd-manager.h" + #include "networkd-network.h" +diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h +index e1bd78f8095..28699ba2369 100644 +--- a/src/network/networkd-routing-policy-rule.h ++++ b/src/network/networkd-routing-policy-rule.h +@@ -7,7 +7,6 @@ + + #include "in-addr-util.h" + #include "conf-parser.h" +-#include "missing_fib_rules.h" + + typedef struct RoutingPolicyRule RoutingPolicyRule; + +diff --git a/src/partition/growfs.c b/src/partition/growfs.c +index 60a310946d0..ce86f96e13d 100644 +--- a/src/partition/growfs.c ++++ b/src/partition/growfs.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c +index 44f70aceaa3..50f9309f105 100644 +--- a/src/resolve/resolved-link.c ++++ b/src/resolve/resolved-link.c +@@ -1,7 +1,9 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include ++#include + #include ++#include + + #include "sd-network.h" + +@@ -9,7 +11,6 @@ + #include "env-file.h" + #include "fd-util.h" + #include "fileio.h" +-#include "missing.h" + #include "mkdir.h" + #include "parse-util.h" + #include "resolved-link.h" +diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c +index ce210bfd436..ac2f7ceaf83 100644 +--- a/src/shared/dissect-image.c ++++ b/src/shared/dissect-image.c +@@ -1,5 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + ++#include ++#include + #include + #include + #include +@@ -25,7 +27,6 @@ + #include "hexdecoct.h" + #include "hostname-util.h" + #include "id128-util.h" +-#include "linux-3.13/dm-ioctl.h" + #include "missing.h" + #include "mount-util.h" + #include "mountpoint-util.h" +diff --git a/src/shared/linux/README b/src/shared/linux/README +new file mode 100644 +index 00000000000..34f90486bb8 +--- /dev/null ++++ b/src/shared/linux/README +@@ -0,0 +1,8 @@ ++The files in this directory are copied from kernel-5.0, and the following modifications are applied: ++- auto_dev-ioctl.h: set AUTOFS_DEV_IOCTL_VERSION_MINOR to 0 ++- auto_dev-ioctl.h: define AUTOFS_IOCTL if not defined ++- bpf_insn.h: This is imported from samples/bpf/bpf_insn.h ++- bpf_insn.h: BPF_JMP_A() macro is also imported from include/linux/filter.h ++- dm-ioctl.h: set DM_VERSION_MINOR to 27 ++- ethtool.h: add a type cast to SPEED_UNKNOWN ++- ethtool.h: define __KERNEL_DIV_ROUND_UP if not defined +diff --git a/src/shared/linux/auto_dev-ioctl.h b/src/shared/linux/auto_dev-ioctl.h +index d9838eba494..261546c667d 100644 +--- a/src/shared/linux/auto_dev-ioctl.h ++++ b/src/shared/linux/auto_dev-ioctl.h +@@ -1,31 +1,24 @@ +-/* SPDX-License-Identifier: GPL-2.0+ */ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ + /* +- * Copyright © 2008 Red Hat, Inc. All rights reserved. +- * Copyright © 2008 Ian Kent ++ * Copyright 2008 Red Hat, Inc. All rights reserved. ++ * Copyright 2008 Ian Kent + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + */ + +-#ifndef _LINUX_AUTO_DEV_IOCTL_H +-#define _LINUX_AUTO_DEV_IOCTL_H ++#ifndef _UAPI_LINUX_AUTO_DEV_IOCTL_H ++#define _UAPI_LINUX_AUTO_DEV_IOCTL_H + + #include +- +-#ifdef __KERNEL__ + #include +-#else +-#include +-#endif /* __KERNEL__ */ + + #define AUTOFS_DEVICE_NAME "autofs" + + #define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1 + #define AUTOFS_DEV_IOCTL_VERSION_MINOR 0 + +-#define AUTOFS_DEVID_LEN 16 +- + #define AUTOFS_DEV_IOCTL_SIZE sizeof(struct autofs_dev_ioctl) + + /* +@@ -119,19 +112,15 @@ struct autofs_dev_ioctl { + char path[0]; + }; + +-static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in) { +- memset(in, 0, sizeof(struct autofs_dev_ioctl)); ++static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in) ++{ ++ memset(in, 0, AUTOFS_DEV_IOCTL_SIZE); + in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR; + in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR; +- in->size = sizeof(struct autofs_dev_ioctl); ++ in->size = AUTOFS_DEV_IOCTL_SIZE; + in->ioctlfd = -1; +- return; + } + +-/* +- * If you change this make sure you make the corresponding change +- * to autofs-dev-ioctl.c:lookup_ioctl() +- */ + enum { + /* Get various version info */ + AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71, +@@ -168,7 +157,9 @@ enum { + AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, + }; + ++#ifndef AUTOFS_IOCTL + #define AUTOFS_IOCTL 0x93 ++#endif + + #define AUTOFS_DEV_IOCTL_VERSION \ + _IOWR(AUTOFS_IOCTL, \ +@@ -226,4 +217,4 @@ enum { + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl) + +-#endif /* _LINUX_AUTO_DEV_IOCTL_H */ ++#endif /* _UAPI_LINUX_AUTO_DEV_IOCTL_H */ +diff --git a/src/shared/linux/bpf.h b/src/shared/linux/bpf.h +index 1df9e7e3d06..91c43884f29 100644 +--- a/src/shared/linux/bpf.h ++++ b/src/shared/linux/bpf.h +@@ -44,106 +44,149 @@ + + /* Register numbers */ + enum { +- BPF_REG_0 = 0, +- BPF_REG_1, +- BPF_REG_2, +- BPF_REG_3, +- BPF_REG_4, +- BPF_REG_5, +- BPF_REG_6, +- BPF_REG_7, +- BPF_REG_8, +- BPF_REG_9, +- BPF_REG_10, +- __MAX_BPF_REG, ++ BPF_REG_0 = 0, ++ BPF_REG_1, ++ BPF_REG_2, ++ BPF_REG_3, ++ BPF_REG_4, ++ BPF_REG_5, ++ BPF_REG_6, ++ BPF_REG_7, ++ BPF_REG_8, ++ BPF_REG_9, ++ BPF_REG_10, ++ __MAX_BPF_REG, + }; + + /* BPF has 10 general purpose 64-bit registers and stack frame. */ + #define MAX_BPF_REG __MAX_BPF_REG + + struct bpf_insn { +- __u8 code; /* opcode */ +- __u8 dst_reg:4; /* dest register */ +- __u8 src_reg:4; /* source register */ +- __s16 off; /* signed offset */ +- __s32 imm; /* signed immediate constant */ ++ __u8 code; /* opcode */ ++ __u8 dst_reg:4; /* dest register */ ++ __u8 src_reg:4; /* source register */ ++ __s16 off; /* signed offset */ ++ __s32 imm; /* signed immediate constant */ + }; + + /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ + struct bpf_lpm_trie_key { +- __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ +- __u8 data[0]; /* Arbitrary size */ ++ __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ ++ __u8 data[0]; /* Arbitrary size */ ++}; ++ ++struct bpf_cgroup_storage_key { ++ __u64 cgroup_inode_id; /* cgroup inode id */ ++ __u32 attach_type; /* program attach type */ + }; + + /* BPF syscall commands, see bpf(2) man-page for details. */ + enum bpf_cmd { +- BPF_MAP_CREATE, +- BPF_MAP_LOOKUP_ELEM, +- BPF_MAP_UPDATE_ELEM, +- BPF_MAP_DELETE_ELEM, +- BPF_MAP_GET_NEXT_KEY, +- BPF_PROG_LOAD, +- BPF_OBJ_PIN, +- BPF_OBJ_GET, +- BPF_PROG_ATTACH, +- BPF_PROG_DETACH, +- BPF_PROG_TEST_RUN, +- BPF_PROG_GET_NEXT_ID, +- BPF_MAP_GET_NEXT_ID, +- BPF_PROG_GET_FD_BY_ID, +- BPF_MAP_GET_FD_BY_ID, +- BPF_OBJ_GET_INFO_BY_FD, +- BPF_PROG_QUERY, ++ BPF_MAP_CREATE, ++ BPF_MAP_LOOKUP_ELEM, ++ BPF_MAP_UPDATE_ELEM, ++ BPF_MAP_DELETE_ELEM, ++ BPF_MAP_GET_NEXT_KEY, ++ BPF_PROG_LOAD, ++ BPF_OBJ_PIN, ++ BPF_OBJ_GET, ++ BPF_PROG_ATTACH, ++ BPF_PROG_DETACH, ++ BPF_PROG_TEST_RUN, ++ BPF_PROG_GET_NEXT_ID, ++ BPF_MAP_GET_NEXT_ID, ++ BPF_PROG_GET_FD_BY_ID, ++ BPF_MAP_GET_FD_BY_ID, ++ BPF_OBJ_GET_INFO_BY_FD, ++ BPF_PROG_QUERY, ++ BPF_RAW_TRACEPOINT_OPEN, ++ BPF_BTF_LOAD, ++ BPF_BTF_GET_FD_BY_ID, ++ BPF_TASK_FD_QUERY, ++ BPF_MAP_LOOKUP_AND_DELETE_ELEM, + }; + + enum bpf_map_type { +- BPF_MAP_TYPE_UNSPEC, +- BPF_MAP_TYPE_HASH, +- BPF_MAP_TYPE_ARRAY, +- BPF_MAP_TYPE_PROG_ARRAY, +- BPF_MAP_TYPE_PERF_EVENT_ARRAY, +- BPF_MAP_TYPE_PERCPU_HASH, +- BPF_MAP_TYPE_PERCPU_ARRAY, +- BPF_MAP_TYPE_STACK_TRACE, +- BPF_MAP_TYPE_CGROUP_ARRAY, +- BPF_MAP_TYPE_LRU_HASH, +- BPF_MAP_TYPE_LRU_PERCPU_HASH, +- BPF_MAP_TYPE_LPM_TRIE, +- BPF_MAP_TYPE_ARRAY_OF_MAPS, +- BPF_MAP_TYPE_HASH_OF_MAPS, +- BPF_MAP_TYPE_DEVMAP, +- BPF_MAP_TYPE_SOCKMAP, +- BPF_MAP_TYPE_CPUMAP, ++ BPF_MAP_TYPE_UNSPEC, ++ BPF_MAP_TYPE_HASH, ++ BPF_MAP_TYPE_ARRAY, ++ BPF_MAP_TYPE_PROG_ARRAY, ++ BPF_MAP_TYPE_PERF_EVENT_ARRAY, ++ BPF_MAP_TYPE_PERCPU_HASH, ++ BPF_MAP_TYPE_PERCPU_ARRAY, ++ BPF_MAP_TYPE_STACK_TRACE, ++ BPF_MAP_TYPE_CGROUP_ARRAY, ++ BPF_MAP_TYPE_LRU_HASH, ++ BPF_MAP_TYPE_LRU_PERCPU_HASH, ++ BPF_MAP_TYPE_LPM_TRIE, ++ BPF_MAP_TYPE_ARRAY_OF_MAPS, ++ BPF_MAP_TYPE_HASH_OF_MAPS, ++ BPF_MAP_TYPE_DEVMAP, ++ BPF_MAP_TYPE_SOCKMAP, ++ BPF_MAP_TYPE_CPUMAP, ++ BPF_MAP_TYPE_XSKMAP, ++ BPF_MAP_TYPE_SOCKHASH, ++ BPF_MAP_TYPE_CGROUP_STORAGE, ++ BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, ++ BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, ++ BPF_MAP_TYPE_QUEUE, ++ BPF_MAP_TYPE_STACK, + }; + ++/* Note that tracing related programs such as ++ * BPF_PROG_TYPE_{KPROBE,TRACEPOINT,PERF_EVENT,RAW_TRACEPOINT} ++ * are not subject to a stable API since kernel internal data ++ * structures can change from release to release and may ++ * therefore break existing tracing BPF programs. Tracing BPF ++ * programs correspond to /a/ specific kernel which is to be ++ * analyzed, and not /a/ specific kernel /and/ all future ones. ++ */ + enum bpf_prog_type { +- BPF_PROG_TYPE_UNSPEC, +- BPF_PROG_TYPE_SOCKET_FILTER, +- BPF_PROG_TYPE_KPROBE, +- BPF_PROG_TYPE_SCHED_CLS, +- BPF_PROG_TYPE_SCHED_ACT, +- BPF_PROG_TYPE_TRACEPOINT, +- BPF_PROG_TYPE_XDP, +- BPF_PROG_TYPE_PERF_EVENT, +- BPF_PROG_TYPE_CGROUP_SKB, +- BPF_PROG_TYPE_CGROUP_SOCK, +- BPF_PROG_TYPE_LWT_IN, +- BPF_PROG_TYPE_LWT_OUT, +- BPF_PROG_TYPE_LWT_XMIT, +- BPF_PROG_TYPE_SOCK_OPS, +- BPF_PROG_TYPE_SK_SKB, +- BPF_PROG_TYPE_CGROUP_DEVICE, ++ BPF_PROG_TYPE_UNSPEC, ++ BPF_PROG_TYPE_SOCKET_FILTER, ++ BPF_PROG_TYPE_KPROBE, ++ BPF_PROG_TYPE_SCHED_CLS, ++ BPF_PROG_TYPE_SCHED_ACT, ++ BPF_PROG_TYPE_TRACEPOINT, ++ BPF_PROG_TYPE_XDP, ++ BPF_PROG_TYPE_PERF_EVENT, ++ BPF_PROG_TYPE_CGROUP_SKB, ++ BPF_PROG_TYPE_CGROUP_SOCK, ++ BPF_PROG_TYPE_LWT_IN, ++ BPF_PROG_TYPE_LWT_OUT, ++ BPF_PROG_TYPE_LWT_XMIT, ++ BPF_PROG_TYPE_SOCK_OPS, ++ BPF_PROG_TYPE_SK_SKB, ++ BPF_PROG_TYPE_CGROUP_DEVICE, ++ BPF_PROG_TYPE_SK_MSG, ++ BPF_PROG_TYPE_RAW_TRACEPOINT, ++ BPF_PROG_TYPE_CGROUP_SOCK_ADDR, ++ BPF_PROG_TYPE_LWT_SEG6LOCAL, ++ BPF_PROG_TYPE_LIRC_MODE2, ++ BPF_PROG_TYPE_SK_REUSEPORT, ++ BPF_PROG_TYPE_FLOW_DISSECTOR, + }; + + enum bpf_attach_type { +- BPF_CGROUP_INET_INGRESS, +- BPF_CGROUP_INET_EGRESS, +- BPF_CGROUP_INET_SOCK_CREATE, +- BPF_CGROUP_SOCK_OPS, +- BPF_SK_SKB_STREAM_PARSER, +- BPF_SK_SKB_STREAM_VERDICT, +- BPF_CGROUP_DEVICE, +- __MAX_BPF_ATTACH_TYPE ++ BPF_CGROUP_INET_INGRESS, ++ BPF_CGROUP_INET_EGRESS, ++ BPF_CGROUP_INET_SOCK_CREATE, ++ BPF_CGROUP_SOCK_OPS, ++ BPF_SK_SKB_STREAM_PARSER, ++ BPF_SK_SKB_STREAM_VERDICT, ++ BPF_CGROUP_DEVICE, ++ BPF_SK_MSG_VERDICT, ++ BPF_CGROUP_INET4_BIND, ++ BPF_CGROUP_INET6_BIND, ++ BPF_CGROUP_INET4_CONNECT, ++ BPF_CGROUP_INET6_CONNECT, ++ BPF_CGROUP_INET4_POST_BIND, ++ BPF_CGROUP_INET6_POST_BIND, ++ BPF_CGROUP_UDP4_SENDMSG, ++ BPF_CGROUP_UDP6_SENDMSG, ++ BPF_LIRC_MODE2, ++ BPF_FLOW_DISSECTOR, ++ __MAX_BPF_ATTACH_TYPE + }; + + #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE +@@ -197,6 +240,20 @@ enum bpf_attach_type { + */ + #define BPF_F_STRICT_ALIGNMENT (1U << 0) + ++/* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the ++ * verifier will allow any alignment whatsoever. On platforms ++ * with strict alignment requirements for loads ands stores (such ++ * as sparc and mips) the verifier validates that all loads and ++ * stores provably follow this requirement. This flag turns that ++ * checking and enforcement off. ++ * ++ * It is mostly used for testing when we want to validate the ++ * context and memory access aspects of the verifier, but because ++ * of an unaligned access the alignment check would trigger before ++ * the one we are interested in. ++ */ ++#define BPF_F_ANY_ALIGNMENT (1U << 1) ++ + /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ + #define BPF_PSEUDO_MAP_FD 1 + +@@ -222,550 +279,2157 @@ enum bpf_attach_type { + /* Specify numa node during map creation */ + #define BPF_F_NUMA_NODE (1U << 2) + +-/* flags for BPF_PROG_QUERY */ +-#define BPF_F_QUERY_EFFECTIVE (1U << 0) +- + #define BPF_OBJ_NAME_LEN 16U + + /* Flags for accessing BPF object */ + #define BPF_F_RDONLY (1U << 3) + #define BPF_F_WRONLY (1U << 4) + ++/* Flag for stack_map, store build_id+offset instead of pointer */ ++#define BPF_F_STACK_BUILD_ID (1U << 5) ++ ++/* Zero-initialize hash function seed. This should only be used for testing. */ ++#define BPF_F_ZERO_SEED (1U << 6) ++ ++/* flags for BPF_PROG_QUERY */ ++#define BPF_F_QUERY_EFFECTIVE (1U << 0) ++ ++enum bpf_stack_build_id_status { ++ /* user space need an empty entry to identify end of a trace */ ++ BPF_STACK_BUILD_ID_EMPTY = 0, ++ /* with valid build_id and offset */ ++ BPF_STACK_BUILD_ID_VALID = 1, ++ /* couldn't get build_id, fallback to ip */ ++ BPF_STACK_BUILD_ID_IP = 2, ++}; ++ ++#define BPF_BUILD_ID_SIZE 20 ++struct bpf_stack_build_id { ++ __s32 status; ++ unsigned char build_id[BPF_BUILD_ID_SIZE]; ++ union { ++ __u64 offset; ++ __u64 ip; ++ }; ++}; ++ + union bpf_attr { +- struct { /* anonymous struct used by BPF_MAP_CREATE command */ +- __u32 map_type; /* one of enum bpf_map_type */ +- __u32 key_size; /* size of key in bytes */ +- __u32 value_size; /* size of value in bytes */ +- __u32 max_entries; /* max number of entries in a map */ +- __u32 map_flags; /* BPF_MAP_CREATE related +- * flags defined above. +- */ +- __u32 inner_map_fd; /* fd pointing to the inner map */ +- __u32 numa_node; /* numa node (effective only if +- * BPF_F_NUMA_NODE is set). +- */ +- char map_name[BPF_OBJ_NAME_LEN]; +- __u32 map_ifindex; /* ifindex of netdev to create on */ +- }; +- +- struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ +- __u32 map_fd; +- __aligned_u64 key; +- union { +- __aligned_u64 value; +- __aligned_u64 next_key; +- }; +- __u64 flags; +- }; +- +- struct { /* anonymous struct used by BPF_PROG_LOAD command */ +- __u32 prog_type; /* one of enum bpf_prog_type */ +- __u32 insn_cnt; +- __aligned_u64 insns; +- __aligned_u64 license; +- __u32 log_level; /* verbosity level of verifier */ +- __u32 log_size; /* size of user buffer */ +- __aligned_u64 log_buf; /* user supplied buffer */ +- __u32 kern_version; /* checked when prog_type=kprobe */ +- __u32 prog_flags; +- char prog_name[BPF_OBJ_NAME_LEN]; +- __u32 prog_ifindex; /* ifindex of netdev to prep for */ +- }; +- +- struct { /* anonymous struct used by BPF_OBJ_* commands */ +- __aligned_u64 pathname; +- __u32 bpf_fd; +- __u32 file_flags; +- }; +- +- struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ +- __u32 target_fd; /* container object to attach to */ +- __u32 attach_bpf_fd; /* eBPF program to attach */ +- __u32 attach_type; +- __u32 attach_flags; +- }; +- +- struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ +- __u32 prog_fd; +- __u32 retval; +- __u32 data_size_in; +- __u32 data_size_out; +- __aligned_u64 data_in; +- __aligned_u64 data_out; +- __u32 repeat; +- __u32 duration; +- } test; +- +- struct { /* anonymous struct used by BPF_*_GET_*_ID */ +- union { +- __u32 start_id; +- __u32 prog_id; +- __u32 map_id; +- }; +- __u32 next_id; +- __u32 open_flags; +- }; +- +- struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ +- __u32 bpf_fd; +- __u32 info_len; +- __aligned_u64 info; +- } info; +- +- struct { /* anonymous struct used by BPF_PROG_QUERY command */ +- __u32 target_fd; /* container object to query */ +- __u32 attach_type; +- __u32 query_flags; +- __u32 attach_flags; +- __aligned_u64 prog_ids; +- __u32 prog_cnt; +- } query; ++ struct { /* anonymous struct used by BPF_MAP_CREATE command */ ++ __u32 map_type; /* one of enum bpf_map_type */ ++ __u32 key_size; /* size of key in bytes */ ++ __u32 value_size; /* size of value in bytes */ ++ __u32 max_entries; /* max number of entries in a map */ ++ __u32 map_flags; /* BPF_MAP_CREATE related ++ * flags defined above. ++ */ ++ __u32 inner_map_fd; /* fd pointing to the inner map */ ++ __u32 numa_node; /* numa node (effective only if ++ * BPF_F_NUMA_NODE is set). ++ */ ++ char map_name[BPF_OBJ_NAME_LEN]; ++ __u32 map_ifindex; /* ifindex of netdev to create on */ ++ __u32 btf_fd; /* fd pointing to a BTF type data */ ++ __u32 btf_key_type_id; /* BTF type_id of the key */ ++ __u32 btf_value_type_id; /* BTF type_id of the value */ ++ }; ++ ++ struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ ++ __u32 map_fd; ++ __aligned_u64 key; ++ union { ++ __aligned_u64 value; ++ __aligned_u64 next_key; ++ }; ++ __u64 flags; ++ }; ++ ++ struct { /* anonymous struct used by BPF_PROG_LOAD command */ ++ __u32 prog_type; /* one of enum bpf_prog_type */ ++ __u32 insn_cnt; ++ __aligned_u64 insns; ++ __aligned_u64 license; ++ __u32 log_level; /* verbosity level of verifier */ ++ __u32 log_size; /* size of user buffer */ ++ __aligned_u64 log_buf; /* user supplied buffer */ ++ __u32 kern_version; /* not used */ ++ __u32 prog_flags; ++ char prog_name[BPF_OBJ_NAME_LEN]; ++ __u32 prog_ifindex; /* ifindex of netdev to prep for */ ++ /* For some prog types expected attach type must be known at ++ * load time to verify attach type specific parts of prog ++ * (context accesses, allowed helpers, etc). ++ */ ++ __u32 expected_attach_type; ++ __u32 prog_btf_fd; /* fd pointing to BTF type data */ ++ __u32 func_info_rec_size; /* userspace bpf_func_info size */ ++ __aligned_u64 func_info; /* func info */ ++ __u32 func_info_cnt; /* number of bpf_func_info records */ ++ __u32 line_info_rec_size; /* userspace bpf_line_info size */ ++ __aligned_u64 line_info; /* line info */ ++ __u32 line_info_cnt; /* number of bpf_line_info records */ ++ }; ++ ++ struct { /* anonymous struct used by BPF_OBJ_* commands */ ++ __aligned_u64 pathname; ++ __u32 bpf_fd; ++ __u32 file_flags; ++ }; ++ ++ struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ ++ __u32 target_fd; /* container object to attach to */ ++ __u32 attach_bpf_fd; /* eBPF program to attach */ ++ __u32 attach_type; ++ __u32 attach_flags; ++ }; ++ ++ struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ ++ __u32 prog_fd; ++ __u32 retval; ++ __u32 data_size_in; /* input: len of data_in */ ++ __u32 data_size_out; /* input/output: len of data_out ++ * returns ENOSPC if data_out ++ * is too small. ++ */ ++ __aligned_u64 data_in; ++ __aligned_u64 data_out; ++ __u32 repeat; ++ __u32 duration; ++ } test; ++ ++ struct { /* anonymous struct used by BPF_*_GET_*_ID */ ++ union { ++ __u32 start_id; ++ __u32 prog_id; ++ __u32 map_id; ++ __u32 btf_id; ++ }; ++ __u32 next_id; ++ __u32 open_flags; ++ }; ++ ++ struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ ++ __u32 bpf_fd; ++ __u32 info_len; ++ __aligned_u64 info; ++ } info; ++ ++ struct { /* anonymous struct used by BPF_PROG_QUERY command */ ++ __u32 target_fd; /* container object to query */ ++ __u32 attach_type; ++ __u32 query_flags; ++ __u32 attach_flags; ++ __aligned_u64 prog_ids; ++ __u32 prog_cnt; ++ } query; ++ ++ struct { ++ __u64 name; ++ __u32 prog_fd; ++ } raw_tracepoint; ++ ++ struct { /* anonymous struct for BPF_BTF_LOAD */ ++ __aligned_u64 btf; ++ __aligned_u64 btf_log_buf; ++ __u32 btf_size; ++ __u32 btf_log_size; ++ __u32 btf_log_level; ++ }; ++ ++ struct { ++ __u32 pid; /* input: pid */ ++ __u32 fd; /* input: fd */ ++ __u32 flags; /* input: flags */ ++ __u32 buf_len; /* input/output: buf len */ ++ __aligned_u64 buf; /* input/output: ++ * tp_name for tracepoint ++ * symbol for kprobe ++ * filename for uprobe ++ */ ++ __u32 prog_id; /* output: prod_id */ ++ __u32 fd_type; /* output: BPF_FD_TYPE_* */ ++ __u64 probe_offset; /* output: probe_offset */ ++ __u64 probe_addr; /* output: probe_addr */ ++ } task_fd_query; + } __attribute__((aligned(8))); + +-/* BPF helper function descriptions: +- * +- * void *bpf_map_lookup_elem(&map, &key) +- * Return: Map value or NULL +- * +- * int bpf_map_update_elem(&map, &key, &value, flags) +- * Return: 0 on success or negative error +- * +- * int bpf_map_delete_elem(&map, &key) +- * Return: 0 on success or negative error +- * +- * int bpf_probe_read(void *dst, int size, void *src) +- * Return: 0 on success or negative error ++/* The description below is an attempt at providing documentation to eBPF ++ * developers about the multiple available eBPF helper functions. It can be ++ * parsed and used to produce a manual page. The workflow is the following, ++ * and requires the rst2man utility: ++ * ++ * $ ./scripts/bpf_helpers_doc.py \ ++ * --filename include/uapi/linux/bpf.h > /tmp/bpf-helpers.rst ++ * $ rst2man /tmp/bpf-helpers.rst > /tmp/bpf-helpers.7 ++ * $ man /tmp/bpf-helpers.7 ++ * ++ * Note that in order to produce this external documentation, some RST ++ * formatting is used in the descriptions to get "bold" and "italics" in ++ * manual pages. Also note that the few trailing white spaces are ++ * intentional, removing them would break paragraphs for rst2man. ++ * ++ * Start of BPF helper function descriptions: ++ * ++ * void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) ++ * Description ++ * Perform a lookup in *map* for an entry associated to *key*. ++ * Return ++ * Map value associated to *key*, or **NULL** if no entry was ++ * found. ++ * ++ * int bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags) ++ * Description ++ * Add or update the value of the entry associated to *key* in ++ * *map* with *value*. *flags* is one of: ++ * ++ * **BPF_NOEXIST** ++ * The entry for *key* must not exist in the map. ++ * **BPF_EXIST** ++ * The entry for *key* must already exist in the map. ++ * **BPF_ANY** ++ * No condition on the existence of the entry for *key*. ++ * ++ * Flag value **BPF_NOEXIST** cannot be used for maps of types ++ * **BPF_MAP_TYPE_ARRAY** or **BPF_MAP_TYPE_PERCPU_ARRAY** (all ++ * elements always exist), the helper would return an error. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_delete_elem(struct bpf_map *map, const void *key) ++ * Description ++ * Delete entry with *key* from *map*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) ++ * Description ++ * Push an element *value* in *map*. *flags* is one of: ++ * ++ * **BPF_EXIST** ++ * If the queue/stack is full, the oldest element is removed to ++ * make room for this. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read(void *dst, u32 size, const void *src) ++ * Description ++ * For tracing programs, safely attempt to read *size* bytes from ++ * address *src* and store the data in *dst*. ++ * Return ++ * 0 on success, or a negative error in case of failure. + * + * u64 bpf_ktime_get_ns(void) +- * Return: current ktime +- * +- * int bpf_trace_printk(const char *fmt, int fmt_size, ...) +- * Return: length of buffer written or negative error +- * +- * u32 bpf_prandom_u32(void) +- * Return: random value +- * +- * u32 bpf_raw_smp_processor_id(void) +- * Return: SMP processor ID +- * +- * int bpf_skb_store_bytes(skb, offset, from, len, flags) +- * store bytes into packet +- * @skb: pointer to skb +- * @offset: offset within packet from skb->mac_header +- * @from: pointer where to copy bytes from +- * @len: number of bytes to store into packet +- * @flags: bit 0 - if true, recompute skb->csum +- * other bits - reserved +- * Return: 0 on success or negative error +- * +- * int bpf_l3_csum_replace(skb, offset, from, to, flags) +- * recompute IP checksum +- * @skb: pointer to skb +- * @offset: offset within packet where IP checksum is located +- * @from: old value of header field +- * @to: new value of header field +- * @flags: bits 0-3 - size of header field +- * other bits - reserved +- * Return: 0 on success or negative error +- * +- * int bpf_l4_csum_replace(skb, offset, from, to, flags) +- * recompute TCP/UDP checksum +- * @skb: pointer to skb +- * @offset: offset within packet where TCP/UDP checksum is located +- * @from: old value of header field +- * @to: new value of header field +- * @flags: bits 0-3 - size of header field +- * bit 4 - is pseudo header +- * other bits - reserved +- * Return: 0 on success or negative error +- * +- * int bpf_tail_call(ctx, prog_array_map, index) +- * jump into another BPF program +- * @ctx: context pointer passed to next program +- * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY +- * @index: 32-bit index inside array that selects specific program to run +- * Return: 0 on success or negative error +- * +- * int bpf_clone_redirect(skb, ifindex, flags) +- * redirect to another netdev +- * @skb: pointer to skb +- * @ifindex: ifindex of the net device +- * @flags: bit 0 - if set, redirect to ingress instead of egress +- * other bits - reserved +- * Return: 0 on success or negative error ++ * Description ++ * Return the time elapsed since system boot, in nanoseconds. ++ * Return ++ * Current *ktime*. ++ * ++ * int bpf_trace_printk(const char *fmt, u32 fmt_size, ...) ++ * Description ++ * This helper is a "printk()-like" facility for debugging. It ++ * prints a message defined by format *fmt* (of size *fmt_size*) ++ * to file *\/sys/kernel/debug/tracing/trace* from DebugFS, if ++ * available. It can take up to three additional **u64** ++ * arguments (as an eBPF helpers, the total number of arguments is ++ * limited to five). ++ * ++ * Each time the helper is called, it appends a line to the trace. ++ * The format of the trace is customizable, and the exact output ++ * one will get depends on the options set in ++ * *\/sys/kernel/debug/tracing/trace_options* (see also the ++ * *README* file under the same directory). However, it usually ++ * defaults to something like: ++ * ++ * :: ++ * ++ * telnet-470 [001] .N.. 419421.045894: 0x00000001: ++ * ++ * In the above: ++ * ++ * * ``telnet`` is the name of the current task. ++ * * ``470`` is the PID of the current task. ++ * * ``001`` is the CPU number on which the task is ++ * running. ++ * * In ``.N..``, each character refers to a set of ++ * options (whether irqs are enabled, scheduling ++ * options, whether hard/softirqs are running, level of ++ * preempt_disabled respectively). **N** means that ++ * **TIF_NEED_RESCHED** and **PREEMPT_NEED_RESCHED** ++ * are set. ++ * * ``419421.045894`` is a timestamp. ++ * * ``0x00000001`` is a fake value used by BPF for the ++ * instruction pointer register. ++ * * ```` is the message formatted with ++ * *fmt*. ++ * ++ * The conversion specifiers supported by *fmt* are similar, but ++ * more limited than for printk(). They are **%d**, **%i**, ++ * **%u**, **%x**, **%ld**, **%li**, **%lu**, **%lx**, **%lld**, ++ * **%lli**, **%llu**, **%llx**, **%p**, **%s**. No modifier (size ++ * of field, padding with zeroes, etc.) is available, and the ++ * helper will return **-EINVAL** (but print nothing) if it ++ * encounters an unknown specifier. ++ * ++ * Also, note that **bpf_trace_printk**\ () is slow, and should ++ * only be used for debugging purposes. For this reason, a notice ++ * bloc (spanning several lines) is printed to kernel logs and ++ * states that the helper should not be used "for production use" ++ * the first time this helper is used (or more precisely, when ++ * **trace_printk**\ () buffers are allocated). For passing values ++ * to user space, perf events should be preferred. ++ * Return ++ * The number of bytes written to the buffer, or a negative error ++ * in case of failure. ++ * ++ * u32 bpf_get_prandom_u32(void) ++ * Description ++ * Get a pseudo-random number. ++ * ++ * From a security point of view, this helper uses its own ++ * pseudo-random internal state, and cannot be used to infer the ++ * seed of other random functions in the kernel. However, it is ++ * essential to note that the generator used by the helper is not ++ * cryptographically secure. ++ * Return ++ * A random 32-bit unsigned value. ++ * ++ * u32 bpf_get_smp_processor_id(void) ++ * Description ++ * Get the SMP (symmetric multiprocessing) processor id. Note that ++ * all programs run with preemption disabled, which means that the ++ * SMP processor id is stable during all the execution of the ++ * program. ++ * Return ++ * The SMP id of the processor running the program. ++ * ++ * int bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len, u64 flags) ++ * Description ++ * Store *len* bytes from address *from* into the packet ++ * associated to *skb*, at *offset*. *flags* are a combination of ++ * **BPF_F_RECOMPUTE_CSUM** (automatically recompute the ++ * checksum for the packet after storing the bytes) and ++ * **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\ ++ * **->swhash** and *skb*\ **->l4hash** to 0). ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_l3_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 size) ++ * Description ++ * Recompute the layer 3 (e.g. IP) checksum for the packet ++ * associated to *skb*. Computation is incremental, so the helper ++ * must know the former value of the header field that was ++ * modified (*from*), the new value of this field (*to*), and the ++ * number of bytes (2 or 4) for this field, stored in *size*. ++ * Alternatively, it is possible to store the difference between ++ * the previous and the new values of the header field in *to*, by ++ * setting *from* and *size* to 0. For both methods, *offset* ++ * indicates the location of the IP checksum within the packet. ++ * ++ * This helper works in combination with **bpf_csum_diff**\ (), ++ * which does not update the checksum in-place, but offers more ++ * flexibility and can handle sizes larger than 2 or 4 for the ++ * checksum to update. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_l4_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 flags) ++ * Description ++ * Recompute the layer 4 (e.g. TCP, UDP or ICMP) checksum for the ++ * packet associated to *skb*. Computation is incremental, so the ++ * helper must know the former value of the header field that was ++ * modified (*from*), the new value of this field (*to*), and the ++ * number of bytes (2 or 4) for this field, stored on the lowest ++ * four bits of *flags*. Alternatively, it is possible to store ++ * the difference between the previous and the new values of the ++ * header field in *to*, by setting *from* and the four lowest ++ * bits of *flags* to 0. For both methods, *offset* indicates the ++ * location of the IP checksum within the packet. In addition to ++ * the size of the field, *flags* can be added (bitwise OR) actual ++ * flags. With **BPF_F_MARK_MANGLED_0**, a null checksum is left ++ * untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and ++ * for updates resulting in a null checksum the value is set to ++ * **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates ++ * the checksum is to be computed against a pseudo-header. ++ * ++ * This helper works in combination with **bpf_csum_diff**\ (), ++ * which does not update the checksum in-place, but offers more ++ * flexibility and can handle sizes larger than 2 or 4 for the ++ * checksum to update. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_tail_call(void *ctx, struct bpf_map *prog_array_map, u32 index) ++ * Description ++ * This special helper is used to trigger a "tail call", or in ++ * other words, to jump into another eBPF program. The same stack ++ * frame is used (but values on stack and in registers for the ++ * caller are not accessible to the callee). This mechanism allows ++ * for program chaining, either for raising the maximum number of ++ * available eBPF instructions, or to execute given programs in ++ * conditional blocks. For security reasons, there is an upper ++ * limit to the number of successive tail calls that can be ++ * performed. ++ * ++ * Upon call of this helper, the program attempts to jump into a ++ * program referenced at index *index* in *prog_array_map*, a ++ * special map of type **BPF_MAP_TYPE_PROG_ARRAY**, and passes ++ * *ctx*, a pointer to the context. ++ * ++ * If the call succeeds, the kernel immediately runs the first ++ * instruction of the new program. This is not a function call, ++ * and it never returns to the previous program. If the call ++ * fails, then the helper has no effect, and the caller continues ++ * to run its subsequent instructions. A call can fail if the ++ * destination program for the jump does not exist (i.e. *index* ++ * is superior to the number of entries in *prog_array_map*), or ++ * if the maximum number of tail calls has been reached for this ++ * chain of programs. This limit is defined in the kernel by the ++ * macro **MAX_TAIL_CALL_CNT** (not accessible to user space), ++ * which is currently set to 32. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_clone_redirect(struct sk_buff *skb, u32 ifindex, u64 flags) ++ * Description ++ * Clone and redirect the packet associated to *skb* to another ++ * net device of index *ifindex*. Both ingress and egress ++ * interfaces can be used for redirection. The **BPF_F_INGRESS** ++ * value in *flags* is used to make the distinction (ingress path ++ * is selected if the flag is present, egress path otherwise). ++ * This is the only flag supported for now. ++ * ++ * In comparison with **bpf_redirect**\ () helper, ++ * **bpf_clone_redirect**\ () has the associated cost of ++ * duplicating the packet buffer, but this can be executed out of ++ * the eBPF program. Conversely, **bpf_redirect**\ () is more ++ * efficient, but it is handled through an action code where the ++ * redirection happens only after the eBPF program has returned. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. + * + * u64 bpf_get_current_pid_tgid(void) +- * Return: current->tgid << 32 | current->pid ++ * Return ++ * A 64-bit integer containing the current tgid and pid, and ++ * created as such: ++ * *current_task*\ **->tgid << 32 \|** ++ * *current_task*\ **->pid**. + * + * u64 bpf_get_current_uid_gid(void) +- * Return: current_gid << 32 | current_uid +- * +- * int bpf_get_current_comm(char *buf, int size_of_buf) +- * stores current->comm into buf +- * Return: 0 on success or negative error +- * +- * u32 bpf_get_cgroup_classid(skb) +- * retrieve a proc's classid +- * @skb: pointer to skb +- * Return: classid if != 0 +- * +- * int bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) +- * Return: 0 on success or negative error +- * +- * int bpf_skb_vlan_pop(skb) +- * Return: 0 on success or negative error +- * +- * int bpf_skb_get_tunnel_key(skb, key, size, flags) +- * int bpf_skb_set_tunnel_key(skb, key, size, flags) +- * retrieve or populate tunnel metadata +- * @skb: pointer to skb +- * @key: pointer to 'struct bpf_tunnel_key' +- * @size: size of 'struct bpf_tunnel_key' +- * @flags: room for future extensions +- * Return: 0 on success or negative error +- * +- * u64 bpf_perf_event_read(map, flags) +- * read perf event counter value +- * @map: pointer to perf_event_array map +- * @flags: index of event in the map or bitmask flags +- * Return: value of perf event counter read or error code +- * +- * int bpf_redirect(ifindex, flags) +- * redirect to another netdev +- * @ifindex: ifindex of the net device +- * @flags: +- * cls_bpf: +- * bit 0 - if set, redirect to ingress instead of egress +- * other bits - reserved +- * xdp_bpf: +- * all bits - reserved +- * Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error +- * xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error +- * int bpf_redirect_map(map, key, flags) +- * redirect to endpoint in map +- * @map: pointer to dev map +- * @key: index in map to lookup +- * @flags: -- +- * Return: XDP_REDIRECT on success or XDP_ABORT on error +- * +- * u32 bpf_get_route_realm(skb) +- * retrieve a dst's tclassid +- * @skb: pointer to skb +- * Return: realm if != 0 +- * +- * int bpf_perf_event_output(ctx, map, flags, data, size) +- * output perf raw sample +- * @ctx: struct pt_regs* +- * @map: pointer to perf_event_array map +- * @flags: index of event in the map or bitmask flags +- * @data: data on stack to be output as raw data +- * @size: size of data +- * Return: 0 on success or negative error +- * +- * int bpf_get_stackid(ctx, map, flags) +- * walk user or kernel stack and return id +- * @ctx: struct pt_regs* +- * @map: pointer to stack_trace map +- * @flags: bits 0-7 - numer of stack frames to skip +- * bit 8 - collect user stack instead of kernel +- * bit 9 - compare stacks by hash only +- * bit 10 - if two different stacks hash into the same stackid +- * discard old +- * other bits - reserved +- * Return: >= 0 stackid on success or negative error +- * +- * s64 bpf_csum_diff(from, from_size, to, to_size, seed) +- * calculate csum diff +- * @from: raw from buffer +- * @from_size: length of from buffer +- * @to: raw to buffer +- * @to_size: length of to buffer +- * @seed: optional seed +- * Return: csum result or negative error code +- * +- * int bpf_skb_get_tunnel_opt(skb, opt, size) +- * retrieve tunnel options metadata +- * @skb: pointer to skb +- * @opt: pointer to raw tunnel option data +- * @size: size of @opt +- * Return: option size +- * +- * int bpf_skb_set_tunnel_opt(skb, opt, size) +- * populate tunnel options metadata +- * @skb: pointer to skb +- * @opt: pointer to raw tunnel option data +- * @size: size of @opt +- * Return: 0 on success or negative error +- * +- * int bpf_skb_change_proto(skb, proto, flags) +- * Change protocol of the skb. Currently supported is v4 -> v6, +- * v6 -> v4 transitions. The helper will also resize the skb. eBPF +- * program is expected to fill the new headers via skb_store_bytes +- * and lX_csum_replace. +- * @skb: pointer to skb +- * @proto: new skb->protocol type +- * @flags: reserved +- * Return: 0 on success or negative error +- * +- * int bpf_skb_change_type(skb, type) +- * Change packet type of skb. +- * @skb: pointer to skb +- * @type: new skb->pkt_type type +- * Return: 0 on success or negative error +- * +- * int bpf_skb_under_cgroup(skb, map, index) +- * Check cgroup2 membership of skb +- * @skb: pointer to skb +- * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type +- * @index: index of the cgroup in the bpf_map +- * Return: +- * == 0 skb failed the cgroup2 descendant test +- * == 1 skb succeeded the cgroup2 descendant test +- * < 0 error +- * +- * u32 bpf_get_hash_recalc(skb) +- * Retrieve and possibly recalculate skb->hash. +- * @skb: pointer to skb +- * Return: hash ++ * Return ++ * A 64-bit integer containing the current GID and UID, and ++ * created as such: *current_gid* **<< 32 \|** *current_uid*. ++ * ++ * int bpf_get_current_comm(char *buf, u32 size_of_buf) ++ * Description ++ * Copy the **comm** attribute of the current task into *buf* of ++ * *size_of_buf*. The **comm** attribute contains the name of ++ * the executable (excluding the path) for the current task. The ++ * *size_of_buf* must be strictly positive. On success, the ++ * helper makes sure that the *buf* is NUL-terminated. On failure, ++ * it is filled with zeroes. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * u32 bpf_get_cgroup_classid(struct sk_buff *skb) ++ * Description ++ * Retrieve the classid for the current task, i.e. for the net_cls ++ * cgroup to which *skb* belongs. ++ * ++ * This helper can be used on TC egress path, but not on ingress. ++ * ++ * The net_cls cgroup provides an interface to tag network packets ++ * based on a user-provided identifier for all traffic coming from ++ * the tasks belonging to the related cgroup. See also the related ++ * kernel documentation, available from the Linux sources in file ++ * *Documentation/cgroup-v1/net_cls.txt*. ++ * ++ * The Linux kernel has two versions for cgroups: there are ++ * cgroups v1 and cgroups v2. Both are available to users, who can ++ * use a mixture of them, but note that the net_cls cgroup is for ++ * cgroup v1 only. This makes it incompatible with BPF programs ++ * run on cgroups, which is a cgroup-v2-only feature (a socket can ++ * only hold data for one version of cgroups at a time). ++ * ++ * This helper is only available is the kernel was compiled with ++ * the **CONFIG_CGROUP_NET_CLASSID** configuration option set to ++ * "**y**" or to "**m**". ++ * Return ++ * The classid, or 0 for the default unconfigured classid. ++ * ++ * int bpf_skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) ++ * Description ++ * Push a *vlan_tci* (VLAN tag control information) of protocol ++ * *vlan_proto* to the packet associated to *skb*, then update ++ * the checksum. Note that if *vlan_proto* is different from ++ * **ETH_P_8021Q** and **ETH_P_8021AD**, it is considered to ++ * be **ETH_P_8021Q**. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_vlan_pop(struct sk_buff *skb) ++ * Description ++ * Pop a VLAN header from the packet associated to *skb*. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_get_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags) ++ * Description ++ * Get tunnel metadata. This helper takes a pointer *key* to an ++ * empty **struct bpf_tunnel_key** of **size**, that will be ++ * filled with tunnel metadata for the packet associated to *skb*. ++ * The *flags* can be set to **BPF_F_TUNINFO_IPV6**, which ++ * indicates that the tunnel is based on IPv6 protocol instead of ++ * IPv4. ++ * ++ * The **struct bpf_tunnel_key** is an object that generalizes the ++ * principal parameters used by various tunneling protocols into a ++ * single struct. This way, it can be used to easily make a ++ * decision based on the contents of the encapsulation header, ++ * "summarized" in this struct. In particular, it holds the IP ++ * address of the remote end (IPv4 or IPv6, depending on the case) ++ * in *key*\ **->remote_ipv4** or *key*\ **->remote_ipv6**. Also, ++ * this struct exposes the *key*\ **->tunnel_id**, which is ++ * generally mapped to a VNI (Virtual Network Identifier), making ++ * it programmable together with the **bpf_skb_set_tunnel_key**\ ++ * () helper. ++ * ++ * Let's imagine that the following code is part of a program ++ * attached to the TC ingress interface, on one end of a GRE ++ * tunnel, and is supposed to filter out all messages coming from ++ * remote ends with IPv4 address other than 10.0.0.1: ++ * ++ * :: ++ * ++ * int ret; ++ * struct bpf_tunnel_key key = {}; ++ * ++ * ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); ++ * if (ret < 0) ++ * return TC_ACT_SHOT; // drop packet ++ * ++ * if (key.remote_ipv4 != 0x0a000001) ++ * return TC_ACT_SHOT; // drop packet ++ * ++ * return TC_ACT_OK; // accept packet ++ * ++ * This interface can also be used with all encapsulation devices ++ * that can operate in "collect metadata" mode: instead of having ++ * one network device per specific configuration, the "collect ++ * metadata" mode only requires a single device where the ++ * configuration can be extracted from this helper. ++ * ++ * This can be used together with various tunnels such as VXLan, ++ * Geneve, GRE or IP in IP (IPIP). ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_set_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags) ++ * Description ++ * Populate tunnel metadata for packet associated to *skb.* The ++ * tunnel metadata is set to the contents of *key*, of *size*. The ++ * *flags* can be set to a combination of the following values: ++ * ++ * **BPF_F_TUNINFO_IPV6** ++ * Indicate that the tunnel is based on IPv6 protocol ++ * instead of IPv4. ++ * **BPF_F_ZERO_CSUM_TX** ++ * For IPv4 packets, add a flag to tunnel metadata ++ * indicating that checksum computation should be skipped ++ * and checksum set to zeroes. ++ * **BPF_F_DONT_FRAGMENT** ++ * Add a flag to tunnel metadata indicating that the ++ * packet should not be fragmented. ++ * **BPF_F_SEQ_NUMBER** ++ * Add a flag to tunnel metadata indicating that a ++ * sequence number should be added to tunnel header before ++ * sending the packet. This flag was added for GRE ++ * encapsulation, but might be used with other protocols ++ * as well in the future. ++ * ++ * Here is a typical usage on the transmit path: ++ * ++ * :: ++ * ++ * struct bpf_tunnel_key key; ++ * populate key ... ++ * bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); ++ * bpf_clone_redirect(skb, vxlan_dev_ifindex, 0); ++ * ++ * See also the description of the **bpf_skb_get_tunnel_key**\ () ++ * helper for additional information. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * u64 bpf_perf_event_read(struct bpf_map *map, u64 flags) ++ * Description ++ * Read the value of a perf event counter. This helper relies on a ++ * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of ++ * the perf event counter is selected when *map* is updated with ++ * perf event file descriptors. The *map* is an array whose size ++ * is the number of available CPUs, and each cell contains a value ++ * relative to one CPU. The value to retrieve is indicated by ++ * *flags*, that contains the index of the CPU to look up, masked ++ * with **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to ++ * **BPF_F_CURRENT_CPU** to indicate that the value for the ++ * current CPU should be retrieved. ++ * ++ * Note that before Linux 4.13, only hardware perf event can be ++ * retrieved. ++ * ++ * Also, be aware that the newer helper ++ * **bpf_perf_event_read_value**\ () is recommended over ++ * **bpf_perf_event_read**\ () in general. The latter has some ABI ++ * quirks where error and counter value are used as a return code ++ * (which is wrong to do since ranges may overlap). This issue is ++ * fixed with **bpf_perf_event_read_value**\ (), which at the same ++ * time provides more features over the **bpf_perf_event_read**\ ++ * () interface. Please refer to the description of ++ * **bpf_perf_event_read_value**\ () for details. ++ * Return ++ * The value of the perf event counter read from the map, or a ++ * negative error code in case of failure. ++ * ++ * int bpf_redirect(u32 ifindex, u64 flags) ++ * Description ++ * Redirect the packet to another net device of index *ifindex*. ++ * This helper is somewhat similar to **bpf_clone_redirect**\ ++ * (), except that the packet is not cloned, which provides ++ * increased performance. ++ * ++ * Except for XDP, both ingress and egress interfaces can be used ++ * for redirection. The **BPF_F_INGRESS** value in *flags* is used ++ * to make the distinction (ingress path is selected if the flag ++ * is present, egress path otherwise). Currently, XDP only ++ * supports redirection to the egress interface, and accepts no ++ * flag at all. ++ * ++ * The same effect can be attained with the more generic ++ * **bpf_redirect_map**\ (), which requires specific maps to be ++ * used but offers better performance. ++ * Return ++ * For XDP, the helper returns **XDP_REDIRECT** on success or ++ * **XDP_ABORTED** on error. For other program types, the values ++ * are **TC_ACT_REDIRECT** on success or **TC_ACT_SHOT** on ++ * error. ++ * ++ * u32 bpf_get_route_realm(struct sk_buff *skb) ++ * Description ++ * Retrieve the realm or the route, that is to say the ++ * **tclassid** field of the destination for the *skb*. The ++ * indentifier retrieved is a user-provided tag, similar to the ++ * one used with the net_cls cgroup (see description for ++ * **bpf_get_cgroup_classid**\ () helper), but here this tag is ++ * held by a route (a destination entry), not by a task. ++ * ++ * Retrieving this identifier works with the clsact TC egress hook ++ * (see also **tc-bpf(8)**), or alternatively on conventional ++ * classful egress qdiscs, but not on TC ingress path. In case of ++ * clsact TC egress hook, this has the advantage that, internally, ++ * the destination entry has not been dropped yet in the transmit ++ * path. Therefore, the destination entry does not need to be ++ * artificially held via **netif_keep_dst**\ () for a classful ++ * qdisc until the *skb* is freed. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_IP_ROUTE_CLASSID** configuration option. ++ * Return ++ * The realm of the route for the packet associated to *skb*, or 0 ++ * if none was found. ++ * ++ * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) ++ * Description ++ * Write raw *data* blob into a special BPF perf event held by ++ * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf ++ * event must have the following attributes: **PERF_SAMPLE_RAW** ++ * as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and ++ * **PERF_COUNT_SW_BPF_OUTPUT** as **config**. ++ * ++ * The *flags* are used to indicate the index in *map* for which ++ * the value must be put, masked with **BPF_F_INDEX_MASK**. ++ * Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU** ++ * to indicate that the index of the current CPU core should be ++ * used. ++ * ++ * The value to write, of *size*, is passed through eBPF stack and ++ * pointed by *data*. ++ * ++ * The context of the program *ctx* needs also be passed to the ++ * helper. ++ * ++ * On user space, a program willing to read the values needs to ++ * call **perf_event_open**\ () on the perf event (either for ++ * one or for all CPUs) and to store the file descriptor into the ++ * *map*. This must be done before the eBPF program can send data ++ * into it. An example is available in file ++ * *samples/bpf/trace_output_user.c* in the Linux kernel source ++ * tree (the eBPF program counterpart is in ++ * *samples/bpf/trace_output_kern.c*). ++ * ++ * **bpf_perf_event_output**\ () achieves better performance ++ * than **bpf_trace_printk**\ () for sharing data with user ++ * space, and is much better suitable for streaming data from eBPF ++ * programs. ++ * ++ * Note that this helper is not restricted to tracing use cases ++ * and can be used with programs attached to TC or XDP as well, ++ * where it allows for passing data to user space listeners. Data ++ * can be: ++ * ++ * * Only custom structs, ++ * * Only the packet payload, or ++ * * A combination of both. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len) ++ * Description ++ * This helper was provided as an easy way to load data from a ++ * packet. It can be used to load *len* bytes from *offset* from ++ * the packet associated to *skb*, into the buffer pointed by ++ * *to*. ++ * ++ * Since Linux 4.7, usage of this helper has mostly been replaced ++ * by "direct packet access", enabling packet data to be ++ * manipulated with *skb*\ **->data** and *skb*\ **->data_end** ++ * pointing respectively to the first byte of packet data and to ++ * the byte after the last byte of packet data. However, it ++ * remains useful if one wishes to read large quantities of data ++ * at once from a packet into the eBPF stack. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) ++ * Description ++ * Walk a user or a kernel stack and return its id. To achieve ++ * this, the helper needs *ctx*, which is a pointer to the context ++ * on which the tracing program is executed, and a pointer to a ++ * *map* of type **BPF_MAP_TYPE_STACK_TRACE**. ++ * ++ * The last argument, *flags*, holds the number of stack frames to ++ * skip (from 0 to 255), masked with ++ * **BPF_F_SKIP_FIELD_MASK**. The next bits can be used to set ++ * a combination of the following flags: ++ * ++ * **BPF_F_USER_STACK** ++ * Collect a user space stack instead of a kernel stack. ++ * **BPF_F_FAST_STACK_CMP** ++ * Compare stacks by hash only. ++ * **BPF_F_REUSE_STACKID** ++ * If two different stacks hash into the same *stackid*, ++ * discard the old one. ++ * ++ * The stack id retrieved is a 32 bit long integer handle which ++ * can be further combined with other data (including other stack ++ * ids) and used as a key into maps. This can be useful for ++ * generating a variety of graphs (such as flame graphs or off-cpu ++ * graphs). ++ * ++ * For walking a stack, this helper is an improvement over ++ * **bpf_probe_read**\ (), which can be used with unrolled loops ++ * but is not efficient and consumes a lot of eBPF instructions. ++ * Instead, **bpf_get_stackid**\ () can collect up to ++ * **PERF_MAX_STACK_DEPTH** both kernel and user frames. Note that ++ * this limit can be controlled with the **sysctl** program, and ++ * that it should be manually increased in order to profile long ++ * user stacks (such as stacks for Java programs). To do so, use: ++ * ++ * :: ++ * ++ * # sysctl kernel.perf_event_max_stack= ++ * Return ++ * The positive or null stack id on success, or a negative error ++ * in case of failure. ++ * ++ * s64 bpf_csum_diff(__be32 *from, u32 from_size, __be32 *to, u32 to_size, __wsum seed) ++ * Description ++ * Compute a checksum difference, from the raw buffer pointed by ++ * *from*, of length *from_size* (that must be a multiple of 4), ++ * towards the raw buffer pointed by *to*, of size *to_size* ++ * (same remark). An optional *seed* can be added to the value ++ * (this can be cascaded, the seed may come from a previous call ++ * to the helper). ++ * ++ * This is flexible enough to be used in several ways: ++ * ++ * * With *from_size* == 0, *to_size* > 0 and *seed* set to ++ * checksum, it can be used when pushing new data. ++ * * With *from_size* > 0, *to_size* == 0 and *seed* set to ++ * checksum, it can be used when removing data from a packet. ++ * * With *from_size* > 0, *to_size* > 0 and *seed* set to 0, it ++ * can be used to compute a diff. Note that *from_size* and ++ * *to_size* do not need to be equal. ++ * ++ * This helper can be used in combination with ++ * **bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\ (), to ++ * which one can feed in the difference computed with ++ * **bpf_csum_diff**\ (). ++ * Return ++ * The checksum result, or a negative error code in case of ++ * failure. ++ * ++ * int bpf_skb_get_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size) ++ * Description ++ * Retrieve tunnel options metadata for the packet associated to ++ * *skb*, and store the raw tunnel option data to the buffer *opt* ++ * of *size*. ++ * ++ * This helper can be used with encapsulation devices that can ++ * operate in "collect metadata" mode (please refer to the related ++ * note in the description of **bpf_skb_get_tunnel_key**\ () for ++ * more details). A particular example where this can be used is ++ * in combination with the Geneve encapsulation protocol, where it ++ * allows for pushing (with **bpf_skb_get_tunnel_opt**\ () helper) ++ * and retrieving arbitrary TLVs (Type-Length-Value headers) from ++ * the eBPF program. This allows for full customization of these ++ * headers. ++ * Return ++ * The size of the option data retrieved. ++ * ++ * int bpf_skb_set_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size) ++ * Description ++ * Set tunnel options metadata for the packet associated to *skb* ++ * to the option data contained in the raw buffer *opt* of *size*. ++ * ++ * See also the description of the **bpf_skb_get_tunnel_opt**\ () ++ * helper for additional information. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_change_proto(struct sk_buff *skb, __be16 proto, u64 flags) ++ * Description ++ * Change the protocol of the *skb* to *proto*. Currently ++ * supported are transition from IPv4 to IPv6, and from IPv6 to ++ * IPv4. The helper takes care of the groundwork for the ++ * transition, including resizing the socket buffer. The eBPF ++ * program is expected to fill the new headers, if any, via ++ * **skb_store_bytes**\ () and to recompute the checksums with ++ * **bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\ ++ * (). The main case for this helper is to perform NAT64 ++ * operations out of an eBPF program. ++ * ++ * Internally, the GSO type is marked as dodgy so that headers are ++ * checked and segments are recalculated by the GSO/GRO engine. ++ * The size for GSO target is adapted as well. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_change_type(struct sk_buff *skb, u32 type) ++ * Description ++ * Change the packet type for the packet associated to *skb*. This ++ * comes down to setting *skb*\ **->pkt_type** to *type*, except ++ * the eBPF program does not have a write access to *skb*\ ++ * **->pkt_type** beside this helper. Using a helper here allows ++ * for graceful handling of errors. ++ * ++ * The major use case is to change incoming *skb*s to ++ * **PACKET_HOST** in a programmatic way instead of having to ++ * recirculate via **redirect**\ (..., **BPF_F_INGRESS**), for ++ * example. ++ * ++ * Note that *type* only allows certain values. At this time, they ++ * are: ++ * ++ * **PACKET_HOST** ++ * Packet is for us. ++ * **PACKET_BROADCAST** ++ * Send packet to all. ++ * **PACKET_MULTICAST** ++ * Send packet to group. ++ * **PACKET_OTHERHOST** ++ * Send packet to someone else. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_under_cgroup(struct sk_buff *skb, struct bpf_map *map, u32 index) ++ * Description ++ * Check whether *skb* is a descendant of the cgroup2 held by ++ * *map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*. ++ * Return ++ * The return value depends on the result of the test, and can be: ++ * ++ * * 0, if the *skb* failed the cgroup2 descendant test. ++ * * 1, if the *skb* succeeded the cgroup2 descendant test. ++ * * A negative error code, if an error occurred. ++ * ++ * u32 bpf_get_hash_recalc(struct sk_buff *skb) ++ * Description ++ * Retrieve the hash of the packet, *skb*\ **->hash**. If it is ++ * not set, in particular if the hash was cleared due to mangling, ++ * recompute this hash. Later accesses to the hash can be done ++ * directly with *skb*\ **->hash**. ++ * ++ * Calling **bpf_set_hash_invalid**\ (), changing a packet ++ * prototype with **bpf_skb_change_proto**\ (), or calling ++ * **bpf_skb_store_bytes**\ () with the ++ * **BPF_F_INVALIDATE_HASH** are actions susceptible to clear ++ * the hash and to trigger a new computation for the next call to ++ * **bpf_get_hash_recalc**\ (). ++ * Return ++ * The 32-bit hash. + * + * u64 bpf_get_current_task(void) +- * Returns current task_struct +- * Return: current +- * +- * int bpf_probe_write_user(void *dst, void *src, int len) +- * safely attempt to write to a location +- * @dst: destination address in userspace +- * @src: source address on stack +- * @len: number of bytes to copy +- * Return: 0 on success or negative error +- * +- * int bpf_current_task_under_cgroup(map, index) +- * Check cgroup2 membership of current task +- * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type +- * @index: index of the cgroup in the bpf_map +- * Return: +- * == 0 current failed the cgroup2 descendant test +- * == 1 current succeeded the cgroup2 descendant test +- * < 0 error +- * +- * int bpf_skb_change_tail(skb, len, flags) +- * The helper will resize the skb to the given new size, to be used f.e. +- * with control messages. +- * @skb: pointer to skb +- * @len: new skb length +- * @flags: reserved +- * Return: 0 on success or negative error +- * +- * int bpf_skb_pull_data(skb, len) +- * The helper will pull in non-linear data in case the skb is non-linear +- * and not all of len are part of the linear section. Only needed for +- * read/write with direct packet access. +- * @skb: pointer to skb +- * @len: len to make read/writeable +- * Return: 0 on success or negative error +- * +- * s64 bpf_csum_update(skb, csum) +- * Adds csum into skb->csum in case of CHECKSUM_COMPLETE. +- * @skb: pointer to skb +- * @csum: csum to add +- * Return: csum on success or negative error +- * +- * void bpf_set_hash_invalid(skb) +- * Invalidate current skb->hash. +- * @skb: pointer to skb +- * +- * int bpf_get_numa_node_id() +- * Return: Id of current NUMA node. +- * +- * int bpf_skb_change_head() +- * Grows headroom of skb and adjusts MAC header offset accordingly. +- * Will extends/reallocae as required automatically. +- * May change skb data pointer and will thus invalidate any check +- * performed for direct packet access. +- * @skb: pointer to skb +- * @len: length of header to be pushed in front +- * @flags: Flags (unused for now) +- * Return: 0 on success or negative error +- * +- * int bpf_xdp_adjust_head(xdp_md, delta) +- * Adjust the xdp_md.data by delta +- * @xdp_md: pointer to xdp_md +- * @delta: An positive/negative integer to be added to xdp_md.data +- * Return: 0 on success or negative on error ++ * Return ++ * A pointer to the current task struct. ++ * ++ * int bpf_probe_write_user(void *dst, const void *src, u32 len) ++ * Description ++ * Attempt in a safe way to write *len* bytes from the buffer ++ * *src* to *dst* in memory. It only works for threads that are in ++ * user context, and *dst* must be a valid user space address. ++ * ++ * This helper should not be used to implement any kind of ++ * security mechanism because of TOC-TOU attacks, but rather to ++ * debug, divert, and manipulate execution of semi-cooperative ++ * processes. ++ * ++ * Keep in mind that this feature is meant for experiments, and it ++ * has a risk of crashing the system and running programs. ++ * Therefore, when an eBPF program using this helper is attached, ++ * a warning including PID and process name is printed to kernel ++ * logs. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_current_task_under_cgroup(struct bpf_map *map, u32 index) ++ * Description ++ * Check whether the probe is being run is the context of a given ++ * subset of the cgroup2 hierarchy. The cgroup2 to test is held by ++ * *map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*. ++ * Return ++ * The return value depends on the result of the test, and can be: ++ * ++ * * 0, if the *skb* task belongs to the cgroup2. ++ * * 1, if the *skb* task does not belong to the cgroup2. ++ * * A negative error code, if an error occurred. ++ * ++ * int bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags) ++ * Description ++ * Resize (trim or grow) the packet associated to *skb* to the ++ * new *len*. The *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * The basic idea is that the helper performs the needed work to ++ * change the size of the packet, then the eBPF program rewrites ++ * the rest via helpers like **bpf_skb_store_bytes**\ (), ++ * **bpf_l3_csum_replace**\ (), **bpf_l3_csum_replace**\ () ++ * and others. This helper is a slow path utility intended for ++ * replies with control messages. And because it is targeted for ++ * slow path, the helper itself can afford to be slow: it ++ * implicitly linearizes, unclones and drops offloads from the ++ * *skb*. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_pull_data(struct sk_buff *skb, u32 len) ++ * Description ++ * Pull in non-linear data in case the *skb* is non-linear and not ++ * all of *len* are part of the linear section. Make *len* bytes ++ * from *skb* readable and writable. If a zero value is passed for ++ * *len*, then the whole length of the *skb* is pulled. ++ * ++ * This helper is only needed for reading and writing with direct ++ * packet access. ++ * ++ * For direct packet access, testing that offsets to access ++ * are within packet boundaries (test on *skb*\ **->data_end**) is ++ * susceptible to fail if offsets are invalid, or if the requested ++ * data is in non-linear parts of the *skb*. On failure the ++ * program can just bail out, or in the case of a non-linear ++ * buffer, use a helper to make the data available. The ++ * **bpf_skb_load_bytes**\ () helper is a first solution to access ++ * the data. Another one consists in using **bpf_skb_pull_data** ++ * to pull in once the non-linear parts, then retesting and ++ * eventually access the data. ++ * ++ * At the same time, this also makes sure the *skb* is uncloned, ++ * which is a necessary condition for direct write. As this needs ++ * to be an invariant for the write part only, the verifier ++ * detects writes and adds a prologue that is calling ++ * **bpf_skb_pull_data()** to effectively unclone the *skb* from ++ * the very beginning in case it is indeed cloned. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * s64 bpf_csum_update(struct sk_buff *skb, __wsum csum) ++ * Description ++ * Add the checksum *csum* into *skb*\ **->csum** in case the ++ * driver has supplied a checksum for the entire packet into that ++ * field. Return an error otherwise. This helper is intended to be ++ * used in combination with **bpf_csum_diff**\ (), in particular ++ * when the checksum needs to be updated after data has been ++ * written into the packet through direct packet access. ++ * Return ++ * The checksum on success, or a negative error code in case of ++ * failure. ++ * ++ * void bpf_set_hash_invalid(struct sk_buff *skb) ++ * Description ++ * Invalidate the current *skb*\ **->hash**. It can be used after ++ * mangling on headers through direct packet access, in order to ++ * indicate that the hash is outdated and to trigger a ++ * recalculation the next time the kernel tries to access this ++ * hash or when the **bpf_get_hash_recalc**\ () helper is called. ++ * ++ * int bpf_get_numa_node_id(void) ++ * Description ++ * Return the id of the current NUMA node. The primary use case ++ * for this helper is the selection of sockets for the local NUMA ++ * node, when the program is attached to sockets using the ++ * **SO_ATTACH_REUSEPORT_EBPF** option (see also **socket(7)**), ++ * but the helper is also available to other eBPF program types, ++ * similarly to **bpf_get_smp_processor_id**\ (). ++ * Return ++ * The id of current NUMA node. ++ * ++ * int bpf_skb_change_head(struct sk_buff *skb, u32 len, u64 flags) ++ * Description ++ * Grows headroom of packet associated to *skb* and adjusts the ++ * offset of the MAC header accordingly, adding *len* bytes of ++ * space. It automatically extends and reallocates memory as ++ * required. ++ * ++ * This helper can be used on a layer 3 *skb* to push a MAC header ++ * for redirection into a layer 2 device. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_xdp_adjust_head(struct xdp_buff *xdp_md, int delta) ++ * Description ++ * Adjust (move) *xdp_md*\ **->data** by *delta* bytes. Note that ++ * it is possible to use a negative value for *delta*. This helper ++ * can be used to prepare the packet for pushing or popping ++ * headers. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. + * + * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) +- * Copy a NUL terminated string from unsafe address. In case the string +- * length is smaller than size, the target is not padded with further NUL +- * bytes. In case the string length is larger than size, just count-1 +- * bytes are copied and the last byte is set to NUL. +- * @dst: destination address +- * @size: maximum number of bytes to copy, including the trailing NUL +- * @unsafe_ptr: unsafe address +- * Return: +- * > 0 length of the string including the trailing NUL on success +- * < 0 error +- * +- * u64 bpf_get_socket_cookie(skb) +- * Get the cookie for the socket stored inside sk_buff. +- * @skb: pointer to skb +- * Return: 8 Bytes non-decreasing number on success or 0 if the socket +- * field is missing inside sk_buff +- * +- * u32 bpf_get_socket_uid(skb) +- * Get the owner uid of the socket stored inside sk_buff. +- * @skb: pointer to skb +- * Return: uid of the socket owner on success or overflowuid if failed. +- * +- * u32 bpf_set_hash(skb, hash) +- * Set full skb->hash. +- * @skb: pointer to skb +- * @hash: hash to set +- * +- * int bpf_setsockopt(bpf_socket, level, optname, optval, optlen) +- * Calls setsockopt. Not all opts are available, only those with +- * integer optvals plus TCP_CONGESTION. +- * Supported levels: SOL_SOCKET and IPPROTO_TCP +- * @bpf_socket: pointer to bpf_socket +- * @level: SOL_SOCKET or IPPROTO_TCP +- * @optname: option name +- * @optval: pointer to option value +- * @optlen: length of optval in bytes +- * Return: 0 or negative error +- * +- * int bpf_getsockopt(bpf_socket, level, optname, optval, optlen) +- * Calls getsockopt. Not all opts are available. +- * Supported levels: IPPROTO_TCP +- * @bpf_socket: pointer to bpf_socket +- * @level: IPPROTO_TCP +- * @optname: option name +- * @optval: pointer to option value +- * @optlen: length of optval in bytes +- * Return: 0 or negative error +- * +- * int bpf_sock_ops_cb_flags_set(bpf_sock_ops, flags) +- * Set callback flags for sock_ops +- * @bpf_sock_ops: pointer to bpf_sock_ops_kern struct +- * @flags: flags value +- * Return: 0 for no error +- * -EINVAL if there is no full tcp socket +- * bits in flags that are not supported by current kernel +- * +- * int bpf_skb_adjust_room(skb, len_diff, mode, flags) +- * Grow or shrink room in sk_buff. +- * @skb: pointer to skb +- * @len_diff: (signed) amount of room to grow/shrink +- * @mode: operation mode (enum bpf_adj_room_mode) +- * @flags: reserved for future use +- * Return: 0 on success or negative error code +- * +- * int bpf_sk_redirect_map(map, key, flags) +- * Redirect skb to a sock in map using key as a lookup key for the +- * sock in map. +- * @map: pointer to sockmap +- * @key: key to lookup sock in map +- * @flags: reserved for future use +- * Return: SK_PASS +- * +- * int bpf_sock_map_update(skops, map, key, flags) +- * @skops: pointer to bpf_sock_ops +- * @map: pointer to sockmap to update +- * @key: key to insert/update sock in map +- * @flags: same flags as map update elem +- * +- * int bpf_xdp_adjust_meta(xdp_md, delta) +- * Adjust the xdp_md.data_meta by delta +- * @xdp_md: pointer to xdp_md +- * @delta: An positive/negative integer to be added to xdp_md.data_meta +- * Return: 0 on success or negative on error +- * +- * int bpf_perf_event_read_value(map, flags, buf, buf_size) +- * read perf event counter value and perf event enabled/running time +- * @map: pointer to perf_event_array map +- * @flags: index of event in the map or bitmask flags +- * @buf: buf to fill +- * @buf_size: size of the buf +- * Return: 0 on success or negative error code +- * +- * int bpf_perf_prog_read_value(ctx, buf, buf_size) +- * read perf prog attached perf event counter and enabled/running time +- * @ctx: pointer to ctx +- * @buf: buf to fill +- * @buf_size: size of the buf +- * Return : 0 on success or negative error code +- * +- * int bpf_override_return(pt_regs, rc) +- * @pt_regs: pointer to struct pt_regs +- * @rc: the return value to set ++ * Description ++ * Copy a NUL terminated string from an unsafe address ++ * *unsafe_ptr* to *dst*. The *size* should include the ++ * terminating NUL byte. In case the string length is smaller than ++ * *size*, the target is not padded with further NUL bytes. If the ++ * string length is larger than *size*, just *size*-1 bytes are ++ * copied and the last byte is set to NUL. ++ * ++ * On success, the length of the copied string is returned. This ++ * makes this helper useful in tracing programs for reading ++ * strings, and more importantly to get its length at runtime. See ++ * the following snippet: ++ * ++ * :: ++ * ++ * SEC("kprobe/sys_open") ++ * void bpf_sys_open(struct pt_regs *ctx) ++ * { ++ * char buf[PATHLEN]; // PATHLEN is defined to 256 ++ * int res = bpf_probe_read_str(buf, sizeof(buf), ++ * ctx->di); ++ * ++ * // Consume buf, for example push it to ++ * // userspace via bpf_perf_event_output(); we ++ * // can use res (the string length) as event ++ * // size, after checking its boundaries. ++ * } ++ * ++ * In comparison, using **bpf_probe_read()** helper here instead ++ * to read the string would require to estimate the length at ++ * compile time, and would often result in copying more memory ++ * than necessary. ++ * ++ * Another useful use case is when parsing individual process ++ * arguments or individual environment variables navigating ++ * *current*\ **->mm->arg_start** and *current*\ ++ * **->mm->env_start**: using this helper and the return value, ++ * one can quickly iterate at the right offset of the memory area. ++ * Return ++ * On success, the strictly positive length of the string, ++ * including the trailing NUL character. On error, a negative ++ * value. ++ * ++ * u64 bpf_get_socket_cookie(struct sk_buff *skb) ++ * Description ++ * If the **struct sk_buff** pointed by *skb* has a known socket, ++ * retrieve the cookie (generated by the kernel) of this socket. ++ * If no cookie has been set yet, generate a new cookie. Once ++ * generated, the socket cookie remains stable for the life of the ++ * socket. This helper can be useful for monitoring per socket ++ * networking traffic statistics as it provides a unique socket ++ * identifier per namespace. ++ * Return ++ * A 8-byte long non-decreasing number on success, or 0 if the ++ * socket field is missing inside *skb*. ++ * ++ * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) ++ * Description ++ * Equivalent to bpf_get_socket_cookie() helper that accepts ++ * *skb*, but gets socket from **struct bpf_sock_addr** contex. ++ * Return ++ * A 8-byte long non-decreasing number. ++ * ++ * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) ++ * Description ++ * Equivalent to bpf_get_socket_cookie() helper that accepts ++ * *skb*, but gets socket from **struct bpf_sock_ops** contex. ++ * Return ++ * A 8-byte long non-decreasing number. ++ * ++ * u32 bpf_get_socket_uid(struct sk_buff *skb) ++ * Return ++ * The owner UID of the socket associated to *skb*. If the socket ++ * is **NULL**, or if it is not a full socket (i.e. if it is a ++ * time-wait or a request socket instead), **overflowuid** value ++ * is returned (note that **overflowuid** might also be the actual ++ * UID value for the socket). ++ * ++ * u32 bpf_set_hash(struct sk_buff *skb, u32 hash) ++ * Description ++ * Set the full hash for *skb* (set the field *skb*\ **->hash**) ++ * to value *hash*. ++ * Return ++ * 0 ++ * ++ * int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen) ++ * Description ++ * Emulate a call to **setsockopt()** on the socket associated to ++ * *bpf_socket*, which must be a full socket. The *level* at ++ * which the option resides and the name *optname* of the option ++ * must be specified, see **setsockopt(2)** for more information. ++ * The option value of length *optlen* is pointed by *optval*. ++ * ++ * This helper actually implements a subset of **setsockopt()**. ++ * It supports the following *level*\ s: ++ * ++ * * **SOL_SOCKET**, which supports the following *optname*\ s: ++ * **SO_RCVBUF**, **SO_SNDBUF**, **SO_MAX_PACING_RATE**, ++ * **SO_PRIORITY**, **SO_RCVLOWAT**, **SO_MARK**. ++ * * **IPPROTO_TCP**, which supports the following *optname*\ s: ++ * **TCP_CONGESTION**, **TCP_BPF_IW**, ++ * **TCP_BPF_SNDCWND_CLAMP**. ++ * * **IPPROTO_IP**, which supports *optname* **IP_TOS**. ++ * * **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_adjust_room(struct sk_buff *skb, s32 len_diff, u32 mode, u64 flags) ++ * Description ++ * Grow or shrink the room for data in the packet associated to ++ * *skb* by *len_diff*, and according to the selected *mode*. ++ * ++ * There is a single supported mode at this time: ++ * ++ * * **BPF_ADJ_ROOM_NET**: Adjust room at the network layer ++ * (room space is added or removed below the layer 3 header). ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_redirect_map(struct bpf_map *map, u32 key, u64 flags) ++ * Description ++ * Redirect the packet to the endpoint referenced by *map* at ++ * index *key*. Depending on its type, this *map* can contain ++ * references to net devices (for forwarding packets through other ++ * ports), or to CPUs (for redirecting XDP frames to another CPU; ++ * but this is only implemented for native XDP (with driver ++ * support) as of this writing). ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * When used to redirect packets to net devices, this helper ++ * provides a high performance increase over **bpf_redirect**\ (). ++ * This is due to various implementation details of the underlying ++ * mechanisms, one of which is the fact that **bpf_redirect_map**\ ++ * () tries to send packet as a "bulk" to the device. ++ * Return ++ * **XDP_REDIRECT** on success, or **XDP_ABORTED** on error. ++ * ++ * int bpf_sk_redirect_map(struct bpf_map *map, u32 key, u64 flags) ++ * Description ++ * Redirect the packet to the socket referenced by *map* (of type ++ * **BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and ++ * egress interfaces can be used for redirection. The ++ * **BPF_F_INGRESS** value in *flags* is used to make the ++ * distinction (ingress path is selected if the flag is present, ++ * egress path otherwise). This is the only flag supported for now. ++ * Return ++ * **SK_PASS** on success, or **SK_DROP** on error. ++ * ++ * int bpf_sock_map_update(struct bpf_sock_ops *skops, struct bpf_map *map, void *key, u64 flags) ++ * Description ++ * Add an entry to, or update a *map* referencing sockets. The ++ * *skops* is used as a new value for the entry associated to ++ * *key*. *flags* is one of: ++ * ++ * **BPF_NOEXIST** ++ * The entry for *key* must not exist in the map. ++ * **BPF_EXIST** ++ * The entry for *key* must already exist in the map. ++ * **BPF_ANY** ++ * No condition on the existence of the entry for *key*. ++ * ++ * If the *map* has eBPF programs (parser and verdict), those will ++ * be inherited by the socket being added. If the socket is ++ * already attached to eBPF programs, this results in an error. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_xdp_adjust_meta(struct xdp_buff *xdp_md, int delta) ++ * Description ++ * Adjust the address pointed by *xdp_md*\ **->data_meta** by ++ * *delta* (which can be positive or negative). Note that this ++ * operation modifies the address stored in *xdp_md*\ **->data**, ++ * so the latter must be loaded only after the helper has been ++ * called. ++ * ++ * The use of *xdp_md*\ **->data_meta** is optional and programs ++ * are not required to use it. The rationale is that when the ++ * packet is processed with XDP (e.g. as DoS filter), it is ++ * possible to push further meta data along with it before passing ++ * to the stack, and to give the guarantee that an ingress eBPF ++ * program attached as a TC classifier on the same device can pick ++ * this up for further post-processing. Since TC works with socket ++ * buffers, it remains possible to set from XDP the **mark** or ++ * **priority** pointers, or other pointers for the socket buffer. ++ * Having this scratch space generic and programmable allows for ++ * more flexibility as the user is free to store whatever meta ++ * data they need. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_perf_event_read_value(struct bpf_map *map, u64 flags, struct bpf_perf_event_value *buf, u32 buf_size) ++ * Description ++ * Read the value of a perf event counter, and store it into *buf* ++ * of size *buf_size*. This helper relies on a *map* of type ++ * **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of the perf event ++ * counter is selected when *map* is updated with perf event file ++ * descriptors. The *map* is an array whose size is the number of ++ * available CPUs, and each cell contains a value relative to one ++ * CPU. The value to retrieve is indicated by *flags*, that ++ * contains the index of the CPU to look up, masked with ++ * **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to ++ * **BPF_F_CURRENT_CPU** to indicate that the value for the ++ * current CPU should be retrieved. ++ * ++ * This helper behaves in a way close to ++ * **bpf_perf_event_read**\ () helper, save that instead of ++ * just returning the value observed, it fills the *buf* ++ * structure. This allows for additional data to be retrieved: in ++ * particular, the enabled and running times (in *buf*\ ++ * **->enabled** and *buf*\ **->running**, respectively) are ++ * copied. In general, **bpf_perf_event_read_value**\ () is ++ * recommended over **bpf_perf_event_read**\ (), which has some ++ * ABI issues and provides fewer functionalities. ++ * ++ * These values are interesting, because hardware PMU (Performance ++ * Monitoring Unit) counters are limited resources. When there are ++ * more PMU based perf events opened than available counters, ++ * kernel will multiplex these events so each event gets certain ++ * percentage (but not all) of the PMU time. In case that ++ * multiplexing happens, the number of samples or counter value ++ * will not reflect the case compared to when no multiplexing ++ * occurs. This makes comparison between different runs difficult. ++ * Typically, the counter value should be normalized before ++ * comparing to other experiments. The usual normalization is done ++ * as follows. ++ * ++ * :: ++ * ++ * normalized_counter = counter * t_enabled / t_running ++ * ++ * Where t_enabled is the time enabled for event and t_running is ++ * the time running for event since last normalization. The ++ * enabled and running times are accumulated since the perf event ++ * open. To achieve scaling factor between two invocations of an ++ * eBPF program, users can can use CPU id as the key (which is ++ * typical for perf array usage model) to remember the previous ++ * value and do the calculation inside the eBPF program. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_perf_prog_read_value(struct bpf_perf_event_data *ctx, struct bpf_perf_event_value *buf, u32 buf_size) ++ * Description ++ * For en eBPF program attached to a perf event, retrieve the ++ * value of the event counter associated to *ctx* and store it in ++ * the structure pointed by *buf* and of size *buf_size*. Enabled ++ * and running times are also stored in the structure (see ++ * description of helper **bpf_perf_event_read_value**\ () for ++ * more details). ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen) ++ * Description ++ * Emulate a call to **getsockopt()** on the socket associated to ++ * *bpf_socket*, which must be a full socket. The *level* at ++ * which the option resides and the name *optname* of the option ++ * must be specified, see **getsockopt(2)** for more information. ++ * The retrieved value is stored in the structure pointed by ++ * *opval* and of length *optlen*. ++ * ++ * This helper actually implements a subset of **getsockopt()**. ++ * It supports the following *level*\ s: ++ * ++ * * **IPPROTO_TCP**, which supports *optname* ++ * **TCP_CONGESTION**. ++ * * **IPPROTO_IP**, which supports *optname* **IP_TOS**. ++ * * **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_override_return(struct pt_reg *regs, u64 rc) ++ * Description ++ * Used for error injection, this helper uses kprobes to override ++ * the return value of the probed function, and to set it to *rc*. ++ * The first argument is the context *regs* on which the kprobe ++ * works. ++ * ++ * This helper works by setting setting the PC (program counter) ++ * to an override function which is run in place of the original ++ * probed function. This means the probed function is not run at ++ * all. The replacement function just returns with the required ++ * value. ++ * ++ * This helper has security implications, and thus is subject to ++ * restrictions. It is only available if the kernel was compiled ++ * with the **CONFIG_BPF_KPROBE_OVERRIDE** configuration ++ * option, and in this case it only works on functions tagged with ++ * **ALLOW_ERROR_INJECTION** in the kernel code. ++ * ++ * Also, the helper is only available for the architectures having ++ * the CONFIG_FUNCTION_ERROR_INJECTION option. As of this writing, ++ * x86 architecture is the only one to support this feature. ++ * Return ++ * 0 ++ * ++ * int bpf_sock_ops_cb_flags_set(struct bpf_sock_ops *bpf_sock, int argval) ++ * Description ++ * Attempt to set the value of the **bpf_sock_ops_cb_flags** field ++ * for the full TCP socket associated to *bpf_sock_ops* to ++ * *argval*. ++ * ++ * The primary use of this field is to determine if there should ++ * be calls to eBPF programs of type ++ * **BPF_PROG_TYPE_SOCK_OPS** at various points in the TCP ++ * code. A program of the same type can change its value, per ++ * connection and as necessary, when the connection is ++ * established. This field is directly accessible for reading, but ++ * this helper must be used for updates in order to return an ++ * error if an eBPF program tries to set a callback that is not ++ * supported in the current kernel. ++ * ++ * The supported callback values that *argval* can combine are: ++ * ++ * * **BPF_SOCK_OPS_RTO_CB_FLAG** (retransmission time out) ++ * * **BPF_SOCK_OPS_RETRANS_CB_FLAG** (retransmission) ++ * * **BPF_SOCK_OPS_STATE_CB_FLAG** (TCP state change) ++ * ++ * Here are some examples of where one could call such eBPF ++ * program: ++ * ++ * * When RTO fires. ++ * * When a packet is retransmitted. ++ * * When the connection terminates. ++ * * When a packet is sent. ++ * * When a packet is received. ++ * Return ++ * Code **-EINVAL** if the socket is not a full TCP socket; ++ * otherwise, a positive number containing the bits that could not ++ * be set is returned (which comes down to 0 if all bits were set ++ * as required). ++ * ++ * int bpf_msg_redirect_map(struct sk_msg_buff *msg, struct bpf_map *map, u32 key, u64 flags) ++ * Description ++ * This helper is used in programs implementing policies at the ++ * socket level. If the message *msg* is allowed to pass (i.e. if ++ * the verdict eBPF program returns **SK_PASS**), redirect it to ++ * the socket referenced by *map* (of type ++ * **BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and ++ * egress interfaces can be used for redirection. The ++ * **BPF_F_INGRESS** value in *flags* is used to make the ++ * distinction (ingress path is selected if the flag is present, ++ * egress path otherwise). This is the only flag supported for now. ++ * Return ++ * **SK_PASS** on success, or **SK_DROP** on error. ++ * ++ * int bpf_msg_apply_bytes(struct sk_msg_buff *msg, u32 bytes) ++ * Description ++ * For socket policies, apply the verdict of the eBPF program to ++ * the next *bytes* (number of bytes) of message *msg*. ++ * ++ * For example, this helper can be used in the following cases: ++ * ++ * * A single **sendmsg**\ () or **sendfile**\ () system call ++ * contains multiple logical messages that the eBPF program is ++ * supposed to read and for which it should apply a verdict. ++ * * An eBPF program only cares to read the first *bytes* of a ++ * *msg*. If the message has a large payload, then setting up ++ * and calling the eBPF program repeatedly for all bytes, even ++ * though the verdict is already known, would create unnecessary ++ * overhead. ++ * ++ * When called from within an eBPF program, the helper sets a ++ * counter internal to the BPF infrastructure, that is used to ++ * apply the last verdict to the next *bytes*. If *bytes* is ++ * smaller than the current data being processed from a ++ * **sendmsg**\ () or **sendfile**\ () system call, the first ++ * *bytes* will be sent and the eBPF program will be re-run with ++ * the pointer for start of data pointing to byte number *bytes* ++ * **+ 1**. If *bytes* is larger than the current data being ++ * processed, then the eBPF verdict will be applied to multiple ++ * **sendmsg**\ () or **sendfile**\ () calls until *bytes* are ++ * consumed. ++ * ++ * Note that if a socket closes with the internal counter holding ++ * a non-zero value, this is not a problem because data is not ++ * being buffered for *bytes* and is sent as it is received. ++ * Return ++ * 0 ++ * ++ * int bpf_msg_cork_bytes(struct sk_msg_buff *msg, u32 bytes) ++ * Description ++ * For socket policies, prevent the execution of the verdict eBPF ++ * program for message *msg* until *bytes* (byte number) have been ++ * accumulated. ++ * ++ * This can be used when one needs a specific number of bytes ++ * before a verdict can be assigned, even if the data spans ++ * multiple **sendmsg**\ () or **sendfile**\ () calls. The extreme ++ * case would be a user calling **sendmsg**\ () repeatedly with ++ * 1-byte long message segments. Obviously, this is bad for ++ * performance, but it is still valid. If the eBPF program needs ++ * *bytes* bytes to validate a header, this helper can be used to ++ * prevent the eBPF program to be called again until *bytes* have ++ * been accumulated. ++ * Return ++ * 0 ++ * ++ * int bpf_msg_pull_data(struct sk_msg_buff *msg, u32 start, u32 end, u64 flags) ++ * Description ++ * For socket policies, pull in non-linear data from user space ++ * for *msg* and set pointers *msg*\ **->data** and *msg*\ ++ * **->data_end** to *start* and *end* bytes offsets into *msg*, ++ * respectively. ++ * ++ * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a ++ * *msg* it can only parse data that the (**data**, **data_end**) ++ * pointers have already consumed. For **sendmsg**\ () hooks this ++ * is likely the first scatterlist element. But for calls relying ++ * on the **sendpage** handler (e.g. **sendfile**\ ()) this will ++ * be the range (**0**, **0**) because the data is shared with ++ * user space and by default the objective is to avoid allowing ++ * user space to modify data while (or after) eBPF verdict is ++ * being decided. This helper can be used to pull in data and to ++ * set the start and end pointer to given values. Data will be ++ * copied if necessary (i.e. if data was not linear and if start ++ * and end pointers do not point to the same chunk). ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_bind(struct bpf_sock_addr *ctx, struct sockaddr *addr, int addr_len) ++ * Description ++ * Bind the socket associated to *ctx* to the address pointed by ++ * *addr*, of length *addr_len*. This allows for making outgoing ++ * connection from the desired IP address, which can be useful for ++ * example when all processes inside a cgroup should use one ++ * single IP address on a host that has multiple IP configured. ++ * ++ * This helper works for IPv4 and IPv6, TCP and UDP sockets. The ++ * domain (*addr*\ **->sa_family**) must be **AF_INET** (or ++ * **AF_INET6**). Looking for a free port to bind to can be ++ * expensive, therefore binding to port is not permitted by the ++ * helper: *addr*\ **->sin_port** (or **sin6_port**, respectively) ++ * must be set to zero. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_xdp_adjust_tail(struct xdp_buff *xdp_md, int delta) ++ * Description ++ * Adjust (move) *xdp_md*\ **->data_end** by *delta* bytes. It is ++ * only possible to shrink the packet as of this writing, ++ * therefore *delta* must be a negative integer. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_skb_get_xfrm_state(struct sk_buff *skb, u32 index, struct bpf_xfrm_state *xfrm_state, u32 size, u64 flags) ++ * Description ++ * Retrieve the XFRM state (IP transform framework, see also ++ * **ip-xfrm(8)**) at *index* in XFRM "security path" for *skb*. ++ * ++ * The retrieved value is stored in the **struct bpf_xfrm_state** ++ * pointed by *xfrm_state* and of length *size*. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_XFRM** configuration option. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_get_stack(struct pt_regs *regs, void *buf, u32 size, u64 flags) ++ * Description ++ * Return a user or a kernel stack in bpf program provided buffer. ++ * To achieve this, the helper needs *ctx*, which is a pointer ++ * to the context on which the tracing program is executed. ++ * To store the stacktrace, the bpf program provides *buf* with ++ * a nonnegative *size*. ++ * ++ * The last argument, *flags*, holds the number of stack frames to ++ * skip (from 0 to 255), masked with ++ * **BPF_F_SKIP_FIELD_MASK**. The next bits can be used to set ++ * the following flags: ++ * ++ * **BPF_F_USER_STACK** ++ * Collect a user space stack instead of a kernel stack. ++ * **BPF_F_USER_BUILD_ID** ++ * Collect buildid+offset instead of ips for user stack, ++ * only valid if **BPF_F_USER_STACK** is also specified. ++ * ++ * **bpf_get_stack**\ () can collect up to ++ * **PERF_MAX_STACK_DEPTH** both kernel and user frames, subject ++ * to sufficient large buffer size. Note that ++ * this limit can be controlled with the **sysctl** program, and ++ * that it should be manually increased in order to profile long ++ * user stacks (such as stacks for Java programs). To do so, use: ++ * ++ * :: ++ * ++ * # sysctl kernel.perf_event_max_stack= ++ * Return ++ * A non-negative value equal to or less than *size* on success, ++ * or a negative error in case of failure. ++ * ++ * int bpf_skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header) ++ * Description ++ * This helper is similar to **bpf_skb_load_bytes**\ () in that ++ * it provides an easy way to load *len* bytes from *offset* ++ * from the packet associated to *skb*, into the buffer pointed ++ * by *to*. The difference to **bpf_skb_load_bytes**\ () is that ++ * a fifth argument *start_header* exists in order to select a ++ * base offset to start from. *start_header* can be one of: ++ * ++ * **BPF_HDR_START_MAC** ++ * Base offset to load data from is *skb*'s mac header. ++ * **BPF_HDR_START_NET** ++ * Base offset to load data from is *skb*'s network header. ++ * ++ * In general, "direct packet access" is the preferred method to ++ * access packet data, however, this helper is in particular useful ++ * in socket filters where *skb*\ **->data** does not always point ++ * to the start of the mac header and where "direct packet access" ++ * is not available. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_fib_lookup(void *ctx, struct bpf_fib_lookup *params, int plen, u32 flags) ++ * Description ++ * Do FIB lookup in kernel tables using parameters in *params*. ++ * If lookup is successful and result shows packet is to be ++ * forwarded, the neighbor tables are searched for the nexthop. ++ * If successful (ie., FIB lookup shows forwarding and nexthop ++ * is resolved), the nexthop address is returned in ipv4_dst ++ * or ipv6_dst based on family, smac is set to mac address of ++ * egress device, dmac is set to nexthop mac address, rt_metric ++ * is set to metric from route (IPv4/IPv6 only), and ifindex ++ * is set to the device index of the nexthop from the FIB lookup. ++ * ++ * *plen* argument is the size of the passed in struct. ++ * *flags* argument can be a combination of one or more of the ++ * following values: ++ * ++ * **BPF_FIB_LOOKUP_DIRECT** ++ * Do a direct table lookup vs full lookup using FIB ++ * rules. ++ * **BPF_FIB_LOOKUP_OUTPUT** ++ * Perform lookup from an egress perspective (default is ++ * ingress). ++ * ++ * *ctx* is either **struct xdp_md** for XDP programs or ++ * **struct sk_buff** tc cls_act programs. ++ * Return ++ * * < 0 if any input argument is invalid ++ * * 0 on success (packet is forwarded, nexthop neighbor exists) ++ * * > 0 one of **BPF_FIB_LKUP_RET_** codes explaining why the ++ * packet is not forwarded or needs assist from full stack ++ * ++ * int bpf_sock_hash_update(struct bpf_sock_ops_kern *skops, struct bpf_map *map, void *key, u64 flags) ++ * Description ++ * Add an entry to, or update a sockhash *map* referencing sockets. ++ * The *skops* is used as a new value for the entry associated to ++ * *key*. *flags* is one of: ++ * ++ * **BPF_NOEXIST** ++ * The entry for *key* must not exist in the map. ++ * **BPF_EXIST** ++ * The entry for *key* must already exist in the map. ++ * **BPF_ANY** ++ * No condition on the existence of the entry for *key*. ++ * ++ * If the *map* has eBPF programs (parser and verdict), those will ++ * be inherited by the socket being added. If the socket is ++ * already attached to eBPF programs, this results in an error. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_msg_redirect_hash(struct sk_msg_buff *msg, struct bpf_map *map, void *key, u64 flags) ++ * Description ++ * This helper is used in programs implementing policies at the ++ * socket level. If the message *msg* is allowed to pass (i.e. if ++ * the verdict eBPF program returns **SK_PASS**), redirect it to ++ * the socket referenced by *map* (of type ++ * **BPF_MAP_TYPE_SOCKHASH**) using hash *key*. Both ingress and ++ * egress interfaces can be used for redirection. The ++ * **BPF_F_INGRESS** value in *flags* is used to make the ++ * distinction (ingress path is selected if the flag is present, ++ * egress path otherwise). This is the only flag supported for now. ++ * Return ++ * **SK_PASS** on success, or **SK_DROP** on error. ++ * ++ * int bpf_sk_redirect_hash(struct sk_buff *skb, struct bpf_map *map, void *key, u64 flags) ++ * Description ++ * This helper is used in programs implementing policies at the ++ * skb socket level. If the sk_buff *skb* is allowed to pass (i.e. ++ * if the verdeict eBPF program returns **SK_PASS**), redirect it ++ * to the socket referenced by *map* (of type ++ * **BPF_MAP_TYPE_SOCKHASH**) using hash *key*. Both ingress and ++ * egress interfaces can be used for redirection. The ++ * **BPF_F_INGRESS** value in *flags* is used to make the ++ * distinction (ingress path is selected if the flag is present, ++ * egress otherwise). This is the only flag supported for now. ++ * Return ++ * **SK_PASS** on success, or **SK_DROP** on error. ++ * ++ * int bpf_lwt_push_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len) ++ * Description ++ * Encapsulate the packet associated to *skb* within a Layer 3 ++ * protocol header. This header is provided in the buffer at ++ * address *hdr*, with *len* its size in bytes. *type* indicates ++ * the protocol of the header and can be one of: ++ * ++ * **BPF_LWT_ENCAP_SEG6** ++ * IPv6 encapsulation with Segment Routing Header ++ * (**struct ipv6_sr_hdr**). *hdr* only contains the SRH, ++ * the IPv6 header is computed by the kernel. ++ * **BPF_LWT_ENCAP_SEG6_INLINE** ++ * Only works if *skb* contains an IPv6 packet. Insert a ++ * Segment Routing Header (**struct ipv6_sr_hdr**) inside ++ * the IPv6 header. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_lwt_seg6_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len) ++ * Description ++ * Store *len* bytes from address *from* into the packet ++ * associated to *skb*, at *offset*. Only the flags, tag and TLVs ++ * inside the outermost IPv6 Segment Routing Header can be ++ * modified through this helper. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_lwt_seg6_adjust_srh(struct sk_buff *skb, u32 offset, s32 delta) ++ * Description ++ * Adjust the size allocated to TLVs in the outermost IPv6 ++ * Segment Routing Header contained in the packet associated to ++ * *skb*, at position *offset* by *delta* bytes. Only offsets ++ * after the segments are accepted. *delta* can be as well ++ * positive (growing) as negative (shrinking). ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_lwt_seg6_action(struct sk_buff *skb, u32 action, void *param, u32 param_len) ++ * Description ++ * Apply an IPv6 Segment Routing action of type *action* to the ++ * packet associated to *skb*. Each action takes a parameter ++ * contained at address *param*, and of length *param_len* bytes. ++ * *action* can be one of: ++ * ++ * **SEG6_LOCAL_ACTION_END_X** ++ * End.X action: Endpoint with Layer-3 cross-connect. ++ * Type of *param*: **struct in6_addr**. ++ * **SEG6_LOCAL_ACTION_END_T** ++ * End.T action: Endpoint with specific IPv6 table lookup. ++ * Type of *param*: **int**. ++ * **SEG6_LOCAL_ACTION_END_B6** ++ * End.B6 action: Endpoint bound to an SRv6 policy. ++ * Type of param: **struct ipv6_sr_hdr**. ++ * **SEG6_LOCAL_ACTION_END_B6_ENCAP** ++ * End.B6.Encap action: Endpoint bound to an SRv6 ++ * encapsulation policy. ++ * Type of param: **struct ipv6_sr_hdr**. ++ * ++ * A call to this helper is susceptible to change the underlaying ++ * packet buffer. Therefore, at load time, all checks on pointers ++ * previously done by the verifier are invalidated and must be ++ * performed again, if the helper is used in combination with ++ * direct packet access. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) ++ * Description ++ * This helper is used in programs implementing IR decoding, to ++ * report a successfully decoded key press with *scancode*, ++ * *toggle* value in the given *protocol*. The scancode will be ++ * translated to a keycode using the rc keymap, and reported as ++ * an input key down event. After a period a key up event is ++ * generated. This period can be extended by calling either ++ * **bpf_rc_keydown**\ () again with the same values, or calling ++ * **bpf_rc_repeat**\ (). ++ * ++ * Some protocols include a toggle bit, in case the button was ++ * released and pressed again between consecutive scancodes. ++ * ++ * The *ctx* should point to the lirc sample as passed into ++ * the program. ++ * ++ * The *protocol* is the decoded protocol number (see ++ * **enum rc_proto** for some predefined values). ++ * ++ * This helper is only available is the kernel was compiled with ++ * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ++ * "**y**". ++ * Return ++ * 0 ++ * ++ * int bpf_rc_repeat(void *ctx) ++ * Description ++ * This helper is used in programs implementing IR decoding, to ++ * report a successfully decoded repeat key message. This delays ++ * the generation of a key up event for previously generated ++ * key down event. ++ * ++ * Some IR protocols like NEC have a special IR message for ++ * repeating last button, for when a button is held down. ++ * ++ * The *ctx* should point to the lirc sample as passed into ++ * the program. ++ * ++ * This helper is only available is the kernel was compiled with ++ * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ++ * "**y**". ++ * Return ++ * 0 ++ * ++ * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) ++ * Description ++ * Return the cgroup v2 id of the socket associated with the *skb*. ++ * This is roughly similar to the **bpf_get_cgroup_classid**\ () ++ * helper for cgroup v1 by providing a tag resp. identifier that ++ * can be matched on or used for map lookups e.g. to implement ++ * policy. The cgroup v2 id of a given path in the hierarchy is ++ * exposed in user space through the f_handle API in order to get ++ * to the same 64-bit id. ++ * ++ * This helper can be used on TC egress path, but not on ingress, ++ * and is available only if the kernel was compiled with the ++ * **CONFIG_SOCK_CGROUP_DATA** configuration option. ++ * Return ++ * The id is returned or 0 in case the id could not be retrieved. ++ * ++ * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) ++ * Description ++ * Return id of cgroup v2 that is ancestor of cgroup associated ++ * with the *skb* at the *ancestor_level*. The root cgroup is at ++ * *ancestor_level* zero and each step down the hierarchy ++ * increments the level. If *ancestor_level* == level of cgroup ++ * associated with *skb*, then return value will be same as that ++ * of **bpf_skb_cgroup_id**\ (). ++ * ++ * The helper is useful to implement policies based on cgroups ++ * that are upper in hierarchy than immediate cgroup associated ++ * with *skb*. ++ * ++ * The format of returned id and helper limitations are same as in ++ * **bpf_skb_cgroup_id**\ (). ++ * Return ++ * The id is returned or 0 in case the id could not be retrieved. ++ * ++ * u64 bpf_get_current_cgroup_id(void) ++ * Return ++ * A 64-bit integer containing the current cgroup id based ++ * on the cgroup within which the current task is running. ++ * ++ * void* get_local_storage(void *map, u64 flags) ++ * Description ++ * Get the pointer to the local storage area. ++ * The type and the size of the local storage is defined ++ * by the *map* argument. ++ * The *flags* meaning is specific for each map type, ++ * and has to be 0 for cgroup local storage. ++ * ++ * Depending on the BPF program type, a local storage area ++ * can be shared between multiple instances of the BPF program, ++ * running simultaneously. ++ * ++ * A user should care about the synchronization by himself. ++ * For example, by using the **BPF_STX_XADD** instruction to alter ++ * the shared data. ++ * Return ++ * A pointer to the local storage area. ++ * ++ * int bpf_sk_select_reuseport(struct sk_reuseport_md *reuse, struct bpf_map *map, void *key, u64 flags) ++ * Description ++ * Select a **SO_REUSEPORT** socket from a ++ * **BPF_MAP_TYPE_REUSEPORT_ARRAY** *map*. ++ * It checks the selected socket is matching the incoming ++ * request in the socket buffer. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) ++ * Description ++ * Look for TCP socket matching *tuple*, optionally in a child ++ * network namespace *netns*. The return value must be checked, ++ * and if non-**NULL**, released via **bpf_sk_release**\ (). ++ * ++ * The *ctx* should point to the context of the program, such as ++ * the skb or socket (depending on the hook in use). This is used ++ * to determine the base network namespace for the lookup. ++ * ++ * *tuple_size* must be one of: ++ * ++ * **sizeof**\ (*tuple*\ **->ipv4**) ++ * Look for an IPv4 socket. ++ * **sizeof**\ (*tuple*\ **->ipv6**) ++ * Look for an IPv6 socket. ++ * ++ * If the *netns* is a negative signed 32-bit integer, then the ++ * socket lookup table in the netns associated with the *ctx* will ++ * will be used. For the TC hooks, this is the netns of the device ++ * in the skb. For socket hooks, this is the netns of the socket. ++ * If *netns* is any other signed 32-bit value greater than or ++ * equal to zero then it specifies the ID of the netns relative to ++ * the netns associated with the *ctx*. *netns* values beyond the ++ * range of 32-bit integers are reserved for future use. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_NET** configuration option. ++ * Return ++ * Pointer to **struct bpf_sock**, or **NULL** in case of failure. ++ * For sockets with reuseport option, the **struct bpf_sock** ++ * result is from **reuse->socks**\ [] using the hash of the tuple. ++ * ++ * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) ++ * Description ++ * Look for UDP socket matching *tuple*, optionally in a child ++ * network namespace *netns*. The return value must be checked, ++ * and if non-**NULL**, released via **bpf_sk_release**\ (). ++ * ++ * The *ctx* should point to the context of the program, such as ++ * the skb or socket (depending on the hook in use). This is used ++ * to determine the base network namespace for the lookup. ++ * ++ * *tuple_size* must be one of: ++ * ++ * **sizeof**\ (*tuple*\ **->ipv4**) ++ * Look for an IPv4 socket. ++ * **sizeof**\ (*tuple*\ **->ipv6**) ++ * Look for an IPv6 socket. ++ * ++ * If the *netns* is a negative signed 32-bit integer, then the ++ * socket lookup table in the netns associated with the *ctx* will ++ * will be used. For the TC hooks, this is the netns of the device ++ * in the skb. For socket hooks, this is the netns of the socket. ++ * If *netns* is any other signed 32-bit value greater than or ++ * equal to zero then it specifies the ID of the netns relative to ++ * the netns associated with the *ctx*. *netns* values beyond the ++ * range of 32-bit integers are reserved for future use. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_NET** configuration option. ++ * Return ++ * Pointer to **struct bpf_sock**, or **NULL** in case of failure. ++ * For sockets with reuseport option, the **struct bpf_sock** ++ * result is from **reuse->socks**\ [] using the hash of the tuple. ++ * ++ * int bpf_sk_release(struct bpf_sock *sock) ++ * Description ++ * Release the reference held by *sock*. *sock* must be a ++ * non-**NULL** pointer that was returned from ++ * **bpf_sk_lookup_xxx**\ (). ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_pop_elem(struct bpf_map *map, void *value) ++ * Description ++ * Pop an element from *map*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_peek_elem(struct bpf_map *map, void *value) ++ * Description ++ * Get an element from *map* without removing it. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags) ++ * Description ++ * For socket policies, insert *len* bytes into *msg* at offset ++ * *start*. ++ * ++ * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a ++ * *msg* it may want to insert metadata or options into the *msg*. ++ * This can later be read and used by any of the lower layer BPF ++ * hooks. ++ * ++ * This helper may fail if under memory pressure (a malloc ++ * fails) in these cases BPF programs will get an appropriate ++ * error and BPF programs will need to handle them. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags) ++ * Description ++ * Will remove *pop* bytes from a *msg* starting at byte *start*. ++ * This may result in **ENOMEM** errors under certain situations if ++ * an allocation and copy are required due to a full ring buffer. ++ * However, the helper will try to avoid doing the allocation ++ * if possible. Other errors can occur if input parameters are ++ * invalid either due to *start* byte not being valid part of *msg* ++ * payload and/or *pop* value being to large. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_rc_pointer_rel(void *ctx, s32 rel_x, s32 rel_y) ++ * Description ++ * This helper is used in programs implementing IR decoding, to ++ * report a successfully decoded pointer movement. ++ * ++ * The *ctx* should point to the lirc sample as passed into ++ * the program. ++ * ++ * This helper is only available is the kernel was compiled with ++ * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ++ * "**y**". ++ * Return ++ * 0 + */ + #define __BPF_FUNC_MAPPER(FN) \ +- FN(unspec), \ +- FN(map_lookup_elem), \ +- FN(map_update_elem), \ +- FN(map_delete_elem), \ +- FN(probe_read), \ +- FN(ktime_get_ns), \ +- FN(trace_printk), \ +- FN(get_prandom_u32), \ +- FN(get_smp_processor_id), \ +- FN(skb_store_bytes), \ +- FN(l3_csum_replace), \ +- FN(l4_csum_replace), \ +- FN(tail_call), \ +- FN(clone_redirect), \ +- FN(get_current_pid_tgid), \ +- FN(get_current_uid_gid), \ +- FN(get_current_comm), \ +- FN(get_cgroup_classid), \ +- FN(skb_vlan_push), \ +- FN(skb_vlan_pop), \ +- FN(skb_get_tunnel_key), \ +- FN(skb_set_tunnel_key), \ +- FN(perf_event_read), \ +- FN(redirect), \ +- FN(get_route_realm), \ +- FN(perf_event_output), \ +- FN(skb_load_bytes), \ +- FN(get_stackid), \ +- FN(csum_diff), \ +- FN(skb_get_tunnel_opt), \ +- FN(skb_set_tunnel_opt), \ +- FN(skb_change_proto), \ +- FN(skb_change_type), \ +- FN(skb_under_cgroup), \ +- FN(get_hash_recalc), \ +- FN(get_current_task), \ +- FN(probe_write_user), \ +- FN(current_task_under_cgroup), \ +- FN(skb_change_tail), \ +- FN(skb_pull_data), \ +- FN(csum_update), \ +- FN(set_hash_invalid), \ +- FN(get_numa_node_id), \ +- FN(skb_change_head), \ +- FN(xdp_adjust_head), \ +- FN(probe_read_str), \ +- FN(get_socket_cookie), \ +- FN(get_socket_uid), \ +- FN(set_hash), \ +- FN(setsockopt), \ +- FN(skb_adjust_room), \ +- FN(redirect_map), \ +- FN(sk_redirect_map), \ +- FN(sock_map_update), \ +- FN(xdp_adjust_meta), \ +- FN(perf_event_read_value), \ +- FN(perf_prog_read_value), \ +- FN(getsockopt), \ +- FN(override_return), \ +- FN(sock_ops_cb_flags_set), ++ FN(unspec), \ ++ FN(map_lookup_elem), \ ++ FN(map_update_elem), \ ++ FN(map_delete_elem), \ ++ FN(probe_read), \ ++ FN(ktime_get_ns), \ ++ FN(trace_printk), \ ++ FN(get_prandom_u32), \ ++ FN(get_smp_processor_id), \ ++ FN(skb_store_bytes), \ ++ FN(l3_csum_replace), \ ++ FN(l4_csum_replace), \ ++ FN(tail_call), \ ++ FN(clone_redirect), \ ++ FN(get_current_pid_tgid), \ ++ FN(get_current_uid_gid), \ ++ FN(get_current_comm), \ ++ FN(get_cgroup_classid), \ ++ FN(skb_vlan_push), \ ++ FN(skb_vlan_pop), \ ++ FN(skb_get_tunnel_key), \ ++ FN(skb_set_tunnel_key), \ ++ FN(perf_event_read), \ ++ FN(redirect), \ ++ FN(get_route_realm), \ ++ FN(perf_event_output), \ ++ FN(skb_load_bytes), \ ++ FN(get_stackid), \ ++ FN(csum_diff), \ ++ FN(skb_get_tunnel_opt), \ ++ FN(skb_set_tunnel_opt), \ ++ FN(skb_change_proto), \ ++ FN(skb_change_type), \ ++ FN(skb_under_cgroup), \ ++ FN(get_hash_recalc), \ ++ FN(get_current_task), \ ++ FN(probe_write_user), \ ++ FN(current_task_under_cgroup), \ ++ FN(skb_change_tail), \ ++ FN(skb_pull_data), \ ++ FN(csum_update), \ ++ FN(set_hash_invalid), \ ++ FN(get_numa_node_id), \ ++ FN(skb_change_head), \ ++ FN(xdp_adjust_head), \ ++ FN(probe_read_str), \ ++ FN(get_socket_cookie), \ ++ FN(get_socket_uid), \ ++ FN(set_hash), \ ++ FN(setsockopt), \ ++ FN(skb_adjust_room), \ ++ FN(redirect_map), \ ++ FN(sk_redirect_map), \ ++ FN(sock_map_update), \ ++ FN(xdp_adjust_meta), \ ++ FN(perf_event_read_value), \ ++ FN(perf_prog_read_value), \ ++ FN(getsockopt), \ ++ FN(override_return), \ ++ FN(sock_ops_cb_flags_set), \ ++ FN(msg_redirect_map), \ ++ FN(msg_apply_bytes), \ ++ FN(msg_cork_bytes), \ ++ FN(msg_pull_data), \ ++ FN(bind), \ ++ FN(xdp_adjust_tail), \ ++ FN(skb_get_xfrm_state), \ ++ FN(get_stack), \ ++ FN(skb_load_bytes_relative), \ ++ FN(fib_lookup), \ ++ FN(sock_hash_update), \ ++ FN(msg_redirect_hash), \ ++ FN(sk_redirect_hash), \ ++ FN(lwt_push_encap), \ ++ FN(lwt_seg6_store_bytes), \ ++ FN(lwt_seg6_adjust_srh), \ ++ FN(lwt_seg6_action), \ ++ FN(rc_repeat), \ ++ FN(rc_keydown), \ ++ FN(skb_cgroup_id), \ ++ FN(get_current_cgroup_id), \ ++ FN(get_local_storage), \ ++ FN(sk_select_reuseport), \ ++ FN(skb_ancestor_cgroup_id), \ ++ FN(sk_lookup_tcp), \ ++ FN(sk_lookup_udp), \ ++ FN(sk_release), \ ++ FN(map_push_elem), \ ++ FN(map_pop_elem), \ ++ FN(map_peek_elem), \ ++ FN(msg_push_data), \ ++ FN(msg_pop_data), \ ++ FN(rc_pointer_rel), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call + */ + #define __BPF_ENUM_FN(x) BPF_FUNC_ ## x + enum bpf_func_id { +- __BPF_FUNC_MAPPER(__BPF_ENUM_FN) +- __BPF_FUNC_MAX_ID, ++ __BPF_FUNC_MAPPER(__BPF_ENUM_FN) ++ __BPF_FUNC_MAX_ID, + }; + #undef __BPF_ENUM_FN + +@@ -791,15 +2455,19 @@ enum bpf_func_id { + /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */ + #define BPF_F_TUNINFO_IPV6 (1ULL << 0) + +-/* BPF_FUNC_get_stackid flags. */ ++/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */ + #define BPF_F_SKIP_FIELD_MASK 0xffULL + #define BPF_F_USER_STACK (1ULL << 8) ++/* flags used by BPF_FUNC_get_stackid only. */ + #define BPF_F_FAST_STACK_CMP (1ULL << 9) + #define BPF_F_REUSE_STACKID (1ULL << 10) ++/* flags used by BPF_FUNC_get_stack only. */ ++#define BPF_F_USER_BUILD_ID (1ULL << 11) + + /* BPF_FUNC_skb_set_tunnel_key flags. */ + #define BPF_F_ZERO_CSUM_TX (1ULL << 1) + #define BPF_F_DONT_FRAGMENT (1ULL << 2) ++#define BPF_F_SEQ_NUMBER (1ULL << 3) + + /* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and + * BPF_FUNC_perf_event_read_value flags. +@@ -809,57 +2477,95 @@ enum bpf_func_id { + /* BPF_FUNC_perf_event_output for sk_buff input context. */ + #define BPF_F_CTXLEN_MASK (0xfffffULL << 32) + ++/* Current network namespace */ ++#define BPF_F_CURRENT_NETNS (-1L) ++ + /* Mode for BPF_FUNC_skb_adjust_room helper. */ + enum bpf_adj_room_mode { +- BPF_ADJ_ROOM_NET, ++ BPF_ADJ_ROOM_NET, ++}; ++ ++/* Mode for BPF_FUNC_skb_load_bytes_relative helper. */ ++enum bpf_hdr_start_off { ++ BPF_HDR_START_MAC, ++ BPF_HDR_START_NET, + }; + ++/* Encapsulation type for BPF_FUNC_lwt_push_encap helper. */ ++enum bpf_lwt_encap_mode { ++ BPF_LWT_ENCAP_SEG6, ++ BPF_LWT_ENCAP_SEG6_INLINE ++}; ++ ++#define __bpf_md_ptr(type, name) \ ++union { \ ++ type name; \ ++ __u64 :64; \ ++} __attribute__((aligned(8))) ++ + /* user accessible mirror of in-kernel sk_buff. + * new fields can only be added to the end of this structure + */ + struct __sk_buff { +- __u32 len; +- __u32 pkt_type; +- __u32 mark; +- __u32 queue_mapping; +- __u32 protocol; +- __u32 vlan_present; +- __u32 vlan_tci; +- __u32 vlan_proto; +- __u32 priority; +- __u32 ingress_ifindex; +- __u32 ifindex; +- __u32 tc_index; +- __u32 cb[5]; +- __u32 hash; +- __u32 tc_classid; +- __u32 data; +- __u32 data_end; +- __u32 napi_id; +- +- /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */ +- __u32 family; +- __u32 remote_ip4; /* Stored in network byte order */ +- __u32 local_ip4; /* Stored in network byte order */ +- __u32 remote_ip6[4]; /* Stored in network byte order */ +- __u32 local_ip6[4]; /* Stored in network byte order */ +- __u32 remote_port; /* Stored in network byte order */ +- __u32 local_port; /* stored in host byte order */ +- /* ... here. */ +- +- __u32 data_meta; ++ __u32 len; ++ __u32 pkt_type; ++ __u32 mark; ++ __u32 queue_mapping; ++ __u32 protocol; ++ __u32 vlan_present; ++ __u32 vlan_tci; ++ __u32 vlan_proto; ++ __u32 priority; ++ __u32 ingress_ifindex; ++ __u32 ifindex; ++ __u32 tc_index; ++ __u32 cb[5]; ++ __u32 hash; ++ __u32 tc_classid; ++ __u32 data; ++ __u32 data_end; ++ __u32 napi_id; ++ ++ /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */ ++ __u32 family; ++ __u32 remote_ip4; /* Stored in network byte order */ ++ __u32 local_ip4; /* Stored in network byte order */ ++ __u32 remote_ip6[4]; /* Stored in network byte order */ ++ __u32 local_ip6[4]; /* Stored in network byte order */ ++ __u32 remote_port; /* Stored in network byte order */ ++ __u32 local_port; /* stored in host byte order */ ++ /* ... here. */ ++ ++ __u32 data_meta; ++ __bpf_md_ptr(struct bpf_flow_keys *, flow_keys); ++ __u64 tstamp; ++ __u32 wire_len; + }; + + struct bpf_tunnel_key { +- __u32 tunnel_id; +- union { +- __u32 remote_ipv4; +- __u32 remote_ipv6[4]; +- }; +- __u8 tunnel_tos; +- __u8 tunnel_ttl; +- __u16 tunnel_ext; +- __u32 tunnel_label; ++ __u32 tunnel_id; ++ union { ++ __u32 remote_ipv4; ++ __u32 remote_ipv6[4]; ++ }; ++ __u8 tunnel_tos; ++ __u8 tunnel_ttl; ++ __u16 tunnel_ext; /* Padding, future use. */ ++ __u32 tunnel_label; ++}; ++ ++/* user accessible mirror of in-kernel xfrm_state. ++ * new fields can only be added to the end of this structure ++ */ ++struct bpf_xfrm_state { ++ __u32 reqid; ++ __u32 spi; /* Stored in network byte order */ ++ __u16 family; ++ __u16 ext; /* Padding, future use. */ ++ union { ++ __u32 remote_ipv4; /* Stored in network byte order */ ++ __u32 remote_ipv6[4]; /* Stored in network byte order */ ++ }; + }; + + /* Generic BPF return codes which all BPF program types may support. +@@ -870,21 +2576,47 @@ struct bpf_tunnel_key { + * XDP is handled seprately, see XDP_*. + */ + enum bpf_ret_code { +- BPF_OK = 0, +- /* 1 reserved */ +- BPF_DROP = 2, +- /* 3-6 reserved */ +- BPF_REDIRECT = 7, +- /* >127 are reserved for prog type specific return codes */ ++ BPF_OK = 0, ++ /* 1 reserved */ ++ BPF_DROP = 2, ++ /* 3-6 reserved */ ++ BPF_REDIRECT = 7, ++ /* >127 are reserved for prog type specific return codes */ + }; + + struct bpf_sock { +- __u32 bound_dev_if; +- __u32 family; +- __u32 type; +- __u32 protocol; +- __u32 mark; +- __u32 priority; ++ __u32 bound_dev_if; ++ __u32 family; ++ __u32 type; ++ __u32 protocol; ++ __u32 mark; ++ __u32 priority; ++ __u32 src_ip4; /* Allows 1,2,4-byte read. ++ * Stored in network byte order. ++ */ ++ __u32 src_ip6[4]; /* Allows 1,2,4-byte read. ++ * Stored in network byte order. ++ */ ++ __u32 src_port; /* Allows 4-byte read. ++ * Stored in host byte order ++ */ ++}; ++ ++struct bpf_sock_tuple { ++ union { ++ struct { ++ __be32 saddr; ++ __be32 daddr; ++ __be16 sport; ++ __be16 dport; ++ } ipv4; ++ struct { ++ __be32 saddr[4]; ++ __be32 daddr[4]; ++ __be16 sport; ++ __be16 dport; ++ } ipv6; ++ }; + }; + + #define XDP_PACKET_HEADROOM 256 +@@ -895,63 +2627,158 @@ struct bpf_sock { + * result in packet drops and a warning via bpf_warn_invalid_xdp_action(). + */ + enum xdp_action { +- XDP_ABORTED = 0, +- XDP_DROP, +- XDP_PASS, +- XDP_TX, +- XDP_REDIRECT, ++ XDP_ABORTED = 0, ++ XDP_DROP, ++ XDP_PASS, ++ XDP_TX, ++ XDP_REDIRECT, + }; + + /* user accessible metadata for XDP packet hook + * new fields must be added to the end of this structure + */ + struct xdp_md { +- __u32 data; +- __u32 data_end; +- __u32 data_meta; +- /* Below access go through struct xdp_rxq_info */ +- __u32 ingress_ifindex; /* rxq->dev->ifindex */ +- __u32 rx_queue_index; /* rxq->queue_index */ ++ __u32 data; ++ __u32 data_end; ++ __u32 data_meta; ++ /* Below access go through struct xdp_rxq_info */ ++ __u32 ingress_ifindex; /* rxq->dev->ifindex */ ++ __u32 rx_queue_index; /* rxq->queue_index */ + }; + + enum sk_action { +- SK_DROP = 0, +- SK_PASS, ++ SK_DROP = 0, ++ SK_PASS, ++}; ++ ++/* user accessible metadata for SK_MSG packet hook, new fields must ++ * be added to the end of this structure ++ */ ++struct sk_msg_md { ++ __bpf_md_ptr(void *, data); ++ __bpf_md_ptr(void *, data_end); ++ ++ __u32 family; ++ __u32 remote_ip4; /* Stored in network byte order */ ++ __u32 local_ip4; /* Stored in network byte order */ ++ __u32 remote_ip6[4]; /* Stored in network byte order */ ++ __u32 local_ip6[4]; /* Stored in network byte order */ ++ __u32 remote_port; /* Stored in network byte order */ ++ __u32 local_port; /* stored in host byte order */ ++ __u32 size; /* Total size of sk_msg */ ++}; ++ ++struct sk_reuseport_md { ++ /* ++ * Start of directly accessible data. It begins from ++ * the tcp/udp header. ++ */ ++ __bpf_md_ptr(void *, data); ++ /* End of directly accessible data */ ++ __bpf_md_ptr(void *, data_end); ++ /* ++ * Total length of packet (starting from the tcp/udp header). ++ * Note that the directly accessible bytes (data_end - data) ++ * could be less than this "len". Those bytes could be ++ * indirectly read by a helper "bpf_skb_load_bytes()". ++ */ ++ __u32 len; ++ /* ++ * Eth protocol in the mac header (network byte order). e.g. ++ * ETH_P_IP(0x0800) and ETH_P_IPV6(0x86DD) ++ */ ++ __u32 eth_protocol; ++ __u32 ip_protocol; /* IP protocol. e.g. IPPROTO_TCP, IPPROTO_UDP */ ++ __u32 bind_inany; /* Is sock bound to an INANY address? */ ++ __u32 hash; /* A hash of the packet 4 tuples */ + }; + + #define BPF_TAG_SIZE 8 + + struct bpf_prog_info { +- __u32 type; +- __u32 id; +- __u8 tag[BPF_TAG_SIZE]; +- __u32 jited_prog_len; +- __u32 xlated_prog_len; +- __aligned_u64 jited_prog_insns; +- __aligned_u64 xlated_prog_insns; +- __u64 load_time; /* ns since boottime */ +- __u32 created_by_uid; +- __u32 nr_map_ids; +- __aligned_u64 map_ids; +- char name[BPF_OBJ_NAME_LEN]; +- __u32 ifindex; +- __u64 netns_dev; +- __u64 netns_ino; ++ __u32 type; ++ __u32 id; ++ __u8 tag[BPF_TAG_SIZE]; ++ __u32 jited_prog_len; ++ __u32 xlated_prog_len; ++ __aligned_u64 jited_prog_insns; ++ __aligned_u64 xlated_prog_insns; ++ __u64 load_time; /* ns since boottime */ ++ __u32 created_by_uid; ++ __u32 nr_map_ids; ++ __aligned_u64 map_ids; ++ char name[BPF_OBJ_NAME_LEN]; ++ __u32 ifindex; ++ __u32 gpl_compatible:1; ++ __u64 netns_dev; ++ __u64 netns_ino; ++ __u32 nr_jited_ksyms; ++ __u32 nr_jited_func_lens; ++ __aligned_u64 jited_ksyms; ++ __aligned_u64 jited_func_lens; ++ __u32 btf_id; ++ __u32 func_info_rec_size; ++ __aligned_u64 func_info; ++ __u32 nr_func_info; ++ __u32 nr_line_info; ++ __aligned_u64 line_info; ++ __aligned_u64 jited_line_info; ++ __u32 nr_jited_line_info; ++ __u32 line_info_rec_size; ++ __u32 jited_line_info_rec_size; ++ __u32 nr_prog_tags; ++ __aligned_u64 prog_tags; + } __attribute__((aligned(8))); + + struct bpf_map_info { +- __u32 type; +- __u32 id; +- __u32 key_size; +- __u32 value_size; +- __u32 max_entries; +- __u32 map_flags; +- char name[BPF_OBJ_NAME_LEN]; +- __u32 ifindex; +- __u64 netns_dev; +- __u64 netns_ino; ++ __u32 type; ++ __u32 id; ++ __u32 key_size; ++ __u32 value_size; ++ __u32 max_entries; ++ __u32 map_flags; ++ char name[BPF_OBJ_NAME_LEN]; ++ __u32 ifindex; ++ __u32 :32; ++ __u64 netns_dev; ++ __u64 netns_ino; ++ __u32 btf_id; ++ __u32 btf_key_type_id; ++ __u32 btf_value_type_id; + } __attribute__((aligned(8))); + ++struct bpf_btf_info { ++ __aligned_u64 btf; ++ __u32 btf_size; ++ __u32 id; ++} __attribute__((aligned(8))); ++ ++/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed ++ * by user and intended to be used by socket (e.g. to bind to, depends on ++ * attach attach type). ++ */ ++struct bpf_sock_addr { ++ __u32 user_family; /* Allows 4-byte read, but no write. */ ++ __u32 user_ip4; /* Allows 1,2,4-byte read and 4-byte write. ++ * Stored in network byte order. ++ */ ++ __u32 user_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. ++ * Stored in network byte order. ++ */ ++ __u32 user_port; /* Allows 4-byte read and write. ++ * Stored in network byte order ++ */ ++ __u32 family; /* Allows 4-byte read, but no write */ ++ __u32 type; /* Allows 4-byte read, but no write */ ++ __u32 protocol; /* Allows 4-byte read, but no write */ ++ __u32 msg_src_ip4; /* Allows 1,2,4-byte read an 4-byte write. ++ * Stored in network byte order. ++ */ ++ __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. ++ * Stored in network byte order. ++ */ ++}; ++ + /* User bpf_sock_ops struct to access socket values and specify request ops + * and their replies. + * Some of this fields are in network (bigendian) byte order and may need +@@ -959,48 +2786,48 @@ struct bpf_map_info { + * New fields can only be added at the end of this structure + */ + struct bpf_sock_ops { +- __u32 op; +- union { +- __u32 args[4]; /* Optionally passed to bpf program */ +- __u32 reply; /* Returned by bpf program */ +- __u32 replylong[4]; /* Optionally returned by bpf prog */ +- }; +- __u32 family; +- __u32 remote_ip4; /* Stored in network byte order */ +- __u32 local_ip4; /* Stored in network byte order */ +- __u32 remote_ip6[4]; /* Stored in network byte order */ +- __u32 local_ip6[4]; /* Stored in network byte order */ +- __u32 remote_port; /* Stored in network byte order */ +- __u32 local_port; /* stored in host byte order */ +- __u32 is_fullsock; /* Some TCP fields are only valid if +- * there is a full socket. If not, the +- * fields read as zero. +- */ +- __u32 snd_cwnd; +- __u32 srtt_us; /* Averaged RTT << 3 in usecs */ +- __u32 bpf_sock_ops_cb_flags; /* flags defined in uapi/linux/tcp.h */ +- __u32 state; +- __u32 rtt_min; +- __u32 snd_ssthresh; +- __u32 rcv_nxt; +- __u32 snd_nxt; +- __u32 snd_una; +- __u32 mss_cache; +- __u32 ecn_flags; +- __u32 rate_delivered; +- __u32 rate_interval_us; +- __u32 packets_out; +- __u32 retrans_out; +- __u32 total_retrans; +- __u32 segs_in; +- __u32 data_segs_in; +- __u32 segs_out; +- __u32 data_segs_out; +- __u32 lost_out; +- __u32 sacked_out; +- __u32 sk_txhash; +- __u64 bytes_received; +- __u64 bytes_acked; ++ __u32 op; ++ union { ++ __u32 args[4]; /* Optionally passed to bpf program */ ++ __u32 reply; /* Returned by bpf program */ ++ __u32 replylong[4]; /* Optionally returned by bpf prog */ ++ }; ++ __u32 family; ++ __u32 remote_ip4; /* Stored in network byte order */ ++ __u32 local_ip4; /* Stored in network byte order */ ++ __u32 remote_ip6[4]; /* Stored in network byte order */ ++ __u32 local_ip6[4]; /* Stored in network byte order */ ++ __u32 remote_port; /* Stored in network byte order */ ++ __u32 local_port; /* stored in host byte order */ ++ __u32 is_fullsock; /* Some TCP fields are only valid if ++ * there is a full socket. If not, the ++ * fields read as zero. ++ */ ++ __u32 snd_cwnd; ++ __u32 srtt_us; /* Averaged RTT << 3 in usecs */ ++ __u32 bpf_sock_ops_cb_flags; /* flags defined in uapi/linux/tcp.h */ ++ __u32 state; ++ __u32 rtt_min; ++ __u32 snd_ssthresh; ++ __u32 rcv_nxt; ++ __u32 snd_nxt; ++ __u32 snd_una; ++ __u32 mss_cache; ++ __u32 ecn_flags; ++ __u32 rate_delivered; ++ __u32 rate_interval_us; ++ __u32 packets_out; ++ __u32 retrans_out; ++ __u32 total_retrans; ++ __u32 segs_in; ++ __u32 data_segs_in; ++ __u32 segs_out; ++ __u32 data_segs_out; ++ __u32 lost_out; ++ __u32 sacked_out; ++ __u32 sk_txhash; ++ __u64 bytes_received; ++ __u64 bytes_acked; + }; + + /* Definitions for bpf_sock_ops_cb_flags */ +@@ -1008,57 +2835,60 @@ struct bpf_sock_ops { + #define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1) + #define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2) + #define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7 /* Mask of all currently +- * supported cb flags +- */ ++ * supported cb flags ++ */ + + /* List of known BPF sock_ops operators. + * New entries can only be added at the end + */ + enum { +- BPF_SOCK_OPS_VOID, +- BPF_SOCK_OPS_TIMEOUT_INIT, /* Should return SYN-RTO value to use or +- * -1 if default value should be used +- */ +- BPF_SOCK_OPS_RWND_INIT, /* Should return initial advertized +- * window (in packets) or -1 if default +- * value should be used +- */ +- BPF_SOCK_OPS_TCP_CONNECT_CB, /* Calls BPF program right before an +- * active connection is initialized +- */ +- BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, /* Calls BPF program when an +- * active connection is +- * established +- */ +- BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, /* Calls BPF program when a +- * passive connection is +- * established +- */ +- BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control +- * needs ECN +- */ +- BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is +- * based on the path and may be +- * dependent on the congestion control +- * algorithm. In general it indicates +- * a congestion threshold. RTTs above +- * this indicate congestion +- */ +- BPF_SOCK_OPS_RTO_CB, /* Called when an RTO has triggered. +- * Arg1: value of icsk_retransmits +- * Arg2: value of icsk_rto +- * Arg3: whether RTO has expired +- */ +- BPF_SOCK_OPS_RETRANS_CB, /* Called when skb is retransmitted. +- * Arg1: sequence number of 1st byte +- * Arg2: # segments +- * Arg3: return value of +- * tcp_transmit_skb (0 => success) +- */ +- BPF_SOCK_OPS_STATE_CB, /* Called when TCP changes state. +- * Arg1: old_state +- * Arg2: new_state +- */ ++ BPF_SOCK_OPS_VOID, ++ BPF_SOCK_OPS_TIMEOUT_INIT, /* Should return SYN-RTO value to use or ++ * -1 if default value should be used ++ */ ++ BPF_SOCK_OPS_RWND_INIT, /* Should return initial advertized ++ * window (in packets) or -1 if default ++ * value should be used ++ */ ++ BPF_SOCK_OPS_TCP_CONNECT_CB, /* Calls BPF program right before an ++ * active connection is initialized ++ */ ++ BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, /* Calls BPF program when an ++ * active connection is ++ * established ++ */ ++ BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, /* Calls BPF program when a ++ * passive connection is ++ * established ++ */ ++ BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control ++ * needs ECN ++ */ ++ BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is ++ * based on the path and may be ++ * dependent on the congestion control ++ * algorithm. In general it indicates ++ * a congestion threshold. RTTs above ++ * this indicate congestion ++ */ ++ BPF_SOCK_OPS_RTO_CB, /* Called when an RTO has triggered. ++ * Arg1: value of icsk_retransmits ++ * Arg2: value of icsk_rto ++ * Arg3: whether RTO has expired ++ */ ++ BPF_SOCK_OPS_RETRANS_CB, /* Called when skb is retransmitted. ++ * Arg1: sequence number of 1st byte ++ * Arg2: # segments ++ * Arg3: return value of ++ * tcp_transmit_skb (0 => success) ++ */ ++ BPF_SOCK_OPS_STATE_CB, /* Called when TCP changes state. ++ * Arg1: old_state ++ * Arg2: new_state ++ */ ++ BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after ++ * socket transition to LISTEN state. ++ */ + }; + + /* List of TCP states. There is a build check in net/ipv4/tcp.c to detect +@@ -1067,29 +2897,29 @@ enum { + * the BPF sock_ops function. + */ + enum { +- BPF_TCP_ESTABLISHED = 1, +- BPF_TCP_SYN_SENT, +- BPF_TCP_SYN_RECV, +- BPF_TCP_FIN_WAIT1, +- BPF_TCP_FIN_WAIT2, +- BPF_TCP_TIME_WAIT, +- BPF_TCP_CLOSE, +- BPF_TCP_CLOSE_WAIT, +- BPF_TCP_LAST_ACK, +- BPF_TCP_LISTEN, +- BPF_TCP_CLOSING, /* Now a valid state */ +- BPF_TCP_NEW_SYN_RECV, +- +- BPF_TCP_MAX_STATES /* Leave at the end! */ ++ BPF_TCP_ESTABLISHED = 1, ++ BPF_TCP_SYN_SENT, ++ BPF_TCP_SYN_RECV, ++ BPF_TCP_FIN_WAIT1, ++ BPF_TCP_FIN_WAIT2, ++ BPF_TCP_TIME_WAIT, ++ BPF_TCP_CLOSE, ++ BPF_TCP_CLOSE_WAIT, ++ BPF_TCP_LAST_ACK, ++ BPF_TCP_LISTEN, ++ BPF_TCP_CLOSING, /* Now a valid state */ ++ BPF_TCP_NEW_SYN_RECV, ++ ++ BPF_TCP_MAX_STATES /* Leave at the end! */ + }; + + #define TCP_BPF_IW 1001 /* Set TCP initial congestion window */ + #define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */ + + struct bpf_perf_event_value { +- __u64 counter; +- __u64 enabled; +- __u64 running; ++ __u64 counter; ++ __u64 enabled; ++ __u64 running; + }; + + #define BPF_DEVCG_ACC_MKNOD (1ULL << 0) +@@ -1100,10 +2930,128 @@ struct bpf_perf_event_value { + #define BPF_DEVCG_DEV_CHAR (1ULL << 1) + + struct bpf_cgroup_dev_ctx { +- /* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */ +- __u32 access_type; +- __u32 major; +- __u32 minor; ++ /* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */ ++ __u32 access_type; ++ __u32 major; ++ __u32 minor; ++}; ++ ++struct bpf_raw_tracepoint_args { ++ __u64 args[0]; ++}; ++ ++/* DIRECT: Skip the FIB rules and go to FIB table associated with device ++ * OUTPUT: Do lookup from egress perspective; default is ingress ++ */ ++#define BPF_FIB_LOOKUP_DIRECT BIT(0) ++#define BPF_FIB_LOOKUP_OUTPUT BIT(1) ++ ++enum { ++ BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */ ++ BPF_FIB_LKUP_RET_BLACKHOLE, /* dest is blackholed; can be dropped */ ++ BPF_FIB_LKUP_RET_UNREACHABLE, /* dest is unreachable; can be dropped */ ++ BPF_FIB_LKUP_RET_PROHIBIT, /* dest not allowed; can be dropped */ ++ BPF_FIB_LKUP_RET_NOT_FWDED, /* packet is not forwarded */ ++ BPF_FIB_LKUP_RET_FWD_DISABLED, /* fwding is not enabled on ingress */ ++ BPF_FIB_LKUP_RET_UNSUPP_LWT, /* fwd requires encapsulation */ ++ BPF_FIB_LKUP_RET_NO_NEIGH, /* no neighbor entry for nh */ ++ BPF_FIB_LKUP_RET_FRAG_NEEDED, /* fragmentation required to fwd */ ++}; ++ ++struct bpf_fib_lookup { ++ /* input: network family for lookup (AF_INET, AF_INET6) ++ * output: network family of egress nexthop ++ */ ++ __u8 family; ++ ++ /* set if lookup is to consider L4 data - e.g., FIB rules */ ++ __u8 l4_protocol; ++ __be16 sport; ++ __be16 dport; ++ ++ /* total length of packet from network header - used for MTU check */ ++ __u16 tot_len; ++ ++ /* input: L3 device index for lookup ++ * output: device index from FIB lookup ++ */ ++ __u32 ifindex; ++ ++ union { ++ /* inputs to lookup */ ++ __u8 tos; /* AF_INET */ ++ __be32 flowinfo; /* AF_INET6, flow_label + priority */ ++ ++ /* output: metric of fib result (IPv4/IPv6 only) */ ++ __u32 rt_metric; ++ }; ++ ++ union { ++ __be32 ipv4_src; ++ __u32 ipv6_src[4]; /* in6_addr; network order */ ++ }; ++ ++ /* input to bpf_fib_lookup, ipv{4,6}_dst is destination address in ++ * network header. output: bpf_fib_lookup sets to gateway address ++ * if FIB lookup returns gateway route ++ */ ++ union { ++ __be32 ipv4_dst; ++ __u32 ipv6_dst[4]; /* in6_addr; network order */ ++ }; ++ ++ /* output */ ++ __be16 h_vlan_proto; ++ __be16 h_vlan_TCI; ++ __u8 smac[6]; /* ETH_ALEN */ ++ __u8 dmac[6]; /* ETH_ALEN */ ++}; ++ ++enum bpf_task_fd_type { ++ BPF_FD_TYPE_RAW_TRACEPOINT, /* tp name */ ++ BPF_FD_TYPE_TRACEPOINT, /* tp name */ ++ BPF_FD_TYPE_KPROBE, /* (symbol + offset) or addr */ ++ BPF_FD_TYPE_KRETPROBE, /* (symbol + offset) or addr */ ++ BPF_FD_TYPE_UPROBE, /* filename + offset */ ++ BPF_FD_TYPE_URETPROBE, /* filename + offset */ ++}; ++ ++struct bpf_flow_keys { ++ __u16 nhoff; ++ __u16 thoff; ++ __u16 addr_proto; /* ETH_P_* of valid addrs */ ++ __u8 is_frag; ++ __u8 is_first_frag; ++ __u8 is_encap; ++ __u8 ip_proto; ++ __be16 n_proto; ++ __be16 sport; ++ __be16 dport; ++ union { ++ struct { ++ __be32 ipv4_src; ++ __be32 ipv4_dst; ++ }; ++ struct { ++ __u32 ipv6_src[4]; /* in6_addr; network order */ ++ __u32 ipv6_dst[4]; /* in6_addr; network order */ ++ }; ++ }; ++}; ++ ++struct bpf_func_info { ++ __u32 insn_off; ++ __u32 type_id; ++}; ++ ++#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10) ++#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff) ++ ++struct bpf_line_info { ++ __u32 insn_off; ++ __u32 file_name_off; ++ __u32 line_off; ++ __u32 line_col; + }; + + #endif /* _UAPI__LINUX_BPF_H__ */ +diff --git a/src/shared/linux/bpf_common.h b/src/shared/linux/bpf_common.h +index afe7433b989..ee97668bdad 100644 +--- a/src/shared/linux/bpf_common.h ++++ b/src/shared/linux/bpf_common.h +@@ -1,5 +1,6 @@ +-#ifndef __LINUX_BPF_COMMON_H__ +-#define __LINUX_BPF_COMMON_H__ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _UAPI__LINUX_BPF_COMMON_H__ ++#define _UAPI__LINUX_BPF_COMMON_H__ + + /* Instruction classes */ + #define BPF_CLASS(code) ((code) & 0x07) +@@ -14,9 +15,10 @@ + + /* ld/ldx fields */ + #define BPF_SIZE(code) ((code) & 0x18) +-#define BPF_W 0x00 +-#define BPF_H 0x08 +-#define BPF_B 0x10 ++#define BPF_W 0x00 /* 32-bit */ ++#define BPF_H 0x08 /* 16-bit */ ++#define BPF_B 0x10 /* 8-bit */ ++/* eBPF BPF_DW 0x18 64-bit */ + #define BPF_MODE(code) ((code) & 0xe0) + #define BPF_IMM 0x00 + #define BPF_ABS 0x20 +@@ -52,4 +54,4 @@ + #define BPF_MAXINSNS 4096 + #endif + +-#endif /* __LINUX_BPF_COMMON_H__ */ ++#endif /* _UAPI__LINUX_BPF_COMMON_H__ */ +diff --git a/src/shared/linux/bpf_insn.h b/src/shared/linux/bpf_insn.h +new file mode 100644 +index 00000000000..e88459fdaae +--- /dev/null ++++ b/src/shared/linux/bpf_insn.h +@@ -0,0 +1,205 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* eBPF instruction mini library */ ++#ifndef __BPF_INSN_H ++#define __BPF_INSN_H ++ ++struct bpf_insn; ++ ++/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ ++ ++#define BPF_ALU64_REG(OP, DST, SRC) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = 0, \ ++ .imm = 0 }) ++ ++#define BPF_ALU32_REG(OP, DST, SRC) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU | BPF_OP(OP) | BPF_X, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = 0, \ ++ .imm = 0 }) ++ ++/* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */ ++ ++#define BPF_ALU64_IMM(OP, DST, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = IMM }) ++ ++#define BPF_ALU32_IMM(OP, DST, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU | BPF_OP(OP) | BPF_K, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = IMM }) ++ ++/* Short form of mov, dst_reg = src_reg */ ++ ++#define BPF_MOV64_REG(DST, SRC) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU64 | BPF_MOV | BPF_X, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = 0, \ ++ .imm = 0 }) ++ ++#define BPF_MOV32_REG(DST, SRC) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU | BPF_MOV | BPF_X, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = 0, \ ++ .imm = 0 }) ++ ++/* Short form of mov, dst_reg = imm32 */ ++ ++#define BPF_MOV64_IMM(DST, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU64 | BPF_MOV | BPF_K, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = IMM }) ++ ++#define BPF_MOV32_IMM(DST, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ALU | BPF_MOV | BPF_K, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = IMM }) ++ ++/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ ++#define BPF_LD_IMM64(DST, IMM) \ ++ BPF_LD_IMM64_RAW(DST, 0, IMM) ++ ++#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_LD | BPF_DW | BPF_IMM, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = 0, \ ++ .imm = (__u32) (IMM) }), \ ++ ((struct bpf_insn) { \ ++ .code = 0, /* zero is reserved opcode */ \ ++ .dst_reg = 0, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = ((__u64) (IMM)) >> 32 }) ++ ++#ifndef BPF_PSEUDO_MAP_FD ++# define BPF_PSEUDO_MAP_FD 1 ++#endif ++ ++/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ ++#define BPF_LD_MAP_FD(DST, MAP_FD) \ ++ BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) ++ ++ ++/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ ++ ++#define BPF_LD_ABS(SIZE, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \ ++ .dst_reg = 0, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = IMM }) ++ ++/* Memory load, dst_reg = *(uint *) (src_reg + off16) */ ++ ++#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = OFF, \ ++ .imm = 0 }) ++ ++/* Memory store, *(uint *) (dst_reg + off16) = src_reg */ ++ ++#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = OFF, \ ++ .imm = 0 }) ++ ++/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ ++ ++#define BPF_STX_XADD(SIZE, DST, SRC, OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = OFF, \ ++ .imm = 0 }) ++ ++/* Memory store, *(uint *) (dst_reg + off16) = imm32 */ ++ ++#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = OFF, \ ++ .imm = IMM }) ++ ++/* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */ ++ ++#define BPF_JMP_REG(OP, DST, SRC, OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_JMP | BPF_OP(OP) | BPF_X, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = OFF, \ ++ .imm = 0 }) ++ ++/* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */ ++ ++#define BPF_JMP_IMM(OP, DST, IMM, OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ ++ .dst_reg = DST, \ ++ .src_reg = 0, \ ++ .off = OFF, \ ++ .imm = IMM }) ++ ++#define BPF_JMP_A(OFF) \ ++ ((struct bpf_insn) { \ ++ .code = BPF_JMP | BPF_JA, \ ++ .dst_reg = 0, \ ++ .src_reg = 0, \ ++ .off = OFF, \ ++ .imm = 0 }) ++ ++/* Raw code statement block */ ++ ++#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ ++ ((struct bpf_insn) { \ ++ .code = CODE, \ ++ .dst_reg = DST, \ ++ .src_reg = SRC, \ ++ .off = OFF, \ ++ .imm = IMM }) ++ ++/* Program exit */ ++ ++#define BPF_EXIT_INSN() \ ++ ((struct bpf_insn) { \ ++ .code = BPF_JMP | BPF_EXIT, \ ++ .dst_reg = 0, \ ++ .src_reg = 0, \ ++ .off = 0, \ ++ .imm = 0 }) ++ ++#endif +diff --git a/src/shared/linux-3.13/dm-ioctl.h b/src/shared/linux/dm-ioctl.h +similarity index 96% +rename from src/shared/linux-3.13/dm-ioctl.h +rename to src/shared/linux/dm-ioctl.h +index c8a4302093a..8faa188c358 100644 +--- a/src/shared/linux-3.13/dm-ioctl.h ++++ b/src/shared/linux/dm-ioctl.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: LGPL-2.0+ WITH Linux-syscall-note */ + /* + * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. + * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved. +@@ -240,7 +241,8 @@ enum { + /* Added later */ + DM_LIST_VERSIONS_CMD, + DM_TARGET_MSG_CMD, +- DM_DEV_SET_GEOMETRY_CMD ++ DM_DEV_SET_GEOMETRY_CMD, ++ DM_DEV_ARM_POLL_CMD, + }; + + #define DM_IOCTL 0xfd +@@ -255,6 +257,7 @@ enum { + #define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl) + #define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl) + #define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl) ++#define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_ARM_POLL_CMD, struct dm_ioctl) + + #define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl) + #define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl) +@@ -269,7 +272,7 @@ enum { + #define DM_VERSION_MAJOR 4 + #define DM_VERSION_MINOR 27 + #define DM_VERSION_PATCHLEVEL 0 +-#define DM_VERSION_EXTRA "-ioctl (2013-10-30)" ++#define DM_VERSION_EXTRA "-ioctl (2018-04-03)" + + /* Status bits */ + #define DM_READONLY_FLAG (1 << 0) /* In/Out */ +@@ -352,4 +355,9 @@ enum { + */ + #define DM_DEFERRED_REMOVE (1 << 17) /* In/Out */ + ++/* ++ * If set, the device is suspended internally. ++ */ ++#define DM_INTERNAL_SUSPEND_FLAG (1 << 18) /* Out */ ++ + #endif /* _LINUX_DM_IOCTL_H */ +diff --git a/src/shared/linux/ethtool.h b/src/shared/linux/ethtool.h +new file mode 100644 +index 00000000000..f6c45a36c92 +--- /dev/null ++++ b/src/shared/linux/ethtool.h +@@ -0,0 +1,1843 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * ethtool.h: Defines for Linux ethtool. ++ * ++ * Copyright (C) 1998 David S. Miller (davem@redhat.com) ++ * Copyright 2001 Jeff Garzik ++ * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) ++ * Portions Copyright 2002 Intel (eli.kupermann@intel.com, ++ * christopher.leech@intel.com, ++ * scott.feldman@intel.com) ++ * Portions Copyright (C) Sun Microsystems 2008 ++ */ ++ ++#ifndef _UAPI_LINUX_ETHTOOL_H ++#define _UAPI_LINUX_ETHTOOL_H ++ ++#include ++#include ++#include ++ ++#ifndef __KERNEL__ ++#include /* for INT_MAX */ ++#endif ++ ++#ifndef __KERNEL_DIV_ROUND_UP ++#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ++#endif ++ ++/* All structures exposed to userland should be defined such that they ++ * have the same layout for 32-bit and 64-bit userland. ++ */ ++ ++/** ++ * struct ethtool_cmd - DEPRECATED, link control and status ++ * This structure is DEPRECATED, please use struct ethtool_link_settings. ++ * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET ++ * @supported: Bitmask of %SUPPORTED_* flags for the link modes, ++ * physical connectors and other link features for which the ++ * interface supports autonegotiation or auto-detection. ++ * Read-only. ++ * @advertising: Bitmask of %ADVERTISED_* flags for the link modes, ++ * physical connectors and other link features that are ++ * advertised through autonegotiation or enabled for ++ * auto-detection. ++ * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN ++ * @duplex: Duplex mode; one of %DUPLEX_* ++ * @port: Physical connector type; one of %PORT_* ++ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not ++ * applicable. For clause 45 PHYs this is the PRTAD. ++ * @transceiver: Historically used to distinguish different possible ++ * PHY types, but not in a consistent way. Deprecated. ++ * @autoneg: Enable/disable autonegotiation and auto-detection; ++ * either %AUTONEG_DISABLE or %AUTONEG_ENABLE ++ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO ++ * protocols supported by the interface; 0 if unknown. ++ * Read-only. ++ * @maxtxpkt: Historically used to report TX IRQ coalescing; now ++ * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. ++ * @maxrxpkt: Historically used to report RX IRQ coalescing; now ++ * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. ++ * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN ++ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of ++ * %ETH_TP_MDI_*. If the status is unknown or not applicable, the ++ * value will be %ETH_TP_MDI_INVALID. Read-only. ++ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of ++ * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads ++ * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. ++ * When written successfully, the link should be renegotiated if ++ * necessary. ++ * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes ++ * and other link features that the link partner advertised ++ * through autonegotiation; 0 if unknown or not applicable. ++ * Read-only. ++ * ++ * The link speed in Mbps is split between @speed and @speed_hi. Use ++ * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to ++ * access it. ++ * ++ * If autonegotiation is disabled, the speed and @duplex represent the ++ * fixed link mode and are writable if the driver supports multiple ++ * link modes. If it is enabled then they are read-only; if the link ++ * is up they represent the negotiated link mode; if the link is down, ++ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and ++ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. ++ * ++ * Some hardware interfaces may have multiple PHYs and/or physical ++ * connectors fitted or do not allow the driver to detect which are ++ * fitted. For these interfaces @port and/or @phy_address may be ++ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. ++ * Otherwise, attempts to write different values may be ignored or ++ * rejected. ++ * ++ * Users should assume that all fields not marked read-only are ++ * writable and subject to validation by the driver. They should use ++ * %ETHTOOL_GSET to get the current values before making specific ++ * changes and then applying them with %ETHTOOL_SSET. ++ * ++ * Deprecated fields should be ignored by both users and drivers. ++ */ ++struct ethtool_cmd { ++ __u32 cmd; ++ __u32 supported; ++ __u32 advertising; ++ __u16 speed; ++ __u8 duplex; ++ __u8 port; ++ __u8 phy_address; ++ __u8 transceiver; ++ __u8 autoneg; ++ __u8 mdio_support; ++ __u32 maxtxpkt; ++ __u32 maxrxpkt; ++ __u16 speed_hi; ++ __u8 eth_tp_mdix; ++ __u8 eth_tp_mdix_ctrl; ++ __u32 lp_advertising; ++ __u32 reserved[2]; ++}; ++ ++static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, ++ __u32 speed) ++{ ++ ep->speed = (__u16)(speed & 0xFFFF); ++ ep->speed_hi = (__u16)(speed >> 16); ++} ++ ++static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) ++{ ++ return (ep->speed_hi << 16) | ep->speed; ++} ++ ++/* Device supports clause 22 register access to PHY or peripherals ++ * using the interface defined in . This should not be ++ * set if there are known to be no such peripherals present or if ++ * the driver only emulates clause 22 registers for compatibility. ++ */ ++#define ETH_MDIO_SUPPORTS_C22 1 ++ ++/* Device supports clause 45 register access to PHY or peripherals ++ * using the interface defined in and . ++ * This should not be set if there are known to be no such peripherals ++ * present. ++ */ ++#define ETH_MDIO_SUPPORTS_C45 2 ++ ++#define ETHTOOL_FWVERS_LEN 32 ++#define ETHTOOL_BUSINFO_LEN 32 ++#define ETHTOOL_EROMVERS_LEN 32 ++ ++/** ++ * struct ethtool_drvinfo - general driver and device information ++ * @cmd: Command number = %ETHTOOL_GDRVINFO ++ * @driver: Driver short name. This should normally match the name ++ * in its bus driver structure (e.g. pci_driver::name). Must ++ * not be an empty string. ++ * @version: Driver version string; may be an empty string ++ * @fw_version: Firmware version string; may be an empty string ++ * @erom_version: Expansion ROM version string; may be an empty string ++ * @bus_info: Device bus address. This should match the dev_name() ++ * string for the underlying bus device, if there is one. May be ++ * an empty string. ++ * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and ++ * %ETHTOOL_SPFLAGS commands; also the number of strings in the ++ * %ETH_SS_PRIV_FLAGS set ++ * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS ++ * command; also the number of strings in the %ETH_SS_STATS set ++ * @testinfo_len: Number of results returned by the %ETHTOOL_TEST ++ * command; also the number of strings in the %ETH_SS_TEST set ++ * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM ++ * and %ETHTOOL_SEEPROM commands, in bytes ++ * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS ++ * command, in bytes ++ * ++ * Users can use the %ETHTOOL_GSSET_INFO command to get the number of ++ * strings in any string set (from Linux 2.6.34). ++ * ++ * Drivers should set at most @driver, @version, @fw_version and ++ * @bus_info in their get_drvinfo() implementation. The ethtool ++ * core fills in the other fields using other driver operations. ++ */ ++struct ethtool_drvinfo { ++ __u32 cmd; ++ char driver[32]; ++ char version[32]; ++ char fw_version[ETHTOOL_FWVERS_LEN]; ++ char bus_info[ETHTOOL_BUSINFO_LEN]; ++ char erom_version[ETHTOOL_EROMVERS_LEN]; ++ char reserved2[12]; ++ __u32 n_priv_flags; ++ __u32 n_stats; ++ __u32 testinfo_len; ++ __u32 eedump_len; ++ __u32 regdump_len; ++}; ++ ++#define SOPASS_MAX 6 ++ ++/** ++ * struct ethtool_wolinfo - Wake-On-Lan configuration ++ * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL ++ * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes. ++ * Read-only. ++ * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes. ++ * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE ++ * is set in @wolopts. ++ */ ++struct ethtool_wolinfo { ++ __u32 cmd; ++ __u32 supported; ++ __u32 wolopts; ++ __u8 sopass[SOPASS_MAX]; ++}; ++ ++/* for passing single values */ ++struct ethtool_value { ++ __u32 cmd; ++ __u32 data; ++}; ++ ++#define PFC_STORM_PREVENTION_AUTO 0xffff ++#define PFC_STORM_PREVENTION_DISABLE 0 ++ ++enum tunable_id { ++ ETHTOOL_ID_UNSPEC, ++ ETHTOOL_RX_COPYBREAK, ++ ETHTOOL_TX_COPYBREAK, ++ ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ ++ /* ++ * Add your fresh new tunable attribute above and remember to update ++ * tunable_strings[] in net/core/ethtool.c ++ */ ++ __ETHTOOL_TUNABLE_COUNT, ++}; ++ ++enum tunable_type_id { ++ ETHTOOL_TUNABLE_UNSPEC, ++ ETHTOOL_TUNABLE_U8, ++ ETHTOOL_TUNABLE_U16, ++ ETHTOOL_TUNABLE_U32, ++ ETHTOOL_TUNABLE_U64, ++ ETHTOOL_TUNABLE_STRING, ++ ETHTOOL_TUNABLE_S8, ++ ETHTOOL_TUNABLE_S16, ++ ETHTOOL_TUNABLE_S32, ++ ETHTOOL_TUNABLE_S64, ++}; ++ ++struct ethtool_tunable { ++ __u32 cmd; ++ __u32 id; ++ __u32 type_id; ++ __u32 len; ++ void *data[0]; ++}; ++ ++#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff ++#define DOWNSHIFT_DEV_DISABLE 0 ++ ++enum phy_tunable_id { ++ ETHTOOL_PHY_ID_UNSPEC, ++ ETHTOOL_PHY_DOWNSHIFT, ++ /* ++ * Add your fresh new phy tunable attribute above and remember to update ++ * phy_tunable_strings[] in net/core/ethtool.c ++ */ ++ __ETHTOOL_PHY_TUNABLE_COUNT, ++}; ++ ++/** ++ * struct ethtool_regs - hardware register dump ++ * @cmd: Command number = %ETHTOOL_GREGS ++ * @version: Dump format version. This is driver-specific and may ++ * distinguish different chips/revisions. Drivers must use new ++ * version numbers whenever the dump format changes in an ++ * incompatible way. ++ * @len: On entry, the real length of @data. On return, the number of ++ * bytes used. ++ * @data: Buffer for the register dump ++ * ++ * Users should use %ETHTOOL_GDRVINFO to find the maximum length of ++ * a register dump for the interface. They must allocate the buffer ++ * immediately following this structure. ++ */ ++struct ethtool_regs { ++ __u32 cmd; ++ __u32 version; ++ __u32 len; ++ __u8 data[0]; ++}; ++ ++/** ++ * struct ethtool_eeprom - EEPROM dump ++ * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or ++ * %ETHTOOL_SEEPROM ++ * @magic: A 'magic cookie' value to guard against accidental changes. ++ * The value passed in to %ETHTOOL_SEEPROM must match the value ++ * returned by %ETHTOOL_GEEPROM for the same device. This is ++ * unused when @cmd is %ETHTOOL_GMODULEEEPROM. ++ * @offset: Offset within the EEPROM to begin reading/writing, in bytes ++ * @len: On entry, number of bytes to read/write. On successful ++ * return, number of bytes actually read/written. In case of ++ * error, this may indicate at what point the error occurred. ++ * @data: Buffer to read/write from ++ * ++ * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find ++ * the length of an on-board or module EEPROM, respectively. They ++ * must allocate the buffer immediately following this structure. ++ */ ++struct ethtool_eeprom { ++ __u32 cmd; ++ __u32 magic; ++ __u32 offset; ++ __u32 len; ++ __u8 data[0]; ++}; ++ ++/** ++ * struct ethtool_eee - Energy Efficient Ethernet information ++ * @cmd: ETHTOOL_{G,S}EEE ++ * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations ++ * for which there is EEE support. ++ * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations ++ * advertised as eee capable. ++ * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex ++ * combinations advertised by the link partner as eee capable. ++ * @eee_active: Result of the eee auto negotiation. ++ * @eee_enabled: EEE configured mode (enabled/disabled). ++ * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given ++ * that eee was negotiated. ++ * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting ++ * its tx lpi (after reaching 'idle' state). Effective only when eee ++ * was negotiated and tx_lpi_enabled was set. ++ */ ++struct ethtool_eee { ++ __u32 cmd; ++ __u32 supported; ++ __u32 advertised; ++ __u32 lp_advertised; ++ __u32 eee_active; ++ __u32 eee_enabled; ++ __u32 tx_lpi_enabled; ++ __u32 tx_lpi_timer; ++ __u32 reserved[2]; ++}; ++ ++/** ++ * struct ethtool_modinfo - plugin module eeprom information ++ * @cmd: %ETHTOOL_GMODULEINFO ++ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx ++ * @eeprom_len: Length of the eeprom ++ * ++ * This structure is used to return the information to ++ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. ++ * The type code indicates the eeprom data format ++ */ ++struct ethtool_modinfo { ++ __u32 cmd; ++ __u32 type; ++ __u32 eeprom_len; ++ __u32 reserved[8]; ++}; ++ ++/** ++ * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates ++ * @cmd: ETHTOOL_{G,S}COALESCE ++ * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after ++ * a packet arrives. ++ * @rx_max_coalesced_frames: Maximum number of packets to receive ++ * before an RX interrupt. ++ * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that ++ * this value applies while an IRQ is being serviced by the host. ++ * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames, ++ * except that this value applies while an IRQ is being serviced ++ * by the host. ++ * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after ++ * a packet is sent. ++ * @tx_max_coalesced_frames: Maximum number of packets to be sent ++ * before a TX interrupt. ++ * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that ++ * this value applies while an IRQ is being serviced by the host. ++ * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames, ++ * except that this value applies while an IRQ is being serviced ++ * by the host. ++ * @stats_block_coalesce_usecs: How many usecs to delay in-memory ++ * statistics block updates. Some drivers do not have an ++ * in-memory statistic block, and in such cases this value is ++ * ignored. This value must not be zero. ++ * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing. ++ * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing. ++ * @pkt_rate_low: Threshold for low packet rate (packets per second). ++ * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after ++ * a packet arrives, when the packet rate is below @pkt_rate_low. ++ * @rx_max_coalesced_frames_low: Maximum number of packets to be received ++ * before an RX interrupt, when the packet rate is below @pkt_rate_low. ++ * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after ++ * a packet is sent, when the packet rate is below @pkt_rate_low. ++ * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before ++ * a TX interrupt, when the packet rate is below @pkt_rate_low. ++ * @pkt_rate_high: Threshold for high packet rate (packets per second). ++ * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after ++ * a packet arrives, when the packet rate is above @pkt_rate_high. ++ * @rx_max_coalesced_frames_high: Maximum number of packets to be received ++ * before an RX interrupt, when the packet rate is above @pkt_rate_high. ++ * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after ++ * a packet is sent, when the packet rate is above @pkt_rate_high. ++ * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before ++ * a TX interrupt, when the packet rate is above @pkt_rate_high. ++ * @rate_sample_interval: How often to do adaptive coalescing packet rate ++ * sampling, measured in seconds. Must not be zero. ++ * ++ * Each pair of (usecs, max_frames) fields specifies that interrupts ++ * should be coalesced until ++ * (usecs > 0 && time_since_first_completion >= usecs) || ++ * (max_frames > 0 && completed_frames >= max_frames) ++ * ++ * It is illegal to set both usecs and max_frames to zero as this ++ * would cause interrupts to never be generated. To disable ++ * coalescing, set usecs = 0 and max_frames = 1. ++ * ++ * Some implementations ignore the value of max_frames and use the ++ * condition time_since_first_completion >= usecs ++ * ++ * This is deprecated. Drivers for hardware that does not support ++ * counting completions should validate that max_frames == !rx_usecs. ++ * ++ * Adaptive RX/TX coalescing is an algorithm implemented by some ++ * drivers to improve latency under low packet rates and improve ++ * throughput under high packet rates. Some drivers only implement ++ * one of RX or TX adaptive coalescing. Anything not implemented by ++ * the driver causes these values to be silently ignored. ++ * ++ * When the packet rate is below @pkt_rate_high but above ++ * @pkt_rate_low (both measured in packets per second) the ++ * normal {rx,tx}_* coalescing parameters are used. ++ */ ++struct ethtool_coalesce { ++ __u32 cmd; ++ __u32 rx_coalesce_usecs; ++ __u32 rx_max_coalesced_frames; ++ __u32 rx_coalesce_usecs_irq; ++ __u32 rx_max_coalesced_frames_irq; ++ __u32 tx_coalesce_usecs; ++ __u32 tx_max_coalesced_frames; ++ __u32 tx_coalesce_usecs_irq; ++ __u32 tx_max_coalesced_frames_irq; ++ __u32 stats_block_coalesce_usecs; ++ __u32 use_adaptive_rx_coalesce; ++ __u32 use_adaptive_tx_coalesce; ++ __u32 pkt_rate_low; ++ __u32 rx_coalesce_usecs_low; ++ __u32 rx_max_coalesced_frames_low; ++ __u32 tx_coalesce_usecs_low; ++ __u32 tx_max_coalesced_frames_low; ++ __u32 pkt_rate_high; ++ __u32 rx_coalesce_usecs_high; ++ __u32 rx_max_coalesced_frames_high; ++ __u32 tx_coalesce_usecs_high; ++ __u32 tx_max_coalesced_frames_high; ++ __u32 rate_sample_interval; ++}; ++ ++/** ++ * struct ethtool_ringparam - RX/TX ring parameters ++ * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM ++ * @rx_max_pending: Maximum supported number of pending entries per ++ * RX ring. Read-only. ++ * @rx_mini_max_pending: Maximum supported number of pending entries ++ * per RX mini ring. Read-only. ++ * @rx_jumbo_max_pending: Maximum supported number of pending entries ++ * per RX jumbo ring. Read-only. ++ * @tx_max_pending: Maximum supported number of pending entries per ++ * TX ring. Read-only. ++ * @rx_pending: Current maximum number of pending entries per RX ring ++ * @rx_mini_pending: Current maximum number of pending entries per RX ++ * mini ring ++ * @rx_jumbo_pending: Current maximum number of pending entries per RX ++ * jumbo ring ++ * @tx_pending: Current maximum supported number of pending entries ++ * per TX ring ++ * ++ * If the interface does not have separate RX mini and/or jumbo rings, ++ * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0. ++ * ++ * There may also be driver-dependent minimum values for the number ++ * of entries per ring. ++ */ ++struct ethtool_ringparam { ++ __u32 cmd; ++ __u32 rx_max_pending; ++ __u32 rx_mini_max_pending; ++ __u32 rx_jumbo_max_pending; ++ __u32 tx_max_pending; ++ __u32 rx_pending; ++ __u32 rx_mini_pending; ++ __u32 rx_jumbo_pending; ++ __u32 tx_pending; ++}; ++ ++/** ++ * struct ethtool_channels - configuring number of network channel ++ * @cmd: ETHTOOL_{G,S}CHANNELS ++ * @max_rx: Read only. Maximum number of receive channel the driver support. ++ * @max_tx: Read only. Maximum number of transmit channel the driver support. ++ * @max_other: Read only. Maximum number of other channel the driver support. ++ * @max_combined: Read only. Maximum number of combined channel the driver ++ * support. Set of queues RX, TX or other. ++ * @rx_count: Valid values are in the range 1 to the max_rx. ++ * @tx_count: Valid values are in the range 1 to the max_tx. ++ * @other_count: Valid values are in the range 1 to the max_other. ++ * @combined_count: Valid values are in the range 1 to the max_combined. ++ * ++ * This can be used to configure RX, TX and other channels. ++ */ ++ ++struct ethtool_channels { ++ __u32 cmd; ++ __u32 max_rx; ++ __u32 max_tx; ++ __u32 max_other; ++ __u32 max_combined; ++ __u32 rx_count; ++ __u32 tx_count; ++ __u32 other_count; ++ __u32 combined_count; ++}; ++ ++/** ++ * struct ethtool_pauseparam - Ethernet pause (flow control) parameters ++ * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM ++ * @autoneg: Flag to enable autonegotiation of pause frame use ++ * @rx_pause: Flag to enable reception of pause frames ++ * @tx_pause: Flag to enable transmission of pause frames ++ * ++ * Drivers should reject a non-zero setting of @autoneg when ++ * autoneogotiation is disabled (or not supported) for the link. ++ * ++ * If the link is autonegotiated, drivers should use ++ * mii_advertise_flowctrl() or similar code to set the advertised ++ * pause frame capabilities based on the @rx_pause and @tx_pause flags, ++ * even if @autoneg is zero. They should also allow the advertised ++ * pause frame capabilities to be controlled directly through the ++ * advertising field of &struct ethtool_cmd. ++ * ++ * If @autoneg is non-zero, the MAC is configured to send and/or ++ * receive pause frames according to the result of autonegotiation. ++ * Otherwise, it is configured directly based on the @rx_pause and ++ * @tx_pause flags. ++ */ ++struct ethtool_pauseparam { ++ __u32 cmd; ++ __u32 autoneg; ++ __u32 rx_pause; ++ __u32 tx_pause; ++}; ++ ++#define ETH_GSTRING_LEN 32 ++ ++/** ++ * enum ethtool_stringset - string set ID ++ * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST ++ * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS ++ * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with ++ * %ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS ++ * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE; ++ * now deprecated ++ * @ETH_SS_FEATURES: Device feature names ++ * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names ++ * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS ++ * @ETH_SS_PHY_TUNABLES: PHY tunable names ++ */ ++enum ethtool_stringset { ++ ETH_SS_TEST = 0, ++ ETH_SS_STATS, ++ ETH_SS_PRIV_FLAGS, ++ ETH_SS_NTUPLE_FILTERS, ++ ETH_SS_FEATURES, ++ ETH_SS_RSS_HASH_FUNCS, ++ ETH_SS_TUNABLES, ++ ETH_SS_PHY_STATS, ++ ETH_SS_PHY_TUNABLES, ++}; ++ ++/** ++ * struct ethtool_gstrings - string set for data tagging ++ * @cmd: Command number = %ETHTOOL_GSTRINGS ++ * @string_set: String set ID; one of &enum ethtool_stringset ++ * @len: On return, the number of strings in the string set ++ * @data: Buffer for strings. Each string is null-padded to a size of ++ * %ETH_GSTRING_LEN. ++ * ++ * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in ++ * the string set. They must allocate a buffer of the appropriate ++ * size immediately following this structure. ++ */ ++struct ethtool_gstrings { ++ __u32 cmd; ++ __u32 string_set; ++ __u32 len; ++ __u8 data[0]; ++}; ++ ++/** ++ * struct ethtool_sset_info - string set information ++ * @cmd: Command number = %ETHTOOL_GSSET_INFO ++ * @sset_mask: On entry, a bitmask of string sets to query, with bits ++ * numbered according to &enum ethtool_stringset. On return, a ++ * bitmask of those string sets queried that are supported. ++ * @data: Buffer for string set sizes. On return, this contains the ++ * size of each string set that was queried and supported, in ++ * order of ID. ++ * ++ * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on ++ * return @sset_mask == 0x6 (sets 1, 2). Then @data[0] contains the ++ * size of set 1 and @data[1] contains the size of set 2. ++ * ++ * Users must allocate a buffer of the appropriate size (4 * number of ++ * sets queried) immediately following this structure. ++ */ ++struct ethtool_sset_info { ++ __u32 cmd; ++ __u32 reserved; ++ __u64 sset_mask; ++ __u32 data[0]; ++}; ++ ++/** ++ * enum ethtool_test_flags - flags definition of ethtool_test ++ * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise ++ * only online tests. ++ * @ETH_TEST_FL_FAILED: Driver set this flag if test fails. ++ * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback ++ * test. ++ * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test ++ */ ++ ++enum ethtool_test_flags { ++ ETH_TEST_FL_OFFLINE = (1 << 0), ++ ETH_TEST_FL_FAILED = (1 << 1), ++ ETH_TEST_FL_EXTERNAL_LB = (1 << 2), ++ ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3), ++}; ++ ++/** ++ * struct ethtool_test - device self-test invocation ++ * @cmd: Command number = %ETHTOOL_TEST ++ * @flags: A bitmask of flags from &enum ethtool_test_flags. Some ++ * flags may be set by the user on entry; others may be set by ++ * the driver on return. ++ * @len: On return, the number of test results ++ * @data: Array of test results ++ * ++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the ++ * number of test results that will be returned. They must allocate a ++ * buffer of the appropriate size (8 * number of results) immediately ++ * following this structure. ++ */ ++struct ethtool_test { ++ __u32 cmd; ++ __u32 flags; ++ __u32 reserved; ++ __u32 len; ++ __u64 data[0]; ++}; ++ ++/** ++ * struct ethtool_stats - device-specific statistics ++ * @cmd: Command number = %ETHTOOL_GSTATS ++ * @n_stats: On return, the number of statistics ++ * @data: Array of statistics ++ * ++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the ++ * number of statistics that will be returned. They must allocate a ++ * buffer of the appropriate size (8 * number of statistics) ++ * immediately following this structure. ++ */ ++struct ethtool_stats { ++ __u32 cmd; ++ __u32 n_stats; ++ __u64 data[0]; ++}; ++ ++/** ++ * struct ethtool_perm_addr - permanent hardware address ++ * @cmd: Command number = %ETHTOOL_GPERMADDR ++ * @size: On entry, the size of the buffer. On return, the size of the ++ * address. The command fails if the buffer is too small. ++ * @data: Buffer for the address ++ * ++ * Users must allocate the buffer immediately following this structure. ++ * A buffer size of %MAX_ADDR_LEN should be sufficient for any address ++ * type. ++ */ ++struct ethtool_perm_addr { ++ __u32 cmd; ++ __u32 size; ++ __u8 data[0]; ++}; ++ ++/* boolean flags controlling per-interface behavior characteristics. ++ * When reading, the flag indicates whether or not a certain behavior ++ * is enabled/present. When writing, the flag indicates whether ++ * or not the driver should turn on (set) or off (clear) a behavior. ++ * ++ * Some behaviors may read-only (unconditionally absent or present). ++ * If such is the case, return EINVAL in the set-flags operation if the ++ * flag differs from the read-only value. ++ */ ++enum ethtool_flags { ++ ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */ ++ ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */ ++ ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ ++ ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ ++ ETH_FLAG_RXHASH = (1 << 28), ++}; ++ ++/* The following structures are for supporting RX network flow ++ * classification and RX n-tuple configuration. Note, all multibyte ++ * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to ++ * be in network byte order. ++ */ ++ ++/** ++ * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc. ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @psrc: Source port ++ * @pdst: Destination port ++ * @tos: Type-of-service ++ * ++ * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow. ++ */ ++struct ethtool_tcpip4_spec { ++ __be32 ip4src; ++ __be32 ip4dst; ++ __be16 psrc; ++ __be16 pdst; ++ __u8 tos; ++}; ++ ++/** ++ * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4 ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @spi: Security parameters index ++ * @tos: Type-of-service ++ * ++ * This can be used to specify an IPsec transport or tunnel over IPv4. ++ */ ++struct ethtool_ah_espip4_spec { ++ __be32 ip4src; ++ __be32 ip4dst; ++ __be32 spi; ++ __u8 tos; ++}; ++ ++#define ETH_RX_NFC_IP4 1 ++ ++/** ++ * struct ethtool_usrip4_spec - general flow specification for IPv4 ++ * @ip4src: Source host ++ * @ip4dst: Destination host ++ * @l4_4_bytes: First 4 bytes of transport (layer 4) header ++ * @tos: Type-of-service ++ * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0 ++ * @proto: Transport protocol number; mask must be 0 ++ */ ++struct ethtool_usrip4_spec { ++ __be32 ip4src; ++ __be32 ip4dst; ++ __be32 l4_4_bytes; ++ __u8 tos; ++ __u8 ip_ver; ++ __u8 proto; ++}; ++ ++/** ++ * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @psrc: Source port ++ * @pdst: Destination port ++ * @tclass: Traffic Class ++ * ++ * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow. ++ */ ++struct ethtool_tcpip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be16 psrc; ++ __be16 pdst; ++ __u8 tclass; ++}; ++ ++/** ++ * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6 ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @spi: Security parameters index ++ * @tclass: Traffic Class ++ * ++ * This can be used to specify an IPsec transport or tunnel over IPv6. ++ */ ++struct ethtool_ah_espip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be32 spi; ++ __u8 tclass; ++}; ++ ++/** ++ * struct ethtool_usrip6_spec - general flow specification for IPv6 ++ * @ip6src: Source host ++ * @ip6dst: Destination host ++ * @l4_4_bytes: First 4 bytes of transport (layer 4) header ++ * @tclass: Traffic Class ++ * @l4_proto: Transport protocol number (nexthdr after any Extension Headers) ++ */ ++struct ethtool_usrip6_spec { ++ __be32 ip6src[4]; ++ __be32 ip6dst[4]; ++ __be32 l4_4_bytes; ++ __u8 tclass; ++ __u8 l4_proto; ++}; ++ ++union ethtool_flow_union { ++ struct ethtool_tcpip4_spec tcp_ip4_spec; ++ struct ethtool_tcpip4_spec udp_ip4_spec; ++ struct ethtool_tcpip4_spec sctp_ip4_spec; ++ struct ethtool_ah_espip4_spec ah_ip4_spec; ++ struct ethtool_ah_espip4_spec esp_ip4_spec; ++ struct ethtool_usrip4_spec usr_ip4_spec; ++ struct ethtool_tcpip6_spec tcp_ip6_spec; ++ struct ethtool_tcpip6_spec udp_ip6_spec; ++ struct ethtool_tcpip6_spec sctp_ip6_spec; ++ struct ethtool_ah_espip6_spec ah_ip6_spec; ++ struct ethtool_ah_espip6_spec esp_ip6_spec; ++ struct ethtool_usrip6_spec usr_ip6_spec; ++ struct ethhdr ether_spec; ++ __u8 hdata[52]; ++}; ++ ++/** ++ * struct ethtool_flow_ext - additional RX flow fields ++ * @h_dest: destination MAC address ++ * @vlan_etype: VLAN EtherType ++ * @vlan_tci: VLAN tag control information ++ * @data: user defined data ++ * ++ * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT ++ * is set in &struct ethtool_rx_flow_spec @flow_type. ++ * @h_dest is valid if %FLOW_MAC_EXT is set. ++ */ ++struct ethtool_flow_ext { ++ __u8 padding[2]; ++ unsigned char h_dest[ETH_ALEN]; ++ __be16 vlan_etype; ++ __be16 vlan_tci; ++ __be32 data[2]; ++}; ++ ++/** ++ * struct ethtool_rx_flow_spec - classification rule for RX flows ++ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW ++ * @h_u: Flow fields to match (dependent on @flow_type) ++ * @h_ext: Additional fields to match ++ * @m_u: Masks for flow field bits to be matched ++ * @m_ext: Masks for additional field bits to be matched ++ * Note, all additional fields must be ignored unless @flow_type ++ * includes the %FLOW_EXT or %FLOW_MAC_EXT flag ++ * (see &struct ethtool_flow_ext description). ++ * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC ++ * if packets should be discarded, or %RX_CLS_FLOW_WAKE if the ++ * packets should be used for Wake-on-LAN with %WAKE_FILTER ++ * @location: Location of rule in the table. Locations must be ++ * numbered such that a flow matching multiple rules will be ++ * classified according to the first (lowest numbered) rule. ++ */ ++struct ethtool_rx_flow_spec { ++ __u32 flow_type; ++ union ethtool_flow_union h_u; ++ struct ethtool_flow_ext h_ext; ++ union ethtool_flow_union m_u; ++ struct ethtool_flow_ext m_ext; ++ __u64 ring_cookie; ++ __u32 location; ++}; ++ ++/* How rings are laid out when accessing virtual functions or ++ * offloaded queues is device specific. To allow users to do flow ++ * steering and specify these queues the ring cookie is partitioned ++ * into a 32bit queue index with an 8 bit virtual function id. ++ * This also leaves the 3bytes for further specifiers. It is possible ++ * future devices may support more than 256 virtual functions if ++ * devices start supporting PCIe w/ARI. However at the moment I ++ * do not know of any devices that support this so I do not reserve ++ * space for this at this time. If a future patch consumes the next ++ * byte it should be aware of this possibility. ++ */ ++#define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL ++#define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL ++#define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32 ++static inline __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie) ++{ ++ return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie; ++} ++ ++static inline __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie) ++{ ++ return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >> ++ ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF; ++} ++ ++/** ++ * struct ethtool_rxnfc - command to get or set RX flow classification rules ++ * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH, ++ * %ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE, ++ * %ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS ++ * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW ++ * @data: Command-dependent value ++ * @fs: Flow classification rule ++ * @rss_context: RSS context to be affected ++ * @rule_cnt: Number of rules to be affected ++ * @rule_locs: Array of used rule locations ++ * ++ * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating ++ * the fields included in the flow hash, e.g. %RXH_IP_SRC. The following ++ * structure fields must not be used, except that if @flow_type includes ++ * the %FLOW_RSS flag, then @rss_context determines which RSS context to ++ * act on. ++ * ++ * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues ++ * on return. ++ * ++ * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined ++ * rules on return. If @data is non-zero on return then it is the ++ * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the ++ * driver supports any special location values. If that flag is not ++ * set in @data then special location values should not be used. ++ * ++ * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an ++ * existing rule on entry and @fs contains the rule on return; if ++ * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is ++ * filled with the RSS context ID associated with the rule. ++ * ++ * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the ++ * user buffer for @rule_locs on entry. On return, @data is the size ++ * of the rule table, @rule_cnt is the number of defined rules, and ++ * @rule_locs contains the locations of the defined rules. Drivers ++ * must use the second parameter to get_rxnfc() instead of @rule_locs. ++ * ++ * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. ++ * @fs.@location either specifies the location to use or is a special ++ * location value with %RX_CLS_LOC_SPECIAL flag set. On return, ++ * @fs.@location is the actual rule location. If @fs.@flow_type ++ * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to ++ * use for flow spreading traffic which matches this rule. The value ++ * from the rxfh indirection table will be added to @fs.@ring_cookie ++ * to choose which ring to deliver to. ++ * ++ * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an ++ * existing rule on entry. ++ * ++ * A driver supporting the special location values for ++ * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused ++ * location, and may remove a rule at a later location (lower ++ * priority) that matches exactly the same set of flows. The special ++ * values are %RX_CLS_LOC_ANY, selecting any location; ++ * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum ++ * priority); and %RX_CLS_LOC_LAST, selecting the last suitable ++ * location (minimum priority). Additional special values may be ++ * defined in future and drivers must return -%EINVAL for any ++ * unrecognised value. ++ */ ++struct ethtool_rxnfc { ++ __u32 cmd; ++ __u32 flow_type; ++ __u64 data; ++ struct ethtool_rx_flow_spec fs; ++ union { ++ __u32 rule_cnt; ++ __u32 rss_context; ++ }; ++ __u32 rule_locs[0]; ++}; ++ ++ ++/** ++ * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection ++ * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR ++ * @size: On entry, the array size of the user buffer, which may be zero. ++ * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware ++ * indirection table. ++ * @ring_index: RX ring/queue index for each hash value ++ * ++ * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size ++ * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means ++ * the table should be reset to default values. This last feature ++ * is not supported by the original implementations. ++ */ ++struct ethtool_rxfh_indir { ++ __u32 cmd; ++ __u32 size; ++ __u32 ring_index[0]; ++}; ++ ++/** ++ * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key. ++ * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH ++ * @rss_context: RSS context identifier. Context 0 is the default for normal ++ * traffic; other contexts can be referenced as the destination for RX flow ++ * classification rules. %ETH_RXFH_CONTEXT_ALLOC is used with command ++ * %ETHTOOL_SRSSH to allocate a new RSS context; on return this field will ++ * contain the ID of the newly allocated context. ++ * @indir_size: On entry, the array size of the user buffer for the ++ * indirection table, which may be zero, or (for %ETHTOOL_SRSSH), ++ * %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH, ++ * the array size of the hardware indirection table. ++ * @key_size: On entry, the array size of the user buffer for the hash key, ++ * which may be zero. On return from %ETHTOOL_GRSSH, the size of the ++ * hardware hash key. ++ * @hfunc: Defines the current RSS hash function used by HW (or to be set to). ++ * Valid values are one of the %ETH_RSS_HASH_*. ++ * @rsvd: Reserved for future extensions. ++ * @rss_config: RX ring/queue index for each hash value i.e., indirection table ++ * of @indir_size __u32 elements, followed by hash key of @key_size ++ * bytes. ++ * ++ * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the ++ * size should be returned. For %ETHTOOL_SRSSH, an @indir_size of ++ * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested ++ * and a @indir_size of zero means the indir table should be reset to default ++ * values (if @rss_context == 0) or that the RSS context should be deleted. ++ * An hfunc of zero means that hash function setting is not requested. ++ */ ++struct ethtool_rxfh { ++ __u32 cmd; ++ __u32 rss_context; ++ __u32 indir_size; ++ __u32 key_size; ++ __u8 hfunc; ++ __u8 rsvd8[3]; ++ __u32 rsvd32; ++ __u32 rss_config[0]; ++}; ++#define ETH_RXFH_CONTEXT_ALLOC 0xffffffff ++#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff ++ ++/** ++ * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter ++ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW ++ * @h_u: Flow field values to match (dependent on @flow_type) ++ * @m_u: Masks for flow field value bits to be ignored ++ * @vlan_tag: VLAN tag to match ++ * @vlan_tag_mask: Mask for VLAN tag bits to be ignored ++ * @data: Driver-dependent data to match ++ * @data_mask: Mask for driver-dependent data bits to be ignored ++ * @action: RX ring/queue index to deliver to (non-negative) or other action ++ * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) ++ * ++ * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where ++ * a field value and mask are both zero this is treated as if all mask ++ * bits are set i.e. the field is ignored. ++ */ ++struct ethtool_rx_ntuple_flow_spec { ++ __u32 flow_type; ++ union { ++ struct ethtool_tcpip4_spec tcp_ip4_spec; ++ struct ethtool_tcpip4_spec udp_ip4_spec; ++ struct ethtool_tcpip4_spec sctp_ip4_spec; ++ struct ethtool_ah_espip4_spec ah_ip4_spec; ++ struct ethtool_ah_espip4_spec esp_ip4_spec; ++ struct ethtool_usrip4_spec usr_ip4_spec; ++ struct ethhdr ether_spec; ++ __u8 hdata[72]; ++ } h_u, m_u; ++ ++ __u16 vlan_tag; ++ __u16 vlan_tag_mask; ++ __u64 data; ++ __u64 data_mask; ++ ++ __s32 action; ++#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ ++#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ ++}; ++ ++/** ++ * struct ethtool_rx_ntuple - command to set or clear RX flow filter ++ * @cmd: Command number - %ETHTOOL_SRXNTUPLE ++ * @fs: Flow filter specification ++ */ ++struct ethtool_rx_ntuple { ++ __u32 cmd; ++ struct ethtool_rx_ntuple_flow_spec fs; ++}; ++ ++#define ETHTOOL_FLASH_MAX_FILENAME 128 ++enum ethtool_flash_op_type { ++ ETHTOOL_FLASH_ALL_REGIONS = 0, ++}; ++ ++/* for passing firmware flashing related parameters */ ++struct ethtool_flash { ++ __u32 cmd; ++ __u32 region; ++ char data[ETHTOOL_FLASH_MAX_FILENAME]; ++}; ++ ++/** ++ * struct ethtool_dump - used for retrieving, setting device dump ++ * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or ++ * %ETHTOOL_SET_DUMP ++ * @version: FW version of the dump, filled in by driver ++ * @flag: driver dependent flag for dump setting, filled in by driver during ++ * get and filled in by ethtool for set operation. ++ * flag must be initialized by macro ETH_FW_DUMP_DISABLE value when ++ * firmware dump is disabled. ++ * @len: length of dump data, used as the length of the user buffer on entry to ++ * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver ++ * for %ETHTOOL_GET_DUMP_FLAG command ++ * @data: data collected for get dump data operation ++ */ ++struct ethtool_dump { ++ __u32 cmd; ++ __u32 version; ++ __u32 flag; ++ __u32 len; ++ __u8 data[0]; ++}; ++ ++#define ETH_FW_DUMP_DISABLE 0 ++ ++/* for returning and changing feature sets */ ++ ++/** ++ * struct ethtool_get_features_block - block with state of 32 features ++ * @available: mask of changeable features ++ * @requested: mask of features requested to be enabled if possible ++ * @active: mask of currently enabled features ++ * @never_changed: mask of features not changeable for any device ++ */ ++struct ethtool_get_features_block { ++ __u32 available; ++ __u32 requested; ++ __u32 active; ++ __u32 never_changed; ++}; ++ ++/** ++ * struct ethtool_gfeatures - command to get state of device's features ++ * @cmd: command number = %ETHTOOL_GFEATURES ++ * @size: On entry, the number of elements in the features[] array; ++ * on return, the number of elements in features[] needed to hold ++ * all features ++ * @features: state of features ++ */ ++struct ethtool_gfeatures { ++ __u32 cmd; ++ __u32 size; ++ struct ethtool_get_features_block features[0]; ++}; ++ ++/** ++ * struct ethtool_set_features_block - block with request for 32 features ++ * @valid: mask of features to be changed ++ * @requested: values of features to be changed ++ */ ++struct ethtool_set_features_block { ++ __u32 valid; ++ __u32 requested; ++}; ++ ++/** ++ * struct ethtool_sfeatures - command to request change in device's features ++ * @cmd: command number = %ETHTOOL_SFEATURES ++ * @size: array size of the features[] array ++ * @features: feature change masks ++ */ ++struct ethtool_sfeatures { ++ __u32 cmd; ++ __u32 size; ++ struct ethtool_set_features_block features[0]; ++}; ++ ++/** ++ * struct ethtool_ts_info - holds a device's timestamping and PHC association ++ * @cmd: command number = %ETHTOOL_GET_TS_INFO ++ * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags ++ * @phc_index: device index of the associated PHC, or -1 if there is none ++ * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values ++ * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values ++ * ++ * The bits in the 'tx_types' and 'rx_filters' fields correspond to ++ * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, ++ * respectively. For example, if the device supports HWTSTAMP_TX_ON, ++ * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set. ++ * ++ * Drivers should only report the filters they actually support without ++ * upscaling in the SIOCSHWTSTAMP ioctl. If the SIOCSHWSTAMP request for ++ * HWTSTAMP_FILTER_V1_SYNC is supported by HWTSTAMP_FILTER_V1_EVENT, then the ++ * driver should only report HWTSTAMP_FILTER_V1_EVENT in this op. ++ */ ++struct ethtool_ts_info { ++ __u32 cmd; ++ __u32 so_timestamping; ++ __s32 phc_index; ++ __u32 tx_types; ++ __u32 tx_reserved[3]; ++ __u32 rx_filters; ++ __u32 rx_reserved[3]; ++}; ++ ++/* ++ * %ETHTOOL_SFEATURES changes features present in features[].valid to the ++ * values of corresponding bits in features[].requested. Bits in .requested ++ * not set in .valid or not changeable are ignored. ++ * ++ * Returns %EINVAL when .valid contains undefined or never-changeable bits ++ * or size is not equal to required number of features words (32-bit blocks). ++ * Returns >= 0 if request was completed; bits set in the value mean: ++ * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not ++ * changeable (not present in %ETHTOOL_GFEATURES' features[].available) ++ * those bits were ignored. ++ * %ETHTOOL_F_WISH - some or all changes requested were recorded but the ++ * resulting state of bits masked by .valid is not equal to .requested. ++ * Probably there are other device-specific constraints on some features ++ * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered ++ * here as though ignored bits were cleared. ++ * %ETHTOOL_F_COMPAT - some or all changes requested were made by calling ++ * compatibility functions. Requested offload state cannot be properly ++ * managed by kernel. ++ * ++ * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of ++ * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands ++ * for ETH_SS_FEATURES string set. First entry in the table corresponds to least ++ * significant bit in features[0] fields. Empty strings mark undefined features. ++ */ ++enum ethtool_sfeatures_retval_bits { ++ ETHTOOL_F_UNSUPPORTED__BIT, ++ ETHTOOL_F_WISH__BIT, ++ ETHTOOL_F_COMPAT__BIT, ++}; ++ ++#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT) ++#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT) ++#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT) ++ ++#define MAX_NUM_QUEUE 4096 ++ ++/** ++ * struct ethtool_per_queue_op - apply sub command to the queues in mask. ++ * @cmd: ETHTOOL_PERQUEUE ++ * @sub_command: the sub command which apply to each queues ++ * @queue_mask: Bitmap of the queues which sub command apply to ++ * @data: A complete command structure following for each of the queues addressed ++ */ ++struct ethtool_per_queue_op { ++ __u32 cmd; ++ __u32 sub_command; ++ __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)]; ++ char data[]; ++}; ++ ++/** ++ * struct ethtool_fecparam - Ethernet forward error correction(fec) parameters ++ * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM ++ * @active_fec: FEC mode which is active on porte ++ * @fec: Bitmask of supported/configured FEC modes ++ * @rsvd: Reserved for future extensions. i.e FEC bypass feature. ++ * ++ * Drivers should reject a non-zero setting of @autoneg when ++ * autoneogotiation is disabled (or not supported) for the link. ++ * ++ */ ++struct ethtool_fecparam { ++ __u32 cmd; ++ /* bitmask of FEC modes */ ++ __u32 active_fec; ++ __u32 fec; ++ __u32 reserved; ++}; ++ ++/** ++ * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration ++ * @ETHTOOL_FEC_NONE: FEC mode configuration is not supported ++ * @ETHTOOL_FEC_AUTO: Default/Best FEC mode provided by driver ++ * @ETHTOOL_FEC_OFF: No FEC Mode ++ * @ETHTOOL_FEC_RS: Reed-Solomon Forward Error Detection mode ++ * @ETHTOOL_FEC_BASER: Base-R/Reed-Solomon Forward Error Detection mode ++ */ ++enum ethtool_fec_config_bits { ++ ETHTOOL_FEC_NONE_BIT, ++ ETHTOOL_FEC_AUTO_BIT, ++ ETHTOOL_FEC_OFF_BIT, ++ ETHTOOL_FEC_RS_BIT, ++ ETHTOOL_FEC_BASER_BIT, ++}; ++ ++#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT) ++#define ETHTOOL_FEC_AUTO (1 << ETHTOOL_FEC_AUTO_BIT) ++#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT) ++#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT) ++#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT) ++ ++/* CMDs currently supported */ ++#define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings. ++ * Please use ETHTOOL_GLINKSETTINGS ++ */ ++#define ETHTOOL_SSET 0x00000002 /* DEPRECATED, Set settings. ++ * Please use ETHTOOL_SLINKSETTINGS ++ */ ++#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ ++#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */ ++#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ ++#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */ ++#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ ++#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */ ++#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */ ++/* Get link status for host, i.e. whether the interface *and* the ++ * physical port (if there is one) are up (ethtool_value). */ ++#define ETHTOOL_GLINK 0x0000000a ++#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ ++#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ ++#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ ++#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ ++#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ ++#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters. */ ++#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ ++#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ ++#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ ++#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ ++#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ ++#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ ++#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable ++ * (ethtool_value) */ ++#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable ++ * (ethtool_value). */ ++#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test. */ ++#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ ++#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ ++#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ ++#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ ++#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ ++#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ ++#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ ++#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ ++#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ ++#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ ++#define ETHTOOL_GFLAGS 0x00000025 /* Get flags bitmap(ethtool_value) */ ++#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */ ++#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */ ++#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */ ++ ++#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */ ++#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ ++#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ ++#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ ++#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */ ++#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */ ++#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */ ++#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */ ++#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */ ++#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */ ++#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ ++#define ETHTOOL_RESET 0x00000034 /* Reset hardware */ ++#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ ++#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */ ++#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */ ++#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ ++#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ ++ ++#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ ++#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ ++#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ ++#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ ++#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ ++#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ ++#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ ++#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */ ++#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ ++#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ ++#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */ ++#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */ ++ ++#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */ ++#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */ ++#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */ ++#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */ ++#define ETHTOOL_GPHYSTATS 0x0000004a /* get PHY-specific statistics */ ++ ++#define ETHTOOL_PERQUEUE 0x0000004b /* Set per queue options */ ++ ++#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */ ++#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */ ++#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */ ++#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */ ++#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */ ++#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */ ++ ++/* compatibility with older code */ ++#define SPARC_ETH_GSET ETHTOOL_GSET ++#define SPARC_ETH_SSET ETHTOOL_SSET ++ ++/* Link mode bit indices */ ++enum ethtool_link_mode_bit_indices { ++ ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, ++ ETHTOOL_LINK_MODE_10baseT_Full_BIT = 1, ++ ETHTOOL_LINK_MODE_100baseT_Half_BIT = 2, ++ ETHTOOL_LINK_MODE_100baseT_Full_BIT = 3, ++ ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 4, ++ ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 5, ++ ETHTOOL_LINK_MODE_Autoneg_BIT = 6, ++ ETHTOOL_LINK_MODE_TP_BIT = 7, ++ ETHTOOL_LINK_MODE_AUI_BIT = 8, ++ ETHTOOL_LINK_MODE_MII_BIT = 9, ++ ETHTOOL_LINK_MODE_FIBRE_BIT = 10, ++ ETHTOOL_LINK_MODE_BNC_BIT = 11, ++ ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 12, ++ ETHTOOL_LINK_MODE_Pause_BIT = 13, ++ ETHTOOL_LINK_MODE_Asym_Pause_BIT = 14, ++ ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 15, ++ ETHTOOL_LINK_MODE_Backplane_BIT = 16, ++ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 17, ++ ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 18, ++ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 19, ++ ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 20, ++ ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21, ++ ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 22, ++ ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 23, ++ ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 24, ++ ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 25, ++ ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 26, ++ ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 27, ++ ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28, ++ ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29, ++ ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30, ++ ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 31, ++ ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 32, ++ ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 33, ++ ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34, ++ ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35, ++ ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 36, ++ ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 37, ++ ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 38, ++ ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39, ++ ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40, ++ ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41, ++ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42, ++ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43, ++ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44, ++ ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45, ++ ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46, ++ ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47, ++ ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48, ++ ++ ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49, ++ ETHTOOL_LINK_MODE_FEC_RS_BIT = 50, ++ ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51, ++ ++ /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit ++ * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_* ++ * macro for bits > 31. The only way to use indices > 31 is to ++ * use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. ++ */ ++ ++ __ETHTOOL_LINK_MODE_LAST ++ = ETHTOOL_LINK_MODE_FEC_BASER_BIT, ++}; ++ ++#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) \ ++ (1UL << (ETHTOOL_LINK_MODE_ ## base_name ## _BIT)) ++ ++/* DEPRECATED macros. Please migrate to ++ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT ++ * define any new SUPPORTED_* macro for bits > 31. ++ */ ++#define SUPPORTED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) ++#define SUPPORTED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) ++#define SUPPORTED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) ++#define SUPPORTED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) ++#define SUPPORTED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) ++#define SUPPORTED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) ++#define SUPPORTED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) ++#define SUPPORTED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) ++#define SUPPORTED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) ++#define SUPPORTED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) ++#define SUPPORTED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) ++#define SUPPORTED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) ++#define SUPPORTED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) ++#define SUPPORTED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) ++#define SUPPORTED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) ++#define SUPPORTED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) ++#define SUPPORTED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) ++#define SUPPORTED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) ++#define SUPPORTED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) ++#define SUPPORTED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) ++#define SUPPORTED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) ++#define SUPPORTED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) ++#define SUPPORTED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) ++#define SUPPORTED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) ++#define SUPPORTED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) ++#define SUPPORTED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) ++#define SUPPORTED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) ++#define SUPPORTED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) ++#define SUPPORTED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) ++#define SUPPORTED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) ++#define SUPPORTED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) ++/* Please do not define any new SUPPORTED_* macro for bits > 31, see ++ * notice above. ++ */ ++ ++/* ++ * DEPRECATED macros. Please migrate to ++ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT ++ * define any new ADERTISE_* macro for bits > 31. ++ */ ++#define ADVERTISED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) ++#define ADVERTISED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) ++#define ADVERTISED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) ++#define ADVERTISED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) ++#define ADVERTISED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) ++#define ADVERTISED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) ++#define ADVERTISED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) ++#define ADVERTISED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) ++#define ADVERTISED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) ++#define ADVERTISED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) ++#define ADVERTISED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) ++#define ADVERTISED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) ++#define ADVERTISED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) ++#define ADVERTISED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) ++#define ADVERTISED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) ++#define ADVERTISED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) ++#define ADVERTISED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) ++#define ADVERTISED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) ++#define ADVERTISED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) ++#define ADVERTISED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) ++#define ADVERTISED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) ++#define ADVERTISED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) ++#define ADVERTISED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) ++#define ADVERTISED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) ++#define ADVERTISED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) ++#define ADVERTISED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) ++#define ADVERTISED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) ++#define ADVERTISED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) ++#define ADVERTISED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) ++#define ADVERTISED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) ++#define ADVERTISED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) ++/* Please do not define any new ADVERTISED_* macro for bits > 31, see ++ * notice above. ++ */ ++ ++/* The following are all involved in forcing a particular link ++ * mode for the device for setting things. When getting the ++ * devices settings, these indicate the current mode and whether ++ * it was forced up into this mode or autonegotiated. ++ */ ++ ++/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. ++ * Update drivers/net/phy/phy.c:phy_speed_to_str() and ++ * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values. ++ */ ++#define SPEED_10 10 ++#define SPEED_100 100 ++#define SPEED_1000 1000 ++#define SPEED_2500 2500 ++#define SPEED_5000 5000 ++#define SPEED_10000 10000 ++#define SPEED_14000 14000 ++#define SPEED_20000 20000 ++#define SPEED_25000 25000 ++#define SPEED_40000 40000 ++#define SPEED_50000 50000 ++#define SPEED_56000 56000 ++#define SPEED_100000 100000 ++ ++#define SPEED_UNKNOWN ((__u32) -1) ++ ++static inline int ethtool_validate_speed(__u32 speed) ++{ ++ return speed <= INT_MAX || speed == SPEED_UNKNOWN; ++} ++ ++/* Duplex, half or full. */ ++#define DUPLEX_HALF 0x00 ++#define DUPLEX_FULL 0x01 ++#define DUPLEX_UNKNOWN 0xff ++ ++static inline int ethtool_validate_duplex(__u8 duplex) ++{ ++ switch (duplex) { ++ case DUPLEX_HALF: ++ case DUPLEX_FULL: ++ case DUPLEX_UNKNOWN: ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* Which connector port. */ ++#define PORT_TP 0x00 ++#define PORT_AUI 0x01 ++#define PORT_MII 0x02 ++#define PORT_FIBRE 0x03 ++#define PORT_BNC 0x04 ++#define PORT_DA 0x05 ++#define PORT_NONE 0xef ++#define PORT_OTHER 0xff ++ ++/* Which transceiver to use. */ ++#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */ ++#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */ ++#define XCVR_DUMMY1 0x02 ++#define XCVR_DUMMY2 0x03 ++#define XCVR_DUMMY3 0x04 ++ ++/* Enable or disable autonegotiation. */ ++#define AUTONEG_DISABLE 0x00 ++#define AUTONEG_ENABLE 0x01 ++ ++/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then ++ * the driver is required to renegotiate link ++ */ ++#define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ ++#define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ ++#define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ ++#define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ ++ ++/* Wake-On-Lan options. */ ++#define WAKE_PHY (1 << 0) ++#define WAKE_UCAST (1 << 1) ++#define WAKE_MCAST (1 << 2) ++#define WAKE_BCAST (1 << 3) ++#define WAKE_ARP (1 << 4) ++#define WAKE_MAGIC (1 << 5) ++#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ ++#define WAKE_FILTER (1 << 7) ++ ++/* L2-L4 network traffic flow types */ ++#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ ++#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ ++#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ ++#define AH_ESP_V4_FLOW 0x04 /* hash only */ ++#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ ++#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ ++#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ ++#define AH_ESP_V6_FLOW 0x08 /* hash only */ ++#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ ++#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ ++#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ ++#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ ++#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ ++#define IP_USER_FLOW IPV4_USER_FLOW ++#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ ++#define IPV4_FLOW 0x10 /* hash only */ ++#define IPV6_FLOW 0x11 /* hash only */ ++#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ ++/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ ++#define FLOW_EXT 0x80000000 ++#define FLOW_MAC_EXT 0x40000000 ++/* Flag to enable RSS spreading of traffic matching rule (nfc only) */ ++#define FLOW_RSS 0x20000000 ++ ++/* L3-L4 network traffic flow hash options */ ++#define RXH_L2DA (1 << 1) ++#define RXH_VLAN (1 << 2) ++#define RXH_L3_PROTO (1 << 3) ++#define RXH_IP_SRC (1 << 4) ++#define RXH_IP_DST (1 << 5) ++#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ ++#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ ++#define RXH_DISCARD (1 << 31) ++ ++#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL ++#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL ++ ++/* Special RX classification rule insert location values */ ++#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ ++#define RX_CLS_LOC_ANY 0xffffffff ++#define RX_CLS_LOC_FIRST 0xfffffffe ++#define RX_CLS_LOC_LAST 0xfffffffd ++ ++/* EEPROM Standards for plug in modules */ ++#define ETH_MODULE_SFF_8079 0x1 ++#define ETH_MODULE_SFF_8079_LEN 256 ++#define ETH_MODULE_SFF_8472 0x2 ++#define ETH_MODULE_SFF_8472_LEN 512 ++#define ETH_MODULE_SFF_8636 0x3 ++#define ETH_MODULE_SFF_8636_LEN 256 ++#define ETH_MODULE_SFF_8436 0x4 ++#define ETH_MODULE_SFF_8436_LEN 256 ++ ++/* Reset flags */ ++/* The reset() operation must clear the flags for the components which ++ * were actually reset. On successful return, the flags indicate the ++ * components which were not reset, either because they do not exist ++ * in the hardware or because they cannot be reset independently. The ++ * driver must never reset any components that were not requested. ++ */ ++enum ethtool_reset_flags { ++ /* These flags represent components dedicated to the interface ++ * the command is addressed to. Shift any flag left by ++ * ETH_RESET_SHARED_SHIFT to reset a shared component of the ++ * same type. ++ */ ++ ETH_RESET_MGMT = 1 << 0, /* Management processor */ ++ ETH_RESET_IRQ = 1 << 1, /* Interrupt requester */ ++ ETH_RESET_DMA = 1 << 2, /* DMA engine */ ++ ETH_RESET_FILTER = 1 << 3, /* Filtering/flow direction */ ++ ETH_RESET_OFFLOAD = 1 << 4, /* Protocol offload */ ++ ETH_RESET_MAC = 1 << 5, /* Media access controller */ ++ ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */ ++ ETH_RESET_RAM = 1 << 7, /* RAM shared between ++ * multiple components */ ++ ETH_RESET_AP = 1 << 8, /* Application processor */ ++ ++ ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to ++ * this interface */ ++ ETH_RESET_ALL = 0xffffffff, /* All components used by this ++ * interface, even if shared */ ++}; ++#define ETH_RESET_SHARED_SHIFT 16 ++ ++ ++/** ++ * struct ethtool_link_settings - link control and status ++ * ++ * IMPORTANT, Backward compatibility notice: When implementing new ++ * user-space tools, please first try %ETHTOOL_GLINKSETTINGS, and ++ * if it succeeds use %ETHTOOL_SLINKSETTINGS to change link ++ * settings; do not use %ETHTOOL_SSET if %ETHTOOL_GLINKSETTINGS ++ * succeeded: stick to %ETHTOOL_GLINKSETTINGS/%SLINKSETTINGS in ++ * that case. Conversely, if %ETHTOOL_GLINKSETTINGS fails, use ++ * %ETHTOOL_GSET to query and %ETHTOOL_SSET to change link ++ * settings; do not use %ETHTOOL_SLINKSETTINGS if ++ * %ETHTOOL_GLINKSETTINGS failed: stick to ++ * %ETHTOOL_GSET/%ETHTOOL_SSET in that case. ++ * ++ * @cmd: Command number = %ETHTOOL_GLINKSETTINGS or %ETHTOOL_SLINKSETTINGS ++ * @speed: Link speed (Mbps) ++ * @duplex: Duplex mode; one of %DUPLEX_* ++ * @port: Physical connector type; one of %PORT_* ++ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not ++ * applicable. For clause 45 PHYs this is the PRTAD. ++ * @autoneg: Enable/disable autonegotiation and auto-detection; ++ * either %AUTONEG_DISABLE or %AUTONEG_ENABLE ++ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO ++ * protocols supported by the interface; 0 if unknown. ++ * Read-only. ++ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of ++ * %ETH_TP_MDI_*. If the status is unknown or not applicable, the ++ * value will be %ETH_TP_MDI_INVALID. Read-only. ++ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of ++ * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads ++ * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. ++ * When written successfully, the link should be renegotiated if ++ * necessary. ++ * @link_mode_masks_nwords: Number of 32-bit words for each of the ++ * supported, advertising, lp_advertising link mode bitmaps. For ++ * %ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user ++ * (>= 0); on return, if handshake in progress, negative if ++ * request size unsupported by kernel: absolute value indicates ++ * kernel expected size and all the other fields but cmd ++ * are 0; otherwise (handshake completed), strictly positive ++ * to indicate size used by kernel and cmd field stays ++ * %ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For ++ * %ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive ++ * value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise ++ * refused. For drivers: ignore this field (use kernel's ++ * __ETHTOOL_LINK_MODE_MASK_NBITS instead), any change to it will ++ * be overwritten by kernel. ++ * @supported: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, physical ++ * connectors and other link features for which the interface ++ * supports autonegotiation or auto-detection. Read-only. ++ * @advertising: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, physical ++ * connectors and other link features that are advertised through ++ * autonegotiation or enabled for auto-detection. ++ * @lp_advertising: Bitmap with each bit meaning given by ++ * %ethtool_link_mode_bit_indices for the link modes, and other ++ * link features that the link partner advertised through ++ * autonegotiation; 0 if unknown or not applicable. Read-only. ++ * @transceiver: Used to distinguish different possible PHY types, ++ * reported consistently by PHYLIB. Read-only. ++ * ++ * If autonegotiation is disabled, the speed and @duplex represent the ++ * fixed link mode and are writable if the driver supports multiple ++ * link modes. If it is enabled then they are read-only; if the link ++ * is up they represent the negotiated link mode; if the link is down, ++ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and ++ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. ++ * ++ * Some hardware interfaces may have multiple PHYs and/or physical ++ * connectors fitted or do not allow the driver to detect which are ++ * fitted. For these interfaces @port and/or @phy_address may be ++ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. ++ * Otherwise, attempts to write different values may be ignored or ++ * rejected. ++ * ++ * Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt ++ * are not available in %ethtool_link_settings. These fields will be ++ * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will ++ * fail if any of them is set to non-zero value. ++ * ++ * Users should assume that all fields not marked read-only are ++ * writable and subject to validation by the driver. They should use ++ * %ETHTOOL_GLINKSETTINGS to get the current values before making specific ++ * changes and then applying them with %ETHTOOL_SLINKSETTINGS. ++ * ++ * Drivers that implement %get_link_ksettings and/or ++ * %set_link_ksettings should ignore the @cmd ++ * and @link_mode_masks_nwords fields (any change to them overwritten ++ * by kernel), and rely only on kernel's internal ++ * %__ETHTOOL_LINK_MODE_MASK_NBITS and ++ * %ethtool_link_mode_mask_t. Drivers that implement ++ * %set_link_ksettings() should validate all fields other than @cmd ++ * and @link_mode_masks_nwords that are not described as read-only or ++ * deprecated, and must ignore all fields described as read-only. ++ */ ++struct ethtool_link_settings { ++ __u32 cmd; ++ __u32 speed; ++ __u8 duplex; ++ __u8 port; ++ __u8 phy_address; ++ __u8 autoneg; ++ __u8 mdio_support; ++ __u8 eth_tp_mdix; ++ __u8 eth_tp_mdix_ctrl; ++ __s8 link_mode_masks_nwords; ++ __u8 transceiver; ++ __u8 reserved1[3]; ++ __u32 reserved[7]; ++ __u32 link_mode_masks[0]; ++ /* layout of link_mode_masks fields: ++ * __u32 map_supported[link_mode_masks_nwords]; ++ * __u32 map_advertising[link_mode_masks_nwords]; ++ * __u32 map_lp_advertising[link_mode_masks_nwords]; ++ */ ++}; ++#endif /* _UAPI_LINUX_ETHTOOL_H */ +diff --git a/src/shared/linux/libbpf.h b/src/shared/linux/libbpf.h +deleted file mode 100644 +index 391eee5a4e3..00000000000 +--- a/src/shared/linux/libbpf.h ++++ /dev/null +@@ -1,207 +0,0 @@ +-/* eBPF mini library */ +-#ifndef __LIBBPF_H +-#define __LIBBPF_H +- +-#include +- +-struct bpf_insn; +- +-/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ +- +-#define BPF_ALU64_REG(OP, DST, SRC) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = 0, \ +- .imm = 0 }) +- +-#define BPF_ALU32_REG(OP, DST, SRC) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU | BPF_OP(OP) | BPF_X, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = 0, \ +- .imm = 0 }) +- +-/* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */ +- +-#define BPF_ALU64_IMM(OP, DST, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = IMM }) +- +-#define BPF_ALU32_IMM(OP, DST, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU | BPF_OP(OP) | BPF_K, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = IMM }) +- +-/* Short form of mov, dst_reg = src_reg */ +- +-#define BPF_MOV64_REG(DST, SRC) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU64 | BPF_MOV | BPF_X, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = 0, \ +- .imm = 0 }) +- +-#define BPF_MOV32_REG(DST, SRC) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU | BPF_MOV | BPF_X, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = 0, \ +- .imm = 0 }) +- +-/* Short form of mov, dst_reg = imm32 */ +- +-#define BPF_MOV64_IMM(DST, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU64 | BPF_MOV | BPF_K, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = IMM }) +- +-#define BPF_MOV32_IMM(DST, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_ALU | BPF_MOV | BPF_K, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = IMM }) +- +-/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ +-#define BPF_LD_IMM64(DST, IMM) \ +- BPF_LD_IMM64_RAW(DST, 0, IMM) +- +-#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_LD | BPF_DW | BPF_IMM, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = 0, \ +- .imm = (__u32) (IMM) }), \ +- ((struct bpf_insn) { \ +- .code = 0, /* zero is reserved opcode */ \ +- .dst_reg = 0, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = ((__u64) (IMM)) >> 32 }) +- +-#ifndef BPF_PSEUDO_MAP_FD +-# define BPF_PSEUDO_MAP_FD 1 +-#endif +- +-/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ +-#define BPF_LD_MAP_FD(DST, MAP_FD) \ +- BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) +- +-/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ +- +-#define BPF_LD_ABS(SIZE, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \ +- .dst_reg = 0, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = IMM }) +- +-/* Memory load, dst_reg = *(uint *) (src_reg + off16) */ +- +-#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = OFF, \ +- .imm = 0 }) +- +-/* Memory store, *(uint *) (dst_reg + off16) = src_reg */ +- +-#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = OFF, \ +- .imm = 0 }) +- +-/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ +- +-#define BPF_STX_XADD(SIZE, DST, SRC, OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = OFF, \ +- .imm = 0 }) +- +-/* Memory store, *(uint *) (dst_reg + off16) = imm32 */ +- +-#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ +- ((struct bpf_insn) { \ +- .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = OFF, \ +- .imm = IMM }) +- +-/* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */ +- +-#define BPF_JMP_REG(OP, DST, SRC, OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_JMP | BPF_OP(OP) | BPF_X, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = OFF, \ +- .imm = 0 }) +- +-/* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */ +- +-#define BPF_JMP_IMM(OP, DST, IMM, OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ +- .dst_reg = DST, \ +- .src_reg = 0, \ +- .off = OFF, \ +- .imm = IMM }) +- +-/* Unconditional jumps */ +- +-#define BPF_JMP_A(OFF) \ +- ((struct bpf_insn) { \ +- .code = BPF_JMP | BPF_JA, \ +- .dst_reg = 0, \ +- .src_reg = 0, \ +- .off = OFF, \ +- .imm = 0 }) +- +-/* Raw code statement block */ +- +-#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ +- ((struct bpf_insn) { \ +- .code = CODE, \ +- .dst_reg = DST, \ +- .src_reg = SRC, \ +- .off = OFF, \ +- .imm = IMM }) +- +-/* Program exit */ +- +-#define BPF_EXIT_INSN() \ +- ((struct bpf_insn) { \ +- .code = BPF_JMP | BPF_EXIT, \ +- .dst_reg = 0, \ +- .src_reg = 0, \ +- .off = 0, \ +- .imm = 0 }) +- +-#endif +diff --git a/src/shared/linux/netdevice.h b/src/shared/linux/netdevice.h +new file mode 100644 +index 00000000000..f3770c5b0fa +--- /dev/null ++++ b/src/shared/linux/netdevice.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Definitions for the Interfaces handler. ++ * ++ * Version: @(#)dev.h 1.0.10 08/12/93 ++ * ++ * Authors: Ross Biro ++ * Fred N. van Kempen, ++ * Corey Minyard ++ * Donald J. Becker, ++ * Alan Cox, ++ * Bjorn Ekwall. ++ * Pekka Riikonen ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Moved to /usr/include/linux for NET3 ++ */ ++#ifndef _UAPI_LINUX_NETDEVICE_H ++#define _UAPI_LINUX_NETDEVICE_H ++ ++#include ++#include ++#include ++#include ++ ++ ++#define MAX_ADDR_LEN 32 /* Largest hardware address length */ ++ ++/* Initial net device group. All devices belong to group 0 by default. */ ++#define INIT_NETDEV_GROUP 0 ++ ++ ++/* interface name assignment types (sysfs name_assign_type attribute) */ ++#define NET_NAME_UNKNOWN 0 /* unknown origin (not exposed to userspace) */ ++#define NET_NAME_ENUM 1 /* enumerated by kernel */ ++#define NET_NAME_PREDICTABLE 2 /* predictably named by the kernel */ ++#define NET_NAME_USER 3 /* provided by user-space */ ++#define NET_NAME_RENAMED 4 /* renamed by user-space */ ++ ++/* Media selection options. */ ++enum { ++ IF_PORT_UNKNOWN = 0, ++ IF_PORT_10BASE2, ++ IF_PORT_10BASET, ++ IF_PORT_AUI, ++ IF_PORT_100BASET, ++ IF_PORT_100BASETX, ++ IF_PORT_100BASEFX ++}; ++ ++/* hardware address assignment types */ ++#define NET_ADDR_PERM 0 /* address is permanent (default) */ ++#define NET_ADDR_RANDOM 1 /* address is generated randomly */ ++#define NET_ADDR_STOLEN 2 /* address is stolen from other device */ ++#define NET_ADDR_SET 3 /* address is set using ++ * dev_set_mac_address() */ ++ ++#endif /* _UAPI_LINUX_NETDEVICE_H */ +diff --git a/src/shared/meson.build b/src/shared/meson.build +index e05fbce30f3..15466bcaf1f 100644 +--- a/src/shared/meson.build ++++ b/src/shared/meson.build +@@ -96,6 +96,13 @@ shared_sources = files(''' + json.c + json.h + libmount-util.h ++ linux/auto_dev-ioctl.h ++ linux/bpf.h ++ linux/bpf_common.h ++ linux/bpf_insn.h ++ linux/dm-ioctl.h ++ linux/ethtool.h ++ linux/netdevice.h + lockfile-util.c + lockfile-util.h + log-link.h +@@ -168,7 +175,6 @@ shared_sources = files(''' + watchdog.h + web-util.c + web-util.h +- wireguard-netlink.h + xml.c + xml.h + '''.split()) +diff --git a/src/shared/wireguard-netlink.h b/src/shared/wireguard-netlink.h +deleted file mode 100644 +index eb170915a6a..00000000000 +--- a/src/shared/wireguard-netlink.h ++++ /dev/null +@@ -1,179 +0,0 @@ +-#pragma once +- +-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR MIT) +- * +- * Copyright (C) 2015-2017 Jason A. Donenfeld . All Rights Reserved. +- * +- * Documentation +- * ============= +- * +- * The below enums and macros are for interfacing with WireGuard, using generic +- * netlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two +- * methods: get and set. Note that while they share many common attributes, these +- * two functions actually accept a slightly different set of inputs and outputs. +- * +- * WG_CMD_GET_DEVICE +- * ----------------- +- * +- * May only be called via NLM_F_REQUEST | NLM_F_DUMP. The command should contain +- * one but not both of: +- * +- * WGDEVICE_A_IFINDEX: NLA_U32 +- * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 +- * +- * The kernel will then return several messages (NLM_F_MULTI) containing the following +- * tree of nested items: +- * +- * WGDEVICE_A_IFINDEX: NLA_U32 +- * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 +- * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN +- * WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN +- * WGDEVICE_A_LISTEN_PORT: NLA_U16 +- * WGDEVICE_A_FWMARK: NLA_U32 +- * WGDEVICE_A_PEERS: NLA_NESTED +- * 0: NLA_NESTED +- * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN +- * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN +- * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 +- * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16 +- * WGPEER_A_LAST_HANDSHAKE_TIME: struct timespec +- * WGPEER_A_RX_BYTES: NLA_U64 +- * WGPEER_A_TX_BYTES: NLA_U64 +- * WGPEER_A_ALLOWEDIPS: NLA_NESTED +- * 0: NLA_NESTED +- * WGALLOWEDIP_A_FAMILY: NLA_U16 +- * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr +- * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 +- * 1: NLA_NESTED +- * ... +- * 2: NLA_NESTED +- * ... +- * ... +- * 1: NLA_NESTED +- * ... +- * ... +- * +- * It is possible that all of the allowed IPs of a single peer will not +- * fit within a single netlink message. In that case, the same peer will +- * be written in the following message, except it will only contain +- * WGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several +- * times in a row for the same peer. It is then up to the receiver to +- * coalesce adjacent peers. Likewise, it is possible that all peers will +- * not fit within a single message. So, subsequent peers will be sent +- * in following messages, except those will only contain WGDEVICE_A_IFNAME +- * and WGDEVICE_A_PEERS. It is then up to the receiver to coalesce these +- * messages to form the complete list of peers. +- * +- * Since this is an NLA_F_DUMP command, the final message will always be +- * NLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message +- * contains an integer error code. It is either zero or a negative error +- * code corresponding to the errno. +- * +- * WG_CMD_SET_DEVICE +- * ----------------- +- * +- * May only be called via NLM_F_REQUEST. The command should contain the following +- * tree of nested items, containing one but not both of WGDEVICE_A_IFINDEX +- * and WGDEVICE_A_IFNAME: +- * +- * WGDEVICE_A_IFINDEX: NLA_U32 +- * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 +- * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current +- * peers should be removed prior to adding the list below. +- * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove +- * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly +- * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable +- * WGDEVICE_A_PEERS: NLA_NESTED +- * 0: NLA_NESTED +- * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN +- * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the specified peer +- * should be removed rather than added/updated and/or +- * WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs of +- * this peer should be removed prior to adding the list below. +- * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove +- * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 +- * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable +- * WGPEER_A_ALLOWEDIPS: NLA_NESTED +- * 0: NLA_NESTED +- * WGALLOWEDIP_A_FAMILY: NLA_U16 +- * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr +- * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 +- * 1: NLA_NESTED +- * ... +- * 2: NLA_NESTED +- * ... +- * ... +- * 1: NLA_NESTED +- * ... +- * ... +- * +- * It is possible that the amount of configuration data exceeds that of +- * the maximum message length accepted by the kernel. In that case, +- * several messages should be sent one after another, with each +- * successive one filling in information not contained in the prior. Note +- * that if WGDEVICE_F_REPLACE_PEERS is specified in the first message, it +- * probably should not be specified in fragments that come after, so that +- * the list of peers is only cleared the first time but appened after. +- * Likewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the +- * first message of a peer, it likely should not be specified in subsequent +- * fragments. +- * +- * If an error occurs, NLMSG_ERROR will reply containing an errno. +- */ +- +-#define WG_GENL_NAME "wireguard" +-#define WG_GENL_VERSION 1 +- +-#define WG_KEY_LEN 32 +- +-enum wg_cmd { +- WG_CMD_GET_DEVICE, +- WG_CMD_SET_DEVICE, +- __WG_CMD_MAX +-}; +-#define WG_CMD_MAX (__WG_CMD_MAX - 1) +- +-enum wgdevice_flag { +- WGDEVICE_F_REPLACE_PEERS = 1U << 0 +-}; +-enum wgdevice_attribute { +- WGDEVICE_A_UNSPEC, +- WGDEVICE_A_IFINDEX, +- WGDEVICE_A_IFNAME, +- WGDEVICE_A_PRIVATE_KEY, +- WGDEVICE_A_PUBLIC_KEY, +- WGDEVICE_A_FLAGS, +- WGDEVICE_A_LISTEN_PORT, +- WGDEVICE_A_FWMARK, +- WGDEVICE_A_PEERS, +- __WGDEVICE_A_LAST +-}; +-#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1) +- +-enum wgpeer_flag { +- WGPEER_F_REMOVE_ME = 1U << 0, +- WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1 +-}; +-enum wgpeer_attribute { +- WGPEER_A_UNSPEC, +- WGPEER_A_PUBLIC_KEY, +- WGPEER_A_PRESHARED_KEY, +- WGPEER_A_FLAGS, +- WGPEER_A_ENDPOINT, +- WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, +- WGPEER_A_LAST_HANDSHAKE_TIME, +- WGPEER_A_RX_BYTES, +- WGPEER_A_TX_BYTES, +- WGPEER_A_ALLOWEDIPS, +- __WGPEER_A_LAST +-}; +-#define WGPEER_A_MAX (__WGPEER_A_LAST - 1) +- +-enum wgallowedip_attribute { +- WGALLOWEDIP_A_UNSPEC, +- WGALLOWEDIP_A_FAMILY, +- WGALLOWEDIP_A_IPADDR, +- WGALLOWEDIP_A_CIDR_MASK, +- __WGALLOWEDIP_A_LAST +-}; +-#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) +diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c +index 928bae6ab19..6afa512bfff 100644 +--- a/src/shutdown/umount.c ++++ b/src/shutdown/umount.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -23,7 +24,6 @@ + #include "fd-util.h" + #include "fstab-util.h" + #include "libmount-util.h" +-#include "linux-3.13/dm-ioctl.h" + #include "mount-setup.h" + #include "mount-util.h" + #include "mountpoint-util.h" +diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c +index 3005fc1b696..02bb25b6956 100644 +--- a/src/test/test-arphrd-list.c ++++ b/src/test/test-arphrd-list.c +@@ -1,10 +1,9 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include ++#include + #include + + #include "macro.h" +-#include "missing_network.h" + #include "string-util.h" + + _unused_ \ +diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c +index cd8d68f215b..6a0bf1462fa 100644 +--- a/src/test/test-bpf.c ++++ b/src/test/test-bpf.c +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include ++#include + #include + #include + #include +diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c +index a1a5eb47788..031a47605e2 100644 +--- a/src/test/test-netlink-manual.c ++++ b/src/test/test-netlink-manual.c +@@ -2,9 +2,8 @@ + + #include + #include +-#include +-#include + #include ++#include + #include + #include + +diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h +index 618b26bf59f..7ca703d22cc 100644 +--- a/src/udev/net/ethtool-util.h ++++ b/src/udev/net/ethtool-util.h +@@ -5,7 +5,6 @@ + #include + + #include "conf-parser.h" +-#include "missing_network.h" + + struct link_config; + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index 14690e364b9..a26c4cefa82 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + ++#include + #include + + #include "sd-device.h" +@@ -15,7 +16,6 @@ + #include "link-config.h" + #include "log.h" + #include "memory-util.h" +-#include "missing_network.h" + #include "naming-scheme.h" + #include "netlink-util.h" + #include "network-internal.h" +diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c +index 956be59afb9..6a69dae3af7 100644 +--- a/src/udev/udev-builtin-btrfs.c ++++ b/src/udev/udev-builtin-btrfs.c +@@ -1,12 +1,12 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include ++#include + #include + #include + + #include "device-util.h" + #include "fd-util.h" +-#include "missing.h" + #include "string-util.h" + #include "strxcpyx.h" + #include "udev-builtin.h" diff --git a/packages/sysutils/systemd/patches/amlogic/systemd-9999.2-backport.patch b/packages/sysutils/systemd/patches/amlogic/systemd-9999.2-backport.patch new file mode 100644 index 000000000..1bfbe4534 --- /dev/null +++ b/packages/sysutils/systemd/patches/amlogic/systemd-9999.2-backport.patch @@ -0,0 +1,41 @@ +From 76566792e33f054dd02df84db044f5ae747afe67 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 13 Apr 2019 18:33:34 +0900 +Subject: [PATCH] linux: move netdevice.h from shared/linux to basic/linux + +As the header linux/if_arp.h includes linux/netdevice.h. +--- + src/{shared => basic}/linux/netdevice.h | 0 + src/basic/meson.build | 1 + + src/shared/meson.build | 1 - + 3 files changed, 1 insertion(+), 1 deletion(-) + rename src/{shared => basic}/linux/netdevice.h (100%) + +diff --git a/src/shared/linux/netdevice.h b/src/basic/linux/netdevice.h +similarity index 100% +rename from src/shared/linux/netdevice.h +rename to src/basic/linux/netdevice.h +diff --git a/src/basic/meson.build b/src/basic/meson.build +index 524f3785dc0..81c3d0f3e80 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -99,6 +99,7 @@ basic_sources = files(''' + linux/if_tun.h + linux/if_tunnel.h + linux/libc-compat.h ++ linux/netdevice.h + linux/netlink.h + linux/rtnetlink.h + linux/wireguard.h +diff --git a/src/shared/meson.build b/src/shared/meson.build +index 15466bcaf1f..c80a67cdde4 100644 +--- a/src/shared/meson.build ++++ b/src/shared/meson.build +@@ -102,7 +102,6 @@ shared_sources = files(''' + linux/bpf_insn.h + linux/dm-ioctl.h + linux/ethtool.h +- linux/netdevice.h + lockfile-util.c + lockfile-util.h + log-link.h diff --git a/packages/sysutils/systemd/patches/amlogic/systemd-9999.3-backport.patch b/packages/sysutils/systemd/patches/amlogic/systemd-9999.3-backport.patch new file mode 100644 index 000000000..47d36b82e --- /dev/null +++ b/packages/sysutils/systemd/patches/amlogic/systemd-9999.3-backport.patch @@ -0,0 +1,648 @@ +From 7057b6144f4c5cb7e284a409c7f24b84c16a3bb8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 13 Apr 2019 18:46:40 +0900 +Subject: [PATCH] linux: also import linux/in.h and in6.h from kernel-5.0 + +Now linux/in.h has better conflict detection with glibc's +netinet/in.h. So, let's import the headers. + +Note that our code already have many workarounds for the conflict, +but in this commit does not drop them. Let's do that in the later +commits if this really helps. +--- + src/basic/linux/in.h | 305 ++++++++++++++++++++++++++++++++++++++++++ + src/basic/linux/in6.h | 299 +++++++++++++++++++++++++++++++++++++++++ + src/basic/meson.build | 2 + + 3 files changed, 606 insertions(+) + create mode 100644 src/basic/linux/in.h + create mode 100644 src/basic/linux/in6.h + +diff --git a/src/basic/linux/in.h b/src/basic/linux/in.h +new file mode 100644 +index 00000000000..a55cb8b1016 +--- /dev/null ++++ b/src/basic/linux/in.h +@@ -0,0 +1,305 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Definitions of the Internet Protocol. ++ * ++ * Version: @(#)in.h 1.0.1 04/21/93 ++ * ++ * Authors: Original taken from the GNU Project file. ++ * Fred N. van Kempen, ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ */ ++#ifndef _UAPI_LINUX_IN_H ++#define _UAPI_LINUX_IN_H ++ ++#include ++#include ++#include ++ ++#if __UAPI_DEF_IN_IPPROTO ++/* Standard well-defined IP protocols. */ ++enum { ++ IPPROTO_IP = 0, /* Dummy protocol for TCP */ ++#define IPPROTO_IP IPPROTO_IP ++ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ ++#define IPPROTO_ICMP IPPROTO_ICMP ++ IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ ++#define IPPROTO_IGMP IPPROTO_IGMP ++ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ ++#define IPPROTO_IPIP IPPROTO_IPIP ++ IPPROTO_TCP = 6, /* Transmission Control Protocol */ ++#define IPPROTO_TCP IPPROTO_TCP ++ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ ++#define IPPROTO_EGP IPPROTO_EGP ++ IPPROTO_PUP = 12, /* PUP protocol */ ++#define IPPROTO_PUP IPPROTO_PUP ++ IPPROTO_UDP = 17, /* User Datagram Protocol */ ++#define IPPROTO_UDP IPPROTO_UDP ++ IPPROTO_IDP = 22, /* XNS IDP protocol */ ++#define IPPROTO_IDP IPPROTO_IDP ++ IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */ ++#define IPPROTO_TP IPPROTO_TP ++ IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ ++#define IPPROTO_DCCP IPPROTO_DCCP ++ IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ ++#define IPPROTO_IPV6 IPPROTO_IPV6 ++ IPPROTO_RSVP = 46, /* RSVP Protocol */ ++#define IPPROTO_RSVP IPPROTO_RSVP ++ IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ ++#define IPPROTO_GRE IPPROTO_GRE ++ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ ++#define IPPROTO_ESP IPPROTO_ESP ++ IPPROTO_AH = 51, /* Authentication Header protocol */ ++#define IPPROTO_AH IPPROTO_AH ++ IPPROTO_MTP = 92, /* Multicast Transport Protocol */ ++#define IPPROTO_MTP IPPROTO_MTP ++ IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ ++#define IPPROTO_BEETPH IPPROTO_BEETPH ++ IPPROTO_ENCAP = 98, /* Encapsulation Header */ ++#define IPPROTO_ENCAP IPPROTO_ENCAP ++ IPPROTO_PIM = 103, /* Protocol Independent Multicast */ ++#define IPPROTO_PIM IPPROTO_PIM ++ IPPROTO_COMP = 108, /* Compression Header Protocol */ ++#define IPPROTO_COMP IPPROTO_COMP ++ IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ ++#define IPPROTO_SCTP IPPROTO_SCTP ++ IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ ++#define IPPROTO_UDPLITE IPPROTO_UDPLITE ++ IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */ ++#define IPPROTO_MPLS IPPROTO_MPLS ++ IPPROTO_RAW = 255, /* Raw IP packets */ ++#define IPPROTO_RAW IPPROTO_RAW ++ IPPROTO_MAX ++}; ++#endif ++ ++#if __UAPI_DEF_IN_ADDR ++/* Internet address. */ ++struct in_addr { ++ __be32 s_addr; ++}; ++#endif ++ ++#define IP_TOS 1 ++#define IP_TTL 2 ++#define IP_HDRINCL 3 ++#define IP_OPTIONS 4 ++#define IP_ROUTER_ALERT 5 ++#define IP_RECVOPTS 6 ++#define IP_RETOPTS 7 ++#define IP_PKTINFO 8 ++#define IP_PKTOPTIONS 9 ++#define IP_MTU_DISCOVER 10 ++#define IP_RECVERR 11 ++#define IP_RECVTTL 12 ++#define IP_RECVTOS 13 ++#define IP_MTU 14 ++#define IP_FREEBIND 15 ++#define IP_IPSEC_POLICY 16 ++#define IP_XFRM_POLICY 17 ++#define IP_PASSSEC 18 ++#define IP_TRANSPARENT 19 ++ ++/* BSD compatibility */ ++#define IP_RECVRETOPTS IP_RETOPTS ++ ++/* TProxy original addresses */ ++#define IP_ORIGDSTADDR 20 ++#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR ++ ++#define IP_MINTTL 21 ++#define IP_NODEFRAG 22 ++#define IP_CHECKSUM 23 ++#define IP_BIND_ADDRESS_NO_PORT 24 ++#define IP_RECVFRAGSIZE 25 ++ ++/* IP_MTU_DISCOVER values */ ++#define IP_PMTUDISC_DONT 0 /* Never send DF frames */ ++#define IP_PMTUDISC_WANT 1 /* Use per route hints */ ++#define IP_PMTUDISC_DO 2 /* Always DF */ ++#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */ ++/* Always use interface mtu (ignores dst pmtu) but don't set DF flag. ++ * Also incoming ICMP frag_needed notifications will be ignored on ++ * this socket to prevent accepting spoofed ones. ++ */ ++#define IP_PMTUDISC_INTERFACE 4 ++/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get ++ * fragmented if they exeed the interface mtu ++ */ ++#define IP_PMTUDISC_OMIT 5 ++ ++#define IP_MULTICAST_IF 32 ++#define IP_MULTICAST_TTL 33 ++#define IP_MULTICAST_LOOP 34 ++#define IP_ADD_MEMBERSHIP 35 ++#define IP_DROP_MEMBERSHIP 36 ++#define IP_UNBLOCK_SOURCE 37 ++#define IP_BLOCK_SOURCE 38 ++#define IP_ADD_SOURCE_MEMBERSHIP 39 ++#define IP_DROP_SOURCE_MEMBERSHIP 40 ++#define IP_MSFILTER 41 ++#define MCAST_JOIN_GROUP 42 ++#define MCAST_BLOCK_SOURCE 43 ++#define MCAST_UNBLOCK_SOURCE 44 ++#define MCAST_LEAVE_GROUP 45 ++#define MCAST_JOIN_SOURCE_GROUP 46 ++#define MCAST_LEAVE_SOURCE_GROUP 47 ++#define MCAST_MSFILTER 48 ++#define IP_MULTICAST_ALL 49 ++#define IP_UNICAST_IF 50 ++ ++#define MCAST_EXCLUDE 0 ++#define MCAST_INCLUDE 1 ++ ++/* These need to appear somewhere around here */ ++#define IP_DEFAULT_MULTICAST_TTL 1 ++#define IP_DEFAULT_MULTICAST_LOOP 1 ++ ++/* Request struct for multicast socket ops */ ++ ++#if __UAPI_DEF_IP_MREQ ++struct ip_mreq { ++ struct in_addr imr_multiaddr; /* IP multicast address of group */ ++ struct in_addr imr_interface; /* local IP address of interface */ ++}; ++ ++struct ip_mreqn { ++ struct in_addr imr_multiaddr; /* IP multicast address of group */ ++ struct in_addr imr_address; /* local IP address of interface */ ++ int imr_ifindex; /* Interface index */ ++}; ++ ++struct ip_mreq_source { ++ __be32 imr_multiaddr; ++ __be32 imr_interface; ++ __be32 imr_sourceaddr; ++}; ++ ++struct ip_msfilter { ++ __be32 imsf_multiaddr; ++ __be32 imsf_interface; ++ __u32 imsf_fmode; ++ __u32 imsf_numsrc; ++ __be32 imsf_slist[1]; ++}; ++ ++#define IP_MSFILTER_SIZE(numsrc) \ ++ (sizeof(struct ip_msfilter) - sizeof(__u32) \ ++ + (numsrc) * sizeof(__u32)) ++ ++struct group_req { ++ __u32 gr_interface; /* interface index */ ++ struct __kernel_sockaddr_storage gr_group; /* group address */ ++}; ++ ++struct group_source_req { ++ __u32 gsr_interface; /* interface index */ ++ struct __kernel_sockaddr_storage gsr_group; /* group address */ ++ struct __kernel_sockaddr_storage gsr_source; /* source address */ ++}; ++ ++struct group_filter { ++ __u32 gf_interface; /* interface index */ ++ struct __kernel_sockaddr_storage gf_group; /* multicast address */ ++ __u32 gf_fmode; /* filter mode */ ++ __u32 gf_numsrc; /* number of sources */ ++ struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */ ++}; ++ ++#define GROUP_FILTER_SIZE(numsrc) \ ++ (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \ ++ + (numsrc) * sizeof(struct __kernel_sockaddr_storage)) ++#endif ++ ++#if __UAPI_DEF_IN_PKTINFO ++struct in_pktinfo { ++ int ipi_ifindex; ++ struct in_addr ipi_spec_dst; ++ struct in_addr ipi_addr; ++}; ++#endif ++ ++/* Structure describing an Internet (IP) socket address. */ ++#if __UAPI_DEF_SOCKADDR_IN ++#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ ++struct sockaddr_in { ++ __kernel_sa_family_t sin_family; /* Address family */ ++ __be16 sin_port; /* Port number */ ++ struct in_addr sin_addr; /* Internet address */ ++ ++ /* Pad to size of `struct sockaddr'. */ ++ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - ++ sizeof(unsigned short int) - sizeof(struct in_addr)]; ++}; ++#define sin_zero __pad /* for BSD UNIX comp. -FvK */ ++#endif ++ ++#if __UAPI_DEF_IN_CLASS ++/* ++ * Definitions of the bits in an Internet address integer. ++ * On subnets, host and network parts are found according ++ * to the subnet mask, not these masks. ++ */ ++#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) ++#define IN_CLASSA_NET 0xff000000 ++#define IN_CLASSA_NSHIFT 24 ++#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) ++#define IN_CLASSA_MAX 128 ++ ++#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) ++#define IN_CLASSB_NET 0xffff0000 ++#define IN_CLASSB_NSHIFT 16 ++#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) ++#define IN_CLASSB_MAX 65536 ++ ++#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) ++#define IN_CLASSC_NET 0xffffff00 ++#define IN_CLASSC_NSHIFT 8 ++#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) ++ ++#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) ++#define IN_MULTICAST(a) IN_CLASSD(a) ++#define IN_MULTICAST_NET 0xe0000000 ++ ++#define IN_BADCLASS(a) (((long int) (a) ) == (long int)0xffffffff) ++#define IN_EXPERIMENTAL(a) IN_BADCLASS((a)) ++ ++#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) ++#define IN_CLASSE_NET 0xffffffff ++#define IN_CLASSE_NSHIFT 0 ++ ++/* Address to accept any incoming messages. */ ++#define INADDR_ANY ((unsigned long int) 0x00000000) ++ ++/* Address to send to all hosts. */ ++#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) ++ ++/* Address indicating an error return. */ ++#define INADDR_NONE ((unsigned long int) 0xffffffff) ++ ++/* Network number for local host loopback. */ ++#define IN_LOOPBACKNET 127 ++ ++/* Address to loopback in software to local host. */ ++#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ ++#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) ++ ++/* Defines for Multicast INADDR */ ++#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ ++#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ ++#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ ++#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ ++#endif ++ ++/* contains the htonl type stuff.. */ ++#include ++ ++ ++#endif /* _UAPI_LINUX_IN_H */ +diff --git a/src/basic/linux/in6.h b/src/basic/linux/in6.h +new file mode 100644 +index 00000000000..71d82fe15b0 +--- /dev/null ++++ b/src/basic/linux/in6.h +@@ -0,0 +1,299 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * Types and definitions for AF_INET6 ++ * Linux INET6 implementation ++ * ++ * Authors: ++ * Pedro Roque ++ * ++ * Sources: ++ * IPv6 Program Interfaces for BSD Systems ++ * ++ * ++ * Advanced Sockets API for IPv6 ++ * ++ * ++ * This program 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 ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#ifndef _UAPI_LINUX_IN6_H ++#define _UAPI_LINUX_IN6_H ++ ++#include ++#include ++ ++/* ++ * IPv6 address structure ++ */ ++ ++#if __UAPI_DEF_IN6_ADDR ++struct in6_addr { ++ union { ++ __u8 u6_addr8[16]; ++#if __UAPI_DEF_IN6_ADDR_ALT ++ __be16 u6_addr16[8]; ++ __be32 u6_addr32[4]; ++#endif ++ } in6_u; ++#define s6_addr in6_u.u6_addr8 ++#if __UAPI_DEF_IN6_ADDR_ALT ++#define s6_addr16 in6_u.u6_addr16 ++#define s6_addr32 in6_u.u6_addr32 ++#endif ++}; ++#endif /* __UAPI_DEF_IN6_ADDR */ ++ ++#if __UAPI_DEF_SOCKADDR_IN6 ++struct sockaddr_in6 { ++ unsigned short int sin6_family; /* AF_INET6 */ ++ __be16 sin6_port; /* Transport layer port # */ ++ __be32 sin6_flowinfo; /* IPv6 flow information */ ++ struct in6_addr sin6_addr; /* IPv6 address */ ++ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ ++}; ++#endif /* __UAPI_DEF_SOCKADDR_IN6 */ ++ ++#if __UAPI_DEF_IPV6_MREQ ++struct ipv6_mreq { ++ /* IPv6 multicast address of group */ ++ struct in6_addr ipv6mr_multiaddr; ++ ++ /* local IPv6 address of interface */ ++ int ipv6mr_ifindex; ++}; ++#endif /* __UAPI_DEF_IVP6_MREQ */ ++ ++#define ipv6mr_acaddr ipv6mr_multiaddr ++ ++struct in6_flowlabel_req { ++ struct in6_addr flr_dst; ++ __be32 flr_label; ++ __u8 flr_action; ++ __u8 flr_share; ++ __u16 flr_flags; ++ __u16 flr_expires; ++ __u16 flr_linger; ++ __u32 __flr_pad; ++ /* Options in format of IPV6_PKTOPTIONS */ ++}; ++ ++#define IPV6_FL_A_GET 0 ++#define IPV6_FL_A_PUT 1 ++#define IPV6_FL_A_RENEW 2 ++ ++#define IPV6_FL_F_CREATE 1 ++#define IPV6_FL_F_EXCL 2 ++#define IPV6_FL_F_REFLECT 4 ++#define IPV6_FL_F_REMOTE 8 ++ ++#define IPV6_FL_S_NONE 0 ++#define IPV6_FL_S_EXCL 1 ++#define IPV6_FL_S_PROCESS 2 ++#define IPV6_FL_S_USER 3 ++#define IPV6_FL_S_ANY 255 ++ ++ ++/* ++ * Bitmask constant declarations to help applications select out the ++ * flow label and priority fields. ++ * ++ * Note that this are in host byte order while the flowinfo field of ++ * sockaddr_in6 is in network byte order. ++ */ ++ ++#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff ++#define IPV6_FLOWINFO_PRIORITY 0x0ff00000 ++ ++/* These definitions are obsolete */ ++#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000 ++#define IPV6_PRIORITY_FILLER 0x0100 ++#define IPV6_PRIORITY_UNATTENDED 0x0200 ++#define IPV6_PRIORITY_RESERVED1 0x0300 ++#define IPV6_PRIORITY_BULK 0x0400 ++#define IPV6_PRIORITY_RESERVED2 0x0500 ++#define IPV6_PRIORITY_INTERACTIVE 0x0600 ++#define IPV6_PRIORITY_CONTROL 0x0700 ++#define IPV6_PRIORITY_8 0x0800 ++#define IPV6_PRIORITY_9 0x0900 ++#define IPV6_PRIORITY_10 0x0a00 ++#define IPV6_PRIORITY_11 0x0b00 ++#define IPV6_PRIORITY_12 0x0c00 ++#define IPV6_PRIORITY_13 0x0d00 ++#define IPV6_PRIORITY_14 0x0e00 ++#define IPV6_PRIORITY_15 0x0f00 ++ ++/* ++ * IPV6 extension headers ++ */ ++#if __UAPI_DEF_IPPROTO_V6 ++#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ ++#define IPPROTO_ROUTING 43 /* IPv6 routing header */ ++#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ ++#define IPPROTO_ICMPV6 58 /* ICMPv6 */ ++#define IPPROTO_NONE 59 /* IPv6 no next header */ ++#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ ++#define IPPROTO_MH 135 /* IPv6 mobility header */ ++#endif /* __UAPI_DEF_IPPROTO_V6 */ ++ ++/* ++ * IPv6 TLV options. ++ */ ++#define IPV6_TLV_PAD1 0 ++#define IPV6_TLV_PADN 1 ++#define IPV6_TLV_ROUTERALERT 5 ++#define IPV6_TLV_CALIPSO 7 /* RFC 5570 */ ++#define IPV6_TLV_JUMBO 194 ++#define IPV6_TLV_HAO 201 /* home address option */ ++ ++/* ++ * IPV6 socket options ++ */ ++#if __UAPI_DEF_IPV6_OPTIONS ++#define IPV6_ADDRFORM 1 ++#define IPV6_2292PKTINFO 2 ++#define IPV6_2292HOPOPTS 3 ++#define IPV6_2292DSTOPTS 4 ++#define IPV6_2292RTHDR 5 ++#define IPV6_2292PKTOPTIONS 6 ++#define IPV6_CHECKSUM 7 ++#define IPV6_2292HOPLIMIT 8 ++#define IPV6_NEXTHOP 9 ++#define IPV6_AUTHHDR 10 /* obsolete */ ++#define IPV6_FLOWINFO 11 ++ ++#define IPV6_UNICAST_HOPS 16 ++#define IPV6_MULTICAST_IF 17 ++#define IPV6_MULTICAST_HOPS 18 ++#define IPV6_MULTICAST_LOOP 19 ++#define IPV6_ADD_MEMBERSHIP 20 ++#define IPV6_DROP_MEMBERSHIP 21 ++#define IPV6_ROUTER_ALERT 22 ++#define IPV6_MTU_DISCOVER 23 ++#define IPV6_MTU 24 ++#define IPV6_RECVERR 25 ++#define IPV6_V6ONLY 26 ++#define IPV6_JOIN_ANYCAST 27 ++#define IPV6_LEAVE_ANYCAST 28 ++#define IPV6_MULTICAST_ALL 29 ++ ++/* IPV6_MTU_DISCOVER values */ ++#define IPV6_PMTUDISC_DONT 0 ++#define IPV6_PMTUDISC_WANT 1 ++#define IPV6_PMTUDISC_DO 2 ++#define IPV6_PMTUDISC_PROBE 3 ++/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4 ++ * also see comments on IP_PMTUDISC_INTERFACE ++ */ ++#define IPV6_PMTUDISC_INTERFACE 4 ++/* weaker version of IPV6_PMTUDISC_INTERFACE, which allows packets to ++ * get fragmented if they exceed the interface mtu ++ */ ++#define IPV6_PMTUDISC_OMIT 5 ++ ++/* Flowlabel */ ++#define IPV6_FLOWLABEL_MGR 32 ++#define IPV6_FLOWINFO_SEND 33 ++ ++#define IPV6_IPSEC_POLICY 34 ++#define IPV6_XFRM_POLICY 35 ++#define IPV6_HDRINCL 36 ++#endif ++ ++/* ++ * Multicast: ++ * Following socket options are shared between IPv4 and IPv6. ++ * ++ * MCAST_JOIN_GROUP 42 ++ * MCAST_BLOCK_SOURCE 43 ++ * MCAST_UNBLOCK_SOURCE 44 ++ * MCAST_LEAVE_GROUP 45 ++ * MCAST_JOIN_SOURCE_GROUP 46 ++ * MCAST_LEAVE_SOURCE_GROUP 47 ++ * MCAST_MSFILTER 48 ++ */ ++ ++/* ++ * Advanced API (RFC3542) (1) ++ * ++ * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c. ++ */ ++ ++#define IPV6_RECVPKTINFO 49 ++#define IPV6_PKTINFO 50 ++#define IPV6_RECVHOPLIMIT 51 ++#define IPV6_HOPLIMIT 52 ++#define IPV6_RECVHOPOPTS 53 ++#define IPV6_HOPOPTS 54 ++#define IPV6_RTHDRDSTOPTS 55 ++#define IPV6_RECVRTHDR 56 ++#define IPV6_RTHDR 57 ++#define IPV6_RECVDSTOPTS 58 ++#define IPV6_DSTOPTS 59 ++#define IPV6_RECVPATHMTU 60 ++#define IPV6_PATHMTU 61 ++#define IPV6_DONTFRAG 62 ++#if 0 /* not yet */ ++#define IPV6_USE_MIN_MTU 63 ++#endif ++ ++/* ++ * Netfilter (1) ++ * ++ * Following socket options are used in ip6_tables; ++ * see include/linux/netfilter_ipv6/ip6_tables.h. ++ * ++ * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO 64 ++ * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES 65 ++ */ ++ ++/* ++ * Advanced API (RFC3542) (2) ++ */ ++#define IPV6_RECVTCLASS 66 ++#define IPV6_TCLASS 67 ++ ++/* ++ * Netfilter (2) ++ * ++ * Following socket options are used in ip6_tables; ++ * see include/linux/netfilter_ipv6/ip6_tables.h. ++ * ++ * IP6T_SO_GET_REVISION_MATCH 68 ++ * IP6T_SO_GET_REVISION_TARGET 69 ++ * IP6T_SO_ORIGINAL_DST 80 ++ */ ++ ++#define IPV6_AUTOFLOWLABEL 70 ++/* RFC5014: Source address selection */ ++#define IPV6_ADDR_PREFERENCES 72 ++ ++#define IPV6_PREFER_SRC_TMP 0x0001 ++#define IPV6_PREFER_SRC_PUBLIC 0x0002 ++#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 ++#define IPV6_PREFER_SRC_COA 0x0004 ++#define IPV6_PREFER_SRC_HOME 0x0400 ++#define IPV6_PREFER_SRC_CGA 0x0008 ++#define IPV6_PREFER_SRC_NONCGA 0x0800 ++ ++/* RFC5082: Generalized Ttl Security Mechanism */ ++#define IPV6_MINHOPCOUNT 73 ++ ++#define IPV6_ORIGDSTADDR 74 ++#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR ++#define IPV6_TRANSPARENT 75 ++#define IPV6_UNICAST_IF 76 ++#define IPV6_RECVFRAGSIZE 77 ++#define IPV6_FREEBIND 78 ++ ++/* ++ * Multicast Routing: ++ * see include/uapi/linux/mroute6.h. ++ * ++ * MRT6_BASE 200 ++ * ... ++ * MRT6_MAX ++ */ ++#endif /* _UAPI_LINUX_IN6_H */ +diff --git a/src/basic/meson.build b/src/basic/meson.build +index 81c3d0f3e80..26c7fc42c76 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -98,6 +98,8 @@ basic_sources = files(''' + linux/if_macsec.h + linux/if_tun.h + linux/if_tunnel.h ++ linux/in.h ++ linux/in6.h + linux/libc-compat.h + linux/netdevice.h + linux/netlink.h diff --git a/packages/sysutils/systemd/patches/amlogic/systemd-9999.4-backport.patch b/packages/sysutils/systemd/patches/amlogic/systemd-9999.4-backport.patch new file mode 100644 index 000000000..01a9d6d8c --- /dev/null +++ b/packages/sysutils/systemd/patches/amlogic/systemd-9999.4-backport.patch @@ -0,0 +1,235 @@ +From aa8129049564627fd9eb7866fa58c9bc9f47c672 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sat, 13 Apr 2019 18:35:15 +0900 +Subject: [PATCH] linux: also import l2tp.h from kernel-5.0 + +The L2TP_ATTR_UDP_ZERO_CSUM6_{TX,RX} attributes are introduced by +6b649feafe10b293f4bd5a74aca95faf625ae525, which is included in +kernel-3.16. To support older kernel, let's import the header. + +Fixes #12300. +--- + src/basic/linux/l2tp.h | 201 +++++++++++++++++++++++++++++++++++++++++ + src/basic/meson.build | 1 + + 2 files changed, 202 insertions(+) + create mode 100644 src/basic/linux/l2tp.h + +diff --git a/src/basic/linux/l2tp.h b/src/basic/linux/l2tp.h +new file mode 100644 +index 00000000000..61158f5a1a5 +--- /dev/null ++++ b/src/basic/linux/l2tp.h +@@ -0,0 +1,201 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * L2TP-over-IP socket for L2TPv3. ++ * ++ * Author: James Chapman ++ */ ++ ++#ifndef _UAPI_LINUX_L2TP_H_ ++#define _UAPI_LINUX_L2TP_H_ ++ ++#include ++#include ++#include ++#include ++ ++#define IPPROTO_L2TP 115 ++ ++/** ++ * struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets ++ * @l2tp_family: address family number AF_L2TPIP. ++ * @l2tp_addr: protocol specific address information ++ * @l2tp_conn_id: connection id of tunnel ++ */ ++#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ ++struct sockaddr_l2tpip { ++ /* The first fields must match struct sockaddr_in */ ++ __kernel_sa_family_t l2tp_family; /* AF_INET */ ++ __be16 l2tp_unused; /* INET port number (unused) */ ++ struct in_addr l2tp_addr; /* Internet address */ ++ ++ __u32 l2tp_conn_id; /* Connection ID of tunnel */ ++ ++ /* Pad to size of `struct sockaddr'. */ ++ unsigned char __pad[__SOCK_SIZE__ - ++ sizeof(__kernel_sa_family_t) - ++ sizeof(__be16) - sizeof(struct in_addr) - ++ sizeof(__u32)]; ++}; ++ ++/** ++ * struct sockaddr_l2tpip6 - the sockaddr structure for L2TP-over-IPv6 sockets ++ * @l2tp_family: address family number AF_L2TPIP. ++ * @l2tp_addr: protocol specific address information ++ * @l2tp_conn_id: connection id of tunnel ++ */ ++struct sockaddr_l2tpip6 { ++ /* The first fields must match struct sockaddr_in6 */ ++ __kernel_sa_family_t l2tp_family; /* AF_INET6 */ ++ __be16 l2tp_unused; /* INET port number (unused) */ ++ __be32 l2tp_flowinfo; /* IPv6 flow information */ ++ struct in6_addr l2tp_addr; /* IPv6 address */ ++ __u32 l2tp_scope_id; /* scope id (new in RFC2553) */ ++ __u32 l2tp_conn_id; /* Connection ID of tunnel */ ++}; ++ ++/***************************************************************************** ++ * NETLINK_GENERIC netlink family. ++ *****************************************************************************/ ++ ++/* ++ * Commands. ++ * Valid TLVs of each command are:- ++ * TUNNEL_CREATE - CONN_ID, pw_type, netns, ifname, ipinfo, udpinfo, udpcsum ++ * TUNNEL_DELETE - CONN_ID ++ * TUNNEL_MODIFY - CONN_ID, udpcsum ++ * TUNNEL_GETSTATS - CONN_ID, (stats) ++ * TUNNEL_GET - CONN_ID, (...) ++ * SESSION_CREATE - SESSION_ID, PW_TYPE, cookie, peer_cookie, l2spec ++ * SESSION_DELETE - SESSION_ID ++ * SESSION_MODIFY - SESSION_ID ++ * SESSION_GET - SESSION_ID, (...) ++ * SESSION_GETSTATS - SESSION_ID, (stats) ++ * ++ */ ++enum { ++ L2TP_CMD_NOOP, ++ L2TP_CMD_TUNNEL_CREATE, ++ L2TP_CMD_TUNNEL_DELETE, ++ L2TP_CMD_TUNNEL_MODIFY, ++ L2TP_CMD_TUNNEL_GET, ++ L2TP_CMD_SESSION_CREATE, ++ L2TP_CMD_SESSION_DELETE, ++ L2TP_CMD_SESSION_MODIFY, ++ L2TP_CMD_SESSION_GET, ++ __L2TP_CMD_MAX, ++}; ++ ++#define L2TP_CMD_MAX (__L2TP_CMD_MAX - 1) ++ ++/* ++ * ATTR types defined for L2TP ++ */ ++enum { ++ L2TP_ATTR_NONE, /* no data */ ++ L2TP_ATTR_PW_TYPE, /* u16, enum l2tp_pwtype */ ++ L2TP_ATTR_ENCAP_TYPE, /* u16, enum l2tp_encap_type */ ++ L2TP_ATTR_OFFSET, /* u16 (not used) */ ++ L2TP_ATTR_DATA_SEQ, /* u16 (not used) */ ++ L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */ ++ L2TP_ATTR_L2SPEC_LEN, /* u8 (not used) */ ++ L2TP_ATTR_PROTO_VERSION, /* u8 */ ++ L2TP_ATTR_IFNAME, /* string */ ++ L2TP_ATTR_CONN_ID, /* u32 */ ++ L2TP_ATTR_PEER_CONN_ID, /* u32 */ ++ L2TP_ATTR_SESSION_ID, /* u32 */ ++ L2TP_ATTR_PEER_SESSION_ID, /* u32 */ ++ L2TP_ATTR_UDP_CSUM, /* u8 */ ++ L2TP_ATTR_VLAN_ID, /* u16 (not used) */ ++ L2TP_ATTR_COOKIE, /* 0, 4 or 8 bytes */ ++ L2TP_ATTR_PEER_COOKIE, /* 0, 4 or 8 bytes */ ++ L2TP_ATTR_DEBUG, /* u32, enum l2tp_debug_flags */ ++ L2TP_ATTR_RECV_SEQ, /* u8 */ ++ L2TP_ATTR_SEND_SEQ, /* u8 */ ++ L2TP_ATTR_LNS_MODE, /* u8 */ ++ L2TP_ATTR_USING_IPSEC, /* u8 */ ++ L2TP_ATTR_RECV_TIMEOUT, /* msec */ ++ L2TP_ATTR_FD, /* int */ ++ L2TP_ATTR_IP_SADDR, /* u32 */ ++ L2TP_ATTR_IP_DADDR, /* u32 */ ++ L2TP_ATTR_UDP_SPORT, /* u16 */ ++ L2TP_ATTR_UDP_DPORT, /* u16 */ ++ L2TP_ATTR_MTU, /* u16 (not used) */ ++ L2TP_ATTR_MRU, /* u16 (not used) */ ++ L2TP_ATTR_STATS, /* nested */ ++ L2TP_ATTR_IP6_SADDR, /* struct in6_addr */ ++ L2TP_ATTR_IP6_DADDR, /* struct in6_addr */ ++ L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* flag */ ++ L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* flag */ ++ L2TP_ATTR_PAD, ++ __L2TP_ATTR_MAX, ++}; ++ ++#define L2TP_ATTR_MAX (__L2TP_ATTR_MAX - 1) ++ ++/* Nested in L2TP_ATTR_STATS */ ++enum { ++ L2TP_ATTR_STATS_NONE, /* no data */ ++ L2TP_ATTR_TX_PACKETS, /* u64 */ ++ L2TP_ATTR_TX_BYTES, /* u64 */ ++ L2TP_ATTR_TX_ERRORS, /* u64 */ ++ L2TP_ATTR_RX_PACKETS, /* u64 */ ++ L2TP_ATTR_RX_BYTES, /* u64 */ ++ L2TP_ATTR_RX_SEQ_DISCARDS, /* u64 */ ++ L2TP_ATTR_RX_OOS_PACKETS, /* u64 */ ++ L2TP_ATTR_RX_ERRORS, /* u64 */ ++ L2TP_ATTR_STATS_PAD, ++ __L2TP_ATTR_STATS_MAX, ++}; ++ ++#define L2TP_ATTR_STATS_MAX (__L2TP_ATTR_STATS_MAX - 1) ++ ++enum l2tp_pwtype { ++ L2TP_PWTYPE_NONE = 0x0000, ++ L2TP_PWTYPE_ETH_VLAN = 0x0004, ++ L2TP_PWTYPE_ETH = 0x0005, ++ L2TP_PWTYPE_PPP = 0x0007, ++ L2TP_PWTYPE_PPP_AC = 0x0008, ++ L2TP_PWTYPE_IP = 0x000b, ++ __L2TP_PWTYPE_MAX ++}; ++ ++enum l2tp_l2spec_type { ++ L2TP_L2SPECTYPE_NONE, ++ L2TP_L2SPECTYPE_DEFAULT, ++}; ++ ++enum l2tp_encap_type { ++ L2TP_ENCAPTYPE_UDP, ++ L2TP_ENCAPTYPE_IP, ++}; ++ ++/* For L2TP_ATTR_DATA_SEQ. Unused. */ ++enum l2tp_seqmode { ++ L2TP_SEQ_NONE = 0, ++ L2TP_SEQ_IP = 1, ++ L2TP_SEQ_ALL = 2, ++}; ++ ++/** ++ * enum l2tp_debug_flags - debug message categories for L2TP tunnels/sessions ++ * ++ * @L2TP_MSG_DEBUG: verbose debug (if compiled in) ++ * @L2TP_MSG_CONTROL: userspace - kernel interface ++ * @L2TP_MSG_SEQ: sequence numbers ++ * @L2TP_MSG_DATA: data packets ++ */ ++enum l2tp_debug_flags { ++ L2TP_MSG_DEBUG = (1 << 0), ++ L2TP_MSG_CONTROL = (1 << 1), ++ L2TP_MSG_SEQ = (1 << 2), ++ L2TP_MSG_DATA = (1 << 3), ++}; ++ ++/* ++ * NETLINK_GENERIC related info ++ */ ++#define L2TP_GENL_NAME "l2tp" ++#define L2TP_GENL_VERSION 0x1 ++#define L2TP_GENL_MCGROUP "l2tp" ++ ++#endif /* _UAPI_LINUX_L2TP_H_ */ +diff --git a/src/basic/meson.build b/src/basic/meson.build +index 26c7fc42c76..67f04bcbc4b 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -100,6 +100,7 @@ basic_sources = files(''' + linux/if_tunnel.h + linux/in.h + linux/in6.h ++ linux/l2tp.h + linux/libc-compat.h + linux/netdevice.h + linux/netlink.h diff --git a/packages/sysutils/systemd/patches/systemd-0001-move-etc-systemd-system-to-storage-.config-system.d.patch b/packages/sysutils/systemd/patches/systemd-0001-move-etc-systemd-system-to-storage-.config-system.d.patch new file mode 100644 index 000000000..c2827cc4d --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0001-move-etc-systemd-system-to-storage-.config-system.d.patch @@ -0,0 +1,19 @@ +commit 43aba5ffffc6d35ed97db035c5818c76652b06de +Author: Matthias Reichl +Date: Mon Sep 28 23:55:13 2020 +0200 + + move /etc/systemd/system to /storage/.config/system.d + +diff --git a/meson.build b/meson.build +index dbbddb68e2..4592cd1094 100644 +--- a/meson.build ++++ b/meson.build +@@ -205,7 +205,7 @@ memory_accounting_default = get_option('memory-accounting-default') + status_unit_format_default = get_option('status-unit-format-default') + + conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir) +-conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'system')) ++conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', '/storage/.config/system.d') + conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) + conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) + conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) diff --git a/packages/sysutils/systemd/patches/systemd-0002-move-hwdb.bin-to-run.patch b/packages/sysutils/systemd/patches/systemd-0002-move-hwdb.bin-to-run.patch new file mode 100644 index 000000000..eafb7e9b7 --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0002-move-hwdb.bin-to-run.patch @@ -0,0 +1,53 @@ +From bf2776b7f9403057cb82c2697e4fca8b554db4bd Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Thu, 11 Apr 2019 20:00:05 +0100 +Subject: [PATCH] move hwdb.bin to /run + +--- + src/libsystemd/sd-hwdb/hwdb-util.c | 2 +- + src/libsystemd/sd-hwdb/sd-hwdb.c | 2 +- + units/systemd-hwdb-update.service.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-hwdb/hwdb-util.c b/src/libsystemd/sd-hwdb/hwdb-util.c +index c83575c..6285f3d 100644 +--- a/src/libsystemd/sd-hwdb/hwdb-util.c ++++ b/src/libsystemd/sd-hwdb/hwdb-util.c +@@ -20,7 +20,7 @@ + #include "strv.h" + #include "tmpfile-util.h" + +-static const char *default_hwdb_bin_dir = "/etc/udev"; ++static const char *default_hwdb_bin_dir = "/run"; + static const char * const conf_file_dirs[] = { + "/etc/udev/hwdb.d", + UDEVLIBEXECDIR "/hwdb.d", +diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c +index 79fe1a8..0acbf71 100644 +--- a/src/libsystemd/sd-hwdb/sd-hwdb.c ++++ b/src/libsystemd/sd-hwdb/sd-hwdb.c +@@ -299,7 +299,7 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) { + + static const char hwdb_bin_paths[] = + "/etc/systemd/hwdb/hwdb.bin\0" +- "/etc/udev/hwdb.bin\0" ++ "/run/hwdb.bin\0" + "/usr/lib/systemd/hwdb/hwdb.bin\0" + #if HAVE_SPLIT_USR + "/lib/systemd/hwdb/hwdb.bin\0" +diff --git a/units/systemd-hwdb-update.service.in b/units/systemd-hwdb-update.service.in +index 259fe0d..18d617f 100644 +--- a/units/systemd-hwdb-update.service.in ++++ b/units/systemd-hwdb-update.service.in +@@ -16,7 +16,7 @@ After=systemd-remount-fs.service + Before=sysinit.target shutdown.target systemd-update-done.service + ConditionNeedsUpdate=/etc + ConditionPathExists=|!@udevlibexecdir@/hwdb.bin +-ConditionPathExists=|/etc/udev/hwdb.bin ++ConditionPathExists=|/run/hwdb.bin + ConditionDirectoryNotEmpty=|/etc/udev/hwdb.d/ + + [Service] +-- +2.14.1 + diff --git a/packages/sysutils/systemd/patches/systemd-0003-remove-nonexistant-dependency.patch b/packages/sysutils/systemd/patches/systemd-0003-remove-nonexistant-dependency.patch new file mode 100644 index 000000000..abcb41211 --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0003-remove-nonexistant-dependency.patch @@ -0,0 +1,24 @@ +From 382709612ae03d6f81049ac72ac2dabd7613763d Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Wed, 18 Feb 2015 18:23:47 +0200 +Subject: [PATCH 7/8] remove nonexistant dependency + +--- + units/graphical.target | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/units/graphical.target b/units/graphical.target +index 87be97e..b01b46d 100644 +--- a/units/graphical.target ++++ b/units/graphical.target +@@ -9,7 +9,6 @@ + Description=Graphical Interface + Documentation=man:systemd.special(7) + Requires=multi-user.target +-Wants=display-manager.service + Conflicts=rescue.service rescue.target + After=multi-user.target rescue.service rescue.target display-manager.service + AllowIsolate=yes +-- +1.7.10.4 + diff --git a/packages/sysutils/systemd/patches/systemd-0200-persist-persistent-timer-stamps.patch b/packages/sysutils/systemd/patches/systemd-0200-persist-persistent-timer-stamps.patch new file mode 100644 index 000000000..3b5315afa --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0200-persist-persistent-timer-stamps.patch @@ -0,0 +1,29 @@ +From c1bcb16c35724404d30fab53017b757c886e9ab7 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 8 Jan 2018 13:46:51 +0000 +Subject: [PATCH] timers: use a persistent filesystem for persistent timers + +--- + src/core/timer.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 03935ee..bfd5c02 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -154,11 +154,11 @@ static int timer_setup_persistent(Timer *t) { + + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { + +- r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE); ++ r = unit_require_mounts_for(UNIT(t), "/storage/.cache/systemd/timers", UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + +- t->stamp_path = strjoin("/var/lib/systemd/timers/stamp-", UNIT(t)->id); ++ t->stamp_path = strjoin("/storage/.cache/systemd/timers/stamp-", UNIT(t)->id); + } else { + const char *e; + +-- +2.14.1 diff --git a/packages/sysutils/systemd/patches/systemd-0300-config-env-unhide-cursor.patch b/packages/sysutils/systemd/patches/systemd-0300-config-env-unhide-cursor.patch new file mode 100644 index 000000000..7405fa07e --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0300-config-env-unhide-cursor.patch @@ -0,0 +1,27 @@ +From 49285dae6756b22bc6881c04939f7c43c35b5506 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Sat, 29 Jun 2019 00:26:41 +0100 +Subject: [PATCH] debug-shell: configure environment, unhide cursor + +--- + units/debug-shell.service.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/units/debug-shell.service.in b/units/debug-shell.service.in +index 1127e68..4c3e971 100644 +--- a/units/debug-shell.service.in ++++ b/units/debug-shell.service.in +@@ -16,8 +16,8 @@ IgnoreOnIsolate=yes + ConditionPathExists=@DEBUGTTY@ + + [Service] +-Environment=TERM=linux +-ExecStart=@SUSHELL@ ++Environment=ENV=/etc/profile ++ExecStart=/bin/sh -c 'echo -en "\033[?25h"; exec /bin/sh' + Restart=always + RestartSec=0 + StandardInput=tty +-- +2.14.1 + diff --git a/packages/sysutils/systemd/patches/systemd-0400-hide-useless-shutdown-log-message.patch b/packages/sysutils/systemd/patches/systemd-0400-hide-useless-shutdown-log-message.patch new file mode 100644 index 000000000..eeb3454ef --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0400-hide-useless-shutdown-log-message.patch @@ -0,0 +1,46 @@ +diff -rupN systemd-247.orig/src/shutdown/shutdown.c systemd-247.new/src/shutdown/shutdown.c +--- systemd-247.orig/src/shutdown/shutdown.c 2021-02-07 14:43:00.075206218 -0500 ++++ systemd-247.new/src/shutdown/shutdown.c 2021-02-07 14:43:52.515152573 -0500 +@@ -540,13 +540,13 @@ int main(int argc, char *argv[]) { + log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m"); + } + +- if (need_umount || need_swapoff || need_loop_detach || need_dm_detach || need_md_detach) +- log_error("Failed to finalize%s%s%s%s%s ignoring.", ++ /* if (need_umount || need_swapoff || need_loop_detach || need_dm_detach || need_md_detach) ++ log_error("Failed to finalize%s%s%s%s%s ignoring.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", + need_dm_detach ? " DM devices," : "", +- need_md_detach ? " MD devices," : ""); ++ need_md_detach ? " MD devices," : ""); */ + + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we +diff -rupN systemd-247.orig/src/shutdown/umount.c systemd-247.new/src/shutdown/umount.c +--- systemd-247.orig/src/shutdown/umount.c 2021-02-07 14:43:00.075206218 -0500 ++++ systemd-247.new/src/shutdown/umount.c 2021-02-07 14:58:13.851587985 -0500 +@@ -566,8 +566,8 @@ static int umount_with_timeout(MountPoin + * filesystem less busy so the unmount might succeed (rather + * then return EBUSY).*/ + r = umount2(m->path, MNT_FORCE); +- if (r < 0) +- log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path); ++ /* if (r < 0) ++ log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path); */ + + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } +diff -rupN systemd-247.orig/src/volatile-root/volatile-root.c systemd-247.new/src/volatile-root/volatile-root.c +--- systemd-247.orig/src/volatile-root/volatile-root.c 2021-02-07 14:43:00.083206834 -0500 ++++ systemd-247.new/src/volatile-root/volatile-root.c 2021-02-07 14:58:50.713285895 -0500 +@@ -50,7 +50,7 @@ static int make_volatile(const char *pat + + r = umount_recursive(path, 0); + if (r < 0) { +- log_error_errno(r, "Failed to unmount %s: %m", path); ++ /* log_error_errno(r, "Failed to unmount %s: %m", path); */ + goto finish_umount; + } + diff --git a/packages/sysutils/systemd/patches/systemd-0500-Add-working-directory-storage-for-debug-shell.patch b/packages/sysutils/systemd/patches/systemd-0500-Add-working-directory-storage-for-debug-shell.patch new file mode 100644 index 000000000..4c5ffee7b --- /dev/null +++ b/packages/sysutils/systemd/patches/systemd-0500-Add-working-directory-storage-for-debug-shell.patch @@ -0,0 +1,24 @@ +From c38a2fc53e5ebb3fc4637a168408591003aad0fb Mon Sep 17 00:00:00 2001 +From: Portisch +Date: Mon, 30 Sep 2019 12:20:00 +0200 +Subject: [PATCH] Add working directory '/storage' for debug-shell + +--- + units/debug-shell.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/units/debug-shell.service.in b/units/debug-shell.service.in +index 9f3868e106..d5f93f18a6 100644 +--- a/units/debug-shell.service.in ++++ b/units/debug-shell.service.in +@@ -16,6 +16,7 @@ IgnoreOnIsolate=yes + ConditionPathExists=@DEBUGTTY@ + + [Service] ++WorkingDirectory=/storage + Environment=ENV=/etc/profile + ExecStart=/bin/sh -c 'echo -en "\033[?25h"; exec /bin/sh' + Restart=always +-- +2.17.1 + diff --git a/packages/sysutils/systemd/profile.d/90-systemd.conf b/packages/sysutils/systemd/profile.d/90-systemd.conf new file mode 100644 index 000000000..51962119f --- /dev/null +++ b/packages/sysutils/systemd/profile.d/90-systemd.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +export SYSTEMD_COLORS=0 diff --git a/packages/sysutils/systemd/scripts/kernel-overlays-setup b/packages/sysutils/systemd/scripts/kernel-overlays-setup new file mode 100755 index 000000000..67c5ca26f --- /dev/null +++ b/packages/sysutils/systemd/scripts/kernel-overlays-setup @@ -0,0 +1,85 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +SYSTEM_OVERLAYS_DIR=/usr/lib/kernel-overlays +OVERLAY_CONFIG_DIR=/storage/.cache/kernel-overlays +KVER=$(uname -r) +MODULES_DIR="/var/lib/modules/${KVER}" +FIRMWARE_DIR="/var/lib/firmware" +USER_FIRMWARE_DIR="/storage/.config/firmware" + +mkdir -p "${MODULES_DIR}" +mkdir -p "${FIRMWARE_DIR}" +mkdir -p "${OVERLAY_CONFIG_DIR}" + +log() { + echo "kernel-overlays-setup: $@" > /dev/kmsg +} + +apply_overlay() { + case "$1" in + /*) + modules_overlay_dir="${1}/lib/modules/${KVER}" + firmware_overlay_dir="${1}/lib/firmware" + ;; + *) + modules_overlay_dir="${SYSTEM_OVERLAYS_DIR}/${1}/lib/modules/${KVER}" + firmware_overlay_dir="${SYSTEM_OVERLAYS_DIR}/${1}/lib/firmware" + ;; + esac + + if [ -d "${modules_overlay_dir}" ] ; then + GOT_MODULE_OVERLAY="yes" + + if cp -rfs "${modules_overlay_dir}"/* "${MODULES_DIR}" ; then + log "added modules from $modules_overlay_dir" + else + log "failed to add modules from $modules_overlay_dir" + fi + fi + + if [ -d "${firmware_overlay_dir}" ] ; then + if cp -rfs "${firmware_overlay_dir}"/* "${FIRMWARE_DIR}" ; then + log "added firmware from $firmware_overlay_dir" + else + log "failed to add firmware from $firmware_overlay_dir" + fi + fi +} + +# setup system base modules + +log "setup base modules" +apply_overlay base + +# apply user-configured module overlays + +if [ -d "${OVERLAY_CONFIG_DIR}" ] ; then + log "adding overlays from ${OVERLAY_CONFIG_DIR}" + GOT_MODULE_OVERLAY="no" + + for conf in "${OVERLAY_CONFIG_DIR}/"*.conf ; do + if [ -e "$conf" ] ; then + log "processing conf $conf" + overlay=$(cat "$conf") + [ -n "$overlay" ] && apply_overlay "$overlay" + fi + done + + if [ "yes" = "$GOT_MODULE_OVERLAY" ] ; then + log "running depmod" + /usr/sbin/depmod -a + fi +fi + +if [ -d "${USER_FIRMWARE_DIR}" ] && [ -n "$(ls ${USER_FIRMWARE_DIR})" ] ; then + if cp -rfs "${USER_FIRMWARE_DIR}"/* "${FIRMWARE_DIR}" ; then + log "added firmware from ${USER_FIRMWARE_DIR}" + else + log "failed to add firmware from ${USER_FIRMWARE_DIR}" + fi +fi + +log "done" diff --git a/packages/sysutils/systemd/scripts/network-base-setup b/packages/sysutils/systemd/scripts/network-base-setup new file mode 100755 index 000000000..8475ec11f --- /dev/null +++ b/packages/sysutils/systemd/scripts/network-base-setup @@ -0,0 +1,30 @@ +#!/bin/sh + +# Source predefined functions and variables +. /etc/profile + +# get system.hostname setting +HOSTNAME=$(get_setting system.hostname) + +# setup hostname +echo $HOSTNAME > /proc/sys/kernel/hostname + +# setup /etc/hosts +rm -f /run/libreelec/hosts +if [ -f /storage/.config/hosts.conf ]; then + cat /storage/.config/hosts.conf > /run/libreelec/hosts +fi + +# setup /etc/resolv.conf +rm -f /run/libreelec/resolv.conf +if [ -f /storage/.config/resolv.conf ]; then + cat /storage/.config/resolv.conf > /run/libreelec/resolv.conf +elif [ -f /dev/.kernel_ipconfig -a -f /proc/net/pnp ]; then + cat /proc/net/pnp > /run/libreelec/resolv.conf +else + cat << EOF > /run/libreelec/resolv.conf +nameserver 8.8.8.8 +nameserver 8.8.4.4 +EOF +fi + diff --git a/packages/sysutils/systemd/scripts/systemd-machine-id-setup b/packages/sysutils/systemd/scripts/systemd-machine-id-setup new file mode 100755 index 000000000..c211973e6 --- /dev/null +++ b/packages/sysutils/systemd/scripts/systemd-machine-id-setup @@ -0,0 +1,20 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +# remove old machine-id file +[[ -f "/storage/.cache/machine-id" ]] && rm /storage/.cache/machine-id + +# If the machine id is in a tmpfs mount, unmount it +[[ "$(/usr/bin/mount 2>/dev/null| grep [m]achine-id)" ]] && umount /storage/.cache/systemd-machine-id + +# test systemd-machine-id exists and is 32 hex chars or generate a new uuid +MACHINEID="$(cat /storage/.cache/systemd-machine-id 2>/dev/null)" +[ "${#MACHINEID}" != "32" ] && MACHINEID= +[[ "${MACHINEID//[a-f0-9]/}" != "" ]] && MACHINEID= +[ -z "${MACHINEID}" ] && MACHINEID=$(/usr/bin/dbus-uuidgen) + +# persist uuid +mkdir -p /storage/.cache + echo "$MACHINEID" > /storage/.cache/systemd-machine-id diff --git a/packages/sysutils/systemd/scripts/systemd-timesyncd-setup b/packages/sysutils/systemd/scripts/systemd-timesyncd-setup new file mode 100755 index 000000000..eb9494ca5 --- /dev/null +++ b/packages/sysutils/systemd/scripts/systemd-timesyncd-setup @@ -0,0 +1,22 @@ +#!/bin/sh +KERNEL_NTP="${1:-/proc/net/ipconfig/ntp_servers}" +NTP_SERVERS="" +if [ -f /proc/net/ipconfig/ntp_servers ]; then + for srv in $(cat /proc/net/ipconfig/ntp_servers); do + if [ -n "$srv" -a "$srv" != "0.0.0.0" ]; then + if [ -z "$NTP_SERVERS" ]; then + NTP_SERVERS="$srv" + else + NTP_SERVERS="${NTP_SERVERS} $srv" + fi + fi + done + if [ -n "$NTP_SERVERS" ]; then + mkdir -p /run/systemd/timesyncd.conf.d/ + cat << EOF > /run/systemd/timesyncd.conf.d/kernel-ntp-servers.conf +[Time] +NTP=$NTP_SERVERS +EOF + fi +fi + diff --git a/packages/sysutils/systemd/scripts/usercache-setup b/packages/sysutils/systemd/scripts/usercache-setup new file mode 100755 index 000000000..9a0e7c978 --- /dev/null +++ b/packages/sysutils/systemd/scripts/usercache-setup @@ -0,0 +1,27 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# Fix bug in older versions creating file /storage/.cache/services +[ -f /storage/.cache/services ] && rm /storage/.cache/services && mkdir -p /storage/.cache/services + +# Copy cache files, but don't overwrite +false | cp -iRp /usr/cache/* /storage/.cache/ &>/dev/null + +# Merge default and custom shadow file details +if [ -f /storage/.cache/shadow -a -f /usr/cache/shadow ]; then + # Get existing root details (possibly user defined) + userroot="$(grep "^root:" /storage/.cache/shadow)" + + # Overwrite users shadow file with default details, replacing root with any existing value + # If current file is garbage (ie. missing root) then replace it + if [ -n "${userroot}" ]; then + sed -e "s ^root:.* ${userroot} " /usr/cache/shadow >/storage/.cache/shadow + else + cp -fp /usr/cache/shadow /storage/.cache/shadow + fi + + # Make sure we have the correct permission + chmod 000 /storage/.cache/shadow +fi diff --git a/packages/sysutils/systemd/scripts/userconfig-setup b/packages/sysutils/systemd/scripts/userconfig-setup new file mode 100755 index 000000000..e6607d873 --- /dev/null +++ b/packages/sysutils/systemd/scripts/userconfig-setup @@ -0,0 +1,27 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +. /etc/os-release + +# Remove those sample files that we manage +for sample in $(find /storage/.config -name '*.sample' 2>/dev/null); do + [ -f /usr/config/${sample:16} ] && rm -f ${sample} +done + +if [ ! -e "/storage/.configured" ] +then + # Copy config files, but don't overwrite. Only run if /storage is fresh + ## cp -iRp /usr/config/* /storage/.config/ &>/dev/null + ## ignore es_systems.cfg and switch to rsync + rsync -a --ignore-existing --exclude=es_systems.cfg /usr/config/* /storage/.config/ + if [ "${HW_DEVICE}" == "RG351P" ]; then + cp -f /usr/config/splash/splash-480l.png /storage/.config/emulationstation/resources/logo.png + elif [ "${HW_DEVICE}" == "RG351V" ] || [ "${HW_DEVICE}" == "RG351MP" ]; then + cp -f /usr/config/splash/splash-640.png /storage/.config/emulationstation/resources/logo.png + elif [ "${HW_DEVICE}" == "RG552" ]; then + cp -f /usr/config/splash/splash-1152.png /storage/.config/emulationstation/resources/logo.png + fi + touch /storage/.configured +fi diff --git a/packages/sysutils/systemd/system.d/debugconfig.service b/packages/sysutils/systemd/system.d/debugconfig.service new file mode 100644 index 000000000..4261d0cf4 --- /dev/null +++ b/packages/sysutils/systemd/system.d/debugconfig.service @@ -0,0 +1,14 @@ +[Unit] +Description=Setup debug config +DefaultDependencies=no +After=systemd-tmpfiles-setup.service +ConditionKernelCommandLine=|debugging +ConditionPathExists=|/storage/.cache/debug.libreelec + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /usr/share/debugconf/*.conf /run/libreelec/debug' +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/system.d/flash.mount.d/dependencies.conf b/packages/sysutils/systemd/system.d/flash.mount.d/dependencies.conf new file mode 100644 index 000000000..911bbfa0c --- /dev/null +++ b/packages/sysutils/systemd/system.d/flash.mount.d/dependencies.conf @@ -0,0 +1,2 @@ +[Unit] +DefaultDependencies=no diff --git a/packages/sysutils/systemd/system.d/hwdb.service b/packages/sysutils/systemd/system.d/hwdb.service new file mode 100644 index 000000000..a608f0fc4 --- /dev/null +++ b/packages/sysutils/systemd/system.d/hwdb.service @@ -0,0 +1,12 @@ +[Unit] +Description=Update hwdb.bin +DefaultDependencies=no +After=systemd-tmpfiles-setup.service +Before=systemd-udevd.service + +[Service] +Type=oneshot +ExecStart=-/usr/bin/udevadm hwdb --update + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/systemd/system.d/kernel-overlays.service b/packages/sysutils/systemd/system.d/kernel-overlays.service new file mode 100644 index 000000000..5d771ac3a --- /dev/null +++ b/packages/sysutils/systemd/system.d/kernel-overlays.service @@ -0,0 +1,12 @@ +[Unit] +Description=Create kernel modules tree from overlays +DefaultDependencies=no +After=var.mount +Before=systemd-udevd.service systemd-udev-trigger.service systemd-modules-load.service systemd-remount-fs.service swap.service machine-id.service kmod-static-nodes.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/kernel-overlays-setup + +[Install] +WantedBy=local-fs.target diff --git a/packages/sysutils/systemd/system.d/machine-id.service b/packages/sysutils/systemd/system.d/machine-id.service new file mode 100644 index 000000000..450b90a9f --- /dev/null +++ b/packages/sysutils/systemd/system.d/machine-id.service @@ -0,0 +1,12 @@ +[Unit] +Description=Setup machine-id +DefaultDependencies=no +Before=systemd-journald.service systemd-tmpfiles-setup-dev.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/systemd-machine-id-setup +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/system.d/network-base.service b/packages/sysutils/systemd/system.d/network-base.service new file mode 100644 index 000000000..bc2c15947 --- /dev/null +++ b/packages/sysutils/systemd/system.d/network-base.service @@ -0,0 +1,12 @@ +[Unit] +Description=Base Network Configuration +DefaultDependencies=no +After=local-fs.target systemd-tmpfiles-setup.service userconfig.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/network-base-setup +RemainAfterExit=yes + +[Install] +WantedBy=network.target diff --git a/packages/sysutils/systemd/system.d/storage.mount.d/dependencies.conf b/packages/sysutils/systemd/system.d/storage.mount.d/dependencies.conf new file mode 100644 index 000000000..911bbfa0c --- /dev/null +++ b/packages/sysutils/systemd/system.d/storage.mount.d/dependencies.conf @@ -0,0 +1,2 @@ +[Unit] +DefaultDependencies=no diff --git a/packages/sysutils/systemd/system.d/systemd-timesyncd-setup.service b/packages/sysutils/systemd/system.d/systemd-timesyncd-setup.service new file mode 100644 index 000000000..852492e3e --- /dev/null +++ b/packages/sysutils/systemd/system.d/systemd-timesyncd-setup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Setup NTP servers for timesyncd +DefaultDependencies=no +After=systemd-remount-fs.service systemd-sysusers.service + +[Service] +Type=oneshot +ExecStart=/usr/sbin/systemd-timesyncd-setup +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/system.d/systemd-timesyncd.service.d/depend-on-kernel-ip-config.conf b/packages/sysutils/systemd/system.d/systemd-timesyncd.service.d/depend-on-kernel-ip-config.conf new file mode 100644 index 000000000..7a50036ce --- /dev/null +++ b/packages/sysutils/systemd/system.d/systemd-timesyncd.service.d/depend-on-kernel-ip-config.conf @@ -0,0 +1,3 @@ +[Unit] +ConditionPathExists=/dev/.kernel_ipconfig +After=systemd-timesyncd-setup.service network-base.service diff --git a/packages/sysutils/systemd/system.d/usercache.service b/packages/sysutils/systemd/system.d/usercache.service new file mode 100644 index 000000000..26e9b5836 --- /dev/null +++ b/packages/sysutils/systemd/system.d/usercache.service @@ -0,0 +1,12 @@ +[Unit] +Description=Setup User cache dir +DefaultDependencies=no +After=systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/usercache-setup +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/system.d/userconfig.service b/packages/sysutils/systemd/system.d/userconfig.service new file mode 100644 index 000000000..2117d8957 --- /dev/null +++ b/packages/sysutils/systemd/system.d/userconfig.service @@ -0,0 +1,12 @@ +[Unit] +Description=Setup User config dir +DefaultDependencies=no +After=systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/userconfig-setup +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/systemd/tmpfiles.d/z_01_openelec.conf b/packages/sysutils/systemd/tmpfiles.d/z_01_openelec.conf new file mode 100644 index 000000000..07d11f550 --- /dev/null +++ b/packages/sysutils/systemd/tmpfiles.d/z_01_openelec.conf @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /run/libreelec 0755 root root - - +d /run/libreelec/debug 0755 root root - - diff --git a/packages/sysutils/systemd/udev.d/51-these-are-not-joysticks.rules b/packages/sysutils/systemd/udev.d/51-these-are-not-joysticks.rules new file mode 100644 index 000000000..3eaef238e --- /dev/null +++ b/packages/sysutils/systemd/udev.d/51-these-are-not-joysticks.rules @@ -0,0 +1,107 @@ +# /etc/udev/rules.d/51-these-are-not-joysticks.rules +# +# This file is auto-generated. For more information: +# https://github.com/denilsonsa/udev-joystick-blacklist + +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="009d", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="009d", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="00b0", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="00b0", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="00b4", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="00b4", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0730", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0730", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0745", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0745", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0748", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0748", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0750", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0750", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0768", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0768", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0773", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0773", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="07a5", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="07a5", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="07b2", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="07b2", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0800", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0800", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c30a", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c30a", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="a0df", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="a0df", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0010", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0010", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0011", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0011", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0012", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0012", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0013", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0013", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0014", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0014", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0015", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0015", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0016", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0016", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0017", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0017", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0018", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0018", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0019", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0019", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00d1", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00d1", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="030e", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="030e", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="054f", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="054f", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="1410", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="1410", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3043", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3043", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="31b5", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="31b5", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3997", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3997", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3f8b", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="3f8b", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="51f4", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="51f4", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="5589", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="5589", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="7b22", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="7b22", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="7f2d", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="7f2d", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="8090", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="8090", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9033", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9033", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9066", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9066", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9090", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="9090", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="90c0", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="90c0", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f012", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f012", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f32a", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f32a", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f613", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f613", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f624", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="09da", ATTRS{idProduct}=="f624", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1b1c", ATTRS{idProduct}=="1b3c", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1b1c", ATTRS{idProduct}=="1b3c", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1d57", ATTRS{idProduct}=="ad03", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1d57", ATTRS{idProduct}=="ad03", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1e7d", ATTRS{idProduct}=="2e4a", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="1e7d", ATTRS{idProduct}=="2e4a", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="422d", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="422d", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="2516", ATTRS{idProduct}=="001f", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="2516", ATTRS{idProduct}=="001f", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="2516", ATTRS{idProduct}=="0028", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{idVendor}=="2516", ATTRS{idProduct}=="0028", KERNEL=="js[0-9]*", MODE="0000", ENV{ID_INPUT_JOYSTICK}="" diff --git a/packages/sysutils/systemd/udev.d/60-not-joysticks.rules b/packages/sysutils/systemd/udev.d/60-not-joysticks.rules new file mode 100644 index 000000000..330c70f3c --- /dev/null +++ b/packages/sysutils/systemd/udev.d/60-not-joysticks.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="input", ATTRS{name}=="aml_keypad", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" +SUBSYSTEM=="input", ATTRS{name}=="Remote+", ENV{ID_INPUT_JOYSTICK}=="?*", ENV{ID_INPUT_JOYSTICK}="" diff --git a/packages/sysutils/systemd/udev.d/80-clock.rules b/packages/sysutils/systemd/udev.d/80-clock.rules new file mode 100644 index 000000000..75a4ef514 --- /dev/null +++ b/packages/sysutils/systemd/udev.d/80-clock.rules @@ -0,0 +1,2 @@ +ACTION=="add", SUBSYSTEM=="rtc", RUN+="/sbin/hwclock --hctosys --utc --rtc=/dev/%k" +ACTION=="add", ENV{MAJOR}=="10", ENV{MINOR}=="135", RUN+="/sbin/hwclock --hctosys --utc --rtc=/dev/%k" diff --git a/packages/sysutils/terminus-font/package.mk b/packages/sysutils/terminus-font/package.mk new file mode 100644 index 000000000..1c5fb325e --- /dev/null +++ b/packages/sysutils/terminus-font/package.mk @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019 Matthias Reichl + +PKG_NAME="terminus-font" +PKG_MAJOR="4.49" +PKG_MINOR=".1" +PKG_LICENSE="OFL1_1" +PKG_SITE="https://terminus-font.sourceforge.net/" +PKG_URL="https://downloads.sourceforge.net/project/${PKG_NAME}/${PKG_NAME}-${PKG_MAJOR}/${PKG_NAME}-${PKG_MAJOR}${PKG_MINOR}.tar.gz" + +PKG_DEPENDS_INIT="toolchain Python3:host" +PKG_DEPENDS_TARGET="toolchain Python3" +PKG_LONGDESC="This package contains the Terminus Font" +PKG_TOOLCHAIN="manual" + +pre_configure_init() { + cd $PKG_BUILD + rm -rf .${TARGET_NAME}-${TARGET} +} + +pre_configure_target() { + cd $PKG_BUILD + rm -rf .${TARGET_NAME}-${TARGET} +} + +configure_init() { + ./configure INT=${TOOLCHAIN}/bin/python3 +} + +configure_target() { + ./configure +} + +make_init() { + make all +} + +make_target() { + make all +} + +makeinstall_init() { + mkdir -p ${INSTALL}/usr/share/consolefonts + cp -rf *.bdf ${INSTALL}/usr/share/consolefonts + cp -rf *.psf ${INSTALL}/usr/share/consolefonts +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/consolefonts + cp -rf ${PKG_BUILD}/*.bdf ${INSTALL}/usr/share/consolefonts + cp -rf ${PKG_BUILD}/*.psf ${INSTALL}/usr/share/consolefonts +} diff --git a/packages/sysutils/tz/package.mk b/packages/sysutils/tz/package.mk new file mode 100644 index 000000000..e06404604 --- /dev/null +++ b/packages/sysutils/tz/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="tz" +PKG_VERSION="2019c" +PKG_SHA256="38b1f7c7a050daa14fb07f6b72cdde1fc895fece40758d4d55736847041ad9e2" +PKG_LICENSE="Public Domain" +PKG_SITE="http://www.iana.org/time-zones" +PKG_URL="https://github.com/eggert/tz/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Time zone and daylight-saving time data." + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="CC=$HOST_CC LDFLAGS=" +} + +makeinstall_target() { + make TZDIR="$INSTALL/usr/share/zoneinfo" REDO=posix_only TOPDIR="$INSTALL" install +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin $INSTALL/usr/sbin + + rm -rf $INSTALL/etc + mkdir -p $INSTALL/etc + ln -sf /var/run/localtime $INSTALL/etc/localtime +} + +post_install() { + enable_service tz-data.service +} diff --git a/packages/sysutils/tz/system.d/tz-data.service b/packages/sysutils/tz/system.d/tz-data.service new file mode 100644 index 000000000..d54d32b8b --- /dev/null +++ b/packages/sysutils/tz/system.d/tz-data.service @@ -0,0 +1,16 @@ +[Unit] +Description=Setup Timezone data +DefaultDependencies=no +Before=systemd-udevd.service +After=var.mount systemd-tmpfiles-setup.service + +[Service] +Type=oneshot +Environment=TIMEZONE=UTC +EnvironmentFile=-/storage/.cache/timezone +ExecStart=/bin/ln -sf /usr/share/zoneinfo/${TIMEZONE} /var/run/localtime +RemainAfterExit=yes +StartLimitInterval=0 + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/udevil/config/udevil.conf b/packages/sysutils/udevil/config/udevil.conf new file mode 100644 index 000000000..9e1669f28 --- /dev/null +++ b/packages/sysutils/udevil/config/udevil.conf @@ -0,0 +1,332 @@ +############################################################################## +# +# udevil configuration file /etc/udevil/udevil.conf +# +# This file controls what devices, networks, and files users may mount and +# unmount via udevil (set suid). +# +# IMPORTANT: IT IS POSSIBLE TO CREATE SERIOUS SECURITY PROBLEMS IF THIS FILE +# IS MISCONFIGURED - EDIT WITH CARE +# +# Note: For greater control for specific users, including root, copy this +# file to /etc/udevil/udevil-user-USERNAME.conf replacing USERNAME with the +# desired username (eg /etc/udevil/udevil-user-jim.conf). +# +# Format: +# OPTION = VALUE[, VALUE, ...] +# +# DO NOT USE QUOTES except literally +# Lines beginning with # are ignored +# +############################################################################## + + +# To log all uses of udevil, set log_file to a file path: +# log_file = /var/log/udevil.log + +# Approximate number of days to retain log entries (0=forever, max=60): +log_keep_days = 10 + + +# allowed_types determines what fstypes can be passed by a user to the u/mount +# program, what device filesystems may be un/mounted implicitly, and what +# network filesystems may be un/mounted. +# It may also include the 'file' keyword, indicating that the user is allowed +# to mount files (eg an ISO file). The $KNOWN_FILESYSTEMS variable may +# be included to include common local filesystems as well as those listed in +# /etc/filesystems and /proc/filesystems. +# allowed_types_USERNAME, if present, is used to override allowed_types for +# the specific user 'USERNAME'. For example, to allow user 'jim' to mount +# only vfat filesystems, add: +# allowed_types_jim = vfat +# Setting allowed_types = * does NOT allow all types, as this is a security +# risk, but does allow all recognized types. +# allowed_types = $KNOWN_FILESYSTEMS, file, cifs, smbfs, nfs, curlftpfs, ftpfs, sshfs, davfs, tmpfs, ramfs +allowed_types = $KNOWN_FILESYSTEMS, hfsplus, hfs + + +# allowed_users is a list of users permitted to mount and unmount with udevil. +# Wildcards (* or ?) may be used in the usernames. To allow all users, +# specify "allowed_users=*". UIDs may be included using the form UID=1000. +# For example: allowed_users = carl, UID=1000, pre* +# Also note that permission to execute udevil may be limited to users belonging +# to the group that owns /usr/bin/udevil, such as 'plugdev' or 'storage', +# depending on installation. +# allowed_users_FSTYPE, if present, is used to override allowed_users when +# mounting or unmounting a specific fstype (eg nfs, ext3, file). +# Note that when mounting a file, fstype will always be 'file' regardless of +# the internal fstype of the file. +# For example, to allow only user 'bob' to mount nfs shares, add: +# allowed_users_nfs = bob +# The root user is NOT automatically allowed to use udevil in some cases unless +# listed here (except for unmounting anything or mounting fstab devices). +allowed_users = * + + +# allowed_groups is a list of groups permitted to mount and unmount with +# udevil. The user MUST belong to at least one of these groups. Wildcards +# or GIDs may NOT be used in group names, but a single * may be used to allow +# all groups. +# Also note that permission to execute udevil may be limited to users belonging +# to the group that owns /usr/bin/udevil, such as 'plugdev' or 'storage', +# depending on installation. +# allowed_groups_FSTYPE, if present, is used to override allowed_groups when +# mounting or unmounting a specific fstype (eg nfs, ext3, file). For example, +# to allow only members of the 'network' group to mount smb and nfs shares, +# use both of these lines: +# allowed_groups_smbfs = network +# allowed_groups_nfs = network +# The root user is NOT automatically allowed to use udevil in some cases unless +# listed here (except for unmounting anything or mounting fstab devices). +allowed_groups = * + + +# allowed_media_dirs specifies the media directories in which user mount points +# may be located. The first directory which exists and does not contain a +# wildcard will be used as the default media directory (normally /media or +# /run/media/$USER). +# The $USER variable, if included, will be replaced with the username of the +# user running udevil. Wildcards may also be used in any directory EXCEPT the +# default. Wildcards will not match a / +# allowed_media_dirs_FSTYPE, if present, is used to override allowed_media_dirs +# when mounting or unmounting a specific fstype (eg ext2, nfs). For example, +# to cause /media/network to be used as the default media directory for +# nfs and ftpfs mounts, use these two lines: +# allowed_media_dirs_nfs = /media/network, /media, /run/media/$USER +# allowed_media_dirs_ftpfs = /media/network, /media, /run/media/$USER +# NOTE: If you want only the user who mounted a device to have access to it +# and be allowed to unmount it, specify /run/media/$USER as the first +# allowed media directory. +# IMPORTANT: If an allowed file is mounted to a media directory, the user may +# be permitted to unmount its associated loop device even though internal. +# INCLUDING /MNT HERE IS NOT RECOMMENDED. ALL ALLOWED MEDIA DIRECTORIES +# SHOULD BE OWNED AND WRITABLE ONLY BY ROOT. +allowed_media_dirs = /var/media, /media, /run/media/$USER + + +# allowed_devices is the first criteria for what block devices users may mount +# or unmount. If a device is not listed in allowed_devices, it cannot be +# un/mounted (unless in fstab). However, even if a device is listed, other +# factors may prevent its use. For example, access to system internal devices +# will be denied to normal users even if they are included in allowed_devices. +# allowed_devices_FSTYPE, if present, is used to override allowed_devices when +# mounting or unmounting a specific fstype (eg ext3, ntfs). For example, to +# prevent all block devices containing an ext4 filesystem from being +# un/mounted use: +# allowed_devices_ext4 = +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "allowed_devices=*" which allows any device. The recommended setting is +# allowed_devices = /dev/* +# WARNING: ALLOWING USERS TO MOUNT DEVICES OUTSIDE OF /dev CAN CAUSE SERIOUS +# SECURITY PROBLEMS. DO NOT ALLOW DEVICES IN /dev/shm +allowed_devices = /dev/* + + +# allowed_internal_devices causes udevil to treat any listed block devices as +# removable, thus allowing normal users to un/mount them (providing they are +# also listed in allowed_devices). +# allowed_internal_devices_FSTYPE, if present, is used to override +# allowed_internal_devices when mounting or unmounting a specific fstype +# (eg ext3, ntfs). For example, to allow block devices containing a vfat +# filesystem to be un/mounted even if they are system internal devices, use: +# allowed_internal_devices_vfat = /dev/sdb* +# Some removable esata drives look like internal drives to udevil. To avoid +# this problem, they can be treated as removable with this setting. +# WARNING: SETTING A SYSTEM DEVICE HERE CAN CAUSE SERIOUS SECURITY PROBLEMS. +# allowed_internal_devices = + + +# allowed_internal_uuids and allowed_internal_uuids_FSTYPE work similarly to +# allowed_internal_devices, except that UUIDs are specified instead of devices. +# For example, to allow un/mounting of an internal filesystem based on UUID: +# allowed_internal_uuids = cc0c4489-8def-1e5b-a304-ab87c3cb626c0 +# WARNING: SETTING A SYSTEM DEVICE HERE CAN CAUSE SERIOUS SECURITY PROBLEMS. +# allowed_internal_uuids = + + +# forbidden_devices is used to prevent block devices from being un/mounted +# even if other settings would allow them (except devices in fstab). +# forbidden_devices_FSTYPE, if present, is used to override +# forbidden_devices when mounting or unmounting a specific fstype +# (eg ext3, ntfs). For example, to prevent device /dev/sdd1 from being +# mounted when it contains an ntfs filesystem, use: +# forbidden_devices_ntfs = /dev/sdd1 +# NOTE: device node paths are canonicalized before being tested, so forbidding +# a link to a device will have no effect. +forbidden_devices = + + +# allowed_networks determines what hosts may be un/mounted by udevil users when +# using nfs, cifs, smbfs, curlftpfs, ftpfs, or sshfs. Hosts may be specified +# using a hostname (eg myserver.com) or IP address (192.168.1.100). +# Wildcards may be used in hostnames and IP addresses, but CIDR notation +# (192.168.1.0/16) is NOT supported. IP v6 is supported. For example: +# allowed_networks = 127.0.0.1, 192.168.1.*, 10.0.0.*, localmachine, *.okay.com +# Or, to prevent un/mounting of any network shares, set: +# allowed_networks = +# allowed_networks_FSTYPE, if present, is used to override allowed_networks +# when mounting or unmounting a specific network fstype (eg nfs, cifs, sshfs, +# curlftpfs). For example, to limit nfs and samba shares to only local +# networks, use these two lines: +# allowed_networks_nfs = 192.168.1.*, 10.0.0.* +# allowed_networks_cifs = 192.168.1.*, 10.0.0.* +allowed_networks = * + + +# forbidden_networks and forbidden_networks_FSTYPE are used to specify networks +# that are never allowed, even if other settings allow them (except fstab). +# NO REVERSE LOOKUP IS PERFORMED, so including bad.com will only have an effect +# if the user uses that hostname. IP lookup is always performed, so forbidding +# an IP address will also forbid all corresponding hostnames. +forbidden_networks = + + +# allowed_files is used to determine what files in what directories may be +# un/mounted. A user must also have read permission on a file to mount it. +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "allowed_files=*" which allows any file. For example, to allow only +# files in the /share directory to be mounted, use: +# allowed_files = /share/* +# NOTE: Specifying allowed_files_FSTYPE will NOT work because the fstype of +# files is always 'file'. +allowed_files = * + + +# forbidden_files is used to specify files that are never allowed, even if +# other settings allow them (except fstab). Specify a full path. +# Note: Wildcards may be used, but a wildcard will never match a /, except +# for "forbidden_files = *". +# NOTE: file paths are canonicalized before being tested, so forbidding +# a link to a file will have no effect. +forbidden_files = + + +# default_options specifies what options are always included when performing +# a mount, in addition to any options the user may specify. +# Note: When a device is present in /etc/fstab, and the user does not specify +# a mount point, the device is mounted with normal user permissions using +# the fstab entry, without these options. +# default_options_FSTYPE, if present, is used to override default_options +# when mounting a specific fstype (eg ext2, nfs). +# The variables $USER, $UID, and $GID are changed to the user's username, UID, +# and GID. +# FOR GOOD SECURITY, default_options SHOULD ALWAYS INCLUDE: nosuid,noexec,nodev +# WARNING: OPTIONS PRESENT OR MISSING CAN CAUSE SERIOUS SECURITY PROBLEMS. +default_options = nosuid, noexec, nodev, noatime +default_options_file = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, ro +# mount iso9660 with 'ro' to prevent mount read-only warning +default_options_iso9660 = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, ro, utf8 +default_options_udf = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_vfat = nosuid, nodev, noatime, umask=0000, uid=$UID, gid=$GID, utf8, codepage=936 +default_options_exfat = nosuid, nodev, noatime, utf8, nonempty, codepage=437 +default_options_msdos = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID +default_options_umsdos = nosuid, noexec, nodev, noatime, fmask=0133, dmask=0022, uid=$UID, gid=$GID +default_options_ntfs = nosuid, noexec, nodev, noatime, big_writes, fmask=0133, uid=$UID, gid=$GID, utf8 +default_options_cifs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_smbfs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_sshfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, nonempty, allow_other +default_options_curlftpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID, nonempty, allow_other +default_options_ftpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_davfs = nosuid, noexec, nodev, uid=$UID, gid=$GID +default_options_tmpfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID +default_options_ramfs = nosuid, noexec, nodev, noatime, uid=$UID, gid=$GID + + +# allowed_options determines all options that a user may specify when mounting. +# All the options used in default_options above must be included here too, or +# they will be rejected. If the user attempts to use an option not included +# here, an error will result. Wildcards may be used. +# allowed_options_FSTYPE, if present, is used to override allowed_options +# when mounting a specific fstype (eg ext2, nfs). +# The variables $USER, $UID, and $GID are changed to the user's username, UID, +# and GID. +# If you want to forbid remounts, remove 'remount' from here. +# WARNING: OPTIONS HERE CAN CAUSE SERIOUS SECURITY PROBLEMS - CHOOSE CAREFULLY +allowed_options = nosuid, noexec, nodev, noatime, big_writes, fmask=0133, dmask=0022, uid=$UID, gid=$GID, ro, rw, sync, flush, iocharset=*, utf8, remount +allowed_options_nfs = nosuid, noexec, nodev, noatime, ro, rw, sync, remount, port=*, rsize=*, wsize=*, hard, proto=*, timeo=*, retrans=* +allowed_options_cifs = nosuid, noexec, nodev, ro, rw, remount, port=*, user=*, username=*, pass=*, password=*, guest, domain=*, uid=$UID, gid=$GID, credentials=* +allowed_options_smbfs = nosuid, noexec, nodev, ro, rw, remount, port=*, user=*, username=*, pass=*, password=*, guest, domain=*, uid=$UID, gid=$GID, credentials=* +allowed_options_sshfs = nosuid, noexec, nodev, noatime, ro, rw, uid=$UID, gid=$GID, nonempty, allow_other, idmap=user, BatchMode=yes, port=* +allowed_options_curlftpfs = nosuid, noexec, nodev, noatime, ro, rw, uid=$UID, gid=$GID, nonempty, allow_other, user=* +allowed_options_ftpfs = nosuid, noexec, nodev, noatime, ro, rw, port=*, user=*, pass=*, ip=*, root=*, uid=$UID, gid=$GID +allowed_options_exfat = nosuid, noexec, nodev, noatime, ro, rw, uid=$UID, gid=$GID, utf8, nonempty + + +# mount_point_mode, if present and set to a non-empty value, will cause udevil +# to set the mode (permissions) on the moint point after mounting If not +# specified or if left empty, the mode is not changed. Mode must be octal +# starting with a zero (0755). +# mount_point_mode_FSTYPE, if present, is used to override mount_point_mode +# when mounting a specific fstype (eg ext2, nfs). +# NOT SETTING A MODE CAN HAVE SECURITY IMPLICATIONS FOR SOME FSTYPES +# mount_point_mode = 0755 +# don't set a mode for some types: +# mount_point_mode_sshfs = +# mount_point_mode_curlftpfs = +# mount_point_mode_ftpfs = + + +# Use the settings below to change the default locations of programs used by +# udevil, or (advanced topic) to redirect commands to your scripts. +# When substituting scripts, make sure they are root-owned and accept the +# options used by udevil (for example, the mount_program must accept --fake, +# -o, -v, and other options valid to mount.) +# Be sure to specify the full path and include NO OPTIONS or other arguments. +# These programs may also be specified as configure options when building +# udevil. +# THESE PROGRAMS ARE RUN AS ROOT +# mount_program = /bin/mount +# umount_program = /bin/umount +# losetup_program = /sbin/losetup +# setfacl_program = /usr/bin/setfacl + + +# validate_exec specifies a program or script which provides additional +# validation of a mount or unmount command, beyond the checks performed by +# udevil. The program is run as a normal user (if root runs udevil, +# validate_exec will NOT be run). The program is NOT run if the user is +# mounting a device without root priviledges (a device in fstab). +# The program is passed the username, a printable description of what is +# happening, and the entire udevil command line as the first three arguments. +# The program must return an exit status of 0 to allow the mount or unmount +# to proceed. If it returns non-zero, the user will be denied permission. +# For example, validate_exec might specify a script which notifies you +# of the command being run, or performs additional steps to authenticate the +# user. +# Specify a full path to the program, with NO options or arguments. +# validate_exec = + + +# validate_rootexec works similarly to validate_exec, except that the program +# is run as root. validate_rootexec will also be run if the root user runs +# udevil. If both validate_exec and validate_rootexec are specified, +# validate_rootexec will run first, followed by validate_exec. +# The program must return an exit status of 0 to allow the mount or unmount +# to proceed. If it returns non-zero, the user will be denied permission. +# Unless you are familiar with writing root scripts, it is recommended that +# rootexec settings NOT be used, as it is easy to inadvertently open exploits. +# THIS PROGRAM IS ALWAYS RUN AS ROOT, even if the user running udevil is not. +# validate_rootexec = + + +# success_exec is run after a successful mount, remount, or unmount. The +# program is run as a normal user (if root runs udevil, success_exec +# will NOT be run). +# The program is passed the username, a printable description of what action +# was taken, and the entire udevil command line as the first three arguments. +# The program's exit status is ignored. +# For example, success_exec might run a script which informs you of what action +# was taken, and might perform further actions. +# Specify a full path to the program, with NO options or arguments. +# success_exec = + + +# success_rootexec works similarly to success_exec, except that the program is +# run as root. success_rootexec will also be run if the root user runs udevil. +# If both success_exec and success_rootexec are specified, success_rootexec +# will run first, followed by success_exec. +# Unless you are familiar with writing root scripts, it is recommended that +# rootexec settings NOT be used, as it is easy to inadvertently open exploits. +# THIS PROGRAM IS ALWAYS RUN AS ROOT, even if the user running udevil is not. +# success_rootexec = + diff --git a/packages/sysutils/udevil/package.mk b/packages/sysutils/udevil/package.mk new file mode 100644 index 000000000..55b2873bb --- /dev/null +++ b/packages/sysutils/udevil/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="udevil" +PKG_VERSION="0.4.4" +PKG_SHA256="ce8c51fd4d589cda7be56e75b42188deeb258c66fc911a9b3a70a3945c157739" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/IgnorantGuru/udevil" +PKG_URL="https://github.com/IgnorantGuru/udevil/raw/pkg/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain systemd glib" +PKG_LONGDESC="Mounts and unmounts removable devices and networks without a password." + +PKG_CONFIGURE_OPTS_TARGET="--disable-systemd \ + --with-mount-prog=/usr/bin/mount \ + --with-umount-prog=/usr/bin/umount \ + --with-losetup-prog=/usr/sbin/losetup \ + --with-setfacl-prog=/usr/bin/setfacl" + +makeinstall_target() { + : # nothing to install +} + +post_makeinstall_target() { + mkdir -p $INSTALL/etc/udevil + cp $PKG_DIR/config/udevil.conf $INSTALL/etc/udevil + + mkdir -p $INSTALL/usr/bin + cp -PR src/udevil $INSTALL/usr/bin +} + +post_install() { + enable_service udevil-mount@.service +} diff --git a/packages/sysutils/udevil/patches/udevil-fix-build.patch b/packages/sysutils/udevil/patches/udevil-fix-build.patch new file mode 100644 index 000000000..91faec86c --- /dev/null +++ b/packages/sysutils/udevil/patches/udevil-fix-build.patch @@ -0,0 +1,11 @@ +diff -Naur udevil-0.4.4/src/device-info.c udevil-0.4.4.patch/src/device-info.c +--- udevil-0.4.4/src/device-info.c 2015-05-04 15:34:32.000000000 +0200 ++++ udevil-0.4.4.patch/src/device-info.c 2015-05-23 16:25:50.545362784 +0200 +@@ -4,6 +4,7 @@ + ************************************************************************** */ + + #include "device-info.h" ++#include + + static char * + _dupv8 (const char *s) diff --git a/packages/sysutils/udevil/system.d/udevil-mount@.service b/packages/sysutils/udevil/system.d/udevil-mount@.service new file mode 100644 index 000000000..83d142c1a --- /dev/null +++ b/packages/sysutils/udevil/system.d/udevil-mount@.service @@ -0,0 +1,10 @@ +[Unit] +Description=Udevil mount service + +[Service] +Type=oneshot +ExecStart=-/usr/bin/udevil --mount %I +ExecStop=-/usr/bin/udevil --umount %I +ExecStartPost=-/usr/lib/samba/samba-autoshare +ExecStopPost=-/usr/lib/samba/samba-autoshare +RemainAfterExit=yes diff --git a/packages/sysutils/udevil/udev.d/95-udevil-mount.rules b/packages/sysutils/udevil/udev.d/95-udevil-mount.rules new file mode 100644 index 000000000..64065d04b --- /dev/null +++ b/packages/sysutils/udevil/udev.d/95-udevil-mount.rules @@ -0,0 +1,30 @@ +# dont run in "installer" mode +IMPORT{cmdline}="installer" +ENV{installer}=="1", GOTO="exit" + +# check for blockdevices, /dev/sd*, /dev/sr* and /dev/mmc* +SUBSYSTEM!="block", KERNEL!="sd*|sr*|mmc*", GOTO="exit" + +# check for special partitions we dont want mount +IMPORT{builtin}="blkid" +ENV{ID_FS_LABEL}=="EFI|BOOT|Recovery|RECOVERY|SETTINGS|boot|root0|share0", GOTO="exit" + +# /dev/sd* and /dev/mmc* ith partitions/disk and filesystems only and /dev/sr* disks only +KERNEL=="sd*|mmc*", ENV{DEVTYPE}=="partition|disk", ENV{ID_FS_USAGE}=="filesystem", GOTO="harddisk" +KERNEL=="sr*", ENV{DEVTYPE}=="disk", GOTO="optical" +GOTO="exit" + +# mount or umount for hdds +LABEL="harddisk" +ACTION=="add", PROGRAM="/usr/bin/sh -c '/usr/bin/grep -E ^/dev/%k\ /proc/mounts || true'", RESULT=="", RUN+="/usr/bin/systemctl restart udevil-mount@/dev/%k.service" +ACTION=="remove", RUN+="/usr/bin/systemctl stop udevil-mount@/dev/%k.service" +GOTO="exit" + +# mount or umount for opticals +LABEL="optical" +ACTION=="add|change", RUN+="/usr/bin/systemctl restart udevil-mount@/dev/%k.service" +GOTO="exit" + +# Exit +LABEL="exit" + diff --git a/packages/sysutils/unrar/package.mk b/packages/sysutils/unrar/package.mk new file mode 100644 index 000000000..bc96a11bb --- /dev/null +++ b/packages/sysutils/unrar/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="unrar" +PKG_VERSION="5.6.8" +PKG_SHA256="a4cc0ac14a354827751912d2af4a0a09e2c2129df5766576fa7e151791dd3dff" +PKG_LICENSE="free" +PKG_SITE="http://www.rarlab.com" +PKG_URL="http://www.rarlab.com/rar/unrarsrc-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="unrar extract, test and view RAR archives" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+pic" + +make_target() { + make CXX="$CXX" \ + CXXFLAGS="$TARGET_CXXFLAGS" \ + RANLIB="$RANLIB" \ + AR="$AR" \ + STRIP="$STRIP" \ + -f makefile unrar + + make clean + + make CXX="$CXX" \ + CXXFLAGS="$TARGET_CXXFLAGS" \ + RANLIB="$RANLIB" \ + AR="$AR" \ + -f makefile lib +} + +post_make_target() { + rm -f libunrar.so +} diff --git a/packages/sysutils/usb-modeswitch/package.mk b/packages/sysutils/usb-modeswitch/package.mk new file mode 100644 index 000000000..93f973ff4 --- /dev/null +++ b/packages/sysutils/usb-modeswitch/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="usb-modeswitch" +PKG_VERSION="2.5.2" +PKG_SHA256="abffac09c87eacd78e101545967dc25af7e989745b4276756d45dbf4008a2ea6" +PKG_LICENSE="GPL" +PKG_SITE="http://www.draisberghof.de/usb_modeswitch/" +PKG_URL="http://www.draisberghof.de/usb_modeswitch/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libusb" +PKG_LONGDESC="USB_ModeSwitch - Handling Mode-Switching USB Devices on Linux" + +makeinstall_target() { + : +} diff --git a/packages/sysutils/usbutils/package.mk b/packages/sysutils/usbutils/package.mk new file mode 100644 index 000000000..3fbf40b17 --- /dev/null +++ b/packages/sysutils/usbutils/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="usbutils" +PKG_VERSION="008" +PKG_SHA256="44741af0bae9d402a0ef160a29b2fa700bb656ab5e0a4b3343d51249c2a44c8c" +PKG_LICENSE="GPL" +PKG_SITE="http://www.linux-usb.org/" +PKG_URL="http://kernel.org/pub/linux/utils/usb/usbutils/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libusb systemd" +PKG_LONGDESC="This package contains various utilities for inspecting and setting of devices connected to the USB bus." + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin/lsusb.py + rm -rf $INSTALL/usr/bin/usbhid-dump +} diff --git a/packages/sysutils/util-linux/config/swap.conf b/packages/sysutils/util-linux/config/swap.conf new file mode 100644 index 000000000..d02e30b03 --- /dev/null +++ b/packages/sysutils/util-linux/config/swap.conf @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +SWAPFILE="$HOME/.cache/swapfile" +SWAPFILESIZE="@SWAPFILESIZE@" +SWAP_ENABLED="@SWAP_ENABLED_DEFAULT@" \ No newline at end of file diff --git a/packages/sysutils/util-linux/package.mk b/packages/sysutils/util-linux/package.mk new file mode 100644 index 000000000..f84c2b3ed --- /dev/null +++ b/packages/sysutils/util-linux/package.mk @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="util-linux" +PKG_VERSION="2.37" +PKG_SHA256="bd07b7e98839e0359842110525a3032fdb8eaf3a90bedde3dd1652d32d15cce5" +PKG_LICENSE="GPL" +PKG_URL="https://www.kernel.org/pub/linux/utils/util-linux/v$(get_pkg_version_maj_min)/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host intltool:host libtool:host pkg-config:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_DEPENDS_INIT="toolchain" +PKG_LONGDESC="A large variety of low-level system utilities that are necessary for a Linux system to function." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic:host" + +UTILLINUX_CONFIG_DEFAULT="--disable-gtk-doc \ + --disable-nls \ + --disable-rpath \ + --enable-tls \ + --disable-all-programs \ + --enable-chsh-only-listed \ + --disable-bash-completion \ + --disable-colors-default \ + --disable-pylibmount \ + --disable-pg-bell \ + --disable-use-tty-group \ + --disable-makeinstall-chown \ + --disable-makeinstall-setuid \ + --with-gnu-ld \ + --without-selinux \ + --without-audit \ + --without-udev \ + --without-ncurses \ + --without-ncursesw \ + --without-readline \ + --without-slang \ + --without-tinfo \ + --without-utempter \ + --without-util \ + --without-libz \ + --without-user \ + --without-systemd \ + --without-smack \ + --without-python \ + --without-systemdsystemunitdir" + +PKG_CONFIGURE_OPTS_TARGET="${UTILLINUX_CONFIG_DEFAULT} \ + --enable-libuuid \ + --enable-libblkid \ + --enable-libmount \ + --enable-libsmartcols \ + --enable-losetup \ + --enable-fsck \ + --enable-fstrim \ + --enable-blkid \ + --enable-schedutils \ + --enable-lscpu" + +if [ "${SWAP_SUPPORT}" = "yes" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" --enable-swapon" +fi + +PKG_CONFIGURE_OPTS_HOST="--enable-static \ + --disable-shared \ + ${UTILLINUX_CONFIG_DEFAULT} \ + --enable-uuidgen \ + --enable-libuuid" + +PKG_CONFIGURE_OPTS_INIT="${UTILLINUX_CONFIG_DEFAULT} \ + --enable-libblkid \ + --enable-libmount \ + --enable-fsck" + +if [ "${INITRAMFS_PARTED_SUPPORT}" = "yes" ]; then + PKG_CONFIGURE_OPTS_INIT+=" --enable-mkfs --enable-libuuid" +fi + +post_makeinstall_target() { + if [ "${SWAP_SUPPORT}" = "yes" ]; then + mkdir -p ${INSTALL}/usr/lib/libreelec + cp -PR ${PKG_DIR}/scripts/mount-swap ${INSTALL}/usr/lib/libreelec + + mkdir -p ${INSTALL}/etc + cat ${PKG_DIR}/config/swap.conf | \ + sed -e "s,@SWAPFILESIZE@,${SWAPFILESIZE},g" \ + -e "s,@SWAP_ENABLED_DEFAULT@,${SWAP_ENABLED_DEFAULT},g" \ + > ${INSTALL}/etc/swap.conf + fi +} + +post_install () { + if [ "${SWAP_SUPPORT}" = "yes" ]; then + enable_service swap.service + fi +} diff --git a/packages/sysutils/util-linux/patches/util-linux-01-fix-pkgconf.patch b/packages/sysutils/util-linux/patches/util-linux-01-fix-pkgconf.patch new file mode 100644 index 000000000..7515acbc7 --- /dev/null +++ b/packages/sysutils/util-linux/patches/util-linux-01-fix-pkgconf.patch @@ -0,0 +1,75 @@ +From 4856beb5186760419bafd1f5686d6492d2d36907 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 16 Aug 2014 13:40:57 +0300 +Subject: [PATCH] fix pkgconf + +--- + libblkid/blkid.pc.in | 6 +++--- + libmount/mount.pc.in | 6 +++--- + libsmartcols/smartcols.pc.in | 6 +++--- + libuuid/uuid.pc.in | 6 +++--- + 4 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/libblkid/blkid.pc.in b/libblkid/blkid.pc.in +index 40ec8a9..056ae64 100644 +--- a/libblkid/blkid.pc.in ++++ b/libblkid/blkid.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@usrlib_execdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: blkid + Description: Block device id library +diff --git a/libmount/mount.pc.in b/libmount/mount.pc.in +index 2c32797..c8112c6 100644 +--- a/libmount/mount.pc.in ++++ b/libmount/mount.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@usrlib_execdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: mount + Description: mount library +diff --git a/libsmartcols/smartcols.pc.in b/libsmartcols/smartcols.pc.in +index 0b16739..8f474ef 100644 +--- a/libsmartcols/smartcols.pc.in ++++ b/libsmartcols/smartcols.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@usrlib_execdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: smartcols + Description: table or tree library +diff --git a/libuuid/uuid.pc.in b/libuuid/uuid.pc.in +index 875de19..ef1009e 100644 +--- a/libuuid/uuid.pc.in ++++ b/libuuid/uuid.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@usrlib_execdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: uuid + Description: Universally unique id library +-- +1.7.2.5 + diff --git a/packages/sysutils/util-linux/patches/util-linux-10-losetup-use-LOOP_CONFIGURE-in-a-more-robust-way.patch b/packages/sysutils/util-linux/patches/util-linux-10-losetup-use-LOOP_CONFIGURE-in-a-more-robust-way.patch new file mode 100644 index 000000000..e8394a93b --- /dev/null +++ b/packages/sysutils/util-linux/patches/util-linux-10-losetup-use-LOOP_CONFIGURE-in-a-more-robust-way.patch @@ -0,0 +1,36 @@ +From 583990d25b5d65a9a9771a39d112de0ee16a1f3a Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 28 Jul 2021 11:05:36 +0200 +Subject: [PATCH] losetup: use LOOP_CONFIGURE in a more robust way +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +32-bit userspace returns ENOTTY: + ioctl(4, LOOP_CONFIGURE, {fd=3, block_size=0, info={lo_offset=0, lo_number=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name="/usr/install/iso/systemrescue-8.04-amd64.iso", ...}}) = -1 ENOTTY (Inappropriate ioctl for device) + +64-bit userspace returns EINVAL: + ioctl(4, LOOP_CONFIGURE, {fd=3, block_size=0, info={lo_offset=0, lo_number=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name="/usr/src/PACKAGES/systemrescue-8.04-amd64.iso", ...}}) = -1 EINVAL (Invalid argument) + +The correct return value for an unknown ioctl is ENOTTY, but we need +to support already released kernels, so let's support both errnos. + +Reported-by: Krzysztof OlÄ™dzki +Signed-off-by: Karel Zak +--- + lib/loopdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/loopdev.c b/lib/loopdev.c +index 1eef15d89..d9ea1d4a2 100644 +--- a/lib/loopdev.c ++++ b/lib/loopdev.c +@@ -1360,7 +1360,7 @@ int loopcxt_setup_device(struct loopdev_cxt *lc) + if (ioctl(dev_fd, LOOP_CONFIGURE, &lc->config) < 0) { + rc = -errno; + errsv = errno; +- if (errno != EINVAL) { ++ if (errno != EINVAL && errno != ENOTTY) { + DBG(SETUP, ul_debugobj(lc, "LOOP_CONFIGURE failed: %m")); + goto err; + } diff --git a/packages/sysutils/util-linux/scripts/mount-swap b/packages/sysutils/util-linux/scripts/mount-swap new file mode 100755 index 000000000..21f5d8532 --- /dev/null +++ b/packages/sysutils/util-linux/scripts/mount-swap @@ -0,0 +1,50 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +. /etc/swap.conf +. /etc/profile + +if [ -f /storage/.config/swap.conf ]; then + . /storage/.config/swap.conf +fi + +if [ -f "$SWAPFILE" ]; then + if [ $(ls -l "$SWAPFILE" | awk '{print $5}') -lt $(($SWAPFILESIZE*1024*1024)) ]; then + swapoff "$SWAPFILE" + rm -rf "$SWAPFILE" + fi +fi + +if [ -e /dev/.storage_netboot ] ; then + logger -t Boot "### netbooting... swap disabled ###" + exit 0 +fi + +if [ ! "$SWAP_ENABLED" = yes ] ; then + logger -t Boot "### swap disabled via configfile ###" + exit 0 +fi + +SWAP=`blkid -t TYPE="swap" -o device` + +case $1 in + create) + if [ -z "$SWAP" -a ! -f "$SWAPFILE" ]; then + mkdir -p `dirname $SWAPFILE` + dd if=/dev/zero of=$SWAPFILE bs=1M count=$SWAPFILESIZE + chmod 0600 $SWAPFILE + mkswap $SWAPFILE + fi + ;; + mount) + [ -z "$SWAP" -a -f "$SWAPFILE" ] && SWAP=$SWAPFILE + for i in $SWAP; do + swapon -p 10000 $i + done + ;; + unmount) + swapoff -a + ;; +esac diff --git a/packages/sysutils/util-linux/sysctl.d/swappiness.conf b/packages/sysutils/util-linux/sysctl.d/swappiness.conf new file mode 100644 index 000000000..b700b4d79 --- /dev/null +++ b/packages/sysutils/util-linux/sysctl.d/swappiness.conf @@ -0,0 +1 @@ +vm.swappiness=10 \ No newline at end of file diff --git a/packages/sysutils/util-linux/system.d/swap.service b/packages/sysutils/util-linux/system.d/swap.service new file mode 100644 index 000000000..4bf0f8fb0 --- /dev/null +++ b/packages/sysutils/util-linux/system.d/swap.service @@ -0,0 +1,21 @@ +[Unit] +Description=Mounting swapfile +DefaultDependencies=false + +Before=swap.target shutdown.target +Conflicts=shutdown.target +Wants=swap.target + +ConditionPathExists=/proc/swaps +ConditionKernelCommandLine=!noswap +ConditionKernelCommandLine=!installer + +[Service] +Environment=HOME=/storage +Type=oneshot +ExecStartPre=/usr/lib/libreelec/mount-swap create +ExecStart=/usr/lib/libreelec/mount-swap mount +RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/packages/sysutils/v4l-utils/config/rc_keymaps/README b/packages/sysutils/v4l-utils/config/rc_keymaps/README new file mode 100644 index 000000000..74b4005d1 --- /dev/null +++ b/packages/sysutils/v4l-utils/config/rc_keymaps/README @@ -0,0 +1,3 @@ +RC keymaps user config dir + +put your own keymaps for ir-keytable in this directory diff --git a/packages/sysutils/v4l-utils/config/rc_maps.cfg.sample b/packages/sysutils/v4l-utils/config/rc_maps.cfg.sample new file mode 100644 index 000000000..c8f6bca22 --- /dev/null +++ b/packages/sysutils/v4l-utils/config/rc_maps.cfg.sample @@ -0,0 +1,20 @@ +# Keymaps table +# +# This table creates an association between a keycode file and a kernel +# driver. It can be used to automatically override a keycode definition. +# +# +# Format: +# driver - name of the driver provided via uevent - use * for any driver +# table - RC keymap table, provided via uevent - use * for any table +# file - file name. If directory is not specified, it is first looked up +# in /storage/.config/rc_keymaps, then /usr/lib/udev/rc_keymaps +# +# For example: +# +# driver table file +# +# gpio-rc-recv rc-streamzap streamzap +# gpio-rc-recv * justboom +# * rc-rc6-mce rc6_mce_new +# * * hauppauge_new diff --git a/packages/sysutils/v4l-utils/keymaps/a95x b/packages/sysutils/v4l-utils/keymaps/a95x new file mode 100644 index 000000000..730bf3577 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/a95x @@ -0,0 +1,35 @@ +# table a95x, type: NEC +0xdf0c KEY_NUMERIC_0 +0xdf54 KEY_NUMERIC_1 +0xdf16 KEY_NUMERIC_2 +0xdf15 KEY_NUMERIC_3 +0xdf50 KEY_NUMERIC_4 +0xdf12 KEY_NUMERIC_5 +0xdf11 KEY_NUMERIC_6 +0xdf4c KEY_NUMERIC_7 +0xdf0e KEY_NUMERIC_8 +0xdf0d KEY_NUMERIC_9 +0xdf06 KEY_ENTER +0xdf1a KEY_UP +0xdf48 KEY_DOWN +0xdf47 KEY_LEFT +0xdf07 KEY_RIGHT +0xdf18 KEY_MENU +0xdf0a KEY_BACK +0xdf5d KEY_VOLUMEUP +0xdf5c KEY_VOLUMEDOWN +0xdf4f KEY_NEXT +0xdf4b KEY_PREVIOUS +0xdf5f KEY_INFO +0xdf01 KEY_EPG +0xdf1c KEY_POWER +0xdf42 KEY_HOME # home +0xdf41 KEY_FAVORITE # planet +0xdf03 KEY_CONTEXT_MENU # mouse +0xdf10 KEY_BACK # back +0xdff1 KEY_SLEEP # TV Power +0xdff2 KEY_SELECT # TV Input +0xdff3 KEY_MUTE # TV Mute +0xdff4 KEY_PAGEUP # TV Vol- +0xdff5 KEY_PAGEDOWN # TV Vol+ +0x07 KEY_PAGEDOWN # TV Vol+ diff --git a/packages/sysutils/v4l-utils/keymaps/beelink_bt_ir b/packages/sysutils/v4l-utils/keymaps/beelink_bt_ir new file mode 100644 index 000000000..9f90188bf --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/beelink_bt_ir @@ -0,0 +1,16 @@ +# table beelink_bt_ir, type: NEC +0x8051 KEY_POWER +0x804d KEY_MUTE +0x8053 KEY_HOME +0x800d KEY_OK +0x8026 KEY_UP +0x8025 KEY_LEFT +0x8027 KEY_RIGHT +0x8028 KEY_DOWN +0x8049 KEY_MENU +0x801b KEY_BACK +0x8056 KEY_VOLUMEDOWN +0x804e KEY_VOLUMEUP +0x8041 KEY_CHANNELUP +0x8042 KEY_CHANNELDOWN +0x8044 KEY_DELETE diff --git a/packages/sysutils/v4l-utils/keymaps/beelink_pwr_only b/packages/sysutils/v4l-utils/keymaps/beelink_pwr_only new file mode 100644 index 000000000..a7157cb32 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/beelink_pwr_only @@ -0,0 +1,3 @@ +# table beelink_pwr_only, type: NEC +0x8051 KEY_POWER +0x59 KEY_POWER diff --git a/packages/sysutils/v4l-utils/keymaps/cubox_i b/packages/sysutils/v4l-utils/keymaps/cubox_i new file mode 100644 index 000000000..e23b3f19a --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/cubox_i @@ -0,0 +1,10 @@ +# table cubox_i, type: RC6 +0x1f020b0 KEY_MEDIA +0x1f02078 KEY_UP +0x1f02044 KEY_ENTER +0x1f020f8 KEY_DOWN +0x1f02004 KEY_LEFT +0x1f02084 KEY_RIGHT +0x1f020c4 KEY_BACKSPACE +0x1f02068 KEY_PLAYPAUSE +0x1f02064 KEY_EPG diff --git a/packages/sysutils/v4l-utils/keymaps/kvim b/packages/sysutils/v4l-utils/keymaps/kvim new file mode 100644 index 000000000..b07061e34 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/kvim @@ -0,0 +1,13 @@ +# table kvim, type: NEC +0x14 KEY_POWER +0x07 KEY_ENTER +0x03 KEY_UP +0x02 KEY_DOWN +0x0e KEY_LEFT +0x1a KEY_RIGHT +0x13 KEY_MENU +0x01 KEY_BACK +0x0b KEY_VOLUMEUP +0x58 KEY_VOLUMEDOWN +0x48 KEY_HOME +0x5b KEY_CONTEXT_MENU # mouse \ No newline at end of file diff --git a/packages/sysutils/v4l-utils/keymaps/kvim2 b/packages/sysutils/v4l-utils/keymaps/kvim2 new file mode 100644 index 000000000..ea0c2085a --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/kvim2 @@ -0,0 +1,46 @@ +# table kvim2, type: NEC +0x113 KEY_1 +0x112 KEY_2 +0x110 KEY_3 +0x117 KEY_4 +0x116 KEY_5 +0x114 KEY_6 +0x11b KEY_7 +0x11a KEY_8 +0x118 KEY_9 +0x11e KEY_0 +0x158 KEY_MENU +0x104 KEY_CHANNELUP +0x106 KEY_CHANNELDOWN +0x148 KEY_VOLUMEUP +0x10b KEY_VOLUMEDOWN +0x150 KEY_HOME +0x115 KEY_RIGHT +0x154 KEY_LEFT +0x159 KEY_UP +0x151 KEY_DOWN +0x155 KEY_ENTER +0x141 KEY_MUTE +0x119 KEY_BACK +0x11d KEY_INFO +0x107 KEY_STOP +0x105 KEY_PREVIOUSSONG +0x101 KEY_NEXTSONG +0x100 KEY_POWER +0x140 KEY_REWIND +0x103 KEY_FASTFORWARD +0x144 KEY_PLAYPAUSE +0x109 KEY_FAVORITES +0x15c KEY_EPG +0x11f KEY_RECORD +0x111 KEY_ESC +0x10a KEY_RED +0x14d KEY_GREEN +0x10e KEY_YELLOW +0x10c KEY_BLUE +0x149 KEY_LANGUAGE # audio +0x108 KEY_SUBTITLE # subtitle +0x10d KEY_CONTEXT_MENU # mouse +0x14c KEY_CONFIG #APPS +0x145 KEY_COMPOSE #RECALL +0x111 KEY_TEXT #TV/RADIO \ No newline at end of file diff --git a/packages/sysutils/v4l-utils/keymaps/mecool b/packages/sysutils/v4l-utils/keymaps/mecool new file mode 100644 index 000000000..ee654adb8 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/mecool @@ -0,0 +1,46 @@ +# table mecool, type: NEC +0x52 KEY_1 +0x50 KEY_2 +0x10 KEY_3 +0x56 KEY_4 +0x54 KEY_5 +0x14 KEY_6 +0x4e KEY_7 +0x4c KEY_8 +0x0c KEY_9 +0x0f KEY_0 +0x45 KEY_MENU +0x55 KEY_CHANNELUP +0x15 KEY_CHANNELDOWN +0x13 KEY_VOLUMEUP +0x17 KEY_VOLUMEDOWN +0x0d KEY_HOME +0x1b KEY_RIGHT +0x5a KEY_LEFT +0x06 KEY_UP +0x16 KEY_DOWN +0x1a KEY_ENTER +0x19 KEY_MUTE +0x05 KEY_BACK +0x02 KEY_INFO +0x44 KEY_STOP +0x08 KEY_PREVIOUSSONG +0x0b KEY_NEXTSONG +0x59 KEY_POWER +0x4a KEY_REWIND +0x48 KEY_FASTFORWARD +0x46 KEY_PLAYPAUSE +0x1f KEY_FAVORITES +0x4d KEY_EPG +0x04 KEY_RECORD +0x51 KEY_ESC +0x42 KEY_RED +0x40 KEY_GREEN +0x00 KEY_YELLOW +0x03 KEY_BLUE +0x01 KEY_LANGUAGE # audio +0x09 KEY_SUBTITLE # subtitle +0x12 KEY_CONTEXT_MENU # mouse +0x11 KEY_COMPOSE # DTV +0x58 KEY_CONFIG # APPS +0x18 KEY_TEXT # BROWSER \ No newline at end of file diff --git a/packages/sysutils/v4l-utils/keymaps/minix_neo b/packages/sysutils/v4l-utils/keymaps/minix_neo new file mode 100644 index 000000000..498282ce8 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/minix_neo @@ -0,0 +1,13 @@ +# table minix_neo, type: NEC +0x118 KEY_POWER +0x146 KEY_UP +0x116 KEY_DOWN +0x147 KEY_LEFT +0x115 KEY_RIGHT +0x155 KEY_ENTER +0x110 KEY_VOLUMEDOWN +0x140 KEY_BACK +0x114 KEY_VOLUMEUP +0x10d KEY_HOME +0x104 KEY_MENU +0x112 KEY_CONFIG diff --git a/packages/sysutils/v4l-utils/keymaps/minix_neo_pwr_only b/packages/sysutils/v4l-utils/keymaps/minix_neo_pwr_only new file mode 100644 index 000000000..59a0aa006 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/minix_neo_pwr_only @@ -0,0 +1,2 @@ +# table minix_neo_pwr_only, type: NEC +0x118 KEY_POWER diff --git a/packages/sysutils/v4l-utils/keymaps/odroid b/packages/sysutils/v4l-utils/keymaps/odroid new file mode 100644 index 000000000..49d7a17f1 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/odroid @@ -0,0 +1,13 @@ +# table odroid, type: NEC +0xb2dc KEY_POWER +0xb288 KEY_MUTE +0xb282 KEY_HOME +0xb2ce KEY_OK +0xb2ca KEY_UP +0xb299 KEY_LEFT +0xb2c1 KEY_RIGHT +0xb2d2 KEY_DOWN +0xb2c5 KEY_MENU +0xb29a KEY_BACK +0xb281 KEY_VOLUMEDOWN +0xb280 KEY_VOLUMEUP diff --git a/packages/sysutils/v4l-utils/keymaps/pine64 b/packages/sysutils/v4l-utils/keymaps/pine64 new file mode 100644 index 000000000..267d73167 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/pine64 @@ -0,0 +1,26 @@ +# table pine64, type: NEC +0x404000 KEY_NUMERIC_0 +0x404001 KEY_NUMERIC_1 +0x404002 KEY_NUMERIC_2 +0x404003 KEY_NUMERIC_3 +0x404004 KEY_NUMERIC_4 +0x404005 KEY_NUMERIC_5 +0x404006 KEY_NUMERIC_6 +0x404007 KEY_NUMERIC_7 +0x404008 KEY_NUMERIC_8 +0x404009 KEY_NUMERIC_9 +0x40400a KEY_MUTE +0x40400b KEY_UP +0x40400c KEY_BACKSPACE +0x40400d KEY_OK +0x40400e KEY_DOWN +0x404010 KEY_LEFT +0x404011 KEY_RIGHT +0x404017 KEY_VOLUMEDOWN +0x404018 KEY_VOLUMEUP +0x40401a KEY_HOME +0x40401d KEY_MENU +0x40401f KEY_WWW +0x404045 KEY_BACK +0x404047 KEY_INFO +0x40404d KEY_POWER diff --git a/packages/sysutils/v4l-utils/keymaps/tanix b/packages/sysutils/v4l-utils/keymaps/tanix new file mode 100644 index 000000000..6c8ca7a0e --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/tanix @@ -0,0 +1,14 @@ +# table tanix, type: NEC +0x40404d KEY_POWER +0x404043 KEY_MUTE +0x40400b KEY_UP +0x40400e KEY_DOWN +0x404010 KEY_LEFT +0x404011 KEY_RIGHT +0x40400d KEY_ENTER +0x40401a KEY_HOME +0x404045 KEY_MENU +0x404042 KEY_BACK +0x404018 KEY_VOLUMEUP +0x404017 KEY_VOLUMEDOWN +0x404047 KEY_PLAYPAUSE diff --git a/packages/sysutils/v4l-utils/keymaps/wetek_hub b/packages/sysutils/v4l-utils/keymaps/wetek_hub new file mode 100644 index 000000000..67fe25fc3 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/wetek_hub @@ -0,0 +1,13 @@ +# table wetek_hub, type: NEC +0x77f1 KEY_POWER +0x77f2 KEY_HOME +0x77f3 KEY_MUTE +0x77f4 KEY_UP +0x77f5 KEY_DOWN +0x77f6 KEY_LEFT +0x77f7 KEY_RIGHT +0x77f8 KEY_OK +0x77f9 KEY_BACK +0x77fa KEY_MENU +0x77fb KEY_VOLUMEUP +0x77fc KEY_VOLUMEDOWN diff --git a/packages/sysutils/v4l-utils/keymaps/wetek_play_2 b/packages/sysutils/v4l-utils/keymaps/wetek_play_2 new file mode 100644 index 000000000..154a45fb1 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/wetek_play_2 @@ -0,0 +1,44 @@ +# table wetek_play_2, type: NEC +0x5e5f02 KEY_POWER +0x5e5f46 KEY_SLEEP +0x5e5f10 KEY_MUTE +0x5e5f22 KEY_1 +0x5e5f23 KEY_2 +0x5e5f24 KEY_3 +0x5e5f25 KEY_4 +0x5e5f26 KEY_5 +0x5e5f27 KEY_6 +0x5e5f28 KEY_7 +0x5e5f29 KEY_8 +0x5e5f30 KEY_9 +0x5e5f71 KEY_ESC +0x5e5f21 KEY_0 +0x5e5f72 KEY_CAPSLOCK +0x5e5f03 KEY_HOME +0x5e5f48 KEY_MENU +0x5e5f61 KEY_BACKSPACE +0x5e5f83 KEY_EPG +0x5e5f84 KEY_COMPOSE +0x5e5f77 KEY_CONFIG +0x5e5f50 KEY_UP +0x5e5f4b KEY_DOWN +0x5e5f4c KEY_LEFT +0x5e5f4d KEY_RIGHT +0x5e5f47 KEY_ENTER +0x5e5f44 KEY_VOLUMEUP +0x5e5f43 KEY_VOLUMEDOWN +0x5e5f41 KEY_PAGEUP +0x5e5f42 KEY_PAGEDOWN +0x5e5f4f KEY_FAVORITES +0x5e5f82 KEY_TEXT +0x5e5f73 KEY_RED +0x5e5f74 KEY_GREEN +0x5e5f75 KEY_YELLOW +0x5e5f76 KEY_BLUE +0x5e5f67 KEY_PREVIOUSSONG +0x5e5f79 KEY_REWIND +0x5e5f80 KEY_FASTFORWARD +0x5e5f81 KEY_NEXTSONG +0x5e5f04 KEY_RECORD +0x5e5f2c KEY_PLAYPAUSE +0x5e5f2b KEY_STOP diff --git a/packages/sysutils/v4l-utils/keymaps/xbox_360 b/packages/sysutils/v4l-utils/keymaps/xbox_360 new file mode 100644 index 000000000..66b62adc7 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xbox_360 @@ -0,0 +1,66 @@ +# table xbox_360, type: RC6 +0x800f7400 KEY_NUMERIC_0 +0x800f7401 KEY_NUMERIC_1 +0x800f7402 KEY_NUMERIC_2 +0x800f7403 KEY_NUMERIC_3 +0x800f7404 KEY_NUMERIC_4 +0x800f7405 KEY_NUMERIC_5 +0x800f7406 KEY_NUMERIC_6 +0x800f7407 KEY_NUMERIC_7 +0x800f7408 KEY_NUMERIC_8 +0x800f7409 KEY_NUMERIC_9 +0x800f740a KEY_DELETE +0x800f740b KEY_ENTER +0x800f740c KEY_SLEEP +0x800f740d KEY_MEDIA +0x800f7464 KEY_MEDIA +0x800f740e KEY_MUTE +0x800f740f KEY_INFO +0x800f7410 KEY_VOLUMEUP +0x800f7411 KEY_VOLUMEDOWN +0x800f7412 KEY_CHANNELUP +0x800f746C KEY_CHANNELUP +0x800f7413 KEY_CHANNELDOWN +0x800f746D KEY_CHANNELDOWN +0x800f7414 KEY_FASTFORWARD +0x800f7415 KEY_REWIND +0x800f7416 KEY_PLAY +0x800f7417 KEY_RECORD +0x800f7418 KEY_PAUSE +0x800f7419 KEY_STOP +0x800f741a KEY_NEXT +0x800f741b KEY_PREVIOUS +0x800f741c KEY_NUMERIC_POUND +0x800f741d KEY_NUMERIC_STAR +0x800f741e KEY_UP +0x800f741f KEY_DOWN +0x800f7420 KEY_LEFT +0x800f7421 KEY_RIGHT +0x800f7422 KEY_OK +0x800f7423 KEY_EXIT +0x800f7424 KEY_DVD +0x800f744f KEY_EPG +0x800f7427 KEY_ZOOM +0x800f7432 KEY_MODE +0x800f7433 KEY_PRESENTATION +0x800f7428 KEY_EJECTCD +0x800f743a KEY_BRIGHTNESSUP +0x800f7446 KEY_TV +0x800f7447 KEY_AUDIO +0x800f7448 KEY_PVR +0x800f7449 KEY_CAMERA +0x800f744a KEY_VIDEO +0x800f744c KEY_LANGUAGE +0x800f7451 KEY_TITLE +0x800f744e KEY_PRINT +0x800f7450 KEY_RADIO +0x800f745a KEY_SUBTITLE +0x800f7425 KEY_RED +0x800f7466 KEY_GREEN +0x800f7426 KEY_YELLOW +0x800f7468 KEY_BLUE +0x800f7465 KEY_POWER2 +0x800f746e KEY_PLAYPAUSE +0x800f746f KEY_PLAYER +0x800f7480 KEY_BRIGHTNESSDOWN +0x800f7481 KEY_PLAYPAUSE diff --git a/packages/sysutils/v4l-utils/keymaps/xbox_dvd b/packages/sysutils/v4l-utils/keymaps/xbox_dvd new file mode 100644 index 000000000..22c9f7026 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xbox_dvd @@ -0,0 +1,28 @@ +# table xbox_dvd, type: xbox-dvd +0xa0b KEY_OK +0xaa6 KEY_UP +0xaa7 KEY_DOWN +0xaa8 KEY_RIGHT +0xaa9 KEY_LEFT +0xac3 KEY_INFO +0xac6 KEY_9 +0xac7 KEY_8 +0xac8 KEY_7 +0xac9 KEY_6 +0xaca KEY_5 +0xacb KEY_4 +0xacc KEY_3 +0xacd KEY_2 +0xace KEY_1 +0xacf KEY_0 +0xad5 KEY_ANGLE +0xad8 KEY_BACK +0xadd KEY_PREVIOUSSONG +0xadf KEY_NEXTSONG +0xae0 KEY_STOP +0xae2 KEY_REWIND +0xae3 KEY_FASTFORWARD +0xae5 KEY_TITLE +0xae6 KEY_PAUSE +0xaea KEY_PLAY +0xaf7 KEY_MENU diff --git a/packages/sysutils/v4l-utils/keymaps/xbox_one b/packages/sysutils/v4l-utils/keymaps/xbox_one new file mode 100644 index 000000000..366a58c8f --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/xbox_one @@ -0,0 +1,22 @@ +# table xbox_one, type: NEC +0x80d864 KEY_MEDIA +0x80d820 KEY_LEFT +0x80d821 KEY_RIGHT +0x80d81e KEY_UP +0x80d81f KEY_DOWN +0x80d822 KEY_OK +0x80d823 KEY_EXIT +0x80d80e KEY_MUTE +0x80d810 KEY_VOLUMEUP +0x80d811 KEY_VOLUMEDOWN +0x80d812 KEY_CHANNELUP +0x80d813 KEY_CHANNELDOWN +0x80d814 KEY_FASTFORWARD +0x80d815 KEY_REWIND +0x80d870 KEY_PLAYPAUSE +0x80d819 KEY_STOP +0x80d81a KEY_NEXT +0x80d81b KEY_PREVIOUS +0x80d826 KEY_INFO +0x80d86f KEY_EPG +0x80d86e KEY_ZOOM diff --git a/packages/sysutils/v4l-utils/keymaps/zotac b/packages/sysutils/v4l-utils/keymaps/zotac new file mode 100644 index 000000000..448d5cbb7 --- /dev/null +++ b/packages/sysutils/v4l-utils/keymaps/zotac @@ -0,0 +1,44 @@ +# table zotac, type: RC6 +0x8034048e KEY_POWER +0x8034043d KEY_SLEEP +0x80340400 KEY_NUMERIC_0 +0x80340401 KEY_NUMERIC_1 +0x80340402 KEY_NUMERIC_2 +0x80340403 KEY_NUMERIC_3 +0x80340404 KEY_NUMERIC_4 +0x80340405 KEY_NUMERIC_5 +0x80340406 KEY_NUMERIC_6 +0x80340407 KEY_NUMERIC_7 +0x80340408 KEY_NUMERIC_8 +0x80340409 KEY_NUMERIC_9 +0x80340432 KEY_NUMERIC_POUND +0x80340433 KEY_NUMERIC_STAR +0x8034043a KEY_DELETE +0x80340434 KEY_ENTER +0x8034045d KEY_MEDIA +0x8034040d KEY_MUTE +0x803404cb KEY_INFO +0x80340410 KEY_VOLUMEUP +0x80340411 KEY_VOLUMEDOWN +0x8034041e KEY_CHANNELUP +0x8034041f KEY_CHANNELDOWN +0x80340428 KEY_FASTFORWARD +0x80340429 KEY_REWIND +0x8034042c KEY_PLAY +0x80340437 KEY_RECORD +0x80340430 KEY_PAUSE +0x80340431 KEY_STOP +0x80340420 KEY_NEXT +0x80340421 KEY_PREVIOUS +0x80340458 KEY_UP +0x80340459 KEY_DOWN +0x8034045a KEY_LEFT +0x8034045b KEY_RIGHT +0x8034045c KEY_OK +0x80340483 KEY_EXIT +0x8034043e KEY_EPG +0x8034042f KEY_TITLE +0x8034046d KEY_RED +0x8034046e KEY_GREEN +0x8034046f KEY_YELLOW +0x80340470 KEY_BLUE diff --git a/packages/sysutils/v4l-utils/package.mk b/packages/sysutils/v4l-utils/package.mk new file mode 100644 index 000000000..d9ef85b6e --- /dev/null +++ b/packages/sysutils/v4l-utils/package.mk @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +# with 1.0.0 repeat delay is broken. test on upgrade + +PKG_NAME="v4l-utils" +PKG_VERSION="1.14.2" +PKG_SHA256="e6b962c4b1253cf852c31da13fd6b5bb7cbe5aa9e182881aec55123bae680692" +PKG_LICENSE="GPL" +PKG_SITE="http://linuxtv.org/" +PKG_URL="http://linuxtv.org/downloads/v4l-utils/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib systemd" +PKG_LONGDESC="Linux V4L2 and DVB API utilities and v4l libraries (libv4l)." +PKG_STAMP_VAR="$IR_REMOTE_KEYMAPS" + +PKG_CONFIGURE_OPTS_TARGET="--without-jpeg \ + --enable-static \ + --with-udevdir=/usr/lib/udev/ \ + --disable-shared" + +pre_configure_target() { + # cec-ctl fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME +} + +make_target() { + make -C utils/keytable CFLAGS="$TARGET_CFLAGS" + make -C utils/ir-ctl CFLAGS="$TARGET_CFLAGS" + if [ "$CEC_FRAMEWORK_SUPPORT" = "yes" ]; then + make -C utils/cec-ctl CFLAGS="$TARGET_CFLAGS" + fi + make -C lib CFLAGS="$TARGET_CFLAGS" + make -C utils/dvb CFLAGS="$TARGET_CFLAGS" + make -C utils/v4l2-ctl CFLAGS="$TARGET_CFLAGS" +} + +makeinstall_target() { + make install DESTDIR=$INSTALL PREFIX=/usr -C utils/keytable + make install DESTDIR=$INSTALL PREFIX=/usr -C utils/ir-ctl + if [ "$CEC_FRAMEWORK_SUPPORT" = "yes" ]; then + make install DESTDIR=$INSTALL PREFIX=/usr -C utils/cec-ctl + fi + make install DESTDIR=$INSTALL PREFIX=/usr -C utils/dvb + make install DESTDIR=$INSTALL PREFIX=/usr -C utils/v4l2-ctl +} + +create_multi_keymap() { + local f name protocols + name="$1" + protocols="$2" + shift 2 + ( + echo "# table $name, type: $protocols" + for f in "$@" ; do + echo "# $f" + grep -v "^#" $INSTALL/usr/lib/udev/rc_keymaps/$f + done + ) > $INSTALL/usr/lib/udev/rc_keymaps/$name +} + +post_makeinstall_target() { + local f keymap + + rm -rf $INSTALL/etc/rc_keymaps + ln -sf /storage/.config/rc_keymaps $INSTALL/etc/rc_keymaps + + mkdir -p $INSTALL/usr/config + cp -PR $PKG_DIR/config/* $INSTALL/usr/config + + rm -rf $INSTALL/usr/lib/udev/rules.d + mkdir -p $INSTALL/usr/lib/udev/rules.d + cp -PR $PKG_DIR/udev.d/*.rules $INSTALL/usr/lib/udev/rules.d + + # install additional keymaps without overwriting upstream maps + ( + set -C + for f in $PKG_DIR/keymaps/* ; do + if [ -e $f ] ; then + keymap=$(basename $f) + cat $f > $INSTALL/usr/lib/udev/rc_keymaps/$keymap + fi + done + ) + + # create multi keymap to support several remotes OOTB + if [ -n "$IR_REMOTE_PROTOCOLS" -a -n "$IR_REMOTE_KEYMAPS" ]; then + create_multi_keymap libreelec_multi "$IR_REMOTE_PROTOCOLS" $IR_REMOTE_KEYMAPS + + # use multi-keymap instead of default one + sed -i '/^\*\s*rc-rc6-mce\s*rc6_mce/d' $INSTALL/etc/rc_maps.cfg + + cat << EOF >> $INSTALL/etc/rc_maps.cfg +# +# Custom LibreELEC configuration starts here +# +# use combined multi-table on MCE receivers +# * rc-rc6-mce rc6_mce +* rc-rc6-mce libreelec_multi +# table for Xbox DVD Playback Kit +* rc-xbox-dvd xbox_dvd +# multi-table for amlogic devices +meson-ir * libreelec_multi +EOF + + fi +} diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-0001-fix-build-with-glibc_2.28.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-0001-fix-build-with-glibc_2.28.patch new file mode 100644 index 000000000..851406f40 --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-0001-fix-build-with-glibc_2.28.patch @@ -0,0 +1,37 @@ +From a46598389950a9764399667c7d30f318c95ffd0a Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Wed, 1 Aug 2018 23:21:24 +0100 +Subject: [PATCH] fix build with glibc-2.28 + +--- + lib/libv4lconvert/control/libv4lcontrol.c | 1 + + utils/v4l2-ctl/v4l2-ctl.cpp | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/lib/libv4lconvert/control/libv4lcontrol.c b/lib/libv4lconvert/control/libv4lcontrol.c +index 1e784ed..1252847 100644 +--- a/lib/libv4lconvert/control/libv4lcontrol.c ++++ b/lib/libv4lconvert/control/libv4lcontrol.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp +index e02dc75..287114b 100644 +--- a/utils/v4l2-ctl/v4l2-ctl.cpp ++++ b/utils/v4l2-ctl/v4l2-ctl.cpp +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.14.1 + diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-0002-add-power-on-argument.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-0002-add-power-on-argument.patch new file mode 100644 index 000000000..87cc02018 --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-0002-add-power-on-argument.patch @@ -0,0 +1,201 @@ +diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c +index 34a1522..88ee52b 100644 +--- a/utils/keytable/keytable.c ++++ b/utils/keytable/keytable.c +@@ -228,6 +228,7 @@ static const struct argp_option options[] = { + {"clear", 'c', 0, 0, N_("clears the old table"), 0}, + {"sysdev", 's', N_("SYSDEV"), 0, N_("ir class device to control"), 0}, + {"test", 't', 0, 0, N_("test if IR is generating events"), 0}, ++ {"power-key", 'u', 0, 0, N_("will scan for NEC power on code"), 0}, + {"device", 'd', N_("DEV"), 0, N_("ir device to control"), 0}, + {"read", 'r', 0, 0, N_("reads the current scancode/keycode table"), 0}, + {"write", 'w', N_("TABLE"), 0, N_("write (adds) the scancodes to the device scancode/keycode table from an specified file"), 0}, +@@ -254,6 +255,7 @@ static int readtable = 0; + static int clear = 0; + static int debug = 0; + static int test = 0; ++static int poweron = 0; + static int delay = -1; + static int period = -1; + static enum sysfs_protocols ch_proto = 0; +@@ -478,6 +480,9 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state) + case 't': + test++; + break; ++ case 'u': ++ poweron++; ++ break; + case 'c': + clear++; + break; +@@ -1339,7 +1344,7 @@ static void print_scancodes(const struct lirc_scancode *scancodes, unsigned coun + } + } + +-static void test_event(struct rc_device *rc_dev, int fd) ++static void test_event(struct rc_device *rc_dev, int fd, int power_on) + { + struct input_event ev[64]; + struct lirc_scancode sc[64]; +@@ -1364,7 +1369,11 @@ static void test_event(struct rc_device *rc_dev, int fd) + } + } + +- printf (_("Testing events. Please, press CTRL-C to abort.\n")); ++ if (!power_on) ++ printf (_("Testing events. Please, press CTRL-C to abort.\n")); ++ else ++ printf (_("Waiting for NEC decode event. Please, press CTRL-C to abort.\n")); ++ + while (1) { + struct pollfd pollstruct[2] = { + { .fd = fd, .events = POLLIN }, +@@ -1399,54 +1408,72 @@ static void test_event(struct rc_device *rc_dev, int fd) + return; + } + +- for (i = 0; i < rd / sizeof(struct input_event); i++) { +- printf(_("%ld.%06ld: event type %s(0x%02x)"), +- ev[i].time.tv_sec, ev[i].time.tv_usec, +- get_event_name(events_type, ev[i].type), ev[i].type); ++ if (!power_on) { ++ for (i = 0; i < rd / sizeof(struct input_event); i++) { ++ printf(_("%ld.%06ld: event type %s(0x%02x)"), ++ ev[i].time.tv_sec, ev[i].time.tv_usec, ++ get_event_name(events_type, ev[i].type), ev[i].type); + +- switch (ev[i].type) { +- case EV_SYN: +- printf(".\n"); +- break; +- case EV_KEY: +- printf(_(" key_%s: %s(0x%04x)\n"), +- (ev[i].value == 0) ? _("up") : _("down"), +- get_event_name(key_events, ev[i].code), +- ev[i].code); +- break; +- case EV_REL: +- printf(_(": %s (0x%04x) value=%d\n"), +- get_event_name(rel_events, ev[i].code), +- ev[i].code, +- ev[i].value); +- break; +- case EV_ABS: +- printf(_(": %s (0x%04x) value=%d\n"), +- get_event_name(abs_events, ev[i].code), +- ev[i].code, +- ev[i].value); +- break; +- case EV_MSC: +- if (ev[i].code == MSC_SCAN) +- printf(_(": scancode = 0x%02x\n"), ev[i].value); +- else +- printf(_(": code = %s(0x%02x), value = %d\n"), +- get_event_name(msc_events, ev[i].code), ++ switch (ev[i].type) { ++ case EV_SYN: ++ printf(".\n"); ++ break; ++ case EV_KEY: ++ printf(_(" key_%s: %s(0x%04x)\n"), ++ (ev[i].value == 0) ? _("up") : _("down"), ++ get_event_name(key_events, ev[i].code), ++ ev[i].code); ++ break; ++ case EV_REL: ++ printf(_(": %s (0x%04x) value=%d\n"), ++ get_event_name(rel_events, ev[i].code), ++ ev[i].code, ++ ev[i].value); ++ break; ++ case EV_ABS: ++ printf(_(": %s (0x%04x) value=%d\n"), ++ get_event_name(abs_events, ev[i].code), ++ ev[i].code, ++ ev[i].value); ++ break; ++ case EV_MSC: ++ if (ev[i].code == MSC_SCAN) ++ printf(_(": scancode = 0x%02x\n"), ev[i].value); ++ else ++ printf(_(": code = %s(0x%02x), value = %d\n"), ++ get_event_name(msc_events, ev[i].code), ++ ev[i].code, ev[i].value); ++ break; ++ case EV_REP: ++ printf(_(": value = %d\n"), ev[i].value); ++ break; ++ case EV_SW: ++ case EV_LED: ++ case EV_SND: ++ case EV_FF: ++ case EV_PWR: ++ case EV_FF_STATUS: ++ default: ++ printf(_(": code = 0x%02x, value = %d\n"), + ev[i].code, ev[i].value); +- break; +- case EV_REP: +- printf(_(": value = %d\n"), ev[i].value); +- break; +- case EV_SW: +- case EV_LED: +- case EV_SND: +- case EV_FF: +- case EV_PWR: +- case EV_FF_STATUS: +- default: +- printf(_(": code = 0x%02x, value = %d\n"), +- ev[i].code, ev[i].value); +- break; ++ break; ++ } ++ } ++ } else { ++ for (i = 0; i < rd / sizeof(struct input_event); i++) { ++ ++ switch (ev[i].type) { ++ case EV_MSC: ++ if (ev[i].code == MSC_SCAN) { ++ unsigned int nec_code = ++ ((~ev[i].value & 0xFF) << 24) | ++ ((ev[i].value & 0xFF) << 16) | ++ ((~(ev[i].value >> 8) & 0xFF) << 8) | ++ ((ev[i].value >> 8) & 0xFF); ++ printf(_("Received NEC code: 0x%08X\n"), nec_code); ++ } ++ break; ++ } + } + } + } +@@ -1624,7 +1651,7 @@ int main(int argc, char *argv[]) + argp_parse(&argp, argc, argv, ARGP_NO_HELP, 0, 0); + + /* Just list all devices */ +- if (!clear && !readtable && !keytable && !ch_proto && !cfg.next && !test && delay < 0 && period < 0) { ++ if (!clear && !readtable && !keytable && !ch_proto && !cfg.next && !test && !poweron && delay < 0 && period < 0) { + if (devicename) { + fd = open(devicename, O_RDONLY); + if (fd < 0) { +@@ -1750,6 +1777,9 @@ int main(int argc, char *argv[]) + /* + * Third step: change protocol + */ ++ if (poweron) ++ ch_proto = SYSFS_NEC; ++ + if (ch_proto) { + rc_dev.current = ch_proto; + if (set_proto(&rc_dev)) +@@ -1780,8 +1810,8 @@ int main(int argc, char *argv[]) + set_rate(fd, new_delay, new_period); + } + +- if (test) +- test_event(&rc_dev, fd); ++ if (test || poweron) ++ test_event(&rc_dev, fd, poweron); + + return 0; + } diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-0002-backport-imon-and-rcmm-protocol-support.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-0002-backport-imon-and-rcmm-protocol-support.patch new file mode 100644 index 000000000..9b04950ee --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-0002-backport-imon-and-rcmm-protocol-support.patch @@ -0,0 +1,35 @@ +From dc70f6cdfa9980b707a958cfca9a3820d51af8f6 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sat, 23 Mar 2019 10:11:55 +0100 +Subject: [PATCH] keytable: backport imon and rc-mm protocols + +Signed-off-by: Matthias Reichl +--- + utils/keytable/keytable.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c +index 34a1522e..67c6f92c 100644 +--- a/utils/keytable/keytable.c ++++ b/utils/keytable/keytable.c +@@ -112,6 +112,8 @@ enum sysfs_protocols { + SYSFS_SHARP = (1 << 11), + SYSFS_XMP = (1 << 12), + SYSFS_CEC = (1 << 13), ++ SYSFS_IMON = (1 << 14), ++ SYSFS_RCMM = (1 << 15), + SYSFS_INVALID = 0, + }; + +@@ -145,6 +147,8 @@ const struct protocol_map_entry protocol_map[] = { + { "sharp", NULL, SYSFS_SHARP }, + { "xmp", "/xmp_decoder", SYSFS_XMP }, + { "cec", NULL, SYSFS_CEC }, ++ { "imon", NULL, SYSFS_IMON }, ++ { "rc-mm", NULL, SYSFS_RCMM }, + { NULL, NULL, SYSFS_INVALID }, + }; + +-- +2.20.1 + diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-0003-add-xbox-dvd-protocol.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-0003-add-xbox-dvd-protocol.patch new file mode 100644 index 000000000..1bbfabae7 --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-0003-add-xbox-dvd-protocol.patch @@ -0,0 +1,33 @@ +From dbf64abf9eed823b35a2931d4882905b6106461e Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sat, 23 Mar 2019 10:19:48 +0100 +Subject: [PATCH] keytable: add xbox-dvd protocol + +Signed-off-by: Matthias Reichl +--- + utils/keytable/keytable.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c +index 67c6f92c..4ee280cc 100644 +--- a/utils/keytable/keytable.c ++++ b/utils/keytable/keytable.c +@@ -114,6 +114,7 @@ enum sysfs_protocols { + SYSFS_CEC = (1 << 13), + SYSFS_IMON = (1 << 14), + SYSFS_RCMM = (1 << 15), ++ SYSFS_XBOX_DVD = (1 << 16), + SYSFS_INVALID = 0, + }; + +@@ -149,6 +150,7 @@ const struct protocol_map_entry protocol_map[] = { + { "cec", NULL, SYSFS_CEC }, + { "imon", NULL, SYSFS_IMON }, + { "rc-mm", NULL, SYSFS_RCMM }, ++ { "xbox-dvd", NULL, SYSFS_XBOX_DVD }, + { NULL, NULL, SYSFS_INVALID }, + }; + +-- +2.20.1 + diff --git a/packages/sysutils/v4l-utils/patches/v4l-utils-0004-add-power-on-argument-fixup.patch b/packages/sysutils/v4l-utils/patches/v4l-utils-0004-add-power-on-argument-fixup.patch new file mode 100644 index 000000000..7f1290f49 --- /dev/null +++ b/packages/sysutils/v4l-utils/patches/v4l-utils-0004-add-power-on-argument-fixup.patch @@ -0,0 +1,91 @@ +diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c +index b45b1fe..1097eb0 100644 +--- a/utils/keytable/keytable.c ++++ b/utils/keytable/keytable.c +@@ -115,6 +115,7 @@ enum sysfs_protocols { + SYSFS_IMON = (1 << 14), + SYSFS_RCMM = (1 << 15), + SYSFS_XBOX_DVD = (1 << 16), ++ SYSFS_IRMP = (1 << 17), + SYSFS_INVALID = 0, + }; + +@@ -151,6 +152,7 @@ const struct protocol_map_entry protocol_map[] = { + { "imon", NULL, SYSFS_IMON }, + { "rc-mm", NULL, SYSFS_RCMM }, + { "xbox-dvd", NULL, SYSFS_XBOX_DVD }, ++ { "irmp", "/irmp_decoder", SYSFS_IRMP }, + { NULL, NULL, SYSFS_INVALID }, + }; + +@@ -234,7 +236,7 @@ static const struct argp_option options[] = { + {"clear", 'c', 0, 0, N_("clears the old table"), 0}, + {"sysdev", 's', N_("SYSDEV"), 0, N_("ir class device to control"), 0}, + {"test", 't', 0, 0, N_("test if IR is generating events"), 0}, +- {"power-key", 'u', 0, 0, N_("will scan for NEC power on code"), 0}, ++ {"power-key", 'u', 0, 0, N_("will scan for a compatible power on code"), 0}, + {"device", 'd', N_("DEV"), 0, N_("ir device to control"), 0}, + {"read", 'r', 0, 0, N_("reads the current scancode/keycode table"), 0}, + {"write", 'w', N_("TABLE"), 0, N_("write (adds) the scancodes to the device scancode/keycode table from an specified file"), 0}, +@@ -1356,6 +1358,8 @@ static void test_event(struct rc_device *rc_dev, int fd, int power_on) + struct lirc_scancode sc[64]; + int rd, i, lircfd = -1; + unsigned mode; ++ unsigned protocol; ++ unsigned undefined; + + /* LIRC reports time in monotonic, set event to same */ + mode = CLOCK_MONOTONIC; +@@ -1378,7 +1382,7 @@ static void test_event(struct rc_device *rc_dev, int fd, int power_on) + if (!power_on) + printf (_("Testing events. Please, press CTRL-C to abort.\n")); + else +- printf (_("Waiting for NEC decode event. Please, press CTRL-C to abort.\n")); ++ printf (_("Waiting for IRMP decode event. Please, press CTRL-C to abort.\n")); + + while (1) { + struct pollfd pollstruct[2] = { +@@ -1471,12 +1475,28 @@ static void test_event(struct rc_device *rc_dev, int fd, int power_on) + switch (ev[i].type) { + case EV_MSC: + if (ev[i].code == MSC_SCAN) { +- unsigned int nec_code = +- ((~ev[i].value & 0xFF) << 24) | +- ((ev[i].value & 0xFF) << 16) | +- ((~(ev[i].value >> 8) & 0xFF) << 8) | +- ((ev[i].value >> 8) & 0xFF); +- printf(_("Received NEC code: 0x%08X\n"), nec_code); ++ if ((ev[i].value & 0xFFFFFF00) == 0xA0A0A000) { ++ protocol = ev[i].value & 0xFF; ++ undefined = 0; ++ mode = 0; ++ } ++ else if ((ev[i].value & 0xFFFFFF00) == 0xB0B0B000) { ++ protocol = ev[i].value & 0xFF; ++ undefined = 1; ++ mode = 0; ++ } ++ else if (!mode) { ++ if (!undefined) { ++ printf(_("Received IRMP code: remotewakeup='0x%08x', decode_type='0x%x', "), ev[i].value, protocol); ++ mode = 1; ++ } ++ else ++ printf(_("Received IRMP code: scancode='0x%08x', IRMP protocol = %d, decode_type is undefined!\n"), ev[i].value, protocol); ++ } ++ else if (mode) { ++ printf(_("remotewakeupmask='0x%08x'\n"), ev[i].value); ++ mode = 0; ++ } + } + break; + } +@@ -1784,7 +1804,7 @@ int main(int argc, char *argv[]) + * Third step: change protocol + */ + if (poweron) +- ch_proto = SYSFS_NEC; ++ ch_proto = SYSFS_IRMP; + + if (ch_proto) { + rc_dev.current = ch_proto; diff --git a/packages/sysutils/v4l-utils/udev.d/70-infrared.rules b/packages/sysutils/v4l-utils/udev.d/70-infrared.rules new file mode 100644 index 000000000..26728303b --- /dev/null +++ b/packages/sysutils/v4l-utils/udev.d/70-infrared.rules @@ -0,0 +1,19 @@ + +# Automatically load the proper keymaps after the Remote Controller device +# creation. +# +# User-defined rules can be stored in /storage/.config/rc_maps.cfg. If that +# file doesn't exist the default rules from /etc/rc_maps.cfg are used. + +ACTION=="add", KERNEL=="event*", SUBSYSTEM=="input", SUBSYSTEMS=="rc", ENV{.rc_sysdev}="$id", GOTO="begin" +GOTO="end" + +LABEL="begin" + +ENV{.rc_maps_cfg}="/etc/rc_maps.cfg" +TEST=="/storage/.config/rc_maps.cfg", ENV{.rc_maps_cfg}="/storage/.config/rc_maps.cfg" + +RUN+="/usr/bin/ir-keytable -a $env{.rc_maps_cfg} -s $env{.rc_sysdev}" + +LABEL="end" + diff --git a/packages/sysutils/v4l-utils/udev.d/70-input-repeat.rules b/packages/sysutils/v4l-utils/udev.d/70-input-repeat.rules new file mode 100644 index 000000000..541276b87 --- /dev/null +++ b/packages/sysutils/v4l-utils/udev.d/70-input-repeat.rules @@ -0,0 +1,18 @@ +ACTION=="add", SUBSYSTEM=="input", KERNEL=="event[0-9]*", GOTO="start" +GOTO="end" +LABEL="start" + +# don't change eventlircd device settings +ATTRS{name}=="eventlircd", GOTO="end" + +# don't change settings of rc remotes +SUBSYSTEMS=="rc", GOTO="end" + +# set default repeat delay to 500ms like rc remotes +RUN+="/usr/bin/ir-keytable --delay=500 --device=$devnode" + +# make lircd-uinput use same repeat period like keyboards in kodi +ATTRS{name}=="lircd-uinput", \ + RUN+="/usr/bin/ir-keytable --period=80 --device=$devnode" + +LABEL="end" diff --git a/packages/sysutils/v86d/package.mk b/packages/sysutils/v86d/package.mk new file mode 100644 index 000000000..2a2355d49 --- /dev/null +++ b/packages/sysutils/v86d/package.mk @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="v86d" +PKG_VERSION="0.1.10" +PKG_SHA256="634964ae18ef68c8493add2ce150e3b4502badeb0d9194b4bd81241d25e6735c" +PKG_ARCH="x86_64" +PKG_LICENSE="GPL" +PKG_SITE="http://dev.gentoo.org/~spock/projects/uvesafb/" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_INIT="toolchain gcc:init" +PKG_LONGDESC="v86d is the userspace helper that runs x86 code in an emulated environment." + +pre_configure_init() { + INIT_CONFIGURE_OPTS="--with-x86emu" + +# v86d fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME-init +} + +makeinstall_init() { + DESTDIR=$INSTALL/usr make install +} diff --git a/packages/sysutils/v86d/patches/v86d-0.1.10-crosscompiling.patch b/packages/sysutils/v86d/patches/v86d-0.1.10-crosscompiling.patch new file mode 100644 index 000000000..f4acf7fd0 --- /dev/null +++ b/packages/sysutils/v86d/patches/v86d-0.1.10-crosscompiling.patch @@ -0,0 +1,12 @@ +diff -Naur v86d-0.1.10/libs/x86emu/Makefile v86d-0.1.10.patch/libs/x86emu/Makefile +--- v86d-0.1.10/libs/x86emu/Makefile 2011-02-25 22:27:39.000000000 +0100 ++++ v86d-0.1.10.patch/libs/x86emu/Makefile 2012-06-28 20:15:36.486234182 +0200 +@@ -1,7 +1,7 @@ + OBJS = decode.o fpu.o ops.o ops2.o prim_ops.o sys.o + + libx86emu.a: $(OBJS) +- ar rv $@ $+ ++ $(AR) rv $@ $+ + + %.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< diff --git a/packages/sysutils/v86d/patches/v86d-0.1.10-dont-include-kernelheaders.patch b/packages/sysutils/v86d/patches/v86d-0.1.10-dont-include-kernelheaders.patch new file mode 100644 index 000000000..c188f0553 --- /dev/null +++ b/packages/sysutils/v86d/patches/v86d-0.1.10-dont-include-kernelheaders.patch @@ -0,0 +1,18 @@ +diff -Naur v86d-0.1.10/Makefile v86d-0.1.10.patch/Makefile +--- v86d-0.1.10/Makefile 2011-02-25 22:27:39.000000000 +0100 ++++ v86d-0.1.10.patch/Makefile 2013-01-14 19:20:13.385465794 +0100 +@@ -3,14 +3,12 @@ + .PHONY: clean install install_testvbe x86emu lrmi + + INSTALL = install +-KDIR ?= /lib/modules/$(shell uname -r)/source + + ifeq ($(call config_opt,CONFIG_KLIBC),true) + export CC = klcc + endif + + CFLAGS ?= -Wall -g -O2 +-CFLAGS += -I$(KDIR)/include + + ifeq ($(call config_opt,CONFIG_X86EMU),true) + CFLAGS += -Ilibs/x86emu diff --git a/packages/sysutils/wait-time-sync/package.mk b/packages/sysutils/wait-time-sync/package.mk new file mode 100644 index 000000000..b45468f08 --- /dev/null +++ b/packages/sysutils/wait-time-sync/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wait-time-sync" +PKG_VERSION="1.0" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A simple tool and systemd service to wait until NTP time is synced" + + +post_install() { + enable_service wait-time-sync.service +} diff --git a/packages/sysutils/wait-time-sync/sources/Makefile b/packages/sysutils/wait-time-sync/sources/Makefile new file mode 100644 index 000000000..1014a4452 --- /dev/null +++ b/packages/sysutils/wait-time-sync/sources/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +.PHONY: all +all: wait-time-sync + +PREFIX = /usr + +.PHONY: install +install: wait-time-sync + install -d $(DESTDIR)$(PREFIX)/bin + install $< $(DESTDIR)$(PREFIX)/bin diff --git a/packages/sysutils/wait-time-sync/sources/wait-time-sync.c b/packages/sysutils/wait-time-sync/sources/wait-time-sync.c new file mode 100644 index 000000000..52cd5d780 --- /dev/null +++ b/packages/sysutils/wait-time-sync/sources/wait-time-sync.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) */ + +#include +#include +#include + +int main() +{ + int rc; + + for (;;) + { + struct timex tx = {}; + + rc = adjtimex(&tx); + if (rc != TIME_ERROR) + break; + usleep(1000000U/3); + } + + return rc == -1 ? errno : 0; +} diff --git a/packages/sysutils/wait-time-sync/system.d/wait-time-sync.service b/packages/sysutils/wait-time-sync/system.d/wait-time-sync.service new file mode 100644 index 000000000..64059530c --- /dev/null +++ b/packages/sysutils/wait-time-sync/system.d/wait-time-sync.service @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file was part of systemd. +# Modified by Team LibreELEC (https://libreelec.tv) +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Wait For Kernel Time Synchronized + +ConditionVirtualization=!container + +DefaultDependencies=no +Before=time-sync.target shutdown.target +Wants=time-sync.target +Conflicts=shutdown.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/wait-time-sync +TimeoutStartSec=30 +RemainAfterExit=yes + +[Install] +WantedBy=sysinit.target diff --git a/packages/sysutils/wget/package.mk b/packages/sysutils/wget/package.mk new file mode 100644 index 000000000..c6e317134 --- /dev/null +++ b/packages/sysutils/wget/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="wget" +PKG_VERSION="1.21.2" +PKG_SHA256="e6d4c76be82c676dd7e8c61a29b2ac8510ae108a810b5d1d18fc9a1d2c9a2497" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/wget/" +PKG_URL="http://ftpmirror.gnu.org/wget/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="ccache:host" +PKG_LONGDESC="GNU Wget is a free software package for retrieving files using HTTP, HTTPS, FTP and FTPS" + +PKG_CONFIGURE_OPTS_HOST="--disable-nls --disable-acl --without-selinux" + +post_install() { + echo -e "\nca_directory = /usr/lib/ssl" >> $INSTALL/etc/wgetrc +} diff --git a/packages/testing/package.mk b/packages/testing/package.mk new file mode 100644 index 000000000..50edb5b78 --- /dev/null +++ b/packages/testing/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="testing" +PKG_VERSION="" +PKG_LICENSE="various" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="virtual" +PKG_LONGDESC="testing: Metapackage for various packages to test while developing" diff --git a/packages/textproc/expat/package.mk b/packages/textproc/expat/package.mk new file mode 100644 index 000000000..ad7a2ea1e --- /dev/null +++ b/packages/textproc/expat/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="expat" +PKG_VERSION="2.4.1" +PKG_SHA256="2f9b6a580b94577b150a7d5617ad4643a4301a6616ff459307df3e225bcfbf40" +PKG_LICENSE="OSS" +PKG_SITE="http://expat.sourceforge.net/" +PKG_URL="https://github.com/libexpat/libexpat/releases/download/R_${PKG_VERSION//./_}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Expat is an XML parser library written in C." + +PKG_CMAKE_OPTS_TARGET="-DBUILD_doc=OFF -DBUILD_tools=OFF -DBUILD_examples=OFF -DBUILD_tests=OFF -DBUILD_shared=ON" +PKG_CMAKE_OPTS_HOST="-DBUILD_doc=OFF -DBUILD_tools=OFF -DBUILD_examples=OFF -DBUILD_tests=OFF -DBUILD_shared=ON" + diff --git a/packages/textproc/harfbuzz/package.mk b/packages/textproc/harfbuzz/package.mk new file mode 100644 index 000000000..63b496aaa --- /dev/null +++ b/packages/textproc/harfbuzz/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="harfbuzz" +PKG_VERSION="1.8.1" +PKG_SHA256="fbed6392ddb085e45e6090a9f389f72926d0e355f4b0a2ef51d35cf21686df45" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freedesktop.org/wiki/Software/HarfBuzz" +PKG_URL="https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain cairo freetype glib icu" +PKG_LONGDESC="HarfBuzz is an OpenType text shaping engine." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--with-icu \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf" + +pre_configure_target() { + export LDFLAGS="$LDFLAGS -ldl" +} diff --git a/packages/textproc/icu/package.mk b/packages/textproc/icu/package.mk new file mode 100644 index 000000000..df29d427d --- /dev/null +++ b/packages/textproc/icu/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="icu" +PKG_VERSION="68.1" +PKG_SHA256="a9f2e3d8b4434b8e53878b4308bd1e6ee51c9c7042e2b1a376abefb6fbb29f2d" +PKG_LICENSE="Custom" +PKG_SITE="http://www.icu-project.org" +PKG_URL="https://github.com/unicode-org/icu/releases/download/release-${PKG_VERSION//./-}/icu4c-${PKG_VERSION//./_}-src.tgz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain icu:host" +PKG_LONGDESC="International Components for Unicode library." + +PKG_ICU_OPTS="--disable-extras \ + --disable-icuio \ + --disable-layoutex \ + --disable-renaming \ + --disable-samples \ + --disable-tests" + +PKG_CONFIGURE_OPTS_HOST="$PKG_ICU_OPTS" + +configure_package() { + rm -f $TOOLCHAIN/lib/libicu*.a + PKG_CONFIGURE_OPTS_TARGET="--disable-tools + --with-cross-build=$PKG_BUILD/.$HOST_NAME \ + $PKG_ICU_OPTS" + + PKG_CONFIGURE_SCRIPT="${PKG_BUILD}/source/configure" +} diff --git a/packages/textproc/icu/patches/icu-01_ldflags.patch b/packages/textproc/icu/patches/icu-01_ldflags.patch new file mode 100644 index 000000000..24e13d28d --- /dev/null +++ b/packages/textproc/icu/patches/icu-01_ldflags.patch @@ -0,0 +1,12 @@ +Fix a runtime error on some devices. Without this patch, code from the icu libraries might fail to run with a message "internal error", and ldd will output "not a dynamic executable" on them. +--- a/source/config/mh-linux 2020-04-22 19:49:10.000000000 +0200 ++++ b/source/config/mh-linux 2020-09-05 17:58:05.635014182 +0200 +@@ -23,7 +23,7 @@ + LD_RPATH_PRE = -Wl,-rpath, + + ## These are the library specific LDFLAGS +-LDFLAGSICUDT=-nodefaultlibs -nostdlib ++#LDFLAGSICUDT=-nodefaultlibs -nostdlib + + ## Compiler switch to embed a library name + # The initial tab in the next line is to prevent icu-config from reading it. diff --git a/packages/textproc/jsoncpp/package.mk b/packages/textproc/jsoncpp/package.mk new file mode 100644 index 000000000..5bf39aadc --- /dev/null +++ b/packages/textproc/jsoncpp/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="jsoncpp" +PKG_VERSION="1.8.4" +PKG_SHA256="c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/open-source-parsers/jsoncpp/" +PKG_URL="https://github.com/open-source-parsers/jsoncpp/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A C++ library for interacting with JSON." +PKG_TOOLCHAIN="cmake" +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DJSONCPP_WITH_TESTS=OFF" diff --git a/packages/textproc/libiconv/package.mk b/packages/textproc/libiconv/package.mk new file mode 100644 index 000000000..127e24f27 --- /dev/null +++ b/packages/textproc/libiconv/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libiconv" +PKG_VERSION="1.15" +PKG_SHA256="ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178" +PKG_LICENSE="GPL" +PKG_SITE="https://savannah.gnu.org/projects/libiconv/" +PKG_URL="http://ftp.gnu.org/pub/gnu/libiconv/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A tool that converts from one character encoding to another through Unicode conversion." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--host=$TARGET_NAME \ + --build=$HOST_NAME \ + --prefix=/usr \ + --includedir=/usr/include/iconv \ + --libdir=/usr/lib/iconv \ + --sysconfdir=/etc \ + --enable-static \ + --disable-shared \ + --disable-nls \ + --disable-extra-encodings \ + --with-gnu-ld" diff --git a/packages/textproc/libidn2/package.mk b/packages/textproc/libidn2/package.mk new file mode 100644 index 000000000..1be8dd572 --- /dev/null +++ b/packages/textproc/libidn2/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libidn2" +PKG_VERSION="2.1.1a" +PKG_SHA256="57666bcf6ecf54230d7bac95c392379561954b57a673903aed4d3336b3048b72" +PKG_LICENSE="LGPL3" +PKG_SITE="https://www.gnu.org/software/libidn/" +PKG_URL="http://ftpmirror.gnu.org/gnu/libidn/libidn2-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Free software implementation of IDNA2008, Punycode and TR46." + +PKG_CONFIGURE_OPTS_TARGET="--disable-doc \ + --enable-shared \ + --disable-static" + +post_makeinstall_target() { + safe_remove ${INSTALL}/usr/bin +} diff --git a/packages/textproc/libxml2/package.mk b/packages/textproc/libxml2/package.mk new file mode 100644 index 000000000..2909c5d2d --- /dev/null +++ b/packages/textproc/libxml2/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxml2" +PKG_VERSION="2.9.10" +#PKG_SHA256="" +PKG_LICENSE="MIT" +PKG_SITE="http://xmlsoft.org" +PKG_URL="ftp://xmlsoft.org/libxml2/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="zlib:host" +PKG_DEPENDS_TARGET="toolchain zlib" +PKG_LONGDESC="The libxml package contains an XML library, which allows you to manipulate XML files." + +PKG_CONFIGURE_OPTS_ALL="ac_cv_header_ansidecl_h=no \ + --enable-static \ + --enable-shared \ + --disable-silent-rules \ + --enable-ipv6 \ + --without-python \ + --with-zlib=$TOOLCHAIN \ + --without-lzma" + +PKG_CONFIGURE_OPTS_HOST="$PKG_CONFIGURE_OPTS_ALL --with-zlib=$TOOLCHAIN" + +PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_ALL --with-zlib=$SYSROOT_PREFIX/usr --with-sysroot=$SYSROOT_PREFIX" + +post_makeinstall_target() { + sed -e "s:\(['= ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/bin/xml2-config + + rm -rf $INSTALL/usr/bin/xml2-config + rm -rf $INSTALL/usr/lib/xml2Conf.sh +} diff --git a/packages/textproc/libxslt/package.mk b/packages/textproc/libxslt/package.mk new file mode 100644 index 000000000..879460915 --- /dev/null +++ b/packages/textproc/libxslt/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxslt" +PKG_VERSION="1.1.33" +PKG_SHA256="8e36605144409df979cab43d835002f63988f3dc94d5d3537c12796db90e38c8" +PKG_LICENSE="MIT" +PKG_SITE="http://xmlsoft.org/xslt/" +PKG_URL="ftp://xmlsoft.org/libxml2/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="libxml2:host" +PKG_DEPENDS_TARGET="toolchain libxml2" +PKG_LONGDESC="A XSLT C library." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_HOST=" ac_cv_header_ansidecl_h=no \ + ac_cv_header_xlocale_h=no \ + --enable-static \ + --disable-shared \ + --without-python \ + --with-libxml-prefix=$TOOLCHAIN \ + --without-crypto" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_ansidecl_h=no \ + ac_cv_header_xlocale_h=no \ + --enable-static \ + --disable-shared \ + --without-python \ + --with-libxml-prefix=$SYSROOT_PREFIX/usr \ + --without-crypto" + +post_makeinstall_target() { + sed -e "s:\(['= ]\)/usr:\\1$SYSROOT_PREFIX/usr:g" -i $SYSROOT_PREFIX/usr/bin/xslt-config + + rm -rf $INSTALL/usr/bin/xsltproc + rm -rf $INSTALL/usr/lib/xsltConf.sh +} diff --git a/packages/textproc/nlohmann-json/package.mk b/packages/textproc/nlohmann-json/package.mk new file mode 100644 index 000000000..1811435f6 --- /dev/null +++ b/packages/textproc/nlohmann-json/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nlohmann-json" +PKG_VERSION="3.6.1" +PKG_SHA256="80c45b090e40bf3d7a7f2a6e9f36206d3ff710acfa8d8cc1f8c763bb3075e22e" +PKG_LICENSE="MIT" +PKG_SITE="https://nlohmann.github.io/json/" +PKG_URL="https://github.com/nlohmann/json/archive/v$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="JSON for Modern C++" +PKG_TOOLCHAIN="cmake" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_TESTING:BOOL=OFF" diff --git a/packages/textproc/rapidxml/package.mk b/packages/textproc/rapidxml/package.mk new file mode 100644 index 000000000..628f9c70c --- /dev/null +++ b/packages/textproc/rapidxml/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rapidxml" +PKG_VERSION="1.13" +PKG_SHA256="c3f0b886374981bb20fabcf323d755db4be6dba42064599481da64a85f5b3571" +PKG_LICENSE="Boost/MIT" +PKG_SITE="https://sourceforge.net/projects/rapidxml/" +PKG_URL="https://sourceforge.net/projects/rapidxml/files/$PKG_NAME-$PKG_VERSION.zip" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A fast XML DOM parser." +PKG_TOOLCHAIN="manual" + +post_unpack() { + mkdir -p $PKG_BUILD/rapidxml + mv $PKG_BUILD/*.hpp $PKG_BUILD/rapidxml +} diff --git a/packages/textproc/textviewer/package.mk b/packages/textproc/textviewer/package.mk new file mode 100644 index 000000000..276a9df6a --- /dev/null +++ b/packages/textproc/textviewer/package.mk @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="textviewer" +PKG_VERSION="6820fd6e036e33f3d56b036978e6ec3c870c6b28" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/lethal-guitar/TvTextViewer" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_SHORTDESC="Full-screen text viewer tool with gamepad controls" +PKG_TOOLCHAIN="make" +GET_HANDLER_SUPPORT="git" + +pre_patch() { + find $(echo "${PKG_BUILD}" | cut -f1 -d\ ) -type f -exec dos2unix -q {} \; +} + +pre_configure_target() { + sed -i "s|sdl2-config|$SYSROOT_PREFIX/usr/bin/sdl2-config|g" Makefile + sed -i 's|ImGui::SetNextWindowFocus();|ImGui::SetFocusID(ImGui::GetID("Close"), ImGui::GetCurrentWindow());\n ImGui::GetCurrentContext()->NavDisableHighlight = false;\n ImGui::GetCurrentContext()->NavDisableMouseHover = true;|g' view.cpp + sed -i 's|ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(ImColor(94, 11, 22, 255))); // Set window background to red|ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(ImColor(100, 0, 0, 255)));\n ImGui::PushStyleColor(ImGuiCol_NavHighlight, ImVec4(ImColor(180, 0, 0, 255)));\n ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(ImColor(180, 0, 0, 255)));|g' main.cpp + sed -i 's|ImColor(94, 11, 22,|ImColor(180, 0, 0,|g' main.cpp + sed -i 's|BUTTON_START|BUTTON_INVALID|g' main.cpp + + if [[ "$DEVICE" == "RG351P" ]] || [[ "$DEVICE" == "RG552" ]]; then + sed -i 's| ImGui::GetIO().Fonts->AddFontDefault(&config);| ImGui::GetIO().Fonts->AddFontDefault(\&config);\n }\n else\n {\n ImFontConfig config;\n config.SizePixels = 13;\n ImGui::GetIO().Fonts->AddFontDefault(\&config);|g' main.cpp + else + sed -i 's| ImGui::GetIO().Fonts->AddFontDefault(&config);| ImGui::GetIO().Fonts->AddFontDefault(\&config);\n }\n else\n {\n ImFontConfig config;\n config.SizePixels = 20;\n ImGui::GetIO().Fonts->AddFontDefault(\&config);|g' main.cpp + fi + +} + +makeinstall_target(){ + mkdir -p $INSTALL/usr/bin + cp text_viewer $INSTALL/usr/bin +} diff --git a/packages/textproc/tinyxml/package.mk b/packages/textproc/tinyxml/package.mk new file mode 100644 index 000000000..afb9c5b44 --- /dev/null +++ b/packages/textproc/tinyxml/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="tinyxml" +PKG_VERSION="2.6.2_2" +PKG_SHA256="8164c9ad48b9028667768a584d62f7760cfbfb90d0dd6214ad174403058da10c" +PKG_LICENSE="OSS" +PKG_SITE="http://www.grinninglizard.com/tinyxml/" +PKG_URL="http://mirrors.xbmc.org/build-deps/sources/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="TinyXML is a simple, small, C++ XML parser." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --with-pic" + +post_makeinstall_target() { + rm -rf $INSTALL/usr +} diff --git a/packages/textproc/tinyxml2/package.mk b/packages/textproc/tinyxml2/package.mk new file mode 100644 index 000000000..efd5247ba --- /dev/null +++ b/packages/textproc/tinyxml2/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="tinyxml2" +PKG_VERSION="1.0.12" +PKG_SHA256="53a4dd1b3aed4aa05b18782e303646669d2d3b2de3c1919fe21aea319b44de7f" +PKG_LICENSE="zlib" +PKG_SITE="http://www.grinninglizard.com/tinyxml2/index.html" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="TinyXML2 is a simple, small, C++ XML parser." +PKG_BUILD_FLAGS="+pic" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SHARED_LIBS=off -DBUILD_STATIC_LIBS=on" + +post_makeinstall_target() { + rm -rf $INSTALL/usr +} diff --git a/packages/textproc/tinyxml2/patches/tinyxml2-0001-really-disable-shared-build.patch b/packages/textproc/tinyxml2/patches/tinyxml2-0001-really-disable-shared-build.patch new file mode 100644 index 000000000..917c759d1 --- /dev/null +++ b/packages/textproc/tinyxml2/patches/tinyxml2-0001-really-disable-shared-build.patch @@ -0,0 +1,30 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -51,26 +51,12 @@ if(BUILD_STATIC_LIBS) + add_library(tinyxml2static STATIC tinyxml2.cpp tinyxml2.h) + set_target_properties(tinyxml2static PROPERTIES OUTPUT_NAME tinyxml2) + endif(BUILD_STATIC_LIBS) +-add_library(tinyxml2 SHARED tinyxml2.cpp tinyxml2.h) +-set_target_properties(tinyxml2 PROPERTIES +- VERSION "${GENERIC_LIB_VERSION}" +- SOVERSION "${GENERIC_LIB_SOVERSION}") +- +-add_executable(test xmltest.cpp) +-add_dependencies(test tinyxml2) +-add_dependencies(test ${TARGET_DATA_COPY}) +-target_link_libraries(test tinyxml2) +- + + if(BUILD_STATIC_LIBS) +- install(TARGETS tinyxml2 tinyxml2static ++ install(TARGETS tinyxml2static + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +-else(BUILD_STATIC_LIBS) +- install(TARGETS tinyxml2 +- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif(BUILD_STATIC_LIBS) + install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + diff --git a/packages/textproc/xmlstarlet/package.mk b/packages/textproc/xmlstarlet/package.mk new file mode 100644 index 000000000..78967bb28 --- /dev/null +++ b/packages/textproc/xmlstarlet/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="xmlstarlet" +PKG_VERSION="1.6.1" +PKG_SHA256="15d838c4f3375332fd95554619179b69e4ec91418a3a5296e7c631b7ed19e7ca" +PKG_LICENSE="MIT" +PKG_SITE="http://xmlstar.sourceforge.net" +PKG_URL="http://netcologne.dl.sourceforge.net/project/xmlstar/$PKG_NAME/$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="libxml2:host libxslt:host" +PKG_DEPENDS_TARGET="toolchain libxml2 libxslt" +PKG_LONGDESC="XMLStarlet is a command-line XML utility which allows the modification and validation of XML documents." + +PKG_CONFIGURE_OPTS_HOST=" ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + --enable-static-libs \ + LIBXML_CONFIG=$TOOLCHAIN/bin/xml2-config \ + LIBXSLT_CONFIG=$TOOLCHAIN/bin/xslt-config \ + --with-libxml-include-prefix=$TOOLCHAIN/include/libxml2 \ + --with-libxml-libs-prefix=$TOOLCHAIN/lib \ + --with-libxslt-include-prefix=$TOOLCHAIN/include \ + --with-libxslt-libs-prefix=$TOOLCHAIN/lib" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + --enable-static-libs \ + LIBXML_CONFIG=$SYSROOT_PREFIX/usr/bin/xml2-config \ + LIBXSLT_CONFIG=$SYSROOT_PREFIX/usr/bin/xslt-config \ + --with-libxml-include-prefix=$SYSROOT_PREFIX/usr/include/libxml2 \ + --with-libxml-libs-prefix=$SYSROOT_PREFIX/usr/lib \ + --with-libxslt-include-prefix=$SYSROOT_PREFIX/usr/include \ + --with-libxslt-libs-prefix=$SYSROOT_PREFIX/usr/lib" + +post_makeinstall_host() { + ln -sf xml $TOOLCHAIN/bin/xmlstarlet +} + +post_makeinstall_target() { + ln -sf xml $INSTALL/usr/bin/xmlstarlet +} diff --git a/packages/textproc/xmlstarlet/patches/xmlstarlet-0001-usage2c.awk-fix-wrong-basename-regexp.patch b/packages/textproc/xmlstarlet/patches/xmlstarlet-0001-usage2c.awk-fix-wrong-basename-regexp.patch new file mode 100644 index 000000000..24b187f2a --- /dev/null +++ b/packages/textproc/xmlstarlet/patches/xmlstarlet-0001-usage2c.awk-fix-wrong-basename-regexp.patch @@ -0,0 +1,37 @@ +Upstream-Status: Submitted [sourceforge] + +From 75d789d0ea9716c9a9ae72f42a2fcfa907cf4a12 Mon Sep 17 00:00:00 2001 +From: Matthieu Crapet +Date: Mon, 30 Jun 2014 13:52:25 +0200 +Subject: [PATCH] usage2c.awk: fix wrong basename regexp + +Previously not matching with filename argument with absolute path. + +Signed-off-by: Matthieu Crapet +--- + usage2c.awk | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/usage2c.awk b/usage2c.awk +index 94b897a..9aea212 100755 +--- a/usage2c.awk ++++ b/usage2c.awk +@@ -6,13 +6,13 @@ BEGIN { + } + + # text in src/foo-bar.txt results in +-# static const char foo_text[] = { ++# static const char foo_bar[] = { + # 't', 'h', 'e', ' ', 't', 'e', 'x', 't', ... + # } + length(command_name) == 0 { + command_name = FILENAME; + sub(/\.txt$/, "", command_name); +- sub(/^([^\/]+\/)*/, "", command_name); ++ sub(/^.*\//, "", command_name); + gsub(/-/, "_", command_name); + printf("static const char %s[] = {\n", command_name); + progs = 0; +-- +2.0.0 + diff --git a/packages/tools/SDL2_gfx/package.mk b/packages/tools/SDL2_gfx/package.mk new file mode 100644 index 000000000..830766ab7 --- /dev/null +++ b/packages/tools/SDL2_gfx/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="SDL2_gfx" +PKG_VERSION="16fa07d08e7cee5ad7dc815cfd1f4816e36cc73c" +PKG_SHA256="6be035fb9f59e3c80503c6fd20fd59354338df56b7839e87d13d1e2a8102dec4" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/jjYBdx4IL/SDL2_gfx" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="SDL_image is an image file loading library. " +PKG_TOOLCHAIN="configure" + +pre_configure_target() { +export CC=$CC +} +PKG_CONFIGURE_OPTS_TARGET=" --disable-mmx" + diff --git a/packages/tools/SDL2_image/package.mk b/packages/tools/SDL2_image/package.mk new file mode 100644 index 000000000..31cba0dce --- /dev/null +++ b/packages/tools/SDL2_image/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="SDL2_image" +PKG_VERSION="2.0.5" +#PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libsdl.org/" +PKG_URL="https://www.libsdl.org/projects/SDL_image/release/SDL2_image-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="SDL_image is an image file loading library. " + diff --git a/packages/tools/SDL2_mixer/package.mk b/packages/tools/SDL2_mixer/package.mk new file mode 100644 index 000000000..955a2e745 --- /dev/null +++ b/packages/tools/SDL2_mixer/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="SDL2_mixer" +PKG_VERSION="2.0.4" +PKG_SHA256="" +PKG_LICENSE="GPLv3" +PKG_SITE="http://www.libsdl.org/projects/SDL_mixer/release" +PKG_URL="$PKG_SITE/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain alsa-lib SDL2 libogg libvorbis flac mpg123 libmodplug" +PKG_LONGDESC="SDL2 mixer" + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} --enable-music-mp3" +} diff --git a/packages/tools/SDL2_net/package.mk b/packages/tools/SDL2_net/package.mk new file mode 100644 index 000000000..b8417f5c3 --- /dev/null +++ b/packages/tools/SDL2_net/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="SDL2_net" +PKG_VERSION="2.0.1" +PKG_SHA256="15ce8a7e5a23dafe8177c8df6e6c79b6749a03fff1e8196742d3571657609d21" +PKG_LICENSE="GPL" +PKG_SITE="https://www.libsdl.org/projects/SDL_net/" +PKG_URL="https://www.libsdl.org/projects/SDL_net/release/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2" +PKG_LONGDESC="SDL2_net: network library" diff --git a/packages/tools/SDL2_ttf/package.mk b/packages/tools/SDL2_ttf/package.mk new file mode 100644 index 000000000..6f8c77411 --- /dev/null +++ b/packages/tools/SDL2_ttf/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="SDL2_ttf" +PKG_VERSION="2.0.14" +#PKG_SHA256="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libsdl.org/" +PKG_URL="https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain SDL2 freetype" +PKG_LONGDESC="This is a sample library which allows you to use TrueType fonts in your SDL applications" +PACKAGE_TOOLCHAIN="autoconf" + +if [ ! "$DISPLAYSERVER" = "x11" ]; then + X11="--without-x" +fi + +PKG_CONFIGURE_OPTS_TARGET="--with-freetype-prefix=$SYSROOT_PREFIX/usr $X11" diff --git a/packages/tools/SDL2_ttf/patches/SDL2_ttf-001-opengl-only-with-x.patch b/packages/tools/SDL2_ttf/patches/SDL2_ttf-001-opengl-only-with-x.patch new file mode 100644 index 000000000..aef457611 --- /dev/null +++ b/packages/tools/SDL2_ttf/patches/SDL2_ttf-001-opengl-only-with-x.patch @@ -0,0 +1,45 @@ +--- a/configure 2016-10-19 00:05:10.219995829 +0200 ++++ b/configure 2016-10-19 00:06:41.154100063 +0200 +@@ -12945,44 +12945,10 @@ + + if test x$have_x = xyes; then + CFLAGS="$CFLAGS $X_CFLAGS" +- SYS_GL_LIBS="$X_LIBS -lGL" +- else +- SYS_GL_LIBS="-lGL" ++ SYS_GL_LIBS="$X_LIBS -lGL -DHAVE_OPENGL" + fi + ;; + esac +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL support" >&5 +-$as_echo_n "checking for OpenGL support... " >&6; } +-have_opengl=no +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +- #include "SDL_opengl.h" +- +-int +-main () +-{ +- +- GLuint texture; +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_compile "$LINENO"; then : +- +-have_opengl=yes +- +-fi +-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_opengl" >&5 +-$as_echo "$have_opengl" >&6; } +-if test x$have_opengl = xyes; then +- CFLAGS="$CFLAGS -DHAVE_OPENGL" +- GL_LIBS="$SYS_GL_LIBS" +-else +- GL_LIBS="" +-fi diff --git a/packages/tools/aml-dtbtools/package.mk b/packages/tools/aml-dtbtools/package.mk new file mode 100644 index 000000000..4e7d68312 --- /dev/null +++ b/packages/tools/aml-dtbtools/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="aml-dtbtools" +PKG_VERSION="cce100f" +PKG_SHA256="8bcaa83fcc9e85c9c04930e7411447d96a97da0809c5ecd9af91c8b554133c41" +PKG_LICENSE="free" +PKG_SITE="https://github.com/Wilhansen/aml-dtbtools" +PKG_URL="https://github.com/Wilhansen/aml-dtbtools/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="gcc:host" +PKG_LONGDESC="AML DTB Tools" + +PKG_MAKE_OPTS_HOST="dtbTool" + +makeinstall_host() { + mkdir -p $TOOLCHAIN/bin + cp dtbTool $TOOLCHAIN/bin +} diff --git a/packages/tools/atf/package.mk b/packages/tools/atf/package.mk new file mode 100644 index 000000000..d48dc715d --- /dev/null +++ b/packages/tools/atf/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC + +PKG_NAME="atf" +PKG_VERSION="v2.1" +PKG_SHA256="7c4c00a4f28d3cfbb235fd1a1fb28c4d2fc1d657c9301686e7d8824ef575d059" +PKG_ARCH="arm aarch64" +PKG_LICENSE="BSD-3c" +PKG_SITE="https://github.com/ARM-software/arm-trusted-firmware" +PKG_URL="https://github.com/ARM-software/arm-trusted-firmware/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="ARM Trusted Firmware is a reference implementation of secure world software, including a Secure Monitor executing at Exception Level 3 and various Arm interface standards." +PKG_TOOLCHAIN="manual" +PKG_IS_KERNEL_PKG="yes" + +make_target() { + CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" CFLAGS="" make PLAT=$ATF_PLATFORM bl31 +} + +post_make_target() { + cp -av build/$ATF_PLATFORM/release/bl31.bin . +} diff --git a/packages/tools/atf/patches/01-plat-allwinner-h6-add-wdt_quirk-to-use-r_wdt-instead.patch b/packages/tools/atf/patches/01-plat-allwinner-h6-add-wdt_quirk-to-use-r_wdt-instead.patch new file mode 100644 index 000000000..51dbfc961 --- /dev/null +++ b/packages/tools/atf/patches/01-plat-allwinner-h6-add-wdt_quirk-to-use-r_wdt-instead.patch @@ -0,0 +1,36 @@ +From 523ab5be1a84e9aa15fb62c3a15a6338b01d3961 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Tue, 9 Apr 2019 00:15:06 +0200 +Subject: [PATCH] plat: allwinner: common: use r_wdog instead of wdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some Allwinner H6 has a broken watchdog that doesn't +make the soc reboot. + +Use the R_WATCHDOG instead. + +Signed-off-by: Clément Péron +Change-Id: Ie95cc30a80ed517b60b30d6bc2e655a1b53f18ba +--- + plat/allwinner/common/sunxi_pm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c +index 1d2dc93852..13e1353258 100644 +--- a/plat/allwinner/common/sunxi_pm.c ++++ b/plat/allwinner/common/sunxi_pm.c +@@ -20,9 +20,9 @@ + #include + #include + +-#define SUNXI_WDOG0_CTRL_REG (SUNXI_WDOG_BASE + 0x0010) +-#define SUNXI_WDOG0_CFG_REG (SUNXI_WDOG_BASE + 0x0014) +-#define SUNXI_WDOG0_MODE_REG (SUNXI_WDOG_BASE + 0x0018) ++#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010) ++#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014) ++#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018) + + #define mpidr_is_valid(mpidr) ( \ + MPIDR_AFFLVL3_VAL(mpidr) == 0 && \ diff --git a/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/config.txt b/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/config.txt new file mode 100644 index 000000000..2a326c212 --- /dev/null +++ b/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/config.txt @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) +################################################################################ +# Bootloader configuration - config.txt +################################################################################ + +################################################################################ +# Memory (System/GPU configuration ) +################################################################################ + +# Default GPU memory split (do not change if you do not know what you are doing) + gpu_mem=128 + +# Configure GPU memory based on SDRAM size - overrides above setting + gpu_mem_256=112 + gpu_mem_512=160 + gpu_mem_1024=256 + +################################################################################ +# For overclocking and various other settings, see: +# https://www.raspberrypi.org/documentation/configuration/config-txt.md +################################################################################ +# Set 'force_turbo=1' to disable dynamic overclocking and enable overclocking always. +force_turbo=0 + +# Make display smaller to stop text spilling off the screen +# +# Note that the overscan settings only affect the splash screen and not Kodi. +# +# If you experience overscan/underscan issues the best solution is to adjust +# your TV settings ("full pixel", "1-1 pixel" etc.). Alternatively, there is a +# calibration menu in the Kodi GUI. +# disable_overscan=1 + +# Force HDMI even if unplugged or powered off +# hdmi_force_hotplug=1 + +# Doesn't sent initial active source message. +# Avoids bringing CEC (enabled TV) out of standby and channel switch when +# rebooting. +hdmi_ignore_cec_init=1 + +################################################################################ +# License keys to enable GPU hardware decoding for various codecs +# to obtain keys visit the shop at http://www.raspberrypi.com +################################################################################ + +# decode_MPG2=0x00000000 +# decode_WVC1=0x00000000 + +################################################################################ +# End of default configuration +################################################################################ + +################################################################################ +# Include distribution specific config file if it exists. +################################################################################ +[all] +include distroconfig.txt diff --git a/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/distroconfig.txt b/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/distroconfig.txt new file mode 100644 index 000000000..5ff97b5be --- /dev/null +++ b/packages/tools/bcm2835-bootloader/files/3rdparty/bootloader/distroconfig.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +# WARNING: DO NOT EDIT THIS FILE - IT WILL BE OVERWRITTEN WHEN UPGRADING! diff --git a/packages/tools/bcm2835-bootloader/package.mk b/packages/tools/bcm2835-bootloader/package.mk new file mode 100644 index 000000000..b0fa233c1 --- /dev/null +++ b/packages/tools/bcm2835-bootloader/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bcm2835-bootloader" + +# use latest master firmware on RPi4 and latest pre-common +# firmware on RPi0-3 +if [ "$DEVICE" = "RPi4" ]; then + PKG_VERSION="66fc5eaac3d0af1d5a7ffa616086cbfaefd72e98" + PKG_SHA256="fe7fe713409120768c37dbbe02a7a06c0e808b0e60dad09ea054d7006947b76d" +else + PKG_VERSION="9e3c23ce779e8cf44c33d6a25bba249319207f68" + PKG_SHA256="7ab85b6d7082be87556bc02353b97f97bb1d4af304e4004a3d7ad2a17bb8a696" +fi + +PKG_ARCH="arm" +PKG_LICENSE="nonfree" +PKG_SITE="http://www.broadcom.com" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain linux bcmstat" +PKG_LONGDESC="bcm2835-bootloader: Tool to create a bootable kernel for RaspberryPi" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/bootloader + cp -PRv LICENCE* $INSTALL/usr/share/bootloader + cp -PRv bootcode.bin $INSTALL/usr/share/bootloader + if [ "$DEVICE" = "RPi4" ]; then + cp -PRv fixup4x.dat $INSTALL/usr/share/bootloader/fixup.dat + cp -PRv start4x.elf $INSTALL/usr/share/bootloader/start.elf + else + cp -PRv fixup_x.dat $INSTALL/usr/share/bootloader/fixup.dat + cp -PRv start_x.elf $INSTALL/usr/share/bootloader/start.elf + fi + + find_file_path config/dt-blob.bin && cp -PRv $FOUND_PATH $INSTALL/usr/share/bootloader + + find_file_path bootloader/update.sh && cp -PRv $FOUND_PATH $INSTALL/usr/share/bootloader + find_file_path bootloader/canupdate.sh && cp -PRv $FOUND_PATH $INSTALL/usr/share/bootloader + + find_file_path config/distroconfig.txt $PKG_DIR/files/3rdparty/bootloader/distroconfig.txt && cp -PRv ${FOUND_PATH} $INSTALL/usr/share/bootloader + find_file_path config/config.txt $PKG_DIR/files/3rdparty/bootloader/config.txt && cp -PRv ${FOUND_PATH} $INSTALL/usr/share/bootloader +} diff --git a/packages/tools/bcm2835-bootloader/release b/packages/tools/bcm2835-bootloader/release new file mode 100755 index 000000000..a2e1ce9aa --- /dev/null +++ b/packages/tools/bcm2835-bootloader/release @@ -0,0 +1,23 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +mkdir -p $RELEASE_DIR/3rdparty/bootloader + cp -PR $INSTALL/usr/share/bootloader/LICENCE* $RELEASE_DIR/3rdparty/bootloader/ + cp -PR $INSTALL/usr/share/bootloader/bootcode.bin $RELEASE_DIR/3rdparty/bootloader/ + cp -PR $INSTALL/usr/share/bootloader/fixup.dat $RELEASE_DIR/3rdparty/bootloader/ + cp -PR $INSTALL/usr/share/bootloader/start.elf $RELEASE_DIR/3rdparty/bootloader/ + if [ -f $(get_build_dir slice-firmware)/dt-blob.bin ]; then + cp -PR $(get_build_dir slice-firmware)/dt-blob.bin $RELEASE_DIR/3rdparty/bootloader/ + fi + cp -PR $INSTALL/usr/share/bootloader/*.dtb $RELEASE_DIR/3rdparty/bootloader/ + cp -PR $INSTALL/usr/share/bootloader/overlays $RELEASE_DIR/3rdparty/bootloader/ + + if [ -f $INSTALL/usr/share/bootloader/config.txt ]; then + cp -PR $INSTALL/usr/share/bootloader/config.txt $RELEASE_DIR/3rdparty/bootloader/ + fi + if [ -f $INSTALL/usr/share/bootloader/distroconfig.txt ]; then + cp -PR $INSTALL/usr/share/bootloader/distroconfig.txt $RELEASE_DIR/3rdparty/bootloader/ + fi diff --git a/packages/tools/bcmstat/package.mk b/packages/tools/bcmstat/package.mk new file mode 100644 index 000000000..e7bdd8b9f --- /dev/null +++ b/packages/tools/bcmstat/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="bcmstat" +PKG_VERSION="0.5.5" +PKG_SHA256="faf21907c183ec45ca5a7737a220d3275d24a7d8a387344ed1562849b2d67f27" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/MilhouseVH/bcmstat" +PKG_URL="https://github.com/MilhouseVH/$PKG_NAME/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="Raspberry Pi monitoring script" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp -PRv bcmstat.sh $INSTALL/usr/bin + chmod +x $INSTALL/usr/bin/* +} diff --git a/packages/tools/bl301/package.mk b/packages/tools/bl301/package.mk new file mode 100644 index 000000000..f33668cff --- /dev/null +++ b/packages/tools/bl301/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="bl301" +PKG_VERSION="85f483db84c1482ee632bf34e6765c92486fc9d0" +PKG_SHA256="526d10570add92e737782cf1b7faae8e329e565d2163fdf5d014d22096291841" +PKG_LICENSE="GPL" +PKG_SITE="https://coreelec.org" +PKG_URL="https://github.com/CoreELEC/bl301/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain gcc-linaro-aarch64-elf:host gcc-linaro-arm-eabi:host" +PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems." +PKG_TOOLCHAIN="manual" + +pre_make_target() { + sed -i "s|arm-none-eabi-|arm-eabi-|g" $PKG_BUILD/Makefile $PKG_BUILD/arch/arm/cpu/armv8/*/firmware/scp_task/Makefile 2>/dev/null || true +} + +make_target() { + [ "${BUILD_WITH_DEBUG}" = "yes" ] && PKG_DEBUG=1 || PKG_DEBUG=0 + export PATH=$TOOLCHAIN/lib/gcc-linaro-aarch64-elf/bin/:$TOOLCHAIN/lib/gcc-linaro-arm-eabi/bin/:$PATH + DEBUG=${PKG_DEBUG} CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make mrproper + + for f in $(find ${PKG_BUILD}/configs -mindepth 1); do + PKG_UBOOT_CONFIG=$(basename -- "$f") + PKG_BL301_SUBDEVICE=${PKG_UBOOT_CONFIG%_defconfig} + echo Building bl301 for ${PKG_BL301_SUBDEVICE} + DEBUG=${PKG_DEBUG} CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make ${PKG_UBOOT_CONFIG} + DEBUG=${PKG_DEBUG} CROSS_COMPILE=aarch64-elf- ARCH=arm CFLAGS="" LDFLAGS="" make HOSTCC="${HOST_CC}" HOSTSTRIP="true" bl301.bin + mv ${PKG_BUILD}/build/scp_task/bl301.bin ${PKG_BUILD}/build/${PKG_BL301_SUBDEVICE}_bl301.bin + echo "moved blob to: " ${PKG_BUILD}/build/${PKG_BL301_SUBDEVICE}_bl301.bin + rm -rf ${PKG_BUILD}/build/scp_task + done +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/bootloader/bl301 + + for f in $(find ${PKG_BUILD}/configs -mindepth 1); do + PKG_UBOOT_CONFIG=$(basename -- "$f") + PKG_BL301_SUBDEVICE=${PKG_UBOOT_CONFIG%_defconfig} + PKG_BIN=${PKG_BUILD}/build/${PKG_BL301_SUBDEVICE}_bl301.bin + cp -av ${PKG_BIN} ${INSTALL}/usr/share/bootloader/bl301/${PKG_BL301_SUBDEVICE}_bl301.bin + done + + [ -d "${PKG_BUILD}/bl30" ] && cp -av ${PKG_BUILD}/bl30 ${INSTALL}/usr/share/bootloader/bl301 || : + [ -d "${PKG_BUILD}/bl31" ] && cp -av ${PKG_BUILD}/bl31 ${INSTALL}/usr/share/bootloader/bl301 || : +} diff --git a/packages/tools/ceemmc/package.mk b/packages/tools/ceemmc/package.mk new file mode 100644 index 000000000..e4d1ccace --- /dev/null +++ b/packages/tools/ceemmc/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="ceemmc" +PKG_VERSION="d74dcaa86e08a7d742218ede660ba9307f1e19fa" +PKG_SHA256="b0755c8d229ce6f9ab1aca88956f4cc441eb0fe0328b29c74b26e3d7e0fa6997" +PKG_LICENSE="proprietary" +PKG_SITE="https://coreelec.org" +PKG_URL="https://sources.coreelec.org/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Tool to install CoreELEC on internal eMMC" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/sbin + install -m 0755 ceemmc $INSTALL/usr/sbin/ceemmc +} diff --git a/packages/tools/dtc/package.mk b/packages/tools/dtc/package.mk new file mode 100644 index 000000000..7807b444b --- /dev/null +++ b/packages/tools/dtc/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="dtc" +PKG_VERSION="1.6.0" +PKG_SHA256="af720893485b02441f8812773484b286f969d1b8c98769d435a75c6ad524104b" +PKG_LICENSE="GPL" +PKG_SITE="https://git.kernel.org/pub/scm/utils/dtc/dtc.git/" +PKG_URL="https://git.kernel.org/pub/scm/utils/dtc/dtc.git/snapshot/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The Device Tree Compiler" + +PKG_MAKE_OPTS_TARGET="dtc fdtput fdtget libfdt" +PKG_MAKE_OPTS_HOST="dtc libfdt" + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp -P ${PKG_BUILD}/dtc ${TOOLCHAIN}/bin + mkdir -p ${TOOLCHAIN}/lib + cp -P ${PKG_BUILD}/libfdt/libfdt.so ${TOOLCHAIN}/lib +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/dtc ${INSTALL}/usr/bin + cp -P ${PKG_BUILD}/fdtput ${INSTALL}/usr/bin/ + cp -P ${PKG_BUILD}/fdtget ${INSTALL}/usr/bin/ + mkdir -p ${INSTALL}/usr/lib + cp -P ${PKG_BUILD}/libfdt/libfdt.so ${INSTALL}/usr/lib/ +} diff --git a/packages/tools/dtc/patches/dtc-0001-libfdt-soname-version.patch b/packages/tools/dtc/patches/dtc-0001-libfdt-soname-version.patch new file mode 100644 index 000000000..a95e51eba --- /dev/null +++ b/packages/tools/dtc/patches/dtc-0001-libfdt-soname-version.patch @@ -0,0 +1,13 @@ +diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt +index e546397..dd71746 100644 +--- a/libfdt/Makefile.libfdt ++++ b/libfdt/Makefile.libfdt +@@ -10,7 +10,7 @@ LIBFDT_VERSION = version.lds + LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ + fdt_addresses.c fdt_overlay.c + LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) +-LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) ++LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT) + + libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" diff --git a/packages/tools/entware/package.mk b/packages/tools/entware/package.mk new file mode 100644 index 000000000..2cf442771 --- /dev/null +++ b/packages/tools/entware/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="entware" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Entware/Entware" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="tools" +PKG_LONGDESC="entware: A software repository that offers various software programs that can be installed on your device" +PKG_TOOLCHAIN="manual" + +post_install() { + mkdir -p $INSTALL/usr/sbin + cp -P $PKG_DIR/scripts/installentware $INSTALL/usr/sbin + + # Replace Entware Arch + sed -e "s/@ENTWARE_ARCH@/$ENTWARE_ARCH/g" \ + -i $INSTALL/usr/sbin/installentware + + enable_service entware.service +} diff --git a/packages/tools/entware/profile.d/99-entware.conf b/packages/tools/entware/profile.d/99-entware.conf new file mode 100644 index 000000000..0ab2dd820 --- /dev/null +++ b/packages/tools/entware/profile.d/99-entware.conf @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +case $- in + *i*) + [ -f /opt/etc/profile ] && . /opt/etc/profile + ;; + *) + ;; +esac diff --git a/packages/tools/entware/scripts/installentware b/packages/tools/entware/scripts/installentware new file mode 100755 index 000000000..51377ed62 --- /dev/null +++ b/packages/tools/entware/scripts/installentware @@ -0,0 +1,21 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +export PATH=/opt/bin:/opt/sbin:$PATH + +[ ! -d /storage/.opt ] && mkdir -p /storage/.opt + +if [ ! -f /opt/bin/opkg ]; then + wget -O - http://bin.entware.net/@ENTWARE_ARCH@/installer/generic.sh | /bin/sh + echo "" + read -p "Would you like to reboot now to finish installation (recommended) [y/N]? " choice + case "$choice" in + [yY]*) + reboot + ;; + esac +else + echo "Entware is already installed." +fi diff --git a/packages/tools/entware/system.d/entware.service b/packages/tools/entware/system.d/entware.service new file mode 100644 index 000000000..124d90134 --- /dev/null +++ b/packages/tools/entware/system.d/entware.service @@ -0,0 +1,15 @@ +[Unit] +Description=Entware service +After=systemd-tmpfiles-setup.service network-online.target +Before=kodi.service +Requires=network-online.target +ConditionPathExists=/opt/etc/init.d/rc.unslung + +[Service] +Type=oneshot +ExecStart=/opt/etc/init.d/rc.unslung start +ExecStop=/opt/etc/init.d/rc.unslung stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/packages/tools/flashrom/package.mk b/packages/tools/flashrom/package.mk new file mode 100644 index 000000000..828a281ed --- /dev/null +++ b/packages/tools/flashrom/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019 Team LibreELEC (https://libreelec.tv) + +PKG_NAME="flashrom" +PKG_VERSION="1.1" +PKG_SHA256="aeada9c70c22421217c669356180c0deddd0b60876e63d2224e3260b90c14e19" +PKG_LICENSE="GPL" +PKG_SITE="https://www.flashrom.org/Flashrom" +PKG_URL="https://download.flashrom.org/releases/${PKG_NAME}-v${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libusb-compat" +PKG_LONGDESC="flashrom is a utility for identifying, reading, writing, verifying and erasing flash chips. It is designed to flash BIOS/EFI/coreboot/firmware/optionROM images on mainboards, network/graphics/storage controller cards, and various other programmer devices." + +PKG_MAKE_OPTS_TARGET="PREFIX=/usr \ + CONFIG_ENABLE_LIBPCI_PROGRAMMERS=no \ + CONFIG_FT2232_SPI=no \ + CONFIG_USBBLASTER_SPI=no \ + CONFIG_JLINK_SPI=no" +PKG_MAKEINSTALL_OPTS_TARGET="${PKG_MAKE_OPTS_TARGET}" + +post_makeinstall_target() { + rm -fr ${INSTALL}/usr/share/man +} diff --git a/packages/tools/grub/package.mk b/packages/tools/grub/package.mk new file mode 100755 index 000000000..14f3aca77 --- /dev/null +++ b/packages/tools/grub/package.mk @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="grub" +PKG_VERSION="2.02" +PKG_SHA256="4ff6999add483bf640e130bc076ca1464901b4677ee01297901b40fe55de03c4" +PKG_ARCH="x86_64" +PKG_LICENSE="GPLv3" +PKG_SITE="https://www.gnu.org/software/grub/index.html" +PKG_URL="http://git.savannah.gnu.org/cgit/grub.git/snapshot/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain flex freetype:host" +PKG_LONGDESC="GRUB is a Multiboot boot loader." +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--target=i386-pc-linux \ + --disable-nls \ + --with-platform=efi" + + unset CFLAGS + unset CPPFLAGS + unset CXXFLAGS + unset LDFLAGS + unset CPP + + cd $PKG_BUILD + ./autogen.sh +} + +make_target() { + make CC=$CC \ + AR=$AR \ + RANLIB=$RANLIB \ + CFLAGS="-I$SYSROOT_PREFIX/usr/include -fomit-frame-pointer -D_FILE_OFFSET_BITS=64" \ + LDFLAGS="-L$SYSROOT_PREFIX/usr/lib" +} + +makeinstall_target() { + cd $PKG_BUILD/grub-core + $PKG_BUILD/grub-mkimage -d . -o bootia32.efi -O i386-efi -p /EFI/BOOT \ + boot chain configfile ext2 fat linux search \ + efi_gop efi_uga part_gpt gzio \ + gettext loadenv loadbios memrw + + mkdir -p $INSTALL/usr/share/grub + cp -P $PKG_BUILD/grub-core/bootia32.efi $INSTALL/usr/share/grub + + mkdir -p $TOOLCHAIN/share/grub + cp -P $PKG_BUILD/grub-core/bootia32.efi $TOOLCHAIN/share/grub +} diff --git a/packages/tools/grub/patches/001-gcc8-fix-packed-not-aligned.patch b/packages/tools/grub/patches/001-gcc8-fix-packed-not-aligned.patch new file mode 100644 index 000000000..51ee7dc86 --- /dev/null +++ b/packages/tools/grub/patches/001-gcc8-fix-packed-not-aligned.patch @@ -0,0 +1,72 @@ +From 563b1da6e6ae7af46cc8354cadb5dab416989f0a Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 26 Mar 2018 16:52:34 +0800 +Subject: Fix packed-not-aligned error on GCC 8 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When building with GCC 8, there are several errors regarding packed-not-aligned. + +./include/grub/gpt_partition.h:79:1: error: alignment 1 of ‘struct grub_gpt_partentry’ is less than 8 [-Werror=packed-not-aligned] + +This patch fixes the build error by cleaning up the ambiguity of placing +aligned structure in a packed one. In "struct grub_btrfs_time" and "struct +grub_gpt_part_type", the aligned attribute seems to be superfluous, and also +has to be packed, to ensure the structure is bit-to-bit mapped to the format +laid on disk. I think we could blame to copy and paste error here for the +mistake. In "struct efi_variable", we have to use grub_efi_packed_guid_t, as +the name suggests. :) + +Signed-off-by: Michael Chang +Tested-by: Michael Chang +Tested-by: Paul Menzel +Reviewed-by: Daniel Kiper +--- + grub-core/fs/btrfs.c | 2 +- + include/grub/efiemu/runtime.h | 2 +- + include/grub/gpt_partition.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 4849c1c..be19544 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -175,7 +175,7 @@ struct grub_btrfs_time + { + grub_int64_t sec; + grub_uint32_t nanosec; +-} __attribute__ ((aligned (4))); ++} GRUB_PACKED; + + struct grub_btrfs_inode + { +diff --git a/include/grub/efiemu/runtime.h b/include/grub/efiemu/runtime.h +index 9b6b729..36d2ded 100644 +--- a/include/grub/efiemu/runtime.h ++++ b/include/grub/efiemu/runtime.h +@@ -29,7 +29,7 @@ struct grub_efiemu_ptv_rel + + struct efi_variable + { +- grub_efi_guid_t guid; ++ grub_efi_packed_guid_t guid; + grub_uint32_t namelen; + grub_uint32_t size; + grub_efi_uint32_t attributes; +diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h +index 1b32f67..9668a68 100644 +--- a/include/grub/gpt_partition.h ++++ b/include/grub/gpt_partition.h +@@ -28,7 +28,7 @@ struct grub_gpt_part_type + grub_uint16_t data2; + grub_uint16_t data3; + grub_uint8_t data4[8]; +-} __attribute__ ((aligned(8))); ++} GRUB_PACKED; + typedef struct grub_gpt_part_type grub_gpt_part_type_t; + + #define GRUB_GPT_PARTITION_TYPE_EMPTY \ +-- +cgit v1.0-41-gc330 + diff --git a/packages/tools/hdparm/package.mk b/packages/tools/hdparm/package.mk new file mode 100644 index 000000000..a41ae9c75 --- /dev/null +++ b/packages/tools/hdparm/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="hdparm" +PKG_VERSION="9.58" +PKG_SHA256="9ae78e883f3ce071d32ee0f1b9a2845a634fc4dd94a434e653fdbef551c5e10f" +PKG_LICENSE="BSD" +PKG_SITE="http://sourceforge.net/projects/hdparm/" +PKG_URL="$SOURCEFORGE_SRC/$PKG_NAME/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Shell utility to access/tune ioctl features of the Linux IDE driver and IDE drives." + +makeinstall_target() { + mkdir -p $INSTALL/usr/sbin + cp -a $PKG_BUILD/hdparm $INSTALL/usr/sbin +} diff --git a/packages/tools/hdparm/patches/hdparm-9.42-cflags.patch b/packages/tools/hdparm/patches/hdparm-9.42-cflags.patch new file mode 100644 index 000000000..7fb69d971 --- /dev/null +++ b/packages/tools/hdparm/patches/hdparm-9.42-cflags.patch @@ -0,0 +1,12 @@ +diff -Naur hdparm-9.39/Makefile hdparm-9.39.patch/Makefile +--- hdparm-9.39/Makefile 2012-01-06 17:05:37.000000000 +0100 ++++ hdparm-9.39.patch/Makefile 2012-07-28 05:22:53.271127964 +0200 +@@ -13,7 +13,7 @@ + CC ?= gcc + STRIP ?= strip + +-CFLAGS := -O2 -W -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -fkeep-inline-functions -Wwrite-strings -Waggregate-return -Wnested-externs -Wtrigraphs $(CFLAGS) ++CFLAGS := -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -fkeep-inline-functions -Wwrite-strings -Waggregate-return -Wnested-externs -Wtrigraphs $(CFLAGS) + + LDFLAGS = -s + #LDFLAGS = -s -static diff --git a/packages/tools/hdparm/udev.d/61-cdrom.rules b/packages/tools/hdparm/udev.d/61-cdrom.rules new file mode 100644 index 000000000..eb6c8b38b --- /dev/null +++ b/packages/tools/hdparm/udev.d/61-cdrom.rules @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# only do anything on block devices which are not removed +ACTION!="add|change", GOTO="cdrom_end" + +# /dev/sr, /dev/sr_mod, /dev/srcutree are not valid +KERNEL=="sr|sr_mod|srcutree", GOTO="cdrom_end" + +# set CDROM speed +KERNEL=="sr*", RUN+="/sbin/hdparm -E8 /dev/%k" + +LABEL="cdrom_end" diff --git a/packages/tools/installer/config/installer.conf b/packages/tools/installer/config/installer.conf new file mode 100644 index 000000000..7f0fd56e6 --- /dev/null +++ b/packages/tools/installer/config/installer.conf @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# Disklabel for System and Storage partition + DISKLABEL_SYSTEM="System" + DISKLABEL_STORAGE="Storage" + +# Default size of system partition, in MB, eg. 512 + PARTSIZE_SYSTEM="@SYSTEM_SIZE@" + +# Default starting offset for system partition, in sectors (1 sector = 512B), eg. 2048 + PARTSIZE_SYSTEM_OFFSET="@SYSTEM_PART_START@" + +# additional parameters to syslinux + SYSLINUX_PARAMETERS="@SYSLINUX_PARAMETERS@" + +# enable BIOS update function + BIOS_UPDATE="no" + +# BIOS file to program + BIOS_FILE="" + +# location for BIOS backup (with filename) + BIOS_BACKUP="" + +# color scheme to use for Whiptail/Newt +# see http://askubuntu.com/questions/776831/whiptail-change-background-color-dynamically-from-magenta + WHIPTAIL_COLORS="" diff --git a/packages/tools/installer/package.mk b/packages/tools/installer/package.mk new file mode 100644 index 000000000..6125d7662 --- /dev/null +++ b/packages/tools/installer/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="installer" +PKG_VERSION="1" +PKG_LICENSE="GPL" +PKG_SITE="http://libreelec.tv/" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain busybox newt parted e2fsprogs syslinux grub" +PKG_LONGDESC="LibreELEC.tv Install manager to install the system on any disk" +PKG_TOOLCHAIN="manual" + +post_install() { + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/installer $INSTALL/usr/bin + sed -e "s/@DISTRONAME@/$DISTRONAME/g" \ + -i $INSTALL/usr/bin/installer + + mkdir -p $INSTALL/etc + find_file_path config/installer.conf + cp ${FOUND_PATH} $INSTALL/etc + sed -e "s/@SYSTEM_SIZE@/$SYSTEM_SIZE/g" \ + -e "s/@SYSTEM_PART_START@/$SYSTEM_PART_START/g" \ + -e "s/@SYSLINUX_PARAMETERS@/$SYSLINUX_PARAMETERS/g" \ + -i $INSTALL/etc/installer.conf + + enable_service installer.service +} diff --git a/packages/tools/installer/scripts/installer b/packages/tools/installer/scripts/installer new file mode 100755 index 000000000..1ec9905ac --- /dev/null +++ b/packages/tools/installer/scripts/installer @@ -0,0 +1,490 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +# some DOCs: + +# list devices: +# cat /proc/partitions | sed -n "s/\ *[0-9][0-9]*\ *[0-9][0-9]*\ *[0-9][0-9]*\ \([a-z]*\)$/\1/p" + +# list all partitionnumbers from /dev/sda: +# parted -m /dev/sda print | grep -v ^/dev | grep -v ^BYT | cut -f1 -d ":" + +# list device data from /dev/sda: +# parted -m /dev/sda print | grep /dev/sda + +# list mounted partitions: +# mount | grep ^/dev + +# list modelnumber: +# parted -m /dev/sda print | grep /dev/sda | cut -f7 -d ":" | sed "s/;//" +# list size: +# parted -m /dev/sda print | grep /dev/sda | cut -f2 -d ":" + +# exclude mounted partitions +# for i in `cat /proc/mounts | grep ^/dev/ | cut -f1 -d " " | sed "s/[0-9]//"`; do TEST="$TEST `echo "| grep -v $i"`"; done + +# disable Ctrl+C - can be very dangerous +trap '' 2 + +[ -f /etc/installer.conf ] && . /etc/installer.conf || exit 0 + +dbglg() { + # Acts just like echo cmd, with automatic redirection + + echo "" >> $LOGFILE + echo "#################################################################" >> $LOGFILE + echo "# $@" >> $LOGFILE + echo "#################################################################" >> $LOGFILE + echo "" >> $LOGFILE +} + +log_system_status() { + echo "# cat /proc/mounts" + cat /proc/mounts + echo + + echo "# df" + df + echo + + echo "# df -h" + df -h + echo + + echo "# parted -s -m -l" + parted -s -m -l + echo + + echo "# blkid" + blkid + echo + + echo "# UEFI (if directory exists)" + ls -la /sys/firmware/efi + echo + + echo "# Disk sizes (bytes)" + grep . /sys/block/*/size + echo +} + +get_device_unmount() { + # get all unmounted devices + # usage: get_devices_unmount + # uses: - + # provides: DEVICES + + DEVICES="" + DEVICES=$(parted -s -m -l 2>/dev/null | grep -E '^/dev/sd|^/dev/mmcblk|^/dev/nvme' | grep -E -v '.?rpmb|.?boot?' | cut -f1 -d ":") + + for i in $(cat /proc/mounts | grep -E '^/dev/sd' | cut -f1 -d " " | sed "s/[0-9].*$//"); do + DEVICES=$(echo $DEVICES | sed -e "s|$i||") + done + + for i in $(cat /proc/mounts | grep -E '^/dev/mmcblk' | cut -f1 -d " " | sed "s/p.*$//"); do + DEVICES=$(echo $DEVICES | sed -e "s|$i||") + done + + for i in $(cat /proc/mounts | grep -E '^/dev/nvme' | cut -f1 -d " " | sed "s/p.*$//"); do + DEVICES=$(echo $DEVICES | sed -e "s|$i||") + done +} + +get_partition() { + # get all partitions of a specifed device + # usage: get_partitions /dev/sda + # uses: - + # provides: PARTITIONS + + PARTITIONS=$(parted -s -m $1 print | grep -v ^/dev | grep -v BYT | cut -f1 -d ":") +} + +create_device_list() { + # creates device list to use in menus + # usage: create_devices_list + # uses: get_device_unmount + # provides: DEVICE_MODEL, DEVICE_SIZE, DEVICE_LIST, DEVICE_NAME, + # DEVICES (get_device_unmount) + + DEVICE_MODEL="" + DEVICE_SIZE="" + DEVICE_LIST="" + DEVICE_NAME="" + + get_device_unmount + + if [ "$DEVICES" = "" ]; then + msg_no_device + return 1 + fi + + for i in $DEVICES; do + DEVICE_MODEL=$(parted -s $i -m print | grep ^$i | cut -f7 -d ":" | sed "s/;//") + DEVICE_SIZE=$(parted -s $i -m print | grep ^$i | cut -f2 -d ":") + DEVICE_NAME=$(echo $DEVICE_MODEL ${DEVICE_SIZE} | sed 's/ /_/g') + DEVICE_LIST="$DEVICE_LIST $i $DEVICE_NAME" + done + return 0 +} + +do_install_quick() { + # show menu + MSG_TITLE="QUICK INSTALL MENU" + MSG_MENU="\nUse the up/down arrows to select the device you wish to install to.\n\nPlease select a device:" + MSG_CANCEL="Back" + + create_device_list || return + + whiptail --backtitle "$BACKTITLE" --cancel-button "$MSG_CANCEL" \ + $DIALOG_OPTIONS --title "$MSG_TITLE" --menu "$MSG_MENU" 20 50 5 \ + $DEVICE_LIST 2> $TMPDIR/device_for_install + [ $? -ne 0 ] && return + + # now we must do everything + INSTALL_DEVICE=$(cat "$TMPDIR/device_for_install") + INSTALL_DEVICE_FULL=$(echo $DEVICE_LIST | sed "s|.*$INSTALL_DEVICE \([^ ]*\).*|$INSTALL_DEVICE \1|") + + case $INSTALL_DEVICE in + "/dev/mmcblk"*|"/dev/nvme"*) + PART1="p1" + PART2="p2" + ;; + *) + PART1="1" + PART2="2" + ;; + esac + + prompt_gpt + prompt_backup_unpack + + # check for confirmation (twice!) + MSG_TITLE="Confirmation before installing" + MSG_DETAIL="\nIf you continue the contents of the target disk will be wiped out:\n\n$INSTALL_DEVICE_FULL\n\n" + DIALOG_OPTIONS="--defaultno" + whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" \ + $DIALOG_OPTIONS --yesno "$MSG_DETAIL" 0 0 + [ $? -ne 0 ] && return + + MSG_TITLE="Confirmation before installing" + MSG_DETAIL="\nThis is last chance to abort the installation!\n\nIf you continue the target disk will be wiped out:\n\n$INSTALL_DEVICE_FULL\n\n\n" + DIALOG_OPTIONS="--defaultno" + whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" \ + $DIALOG_OPTIONS --yesno "$MSG_DETAIL" 0 0 + [ $? -ne 0 ] && return + + # start the progress bar (whiptail --gauge) + { + # remove all partitions + msg_progress_install "1" "Get all partitions $INSTALL_DEVICE" + get_partition $INSTALL_DEVICE + + msg_progress_install "5" "Wiping disk $INSTALL_DEVICE" + dd if=/dev/zero of=$INSTALL_DEVICE bs=4096 count=1024 2>>$LOGFILE + + # create 2 new partitions (first $PARTSIZE_SYSTEM, second rest) + msg_progress_install "7" "Creating label on $INSTALL_DEVICE" + if [ "$GPT" = "1" ]; then + parted -s $INSTALL_DEVICE mklabel gpt >> $LOGFILE 2>&1 + else + parted -s $INSTALL_DEVICE mklabel msdos >> $LOGFILE 2>&1 + fi + + msg_progress_install "9" "Writing Master Boot Record on $INSTALL_DEVICE" + if [ "$GPT" = "1" ]; then + cat /usr/share/syslinux/gptmbr.bin > $INSTALL_DEVICE + else + cat /usr/share/syslinux/mbr.bin > $INSTALL_DEVICE + fi + + partsize_system_start=$PARTSIZE_SYSTEM_OFFSET + partsize_system_end=$(((PARTSIZE_SYSTEM * 1024 * 1024 / 512) + partsize_system_start - 1)) + partsize_storage_start=$((partsize_system_end + 1)) + partsize_storage_end=-1024 + + msg_progress_install "10" "Creating partition on $INSTALL_DEVICE" + if [ "$GPT" = "1" ]; then + parted -s $INSTALL_DEVICE unit s mkpart $DISKLABEL_SYSTEM fat16 -- $partsize_system_start $partsize_system_end >> $LOGFILE 2>&1 + else + parted -s $INSTALL_DEVICE unit s mkpart primary fat16 -- $partsize_system_start $partsize_system_end >> $LOGFILE 2>&1 + fi + + msg_progress_install "13" "Creating partition on $INSTALL_DEVICE" + if [ "$GPT" = "1" ]; then + parted -s $INSTALL_DEVICE unit s mkpart $DISKLABEL_STORAGE ext4 -- $partsize_storage_start $partsize_storage_end >> $LOGFILE 2>&1 + else + parted -s $INSTALL_DEVICE unit s mkpart primary ext4 -- $partsize_storage_start $partsize_storage_end >> $LOGFILE 2>&1 + fi + + msg_progress_install "16" "Setup bootflag on partition 1 of $INSTALL_DEVICE" + parted -s $INSTALL_DEVICE set 1 boot on >> $LOGFILE 2>&1 + if [ "$GPT" = "1" ]; then + parted -s $INSTALL_DEVICE set 1 legacy_boot on >> $LOGFILE 2>&1 + fi + + msg_progress_install "20" "Tell the kernel we have a new partition table on $INSTALL_DEVICE" + partprobe $INSTALL_DEVICE >> $LOGFILE 2>&1 + + # create filesystem + msg_progress_install "23" "Creating filesystem on ${INSTALL_DEVICE}1" + mkfs.vfat -F 16 ${INSTALL_DEVICE}${PART1} >> $LOGFILE 2>&1 + + msg_progress_install "25" "Set uuid and disklabel $DISKLABEL_SYSTEM on ${INSTALL_DEVICE}${PART1}" + dosfslabel ${INSTALL_DEVICE}${PART1} $DISKLABEL_SYSTEM >> $LOGFILE 2>&1 + + msg_progress_install "28" "Creating filesystem on ${INSTALL_DEVICE}${PART2}" + mke2fs -t ext4 -m 0 ${INSTALL_DEVICE}${PART2} >> $LOGFILE 2>&1 + + msg_progress_install "30" "Set uuid and disklabel $DISKLABEL_STORAGE on ${INSTALL_DEVICE}${PART2}" + tune2fs -U random -L $DISKLABEL_STORAGE ${INSTALL_DEVICE}${PART2} >> $LOGFILE 2>&1 + + UUID_SYSTEM="$(blkid --output udev ${INSTALL_DEVICE}${PART1} | grep ^ID_FS_UUID= | cut -d= -f2)" + UUID_STORAGE="$(blkid --output udev ${INSTALL_DEVICE}${PART2} | grep ^ID_FS_UUID= | cut -d= -f2)" + + echo "" >> $LOGFILE + echo "UUID_SYSTEM : ${UUID_SYSTEM}" >> $LOGFILE + echo "UUID_STORAGE: ${UUID_STORAGE}" >> $LOGFILE + + # mount system partition + msg_progress_install "35" "Creating $TMPDIR/part1" + mkdir -p $TMPDIR/part1 >> $LOGFILE 2>&1 + + msg_progress_install "40" "Mounting ${INSTALL_DEVICE}${PART1} to $TMPDIR/part1" + mount -t vfat ${INSTALL_DEVICE}${PART1} $TMPDIR/part1 >> $LOGFILE 2>&1 + + # installing syslinux + msg_progress_install "50" "Installing syslinux to $TMPDIR/part1" + syslinux -i ${INSTALL_DEVICE}${PART1} >> $LOGFILE 2>&1 + + # install system files + msg_progress_install "60" "Installing Kernel" + cp /flash/KERNEL $TMPDIR/part1 >> $LOGFILE 2>&1 + + msg_progress_install "65" "Installing System" + cp /flash/SYSTEM $TMPDIR/part1 >> $LOGFILE 2>&1 + sync + + # configuring bootloader + msg_progress_install "80" "Setup bootloader with boot label = $DISKLABEL_SYSTEM and disk label = $DISKLABEL_STORAGE" + mkdir -p $TMPDIR/part1/EFI/BOOT + cat << EOF > $TMPDIR/part1/syslinux.cfg +DEFAULT linux +PROMPT 0 + +LABEL linux + KERNEL /KERNEL + APPEND boot=UUID=$UUID_SYSTEM disk=UUID=$UUID_STORAGE $SYSLINUX_PARAMETERS quiet +EOF + + cat << EOF > $TMPDIR/part1/EFI/BOOT/grub.cfg +set timeout="0" +set default="LibreELEC" + +menuentry "LibreELEC" { + search --set -f /KERNEL + linux /KERNEL boot=UUID=$UUID_SYSTEM disk=UUID=$UUID_STORAGE quiet +} +EOF + + # uefi boot / hybrid mode + cp /usr/share/syslinux/bootx64.efi $TMPDIR/part1/EFI/BOOT + cp /usr/share/syslinux/ldlinux.e64 $TMPDIR/part1/EFI/BOOT + cp /usr/share/grub/bootia32.efi $TMPDIR/part1/EFI/BOOT + sync + + # umount system partition, remove mountpoint + msg_progress_install "85" "Unmount $TMPDIR/part1" + umount $TMPDIR/part1 >> $LOGFILE 2>&1 + + msg_progress_install "87" "Remove $TMPDIR/part1" + rmdir $TMPDIR/part1 >> $LOGFILE 2>&1 + + if [ "$BACKUP_UNPACK" = "1" ]; then + # mount storage partition + msg_progress_install "89" "Creating $TMPDIR/part2" + mkdir -p $TMPDIR/part2 >> $LOGFILE 2>&1 + + msg_progress_install "90" "Mounting ${INSTALL_DEVICE}${PART2} to $TMPDIR/part2" + mount -t ext4 ${INSTALL_DEVICE}${PART2} $TMPDIR/part2 >> $LOGFILE 2>&1 + + msg_progress_install "92" "Restoring backup" + [ -f /flash/backup.tar.bz2 ] && tar -xjf /flash/backup.tar.bz2 -C $TMPDIR/part2 >> $LOGFILE 2>&1 + [ -f /flash/backup.zip ] && unzip -qq /flash/backup.zip -d $TMPDIR/part2 >> $LOGFILE 2>&1 + sync + + # umount system partition, remove mountpoint + msg_progress_install "97" "Unmount $TMPDIR/part2" + umount $TMPDIR/part2 >> $LOGFILE 2>&1 + + msg_progress_install "100" "Remove $TMPDIR/part2" + rmdir $TMPDIR/part2 >> $LOGFILE 2>&1 + fi + } | whiptail --backtitle "$BACKTITLE" --gauge "Please wait while your system is being setup ..." 6 73 0 + + # install complete + MSG_TITLE="@DISTRONAME@ Install Complete" + MSG_DETAIL="You may now remove the install media and reboot.\n" + whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" --msgbox "$MSG_DETAIL" 7 52 +} + +msg_no_device() { + # show a warning dialog if we dont find not mounted devices for install and return to main menu + MSG_TITLE="WARNING" + MSG_INFOBOX=" No devices were found. " + + whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" --msgbox "$MSG_INFOBOX" 9 73 +} + +msg_progress_install() { + # update the whiptail gauge window + + dbglg "$2" + sleep .3 + echo XXX + echo $1 + echo "$2 ..." + echo XXX +} + +prompt_gpt() { + GPT="0" + UEFI="0" + # Get size in GB. + # 2^41 bytes is the DOS limit (2199023255552 bytes, 2.2TB). Use GUID Partition Table.>= 2200GB + INSTALL_DEVICE_SIZE=$(($(cat /sys/block/${INSTALL_DEVICE#/dev/}/size)*512/1000/1000/1000)) + if [ "$INSTALL_DEVICE_SIZE" -ge 2200 ] 2>/dev/null; then + GPT="1" + fi + # force gpt + uefi in uefi boot mode + if [ -d /sys/firmware/efi ]; then + UEFI="1" + GPT="1" + fi +} + +prompt_backup_unpack() { + # Prompt for unpacking backup files to /storage + # usage: prompt_backup_unpack + # uses: + # provides: BACKUP_UNPACK + BACKUP_UNPACK="0" + if [ -f /flash/backup.tar.bz2 -o -f /flash/backup.zip ]; then + MSG_TITLE="Restore backup files" + MSG_DETAIL="Restore backup files to storage partition.\nFile backup.tar.bz2 or/and backup.zip exist on\ninstallation USB stick." + DIALOG_OPTIONS="--defaultno" + if whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" $DIALOG_OPTIONS --yesno "$MSG_DETAIL" 0 0; then + BACKUP_UNPACK="1" + fi + fi +} + +menu_main() { + # show the mainmenu + MSG_TITLE="MAIN MENU" + MSG_MENU="\nWelcome to @DISTRONAME@ installation tool! \ +\n +This tool is used to copy @DISTRONAME@ from the installation media \ +to your disk or other device. You'll be up and running in no time! \ +Please note that the contents of the disk you choose will be wiped \ +out during the installation. \ +\n\nPlease select:" + MSG_CANCEL="Close" + + whiptail --backtitle "$BACKTITLE" --cancel-button "$MSG_CANCEL" \ + --title "$MSG_TITLE" --menu "$MSG_MENU" 18 73 4 \ + 1 "Install @DISTRONAME@" \ + 2 "View installation log" \ + 3 "Save installation log" \ + 4 "Reboot" 2> $TMPDIR/mainmenu + + case $? in + 0) + ITEM_MAINMENU=$(cat "$TMPDIR/mainmenu") + case $ITEM_MAINMENU in + 1) do_install_quick;; + 2) logfile_show;; + 3) logfile_save;; + 4) do_reboot;; + esac + ;; + 1) + do_reboot + ;; + 255) + do_poweroff + ;; + esac +} + +logfile_show() { + whiptail --textbox "$LOGFILE" 20 73 --scrolltext --backtitle "$BACKTITLE" +} + +logfile_save() { + mount -o remount,rw /flash + + mkdir -p $(dirname $LOGBACKUP) + cp $LOGFILE $LOGBACKUP + sync + + mount -o remount,ro /flash + + MSG_TITLE="@DISTRONAME@ Log Saved" + MSG_DETAIL="Log location: ${LOGBACKUP}\n" + whiptail --backtitle "$BACKTITLE" --title "$MSG_TITLE" --msgbox "$MSG_DETAIL" 7 52 +} + +do_reboot() { + # reboot on request + clear + sync + reboot -f +} + +do_poweroff() { + # powerdown on request + clear + sync + poweroff -f +} + +# setup needed variables +OS_VERSION=$(lsb_release) +BACKTITLE="@DISTRONAME@ Installer - $OS_VERSION" + +TMPDIR="/tmp/installer" +LOGFILE="$TMPDIR/install.log" +LOGBACKUP="/flash/logs/$(date +%Y%m%d%H%M%S).log" + +export COLORTERM="1" +export NEWT_COLORS="$WHIPTAIL_COLORS" + +# prepare temporary directory +rm -rf $TMPDIR +mkdir -p $TMPDIR + +#create log file +echo "@DISTRONAME@ Installer - $OS_VERSION started at:" > $LOGFILE +date >> $LOGFILE + +dbglg "System status" +log_system_status >> $LOGFILE 2>&1 + +# generate the en_US.UTF-8 locale to enable line drawing +mkdir -p $TMPDIR/locale +localedef -i en_US -f UTF-8 $TMPDIR/locale/en_US.UTF-8 +export LOCPATH=$TMPDIR/locale +export LC_ALL=en_US.UTF-8 + +# main + +while true; do + clear + menu_main +done + +# exit cleanly +exit 0 diff --git a/packages/tools/installer/system.d/installer.service b/packages/tools/installer/system.d/installer.service new file mode 100644 index 000000000..a573b05a2 --- /dev/null +++ b/packages/tools/installer/system.d/installer.service @@ -0,0 +1,18 @@ +[Unit] +Description=XBMC Media Center +Requires=installer.target + +[Service] +ExecStart=/usr/bin/installer +Type=idle +StandardInput=tty-force +StandardOutput=inherit +StandardError=inherit +KillMode=process + +# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash +# terminates cleanly. +KillSignal=SIGHUP + +[Install] +WantedBy=installer.target diff --git a/packages/tools/installer/system.d/installer.target b/packages/tools/installer/system.d/installer.target new file mode 100644 index 000000000..cd1cb7f7f --- /dev/null +++ b/packages/tools/installer/system.d/installer.target @@ -0,0 +1,6 @@ +[Unit] +Description=OpenELEC installer +Requires=basic.target +After=basic.target +Conflicts=rescue.target multi-user.target graphical.target +AllowIsolate=yes diff --git a/packages/tools/led_tools/package.mk b/packages/tools/led_tools/package.mk new file mode 100644 index 000000000..dfcf59768 --- /dev/null +++ b/packages/tools/led_tools/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2014 Gordon Hollingworth (gordon@fiveninjas.com) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="led_tools" +PKG_VERSION="0.1" +PKG_SHA256="0484b4a2da9d586accef87ba7dd18595baae1d602c1b1bd9e0a8565ab50419a2" +PKG_LICENSE="GPL" +PKG_SITE="http://www.fiveninjas.com" +PKG_URL="http://updates.fiveninjas.com/src/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain zlib libpng slice" +PKG_DEPENDS_HOST="toolchain" +PKG_LONGDESC="LED tools, these are a set of tools to control the LEDs on Slice" + +make_target() { + make CC="$CC" \ + CFLAGS="$CFLAGS" \ + LDFLAGS="$LDFLAGS" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp led_png $INSTALL/usr/bin +} diff --git a/packages/tools/luajit/package.mk b/packages/tools/luajit/package.mk new file mode 100644 index 000000000..5e18e7759 --- /dev/null +++ b/packages/tools/luajit/package.mk @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019 Trond Haugland (github.com/escalade) + +PKG_NAME="luajit" +PKG_VERSION="99168476b9f6e1910057181428f2225b09458747" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/moonjit/moonjit" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain luajit:host" +PKG_SHORTDESC="LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. " +GET_HANDLER_SUPPORT="git" +PKG_GIT_CLONE_BRANCH="v2.1" +PKG_TOOLCHAIN="manual" +PKG_BUILD_FLAGS="+speed" + +post_patch() { + mkdir -p ${PKG_BUILD}/.${TARGET_NAME} && cp -r ${PKG_BUILD}/* $PKG_BUILD/.${TARGET_NAME} + mkdir -p ${PKG_BUILD}/.${HOST_NAME} && cp -r ${PKG_BUILD}/* $PKG_BUILD/.${HOST_NAME} +} + +makeinstall_host() { + cd .${HOST_NAME} + make amalg + make PREFIX=/ DESTDIR=${TOOLCHAIN} install + VER=$(grep LUAJIT_VERSION src/luajit.h | head -n1 | cut -d \" -f 2 | cut -d " " -f 2) + ln -sf luajit-${VER} ${TOOLCHAIN}/bin/luajit +} + +makeinstall_target() { + cd .${TARGET_NAME} + unset CFLAGS + [ "${ARCH}" = "arm" ] && BIT="-m32" + make PREFIX="/usr" \ + CC="${CC} -fPIC" \ + TARGET_LD="${CC}" \ + TARGET_AR="${AR} rcus" \ + TARGET_STRIP=true \ + TARGET_CFLAGS="${TARGET_CFLAGS}" \ + TARGET_LDFLAGS="${LDFLAGS}" \ + HOST_CC="${HOST_CC} ${BIT}" \ + HOST_CFLAGS="${CFLAGS}" \ + HOST_LDFLAGS="${LDFLAGS}" \ + XCFLAGS= \ + ${JITARCH} \ + amalg + make PREFIX=/usr DESTDIR=${INSTALL} install + make PREFIX=/usr DESTDIR=${SYSROOT_PREFIX} install + + VER=$(grep LUAJIT_VERSION src/luajit.h | head -n1 | cut -d \" -f 2 | cut -d " " -f 2) + + ln -sf /usr/bin/luajit-${VER} ${INSTALL}/usr/bin/lua +} diff --git a/packages/tools/luajit/patches/luajit-crosscompile.patch b/packages/tools/luajit/patches/luajit-crosscompile.patch new file mode 100644 index 000000000..5b28226f4 --- /dev/null +++ b/packages/tools/luajit/patches/luajit-crosscompile.patch @@ -0,0 +1,15 @@ +--- a/src/host/buildvm.c 2019-11-19 18:33:03.914237086 +0100 ++++ b/src/host/buildvm.c 2019-11-19 18:33:08.837645902 +0100 +@@ -434,12 +434,6 @@ + BuildCtx *ctx = &ctx_; + int status, binmode; + +- if (sizeof(void *) != 4*LJ_32+8*LJ_64) { +- fprintf(stderr,"Error: pointer size mismatch in cross-build.\n"); +- fprintf(stderr,"Try: make HOST_CC=\"gcc -m32\" CROSS=...\n\n"); +- return 1; +- } +- + UNUSED(argc); + parseargs(ctx, argv); + diff --git a/packages/tools/miniupnpc/package.mk b/packages/tools/miniupnpc/package.mk new file mode 100644 index 000000000..9ce391409 --- /dev/null +++ b/packages/tools/miniupnpc/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="miniupnpc" +PKG_VERSION="2.1" +PKG_SHA256="e19fb5e01ea5a707e2a8cb96f537fbd9f3a913d53d804a3265e3aeab3d2064c6" +PKG_LICENSE="BSD" +PKG_SITE="http://miniupnp.free.fr" +PKG_URL="http://miniupnp.free.fr/files/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The MiniUPnP project offers software which supports the UPnP Internet Gateway Device (IGD) specifications" + +PKG_CMAKE_OPTS_TARGET="-DUPNPC_BUILD_SHARED=OFF -DUPNPC_BUILD_STATIC=ON" diff --git a/packages/tools/mkbootimg/package.mk b/packages/tools/mkbootimg/package.mk new file mode 100644 index 000000000..adc1d3acd --- /dev/null +++ b/packages/tools/mkbootimg/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mkbootimg" +PKG_VERSION="6668fc2" +PKG_SHA256="d84870e055414d638a3e7eb4b7a3ebf415899841218f24cb3647d06ecf6ddb17" +PKG_LICENSE="GPL" +PKG_SITE="https://android.googlesource.com/platform/system/core/+/master/mkbootimg/" +PKG_URL="https://github.com/codesnake/mkbootimg/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_HOST="gcc:host" +PKG_LONGDESC="mkbootimg: Creates kernel boot images for Android" + +makeinstall_host() { + mkdir -p $SYSROOT_PREFIX/usr/include + cp mkbootimg $TOOLCHAIN/bin/ +} diff --git a/packages/tools/mtools/package.mk b/packages/tools/mtools/package.mk new file mode 100644 index 000000000..eed9d81b9 --- /dev/null +++ b/packages/tools/mtools/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mtools" +PKG_VERSION="4.0.23" +PKG_SHA256="f188db26751aeb5692a79b2380b440ecc05fd1848a52f869d7ca1193f2ef8ee3" +PKG_LICENSE="GPL" +PKG_SITE="http://www.gnu.org/software/mtools/" +PKG_URL="http://ftpmirror.gnu.org/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_HOST="gcc:host" +PKG_LONGDESC="mtools: A collection of utilities to access MS-DOS disks" +PKG_TOOLCHAIN="autotools" diff --git a/packages/tools/mtools/patches/mtools-05-fix-install.patch b/packages/tools/mtools/patches/mtools-05-fix-install.patch new file mode 100644 index 000000000..962d88643 --- /dev/null +++ b/packages/tools/mtools/patches/mtools-05-fix-install.patch @@ -0,0 +1,16 @@ +removes installing of floppyd, manuals and info +should fix occasional mtools installation problems few of us had + +--- a/Makefile.in 2010-10-17 17:41:09.000000000 +0200 ++++ b/Makefile.in 2016-04-28 11:42:28.015052786 +0200 +@@ -236,8 +236,8 @@ + uninstall-info: + cd $(DESTDIR)$(infodir) && rm -f mtools.info* + +-install: $(DESTDIR)$(bindir)/mtools @BINFLOPPYD@ install-man install-links \ +- $(DESTDIR)$(bindir)/mkmanifest install-scripts install-info ++install: $(DESTDIR)$(bindir)/mtools install-links \ ++ $(DESTDIR)$(bindir)/mkmanifest install-scripts + + uninstall: uninstall-bin uninstall-man uninstall-links \ + uninstall-scripts diff --git a/packages/tools/nano/config/nanorc b/packages/tools/nano/config/nanorc new file mode 100644 index 000000000..7fa0d6cc7 --- /dev/null +++ b/packages/tools/nano/config/nanorc @@ -0,0 +1 @@ +include /usr/share/nano/*.nanorc diff --git a/packages/tools/nano/package.mk b/packages/tools/nano/package.mk new file mode 100644 index 000000000..478893b09 --- /dev/null +++ b/packages/tools/nano/package.mk @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nano" +PKG_VERSION="4.3" +PKG_SHA256="00d3ad1a287a85b4bf83e5f06cedd0a9f880413682bebd52b4b1e2af8cfc0d81" +PKG_LICENSE="GPL" +PKG_SITE="http://www.nano-editor.org/" +PKG_URL="http://ftpmirror.gnu.org/nano/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Nano is an enhanced clone of the Pico text editor." + +PKG_CONFIGURE_OPTS_TARGET="--disable-utf8 \ + --disable-nls \ + --disable-libmagic \ + --disable-wrapping" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share/nano + + mkdir -p ${INSTALL}/etc + cp -a ${PKG_DIR}/config/* ${INSTALL}/etc/ + + mkdir -p ${INSTALL}/usr/share/nano + for FILE_TYPES in \ + css \ + html \ + java \ + javascript \ + json \ + php \ + python \ + sh \ + xml + do + cp -a ${PKG_BUILD}/syntax/${FILE_TYPES}.nanorc ${INSTALL}/usr/share/nano/ + done +} diff --git a/packages/tools/nano/profile.d/52-nano.conf b/packages/tools/nano/profile.d/52-nano.conf new file mode 100644 index 000000000..e5fddf678 --- /dev/null +++ b/packages/tools/nano/profile.d/52-nano.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +export EDITOR="nano" diff --git a/packages/tools/newt/package.mk b/packages/tools/newt/package.mk new file mode 100644 index 000000000..6eaece09e --- /dev/null +++ b/packages/tools/newt/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="newt" +PKG_VERSION="0.52.21" +PKG_SHA256="265eb46b55d7eaeb887fca7a1d51fe115658882dfe148164b6c49fccac5abb31" +PKG_LICENSE="GPL" +PKG_SITE="https://pagure.io/newt" +PKG_URL="https://releases.pagure.org/newt/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain slang popt" +PKG_LONGDESC="Newt is a programming library for color text mode, widget based user interfaces." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-nls \ + --without-python \ + --without-tcl" + +pre_configure_target() { + # newt fails to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME +} + +pre_configure_host() { + # newt fails to build in subdirs + cd $PKG_BUILD + rm -rf .$HOST_NAME +} diff --git a/packages/tools/plymouth-lite/package.mk b/packages/tools/plymouth-lite/package.mk new file mode 100644 index 000000000..85bb986c6 --- /dev/null +++ b/packages/tools/plymouth-lite/package.mk @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="plymouth-lite" +PKG_VERSION="0.6.0" +PKG_SHA256="fa7b581bdd38c5751668243ff9d2ebaee7c45753358cbb310fb50cfcd3a8081b" +PKG_LICENSE="GPL" +PKG_SITE="http://www.meego.com" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_INIT="toolchain ccache:init libpng" +PKG_DEPENDS_TARGET="toolchain libpng" +PKG_LONGDESC="Boot splash screen based on Fedora's Plymouth code" + +if [ "$UVESAFB_SUPPORT" = yes ]; then + PKG_DEPENDS_INIT="$PKG_DEPENDS_INIT v86d:init" +fi + +pre_configure_init() { + # plymouth-lite dont support to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME-init +} + +makeinstall_init() { + mkdir -p $INSTALL/usr/bin + cp ply-image $INSTALL/usr/bin + + mkdir -p $INSTALL/splash + find_file_path splash/splash.conf && cp ${FOUND_PATH} $INSTALL/splash + find_file_path "splash/splash-*.png" && cp ${FOUND_PATH} $INSTALL/splash +} + +pre_configure_target() { + # plymouth-lite dont support to build in subdirs + cd $PKG_BUILD + rm -rf .$TARGET_NAME-init +} + +post_makeinstall_target() { + + mkdir -p ${INSTALL}/usr/config/splash + + find_file_path "splash/splash-*.png" && cp ${FOUND_PATH} ${INSTALL}/usr/config/splash + + mkdir -p ${INSTALL}/usr/share/bootloader + if [ "${DEVICE}" == "RG351P" ]; then + find_file_path "splash/splash-480.bmp" && cp ${FOUND_PATH} ${INSTALL}/usr/share/bootloader/logo.bmp + elif [ "${DEVICE}" == "RG351V" ] || [ "${DEVICE}" == "RG351MP" ] ; then + find_file_path "splash/splash-640.bmp" && cp ${FOUND_PATH} ${INSTALL}/usr/share/bootloader/logo.bmp + elif [ "${DEVICE}" == "RG552" ]; then + find_file_path "splash/splash-1152.bmp" && cp ${FOUND_PATH} ${INSTALL}/usr/share/bootloader/logo.bmp + fi +} diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-01-fix-build.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-01-fix-build.patch new file mode 100644 index 000000000..f9baa3853 --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-01-fix-build.patch @@ -0,0 +1,10 @@ +--- plymouth-lite-0.6.0/Makefile~ 2009-07-22 11:22:32.000000000 -0700 ++++ plymouth-lite-0.6.0/Makefile 2009-07-22 11:22:32.000000000 -0700 +@@ -1,6 +1,6 @@ + + ply-image: ply-image.c ply-frame-buffer.c Makefile +- gcc -O2 -march=core2 -mtune=generic -lm `pkg-config --cflags libpng12` `pkg-config --libs libpng12` ply-image.c ply-frame-buffer.c -o ply-image ++ $(CC) $(CFLAGS) `pkg-config --cflags libpng` ply-image.c ply-frame-buffer.c -o ply-image -lm `pkg-config --libs libpng` -lm -lz + + clean: + rm -f ply-image *~ gmon.out diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-02-libpng_1.4.0.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-02-libpng_1.4.0.patch new file mode 100644 index 000000000..cf5a08ac9 --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-02-libpng_1.4.0.patch @@ -0,0 +1,12 @@ +diff -Naur plymouth-lite-0.6.0/ply-image.c plymouth-lite-0.6.0.patch/ply-image.c +--- plymouth-lite-0.6.0/ply-image.c 2009-02-19 12:16:36.000000000 +0100 ++++ plymouth-lite-0.6.0.patch/ply-image.c 2010-02-08 01:30:05.336856616 +0100 +@@ -220,7 +220,7 @@ + png_set_palette_to_rgb (png); + + if ((color_type == PNG_COLOR_TYPE_GRAY) && (bits_per_pixel < 8)) +- png_set_gray_1_2_4_to_8 (png); ++ png_set_expand_gray_1_2_4_to_8 (png); + + if (png_get_valid (png, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha (png); diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-11-cursor.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-11-cursor.patch new file mode 100644 index 000000000..fc69b2781 --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-11-cursor.patch @@ -0,0 +1,11 @@ +--- plymouth-lite-0.6.0/ply-image.c~ 2009-03-06 16:20:52.000000000 -0800 ++++ plymouth-lite-0.6.0/ply-image.c 2009-03-06 16:20:52.000000000 -0800 +@@ -439,7 +439,7 @@ + + exit_code = 0; + +-// hide_cursor (); ++ hide_cursor (); + + if (argc == 1) + image = ply_image_new ("/usr/share/plymouth/splash.png"); diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-12-resize.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-12-resize.patch new file mode 100644 index 000000000..4bebf1121 --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-12-resize.patch @@ -0,0 +1,110 @@ +diff -urN plymouth-lite-0.6.0/ply-frame-buffer.c plymouth-lite-0.6.0.change/ply-frame-buffer.c +--- plymouth-lite-0.6.0/ply-frame-buffer.c 2009-02-19 19:14:24.000000000 +0800 ++++ plymouth-lite-0.6.0.change/ply-frame-buffer.c 2009-06-13 17:44:05.000000000 +0800 +@@ -47,41 +47,6 @@ + #define PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME "/dev/fb0" + #endif + +-struct _ply_frame_buffer +-{ +- char *device_name; +- int device_fd; +- +- char *map_address; +- size_t size; +- +- uint32_t *shadow_buffer; +- +- uint32_t red_bit_position; +- uint32_t green_bit_position; +- uint32_t blue_bit_position; +- uint32_t alpha_bit_position; +- +- uint32_t bits_for_red; +- uint32_t bits_for_green; +- uint32_t bits_for_blue; +- uint32_t bits_for_alpha; +- +- int32_t dither_red; +- int32_t dither_green; +- int32_t dither_blue; +- +- unsigned int bytes_per_pixel; +- unsigned int row_stride; +- +- ply_frame_buffer_area_t area; +- ply_frame_buffer_area_t area_to_flush; +- +- void (*flush)(ply_frame_buffer_t *buffer); +- +- int pause_count; +-}; +- + static bool ply_frame_buffer_open_device (ply_frame_buffer_t *buffer); + static void ply_frame_buffer_close_device (ply_frame_buffer_t *buffer); + static bool ply_frame_buffer_query_device (ply_frame_buffer_t *buffer); +diff -urN plymouth-lite-0.6.0/ply-frame-buffer.h plymouth-lite-0.6.0.change/ply-frame-buffer.h +--- plymouth-lite-0.6.0/ply-frame-buffer.h 2009-02-19 17:35:54.000000000 +0800 ++++ plymouth-lite-0.6.0.change/ply-frame-buffer.h 2009-06-13 17:31:42.000000000 +0800 +@@ -38,6 +38,41 @@ + unsigned long height; + }; + ++struct _ply_frame_buffer ++{ ++ char *device_name; ++ int device_fd; ++ ++ char *map_address; ++ size_t size; ++ ++ uint32_t *shadow_buffer; ++ ++ uint32_t red_bit_position; ++ uint32_t green_bit_position; ++ uint32_t blue_bit_position; ++ uint32_t alpha_bit_position; ++ ++ uint32_t bits_for_red; ++ uint32_t bits_for_green; ++ uint32_t bits_for_blue; ++ uint32_t bits_for_alpha; ++ ++ int32_t dither_red; ++ int32_t dither_green; ++ int32_t dither_blue; ++ ++ unsigned int bytes_per_pixel; ++ unsigned int row_stride; ++ ++ ply_frame_buffer_area_t area; ++ ply_frame_buffer_area_t area_to_flush; ++ ++ void (*flush)(ply_frame_buffer_t *buffer); ++ ++ int pause_count; ++}; ++ + #define PLY_FRAME_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \ + (((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \ + | ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \ +diff -urN plymouth-lite-0.6.0/ply-image.c plymouth-lite-0.6.0.change/ply-image.c +--- plymouth-lite-0.6.0/ply-image.c 2009-02-19 19:16:36.000000000 +0800 ++++ plymouth-lite-0.6.0.change/ply-image.c 2009-06-13 17:42:52.000000000 +0800 +@@ -43,6 +43,7 @@ + #include + + #include ++#include "ply-frame-buffer.h" + + #define MIN(a,b) ((a) <= (b)? (a) : (b)) + #define MAX(a,b) ((a) >= (b)? (a) : (b)) +@@ -464,6 +465,8 @@ + return exit_code; + } + ++ image = ply_image_resize(image, buffer->area.width, buffer->area.height); ++ + animate_at_time (buffer, image); + + ply_frame_buffer_close (buffer); diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-21-16bpp.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-21-16bpp.patch new file mode 100644 index 000000000..a1110aaaf --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-21-16bpp.patch @@ -0,0 +1,78 @@ +--- plymouth-lite-0.6.0/ply-frame-buffer.c 2015-07-02 01:04:37.625076373 +0100 ++++ plymouth-lite-0.6.0.patch/ply-frame-buffer.c 2015-07-02 01:04:42.973076293 +0100 +@@ -184,6 +184,58 @@ + } + } + ++static void ++flush_xbgr32 (ply_frame_buffer_t *buffer) ++{ ++ unsigned long x1, y1, x2, y2, x, y; ++ char *dst, *src; ++ ++ x1 = buffer->area_to_flush.x; ++ y1 = buffer->area_to_flush.y; ++ x2 = x1 + buffer->area_to_flush.width; ++ y2 = y1 + buffer->area_to_flush.height; ++ ++ for (y = y1; y < y2; y++) ++ { ++ dst = &buffer->map_address[(y * buffer->row_stride + x1) * 4]; ++ src = (char *) &buffer->shadow_buffer[y * buffer->area.width + x1]; ++ ++ for (x = x1; x < x2; x++) ++ { ++ dst[0] = src[2]; ++ dst[1] = src[1]; ++ dst[2] = src[0]; ++ dst[3] = src[3]; ++ dst += 4; ++ src += 4; ++ } ++ } ++} ++ ++static void ++flush_rgb16 (ply_frame_buffer_t *buffer) ++{ ++ unsigned long x1, y1, x2, y2, x, y; ++ unsigned short *dst; unsigned char *src; ++ ++ x1 = buffer->area_to_flush.x; ++ y1 = buffer->area_to_flush.y; ++ x2 = x1 + buffer->area_to_flush.width; ++ y2 = y1 + buffer->area_to_flush.height; ++ ++ for (y = y1; y < y2; y++) ++ { ++ dst = (unsigned short *)&buffer->map_address[(y * buffer->row_stride + x1) * 2]; ++ src = (unsigned char *) &buffer->shadow_buffer[y * buffer->area.width + x1]; ++ ++ for (x = x1; x < x2; x++) ++ { ++ *dst++ = (src[0]>>3) << 0 | (src[1]>>2) << 5 | (src[2]>>3) << 11; ++ src += 4; ++ } ++ } ++} ++ + static const char const *p_visual(int visual) + { + static const char const *visuals[] = +@@ -300,6 +352,16 @@ + buffer->green_bit_position == 8 && buffer->bits_for_green == 8 && + buffer->blue_bit_position == 0 && buffer->bits_for_blue == 8) + buffer->flush = flush_xrgb32; ++ else if (buffer->bytes_per_pixel == 4 && ++ buffer->red_bit_position == 0 && buffer->bits_for_red == 8 && ++ buffer->green_bit_position == 8 && buffer->bits_for_green == 8 && ++ buffer->blue_bit_position == 16 && buffer->bits_for_blue == 8) ++ buffer->flush = flush_xbgr32; ++ else if (buffer->bytes_per_pixel == 2 && ++ buffer->red_bit_position == 11 && buffer->bits_for_red == 5 && ++ buffer->green_bit_position == 5 && buffer->bits_for_green == 6 && ++ buffer->blue_bit_position == 0 && buffer->bits_for_blue == 5) ++ buffer->flush = flush_rgb16; + else + buffer->flush = flush_generic; + diff --git a/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-22-link-static.patch b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-22-link-static.patch new file mode 100644 index 000000000..d1b0ee88c --- /dev/null +++ b/packages/tools/plymouth-lite/patches/plymouth-lite-0.6.0-22-link-static.patch @@ -0,0 +1,18 @@ +diff --git a/Makefile b/Makefile +index 6ab27ef..17d12a0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + + ply-image: ply-image.c ply-frame-buffer.c Makefile +- $(CC) $(CFLAGS) `pkg-config --cflags libpng` ply-image.c ply-frame-buffer.c -o ply-image -lm `pkg-config --libs libpng` -lm -lz ++ $(CC) $(CFLAGS) -Wl,-Bstatic `pkg-config --cflags libpng` ply-image.c ply-frame-buffer.c -o ply-image `pkg-config --libs libpng` -lz -Wl,-Bdynamic -lc -lm $(LDFLAGS) + + clean: + rm -f ply-image *~ gmon.out +@@ -11,4 +11,3 @@ install: ply-image + cp ply-image $(DESTDIR)/usr/bin + cp splash.png $(DESTDIR)/usr/share/plymouth/splash.png + +- +\ No newline at end of file diff --git a/packages/tools/populatefs/package.mk b/packages/tools/populatefs/package.mk new file mode 100644 index 000000000..196dca1cb --- /dev/null +++ b/packages/tools/populatefs/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="populatefs" +PKG_VERSION="1.0" +PKG_SHA256="e5845404188b5da3afb11229ecb38646cc1562b61400035774dbc237c3b706d2" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/lipnitsk/populatefs" +PKG_URL="https://github.com/lipnitsk/$PKG_NAME/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="e2fsprogs:host" +PKG_LONGDESC="populatefs: Tool for replacing genext2fs when creating ext4 images" +PKG_BUILD_FLAGS="+pic:host" + +make_host() { + make EXTRA_LIBS="-lcom_err -lpthread" +} + +makeinstall_host() { + $STRIP src/populatefs + + mkdir -p $TOOLCHAIN/sbin + cp src/populatefs $TOOLCHAIN/sbin +} diff --git a/packages/tools/populatefs/patches/fix-compilation-issue.patch b/packages/tools/populatefs/patches/fix-compilation-issue.patch new file mode 100644 index 000000000..e9b360cca --- /dev/null +++ b/packages/tools/populatefs/patches/fix-compilation-issue.patch @@ -0,0 +1,11 @@ +diff -Nur a/src/mod_path.c b/src/mod_path.c +--- a/src/mod_path.c 2016-02-24 04:15:10.000000000 +0100 ++++ b/src/mod_path.c 2018-08-22 16:58:11.884462070 +0200 +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/packages/tools/procps-ng/package.mk b/packages/tools/procps-ng/package.mk new file mode 100644 index 000000000..3b91e9ff6 --- /dev/null +++ b/packages/tools/procps-ng/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="procps-ng" +PKG_VERSION="3.3.15" +PKG_SHA256="191391fde24a1d3b9b0030d26f8dfdcbf641d36297aab7ecf2f941c5ca927e21" +PKG_LICENSE="GPL" +PKG_SITE="https://gitlab.com/procps-ng/procps" +PKG_URL="https://gitlab.com/procps-ng/procps/-/archive/v${PKG_VERSION}/procps-v${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Command line and full screen utilities for browsing procfs." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + --disable-shared \ + --disable-modern-top \ + --enable-static" + +PKG_MAKE_OPTS_TARGET="free top/top proc/libprocps.la proc/libprocps.pc" + +PKG_MAKEINSTALL_OPTS_TARGET="install-libLTLIBRARIES install-pkgconfigDATA" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp -P $PKG_BUILD/.$TARGET_NAME/free $INSTALL/usr/bin + cp -P $PKG_BUILD/.$TARGET_NAME/top/top $INSTALL/usr/bin + + make DESTDIR=$SYSROOT_PREFIX -j1 $PKG_MAKEINSTALL_OPTS_TARGET +} diff --git a/packages/tools/qemu/package.mk b/packages/tools/qemu/package.mk new file mode 100644 index 000000000..419344858 --- /dev/null +++ b/packages/tools/qemu/package.mk @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="qemu" +PKG_VERSION="4.0.0" +PKG_SHA256="13a93dfe75b86734326f8d5b475fde82ec692d5b5a338b4262aeeb6b0fa4e469" +PKG_LICENSE="GPL" +PKG_SITE="http://wiki.qemu.org" +PKG_URL="https://download.qemu.org/qemu-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="toolchain glib:host pixman:host Python2:host zlib:host" +PKG_LONGDESC="QEMU is a generic and open source machine emulator and virtualizer." + +pre_configure_host() { + HOST_CONFIGURE_OPTS="--bindir=$TOOLCHAIN/bin \ + --extra-cflags=-I$TOOLCHAIN/include \ + --extra-ldflags=-L$TOOLCHAIN/lib \ + --libexecdir=$TOOLCHAIN/lib \ + --localstatedir=$TOOLCHAIN/var \ + --prefix=$TOOLCHAIN \ + --sbindir=$TOOLCHAIN/sbin \ + --static \ + --sysconfdir=$TOOLCHAIN/etc \ + --disable-blobs \ + --disable-docs \ + --disable-gcrypt \ + --disable-system \ + --disable-user \ + --disable-vnc \ + --disable-werror" +} diff --git a/packages/tools/rkbin/package.mk b/packages/tools/rkbin/package.mk new file mode 100644 index 000000000..e24aae95a --- /dev/null +++ b/packages/tools/rkbin/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rkbin" + +if [[ "${DEVICE}" =~ RG351 ]]; then + PKG_VERSION="0bb1c512492386a72a3a0b5a0e18e49c636577b9" +else + PKG_VERSION="7d631e0d5b2d373b54d4533580d08fb9bd2eaad4" +fi + +PKG_ARCH="arm aarch64" +PKG_LICENSE="nonfree" +PKG_SITE="https://github.com/rockchip-linux/rkbin" +PKG_URL="https://github.com/rockchip-linux/rkbin/archive/$PKG_VERSION.tar.gz" +PKG_LONGDESC="rkbin: Rockchip Firmware and Tool Binaries" +PKG_TOOLCHAIN="manual" diff --git a/packages/tools/rpi-eeprom/config/rpi-eeprom-update b/packages/tools/rpi-eeprom/config/rpi-eeprom-update new file mode 100644 index 000000000..0a62ac0b4 --- /dev/null +++ b/packages/tools/rpi-eeprom/config/rpi-eeprom-update @@ -0,0 +1,4 @@ +# Use direct path to firmware as update script doesn't dereference sym links. +FIRMWARE_ROOT="/usr/lib/kernel-overlays/base/lib/firmware/raspberrypi/bootloader" +FIRMWARE_BACKUP_DIR="/storage/.config/rpifw-backup" +BOOTFS=${BOOTFS:-/flash} diff --git a/packages/tools/rpi-eeprom/package.mk b/packages/tools/rpi-eeprom/package.mk new file mode 100644 index 000000000..5c6d3f503 --- /dev/null +++ b/packages/tools/rpi-eeprom/package.mk @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="rpi-eeprom" +PKG_VERSION="8e9aca34aeead5fb87aa334cc29edc927bbeae7a" +PKG_SHA256="f3d3af536adf4bc105ed5b86e4090b008f298daccacc7536cb3c91a2f8a22352" +PKG_ARCH="arm" +PKG_LICENSE="BSD-3/custom" +PKG_SITE="https://github.com/raspberrypi/rpi-eeprom" +PKG_URL="https://github.com/raspberrypi/rpi-eeprom/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="flashrom" +PKG_LONGDESC="rpi-eeprom: firmware, config and scripts to update RPi4 SPI bootloader" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + DESTDIR=${INSTALL}/$(get_kernel_overlay_dir)/lib/firmware/raspberrypi/bootloader + + mkdir -p ${DESTDIR} + _dirs="critical stable" + [ "${OS_VERSION}" = "devel" ] && _dirs+=" beta" + + for _maindir in ${_dirs}; do + for _dir in ${PKG_BUILD}/firmware/${_maindir} ${PKG_BUILD}/firmware/{_maindir}-*; do + [ -d "${_dir}" ] || continue + + _basedir="$(basename "${_dir}")" + + mkdir -p ${DESTDIR}/${_basedir} + cp -PRv ${_dir}/recovery.bin ${DESTDIR}/${_basedir} + + # Bootloader SPI + PKG_FW_FILE="$(ls -1 /${_dir}/pieeprom-* 2>/dev/null | tail -1)" + [ -n "${PKG_FW_FILE}" ] && cp -PRv "${PKG_FW_FILE}" ${DESTDIR}/${_basedir} + + # VIA USB3 + PKG_FW_FILE="$(ls -1 ${_dir}/vl805-*.bin 2>/dev/null | tail -1)" + [ -n "${PKG_FW_FILE}" ] && cp -PRv "${PKG_FW_FILE}" ${DESTDIR}/${_basedir} + done + done + + mkdir -p ${INSTALL}/usr/bin + cp -PRv ${PKG_DIR}/source/rpi-eeprom-update ${INSTALL}/usr/bin + cp -PRv ${PKG_BUILD}/rpi-eeprom-update ${INSTALL}/usr/bin/.rpi-eeprom-update.real + cp -PRv ${PKG_BUILD}/rpi-eeprom-config ${INSTALL}/usr/bin + cp -PRv ${PKG_BUILD}/firmware/vl805 ${INSTALL}/usr/bin + + mkdir -p ${INSTALL}/etc/default + cp -PRv ${PKG_DIR}/config/* ${INSTALL}/etc/default +} diff --git a/packages/tools/rpi-eeprom/source/rpi-eeprom-update b/packages/tools/rpi-eeprom/source/rpi-eeprom-update new file mode 100755 index 000000000..6070549b2 --- /dev/null +++ b/packages/tools/rpi-eeprom/source/rpi-eeprom-update @@ -0,0 +1,10 @@ +#!/bin/sh + +# If read-only then mount writeable, and restore read-only on exit +# This means we don't restore read-only if /flash is already writeable +if [ -n "$(grep " /flash " /proc/mounts | grep "[[:space:]]ro[[:space:],]")" ]; then + trap "mount -o remount,ro /flash" EXIT + mount -o remount,rw /flash +fi + +sh /usr/bin/.rpi-eeprom-update.real $@ diff --git a/packages/tools/rtk_hciattach/package.mk b/packages/tools/rtk_hciattach/package.mk new file mode 100644 index 000000000..a7f7cc508 --- /dev/null +++ b/packages/tools/rtk_hciattach/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="rtk_hciattach" +PKG_VERSION="58820c428d2ecae6aaf5e4f00997652b9479853a" +PKG_SHA256="20161cf3011f57dc9912db7270be1a83e543a61ea8757c23eaf983542fb021e0" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/Caesar-github/rkwifibt" +PKG_URL="https://github.com/Caesar-github/rkwifibt/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="Realtek BT FW loader" +PKG_TOOLCHAIN="make" + +unpack() { + mkdir -p $PKG_BUILD + tar --strip-components=3 -xf $SOURCES/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz -C $PKG_BUILD rkwifibt-$PKG_VERSION/realtek/rtk_hciattach +} diff --git a/packages/tools/rtk_hciattach/patches/rtk_hciattach-01-Makefile.patch b/packages/tools/rtk_hciattach/patches/rtk_hciattach-01-Makefile.patch new file mode 100644 index 000000000..0f312243a --- /dev/null +++ b/packages/tools/rtk_hciattach/patches/rtk_hciattach-01-Makefile.patch @@ -0,0 +1,19 @@ +--- a/Makefile ++++ b/Makefile +@@ -1,4 +1,4 @@ +-CFLAGS := -Wall -g ++CFLAGS := -g + #CC := $(CROSS_COMPLE)gcc + all: rtk_hciattach + OBJS := hciattach.o hciattach_rtk.o hciattach_h4.o rtb_fwc.o +@@ -12,6 +12,10 @@ + clean: + rm -f $(OBJS) rtk_hciattach + ++install: ++ install -m 755 -d $(DESTDIR)/usr/bin ++ install -m 755 rtk_hciattach $(DESTDIR)/usr/bin ++ + tags: FORCE + ctags -R + find ./ -name "*.h" -o -name "*.c" -o -name "*.cc" -o -name "*.cpp" > cscope.files diff --git a/packages/tools/rtk_hciattach/patches/rtk_hciattach-02-dont-read-mac-from-vendor-storage.patch b/packages/tools/rtk_hciattach/patches/rtk_hciattach-02-dont-read-mac-from-vendor-storage.patch new file mode 100644 index 000000000..6f6883188 --- /dev/null +++ b/packages/tools/rtk_hciattach/patches/rtk_hciattach-02-dont-read-mac-from-vendor-storage.patch @@ -0,0 +1,13 @@ +--- a/rtb_fwc.c ++++ b/rtb_fwc.c +@@ -39,8 +39,8 @@ + #define BT_CONFIG_DIRECTORY "/lib/firmware/rtlbt/" + + #ifdef USE_CUSTOMER_ADDRESS +-#define BT_ADDR_FROM_VENDOR_STORAGE +-#define BT_ADDR_FILE "/opt/bdaddr" ++//#define BT_ADDR_FROM_VENDOR_STORAGE ++#define BT_ADDR_FILE "/storage/.config/btaddr" + static uint8_t customer_bdaddr = 0; + #endif + diff --git a/packages/tools/scrapers/Skyscraper/config/artwork.xml b/packages/tools/scrapers/Skyscraper/config/artwork.xml new file mode 100644 index 000000000..7d16bae21 --- /dev/null +++ b/packages/tools/scrapers/Skyscraper/config/artwork.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/packages/tools/scrapers/Skyscraper/config/config.ini b/packages/tools/scrapers/Skyscraper/config/config.ini new file mode 100644 index 000000000..7b6201eec --- /dev/null +++ b/packages/tools/scrapers/Skyscraper/config/config.ini @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) +[main] +inputFolder="/storage/roms" +gamelistFolder="/storage/roms" +videos="true" +symlink="false" +brackets="true" +maxLength="10000" +unattend="true" +verbosity="0" +hints="false" + +# List of supported languages https://github.com/muldjord/skyscraper/blob/master/docs/LANGUAGES.md +# List of supported regions https://github.com/muldjord/skyscraper/blob/master/docs/REGIONS.md +lang="en" +langPrios="en,es,ja,de,fr,it" +region="us" +regionPrios="us,es,jp,eu,de,fr,it,wor" + +[screenscraper] +userCreds="Username:Pass" + diff --git a/packages/tools/scrapers/Skyscraper/package.mk b/packages/tools/scrapers/Skyscraper/package.mk new file mode 100644 index 000000000..69436dcae --- /dev/null +++ b/packages/tools/scrapers/Skyscraper/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present CoreELEC (https://coreelec.org) + +PKG_NAME="Skyscraper" +PKG_VERSION="f30c88c336ac3763dd2f3cc563622dc372b8785f" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/muldjord/skyscraper" +PKG_URL="$PKG_SITE.git" +PKG_DEPENDS_TARGET="toolchain qt-everywhere p7zip:host" +PKG_PRIORITY="optional" +PKG_SECTION="emuelec" +PKG_SHORTDESC="Powerful and versatile game scraper written in c++ " +PKG_TOOLCHAIN="make" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" + +configure_target() { + # Fix install paths / 5schatten + sed -e "s#target.path=/usr/local/bin#target.path=$INSTALL/usr/bin#" -i ${PKG_BUILD}/skyscraper.pro + sed -e "s#examples.path=/usr/local/etc/skyscraper#examples.path=$INSTALL/usr/share/skyscraper#" -i ${PKG_BUILD}/skyscraper.pro + sed -e "s#cacheexamples.path=/usr/local/etc/skyscraper/cache#cacheexamples.path=$INSTALL/usr/share/skyscraper/cache#" -i ${PKG_BUILD}/skyscraper.pro + sed -e "s#impexamples.path=/usr/local/etc/skyscraper/import#impexamples.path=$INSTALL/usr/share/skyscraper/import#" -i ${PKG_BUILD}/skyscraper.pro + sed -e "s#resexamples.path=/usr/local/etc/skyscraper/resources#resexamples.path=$INSTALL/usr/share/skyscraper/resources#" -i ${PKG_BUILD}/skyscraper.pro + + rm -rf .qmake.stash + QMAKEPATH=$(find $BUILD/qt-everywhere*/qtbase/bin -maxdepth 1 -name qmake) + $QMAKEPATH $PKG_BUILD/skyscraper.pro +} + +post_makeinstall_target() { + # Install scripts + cp $PKG_DIR/scripts/* $INSTALL/usr/bin/ + + # Install config + mkdir -p $INSTALL/usr/config/skyscraper + cp $PKG_DIR/config/* $INSTALL/usr/config/skyscraper/ +} + diff --git a/packages/tools/scrapers/Skyscraper/scripts/skyscraper b/packages/tools/scrapers/Skyscraper/scripts/skyscraper new file mode 100755 index 000000000..919dada37 --- /dev/null +++ b/packages/tools/scrapers/Skyscraper/scripts/skyscraper @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +. /etc/profile + +# Set common paths +SKYSCRAPER_HOME_CONFIG=/storage/.config/skyscraper +SKYSCRAPER_HOME=/storage/.skyscraper + +# create link to config directory +if [ ! -L ${SKYSCRAPER_HOME} ]; then + cp -r ${SKYSCRAPER_HOME}/* ${SKYSCRAPER_HOME_CONFIG}/ + rm -rf ${SKYSCRAPER_HOME} + ln -s ${SKYSCRAPER_HOME_CONFIG} ${SKYSCRAPER_HOME} +fi + +Skyscraper "$@" + + diff --git a/packages/tools/scrapers/scraper/package.mk b/packages/tools/scrapers/scraper/package.mk new file mode 100644 index 000000000..f35c960e2 --- /dev/null +++ b/packages/tools/scrapers/scraper/package.mk @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="scraper" +PKG_VERSION="509443bf66d9fccb1d6aa2417902124bd48f2141" +PKG_SHA256="5784ac4aa35919233774c3c0210d5cae4aa296ec30165b6b7a7cb41a7d98cb6d" +PKG_REV="2" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/sselph/scraper" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain go:host" +PKG_PRIORITY="optional" +PKG_SECTION="emuelec" +PKG_LONGDESC="A scraper for EmulationStation written in Go using hashing" +PKG_TOOLCHAIN="manual" + +configure_target() { + + case ${TARGET_ARCH} in + x86_64) + export GOARCH=amd64 + ;; + arm) + export GOARCH=arm + + case ${TARGET_CPU} in + arm1176jzf-s) + export GOARM=6 + ;; + *) + export GOARM=7 + ;; + esac + ;; + aarch64) + export GOARCH=arm64 + ;; + esac + + export GOOS=linux + export GOLANG=${TOOLCHAIN}/lib/golang/bin/go + export LDFLAGS="-w -extldflags -static -X main.gitCommit=${PKG_VERSION} -X main.versionStr=${PKG_VERSION:0:7} -extld $CC" +} + +make_target() { + mkdir -p bin + cd $PKG_BUILD + ${GOLANG} get github.com/sselph/scraper + ${GOLANG} build -ldflags "$LDFLAGS" github.com/sselph/scraper +} + +makeinstall_target() { +mkdir -p $INSTALL/usr/bin/ + cp $PKG_BUILD/scraper $INSTALL/usr/bin/ +} diff --git a/packages/tools/socat/package.mk b/packages/tools/socat/package.mk new file mode 100644 index 000000000..262354f84 --- /dev/null +++ b/packages/tools/socat/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="socat" +PKG_VERSION="1.7.3.4" +PKG_SHA256="972374ca86f65498e23e3259c2ee1b8f9dbeb04d12c2a78c0c9b5d1cb97dfdfc" +PKG_LICENSE="GPLv2+" +PKG_SITE="http://www.dest-unreach.org/socat/download" +PKG_URL="$PKG_SITE/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A multipurpose relay (SOcket CAT)" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET+=" --disable-libwrap \ + --disable-readline \ + --enable-termios" + diff --git a/packages/tools/sound/fluidsynth-git/config/fluidsynth.conf b/packages/tools/sound/fluidsynth-git/config/fluidsynth.conf new file mode 100644 index 000000000..f41ee1edc --- /dev/null +++ b/packages/tools/sound/fluidsynth-git/config/fluidsynth.conf @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +SOUND_FONT=/storage/.config/fluidsynth/soundfonts/GeneralUser.sf2 +AUDIO_DRIVER=pulseaudio +MIDI_DRIVER=alsa_seq +PORT_NAME=FluidSynth +OTHER_OPTS='-r 48000' diff --git a/packages/tools/sound/fluidsynth-git/package.mk b/packages/tools/sound/fluidsynth-git/package.mk new file mode 100644 index 000000000..157fa9761 --- /dev/null +++ b/packages/tools/sound/fluidsynth-git/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Frank Hartung (supervisedthinking (@) gmail.com) + +PKG_NAME="fluidsynth-git" +PKG_VERSION="2.0.6" +PKG_SHA256="e97e63c1045e102465f1aa848f9d712c5528c58685b8d40062e4aaf6af7edb75" +PKG_LICENSE="LGPL" +PKG_SITE="http://fluidsynth.org/" +PKG_URL="https://github.com/FluidSynth/fluidsynth/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain glib soundfont-generaluser" +PKG_LONGDESC="FluidSynth is a software real-time synthesizer based on the Soundfont 2 specifications." +PKG_BUILD_FLAGS="+pic" + +pre_configure_target() { + PKG_CMAKE_OPTS_TARGET="-DLIB_SUFFIX= \ + -Denable-readline=0 \ + -Denable-oss=0 \ + -Denable-pulseaudio=1 \ + -Denable-libsndfile=1" +} + +post_makeinstall_target() { + # Create directories + mkdir -p ${INSTALL}/etc/fluidsynth + mkdir -p ${INSTALL}/usr/config/fluidsynth/soundfonts + + # Create symlinks & install config file + cp -a ${PKG_DIR}/config/* ${INSTALL}/usr/config/fluidsynth/ + ln -s /storage/.config/fluidsynth/fluidsynth.conf ${INSTALL}/etc/fluidsynth/ + echo "Place your SoundFonts here!" >> ${INSTALL}/usr/config/fluidsynth/soundfonts/readme.txt + + # Create symlink to SoundFont + ln -s /usr/share/soundfonts/GeneralUser.sf2 ${INSTALL}/usr/config/fluidsynth/soundfonts/ +} diff --git a/packages/tools/sound/fluidsynth-git/system.d/fluidsynth.service b/packages/tools/sound/fluidsynth-git/system.d/fluidsynth.service new file mode 100644 index 000000000..d68241196 --- /dev/null +++ b/packages/tools/sound/fluidsynth-git/system.d/fluidsynth.service @@ -0,0 +1,10 @@ +[Unit] +Description=FluidSynth Software Synthesizer Daemon +After=sound.target + +[Service] +EnvironmentFile=/etc/fluidsynth/fluidsynth.conf +ExecStart=/usr/bin/fluidsynth -is -a $AUDIO_DRIVER -m $MIDI_DRIVER -p $PORT_NAME $OTHER_OPTS $SOUND_FONT + +[Install] +WantedBy=multi-user.target diff --git a/packages/tools/sound/libmad/package.mk b/packages/tools/sound/libmad/package.mk new file mode 100644 index 000000000..1ef3ae361 --- /dev/null +++ b/packages/tools/sound/libmad/package.mk @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libmad" +PKG_VERSION="0.15.1b" +PKG_SHA256="bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690" +PKG_LICENSE="GPL" +PKG_SITE="http://www.mars.org/home/rob/proj/mpeg/" +PKG_URL="$SOURCEFORGE_SRC/mad/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A high-quality MPEG audio decoder." +PKG_TOOLCHAIN="autotools" + +# package specific configure options +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" +if [ "$TARGET_ARCH" = "x86_64" ] ; then + PKG_CONFIGURE_OPTS_TARGET="$PKG_CONFIGURE_OPTS_TARGET --enable-accuracy --enable-fpm=64bit" +fi + +post_makeinstall_target() { + mkdir -p $SYSROOT_PREFIX/usr/lib/pkgconfig + cat > $SYSROOT_PREFIX/usr/lib/pkgconfig/mad.pc << "EOF" +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: mad +Description: MPEG audio decoder +Requires: +Version: 0.15.1b +Libs: -L${libdir} -lmad +Cflags: -I${includedir} +EOF +} diff --git a/packages/tools/sound/libmad/patches/libmad-0.15.1b-automake_1.13.patch b/packages/tools/sound/libmad/patches/libmad-0.15.1b-automake_1.13.patch new file mode 100644 index 000000000..270ff8156 --- /dev/null +++ b/packages/tools/sound/libmad/patches/libmad-0.15.1b-automake_1.13.patch @@ -0,0 +1,12 @@ +diff -Naur libmad-0.15.1b-old/configure.ac libmad-0.15.1b-new/configure.ac +--- libmad-0.15.1b-old/configure.ac 2004-01-23 01:41:32.000000000 -0800 ++++ libmad-0.15.1b-new/configure.ac 2012-12-30 15:14:37.000000000 -0800 +@@ -28,7 +28,7 @@ + + AM_INIT_AUTOMAKE + +-AM_CONFIG_HEADER([config.h]) ++AC_CONFIG_HEADERS([config.h]) + + dnl System type. + diff --git a/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags-O2.patch b/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags-O2.patch new file mode 100644 index 000000000..61b4b13bd --- /dev/null +++ b/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags-O2.patch @@ -0,0 +1,12 @@ +diff -Naur libmad-0.15.1b-orig/configure.ac libmad-0.15.1b/configure.ac +--- libmad-0.15.1b-orig/configure.ac 2007-07-01 12:58:13.000000000 -0600 ++++ libmad-0.15.1b/configure.ac 2007-07-01 12:59:13.000000000 -0600 +@@ -105,7 +105,7 @@ + shift + ;; + -O2) +- optimize="-O" ++ optimize="-O2" + shift + ;; + -fomit-frame-pointer) diff --git a/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags.patch b/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags.patch new file mode 100644 index 000000000..2ec44e344 --- /dev/null +++ b/packages/tools/sound/libmad/patches/libmad-0.15.1b-cflags.patch @@ -0,0 +1,146 @@ +diff -Naur libmad-0.15.1b-orig/configure.ac libmad-0.15.1b/configure.ac +--- libmad-0.15.1b-orig/configure.ac 2007-06-30 20:22:31.000000000 -0600 ++++ libmad-0.15.1b/configure.ac 2007-06-30 20:25:31.000000000 -0600 +@@ -122,74 +122,74 @@ + esac + done + +-if test "$GCC" = yes +-then +- if test -z "$arch" +- then +- case "$host" in +- i386-*) ;; +- i?86-*) arch="-march=i486" ;; +- arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;; +- armv4*-*) arch="-march=armv4 -mtune=strongarm" ;; +- powerpc-*) ;; +- mips*-agenda-*) arch="-mcpu=vr4100" ;; +- mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;; +- esac +- fi +- +- case "$optimize" in +- -O|"-O "*) +- optimize="-O" +- optimize="$optimize -fforce-mem" +- optimize="$optimize -fforce-addr" +- : #x optimize="$optimize -finline-functions" +- : #- optimize="$optimize -fstrength-reduce" +- optimize="$optimize -fthread-jumps" +- optimize="$optimize -fcse-follow-jumps" +- optimize="$optimize -fcse-skip-blocks" +- : #x optimize="$optimize -frerun-cse-after-loop" +- : #x optimize="$optimize -frerun-loop-opt" +- : #x optimize="$optimize -fgcse" +- optimize="$optimize -fexpensive-optimizations" +- optimize="$optimize -fregmove" +- : #* optimize="$optimize -fdelayed-branch" +- : #x optimize="$optimize -fschedule-insns" +- optimize="$optimize -fschedule-insns2" +- : #? optimize="$optimize -ffunction-sections" +- : #? optimize="$optimize -fcaller-saves" +- : #> optimize="$optimize -funroll-loops" +- : #> optimize="$optimize -funroll-all-loops" +- : #x optimize="$optimize -fmove-all-movables" +- : #x optimize="$optimize -freduce-all-givs" +- : #? optimize="$optimize -fstrict-aliasing" +- : #* optimize="$optimize -fstructure-noalias" +- +- case "$host" in +- arm*-*) +- optimize="$optimize -fstrength-reduce" +- ;; +- mips*-*) +- optimize="$optimize -fstrength-reduce" +- optimize="$optimize -finline-functions" +- ;; +- i?86-*) +- optimize="$optimize -fstrength-reduce" +- ;; +- powerpc-apple-*) +- # this triggers an internal compiler error with gcc2 +- : #optimize="$optimize -fstrength-reduce" +- +- # this is really only beneficial with gcc3 +- : #optimize="$optimize -finline-functions" +- ;; +- *) +- # this sometimes provokes bugs in gcc 2.95.2 +- : #optimize="$optimize -fstrength-reduce" +- ;; +- esac +- ;; +- esac +-fi ++#if test "$GCC" = yes ++#then ++# if test -z "$arch" ++# then ++# case "$host" in ++# i386-*) ;; ++# i?86-*) arch="-march=i486" ;; ++# arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;; ++# armv4*-*) arch="-march=armv4 -mtune=strongarm" ;; ++# powerpc-*) ;; ++# mips*-agenda-*) arch="-mcpu=vr4100" ;; ++# mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;; ++# esac ++# fi ++# ++# case "$optimize" in ++# -O|"-O "*) ++# optimize="-O" ++# optimize="$optimize -fforce-mem" ++# optimize="$optimize -fforce-addr" ++# : #x optimize="$optimize -finline-functions" ++# : #- optimize="$optimize -fstrength-reduce" ++# optimize="$optimize -fthread-jumps" ++# optimize="$optimize -fcse-follow-jumps" ++# optimize="$optimize -fcse-skip-blocks" ++# : #x optimize="$optimize -frerun-cse-after-loop" ++# : #x optimize="$optimize -frerun-loop-opt" ++# : #x optimize="$optimize -fgcse" ++# optimize="$optimize -fexpensive-optimizations" ++# optimize="$optimize -fregmove" ++# : #* optimize="$optimize -fdelayed-branch" ++# : #x optimize="$optimize -fschedule-insns" ++# optimize="$optimize -fschedule-insns2" ++# : #? optimize="$optimize -ffunction-sections" ++# : #? optimize="$optimize -fcaller-saves" ++# : #> optimize="$optimize -funroll-loops" ++# : #> optimize="$optimize -funroll-all-loops" ++# : #x optimize="$optimize -fmove-all-movables" ++# : #x optimize="$optimize -freduce-all-givs" ++# : #? optimize="$optimize -fstrict-aliasing" ++# : #* optimize="$optimize -fstructure-noalias" ++# ++# case "$host" in ++# arm*-*) ++# optimize="$optimize -fstrength-reduce" ++# ;; ++# mips*-*) ++# optimize="$optimize -fstrength-reduce" ++# optimize="$optimize -finline-functions" ++# ;; ++# i?86-*) ++# optimize="$optimize -fstrength-reduce" ++# ;; ++# powerpc-apple-*) ++# # this triggers an internal compiler error with gcc2 ++# : #optimize="$optimize -fstrength-reduce" ++# ++# # this is really only beneficial with gcc3 ++# : #optimize="$optimize -finline-functions" ++# ;; ++# *) ++# # this sometimes provokes bugs in gcc 2.95.2 ++# : #optimize="$optimize -fstrength-reduce" ++# ;; ++# esac ++# ;; ++# esac ++#fi + + case "$host" in + mips*-agenda-*) diff --git a/packages/tools/sound/libvorbisidec/package.mk b/packages/tools/sound/libvorbisidec/package.mk new file mode 100644 index 000000000..169baf712 --- /dev/null +++ b/packages/tools/sound/libvorbisidec/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="libvorbisidec" +PKG_VERSION="a76e41f6ece93d10deac5f9ef3a84dce5b9c2a84" +PKG_SHA256="54c4cfaf442885575261d7b310b2dfa79e4fbf095aaf34de07875b024e499991" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/sezero/tremor" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libvorbisidec" +PKG_TOOLCHAIN="make" + + +make_target() { +cd $PKG_BUILD +./autogen.sh HAVE_OGG=no --disable-mmx --prefix=/usr --datadir=/usr/share/ --datarootdir=/usr/share/ --host=armv8a-libreelec-linux --enable-fb --enable-freetype --with-freetype-prefix=$SYSROOT_PREFIX/usr/ --enable-slang +make +} + diff --git a/packages/tools/sound/mpg123/package.mk b/packages/tools/sound/mpg123/package.mk new file mode 100644 index 000000000..1c5a69830 --- /dev/null +++ b/packages/tools/sound/mpg123/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="mpg123" +PKG_VERSION="1.29.0" +#PKG_SHA256="" +PKG_LICENSE="LGPLv2" +PKG_SITE="http://www.mpg123.org/" +PKG_URL="http://www.mpg123.org/download/mpg123-$PKG_VERSION.tar.bz2" +PKG_DEPENDS_TARGET="toolchain alsa-lib SDL2" +PKG_LONGDESC="A console based real time MPEG Audio Player for Layer 1, 2 and 3." +PKG_BUILD_FLAGS="-fpic" + +if [ "$PULSEAUDIO_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET pulseaudio" + PKG_CONFIGURE_OPTS_TARGET="${PKG_CONFIGURE_OPTS_TARGET} --with-default-audio=pulse --with-audio=alsa,pulse" +fi diff --git a/packages/tools/sound/munt_neon/math_neon/package.mk b/packages/tools/sound/munt_neon/math_neon/package.mk new file mode 100644 index 000000000..2075951c8 --- /dev/null +++ b/packages/tools/sound/munt_neon/math_neon/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="math_neon" +PKG_VERSION="bc25cd6715796c2c656dca9244f042b79c6bac8c" +PKG_ARCH="arm" +PKG_LICENSE="GPLv3" +PKG_SITE="https://github.com/asakous/math_neon" +PKG_URL="https://github.com/asakous/math_neon.git" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="This project implements the cmath functions and some optimised matrix functions with the aim of increasing the floating point performance of ARM Cortex A-8 based platforms. As well as implementing the functions in ARM NEON assembly, they sacrifice error checking and some accuracy to achieve better performance" +GET_HANDLER_SUPPORT="git" +PKG_TOOLCHAIN="make" + + +PKG_MAKE_OPTS_TARGET="all" + +pre_configure_target() { +if [[ "$DEVICE" =~ RG351 ]]; then +sed -i -e "s/cortex-a7/cortex-a35/" $PKG_BUILD/Makefile +else +sed -i -e "s/cortex-a7/cortex-a53/" $PKG_BUILD/Makefile +fi +} + +makeinstall_target() { +cd $PKG_BUILD +cp -f $PKG_BUILD/libmathneon.a $SYSROOT_PREFIX/usr/lib/ +} diff --git a/packages/tools/sound/munt_neon/package.mk b/packages/tools/sound/munt_neon/package.mk new file mode 100644 index 000000000..9485f000b --- /dev/null +++ b/packages/tools/sound/munt_neon/package.mk @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present asakous (https://github.com/asakous) + +PKG_NAME="munt_neon" +PKG_VERSION="5785a6c9321179cf0544128ea4f740bb59f1928b" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/asakous/munt" +PKG_URL="https://github.com/asakous/munt.git" +PKG_DEPENDS_TARGET="toolchain math_neon" +PKG_LONGDESC="A software synthesiser emulating pre-GM MIDI devices such as the Roland MT-32." +GET_HANDLER_SUPPORT="git" +PKG_CMAKE_OPTS_TARGET="-Dmunt_WITH_MT32EMU_QT=0 \ + -Dmunt_WITH_MT32EMU_SMF2WAV=0 \ + -Dlibmt32emu_SHARED=1" + + +pre_configure_target() { +if [[ "$DEVICE" =~ RG351 ]]; then +sed -i -e "s/cortex-a7/cortex-a35/" $PKG_BUILD/mt32emu_alsadrv/Makefile +else +sed -i -e "s/cortex-a7/cortex-a53/" $PKG_BUILD/mt32emu_alsadrv/Makefile +fi +sed -i -e "s|../libmathneon.a|$(get_build_dir math_neon)/libmathneon.a|" $PKG_BUILD/mt32emu_alsadrv/Makefile +sed -i -e "s|/usr/share/mt32-rom-data/|/storage/mt32-rom-data/|" $PKG_BUILD/mt32emu_alsadrv/src/alsadrv.cpp +sed -i -e "s|../build/mt32emu/libmt32emu.a|${PKG_BUILD}/.${TARGET_NAME}/mt32emu/libmt32emu.so|" $PKG_BUILD/mt32emu_alsadrv/Makefile +} + +post_configure_target() { +cp -rf ${PKG_BUILD}/.${TARGET_NAME}/mt32emu/include/* $SYSROOT_PREFIX/usr/include +} + +pre_makeinstall_target() { +PKG_LIBNAME="libmt32emu.so.2" +PKG_LIBPATH="$PKG_BUILD/.${TARGET_NAME}/mt32emu/libmt32emu.so*" + +cp $PKG_LIBPATH $SYSROOT_PREFIX/usr/lib +cd $PKG_BUILD/mt32emu_alsadrv/ +make mt32d +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp mt32d $INSTALL/usr/bin/mt32d + + #build systems will not copy .la files so this is pointless + mkdir -p $INSTALL/usr/lib + cp $PKG_LIBPATH $INSTALL/usr/lib +} diff --git a/packages/tools/sound/soundfont-generaluser/package.mk b/packages/tools/sound/soundfont-generaluser/package.mk new file mode 100644 index 000000000..d582f0cb5 --- /dev/null +++ b/packages/tools/sound/soundfont-generaluser/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="soundfont-generaluser" +PKG_VERSION="1.471" +PKG_SHA256="4203835164766f428c4926c097c9ea58dae431c7fb8f9dbe277b92d80da45ec2" +PKG_LICENSE="OSS" +PKG_SITE="http://www.schristiancollins.com/generaluser.php" +PKG_URL="https://www.dropbox.com/s/4x27l49kxcwamp5/GeneralUser_GS_$PKG_VERSION.zip" +PKG_SOURCE_DIR="GeneralUser*" +PKG_DEPENDS_TARGET="" +PKG_LONGDESC="GeneralUser GS is a GM and GS compatible SoundFont bank for composing, playing MIDI files, and retro gaming." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/soundfonts + cp GeneralUser*$PKG_VERSION.sf2 $INSTALL/usr/share/soundfonts/GeneralUser.sf2 +} diff --git a/packages/tools/sound/timidity/config/GeneralUser.cfg b/packages/tools/sound/timidity/config/GeneralUser.cfg new file mode 100644 index 000000000..970e587d2 --- /dev/null +++ b/packages/tools/sound/timidity/config/GeneralUser.cfg @@ -0,0 +1,1796 @@ +dir /storage/.config/fluidsynth/soundfonts/ + +bank 0 +0 %font "GeneralUser.sf2" 0 0 amp=52 pan=0 +1 %font "GeneralUser.sf2" 0 1 amp=84 pan=0 +2 %font "GeneralUser.sf2" 0 2 amp=51 pan=0 +3 %font "GeneralUser.sf2" 0 3 amp=139 pan=0 +4 %font "GeneralUser.sf2" 0 4 amp=79 pan=0 +5 %font "GeneralUser.sf2" 0 5 amp=102 pan=0 +6 %font "GeneralUser.sf2" 0 6 amp=50 pan=0 +7 %font "GeneralUser.sf2" 0 7 amp=103 pan=0 +8 %font "GeneralUser.sf2" 0 8 amp=127 pan=0 +9 %font "GeneralUser.sf2" 0 9 amp=214 pan=0 +10 %font "GeneralUser.sf2" 0 10 amp=207 pan=0 +11 %font "GeneralUser.sf2" 0 11 amp=39 pan=0 +12 %font "GeneralUser.sf2" 0 12 amp=143 pan=0 +13 %font "GeneralUser.sf2" 0 13 amp=101 pan=0 +14 %font "GeneralUser.sf2" 0 14 amp=77 pan=0 +15 %font "GeneralUser.sf2" 0 15 amp=134 pan=0 +16 %font "GeneralUser.sf2" 0 16 amp=119 pan=0 +17 %font "GeneralUser.sf2" 0 17 amp=112 pan=0 +18 %font "GeneralUser.sf2" 0 18 amp=93 pan=0 +19 %font "GeneralUser.sf2" 0 19 amp=201 pan=0 +20 %font "GeneralUser.sf2" 0 20 amp=86 pan=0 +21 %font "GeneralUser.sf2" 0 21 amp=59 pan=0 +22 %font "GeneralUser.sf2" 0 22 amp=51 pan=0 +23 %font "GeneralUser.sf2" 0 23 amp=42 pan=0 +24 %font "GeneralUser.sf2" 0 24 amp=130 pan=0 +25 %font "GeneralUser.sf2" 0 25 amp=65 pan=0 +26 %font "GeneralUser.sf2" 0 26 amp=193 pan=0 +27 %font "GeneralUser.sf2" 0 27 amp=110 pan=0 +28 %font "GeneralUser.sf2" 0 28 amp=187 pan=0 +29 %font "GeneralUser.sf2" 0 29 amp=124 pan=0 +30 %font "GeneralUser.sf2" 0 30 amp=154 pan=0 +31 %font "GeneralUser.sf2" 0 31 amp=94 pan=0 +32 %font "GeneralUser.sf2" 0 32 amp=231 pan=0 +33 %font "GeneralUser.sf2" 0 33 amp=112 pan=0 +34 %font "GeneralUser.sf2" 0 34 amp=441 pan=0 +35 %font "GeneralUser.sf2" 0 35 amp=147 pan=0 +36 %font "GeneralUser.sf2" 0 36 amp=342 pan=0 +37 %font "GeneralUser.sf2" 0 37 amp=110 pan=0 +38 %font "GeneralUser.sf2" 0 38 amp=51 pan=0 +39 %font "GeneralUser.sf2" 0 39 amp=186 pan=0 +40 %font "GeneralUser.sf2" 0 40 amp=115 pan=0 +41 %font "GeneralUser.sf2" 0 41 amp=190 pan=0 +42 %font "GeneralUser.sf2" 0 42 amp=53 pan=0 +43 %font "GeneralUser.sf2" 0 43 amp=89 pan=0 +44 %font "GeneralUser.sf2" 0 44 amp=147 pan=0 +45 %font "GeneralUser.sf2" 0 45 amp=381 pan=0 +46 %font "GeneralUser.sf2" 0 46 amp=160 pan=0 +47 %font "GeneralUser.sf2" 0 47 amp=138 pan=0 +48 %font "GeneralUser.sf2" 0 48 amp=127 pan=0 +49 %font "GeneralUser.sf2" 0 49 amp=127 pan=0 +50 %font "GeneralUser.sf2" 0 50 amp=72 pan=0 +51 %font "GeneralUser.sf2" 0 51 amp=45 pan=0 +52 %font "GeneralUser.sf2" 0 52 amp=64 pan=0 +53 %font "GeneralUser.sf2" 0 53 amp=68 pan=0 +54 %font "GeneralUser.sf2" 0 54 amp=168 pan=0 +55 %font "GeneralUser.sf2" 0 55 amp=102 pan=0 +56 %font "GeneralUser.sf2" 0 56 amp=112 pan=0 +57 %font "GeneralUser.sf2" 0 57 amp=132 pan=0 +58 %font "GeneralUser.sf2" 0 58 amp=107 pan=0 +59 %font "GeneralUser.sf2" 0 59 amp=63 pan=0 +60 %font "GeneralUser.sf2" 0 60 amp=120 pan=0 +61 %font "GeneralUser.sf2" 0 61 amp=168 pan=0 +62 %font "GeneralUser.sf2" 0 62 amp=45 pan=0 +63 %font "GeneralUser.sf2" 0 63 amp=47 pan=0 +64 %font "GeneralUser.sf2" 0 64 amp=90 pan=0 +65 %font "GeneralUser.sf2" 0 65 amp=117 pan=0 +66 %font "GeneralUser.sf2" 0 66 amp=105 pan=0 +67 %font "GeneralUser.sf2" 0 67 amp=73 pan=0 +68 %font "GeneralUser.sf2" 0 68 amp=110 pan=0 +69 %font "GeneralUser.sf2" 0 69 amp=134 pan=0 +70 %font "GeneralUser.sf2" 0 70 amp=92 pan=0 +71 %font "GeneralUser.sf2" 0 71 amp=94 pan=0 +72 %font "GeneralUser.sf2" 0 72 amp=58 pan=0 +73 %font "GeneralUser.sf2" 0 73 amp=144 pan=0 +74 %font "GeneralUser.sf2" 0 74 amp=129 pan=0 +75 %font "GeneralUser.sf2" 0 75 amp=79 pan=0 +76 %font "GeneralUser.sf2" 0 76 amp=87 pan=0 +77 %font "GeneralUser.sf2" 0 77 amp=114 pan=0 +78 %font "GeneralUser.sf2" 0 78 amp=316 pan=0 +79 %font "GeneralUser.sf2" 0 79 amp=164 pan=0 +80 %font "GeneralUser.sf2" 0 80 amp=22 pan=0 +81 %font "GeneralUser.sf2" 0 81 amp=41 pan=0 +82 %font "GeneralUser.sf2" 0 82 amp=55 pan=0 +83 %font "GeneralUser.sf2" 0 83 amp=79 pan=0 +84 %font "GeneralUser.sf2" 0 84 amp=140 pan=0 +85 %font "GeneralUser.sf2" 0 85 amp=79 pan=0 +86 %font "GeneralUser.sf2" 0 86 amp=84 pan=0 +87 %font "GeneralUser.sf2" 0 87 amp=105 pan=0 +88 %font "GeneralUser.sf2" 0 88 amp=165 pan=0 +89 %font "GeneralUser.sf2" 0 89 amp=203 pan=0 +90 %font "GeneralUser.sf2" 0 90 amp=80 pan=0 +91 %font "GeneralUser.sf2" 0 91 amp=88 pan=0 +92 %font "GeneralUser.sf2" 0 92 amp=168 pan=0 +93 %font "GeneralUser.sf2" 0 93 amp=123 pan=0 +94 %font "GeneralUser.sf2" 0 94 amp=69 pan=0 +95 %font "GeneralUser.sf2" 0 95 amp=89 pan=0 +96 %font "GeneralUser.sf2" 0 96 amp=77 pan=0 +97 %font "GeneralUser.sf2" 0 97 amp=78 pan=0 +98 %font "GeneralUser.sf2" 0 98 amp=74 pan=0 +99 %font "GeneralUser.sf2" 0 99 amp=115 pan=0 +100 %font "GeneralUser.sf2" 0 100 amp=109 pan=0 +101 %font "GeneralUser.sf2" 0 101 amp=67 pan=0 +102 %font "GeneralUser.sf2" 0 102 amp=71 pan=0 +103 %font "GeneralUser.sf2" 0 103 amp=99 pan=0 +104 %font "GeneralUser.sf2" 0 104 amp=126 pan=0 +105 %font "GeneralUser.sf2" 0 105 amp=118 pan=0 +106 %font "GeneralUser.sf2" 0 106 amp=185 pan=0 +107 %font "GeneralUser.sf2" 0 107 amp=203 pan=0 +108 %font "GeneralUser.sf2" 0 108 amp=62 pan=0 +109 %font "GeneralUser.sf2" 0 109 amp=72 pan=0 +110 %font "GeneralUser.sf2" 0 110 amp=143 pan=0 +111 %font "GeneralUser.sf2" 0 111 amp=93 pan=0 +112 %font "GeneralUser.sf2" 0 112 amp=126 pan=0 +113 %font "GeneralUser.sf2" 0 113 amp=154 pan=0 +114 %font "GeneralUser.sf2" 0 114 amp=91 pan=0 +115 %font "GeneralUser.sf2" 0 115 amp=119 pan=0 +116 %font "GeneralUser.sf2" 0 116 amp=99 pan=0 +117 %font "GeneralUser.sf2" 0 117 amp=132 pan=0 +118 %font "GeneralUser.sf2" 0 118 amp=125 pan=0 +119 %font "GeneralUser.sf2" 0 119 amp=82 pan=0 +120 %font "GeneralUser.sf2" 0 120 amp=68 pan=0 +121 %font "GeneralUser.sf2" 0 121 amp=77 pan=0 +122 %font "GeneralUser.sf2" 0 122 amp=77 pan=0 +123 %font "GeneralUser.sf2" 0 123 amp=74 pan=0 +124 %font "GeneralUser.sf2" 0 124 amp=57 pan=0 +125 %font "GeneralUser.sf2" 0 125 amp=211 pan=0 +126 %font "GeneralUser.sf2" 0 126 amp=40 pan=0 +127 %font "GeneralUser.sf2" 0 127 amp=149 pan=0 + +bank 1 +38 %font "GeneralUser.sf2" 1 38 amp=103 pan=0 +44 %font "GeneralUser.sf2" 1 44 amp=142 pan=0 +48 %font "GeneralUser.sf2" 1 48 amp=119 pan=0 +49 %font "GeneralUser.sf2" 1 49 amp=108 pan=0 +57 %font "GeneralUser.sf2" 1 57 amp=89 pan=0 +60 %font "GeneralUser.sf2" 1 60 amp=196 pan=0 +80 %font "GeneralUser.sf2" 1 80 amp=31 pan=0 +81 %font "GeneralUser.sf2" 1 81 amp=45 pan=0 +98 %font "GeneralUser.sf2" 1 98 amp=89 pan=0 +120 %font "GeneralUser.sf2" 1 120 amp=28 pan=0 +121 %font "GeneralUser.sf2" 1 121 amp=104 pan=0 +122 %font "GeneralUser.sf2" 1 122 amp=59 pan=0 +123 %font "GeneralUser.sf2" 1 123 amp=50 pan=0 +124 %font "GeneralUser.sf2" 1 124 amp=101 pan=0 +125 %font "GeneralUser.sf2" 1 125 amp=203 pan=0 +126 %font "GeneralUser.sf2" 1 126 amp=207 pan=0 +127 %font "GeneralUser.sf2" 1 127 amp=65 pan=0 + +bank 2 +44 %font "GeneralUser.sf2" 2 44 amp=361 pan=0 +48 %font "GeneralUser.sf2" 2 48 amp=118 pan=0 +49 %font "GeneralUser.sf2" 2 49 amp=195 pan=0 +102 %font "GeneralUser.sf2" 2 102 amp=90 pan=0 +120 %font "GeneralUser.sf2" 2 120 amp=52 pan=0 +122 %font "GeneralUser.sf2" 2 122 amp=85 pan=0 +123 %font "GeneralUser.sf2" 2 123 amp=276 pan=0 +124 %font "GeneralUser.sf2" 2 124 amp=94 pan=0 +125 %font "GeneralUser.sf2" 2 125 amp=38 pan=0 +126 %font "GeneralUser.sf2" 2 126 amp=38 pan=0 +127 %font "GeneralUser.sf2" 2 127 amp=128 pan=0 + +bank 3 +122 %font "GeneralUser.sf2" 3 122 amp=72 pan=0 +123 %font "GeneralUser.sf2" 3 123 amp=45 pan=0 +124 %font "GeneralUser.sf2" 3 124 amp=128 pan=0 +125 %font "GeneralUser.sf2" 3 125 amp=61 pan=0 +126 %font "GeneralUser.sf2" 3 126 amp=83 pan=0 +127 %font "GeneralUser.sf2" 3 127 amp=77 pan=0 + +bank 4 +122 %font "GeneralUser.sf2" 4 122 amp=299 pan=0 +123 %font "GeneralUser.sf2" 4 123 amp=62 pan=0 +125 %font "GeneralUser.sf2" 4 125 amp=73 pan=0 +126 %font "GeneralUser.sf2" 4 126 amp=60 pan=0 + +bank 5 +122 %font "GeneralUser.sf2" 5 122 amp=81 pan=0 +124 %font "GeneralUser.sf2" 5 124 amp=98 pan=0 +125 %font "GeneralUser.sf2" 5 125 amp=58 pan=0 +126 %font "GeneralUser.sf2" 5 126 amp=141 pan=0 + +bank 6 +125 %font "GeneralUser.sf2" 6 125 amp=91 pan=0 + +bank 7 +125 %font "GeneralUser.sf2" 7 125 amp=41 pan=0 + +bank 8 +0 %font "GeneralUser.sf2" 8 0 amp=52 pan=0 +1 %font "GeneralUser.sf2" 8 1 amp=84 pan=0 +2 %font "GeneralUser.sf2" 8 2 amp=51 pan=0 +3 %font "GeneralUser.sf2" 8 3 amp=110 pan=0 +4 %font "GeneralUser.sf2" 8 4 amp=82 pan=0 +5 %font "GeneralUser.sf2" 8 5 amp=52 pan=0 +6 %font "GeneralUser.sf2" 8 6 amp=47 pan=0 +11 %font "GeneralUser.sf2" 8 11 amp=53 pan=0 +12 %font "GeneralUser.sf2" 8 12 amp=143 pan=0 +14 %font "GeneralUser.sf2" 8 14 amp=35 pan=0 +16 %font "GeneralUser.sf2" 8 16 amp=64 pan=0 +17 %font "GeneralUser.sf2" 8 17 amp=100 pan=0 +19 %font "GeneralUser.sf2" 8 19 amp=153 pan=0 +21 %font "GeneralUser.sf2" 8 21 amp=28 pan=0 +24 %font "GeneralUser.sf2" 8 24 amp=117 pan=0 +25 %font "GeneralUser.sf2" 8 25 amp=82 pan=0 +26 %font "GeneralUser.sf2" 8 26 amp=87 pan=0 +27 %font "GeneralUser.sf2" 8 27 amp=57 pan=0 +28 %font "GeneralUser.sf2" 8 28 amp=47 pan=0 +30 %font "GeneralUser.sf2" 8 30 amp=71 pan=0 +31 %font "GeneralUser.sf2" 8 31 amp=100 pan=0 +38 %font "GeneralUser.sf2" 8 38 amp=38 pan=0 +39 %font "GeneralUser.sf2" 8 39 amp=231 pan=0 +40 %font "GeneralUser.sf2" 8 40 amp=112 pan=0 +48 %font "GeneralUser.sf2" 8 48 amp=86 pan=0 +50 %font "GeneralUser.sf2" 8 50 amp=63 pan=0 +61 %font "GeneralUser.sf2" 8 61 amp=93 pan=0 +62 %font "GeneralUser.sf2" 8 62 amp=49 pan=0 +63 %font "GeneralUser.sf2" 8 63 amp=74 pan=0 +80 %font "GeneralUser.sf2" 8 80 amp=86 pan=0 +81 %font "GeneralUser.sf2" 8 81 amp=62 pan=0 +107 %font "GeneralUser.sf2" 8 107 amp=118 pan=0 +115 %font "GeneralUser.sf2" 8 115 amp=149 pan=0 +116 %font "GeneralUser.sf2" 8 116 amp=76 pan=0 +117 %font "GeneralUser.sf2" 8 117 amp=141 pan=0 +118 %font "GeneralUser.sf2" 8 118 amp=167 pan=0 +125 %font "GeneralUser.sf2" 8 125 amp=80 pan=0 + +bank 9 +14 %font "GeneralUser.sf2" 9 14 amp=53 pan=0 +125 %font "GeneralUser.sf2" 9 125 amp=19 pan=0 + +bank 11 +1 %font "GeneralUser.sf2" 11 1 amp=362 pan=0 +4 %font "GeneralUser.sf2" 11 4 amp=143 pan=0 +5 %font "GeneralUser.sf2" 11 5 amp=494 pan=0 +8 %font "GeneralUser.sf2" 11 8 amp=355 pan=0 +14 %font "GeneralUser.sf2" 11 14 amp=376 pan=0 +38 %font "GeneralUser.sf2" 11 38 amp=136 pan=0 +39 %font "GeneralUser.sf2" 11 39 amp=33 pan=0 +50 %font "GeneralUser.sf2" 11 50 amp=73 pan=0 +51 %font "GeneralUser.sf2" 11 51 amp=180 pan=0 +61 %font "GeneralUser.sf2" 11 61 amp=51 pan=0 +78 %font "GeneralUser.sf2" 11 78 amp=40 pan=0 +81 %font "GeneralUser.sf2" 11 81 amp=194 pan=0 +87 %font "GeneralUser.sf2" 11 87 amp=92 pan=0 +88 %font "GeneralUser.sf2" 11 88 amp=317 pan=0 +89 %font "GeneralUser.sf2" 11 89 amp=262 pan=0 +96 %font "GeneralUser.sf2" 11 96 amp=40 pan=0 +98 %font "GeneralUser.sf2" 11 98 amp=93 pan=0 +100 %font "GeneralUser.sf2" 11 100 amp=188 pan=0 +119 %font "GeneralUser.sf2" 11 119 amp=674 pan=0 +121 %font "GeneralUser.sf2" 11 121 amp=71 pan=0 +127 %font "GeneralUser.sf2" 11 127 amp=37 pan=0 + +bank 12 +10 %font "GeneralUser.sf2" 12 10 amp=55 pan=0 +27 %font "GeneralUser.sf2" 12 27 amp=69 pan=0 +38 %font "GeneralUser.sf2" 12 38 amp=34 pan=0 +48 %font "GeneralUser.sf2" 12 48 amp=156 pan=0 +49 %font "GeneralUser.sf2" 12 49 amp=193 pan=0 +80 %font "GeneralUser.sf2" 12 80 amp=13 pan=0 +81 %font "GeneralUser.sf2" 12 81 amp=21 pan=0 +88 %font "GeneralUser.sf2" 12 88 amp=108 pan=0 +89 %font "GeneralUser.sf2" 12 89 amp=64 pan=0 +119 %font "GeneralUser.sf2" 12 119 amp=422 pan=0 +122 %font "GeneralUser.sf2" 12 122 amp=68 pan=0 +127 %font "GeneralUser.sf2" 12 127 amp=185 pan=0 + +bank 13 +88 %font "GeneralUser.sf2" 13 88 amp=128 pan=0 + +bank 16 +0 %font "GeneralUser.sf2" 16 0 amp=118 pan=0 +4 %font "GeneralUser.sf2" 16 4 amp=78 pan=0 +5 %font "GeneralUser.sf2" 16 5 amp=107 pan=0 +6 %font "GeneralUser.sf2" 16 6 amp=50 pan=0 +25 %font "GeneralUser.sf2" 16 25 amp=61 pan=0 + +bank 126 +0 %font "GeneralUser.sf2" 0 1 amp=112 pan=0 +1 %font "GeneralUser.sf2" 0 1 amp=112 pan=0 +2 %font "GeneralUser.sf2" 0 1 amp=112 pan=0 +3 %font "GeneralUser.sf2" 0 3 amp=134 pan=0 +4 %font "GeneralUser.sf2" 0 0 amp=72 pan=0 +5 %font "GeneralUser.sf2" 0 1 amp=111 pan=0 +6 %font "GeneralUser.sf2" 0 1 amp=112 pan=0 +7 %font "GeneralUser.sf2" 0 4 amp=91 pan=0 +8 %font "GeneralUser.sf2" 0 4 amp=80 pan=0 +9 %font "GeneralUser.sf2" 0 5 amp=73 pan=0 +10 %font "GeneralUser.sf2" 0 25 amp=75 pan=0 +11 %font "GeneralUser.sf2" 0 25 amp=76 pan=0 +12 %font "GeneralUser.sf2" 0 26 amp=92 pan=0 +13 %font "GeneralUser.sf2" 0 26 amp=104 pan=0 +14 %font "GeneralUser.sf2" 0 28 amp=222 pan=0 +15 %font "GeneralUser.sf2" 0 36 amp=152 pan=0 +16 %font "GeneralUser.sf2" 0 36 amp=152 pan=0 +17 %font "GeneralUser.sf2" 0 36 amp=152 pan=0 +18 %font "GeneralUser.sf2" 0 36 amp=152 pan=0 +19 %font "GeneralUser.sf2" 0 37 amp=48 pan=0 +20 %font "GeneralUser.sf2" 0 37 amp=48 pan=0 +21 %font "GeneralUser.sf2" 0 37 amp=48 pan=0 +22 %font "GeneralUser.sf2" 0 37 amp=48 pan=0 +23 %font "GeneralUser.sf2" 0 33 amp=119 pan=0 +24 %font "GeneralUser.sf2" 0 33 amp=120 pan=0 +25 %font "GeneralUser.sf2" 0 34 amp=408 pan=0 +26 %font "GeneralUser.sf2" 0 34 amp=412 pan=0 +27 %font "GeneralUser.sf2" 0 35 amp=160 pan=0 +28 %font "GeneralUser.sf2" 0 32 amp=361 pan=0 +29 %font "GeneralUser.sf2" 0 52 amp=89 pan=0 +30 %font "GeneralUser.sf2" 0 52 amp=89 pan=0 +31 %font "GeneralUser.sf2" 0 52 amp=90 pan=0 +32 %font "GeneralUser.sf2" 0 52 amp=89 pan=0 +33 %font "GeneralUser.sf2" 0 49 amp=116 pan=0 +34 %font "GeneralUser.sf2" 0 48 amp=89 pan=0 +35 %font "GeneralUser.sf2" 0 50 amp=100 pan=0 +36 %font "GeneralUser.sf2" 0 50 amp=76 pan=0 +37 %font "GeneralUser.sf2" 0 16 amp=54 pan=0 +38 %font "GeneralUser.sf2" 0 16 amp=75 pan=0 +39 %font "GeneralUser.sf2" 0 16 amp=75 pan=0 +40 %font "GeneralUser.sf2" 0 17 amp=167 pan=0 +41 %font "GeneralUser.sf2" 0 16 amp=75 pan=0 +42 %font "GeneralUser.sf2" 0 16 amp=75 pan=0 +43 %font "GeneralUser.sf2" 0 17 amp=167 pan=0 +44 %font "GeneralUser.sf2" 0 17 amp=167 pan=0 +45 %font "GeneralUser.sf2" 0 17 amp=167 pan=0 +46 %font "GeneralUser.sf2" 0 56 amp=104 pan=0 +47 %font "GeneralUser.sf2" 0 56 amp=104 pan=0 +48 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +49 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +50 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +51 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +52 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +53 %font "GeneralUser.sf2" 0 57 amp=94 pan=0 +54 %font "GeneralUser.sf2" 0 65 amp=116 pan=0 +55 %font "GeneralUser.sf2" 0 66 amp=86 pan=0 +56 %font "GeneralUser.sf2" 0 67 amp=144 pan=0 +57 %font "GeneralUser.sf2" 0 65 amp=116 pan=0 +58 %font "GeneralUser.sf2" 0 61 amp=89 pan=0 +59 %font "GeneralUser.sf2" 0 61 amp=88 pan=0 +60 %font "GeneralUser.sf2" 0 61 amp=105 pan=0 +61 %font "GeneralUser.sf2" 0 61 amp=105 pan=0 +62 %font "GeneralUser.sf2" 0 61 amp=88 pan=0 +63 %font "GeneralUser.sf2" 0 55 amp=112 pan=0 + +bank 127 +0 %font "GeneralUser.sf2" 127 0 amp=80 pan=0 +1 %font "GeneralUser.sf2" 127 1 amp=143 pan=0 +8 %font "GeneralUser.sf2" 127 8 amp=204 pan=0 +9 %font "GeneralUser.sf2" 0 17 amp=101 pan=0 +10 %font "GeneralUser.sf2" 0 18 amp=106 pan=0 +11 %font "GeneralUser.sf2" 0 18 amp=79 pan=0 +12 %font "GeneralUser.sf2" 0 19 amp=87 pan=0 +13 %font "GeneralUser.sf2" 0 19 amp=148 pan=0 +14 %font "GeneralUser.sf2" 0 20 amp=35 pan=0 +15 %font "GeneralUser.sf2" 0 21 amp=53 pan=0 +16 %font "GeneralUser.sf2" 127 16 amp=96 pan=0 +17 %font "GeneralUser.sf2" 0 6 amp=38 pan=0 +18 %font "GeneralUser.sf2" 0 6 amp=43 pan=0 +19 %font "GeneralUser.sf2" 0 7 amp=63 pan=0 +20 %font "GeneralUser.sf2" 0 7 amp=111 pan=0 +21 %font "GeneralUser.sf2" 0 7 amp=72 pan=0 +22 %font "GeneralUser.sf2" 0 8 amp=32 pan=0 +23 %font "GeneralUser.sf2" 0 8 amp=32 pan=0 +24 %font "GeneralUser.sf2" 127 24 amp=332 pan=0 +25 %font "GeneralUser.sf2" 127 25 amp=406 pan=0 +26 %font "GeneralUser.sf2" 127 26 amp=350 pan=0 +27 %font "GeneralUser.sf2" 0 63 amp=89 pan=0 +28 %font "GeneralUser.sf2" 0 38 amp=55 pan=0 +29 %font "GeneralUser.sf2" 0 39 amp=50 pan=0 +30 %font "GeneralUser.sf2" 0 38 amp=55 pan=0 +31 %font "GeneralUser.sf2" 0 39 amp=69 pan=0 +32 %font "GeneralUser.sf2" 127 32 amp=205 pan=0 +33 %font "GeneralUser.sf2" 0 89 amp=48 pan=0 +34 %font "GeneralUser.sf2" 0 52 amp=52 pan=0 +35 %font "GeneralUser.sf2" 0 113 amp=165 pan=0 +36 %font "GeneralUser.sf2" 0 97 amp=78 pan=0 +37 %font "GeneralUser.sf2" 0 96 amp=56 pan=0 +38 %font "GeneralUser.sf2" 0 91 amp=47 pan=0 +39 %font "GeneralUser.sf2" 0 85 amp=16 pan=0 +40 %font "GeneralUser.sf2" 127 40 amp=356 pan=0 +41 %font "GeneralUser.sf2" 0 101 amp=107 pan=0 +42 %font "GeneralUser.sf2" 0 68 amp=40 pan=0 +43 %font "GeneralUser.sf2" 0 95 amp=119 pan=0 +44 %font "GeneralUser.sf2" 0 86 amp=49 pan=0 +45 %font "GeneralUser.sf2" 0 103 amp=104 pan=0 +46 %font "GeneralUser.sf2" 0 88 amp=33 pan=0 +47 %font "GeneralUser.sf2" 0 80 amp=19 pan=0 +48 %font "GeneralUser.sf2" 127 48 amp=189 pan=0 +49 %font "GeneralUser.sf2" 0 49 amp=111 pan=0 +51 %font "GeneralUser.sf2" 0 45 amp=76 pan=0 +52 %font "GeneralUser.sf2" 0 40 amp=86 pan=0 +53 %font "GeneralUser.sf2" 0 40 amp=76 pan=0 +54 %font "GeneralUser.sf2" 0 42 amp=64 pan=0 +55 %font "GeneralUser.sf2" 0 42 amp=64 pan=0 +56 %font "GeneralUser.sf2" 127 56 amp=220 pan=0 +57 %font "GeneralUser.sf2" 0 46 amp=36 pan=0 +58 %font "GeneralUser.sf2" 0 46 amp=48 pan=0 +59 %font "GeneralUser.sf2" 0 24 amp=56 pan=0 +60 %font "GeneralUser.sf2" 0 24 amp=43 pan=0 +61 %font "GeneralUser.sf2" 0 26 amp=88 pan=0 +62 %font "GeneralUser.sf2" 0 27 amp=198 pan=0 +63 %font "GeneralUser.sf2" 0 104 amp=77 pan=0 +64 %font "GeneralUser.sf2" 0 32 amp=158 pan=0 +65 %font "GeneralUser.sf2" 0 33 amp=67 pan=0 +66 %font "GeneralUser.sf2" 0 34 amp=201 pan=0 +67 %font "GeneralUser.sf2" 0 39 amp=99 pan=0 +68 %font "GeneralUser.sf2" 0 36 amp=117 pan=0 +69 %font "GeneralUser.sf2" 0 37 amp=35 pan=0 +70 %font "GeneralUser.sf2" 0 35 amp=88 pan=0 +71 %font "GeneralUser.sf2" 0 35 amp=64 pan=0 +72 %font "GeneralUser.sf2" 0 73 amp=64 pan=0 +73 %font "GeneralUser.sf2" 0 73 amp=110 pan=0 +74 %font "GeneralUser.sf2" 0 72 amp=62 pan=0 +75 %font "GeneralUser.sf2" 0 72 amp=40 pan=0 +76 %font "GeneralUser.sf2" 0 74 amp=71 pan=0 +77 %font "GeneralUser.sf2" 0 75 amp=62 pan=0 +78 %font "GeneralUser.sf2" 0 64 amp=53 pan=0 +79 %font "GeneralUser.sf2" 0 65 amp=95 pan=0 +80 %font "GeneralUser.sf2" 0 66 amp=111 pan=0 +81 %font "GeneralUser.sf2" 0 67 amp=111 pan=0 +82 %font "GeneralUser.sf2" 0 71 amp=39 pan=0 +83 %font "GeneralUser.sf2" 0 71 amp=34 pan=0 +84 %font "GeneralUser.sf2" 0 68 amp=66 pan=0 +85 %font "GeneralUser.sf2" 0 69 amp=130 pan=0 +86 %font "GeneralUser.sf2" 0 70 amp=49 pan=0 +87 %font "GeneralUser.sf2" 0 22 amp=80 pan=0 +88 %font "GeneralUser.sf2" 0 56 amp=156 pan=0 +89 %font "GeneralUser.sf2" 0 56 amp=136 pan=0 +90 %font "GeneralUser.sf2" 0 57 amp=216 pan=0 +91 %font "GeneralUser.sf2" 0 57 amp=125 pan=0 +92 %font "GeneralUser.sf2" 0 60 amp=146 pan=0 +93 %font "GeneralUser.sf2" 0 60 amp=203 pan=0 +94 %font "GeneralUser.sf2" 0 58 amp=111 pan=0 +95 %font "GeneralUser.sf2" 0 61 amp=100 pan=0 +96 %font "GeneralUser.sf2" 0 61 amp=89 pan=0 +97 %font "GeneralUser.sf2" 0 11 amp=18 pan=0 +98 %font "GeneralUser.sf2" 0 11 amp=19 pan=0 +99 %font "GeneralUser.sf2" 0 12 amp=43 pan=0 +100 %font "GeneralUser.sf2" 0 88 amp=30 pan=0 +101 %font "GeneralUser.sf2" 0 9 amp=76 pan=0 +102 %font "GeneralUser.sf2" 0 14 amp=57 pan=0 +103 %font "GeneralUser.sf2" 0 13 amp=103 pan=0 +104 %font "GeneralUser.sf2" 0 12 amp=61 pan=0 +105 %font "GeneralUser.sf2" 0 107 amp=100 pan=0 +106 %font "GeneralUser.sf2" 0 111 amp=63 pan=0 +107 %font "GeneralUser.sf2" 0 77 amp=171 pan=0 +108 %font "GeneralUser.sf2" 0 78 amp=164 pan=0 +109 %font "GeneralUser.sf2" 0 78 amp=83 pan=0 +110 %font "GeneralUser.sf2" 0 76 amp=68 pan=0 +111 %font "GeneralUser.sf2" 0 76 amp=75 pan=0 +112 %font "GeneralUser.sf2" 0 47 amp=40 pan=0 +113 %font "GeneralUser.sf2" 0 117 amp=66 pan=0 +114 %font "GeneralUser.sf2" 0 118 amp=39 pan=0 +115 %font "GeneralUser.sf2" 0 118 amp=41 pan=0 +116 %font "GeneralUser.sf2" 0 118 amp=67 pan=0 +117 %font "GeneralUser.sf2" 0 116 amp=84 pan=0 +118 %font "GeneralUser.sf2" 0 116 amp=30 pan=0 +119 %font "GeneralUser.sf2" 128 0 49 amp=72 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal + +drumset 0 +0 %font "GeneralUser.sf2" 128 0 36 amp=231 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +1 %font "GeneralUser.sf2" 128 0 35 amp=172 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +2 %font "GeneralUser.sf2" 128 1 36 amp=196 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +3 %font "GeneralUser.sf2" 128 1 35 amp=149 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +4 %font "GeneralUser.sf2" 128 0 36 amp=112 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +5 %font "GeneralUser.sf2" 128 0 35 amp=134 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +6 %font "GeneralUser.sf2" 128 32 36 amp=109 pan=0 # Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Standard Kick 1 Standard Kick 1 Standard Kick 1 +7 %font "GeneralUser.sf2" 128 32 35 amp=169 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +8 %font "GeneralUser.sf2" 128 8 36 amp=145 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +9 %font "GeneralUser.sf2" 128 8 35 amp=91 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +10 %font "GeneralUser.sf2" 128 16 36 amp=57 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +11 %font "GeneralUser.sf2" 128 16 35 amp=87 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +12 %font "GeneralUser.sf2" 128 24 36 amp=94 pan=0 # TR-909 Kick Electric Tom +13 %font "GeneralUser.sf2" 128 24 35 amp=294 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +14 %font "GeneralUser.sf2" 128 25 36 amp=88 pan=0 # TR-909 Kick +15 %font "GeneralUser.sf2" 128 25 35 amp=111 pan=0 # Sine-93.75Hz +16 %font "GeneralUser.sf2" 128 26 35 amp=147 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +27 %font "GeneralUser.sf2" 128 0 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 0 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 0 29 amp=44 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 0 30 amp=50 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 0 31 amp=154 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 0 32 amp=315 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 0 33 amp=77 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 0 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 0 35 amp=161 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 0 36 amp=158 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +37 %font "GeneralUser.sf2" 128 0 37 amp=72 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 0 38 amp=129 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +39 %font "GeneralUser.sf2" 128 0 39 amp=54 pan=-16 # Hand Clap +40 %font "GeneralUser.sf2" 128 0 40 amp=378 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +41 %font "GeneralUser.sf2" 128 0 41 amp=137 pan=-47 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +42 %font "GeneralUser.sf2" 128 0 42 amp=36 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 0 43 amp=130 pan=-28 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +44 %font "GeneralUser.sf2" 128 0 44 amp=23 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 0 45 amp=119 pan=-9 # Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 +46 %font "GeneralUser.sf2" 128 0 46 amp=59 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 0 47 amp=141 pan=9 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +48 %font "GeneralUser.sf2" 128 0 48 amp=84 pan=28 # Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 +49 %font "GeneralUser.sf2" 128 0 49 amp=166 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 0 50 amp=52 pan=47 # Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 +51 %font "GeneralUser.sf2" 128 0 51 amp=62 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 0 52 amp=70 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 0 53 amp=62 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 0 54 amp=66 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 0 55 amp=61 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 0 56 amp=102 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 0 57 amp=136 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 0 58 amp=33 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 0 59 amp=64 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 0 60 amp=17 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 0 61 amp=77 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 0 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 0 63 amp=68 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 0 64 amp=49 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 0 65 amp=127 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 0 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 0 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 0 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 0 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 0 70 amp=44 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 0 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 0 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 0 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 0 74 amp=46 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 0 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 0 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 0 77 amp=101 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 0 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 0 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 0 80 amp=45 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 0 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 0 82 amp=155 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 0 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 0 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 0 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 0 86 amp=64 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 0 87 amp=104 pan=-31 # Surdo Open +97 %font "GeneralUser.sf2" 128 0 38 amp=128 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +98 %font "GeneralUser.sf2" 128 0 40 amp=204 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +99 %font "GeneralUser.sf2" 128 1 38 amp=174 pan=0 # Standard 2 Snare Standard 2 Snare Standard 2 Snare Standard 2 Snare +100 %font "GeneralUser.sf2" 128 1 40 amp=211 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +101 %font "GeneralUser.sf2" 128 0 40 amp=345 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +102 %font "GeneralUser.sf2" 128 0 38 amp=129 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +103 %font "GeneralUser.sf2" 128 0 40 amp=250 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +104 %font "GeneralUser.sf2" 128 0 38 amp=157 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +105 %font "GeneralUser.sf2" 128 32 38 amp=80 pan=0 # Jazz Snare Soft 1 Jazz Snare Soft 1 Jazz Snare Soft 2 Jazz Snare Hard Jazz Snare Hard +106 %font "GeneralUser.sf2" 128 32 40 amp=179 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +107 %font "GeneralUser.sf2" 128 8 38 amp=117 pan=0 # Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 +108 %font "GeneralUser.sf2" 128 8 40 amp=144 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +109 %font "GeneralUser.sf2" 128 16 38 amp=50 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +110 %font "GeneralUser.sf2" 128 16 40 amp=58 pan=0 # Power Snare 2 Power Snare 2 Power Snare 2 Power Snare 2 +111 %font "GeneralUser.sf2" 128 24 40 amp=64 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +112 %font "GeneralUser.sf2" 128 26 38 amp=87 pan=0 # Dance Snare +113 %font "GeneralUser.sf2" 128 26 40 amp=75 pan=0 # TR-909 Snare 2 +114 %font "GeneralUser.sf2" 128 26 38 amp=93 pan=0 # Dance Snare +115 %font "GeneralUser.sf2" 128 24 40 amp=43 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +116 %font "GeneralUser.sf2" 128 24 38 amp=116 pan=0 # Electric Tom White Noise +117 %font "GeneralUser.sf2" 128 24 38 amp=190 pan=0 # Electric Tom White Noise +118 %font "GeneralUser.sf2" 128 25 38 amp=83 pan=0 # TR-909 Snare 1 +119 %font "GeneralUser.sf2" 128 25 38 amp=72 pan=0 # TR-909 Snare 1 +120 %font "GeneralUser.sf2" 128 25 40 amp=53 pan=0 # TR-909 Snare 2 +121 %font "GeneralUser.sf2" 128 25 38 amp=58 pan=0 # TR-909 Snare 1 +122 %font "GeneralUser.sf2" 128 25 40 amp=77 pan=0 # TR-909 Snare 2 +123 %font "GeneralUser.sf2" 128 25 38 amp=93 pan=0 # TR-909 Snare 1 +124 %font "GeneralUser.sf2" 128 25 38 amp=68 pan=0 # TR-909 Snare 1 +125 %font "GeneralUser.sf2" 128 26 38 amp=149 pan=0 # Dance Snare +126 %font "GeneralUser.sf2" 128 26 38 amp=101 pan=0 # Dance Snare +127 %font "GeneralUser.sf2" 128 26 38 amp=115 pan=0 # Dance Snare + +drumset 1 +27 %font "GeneralUser.sf2" 128 1 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 1 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 1 29 amp=44 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 1 30 amp=80 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 1 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 1 32 amp=432 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 1 33 amp=76 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 1 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 1 35 amp=161 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 1 36 amp=218 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +37 %font "GeneralUser.sf2" 128 1 37 amp=115 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 1 38 amp=286 pan=0 # Standard 2 Snare Standard 2 Snare Standard 2 Snare Standard 2 Snare +39 %font "GeneralUser.sf2" 128 1 39 amp=81 pan=-16 # Hand Clap +40 %font "GeneralUser.sf2" 128 1 40 amp=139 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +41 %font "GeneralUser.sf2" 128 1 41 amp=200 pan=-47 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +42 %font "GeneralUser.sf2" 128 1 42 amp=58 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 1 43 amp=130 pan=-28 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +44 %font "GeneralUser.sf2" 128 1 44 amp=33 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 1 45 amp=119 pan=-9 # Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 +46 %font "GeneralUser.sf2" 128 1 46 amp=31 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 1 47 amp=95 pan=9 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +48 %font "GeneralUser.sf2" 128 1 48 amp=124 pan=28 # Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 +49 %font "GeneralUser.sf2" 128 1 49 amp=176 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 1 50 amp=163 pan=47 # Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 +51 %font "GeneralUser.sf2" 128 1 51 amp=61 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 1 52 amp=55 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 1 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 1 54 amp=18 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 1 55 amp=63 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 1 56 amp=106 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 1 57 amp=114 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 1 58 amp=80 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 1 59 amp=65 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 1 60 amp=159 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 1 61 amp=124 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 1 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 1 63 amp=67 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 1 64 amp=49 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 1 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 1 66 amp=98 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 1 67 amp=64 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 1 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 1 69 amp=40 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 1 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 1 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 1 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 1 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 1 74 amp=45 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 1 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 1 76 amp=57 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 1 77 amp=62 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 1 78 amp=63 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 1 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 1 80 amp=45 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 1 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 1 82 amp=96 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 1 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 1 84 amp=110 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 1 85 amp=14 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 1 86 amp=61 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 1 87 amp=102 pan=-31 # Surdo Open + +drumset 8 +27 %font "GeneralUser.sf2" 128 8 27 amp=51 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 8 28 amp=167 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 8 29 amp=44 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 8 30 amp=50 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 8 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 8 32 amp=321 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 8 33 amp=77 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 8 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 8 35 amp=95 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +36 %font "GeneralUser.sf2" 128 8 36 amp=100 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +37 %font "GeneralUser.sf2" 128 8 37 amp=72 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 8 38 amp=194 pan=0 # Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 +39 %font "GeneralUser.sf2" 128 8 39 amp=81 pan=-16 # Hand Clap +40 %font "GeneralUser.sf2" 128 8 40 amp=197 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +41 %font "GeneralUser.sf2" 128 8 41 amp=115 pan=-47 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +42 %font "GeneralUser.sf2" 128 8 42 amp=35 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 8 43 amp=113 pan=-28 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +44 %font "GeneralUser.sf2" 128 8 44 amp=71 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 8 45 amp=221 pan=-9 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +46 %font "GeneralUser.sf2" 128 8 46 amp=42 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 8 47 amp=148 pan=9 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +48 %font "GeneralUser.sf2" 128 8 48 amp=152 pan=28 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +49 %font "GeneralUser.sf2" 128 8 49 amp=176 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 8 50 amp=249 pan=47 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +51 %font "GeneralUser.sf2" 128 8 51 amp=77 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 8 52 amp=71 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 8 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 8 54 amp=68 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 8 55 amp=63 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 8 56 amp=163 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 8 57 amp=121 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 8 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 8 59 amp=51 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 8 60 amp=98 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 8 61 amp=75 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 8 62 amp=48 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 8 63 amp=67 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 8 64 amp=49 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 8 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 8 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 8 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 8 68 amp=113 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 8 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 8 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 8 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 8 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 8 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 8 74 amp=43 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 8 75 amp=145 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 8 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 8 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 8 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 8 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 8 80 amp=65 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 8 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 8 82 amp=96 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 8 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 8 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 8 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 8 86 amp=95 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 8 87 amp=144 pan=-31 # Surdo Open + +drumset 9 +29 %font "GeneralUser.sf2" 128 25 29 amp=72 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=57 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=177 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=94 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=175 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=93 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=45 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=64 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=123 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=57 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=72 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=36 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=68 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=18 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=68 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=46 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=89 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=55 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=62 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=23 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=62 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=22 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=61 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=32 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=121 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=66 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=98 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=76 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=16 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=47 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=57 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=64 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=43 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=116 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=80 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=102 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=73 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=14 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=64 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=102 pan=-31 # Surdo Open + +drumset 10 +29 %font "GeneralUser.sf2" 128 25 29 amp=44 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=91 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=51 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=132 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=98 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=79 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=83 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=80 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=124 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=85 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=72 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=69 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=68 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=47 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=68 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=46 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=97 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=19 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=61 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=23 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=62 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=101 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=62 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=32 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=136 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=33 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=65 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=159 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=76 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=16 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=48 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=36 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=43 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=59 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=116 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=75 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=101 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=72 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=61 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=63 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=103 pan=-31 # Surdo Open + +drumset 11 +29 %font "GeneralUser.sf2" 128 25 29 amp=44 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=91 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=72 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=154 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=175 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=71 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=66 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=94 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=68 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=67 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=109 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=93 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=65 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=31 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=63 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=111 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=144 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=88 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=62 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=23 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=46 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=101 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=89 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=32 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=140 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=59 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=52 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=194 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=136 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=36 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=54 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=70 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=98 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=64 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=43 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=117 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=84 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=79 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=113 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=61 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=162 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=64 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=103 pan=-31 # Surdo Open + +drumset 16 +27 %font "GeneralUser.sf2" 128 16 27 amp=52 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 16 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 16 29 amp=44 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 16 30 amp=50 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 16 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 16 32 amp=431 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 16 33 amp=123 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 16 34 amp=68 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 16 35 amp=106 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +36 %font "GeneralUser.sf2" 128 16 36 amp=75 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +37 %font "GeneralUser.sf2" 128 16 37 amp=72 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 16 38 amp=71 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +39 %font "GeneralUser.sf2" 128 16 39 amp=129 pan=-16 # Hand Clap +40 %font "GeneralUser.sf2" 128 16 40 amp=86 pan=0 # Power Snare 2 Power Snare 2 Power Snare 2 Power Snare 2 +41 %font "GeneralUser.sf2" 128 16 41 amp=102 pan=-47 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +42 %font "GeneralUser.sf2" 128 16 42 amp=35 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 16 43 amp=99 pan=-28 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +44 %font "GeneralUser.sf2" 128 16 44 amp=23 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 16 45 amp=161 pan=-9 # Room Tom 1 Room Tom 1 Room Tom 1 Room Tom 1 +46 %font "GeneralUser.sf2" 128 16 46 amp=41 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 16 47 amp=109 pan=9 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +48 %font "GeneralUser.sf2" 128 16 48 amp=128 pan=28 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +49 %font "GeneralUser.sf2" 128 16 49 amp=176 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 16 50 amp=56 pan=47 # Room Tom 2 Room Tom 2 Room Tom 2 Room Tom 2 +51 %font "GeneralUser.sf2" 128 16 51 amp=77 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 16 52 amp=32 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 16 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 16 54 amp=18 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 16 55 amp=62 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 16 56 amp=106 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 16 57 amp=136 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 16 58 amp=80 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 16 59 amp=51 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 16 60 amp=98 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 16 61 amp=78 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 16 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 16 63 amp=108 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 16 64 amp=75 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 16 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 16 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 16 67 amp=64 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 16 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 16 69 amp=124 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 16 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 16 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 16 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 16 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 16 74 amp=44 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 16 75 amp=145 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 16 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 16 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 16 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 16 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 16 80 amp=46 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 16 81 amp=17 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 16 82 amp=96 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 16 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 16 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 16 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 16 86 amp=61 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 16 87 amp=144 pan=-31 # Surdo Open + +drumset 24 +27 %font "GeneralUser.sf2" 128 24 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 24 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 24 29 amp=52 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 24 30 amp=106 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 24 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 24 32 amp=431 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 24 33 amp=77 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 24 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 24 35 amp=213 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 24 36 amp=297 pan=0 # TR-909 Kick Electric Tom +37 %font "GeneralUser.sf2" 128 24 37 amp=90 pan=0 # Rim Shot +38 %font "GeneralUser.sf2" 128 24 38 amp=182 pan=0 # Electric Tom White Noise +39 %font "GeneralUser.sf2" 128 24 39 amp=67 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 24 40 amp=57 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +41 %font "GeneralUser.sf2" 128 24 41 amp=118 pan=-47 # Electric Tom +42 %font "GeneralUser.sf2" 128 24 42 amp=58 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 24 43 amp=82 pan=-28 # Electric Tom +44 %font "GeneralUser.sf2" 128 24 44 amp=32 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 24 45 amp=82 pan=-9 # Electric Tom +46 %font "GeneralUser.sf2" 128 24 46 amp=31 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 24 47 amp=84 pan=9 # Electric Tom +48 %font "GeneralUser.sf2" 128 24 48 amp=120 pan=28 # Electric Tom +49 %font "GeneralUser.sf2" 128 24 49 amp=176 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 24 50 amp=35 pan=47 # Electric Tom +51 %font "GeneralUser.sf2" 128 24 51 amp=62 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 24 52 amp=24 pan=-31 # Reverse Cymbal +53 %font "GeneralUser.sf2" 128 24 53 amp=47 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 24 54 amp=104 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 24 55 amp=63 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 24 56 amp=104 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 24 57 amp=121 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 24 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 24 59 amp=65 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 24 60 amp=157 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 24 61 amp=75 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 24 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 24 63 amp=68 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 24 64 amp=49 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 24 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 24 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 24 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 24 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 24 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 24 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 24 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 24 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 24 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 24 74 amp=43 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 24 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 24 76 amp=90 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 24 77 amp=63 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 24 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 24 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 24 80 amp=44 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 24 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 24 82 amp=155 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 24 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 24 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 24 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 24 86 amp=61 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 24 87 amp=103 pan=-31 # Surdo Open + +drumset 25 +27 %font "GeneralUser.sf2" 128 25 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 25 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 25 29 amp=43 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=57 pan=-16 # TR-909 Scratch Push +31 %font "GeneralUser.sf2" 128 25 31 amp=154 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 25 32 amp=320 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 25 33 amp=77 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 25 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 25 35 amp=70 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=97 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=275 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=62 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=67 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=72 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=67 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=68 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=69 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=86 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=101 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=38 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=64 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=72 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=76 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=135 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=111 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=55 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=107 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=55 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=32 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=140 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=81 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=50 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=28 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=89 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=33 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=76 pan=-31 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=69 pan=-23 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=124 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=70 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=116 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=111 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=90 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=62 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=72 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=62 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=143 pan=-31 # Surdo Open + +drumset 26 +21 %font "GeneralUser.sf2" 128 26 21 amp=100 pan=0 # WhiteNoiseWave FilterSnap +23 %font "GeneralUser.sf2" 128 26 23 amp=268 pan=0 # FilterSnap WhiteNoiseWave +24 %font "GeneralUser.sf2" 128 26 24 amp=76 pan=0 # WhiteNoiseWave FilterSnap +27 %font "GeneralUser.sf2" 128 26 27 amp=52 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 26 28 amp=167 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 26 29 amp=52 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 26 30 amp=66 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 26 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 26 32 amp=315 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 26 33 amp=77 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 26 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 26 35 amp=236 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 26 36 amp=94 pan=0 # TR-909 Kick TR-909 Kick +37 %font "GeneralUser.sf2" 128 26 37 amp=90 pan=0 # Rim Shot +38 %font "GeneralUser.sf2" 128 26 38 amp=93 pan=0 # Dance Snare +39 %font "GeneralUser.sf2" 128 26 39 amp=68 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 26 40 amp=142 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 26 41 amp=80 pan=-47 # Electric Tom +42 %font "GeneralUser.sf2" 128 26 42 amp=110 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 26 43 amp=81 pan=-28 # Electric Tom +44 %font "GeneralUser.sf2" 128 26 44 amp=35 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 26 45 amp=84 pan=-9 # Electric Tom +46 %font "GeneralUser.sf2" 128 26 46 amp=54 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 26 47 amp=83 pan=9 # Electric Tom +48 %font "GeneralUser.sf2" 128 26 48 amp=82 pan=28 # Electric Tom +49 %font "GeneralUser.sf2" 128 26 49 amp=116 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 26 50 amp=35 pan=47 # Electric Tom +51 %font "GeneralUser.sf2" 128 26 51 amp=113 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 26 52 amp=69 pan=-31 # Reverse Cymbal +53 %font "GeneralUser.sf2" 128 26 53 amp=62 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 26 54 amp=64 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 26 55 amp=61 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 26 56 amp=57 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 26 57 amp=136 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 26 58 amp=80 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 26 59 amp=51 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 26 60 amp=17 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 26 61 amp=75 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 26 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 26 63 amp=106 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 26 64 amp=73 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 26 65 amp=127 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 26 66 amp=98 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 26 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 26 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 26 69 amp=40 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 26 70 amp=44 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 26 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 26 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 26 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 26 74 amp=46 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 26 75 amp=145 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 26 76 amp=90 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 26 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 26 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 26 79 amp=72 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 26 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 26 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 26 82 amp=98 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 26 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 26 84 amp=39 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 26 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 26 86 amp=62 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 26 87 amp=101 pan=-31 # Surdo Open + +drumset 27 +29 %font "GeneralUser.sf2" 128 25 29 amp=43 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=57 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=100 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=88 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=293 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=87 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=66 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=81 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=105 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=110 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=135 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=64 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=98 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=34 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=57 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=145 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=97 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=32 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=113 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=54 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=33 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=89 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=96 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=141 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=58 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=49 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=129 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=89 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=33 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=81 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=102 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=122 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=126 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=116 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=64 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=62 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=72 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=163 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=46 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=98 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=41 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=63 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=144 pan=-31 # Surdo Open + +drumset 28 +29 %font "GeneralUser.sf2" 128 25 29 amp=44 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=91 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=100 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=85 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=293 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=84 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=66 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=110 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=126 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=76 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=64 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=64 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=62 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=47 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=58 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=86 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=75 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=67 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=113 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=54 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=44 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=107 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=90 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=59 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=140 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=58 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=50 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=28 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=89 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=52 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=76 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=72 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=98 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=64 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=113 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=40 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=78 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=116 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=98 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=51 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=72 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=157 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=46 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=61 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=64 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=104 pan=-31 # Surdo Open + +drumset 29 +29 %font "GeneralUser.sf2" 128 25 29 amp=71 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=91 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=90 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=90 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=124 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=235 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=66 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=141 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=105 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=67 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=105 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=31 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=105 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=34 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=44 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=51 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=144 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=91 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=142 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=50 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=44 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=107 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=61 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=32 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=119 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=49 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=17 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=75 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=16 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=76 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=56 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=127 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=63 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=70 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=46 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=101 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=80 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=73 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=39 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=96 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=103 pan=-31 # Surdo Open + +drumset 30 +29 %font "GeneralUser.sf2" 128 25 29 amp=44 pan=-16 # TR-909 Scratch Pull +30 %font "GeneralUser.sf2" 128 25 30 amp=91 pan=-16 # TR-909 Scratch Push +35 %font "GeneralUser.sf2" 128 25 35 amp=74 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=132 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 37 amp=304 pan=0 # TR-808 Click +38 %font "GeneralUser.sf2" 128 25 38 amp=136 pan=0 # TR-909 Snare 1 +39 %font "GeneralUser.sf2" 128 25 39 amp=45 pan=-16 # Synth Hand Clap +40 %font "GeneralUser.sf2" 128 25 40 amp=48 pan=0 # TR-909 Snare 2 +41 %font "GeneralUser.sf2" 128 25 41 amp=81 pan=-47 # Sine-750Hz +42 %font "GeneralUser.sf2" 128 25 42 amp=44 pan=31 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 43 amp=72 pan=-28 # Sine-750Hz +44 %font "GeneralUser.sf2" 128 25 44 amp=42 pan=31 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 45 amp=68 pan=-9 # Sine-750Hz +46 %font "GeneralUser.sf2" 128 25 46 amp=31 pan=31 # TR-909 Hi-Hat Open +47 %font "GeneralUser.sf2" 128 25 47 amp=43 pan=9 # Sine-750Hz +48 %font "GeneralUser.sf2" 128 25 48 amp=46 pan=28 # Sine-750Hz +49 %font "GeneralUser.sf2" 128 25 49 amp=90 pan=31 # TR-808 Hi-Hat Crash Cymbal +50 %font "GeneralUser.sf2" 128 25 50 amp=86 pan=47 # Sine-750Hz +51 %font "GeneralUser.sf2" 128 25 51 amp=142 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 25 52 amp=70 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 25 53 amp=46 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 25 54 amp=108 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 25 55 amp=62 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 25 56 amp=52 pan=31 # TR-808 Cowbell +57 %font "GeneralUser.sf2" 128 25 57 amp=122 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 25 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 25 59 amp=50 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 25 60 amp=99 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 25 61 amp=77 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 25 62 amp=15 pan=-39 # Sine-750Hz +63 %font "GeneralUser.sf2" 128 25 63 amp=75 pan=-39 # Sine-750Hz +64 %font "GeneralUser.sf2" 128 25 64 amp=53 pan=-31 # Sine-750Hz +65 %font "GeneralUser.sf2" 128 25 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 25 66 amp=65 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 25 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 25 68 amp=113 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 25 69 amp=123 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 25 70 amp=70 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 25 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 25 72 amp=40 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 25 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 25 74 amp=117 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 25 75 amp=82 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 25 76 amp=91 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 25 77 amp=101 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 25 78 amp=80 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 25 79 amp=73 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 25 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 25 81 amp=9 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 25 82 amp=61 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 25 83 amp=114 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 25 84 amp=60 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 25 85 amp=106 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 25 86 amp=65 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 25 87 amp=144 pan=-31 # Surdo Open + +drumset 32 +27 %font "GeneralUser.sf2" 128 32 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 32 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 32 29 amp=71 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 32 30 amp=80 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 32 31 amp=97 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 32 32 amp=433 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 32 33 amp=76 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 32 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 32 35 amp=169 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 32 36 amp=156 pan=0 # Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Standard Kick 1 Standard Kick 1 Standard Kick 1 +37 %font "GeneralUser.sf2" 128 32 37 amp=115 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 32 38 amp=95 pan=0 # Jazz Snare Soft 1 Jazz Snare Soft 1 Jazz Snare Soft 2 Jazz Snare Hard Jazz Snare Hard +39 %font "GeneralUser.sf2" 128 32 39 amp=92 pan=-16 # Hand Clap +40 %font "GeneralUser.sf2" 128 32 40 amp=132 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +41 %font "GeneralUser.sf2" 128 32 41 amp=123 pan=-47 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +42 %font "GeneralUser.sf2" 128 32 42 amp=37 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 32 43 amp=131 pan=-28 # Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 Standard Tom 5 +44 %font "GeneralUser.sf2" 128 32 44 amp=50 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 32 45 amp=118 pan=-9 # Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 Standard Tom 4 +46 %font "GeneralUser.sf2" 128 32 46 amp=30 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 32 47 amp=97 pan=9 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +48 %font "GeneralUser.sf2" 128 32 48 amp=84 pan=28 # Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 Standard Tom 2 +49 %font "GeneralUser.sf2" 128 32 49 amp=176 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 32 50 amp=50 pan=47 # Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 Standard Tom 1 +51 %font "GeneralUser.sf2" 128 32 51 amp=73 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 32 52 amp=32 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 32 53 amp=27 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 32 54 amp=68 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 32 55 amp=55 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 32 56 amp=103 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 32 57 amp=136 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 32 58 amp=81 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 32 59 amp=69 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 32 60 amp=98 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 32 61 amp=77 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 32 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 32 63 amp=68 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 32 64 amp=74 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 32 65 amp=127 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 32 66 amp=64 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 32 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 32 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 32 69 amp=39 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 32 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 32 71 amp=60 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 32 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 32 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 32 74 amp=43 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 32 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 32 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 32 77 amp=64 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 32 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 32 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 32 80 amp=45 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 32 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 32 82 amp=96 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 32 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 32 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 32 85 amp=162 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 32 86 amp=67 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 32 87 amp=98 pan=-31 # Surdo Open + +drumset 40 +27 %font "GeneralUser.sf2" 128 40 27 amp=36 pan=-23 # Filter Snap +28 %font "GeneralUser.sf2" 128 40 28 amp=104 pan=31 # Slap +29 %font "GeneralUser.sf2" 128 40 29 amp=44 pan=-16 # Scratch Push +30 %font "GeneralUser.sf2" 128 40 30 amp=50 pan=-16 # Scratch Pull +31 %font "GeneralUser.sf2" 128 40 31 amp=155 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 40 32 amp=436 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 40 33 amp=121 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 40 34 amp=45 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 40 35 amp=133 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 40 36 amp=104 pan=0 # Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Standard Kick 1 Standard Kick 1 Standard Kick 1 +37 %font "GeneralUser.sf2" 128 40 37 amp=72 pan=0 # Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Jazz Rim Shot Rim Shot +38 %font "GeneralUser.sf2" 128 40 38 amp=37 pan=0 # Brush Snare Brush Snare Brush Snare +39 %font "GeneralUser.sf2" 128 40 39 amp=90 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +40 %font "GeneralUser.sf2" 128 40 40 amp=16 pan=0 # Brush Swirl +41 %font "GeneralUser.sf2" 128 40 41 amp=138 pan=-47 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +42 %font "GeneralUser.sf2" 128 40 42 amp=36 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +43 %font "GeneralUser.sf2" 128 40 43 amp=111 pan=-28 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +44 %font "GeneralUser.sf2" 128 40 44 amp=31 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +45 %font "GeneralUser.sf2" 128 40 45 amp=157 pan=-9 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +46 %font "GeneralUser.sf2" 128 40 46 amp=39 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +47 %font "GeneralUser.sf2" 128 40 47 amp=104 pan=9 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +48 %font "GeneralUser.sf2" 128 40 48 amp=101 pan=28 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +49 %font "GeneralUser.sf2" 128 40 49 amp=183 pan=31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +50 %font "GeneralUser.sf2" 128 40 50 amp=54 pan=47 # Brushed Tom Brushed Tom Brushed Tom Brushed Tom +51 %font "GeneralUser.sf2" 128 40 51 amp=49 pan=-31 # Ride Cymbal +52 %font "GeneralUser.sf2" 128 40 52 amp=71 pan=-31 # Chinese Cymbal +53 %font "GeneralUser.sf2" 128 40 53 amp=110 pan=-31 # Ride Bell +54 %font "GeneralUser.sf2" 128 40 54 amp=19 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 40 55 amp=55 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 40 56 amp=106 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 40 57 amp=121 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 40 58 amp=34 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 40 59 amp=60 pan=-31 # Ride Cymbal +60 %font "GeneralUser.sf2" 128 40 60 amp=98 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 40 61 amp=78 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 40 62 amp=31 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 40 63 amp=69 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 40 64 amp=48 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 40 65 amp=82 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 40 66 amp=98 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 40 67 amp=63 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 40 68 amp=71 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 40 69 amp=40 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 40 70 amp=28 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 40 71 amp=37 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 40 72 amp=65 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 40 73 amp=77 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 40 74 amp=43 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 40 75 amp=92 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 40 76 amp=56 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 40 77 amp=63 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 40 78 amp=39 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 40 79 amp=43 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 40 80 amp=46 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 40 81 amp=11 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 40 82 amp=96 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 40 83 amp=71 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 40 84 amp=40 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 40 85 amp=162 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 40 86 amp=67 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 40 87 amp=144 pan=-31 # Surdo Open + +drumset 48 +27 %font "GeneralUser.sf2" 128 48 27 amp=38 pan=31 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +28 %font "GeneralUser.sf2" 128 48 28 amp=63 pan=31 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal +29 %font "GeneralUser.sf2" 128 48 29 amp=31 pan=31 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +30 %font "GeneralUser.sf2" 128 48 30 amp=52 pan=-31 # Ride Cymbal +31 %font "GeneralUser.sf2" 128 48 31 amp=23 pan=0 # Sticks +32 %font "GeneralUser.sf2" 128 48 32 amp=351 pan=-16 # Square Click +33 %font "GeneralUser.sf2" 128 48 33 amp=61 pan=0 # TR-808 Click +34 %font "GeneralUser.sf2" 128 48 34 amp=37 pan=0 # TR-808 Click Carillon-C6 +35 %font "GeneralUser.sf2" 128 48 35 amp=154 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +36 %font "GeneralUser.sf2" 128 48 36 amp=67 pan=0 # Taiko Drum Timpani Hard Timpani Hard Timpani Hard Timpani Hard +37 %font "GeneralUser.sf2" 128 48 37 amp=16 pan=0 # Rim Shot +38 %font "GeneralUser.sf2" 128 48 38 amp=55 pan=-31 # Orchestral Snare Orchestral Snare Orchestral Snare Orchestral Snare +39 %font "GeneralUser.sf2" 128 48 39 amp=70 pan=-47 # Castanets +40 %font "GeneralUser.sf2" 128 48 40 amp=55 pan=0 # Orchestral Snare Orchestral Snare Orchestral Snare Orchestral Snare +41 %font "GeneralUser.sf2" 128 48 41 amp=200 pan=-47 # Timpani Hard Timpani Hard Timpani Hard Timpani Soft Timpani Soft Timpani Hard Timpani Hard Timpani Soft +42 %font "GeneralUser.sf2" 0 47 amp=197 pan=-47 +43 %font "GeneralUser.sf2" 0 47 amp=123 pan=-47 +44 %font "GeneralUser.sf2" 0 47 amp=191 pan=-47 +45 %font "GeneralUser.sf2" 0 47 amp=112 pan=-47 +46 %font "GeneralUser.sf2" 0 47 amp=181 pan=-47 +47 %font "GeneralUser.sf2" 0 47 amp=108 pan=-47 +48 %font "GeneralUser.sf2" 0 47 amp=168 pan=-47 +49 %font "GeneralUser.sf2" 0 47 amp=166 pan=-47 +50 %font "GeneralUser.sf2" 0 47 amp=159 pan=-47 +51 %font "GeneralUser.sf2" 0 47 amp=93 pan=-47 +52 %font "GeneralUser.sf2" 0 47 amp=91 pan=-47 +53 %font "GeneralUser.sf2" 0 47 amp=89 pan=-47 +54 %font "GeneralUser.sf2" 128 48 54 amp=72 pan=16 # Tambourine +55 %font "GeneralUser.sf2" 128 48 55 amp=63 pan=-16 # Splash Cymbal +56 %font "GeneralUser.sf2" 128 48 56 amp=95 pan=31 # Cowbell +57 %font "GeneralUser.sf2" 128 48 57 amp=122 pan=-31 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +58 %font "GeneralUser.sf2" 128 48 58 amp=27 pan=-55 # Vibra Slap +59 %font "GeneralUser.sf2" 128 48 59 amp=99 pan=-47 # Orchestral Cymbal +60 %font "GeneralUser.sf2" 128 48 60 amp=16 pan=55 # Bongo Rim +61 %font "GeneralUser.sf2" 128 48 61 amp=115 pan=55 # Bongo Tone +62 %font "GeneralUser.sf2" 128 48 62 amp=43 pan=-39 # Conga High Muted +63 %font "GeneralUser.sf2" 128 48 63 amp=66 pan=-39 # Conga High Open +64 %font "GeneralUser.sf2" 128 48 64 amp=48 pan=-31 # Tumba Low +65 %font "GeneralUser.sf2" 128 48 65 amp=66 pan=31 # Timbale Rim +66 %font "GeneralUser.sf2" 128 48 66 amp=53 pan=31 # Timbale Low +67 %font "GeneralUser.sf2" 128 48 67 amp=91 pan=-55 # Agogo Agogo Agogo +68 %font "GeneralUser.sf2" 128 48 68 amp=101 pan=-55 # Agogo Agogo Agogo +69 %font "GeneralUser.sf2" 128 48 69 amp=30 pan=-55 # Cabasa +70 %font "GeneralUser.sf2" 128 48 70 amp=24 pan=-63 # Maracas +71 %font "GeneralUser.sf2" 128 48 71 amp=28 pan=55 # Whistle Short +72 %font "GeneralUser.sf2" 128 48 72 amp=29 pan=55 # Whistle Long +73 %font "GeneralUser.sf2" 128 48 73 amp=58 pan=47 # Guiro Short +74 %font "GeneralUser.sf2" 128 48 74 amp=65 pan=47 # Guiro Long +75 %font "GeneralUser.sf2" 128 48 75 amp=72 pan=31 # Claves +76 %font "GeneralUser.sf2" 128 48 76 amp=43 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +77 %font "GeneralUser.sf2" 128 48 77 amp=48 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +78 %font "GeneralUser.sf2" 128 48 78 amp=32 pan=-31 # Cuica Mute +79 %font "GeneralUser.sf2" 128 48 79 amp=35 pan=-31 # Cuica Open +80 %font "GeneralUser.sf2" 128 48 80 amp=36 pan=-63 # Triangle (Perc) +81 %font "GeneralUser.sf2" 128 48 81 amp=14 pan=-63 # Triangle (Perc) +82 %font "GeneralUser.sf2" 128 48 82 amp=71 pan=47 # Shaker +83 %font "GeneralUser.sf2" 128 48 83 amp=54 pan=55 # Jingle Bell +84 %font "GeneralUser.sf2" 128 48 84 amp=32 pan=63 # Bell Tree +85 %font "GeneralUser.sf2" 128 48 85 amp=81 pan=-47 # Castanets +86 %font "GeneralUser.sf2" 128 48 86 amp=52 pan=-31 # Surdo Muted +87 %font "GeneralUser.sf2" 128 48 87 amp=118 pan=-31 # Surdo Open +88 %font "GeneralUser.sf2" 128 48 88 amp=55 pan=0 # Applause + +drumset 49 +30 %font "GeneralUser.sf2" 128 0 38 amp=109 pan=-31 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +31 %font "GeneralUser.sf2" 128 0 49 amp=110 pan=-47 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +32 %font "GeneralUser.sf2" 128 0 35 amp=27 pan=-63 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +33 %font "GeneralUser.sf2" 0 116 amp=42 pan=55 +36 %font "GeneralUser.sf2" 128 0 47 amp=110 pan=0 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +38 %font "GeneralUser.sf2" 128 0 47 amp=216 pan=-31 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +39 %font "GeneralUser.sf2" 128 0 47 amp=100 pan=63 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +40 %font "GeneralUser.sf2" 128 0 47 amp=75 pan=63 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +41 %font "GeneralUser.sf2" 128 0 47 amp=140 pan=31 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +42 %font "GeneralUser.sf2" 128 0 63 amp=59 pan=47 # Conga High Open +43 %font "GeneralUser.sf2" 128 0 64 amp=81 pan=47 # Tumba Low +44 %font "GeneralUser.sf2" 128 0 47 amp=152 pan=63 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +49 %font "GeneralUser.sf2" 128 0 52 amp=45 pan=-47 # Chinese Cymbal +50 %font "GeneralUser.sf2" 128 0 52 amp=177 pan=31 # Chinese Cymbal +51 %font "GeneralUser.sf2" 128 0 47 amp=247 pan=47 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +52 %font "GeneralUser.sf2" 128 0 47 amp=260 pan=47 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +54 %font "GeneralUser.sf2" 128 0 64 amp=60 pan=23 # Tumba Low +55 %font "GeneralUser.sf2" 128 0 64 amp=55 pan=47 # Tumba Low +56 %font "GeneralUser.sf2" 128 0 64 amp=30 pan=47 # Tumba Low +57 %font "GeneralUser.sf2" 128 0 60 amp=97 pan=-47 # Bongo Rim +58 %font "GeneralUser.sf2" 128 0 61 amp=56 pan=-47 # Bongo Tone +59 %font "GeneralUser.sf2" 128 0 63 amp=27 pan=-47 # Conga High Open +60 %font "GeneralUser.sf2" 128 0 64 amp=55 pan=-47 # Tumba Low +61 %font "GeneralUser.sf2" 128 0 62 amp=99 pan=-31 # Conga High Muted +62 %font "GeneralUser.sf2" 128 0 47 amp=159 pan=31 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +63 %font "GeneralUser.sf2" 128 0 47 amp=175 pan=31 # Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 Standard Tom 3 +64 %font "GeneralUser.sf2" 128 0 64 amp=23 pan=-16 # Tumba Low +65 %font "GeneralUser.sf2" 128 0 60 amp=203 pan=-31 # Bongo Rim +67 %font "GeneralUser.sf2" 128 0 66 amp=76 pan=31 # Timbale Low +68 %font "GeneralUser.sf2" 128 0 66 amp=28 pan=39 # Timbale Low +69 %font "GeneralUser.sf2" 128 0 65 amp=69 pan=39 # Timbale Rim +70 %font "GeneralUser.sf2" 128 0 56 amp=74 pan=31 # Cowbell +71 %font "GeneralUser.sf2" 128 0 60 amp=93 pan=55 # Bongo Rim +72 %font "GeneralUser.sf2" 128 0 61 amp=91 pan=47 # Bongo Tone +73 %font "GeneralUser.sf2" 128 0 62 amp=58 pan=-31 # Conga High Muted +74 %font "GeneralUser.sf2" 128 0 63 amp=139 pan=-31 # Conga High Open +75 %font "GeneralUser.sf2" 128 0 64 amp=29 pan=-39 # Tumba Low +76 %font "GeneralUser.sf2" 128 0 64 amp=48 pan=-39 # Tumba Low +77 %font "GeneralUser.sf2" 128 0 64 amp=50 pan=-39 # Tumba Low +78 %font "GeneralUser.sf2" 128 0 64 amp=64 pan=-39 # Tumba Low +79 %font "GeneralUser.sf2" 0 116 amp=125 pan=63 +80 %font "GeneralUser.sf2" 0 116 amp=56 pan=63 +81 %font "GeneralUser.sf2" 0 116 amp=96 pan=-31 +82 %font "GeneralUser.sf2" 0 116 amp=66 pan=-31 +83 %font "GeneralUser.sf2" 128 0 54 amp=186 pan=8 # Tambourine +84 %font "GeneralUser.sf2" 128 0 67 amp=56 pan=-55 # Agogo Agogo Agogo +85 %font "GeneralUser.sf2" 128 0 68 amp=63 pan=-55 # Agogo Agogo Agogo +87 %font "GeneralUser.sf2" 128 0 71 amp=70 pan=55 # Whistle Short +88 %font "GeneralUser.sf2" 128 0 72 amp=39 pan=55 # Whistle Long +89 %font "GeneralUser.sf2" 128 0 78 amp=36 pan=-31 # Cuica Mute +90 %font "GeneralUser.sf2" 128 0 79 amp=39 pan=-31 # Cuica Open +91 %font "GeneralUser.sf2" 128 0 80 amp=43 pan=-63 # Triangle (Perc) +92 %font "GeneralUser.sf2" 128 0 81 amp=24 pan=-63 # Triangle (Perc) +93 %font "GeneralUser.sf2" 128 0 73 amp=63 pan=47 # Guiro Short +94 %font "GeneralUser.sf2" 128 0 74 amp=33 pan=47 # Guiro Long +95 %font "GeneralUser.sf2" 128 0 69 amp=44 pan=-55 # Cabasa +96 %font "GeneralUser.sf2" 128 0 69 amp=65 pan=-55 # Cabasa +97 %font "GeneralUser.sf2" 128 0 75 amp=65 pan=31 # Claves +98 %font "GeneralUser.sf2" 128 0 76 amp=79 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard +99 %font "GeneralUser.sf2" 128 0 77 amp=88 pan=55 # Wood Block Med Wood Block Med Wood Block Med Wood Block Med Wood Block Hard Wood Block Hard Wood Block Hard + +drumset 50 +25 %font "GeneralUser.sf2" 128 25 36 amp=88 pan=0 # TR-909 Kick +26 %font "GeneralUser.sf2" 128 25 35 amp=186 pan=0 # Sine-93.75Hz +27 %font "GeneralUser.sf2" 128 25 36 amp=82 pan=0 # TR-909 Kick +28 %font "GeneralUser.sf2" 128 25 36 amp=90 pan=0 # TR-909 Kick +29 %font "GeneralUser.sf2" 128 25 36 amp=80 pan=0 # TR-909 Kick +30 %font "GeneralUser.sf2" 128 25 36 amp=112 pan=0 # TR-909 Kick +31 %font "GeneralUser.sf2" 128 25 35 amp=311 pan=0 # Sine-93.75Hz +32 %font "GeneralUser.sf2" 128 25 36 amp=106 pan=0 # TR-909 Kick +33 %font "GeneralUser.sf2" 128 25 35 amp=160 pan=0 # Sine-93.75Hz +34 %font "GeneralUser.sf2" 128 25 36 amp=59 pan=0 # TR-909 Kick +35 %font "GeneralUser.sf2" 128 25 35 amp=67 pan=0 # Sine-93.75Hz +36 %font "GeneralUser.sf2" 128 25 36 amp=93 pan=0 # TR-909 Kick +37 %font "GeneralUser.sf2" 128 25 35 amp=323 pan=0 # Sine-93.75Hz +38 %font "GeneralUser.sf2" 128 0 36 amp=144 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +39 %font "GeneralUser.sf2" 128 0 35 amp=282 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +40 %font "GeneralUser.sf2" 128 0 36 amp=159 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +41 %font "GeneralUser.sf2" 128 0 35 amp=172 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +42 %font "GeneralUser.sf2" 128 1 36 amp=195 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +43 %font "GeneralUser.sf2" 128 1 35 amp=148 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +44 %font "GeneralUser.sf2" 128 0 36 amp=174 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +45 %font "GeneralUser.sf2" 128 0 35 amp=108 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +46 %font "GeneralUser.sf2" 128 0 36 amp=179 pan=0 # Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 Standard Kick 1 +47 %font "GeneralUser.sf2" 128 32 36 amp=106 pan=0 # Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Jazz Bass Drum Standard Kick 1 Standard Kick 1 Standard Kick 1 +48 %font "GeneralUser.sf2" 128 32 35 amp=133 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +49 %font "GeneralUser.sf2" 128 48 36 amp=58 pan=0 # Taiko Drum Timpani Hard Timpani Hard Timpani Hard Timpani Hard +50 %font "GeneralUser.sf2" 128 8 36 amp=45 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +51 %font "GeneralUser.sf2" 128 8 35 amp=137 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +52 %font "GeneralUser.sf2" 128 16 36 amp=92 pan=0 # Power Kick 2 Power Kick 2 Power Kick 2 Power Kick 2 +53 %font "GeneralUser.sf2" 128 16 35 amp=87 pan=0 # Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 Power/Room Kick 1 +54 %font "GeneralUser.sf2" 128 24 36 amp=94 pan=0 # TR-909 Kick Electric Tom +55 %font "GeneralUser.sf2" 128 24 35 amp=181 pan=0 # Standard Kick 2 Standard Kick 2 Standard Kick 2 Standard Kick 2 +56 %font "GeneralUser.sf2" 128 24 36 amp=68 pan=0 # TR-909 Kick Electric Tom +57 %font "GeneralUser.sf2" 128 25 36 amp=87 pan=0 # TR-909 Kick +58 %font "GeneralUser.sf2" 128 25 36 amp=101 pan=0 # TR-909 Kick +59 %font "GeneralUser.sf2" 128 26 36 amp=101 pan=0 # TR-909 Kick TR-909 Kick +60 %font "GeneralUser.sf2" 128 0 38 amp=127 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +61 %font "GeneralUser.sf2" 128 0 40 amp=202 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +62 %font "GeneralUser.sf2" 128 0 38 amp=135 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +63 %font "GeneralUser.sf2" 128 0 40 amp=139 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +64 %font "GeneralUser.sf2" 128 0 38 amp=125 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +65 %font "GeneralUser.sf2" 128 48 38 amp=85 pan=0 # Orchestral Snare Orchestral Snare Orchestral Snare Orchestral Snare +66 %font "GeneralUser.sf2" 128 32 38 amp=122 pan=0 # Jazz Snare Soft 1 Jazz Snare Soft 1 Jazz Snare Soft 2 Jazz Snare Hard Jazz Snare Hard +67 %font "GeneralUser.sf2" 128 32 40 amp=118 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +68 %font "GeneralUser.sf2" 128 8 38 amp=118 pan=0 # Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 Room Snare 1 +69 %font "GeneralUser.sf2" 128 8 40 amp=144 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +70 %font "GeneralUser.sf2" 128 16 38 amp=77 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +71 %font "GeneralUser.sf2" 128 16 40 amp=57 pan=0 # Power Snare 2 Power Snare 2 Power Snare 2 Power Snare 2 +72 %font "GeneralUser.sf2" 128 24 40 amp=103 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +73 %font "GeneralUser.sf2" 128 26 38 amp=133 pan=0 # Dance Snare +74 %font "GeneralUser.sf2" 128 26 40 amp=116 pan=0 # TR-909 Snare 2 +75 %font "GeneralUser.sf2" 128 26 40 amp=78 pan=0 # TR-909 Snare 2 +76 %font "GeneralUser.sf2" 128 24 38 amp=64 pan=0 # Electric Tom White Noise +77 %font "GeneralUser.sf2" 128 26 38 amp=67 pan=0 # Dance Snare +78 %font "GeneralUser.sf2" 128 24 38 amp=120 pan=0 # Electric Tom White Noise +79 %font "GeneralUser.sf2" 128 24 40 amp=126 pan=0 # Power Snare 1 Power Snare 1 Power Snare 1 Power Snare 1 +80 %font "GeneralUser.sf2" 128 25 38 amp=47 pan=0 # TR-909 Snare 1 +81 %font "GeneralUser.sf2" 128 25 40 amp=53 pan=0 # TR-909 Snare 2 +82 %font "GeneralUser.sf2" 128 25 38 amp=60 pan=0 # TR-909 Snare 1 +83 %font "GeneralUser.sf2" 128 25 40 amp=77 pan=0 # TR-909 Snare 2 +84 %font "GeneralUser.sf2" 128 40 38 amp=26 pan=0 # Brush Snare Brush Snare Brush Snare +85 %font "GeneralUser.sf2" 128 40 38 amp=36 pan=0 # Brush Snare Brush Snare Brush Snare +86 %font "GeneralUser.sf2" 128 40 39 amp=103 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +87 %font "GeneralUser.sf2" 128 40 39 amp=100 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +88 %font "GeneralUser.sf2" 128 40 39 amp=131 pan=0 # Brush Snare Brush Snare Brush Snare Standard Snare 2 Standard Snare 2 Standard Snare 2 +89 %font "GeneralUser.sf2" 128 40 40 amp=19 pan=0 # Brush Swirl +90 %font "GeneralUser.sf2" 128 40 40 amp=17 pan=0 # Brush Swirl +91 %font "GeneralUser.sf2" 128 40 40 amp=23 pan=0 # Brush Swirl +92 %font "GeneralUser.sf2" 128 0 38 amp=207 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +93 %font "GeneralUser.sf2" 128 0 40 amp=413 pan=0 # Standard Snare 2 Standard Snare 2 Standard Snare 2 Standard Snare 2 +94 %font "GeneralUser.sf2" 128 0 38 amp=267 pan=0 # Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Standard Snare 1 Jazz Snare Soft 1 Jazz Snare Soft 1 +95 %font "GeneralUser.sf2" 128 25 38 amp=93 pan=0 # TR-909 Snare 1 +96 %font "GeneralUser.sf2" 128 25 40 amp=61 pan=0 # TR-909 Snare 2 +97 %font "GeneralUser.sf2" 128 25 38 amp=68 pan=0 # TR-909 Snare 1 +98 %font "GeneralUser.sf2" 128 25 40 amp=80 pan=0 # TR-909 Snare 2 +99 %font "GeneralUser.sf2" 128 25 38 amp=66 pan=0 # TR-909 Snare 1 + +drumset 53 +32 %font "GeneralUser.sf2" 128 0 46 amp=51 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +33 %font "GeneralUser.sf2" 128 0 42 amp=61 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +34 %font "GeneralUser.sf2" 128 0 42 amp=82 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +35 %font "GeneralUser.sf2" 128 25 44 amp=170 pan=0 # TR-808 Hi-Hat +36 %font "GeneralUser.sf2" 128 0 42 amp=42 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +37 %font "GeneralUser.sf2" 128 0 42 amp=45 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +38 %font "GeneralUser.sf2" 128 0 42 amp=33 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +39 %font "GeneralUser.sf2" 128 0 42 amp=34 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +40 %font "GeneralUser.sf2" 128 0 42 amp=35 pan=0 # Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Hard Hi-Hat Closed Soft Hi-Hat Closed Soft Hi-Hat Closed Soft +41 %font "GeneralUser.sf2" 128 25 42 amp=50 pan=0 # TR-808 Hi-Hat +42 %font "GeneralUser.sf2" 128 25 42 amp=72 pan=0 # TR-808 Hi-Hat +43 %font "GeneralUser.sf2" 128 25 42 amp=88 pan=0 # TR-808 Hi-Hat +44 %font "GeneralUser.sf2" 128 25 42 amp=69 pan=0 # TR-808 Hi-Hat +45 %font "GeneralUser.sf2" 128 25 42 amp=151 pan=0 # TR-808 Hi-Hat +46 %font "GeneralUser.sf2" 128 0 44 amp=41 pan=0 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +47 %font "GeneralUser.sf2" 128 0 44 amp=60 pan=0 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +48 %font "GeneralUser.sf2" 128 0 44 amp=43 pan=0 # Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Hi-Hat Pedal Dead Air +49 %font "GeneralUser.sf2" 128 0 46 amp=43 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +50 %font "GeneralUser.sf2" 128 0 46 amp=36 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +51 %font "GeneralUser.sf2" 128 0 46 amp=38 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +52 %font "GeneralUser.sf2" 128 0 46 amp=18 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +53 %font "GeneralUser.sf2" 128 0 46 amp=42 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +54 %font "GeneralUser.sf2" 128 0 46 amp=60 pan=0 # Hi-Hat Open Hi-Hat Open Attack Hi-Hat Open Attack +55 %font "GeneralUser.sf2" 128 25 46 amp=31 pan=0 # TR-909 Hi-Hat Open +56 %font "GeneralUser.sf2" 128 25 46 amp=31 pan=0 # TR-909 Hi-Hat Open +57 %font "GeneralUser.sf2" 128 25 46 amp=47 pan=0 # TR-909 Hi-Hat Open +58 %font "GeneralUser.sf2" 128 25 46 amp=61 pan=0 # TR-909 Hi-Hat Open +59 %font "GeneralUser.sf2" 128 25 46 amp=38 pan=0 # TR-909 Hi-Hat Open +60 %font "GeneralUser.sf2" 128 25 46 amp=34 pan=0 # TR-909 Hi-Hat Open +61 %font "GeneralUser.sf2" 128 0 49 amp=176 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +62 %font "GeneralUser.sf2" 128 0 57 amp=164 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +63 %font "GeneralUser.sf2" 128 0 49 amp=180 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +64 %font "GeneralUser.sf2" 128 40 49 amp=105 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +65 %font "GeneralUser.sf2" 128 0 49 amp=172 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +66 %font "GeneralUser.sf2" 128 25 49 amp=60 pan=0 # TR-808 Hi-Hat Crash Cymbal +67 %font "GeneralUser.sf2" 128 25 49 amp=97 pan=0 # TR-808 Hi-Hat Crash Cymbal +68 %font "GeneralUser.sf2" 128 0 49 amp=271 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +69 %font "GeneralUser.sf2" 128 0 57 amp=220 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +70 %font "GeneralUser.sf2" 128 0 49 amp=169 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +71 %font "GeneralUser.sf2" 128 0 57 amp=148 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +72 %font "GeneralUser.sf2" 128 0 49 amp=155 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +73 %font "GeneralUser.sf2" 128 40 49 amp=155 pan=0 # Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Crash Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal Ride Cymbal +74 %font "GeneralUser.sf2" 128 0 55 amp=71 pan=0 # Splash Cymbal +75 %font "GeneralUser.sf2" 128 0 55 amp=90 pan=0 # Splash Cymbal +76 %font "GeneralUser.sf2" 128 0 53 amp=47 pan=0 # Ride Bell +77 %font "GeneralUser.sf2" 128 40 53 amp=58 pan=0 # Ride Bell +78 %font "GeneralUser.sf2" 128 0 51 amp=58 pan=0 # Ride Cymbal +79 %font "GeneralUser.sf2" 128 0 59 amp=58 pan=0 # Ride Cymbal +80 %font "GeneralUser.sf2" 128 40 51 amp=75 pan=0 # Ride Cymbal +81 %font "GeneralUser.sf2" 128 0 51 amp=83 pan=0 # Ride Cymbal +82 %font "GeneralUser.sf2" 128 0 51 amp=42 pan=0 # Ride Cymbal +83 %font "GeneralUser.sf2" 128 0 51 amp=36 pan=0 # Ride Cymbal +84 %font "GeneralUser.sf2" 128 0 51 amp=41 pan=0 # Ride Cymbal +85 %font "GeneralUser.sf2" 128 0 51 amp=41 pan=0 # Ride Cymbal +86 %font "GeneralUser.sf2" 128 0 51 amp=33 pan=0 # Ride Cymbal +87 %font "GeneralUser.sf2" 128 25 51 amp=80 pan=0 # Ride Cymbal +88 %font "GeneralUser.sf2" 128 25 51 amp=252 pan=0 # Ride Cymbal +89 %font "GeneralUser.sf2" 128 0 51 amp=308 pan=0 # Ride Cymbal +90 %font "GeneralUser.sf2" 128 0 51 amp=276 pan=0 # Ride Cymbal +91 %font "GeneralUser.sf2" 128 0 39 amp=21 pan=0 # Hand Clap +92 %font "GeneralUser.sf2" 128 0 39 amp=93 pan=0 # Hand Clap +93 %font "GeneralUser.sf2" 128 0 39 amp=81 pan=0 # Hand Clap +94 %font "GeneralUser.sf2" 128 0 39 amp=83 pan=0 # Hand Clap +95 %font "GeneralUser.sf2" 128 0 39 amp=155 pan=0 # Hand Clap +96 %font "GeneralUser.sf2" 128 25 39 amp=66 pan=0 # Synth Hand Clap + +drumset 56 +39 %font "GeneralUser.sf2" 128 56 39 amp=36 pan=-23 # Filter Snap +40 %font "GeneralUser.sf2" 128 56 40 amp=167 pan=-23 # Slap +41 %font "GeneralUser.sf2" 128 56 41 amp=74 pan=-16 # Scratch Push +42 %font "GeneralUser.sf2" 128 56 42 amp=52 pan=-16 # Scratch Pull +43 %font "GeneralUser.sf2" 128 56 43 amp=97 pan=0 # Sticks +44 %font "GeneralUser.sf2" 128 56 44 amp=433 pan=-16 # Square Click +45 %font "GeneralUser.sf2" 128 56 45 amp=77 pan=0 # TR-808 Click +46 %font "GeneralUser.sf2" 128 56 46 amp=45 pan=0 # TR-808 Click Carillon-C6 +47 %font "GeneralUser.sf2" 128 56 47 amp=68 pan=0 # Fret Slide +48 %font "GeneralUser.sf2" 128 56 48 amp=17 pan=0 # Gtr Cut Up +49 %font "GeneralUser.sf2" 128 56 49 amp=73 pan=0 # Gtr Cut Down +50 %font "GeneralUser.sf2" 128 56 50 amp=28 pan=0 # Gtr Slap +51 %font "GeneralUser.sf2" 128 56 51 amp=154 pan=0 # Gtr Click +52 %font "GeneralUser.sf2" 128 56 52 amp=87 pan=0 # Laughing +53 %font "GeneralUser.sf2" 128 56 53 amp=61 pan=0 # Scream +54 %font "GeneralUser.sf2" 128 56 54 amp=174 pan=0 # Punch Bone Crunch +55 %font "GeneralUser.sf2" 128 56 55 amp=155 pan=0 # Heartbeat +56 %font "GeneralUser.sf2" 128 56 56 amp=83 pan=0 # Foot Step +58 %font "GeneralUser.sf2" 128 56 58 amp=9 pan=0 # Applause Applause +59 %font "GeneralUser.sf2" 128 56 59 amp=24 pan=0 # Door Creak +60 %font "GeneralUser.sf2" 128 56 60 amp=75 pan=0 # Door Slam +61 %font "GeneralUser.sf2" 128 56 61 amp=74 pan=0 # Scratch Pull +62 %font "GeneralUser.sf2" 128 56 62 amp=118 pan=0 # Windchimes +63 %font "GeneralUser.sf2" 128 56 63 amp=55 pan=0 # Car-Start Car-Start +64 %font "GeneralUser.sf2" 128 56 64 amp=117 pan=0 # Car-Skid +65 %font "GeneralUser.sf2" 128 56 65 amp=56 pan=0 # Car-Pass Car-Pass +66 %font "GeneralUser.sf2" 128 56 66 amp=142 pan=0 # Car-Crash +67 %font "GeneralUser.sf2" 128 56 67 amp=14 pan=0 # Siren Siren +68 %font "GeneralUser.sf2" 128 56 68 amp=302 pan=0 # Train Train +69 %font "GeneralUser.sf2" 128 56 69 amp=26 pan=0 # Jet +70 %font "GeneralUser.sf2" 128 56 70 amp=171 pan=0 # Helicopter +71 %font "GeneralUser.sf2" 128 56 71 amp=12 pan=0 # Starship Noise Harpsichord-C6 +72 %font "GeneralUser.sf2" 128 56 72 amp=79 pan=0 # Gun Shot +73 %font "GeneralUser.sf2" 128 56 73 amp=33 pan=0 # Gun Shot +74 %font "GeneralUser.sf2" 128 56 74 amp=154 pan=0 # Sine-Triangle-12000 White Noise White Noise +75 %font "GeneralUser.sf2" 128 56 75 amp=65 pan=0 # Explosion Explosion +76 %font "GeneralUser.sf2" 128 56 76 amp=141 pan=0 # Dog +77 %font "GeneralUser.sf2" 128 56 77 amp=3 pan=0 # Horse Gallop +78 %font "GeneralUser.sf2" 128 56 78 amp=99 pan=0 # Birds Birds +79 %font "GeneralUser.sf2" 128 56 79 amp=14 pan=0 # Rain Rain +80 %font "GeneralUser.sf2" 128 56 80 amp=182 pan=0 # Thunder Thunder +81 %font "GeneralUser.sf2" 128 56 81 amp=12 pan=0 # WhiteNoiseWave WhiteNoiseWave +82 %font "GeneralUser.sf2" 128 56 82 amp=82 pan=0 # Seashore Seashore +83 %font "GeneralUser.sf2" 128 56 83 amp=109 pan=0 # Stream Stream +84 %font "GeneralUser.sf2" 128 56 84 amp=57 pan=0 # Bubbles + + diff --git a/packages/tools/sound/timidity/config/fluidr3_gm.cfg b/packages/tools/sound/timidity/config/fluidr3_gm.cfg new file mode 100644 index 000000000..4b97176fe --- /dev/null +++ b/packages/tools/sound/timidity/config/fluidr3_gm.cfg @@ -0,0 +1,2830 @@ +dir /storage/roms/bios/timidity/sf2 + +bank 0 +0 %font "FluidR3_GM.sf2" 0 0 amp=29 pan=0 +1 %font "FluidR3_GM.sf2" 0 1 amp=41 pan=0 +2 %font "FluidR3_GM.sf2" 0 2 amp=64 pan=0 +3 %font "FluidR3_GM.sf2" 0 3 amp=32 pan=0 +4 %font "FluidR3_GM.sf2" 0 4 amp=35 pan=0 +5 %font "FluidR3_GM.sf2" 0 5 amp=51 pan=0 +6 %font "FluidR3_GM.sf2" 0 6 amp=71 pan=0 +7 %font "FluidR3_GM.sf2" 0 7 amp=65 pan=0 +8 %font "FluidR3_GM.sf2" 0 8 amp=73 pan=0 +9 %font "FluidR3_GM.sf2" 0 9 amp=98 pan=0 +10 %font "FluidR3_GM.sf2" 0 10 amp=150 pan=0 +11 %font "FluidR3_GM.sf2" 0 11 amp=63 pan=0 +12 %font "FluidR3_GM.sf2" 0 12 amp=48 pan=0 +13 %font "FluidR3_GM.sf2" 0 13 amp=46 pan=0 +14 %font "FluidR3_GM.sf2" 0 14 amp=65 pan=0 +15 %font "FluidR3_GM.sf2" 0 15 amp=62 pan=0 +16 %font "FluidR3_GM.sf2" 0 16 amp=154 pan=0 +17 %font "FluidR3_GM.sf2" 0 17 amp=96 pan=0 +18 %font "FluidR3_GM.sf2" 0 18 amp=75 pan=0 +19 %font "FluidR3_GM.sf2" 0 19 amp=128 pan=0 +20 %font "FluidR3_GM.sf2" 0 20 amp=45 pan=0 +21 %font "FluidR3_GM.sf2" 0 21 amp=50 pan=0 +22 %font "FluidR3_GM.sf2" 0 22 amp=36 pan=0 +23 %font "FluidR3_GM.sf2" 0 23 amp=46 pan=0 +24 %font "FluidR3_GM.sf2" 0 24 amp=139 pan=0 +25 %font "FluidR3_GM.sf2" 0 25 amp=92 pan=0 +26 %font "FluidR3_GM.sf2" 0 26 amp=87 pan=0 +27 %font "FluidR3_GM.sf2" 0 27 amp=46 pan=0 +28 %font "FluidR3_GM.sf2" 0 28 amp=92 pan=0 +29 %font "FluidR3_GM.sf2" 0 29 amp=41 pan=0 +30 %font "FluidR3_GM.sf2" 0 30 amp=91 pan=0 +31 %font "FluidR3_GM.sf2" 0 31 amp=60 pan=0 +32 %font "FluidR3_GM.sf2" 0 32 amp=125 pan=0 +33 %font "FluidR3_GM.sf2" 0 33 amp=85 pan=0 +34 %font "FluidR3_GM.sf2" 0 34 amp=148 pan=0 +35 %font "FluidR3_GM.sf2" 0 35 amp=98 pan=0 +36 %font "FluidR3_GM.sf2" 0 36 amp=207 pan=0 +37 %font "FluidR3_GM.sf2" 0 37 amp=223 pan=0 +38 %font "FluidR3_GM.sf2" 0 38 amp=35 pan=0 +39 %font "FluidR3_GM.sf2" 0 39 amp=38 pan=0 +40 %font "FluidR3_GM.sf2" 0 40 amp=48 pan=0 +41 %font "FluidR3_GM.sf2" 0 41 amp=69 pan=0 +42 %font "FluidR3_GM.sf2" 0 42 amp=34 pan=0 +43 %font "FluidR3_GM.sf2" 0 43 amp=109 pan=0 +44 %font "FluidR3_GM.sf2" 0 44 amp=68 pan=0 +45 %font "FluidR3_GM.sf2" 0 45 amp=124 pan=0 +46 %font "FluidR3_GM.sf2" 0 46 amp=117 pan=0 +47 %font "FluidR3_GM.sf2" 0 47 amp=98 pan=0 +48 %font "FluidR3_GM.sf2" 0 48 amp=91 pan=0 +49 %font "FluidR3_GM.sf2" 0 49 amp=79 pan=0 +50 %font "FluidR3_GM.sf2" 0 50 amp=30 pan=0 +51 %font "FluidR3_GM.sf2" 0 51 amp=14 pan=0 +52 %font "FluidR3_GM.sf2" 0 52 amp=56 pan=0 +53 %font "FluidR3_GM.sf2" 0 53 amp=66 pan=0 +54 %font "FluidR3_GM.sf2" 0 54 amp=79 pan=0 +55 %font "FluidR3_GM.sf2" 0 55 amp=105 pan=0 +56 %font "FluidR3_GM.sf2" 0 56 amp=102 pan=0 +57 %font "FluidR3_GM.sf2" 0 57 amp=54 pan=0 +58 %font "FluidR3_GM.sf2" 0 58 amp=60 pan=0 +59 %font "FluidR3_GM.sf2" 0 59 amp=42 pan=0 +60 %font "FluidR3_GM.sf2" 0 60 amp=80 pan=0 +61 %font "FluidR3_GM.sf2" 0 61 amp=89 pan=0 +62 %font "FluidR3_GM.sf2" 0 62 amp=82 pan=0 +63 %font "FluidR3_GM.sf2" 0 63 amp=117 pan=0 +64 %font "FluidR3_GM.sf2" 0 64 amp=90 pan=0 +65 %font "FluidR3_GM.sf2" 0 65 amp=30 pan=0 +66 %font "FluidR3_GM.sf2" 0 66 amp=51 pan=0 +67 %font "FluidR3_GM.sf2" 0 67 amp=33 pan=0 +68 %font "FluidR3_GM.sf2" 0 68 amp=58 pan=0 +69 %font "FluidR3_GM.sf2" 0 69 amp=68 pan=0 +70 %font "FluidR3_GM.sf2" 0 70 amp=67 pan=0 +71 %font "FluidR3_GM.sf2" 0 71 amp=61 pan=0 +72 %font "FluidR3_GM.sf2" 0 72 amp=43 pan=0 +73 %font "FluidR3_GM.sf2" 0 73 amp=43 pan=0 +74 %font "FluidR3_GM.sf2" 0 74 amp=116 pan=0 +75 %font "FluidR3_GM.sf2" 0 75 amp=51 pan=0 +76 %font "FluidR3_GM.sf2" 0 76 amp=56 pan=0 +77 %font "FluidR3_GM.sf2" 0 77 amp=32 pan=0 +78 %font "FluidR3_GM.sf2" 0 78 amp=122 pan=0 +79 %font "FluidR3_GM.sf2" 0 79 amp=144 pan=0 +80 %font "FluidR3_GM.sf2" 0 80 amp=24 pan=0 +81 %font "FluidR3_GM.sf2" 0 81 amp=65 pan=0 +82 %font "FluidR3_GM.sf2" 0 82 amp=222 pan=0 +83 %font "FluidR3_GM.sf2" 0 83 amp=86 pan=0 +84 %font "FluidR3_GM.sf2" 0 84 amp=41 pan=0 +85 %font "FluidR3_GM.sf2" 0 85 amp=147 pan=0 +86 %font "FluidR3_GM.sf2" 0 86 amp=29 pan=0 +87 %font "FluidR3_GM.sf2" 0 87 amp=60 pan=0 +88 %font "FluidR3_GM.sf2" 0 88 amp=205 pan=0 +89 %font "FluidR3_GM.sf2" 0 89 amp=52 pan=0 +90 %font "FluidR3_GM.sf2" 0 90 amp=39 pan=0 +91 %font "FluidR3_GM.sf2" 0 91 amp=60 pan=0 +92 %font "FluidR3_GM.sf2" 0 92 amp=107 pan=0 +93 %font "FluidR3_GM.sf2" 0 93 amp=50 pan=0 +94 %font "FluidR3_GM.sf2" 0 94 amp=87 pan=0 +95 %font "FluidR3_GM.sf2" 0 95 amp=70 pan=0 +96 %font "FluidR3_GM.sf2" 0 96 amp=37 pan=0 +97 %font "FluidR3_GM.sf2" 0 97 amp=74 pan=0 +98 %font "FluidR3_GM.sf2" 0 98 amp=132 pan=0 +99 %font "FluidR3_GM.sf2" 0 99 amp=117 pan=0 +100 %font "FluidR3_GM.sf2" 0 100 amp=64 pan=0 +101 %font "FluidR3_GM.sf2" 0 101 amp=53 pan=0 +102 %font "FluidR3_GM.sf2" 0 102 amp=51 pan=0 +103 %font "FluidR3_GM.sf2" 0 103 amp=110 pan=0 +104 %font "FluidR3_GM.sf2" 0 104 amp=66 pan=0 +105 %font "FluidR3_GM.sf2" 0 105 amp=120 pan=0 +106 %font "FluidR3_GM.sf2" 0 106 amp=77 pan=0 +107 %font "FluidR3_GM.sf2" 0 107 amp=182 pan=0 +108 %font "FluidR3_GM.sf2" 0 108 amp=88 pan=0 +109 %font "FluidR3_GM.sf2" 0 109 amp=62 pan=0 +110 %font "FluidR3_GM.sf2" 0 110 amp=45 pan=0 +111 %font "FluidR3_GM.sf2" 0 111 amp=78 pan=0 +112 %font "FluidR3_GM.sf2" 0 112 amp=72 pan=0 +113 %font "FluidR3_GM.sf2" 0 113 amp=122 pan=0 +114 %font "FluidR3_GM.sf2" 0 114 amp=47 pan=0 +115 %font "FluidR3_GM.sf2" 0 115 amp=142 pan=0 +116 %font "FluidR3_GM.sf2" 0 116 amp=61 pan=0 +117 %font "FluidR3_GM.sf2" 0 117 amp=83 pan=0 +118 %font "FluidR3_GM.sf2" 0 118 amp=42 pan=0 +119 %font "FluidR3_GM.sf2" 0 119 amp=75 pan=0 +120 %font "FluidR3_GM.sf2" 0 120 amp=56 pan=0 +121 %font "FluidR3_GM.sf2" 0 121 amp=13 pan=0 +122 %font "FluidR3_GM.sf2" 0 122 amp=113 pan=0 +123 %font "FluidR3_GM.sf2" 0 123 amp=80 pan=0 +124 %font "FluidR3_GM.sf2" 0 124 amp=91 pan=0 +125 %font "FluidR3_GM.sf2" 0 125 amp=67 pan=0 +126 %font "FluidR3_GM.sf2" 0 126 amp=31 pan=0 +127 %font "FluidR3_GM.sf2" 0 127 amp=117 pan=0 + +bank 8 +4 %font "FluidR3_GM.sf2" 8 4 amp=46 pan=0 +5 %font "FluidR3_GM.sf2" 8 5 amp=37 pan=0 +6 %font "FluidR3_GM.sf2" 8 6 amp=57 pan=0 +14 %font "FluidR3_GM.sf2" 8 14 amp=35 pan=0 +16 %font "FluidR3_GM.sf2" 8 16 amp=118 pan=0 +17 %font "FluidR3_GM.sf2" 8 17 amp=96 pan=0 +19 %font "FluidR3_GM.sf2" 8 19 amp=78 pan=0 +21 %font "FluidR3_GM.sf2" 8 21 amp=24 pan=0 +24 %font "FluidR3_GM.sf2" 8 24 amp=123 pan=0 +25 %font "FluidR3_GM.sf2" 8 25 amp=114 pan=0 +26 %font "FluidR3_GM.sf2" 8 26 amp=111 pan=0 +28 %font "FluidR3_GM.sf2" 8 28 amp=25 pan=0 +30 %font "FluidR3_GM.sf2" 8 30 amp=38 pan=0 +31 %font "FluidR3_GM.sf2" 8 31 amp=109 pan=0 +38 %font "FluidR3_GM.sf2" 8 38 amp=59 pan=0 +39 %font "FluidR3_GM.sf2" 8 39 amp=51 pan=0 +40 %font "FluidR3_GM.sf2" 8 40 amp=46 pan=0 +48 %font "FluidR3_GM.sf2" 8 48 amp=52 pan=0 +50 %font "FluidR3_GM.sf2" 8 50 amp=32 pan=0 +61 %font "FluidR3_GM.sf2" 8 61 amp=87 pan=0 +62 %font "FluidR3_GM.sf2" 8 62 amp=49 pan=0 +63 %font "FluidR3_GM.sf2" 8 63 amp=78 pan=0 +80 %font "FluidR3_GM.sf2" 8 80 amp=84 pan=0 +107 %font "FluidR3_GM.sf2" 8 107 amp=93 pan=0 +115 %font "FluidR3_GM.sf2" 8 115 amp=115 pan=0 +116 %font "FluidR3_GM.sf2" 8 116 amp=62 pan=0 +117 %font "FluidR3_GM.sf2" 8 117 amp=73 pan=0 +118 %font "FluidR3_GM.sf2" 8 118 amp=131 pan=0 + +bank 9 +125 %font "FluidR3_GM.sf2" 9 125 amp=51 pan=0 + +bank 16 +25 %font "FluidR3_GM.sf2" 16 25 amp=82 pan=0 + +bank 126 +0 %font "FluidR3_GM.sf2" 0 1 amp=55 pan=0 +1 %font "FluidR3_GM.sf2" 0 1 amp=55 pan=0 +2 %font "FluidR3_GM.sf2" 0 1 amp=55 pan=0 +3 %font "FluidR3_GM.sf2" 0 3 amp=31 pan=0 +4 %font "FluidR3_GM.sf2" 0 0 amp=40 pan=0 +5 %font "FluidR3_GM.sf2" 0 1 amp=55 pan=0 +6 %font "FluidR3_GM.sf2" 0 1 amp=55 pan=0 +7 %font "FluidR3_GM.sf2" 0 4 amp=40 pan=0 +8 %font "FluidR3_GM.sf2" 0 4 amp=35 pan=0 +9 %font "FluidR3_GM.sf2" 0 5 amp=37 pan=0 +10 %font "FluidR3_GM.sf2" 0 25 amp=106 pan=0 +11 %font "FluidR3_GM.sf2" 0 25 amp=107 pan=0 +12 %font "FluidR3_GM.sf2" 0 26 amp=41 pan=0 +13 %font "FluidR3_GM.sf2" 0 26 amp=47 pan=0 +14 %font "FluidR3_GM.sf2" 0 28 amp=109 pan=0 +15 %font "FluidR3_GM.sf2" 0 36 amp=92 pan=0 +16 %font "FluidR3_GM.sf2" 0 36 amp=92 pan=0 +17 %font "FluidR3_GM.sf2" 0 36 amp=92 pan=0 +18 %font "FluidR3_GM.sf2" 0 36 amp=92 pan=0 +19 %font "FluidR3_GM.sf2" 0 37 amp=98 pan=0 +20 %font "FluidR3_GM.sf2" 0 37 amp=98 pan=0 +21 %font "FluidR3_GM.sf2" 0 37 amp=98 pan=0 +22 %font "FluidR3_GM.sf2" 0 37 amp=98 pan=0 +23 %font "FluidR3_GM.sf2" 0 33 amp=91 pan=0 +24 %font "FluidR3_GM.sf2" 0 33 amp=92 pan=0 +25 %font "FluidR3_GM.sf2" 0 34 amp=137 pan=0 +26 %font "FluidR3_GM.sf2" 0 34 amp=138 pan=0 +27 %font "FluidR3_GM.sf2" 0 35 amp=107 pan=0 +28 %font "FluidR3_GM.sf2" 0 32 amp=195 pan=0 +29 %font "FluidR3_GM.sf2" 0 52 amp=78 pan=0 +30 %font "FluidR3_GM.sf2" 0 52 amp=77 pan=0 +31 %font "FluidR3_GM.sf2" 0 52 amp=78 pan=0 +32 %font "FluidR3_GM.sf2" 0 52 amp=78 pan=0 +33 %font "FluidR3_GM.sf2" 0 49 amp=72 pan=0 +34 %font "FluidR3_GM.sf2" 0 48 amp=64 pan=0 +35 %font "FluidR3_GM.sf2" 0 50 amp=42 pan=0 +36 %font "FluidR3_GM.sf2" 0 50 amp=32 pan=0 +37 %font "FluidR3_GM.sf2" 0 16 amp=70 pan=0 +38 %font "FluidR3_GM.sf2" 0 16 amp=98 pan=0 +39 %font "FluidR3_GM.sf2" 0 16 amp=98 pan=0 +40 %font "FluidR3_GM.sf2" 0 17 amp=144 pan=0 +41 %font "FluidR3_GM.sf2" 0 16 amp=98 pan=0 +42 %font "FluidR3_GM.sf2" 0 16 amp=98 pan=0 +43 %font "FluidR3_GM.sf2" 0 17 amp=144 pan=0 +44 %font "FluidR3_GM.sf2" 0 17 amp=144 pan=0 +45 %font "FluidR3_GM.sf2" 0 17 amp=144 pan=0 +46 %font "FluidR3_GM.sf2" 0 56 amp=94 pan=0 +47 %font "FluidR3_GM.sf2" 0 56 amp=95 pan=0 +48 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +49 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +50 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +51 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +52 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +53 %font "FluidR3_GM.sf2" 0 57 amp=38 pan=0 +54 %font "FluidR3_GM.sf2" 0 65 amp=29 pan=0 +55 %font "FluidR3_GM.sf2" 0 66 amp=41 pan=0 +56 %font "FluidR3_GM.sf2" 0 67 amp=65 pan=0 +57 %font "FluidR3_GM.sf2" 0 65 amp=29 pan=0 +58 %font "FluidR3_GM.sf2" 0 61 amp=47 pan=0 +59 %font "FluidR3_GM.sf2" 0 61 amp=47 pan=0 +60 %font "FluidR3_GM.sf2" 0 61 amp=56 pan=0 +61 %font "FluidR3_GM.sf2" 0 61 amp=56 pan=0 +62 %font "FluidR3_GM.sf2" 0 61 amp=46 pan=0 +63 %font "FluidR3_GM.sf2" 0 55 amp=116 pan=0 + +bank 127 +8 %font "FluidR3_GM.sf2" 0 16 amp=59 pan=0 +9 %font "FluidR3_GM.sf2" 0 17 amp=87 pan=0 +10 %font "FluidR3_GM.sf2" 0 18 amp=86 pan=0 +11 %font "FluidR3_GM.sf2" 0 18 amp=64 pan=0 +12 %font "FluidR3_GM.sf2" 0 19 amp=55 pan=0 +13 %font "FluidR3_GM.sf2" 0 19 amp=94 pan=0 +14 %font "FluidR3_GM.sf2" 0 20 amp=18 pan=0 +15 %font "FluidR3_GM.sf2" 0 21 amp=45 pan=0 +16 %font "FluidR3_GM.sf2" 0 6 amp=60 pan=0 +17 %font "FluidR3_GM.sf2" 0 6 amp=53 pan=0 +18 %font "FluidR3_GM.sf2" 0 6 amp=60 pan=0 +19 %font "FluidR3_GM.sf2" 0 7 amp=40 pan=0 +20 %font "FluidR3_GM.sf2" 0 7 amp=71 pan=0 +21 %font "FluidR3_GM.sf2" 0 7 amp=46 pan=0 +22 %font "FluidR3_GM.sf2" 0 8 amp=18 pan=0 +23 %font "FluidR3_GM.sf2" 0 8 amp=19 pan=0 +24 %font "FluidR3_GM.sf2" 0 62 amp=83 pan=0 +25 %font "FluidR3_GM.sf2" 0 63 amp=141 pan=0 +26 %font "FluidR3_GM.sf2" 0 62 amp=88 pan=0 +27 %font "FluidR3_GM.sf2" 0 63 amp=222 pan=0 +28 %font "FluidR3_GM.sf2" 0 38 amp=38 pan=0 +29 %font "FluidR3_GM.sf2" 0 39 amp=10 pan=0 +30 %font "FluidR3_GM.sf2" 0 38 amp=38 pan=0 +31 %font "FluidR3_GM.sf2" 0 39 amp=14 pan=0 +32 %font "FluidR3_GM.sf2" 0 88 amp=108 pan=0 +33 %font "FluidR3_GM.sf2" 0 89 amp=12 pan=0 +34 %font "FluidR3_GM.sf2" 0 52 amp=46 pan=0 +35 %font "FluidR3_GM.sf2" 0 113 amp=131 pan=0 +36 %font "FluidR3_GM.sf2" 0 97 amp=74 pan=0 +37 %font "FluidR3_GM.sf2" 0 96 amp=27 pan=0 +38 %font "FluidR3_GM.sf2" 0 91 amp=32 pan=0 +39 %font "FluidR3_GM.sf2" 0 85 amp=30 pan=0 +40 %font "FluidR3_GM.sf2" 0 102 amp=83 pan=0 +41 %font "FluidR3_GM.sf2" 0 101 amp=85 pan=0 +42 %font "FluidR3_GM.sf2" 0 68 amp=21 pan=0 +43 %font "FluidR3_GM.sf2" 0 95 amp=94 pan=0 +44 %font "FluidR3_GM.sf2" 0 86 amp=17 pan=0 +45 %font "FluidR3_GM.sf2" 0 103 amp=116 pan=0 +46 %font "FluidR3_GM.sf2" 0 88 amp=41 pan=0 +47 %font "FluidR3_GM.sf2" 0 80 amp=22 pan=0 +48 %font "FluidR3_GM.sf2" 0 48 amp=55 pan=0 +49 %font "FluidR3_GM.sf2" 0 49 amp=69 pan=0 +51 %font "FluidR3_GM.sf2" 0 45 amp=25 pan=0 +52 %font "FluidR3_GM.sf2" 0 40 amp=35 pan=0 +53 %font "FluidR3_GM.sf2" 0 40 amp=32 pan=0 +54 %font "FluidR3_GM.sf2" 0 42 amp=40 pan=0 +55 %font "FluidR3_GM.sf2" 0 42 amp=40 pan=0 +56 %font "FluidR3_GM.sf2" 0 43 amp=79 pan=0 +57 %font "FluidR3_GM.sf2" 0 46 amp=26 pan=0 +58 %font "FluidR3_GM.sf2" 0 46 amp=35 pan=0 +59 %font "FluidR3_GM.sf2" 0 24 amp=60 pan=0 +60 %font "FluidR3_GM.sf2" 0 24 amp=46 pan=0 +61 %font "FluidR3_GM.sf2" 0 26 amp=39 pan=0 +62 %font "FluidR3_GM.sf2" 0 27 amp=83 pan=0 +63 %font "FluidR3_GM.sf2" 0 104 amp=40 pan=0 +64 %font "FluidR3_GM.sf2" 0 32 amp=85 pan=0 +65 %font "FluidR3_GM.sf2" 0 33 amp=51 pan=0 +66 %font "FluidR3_GM.sf2" 0 34 amp=67 pan=0 +67 %font "FluidR3_GM.sf2" 0 39 amp=20 pan=0 +68 %font "FluidR3_GM.sf2" 0 36 amp=71 pan=0 +69 %font "FluidR3_GM.sf2" 0 37 amp=72 pan=0 +70 %font "FluidR3_GM.sf2" 0 35 amp=58 pan=0 +71 %font "FluidR3_GM.sf2" 0 35 amp=42 pan=0 +72 %font "FluidR3_GM.sf2" 0 73 amp=19 pan=0 +73 %font "FluidR3_GM.sf2" 0 73 amp=33 pan=0 +74 %font "FluidR3_GM.sf2" 0 72 amp=47 pan=0 +75 %font "FluidR3_GM.sf2" 0 72 amp=30 pan=0 +76 %font "FluidR3_GM.sf2" 0 74 amp=64 pan=0 +77 %font "FluidR3_GM.sf2" 0 75 amp=40 pan=0 +78 %font "FluidR3_GM.sf2" 0 64 amp=53 pan=0 +79 %font "FluidR3_GM.sf2" 0 65 amp=24 pan=0 +80 %font "FluidR3_GM.sf2" 0 66 amp=54 pan=0 +81 %font "FluidR3_GM.sf2" 0 67 amp=50 pan=0 +82 %font "FluidR3_GM.sf2" 0 71 amp=25 pan=0 +83 %font "FluidR3_GM.sf2" 0 71 amp=22 pan=0 +84 %font "FluidR3_GM.sf2" 0 68 amp=35 pan=0 +85 %font "FluidR3_GM.sf2" 0 69 amp=66 pan=0 +86 %font "FluidR3_GM.sf2" 0 70 amp=35 pan=0 +87 %font "FluidR3_GM.sf2" 0 22 amp=56 pan=0 +88 %font "FluidR3_GM.sf2" 0 56 amp=142 pan=0 +89 %font "FluidR3_GM.sf2" 0 56 amp=124 pan=0 +90 %font "FluidR3_GM.sf2" 0 57 amp=88 pan=0 +91 %font "FluidR3_GM.sf2" 0 57 amp=51 pan=0 +92 %font "FluidR3_GM.sf2" 0 60 amp=98 pan=0 +93 %font "FluidR3_GM.sf2" 0 60 amp=136 pan=0 +94 %font "FluidR3_GM.sf2" 0 58 amp=63 pan=0 +95 %font "FluidR3_GM.sf2" 0 61 amp=53 pan=0 +96 %font "FluidR3_GM.sf2" 0 61 amp=47 pan=0 +97 %font "FluidR3_GM.sf2" 0 11 amp=28 pan=0 +98 %font "FluidR3_GM.sf2" 0 11 amp=31 pan=0 +99 %font "FluidR3_GM.sf2" 0 12 amp=14 pan=0 +100 %font "FluidR3_GM.sf2" 0 88 amp=38 pan=0 +101 %font "FluidR3_GM.sf2" 0 9 amp=35 pan=0 +102 %font "FluidR3_GM.sf2" 0 14 amp=48 pan=0 +103 %font "FluidR3_GM.sf2" 0 13 amp=47 pan=0 +104 %font "FluidR3_GM.sf2" 0 12 amp=21 pan=0 +105 %font "FluidR3_GM.sf2" 0 107 amp=89 pan=0 +106 %font "FluidR3_GM.sf2" 0 111 amp=53 pan=0 +107 %font "FluidR3_GM.sf2" 0 77 amp=49 pan=0 +108 %font "FluidR3_GM.sf2" 0 78 amp=63 pan=0 +109 %font "FluidR3_GM.sf2" 0 78 amp=32 pan=0 +110 %font "FluidR3_GM.sf2" 0 76 amp=44 pan=0 +111 %font "FluidR3_GM.sf2" 0 76 amp=48 pan=0 +112 %font "FluidR3_GM.sf2" 0 47 amp=28 pan=0 +113 %font "FluidR3_GM.sf2" 0 117 amp=42 pan=0 +114 %font "FluidR3_GM.sf2" 0 118 amp=13 pan=0 +115 %font "FluidR3_GM.sf2" 0 118 amp=14 pan=0 +116 %font "FluidR3_GM.sf2" 0 118 amp=22 pan=0 +117 %font "FluidR3_GM.sf2" 0 116 amp=52 pan=0 +118 %font "FluidR3_GM.sf2" 0 116 amp=18 pan=0 +119 %font "FluidR3_GM.sf2" 128 0 49 amp=34 pan=0 # Crsh 1(L) Crsh 1(R) + +drumset 0 +0 %font "FluidR3_GM.sf2" 128 0 35 amp=206 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +1 %font "FluidR3_GM.sf2" 128 0 35 amp=138 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +2 %font "FluidR3_GM.sf2" 128 1 35 amp=189 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +3 %font "FluidR3_GM.sf2" 128 1 35 amp=129 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +4 %font "FluidR3_GM.sf2" 128 0 35 amp=100 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +5 %font "FluidR3_GM.sf2" 128 0 35 amp=107 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +6 %font "FluidR3_GM.sf2" 128 32 35 amp=89 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +7 %font "FluidR3_GM.sf2" 128 32 35 amp=119 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +8 %font "FluidR3_GM.sf2" 128 8 35 amp=249 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +9 %font "FluidR3_GM.sf2" 128 8 35 amp=143 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +10 %font "FluidR3_GM.sf2" 128 16 35 amp=86 pan=0 # Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R +11 %font "FluidR3_GM.sf2" 128 16 36 amp=85 pan=0 # Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R +12 %font "FluidR3_GM.sf2" 128 24 35 amp=86 pan=0 # Elec Kick1(L) Elec Kick1(R) +13 %font "FluidR3_GM.sf2" 128 24 36 amp=219 pan=0 # Elec Kick2(L) Elec Kick2(R) +14 %font "FluidR3_GM.sf2" 128 25 35 amp=59 pan=0 # 808 Kick 1 808 Kick 1 +15 %font "FluidR3_GM.sf2" 128 25 36 amp=47 pan=0 # 808 Kick 2 808 Kick 2 +16 %font "FluidR3_GM.sf2" 128 25 35 amp=60 pan=0 # 808 Kick 1 808 Kick 1 +27 %font "FluidR3_GM.sf2" 128 0 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 0 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 0 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 0 30 amp=27 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 0 31 amp=119 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 0 32 amp=128 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 0 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 0 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 0 35 amp=129 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +36 %font "FluidR3_GM.sf2" 128 0 35 amp=141 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +37 %font "FluidR3_GM.sf2" 128 0 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 0 38 amp=110 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 0 39 amp=38 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 0 40 amp=241 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 0 41 amp=105 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 0 42 amp=20 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 0 43 amp=73 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 0 44 amp=10 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 0 45 amp=132 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 0 46 amp=89 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 0 47 amp=167 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 0 48 amp=148 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 0 49 amp=79 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 0 50 amp=78 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 0 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 0 52 amp=84 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 0 53 amp=55 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 0 54 amp=62 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 0 55 amp=49 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 0 56 amp=100 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 0 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 0 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 0 59 amp=25 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 0 60 amp=9 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 0 61 amp=55 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 0 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 0 63 amp=80 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 0 64 amp=46 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 0 65 amp=153 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 0 66 amp=96 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 0 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 0 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 0 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 0 70 amp=49 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 0 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 0 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 0 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 0 74 amp=33 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 0 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 0 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 0 77 amp=131 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 0 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 0 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 0 80 amp=44 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 0 81 amp=64 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 0 82 amp=249 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 0 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 0 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 0 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 0 86 amp=48 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 0 87 amp=56 pan=-31 # Long Taiko Hit Long Taiko Hit +97 %font "FluidR3_GM.sf2" 128 0 38 amp=108 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +98 %font "FluidR3_GM.sf2" 128 0 40 amp=130 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +99 %font "FluidR3_GM.sf2" 128 1 38 amp=94 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +100 %font "FluidR3_GM.sf2" 128 1 40 amp=79 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +101 %font "FluidR3_GM.sf2" 128 0 40 amp=220 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +102 %font "FluidR3_GM.sf2" 128 0 38 amp=109 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +103 %font "FluidR3_GM.sf2" 128 0 40 amp=160 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +104 %font "FluidR3_GM.sf2" 128 0 38 amp=133 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +105 %font "FluidR3_GM.sf2" 128 32 38 amp=88 pan=0 # Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) +106 %font "FluidR3_GM.sf2" 128 32 40 amp=138 pan=0 # Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) +107 %font "FluidR3_GM.sf2" 128 8 38 amp=75 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +108 %font "FluidR3_GM.sf2" 128 8 40 amp=92 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +109 %font "FluidR3_GM.sf2" 128 16 38 amp=74 pan=0 # Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) +110 %font "FluidR3_GM.sf2" 128 16 40 amp=104 pan=0 # Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) +111 %font "FluidR3_GM.sf2" 128 24 40 amp=76 pan=0 # Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) +112 %font "FluidR3_GM.sf2" 128 11 38 amp=67 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +113 %font "FluidR3_GM.sf2" 128 11 40 amp=100 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +114 %font "FluidR3_GM.sf2" 128 11 38 amp=71 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +115 %font "FluidR3_GM.sf2" 128 24 40 amp=51 pan=0 # Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) +116 %font "FluidR3_GM.sf2" 128 24 38 amp=99 pan=0 # Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) +117 %font "FluidR3_GM.sf2" 128 24 38 amp=155 pan=0 # Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) +118 %font "FluidR3_GM.sf2" 128 25 38 amp=39 pan=0 # 808 Snare 1 808 Snare 1 +119 %font "FluidR3_GM.sf2" 128 25 38 amp=34 pan=0 # 808 Snare 1 808 Snare 1 +120 %font "FluidR3_GM.sf2" 128 25 40 amp=33 pan=0 # 808 Snare 2 808 Snare 2 +121 %font "FluidR3_GM.sf2" 128 25 38 amp=27 pan=0 # 808 Snare 1 808 Snare 1 +122 %font "FluidR3_GM.sf2" 128 25 40 amp=48 pan=0 # 808 Snare 2 808 Snare 2 +123 %font "FluidR3_GM.sf2" 128 9 38 amp=79 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +124 %font "FluidR3_GM.sf2" 128 10 38 amp=58 pan=0 # RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) +125 %font "FluidR3_GM.sf2" 128 11 38 amp=113 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +126 %font "FluidR3_GM.sf2" 128 11 38 amp=77 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +127 %font "FluidR3_GM.sf2" 128 11 38 amp=88 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) + +drumset 1 +27 %font "FluidR3_GM.sf2" 128 1 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 1 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 1 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 1 30 amp=43 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 1 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 1 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 1 33 amp=53 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 1 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 1 35 amp=139 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +36 %font "FluidR3_GM.sf2" 128 1 35 amp=210 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +37 %font "FluidR3_GM.sf2" 128 1 37 amp=186 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 1 38 amp=154 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +39 %font "FluidR3_GM.sf2" 128 1 39 amp=58 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 1 40 amp=52 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +41 %font "FluidR3_GM.sf2" 128 1 41 amp=153 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 1 42 amp=33 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 1 43 amp=73 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 1 44 amp=14 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 1 45 amp=132 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 1 46 amp=47 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 1 47 amp=112 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 1 48 amp=217 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 1 49 amp=83 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 1 50 amp=247 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 1 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 1 52 amp=65 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 1 53 amp=24 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 1 54 amp=17 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 1 55 amp=51 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 1 56 amp=103 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 1 57 amp=47 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 1 58 amp=64 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 1 59 amp=26 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 1 60 amp=87 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 1 61 amp=88 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 1 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 1 63 amp=78 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 1 64 amp=46 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 1 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 1 66 amp=145 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 1 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 1 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 1 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 1 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 1 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 1 72 amp=76 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 1 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 1 74 amp=32 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 1 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 1 76 amp=69 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 1 77 amp=81 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 1 78 amp=105 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 1 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 1 80 amp=45 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 1 81 amp=63 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 1 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 1 83 amp=165 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 1 84 amp=95 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 1 85 amp=11 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 1 86 amp=46 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 1 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 2 +27 %font "FluidR3_GM.sf2" 128 2 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 2 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 2 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 2 30 amp=27 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 2 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 2 32 amp=129 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 2 33 amp=85 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 2 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 2 35 amp=110 pan=0 # Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) +37 %font "FluidR3_GM.sf2" 128 2 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 2 38 amp=281 pan=0 # Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) +39 %font "FluidR3_GM.sf2" 128 2 39 amp=38 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 2 40 amp=221 pan=0 # Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) +41 %font "FluidR3_GM.sf2" 128 2 41 amp=105 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 2 42 amp=20 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 2 43 amp=106 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 2 44 amp=16 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 2 45 amp=194 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 2 46 amp=62 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 2 47 amp=114 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 2 48 amp=148 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 2 49 amp=81 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 2 50 amp=245 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 2 51 amp=25 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 2 52 amp=38 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 2 53 amp=21 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 2 54 amp=17 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 2 55 amp=71 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 2 56 amp=102 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 2 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 2 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 2 59 amp=16 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 2 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 2 61 amp=88 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 2 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 2 63 amp=78 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 2 64 amp=45 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 2 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 2 66 amp=95 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 2 67 amp=92 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 2 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 2 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 2 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 2 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 2 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 2 73 amp=69 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 2 74 amp=30 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 2 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 2 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 2 77 amp=83 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 2 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 2 79 amp=49 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 2 80 amp=63 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 2 81 amp=63 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 2 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 2 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 2 84 amp=35 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 2 85 amp=127 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 2 86 amp=51 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 2 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 3 +27 %font "FluidR3_GM.sf2" 128 3 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 3 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 3 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 3 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 3 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 3 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 3 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 3 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 3 35 amp=100 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +37 %font "FluidR3_GM.sf2" 128 3 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 3 38 amp=100 pan=0 # Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 3 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 3 40 amp=100 pan=0 # Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 3 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 3 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 3 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 3 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 3 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 3 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 3 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 3 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 3 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 3 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 3 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 3 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 3 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 3 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 3 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 3 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 3 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 3 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 3 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 3 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 3 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 3 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 3 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 3 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 3 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 3 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 3 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 3 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 3 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 3 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 3 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 3 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 3 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 3 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 3 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 3 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 3 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 3 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 3 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 3 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 3 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 3 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 3 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 3 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 3 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 3 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 3 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 4 +27 %font "FluidR3_GM.sf2" 128 4 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 4 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 4 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 4 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 4 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 4 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 4 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 4 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 4 35 amp=100 pan=0 # Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) +37 %font "FluidR3_GM.sf2" 128 4 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 4 38 amp=100 pan=0 # Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) +39 %font "FluidR3_GM.sf2" 128 4 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 4 40 amp=100 pan=0 # Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) +41 %font "FluidR3_GM.sf2" 128 4 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 4 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 4 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 4 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 4 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 4 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 4 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 4 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 4 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 4 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 4 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 4 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 4 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 4 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 4 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 4 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 4 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 4 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 4 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 4 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 4 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 4 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 4 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 4 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 4 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 4 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 4 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 4 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 4 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 4 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 4 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 4 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 4 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 4 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 4 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 4 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 4 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 4 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 4 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 4 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 4 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 4 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 4 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 4 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 4 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 4 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 4 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 5 +27 %font "FluidR3_GM.sf2" 128 5 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 5 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 5 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 5 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 5 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 5 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 5 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 5 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 5 35 amp=100 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +37 %font "FluidR3_GM.sf2" 128 5 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 5 38 amp=100 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 5 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 5 40 amp=100 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 5 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 5 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 5 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 5 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 5 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 5 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 5 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 5 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 5 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 5 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 5 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 5 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 5 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 5 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 5 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 5 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 5 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 5 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 5 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 5 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 5 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 5 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 5 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 5 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 5 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 5 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 5 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 5 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 5 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 5 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 5 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 5 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 5 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 5 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 5 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 5 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 5 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 5 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 5 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 5 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 5 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 5 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 5 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 5 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 5 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 5 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 5 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 6 +27 %font "FluidR3_GM.sf2" 128 6 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 6 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 6 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 6 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 6 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 6 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 6 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 6 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 6 35 amp=100 pan=0 # Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) +37 %font "FluidR3_GM.sf2" 128 6 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 6 38 amp=100 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 6 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 6 40 amp=100 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 6 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 6 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 6 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 6 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 6 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 6 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 6 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 6 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 6 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 6 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 6 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 6 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 6 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 6 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 6 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 6 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 6 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 6 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 6 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 6 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 6 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 6 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 6 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 6 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 6 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 6 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 6 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 6 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 6 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 6 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 6 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 6 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 6 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 6 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 6 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 6 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 6 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 6 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 6 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 6 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 6 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 6 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 6 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 6 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 6 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 6 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 6 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 7 +27 %font "FluidR3_GM.sf2" 128 7 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 7 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 7 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 7 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 7 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 7 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 7 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 7 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 7 35 amp=100 pan=0 # Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) +37 %font "FluidR3_GM.sf2" 128 7 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 7 38 amp=100 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +39 %font "FluidR3_GM.sf2" 128 7 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 7 40 amp=100 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +41 %font "FluidR3_GM.sf2" 128 7 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 7 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 7 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 7 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 7 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 7 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 7 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 7 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 7 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 7 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 7 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 7 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 7 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 7 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 7 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 7 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 7 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 7 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 7 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 7 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 7 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 7 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 7 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 7 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 7 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 7 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 7 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 7 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 7 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 7 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 7 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 7 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 7 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 7 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 7 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 7 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 7 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 7 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 7 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 7 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 7 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 7 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 7 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 7 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 7 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 7 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 7 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 8 +27 %font "FluidR3_GM.sf2" 128 8 27 amp=45 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 8 28 amp=70 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 8 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 8 30 amp=27 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 8 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 8 32 amp=131 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 8 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 8 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 8 35 amp=149 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +37 %font "FluidR3_GM.sf2" 128 8 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 8 38 amp=125 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 8 39 amp=58 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 8 40 amp=126 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 8 41 amp=84 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 8 42 amp=20 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 8 43 amp=62 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 8 44 amp=31 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 8 45 amp=231 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 8 46 amp=64 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 8 47 amp=127 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 8 48 amp=129 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 8 49 amp=83 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 8 50 amp=238 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 8 51 amp=29 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 8 52 amp=84 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 8 53 amp=24 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 8 54 amp=63 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 8 55 amp=51 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 8 56 amp=158 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 8 57 amp=50 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 8 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 8 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 8 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 8 61 amp=53 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 8 62 amp=46 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 8 63 amp=78 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 8 64 amp=45 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 8 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 8 66 amp=96 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 8 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 8 68 amp=103 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 8 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 8 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 8 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 8 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 8 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 8 74 amp=30 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 8 75 amp=123 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 8 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 8 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 8 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 8 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 8 80 amp=64 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 8 81 amp=64 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 8 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 8 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 8 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 8 85 amp=84 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 8 86 amp=71 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 8 87 amp=78 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 9 +27 %font "FluidR3_GM.sf2" 128 9 27 amp=32 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 9 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 9 29 amp=52 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 9 30 amp=35 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 9 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 9 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 9 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 9 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 9 35 amp=288 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +36 %font "FluidR3_GM.sf2" 128 25 36 amp=68 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 9 37 amp=210 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 9 38 amp=79 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +39 %font "FluidR3_GM.sf2" 128 9 39 amp=38 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 9 40 amp=57 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +41 %font "FluidR3_GM.sf2" 128 9 41 amp=237 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 9 42 amp=30 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 9 43 amp=95 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 9 44 amp=20 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 9 45 amp=178 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 9 46 amp=64 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 9 47 amp=159 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 9 48 amp=91 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 9 49 amp=66 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 9 50 amp=100 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 9 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 9 52 amp=28 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 9 53 amp=55 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 9 54 amp=20 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 9 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 9 56 amp=55 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 9 57 amp=50 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 9 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 9 59 amp=26 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 9 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 9 61 amp=54 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 9 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 9 63 amp=78 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 9 64 amp=72 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 9 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 9 66 amp=95 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 9 67 amp=58 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 9 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 9 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 9 70 amp=48 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 9 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 9 72 amp=76 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 9 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 9 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 9 75 amp=68 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 9 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 9 77 amp=133 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 9 78 amp=87 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 9 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 9 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 9 81 amp=81 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 9 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 9 83 amp=165 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 9 84 amp=35 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 9 85 amp=84 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 9 86 amp=48 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 9 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 10 +27 %font "FluidR3_GM.sf2" 128 10 27 amp=32 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 10 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 10 29 amp=32 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 10 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 10 31 amp=76 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 10 32 amp=178 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 10 33 amp=53 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 10 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 10 35 amp=63 pan=0 # Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) +36 %font "FluidR3_GM.sf2" 128 25 36 amp=96 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 10 37 amp=118 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 10 38 amp=68 pan=0 # RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 10 39 amp=71 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 10 40 amp=70 pan=0 # RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 10 41 amp=237 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 10 42 amp=45 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 10 43 amp=95 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 10 44 amp=39 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 10 45 amp=178 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 10 46 amp=161 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 10 47 amp=159 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 10 48 amp=91 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 10 49 amp=72 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 10 50 amp=34 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 10 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 10 52 amp=28 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 10 53 amp=55 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 10 54 amp=94 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 10 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 10 56 amp=55 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 10 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 10 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 10 59 amp=26 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 10 60 amp=87 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 10 61 amp=54 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 10 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 10 63 amp=80 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 10 64 amp=46 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 10 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 10 66 amp=95 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 10 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 10 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 10 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 10 70 amp=48 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 10 71 amp=95 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 10 72 amp=76 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 10 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 10 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 10 75 amp=64 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 10 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 10 77 amp=131 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 10 78 amp=86 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 10 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 10 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 10 81 amp=53 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 10 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 10 83 amp=164 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 10 84 amp=53 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 10 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 10 86 amp=47 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 10 87 amp=56 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 11 +27 %font "FluidR3_GM.sf2" 128 11 27 amp=32 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 11 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 11 29 amp=32 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 11 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 11 31 amp=119 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 11 32 amp=175 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 11 33 amp=53 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 11 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 11 35 amp=184 pan=0 # Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) +36 %font "FluidR3_GM.sf2" 128 25 36 amp=111 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 11 37 amp=210 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 11 38 amp=61 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +39 %font "FluidR3_GM.sf2" 128 11 39 amp=57 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 11 40 amp=126 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +41 %font "FluidR3_GM.sf2" 128 11 41 amp=130 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 11 42 amp=36 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 11 43 amp=143 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 11 44 amp=52 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 11 45 amp=170 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 11 46 amp=106 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 11 47 amp=148 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 11 48 amp=218 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 11 49 amp=106 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 11 50 amp=160 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 11 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 11 52 amp=28 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 11 53 amp=41 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 11 54 amp=94 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 11 55 amp=72 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 11 56 amp=55 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 11 57 amp=58 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 11 58 amp=47 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 11 59 amp=21 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 11 60 amp=106 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 11 61 amp=97 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 11 62 amp=69 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 11 63 amp=89 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 11 64 amp=88 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 11 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 11 66 amp=145 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 11 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 11 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 11 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 11 70 amp=48 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 11 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 11 72 amp=76 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 11 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 11 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 11 75 amp=71 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 11 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 11 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 11 78 amp=133 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 11 79 amp=79 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 11 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 11 81 amp=53 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 11 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 11 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 11 84 amp=52 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 11 85 amp=127 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 11 86 amp=48 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 11 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 12 +27 %font "FluidR3_GM.sf2" 128 12 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 12 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 12 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 12 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 12 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 12 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 12 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 12 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 12 35 amp=100 pan=0 # Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) +37 %font "FluidR3_GM.sf2" 128 12 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 12 38 amp=100 pan=0 # Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) +39 %font "FluidR3_GM.sf2" 128 12 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 12 40 amp=100 pan=0 # Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) +41 %font "FluidR3_GM.sf2" 128 12 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 12 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 12 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 12 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 12 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 12 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 12 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 12 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 12 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 12 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 12 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 12 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 12 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 12 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 12 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 12 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 12 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 12 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 12 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 12 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 12 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 12 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 12 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 12 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 12 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 12 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 12 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 12 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 12 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 12 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 12 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 12 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 12 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 12 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 12 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 12 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 12 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 12 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 12 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 12 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 12 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 12 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 12 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 12 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 12 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 12 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 12 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 13 +27 %font "FluidR3_GM.sf2" 128 13 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 13 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 13 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 13 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 13 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 13 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 13 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 13 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 13 35 amp=100 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +37 %font "FluidR3_GM.sf2" 128 13 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 13 38 amp=100 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 13 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 13 40 amp=100 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 13 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 13 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 13 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 13 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 13 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 13 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 13 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 13 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 13 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 13 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 13 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 13 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 13 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 13 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 13 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 13 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 13 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 13 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 13 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 13 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 13 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 13 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 13 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 13 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 13 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 13 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 13 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 13 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 13 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 13 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 13 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 13 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 13 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 13 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 13 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 13 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 13 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 13 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 13 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 13 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 13 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 13 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 13 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 13 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 13 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 13 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 13 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 14 +27 %font "FluidR3_GM.sf2" 128 14 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 14 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 14 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 14 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 14 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 14 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 14 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 14 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 14 35 amp=100 pan=0 # Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) Std Kick 4(L) Std Kick 4(R) +37 %font "FluidR3_GM.sf2" 128 14 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 14 38 amp=100 pan=0 # Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) +39 %font "FluidR3_GM.sf2" 128 14 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 14 40 amp=100 pan=0 # Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) +41 %font "FluidR3_GM.sf2" 128 14 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 14 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 14 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 14 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 14 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 14 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 14 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 14 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 14 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 14 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 14 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 14 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 14 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 14 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 14 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 14 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 14 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 14 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 14 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 14 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 14 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 14 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 14 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 14 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 14 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 14 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 14 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 14 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 14 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 14 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 14 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 14 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 14 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 14 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 14 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 14 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 14 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 14 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 14 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 14 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 14 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 14 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 14 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 14 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 14 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 14 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 14 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 15 +27 %font "FluidR3_GM.sf2" 128 15 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 15 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 15 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 15 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 15 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 15 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 15 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 15 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 15 35 amp=100 pan=0 # Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) +37 %font "FluidR3_GM.sf2" 128 15 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 15 38 amp=100 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 15 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 15 40 amp=100 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 15 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 15 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 15 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 15 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 15 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 15 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 15 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 15 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 15 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 15 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 15 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 15 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 15 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 15 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 15 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 15 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 15 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 15 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 15 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 15 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 15 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 15 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 15 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 15 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 15 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 15 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 15 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 15 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 15 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 15 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 15 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 15 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 15 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 15 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 15 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 15 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 15 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 15 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 15 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 15 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 15 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 15 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 15 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 15 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 15 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 15 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 15 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 16 +27 %font "FluidR3_GM.sf2" 128 16 27 amp=45 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 16 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 16 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 16 30 amp=27 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 16 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 16 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 16 33 amp=86 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 16 34 amp=24 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 16 35 amp=147 pan=0 # Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R +36 %font "FluidR3_GM.sf2" 128 16 36 amp=80 pan=0 # Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R +37 %font "FluidR3_GM.sf2" 128 16 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 16 38 amp=105 pan=0 # Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) +39 %font "FluidR3_GM.sf2" 128 16 39 amp=93 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 16 40 amp=155 pan=0 # Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) +41 %font "FluidR3_GM.sf2" 128 16 41 amp=82 pan=-47 # Tom Floor(L) Tom Floor(R) +42 %font "FluidR3_GM.sf2" 128 16 42 amp=20 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 16 43 amp=79 pan=-28 # Tom Floor(L) Tom Floor(R) +44 %font "FluidR3_GM.sf2" 128 16 44 amp=10 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 16 45 amp=98 pan=-9 # Tom Low(L) Tom Low(R) +46 %font "FluidR3_GM.sf2" 128 16 46 amp=62 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 16 47 amp=59 pan=9 # Tom Med(L) Tom Med(R) +48 %font "FluidR3_GM.sf2" 128 16 48 amp=72 pan=28 # Tom Hi(L) Tom Hi(R) +49 %font "FluidR3_GM.sf2" 128 16 49 amp=83 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 16 50 amp=31 pan=47 # Tom Hi(L) Tom Hi(R) +51 %font "FluidR3_GM.sf2" 128 16 51 amp=29 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 16 52 amp=38 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 16 53 amp=24 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 16 54 amp=17 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 16 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 16 56 amp=103 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 16 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 16 58 amp=65 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 16 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 16 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 16 61 amp=55 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 16 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 16 63 amp=126 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 16 64 amp=70 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 16 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 16 66 amp=95 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 16 67 amp=58 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 16 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 16 69 amp=47 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 16 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 16 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 16 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 16 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 16 74 amp=32 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 16 75 amp=123 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 16 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 16 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 16 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 16 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 16 80 amp=45 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 16 81 amp=97 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 16 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 16 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 16 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 16 85 amp=84 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 16 86 amp=46 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 16 87 amp=78 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 17 +27 %font "FluidR3_GM.sf2" 128 17 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 17 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 17 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 17 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 17 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 17 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 17 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 17 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 17 35 amp=100 pan=0 # Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) Power Kick (L) Power Kick (R) +37 %font "FluidR3_GM.sf2" 128 17 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 17 38 amp=100 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +39 %font "FluidR3_GM.sf2" 128 17 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 17 40 amp=100 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +41 %font "FluidR3_GM.sf2" 128 17 41 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +42 %font "FluidR3_GM.sf2" 128 17 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 17 43 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +44 %font "FluidR3_GM.sf2" 128 17 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 17 45 amp=100 pan=0 # Tom Low(L) Tom Low(R) +46 %font "FluidR3_GM.sf2" 128 17 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 17 47 amp=100 pan=0 # Tom Med(L) Tom Med(R) +48 %font "FluidR3_GM.sf2" 128 17 48 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +49 %font "FluidR3_GM.sf2" 128 17 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 17 50 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +51 %font "FluidR3_GM.sf2" 128 17 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 17 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 17 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 17 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 17 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 17 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 17 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 17 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 17 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 17 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 17 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 17 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 17 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 17 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 17 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 17 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 17 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 17 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 17 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 17 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 17 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 17 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 17 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 17 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 17 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 17 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 17 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 17 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 17 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 17 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 17 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 17 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 17 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 17 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 17 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 17 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 17 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 18 +27 %font "FluidR3_GM.sf2" 128 18 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 18 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 18 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 18 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 18 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 18 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 18 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 18 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 18 35 amp=100 pan=0 # Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) Power Kick 2(L) Power Kick 2(R) +37 %font "FluidR3_GM.sf2" 128 18 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 18 38 amp=100 pan=0 # RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 18 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 18 40 amp=100 pan=0 # RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 18 41 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +42 %font "FluidR3_GM.sf2" 128 18 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 18 43 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +44 %font "FluidR3_GM.sf2" 128 18 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 18 45 amp=100 pan=0 # Tom Low(L) Tom Low(R) +46 %font "FluidR3_GM.sf2" 128 18 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 18 47 amp=100 pan=0 # Tom Med(L) Tom Med(R) +48 %font "FluidR3_GM.sf2" 128 18 48 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +49 %font "FluidR3_GM.sf2" 128 18 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 18 50 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +51 %font "FluidR3_GM.sf2" 128 18 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 18 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 18 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 18 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 18 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 18 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 18 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 18 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 18 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 18 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 18 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 18 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 18 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 18 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 18 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 18 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 18 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 18 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 18 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 18 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 18 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 18 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 18 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 18 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 18 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 18 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 18 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 18 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 18 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 18 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 18 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 18 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 18 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 18 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 18 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 18 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 18 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 19 +27 %font "FluidR3_GM.sf2" 128 19 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 19 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 19 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 19 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 19 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 19 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 19 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 19 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 19 35 amp=100 pan=0 # Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) Power Kick 3(L) Power Kick 3(R) +37 %font "FluidR3_GM.sf2" 128 19 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 19 38 amp=100 pan=0 # RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 19 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 19 40 amp=100 pan=0 # RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 19 41 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +42 %font "FluidR3_GM.sf2" 128 19 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 19 43 amp=100 pan=0 # Tom Floor(L) Tom Floor(R) +44 %font "FluidR3_GM.sf2" 128 19 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 19 45 amp=100 pan=0 # Tom Low(L) Tom Low(R) +46 %font "FluidR3_GM.sf2" 128 19 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 19 47 amp=100 pan=0 # Tom Med(L) Tom Med(R) +48 %font "FluidR3_GM.sf2" 128 19 48 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +49 %font "FluidR3_GM.sf2" 128 19 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 19 50 amp=100 pan=0 # Tom Hi(L) Tom Hi(R) +51 %font "FluidR3_GM.sf2" 128 19 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 19 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 19 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 19 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 19 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 19 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 19 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 19 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 19 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 19 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 19 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 19 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 19 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 19 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 19 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 19 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 19 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 19 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 19 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 19 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 19 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 19 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 19 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 19 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 19 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 19 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 19 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 19 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 19 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 19 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 19 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 19 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 19 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 19 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 19 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 19 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 19 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 24 +27 %font "FluidR3_GM.sf2" 128 24 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 24 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 24 29 amp=31 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 24 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 24 31 amp=74 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 24 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 24 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 24 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 24 35 amp=162 pan=0 # Elec Kick1(L) Elec Kick1(R) +36 %font "FluidR3_GM.sf2" 128 24 36 amp=265 pan=0 # Elec Kick2(L) Elec Kick2(R) +37 %font "FluidR3_GM.sf2" 128 24 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 24 38 amp=151 pan=0 # Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 24 39 amp=58 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 24 40 amp=67 pan=0 # Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) +41 %font "FluidR3_GM.sf2" 128 24 41 amp=180 pan=-47 # ElectTom(L) ElectTom(R) +42 %font "FluidR3_GM.sf2" 128 24 42 amp=33 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 24 43 amp=119 pan=-28 # ElectTom(L) ElectTom(R) +44 %font "FluidR3_GM.sf2" 128 24 44 amp=14 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 24 45 amp=114 pan=-9 # ElectTom(L) ElectTom(R) +46 %font "FluidR3_GM.sf2" 128 24 46 amp=47 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 24 47 amp=116 pan=9 # ElectTom(L) ElectTom(R) +48 %font "FluidR3_GM.sf2" 128 24 48 amp=171 pan=28 # ElectTom(L) ElectTom(R) +49 %font "FluidR3_GM.sf2" 128 24 49 amp=83 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 24 50 amp=53 pan=47 # ElectTom(L) ElectTom(R) +51 %font "FluidR3_GM.sf2" 128 24 51 amp=23 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 24 52 amp=28 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 24 53 amp=41 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 24 54 amp=97 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 24 55 amp=51 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 24 56 amp=101 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 24 57 amp=50 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 24 58 amp=27 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 24 59 amp=25 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 24 60 amp=86 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 24 61 amp=54 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 24 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 24 63 amp=79 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 24 64 amp=45 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 24 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 24 66 amp=96 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 24 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 24 68 amp=65 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 24 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 24 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 24 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 24 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 24 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 24 74 amp=30 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 24 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 24 76 amp=109 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 24 77 amp=82 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 24 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 24 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 24 80 amp=43 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 24 81 amp=64 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 24 82 amp=249 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 24 83 amp=103 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 24 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 24 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 24 86 amp=46 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 24 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 25 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=31 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=35 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=119 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=130 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=54 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 25 36 amp=70 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 25 37 amp=331 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 25 38 amp=29 pan=0 # 808 Snare 1 808 Snare 1 +39 %font "FluidR3_GM.sf2" 128 25 39 amp=45 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 25 40 amp=45 pan=0 # 808 Snare 2 808 Snare 2 +41 %font "FluidR3_GM.sf2" 128 25 41 amp=38 pan=-47 # 808 Tom 1 808 Tom 1 +42 %font "FluidR3_GM.sf2" 128 25 42 amp=21 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 25 43 amp=36 pan=-28 # 808 Tom 2 808 Tom 2 +44 %font "FluidR3_GM.sf2" 128 25 44 amp=70 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 25 45 amp=53 pan=-9 # 808 Tom 3 808 Tom 3 +46 %font "FluidR3_GM.sf2" 128 25 46 amp=78 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 25 47 amp=33 pan=9 # 808 Tom 4 808 Tom 4 +48 %font "FluidR3_GM.sf2" 128 25 48 amp=30 pan=28 # 808 Tom 5 808 Tom 5 +49 %font "FluidR3_GM.sf2" 128 25 49 amp=56 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 25 50 amp=46 pan=47 # 808 Tom 6 808 Tom 6 +51 %font "FluidR3_GM.sf2" 128 25 51 amp=22 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=65 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=24 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 25 54 amp=99 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=44 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=30 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=58 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=15 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=63 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=28 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=66 pan=-31 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=61 pan=-23 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=47 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=78 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=41 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=109 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=81 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=86 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=54 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=35 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=46 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=77 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 26 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=45 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=70 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=31 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=35 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=128 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=97 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 24 35 amp=104 pan=0 # Elec Kick1(L) Elec Kick1(R) +37 %font "FluidR3_GM.sf2" 128 25 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 11 38 amp=71 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +39 %font "FluidR3_GM.sf2" 128 25 39 amp=46 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 11 40 amp=190 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +41 %font "FluidR3_GM.sf2" 128 24 41 amp=123 pan=-47 # ElectTom(L) ElectTom(R) +42 %font "FluidR3_GM.sf2" 128 25 42 amp=34 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 24 43 amp=117 pan=-28 # ElectTom(L) ElectTom(R) +44 %font "FluidR3_GM.sf2" 128 25 44 amp=28 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 24 45 amp=116 pan=-9 # ElectTom(L) ElectTom(R) +46 %font "FluidR3_GM.sf2" 128 25 46 amp=112 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 24 47 amp=114 pan=9 # ElectTom(L) ElectTom(R) +48 %font "FluidR3_GM.sf2" 128 24 48 amp=117 pan=28 # ElectTom(L) ElectTom(R) +49 %font "FluidR3_GM.sf2" 128 25 49 amp=55 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 24 50 amp=53 pan=47 # ElectTom(L) ElectTom(R) +51 %font "FluidR3_GM.sf2" 128 25 51 amp=22 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=80 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=55 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 11 54 amp=59 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=31 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=9 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=53 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=13 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=65 pan=-39 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=48 pan=-31 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=65 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=49 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=32 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=53 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=109 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=86 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=53 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=158 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=165 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=46 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=54 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 27 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=32 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=31 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=35 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=178 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=78 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 25 36 amp=64 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 25 37 amp=352 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 25 38 amp=41 pan=0 # 808 Snare 1 808 Snare 1 +39 %font "FluidR3_GM.sf2" 128 25 39 amp=44 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 25 40 amp=50 pan=0 # 808 Snare 2 808 Snare 2 +41 %font "FluidR3_GM.sf2" 128 25 41 amp=60 pan=-47 # 808 Tom 1 808 Tom 1 +42 %font "FluidR3_GM.sf2" 128 25 42 amp=34 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 25 43 amp=70 pan=-28 # 808 Tom 2 808 Tom 2 +44 %font "FluidR3_GM.sf2" 128 25 44 amp=52 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 25 45 amp=51 pan=-9 # 808 Tom 3 808 Tom 3 +46 %font "FluidR3_GM.sf2" 128 25 46 amp=71 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 25 47 amp=29 pan=9 # 808 Tom 4 808 Tom 4 +48 %font "FluidR3_GM.sf2" 128 25 48 amp=61 pan=28 # 808 Tom 5 808 Tom 5 +49 %font "FluidR3_GM.sf2" 128 25 49 amp=72 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 25 50 amp=11 pan=47 # 808 Tom 6 808 Tom 6 +51 %font "FluidR3_GM.sf2" 128 25 51 amp=22 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=65 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=24 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 25 54 amp=30 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=72 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=91 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=58 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=19 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=70 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=63 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=28 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=70 pan=-39 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=90 pan=-31 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=47 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=141 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=23 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=81 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=87 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=161 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=256 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=158 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=36 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=47 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=78 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 28 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=70 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=32 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=178 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=86 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=24 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=78 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 25 36 amp=61 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 25 37 amp=352 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 25 38 amp=40 pan=0 # 808 Snare 1 808 Snare 1 +39 %font "FluidR3_GM.sf2" 128 25 39 amp=44 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 25 40 amp=69 pan=0 # 808 Snare 2 808 Snare 2 +41 %font "FluidR3_GM.sf2" 128 25 41 amp=71 pan=-47 # 808 Tom 1 808 Tom 1 +42 %font "FluidR3_GM.sf2" 128 25 42 amp=24 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 25 43 amp=33 pan=-28 # 808 Tom 2 808 Tom 2 +44 %font "FluidR3_GM.sf2" 128 25 44 amp=52 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 25 45 amp=33 pan=-9 # 808 Tom 3 808 Tom 3 +46 %font "FluidR3_GM.sf2" 128 25 46 amp=97 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 25 47 amp=30 pan=9 # 808 Tom 4 808 Tom 4 +48 %font "FluidR3_GM.sf2" 128 25 48 amp=36 pan=28 # 808 Tom 5 808 Tom 5 +49 %font "FluidR3_GM.sf2" 128 25 49 amp=55 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 25 50 amp=23 pan=47 # 808 Tom 6 808 Tom 6 +51 %font "FluidR3_GM.sf2" 128 25 51 amp=22 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=65 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=39 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 25 54 amp=100 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=73 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=56 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=58 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=15 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=63 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=44 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=65 pan=-39 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=63 pan=-31 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=103 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=87 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=36 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=86 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=50 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=155 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=256 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=165 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=53 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=48 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=56 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 29 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=32 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=52 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=119 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=178 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=70 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 25 36 amp=65 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 25 37 amp=150 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 25 38 amp=112 pan=0 # 808 Snare 1 808 Snare 1 +39 %font "FluidR3_GM.sf2" 128 25 39 amp=44 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 25 40 amp=88 pan=0 # 808 Snare 2 808 Snare 2 +41 %font "FluidR3_GM.sf2" 128 25 41 amp=60 pan=-47 # 808 Tom 1 808 Tom 1 +42 %font "FluidR3_GM.sf2" 128 25 42 amp=20 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 25 43 amp=55 pan=-28 # 808 Tom 2 808 Tom 2 +44 %font "FluidR3_GM.sf2" 128 25 44 amp=25 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 25 45 amp=55 pan=-9 # 808 Tom 3 808 Tom 3 +46 %font "FluidR3_GM.sf2" 128 25 46 amp=71 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 25 47 amp=23 pan=9 # 808 Tom 4 808 Tom 4 +48 %font "FluidR3_GM.sf2" 128 25 48 amp=21 pan=28 # 808 Tom 5 808 Tom 5 +49 %font "FluidR3_GM.sf2" 128 25 49 amp=107 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 25 50 amp=31 pan=47 # 808 Tom 6 808 Tom 6 +51 %font "FluidR3_GM.sf2" 128 25 51 amp=28 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=60 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=39 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 25 54 amp=100 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=30 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=49 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=19 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=9 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=54 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=13 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=66 pan=-39 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=50 pan=-31 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=78 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=33 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=33 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=131 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=134 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=53 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=84 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=72 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=55 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 30 +27 %font "FluidR3_GM.sf2" 128 25 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 25 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 25 29 amp=32 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 25 30 amp=57 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 25 31 amp=74 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 25 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 25 33 amp=54 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 25 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 25 35 amp=58 pan=0 # 808 Kick 1 808 Kick 1 +36 %font "FluidR3_GM.sf2" 128 25 36 amp=95 pan=0 # 808 Kick 2 808 Kick 2 +37 %font "FluidR3_GM.sf2" 128 25 37 amp=365 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 25 38 amp=65 pan=0 # 808 Snare 1 808 Snare 1 +39 %font "FluidR3_GM.sf2" 128 25 39 amp=30 pan=-16 # 808 Clap 808 Clap +40 %font "FluidR3_GM.sf2" 128 25 40 amp=30 pan=0 # 808 Snare 2 808 Snare 2 +41 %font "FluidR3_GM.sf2" 128 25 41 amp=46 pan=-47 # 808 Tom 1 808 Tom 1 +42 %font "FluidR3_GM.sf2" 128 25 42 amp=13 pan=31 # 808 Closed Hat 808 Closed Hat +43 %font "FluidR3_GM.sf2" 128 25 43 amp=38 pan=-28 # 808 Tom 2 808 Tom 2 +44 %font "FluidR3_GM.sf2" 128 25 44 amp=35 pan=31 # 808 Open Hat 808 Open Hat +45 %font "FluidR3_GM.sf2" 128 25 45 amp=36 pan=-9 # 808 Tom 3 808 Tom 3 +46 %font "FluidR3_GM.sf2" 128 25 46 amp=64 pan=31 # 808 Open Hat 808 Open Hat +47 %font "FluidR3_GM.sf2" 128 25 47 amp=22 pan=9 # 808 Tom 4 808 Tom 4 +48 %font "FluidR3_GM.sf2" 128 25 48 amp=19 pan=28 # 808 Tom 5 808 Tom 5 +49 %font "FluidR3_GM.sf2" 128 25 49 amp=66 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 25 50 amp=29 pan=47 # 808 Tom 6 808 Tom 6 +51 %font "FluidR3_GM.sf2" 128 25 51 amp=28 pan=-31 # Ride1(L) Ride1(R) 808 Ride 808 Ride +52 %font "FluidR3_GM.sf2" 128 25 52 amp=84 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 25 53 amp=41 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 25 54 amp=100 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 25 55 amp=50 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 25 56 amp=49 pan=31 # 808 Cowbell 808 Cowbell +57 %font "FluidR3_GM.sf2" 128 25 57 amp=50 pan=-31 # Crsh 2(L) Crsh 2(R) +59 %font "FluidR3_GM.sf2" 128 25 59 amp=20 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 25 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 25 61 amp=55 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 25 62 amp=13 pan=-39 # 808 High Conga 808 High Conga +63 %font "FluidR3_GM.sf2" 128 25 63 amp=65 pan=-39 # 808 Mid Conga 808 Mid Conga +64 %font "FluidR3_GM.sf2" 128 25 64 amp=47 pan=-31 # 808 Low Conga 808 Low Conga +67 %font "FluidR3_GM.sf2" 128 25 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 25 68 amp=103 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 25 69 amp=47 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 25 70 amp=78 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 25 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 25 72 amp=47 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 25 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 25 74 amp=83 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 25 75 amp=30 pan=31 # 808 Clave 808 Clave +76 %font "FluidR3_GM.sf2" 128 25 76 amp=110 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 25 77 amp=131 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 25 78 amp=134 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 25 79 amp=51 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 25 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 25 81 amp=53 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 25 82 amp=99 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 25 83 amp=164 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 25 84 amp=52 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 25 85 amp=83 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 25 86 amp=49 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 25 87 amp=78 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 32 +27 %font "FluidR3_GM.sf2" 128 32 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 32 28 amp=43 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 32 29 amp=43 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 32 30 amp=43 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 32 31 amp=75 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 32 32 amp=176 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 32 33 amp=53 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 32 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 32 35 amp=119 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +37 %font "FluidR3_GM.sf2" 128 32 37 amp=186 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 32 38 amp=104 pan=0 # Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 32 39 amp=66 pan=-16 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 32 40 amp=101 pan=0 # Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 32 41 amp=94 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 32 42 amp=21 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 32 43 amp=73 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 32 44 amp=21 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 32 45 amp=131 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 32 46 amp=46 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 32 47 amp=114 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 32 48 amp=148 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 32 49 amp=83 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 32 50 amp=76 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 32 51 amp=27 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 32 52 amp=38 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 32 53 amp=23 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 32 54 amp=63 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 32 55 amp=44 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 32 56 amp=101 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 32 57 amp=56 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 32 58 amp=65 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 32 59 amp=27 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 32 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 32 61 amp=55 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 32 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 32 63 amp=79 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 32 64 amp=69 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 32 65 amp=152 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 32 66 amp=95 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 32 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 32 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 32 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 32 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 32 71 amp=95 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 32 72 amp=75 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 32 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 32 74 amp=31 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 32 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 32 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 32 77 amp=84 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 32 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 32 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 32 80 amp=44 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 32 81 amp=63 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 32 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 32 83 amp=103 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 32 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 32 85 amp=127 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 32 86 amp=50 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 32 87 amp=53 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 33 +27 %font "FluidR3_GM.sf2" 128 33 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 33 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 33 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 33 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 33 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 33 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 33 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 33 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 33 35 amp=100 pan=0 # Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) +37 %font "FluidR3_GM.sf2" 128 33 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 33 38 amp=100 pan=0 # Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) Piccolo 1-1(L) Piccolo 1-1(R) +39 %font "FluidR3_GM.sf2" 128 33 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 33 40 amp=100 pan=0 # Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) Piccolo 1-2(L) Piccolo 1-2(R) +41 %font "FluidR3_GM.sf2" 128 33 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 33 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 33 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 33 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 33 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 33 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 33 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 33 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 33 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 33 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 33 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 33 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 33 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 33 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 33 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 33 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 33 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 33 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 33 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 33 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 33 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 33 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 33 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 33 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 33 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 33 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 33 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 33 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 33 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 33 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 33 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 33 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 33 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 33 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 33 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 33 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 33 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 33 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 33 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 33 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 33 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 33 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 33 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 33 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 33 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 33 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 33 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 34 +27 %font "FluidR3_GM.sf2" 128 34 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 34 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 34 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 34 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 34 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 34 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 34 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 34 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 34 35 amp=100 pan=0 # Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) +37 %font "FluidR3_GM.sf2" 128 34 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 34 38 amp=100 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +39 %font "FluidR3_GM.sf2" 128 34 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 34 40 amp=100 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +41 %font "FluidR3_GM.sf2" 128 34 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 34 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 34 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 34 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 34 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 34 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 34 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 34 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 34 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 34 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 34 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 34 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 34 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 34 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 34 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 34 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 34 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 34 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 34 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 34 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 34 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 34 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 34 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 34 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 34 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 34 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 34 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 34 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 34 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 34 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 34 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 34 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 34 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 34 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 34 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 34 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 34 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 34 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 34 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 34 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 34 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 34 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 34 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 34 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 34 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 34 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 34 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 35 +27 %font "FluidR3_GM.sf2" 128 35 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 35 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 35 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 35 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 35 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 35 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 35 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 35 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 35 35 amp=100 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +37 %font "FluidR3_GM.sf2" 128 35 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 35 38 amp=100 pan=0 # Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) +39 %font "FluidR3_GM.sf2" 128 35 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 35 40 amp=100 pan=0 # Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) +41 %font "FluidR3_GM.sf2" 128 35 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 35 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 35 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 35 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 35 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 35 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 35 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 35 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 35 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 35 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 35 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 35 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 35 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 35 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 35 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 35 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 35 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 35 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 35 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 35 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 35 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 35 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 35 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 35 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 35 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 35 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 35 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 35 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 35 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 35 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 35 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 35 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 35 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 35 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 35 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 35 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 35 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 35 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 35 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 35 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 35 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 35 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 35 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 35 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 35 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 35 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 35 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 36 +27 %font "FluidR3_GM.sf2" 128 36 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 36 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 36 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 36 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 36 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 36 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 36 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 36 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 36 35 amp=100 pan=0 # Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) +37 %font "FluidR3_GM.sf2" 128 36 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 36 38 amp=100 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +39 %font "FluidR3_GM.sf2" 128 36 39 amp=100 pan=0 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 36 40 amp=100 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +41 %font "FluidR3_GM.sf2" 128 36 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 36 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 36 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 36 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 36 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 36 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 36 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 36 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 36 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 36 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 36 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 36 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 36 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 36 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 36 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 36 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 36 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 36 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 36 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 36 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 36 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 36 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 36 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 36 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 36 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 36 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 36 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 36 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 36 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 36 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 36 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 36 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 36 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 36 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 36 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 36 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 36 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 36 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 36 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 36 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 36 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 36 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 36 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 36 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 36 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 36 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 36 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 40 +27 %font "FluidR3_GM.sf2" 128 40 27 amp=31 pan=-23 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 40 28 amp=44 pan=31 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 40 29 amp=26 pan=-16 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 40 30 amp=27 pan=-16 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 40 31 amp=119 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 40 32 amp=178 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 40 33 amp=85 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 40 34 amp=16 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 40 35 amp=94 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +37 %font "FluidR3_GM.sf2" 128 40 37 amp=116 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 40 38 amp=28 pan=0 # Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 40 39 amp=69 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +40 %font "FluidR3_GM.sf2" 128 40 40 amp=33 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +41 %font "FluidR3_GM.sf2" 128 40 41 amp=76 pan=-47 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 40 42 amp=20 pan=31 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 40 43 amp=46 pan=-28 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 40 44 amp=13 pan=31 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 40 45 amp=125 pan=-9 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 40 46 amp=59 pan=31 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 40 47 amp=74 pan=9 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 40 48 amp=73 pan=28 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 40 49 amp=87 pan=31 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 40 50 amp=39 pan=47 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 40 51 amp=18 pan=-31 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 40 52 amp=84 pan=-31 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 40 53 amp=97 pan=-31 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 40 54 amp=17 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 40 55 amp=44 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 40 56 amp=103 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 40 57 amp=50 pan=-31 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 40 58 amp=28 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 40 59 amp=24 pan=-31 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 40 60 amp=54 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 40 61 amp=56 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 40 62 amp=30 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 40 63 amp=80 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 40 64 amp=44 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 40 65 amp=98 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 40 66 amp=146 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 40 67 amp=57 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 40 68 amp=64 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 40 69 amp=15 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 40 70 amp=31 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 40 71 amp=59 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 40 72 amp=76 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 40 73 amp=43 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 40 74 amp=30 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 40 75 amp=78 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 40 76 amp=68 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 40 77 amp=82 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 40 78 amp=66 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 40 79 amp=30 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 40 80 amp=45 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 40 81 amp=64 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 40 82 amp=155 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 40 83 amp=102 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 40 84 amp=34 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 40 85 amp=127 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 40 86 amp=50 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 40 87 amp=78 pan=-31 # Long Taiko Hit Long Taiko Hit + +drumset 41 +27 %font "FluidR3_GM.sf2" 128 41 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 41 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 41 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 41 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 41 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 41 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 41 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 41 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 41 35 amp=100 pan=0 # Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) Std Kick 5(L) Std Kick 5(R) +37 %font "FluidR3_GM.sf2" 128 41 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 41 38 amp=100 pan=0 # Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 41 39 amp=100 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +40 %font "FluidR3_GM.sf2" 128 41 40 amp=100 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +41 %font "FluidR3_GM.sf2" 128 41 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 41 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 41 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 41 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 41 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 41 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 41 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 41 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 41 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 41 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 41 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 41 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 41 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 41 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 41 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 41 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 41 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 41 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 41 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 41 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 41 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 41 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 41 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 41 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 41 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 41 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 41 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 41 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 41 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 41 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 41 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 41 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 41 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 41 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 41 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 41 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 41 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 41 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 41 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 41 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 41 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 41 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 41 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 41 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 41 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 41 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 41 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 42 +27 %font "FluidR3_GM.sf2" 128 42 27 amp=100 pan=0 # High Q(L) High Q(R) +28 %font "FluidR3_GM.sf2" 128 42 28 amp=100 pan=0 # Slap Slap +29 %font "FluidR3_GM.sf2" 128 42 29 amp=100 pan=0 # Scratch Push(L) Scratch Push(R) +30 %font "FluidR3_GM.sf2" 128 42 30 amp=100 pan=0 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 42 31 amp=100 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 42 32 amp=100 pan=0 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 42 33 amp=100 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 42 34 amp=100 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 42 35 amp=100 pan=0 # Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) Std Kick 1(L) Std Kick 1(R) +37 %font "FluidR3_GM.sf2" 128 42 37 amp=100 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 42 38 amp=100 pan=0 # Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) +39 %font "FluidR3_GM.sf2" 128 42 39 amp=100 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +40 %font "FluidR3_GM.sf2" 128 42 40 amp=100 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +41 %font "FluidR3_GM.sf2" 128 42 41 amp=100 pan=0 # Low Flr Studio(L) Low Flr Studio(R) +42 %font "FluidR3_GM.sf2" 128 42 42 amp=100 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 42 43 amp=100 pan=0 # Flr Studio(L) Flr Studio(R) +44 %font "FluidR3_GM.sf2" 128 42 44 amp=100 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +45 %font "FluidR3_GM.sf2" 128 42 45 amp=100 pan=0 # Low Studio(L) Low Studio(R) +46 %font "FluidR3_GM.sf2" 128 42 46 amp=100 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +47 %font "FluidR3_GM.sf2" 128 42 47 amp=100 pan=0 # Md Studio(L) Md Studio(R) +48 %font "FluidR3_GM.sf2" 128 42 48 amp=100 pan=0 # MdHi Studio(L) MdHi Studio(R) +49 %font "FluidR3_GM.sf2" 128 42 49 amp=100 pan=0 # Crsh 1(L) Crsh 1(R) +50 %font "FluidR3_GM.sf2" 128 42 50 amp=100 pan=0 # Hi Studio(L) Hi Studio(R) +51 %font "FluidR3_GM.sf2" 128 42 51 amp=100 pan=0 # Ride1(L) Ride1(R) +52 %font "FluidR3_GM.sf2" 128 42 52 amp=100 pan=0 # China Crash(L) China Crash(R) +53 %font "FluidR3_GM.sf2" 128 42 53 amp=100 pan=0 # BellRide(L) BellRide(R) +54 %font "FluidR3_GM.sf2" 128 42 54 amp=100 pan=0 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 42 55 amp=100 pan=0 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 42 56 amp=100 pan=0 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 42 57 amp=100 pan=0 # Crsh 2(L) Crsh 2(R) +58 %font "FluidR3_GM.sf2" 128 42 58 amp=100 pan=0 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 42 59 amp=100 pan=0 # Ride2(L) Ride2(R) +60 %font "FluidR3_GM.sf2" 128 42 60 amp=100 pan=0 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 42 61 amp=100 pan=0 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 42 62 amp=100 pan=0 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 42 63 amp=100 pan=0 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 42 64 amp=100 pan=0 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 42 65 amp=100 pan=0 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 42 66 amp=100 pan=0 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 42 67 amp=100 pan=0 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 42 68 amp=100 pan=0 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 42 69 amp=100 pan=0 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 42 70 amp=100 pan=0 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 42 71 amp=100 pan=0 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 42 72 amp=100 pan=0 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 42 73 amp=100 pan=0 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 42 74 amp=100 pan=0 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 42 75 amp=100 pan=0 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 42 76 amp=100 pan=0 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 42 77 amp=100 pan=0 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 42 78 amp=100 pan=0 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 42 79 amp=100 pan=0 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 42 80 amp=100 pan=0 # Triangle +81 %font "FluidR3_GM.sf2" 128 42 81 amp=100 pan=0 # Triangle +82 %font "FluidR3_GM.sf2" 128 42 82 amp=100 pan=0 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 42 83 amp=100 pan=0 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 42 84 amp=100 pan=0 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 42 85 amp=100 pan=0 # Castanet +86 %font "FluidR3_GM.sf2" 128 42 86 amp=100 pan=0 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 42 87 amp=100 pan=0 # Long Taiko Hit Long Taiko Hit + +drumset 48 +27 %font "FluidR3_GM.sf2" 128 48 27 amp=11 pan=31 # High Q(L) High Q(R) Hi-Hat Closed(L) Hi-Hat Closed(R) +28 %font "FluidR3_GM.sf2" 128 48 28 amp=24 pan=31 # Slap Slap Hi-Hat Foot(L) Hi-Hat Foot(R) +29 %font "FluidR3_GM.sf2" 128 48 29 amp=23 pan=31 # Scratch Push(L) Scratch Push(R) Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +30 %font "FluidR3_GM.sf2" 128 48 30 amp=3 pan=-31 # Scratch Pull(L) Scratch Pull(R) +31 %font "FluidR3_GM.sf2" 128 48 31 amp=18 pan=0 # Sticks(L) Sticks(R) +32 %font "FluidR3_GM.sf2" 128 48 32 amp=143 pan=-16 # Square Click(L) Square Click(R) +33 %font "FluidR3_GM.sf2" 128 48 33 amp=43 pan=0 # Metronome Click Metronome Click +34 %font "FluidR3_GM.sf2" 128 48 34 amp=13 pan=0 # Metronome Bell(L) Metronome Bell(R) +35 %font "FluidR3_GM.sf2" 128 48 35 amp=187 pan=0 # Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) +36 %font "FluidR3_GM.sf2" 128 48 35 amp=57 pan=0 # Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) +37 %font "FluidR3_GM.sf2" 128 48 37 amp=21 pan=0 # Rim Tap(L) Rim Tap(R) +38 %font "FluidR3_GM.sf2" 128 48 38 amp=126 pan=-31 # Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) +39 %font "FluidR3_GM.sf2" 128 48 39 amp=33 pan=-47 # Clap(L) Clap(R) +40 %font "FluidR3_GM.sf2" 128 48 40 amp=126 pan=0 # Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) +41 %font "FluidR3_GM.sf2" 128 48 41 amp=87 pan=-47 # Timpani 2(L) Timpani 2(R) +42 %font "FluidR3_GM.sf2" 128 48 41 amp=86 pan=-47 # Timpani 2(L) Timpani 2(R) +43 %font "FluidR3_GM.sf2" 128 48 43 amp=81 pan=-47 # Timpani 3(L) Timpani 3(R) +44 %font "FluidR3_GM.sf2" 128 48 43 amp=126 pan=-47 # Timpani 3(L) Timpani 3(R) +45 %font "FluidR3_GM.sf2" 128 48 43 amp=75 pan=-47 # Timpani 3(L) Timpani 3(R) +46 %font "FluidR3_GM.sf2" 128 48 43 amp=120 pan=-47 # Timpani 3(L) Timpani 3(R) +47 %font "FluidR3_GM.sf2" 128 48 43 amp=72 pan=-47 # Timpani 3(L) Timpani 3(R) +48 %font "FluidR3_GM.sf2" 128 48 43 amp=114 pan=-47 # Timpani 3(L) Timpani 3(R) +49 %font "FluidR3_GM.sf2" 128 48 43 amp=113 pan=-47 # Timpani 3(L) Timpani 3(R) +50 %font "FluidR3_GM.sf2" 128 48 43 amp=110 pan=-47 # Timpani 3(L) Timpani 3(R) +51 %font "FluidR3_GM.sf2" 128 48 43 amp=63 pan=-47 # Timpani 3(L) Timpani 3(R) +52 %font "FluidR3_GM.sf2" 128 48 43 amp=63 pan=-47 # Timpani 3(L) Timpani 3(R) +53 %font "FluidR3_GM.sf2" 128 48 43 amp=61 pan=-47 # Timpani 3(L) Timpani 3(R) +54 %font "FluidR3_GM.sf2" 128 48 54 amp=67 pan=16 # Tambourine(L) Tambourine(R) +55 %font "FluidR3_GM.sf2" 128 48 55 amp=49 pan=-16 # Splash(L) Splash(R) +56 %font "FluidR3_GM.sf2" 128 48 56 amp=92 pan=31 # Cow Bell(L) Cow Bell(R) +57 %font "FluidR3_GM.sf2" 128 48 57 amp=69 pan=-31 # Orchcrash(L) Orchcrash(R) +58 %font "FluidR3_GM.sf2" 128 48 58 amp=22 pan=-55 # Vibra Slap +59 %font "FluidR3_GM.sf2" 128 48 59 amp=76 pan=-47 # Orchcrash(L) Orchcrash(R) +60 %font "FluidR3_GM.sf2" 128 48 60 amp=8 pan=55 # Bongo Rim(L) Bongo Rim(R) +61 %font "FluidR3_GM.sf2" 128 48 61 amp=82 pan=55 # Low Bongo(L) Low Bongo(R) +62 %font "FluidR3_GM.sf2" 128 48 62 amp=41 pan=-39 # Closed Slap(L) Closed Slap(R) +63 %font "FluidR3_GM.sf2" 128 48 63 amp=77 pan=-39 # High Conga(L) High Conga(R) +64 %font "FluidR3_GM.sf2" 128 48 64 amp=45 pan=-31 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 48 65 amp=80 pan=31 # High Timbale(L) High Timbale(R) +66 %font "FluidR3_GM.sf2" 128 48 66 amp=78 pan=31 # Low Timbale(L) Low Timbale(R) +67 %font "FluidR3_GM.sf2" 128 48 67 amp=82 pan=-55 # High Agogo(L) High Agogo(R) +68 %font "FluidR3_GM.sf2" 128 48 68 amp=92 pan=-55 # Low Agogo(L) Low Agogo(R) +69 %font "FluidR3_GM.sf2" 128 48 69 amp=11 pan=-55 # Cabasa(L) Cabasa(R) +70 %font "FluidR3_GM.sf2" 128 48 70 amp=27 pan=-63 # Maracas(L) Maracas(R) +71 %font "FluidR3_GM.sf2" 128 48 71 amp=45 pan=55 # Short Whistle +72 %font "FluidR3_GM.sf2" 128 48 72 amp=34 pan=55 # Long Whistle +73 %font "FluidR3_GM.sf2" 128 48 73 amp=32 pan=47 # Guiro Down(L) Guiro Down(R) +74 %font "FluidR3_GM.sf2" 128 48 74 amp=46 pan=47 # Guiro Up(L) Guiro Up(R) +75 %font "FluidR3_GM.sf2" 128 48 75 amp=61 pan=31 # Clave(L) Clave(R) +76 %font "FluidR3_GM.sf2" 128 48 76 amp=52 pan=55 # High Woodblock(L) High Woodblock(R) +77 %font "FluidR3_GM.sf2" 128 48 77 amp=63 pan=55 # Low Woodblock(L) Low Woodblock(R) +78 %font "FluidR3_GM.sf2" 128 48 78 amp=54 pan=-31 # Quica Hi Quica Hi +79 %font "FluidR3_GM.sf2" 128 48 79 amp=24 pan=-31 # Quica Low Quica Low +80 %font "FluidR3_GM.sf2" 128 48 80 amp=36 pan=-63 # Triangle +81 %font "FluidR3_GM.sf2" 128 48 81 amp=76 pan=-63 # Triangle +82 %font "FluidR3_GM.sf2" 128 48 82 amp=114 pan=47 # Small Shaker (L) Small Shaker (R) +83 %font "FluidR3_GM.sf2" 128 48 83 amp=78 pan=55 # Sleigh Bells +84 %font "FluidR3_GM.sf2" 128 48 84 amp=27 pan=63 # Bell Tree Bell Tree +85 %font "FluidR3_GM.sf2" 128 48 85 amp=63 pan=-47 # Castanet +86 %font "FluidR3_GM.sf2" 128 48 86 amp=39 pan=-31 # Short Taiko Hit Short Taiko Hit +87 %font "FluidR3_GM.sf2" 128 48 87 amp=64 pan=-31 # Long Taiko Hit Long Taiko Hit +88 %font "FluidR3_GM.sf2" 128 48 88 amp=44 pan=0 # Applause Applause + +drumset 49 +30 %font "FluidR3_GM.sf2" 128 0 38 amp=93 pan=-31 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +31 %font "FluidR3_GM.sf2" 128 0 49 amp=52 pan=-47 # Crsh 1(L) Crsh 1(R) +32 %font "FluidR3_GM.sf2" 128 0 35 amp=21 pan=-63 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +33 %font "FluidR3_GM.sf2" 0 116 amp=26 pan=55 +36 %font "FluidR3_GM.sf2" 128 0 47 amp=96 pan=0 # Md Studio(L) Md Studio(R) +38 %font "FluidR3_GM.sf2" 128 0 47 amp=189 pan=-31 # Md Studio(L) Md Studio(R) +39 %font "FluidR3_GM.sf2" 128 0 47 amp=88 pan=63 # Md Studio(L) Md Studio(R) +40 %font "FluidR3_GM.sf2" 128 0 47 amp=66 pan=63 # Md Studio(L) Md Studio(R) +41 %font "FluidR3_GM.sf2" 128 0 47 amp=122 pan=31 # Md Studio(L) Md Studio(R) +42 %font "FluidR3_GM.sf2" 128 0 63 amp=69 pan=47 # High Conga(L) High Conga(R) +43 %font "FluidR3_GM.sf2" 128 0 64 amp=76 pan=47 # Low Tumba(L) Low Tumba(R) +44 %font "FluidR3_GM.sf2" 128 0 47 amp=133 pan=63 # Md Studio(L) Md Studio(R) +49 %font "FluidR3_GM.sf2" 128 0 52 amp=43 pan=-47 # China Crash(L) China Crash(R) +50 %font "FluidR3_GM.sf2" 128 0 52 amp=170 pan=31 # China Crash(L) China Crash(R) +51 %font "FluidR3_GM.sf2" 128 0 47 amp=216 pan=47 # Md Studio(L) Md Studio(R) +52 %font "FluidR3_GM.sf2" 128 0 47 amp=227 pan=47 # Md Studio(L) Md Studio(R) +54 %font "FluidR3_GM.sf2" 128 0 64 amp=56 pan=23 # Low Tumba(L) Low Tumba(R) +55 %font "FluidR3_GM.sf2" 128 0 64 amp=52 pan=47 # Low Tumba(L) Low Tumba(R) +56 %font "FluidR3_GM.sf2" 128 0 64 amp=28 pan=47 # Low Tumba(L) Low Tumba(R) +57 %font "FluidR3_GM.sf2" 128 0 60 amp=53 pan=-47 # Bongo Rim(L) Bongo Rim(R) +58 %font "FluidR3_GM.sf2" 128 0 61 amp=40 pan=-47 # Low Bongo(L) Low Bongo(R) +59 %font "FluidR3_GM.sf2" 128 0 63 amp=31 pan=-47 # High Conga(L) High Conga(R) +60 %font "FluidR3_GM.sf2" 128 0 64 amp=51 pan=-47 # Low Tumba(L) Low Tumba(R) +61 %font "FluidR3_GM.sf2" 128 0 62 amp=96 pan=-31 # Closed Slap(L) Closed Slap(R) +62 %font "FluidR3_GM.sf2" 128 0 47 amp=139 pan=31 # Md Studio(L) Md Studio(R) +63 %font "FluidR3_GM.sf2" 128 0 47 amp=153 pan=31 # Md Studio(L) Md Studio(R) +64 %font "FluidR3_GM.sf2" 128 0 64 amp=22 pan=-16 # Low Tumba(L) Low Tumba(R) +65 %font "FluidR3_GM.sf2" 128 0 60 amp=111 pan=-31 # Bongo Rim(L) Bongo Rim(R) +67 %font "FluidR3_GM.sf2" 128 0 66 amp=113 pan=31 # Low Timbale(L) Low Timbale(R) +68 %font "FluidR3_GM.sf2" 128 0 66 amp=41 pan=39 # Low Timbale(L) Low Timbale(R) +69 %font "FluidR3_GM.sf2" 128 0 65 amp=83 pan=39 # High Timbale(L) High Timbale(R) +70 %font "FluidR3_GM.sf2" 128 0 56 amp=72 pan=31 # Cow Bell(L) Cow Bell(R) +71 %font "FluidR3_GM.sf2" 128 0 60 amp=50 pan=55 # Bongo Rim(L) Bongo Rim(R) +72 %font "FluidR3_GM.sf2" 128 0 61 amp=65 pan=47 # Low Bongo(L) Low Bongo(R) +73 %font "FluidR3_GM.sf2" 128 0 62 amp=56 pan=-31 # Closed Slap(L) Closed Slap(R) +74 %font "FluidR3_GM.sf2" 128 0 63 amp=162 pan=-31 # High Conga(L) High Conga(R) +75 %font "FluidR3_GM.sf2" 128 0 64 amp=27 pan=-39 # Low Tumba(L) Low Tumba(R) +76 %font "FluidR3_GM.sf2" 128 0 64 amp=45 pan=-39 # Low Tumba(L) Low Tumba(R) +77 %font "FluidR3_GM.sf2" 128 0 64 amp=47 pan=-39 # Low Tumba(L) Low Tumba(R) +78 %font "FluidR3_GM.sf2" 128 0 64 amp=60 pan=-39 # Low Tumba(L) Low Tumba(R) +79 %font "FluidR3_GM.sf2" 0 116 amp=58 pan=63 +80 %font "FluidR3_GM.sf2" 0 116 amp=26 pan=63 +81 %font "FluidR3_GM.sf2" 0 116 amp=44 pan=-31 +82 %font "FluidR3_GM.sf2" 0 116 amp=30 pan=-31 +83 %font "FluidR3_GM.sf2" 128 0 54 amp=79 pan=8 # Tambourine(L) Tambourine(R) +84 %font "FluidR3_GM.sf2" 128 0 67 amp=50 pan=-55 # High Agogo(L) High Agogo(R) +85 %font "FluidR3_GM.sf2" 128 0 68 amp=57 pan=-55 # Low Agogo(L) Low Agogo(R) +87 %font "FluidR3_GM.sf2" 128 0 71 amp=111 pan=55 # Short Whistle +88 %font "FluidR3_GM.sf2" 128 0 72 amp=45 pan=55 # Long Whistle +89 %font "FluidR3_GM.sf2" 128 0 78 amp=61 pan=-31 # Quica Hi Quica Hi +90 %font "FluidR3_GM.sf2" 128 0 79 amp=27 pan=-31 # Quica Low Quica Low +91 %font "FluidR3_GM.sf2" 128 0 80 amp=41 pan=-63 # Triangle +92 %font "FluidR3_GM.sf2" 128 0 81 amp=48 pan=-63 # Triangle +93 %font "FluidR3_GM.sf2" 128 0 73 amp=35 pan=47 # Guiro Down(L) Guiro Down(R) +94 %font "FluidR3_GM.sf2" 128 0 74 amp=23 pan=47 # Guiro Up(L) Guiro Up(R) +95 %font "FluidR3_GM.sf2" 128 0 69 amp=17 pan=-55 # Cabasa(L) Cabasa(R) +96 %font "FluidR3_GM.sf2" 128 0 69 amp=25 pan=-55 # Cabasa(L) Cabasa(R) +97 %font "FluidR3_GM.sf2" 128 0 75 amp=55 pan=31 # Clave(L) Clave(R) +98 %font "FluidR3_GM.sf2" 128 0 76 amp=96 pan=55 # High Woodblock(L) High Woodblock(R) +99 %font "FluidR3_GM.sf2" 128 0 77 amp=115 pan=55 # Low Woodblock(L) Low Woodblock(R) + +drumset 50 +25 %font "FluidR3_GM.sf2" 128 25 36 amp=63 pan=0 # 808 Kick 2 808 Kick 2 +26 %font "FluidR3_GM.sf2" 128 25 35 amp=73 pan=0 # 808 Kick 1 808 Kick 1 +27 %font "FluidR3_GM.sf2" 128 25 36 amp=59 pan=0 # 808 Kick 2 808 Kick 2 +28 %font "FluidR3_GM.sf2" 128 25 36 amp=65 pan=0 # 808 Kick 2 808 Kick 2 +29 %font "FluidR3_GM.sf2" 128 25 36 amp=58 pan=0 # 808 Kick 2 808 Kick 2 +30 %font "FluidR3_GM.sf2" 128 25 36 amp=81 pan=0 # 808 Kick 2 808 Kick 2 +31 %font "FluidR3_GM.sf2" 128 25 35 amp=123 pan=0 # 808 Kick 1 808 Kick 1 +32 %font "FluidR3_GM.sf2" 128 9 35 amp=150 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +33 %font "FluidR3_GM.sf2" 128 9 35 amp=133 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +34 %font "FluidR3_GM.sf2" 128 10 35 amp=63 pan=0 # Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) +35 %font "FluidR3_GM.sf2" 128 10 35 amp=82 pan=0 # Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) Std Kick 3(L) Std Kick 3(R) +36 %font "FluidR3_GM.sf2" 128 11 35 amp=205 pan=0 # Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) +37 %font "FluidR3_GM.sf2" 128 11 35 amp=417 pan=0 # Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) Room Kick (L) Room Kick (R) +38 %font "FluidR3_GM.sf2" 128 0 35 amp=129 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +39 %font "FluidR3_GM.sf2" 128 0 35 amp=226 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +40 %font "FluidR3_GM.sf2" 128 0 35 amp=142 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +41 %font "FluidR3_GM.sf2" 128 0 35 amp=138 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +42 %font "FluidR3_GM.sf2" 128 1 35 amp=188 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +43 %font "FluidR3_GM.sf2" 128 1 35 amp=128 pan=0 # Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) Std Kick 2(L) Std Kick 2(R) +44 %font "FluidR3_GM.sf2" 128 0 35 amp=156 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +45 %font "FluidR3_GM.sf2" 128 0 35 amp=86 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +46 %font "FluidR3_GM.sf2" 128 0 35 amp=160 pan=0 # Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) Std Kick(L) Std Kick(R) +47 %font "FluidR3_GM.sf2" 128 32 35 amp=86 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +48 %font "FluidR3_GM.sf2" 128 32 35 amp=94 pan=0 # Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) Std Kick 7(L) Std Kick 7(R) +49 %font "FluidR3_GM.sf2" 128 48 35 amp=50 pan=0 # Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) Orch Bass Drum(L) Orch Bass Drum(R) +50 %font "FluidR3_GM.sf2" 128 8 35 amp=77 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +51 %font "FluidR3_GM.sf2" 128 8 35 amp=215 pan=0 # Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) Std Kick 6(L) Std Kick 6(R) +52 %font "FluidR3_GM.sf2" 128 16 35 amp=140 pan=0 # Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R Power Bass Drum 1(L Power Bass Drum 1(R +53 %font "FluidR3_GM.sf2" 128 16 36 amp=85 pan=0 # Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R Power Bass Drum 2(L Power Bass Drum 2(R +54 %font "FluidR3_GM.sf2" 128 24 35 amp=86 pan=0 # Elec Kick1(L) Elec Kick1(R) +55 %font "FluidR3_GM.sf2" 128 24 36 amp=135 pan=0 # Elec Kick2(L) Elec Kick2(R) +56 %font "FluidR3_GM.sf2" 128 24 35 amp=62 pan=0 # Elec Kick1(L) Elec Kick1(R) +57 %font "FluidR3_GM.sf2" 128 25 35 amp=59 pan=0 # 808 Kick 1 808 Kick 1 +58 %font "FluidR3_GM.sf2" 128 25 35 amp=68 pan=0 # 808 Kick 1 808 Kick 1 +59 %font "FluidR3_GM.sf2" 128 25 35 amp=60 pan=0 # 808 Kick 1 808 Kick 1 +60 %font "FluidR3_GM.sf2" 128 0 38 amp=108 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +61 %font "FluidR3_GM.sf2" 128 0 40 amp=129 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +62 %font "FluidR3_GM.sf2" 128 1 38 amp=93 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +63 %font "FluidR3_GM.sf2" 128 1 40 amp=52 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +64 %font "FluidR3_GM.sf2" 128 0 38 amp=106 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +65 %font "FluidR3_GM.sf2" 128 48 38 amp=194 pan=0 # Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) Orch Snare(L) Orch Snare(R) +66 %font "FluidR3_GM.sf2" 128 32 38 amp=134 pan=0 # Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) Snr 2-1(L) Snr 2-1(R) +67 %font "FluidR3_GM.sf2" 128 32 40 amp=91 pan=0 # Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) Snr 2-2(L) Snr 2-2(R) +68 %font "FluidR3_GM.sf2" 128 8 38 amp=76 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +69 %font "FluidR3_GM.sf2" 128 8 40 amp=92 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +70 %font "FluidR3_GM.sf2" 128 16 38 amp=113 pan=0 # Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) Power Snare 1(L) Power Snare 1(R) +71 %font "FluidR3_GM.sf2" 128 16 40 amp=103 pan=0 # Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) Power Snare 2(L) Power Snare 2(R) +72 %font "FluidR3_GM.sf2" 128 24 40 amp=123 pan=0 # Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) +73 %font "FluidR3_GM.sf2" 128 11 38 amp=102 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +74 %font "FluidR3_GM.sf2" 128 11 40 amp=155 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +75 %font "FluidR3_GM.sf2" 128 11 38 amp=71 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) +76 %font "FluidR3_GM.sf2" 128 11 40 amp=66 pan=0 # RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) RmPwr 1-2(L) RmPwr 1-2(R) +77 %font "FluidR3_GM.sf2" 128 8 38 amp=63 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +78 %font "FluidR3_GM.sf2" 128 24 38 amp=100 pan=0 # Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) Electronic Snr 1(L) Electronic Snr 1(R) +79 %font "FluidR3_GM.sf2" 128 24 40 amp=149 pan=0 # Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) Electronic Snr 2(L) Electronic Snr 2(R) +80 %font "FluidR3_GM.sf2" 128 25 38 amp=22 pan=0 # 808 Snare 1 808 Snare 1 +81 %font "FluidR3_GM.sf2" 128 25 40 amp=33 pan=0 # 808 Snare 2 808 Snare 2 +82 %font "FluidR3_GM.sf2" 128 25 38 amp=28 pan=0 # 808 Snare 1 808 Snare 1 +83 %font "FluidR3_GM.sf2" 128 25 40 amp=48 pan=0 # 808 Snare 2 808 Snare 2 +84 %font "FluidR3_GM.sf2" 128 40 38 amp=19 pan=0 # Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) +85 %font "FluidR3_GM.sf2" 128 40 38 amp=27 pan=0 # Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) Brush Snr 1(L) Brush Snr 1(R) +86 %font "FluidR3_GM.sf2" 128 40 39 amp=79 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +87 %font "FluidR3_GM.sf2" 128 40 39 amp=76 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +88 %font "FluidR3_GM.sf2" 128 40 39 amp=101 pan=0 # Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) Brush Snr 2(L) Brush Snr 2(R) +89 %font "FluidR3_GM.sf2" 128 40 40 amp=40 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +90 %font "FluidR3_GM.sf2" 128 40 40 amp=37 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +91 %font "FluidR3_GM.sf2" 128 40 40 amp=48 pan=0 # Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) Brush Swirl(L) Brush Swirl(R) +92 %font "FluidR3_GM.sf2" 128 0 38 amp=175 pan=0 # Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) Std Snr 1(L) Std Snr 1(R) +93 %font "FluidR3_GM.sf2" 128 0 40 amp=264 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +94 %font "FluidR3_GM.sf2" 128 0 40 amp=304 pan=0 # Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) Std Snr 2(L) Std Snr 2(R) +95 %font "FluidR3_GM.sf2" 128 9 38 amp=79 pan=0 # Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) Snr 1-2(L) Snr 1-2(R) +96 %font "FluidR3_GM.sf2" 128 9 40 amp=54 pan=0 # Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) Snr 1-1(L) Snr 1-1(R) +97 %font "FluidR3_GM.sf2" 128 10 38 amp=58 pan=0 # RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) RmPwr 2-1(L) RmPwr 2-1(R) +98 %font "FluidR3_GM.sf2" 128 10 40 amp=70 pan=0 # RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) RmPwr 2-2(L) RmPwr 2-2(R) +99 %font "FluidR3_GM.sf2" 128 11 38 amp=56 pan=0 # RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) RmPwr 1-1(L) RmPwr 1-1(R) + +drumset 53 +32 %font "FluidR3_GM.sf2" 128 0 46 amp=77 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +33 %font "FluidR3_GM.sf2" 128 0 42 amp=35 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +34 %font "FluidR3_GM.sf2" 128 0 42 amp=47 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +35 %font "FluidR3_GM.sf2" 128 0 46 amp=272 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +36 %font "FluidR3_GM.sf2" 128 0 42 amp=24 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +37 %font "FluidR3_GM.sf2" 128 0 42 amp=26 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +38 %font "FluidR3_GM.sf2" 128 0 42 amp=19 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +39 %font "FluidR3_GM.sf2" 128 0 42 amp=19 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +40 %font "FluidR3_GM.sf2" 128 0 42 amp=20 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +41 %font "FluidR3_GM.sf2" 128 0 42 amp=27 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +42 %font "FluidR3_GM.sf2" 128 0 42 amp=39 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +43 %font "FluidR3_GM.sf2" 128 0 42 amp=47 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +44 %font "FluidR3_GM.sf2" 128 0 42 amp=36 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +45 %font "FluidR3_GM.sf2" 128 0 42 amp=80 pan=0 # Hi-Hat Closed(L) Hi-Hat Closed(R) +46 %font "FluidR3_GM.sf2" 128 0 44 amp=17 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +47 %font "FluidR3_GM.sf2" 128 0 44 amp=26 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +48 %font "FluidR3_GM.sf2" 128 0 44 amp=18 pan=0 # Hi-Hat Foot(L) Hi-Hat Foot(R) +49 %font "FluidR3_GM.sf2" 128 0 46 amp=66 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +50 %font "FluidR3_GM.sf2" 128 0 46 amp=55 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +51 %font "FluidR3_GM.sf2" 128 0 46 amp=58 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +52 %font "FluidR3_GM.sf2" 128 0 46 amp=27 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +53 %font "FluidR3_GM.sf2" 128 0 46 amp=64 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +54 %font "FluidR3_GM.sf2" 128 0 46 amp=90 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +55 %font "FluidR3_GM.sf2" 128 0 46 amp=107 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +56 %font "FluidR3_GM.sf2" 128 0 46 amp=108 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +57 %font "FluidR3_GM.sf2" 128 0 46 amp=161 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +58 %font "FluidR3_GM.sf2" 128 0 46 amp=208 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +59 %font "FluidR3_GM.sf2" 128 0 46 amp=131 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +60 %font "FluidR3_GM.sf2" 128 0 46 amp=117 pan=0 # Hi-Hat Half-Open(L) Hi-Hat Half-Open(R) +61 %font "FluidR3_GM.sf2" 128 0 49 amp=83 pan=0 # Crsh 1(L) Crsh 1(R) +62 %font "FluidR3_GM.sf2" 128 0 57 amp=68 pan=0 # Crsh 2(L) Crsh 2(R) +63 %font "FluidR3_GM.sf2" 128 0 49 amp=85 pan=0 # Crsh 1(L) Crsh 1(R) +64 %font "FluidR3_GM.sf2" 128 0 49 amp=49 pan=0 # Crsh 1(L) Crsh 1(R) +65 %font "FluidR3_GM.sf2" 128 0 49 amp=81 pan=0 # Crsh 1(L) Crsh 1(R) +66 %font "FluidR3_GM.sf2" 128 0 49 amp=44 pan=0 # Crsh 1(L) Crsh 1(R) +67 %font "FluidR3_GM.sf2" 128 0 49 amp=72 pan=0 # Crsh 1(L) Crsh 1(R) +68 %font "FluidR3_GM.sf2" 128 0 49 amp=128 pan=0 # Crsh 1(L) Crsh 1(R) +69 %font "FluidR3_GM.sf2" 128 0 57 amp=91 pan=0 # Crsh 2(L) Crsh 2(R) +70 %font "FluidR3_GM.sf2" 128 0 49 amp=80 pan=0 # Crsh 1(L) Crsh 1(R) +71 %font "FluidR3_GM.sf2" 128 0 57 amp=61 pan=0 # Crsh 2(L) Crsh 2(R) +72 %font "FluidR3_GM.sf2" 128 0 49 amp=73 pan=0 # Crsh 1(L) Crsh 1(R) +73 %font "FluidR3_GM.sf2" 128 0 49 amp=73 pan=0 # Crsh 1(L) Crsh 1(R) +74 %font "FluidR3_GM.sf2" 128 0 55 amp=58 pan=0 # Splash(L) Splash(R) +75 %font "FluidR3_GM.sf2" 128 0 55 amp=73 pan=0 # Splash(L) Splash(R) +76 %font "FluidR3_GM.sf2" 128 0 53 amp=41 pan=0 # BellRide(L) BellRide(R) +77 %font "FluidR3_GM.sf2" 128 0 53 amp=51 pan=0 # BellRide(L) BellRide(R) +78 %font "FluidR3_GM.sf2" 128 0 51 amp=22 pan=0 # Ride1(L) Ride1(R) +79 %font "FluidR3_GM.sf2" 128 0 59 amp=23 pan=0 # Ride2(L) Ride2(R) +80 %font "FluidR3_GM.sf2" 128 0 51 amp=28 pan=0 # Ride1(L) Ride1(R) +81 %font "FluidR3_GM.sf2" 128 0 51 amp=31 pan=0 # Ride1(L) Ride1(R) +82 %font "FluidR3_GM.sf2" 128 0 51 amp=16 pan=0 # Ride1(L) Ride1(R) +83 %font "FluidR3_GM.sf2" 128 0 51 amp=13 pan=0 # Ride1(L) Ride1(R) +84 %font "FluidR3_GM.sf2" 128 0 51 amp=15 pan=0 # Ride1(L) Ride1(R) +85 %font "FluidR3_GM.sf2" 128 0 51 amp=15 pan=0 # Ride1(L) Ride1(R) +86 %font "FluidR3_GM.sf2" 128 0 51 amp=12 pan=0 # Ride1(L) Ride1(R) +87 %font "FluidR3_GM.sf2" 128 0 51 amp=30 pan=0 # Ride1(L) Ride1(R) +88 %font "FluidR3_GM.sf2" 128 0 51 amp=95 pan=0 # Ride1(L) Ride1(R) +89 %font "FluidR3_GM.sf2" 128 0 51 amp=116 pan=0 # Ride1(L) Ride1(R) +90 %font "FluidR3_GM.sf2" 128 0 51 amp=104 pan=0 # Ride1(L) Ride1(R) +91 %font "FluidR3_GM.sf2" 128 0 39 amp=15 pan=0 # Clap(L) Clap(R) +92 %font "FluidR3_GM.sf2" 128 0 39 amp=67 pan=0 # Clap(L) Clap(R) +93 %font "FluidR3_GM.sf2" 128 0 39 amp=58 pan=0 # Clap(L) Clap(R) +94 %font "FluidR3_GM.sf2" 128 0 39 amp=60 pan=0 # Clap(L) Clap(R) +95 %font "FluidR3_GM.sf2" 128 0 39 amp=111 pan=0 # Clap(L) Clap(R) +96 %font "FluidR3_GM.sf2" 128 0 39 amp=57 pan=0 # Clap(L) Clap(R) + diff --git a/packages/tools/sound/timidity/config/fluidr3_gs.cfg b/packages/tools/sound/timidity/config/fluidr3_gs.cfg new file mode 100644 index 000000000..29b89da14 --- /dev/null +++ b/packages/tools/sound/timidity/config/fluidr3_gs.cfg @@ -0,0 +1,97 @@ +dir /storage/roms/bios/timidity/sf2 + +bank 1 +120 %font "FluidR3_GS.sf2" 1 120 amp=42 pan=0 +121 %font "FluidR3_GS.sf2" 1 121 amp=170 pan=0 +122 %font "FluidR3_GS.sf2" 1 122 amp=24 pan=0 +123 %font "FluidR3_GS.sf2" 1 123 amp=26 pan=0 +124 %font "FluidR3_GS.sf2" 1 124 amp=66 pan=0 +125 %font "FluidR3_GS.sf2" 1 125 amp=97 pan=0 +126 %font "FluidR3_GS.sf2" 1 126 amp=181 pan=0 +127 %font "FluidR3_GS.sf2" 1 127 amp=44 pan=0 + +bank 2 +120 %font "FluidR3_GS.sf2" 2 120 amp=89 pan=0 +122 %font "FluidR3_GS.sf2" 2 122 amp=93 pan=0 +123 %font "FluidR3_GS.sf2" 2 123 amp=147 pan=0 +124 %font "FluidR3_GS.sf2" 2 124 amp=68 pan=0 +125 %font "FluidR3_GS.sf2" 2 125 amp=33 pan=0 +126 %font "FluidR3_GS.sf2" 2 126 amp=17 pan=0 +127 %font "FluidR3_GS.sf2" 2 127 amp=95 pan=0 + +bank 3 +122 %font "FluidR3_GS.sf2" 3 122 amp=45 pan=0 +123 %font "FluidR3_GS.sf2" 3 123 amp=58 pan=0 +124 %font "FluidR3_GS.sf2" 3 124 amp=146 pan=0 +125 %font "FluidR3_GS.sf2" 3 125 amp=121 pan=0 +126 %font "FluidR3_GS.sf2" 3 126 amp=67 pan=0 +127 %font "FluidR3_GS.sf2" 3 127 amp=94 pan=0 + +bank 4 +122 %font "FluidR3_GS.sf2" 4 122 amp=68 pan=0 +124 %font "FluidR3_GS.sf2" 4 124 amp=41 pan=0 +125 %font "FluidR3_GS.sf2" 4 125 amp=33 pan=0 +126 %font "FluidR3_GS.sf2" 4 126 amp=30 pan=0 + +bank 5 +122 %font "FluidR3_GS.sf2" 5 122 amp=81 pan=0 +124 %font "FluidR3_GS.sf2" 5 124 amp=136 pan=0 +125 %font "FluidR3_GS.sf2" 5 125 amp=22 pan=0 +126 %font "FluidR3_GS.sf2" 5 126 amp=51 pan=0 + +bank 6 +125 %font "FluidR3_GS.sf2" 6 125 amp=61 pan=0 + +bank 7 +125 %font "FluidR3_GS.sf2" 7 125 amp=47 pan=0 + +bank 8 +125 %font "FluidR3_GS.sf2" 8 125 amp=27 pan=0 + +drumset 56 +39 %font "FluidR3_GS.sf2" 128 56 39 amp=49 pan=-23 # High Q(L) +40 %font "FluidR3_GS.sf2" 128 56 40 amp=116 pan=-23 # Slap +41 %font "FluidR3_GS.sf2" 128 56 41 amp=71 pan=-16 # Scratch Push(L) +42 %font "FluidR3_GS.sf2" 128 56 42 amp=45 pan=-16 # Scratch Pull(L) +43 %font "FluidR3_GS.sf2" 128 56 43 amp=152 pan=0 # Sticks(L) +44 %font "FluidR3_GS.sf2" 128 56 44 amp=296 pan=-16 # Square Click(L) +45 %font "FluidR3_GS.sf2" 128 56 45 amp=91 pan=0 # Metronome Click +46 %font "FluidR3_GS.sf2" 128 56 46 amp=52 pan=0 # Metronome Click +47 %font "FluidR3_GS.sf2" 128 56 47 amp=56 pan=0 # Fretnoise +48 %font "FluidR3_GS.sf2" 128 56 48 amp=26 pan=0 # Gtr Cut Up +49 %font "FluidR3_GS.sf2" 128 56 49 amp=65 pan=0 # Gtr Cut Down +50 %font "FluidR3_GS.sf2" 128 56 50 amp=47 pan=0 # Str. Slap +51 %font "FluidR3_GS.sf2" 128 56 51 amp=106 pan=0 # Pick Click +52 %font "FluidR3_GS.sf2" 128 56 52 amp=76 pan=0 # Laugh +53 %font "FluidR3_GS.sf2" 128 56 53 amp=27 pan=0 # Scream +54 %font "FluidR3_GS.sf2" 128 56 54 amp=140 pan=0 # Punch Punch +55 %font "FluidR3_GS.sf2" 128 56 55 amp=78 pan=0 # HeartBeat HeartBeat +56 %font "FluidR3_GS.sf2" 128 56 56 amp=30 pan=0 # FootStep FootStep +57 %font "FluidR3_GS.sf2" 128 56 57 amp=30 pan=0 # FootStep FootStep +58 %font "FluidR3_GS.sf2" 128 56 58 amp=7 pan=0 # Applause Applause +59 %font "FluidR3_GS.sf2" 128 56 59 amp=17 pan=0 # doorcreak doorcreak +60 %font "FluidR3_GS.sf2" 128 56 60 amp=86 pan=0 # Door +61 %font "FluidR3_GS.sf2" 128 56 61 amp=40 pan=0 # Scratchgs(L) Scratchgs(R) +62 %font "FluidR3_GS.sf2" 128 56 62 amp=225 pan=0 # Wind Chime Wind Chime Wind Chime +63 %font "FluidR3_GS.sf2" 128 56 63 amp=26 pan=0 # Car Start Car Start +64 %font "FluidR3_GS.sf2" 128 56 64 amp=101 pan=0 # Car Stop Car Stop +65 %font "FluidR3_GS.sf2" 128 56 65 amp=112 pan=0 # Car Pass Car Pass +66 %font "FluidR3_GS.sf2" 128 56 66 amp=78 pan=0 # Crash Car Crash1 +67 %font "FluidR3_GS.sf2" 128 56 67 amp=3 pan=0 # Siren Siren +68 %font "FluidR3_GS.sf2" 128 56 68 amp=116 pan=0 # train train +69 %font "FluidR3_GS.sf2" 128 56 69 amp=43 pan=0 # Noise +70 %font "FluidR3_GS.sf2" 128 56 70 amp=76 pan=0 # Heli Heli +71 %font "FluidR3_GS.sf2" 128 56 71 amp=4 pan=0 # Ufo1 Ufo1 +72 %font "FluidR3_GS.sf2" 128 56 72 amp=62 pan=0 # Gun +73 %font "FluidR3_GS.sf2" 128 56 73 amp=32 pan=0 # MachineGun MachineGun +74 %font "FluidR3_GS.sf2" 128 56 74 amp=55 pan=0 # Noise Gun +75 %font "FluidR3_GS.sf2" 128 56 75 amp=83 pan=0 # Explosion Explosion +76 %font "FluidR3_GS.sf2" 128 56 76 amp=74 pan=0 # Dog Bark Dog Bark +77 %font "FluidR3_GS.sf2" 128 56 77 amp=6 pan=0 # Gallops Gallops +78 %font "FluidR3_GS.sf2" 128 56 78 amp=49 pan=0 # Bird2(R) Bird2(L) +79 %font "FluidR3_GS.sf2" 128 56 79 amp=4 pan=0 # SeattleRain...(L) SeattleRain...(R) +80 %font "FluidR3_GS.sf2" 128 56 80 amp=185 pan=0 # Thunder(R) Thunder(L) +81 %font "FluidR3_GS.sf2" 128 56 81 amp=7 pan=0 # Noise Noise +82 %font "FluidR3_GS.sf2" 128 56 82 amp=111 pan=0 # Sea Shore Sea Shore Sea Shore +83 %font "FluidR3_GS.sf2" 128 56 83 amp=132 pan=0 # River bubbles River +84 %font "FluidR3_GS.sf2" 128 56 84 amp=96 pan=0 # bubbles bubbles diff --git a/packages/tools/sound/timidity/config/freepats.cfg b/packages/tools/sound/timidity/config/freepats.cfg new file mode 100644 index 000000000..e7cca8209 --- /dev/null +++ b/packages/tools/sound/timidity/config/freepats.cfg @@ -0,0 +1,135 @@ + +drumset 0 + + 25 /storage/.config/timidity/freepats/Drum_000/025_Snare_Roll.pat + 26 /storage/.config/timidity/freepats/Drum_000/026_Snap.pat + 27 /storage/.config/timidity/freepats/Drum_000/027_High_Q.pat + 31 /storage/.config/timidity/freepats/Drum_000/031_Sticks.pat + 32 /storage/.config/timidity/freepats/Drum_000/032_Square_Click.pat + 33 /storage/.config/timidity/freepats/Drum_000/033_Metronome_Click.pat + 34 /storage/.config/timidity/freepats/Drum_000/034_Metronome_Bell.pat + 35 /storage/.config/timidity/freepats/Drum_000/035_Kick_1.pat amp=100 + 36 /storage/.config/timidity/freepats/Drum_000/036_Kick_2.pat amp=100 + 37 /storage/.config/timidity/freepats/Drum_000/037_Stick_Rim.pat + 38 /storage/.config/timidity/freepats/Drum_000/038_Snare_1.pat + 39 /storage/.config/timidity/freepats/Drum_000/039_Clap_Hand.pat amp=100 + 40 /storage/.config/timidity/freepats/Drum_000/040_Snare_2.pat + 41 /storage/.config/timidity/freepats/Drum_000/041_Tom_Low_2.pat amp=100 + 42 /storage/.config/timidity/freepats/Drum_000/042_Hi-Hat_Closed.pat + 43 /storage/.config/timidity/freepats/Drum_000/043_Tom_Low_1.pat amp=100 + 44 /storage/.config/timidity/freepats/Drum_000/044_Hi-Hat_Pedal.pat + 45 /storage/.config/timidity/freepats/Drum_000/045_Tom_Mid_2.pat amp=100 + 46 /storage/.config/timidity/freepats/Drum_000/046_Hi-Hat_Open.pat + 47 /storage/.config/timidity/freepats/Drum_000/047_Tom_Mid_1.pat amp=100 + 48 /storage/.config/timidity/freepats/Drum_000/048_Tom_High_2.pat amp=100 + 49 /storage/.config/timidity/freepats/Drum_000/049_Cymbal_Crash_1.pat + 50 /storage/.config/timidity/freepats/Drum_000/050_Tom_High_1.pat amp=100 + 51 /storage/.config/timidity/freepats/Drum_000/051_Cymbal_Ride_1.pat + 52 /storage/.config/timidity/freepats/Drum_000/052_Cymbal_Chinese.pat + 53 /storage/.config/timidity/freepats/Drum_000/053_Cymbal_Ride_Bell.pat amp=100 + 54 /storage/.config/timidity/freepats/Drum_000/054_Tombourine.pat + 55 /storage/.config/timidity/freepats/Drum_000/055_Cymbal_Splash.pat + 56 /storage/.config/timidity/freepats/Drum_000/056_Cow_Bell.pat + 57 /storage/.config/timidity/freepats/Drum_000/057_Cymbal_Crash_2.pat + 58 /storage/.config/timidity/freepats/Drum_000/058_Vibra-Slap.pat + 59 /storage/.config/timidity/freepats/Drum_000/059_Cymbal_Ride_2.pat + 60 /storage/.config/timidity/freepats/Drum_000/060_Bongo_High.pat + 61 /storage/.config/timidity/freepats/Drum_000/061_Bongo_Low.pat + 62 /storage/.config/timidity/freepats/Drum_000/062_Conga_High_1_Mute.pat + 63 /storage/.config/timidity/freepats/Drum_000/063_Conga_High_2_Open.pat + 64 /storage/.config/timidity/freepats/Drum_000/064_Conga_Low.pat + 65 /storage/.config/timidity/freepats/Drum_000/065_Timbale_High.pat + 66 /storage/.config/timidity/freepats/Drum_000/066_Timbale_Low.pat + 67 /storage/.config/timidity/freepats/Drum_000/067_Agogo_High.pat + 68 /storage/.config/timidity/freepats/Drum_000/068_Agogo_Low.pat + 69 /storage/.config/timidity/freepats/Drum_000/069_Cabasa.pat amp=100 + 70 /storage/.config/timidity/freepats/Drum_000/070_Maracas.pat + 71 /storage/.config/timidity/freepats/Drum_000/071_Whistle_1_High_Short.pat + 72 /storage/.config/timidity/freepats/Drum_000/072_Whistle_2_Low_Long.pat + 73 /storage/.config/timidity/freepats/Drum_000/073_Guiro_1_Short.pat + 74 /storage/.config/timidity/freepats/Drum_000/074_Guiro_2_Long.pat + 75 /storage/.config/timidity/freepats/Drum_000/075_Claves.pat amp=100 + 76 /storage/.config/timidity/freepats/Drum_000/076_Wood_Block_1_High.pat + 77 /storage/.config/timidity/freepats/Drum_000/077_Wood_Block_2_Low.pat + 78 /storage/.config/timidity/freepats/Drum_000/078_Cuica_1_Mute.pat amp=100 + 79 /storage/.config/timidity/freepats/Drum_000/079_Cuica_2_Open.pat amp=100 + 80 /storage/.config/timidity/freepats/Drum_000/080_Triangle_1_Mute.pat + 81 /storage/.config/timidity/freepats/Drum_000/081_Triangle_2_Open.pat + 82 /storage/.config/timidity/freepats/Drum_000/082_Shaker.pat + 84 /storage/.config/timidity/freepats/Drum_000/084_Belltree.pat + +bank 0 + + 0 /storage/.config/timidity/freepats/Tone_000/000_Acoustic_Grand_Piano.pat amp=120 pan=center + 1 /storage/.config/timidity/freepats/Tone_000/001_Acoustic_Brite_Piano.pat + 2 /storage/.config/timidity/freepats/Tone_000/002_Electric_Grand_Piano.pat + 4 /storage/.config/timidity/freepats/Tone_000/004_Electric_Piano_1_Rhodes.pat + 5 /storage/.config/timidity/freepats/Tone_000/005_Electric_Piano_2_Chorused_Yamaha_DX.pat + 6 /storage/.config/timidity/freepats/Tone_000/006_Harpsichord.pat + 7 /storage/.config/timidity/freepats/Tone_000/007_Clavinet.pat + 8 /storage/.config/timidity/freepats/Tone_000/008_Celesta.pat + 9 /storage/.config/timidity/freepats/Tone_000/009_Glockenspiel.pat + 13 /storage/.config/timidity/freepats/Tone_000/013_Xylophone.pat + 14 /storage/.config/timidity/freepats/Tone_000/014_Tubular_Bells.pat + 15 /storage/.config/timidity/freepats/Tone_000/015_Dulcimer.pat + 16 /storage/.config/timidity/freepats/Tone_000/016_Hammond_Organ.pat + 19 /storage/.config/timidity/freepats/Tone_000/019_Church_Organ.pat + 21 /storage/.config/timidity/freepats/Tone_000/021_Accordion.pat + 23 /storage/.config/timidity/freepats/Tone_000/023_Tango_Accordion.pat + 24 /storage/.config/timidity/freepats/Tone_000/024_Nylon_Guitar.pat + 25 /storage/.config/timidity/freepats/Tone_000/025_Steel_Guitar.pat + 26 /storage/.config/timidity/freepats/Tone_000/026_Jazz_Guitar.pat + 27 /storage/.config/timidity/freepats/Tone_000/027_Clean_Electric_Guitar.pat + 28 /storage/.config/timidity/freepats/Tone_000/028_Muted_Electric_Guitar.pat + 29 /storage/.config/timidity/freepats/Tone_000/029_Overdriven_Guitar.pat + 30 /storage/.config/timidity/freepats/Tone_000/030_Distortion_Guitar.pat + 32 /storage/.config/timidity/freepats/Tone_000/032_Acoustic_Bass.pat + 33 /storage/.config/timidity/freepats/Tone_000/033_Finger_Bass.pat + 34 /storage/.config/timidity/freepats/Tone_000/034_Pick_Bass.pat + 35 /storage/.config/timidity/freepats/Tone_000/035_Fretless_Bass.pat + 36 /storage/.config/timidity/freepats/Tone_000/036_Slap_Bass_1.pat + 37 /storage/.config/timidity/freepats/Tone_000/037_Slap_Bass_2.pat + 38 /storage/.config/timidity/freepats/Tone_000/038_Synth_Bass_1.pat + 40 /storage/.config/timidity/freepats/Tone_000/040_Violin.pat + 42 /storage/.config/timidity/freepats/Tone_000/042_Cello.pat + 44 /storage/.config/timidity/freepats/Tone_000/044_Tremolo_Strings.pat + 45 /storage/.config/timidity/freepats/Tone_000/045_Pizzicato_Strings.pat + 46 /storage/.config/timidity/freepats/Tone_000/046_Harp.pat + 47 /storage/.config/timidity/freepats/Tone_000/047_Timpani.pat + 48 /storage/.config/timidity/freepats/Tone_000/048_String_Ensemble_1_Marcato.pat + 53 /storage/.config/timidity/freepats/Tone_000/053_Voice_Oohs.pat + 56 /storage/.config/timidity/freepats/Tone_000/056_Trumpet.pat + 57 /storage/.config/timidity/freepats/Tone_000/057_Trombone.pat + 58 /storage/.config/timidity/freepats/Tone_000/058_Tuba.pat + 59 /storage/.config/timidity/freepats/Tone_000/059_Muted_Trumpet.pat + 60 /storage/.config/timidity/freepats/Tone_000/060_French_Horn.pat + 61 /storage/.config/timidity/freepats/Tone_000/061_Brass_Section.pat + 64 /storage/.config/timidity/freepats/Tone_000/064_Soprano_Sax.pat + 65 /storage/.config/timidity/freepats/Tone_000/065_Alto_Sax.pat + 66 /storage/.config/timidity/freepats/Tone_000/066_Tenor_Sax.pat + 67 /storage/.config/timidity/freepats/Tone_000/067_Baritone_Sax.pat + 68 /storage/.config/timidity/freepats/Tone_000/068_Oboe.pat + 69 /storage/.config/timidity/freepats/Tone_000/069_English_Horn.pat + 70 /storage/.config/timidity/freepats/Tone_000/070_Bassoon.pat + 71 /storage/.config/timidity/freepats/Tone_000/071_Clarinet.pat + 72 /storage/.config/timidity/freepats/Tone_000/072_Piccolo.pat + 73 /storage/.config/timidity/freepats/Tone_000/073_Flute.pat + 74 /storage/.config/timidity/freepats/Tone_000/074_Recorder.pat + 75 /storage/.config/timidity/freepats/Tone_000/075_Pan_Flute.pat + 76 /storage/.config/timidity/freepats/Tone_000/076_Bottle_Blow.pat + 79 /storage/.config/timidity/freepats/Tone_000/079_Ocarina.pat + 80 /storage/.config/timidity/freepats/Tone_000/080_Square_Wave.pat + 84 /storage/.config/timidity/freepats/Tone_000/084_Charang.pat + 88 /storage/.config/timidity/freepats/Tone_000/088_New_Age.pat + 94 /storage/.config/timidity/freepats/Tone_000/094_Halo_Pad.pat + 95 /storage/.config/timidity/freepats/Tone_000/095_Sweep_Pad.pat + 98 /storage/.config/timidity/freepats/Tone_000/098_Crystal.pat + 101 /storage/.config/timidity/freepats/Tone_000/101_Goblins--Unicorn.pat + 102 /storage/.config/timidity/freepats/Tone_000/102_Echo_Voice.pat + 104 /storage/.config/timidity/freepats/Tone_000/104_Sitar.pat + 114 /storage/.config/timidity/freepats/Tone_000/114_Steel_Drums.pat + 115 /storage/.config/timidity/freepats/Tone_000/115_Wood_Block.pat + 120 /storage/.config/timidity/freepats/Tone_000/120_Guitar_Fret_Noise.pat + 122 /storage/.config/timidity/freepats/Tone_000/122_Seashore.pat + 125 /storage/.config/timidity/freepats/Tone_000/125_Helicopter.pat + diff --git a/packages/tools/sound/timidity/config/soundfont_readme.txt b/packages/tools/sound/timidity/config/soundfont_readme.txt new file mode 100644 index 000000000..8f1c9ef70 --- /dev/null +++ b/packages/tools/sound/timidity/config/soundfont_readme.txt @@ -0,0 +1,9 @@ +If you want music using FluidR3_GM and FluidR3_GS you need to download the soundfonts from: +https://osdn.net/projects/sfnet_androidframe/downloads/soundfonts/FluidR3_GM.sf2/ +https://osdn.net/projects/sfnet_androidframe/downloads/soundfonts/FluidR3_GS.sf2/ +and place them in /storage/roms/bios/timidity/sf2 + + +If you want music using freepats you need to download http://freepats.zenvoid.org/freepats-20060219.zip +and unzip the file to /storage/roms/bios/timidity/freepats + diff --git a/packages/tools/sound/timidity/config/timidity.cfg b/packages/tools/sound/timidity/config/timidity.cfg new file mode 100644 index 000000000..3ce424fd2 --- /dev/null +++ b/packages/tools/sound/timidity/config/timidity.cfg @@ -0,0 +1,42 @@ +# Instrument configuration file for timidity +# $Id: timidity.cfg,v 1.7 2005/09/03 19:26:03 hmh Exp $ + +# You can change just about every option in TiMidity++ using +# This config file. Please refer to the timidity.cfg(5) manpage +# for more details + +## If you have a slow CPU, uncomment these: +#opt EFresamp=d #disable resampling +#opt EFvlpf=d #disable VLPF +#opt EFreverb=d #disable reverb +#opt EFchorus=d #disable chorus +#opt EFdelay=d #disable delay +#opt anti-alias=d #disable sample anti-aliasing +#opt EWPVSETOZ #disable all Midi Controls +#opt p32a #default to 32 voices with auto reduction +#opt s32kHz #default sample frequency to 32kHz +#opt fast-decay #fast decay notes + +## If you have a moderate CPU, try these: +#opt EFresamp=l +#opt EFreverb=g,42 +#opt EFchorus=s +#opt s32kHz +#opt p64a + +# Disabling some of the Midi Controls can help with the CPU usage a lot. +# The same goes to the VLPF, sample anti-aliasing and effects such as +# reverb and chorus + + +# By default, try to use the instrument patches from GeneralUser.cfg: + +source /storage/.config/timidity/GeneralUser.cfg + +# alternatively, you can use freepats +# source /storage/.config/timidity/freepats.cfg + +# or alternatively, you can use the fluid-soundfont: +# source /storage/.config/timidity/fluidr3_gm.cfg +# source /storage/.config/timidity/fluidr3_gs.cfg + diff --git a/packages/tools/sound/timidity/package.mk b/packages/tools/sound/timidity/package.mk new file mode 100644 index 000000000..1899266e2 --- /dev/null +++ b/packages/tools/sound/timidity/package.mk @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="timidity" +PKG_VERSION="2.15.0" +PKG_ARCH="any" +PKG_LICENSE="GPL2" +PKG_SITE="https://sourceforge.net/projects/timidity/" +PKG_URL="$SOURCEFORGE_SRC/timidity/TiMidity++-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain SDL2 SDL2_mixer" +PKG_LONGDESC="TiMidity++" +PKG_TOOLCHAIN="autotools" + +pre_configure_target() { + # doesn't like to be build in target folder + cd $PKG_BUILD + rm -fr .$TARGET_NAME + + # simple tool can be build directly + $HOST_CC timidity/calcnewt.c -o timidity/calcnewt_host -lm + + PKG_CONFIGURE_OPTS_TARGET="--host=${TARGET_NAME} \ + enable_audio=alsa \ + --with-default-output=alsa \ + --with-default-path=/storage/.config/timidity \ + lib_cv_va_copy=yes \ + lib_cv___va_copy=yes \ + lib_cv_va_val_copy=no" +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/timidity + cp -rf $PKG_DIR/config/* $INSTALL/usr/config/timidity + + mkdir -p $INSTALL/usr/bin + cp $PKG_BUILD/timidity/timidity $INSTALL/usr/bin +} diff --git a/packages/tools/sound/timidity/patches/02-calcnewt-host-build.patch b/packages/tools/sound/timidity/patches/02-calcnewt-host-build.patch new file mode 100644 index 000000000..d8d59c01b --- /dev/null +++ b/packages/tools/sound/timidity/patches/02-calcnewt-host-build.patch @@ -0,0 +1,28 @@ +--- a/timidity/Makefile.am 2008-03-30 04:31:14.000000000 +0200 ++++ b/timidity/Makefile.am 2020-08-17 10:55:25.271404644 +0200 +@@ -446,21 +446,21 @@ resample.c: newton_table.c + + if VCPP + newton_table.c: calcnewt$(EXEEXT) +- ./calcnewt $@ ++ ./calcnewt_host $@ + + else + if POCC + newton_table.c: calcnewt$(EXEEXT) +- ./calcnewt $@ ++ ./calcnewt_host $@ + + else + if WATCOM_C + newton_table.c: calcnewt$(EXEEXT) +- ./calcnewt > $@ ++ ./calcnewt_host > $@ + + else + newton_table.c: calcnewt$(EXEEXT) +- ./calcnewt > $@ ++ ./calcnewt_host > $@ + + endif + endif diff --git a/packages/tools/sound/timidity/patches/03-ar-cru-fix.patch b/packages/tools/sound/timidity/patches/03-ar-cru-fix.patch new file mode 100644 index 000000000..78ababd58 --- /dev/null +++ b/packages/tools/sound/timidity/patches/03-ar-cru-fix.patch @@ -0,0 +1,11 @@ +--- a/interface/Makefile.am 2013-12-12 03:04:52.000000000 +0100 ++++ b/interface/Makefile.am 2020-08-17 10:56:55.977780546 +0200 +@@ -220,7 +220,7 @@ if POCC + if test -f interface.lib ; then touch $@ ; fi + else + rm -f libinterface.a +- $(AR) cru libinterface.a $(libinterface_a_OBJECTS) $(libinterface_a_LIBADD) ++ $(AR) cr libinterface.a $(libinterface_a_OBJECTS) $(libinterface_a_LIBADD) + $(RANLIB) libinterface.a + endif + endif diff --git a/packages/tools/syslinux/package.mk b/packages/tools/syslinux/package.mk new file mode 100644 index 000000000..25b8bb421 --- /dev/null +++ b/packages/tools/syslinux/package.mk @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="syslinux" +PKG_VERSION="6.03" +PKG_SHA256="26d3986d2bea109d5dc0e4f8c4822a459276cf021125e8c9f23c3cca5d8c850e" +PKG_ARCH="x86_64 aarch64" +PKG_LICENSE="GPL" +PKG_SITE="http://syslinux.zytor.com/" +PKG_URL="http://www.kernel.org/pub/linux/utils/boot/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_HOST="util-linux:host" +PKG_DEPENDS_TARGET="toolchain util-linux e2fsprogs syslinux:host" +PKG_LONGDESC="The SYSLINUX project covers lightweight linux bootloaders." + +pre_configure_target() { + PKG_MAKE_OPTS_TARGET="CC=$CC AR=$AR RANLIB=$RANLIB installer" + +# Unset all compiler FLAGS + unset CFLAGS + unset CPPFLAGS + unset CXXFLAGS + unset LDFLAGS +} + +pre_build_target() { + mkdir -p $PKG_BUILD/.$TARGET_NAME + cp -RP $PKG_BUILD/* $PKG_BUILD/.$TARGET_NAME +} + +pre_build_host() { + mkdir -p $PKG_BUILD/.$HOST_NAME + cp -RP $PKG_BUILD/* $PKG_BUILD/.$HOST_NAME +} + +pre_make_target() { + cd .$TARGET_NAME +} + +pre_make_host() { + cd .$HOST_NAME +} + +make_host() { + make CC=$CC \ + AR=$AR \ + RANLIB=$RANLIB \ + CFLAGS="-I${TOOLCHAIN}/include -I$PKG_BUILD/libinstaller -I$PKG_BUILD/libfat -I$PKG_BUILD/bios -I$PKG_BUILD/utils -fomit-frame-pointer -D_FILE_OFFSET_BITS=64" \ + LDFLAGS="-L${TOOLCHAIN}/lib" \ + installer +} + +makeinstall_host() { + mkdir -p ${TOOLCHAIN}/bin + cp bios/linux/syslinux ${TOOLCHAIN}/bin + cp bios/mtools/syslinux ${TOOLCHAIN}/bin/syslinux.mtools + + mkdir -p ${TOOLCHAIN}/share/syslinux + cp bios/mbr/mbr.bin ${TOOLCHAIN}/share/syslinux + cp bios/mbr/gptmbr.bin ${TOOLCHAIN}/share/syslinux + cp efi64/efi/syslinux.efi ${TOOLCHAIN}/share/syslinux/bootx64.efi + cp efi64/com32/elflink/ldlinux/ldlinux.e64 ${TOOLCHAIN}/share/syslinux +} + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + cp bios/linux/syslinux ${INSTALL}/usr/bin + + $STRIP ${INSTALL}/usr/bin/syslinux + + mkdir -p ${INSTALL}/usr/share/syslinux + cp bios/mbr/mbr.bin ${INSTALL}/usr/share/syslinux + cp bios/mbr/gptmbr.bin ${INSTALL}/usr/share/syslinux + cp efi64/efi/syslinux.efi ${INSTALL}/usr/share/syslinux/bootx64.efi + cp efi64/com32/elflink/ldlinux/ldlinux.e64 ${INSTALL}/usr/share/syslinux +} diff --git a/packages/tools/syslinux/patches/syslinux-0001-fix-build-with-glibc_2.28.patch b/packages/tools/syslinux/patches/syslinux-0001-fix-build-with-glibc_2.28.patch new file mode 100644 index 000000000..a39019e61 --- /dev/null +++ b/packages/tools/syslinux/patches/syslinux-0001-fix-build-with-glibc_2.28.patch @@ -0,0 +1,33 @@ +From 1a74985b2a404639b08882c57f3147229605dfd5 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Tue, 19 Apr 2016 06:50:31 -0400 +Subject: [PATCH] extlinux: pull in sys/sysmacros.h for major/minor/makedev + +These functions are defined in sys/sysmacros.h, so add the include to +main.c. This is already handled correctly in mountinfo.c. Otherwise +we get build failures like: + +main.o: In function 'find_device_sysfs': +extlinux/main.c:1131: undefined reference to 'minor' + +Signed-off-by: Mike Frysinger +Signed-off-by: Gene Cumm +--- + extlinux/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/extlinux/main.c b/extlinux/main.c +index a7ebd49..ebff7ea 100644 +--- a/extlinux/main.c ++++ b/extlinux/main.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.10.5.GIT + diff --git a/packages/tools/sysutils/MC/etc/edit.indent.rc b/packages/tools/sysutils/MC/etc/edit.indent.rc new file mode 100644 index 000000000..92f82d595 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/edit.indent.rc @@ -0,0 +1,31 @@ +#! /bin/sh +# *** External Formatter (Indenter) for GNU Midnight Commander. +# arguments: +# $1 - Name of the file being edited +# $2 - Name of the file to be processed + +exec >/dev/null + +case `echo $1 |sed 's/^.*\.//'` in + c|h) + # ftp://ftp.gnu.org/pub/gnu/indent/ + # Please add options to your ~/.indent.pro, not here. + indent "$2" + ;; + C|cc|CC|cxx|CXX|cpp|CPP) + # http://astyle.sourceforge.net/ + astyle "$2" + ;; + java|JAVA) + # http://astyle.sourceforge.net/ + astyle --style=java --mode=java "$2" + ;; + htm|html|HTM|HTML) + # http://tidy.sourceforge.net/ + tidy -q -m -ascii -wrap 80 "$2" + ;; + *) + # http://www.gnu.org/software/coreutils/ + fmt "$2" >"$2.tmp" && rm -f "$2" && mv -f "$2.tmp" "$2" + ;; +esac diff --git a/packages/tools/sysutils/MC/etc/edit.spell.rc b/packages/tools/sysutils/MC/etc/edit.spell.rc new file mode 100644 index 000000000..e9dee8bbe --- /dev/null +++ b/packages/tools/sysutils/MC/etc/edit.spell.rc @@ -0,0 +1,11 @@ +#! /bin/sh +# *** External Spell Checker for GNU Midnight Commander. +# arguments: +# $1 - Name of the file being edited +# $2 - Name of the file to be processed + +if aspell /dev/null 2>&1; then + aspell -c "$2" +else + ispell "$2" +fi diff --git a/packages/tools/sysutils/MC/etc/filehighlight.ini b/packages/tools/sysutils/MC/etc/filehighlight.ini new file mode 100644 index 000000000..af911fed9 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/filehighlight.ini @@ -0,0 +1,47 @@ +[executable] + type=FILE_EXE + +[directory] + type=DIR + +[device] + type=DEVICE + +[special] + type=SPECIAL + +[stalelink] + type=STALE_LINK + +[symlink] + type=SYMLINK + +[hardlink] + type=HARDLINK + +[core] + regexp=^core\\.*\\d*$ + +[temp] + extensions=tmp;$$$;~;bak + extensions_case=false + regexp=(^#.*|.*~$) + +[archive] + extensions=gz;bz2;tar;tgz;rpm;Z;rar;zip;arj;cab;lzh;lha;zoo;arc;ark;xz;tbz;tbz2; + +[doc] + extensions=txt;doc;rtf;diz;ctl;me;ps;pdf;xml;xsd;xslt;dtd;html;shtml;htm;mail;msg;lsm;po;nroff;man;tex;sgml;css;text;letter;chm + +[source] + extensions=c;h;cc;hh;cpp;cxx;hpp;asm;py;pl;pm;inc;cgi;php;phps;js;java;jav;jasm;sh;bash;diff;patch;pas;tcl;tk;awk;m4;st;mak;sl;ada;caml;ml;mli;mly;mll;mlp;sas;prg;hs;hi;erl + +[media] + extensions=mp2;mp3;mpg;ogg;mpeg;wav;avi;asf;mov;mol;mpl;xm;mod;it;med;mid;midi;s3m;umx;vob;mkv;flv;mp4;m3u + +[graph] + extensions=jpg;jpeg;gif;png;tif;pcx;bmp;xpm;xbm;eps;pic;rle;ico;wmf;omf;ai;cdr + +[database] + extensions=dbf;mdn;db;mdb;dat;fox;dbx;mdx;sql;mssql;msql;ssql;pgsql;xls;cdx;dbi + diff --git a/packages/tools/sysutils/MC/etc/ini b/packages/tools/sysutils/MC/etc/ini new file mode 100644 index 000000000..ba473564c --- /dev/null +++ b/packages/tools/sysutils/MC/etc/ini @@ -0,0 +1,159 @@ +[Midnight-Commander] +verbose=1 +pause_after_run=1 +shell_patterns=1 +auto_save_setup=1 +auto_menu=0 +use_internal_view=1 +use_internal_edit=1 +clear_before_exec=1 +confirm_delete=1 +confirm_overwrite=1 +confirm_execute=0 +confirm_history_cleanup=1 +confirm_exit=1 +confirm_directory_hotlist_delete=1 +safe_delete=0 +mouse_repeat_rate=100 +double_click_speed=250 +use_8th_bit_as_meta=0 +confirm_view_dir=0 +mouse_move_pages_viewer=1 +mouse_close_dialog=0 +fast_refresh=0 +drop_menus=0 +wrap_mode=1 +old_esc_mode=0 +old_esc_mode_timeout=1000000 +cd_symlinks=1 +show_all_if_ambiguous=0 +max_dirt_limit=10 +use_file_to_guess_type=1 +alternate_plus_minus=0 +only_leading_plus_minus=1 +show_output_starts_shell=0 +xtree_mode=0 +num_history_items_recorded=60 +file_op_compute_totals=1 +classic_progressbar=1 +vfs_timeout=60 +ftpfs_directory_timeout=900 +use_netrc=1 +ftpfs_retry_seconds=30 +ftpfs_always_use_proxy=0 +ftpfs_use_passive_connections=1 +ftpfs_use_passive_connections_over_proxy=0 +ftpfs_use_unix_list_options=1 +ftpfs_first_cd_then_ls=1 +fish_directory_timeout=900 +editor_tab_spacing=8 +editor_word_wrap_line_length=72 +editor_fill_tabs_with_spaces=0 +editor_return_does_auto_indent=1 +editor_backspace_through_tabs=0 +editor_fake_half_tabs=1 +editor_option_save_mode=0 +editor_option_save_position=1 +editor_option_auto_para_formatting=0 +editor_option_typewriter_wrap=0 +editor_edit_confirm_save=1 +editor_syntax_highlighting=1 +editor_persistent_selections=1 +editor_cursor_beyond_eol=0 +editor_visible_tabs=1 +editor_visible_spaces=1 +editor_line_state=0 +editor_simple_statusbar=0 +editor_check_new_line=0 +editor_show_right_margin=0 +editor_group_undo=0 +nice_rotating_dash=1 +mcview_remember_file_position=0 +auto_fill_mkdir_name=1 +copymove_persistent_attr=1 +select_flags=6 +editor_backup_extension=~ +mcview_eof= +ignore_ftp_chattr_errors=true +keymap=mc.keymap +skin=default + +filepos_max_saved_entries=1024 + +preallocate_space=0 +editor_cursor_after_inserted_block=0 +editor_ask_filename_before_edit=0 +editor_filesize_threshold=64M + +[Layout] +message_visible=0 +keybar_visible=1 +xterm_title=1 +output_lines=0 +command_prompt=1 +menubar_visible=1 +free_space=1 + +horizontal_split=0 +vertical_equal=1 +left_panel_size=118 +horizontal_equal=1 +top_panel_size=118 + +[Misc] +timeformat_recent=%b %e %H:%M +timeformat_old=%b %e %Y +ftp_proxy_host=gate +ftpfs_password=anonymous@ +display_codepage=UTF-8 +source_codepage=UTF-8 +autodetect_codeset= +clipboard_store= +clipboard_paste= + +[Colors] +base_color= +linux= +color_terminals= + +xterm= + +[Panels] +show_mini_info=true +kilobyte_si=false +mix_all_files=false +show_backups=true +show_dot_files=true +fast_reload=false +fast_reload_msg_shown=false +mark_moves_down=true +reverse_files_only=true +auto_save_setup_panels=true +navigate_with_arrows=false +panel_scroll_pages=true +mouse_move_pages=true +filetype_mode=true +permission_mode=false +torben_fj_mode=false +quick_search_mode=2 + +simple_swap=false + +[terminal:linux] +f1=\\e[11~ +f2=\\e[12~ +f3=\\e[13~ +f4=\\e[14~ +f5=\\e[15~ + +[terminal:xterm] +f1=\\e[11~ +up=\\e[A +down=\\e[B +left=\\e[D +right=\\e[C + +[Panelize] +Find *.orig after patching=find . -name \\*.orig -print +Find SUID and SGID programs=find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print +Find rejects after patching=find . -name \\*.rej -print diff --git a/packages/tools/sysutils/MC/etc/mc.ext b/packages/tools/sysutils/MC/etc/mc.ext new file mode 100644 index 000000000..204d1a5f6 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.ext @@ -0,0 +1,684 @@ +# Midnight Commander 3.0 extension file +# Warning: Structure of this file has changed completely with version 3.0 +# +# All lines starting with # or empty lines are thrown away. +# Lines starting in the first column should have following format: +# +# keyword/descNL, i.e. everything after keyword/ until new line is desc +# +# keyword can be: +# +# shell (desc is, when starting with a dot, any extension (no wildcars), +# i.e. matches all the files *desc . Example: .tar matches *.tar; +# if it doesn't start with a dot, it matches only a file of that name) +# +# regex (desc is an extended regular expression) +# Please note that we are using the GNU regex library and thus +# \| matches the literal | and | has special meaning (or) and +# () have special meaning and \( \) stand for literal ( ). +# +# type (file matches this if `file %f` matches regular expression desc +# (the filename: part from `file %f` is removed)) +# +# directory (matches any directory matching regular expression desc) +# +# include (matches an include directive) +# +# default (matches any file no matter what desc is) +# +# Other lines should start with a space or tab and should be in the format: +# +# keyword=commandNL (with no spaces around =), where keyword should be: +# +# Open (if the user presses Enter or doubleclicks it), +# +# View (F3), Edit (F4) +# +# Include is the keyword used to add any further entries from an include/ +# section +# +# command is any one-line shell command, with the following substitutions: +# +# %% -> % character +# %p -> name of the current file (without path, but pwd is its path) +# %f -> name of the current file. Unlike %p, if file is located on a +# non-local virtual filesystem, i.e. either tarfs or ftpfs, +# then the file will be temporarily copied into a local directory +# and %f will be the full path to this local temporal file. +# If you don't want to get a local copy and want to get the +# virtual fs path (like /#ftp:ftp.cvut.cz/pub/hungry/xword), then +# use %d/%p instead of %f. +# %d -> name of the current directory (pwd, without trailing slash) +# %s -> "selected files", i.e. space separated list of tagged files if any +# or name of the current file +# %t -> list of tagged files +# %u -> list of tagged files (they'll be untaged after the command) +# +# (If these 6 letters are in uppercase, they refer to the other panel. +# But you shouldn't have to use it in this file.) +# +# +# %cd -> the rest is a path mc should change into (cd won't work, since it's +# a child process). %cd handles even vfs names. +# +# %view -> the command you type will be piped into mc's internal file viewer +# if you type only the %view and no command, viewer will load %f file +# instead (i.e. no piping, so it is different to %view cat %f) +# %view may be directly followed by {} with a list of any of +# ascii (Ascii mode), hex (Hex mode), nroff (color highlighting for +# text using backspace for bold and underscore) and unform +# (no highlighting for nroff sequences) separated by commas. +# +# %var -> You use it like this: %var{VAR:default}. This macro will expand +# to the value of the VAR variable in the environment if it's set +# otherwise the value in default will be used. This is similar to +# the Bourne shell ${VAR-default} construct. +# +# Rules are applied from top to bottom, thus the order is important. +# If some actions are missing, search continues as if this target didn't +# match (i.e. if a file matches the first and second entry and View action +# is missing in the first one, then on pressing F3 the View action from +# the second entry will be used. default should catch all the actions. +# +# Any new entries you develop for you are always welcome if they are +# useful on more than one system. You can post your modifications +# as tickets at www.midnight-commander.org + + +### Changes ### +# +# Reorganization: 2000-05-01 Michal Svec + + +### TODO ### +# +# Postscript Open: ps2svga [gs -DEVICE=jpeg|zgv or something] +# Images asciiview +# +# All X Apps [Nothing/Warning] if no DISPLAY +# Not found [Default/Warning] +# Empty Output [Default/Warning] +# Edit: CopyOut+EDIT+CopyIn +# Security Check gzip/bzip EDIT (mktemp) +# +# Maybe: Open/XOpen/GOpen/KOpen/... for Console/X/GNOME/KDE/etc. + + +### GIT Repo ### +# gitfs changeset +regex/^\[git\] + Open=%cd %p/changesetfs:// + View=%cd %p/patchsetfs:// + +### Archives ### + +# .tgz, .tpz, .tar.gz, .tar.z, .tar.Z, .ipk +regex/\.t([gp]?z|ar\.g?[zZ])$|\.ipk$ + Open=%cd %p/utar:// + View=%view{ascii} gzip -dc %f 2>/dev/null | tar tvvf - + +regex/\.tar\.bz$ + # Open=%cd %p/utar:// + View=%view{ascii} bzip -dc %f 2>/dev/null | tar tvvf - + +regex/\.t(ar\.bz2|bz2?|b2)$ + Open=%cd %p/utar:// + View=%view{ascii} bzip2 -dc %f 2>/dev/null | tar tvvf - + +# .tar.lzma, .tlz +regex/\.t(ar\.lzma|lz)$ + Open=%cd %p/utar:// + View=%view{ascii} lzma -dc %f 2>/dev/null | tar tvvf - + +# .tar.xz, .txz +regex/\.t(ar\.xz|xz)$ + Open=%cd %p/utar:// + View=%view{ascii} xz -dc %f 2>/dev/null | tar tvvf - + +# .tar.F - used in QNX +regex/\.tar\.F$ + # Open=%cd %p/utar:// + View=%view{ascii} freeze -dc %f 2>/dev/null | tar tvvf - + +# .qpr/.qpk - QNX Neutrino package installer files +regex/\.(qp[rk])$ + Open=%cd %p/utar:// + View=%view{ascii} gzip -dc %f 2>/dev/null | tar tvvf - + +# tar +regex/\.(tar|TAR)$ + Open=%cd %p/utar:// + View=%view{ascii} tar tvvf - < %f + +# lha +type/^LHa\ .*archive + Open=%cd %p/ulha:// + View=%view{ascii} lha l %f + +# arj +regex/\.a(rj|[0-9][0-9])$ + Open=%cd %p/uarj:// + View=%view{ascii} unarj l %f + +# cab +regex/\.([cC][aA][bB])$ + Open=%cd %p/ucab:// + View=%view{ascii} cabextract -l %f + +# ha +regex/\.([Hh][Aa])$ + Open=%cd %p/uha:// + View=%view{ascii} ha lf %f + +# rar +regex/\.[rR]([aA][rR]|[0-9][0-9])$ + Open=%cd %p/urar:// + View=%view{ascii} rar v -c- %f + +# ALZip +regex/\.(alz|ALZ)$ + Open=%cd %p/ualz:// + View=%view{ascii} unalz -l %f + +# cpio +shell/.cpio.Z + Open=%cd %p/ucpio:// + View=%view{ascii} gzip -dc %f | cpio -itv 2>/dev/null + +shell/.cpio.gz + Open=%cd %p/ucpio:// + View=%view{ascii} gzip -dc %f | cpio -itv 2>/dev/null + +shell/.cpio + Open=%cd %p/ucpio:// + View=%view{ascii} cpio -itv < %f 2>/dev/null + +# ls-lR +regex/(^|\.)ls-?lR(\.gz|Z|bz2)$ + Open=%cd %p/lslR:// + +# patch +regex/\.(diff|patch)(\.bz2)$ + Open=%cd %p/patchfs:// + View=%view{ascii} bzip2 -dc %f 2>/dev/null + +regex/\.(diff|patch)(\.(gz|Z))$ + Open=%cd %p/patchfs:// + View=%view{ascii} gzip -dc %f 2>/dev/null + +regex/\.(diff|patch)$ + Open=%cd %p/patchfs:// + View=%view{ascii} /bin/cat %f 2>/dev/null + +# ar library +regex/\.s?a$ + Open=%cd %p/uar:// + #Open=%view{ascii} ar tv %f + View=%view{ascii} file %f && nm -C %f + +# trpm +regex/\.trpm$ + Open=%cd %p/trpm:// + View=%view{ascii} rpm -qivl --scripts `basename %p .trpm` + +# RPM packages (SuSE uses *.spm for source packages) +regex/\.(src\.rpm|spm)$ + Open=%cd %p/rpm:// + View=%view{ascii} if rpm --nosignature --version >/dev/null 2>&1; then RPM="rpm --nosignature" ; else RPM="rpm" ; fi ; $RPM -qivlp --scripts %f + +regex/\.rpm$ + Open=%cd %p/rpm:// + View=%view{ascii} if rpm --nosignature --version >/dev/null 2>&1; then RPM="rpm --nosignature" ; else RPM="rpm" ; fi ; $RPM -qivlp --scripts %f + +# deb +regex/\.u?deb$ + Open=%cd %p/deb:// + View=%view{ascii} dpkg-deb -I %f && echo && dpkg-deb -c %f + +# dpkg +shell/.debd + Open=%cd %p/debd:// + View=%view{ascii} dpkg -s `echo %p | sed 's/\([0-9a-z.-]*\).*/\1/'` +# apt +shell/.deba + Open=%cd %p/deba:// + View=%view{ascii} apt-cache show `echo %p | sed 's/\([0-9a-z.-]*\).*/\1/'` + +# ISO9660 +regex/\.([iI][sS][oO])$ + Open=%cd %p/iso9660:// + View=%view{ascii} isoinfo -l -i %f + +# 7zip archives (they are not man pages) +regex/\.(7z|7Z)$ + Open=%cd %p/u7z:// + View=%view{ascii} 7za l %f 2>/dev/null + +# Mailboxes +type/^ASCII\ mail\ text + Open=%cd %p/mailfs:// + + +### Sources ### + +# C +shell/.c + Include=editor + +# Fortran +shell/.f + Include=editor + +# Header +regex/\.(h|hpp)$ + Include=editor + +# Asm +shell/.s + Include=editor + +# C++ +regex/\.(C|cc|cpp)$ + Include=editor + +include/editor + Open=%var{EDITOR:vi} %f + +# .so libraries +regex/\.(so|so\.[0-9\.]*)$ + View=%view{ascii} file %f && nm -C -D %f + +# Object +type/^ELF + #Open=%var{PAGER:more} %f + View=%view{ascii} file %f && nm -C %f + +### Documentation ### + +# Texinfo +regex/\.(te?xi|texinfo)$ + +# GNU Info page +type/^Info\ text + Open=info -f %f + +shell/.info + Open=info -f %f + +# Exception: .3gp are video files not manual pages +regex/\.(3[gG][pP])$ + Include=video + +# Manual page +regex/(([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])|\.man)$ + Open=case %d/%f in */log/*|*/logs/*) cat %f ;; *) { zsoelim %f 2>/dev/null || cat %f; } | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) cat %f ;; *) { zsoelim %f 2>/dev/null || cat %f; } | nroff -c -Tlatin1 -mandoc ;; esac + +# Perl pod page +shell/.pod + Open=pod2man %f | nroff -c -Tlatin1 -mandoc | %var{PAGER:more} + View=%view{ascii,nroff} pod2man %f | nroff -c -Tlatin1 -mandoc + +# Troff with me macros. +# Exception - "read.me" is not a nroff file. +shell/read.me + Open= + View= + +shell/.me + Open=nroff -c -Tlatin1 -me %f | %var{PAGER:more} + View=%view{ascii,nroff} nroff -c -Tlatin1 -me %f + +# Troff with ms macros. +shell/.ms + Open=nroff -c -Tlatin1 -ms %f | %var{PAGER:more} + View=%view{ascii,nroff} nroff -c -Tlatin1 -ms %f + +# Manual page - compressed +regex/([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])\.g?[Zz]$ + Open=case %d/%f in */log/*|*/logs/*) gzip -dc %f ;; *) gzip -dc %f | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) gzip -dc %f ;; *) gzip -dc %f | nroff -c -Tlatin1 -mandoc ;; esac + +regex/([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])\.bz$ + Open=case %d/%f in */log/*|*/logs/*) bzip -dc %f ;; *) bzip -dc %f | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) bzip -dc %f ;; *) bzip -dc %f | nroff -c -Tlatin1 -mandoc ;; esac + +regex/([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])\.bz2$ + Open=case %d/%f in */log/*|*/logs/*) bzip2 -dc %f ;; *) bzip2 -dc %f | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) bzip2 -dc %f ;; *) bzip2 -dc %f | nroff -c -Tlatin1 -mandoc ;; esac + +regex/([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])\.lzma$ + Open=case %d/%f in */log/*|*/logs/*) lzma -dc %f ;; *) lzma -dc %f | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) lzma -dc %f ;; *) lzma -dc %f | nroff -c -Tlatin1 -mandoc ;; esac + +regex/([^0-9]|^[^\.]*)\.([1-9][A-Za-z]*|[ln])\.xz$ + Open=case %d/%f in */log/*|*/logs/*) xz -dc %f ;; *) xz -dc %f | nroff -c -Tlatin1 -mandoc ;; esac | %var{PAGER:more} + View=%view{ascii,nroff} case %d/%f in */log/*|*/logs/*) xz -dc %f ;; *) xz -dc %f | nroff -c -Tlatin1 -mandoc ;; esac + +# CHM +regex/\.(chm|CHM)$ + Open=which kchmviewer > /dev/null 2>&1 && (kchmviewer %f &) || (xchm %f &) + +### Images ### + +type/^GIF + Include=image + +type/^JPEG + View=%view{ascii} identify %f; test -x /usr/bin/exif && echo && exif %f 2>/dev/null + Include=image + +type/^PC\ bitmap + Include=image + +type/^PNG + Include=image + +type/^TIFF + Include=image + +type/^PBM + Include=image + +type/^PGM + Include=image + +type/^PPM + Include=image + +type/^Netpbm + Include=image + +shell/.xcf + Open=(gimp %f &) + +shell/.xbm + Open=bitmap %f + +shell/.xpm + Include=image + View=sxpm %f + +shell/.ico + Include=image + +include/image + Open=if [ "$DISPLAY" = "" ]; then zgv %f; else (gqview %f &); fi + View=%view{ascii} identify %f + #View=%view{ascii} asciiview %f + + +### Sound files ### + +regex/\.([wW][aA][vV]|[sS][nN][dD]|[vV][oO][cC]|[aA][uU]|[sS][mM][pP]|[aA][iI][fF][fF]|[sS][nN][dD])$ + Open=if [ "$DISPLAY" = "" ]; then play %f; else (xmms %f >/dev/null 2>&1 &); fi + +regex/\.([mM][oO][dD]|[sS]3[mM]|[xX][mM]|[iI][tT]|[mM][tT][mM]|669|[sS][tT][mM]|[uU][lL][tT]|[fF][aA][rR])$ + Open=mikmod %f + #Open=tracker %f + +regex/\.([wW][aA][wW]22)$ + Open=vplay -s 22 %f + +regex/\.([mM][pP]3)$ + Open=if [ "$DISPLAY" = "" ]; then mpg123 %f; else (xmms %f >/dev/null 2>&1 &); fi + View=%view{ascii} mpg123 -vtn1 %f 2>&1 | sed -n '/^Title/,/^Comment/p;/^MPEG/,/^Audio/p' + +regex/\.([oO][gG][gG|aA|vV|xX])$ + Open=if [ "$DISPLAY" = "" ]; then ogg123 %f; else (xmms %f >/dev/null 2>&1 &); fi + View=%view{ascii} ogginfo %s + +regex/\.([sS][pP][xX]|[fF][lL][aA][cC])$ + Open=if [ "$DISPLAY" = "" ]; then play %f; else (xmms %f >/dev/null 2>&1 &); fi + +regex/\.([mM][iI][dD][iI]?|[rR][mM][iI][dD]?)$ + Open=timidity %f + +regex/\.([wW][mM][aA])$ + Open=mplayer -vo null %f + View=%view{ascii} mplayer -quiet -slave -frames 0 -vo null -ao null -identify %f 2>/dev/null | tail +13 || file %f + + +### Play lists ### + +regex/\.([mM]3[uU]|[pP][lL][sS])$ + Open=if [ -z "$DISPLAY" ]; then mplayer -vo null -playlist %f; else (xmms -p %f >/dev/null 2>&1 &); fi + + +### Video ### + +regex/\.([aA][vV][iI])$ + Include=video + +regex/\.([aA][sS][fFxX])$ + Include=video + +regex/\.([dD][iI][vV][xX])$ + Include=video + +regex/\.([mM][kK][vV])$ + Include=video + +regex/\.([mM][oO][vV]|[qQ][tT])$ + Include=video + +regex/\.([mM][pP]4|[mM][pP][eE]?[gG])$ + Include=video + +# MPEG-2 TS container + H.264 codec +regex/\.([mM][tT][sS])$ + Include=video + +regex/\.([vV][oO][bB])$ + Include=video + +regex/\.([wW][mM][vV])$ + Include=video + +regex/\.([fF][lL][iIcCvV])$ + Include=video + +regex/\.([oO][gG][mM])$ + Include=video + +regex/\.([rR][aA]?[mM])$ + Open=(realplay %f >/dev/null 2>&1 &) + +include/video + Open=(mplayer %f >/dev/null 2>&1 &) + #Open=(gtv %f >/dev/null 2>&1 &) + #Open=(xanim %f >/dev/null 2>&1 &) + + +### Documents ### + +# Postscript +type/^PostScript + Open=(gv %f &) + View=%view{ascii} ps2ascii %f + +# PDF +type/^PDF + Open=(xpdf %f &) + #Open=(acroread %f &) + #Open=(ghostview %f &) + View=%view{ascii} pdftotext %f - + +# The following code very ugly and should not be taken as example. +# It should be cleaned up when the new format of mc.ext is developed. + +# html +regex/\.([hH][tT][mM][lL]?)$ + Open=(if test -n "" && test -n "$DISPLAY"; then ( file://%d/%p &) 1>&2; else links %f || lynx -force_html %f || ${PAGER:-more} %f; fi) 2>/dev/null + View=%view{ascii} links -dump %f 2>/dev/null || w3m -dump %f 2>/dev/null || lynx -dump -force_html %f + +# StarOffice 5.2 +shell/.sdw + Open=(ooffice %f &) + +# StarOffice 6 and OpenOffice.org formats +regex/\.(odt|ott|sxw|stw|ods|ots|sxc|stc|odp|otp|sxi|sti|odg|otg|sxd|std|odb|odf|sxm|odm|sxg)$ + Open=(ooffice %f &) + View=%view{ascii} odt2txt %f + +# AbiWord +shell/.abw + Open=(abiword %f &) + +# Microsoft Word Document +regex/\.([Dd][oO][cCtT]|[Ww][rR][iI])$ + Open=(abiword %f >/dev/null 2>&1 &) + View=%view{ascii} antiword -t %f || catdoc -w %f || word2x -f text %f - || strings %f +type/^Microsoft\ Word + Open=(abiword %f >/dev/null 2>&1 &) + View=%view{ascii} antiword -t %f || catdoc -w %f || word2x -f text %f - || strings %f + +# RTF document +regex/\.([rR][tT][fF])$ + Open=(abiword %f >/dev/null 2>&1 &) + +# Microsoft Excel Worksheet +regex/\.([xX][lL][sSwW])$ + Open=(gnumeric %f >/dev/null 2>&1 &) + View=%view{ascii} xls2csv %f || strings %f +type/^Microsoft\ Excel + Open=(gnumeric %f >/dev/null 2>&1 &) + View=%view{ascii} xls2csv %f || strings %f + +# Use OpenOffice.org to open any MS Office documents +type/^Microsoft\ Office\ Document + Open=(ooffice %f &) + +# Framemaker +type/^FrameMaker + Open=fmclient -f %f + +# DVI +regex/\.([dD][vV][iI])$ + Open=if [ x$DISPLAY = x ]; then dvisvga %f; else (xdvi %f &); fi + View=%view{ascii} dvi2tty %f + +# TeX +regex/\.([Tt][Ee][Xx])$ + Include=editor + +# DjVu +regex/\.(djvu|DJVU)$ + Open=djview %f & + +### Miscellaneous ### + +# Makefile +regex/[Mm]akefile$ + Open=make -f %f %{Enter parameters} + +# Imakefile +shell/Imakefile + Open=xmkmf -a + +# Makefile.PL (MakeMaker) +regex/^Makefile.(PL|pl)$ + Open=%var{PERL:perl} %f + +# dbf +regex/\.([dD][bB][fF])$ + Open=%view{ascii} dbview %f + View=%view{ascii} dbview -b %f + +# REXX script +regex/\.(rexx?|cmd)$ + Open=rexx %f %{Enter parameters};echo "Press ENTER";read y + +# Disk images for Commodore computers (VIC20, C64, C128) +regex/\.(d64|D64)$ + Open=%cd %p/uc1541:// + View=%view{ascii} c1541 %f -list + Extract=c1541 %f -extract + +# Glade, a user interface designer for GTK+ and GNOME +regex/\.([Gg][Ll][Aa][Dd][Ee])$ + Open=if glade-3 --version >/dev/null 2>&1; then (glade-3 %f >/dev/null 2>&1 &); else (glade-2 %f >/dev/null 2>&1 &); fi + +# Gettext Catalogs +shell/.mo + View=%view{ascii} msgunfmt %f || cat %f + +# lyx +regex/\.(lyx|LYX)$ + Open=lyx %f + View=%view{ascii} lyxcat %f + +# torrent +regex/\.([tT][oO][rR][rR][eE][nN][tT])$ + View=%view{ascii} ctorrent -x %f 2>/dev/null + +### Plain compressed files ### + +# ace +regex/\.(ace|ACE)$ + Open=%cd %p/uace:// + View=%view{ascii} unace l %f + Extract=unace x %f + +# arc +regex/\.(arc|ARC)$ + Open=%cd %p/uarc:// + View=%view{ascii} arc l %f + Extract=arc x %f '*' + Extract (with flags)=I=%{Enter any Arc flags:}; if test -n "$I"; then arc x $I %f; fi + +# zip +type/^([Zz][Ii][Pp])\ archive + Open=%cd %p/uzip:// + View=%view{ascii} unzip -v %f + +# zoo +regex/\.([Zz][Oo][Oo])$ + Open=%cd %p/uzoo:// + View=%view{ascii} zoo l %f + +# gzip +type/^gzip + Open=gzip -dc %f | %var{PAGER:more} + View=%view{ascii} gzip -dc %f 2>/dev/null + +regex/\.(gz|Z)$ + View=%view{ascii} gzip -dc %f 2>/dev/null + +# bzip2 +type/^bzip2 + Open=bzip2 -dc %f | %var{PAGER:more} + View=%view{ascii} bzip2 -dc %f 2>/dev/null + +regex/\.bz2?$ + View=%view{ascii} bzip2 -dc %f 2>/dev/null + +# bzip +type/^bzip + Open=bzip -dc %f | %var{PAGER:more} + View=%view{ascii} bzip -dc %f 2>/dev/null + +# compress +type/^compress + Open=gzip -dc %f | %var{PAGER:more} + View=%view{ascii} gzip -dc %f 2>/dev/null + +# lzma +regex/\.lzma$ + Open=lzma -dc %f | %var{PAGER:more} + View=%view{ascii} lzma -dc %f 2>/dev/null + +# xz +regex/\.xz$ + Open=xz -dc %f | %var{PAGER:more} + View=%view{ascii} xz -dc %f 2>/dev/null + +### Default ### + +# Default target for anything not described above +default/* + Open= + View= + + +### EOF ### diff --git a/packages/tools/sysutils/MC/etc/mc.keymap b/packages/tools/sysutils/MC/etc/mc.keymap new file mode 100644 index 000000000..287557e26 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.keymap @@ -0,0 +1,429 @@ +[main] +Help = f1 +UserMenu = f2 +View = f3 +ViewFile = +Edit = f4 +EditForceInternal = +Copy = f5 +Move = f6 +MakeDir = f7 +Delete = f8 +Menu = f9 +Quit = f10 +MenuLastSelected = f19 +QuitQuiet = f20 +Find = alt-question +CdQuick = alt-c +HotList = ctrl-backslash +Reread = ctrl-r +DirSize = ctrl-space +Suspend = ctrl-z +Swap = ctrl-u +History = alt-h +PanelListing = +PanelListingSwitch = alt-t +PanelListingChange = +ShowHidden = alt-dot +SplitVertHoriz = alt-comma +Shell = ctrl-o +PutCurrentPath = alt-a +PutOtherPath = alt-shift-a +ViewFiltered = alt-exclamation +Select = kpplus +Unselect = kpminus +SelectInvert = kpasterisk +ScreenList = alt-prime +OptionsLayout = +OptionsPanel = +OptionsConfirm = +OptionsDisplayBits = +OptionsVfs = +LearnKeys = +SaveSetup = +EditExtensionsFile = +EditFileHighlightFile = +Filter = +ConnectFish = +ConnectFtp = +ConnectSmb = +Undelete = +ExtendedKeyMap = ctrl-x + +[main:xmap] +ChangeMode = c +ChangeOwn = o +CompareDirs = d +CompareFiles = ctrl-d +HotListAdd = h +LinkSymbolicEdit = ctrl-s +Link = l +LinkSymbolic = s +LinkSymbolicRelative = v +PanelInfo = i +PanelQuickView = q +ExternalPanelize = exclamation +VfsList = a +Jobs = j +PutCurrentPath = p +PutOtherPath = ctrl-p +PutCurrentTagged = t +PutOtherTagged = ctrl-t +PutCurrentLink = r +PutOtherLink = ctrl-r + +[panel] +Search = ctrl-s; alt-s +Mark = insert; ctrl-t +MarkUp = shift-up +MarkDown = shift-down +MarkLeft = +MarkRight = +Down = down; ctrl-n +Up = up; ctrl-p +Left = left +Right = right +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +PanelOtherCd = alt-o +PanelOtherCdLink = alt-l +ViewRaw = f13 +EditNew = f14 +CopySingle = f15 +MoveSingle = f16 +DeleteSingle = f18 +Select = alt-plus +Unselect = alt-minus +SelectInvert = alt-asterisk +CdChild = ctrl-pgdn +CdParent = ctrl-pgup +CdParentSmart = +History = alt-shift-h +HistoryNext = alt-u +HistoryPrev = alt-y +BottomOnScreen = alt-j +MiddleOnScreen = alt-r +TopOnScreen = alt-g +PanelOtherSync = alt-i +SelectCodepage = alt-e +Top = alt-lt; home; a1 +Bottom = alt-gt; end; c1 +Sort = +SortPrev = +SortNext = +SortReverse = +SortByName = +SortByExt = +SortBySize = +SortByMTime = + +[dialog] +Ok = enter +Cancel = f10; esc; ctrl-g +Up = left; up +#Left = left; up +Down = right; down +#Right = right; down +Help = f1 +Suspend = ctrl-z +Refresh = ctrl-l +ScreenList = alt-prime +ScreenNext = alt-rbrace +ScreenPrev = alt-lbrace + +[input] +Home = ctrl-a; alt-lt; home; a1 +End = ctrl-e; alt-gt; end; c1 +Left = left; alt-left; ctrl-b +Right = right; alt-right; ctrl-f +WordLeft = ctrl-left; alt-b +WordRight = ctrl-right; alt-f +Backspace = backspace; ctrl-h +Delete = delete; ctrl-d +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +Mark = +Remove = ctrl-w +Cut = +Store = alt-w +Paste = +Yank = ctrl-y +DeleteToEnd = ctrl-k +HistoryPrev = alt-p; ctrl-down +HistoryNext = alt-n; ctrl-up +History = alt-h +Complete = alt-tab +Clear = +MarkLeft = shift-left +MarkRight = shift-right +MarkToWordBegin = ctrl-shift-left +MarkToWordEnd = ctrl-shift-right +MarkToHome = shift-home +MarkToEnd = shift-end + +[listbox] +Up = up; ctrl-p +Down = down; ctrl-n +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Delete = delete; d +Clear = shift-delete; shift-d + +[tree] +Help = f1 +Reread = f2; ctrl-r +Forget = f3 +ToggleNavigation = f4 +Copy = f5 +Move = f6 +Up = up; ctrl-p +Down = down; ctrl-n +Left = left +Right = right +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +Search = ctrl-s; alt-s +Delete = f8; delete + +[help] +Help = f1 +Index = f2; c +Back = f3; left; l +Quit = f10; esc +Up = up; ctrl-p +Down = down; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +Enter = right; enter +LinkNext = tab +LinkPrev = alt-tab +NodeNext = n +NodePrev = p + +[editor] +Store = ctrl-insert +Paste = shift-insert +Cut = shift-delete +Up = up +Down = down +Left = left +Right = right +WordLeft = ctrl-left; ctrl-z +WordRight = ctrl-right; ctrl-x +Enter = enter +Return = shift-enter +BackSpace = backspace; ctrl-h +Delete = delete; ctrl-d +PageUp = pgup +PageDown = pgdn +Home = home +End = end +Tab = tab +Undo = ctrl-u +Redo = alt-r +Top = ctrl-home; alt-lt +Bottom = ctrl-end; alt-gt +ScrollUp = ctrl-up +ScrollDown = ctrl-down +TopOnScreen = ctrl-pgup +BottomOnScreen = ctrl-pgdn +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +DeleteLine = ctrl-y +DeleteToEnd = ctrl-k +DeleteToHome = +ParagraphUp = +ParagraphDown = +Save = f2 +EditFile = +EditNew = ctrl-n +SaveAs = f12; ctrl-f2 +Mark = f3 +Copy = f5 +Move = f6 +Remove = f8 +MarkLine = +MarkWord = +MarkAll = +Unmark = +Search = f7 +SearchContinue = f17 +BlockShiftLeft = +BlockShiftRight = +MarkPageUp = shift-pgup +MarkPageDown = shift-pgdn +MarkLeft = shift-left +MarkRight = shift-right +MarkToWordBegin = ctrl-shift-left +MarkToWordEnd = ctrl-shift-right +MarkUp = shift-up +MarkDown = shift-down +MarkToHome = shift-home +MarkToEnd = shift-end +MarkToFileBegin = ctrl-shift-home +MarkToFileEnd = ctrl-shift-end +MarkToPageBegin = ctrl-shift-pgup +MarkToPageEnd = ctrl-shift-pgdn +MarkScrollUp = ctrl-shift-up +MarkScrollDown = ctrl-shift-down +MarkParagraphUp = +MarkParagraphDown = +MarkColumnPageUp = alt-pgup +MarkColumnPageDown = alt-pgdn +MarkColumnLeft = alt-left +MarkColumnRight = alt-right +MarkColumnUp = alt-up +MarkColumnDown = alt-down +MarkColumnScrollUp = +MarkColumnScrollDown = +MarkColumnParagraphUp = +MarkColumnParagraphDown = +BlockSave = ctrl-f +MarkColumn = f13 +Replace = f4 +ReplaceContinue = f14 +Complete = alt-tab +InsertFile = f15 +Quit = f10 +InsertOverwrite = insert +Help = f1 +Date = +Refresh = ctrl-l +Goto = alt-l +Sort = alt-t +Mail = alt-m +ParagraphFormat = alt-p +MatchBracket = alt-b +ExternalCommand = alt-u +UserMenu = f11 +Menu = f9 +Bookmark = alt-k +BookmarkFlush = alt-o +BookmarkNext = alt-j +BookmarkPrev = alt-i +History = +Shell = ctrl-o +InsertLiteral = ctrl-q +MacroStartRecord = +MacroStopRecord = +MacroStartStopRecord = ctrl-r +MacroDelete = +ShowNumbers = alt-n +ShowTabTws = alt-underline +SyntaxOnOff = ctrl-s +SyntaxChoose = +ShowMargin = +Find = alt-enter +FilePrev = alt-minus +FileNext = alt-plus +RepeatStartStopRecord = +SelectCodepage = alt-e +Options = +OptionsSaveMode = +LearnKeys = +ExtendedKeyMap = + +[viewer] +Help = f1 +WrapMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Search = f7; question; slash +SearchContinue = ctrl-r; ctrl-s; f17; n +MagicMode = f8 +NroffMode = f9 +Home = ctrl-a +End = ctrl-e +Left = h; left +Right = l; right +LeftQuick = ctrl-left +RightQuick = ctrl-right +Up = k; y; insert; up; ctrl-p +Down = j; e; delete; down; enter; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +BookmarkGoto = m +Bookmark = r +FileNext = ctrl-f +FilePrev = ctrl-b +SelectCodepage = alt-e +Shell = ctrl-o +Ruler = alt-r + +[viewer:hex] +Help = f1 +HexEditMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Save = f6 +Search = f7; question; slash +SearchContinue = ctrl-r; ctrl-s; f17; n +MagicMode = f8 +NroffMode = f9 +ToggleNavigation = tab +Home = ctrl-a; home +End = ctrl-e; end +Left = b; left +Right = f; right +Up = k; y; up +Down = j; delete; down +PageDown = pgdn; ctrl-v +PageUp = pgup; alt-v +Top = ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g + +[diffviewer] +ShowSymbols = alt-s; s +ShowNumbers = alt-n; l +SplitFull = f +SplitEqual = equal +SplitMore = gt +SplitLess = lt +Tab2 = 2 +Tab3 = 3 +Tab4 = 4 +Tab8 = 8 +Swap = ctrl-u +Redo = ctrl-r +HunkNext = n; enter; space +HunkPrev = p; backspace +Goto = g; shift-g +Save = f2 +Edit = f4 +EditOther = f14 +Merge = f5 +Search = f7 +SearchContinue = f17 +Options = f9 +Top = ctrl-home +Bottom = ctrl-end +Down = down +Up = up +LeftQuick = ctrl-left +RightQuick = ctrl-right +Left = left +Right = right +PageDown = pgdn +PageUp = pgup +Home = home +End = end +Help = f1 +Quit = f10; q; shift-q; esc +Shell = ctrl-o +SelectCodepage = alt-e diff --git a/packages/tools/sysutils/MC/etc/mc.keymap.default b/packages/tools/sysutils/MC/etc/mc.keymap.default new file mode 100644 index 000000000..287557e26 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.keymap.default @@ -0,0 +1,429 @@ +[main] +Help = f1 +UserMenu = f2 +View = f3 +ViewFile = +Edit = f4 +EditForceInternal = +Copy = f5 +Move = f6 +MakeDir = f7 +Delete = f8 +Menu = f9 +Quit = f10 +MenuLastSelected = f19 +QuitQuiet = f20 +Find = alt-question +CdQuick = alt-c +HotList = ctrl-backslash +Reread = ctrl-r +DirSize = ctrl-space +Suspend = ctrl-z +Swap = ctrl-u +History = alt-h +PanelListing = +PanelListingSwitch = alt-t +PanelListingChange = +ShowHidden = alt-dot +SplitVertHoriz = alt-comma +Shell = ctrl-o +PutCurrentPath = alt-a +PutOtherPath = alt-shift-a +ViewFiltered = alt-exclamation +Select = kpplus +Unselect = kpminus +SelectInvert = kpasterisk +ScreenList = alt-prime +OptionsLayout = +OptionsPanel = +OptionsConfirm = +OptionsDisplayBits = +OptionsVfs = +LearnKeys = +SaveSetup = +EditExtensionsFile = +EditFileHighlightFile = +Filter = +ConnectFish = +ConnectFtp = +ConnectSmb = +Undelete = +ExtendedKeyMap = ctrl-x + +[main:xmap] +ChangeMode = c +ChangeOwn = o +CompareDirs = d +CompareFiles = ctrl-d +HotListAdd = h +LinkSymbolicEdit = ctrl-s +Link = l +LinkSymbolic = s +LinkSymbolicRelative = v +PanelInfo = i +PanelQuickView = q +ExternalPanelize = exclamation +VfsList = a +Jobs = j +PutCurrentPath = p +PutOtherPath = ctrl-p +PutCurrentTagged = t +PutOtherTagged = ctrl-t +PutCurrentLink = r +PutOtherLink = ctrl-r + +[panel] +Search = ctrl-s; alt-s +Mark = insert; ctrl-t +MarkUp = shift-up +MarkDown = shift-down +MarkLeft = +MarkRight = +Down = down; ctrl-n +Up = up; ctrl-p +Left = left +Right = right +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +PanelOtherCd = alt-o +PanelOtherCdLink = alt-l +ViewRaw = f13 +EditNew = f14 +CopySingle = f15 +MoveSingle = f16 +DeleteSingle = f18 +Select = alt-plus +Unselect = alt-minus +SelectInvert = alt-asterisk +CdChild = ctrl-pgdn +CdParent = ctrl-pgup +CdParentSmart = +History = alt-shift-h +HistoryNext = alt-u +HistoryPrev = alt-y +BottomOnScreen = alt-j +MiddleOnScreen = alt-r +TopOnScreen = alt-g +PanelOtherSync = alt-i +SelectCodepage = alt-e +Top = alt-lt; home; a1 +Bottom = alt-gt; end; c1 +Sort = +SortPrev = +SortNext = +SortReverse = +SortByName = +SortByExt = +SortBySize = +SortByMTime = + +[dialog] +Ok = enter +Cancel = f10; esc; ctrl-g +Up = left; up +#Left = left; up +Down = right; down +#Right = right; down +Help = f1 +Suspend = ctrl-z +Refresh = ctrl-l +ScreenList = alt-prime +ScreenNext = alt-rbrace +ScreenPrev = alt-lbrace + +[input] +Home = ctrl-a; alt-lt; home; a1 +End = ctrl-e; alt-gt; end; c1 +Left = left; alt-left; ctrl-b +Right = right; alt-right; ctrl-f +WordLeft = ctrl-left; alt-b +WordRight = ctrl-right; alt-f +Backspace = backspace; ctrl-h +Delete = delete; ctrl-d +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +Mark = +Remove = ctrl-w +Cut = +Store = alt-w +Paste = +Yank = ctrl-y +DeleteToEnd = ctrl-k +HistoryPrev = alt-p; ctrl-down +HistoryNext = alt-n; ctrl-up +History = alt-h +Complete = alt-tab +Clear = +MarkLeft = shift-left +MarkRight = shift-right +MarkToWordBegin = ctrl-shift-left +MarkToWordEnd = ctrl-shift-right +MarkToHome = shift-home +MarkToEnd = shift-end + +[listbox] +Up = up; ctrl-p +Down = down; ctrl-n +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Delete = delete; d +Clear = shift-delete; shift-d + +[tree] +Help = f1 +Reread = f2; ctrl-r +Forget = f3 +ToggleNavigation = f4 +Copy = f5 +Move = f6 +Up = up; ctrl-p +Down = down; ctrl-n +Left = left +Right = right +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +Search = ctrl-s; alt-s +Delete = f8; delete + +[help] +Help = f1 +Index = f2; c +Back = f3; left; l +Quit = f10; esc +Up = up; ctrl-p +Down = down; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +Enter = right; enter +LinkNext = tab +LinkPrev = alt-tab +NodeNext = n +NodePrev = p + +[editor] +Store = ctrl-insert +Paste = shift-insert +Cut = shift-delete +Up = up +Down = down +Left = left +Right = right +WordLeft = ctrl-left; ctrl-z +WordRight = ctrl-right; ctrl-x +Enter = enter +Return = shift-enter +BackSpace = backspace; ctrl-h +Delete = delete; ctrl-d +PageUp = pgup +PageDown = pgdn +Home = home +End = end +Tab = tab +Undo = ctrl-u +Redo = alt-r +Top = ctrl-home; alt-lt +Bottom = ctrl-end; alt-gt +ScrollUp = ctrl-up +ScrollDown = ctrl-down +TopOnScreen = ctrl-pgup +BottomOnScreen = ctrl-pgdn +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +DeleteLine = ctrl-y +DeleteToEnd = ctrl-k +DeleteToHome = +ParagraphUp = +ParagraphDown = +Save = f2 +EditFile = +EditNew = ctrl-n +SaveAs = f12; ctrl-f2 +Mark = f3 +Copy = f5 +Move = f6 +Remove = f8 +MarkLine = +MarkWord = +MarkAll = +Unmark = +Search = f7 +SearchContinue = f17 +BlockShiftLeft = +BlockShiftRight = +MarkPageUp = shift-pgup +MarkPageDown = shift-pgdn +MarkLeft = shift-left +MarkRight = shift-right +MarkToWordBegin = ctrl-shift-left +MarkToWordEnd = ctrl-shift-right +MarkUp = shift-up +MarkDown = shift-down +MarkToHome = shift-home +MarkToEnd = shift-end +MarkToFileBegin = ctrl-shift-home +MarkToFileEnd = ctrl-shift-end +MarkToPageBegin = ctrl-shift-pgup +MarkToPageEnd = ctrl-shift-pgdn +MarkScrollUp = ctrl-shift-up +MarkScrollDown = ctrl-shift-down +MarkParagraphUp = +MarkParagraphDown = +MarkColumnPageUp = alt-pgup +MarkColumnPageDown = alt-pgdn +MarkColumnLeft = alt-left +MarkColumnRight = alt-right +MarkColumnUp = alt-up +MarkColumnDown = alt-down +MarkColumnScrollUp = +MarkColumnScrollDown = +MarkColumnParagraphUp = +MarkColumnParagraphDown = +BlockSave = ctrl-f +MarkColumn = f13 +Replace = f4 +ReplaceContinue = f14 +Complete = alt-tab +InsertFile = f15 +Quit = f10 +InsertOverwrite = insert +Help = f1 +Date = +Refresh = ctrl-l +Goto = alt-l +Sort = alt-t +Mail = alt-m +ParagraphFormat = alt-p +MatchBracket = alt-b +ExternalCommand = alt-u +UserMenu = f11 +Menu = f9 +Bookmark = alt-k +BookmarkFlush = alt-o +BookmarkNext = alt-j +BookmarkPrev = alt-i +History = +Shell = ctrl-o +InsertLiteral = ctrl-q +MacroStartRecord = +MacroStopRecord = +MacroStartStopRecord = ctrl-r +MacroDelete = +ShowNumbers = alt-n +ShowTabTws = alt-underline +SyntaxOnOff = ctrl-s +SyntaxChoose = +ShowMargin = +Find = alt-enter +FilePrev = alt-minus +FileNext = alt-plus +RepeatStartStopRecord = +SelectCodepage = alt-e +Options = +OptionsSaveMode = +LearnKeys = +ExtendedKeyMap = + +[viewer] +Help = f1 +WrapMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Search = f7; question; slash +SearchContinue = ctrl-r; ctrl-s; f17; n +MagicMode = f8 +NroffMode = f9 +Home = ctrl-a +End = ctrl-e +Left = h; left +Right = l; right +LeftQuick = ctrl-left +RightQuick = ctrl-right +Up = k; y; insert; up; ctrl-p +Down = j; e; delete; down; enter; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +BookmarkGoto = m +Bookmark = r +FileNext = ctrl-f +FilePrev = ctrl-b +SelectCodepage = alt-e +Shell = ctrl-o +Ruler = alt-r + +[viewer:hex] +Help = f1 +HexEditMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Save = f6 +Search = f7; question; slash +SearchContinue = ctrl-r; ctrl-s; f17; n +MagicMode = f8 +NroffMode = f9 +ToggleNavigation = tab +Home = ctrl-a; home +End = ctrl-e; end +Left = b; left +Right = f; right +Up = k; y; up +Down = j; delete; down +PageDown = pgdn; ctrl-v +PageUp = pgup; alt-v +Top = ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g + +[diffviewer] +ShowSymbols = alt-s; s +ShowNumbers = alt-n; l +SplitFull = f +SplitEqual = equal +SplitMore = gt +SplitLess = lt +Tab2 = 2 +Tab3 = 3 +Tab4 = 4 +Tab8 = 8 +Swap = ctrl-u +Redo = ctrl-r +HunkNext = n; enter; space +HunkPrev = p; backspace +Goto = g; shift-g +Save = f2 +Edit = f4 +EditOther = f14 +Merge = f5 +Search = f7 +SearchContinue = f17 +Options = f9 +Top = ctrl-home +Bottom = ctrl-end +Down = down +Up = up +LeftQuick = ctrl-left +RightQuick = ctrl-right +Left = left +Right = right +PageDown = pgdn +PageUp = pgup +Home = home +End = end +Help = f1 +Quit = f10; q; shift-q; esc +Shell = ctrl-o +SelectCodepage = alt-e diff --git a/packages/tools/sysutils/MC/etc/mc.keymap.emacs b/packages/tools/sysutils/MC/etc/mc.keymap.emacs new file mode 100644 index 000000000..7f51c1cb3 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.keymap.emacs @@ -0,0 +1,432 @@ +[main] +Help = f1 +UserMenu = f2 +View = f3 +ViewFile = +Edit = f4 +EditForceInternal = +Copy = f5 +Move = f6 +MakeDir = f7 +Delete = f8 +Menu = f9 +Quit = f10 +MenuLastSelected = f19 +QuitQuiet = f20 +Find = alt-question +CdQuick = alt-c +HotList = ctrl-backslash +Reread = ctrl-r +DirSize = ctrl-space +Suspend = ctrl-z +Swap = ctrl-u +History = alt-h +PanelListing = +PanelListingSwitch = alt-t +PanelListingChange = +ShowHidden = alt-dot +SplitVertHoriz = alt-comma +Shell = ctrl-o +PutCurrentPath = alt-a +PutOtherPath = alt-shift-a +ViewFiltered = alt-exclamation +Select = kpplus +Unselect = kpminus +SelectInvert = kpasterisk +ScreenList = alt-prime +Options = +OptionsLayout = +OptionsPanel = +OptionsConfirm = +OptionsDisplayBits = +OptionsVfs = +LearnKeys = +SaveSetup = +EditExtensionsFile = +EditFileHighlightFile = +Filter = +ConnectFish = +ConnectFtp = +ConnectSmb = +Undelete = +ExtendedKeyMap = ctrl-x + +[main:xmap] +ChangeMode = c +ChangeOwn = o +CompareDirs = d +CompareFiles = ctrl-d +HotListAdd = h +LinkSymbolicEdit = ctrl-s +Link = l +LinkSymbolic = s +LinkSymbolicRelative +PanelInfo = i +PanelQuickView = q +ExternalPanelize = exclamation +VfsList = a +Jobs = j +PutCurrentPath = p +PutOtherPath = ctrl-p +PutCurrentTagged = t +PutOtherTagged = ctrl-t +PutCurrentLink = r +PutOtherLink = ctrl-r + +[panel] +Search = ctrl-s; alt-s +Mark = insert; ctrl-t +MarkUp = shift-up +MarkDown = shift-down +MarkLeft = +MarkRight = +Down = down; ctrl-n +Up = up; ctrl-p +Left = left +Right = right +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +PanelOtherCd = alt-o +PanelOtherCdLink = alt-l +ViewRaw = f13 +EditNew = f14 +CopySingle = f15 +MoveSingle = f16 +DeleteSingle = f18 +Select = alt-plus +Unselect = alt-minus +SelectInvert = alt-asterisk +CdChild = ctrl-pgdn +CdParent = ctrl-pgup +CdParentSmart = +History = alt-shift-h +HistoryNext = alt-u +HistoryPrev = alt-y +BottomOnScreen = alt-j +MiddleOnScreen = alt-r +TopOnScreen = alt-g +PanelOtherSync = alt-i +SelectCodepage = alt-e +Top = alt-lt; home; a1 +Bottom = alt-gt; end; c1 +Sort = +SortPrev = +SortNext = +SortReverse = +SortByName = +SortByExt = +SortBySize = +SortByMTime = + +[dialog] +Ok = enter +Cancel = f10; esc +Up = left; up +#Left = left; up +Down = right; down +#Right = right; down +Help = f1 +Suspend = ctrl-z +Refresh = ctrl-l +ScreenList = alt-prime +ScreenNext = alt-rbrace +ScreenPrev = alt-lbrace + +[input] +Home = ctrl-a; alt-lt; home; a1 +End = ctrl-e; alt-gt; end; c1 +Left = left; alt-left; ctrl-b +Right = right; alt-right; ctrl-f +WordLeft = ctrl-left; alt-b +WordRight = ctrl-right; alt-f +Backspace = backspace +Delete = delete +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +Mark = +Remove = ctrl-w +Cut = +Store = alt-w +Paste = +Yank = ctrl-y +DeleteToEnd = ctrl-k +HistoryPrev = alt-p; ctrl-down +HistoryNext = alt-n; ctrl-up +History = alt-h +Complete = alt-tab +Clear = +MarkLeft = +MarkRight = +MarkToWordBegin = +MarkToWordEnd = +MarkToHome = +MarkToEnd = + +[listbox] +Up = up; ctrl-p +Down = down; ctrl-n +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Delete = delete; d +Clear = shift-delete; shift-d + +[tree] +Help = f1 +Reread = f2; ctrl-r +Forget = f3 +ToggleNavigation = f4 +Copy = f5 +Move = f6 +Up = up; ctrl-p +Down = down; ctrl-n +Left = left +Right = right +Top = home; alt-lt; a1 +Bottom = end; alt-gt; c1 +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Enter = enter +Search = ctrl-s; alt-s +Delete = f8; delete + +[help] +Help = f1 +Index = f2; c +Back = f3; left; l +Quit = f10; esc; ctrl-g +Up = up; ctrl-p +Down = down; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +Enter = right; enter +LinkNext = tab +LinkPrev = alt-tab +NodeNext = n +NodePrev = p + +[editor] +Store = alt-w +Paste = ctrl-y +Cut = ctrl-w +Up = up; ctrl-p +Down = down; ctrl-n +Left = left; ctrl-b +Right = right; ctrl-f +WordLeft = ctrl-left; alt-b +WordRight = ctrl-right; alt-f +Enter = enter +Return = shift-enter +BackSpace = backspace +Delete = delete +PageUp = pgup; alt-v +PageDown = pgdn; ctrl-v +Home = home; ctrl-a +End = end; ctrl-e +Tab = tab +Undo = ctrl-u +Redo = +Top = ctrl-home; alt-lt +Bottom = ctrl-end; alt-gt +ScrollUp = ctrl-up +ScrollDown = ctrl-down +TopOnScreen = ctrl-pgup +BottomOnScreen = ctrl-pgdn +DeleteToWordBegin = alt-backspace +DeleteToWordEnd = alt-d +DeleteLine = ctrl-y +DeleteToEnd = ctrl-k +DeleteToHome = +ParagraphUp = +ParagraphDown = +Save = f2 +EditFile = +SaveAs = f12; ctrl-f2 +Mark = f3; ctrl-at +Copy = f5 +Move = f6 +Remove = f8 +MarkLine = +MarkWord = +MarkAll = +Unmark = +Search = f7; ctrl-s +SearchContinue = f17 +BlockShiftLeft = +BlockShiftRight = +MarkPageUp = shift-pgup +MarkPageDown = shift-pgdn +MarkLeft = shift-left +MarkRight = shift-right +MarkToWordBegin = ctrl-shift-left +MarkToWordEnd = ctrl-shift-right +MarkUp = shift-up +MarkDown = shift-down +MarkToHome = shift-home +MarkToEnd = shift-end +MarkToFileBegin = ctrl-shift-home +MarkToFileEnd = ctrl-shift-end +MarkToPageBegin = ctrl-shift-pgup +MarkToPageEnd = ctrl-shift-pgdn +MarkScrollUp = ctrl-shift-up +MarkScrollDown = ctrl-shift-down +MarkParagraphUp = +MarkParagraphDown = +MarkColumnPageUp = alt-pgup +MarkColumnPageDown = alt-pgdn +MarkColumnLeft = alt-left +MarkColumnRight = alt-right +MarkColumnUp = alt-up +MarkColumnDown = alt-down +MarkColumnScrollUp = +MarkColumnScrollDown = +MarkColumnParagraphUp = +MarkColumnParagraphDown = +BlockSave = +MarkColumn = f13 +Replace = f4 +ReplaceContinue = f14 +Complete = alt-tab +InsertFile = f15 +Quit = f10 +InsertOverwrite = insert +Help = f1 +Date = +Refresh = ctrl-l +Goto = alt-l +Sort = alt-t +Mail = +ParagraphFormat = alt-p +MatchBracket = +ExternalCommand = alt-u +UserMenu = f11 +Menu = f9 +Bookmark = +BookmarkFlush = +BookmarkNext = +BookmarkPrev = +History = +Shell = ctrl-o +InsertLiteral = ctrl-q +MacroStartRecord = +MacroStopRecord = +MacroStartStopRecord = ctrl-r +MacroDelete = +ShowNumbers = alt-n +ShowTabTws = alt-underline +SyntaxOnOff = ctrl-s +SyntaxChoose = +ShowMargin = +Find = alt-enter +FilePrev = alt-minus +FileNext = alt-plus +RepeatStartStopRecord = +SelectCodepage = alt-e +Options = +OptionsSaveMode = +LearnKeys = +ExtendedKeyMap = ctrl-x + +[editor:xmap] +EditNew = k + +[viewer] +Help = f1 +WrapMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Search = f7; question; slash +MagicMode = f8 +NroffMode = f9 +SearchContinue = ctrl-r; ctrl-s; f17; n +Home = ctrl-a +End = ctrl-e +Left = h; left +Right = l; right +LeftQuick= ctrl-left +RightQuick = ctrl-right +Up = k; y; insert; up; ctrl-p +Down = j; e; delete; down; enter; ctrl-n +PageDown = f; space; pgdn; ctrl-v +PageUp = b; pgup; alt-v; backspace +HalfPageDown = d +HalfPageUp = u +Top = home; ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g +BookmarkGoto = m +Bookmark = r +FileNext = ctrl-f +FilePrev = ctrl-b +SelectCodepage = alt-e +Shell = ctrl-o +Ruler = alt-r + +[viewer:hex] +Help = f1 +HexEditMode = f2 +Quit = f3; f10; q; esc +HexMode = f4 +Goto = f5 +Save = f6 +Search = f7; question; slash +SearchContinue = ctrl-r; ctrl-s; f17; n +MagicMode = f8 +NroffMode = f9 +ToggleNavigation = tab +Home = ctrl-a; home +End = ctrl-e; end +Left = b; left +Right = f; right +Up = k; y; up +Down = j; delete; down +PageDown = pgdn; ctrl-v +PageUp = pgup; alt-v +Top = ctrl-home; ctrl-pgup; a1; alt-lt; g +Bottom = ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g + +[diffviewer] +ShowSymbols = alt-s; s +ShowNumbers = alt-n; l +SplitFull = f +SplitEqual = equal +SplitMore = gt +SplitLess = lt +Tab2 = 2 +Tab3 = 3 +Tab4 = 4 +Tab8 = 8 +Swap = ctrl-u +Redo = ctrl-r +HunkNext = n; enter; space +HunkPrev = p; backspace +Goto = g; shift-g +Save = f2 +Edit = f4 +EditOther = f14 +Merge = f5 +Search = f7 +SearchContinue = f17 +Options = f9 +Top = ctrl-home +Bottom = ctrl-end +Down = down +Up = up +LeftQuick = ctrl-left +RightQuick = ctrl-right +Left = left +Right = right +PageDown = pgdn +PageUp = pgup +Home = home +End = end +Help = f1 +Quit = f10; q; shift-q; esc +Shell = ctrl-o +SelectCodepage = alt-e diff --git a/packages/tools/sysutils/MC/etc/mc.menu b/packages/tools/sysutils/MC/etc/mc.menu new file mode 100644 index 000000000..6aa01aa71 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.menu @@ -0,0 +1,383 @@ +shell_patterns=0 ++ ! t t +@ Do something on the current file + CMD=%{Enter command} + $CMD %f + ++ t t +@ Do something on the tagged files + set %t; CMD=%{Enter command} + while [ -n "$1" ]; do + $CMD "$1" + shift + done + + +0 Edit a bug report and send it to root + I=`mktemp "${MC_TMPDIR:-/tmp}/mail.XXXXXX"` || exit 1 + ${EDITOR-vi} "$I" + test -r $I && mail root < $I + rm -f "$I" + +=+ f \.1$ | f \.3$ | f \.4$ | f \.5$ | f \.6$ | f \.7$ | f \.8$ | f \.man$ & t r +1 Display the file with roff -man + nroff -man %f | less + +2 Call the info hypertext browser + info + += t d +3 Compress the current subdirectory (tar.gz) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | gzip -f9 > "$tar.tar.gz" && \ + echo "../$tar.tar.gz created." + +4 Compress the current subdirectory (tar.bz2) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | bzip2 -f > "$tar.tar.bz2" && \ + echo "../$tar.tar.bz2 created." + +5 Compress the current subdirectory (tar.p7) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | 7za a -si "$tar.tar.7z" && \ + echo "../$tar.tar.7z created." + +6 Compress the current subdirectory (tar.lzma) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | lzma -f > "$tar.tar.lzma" && \ + echo "../$tar.tar.lzma created." + +7 Compress the current subdirectory (tar.lz) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | lzip -f > "$tar.tar.lz" && \ + echo "../$tar.tar.lz created." + +8 Compress the current subdirectory (tar.xz) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | xz -f > "$tar.tar.xz" && \ + echo "../$tar.tar.xz created." + += f \.c$ & t r ++ f \.c$ & t r & ! t t +Ñ Compile and link current .c file + make `basename %f .c` 2>/dev/null || cc -O -o `basename %f .c` %f + ++ t r & ! t t +a Append file to opposite + cat %f >> %D/%f + ++ t t +A Append files to opposite files + set %t + while [ -n "$1" ]; do + cat "$1" >> "%D/$1" + shift + done + ++ t r & ! t t +d Delete file if a copy exists in the other directory. + if [ "%d" = "%D" ]; then + echo "The two directories must be different." + exit 1 + fi + if [ -f %D/%f ]; then # if two of them, then + if cmp -s %D/%f %f; then + rm %f && echo "%f: DELETED." + else + echo "%f and %D/%f differ: NOT deleted." + echo -n "Press RETURN " + read key + fi + else + echo "%f: No copy in %D/%f: NOT deleted." + fi + ++ t t +D Delete tagged files if a copy exists in the other directory. + if [ "%d" = "%D" ]; then + echo "The two directores must be different." + exit 1 + fi + for i in %t + do + if [ -f "%D/$i" ]; then + SUM1="`sum $i`" + SUM2="`sum %D/$i`" + if [ "$SUM1" = "$SUM2" ]; then + rm "$i" && echo "${i}: DELETED." + else + echo "$i and %D/$i differ: NOT deleted." + fi + else + echo "%f has no copy in %D/%f: NOT deleted." + fi + done + +m View manual page + MAN=%{Enter manual name} + %view man -P cat $MAN + += f \.gz$ & t r ++ ! t t +n Inspect gzip'ed newsbatch file + dd if=%f bs=1 skip=12|zcat|${PAGER-more} + # assuming the cunbatch header is 12 bytes long. + += t r & ++ ! t t +h Strip headers from current newsarticle + CHECK=`awk '{print $1 ; exit}' %f` 2>/dev/null + case "$CHECK" in + Newsgroups:|Path:) + I=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1 + cp %f "$I" && sed '/^'"$CHECK"' /,/^$/d' "$I" > %f + [ "$?" = "0" ] && rm "$I" + echo "%f: header removed." + ;; + *) + echo "%f is not a news article." + ;; + esac + ++ t t +H Strip headers from the marked newsarticles + set %t + while [ -n "$1" ]; do + CHECK=`awk '{print $1 ; exit}' $1` 2>/dev/null + WFILE=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1 + case "$CHECK" in + Newsgroups:|Path:) + cp "$1" "$WFILE" && sed '/^'"$CHECK"' /,/^$/d' "$WFILE" > "$1" + if [ "$?" = "0" ]; then + rm "$WFILE"; echo "$1 header removed. OK." + else + echo "Oops! Please check $1 against $WFILE." + fi + ;; + *) + echo "$1 skipped: Not a news article." + ;; + esac + shift + done + += t r ++ ! t t +r Copy file to remote host + echo -n "To which host?: " + read Host + echo -n "To which directory on $Host?: " + read Dir + rcp -p %f "${Host}:$Dir" + ++ t t +R Copy files to remote host (no error checking) + echo -n "Copy files to which host?: " + read Host + echo -n "To which directory on $Host? :" + read Dir + rcp -pr %u "${Host}:$Dir" + += f \.tex$ & t r ++ f \.tex$ & t r & ! t t +t Run latex on file and show it with xdvi + latex %f && xdvi `basename %f .tex`.dvi + +=+ f ^part | f ^Part | f uue & t r ++ t t +U Uudecode marked news articles (needs work) + set %t + ( + while [ -n "$1" ]; do # strip headers + FIRST=`awk '{print $1 ; exit}' "$1"` + cat "$1" | sed '/^'"$FIRST"' /,/^$/d'; shift + done + ) |sed '/^$/d' |sed -n '/^begin 6/,/^end$/p' | uudecode + if [ "$?" != "0" ]; then + echo "Cannot decode %t." + fi + echo "Please test the output file before deleting anything." + +=+ f \.tar\.gz$ | f \.tar\.z$ | f \.tgz$ | f \.tpz$ | f \.tar\.lz$ | f \.tar\.lzma$ | f \.tar\.7z$ | f \.tar\.xz$ | f \.tar\.Z$ | f \.tar\.bz2$ & t r +x Extract the contents of a compressed tar file + unset PRG + case %f in + *.tar.bz2) + PRG="bunzip2 -c" + ;; + *.tar.gz|*.tar.z|*.tgz|*.tpz|*.tar.Z) + PRG="gzip -dc" + ;; + *.tar.lzma) + PRG="lzma -dc" + ;; + *.tar.lz) + PRG="lzip -dc" + ;; + *.tar.xz) + PRG="xz -dc" + ;; + *.tar.7z) + PRG="7za e -so" + ;; + *) + exit 1 + ;; + esac + $PRG %f | tar xvf - + += t r ++ ! t t +y Gzip or gunzip current file + unset DECOMP + case %f in + *.gz) DECOMP=-d;; + *.[zZ]) DECOMP=-d;; + esac + gzip $DECOMP -v %f + ++ t t +Y Gzip or gunzip tagged files + for i in %t + do + unset DECOMP + case "$i" in + *.gz) DECOMP=-d;; + *.[zZ]) DECOMP=-d;; + esac + gzip $DECOMP -v "$i" + done + ++ ! t t +b Bzip2 or bunzip2 current file + unset DECOMP + case %f in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v %f + ++ t t +B Bzip2 or bunzip2 tagged files + for i in %t + do + unset DECOMP + case "$i" in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v "$i" + done + ++ f \.tar.gz$ | f \.tgz$ | f \.tpz$ | f \.tar.Z$ | f \.tar.z$ | f \.tar.bz2$ | f \.tar.F$ & t r & ! t t +z Extract compressed tar file to subdirectory + unset D + set gzip -cd + case %f in + *.tar.gz) D="`basename %f .tar.gz`";; + *.tgz) D="`basename %f .tgz`";; + *.tpz) D="`basename %f .tpz`";; + *.tar.Z) D="`basename %f .tar.Z`";; + *.tar.z) D="`basename %f .tar.z`";; + *.tar.bz2) D="`basename %f .tar.bz2`"; set bunzip2 -c ;; + *.tar.F) D="`basename %f .tar.F`"; set freeze -dc; + esac + mkdir "$D"; cd "$D" && ("$1" "$2" ../%f | tar xvf -) + ++ t t +Z Extract compressed tar files to subdirectories + for i in %t + do + set gzip -dc + unset D + case "$i" in + *.tar.gz) D="`basename $i .tar.gz`";; + *.tgz) D="`basename $i .tgz`";; + *.tpz) D="`basename $i .tpz`";; + *.tar.Z) D="`basename $i .tar.Z`";; + *.tar.z) D="`basename $i .tar.z`";; + *.tar.F) D="`basename $i .tar.F`"; set freeze -dc;; + *.tar.bz2) D="`basename $i .tar.bz2`"; set bunzip2 -c;; + esac + mkdir "$D"; (cd "$D" && "$1" "$2" "../$i" | tar xvf -) + done + ++ f \.gz$ | f \.tgz$ | f \.tpz$ | f \.Z$ | f \.z$ | f \.bz2$ & t r & ! t t +c Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2 + unset D + unset EXT + case %f in + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.Z) EXT=Z;; + *.z) EXT=z;; + *.gz) EXT=gz;; + *.bz2) EXT=bz2;; + esac + case $EXT in + tgz|tpz) D="`basename %f .$EXT`.tar";; + gz|Z|z) D="`basename %f .$EXT`";; + bz2) D="`basename %f .bz2`";; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v %f ; gzip -f9 -v "$D" + else + gunzip -v %f ; bzip2 -v "$D" + fi + ++ t t +C Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2 + set %t + while [ -n "$1" ] + do + unset D + unset EXT + case "$1" in + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.Z) EXT=Z;; + *.z) EXT=z;; + *.gz) EXT=gz;; + *.bz2) EXT=bz2;; + esac + case $EXT in + tgz) D="`basename $1 .tgz`.tar";; + tpz) D="`basename $1 .tpz`.tar";; + gz|Z|z) D="`basename $1 .$EXT`";; + bz2) D="`basename $1 .bz2`";; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v "$1" + gzip -f9 -v "$D" + else + gunzip -v "$1" + bzip2 -v "$D" + fi + shift + done + ++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh +o Open next a free console + open -s -- sh diff --git a/packages/tools/sysutils/MC/etc/mc.menu.sr b/packages/tools/sysutils/MC/etc/mc.menu.sr new file mode 100644 index 000000000..e57a628ce --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mc.menu.sr @@ -0,0 +1,344 @@ +shell_patterns=0 ++ ! t t +@ Ради нешто над текућом датотеком + CMD=%{УнеÑите наредбу} + $CMD %f + ++ t t +@ Ради нешто над означеним датотекама + set %t; CMD=%{УнеÑите наредбу} + while [ -n "$1" ]; do + $CMD "$1" + shift + done + + +0 Уреди пријаву грешке и пошаљи је админиÑтратору + ${EDITOR-vi} /tmp/mail.$$ + test -r /tmp/mail.$$ && mail root < /tmp/mail.$$ + rm -f /tmp/mail.$$ + +=+ f \.1$ | f \.3$ | f \.4$ | f \.5$ | f \.6$ | f \.7$ | f \.8$ | f \.man$ & t r +1 Прикажи датотеку уз помоћ roff -man + nroff -man %f | less + +2 Позови читач хипертекÑта info + info + += t d +3 Компримуј текући поддиректоријум (tar.gz) + Pwd=`basename "%d" /` + echo -n "Ðазив компримоване датотеке (без врÑте) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | gzip -f9 > "$tar.tar.gz" && \ + echo "Датотека ../$tar.tar.gz је Ñтворена." + +4 Компримуј текући поддиректоријум (tar.bz2) + Pwd=`basename %d /` + echo -n "Ðазив компримоване датотеке (без врÑте) [$Pwd]: " + read tar + if [ "$tar"x = x ]; then tar="$Pwd"; fi + cd .. && \ + tar cf - "$Pwd" | bzip2 -f > "$tar.tar.bz2" && \ + echo "Датотека ../$tar.tar.bz2 је Ñтворена." + += f \.c$ & t r ++ f \.c$ & t r & ! t t +5 Преведи и повежи текућу датотеку врÑте `.c' + make `basename %f .c` 2>/dev/null || cc -O -o `basename %f .c` %f + ++ t r & ! t t +a Ðадовежи датотеку на ону из другог окна + cat %f >>%D/%f + ++ t t +A Ðадовежи датотеке на оне из другог окна + set %t + while [ -n "$1" ]; do + cat "$1" >> "%D/$1" + shift + done + ++ t r & ! t t +d Обриши датотеку ако њена копија поÑтоји у другом окну. + if [ "%d" = "%D" ]; then + echo "Два директоријума морају да буду различити." + exit 1 + fi + if [ -f %D/%f ]; then # if two of them, then + if cmp -s %D/%f %f; then + rm %f && echo "%f: ОБРИСÐÐÐ." + else + echo "%f и %D/%f Ñе разликују: ÐИЈЕ обриÑана." + echo -n "ПритиÑните `RETURN' " + read таÑтер + fi + else + echo "%f: Ðема копије у %D/%f: ÐИЈЕ обриÑана." + fi + ++ t t +D Обриши означене датотеке ако поÑтоји копија у другом окну. + if [ "%d" = "%D" ]; then + echo "Два директоријума морају да буду различити." + exit 1 + fi + for i in %t + do + if [ -f "%D/$i" ]; then + SUM1="`sum $i`" + SUM2="`sum %D/$i`" + if [ "$SUM1" = "$SUM2" ]; then + rm "$i" && echo "${i}: ОБРИСÐÐÐ." + else + echo "$i и %D/$i Ñе разликују: ÐИЈЕ обриÑана." + fi + else + echo "%f нема копију у %D/%f: ÐИЈЕ обриÑана." + fi + done + +m Погледај Ñтраницу упутÑтва + MAN=%{УнеÑите назив упутÑтва} + %view man -P cat $MAN + += f \.gz$ & t r ++ ! t t +n Прегледај датотеку веÑти компримовану програмом gzip + dd if=%f bs=1 skip=12|zcat|${PAGER-more} + # assuming the cunbatch header is 12 bytes long. + += t r & ++ ! t t +h Скини заглавља из текућег чланка веÑти + CHECK=`awk '{print $1 ; exit}' %f` 2>/dev/null + case "$CHECK" in + Newsgroups:|Path:) + cp %f /tmp/%f.$$ && sed '/^'"$CHECK"' /,/^$/d' /tmp/%f.$$ > %f + [ "$?" = "0" ] && rm "/tmp/%f.$$" + echo "%f: уклоњено заглавље." + ;; + *) + echo "%f није чланак веÑти." + ;; + esac + ++ t t +H Скини заглавља из означених чланака веÑти + set %t + while [ -n "$1" ]; do + CHECK=`awk '{print $1 ; exit}' "$1"` 2>/dev/null + WFILE=/tmp/${1}.$$ + case "$CHECK" in + Newsgroups:|Path:) + cp "$1" "$WFILE" && sed '/^'"$CHECK"' /,/^$/d' "$WFILE" > "$1" + if [ "$?" = "0" ]; then + rm "$WFILE"; echo "$1 заглавље уклоњено. У реду." + else + echo "УупÑ! Молим да проверите $1 Ñа $WFILE." + fi + ;; + *) + echo "$1 преÑкочена: Ðије чланак веÑти." + ;; + esac + shift + done + += t r ++ ! t t +r Копирај датотеку на удаљеног домаћина + echo -n "Ðа ког домаћина?: " + read Домаћин + echo -n "У који директоријум на $Домаћин?: " + read Дир + rcp -p %f "${Домаћин}:$Дир" + ++ t t +R Копирај датотеке на удаљеног домаћина (без провере грешака) + echo -n "Ðа ког домаћина да копирам датотеке?: " + read Домаћин + echo -n "У који директоријум на $Домаћин? :" + read Дир + rcp -pr %u "${Домаћин}:$Дир" + += f \.tex$ & t r ++ f \.tex$ & t r & ! t t +t Покрени ЛаТеХ над датотеком и прикажи је преко програма `xdvi' + latex %f && xdvi `basename %f .tex`.dvi + +=+ f ^part | f ^Part | f uue & t r ++ t t +U Уудекодирај означени чланак веÑти (требало би разрадити) + set %t + ( + while [ -n "$1" ]; do # strip headers + FIRST=`awk '{print $1 ; exit}' "$1"` + cat "$1" | sed '/^'"$FIRST"' /,/^$/d'; shift + done + ) |sed '/^$/d' |sed -n '/^begin 6/,/^end$/p' | uudecode + if [ "$?" != "0" ]; then + echo "Ðе могу да декодирам %t." + fi + echo "Молим да проверите излазну датотеку пре било каквог бриÑања." + +=+ f \.tar\.gz$ | f \.tar\.z$ | f \.tgz$ | f \.tpz$ | f \.tar\.lz$ | f \.tar\.lzma$ | f \.tar\.7z$ | f \.tar\.xz$ | f \.tar\.Z$ | f \.tar\.bz2$ & t r +x Издвој Ñадржај компримоване датотеке врÑте `tar' + unset PRG + case %f in + *.tar.bz2) + PRG="bunzip2 -c" + ;; + *.tar.gz|*.tar.z|*.tgz|*.tpz|*.tar.Z) + PRG="gzip -dc" + ;; + *.tar.lzma) + PRG="lzma -dc" + ;; + *.tar.lz) + PRG="lzip -dc" + ;; + *.tar.xz) + PRG="xz -dc" + ;; + *.tar.7z) + PRG="7za e -so" + ;; + *) + exit 1 + ;; + esac + $PRG %f | tar xvf - + += t r ++ ! t t +y Пакуј или раÑп. тек. дат. програмима `gzip' или `gunzip' + unset DECOMP + case %f in + *.gz) DECOMP=-d;; + *.[zZ]) DECOMP=-d;; + esac + gzip $DECOMP -v %f + ++ t t +Y Пакуј или раÑп. означ. дат. програмима `gzip' или `gunzip' + for i in %t + do + unset DECOMP + case "$i" in + *.gz) DECOMP=-d;; + *.[zZ]) DECOMP=-d;; + esac + gzip $DECOMP -v "$i" + done + ++ ! t t +b Пакуј или раÑп. тек. дат. програмима `bzip2' или `bunzip2' + unset DECOMP + case %f in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v %f + ++ t t +B Пакуј или раÑп. означ. дат. програмима `bzip2' или `bunzip2' + for i in %t + do + unset DECOMP + case "$i" in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v "$i" + done + ++ f \.tar.gz$ | f \.tgz$ | f \.tpz$ | f \.tar.Z$ | f \.tar.z$ | f \.tar.bz2$ | f \.tar.F$ & t r & ! t t +z Издвој компримовану датотеку врÑте `tar' у поддиректоријум + unset D + set gzip -cd + case %f in + *.tar.gz) D="`basename %f .tar.gz`";; + *.tgz) D="`basename %f .tgz`";; + *.tpz) D="`basename %f .tpz`";; + *.tar.Z) D="`basename %f .tar.Z`";; + *.tar.z) D="`basename %f .tar.z`";; + *.tar.bz2) D="`basename %f .tar.bz2`"; set bunzip2 -c ;; + *.tar.F) D="`basename %f .tar.F`"; set freeze -dc; + esac + mkdir "$D"; cd "$D" && ("$1" "$2" ../%f | tar xvf -) + ++ t t +Z Издвој компримовану датотеке врÑте `tar' у поддиректоријуме + for i in %t + do + set gzip -dc + unset D + case "$i" in + *.tar.gz) D="`basename $i .tar.gz`";; + *.tgz) D="`basename $i .tgz`";; + *.tpz) D="`basename $i .tpz`";; + *.tar.Z) D="`basename $i .tar.Z`";; + *.tar.z) D="`basename $i .tar.z`";; + *.tar.F) D="`basename $i .tar.F`"; set freeze -dc;; + *.tar.bz2) D="`basename $i .tar.bz2`"; set bunzip2 -c;; + esac + mkdir "$D"; (cd "$D" && "$1" "$2" "../$i" | tar xvf -) + done + ++ f \.gz$ | f \.tgz$ | f \.tpz$ | f \.Z$ | f \.z$ | f \.bz2$ & t r & ! t t +c Пребаци gz<->bz2, tar.gz<->tar.bz2 и tgz->tar.bz2 + unset D + case "%f" in + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.Z) EXT=Z;; + *.z) EXT=z;; + *.gz) EXT=gz;; + *.bz2) EXT=bz2;; + esac + case $EXT in + tgz|tpz) D="`basename %f .$EXT`.tar";; + gz|Z|z) D="`basename %f .$EXT`";; + bz2) D="`basename %f .bz2`";; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v "%f" ; gzip -f9 -v "$D" + else + gunzip -v "%f" ; bzip2 -v "$D" + fi + ++ t t +C Пребаци gz<->bz2, tar.gz<->tar.bz2 и tgz->tar.bz2 + set %t + while [ -n "$1" ] + do + unset D + case "$1" in + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.Z) EXT=Z;; + *.z) EXT=z;; + *.gz) EXT=gz;; + *.bz2) EXT=bz2;; + esac + case $EXT in + tgz) D="`basename $1 .tgz`.tar";; + tpz) D="`basename $1 .tpz`.tar";; + gz|Z|z) D="`basename $1 .$EXT`";; + bz2) D="`basename $1 .bz2`";; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v "$1" + gzip -f9 -v "$D" + else + gunzip -v "$1" + bzip2 -v "$D" + fi + shift + done + ++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh +o Отвори Ñледећу Ñлободну конзолу + open -s -- sh + diff --git a/packages/tools/sysutils/MC/etc/mcedit.menu b/packages/tools/sysutils/MC/etc/mcedit.menu new file mode 100644 index 000000000..3d11d96f8 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/mcedit.menu @@ -0,0 +1,486 @@ +shell_patterns=0 # expression type + +# The macros are: +# +# %c The cursor column position number. For edit menu only. +# %i The indent of blank space, equal the cursor column +# position. For edit menu only. +# %y The syntax type of current file. For edit menu only. +# %b The block file name. +# %f The current file name. +# %n Only the current file name without extension. +# %x The extension of current file name. +# %d The current directory name. +# %F The current file in the unselected panel. +# %D The directory name of the unselected panel. +# %t The currently tagged files. +# %T The tagged files in the unselected panel. +# %u and %U Similar to the %t and %T macros, but in +# addition the files are untagged. You can use this macro +# only once per menu file entry or extension file entry, +# because next time there will be no tagged files. +# %s and %S The selected files: The tagged files if +# there are any. Otherwise the current file. +# +# %% The % character +# +# %{some text} Prompt for the substitution. An input box +# is shown and the text inside the braces is used as a +# prompt. The macro is substituted by the text typed by the +# user. The user can press ESC or F10 to cancel. This macro +# doesn't work on the command line yet. + +#----------------------- Begin [perl] language template ----------------------- ++ y Perl\ Program | f \.pl$ +1 Author description header + unset LANG + unset LANGUAGE + LC_ALL= + MY_UID="`id | sed 's/^.*uid=\([^(]*\).*$/\1/'`" + AUTHOR="`awk -F: '$3 == '$MY_UID' {print $5}' /etc/passwd`" + cat >>%b < + # Created at: `date` + # Computer: `uname -n` + # System: `uname -sr` on `uname -m` + # + # Copyright (c) `date +%%Y` $AUTHOR All rights reserved. + # + #---------------------------------------------------------------------- + # Configure section: + + #---------------------------------------------------------------------- + # + # main() + + EOF + ++ y Perl\ Program | f \.pl$ +2 while () + cat < %b + %iwhile() { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +3 for () + cat < %b + %ifor ($i = ; $i < ; $i++) { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +4 foreach () + cat < %b + %iforeach ($ ) { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +5 if () + cat < %b + %iif () { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +6 if () else + cat < %b + %iif () { + %i} else { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +7 if () elsif () + cat < %b + %iif () { + %i} elsif () { + %i} + EOF + ++ y Perl\ Program | f \.pl$ +8 substr () + echo "%i$ = substr(\$str, \$off, \$cnt);" >%b + ++ y Perl\ Program | f \.pl$ +9 opendir () + cat < %b + %iopendir(DIR, \$dir) || die("\$0: can't open \$dir\n"); + EOF + ++ y Perl\ Program | f \.pl$ +a sub () + NAME=%{ Enter name of subroutine: } + cat < %b + sub + $NAME () + { + } # end of $NAME() + EOF +#----------------------- End [perl] language template ------------------------- + +#---------------------- Begin [shell] language template ----------------------- ++ y Shell\ Script | f \.sh$ +1 Author description header + unset LANG + unset LANGUAGE + LC_ALL= + MY_UID="`id | sed 's/^.*uid=\([^(]*\).*$/\1/'`" + AUTHOR="`awk -F: '$3 == '$MY_UID' {print $5}' /etc/passwd`" + cat >>%b < + # Created at: `date` + # Computer: `uname -n` + # System: `uname -sr` on `uname -m` + # + # Copyright (c) `date +%%Y` $AUTHOR All rights reserved. + # + #---------------------------------------------------------------------- + # Configure section: + + #---------------------------------------------------------------------- + # + # main() + + EOF + ++ y Shell\ Script | f \.sh$ +3 for + cat < %b + %ifor i in \$ + %ido + %idone + EOF + ++ y Shell\ Script | f \.sh$ +4 while + cat < %b + %iwhile + %ido + %idone + EOF + ++ y Shell\ Script | f \.sh$ +5 if [] then else + cat <> %b + %iif [ ];then + %ielse + %ifi + EOF + ++ y Shell\ Script | f \.sh$ +6 case + NUMBER=%{ Enter number elements of case:} + cat < %b + %icase "\$" in + EOF + while [ "$NUMBER" -gt 0 ] + do + cat <> %b + %i) + %i ;; + EOF + let NUMBER=$NUMBER-1 + done + cat <> %b + %i*) + %iesac + EOF + ++ y Shell\ Script | f \.sh$ +7 function + NAME=%{ Enter name of function:} + cat <> %b + $NAME() { + } # end of $NAME() + EOF + ++ y Shell\ Script | f \.sh$ +8 select of bash + cat <> %b + %iselect i in \$l + %ido + %i if [ -n "\$i" ];then + %i break + %i else + %i continue + %i fi + %idone + EOF + +#----------------------- End [shell] language template ------------------------ + +#------------------------- Begin [c] language template ------------------------ ++ f \.h$ | f \.c$ | f \.cc$ +1 Author description header + unset LANG + unset LANGUAGE + LC_ALL= + MY_UID="`id | sed 's/^.*uid=\([^(]*\).*$/\1/'`" + AUTHOR="`awk -F: '$3 == '$MY_UID' {print $5}' /etc/passwd`" + cat >> %b < + * Created at: `date` + * Computer: `uname -n` + * System: `uname -sr` on `uname -m` + * + * Copyright (c) `date +%%Y` $AUTHOR All rights reserved. + * + ********************************************************************/ + EOF + ++ f \.h$ | f \.c$ | f \.cc$ +2 GPL description header + cat >>%b <. + */ + EOF + ++ f \.c$ | f \.cc$ +3 if () + cat < %b + %iif () { + %i} + EOF + ++ f \.c$ | f \.cc$ +4 if () else + cat < %b + %iif () { + %i} else { + %i} + EOF + ++ f \.c$ | f \.cc$ +5 if () else if () + cat < %b + %iif ( ) { + %i} else if ( ) { + %i} + EOF + ++ f \.c$ | f \.cc$ +6 switch () + NUMBER=%{ Enter number elements of switch:} + echo "%iswitch () {" >%b + while [ "$NUMBER" -gt 0 ] + do + echo "%icase '':" >>%b + echo "%i break;" >>%b + let NUMBER=$NUMBER-1 + done + echo "%i default:" >>%b + echo "%i}" >>%b + ++ f \.c$ | f \.cc$ +7 for () + cat < %b + %ifor (i = ; i < ; i++) { + %i} + EOF + ++ f \.c$ | f \.cc$ +8 while () + cat < %b + %iwhile () { + %i} + EOF + ++ f \.c$ | f \.cc$ +9 do {} while () + cat < %b + %ido { + %i} while () + EOF + ++ f \.c$ | f \.cc$ +a array + cat < %b + %ichar const x[] = { + %i, , + %i}; + EOF + ++ f \.c$ | f \.cc$ +b enum + cat < %b + %ienum x { + %i, , + %i}; + EOF + ++ f \.c$ | f \.cc$ +c struct + cat < %b + %istruct ? { + %i; + %i}; + EOF + ++ f \.c$ | f \.cc$ +d union + cat < %b + %iunion ? { + %i; + %i}; + EOF + ++ f \.c$ | f \.cc$ +e typedef struct + cat < %b + %itypedef struct { + %i; + %i} ?; + EOF + ++ f \.c$ | f \.cc$ +f function + NAME=%{ Enter name of function:} + cat <> %b + $NAME() + { + } /* end of $NAME() */ + EOF + ++ f \.c$ | f \.h$ | f \.cc$ +g #include + INC=%{ Enter include name: } + if [ -r "$INC" ];then + echo \#include \"$INC\" >%b + else + echo \#include \<$INC\> >%b + fi + ++ f \.c$ | f \.h$ | f \.cc$ +d #define + echo "#define " >%b + ++ f \.c$ | f \.h$ | f \.cc$ +d #ifdef + cat < %b + #ifdef + #else + #endif + EOF + ++ f \.c$ | f \.h$ | f \.cc$ +............................................................................... + ++ f \.c$ | f \.h$ | f \.cc$ +h View all *.h into current directory + cat *.h |less + ++ f \.c$ | f \.cc$ +d Run gdb for current file + [ -x "./%n" ] && gdb ./%n + += f \.c$ | f \.cc$ ++ f \.c$ | f \.cc$ +c Compile, link and run the current .c file + export CFLAGS="-g -Wall -O2" + make || make %n || cc $CFLAGS -o %n %f + [ -r "%n" ] && (echo "*** press any key for run... ***"; read) + [ -x "%n" ] && ./%n + (echo -ne "\n--- Press any key for return to edit. ---"; read) + ++ f \.c$ | f \.h$ +t Indent `C' formatter + indent -kr -pcs %b 1>/dev/null 2> %e + +#--------------------- End [c/c++] language template -------------------------- + +#------------------------- Begin unknown template ----------------------------- ++ y unknown & t r +s #! /bin/sh + echo "#! /bin/sh" >%b + ++ y unknown & t r +p #! /usr/bin/perl + echo "#! /usr/bin/perl" >%b + ++ y unknown & t r +a Author description header + unset LANG + unset LANGUAGE + LC_ALL= + MY_UID="`id | sed 's/^.*uid=\([^(]*\).*$/\1/'`" + AUTHOR="`awk -F: '$3 == '$MY_UID' {print $5}' /etc/passwd`" + cat >>%b < + Created at: `date` + Computer: `uname -n` + System: `uname -sr` on `uname -m` + + Copyright (c) `date +%%Y` $AUTHOR All rights reserved. + ---------------------------------------------------------------------- + + EOF +#--------------------------- End unknown template ----------------------------- + +------------------------------------------------------------------------------- + +#----------------------- Begin common section --------------------------------- +S Sort selection + TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1 + cat %b > $TMPFILE + cat $TMPFILE| sort >%b + rm -f $TMPFILE + +I Insert `Changelog' string + DATE="`date +%%Y-%%m-%%d`" + MY_UID="`id | sed 's/^.*uid=\([^(]*\).*$/\1/'`" + AUTHOR="`awk -F: '$3 == '$MY_UID' {print $5}' /etc/passwd`" + EMAIL="<$REPLYTO>" + echo "$DATE $AUTHOR $EMAIL" >%b + +s Invoke `shell' + sh + +m view `man' + MAN=%{Enter name of man:} + TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/mcview.$MAN.XXXXXX` || exit 1 + man -Pcat $MAN >$TMPFILE + mcview $TMPFILE + rm -f $TMPFILE + +i Insert a out of command to cursor. + CMD=%{ Enter command: } + eval $CMD > %b + +o Open bash to next free console + open -s -- /bin/bash + +u Upper case selection + TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1 + cat %b > $TMPFILE + cat $TMPFILE| sed 's/\(.*\)/\U\1/' >%b + rm -f $TMPFILE + +l Lower case selection + TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1 + cat %b > $TMPFILE + cat $TMPFILE| sed 's/\(.*\)/\U\1/' >%b + rm -f $TMPFILE + +#-------------------------- End of common section ----------------------------- diff --git a/packages/tools/sysutils/MC/etc/panels.ini b/packages/tools/sysutils/MC/etc/panels.ini new file mode 100644 index 000000000..639dd96c8 --- /dev/null +++ b/packages/tools/sysutils/MC/etc/panels.ini @@ -0,0 +1,31 @@ +[New Left Panel] +display=listing +reverse=0 +case_sensitive=1 +exec_first=0 +sort_order=name +list_mode=full +user_format=half type name | size | perm +user_status0=half type name | size | perm +user_status1=half type name | size | perm +user_status2=half type name | size | perm +user_status3=half type name | size | perm +user_mini_status=0 + +[New Right Panel] +display=listing +reverse=0 +case_sensitive=1 +exec_first=0 +sort_order=name +list_mode=full +user_format=half type name | size | perm +user_status0=half type name | size | perm +user_status1=half type name | size | perm +user_status2=half type name | size | perm +user_status3=half type name | size | perm +user_mini_status=0 + +[Dirs] +other_dir=/ +current_is_left=false diff --git a/packages/tools/sysutils/MC/etc/sfs.ini b/packages/tools/sysutils/MC/etc/sfs.ini new file mode 100644 index 000000000..522cca10a --- /dev/null +++ b/packages/tools/sysutils/MC/etc/sfs.ini @@ -0,0 +1,28 @@ +# +# This is config for Single File fileSystem +# +# Notice that output files (%3) are pre-created atomically in /tmp +# with 0600 rights, so it is safe to > %3 +# +gz/1 gzip < %1 > %3 +ugz/1 gzip -cdf < %1 > %3 +bz/1 bzip < %1 > %3 +ubz/1 bzip -d < %1 > %3 +bz2/1 bzip2 < %1 > %3 +ubz2/1 bzip2 -d < %1 > %3 +lzma/1 lzma < %1 > %3 +ulzma/1 lzma -d < %1 > %3 +xz/1 xz < %1 > %3 +uxz/1 xz -d < %1 > %3 +tar/1 tar cf %3 %1 +tgz/1 tar czf %3 %1 +uhtml/1 lynx -force_html -dump %1 > %3 +uman/1 groff -Tascii -man %1 > %3 +uue/1 uuenpipe < %1 > %3 +uude/1 uudepipe < %1 > %3 +crlf/1 todos < %1 > %3 +cr/1 fromdos < %1 > %3 +# Fixme: we need it to fail whenever it should +url:2 lynx -source `echo "%2" | sed 's-|-/-g'` > %3 +nop/1 cat %1 > %3 +strings/1 strings %1 > %3 diff --git a/packages/tools/sysutils/MC/package.mk b/packages/tools/sysutils/MC/package.mk new file mode 100644 index 000000000..46aacb5ff --- /dev/null +++ b/packages/tools/sysutils/MC/package.mk @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2011-present AlexELEC (http://alexelec.in.ua) + +PKG_NAME="MC" +PKG_VERSION="4.8.22" +PKG_SHA256="ee7868d7ba0498cf2cccefe107d7efee7f2571098806bba2aed5a159db801318" +PKG_LICENSE="GPL" +PKG_SITE="http://www.midnight-commander.org/" +PKG_URL="http://ftp.midnight-commander.org/mc-$PKG_VERSION.tar.xz" +PKG_SOURCE_NAME="$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain libtool:host gettext:host glib libssh2 pcre slang" +PKG_LONGDESC="Midnight Commander is a visual file manager" +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET=" \ + --prefix=/usr \ + --sysconfdir=/etc \ + --with-screen=slang \ + --with-sysroot=$SYSROOT_PREFIX \ + --disable-aspell \ + --without-diff-viewer \ + --disable-doxygen-doc \ + --disable-doxygen-dot \ + --disable-doxygen-html \ + --with-gnu-ld \ + --without-libiconv-prefix \ + --without-libintl-prefix \ + --without-gpm-mouse \ + --disable-mclib \ + --with-subshell \ + --with-edit \ + --with-internal-edit \ + --enable-vfs-extfs \ + --enable-vfs-ftp \ + --enable-vfs-sftp \ + --enable-vfs-tar \ + --without-x \ + --with-slang-includes=$SYSROOT_PREFIX/usr/include" + +pre_configure_target() { + LDFLAGS="$LDFLAGS -lcrypto -lssl" +} + +post_install() { + rm -rf $INSTALL/etc/mc + mkdir -p $INSTALL/usr/config/mc + cp -a $PKG_DIR/etc/* $INSTALL/usr/config/mc + ln -sf /storage/.config/mc $INSTALL/etc/mc +} diff --git a/packages/tools/sysutils/MC/patches/MC-01-utf8.patch b/packages/tools/sysutils/MC/patches/MC-01-utf8.patch new file mode 100644 index 000000000..53bb252fb --- /dev/null +++ b/packages/tools/sysutils/MC/patches/MC-01-utf8.patch @@ -0,0 +1,33 @@ +diff -Naurp mc-4.8.8/lib/strutil/strutil.c mc-4.8.8-patch/lib/strutil/strutil.c +--- mc-4.8.8/lib/strutil/strutil.c 2013-03-07 12:45:57.000000000 +0200 ++++ mc-4.8.8-patch/lib/strutil/strutil.c 2013-05-14 09:39:14.000000000 +0300 +@@ -322,16 +322,7 @@ str_translate_char (GIConv conv, const c + const char * + str_detect_termencoding (void) + { +- if (term_encoding == NULL) +- { +- /* On Linux, nl_langinfo (CODESET) returns upper case UTF-8 whether the LANG is set +- to utf-8 or UTF-8. +- On Mac OS X, it returns the same case as the LANG input. +- So let tranform result of nl_langinfo (CODESET) to upper case unconditionally. */ +- term_encoding = g_ascii_strup (nl_langinfo (CODESET), -1); +- } +- +- return term_encoding; ++ return "UTF8"; + } + + static int +diff -Naurp mc-4.8.8/lib/tty/tty-slang.c mc-4.8.8-patch/lib/tty/tty-slang.c +--- mc-4.8.8/lib/tty/tty-slang.c 2013-03-07 12:45:57.000000000 +0200 ++++ mc-4.8.8-patch/lib/tty/tty-slang.c 2013-05-14 09:40:10.000000000 +0300 +@@ -268,7 +268,7 @@ tty_init (gboolean mouse_enable, gboolea + { + SLtt_Ignore_Beep = 1; + +- SLutf8_enable (-1); /* has to be called first before any of the other functions. */ ++ SLutf8_enable (1); /* has to be called first before any of the other functions. */ + SLtt_get_terminfo (); + /* + * If the terminal in not in terminfo but begins with a well-known diff --git a/packages/tools/sysutils/MC/profile.d/52-mc.conf b/packages/tools/sysutils/MC/profile.d/52-mc.conf new file mode 100644 index 000000000..8b89c6d12 --- /dev/null +++ b/packages/tools/sysutils/MC/profile.d/52-mc.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2011-present AlexELEC (http://alexelec.in.ua) + +export EDITOR="mcedit" diff --git a/packages/tools/sysutils/bluetool/package.mk b/packages/tools/sysutils/bluetool/package.mk new file mode 100755 index 000000000..9e21e8bca --- /dev/null +++ b/packages/tools/sysutils/bluetool/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) +# Based on libreelec pycryptodome package + +PKG_NAME="bluetool" +PKG_VERSION="0.2.3" +PKG_SHA256="09aca1174ea9d8b402f2231aa2277726174c30482710fc887ebbda7eb820f614" +PKG_LICENSE="GPL" +PKG_SITE="https://pypi.org/project/bluetool" +PKG_URL="https://files.pythonhosted.org/packages/source/${PKG_NAME:0:1}/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="Python3 dbus-python tcpbridge" +PKG_LONGDESC="A simple Python API for Bluetooth D-Bus calls. Allows easy pairing, connecting and scanning.Also provides a TCP-to-RFCOMM socket bridge for data transfer." +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + cd $PKG_BUILD + rm -rf .$TARGET_NAME + + export PYTHONXCPREFIX="$SYSROOT_PREFIX/usr" + export LDSHARED="$CC -shared" +} + +make_target() { + python3 setup.py build +} + +makeinstall_target() { + python3 setup.py install --root=$INSTALL --prefix=/usr +} diff --git a/packages/tools/sysutils/coreutils/package.mk b/packages/tools/sysutils/coreutils/package.mk new file mode 100644 index 000000000..ad505dd58 --- /dev/null +++ b/packages/tools/sysutils/coreutils/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="coreutils" +PKG_VERSION="8.31" +PKG_SHA256="ff7a9c918edce6b4f4b2725e3f9b37b0c4d193531cac49a48b56c4d0d3a9e9fd" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://www.gnu.org/software/coreutils/" +PKG_URL="https://ftp.gnu.org/gnu/coreutils/coreutils-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The GNU Core Utilities are the basic file, shell and text manipulation utilities of the GNU operating system." +PKG_TOOLCHAIN="auto" + +makeinstall_target() { +mkdir -p $INSTALL/usr/bin +cp $PKG_BUILD/.${TARGET_NAME}/src/stdbuf $INSTALL/usr/bin/ +cp $PKG_BUILD/.${TARGET_NAME}/src/timeout $INSTALL/usr/bin/ +cp $PKG_BUILD/.${TARGET_NAME}/src/sort $INSTALL/usr/bin/ +mkdir -p $INSTALL/usr/lib/coreutils +cp $PKG_BUILD/.${TARGET_NAME}/src/libstdbuf.so $INSTALL/usr/lib/coreutils/ +} diff --git a/packages/tools/sysutils/dialog/package.mk b/packages/tools/sysutils/dialog/package.mk new file mode 100644 index 000000000..613f036db --- /dev/null +++ b/packages/tools/sysutils/dialog/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="dialog" +PKG_VERSION="1.3-20190211" +PKG_SHA256="49c0e289d77dcd7806f67056c54f36a96826a9b73a53fb0ffda1ffa6f25ea0d3" +PKG_LICENSE="GNU-2.1" +PKG_SITE="https://invisible-mirror.net/archives/dialog" +PKG_URL="$PKG_SITE/dialog-$PKG_VERSION.tgz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="This version of dialog, formerly known as cdialog is based on the Debian package for dialog 0.9a" +PKG_TOOLCHAIN="auto" + +PKG_CONFIGURE_OPTS_TARGET="--with-ncurses --disable-rpath-hack" + + diff --git a/packages/tools/sysutils/empty/package.mk b/packages/tools/sysutils/empty/package.mk new file mode 100644 index 000000000..390f501b2 --- /dev/null +++ b/packages/tools/sysutils/empty/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="empty" +PKG_VERSION="0.6.20b" +PKG_SHA256="7e6636e400856984c4405ce7bd0843aaa3329fa3efd20c58df8400a9eaa35f09" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://empty.sourceforge.net/" +PKG_DEPENDS_TARGET="toolchain linux" +PKG_URL="http://downloads.sourceforge.net/sourceforge/$PKG_NAME/$PKG_NAME-$PKG_VERSION.tgz" +PKG_SECTION="sysutils" +PKG_SHORTDESC="Run applications under pseudo-terminal sessions" +PKG_LONGDESC="Run applications under pseudo-terminal sessions" + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +make_target() { + make CC=$CC +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp empty $INSTALL/usr/bin/ +} diff --git a/packages/tools/sysutils/evdev_tools/package.mk b/packages/tools/sysutils/evdev_tools/package.mk new file mode 100644 index 000000000..2805dbc41 --- /dev/null +++ b/packages/tools/sysutils/evdev_tools/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present BetaXOi (https://github.com/BetaXOi) +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="evdev_tools" +PKG_VERSION="" +PKG_REV="1" +PKG_ARCH="any" +PKG_SITE="https://github.com/BetaXOi" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="emuelec" +PKG_LONGDESC="A set of small evdev tools by https://github.com/BetaXOi" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="make" + +make_target() { + cd $PKG_BUILD/ + $CC -O2 evtest.c -o evtest + $CC -O2 send.c -o evsend + $CC -O2 remap.c -o evremap + $CC -O2 evkill.c -o evkill +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/distribution/bin + cp $PKG_BUILD/evtest $INSTALL/usr/config/distribution/bin + cp $PKG_BUILD/evsend $INSTALL/usr/config/distribution/bin + cp $PKG_BUILD/evremap $INSTALL/usr/config/distribution/bin + cp $PKG_BUILD/evkill $INSTALL/usr/config/distribution/bin +} diff --git a/packages/tools/sysutils/evdev_tools/sources/evkill.c b/packages/tools/sysutils/evdev_tools/sources/evkill.c new file mode 100644 index 000000000..a0ca959a1 --- /dev/null +++ b/packages/tools/sysutils/evdev_tools/sources/evkill.c @@ -0,0 +1,173 @@ +/* Usage: evkill <-k, --keys keys> <-d, --device evdev> +eg: evkill -k 304+305 -d /dev/input/event3 retroarch + +Signed-off-by: Ning Bo +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void set_bit(char *mem, int key) { + int8_t *byte = (int8_t *)mem + key / 8; + *byte |= 1 << key % 8; +} + +void clr_bit(char *mem, int key) { + int8_t *byte = (int8_t *)mem + key / 8; + *byte &= ~(1 << key % 8); +} + +static const struct option long_options[] = { + {"device", required_argument, NULL, 'd'}, + {"keys", required_argument, NULL, 'k'}, + {0, 0, 0, 0} +}; + +char *js2evdev(char *joystick) { + char *evdev = NULL; + char *path = NULL; + DIR *dir; + struct dirent *ptr; + + asprintf(&path, "/sys/class/input/%s/device", basename(joystick)); + dir = opendir(path); + free(path); + if (dir == NULL) { + return NULL; + } + + while((ptr = readdir(dir)) != NULL) { + if (ptr->d_type == DT_DIR && strncmp(ptr->d_name, "event", 5) == 0) { + asprintf(&evdev, "/dev/input/%s", ptr->d_name); + } + } + + return evdev; +} + +int main(int argc, char* argv[]) +{ + int ret = 0; + int opt = 0; + struct input_event ev; + char *dev = NULL, *keys = NULL; + char cmd[1024]; + + int size = (KEY_CNT - 1) / 8 + 1; + char *bitmap0 = (char *)malloc(size); + char *bitmap1 = (char *)malloc(size); + memset(bitmap0, 0x0, size); + memset(bitmap1, 0x0, size); + + while((opt = getopt_long(argc, argv, "d:k:", long_options, NULL)) != -1) + { + switch(opt) + { + case 'd': + dev = strdup(optarg); + break; + case 'k': + keys = strdup(optarg); + break; + default: + printf("Usage: %s <-k, --keys keys> <-d, --device evdev or joystick> \n", argv[0]); + exit(1); + break; + } + } + + if (dev == NULL || keys== NULL || optind == argc) { + printf("Usage: %s <-k, --keys keys> <-d, --device evdev or joystick> \n", argv[0]); + exit(1); + } + + strcpy(cmd, "killall "); + int i; + for (i = optind; i < argc; i++) { + strcat(cmd, argv[i]); + } + + char *str, *saveptr, *key; + for (i = 0, str = keys; ; i++, str = NULL) { + key = strtok_r(str, ",+", &saveptr); + if (key == NULL) + break; + + if (atoi(key) > KEY_MAX) + continue; + + set_bit(bitmap0, atoi(key)); + } + + while(1) { + int fd, version, ready; + + ready = 0; + do { + fd = open(dev, O_RDONLY); + if (fd > 0) { + if (ioctl(fd, EVIOCGVERSION, &version)) { + ready = 1; + break; + } + } + + char *evdev = js2evdev(dev); + if (!evdev) { + break; + } + + fd = open(evdev, O_RDONLY); + free(evdev); + if (fd > 0) { + if (ioctl(fd, EVIOCGVERSION, &version) == 0) { + ready = 1; + break; + } + } + } while(0); + + if (!ready) { + sleep(1); + continue; + } + + while(1) { + ret = read(fd, &ev, sizeof(struct input_event)); + if (ret < 0) { + perror("read"); + break; + } + + if (ev.type == EV_KEY) { + if (ev.value == 0) { + clr_bit(bitmap1, ev.code); + continue; + } else { + set_bit(bitmap1, ev.code); + } + } + + if (memcmp(bitmap0, bitmap1, size) == 0) { + memset(bitmap1, 0x0, size); + /* printf("execute cmd: %s\n", cmd);*/ + system(cmd); + exit(0); + } + } + + close(fd); + } + + return 0; +} + diff --git a/packages/tools/sysutils/evdev_tools/sources/evtest.c b/packages/tools/sysutils/evdev_tools/sources/evtest.c new file mode 100644 index 000000000..3f1f1186e --- /dev/null +++ b/packages/tools/sysutils/evdev_tools/sources/evtest.c @@ -0,0 +1,364 @@ +/* +evtest is used for show input event received. +send is used for send BTN_A input event. + +Signed-off-by: Ning Bo +*/ +#include +#include +#include +#include +#include +#include + +#ifndef EV_SYN +#define EV_SYN 0 +#endif + +char *events[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + [EV_SYN] = "Sync", [EV_KEY] = "Key", + [EV_REL] = "Relative", [EV_ABS] = "Absolute", + [EV_MSC] = "Misc", [EV_LED] = "LED", + [EV_SND] = "Sound", [EV_REP] = "Repeat", + [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", + [EV_FF_STATUS] = "ForceFeedbackStatus", +}; + +char *keys[KEY_MAX + 1] = { + [0 ... KEY_MAX] = NULL, + [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", + [KEY_1] = "1", [KEY_2] = "2", + [KEY_3] = "3", [KEY_4] = "4", + [KEY_5] = "5", [KEY_6] = "6", + [KEY_7] = "7", [KEY_8] = "8", + [KEY_9] = "9", [KEY_0] = "0", + [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", + [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", + [KEY_Q] = "Q", [KEY_W] = "W", + [KEY_E] = "E", [KEY_R] = "R", + [KEY_T] = "T", [KEY_Y] = "Y", + [KEY_U] = "U", [KEY_I] = "I", + [KEY_O] = "O", [KEY_P] = "P", + [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", + [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", + [KEY_A] = "A", [KEY_S] = "S", + [KEY_D] = "D", [KEY_F] = "F", + [KEY_G] = "G", [KEY_H] = "H", + [KEY_J] = "J", [KEY_K] = "K", + [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", + [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", + [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", + [KEY_Z] = "Z", [KEY_X] = "X", + [KEY_C] = "C", [KEY_V] = "V", + [KEY_B] = "B", [KEY_N] = "N", + [KEY_M] = "M", [KEY_COMMA] = "Comma", + [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", + [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", + [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", + [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", + [KEY_F2] = "F2", [KEY_F3] = "F3", + [KEY_F4] = "F4", [KEY_F5] = "F5", + [KEY_F6] = "F6", [KEY_F7] = "F7", + [KEY_F8] = "F8", [KEY_F9] = "F9", + [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", + [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", + [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", + [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", + [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", + [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", + [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", + [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", + [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", + [KEY_F11] = "F11", [KEY_F12] = "F12", + [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", + [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", + [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", + [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", + [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", + [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", + [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", + [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", + [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", + [KEY_END] = "End", [KEY_DOWN] = "Down", + [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", + [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", + [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", + [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", + [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", + [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", + [KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja", + [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", + [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", + [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", + [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", + [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", + [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", + [KEY_FIND] = "Find", [KEY_CUT] = "Cut", + [KEY_HELP] = "Help", [KEY_MENU] = "Menu", + [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", + [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", + [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", + [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", + [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", + [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", + [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", + [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", + [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", + [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", + [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", + [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", + [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", + [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", + [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", + [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", + [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", + [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", + [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", + [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", + [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13", + [KEY_F14] = "F14", [KEY_F15] = "F15", + [KEY_F16] = "F16", [KEY_F17] = "F17", + [KEY_F18] = "F18", [KEY_F19] = "F19", + [KEY_F20] = "F20", [KEY_F21] = "F21", + [KEY_F22] = "F22", [KEY_F23] = "F23", + [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", + [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", + [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", + [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", + [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost", + [KEY_PRINT] = "Print", [KEY_HP] = "HP", + [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", + [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", + [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", + [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", + [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", + [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel", + [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up", + [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", + [BTN_0] = "Btn0", [BTN_1] = "Btn1", + [BTN_2] = "Btn2", [BTN_3] = "Btn3", + [BTN_4] = "Btn4", [BTN_5] = "Btn5", + [BTN_6] = "Btn6", [BTN_7] = "Btn7", + [BTN_8] = "Btn8", [BTN_9] = "Btn9", + [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", + [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", + [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", + [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", + [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", + [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", + [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", + [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", + [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", + [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", + [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", + [BTN_B] = "BtnB", [BTN_C] = "BtnC", + [BTN_X] = "BtnX", [BTN_Y] = "BtnY", + [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", + [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", + [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", + [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", + [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", + [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", + [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", + [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", + [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", + [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", + [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap", + [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", + [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", + [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", + [KEY_OPTION] = "Option", [KEY_INFO] = "Info", + [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", + [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", + [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", + [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", + [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", + [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", + [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", + [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", + [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", + [KEY_TV] = "TV", [KEY_TV2] = "TV2", + [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", + [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", + [KEY_CD] = "CD", [KEY_TAPE] = "Tape", + [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", + [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", + [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", + [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", + [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", + [KEY_LIST] = "List", [KEY_MEMO] = "Memo", + [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", + [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", + [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", + [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", + [KEY_LAST] = "Last", [KEY_AB] = "AB", + [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", + [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", + [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", + [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", + [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "Delete EOL", + [KEY_DEL_EOS] = "Delete EOS", [KEY_INS_LINE] = "Insert line", + [KEY_DEL_LINE] = "Delete line", +}; + +char *absval[5] = { "Value", "Min ", "Max ", "Fuzz ", "Flat " }; + +char *relatives[REL_MAX + 1] = { + [0 ... REL_MAX] = NULL, + [REL_X] = "X", [REL_Y] = "Y", + [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", + [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", + [REL_MISC] = "Misc", +}; + +char *absolutes[ABS_MAX + 1] = { + [0 ... ABS_MAX] = NULL, + [ABS_X] = "X", [ABS_Y] = "Y", + [ABS_Z] = "Z", [ABS_RX] = "Rx", + [ABS_RY] = "Ry", [ABS_RZ] = "Rz", + [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", + [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", + [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", + [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", + [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", + [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", + [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", + [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", + [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", + [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", +}; + +char *misc[MSC_MAX + 1] = { + [ 0 ... MSC_MAX] = NULL, + [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", + [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData", + [MSC_SCAN] = "ScanCode", +}; + +char *leds[LED_MAX + 1] = { + [0 ... LED_MAX] = NULL, + [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", + [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", + [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", + [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", + [LED_MISC] = "Misc", +}; + +char *repeats[REP_MAX + 1] = { + [0 ... REP_MAX] = NULL, + [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" +}; + +char *sounds[SND_MAX + 1] = { + [0 ... SND_MAX] = NULL, + [SND_CLICK] = "Click", [SND_BELL] = "Bell", + [SND_TONE] = "Tone" +}; + +char **names[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + [EV_SYN] = events, [EV_KEY] = keys, + [EV_REL] = relatives, [EV_ABS] = absolutes, + [EV_MSC] = misc, [EV_LED] = leds, + [EV_SND] = sounds, [EV_REP] = repeats, +}; + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define BIT(x) (1UL<> OFF(bit)) & 1) + +int main (int argc, char **argv) +{ + int fd, rd, i, j, k; + struct input_event ev[64]; + int version; + unsigned short id[4]; + unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; + char name[256] = "Unknown"; + int abs[5]; + + if (argc < 2) { + printf("Usage: evtest /dev/input/eventX\n"); + printf("Where X = input device number\n"); + return 1; + } + + if ((fd = open(argv[argc - 1], O_RDONLY)) < 0) { + perror("evtest"); + return 1; + } + + if (ioctl(fd, EVIOCGVERSION, &version)) { + perror("evtest: can't get version"); + return 1; + } + + printf("Input driver version is %d.%d.%d\n", + version >> 16, (version >> 8) & 0xff, version & 0xff); + + ioctl(fd, EVIOCGID, id); + printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", + id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]); + + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + printf("Input device name: \"%s\"\n", name); + + memset(bit, 0, sizeof(bit)); + ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]); + printf("Supported events:\n"); + + for (i = 0; i < EV_MAX; i++) + if (test_bit(i, bit[0])) { + printf(" Event type %d (%s)\n", i, events[i] ? events[i] : "?"); + if (!i) continue; + ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]); + for (j = 0; j < KEY_MAX; j++) + if (test_bit(j, bit[i])) { + printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?"); + if (i == EV_ABS) { + ioctl(fd, EVIOCGABS(j), abs); + for (k = 0; k < 5; k++) + if ((k < 3) || abs[k]) + printf(" %s %6d\n", absval[k], abs[k]); + } + } + } + printf("Testing ... (interrupt to exit)\n"); + + while (1) { + rd = read(fd, ev, sizeof(struct input_event) * 64); + + if (rd < (int) sizeof(struct input_event)) { + printf("yyy\n"); + perror("\nevtest: error reading"); + return 1; + } + + for (i = 0; i < rd / sizeof(struct input_event); i++) + + if (ev[i].type == EV_SYN) { + printf("Event: time %ld.%06ld, -------------- %s ------------\n", + ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" ); + } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) { + printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %02x\n", + ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, + events[ev[i].type] ? events[ev[i].type] : "?", + ev[i].code, + names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", + ev[i].value); + } else { + printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n", + ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, + events[ev[i].type] ? events[ev[i].type] : "?", + ev[i].code, + names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", + ev[i].value); + } + + } +} diff --git a/packages/tools/sysutils/evdev_tools/sources/remap.c b/packages/tools/sysutils/evdev_tools/sources/remap.c new file mode 100644 index 000000000..2e708d6be --- /dev/null +++ b/packages/tools/sysutils/evdev_tools/sources/remap.c @@ -0,0 +1,118 @@ +/* + * Signed-off-by: Ning Bo +*/ +#include +#include +#include +#include +#include +#include +#include + +void remap(int src, int dst) { + int ret = 0; + int power = 0, back = 0; + struct input_event ev, ev_pre, ev_end; + + while(1) { + ret = read(src, &ev, sizeof(struct input_event)); + if(ret != sizeof(struct input_event)) + { + perror("read"); + break; + } + + if (ev.value == 0xc0030) { + ev_pre.time = ev.time; + ev_pre.type = 4; + ev_pre.code = 4; + ev_pre.value = 0x9000b; + power = 1; + continue; + } + + if (power==0 && ev.value==0xc0224) { + ev_pre.time = ev.time; + ev_pre.type = 4; + ev_pre.code = 4; + ev_pre.value = 0x9000b; + back = 1; + continue; + } + + if (power) { + write(dst, &ev_pre, sizeof(struct input_event)); + + ev.code = 0x13a; + write(dst, &ev, sizeof(struct input_event)); + + ev_end.time = ev.time; + ev_end.type = 0; + ev_end.code = 0; + ev_end.value = 0; + write(dst, &ev_end, sizeof(struct input_event)); + + ev_pre.value = 0x9000c; + write(dst, &ev_pre, sizeof(struct input_event)); + + ev.code = 0x13b; + write(dst, &ev, sizeof(struct input_event)); + + write(dst, &ev_end, sizeof(struct input_event)); + + power = 0; + continue; + } + + if (back) { + write(dst, &ev_pre, sizeof(struct input_event)); + + ev.code = 0x13a; + write(dst, &ev, sizeof(struct input_event)); + + ev_end.time = ev.time; + ev_end.type = 0; + ev_end.code = 0; + ev_end.value = 0; + write(dst, &ev_end, sizeof(struct input_event)); + + back = 0; + continue; + } + } + + close(src); + close(dst); + + return; +} + +int main(int argc, char *argv[]) +{ + int fd_from = 0, fd_to = 0; + + if (argc != 3) { + printf("usage: %s ", argv[0]); + return 1; + } + + while(1) { + fd_from = open(argv[1], O_RDONLY); + if(fd_from < 0) + { + perror("open from"); + sleep(1); + break; + } + fd_to = open(argv[2], O_WRONLY); + if(fd_to < 0) + { + perror("open to"); + sleep(1); + break; + } + + remap(fd_from, fd_to); + } +} + diff --git a/packages/tools/sysutils/evdev_tools/sources/send.c b/packages/tools/sysutils/evdev_tools/sources/send.c new file mode 100644 index 000000000..0c4625b0b --- /dev/null +++ b/packages/tools/sysutils/evdev_tools/sources/send.c @@ -0,0 +1,68 @@ +/* + * Signed-off-by: Ning Bo +*/ +#include +#include +#include +#include +#include +#include +#include + +#define BASE_VALUE 0x9000b +#define BASE_CODE BTN_SELECT + +int main(int argc, char *argv[]) +{ + int fd_to = -1, ret = -1; + struct input_event ev, ev_pre, ev_end; + struct timeval ts; + + if (argc != 2) { + printf("usage: %s ", argv[0]); + return 1; + } + + char *to = argv[1]; + + fd_to = open(to, O_WRONLY); + if(fd_to < 0) + { + perror("open to"); + return -1; + } + + int version; + ioctl(fd_to, EVIOCGVERSION, &version); + + gettimeofday(&ts, NULL); + ev_pre.time=ts; + ev_pre.type=4; + ev_pre.code=4; + ev_pre.value=BASE_VALUE+(BTN_A-BTN_SELECT); + write(fd_to, &ev_pre, sizeof(struct input_event)); + + ev.time=ts; + ev.type=1; + ev.code=BASE_CODE+(BTN_A-BTN_SELECT); + ev.value=1; + write(fd_to, &ev, sizeof(struct input_event)); + + ev_end.time=ev.time; + ev_end.type=0; + ev_end.code=0; + ev_end.value=0; + write(fd_to, &ev_end, sizeof(struct input_event)); + + sleep(1); + + gettimeofday(&ts, NULL); + ev_pre.time=ts; + write(fd_to, &ev_pre, sizeof(struct input_event)); + ev.time=ts; + ev.value=0; + write(fd_to, &ev, sizeof(struct input_event)); + ev_end.time=ts; + write(fd_to, &ev_end, sizeof(struct input_event)); +} + diff --git a/packages/tools/sysutils/fbterm/package.mk b/packages/tools/sysutils/fbterm/package.mk new file mode 100644 index 000000000..d836797f1 --- /dev/null +++ b/packages/tools/sysutils/fbterm/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="fbterm" +PKG_VERSION="ef9a13146e24c059fa44151e2a0a22b9762853bc" +PKG_SHA256="149c9fd243b6f93a0e907c8adf281e6e308d15be6a30fc0b1081755c0bc44dbc" +PKG_LICENSE="GPLv2+" +PKG_SITE="https://github.com/sfzhi/fbterm" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain freetype fontconfig" +PKG_LONGDESC=" fbterm is a framebuffer based terminal emulator for linux " +PKG_TOOLCHAIN="configure" + +pre_configure_target() { + cd .. + rm -rf .$TARGET_NAME +} + +makeinstall_target() { +mkdir -p $INSTALL/usr/bin +cp -rf $PKG_BUILD/src/fbterm $INSTALL/usr/bin +mkdir -p $INSTALL/usr/share/terminfo +cp -rf $PKG_DIR/terminfo/* $INSTALL/usr/share/terminfo/ +tic $PKG_BUILD/terminfo/fbterm -o $INSTALL/usr/share/terminfo +# mv $INSTALL/usr/share/terminfo/f/fbterm $INSTALL/usr/share/terminfo/f/linux +# mv $INSTALL/usr/share/terminfo/f $INSTALL/usr/share/terminfo/l +# mkdir -p $INSTALL/usr/share/terminfo/f/ +# cp $PKG_BUILD/terminfo/fbterm $INSTALL/usr/share/terminfo/f/ +} diff --git a/packages/tools/sysutils/fbterm/patches/0001-fbio.cpp-improxy.cpp-fbterm.cpp-fix-musl-compile.patch b/packages/tools/sysutils/fbterm/patches/0001-fbio.cpp-improxy.cpp-fbterm.cpp-fix-musl-compile.patch new file mode 100644 index 000000000..27e1e9106 --- /dev/null +++ b/packages/tools/sysutils/fbterm/patches/0001-fbio.cpp-improxy.cpp-fbterm.cpp-fix-musl-compile.patch @@ -0,0 +1,70 @@ +From 1072d60c6c8f1f51feb740527a8a056bfead9318 Mon Sep 17 00:00:00 2001 +From: Peter Seiderer +Date: Thu, 8 Oct 2015 19:53:47 +0200 +Subject: [PATCH] fbio.cpp, improxy.cpp, fbterm.cpp: fix musl compile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +- add missing include, fixes: + + fbio.cpp:33:8: error: ‘fd_set’ does not name a type + static fd_set fds; + + improxy.cpp:439:3: error: ‘fd_set’ was not declared in this scope + +- add missing WAIT_ANY define, fixes: + + fbterm.cpp: In member function ‘void FbTerm::processSignal(u32)’: + fbterm.cpp:212:22: error: ‘WAIT_ANY’ was not declared in this scope + s32 pid = waitpid(WAIT_ANY, 0, WNOHANG); + +Signed-off-by: Peter Seiderer +--- + src/fbio.cpp | 1 + + src/fbterm.cpp | 4 ++++ + src/improxy.cpp | 1 + + 3 files changed, 6 insertions(+) + +diff --git a/src/fbio.cpp b/src/fbio.cpp +index e5afc44..88c632c 100644 +--- a/src/fbio.cpp ++++ b/src/fbio.cpp +@@ -30,6 +30,7 @@ + #define NR_EPOLL_FDS 10 + s32 epollFd; + #else ++#include + static fd_set fds; + static u32 maxfd = 0; + #endif +diff --git a/src/fbterm.cpp b/src/fbterm.cpp +index 38d4014..60288e4 100644 +--- a/src/fbterm.cpp ++++ b/src/fbterm.cpp +@@ -37,6 +37,10 @@ + #include "input_key.h" + #include "mouse.h" + ++#ifndef WAIT_ANY ++#define WAIT_ANY (-1) ++#endif ++ + #ifdef HAVE_SIGNALFD + // offered by some systems has bug with g++ + #include "signalfd.h" +diff --git a/src/improxy.cpp b/src/improxy.cpp +index 3d03e66..4e046d2 100644 +--- a/src/improxy.cpp ++++ b/src/improxy.cpp +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include "improxy.h" + #include "immessage.h" +-- +2.1.4 + diff --git a/packages/tools/sysutils/fbterm/patches/gcc-6-build-fixes.patch b/packages/tools/sysutils/fbterm/patches/gcc-6-build-fixes.patch new file mode 100644 index 000000000..ad5dd65c4 --- /dev/null +++ b/packages/tools/sysutils/fbterm/patches/gcc-6-build-fixes.patch @@ -0,0 +1,104 @@ +From 69917d25c6f718572433262d86691bf24e72e4c8 Mon Sep 17 00:00:00 2001 +From: Nobuhiro Iwamatsu +Date: Wed, 13 Jul 2016 12:02:10 +0900 +Subject: [PATCH] Fix build with gcc-6 + +Signed-off-by: Nobuhiro Iwamatsu +--- + src/lib/vterm.cpp | 4 ++-- + src/lib/vterm_states.cpp | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/lib/vterm.cpp b/src/lib/vterm.cpp +index 3a5dcc7..f79f44c 100644 +--- a/src/lib/vterm.cpp ++++ b/src/lib/vterm.cpp +@@ -68,13 +68,13 @@ u8 VTerm::control_map[MAX_CONTROL_CODE], VTerm::escape_map[NR_STATES][MAX_ESCAPE + + void VTerm::init_state() + { +- for (u8 i = 1; control_sequences[i].code != (u16)-1; i++) { ++ for (u8 i = 1; control_sequences[i].code != (u16)0xFFFF; i++) { + control_map[control_sequences[i].code] = i; + } + + u8 state = ESnormal; + for (u8 i = 1; ; i++) { +- if (escape_sequences[i].code == (u16)-1) { ++ if (escape_sequences[i].code == (u16)0xFFFF) { + state++; + if (state == NR_STATES) break; + } else { +diff --git a/src/lib/vterm_states.cpp b/src/lib/vterm_states.cpp +index 49e7588..6aaa8b3 100644 +--- a/src/lib/vterm_states.cpp ++++ b/src/lib/vterm_states.cpp +@@ -39,14 +39,14 @@ const VTerm::Sequence VTerm::control_sequences[] = { + { 0x1B, 0, ESesc }, + { 0x7F, 0, ESkeep }, + { 0x9B, 0, ESsquare }, +- { -1} ++ { 0xFFFF} + }; + + const VTerm::Sequence VTerm::escape_sequences[] = { + { 0, 0, ESnormal }, + + // ESnormal +- { -1 }, ++ { 0xFFFF }, + + // ESesc + { '[', &VTerm::clear_param, ESsquare }, +@@ -65,7 +65,7 @@ const VTerm::Sequence VTerm::escape_sequences[] = { + { '8', &VTerm::restore_cursor, ESnormal }, + { '>', &VTerm::keypad_numeric, ESnormal }, + { '=', &VTerm::keypad_application, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // ESsquare + { '[', 0, ESfunckey }, +@@ -104,7 +104,7 @@ const VTerm::Sequence VTerm::escape_sequences[] = { + { '`', &VTerm::cursor_position_col, ESnormal }, + { ']', &VTerm::linux_specific, ESnormal }, + { '}', &VTerm::fbterm_specific, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // ESnonstd + { '0' | ADDSAME(9), &VTerm::set_palette, ESkeep }, +@@ -112,25 +112,25 @@ const VTerm::Sequence VTerm::escape_sequences[] = { + { 'a' | ADDSAME(5), &VTerm::set_palette, ESkeep }, + { 'P', &VTerm::begin_set_palette, ESkeep }, + { 'R', &VTerm::reset_palette, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // ESpercent + { '@', &VTerm::clear_utf8, ESnormal }, + { 'G', &VTerm::set_utf8, ESnormal }, + { '8', &VTerm::set_utf8, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // EScharset + { '0', &VTerm::set_charset, ESnormal }, + { 'B', &VTerm::set_charset, ESnormal }, + { 'U', &VTerm::set_charset, ESnormal }, + { 'K', &VTerm::set_charset, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // EShash + { '8', &VTerm::screen_align, ESnormal }, +- { -1 }, ++ { 0xFFFF }, + + // ESfunckey +- { -1 }, ++ { 0xFFFF }, + }; +-- +2.8.1 + diff --git a/packages/tools/sysutils/fbterm/terminfo/E/Eterm b/packages/tools/sysutils/fbterm/terminfo/E/Eterm new file mode 100644 index 0000000000000000000000000000000000000000..f4f767886fb631906868fedf1bbb1e3fc243f8df GIT binary patch literal 2267 zcmbtVU1%It6h3$E#->UWFcfRo(rs~SV@TP#GrOB*v1v?FlQhY$=}!W!q51D7yV=d| z=0B~96!oEfun)zj7C}UOQUnnZ1*sqi1w|k9K|v5f5J7|r*6}-Mc4MFw6(^kUe)rt( zoW1v)xtZOnm-f(J%Bnq~?#fgtzaiKa zC30{iGMt^CEG$Qkua+xQ`DRjz#E2iB@PI!VGgMEz!2CO&dOAXX+~M8os6!NyMIqWr zyJMp)RV+P+e8m)$17F+KhNleF%O-eJ`F}R@gdVHCrv#A#2I<{Z&}- ztXt1m7p)hq%i_7R>HpaJRQP9tUvBz+|10Yo%)YaJ*y5{Y`}^@HsDH6;ZN}WTEWJ&$ zp8Hno-F@N-vNYeN%t2C0mg5?)de;)YYQD)j#T=^)3DTe~hce|DUlg6hv=Ms#;#$g@!*Hb+kS40juP$Rqx@$l}1^w$Vy6b~m8!bSD6fEWNL4-OcU zBg&Cc0n~xZ)&tc)lq9HKG#W*L&_eWs%Uo^vBzi^nQkXXywcGjUi*b9yuB040#d8Dd z1r$rJEG2@uhozXE%CjtKR~qc8Mmt5}9@>s%QZcSkdJ!`zD9U#B?AX}!^vulc?A%-~ zm(S177YfDV!a}K3E>|jxi%Uz(%PT9Zt7~iP>l+*A&tKq5XsYCQ zAI4mo*~TovU>GK06FiZA8<804pOID?2{+PjR}#9?YghDcpqK2%<9v=Y%4h^#K~FFy zm=Fx!xg>KF6_h9=dLw!xdJ~sb(HqgbqI4y{D|$E3yZrVTkI~_qizeb?PY!{`=K;71 zh7Zc-CR1LLZyQ(1mG_EgUX|fnNAv(i=_bCT{Ozm5YtTUV!}k#F!}qTRYaS)(Fm+N7 z^;4$y#e!DTJ!oPjvMjazGa)P>Dn(OL}F~k9bY?yTqb_ED$PkI0x r2;R%mUY7PBJpnp6Qbl+&L#N;Yf)Dkw|73;@WX#aqxC6tlO&IzUv8ZpM literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/E/Eterm-color b/packages/tools/sysutils/fbterm/terminfo/E/Eterm-color new file mode 120000 index 000000000..74aebd749 --- /dev/null +++ b/packages/tools/sysutils/fbterm/terminfo/E/Eterm-color @@ -0,0 +1 @@ +Eterm \ No newline at end of file diff --git a/packages/tools/sysutils/fbterm/terminfo/a/ansi b/packages/tools/sysutils/fbterm/terminfo/a/ansi new file mode 100644 index 0000000000000000000000000000000000000000..6de79787ad2d3fd89a05b113e11d98c012f4314a GIT binary patch literal 1481 zcmds%J!n%=6vxkf78@*u3LRP_rOVT3Tg^*enuMn&)qqh`2-=}ENKNx<`!ruB(N^0O zoE#lQ6s&`TgM(mE7Z*QTH&>xr&_Th`&p{XC|GbYRgB6?vANQ)MJ@rwo<^%7ABH}9S^`?w7gZ(1nYwP5i>;5l(`PNl$wv!)G_lhqmIr?XVlTcphZNB zh!!o1f?Bj_5xr>9qK7>eEg~YKETTnFix&1+CCYDRfR%Qz~WAuX$D~6;cL{q|g$*pGvD}HLZbOPgb(SJ3#>z!Xlvz_Ov3GBb8Pc%u>#A>-pSJ`T#+N$Q(h<4~qkt$JDs#Z0qW*wjVqwah% zx(M|=8U5WW9>4s@{`{vFpM9;~sSoO-`mDaFN%ccbsh^5Cg;RM2r*S%G@;Wy12F~Hl zZ03A+@OCcb5_WL~S92XVatpVyhkMx1i=V!b6XE~VcOkQ*JjMohGcBc+WN^C-?mckj zK)lIk3g?+TZL`v83R_Gb7ZN*x3x5@ZyTDuwD-=nTC#o7$0$TtkPmI;<)ZQ+EHoA8s zBFPAapaLzAz)Sl|&;a&=Dj-d3KrPq@>Oeh^>r{XePzH8`nd_87>p^l@3+bwbjL<^n zY9URvkZxK?OD&|I7BW-|`LHou+|Wq|ha}^V?EDdlEv$uhrfOKHE>HP!vK=ejSW_f6kD|3u(^@Nxg6=)=KV zLl1_>V>d^>kA54Q#*t>Q3+xB-!c9PO?VtnT%5GfL?FC(+8}tAl=mmYi59C`3f)EIU relP$cAPNS-5EuqAFakz_yr>(rfCHcv90c-9Is~NFs$Wqi)S# literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/c/cons25-debian b/packages/tools/sysutils/fbterm/terminfo/c/cons25-debian new file mode 100644 index 0000000000000000000000000000000000000000..b379983e204e0ec7183590f63f58afe2b77d3703 GIT binary patch literal 1519 zcmcJOOGuPa6vxlKSsGCWB4!`aPz)tujWbRYe2A9XOsVEm}lGm_$U2pcYXsDhlj>?u?^FkS@CLJNJLiJ&!wgX4VTA zZJ@Oj5ND(}5{_Bzg+9M0;0_<_8u0r)F`tQ}kv_jE5s3Ggl4mB5+Z&8U-CnAo zVZX^8js;Aih|ga@LJ$$7R$8c-pgPK;e472s%AzvLMNI~+Q0G~cO*xbYy@_n(z^;Q5 zDu;Da71dJ{6t5O)SIV36gA|1t1Y@bl$<&_AXM2iHBX%|wKZpH%I_Cmiq$_lduG0+~ zr#p0)?$HEI;`|ACO3&y;Dt9VfGv9fkdX4k9^nqsRCoLCiM4m8-0$~*kb6D#tQX!n8 zK{SaL(Wd-MzvW#{dsm^Jr@cRWCH2p2$xOLQ zX3HFzCpEcIZkAi*Hn~IEq(kbmRF+Gptdg~|Q8r6Mc1W-6mO&YjOP{`&ir9bZyO`Mt zc|vMND`nDZ(hQeo?8jCGcsB>k(IT_2b6)D^sMYLqA+QIy@K@1{5=%KOvzxslR&}5T z*h4TyY-|=??GAR7QN0ht;|Nm*s_8haZ48Dd)PO_a0H_7rw;nWrMsN@`0lrZ+r~po| z56s=D5?amTVkNk%5qGogOifQkoIKM4#}^S^mf974ADxos-(ho+w(2cof+<%UEjJt_lyT} zd#8f;`(A|}geUtS#~%&e9-2rz9KJO&Gx}xhJ4#x?UeFBqky`-A+`t2HWdj#A{GbbT zgB}n7y&wqs0Dm!I5CKup4+cOC#K9mK0tqk-M!+cG7d5~U&<5H;2jCymQNX!2^@=>9 HIHi68B~0x4 literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/c/cygwin b/packages/tools/sysutils/fbterm/terminfo/c/cygwin new file mode 100644 index 0000000000000000000000000000000000000000..56560d23a7a88dcb4341677b9a93cf270a57b5f1 GIT binary patch literal 1518 zcmbtSOGuPa6h8MN`3TL3qMQgT27=7ye>jhZQZv&`$)Zh6VxyDeV#HJCA$Lf6jj^)OOlP>u5q< z)7@jy(O7akoE(Z(o=ptL!|7Omva+Xtu(ClSM2eilS~-SVSSX@}Kb|70Lxf06ynxoC z&j#>qw3jSspZEj7{g8TU6#EG97@ZW}L0!;Miqin}2#wPv=&N*{CMAADkelD6Ti~~| z_8sV{eCz=|q#1fnFX7SLDIn zwVav``rJXLCaCRDYtickH5{)G)bG#$d*Mz{F}XT|DA+{1%d6J!*<8KF^Zrah_+HO^ z^lR_kb8q_|#or~SlTZ6Iso8HDeeFO literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/d/dumb b/packages/tools/sysutils/fbterm/terminfo/d/dumb new file mode 100644 index 0000000000000000000000000000000000000000..fd4091a9946019db595d9b4ac2a6b935fe42dd20 GIT binary patch literal 308 zcmb1Qlwe?DU}R`w;9y88%}uJYFwjlT&neB#Qvh)lN=hmj7#IT>{{LqHs{4-ySTID; R6bvIS8v{E7F9R140szw?1nB?( literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/h/hurd b/packages/tools/sysutils/fbterm/terminfo/h/hurd new file mode 100644 index 0000000000000000000000000000000000000000..75bd67ca56093acae3ec7d7c787521da7f4036af GIT binary patch literal 1570 zcmbu9O=uHQ5Xa{&rLAHS4}vy|5nTlPVfO8&Nr?1ATUxbkTCG}|9?~{xHf_GTNx$1D zC@P`{1yQ7+mmb86AfCj7;6c22@ZiaV2M?Y+c@m5>v)P8$qD2>G<~RR0JNq(kv$f(N z?1!C@5U&(-+KMg>m@#)}?|F9@ChoCJI+sbt+_{)F6SF`Funq8{gaUhv#bPxSH@&K% z6^kmM5~yM?>;pF(MmmOiJ9I$^xgQ464?_gTVFIaGOhX>#nF??PZXn%;yKo;?U=^OS z{tRBgOL)y(e()R2-zw+Hu}`_63@f9Gsic*>vY=d6uKj1njZbj$TmRVi&L8f3xXIe1O*Cf@ zTaBxw9#53#iYq(>RZs)2u$oY_ni>tNS*b=XaE+mM2JLitt+R}FSr-Z?&?vS@Zxa6+ z3?_z?Xl-b^kwo8z)`O;LDfC`)Op?f;dOwkG%^5_zqd^4CLn%9MC%I5kQ5+Y#;Szei z0Im>jCqxgE8fE=xXVK1~qIppXYd-dV_5t$J!_0^-)Q(ycWmF%+pAl+rrou4b0L}I4Kq|^9*oOT(p{}mJzM-M9(c?)ZB9W1i@$q=vG$$q|CzHuk zDxJ<`ve~IA%gW{Q`RVDInc3O7x%v5pg~i3CrRC)UjcN$ZC_pU+NyiYDn4#y9OP;3W zkxL%APKOiLC3~*dxn83eP7ef)03EkZPO_(A>pVBoj1uujTfuMg9;8Y(SGZZD_pMno NA#ROkQV`FP{{?6H2-^Sv literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/l/linux b/packages/tools/sysutils/fbterm/terminfo/l/linux new file mode 100644 index 0000000000000000000000000000000000000000..c959c318be3f0b3085fcf97e34abd9226c7d9a33 GIT binary patch literal 1788 zcmbtVOK6l=6h8Nk#2DYAlsX6oz2Gb6{`dd?nG7S2uQ5Rl)oL;A5R!57n8`d6lZoav zQ4yt!>Ourvh@jY(b|Zx%lrD<6aMOib7hRNYy6C2>ZVKaf?mv?unihkXobP<+anHT~ zxp#86ip{i*Hc&+*Lxo&va%#@v_RMH$Vze+wB=85Zqef~btZKCxveam%L$nDoB1tP~ z3vH!VQnVW$kCN0$C+R%+=QIe+QIV#p0#>bFqwDmgWw+>#)%WNDJ)&>uDg9vWXY?~Y zru!T!DG`vdyVh4^3eH~mBZ;wzfOYOzs#B({kiVwb2^+aQjJh&VKlL`?_Q zyLc4w)u~rUk17tlL^=gjJy~Ym@8pm2C;5wf zA%B&xmN|Fv%FDM}L%|#sYOk^XuMrC+LMv%4g;Of0#vC;eS7SyEjKkp$1G>Vg6Hq51 ztZPY~4I1QkQ43sMkc9CIKqo`Zft7`&GvG%dha0{Q_ML`w(>kDE1UL+a!OH@o%q)1! z?EZRaJ!p}^D*%j*8=H{uc`?7R^MKL1{UD-;AgAaG(47Yyf!IA5ht0s|eWi{uBmqv8 zBTk3K7^BgaTgt$x5hgxE@KtO1^X>lli!AA`6JFGMcr%uqsuM0{JzT{SG$<49{glET z>&|x!d7TBKg zx^(&S)YSC!%*^cU+*~Cy&mH*!l8Ey8C89W?-5SiB$A49{(w>5W1#a7CY$uIvx3TSZ z?a{b~b6lJ6+I)xaAUc8@I)MJ9A|*f~!ncUUjm5nfZVC6U_cS+Xid!>le7~ahs98sA zT~X~y8~EM-@Ow-8QJq`w+5^H8DQ|%}_QpE8NEE{Jvl8#f9)5-({GK#^dmL{ rZo(V$Fzq#3Y?=5>fYz-oTPTb-PjcT}aw7K-S>5R?Kss7iIA8-3yiki-bxsO-k5DWVr77lQTW1Qd=XE?_NE?K|AHEwW+`?&YP%;*!_tw%gb-!oqDO855f z)VryE7}xIP_W37YuOD^@J6I$O#MyP4X{R>jG&4@kLoXwbZ*B)J$rGPUG$?5;lSZ=I zrHo``U*O}|L5|GAUMi9bStcd2LRQHdStn((!CsHdkU26>SPxh?SCAX}48-u{A5-`> RdQM9E&SLWXkpwptd;|L>F=+q* literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/m/mach-bold b/packages/tools/sysutils/fbterm/terminfo/m/mach-bold new file mode 100644 index 0000000000000000000000000000000000000000..1b72fcc0a3fcb61ebe24ca13379a65248d56c42d GIT binary patch literal 652 zcmaKoyGz4R7{yOj&?@4rS%MI8P-w*mMG$L6f;L#|qn0|@Hjzf!q_kB*M8Uzq!NI}7 z!9mc$!NJwl)z#Hi#KHd{o_mcEhkD`n<$ULRaC7@Y;|QY_H~2&)Un~t5+_HIKP^k&m zsk>!M-Lo4dRoJTS)EidbRNXCg$1$y1*>)@-1bIS8p##0}JfMZq^V-mkE~$E;qMvF& zW`m4FQblC+yivq_CFVSD3JK`aF?>Ib%%2X?wLxdocMJS(1s&UPP{S_vafoA_;1p*# z#|7(`xWYAVap(8m2Qy-0v-5yQ+4qEJyimRVJM|V+-viZbb94WLuh$Kw2qm{b=80x& z)u?7pYSj_V)X_;x=bJ0J1c?)aj8zz-B1{B9rV)|;h9r)d$H)wn#T3bsC6Xq~WQDAf tHIgCg?A6IMnI&_C^&IQL4dew48d7lcw@Cg7F(*sn%2LGnA7Lh0d;yFWK7s%M literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/m/mach-color b/packages/tools/sysutils/fbterm/terminfo/m/mach-color new file mode 100644 index 0000000000000000000000000000000000000000..0e63d81081fa72c13e5f8112a14756ccee099d8f GIT binary patch literal 1095 zcmdUuKP&@r9L3)WX-lMYb-74RI*|0Alr)i6MT(YcQBn)7q)qxSB_tvw27|$1Fc=I5 zgTY`h7_3&S)oK+nNY1;jx(*c`4C0c{>$~@Uzu$fDlJ+Pr*kDINaVVvgY<1QxmF`fC9M`Bw&RD`Zt#qA?84vwC%8d|sRt?JcsQFJnj@;~9sL`ay#$zX}%F~n=gkRbt6{DyNI;+4=V zK@59LhRGdx_8Io(G%{?Qff%0rX<}c-*e8`S azL+rI$;KN#J>v@m{W7ReDr01S-F*O7b=5Th literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/m/mach-gnu b/packages/tools/sysutils/fbterm/terminfo/m/mach-gnu new file mode 100644 index 0000000000000000000000000000000000000000..c7174da0978008f3606307e113fec46cbd75df5f GIT binary patch literal 1056 zcmd6mJxmi}9LAqlO)45SVUt@-`&tK_<@UeXlJI35lbZJkS09AMgKt?{Zfnicy4v zI4-`4c&xkM)0Y^Tti95DD$D>7P?taihj9|N4IH4`_93`%6eq|faKpp9q4H()0A-<4 z#kO68kfJcXnQB8jV(29es=RHdFp(uWSzgnaVdgvA3@S|g`6-k_SOX6h={LbX!Ys5VMY3Q=

      @fM;-^TD=OdUMbTlE1+8v zO`^}ivfZqY=y$SyqUm5c(Qq(84C+>#|Fir2nRA|wv!mW0UGCUI?{?ot|LcL%H&<_c yxV;wtm{=a1N~VX>!|6Mnsm~*CN0-JvjlY@Ly1RMr*W~y6FQ#^QKEAi8QIEfog)~I~ literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/m/mach-gnu-color b/packages/tools/sysutils/fbterm/terminfo/m/mach-gnu-color new file mode 100644 index 0000000000000000000000000000000000000000..ffa47e14bd7b842fb90f672c7fc1bead84b732c6 GIT binary patch literal 1318 zcmd6nJxo(k7>3_tOhAlraFRMSF?T8@?QQFYTqD%_Q|J5?%Ls2CLo|5fezGS zE$lx$wPc$}?&_}XV-nI)E zEm3*fb2!h;g;Mq+$19bJtGI^ixQSc1jXSuD2Y8GpcuIc)ukadEm@d`6sjMmYtsZCS zf52ya#T6=a z6kkLQR>75oE53``Noi><@7H>_&!eg3b*(pwI;NuhdAQ;cDok}yF)Ea0@XMgf&?JLV z2|-D!=>dXI&UEGK%4y}i4QCmfsm*Y;vu*o9Y7f;(by0h%ebj!co06@flw7@q+D6fj z(=Q)yD^YDLkEtM52JYfy22kxPj<*&>%KxW|n_ko=puKy@wlzeX~8D#Qnax{%@&!>Gj9nAAgpa$v)3b zTI2cRiQ+(U@JQk1(4*lOBNHbdp87HR{q(1?cV}*l|Kj<0Z*jl;mI1>Is=E%Tv&&l# GmgqM-!wb&< literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/p/pcansi b/packages/tools/sysutils/fbterm/terminfo/p/pcansi new file mode 100644 index 0000000000000000000000000000000000000000..b24fba9358f5bbe4e55b1916dce62baae9c63cf1 GIT binary patch literal 1198 zcmb1QG+|I<5Man;3}Y-vPRuLLtjSEu)h$R?C`m2K&CE;8Q79i5 zkwiO@*f2E+x)&@v5vpb?l%9!K4?;I7thqol=QDf-l0R^m{tJgVDYlFpwU&$n=T|32 zA4ciuCRP6rYm($QW(${UD5v}&emfuU-OwQ7NpYKjL?zzK*!v5kLR{ literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/r/rxvt b/packages/tools/sysutils/fbterm/terminfo/r/rxvt new file mode 100644 index 0000000000000000000000000000000000000000..12d9e9b4390b5941d7a67288bc7637dfeacfb9f2 GIT binary patch literal 2078 zcmbVNOKcoP5UrjL;E-UOPXJ{=S|Af_#Al{wW?y8>ct?EhIPVF?SzSH&P#l|W_qEW0@re_P~M6t3^E;Oq3M8`QZ88 zWxi3YbP_52*a#03c7j(usX=O?`zgA?(?YxG55$Qq+CW=qD?N;rJO*t@dnrf#Gz30O zF9FA7h6%wbnxQH+gs%y{N^j6xVDHeobPE1MIzyk(dFlI{E{gw|eucj*Jc@pUCly5- zU{SPDwW%%2Ru8F1)f38B8P%oss6O=NVMA&}y)3#YDyX8GYVsRwsTnG%hFXK_b#+pm zf(lyUee?BP+jI6`>aHEb{M`Q> zcl|v7rG26K&QJB1O?F9tqi>@-$R2g3oto!NWSyFECh7?IlYpE(YWm=xgRyU_dau%W zK#p!lC{P%tH!7R)djmr=qprU$JgheY2@z)rGvAS6j1SSS2qiSUAi^sf`1L?S$1 z2(q{n3zD6LvKQGKwu%jNs&Y{N!`|a0xvq;$pi)RZr?y$u36zEF$jft`E~l1s8d=ZD zGBuz}SfOzA=;Y+g zOsP~ZS1Pl!)oQIaH&?IE&o>$i3yX_OOUuhEE60uw-ZAJ+mr8%}I~8P>jyOD&~SoO+sT*LSFLn`{pGt zFE4*>5={_=QnX?9{mWJN-vK3S{G&KJW3rX~}~p~U&w`O?B_ zqJMpe&|8E03HLP zs3bf?bF@Hp(VN0=(`9-O>I3?at|DHi8}vDC%iJBhEAbcl4e_4nDEb{ysVI6Hh@xF; zkJ_&eslzI%UQvO1Rh?2@>I~-kfC2TU8Wmp@jjJg&+t9r7pRZ6Yt1Y-Lt1Id%;-qtojD(u8h6|f8WUe(1^UxkJeAt&(^QjJ&W`X-K6*G1NueXqK|1;r}c5& zq4T;|59nb%rl)kMYkEy@>38(I`ilNYf2^;2;ZK9|_K4|5JOglSxK2Nm@q#?AeRms+nj={hu#AFTc8dgI|}kV9vWfKu=d2@1)@{J8R4vOE3MzXQsuMv1>aaQ{6Hdl?hD>TGQ3^{%6JkFBqvG9S>$XuDh|x0 z%ES3DXOD~Ix-Ke#R-yJ>+D2PT=nFTJAJ28#oNC&s=R7CJ(m)2W^qi{iY+#&;#{p!@ z$yM0a>eP2Tlg&^wb7c3~A*2bO_FV2Q@Yip8m^>FK$-aybkumHGLFg=%$iu~u7J zs@Ip7S5{V6*Vfk8FJ8QKX=7t^bBilEOm?!vKI%ep;S2nT(j~tIO1hI}m0`j;M$#-& zOcQ{SE*kL}>57pC8R?>tF8c9)(m`MRe(aZ9n1J{4yisN&>l_$9|t*5EC$a{A0xVlX!WOF5xSvXb-i}`||OM|F;mn zRXeE(`F;3$9ijy0lk^g~6u_lv2YS z6;RVcCxB`e_>C+gGVoFs)_^*&0@SE|h)%mSG(dw{dfladm&%>Jj1*Iv$~|2JkYMO@ aZ?FbK5B4!I9PGoWXsA5y0X~%{4E+gKyCb>) literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/r/rxvt-m b/packages/tools/sysutils/fbterm/terminfo/r/rxvt-m new file mode 120000 index 000000000..f61abac26 --- /dev/null +++ b/packages/tools/sysutils/fbterm/terminfo/r/rxvt-m @@ -0,0 +1 @@ +rxvt-basic \ No newline at end of file diff --git a/packages/tools/sysutils/fbterm/terminfo/r/rxvt-unicode b/packages/tools/sysutils/fbterm/terminfo/r/rxvt-unicode new file mode 100644 index 0000000000000000000000000000000000000000..9b54df424c3844df356949076b84e8bcbb2db8a3 GIT binary patch literal 2508 zcmb_eO>9(E6h8O8j;I8qqCptJqFm&kdH*v!XelkFVE@trjueoVDg9w)I!vd3v_-=L z5@kV5Ow>dc8WT2{5TjAz!oP(J+?bfSV(ZSIn3%9I&+nW!g#sl8 z=T6=V<9+$D$RaYRhMuMs^gOMl4NyF4rWR_YZtw%t z2RuQ;RG~?l0Y6LU=uNr^7Dew0UZM}_GF_q1=o)ztJD`m&9yQwu&Mj z#!njU4p@Wu&8k&(sjNDxa%xzW)VP{aXVrQ1U4UIwZ>#qtE{ZOx57b9h9*=Y{URGDt zHTA8!u6|NC)Gz9Hb+ejb7!MhXjVOBDSPG1yJ;pxcfRQy08Aptdpc}%JZ-*io-;3)Z_Vpnc$WXBzVm?NzHeSOub7{jUm))r$z5CXM$Mgb z|9Y3ty?-vC-I?|8-p%S5f7dKd#L>$WD-){|I5`>$p)T1vSBBsW09ukg z_CB;P!MLqP?YT|kgcf=fQVXo!_VT!HAeNmMcMwh^tRWUd+he5@)<(%AcDRU=>r(K% z0>EOZw^D9~gItDyB>|V2EHjIoU2qC3bUmv} z03;Ro^&khlC>|qpLO1k6Kg@)_A6ltYiopW78N7{*y%V{u^cv7P1K?$(j{+=B1=vaJf9_rukKqNC3irQSLclr(l$qU1)}iEgmll5);Yq% zN*9kPWd9uDa~XoU3?AS(+IVvwXk*eytJX)3k^xtQEU{jfd|e4G9coY;)Qzd7OOBp_ zAH=>3>cunwP3y4085vzcf#`l5wGJuSLXSwvr#p1|FsdVa8xjZ^rsf>+{k55cYPEJjoK0Q4>Gc!AT=FH}XExR^0ZfZ*H9&8@s zx;_M}54iB^gFK<(!|LESk&|`SfXRubnOO`0gUyhG`Aj?p-bh<&z?KYK&eWFUwWS7Z zsR1V*SldH@toMp@ll6&&*9!Vhx@EzZm{&+JGCj zaTh)y@H|E9=sMa2>iaQzl9ti4v>IOp8!1H|ZKFDB#Fs%EbgP3l5gw-)GFl}Q7Ay~hW9#3y{l7ktGge$b&xM7hZ2 z4vbnlJ1aUwuNWe_A*Mu%{PK<&w`Ar%=>zddJQf?`8}a6j zI(zl+ly7!y-|1XI#3LO$GTZC_9d|qW{?kr_yWHp6F6aGCkH+$QPC8N!B{+f-?1K_i zqiRZ5$GvLGP{-4hFsDemmEa|EJ!I?)in_6vE699?D^7n4nqx&|6d~?_;+Ls7X+N1C z6{M~NiO%BFHOs@521gc?o5_@60+qxG7Fo!vSS*GdH!P~6Z&;&Isuwp&&2=b&b~4_~ z&^fwHc7<$!GP;X0LESC2S*nNC&?HMF33O7fi6gEL&?y3K6!`SG(jt9CIS-|aQ1*-W zlHlJ0`UZBUbqjj8fR~oVw5koXbXXox)8ga}7j>Z-ikn-@D{87wO*N?*udaF-bwbld zgV3_kBy`(o5xQ)25gMvD!Sg(7rb3;lRJ~BTQHI*uy1M%Mh6YU=9SwyhC#R+&k!W;! zIu?t^6NzMUW+s)IolU3b<}#W2`GtkW#iga?gWDf8 zB#d?;h&PvVaj83WaX)dZsbxNf+a6yzJU3iF8+Pb0Y!AzmZ6;9gM+A|d-*7w oILW(`@giZg4da4_;Xw>Fqf0}V3I7}hG{iy%Vq-d)iCEacFLbXL5&!@I literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/s/screen-256color b/packages/tools/sysutils/fbterm/terminfo/s/screen-256color new file mode 100644 index 0000000000000000000000000000000000000000..6a9d9696abb51af8fa79a9ef83579028fbe64323 GIT binary patch literal 1912 zcmcgtOKcle6g|&WZ9%0KNC@bl5`-SKO5M)aA6%NYPN-?)acB~$jRi{TII&|paUG}m zrxLJ0NJt0}P*GJ#h#d=9u|i_O0+2pUIBT^uKI3WGS$D343TS22kh%o%kaO)O!J{0+Qi zGVkC$d_;BwH}M($7x)Ta;~S%OI^TBvcl6(P`49BBy1di*5kKK){DRx~6~EyQ{^T9) zQTtS<^9b!Rbx=J`FW0l`d3C(Yqf9R*slA}GYFLevy{2YWlYVu_h}TW#ed34ey81-j zRKJto*-;nG{s;4^*xf6g=!rzh?#SF-|KIUkEc~BV8oSSRF5Tz2f77GO-8E-opU14? z1oq%zSVdjcO-D~>bko(-EhfBKLe46lqdQL%-&2&sLsCH-aDzHu3y$$CCaREUVdYJ# zP8^}-v7Z<;2#&yjWBX~TbS3hIC53q=Z16p|iVXo%D6{wiuF+keRovkbo2g-3BYIn~ z3TJ4tnCnRN3he@Ilo=;rrsyOMrVOS9UE6R&357xC5)w&$fp<|j&0xT(TPKaLSTDjF zA~pSzwG7E`6Ye0&oZ2SC+eD@|#hf)FoVsLg(6;OJZon?2U?rusGNY{rbTgsb8AoS? zI;37iT~a@y9%(Y7K4}oqfYjBQhKx(=_I_PHpfj*?co6;lM~}wi$BxuvY;JBzcP3yRJ`=Uy zm)Mo|7hS_0d0xD9#!t&%X*y%}zMk6DCv@90JrTSt(k7rD*VDS}r7}S#s>;X| z(XDrf`}Y{`*gfO@p7D5qNB<$7(qEd>Urzd6f1juS^i2Y1+szj4-I72G8-U zbR0g?{1#-9Lx?d0eW znDqpFfj}T3kR*g+B8DP{B8DP{6oFY Ssg94JHszvr*`cwn2R#bM70bs+Ddih>`EP=iYPQ zXRc@798oC@;4rG{Mr66vE|;4zH<2tY)tB0_*;0AyTre3OH~HvlwNr^wj2d-0I@6qs z4rNCGWq#sF3<@*Xttb@7a4#N3_YN0S_bRXt`&scAjzZ&@sf*z>&R`hl8Rc<__zI>m zk42+4(ZUKg$X~~sCi6Dl#fN0qa2=n~e}S*?HNG)gxBG3+e@Fj)kN-gbV~=;cKjCNm zf?sh1zu|Y>#9zFl1L~mab|0iYtd6KB=;eA!J)=(cc$n$O6t(A6R*kAjvRBoDYSFLn z8S$FQyhr>%eXKrF*VP~7H}}+qv;WC_I&%9;r}`pMvU@VO*Z+4s7YY8Sl_u_TolAE) z?%(uiwzuYd*+V>VNxxJr!gz$y&UWHHx~=w;dk+Bh>#f|;U|GMF})5p-?C4J8zYnM+C}^#$HV z;Vgqer*54#zG6KOYlPJFOV%*x20M z+S=aUk?u^vdUhymzbCOP?Jv59JMz55GrpIRztVKZ?0qx6txxGr-1I<~#ceuClgpTZ zdQ8vhay;!P{IJTGDZ*Rt4fpOa+_C${dwt_^50Cz%Jf*)hr@x%^`)-}5|MX1)XWP#f z9^~`+5FWwfcoI+Z3w076GW-@~kwbt9Oqs7h9c`>(2XEjlyo2}g5w77==^RaVT*BFl zIA`PH1SZoMu`zC=Hk^$McmfH5q(F)gh=~}87>F2%7*HGuh8gDydE)2`6RaY#j2LEE fNY2U&FN#W}N~B7pN~AhDhT4pa+N?ukUCG7YH|dMy literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/s/screen-bce b/packages/tools/sysutils/fbterm/terminfo/s/screen-bce new file mode 100644 index 0000000000000000000000000000000000000000..3956c55cb889fe0bdc9ca40fbdc78bdf266c915a GIT binary patch literal 1590 zcmchXJxo(k7>3_dh@wIKNi@n$w28S>rO?tJYbhXzn&{%< zqKU?6SX^D4oJ<@XjEjSVlY@hUlZgp&FtNVhxy49uLgP)p_j|sdb576c?Wt8^)MF!3 zYA!GtFC-GVhLLz;{_H@|wydVMll{kogKlH97o1KNic`axU@=k1rgDUtR52N3FQD{C z96_s)ett!Mu@6<)j?y2VDjep3N~~eW4(x=9I^EZRL#!M@7o#4Wqh7!e#xS9)Ipi^g zIr1&s)|orFiwF2odW;1;Vdg2G;W=LDTB-E1>|fEpF7q4uw`DGs-r+qy;3GcaGrnLE z-?^i;s#=vwn`v8Bt=dH|&u+CxHI>=VEY~n=`&EbPR%b{T)ws&j&#oA8Q)li`@2iLE zky=n+$%`xc{Mo-T-xBzJr31?%sdTK!{NDfXxHE9_Kdm&d%5~1Ia@^mX(MWmCu|Pgx z#LiK3WfIsG%&y7HPFDFCv|eM4nJs$kkz%|9K;p7150{iznjfy5q5n->}YNsv9?` z?sXWw?KD};u_Zc1J5B3n#ttzPv%^|jv_?c7OS48w?-AyjC6fML?xMGiL93lH4r!k> z4#GG})aNB@Y3Nx3egi*qcnP|fK&IBsoYeq=WGXc=kxpka*=#O%=~6y_`EsE!Iaw@DO-)bF%v`xLJ3BXb_3HfmwQJYqbk4)r z+wLE~C$S^PA9FO@^1ir{s27o+Qug8MZA;{pse;$>8f-$NzLDkjt^9Sz0TryRLp9%l oE!c)y-nU$hCWGT>8^kdSg9A9zf}OV literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/s/screen-s b/packages/tools/sysutils/fbterm/terminfo/s/screen-s new file mode 100644 index 0000000000000000000000000000000000000000..f0be9b1a387431faca9eab48d8bed0087b7f7a13 GIT binary patch literal 1612 zcmchXO=uHA6vzJ)rGB7RL_}SbAS^2VaCft58iK}F#cHipTctLNjcwYb`DmJK+S*pd zgCK$zFCG*@1o7&{lP5v&;6c22@ZiaV2M?YELDv79O)aIKR2=gD@Auxknc1D$%y!j* zCNv_aZicGEl}x78Qk_57AGR%PU&qP5W8r~FYnvOM%2m8tx)AmQl>;{{%lUeR9Dq`jekTjzK5@9XUQ zAMg>M@EKq572og!E7Tg*s5UF#-$vV^cB$R;(wfvh6{~ZQS*l6)b*gUFuP%~C)r6X% zzp-q@ZJoJKeW)I($LfjtPX3|%WtB32DCGNxXp8OWl1TC=mt_{K|0VT>&i|*CF8$#; zBY!yVZ+59zUvn}v7cx?VScUa4QfAI9+vZ5ZEIZ~%g^9=*rOQYir|YJPUsBYCwNgP# zI?)3E798Vdb(AF^g3+T>1?njpqf5pGY#>I96k8-|TW(y+9f@3_m{3HAMP30$swkoh zWhz(1(fy9gDn8}~7<(;dPw=0{q1RyacG6@~$Cl_c?F_At89T~M%8qGm*BTdfEX^7z zy@#1=lSt}&`8K^B43c)iIG}yj*bn0fQSY0qrJ-j5_yj@b-~yaj0GV1BbJhSj^{{?N z%PP=2QEo&#jF@b(%xIZOv)pES3ENBv+QdkJ4$%!TLW~9I5~Be|iH?~l%DA}cZ7?&9 zW&%bR*6={k)YRPE($d;$SwlnV^yui=ST>u>jgRN^g+j4dDosq3%afCpO10{Fwc6Cw z^z_Wkl`FHeb93|aSFc`^4H|^8r!zPKS7Jv_AmwPb<b-&`WMPFTUK zxd9u|s&8kxiC6x*@4(&$KI%Gt3Y)M6+j;kLIhu?fM#lh-S{UfZ*>)VU&}Si^c96ep K(;~9^ z`Xi2@RcQX>7jXm2unG0wJj>9*5sR^e9h`gD zW2lj@u4KPliErz&o;GP?QXE2nXeJn_NXq^qfV19s9{y2pIR{Dn$Fyz-c|S2 z1NBIKA%9)a=gZNu_H+=GXpz$K8SB|7oTEKV0YRACCK*GrHJVb0|;> z7>RROid8TYX4Wj(=B1cfa?DF*Cfs34w~;tXcZ?=}UQ;(#NC&Om3FrB@;21BXqYSwV zMz2ogsV8W?SWOKVD7HwuZFy1YbR_bGB0{bX3;f?3iGql3lvz9xN7o&XUHpbSEv9;K zmFixB5kEka#T;9rleAN`K4$DNGYLDQwM}bO)Uh;cq{I(0*D8_p$GMAmCxdo7Z|v7T zW9)-*h^Ws?*3!^B2mA(preh9z=0K*_&79Q-PMy*lw5&Y66Xq$j!HCGw%8ZuTZkAfj zYRoocf;Q3h(II+1y2OZ&9x?1=nCO_Xf{crr)zxNtjTwW{jpb-=-nFZxB^0u(!NFv5 zXlQsilgVaBMsm4)zECI@M@LJg%a_aLN~KyI8yg>=n3$ZLnyS^Nr)OqnXRpZVoP)9B zfPeg+#Eu+)!qIHY`{G7pUQ~Wc*@vsQEs@utMZAxfU@b!WN|x()@y|OBSj5_LtmHee o9vjib`?xIa|kxM!F0fG?}-~a#s literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/s/sun b/packages/tools/sysutils/fbterm/terminfo/s/sun new file mode 100644 index 0000000000000000000000000000000000000000..52a27310747325b14902b2874b80ab99b933e2e1 GIT binary patch literal 1004 zcmb_aJ1+!L7(Ey9ek3{+2DuTD;Lc!oZNxkA+90B$kzK`NXO5tI&gZvDu$66xfj=b!q) zPR6$u+~k0D>>cj;!FG`LTr26hzPG;v2=Fl^u!?-Xn*dZ$%;&36je5?S(aGG!v4>(W zp&x@>Yi;py5Dh2eAy55M&S8OiiLk#yy!Nfxz!s9&#Q{!mjtgAk3fH)y`7PlN_jm}k zkKcES9TZkicqY{g;kB&#tzhy_`3Kh(qHs@DQB^o8l{b`7xBlq0ac%wRmfBXn*DD78 zbie%O|Co%3F;RmiG@@g3iLgkJX_-|r6_;6CrsnAvtEJ`)VT!OyNDv~Kub>l+Ny0K| z&xxlAwmp2N$#IzM5ksSfB8H-dVoc7EA!W#BQfA9AUzp{+;ea=N`C`l394Fc#C)yMz y%ar)^mX6IKIiWjQN9JS@kH~lib=0<1=!H$F7=Kp9*u07v^G^68u2ev`6va=T6j7=G literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/v/vt100 b/packages/tools/sysutils/fbterm/terminfo/v/vt100 new file mode 100644 index 0000000000000000000000000000000000000000..1a7176ddb41bc387d498c54de47c3b3a02f6c95c GIT binary patch literal 1194 zcmdT?O=}ZT6umDN8by;;Ksz8o^0Wm%W|A3GO-yL(BB-^sx{F9dCZEm6B$<4*X~C^q zaqH5hxDZhk6ciK`bm78<3l}b2xO6GR^WIF_1pNa(a?U;XynFAPd6OA-l8)0f`PeZ} z$JSJJAo*0LIxutDpiF|Z-7^`plc{BMX0TH-bM-kQCV%8CBv?$C9^ z9-5*6&EU+_(vQ*=x(c->vm4->QaL>)<*7cF4~IRvO?TkjrF*V_pB_w9IGw}c!!h@f zs~^)-dO@$~4ZWie^oc&x7y9b%eRJb?H~yfX^b7hoKx~S6*=X`)Jm~rXb`msw*vq0_ICe2b;L7G zhe%2D61OyN#<&&cW)nuF07@z8OQE=-CZI2e;t>&djfs{N$`W)y^x&VTq?bbRu&7>; z(FbKzT}vB@=wCv296!pdez$y7 zt0>~Rl3G!@KvrG@!axMj;mcdV0ggbYBhc;$F+(kZbU_9vfnkvfNEc)XiWWihMN;NT ziHb{EmbZgWo)iaIXZe8JF^$JW9){E%iLHp-iaNQDErZ9ZqU;>EeLUyqG3Q=Vv>&h3 z09pXP*op$4&a(QE;QmIyJwR+vM8jWVN)w1n&yVL1*d%b>tb8~BJFxcMS Y*};3@i6!I4W*3z?6_b`>XwEnP1GPOry8r+H literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/v/vt102 b/packages/tools/sysutils/fbterm/terminfo/v/vt102 new file mode 100644 index 0000000000000000000000000000000000000000..b9a393c517681ca17195bd40dafd638daad2ec0d GIT binary patch literal 1188 zcmdT?&ubGw6n?V`wFMIql#+!ak`bk#+0Dj8k|wkj3AQn@>M0&tOp~~>K!ISw+#4)MM`)b-G7cdVX>^!QPyln!OFv5UbPZ}jRyV=7 zfdZ9fZBv!nQuX^gGT)_pbRX&gJ(Tq$dQ4B$3hx}jPvJb<<33mV1-+uT^qxM_XZlLt z=?DF!U#j<8|_(A8)sN@YDrugpQJ)=PTSXcp=UmlNahR z!X;2z&tDBDBB3PoTrd$9d1(B%C5>fC8WVf)<>~p^V8Rrur&Z2DXUGSRRFq{5gjI$e z9aKYMd5#~=ieK%qY*DFVkmtpT*%_b<;G}E^xDG4;HvkuC0xbX&vTfipFbhm$V#=^} z@w6$UtWS|sGyoF_0~UOFH#oo(*y#yu_k@@cS^-&tBA_IOg>8@}C?Y6Y2F38MG18;r zsxtD060nSC<<8IvGaZ#I)mM75)%U0B@Ewmy$UJ=VKao5L}{XFj7Nt#CSN;RMX z;D5|IK$R93mzIjfQfYN{ZOyhTm1=c;-EnHQdcDzb-Db1ZYPUO`Zg*p2bFN>4R$OeFY6yaWO)p_6|uF-nK1fdXC!;E5#F(Ftm#)1)}xLKmqWtc#-_ zU_We-u5mm@x9ASDAV{&#(L5Dtg|_Gc$B*e5y`Yy>%{%x{u+OkB)!bM3Z&e-y-{}Ya zq+cXO5F8Xo#c|O9b_#X|c1~On7Q9~Js*l2Vh;GqWjVsk4xPo{{+!VLPG?*t=#Xb0k zRn=4RTx^5yRO46huf-ejR=gJhxRkqnYJJ^aJ|a7q_wHqCm6zqvUzM@HGPQfg|5LA3 zPsk~mlMB43B-iDZyuYvgwcY*|J=$mACvscv$Pcofj**d2IptX@6;qzAQUxTOX~2My z7=*hD)4oPDKu5F!uhU5M!n$FjuwgRJo6YTZCwMpyur#T7Q1l8FG9cGoO%+#OtMX%( zifL+tx)thzhAY%ko}e|}+dbzx@v8ktkJ7C18wdg79i6(5GpUv}gIl*JM yE1aii^B^6TJGRz1tZ`Ul>BokLhNqaq)g)Ty0dbXxnU?Li;nql7bYcprDf$iDv1{i5 literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/v/vt52 b/packages/tools/sysutils/fbterm/terminfo/v/vt52 new file mode 100644 index 0000000000000000000000000000000000000000..8137caf32e744fd9382e7727743b6c73b9bf6e99 GIT binary patch literal 470 zcma)&%L@Tf6vn?nVe;6@+1Omv)PzVW$@^7OvapoL2r(X6`7ivz*S%wIO={vUzVkch zeBWK1w3a{?LA%ac?eO&97-Y&Ly+loMWJPfq>J;a zhd&dgHQ$YL)IE-dht>YOwp>rwt%Dz#@sIuY|FWN8>ZWEs={drPg9bDLjUjcx>>|r$ za?D^WW|tI#TEYhEfZCuYs0ZqcGt04>#dYYQp*Xg&GY^I3c57MZqkX#A*X!+uH$-?8 AfB*mh literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/w/wsvt25 b/packages/tools/sysutils/fbterm/terminfo/w/wsvt25 new file mode 100644 index 0000000000000000000000000000000000000000..0ce5b567450ea46294a8c46ba8477043c64761f9 GIT binary patch literal 1597 zcmb7DO=uHQ5T5r`{6kQohz&wSpV(7&-|i-@sixKztF~Hf(P9)^o3u@vq}ybZRGSK3 z>Pb9!P%nyz2Yb+i2%;bq1TT8<;Mt1@_2R*kr*&p_Qz%NMkIa1E%zSTlciv00h`|Ba z4mt5%*2+~+JN469uXCU)S}TuE7t7IHF{+(tK3B{}ySk4>&kbsAL<`fIEP&u2@Ddo{ z5|m_QphQ1xg5BWrS{GsvZGsMvm;vDz#(YI>T!%tUq#OTpfl9 zC@}N=5@QYOa03?LHr(a-0X&AM@I2HkA$~yniuNtc{XqN~a^L?2zrlwMVyoC8c8NV= zpJ)*=VGG}HLpv-w#c@Phr$Rh~I3Ui8bQlL!-@lCU6)`0|F^_CP+!pr`ABCz#@l3ox z{wj>$Aifn#;+=Rec1quGLi^X+wVXdG`L z+Dx7s_bwf0$lksDzfMA9m!TvKI| z%GD}U!h|)Bt|yW{iEs*yaD}J`wvYlXrJX$fZJ10T978*b){oW)k%Pwmc6|i7Q$S~u zvq_d9#?B_j&mTg0=l*t^Oq;pGKEb|~eH(dgkmoe->B1;Z zDb@#{?T(q?j%hRt&4x%f*7@6L98CHegx-WR9SzdkAk>;m)RhTMG>2xBbI^@Kq!l6w zh@h5Q8Y-pSxbl*wN)pvb?SR@yoq(FkwNxGBgi01j)}}l>B9+Byt7LFeJ+K*uhet-n z#>U4dC#R@MGu3n#?zfN;VCFo#N2|Sb* zntCuh9vxH7W8@iYp0^G-&rkCxEj|;A=WDUX3eJQsAznbdqM5Tu<3)OsN+%6dTecHV Uw606d8UO8@`> literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/w/wsvt25m b/packages/tools/sysutils/fbterm/terminfo/w/wsvt25m new file mode 100644 index 0000000000000000000000000000000000000000..b016cd09fcbb106507e0702a98731f3e3b52ef9b GIT binary patch literal 1607 zcmb7DO=uHQ5T5r`{6kPdM1!zmpV(7&-|jX|Q;qfq>rb_)Xfa9~P12-I(rvPB)TV-$ zdJ+#F)QckG!5;J=f+z@r;6)D}JbUq=UOag6w9d?Kgi=wuWWMj4neV;bowwO8x?neK zgp&9s8}%7qyOrj#yx()O&uG*yPFCwiscLA~D3_{vqp!c$IDJZM)2K}5@{2t>A#@DF!9r;J3gWxCpf&f;D z^ye6;nnj7+#yesc7YyINg{*^si=DrK^xqK-<$dAih_pfJIZts))ELXz@ zh-Fksd6vqhl&4j$h6Q^JVIY<{jC2Hpc#&xU){z4vt=%&IZCDhMdNB@Q3}FmHY>(O2 zt@ojJD+m^WL$(Ad28R^ie;DmOZQTypD=3kiGJ z%er)x3LIAwOYOI`_t1iGmXZjOP4QSxiUN3Y|hPHr8%S% zbg=0J9!fh+J)9knj-}=?@{BdlTZfwGr+Jh%pNY-$wb^5bXF?w#et`Ii=1!pOsM4KO bCS_XMcHE9cXYxEwBtt=;lg&dTseApNhq%MUD-qAj%Baw!y65~^LGbX!UOqxv3sNtHCq0&I_sKMD?rQ5nY`$juFZw5!Z`#Q@rO1;D7&Y>*>M9O@b zU>Ia$?8{NM+vt3{j4EgOoKFjp;m~==xSX!U3~rzsk(r|<)Qo*-k-n|Hh!wAS1L7nqP|F9rl;$fdbW=Ae7#t= z=yttMmvpZl(mVCt`hNY0-lw0}2lT7@kbYku)t~Aw^>_N1{!Jg(Cv}Z8$(ib0;keE$ zCvfIE^-hzs%vs}fI^E7zXS;KkbD#5&^SCp9uIKWea`rn1o!6WwP5C}E`8q-C8 z33w?Qv(38Yv?(1L=>mir(ei#&#-j+s^UKEF1ZNRiy#y0K;z%1>3#G5C14q38k0I~X zg*lde_CmI@Y-OqtvSp^)f!;T9OBXq2x|U&t48G~%o9ukF>6&?7UEQ1o$inQ>#jE;Z z1xbhrqAftAneGGzyD8m@nyoxL-(znX+H$lNhd|`>o^v>Ly6}mY(_ABF@2b! zn4a4oxTEkh;)gIJF*7i;Zi3xvqzPDv#k78XXXl0u8#i`$Z{FO~Q!e-R_VsPq(%-*z z>%hR^;Ly?N_(j-_@iwPRb`97r#d2xl$lgi+hXQCm2$ z9143$AhiRj9Z2oK);6n$+QM1OIbqb6)kP7zCc>f3OG2p~O6}0p<`)jmB;H3|?8kk8 zJXVztFt;F=ggJif13rnKyVKj{&Uc4Gw`9D)c(L_D<9XJLjTea5WsYMp{9mdBJR#qp zIgRFF0;b%ZlF4vOZC)9t+a~PQ5W^l0Bxr|v={f3 z$8bw|kzS%#=`A`;N9bevg1(_2>1X9`$TuWnQUZb$RfLd-C|&hz|Q0{IEA&>-w$fd83wkqsd1OW2>W6{1;3V+C@0@Dk@k zWuFCmY=cBz(PMAjKwiF~P$U!!WrPBGVT3}FP%M-Y3ixH>C81Cx6bogTe0#uUO1^zO z?UOV%rGQ^Ts3H^z#X=dTSgOQQC6+3&REecZBq@=kM3NFoN>m+)Uu+miC=!Z=GD7@s zgp@!i6pDmmp-es1cTmSlS~Nh525E6XErYb8L@NfVr(sdR5HdszF+&DW;KpKs#R7{3 z77Gv;7aE`dApxNQAp)T`wzfb8LIpwvLIpx?;t`v8#3mlGiAQYW5u0yb2?YoV2n`4k z2({3`DiA6VDiA6VYTNQvP=Qc^P=Qc^P?tAxUm#QV!Z literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-256color b/packages/tools/sysutils/fbterm/terminfo/x/xterm-256color new file mode 100644 index 0000000000000000000000000000000000000000..dbef19eab8be3a579a13f5bd03b5550370563fe2 GIT binary patch literal 3430 zcmb_eduW_h7C(3Hm#wuH(c*K^jjP|PwYKv;XQp56w3}3uwwcK`jg1|Htx1}uc{Y=p zv`O0TZn5egx(h3=;41Edva8?;lj)!8P~F5>&*lT%s#h1Ni_{Y3tDIV?8r51=gx-d>NnNeBsvb1}yQ0R`zFM5*`Z*p{e^s}uf2sS_ zL+VL&SRGNX+lY77hw2m9pR4bT=fu>))S0Pt>YP-4YC2V|?nj&b{JGY<9@gWgcPRC2 z%{x1itrt>9j-$*SH@Ek)iFvaY`EKf?)aR!64e$r+cl2!30)2`;L!YZ%y+j8((G7Z? zZqsGmrTcY7@6mtKH|SgRZTc>KuYN#3q7Uik^b!54ep`Q_Khoz?v$Osh>u%?M=RxN&=Sk43*X{m4Wc%g0SbePSiMn)oGtHxglrFn{?uh4hC+>*vc8|gl^a7gF zWq&Pr9U8M8b;YbH0ZnuwTuo>NKN`SS5r*dvnC^CT8qijYGw~z#w4$|8`l1Xt8U%O@ z1uqlkS@yXXvXx^iTZ51-v(yem|AAY&%svx303&4ZO@wbo7ozPKtnf0KWh*fXt4o*9 z8-W!hAr^?X5}x(64;bvFbO||2ygJ|G-XGC6ptZr{MevlptihbYJfoihmYUdNqY*~T zejZ-pf89%bWM#r8lw>1h-h#J1eHkS4AMvclXqhoM%6L}I7`zVSSwCa&bjHIo8Dry& z!87%tg$xm(E8U45o`>F1Tabg(9&b0LvwWZ}lY$bg)&xV;$B#c~UT>PFpnVWW3xMP8t*zGYcFE+mXjDD%x?e+vXNm-t${kh@c zF~YsfocM5VJPLl0D22z;O4>`GrTDcpj~3yTw3srqoK{m4mFP<9q;Be`QQA%W=^$P_ zx8l9?Z~8AiNRQGXI!rIpEA$qL2Q^+AD@g;{`UKPQu&oR5}f-IEQ{m7t#{)D8gzA)JV-#q>Z$h zw%|23fE7((-3RCt%X_-k}faQ~DAs`+>BYuTEB{ zskHhn-dPu`r7FNXYlT{c6`}$>AJ4ZX&P%M-c3iv|ul29lTiiNUFzWtKO zl6?CWx8KH@B?WwuA&XEX6bogUV#yLqmRPdHk|mZbkqn7sNF+ld84}ed;>!^e2}MG& zP*#Y4*Dxdy3WXw}SSY)iR(DXxMrs(Ph6=3-sHH+}J=9jA{>FxYA!LXcVumcB$c@D! zi$xZTEEXZIDKDz!ibLIpwvLIpx?<{6uL#%7+enP+U~8P{LF5eg6z z5E>975Nff5RUlL#R3KC!)Yc7GLIpwvLIpwvLfz2Ju|TLms6ePdsO_!XFrd8^dV4G6 V_ExCvtq`~R)PJpq2EEItp8&5QjFtcZ literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-color b/packages/tools/sysutils/fbterm/terminfo/x/xterm-color new file mode 100644 index 0000000000000000000000000000000000000000..dd7395c9999d29c81856e19a258ee7acc851772f GIT binary patch literal 1569 zcmc&zOKTHR6h3!UtZ%#UK?WrhQd*(Xd9>3IY8xxqrztJP;%r)yG)bFD(rMZ>eYtm` zh@uGU?{Fb*T)1-8g$RPU5Es&gxDXc_zjKmON)&Nphn(+x=euXlz31FXK!vH9PSO+Q zYRko>@3qDA*}T7&O6HP&CLU~xUK<~13W^w%gkZ~L@Ombf$d`iS<%MF>Yb8?hV+SJ0 zZ1XX`1U)6V2Q3tdmTBCMG+o`pe?3~u3wP_t%cn{9gUE4FN4gHth zC$vfJARQy!4P`eI9u_K+;>|wfz zG;4$O*kusI0CP=2!(?vonrqmC9fFQvmtdIDY!?K?t|08>h*M)|DaI}J7}#HYTJMIJ zIdPvtMz#r`K$PKa!sSHa;RxY!f9nckaCopN+)sySYHE6VW+s)&WM*gQ=CWDO%jNR< zLScU1_ZJq5#l^*?rBZ2mxm;dZSzTRQTVLP6;al6WlMF(7H)RfHmCGDV>C==sm@)@T q(k+>rCHa=*B*sv%GY7yGm~nVEz9k-jCEamkZ!=t^N525v9AyIl literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-debian b/packages/tools/sysutils/fbterm/terminfo/x/xterm-debian new file mode 120000 index 000000000..18632c408 --- /dev/null +++ b/packages/tools/sysutils/fbterm/terminfo/x/xterm-debian @@ -0,0 +1 @@ +xterm \ No newline at end of file diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-mono b/packages/tools/sysutils/fbterm/terminfo/x/xterm-mono new file mode 100644 index 0000000000000000000000000000000000000000..d911dfcbc021c640887fe4801fc022b8ea3fcf4f GIT binary patch literal 1515 zcmc&z&ubG=5T3Ux*5CHv53(vEq^MBo?xxw65ZfBT*dL@+yttQ^rcKgjlXROlNt@KW z2SpS`Q2!1O;>Cj}Pd$hrhzIc?9>jxquuI}kx;TZbB_4mwKyPsWDNKi?G7@kK+olsp(9w_a2PT6WuaxSY0<$$Hz zo^VCE3B0ZDs(Wg~e*pflEib74xJ_SgQ-aJ_ztG!vxv9MQqi5c!59*WpqP{6#?a=mU zo!Sv?v)2D)$FkYlGTO+DEz*&V@@xI2{X@%y8O+ zU}XSF-7$yZM_}x?WF=`gr{KfXodj$MHVzx3{XoMd-PWCfh@C|gVXz?u5OL`MILGF& zB<1x!1d)7G1bE6d!58!205|dK_N*#OD+;)*`$EQAS&Y%Zb9x5yItu zcPg~O=EkCMl6KMLIo^u&1PVqA09=7N M4bO%>;=)||0o6WU=Kufz literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-r5 b/packages/tools/sysutils/fbterm/terminfo/x/xterm-r5 new file mode 100644 index 0000000000000000000000000000000000000000..f63aa2f576ceabe5771cb354a8ea2cc4bfb67ca0 GIT binary patch literal 1301 zcmc(eKWG$D5XQezK_ggL2y)wm$XbYk`|mcg>EL{q-W z_2t=o;aDEsG#H+VhOf=$OY@f(0kNMtK0P)3RiuGEIEZc+*nwR*fD%S{c9+i)Bp4%& z+iHS3Nt;4yYt1-Y&^hxLa1nDxZPN~};zp67+4|hV9Y$7*=o;?h0r?^A5gy|Sp5hsv z;{{&g4c4)NO}xWx-W0g9sTjQe^J|i+Th5#Z2Y5}2KVsiolW^5Tk`3@boWJeV;`K%op(E)+f3Y! z?>2J=f;mdf$^0|)Q#AFzW!11(Q}{7B*#vEz)}YmC-U20TQDP;NP|4!$0(5bbHjNc( za9hQrrl&}w3Rei8hBDvO^OZeI^+MywG&a?m%sZj#A2&8s33Q#FCY5!mRVlkpwd<m==(s@5(iv75L=pBVNq_!$j}Q7>91dTzow)-c4IZ6dx+$2aB+<2!B6aId^b MVL$#QdbK)!0JyTvfB*mh literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-r6 b/packages/tools/sysutils/fbterm/terminfo/x/xterm-r6 new file mode 100644 index 0000000000000000000000000000000000000000..91c4f5d390954c164ed09ad04f86b470d1e7acda GIT binary patch literal 1491 zcmc&z&1(}u6o0c-tl#wD2U#jbNKv8Eo!w?zLTqaUV?RiV6vVx>G;NYLo1~jGA8k_a z9u!d&LH#>Ch!+o@JoO-gARfencn}ZbLDt{Aq?EFVc(Fs?@BQ9y-n^N4vk8e_>ZdMx zD&ktbvgo-3UZlyS?}lNdB7N0Gube9uhy?$X17TEb_YgEg-E^9KpGc#9bb>;37WI9M z3lyao*f>XV;8oZpB{{whoTZ!07Z|hTk_T3!2DRXC(_OmHGpgF74toy&qQhUpzv^(` ze@$;_i{8-(`b1yo8~vbPnClY0-wit=dc;Y1HA3Qy=N_*AYKj^`lJIeciTJuqS7GK48@l*I>zjj#b(N1YQ zwf2(rYUi{8ZD>zUGxDEzjcH@r0Xj;$6V8Q8MmQY}mt;8YK`=9bgzm@*_(_=ZyRs5= zNTuNKr#o@jIBW(sO~-(SOS-K)qn4dTWGS#AwZU@fIJk=C1SjS7VFXsbqpBGf6LwaK z`XyD$Lu^FNs1=R0v#015(#%cLlb1mZ1I&?(hE&{8bBiU x?vnc;+noC#`JR&dAh{1Fr<>e2lk-i^$CKl$NT*ORQUKry>SD literal 0 HcmV?d00001 diff --git a/packages/tools/sysutils/fbterm/terminfo/x/xterm-vt220 b/packages/tools/sysutils/fbterm/terminfo/x/xterm-vt220 new file mode 100644 index 0000000000000000000000000000000000000000..7e44160cd17d991ed3a2e805f988f821183fd91e GIT binary patch literal 2316 zcmb_dUuaup6hGg+&UTY1P7qy~)VeEW=*<1@P0|?GY_`*+wo9!=<1Wg&rhn4>X_}^O z+NPUOUj)&o;e$Hx#XX2H5K&PS>dQnF9K!ZsUmOYp!KWeUL;Rg{lZe_r=oWH*-|w8? z`TpEU{ya?qXQ@Ors>>=b(aZD-y$1dU zy+!X}e3#y%3-lpuv<&tI#Bt7=1(SJhc{PMrt8pgvKX7{6}L_+DL6 zTi`#cpCs~|`d#fZI*mO>z?d}}jUvqd%oz*Dvax2Ik;n${V_}~eo9&!du0LKhzS%+f zd)|$D-x-&UE#sb%EHTRp{=0WpNdtTIBZ*zZ-FaP0l z^x`(L?N79G^xNhdm&_k-!fHG3(^7smubDyb1a(k=f}WML%C?n_TV-u!D+oB#fMn3q zgBYKJ@z~6I@-OO7NYWmJlCXph7w}UAv2{V*894p0qkb^1!yFlb4O6fugfUzM*bE6f z+GLxfbF#B<~pvN(pS^#kww9L?woe0kyc+3uk9_d3CP8amc~fX-f zMX=e+ECr+7y(GzPDWwqi#FT}BkRgK$LoM{+T`&5IvKDDi~W7XkDecuHQ z`!ovLYsJx^B<)5amSHQfMc6!Sfli(rAD^0-tComL*SXYOGR;l&v@0kL)6xqq4b##vhg<78 zT2S&G$+!7EM_uqU$fD_9qy$LVam__!b7FBf#&4U$)v&EKd)+#0Rb6XRJV(4p({shM zn_fgb$M>>Q63@LUt2lfhEyx9M$Ti#g7x+KpF0?X0cVayg z_wH`Go$kWzyq~(M2Y0VakK#^#0=MrdW#~nkpcyJsg_dcZHgM~{PG{*&+_~rJefoet zqEG1yJ~jSc(luBWwgjut(F|qA=$J$Kfqns(S(qWh5T*RF;{#BDkbuyD5P?vW>0ziq zs6ePds6ePGUNqGYEyatbc+nIudOR}*1qcZU4G0kkb!7Bes6ePds6ePdsNpBMP+tZR<(ag;tb+GZ2i;7~D||X=7ZO5rEiyLJ?U>nJv<;a_ zIzYYDM@PUPq7nFUs!)R#RF#wTI6Xm6EB*q#1bl^-=?!{|-lq@fW5i$33VluAs*Gmy zqQ+GqiC`KAaE<28=JldWY!Dm8ZDNzSQ*0HENQ#u$gZ4D6R~!-#>fAx`h!|=2yTXzn zRm7|~DV`F~iFwGVV6Dw?I;WO zjEbH!PAOb!x3%(@jn^;JT5VUyGpf%!?Ve|i&x~^_`V#)U)_-WXH=7rXi^ea;Z^j=+ z(+J76@lqFj=vv3KUz5Tz8csBG=D4ZLl zHMEYxIkRY1Ei><%Rol$hAULCN>2S_I0K6Z@sI%_9M1u}#x(-qrma@GP9z_t#E~#(~ z!5-M|K=f^ol|I-(S`Y7);VgD3E9xe>(PfulDc*K2Gd0I7UOwSmnVsrU0&&^dD%)0> zDQ|4^b}JgaXD6~SrEqRj70mHn%nG&>N-sSI@0_4;rU%ATvMr7d!4AXvp;#W2oE29- zp?s3P9fi-NnK9W55@VgyGgxmXSZ^>=${GvrK%<&JkE6)J7QyI&va3aSWR=s~B0PXn zcrO(hXb~Q%2y@waa7TfcEjIyCpI@HBaXvAgK-5f`)tFiLEz@UegSr8=%&KE9AdUyI z3+e?l4w^9iGWSTD_4Q_<%k(LnrcSJU9}Nu+508wDjuwmK;}a95Qn_5IOios-$Bxx% zQ&aW&^z_Wk>};bkH+TH_{QSbg;^GP3yFpkg&WE3h93=lPyZd)21jjqB>jBCcYW{hjbbWL@|thgUwLSr&O)KofZ z2Iy#X1GM-t#udO*o=4GKtOA$9qWHeBIZ5A5@^j|!xmxDDwP@}z>#kW)k)xuRj$9R4 zI*O^t38Fl12CBIKN)>hT>cR&#`85TG`%xwXzx~(HTI$AM2mCVQe?SK!B8mS4op`U^ hKpU`m4OksE1FO;QEM*61pF&1 | tail -n 1 |awk '{print $3}'` : $CC : \"$CFLAGS\" \"$LDFLAGS\" ;" \ + > tools/build/src/user-config.jam + echo "using python : ${PKG_PYTHON_VERSION/#python} : $TOOLCHAIN : $SYSROOT_PREFIX/usr/include : $SYSROOT_PREFIX/usr/lib ;" \ + >> tools/build/src/user-config.jam +} + +makeinstall_target() { + $TOOLCHAIN/bin/bjam -d2 --ignore-site-config \ + --layout=system \ + --prefix=$SYSROOT_PREFIX/usr \ + --toolset=gcc link=static \ + --with-chrono \ + --with-date_time \ + --with-filesystem \ + --with-iostreams \ + --with-python \ + --with-random \ + --with-regex -sICU_PATH="$SYSROOT_PREFIX/usr" \ + --with-locale \ + --with-serialization \ + --with-system \ + --with-thread \ + install +} diff --git a/packages/tools/unused/eigen/package.mk b/packages/tools/unused/eigen/package.mk new file mode 100644 index 000000000..09f0c8d7d --- /dev/null +++ b/packages/tools/unused/eigen/package.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="eigen" +PKG_VERSION="3.2.10" +PKG_SHA256="760e6656426fde71cc48586c971390816f456d30f0b5d7d4ad5274d8d2cb0a6d" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://eigen.tuxfamily.org/index.php?title=Main_Page" +PKG_URL="http://bitbucket.org/eigen/eigen/get/$PKG_VERSION.tar.bz2" +PKG_SOURCE_DIR="eigen-*" +PKG_DEPENDS_TARGET="toolchain cmake:host" +PKG_SECTION="xmedia/games" +PKG_SHORTDESC="eigen c++ headers" +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" +PKG_TOOLCHAIN="configure" + +configure_target() { + SYSROOT_PREFIX=$SYSROOT_PREFIX cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_CONF \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=/usr/lib \ + -DCMAKE_INSTALL_LIBDIR_NOARCH=/usr/lib \ + -DCMAKE_INSTALL_PREFIX_TOOLCHAIN=$SYSROOT_PREFIX/usr \ + -DCMAKE_PREFIX_PATH=$SYSROOT_PREFIX/usr \ + $EXTRA_CMAKE_OPTS \ + .. +} diff --git a/packages/tools/unused/fbida/package.mk b/packages/tools/unused/fbida/package.mk new file mode 100644 index 000000000..804bb1ddc --- /dev/null +++ b/packages/tools/unused/fbida/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="fbida" +PKG_VERSION="b733a22190c70443fedcd4e87397c426c9d48af6" +PKG_SHA256="4aa43acc5c47fac8cb54db787d7a77ad4c20c08e2913162cf52a53ab9533740f" +PKG_ARCH="any" +PKG_SITE="https://github.com/kraxel/fbida" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain libexif pixman libdrm libepoxy tiff fontconfig" +PKG_SHORTDESC="The fbida project contains a few applications for viewing and editing images, with the main focus being photos." +PKG_LONGDESC="The fbida project contains a few applications for viewing and editing images, with the main focus being photos." +PKG_TOOLCHAIN="manual" + +pre_configure_target() { + sed -i "s|cpp -include jpeglib.h|$CPP -include $SYSROOT_PREFIX/usr/include/jpeglib.h|" GNUmakefile + sed -i "s|LIRC||" GNUmakefile + + + CFLAGS="$CFLAGS -I$(get_build_dir libepoxy)/include" + CFLAGS="$CFLAGS -I$(get_build_dir libepoxy)/.$TARGET_NAME/include" +} + +make_target() { + make -f GNUmakefile fbi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp fbi $INSTALL/usr/bin +} diff --git a/packages/tools/unused/fbpad/package.mk b/packages/tools/unused/fbpad/package.mk new file mode 100644 index 000000000..8979b3b91 --- /dev/null +++ b/packages/tools/unused/fbpad/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) + +PKG_NAME="fbpad" +PKG_VERSION="52b6bed1d8ce6357992e8fff6d53fef3c9fb047c" +PKG_SHA256="65ce00aa9709c4fc747499b0c5a8e0d084fa134678a3d781a7634f8d8a2f452f" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/aligrudi/fbpad" +PKG_URL="$PKG_SITE/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A small Linux framebuffer virtual terminal http://litcave.rudi.ir/" +PKG_TOOLCHAIN="auto" + +export CC=$CC +export CFLAGS="-Wall -O2" + +make_target() { +make fbpad + +if [ ${PROJECT} == "Amlogic" ]; then + sed -i "s|unsigned int|unsigned short|" $PKG_BUILD/conf.h + mv fbpad fbpad32 + make fbpad +fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin +if [ ${PROJECT} == "Amlogic" ]; then + cp fbpad32 $INSTALL/usr/bin/fbpad + cp fbpad $INSTALL/usr/bin/fbpad16 +else + cp fbpad $INSTALL/usr/bin/fbpad +fi + mkdir -p $INSTALL/usr/config/distribution/configs + cp courr.tf $INSTALL/usr/config/distribution/configs + mkdir -p $INSTALL/usr/share/terminfo + tic -x $PKG_BUILD/fbpad-256 -o $INSTALL/usr/share/terminfo + } + diff --git a/packages/tools/unused/fbpad/sources/Makefile b/packages/tools/unused/fbpad/sources/Makefile new file mode 100644 index 000000000..95132e012 --- /dev/null +++ b/packages/tools/unused/fbpad/sources/Makefile @@ -0,0 +1,7 @@ +all: fbpad +%.o: %.c conf.h + $(CC) -c $(CFLAGS) $< +fbpad: fbpad.o term.o pad.o draw.o font.o isdw.o scrsnap.o + $(CC) -o $@ $^ $(LDFLAGS) +clean: + rm -f *.o fbpad diff --git a/packages/tools/unused/fbpad/sources/conf.h b/packages/tools/unused/fbpad/sources/conf.h new file mode 100644 index 000000000..ec708b0ef --- /dev/null +++ b/packages/tools/unused/fbpad/sources/conf.h @@ -0,0 +1,63 @@ +/* framebuffer device */ +#define FBDEV "/dev/fb0" + +/* list of tags */ +#define TAGS "xnlhtr01uiva-" +#define TAGS_SAVED "" + +/* programs mapped to m-c, m-m, m-e */ +#define SHELL {"bash"} +#define EDITOR {"nano"} +#define MAIL {"mailx", "-f", "+inbox"} + +/* TERM variable for launched programs */ +#define TERM "fbpad-256" + +/* fbval_t should match framebuffer depth */ +typedef unsigned int fbval_t; + +/* tinyfont files for regular, italic, and bold fonts */ +#define FR "/storage/.config/distribution/configs/courr.tf" +#define FI NULL +#define FB NULL + +/* foreground and background colors */ +#define FGCOLOR COLOR2 +#define BGCOLOR COLOR0 + +/* where to write the screen shot */ +#define SCRSHOT "/tmp/scr" + +/* lock command password; NULL disables locking */ +#define PASS NULL + +/* optimized version of fb_val() */ +#define FB_VAL(r, g, b) fb_val((r), (g), (b)) + +/* brighten colors 0-7 for bold text */ +#define BRIGHTEN 1 + +/* black */ +#define COLOR0 0x000000 +#define COLOR8 0x555555 +/* red */ +#define COLOR1 0xaa0000 +#define COLOR9 0xff5555 +/* green */ +#define COLOR2 0x00aa00 +#define COLORA 0x55ff55 +/* yellow */ +#define COLOR3 0xaa5500 +#define COLORB 0xffff55 +/* blue */ +#define COLOR4 0x0000aa +#define COLORC 0x5555ff +/* magenta */ +#define COLOR5 0xaa00aa +#define COLORD 0xff55ff +/* cyan */ +#define COLOR6 0x00aaaa +#define COLORE 0x55ffff +/* white */ +#define COLOR7 0xaaaaaa +#define COLORF 0xffffff diff --git a/packages/tools/unused/fbpad/sources/courr.tf b/packages/tools/unused/fbpad/sources/courr.tf new file mode 100644 index 0000000000000000000000000000000000000000..3dbc16153bddd08e37ae3680be97746ba5fed27f GIT binary patch literal 136976 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 nVlWXV9S)0bq!kcG&S#5$jKA|r__8wZz8N+OVs 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 +#include +#include +#include +#include +#include +#include +#include +#include "draw.h" + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define NLEVELS (1 << 8) + +static struct fb_var_screeninfo vinfo; /* linux-specific FB structure */ +static struct fb_fix_screeninfo finfo; /* linux-specific FB structure */ +static int fd; /* FB device file descriptor */ +static void *fb; /* mmap()ed FB memory */ +static int bpp; /* bytes per pixel */ +static int nr, ng, nb; /* color levels */ +static int rl, rr, gl, gr, bl, br; /* shifts per color */ + +static int fb_len(void) +{ + return finfo.line_length * vinfo.yres_virtual; +} + +static void fb_cmap_save(int save) +{ + static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS]; + struct fb_cmap cmap; + if (finfo.visual == FB_VISUAL_TRUECOLOR) + return; + cmap.start = 0; + cmap.len = MAX(nr, MAX(ng, nb)); + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = NULL; + ioctl(fd, save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap); +} + +void fb_cmap(void) +{ + unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS]; + struct fb_cmap cmap; + int i; + if (finfo.visual == FB_VISUAL_TRUECOLOR) + return; + + for (i = 0; i < nr; i++) + red[i] = (65535 / (nr - 1)) * i; + for (i = 0; i < ng; i++) + green[i] = (65535 / (ng - 1)) * i; + for (i = 0; i < nb; i++) + blue[i] = (65535 / (nb - 1)) * i; + + cmap.start = 0; + cmap.len = MAX(nr, MAX(ng, nb)); + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = NULL; + + ioctl(fd, FBIOPUTCMAP, &cmap); +} + +unsigned fb_mode(void) +{ + return ((rl < gl) << 22) | ((rl < bl) << 21) | ((gl < bl) << 20) | + (bpp << 16) | (vinfo.red.length << 8) | + (vinfo.green.length << 4) | (vinfo.blue.length); +} + +static void init_colors(void) +{ + nr = 1 << vinfo.red.length; + ng = 1 << vinfo.blue.length; + nb = 1 << vinfo.green.length; + rr = 8 - vinfo.red.length; + rl = vinfo.red.offset; + gr = 8 - vinfo.green.length; + gl = vinfo.green.offset; + br = 8 - vinfo.blue.length; + bl = vinfo.blue.offset; +} + +int fb_init(char *dev) +{ + fd = open(dev, O_RDWR); + if (fd < 0) + goto failed; + if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) + goto failed; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) + goto failed; + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + bpp = (vinfo.bits_per_pixel + 7) >> 3; + fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +/* emuelec fbfix for n2 */ + if (vinfo.yoffset != 0) + { + vinfo.yoffset = 0; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) + { + printf("Error setting variable information.\n"); + exit(4); + } + } +/* emuelec fbfix for n2 */ + if (fb == MAP_FAILED) + goto failed; + init_colors(); + fb_cmap_save(1); + fb_cmap(); + return 0; +failed: + perror("fb_init()"); + close(fd); + return 1; +} + +void fb_free(void) +{ + fb_cmap_save(0); + munmap(fb, fb_len()); + close(fd); +} + +int fb_rows(void) +{ + return vinfo.yres; +} + +int fb_cols(void) +{ + return vinfo.xres; +} + +void *fb_mem(int r) +{ + return fb + (r + vinfo.yoffset) * finfo.line_length + vinfo.xoffset * bpp; +} + +unsigned fb_val(int r, int g, int b) +{ + return ((r >> rr) << rl) | ((g >> gr) << gl) | ((b >> br) << bl); +} diff --git a/packages/tools/unused/fbpad/sources/fbpad-256 b/packages/tools/unused/fbpad/sources/fbpad-256 new file mode 100644 index 000000000..11a894792 --- /dev/null +++ b/packages/tools/unused/fbpad/sources/fbpad-256 @@ -0,0 +1,6 @@ +fbpad-256, + use=linux, U8#0, + colors#256, + pairs#32767, + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, diff --git a/packages/tools/unused/munt/package.mk b/packages/tools/unused/munt/package.mk new file mode 100644 index 000000000..a1b817a54 --- /dev/null +++ b/packages/tools/unused/munt/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 0riginally created by Escalade (https://github.com/escalade) +# Copyright (C) 2018-present 5schatten (https://github.com/5schatten) + +PKG_NAME="munt" +PKG_VERSION="99f5c729be38770cb2cef67c824b1af3bb9adedc" +PKG_SHA256="dab18cb7ece5ef67a39f61f7acc479f2c2f0cb2fa9cfc731702c596b7471c769" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/munt/munt" +PKG_URL="https://github.com/munt/munt/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="A software synthesiser emulating pre-GM MIDI devices such as the Roland MT-32." + +PKG_CMAKE_OPTS_TARGET="-Dmunt_WITH_MT32EMU_QT=0 \ + -Dmunt_WITH_MT32EMU_SMF2WAV=0 \ + -Dlibmt32emu_SHARED=1" diff --git a/packages/tools/unused/steam-controller/package.mk b/packages/tools/unused/steam-controller/package.mk new file mode 100644 index 000000000..32acae259 --- /dev/null +++ b/packages/tools/unused/steam-controller/package.mk @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="steam-controller" +PKG_VERSION="60499dc" +PKG_SHA256="04a846c6f659fb5efca7747fe78e15c1348b5e0579437bb425f538318289bb80" +PKG_REV="102" +PKG_ARCH="any" +PKG_LICENSE="MIT" +PKG_SITE="https://github.com/ynsta/steamcontroller" +PKG_URL="https://github.com/ynsta/steamcontroller/archive/$PKG_VERSION.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python2 distutilscross:host python-libusb1 enum34 linux:host" +PKG_SECTION="driver" +PKG_SHORTDESC="A standalone userland driver for the steam controller to be used where steam client can't be installed." +PKG_LONGDESC="A standalone userland driver for the steam controller to be used where steam client can't be installed." +PKG_TOOLCHAIN="manual" + +pre_make_target() { + export PYTHONXCPREFIX="$SYSROOT_PREFIX/usr" + export LDSHARED="$CC -shared" +} + +make_target() { + python setup.py build +} + +makeinstall_target() { + +find $PKG_BUILD/build/scripts-2.7 -type f -exec sed -i "s|\#\!/mnt.*|\#\!/usr/bin/python|g" {} \; + + mkdir -p $INSTALL/usr/bin/ + cp -a $PKG_BUILD/build/scripts-2.7/* $INSTALL/usr/bin/ + + + mkdir -p $INSTALL/usr/lib + cp -a $PKG_BUILD/build/lib.linux-*-2.7/* $INSTALL/usr/lib/ + cp -a $(get_build_dir python-libusb1)/build/lib/* $INSTALL/usr/lib/ + cp -a $(get_build_dir enum34)/build/lib/* $INSTALL/usr/lib/ + + mkdir -p $INSTALL/usr/config/distribution/scinclude/linux + if [ -f "$(get_build_dir linux)/usr/include/linux/input-event-codes.h" ]; then + cp $(get_build_dir linux)/usr/include/linux/input-event-codes.h $INSTALL/usr/config/distribution/scinclude/linux/ + fi + cp $(get_build_dir linux)/usr/include/linux/input.h $INSTALL/usr/config/distribution/scinclude/linux/input.h + + $TOOLCHAIN/bin/python -Wi -t -B $TOOLCHAIN/lib/$PKG_PYTHON_VERSION/compileall.py $INSTALL/usr/lib/ -f 1>/dev/null + find $INSTALL/usr/lib/ -name '*.py' -exec rm {} \; +} + +post_install() { + enable_service driver.steam-controller.service + } diff --git a/packages/tools/unused/steam-controller/patches/steamcontroller-0001-fix-include-dir.patch b/packages/tools/unused/steam-controller/patches/steamcontroller-0001-fix-include-dir.patch new file mode 100644 index 000000000..69a344d85 --- /dev/null +++ b/packages/tools/unused/steam-controller/patches/steamcontroller-0001-fix-include-dir.patch @@ -0,0 +1,24 @@ +commit 8da1123bcbf3ad12b6c9d7975ebbb3f8663fd166 +Author: Lukas Rusak +Date: Sat Jan 7 13:50:30 2017 -0800 + + fix include dir + +diff --git a/src/uinput.py b/src/uinput.py +index 684a018..ffc2354 100644 +--- a/src/uinput.py ++++ b/src/uinput.py +@@ -36,10 +36,10 @@ from steamcontroller.tools import get_so_extensions + from collections import deque + + # Get All defines from linux headers +-if os.path.exists('/usr/include/linux/input-event-codes.h'): +- CHEAD = defines('/usr/include', 'linux/input-event-codes.h') ++if os.path.exists('/storage/.config/distribution/scinclude/linux/input-event-codes.h'): ++ CHEAD = defines('/storage/.config/distribution/scinclude', 'linux/input-event-codes.h') + else: +- CHEAD = defines('/usr/include', 'linux/input.h') ++ CHEAD = defines('/storage/.config/distribution/scinclude', 'linux/input.h') + + # Keys enum contains all keys and button from linux/uinput.h (KEY_* BTN_*) + Keys = IntEnum('Keys', {i: CHEAD[i] for i in CHEAD.keys() if (i.startswith('KEY_') or diff --git a/packages/tools/unused/steam-controller/patches/steamcontroller-0002-append-python-path.patch b/packages/tools/unused/steam-controller/patches/steamcontroller-0002-append-python-path.patch new file mode 100644 index 000000000..2552835c2 --- /dev/null +++ b/packages/tools/unused/steam-controller/patches/steamcontroller-0002-append-python-path.patch @@ -0,0 +1,92 @@ +commit b1bcba9b73d1e5e755ef6cda014ea3cc5a5ba270 +Author: Lukas Rusak +Date: Sat Jan 7 13:51:01 2017 -0800 + + append python path + +diff --git a/scripts/sc-callbacks.py b/scripts/sc-callbacks.py +index eaeb658..35a272a 100755 +--- a/scripts/sc-callbacks.py ++++ b/scripts/sc-callbacks.py +@@ -25,6 +25,8 @@ + """Steam Controller Callback Mode example""" + import sys + ++sys.path.append('/usr/lib') ++ + from steamcontroller import SteamController, SCButtons + from steamcontroller.events import EventMapper, Pos + from steamcontroller.uinput import Keys +diff --git a/scripts/sc-desktop.py b/scripts/sc-desktop.py +index 9eff430..e0b8ec7 100755 +--- a/scripts/sc-desktop.py ++++ b/scripts/sc-desktop.py +@@ -22,6 +22,10 @@ + # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + # THE SOFTWARE. + ++import sys ++ ++sys.path.append('/usr/lib') ++ + """Steam Controller Mouse, Keyboard mode""" + + from steamcontroller import SteamController, SCButtons +diff --git a/scripts/sc-dump.py b/scripts/sc-dump.py +index b6f2c24..b582771 100755 +--- a/scripts/sc-dump.py ++++ b/scripts/sc-dump.py +@@ -25,6 +25,9 @@ + """Steam Controller USB Dumper""" + + import sys ++ ++sys.path.append('/usr/lib') ++ + from steamcontroller import SteamController + + def dump(_, sci): +diff --git a/scripts/sc-mixed.py b/scripts/sc-mixed.py +index 4a9c3c0..5e25af9 100755 +--- a/scripts/sc-mixed.py ++++ b/scripts/sc-mixed.py +@@ -22,6 +22,10 @@ + # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + # THE SOFTWARE. + ++import sys ++ ++sys.path.append('/usr/lib') ++ + """Steam Controller XBOX360 Gamepad Emulator""" + + from steamcontroller import \ +diff --git a/scripts/sc-test-cmsg.py b/scripts/sc-test-cmsg.py +index 08c8481..a59fbe9 100755 +--- a/scripts/sc-test-cmsg.py ++++ b/scripts/sc-test-cmsg.py +@@ -26,6 +26,9 @@ + + import sys + import struct ++ ++sys.path.append('/usr/lib') ++ + from steamcontroller import SteamController + + def dump(_, sci): +diff --git a/scripts/sc-xbox.py b/scripts/sc-xbox.py +index 814c8bc..89d4f55 100755 +--- a/scripts/sc-xbox.py ++++ b/scripts/sc-xbox.py +@@ -22,6 +22,10 @@ + # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + # THE SOFTWARE. + ++import sys ++ ++sys.path.append('/usr/lib') ++ + """Steam Controller XBOX360 Gamepad Emulator""" + + from steamcontroller import \ diff --git a/packages/tools/unused/steam-controller/patches/steamcontroller-0003-wait-for-controller-connection.patch b/packages/tools/unused/steam-controller/patches/steamcontroller-0003-wait-for-controller-connection.patch new file mode 100644 index 000000000..5dbbba38c --- /dev/null +++ b/packages/tools/unused/steam-controller/patches/steamcontroller-0003-wait-for-controller-connection.patch @@ -0,0 +1,62 @@ +commit 21abfb33340ba34de9c7266568515fc42608b339 +Author: Lukas Rusak +Date: Fri Jan 13 14:27:18 2017 -0800 + + wait for controller + +diff --git a/src/__init__.py b/src/__init__.py +index 1bf111e..353f032 100644 +--- a/src/__init__.py ++++ b/src/__init__.py +@@ -24,7 +24,7 @@ import struct + from enum import IntEnum + + from threading import Timer +-from time import time ++from time import time, sleep + + + VENDOR_ID = 0x28de +@@ -121,24 +121,28 @@ class SteamController(object): + self._cmsg = [] + self._ctx = usb1.USBContext() + ++ _handle = None + handle = [] + pid = [] + endpoint = [] + ccidx = [] +- for i in range(len(PRODUCT_ID)): +- _pid = PRODUCT_ID[i] +- _endpoint = ENDPOINT[i] +- _ccidx = CONTROLIDX[i] +- +- _handle = self._ctx.openByVendorIDAndProductID( +- VENDOR_ID, _pid, +- skip_on_error=True, +- ) +- if _handle != None: +- handle.append(_handle) +- pid.append(_pid) +- endpoint.append(_endpoint) +- ccidx.append(_ccidx) ++ ++ while _handle is None: ++ for i in range(len(PRODUCT_ID)): ++ _pid = PRODUCT_ID[i] ++ _endpoint = ENDPOINT[i] ++ _ccidx = CONTROLIDX[i] ++ ++ _handle = self._ctx.openByVendorIDAndProductID( ++ VENDOR_ID, _pid, ++ skip_on_error=True, ++ ) ++ if _handle != None: ++ handle.append(_handle) ++ pid.append(_pid) ++ endpoint.append(_endpoint) ++ ccidx.append(_ccidx) ++ sleep(2) + + if len(handle) == 0: + raise ValueError('No SteamControler Device found') diff --git a/packages/tools/unused/steam-controller/patches/steamcontroller-0004-use-run-for-pid-directory.patch b/packages/tools/unused/steam-controller/patches/steamcontroller-0004-use-run-for-pid-directory.patch new file mode 100644 index 000000000..d074cb640 --- /dev/null +++ b/packages/tools/unused/steam-controller/patches/steamcontroller-0004-use-run-for-pid-directory.patch @@ -0,0 +1,54 @@ +commit 5947f69820db3ce2d976ac533fb64319637d3f93 +Author: Lukas Rusak +Date: Sat Jan 7 13:53:36 2017 -0800 + + use run for pid directory + +diff --git a/scripts/sc-desktop.py b/scripts/sc-desktop.py +index e0b8ec7..ad494d8 100755 +--- a/scripts/sc-desktop.py ++++ b/scripts/sc-desktop.py +@@ -87,9 +87,9 @@ if __name__ == '__main__': + parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + args = parser.parse_args() + if args.index != None: +- daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) ++ daemon = SCDaemon('/run/steamcontroller{:d}.pid'.format(args.index)) + else: +- daemon = SCDaemon('/tmp/steamcontroller.pid') ++ daemon = SCDaemon('/run/steamcontroller.pid') + + if 'start' == args.command: + daemon.start() +diff --git a/scripts/sc-mixed.py b/scripts/sc-mixed.py +index 5e25af9..c9139e7 100755 +--- a/scripts/sc-mixed.py ++++ b/scripts/sc-mixed.py +@@ -126,9 +126,9 @@ if __name__ == '__main__': + parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + args = parser.parse_args() + if args.index != None: +- daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) ++ daemon = SCDaemon('/run/steamcontroller{:d}.pid'.format(args.index)) + else: +- daemon = SCDaemon('/tmp/steamcontroller.pid') ++ daemon = SCDaemon('/run/steamcontroller.pid') + + if 'start' == args.command: + daemon.start() +diff --git a/scripts/sc-xbox.py b/scripts/sc-xbox.py +index 89d4f55..0c61b4e 100755 +--- a/scripts/sc-xbox.py ++++ b/scripts/sc-xbox.py +@@ -86,9 +86,9 @@ if __name__ == '__main__': + parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + args = parser.parse_args() + if args.index != None: +- daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) ++ daemon = SCDaemon('/run/steamcontroller{:d}.pid'.format(args.index)) + else: +- daemon = SCDaemon('/tmp/steamcontroller.pid') ++ daemon = SCDaemon('/run/steamcontroller.pid') + + if 'start' == args.command: + daemon.start() diff --git a/packages/tools/unused/steam-controller/patches/steamcontroller-0005-steam-client-will-never-be-running.patch b/packages/tools/unused/steam-controller/patches/steamcontroller-0005-steam-client-will-never-be-running.patch new file mode 100644 index 000000000..8a2061cb3 --- /dev/null +++ b/packages/tools/unused/steam-controller/patches/steamcontroller-0005-steam-client-will-never-be-running.patch @@ -0,0 +1,41 @@ +commit 1467b7cd9d153be6680cc818b10c66967a2f0951 +Author: Lukas Rusak +Date: Sat Jan 7 14:11:25 2017 -0800 + + steam client will never be running + +diff --git a/src/daemon.py b/src/daemon.py +index 964c765..fba7792 100644 +--- a/src/daemon.py ++++ b/src/daemon.py +@@ -9,7 +9,6 @@ import time + import atexit + import signal + import syslog +-import psutil + import traceback + import gc + +@@ -92,16 +91,12 @@ class Daemon(object): + self.daemonize() + syslog.syslog(syslog.LOG_INFO, '{}: started'.format(os.path.basename(sys.argv[0]))) + while True: +- # look if steam is running +- if len([p for p in psutil.process_iter() if p.name() == 'steam']) == 0: +- try: +- self.run() +- except Exception as e: # pylint: disable=W0703 +- syslog.syslog(syslog.LOG_ERR, '{}: {!s}'.format(os.path.basename(sys.argv[0]), e)) +- syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) +- gc.collect() +- else: +- syslog.syslog(syslog.LOG_INFO, '{}: steam client is runing'.format(os.path.basename(sys.argv[0]))) ++ try: ++ self.run() ++ except Exception as e: # pylint: disable=W0703 ++ syslog.syslog(syslog.LOG_ERR, '{}: {!s}'.format(os.path.basename(sys.argv[0]), e)) ++ syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) ++ gc.collect() + time.sleep(2) + + def stop(self): diff --git a/packages/tools/unused/steam-controller/system.d/driver.steam-controller.service b/packages/tools/unused/steam-controller/system.d/driver.steam-controller.service new file mode 100644 index 000000000..9318f1efa --- /dev/null +++ b/packages/tools/unused/steam-controller/system.d/driver.steam-controller.service @@ -0,0 +1,14 @@ +[Unit] +Description=Steam Controller driver + +[Service] +Type=forking +ExecStart=/usr/bin/python /usr/bin/sc-xbox.py start +ExecReload=/usr/bin/python /usr/bin/sc-xbox.py restart +ExecStop=/usr/bin/python /usr/bin/sc-xbox.py stop +PIDFile=/run/steamcontroller.pid +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/packages/tools/vim/package.mk b/packages/tools/vim/package.mk new file mode 100644 index 000000000..5f3d13aad --- /dev/null +++ b/packages/tools/vim/package.mk @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="vim" +PKG_VERSION="8.2.4065" +PKG_SHA256="afc4a51eeeddf81c810dc29e364e7babe1cfebafcf2fd15547b35f56b7f0cb14" +PKG_LICENSE="VIM" +PKG_SITE="http://www.vim.org/" +PKG_URL="https://github.com/vim/vim/archive/v${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain ncurses" +PKG_LONGDESC="Vim is a highly configurable text editor built to enable efficient text editing." +PKG_BUILD_FLAGS="-sysroot" + +PKG_CONFIGURE_OPTS_TARGET="vim_cv_getcwd_broken=no \ + vim_cv_memmove_handles_overlap=yes \ + vim_cv_stat_ignores_slash=yes \ + vim_cv_terminfo=yes \ + vim_cv_tgetent=zero \ + vim_cv_toupper_broken=no \ + vim_cv_tty_group=world \ + vim_cv_tty_mode=0620 \ + ac_cv_sizeof_int=4 \ + ac_cv_small_wchar_t=no \ + --datarootdir=/storage/.config/vim \ + --disable-canberra \ + --disable-nls \ + --enable-selinux=no \ + --enable-gui=no \ + --with-features=huge \ + --with-tlib=tinfo \ + --without-x" + +PKG_MAKEINSTALL_OPTS_TARGET=VIMRTDIR= + +pre_configure_target() { + cd .. + rm -rf .${TARGET_NAME} +} + +make_target() { + : +} + +pre_makeinstall_target() { + mkdir -p ${INSTALL}/usr/bin + mkdir -p ${INSTALL}/usr/config/vim +} + +post_makeinstall_target() { + ( + mv ${INSTALL}/storage/.config/vim/vim/vimrc_example.vim ${INSTALL}/usr/config/vim/vimrc + rm -r ${INSTALL}/storage/ + ) +} diff --git a/packages/ui/emulationstation/bluez/bluezutils.py b/packages/ui/emulationstation/bluez/bluezutils.py new file mode 100644 index 000000000..de08cbdcb --- /dev/null +++ b/packages/ui/emulationstation/bluez/bluezutils.py @@ -0,0 +1,47 @@ +import dbus + +SERVICE_NAME = "org.bluez" +ADAPTER_INTERFACE = SERVICE_NAME + ".Adapter1" +DEVICE_INTERFACE = SERVICE_NAME + ".Device1" + +def get_managed_objects(): + bus = dbus.SystemBus() + manager = dbus.Interface(bus.get_object("org.bluez", "/"), + "org.freedesktop.DBus.ObjectManager") + return manager.GetManagedObjects() + +def find_adapter(pattern=None): + return find_adapter_in_objects(get_managed_objects(), pattern) + +def find_adapter_in_objects(objects, pattern=None): + bus = dbus.SystemBus() + for path, ifaces in objects.iteritems(): + adapter = ifaces.get(ADAPTER_INTERFACE) + if adapter is None: + continue + if not pattern or pattern == adapter["Address"] or \ + path.endswith(pattern): + obj = bus.get_object(SERVICE_NAME, path) + return dbus.Interface(obj, ADAPTER_INTERFACE) + raise Exception("Bluetooth adapter not found") + +def find_device(device_address, adapter_pattern=None): + return find_device_in_objects(get_managed_objects(), device_address, + adapter_pattern) + +def find_device_in_objects(objects, device_address, adapter_pattern=None): + bus = dbus.SystemBus() + path_prefix = "" + if adapter_pattern: + adapter = find_adapter_in_objects(objects, adapter_pattern) + path_prefix = adapter.object_path + for path, ifaces in objects.iteritems(): + device = ifaces.get(DEVICE_INTERFACE) + if device is None: + continue + if (device["Address"] == device_address and + path.startswith(path_prefix)): + obj = bus.get_object(SERVICE_NAME, path) + return dbus.Interface(obj, DEVICE_INTERFACE) + + raise Exception("Bluetooth device not found") diff --git a/packages/ui/emulationstation/config/es_features.cfg b/packages/ui/emulationstation/config/es_features.cfg new file mode 100644 index 000000000..6112dd1e7 --- /dev/null +++ b/packages/ui/emulationstation/config/es_features.cfg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/emulationstation/config/es_input.cfg b/packages/ui/emulationstation/config/es_input.cfg new file mode 100644 index 000000000..c35dbff22 --- /dev/null +++ b/packages/ui/emulationstation/config/es_input.cfg @@ -0,0 +1,90 @@ + + + + bash /storage/.emulationstation/scripts/inputconfiguration.sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/emulationstation/config/es_settings.cfg b/packages/ui/emulationstation/config/es_settings.cfg new file mode 100644 index 000000000..905e23e7f --- /dev/null +++ b/packages/ui/emulationstation/config/es_settings.cfg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/emulationstation/config/es_systems.cfg b/packages/ui/emulationstation/config/es_systems.cfg new file mode 100644 index 000000000..b16f03348 --- /dev/null +++ b/packages/ui/emulationstation/config/es_systems.cfg @@ -0,0 +1,2069 @@ + + + + 3do + 3DO + Panasonic + 1993 + console + /storage/roms/3do + .iso .ISO .bin .BIN .chd .CHD .cue .CUE + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + 3do + 3do + + + + opera + + + + + + amiga + Amiga + Commodore + 1985 + computer + /storage/roms/amiga + .zip .ZIP .adf .ADF .uae .UAE .ipf .IPF .dms .DMS .adz .ADZ .lha .LHA .m3u .M3U .hdf .HDF .hdz .HDZ + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + amiga + amiga + + + + puae + uae4arm + + + + + AMIBERRY + + + + + + amigacd32 + Amiga CD32 + Commodore + 1994 + console + /storage/roms/amigacd32 + .iso .ISO .cue .CUE .lha .LHA .chd .CHD + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + amigacd32 + amigacd32 + + + + puae + uae4arm + + + + + + amstradcpc + Amstrad CPC + Amstrad + 1984 + computer + /storage/roms/amstradcpc + .dsk .DSK .sna .SNA .tap .TAP .cdt .CDT .kcr .KCR .voc .VOC .m3u .M3U .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + amstradcpc + amstradcpc + + + + crocods + cap32 + + + + + + arcade + Arcade + Arcade + arcade + /storage/roms/arcade + .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + arcade + arcade + + + + mame2003_plus + mame2000 + mame2010 + mame2015 + mame + fbneo + fbalpha2012 + fbalpha2019 + + + + + AdvanceMame + + + + + + atari2600 + Atari 2600 + Atari + 1977 + console + /storage/roms/atari2600 + .a26 .A26 .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atari2600 + atari2600 + + + + stella + stella2014 + + + + + + atari5200 + Atari 5200 + Atari + 1982 + console + /storage/roms/atari5200 + .rom .ROM .xfd .XFD .atr .ATR .atx .ATX .cdm .CDM .cas .CAS .car .CAR .bin .BIN .a52 .A52 .xex .XEX .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atari5200 + atari5200 + + + + atari800 + + + + + + atari7800 + Atari 7800 + Atari + 1986 + console + /storage/roms/atari7800 + .a78 .A78 .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atari7800 + atari7800 + + + + prosystem + + + + + + atari800 + Atari 800 + Atari + 1979 + console + /storage/roms/atari800 + .rom .ROM .xfd .XFD .atr .ATR .atx .ATX .cdm .CDM .cas .CAS .car .CAR .bin .BIN .a52 .A52 .xex .XEX .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atari800 + atari800 + + + + atari800 + + + + + + atarist + Atari ST + Atari + 1985 + computer + /storage/roms/atarist + .st .ST .msa .MSA .stx .STX .dim .DIM .ipf .IPF .m3u .M3U .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atarist + atarist + + + + hatari + + + + + HATARISA + + + + + + atomiswave + Atomiswave + Sammy + 2003 + arcade + /storage/roms/atomiswave + .lst .LST .bin .BIN .dat .DAT .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atomiswave arcade + atomiswave + + + + flycast + + + + + + channelf + Channel F + Fairchild + 1976 + console + /storage/roms/channelf + .bin .BIN .chf .CHF .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + channelf + channelf + + + + freechaf + + + + + + colecovision + ColecoVision + Coleco + 1982 + console + /storage/roms/coleco + .bin .BIN .col .COL .rom .ROM .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + colecovision + colecovision + + + + bluemsx + gearcoleco + smsplus + + + + + + c128 + Commodore 128 + Commodore + 1985 + computer + /storage/roms/c128 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB . + .NBZ .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + c128 + c128 + + + + vice_x128 + + + + + + c16 + Commodore 16 + Commodore + 1984 + computer + /storage/roms/c16 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + c16 + c16 + + + + vice_xplus4 + + + + + + c64 + Commodore 64 + Commodore + 1982 + computer + /storage/roms/c64 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + c64 + c64 + + + + vice_x64 + + + + + + vic20 + Commodore VIC-20 + Commodore + 1980 + computer + /storage/roms/vic20 + .20 .40 .60 .a0 .A0 .b0 .B0 .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .gz .GZ .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + vic20 + vic20 + + + + vice_xvic + + + + + + daphne + Daphne + Arcade + arcade + /storage/roms/daphne + .daphne .DAPHNE + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + daphne arcade + daphne + + + + daphne + + + + + HYPSEUS + + + + + + dreamcast + Dreamcast + Sega + 1998 + console + /storage/roms/dreamcast + .cdi .CDI .gdi .GDI .chd .CHD .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + dreamcast + dreamcast + + + + flycast + + + + + + easyrpg + EasyRPG + Various + 2003 + game engine + /storage/roms/easyrpg + .zip .ZIP .easyrpg .EASYRPG .ldb .LDB + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + easyrpg + easyrpg + + + + easyrpg + + + + + + famicom + Famicom + Nintendo + 1983 + console + /storage/roms/famicom + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + nes + famicom + + + + fceumm + nestopia + quicknes + + + + + + fds + Famicom Disk System + Nintendo + 1986 + console + /storage/roms/fds + .fds .FDS .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + fds + fds + + + + fceumm + nestopia + quicknes + + + + + + fbn + Final Burn Neo + Arcade + arcade + /storage/roms/fbneo + .7z .zip .7Z .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + arcade + fbn + + + + fbneo + mame2003 + mame2010 + mame2015 + mame + fbalpha2012 + fbalpha2019 + + + + + + gameandwatch + Game and Watch + Nintendo + 1980 + portable + /storage/roms/gameandwatch + .mgw .MGW .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gameandwatch + gameandwatch + + + + gw + + + + + + gb + Game Boy + Nintendo + 1989 + portable + /storage/roms/gb + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gb + gb + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + + gbh + Game Boy (Hacks) + Nintendo + 1989 + portable + /storage/roms/gbh + .gb .GB .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gb + gbh + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + + gba + Game Boy Advance + Nintendo + 2001 + portable + /storage/roms/gba + .gba .GBA .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gba + gba + + + + mgba + gpsp + vbam + vba_next + beetle_gba + + + + + + gbah + Game Boy Advance (Hacks) + Nintendo + 2001 + portable + /storage/roms/gbah + .gba .GBA .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gba + gbah + + + + mgba + gpsp + vbam + vba_next + beetle_gba + + + + + + gbc + Game Boy Color + Nintendo + 1998 + portable + /storage/roms/gbc + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gbc + gbc + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + + gbch + Game Boy Color (Hacks) + Nintendo + 1998 + portable + /storage/roms/gbch + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gbc + gbch + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + + gamegear + Game Gear + Sega + 1990 + portable + /storage/roms/gamegear + .bin .BIN .gg .GG .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gamegear + gamegear + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + ggh + Game Gear (Hacks) + Sega + 1990 + portable + /storage/roms/gamegearh + .bin .BIN .gg .GG .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + gamegear + ggh + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + intellivision + Intellivision + Mattel + 1979 + console + /storage/roms/intellivision + .int .INT .bin .BIN .rom .ROM .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + intellivision + intellivision + + + + freeintv + + + + + + j2me + J2ME + Sun Microsystems + 2002 + portable + /storage/roms/j2me + .jar .JAR + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + j2me + j2me + + + + freej2me + + + + + + atarilynx + Lynx + Atari + 1989 + portable + /storage/roms/atarilynx + .lnx .LNX .o .O .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + atarilynx + atarilynx + + + + handy + beetle_lynx + + + + + + mame + MAME + Arcade + arcade + /storage/roms/mame + .7z .7Z .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + arcade + mame + + + + mame2003_plus + mame2000 + mame2010 + mame2015 + mame + fbneo + fbalpha2012 + fbalpha2019 + + + + + AdvanceMame + + + + + + megadrive-japan + Sega Mega Drive + Sega + 1988 + console + /storage/roms/megadrive-japan + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + megadrive + megadrive-japan + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + pc + MS-DOS + Microsoft + 1981 + computer + /storage/roms/pc + .com .COM .bat .BAT .exe .EXE .dosz .DOSZ + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + pc + + + + dosbox_pure + dosbox_svn + + + + + + snesmsu1 + MSU-1 + Nintendo + 2012 + console + /storage/roms/snesmsu1 + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + snesmsu1 snes + snesmsu1 + + + + snes9x + beetle_supafaust + + + + + + msx + MSX + Microsoft + 1983 + computer + /storage/roms/msx + .dsk .DSK .mx1 .MX1 .mx2 .MX2 .rom .ROM .zip .ZIP .7z .7Z .M3U .m3u + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + msx + msx + + + + bluemsx + fmsx + + + + + + msx2 + MSX2 + Microsoft + 1985 + computer + /storage/roms/msx2 + .dsk .DSK .mx1 .MX1 .mx2 .MX2 .rom .ROM .zip .ZIP .7z .7Z .M3U .m3u + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + msx + msx2 + + + + bluemsx + fmsx + + + + + + naomi + Naomi + Sega + 1998 + arcade + /storage/roms/naomi + .lst .LST .bin .BIN .dat .DAT .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + naomi arcade + naomi + + + + flycast + + + + + + neogeo + Neo Geo + SNK + 1990 + console + /storage/roms/neogeo + .7z .7Z .zip .ZIP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + neogeo + neogeo + + + + fbneo + mame2003_plus + fbalpha2012 + fbalpha2019 + mame2010 + mame2015 + mame + + + + + + neocd + Neo Geo CD + SNK + 1990 + console + /storage/roms/neocd + .cue .CUE .iso .ISO .chd .CHD + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + neogeocd + neogeocd + + + + neocd + fbneo + + + + + + ngp + Neo Geo Pocket + SNK + 1998 + portable + /storage/roms/ngp + .ngc .NGC .ngp .NGP .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + ngp + ngp + + + + beetle_ngp + race + + + + + + ngpc + Neo Geo Pocket Color + SNK + 1999 + portable + /storage/roms/ngpc + .ngc .NGC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + ngpc + ngpc + + + + beetle_ngp + race + + + + + + n64 + Nintendo 64 + Nintendo + 1996 + console + /storage/roms/n64 + .z64 .Z64 .n64 .N64 .v64 .V64 .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + n64 + n64 + + + + parallel_n64 + parallel_n64_gln64 + mupen64plus + mupen64plus_next + + + + + m64p_gl64mk2 + m64p_rice + + + + + + nes + Nintendo Entertainment System + Nintendo + 1985 + console + /storage/roms/nes + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + nes + nes + + + + fceumm + nestopia + quicknes + + + + + + nesh + Nintendo Entertainment System (Hacks) + Nintendo + 1985 + console + /storage/roms/nesh + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + nes + nesh + + + + fceumm + nestopia + quicknes + + + + + + odyssey2 + Odyssey² + Magnavox + 1979 + console + /storage/roms/odyssey + .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + odyssey2 + odyssey2 + + + + o2em + + + + + + openbor + OpenBOR + Various + 2008 + game engine + /storage/roms/openbor + .pak .PAK + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + openbor + openbor + + + + OPENBOR + + + + + + pc-8800 + PC-8800 + NEC + 1981 + computer + /storage/roms/pc88 + .d88 .D88 .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc88 + pc88 + + + + quasi88 + + + + + + pc-9800 + PC-9800 + NEC + 1983 + computer + /storage/roms/pc98 + .d98 .zip .98d .fdi .fdd .2hd .tfd .d88 .88d .hdm .xdf .dup .hdi .thd .nhd .hdd .hdn + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc98 + pc98 + + + + np2kai + nekop2 + + + + + + pcengine + PC Engine + NEC + 1987 + console + /storage/roms/pcengine + .pce .PCE .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pcengine + pcengine + + + + beetle_pce_fast + beetle_supergrafx + + + + + + pcenginecd + PC Engine CD + NEC + 1988 + console + /storage/roms/pcenginecd + .cue .CUE .ccd .CCD .chd .CHD .toc .TOC .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pcenginecd + pce-cd + + + + beetle_pce_fast + beetle_supergrafx + + + + + + pcfx + PC-FX + NEC + 1994 + console + /storage/roms/pcfx + .chd .CHD .cue .CUE .ccd .CCD .toc .TOC + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pcfx + pcfx + + + + beetle_pcfx + + + + + + pico-8 + PICO-8 + Lexaloffle + 2015 + console + /storage/roms/pico-8 + .sh .p8 .png .SH .P8 .PNG + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --controllers="%CONTROLLERSCONFIG%" + pico-8 + pico-8 + + + psx + PlayStation + Sony + 1994 + console + /storage/roms/psx + .bin .BIN .cue .CUE .img .IMG .mdf .MDF .pbp .PBP .toc .TOC .cbn .CBN .m3u .M3U .ccd .CCD .chd .CHD .iso .ISO + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + psx + psx + + + + pcsx_rearmed + duckstation + swanstation + + + + + + psp + PlayStation Portable + Sony + 2004 + portable + /storage/roms/psp + .iso .ISO .cso .CSO .pbp .PBP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + psp + psp + + + + PPSSPPSDL + + + + + ppsspp + + + + + + pspminis + PSP Minis + Sony + 2004 + portable + /storage/roms/pspminis + .iso .ISO .cso .CSO .pbp .PBP + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + psp + pspminis + + + + PPSSPPSDL + + + + + ppsspp + + + + + + pokemini + Pokémon Mini + Nintendo + 2001 + portable + /storage/roms/pokemini + .min .MIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pokemini + pokemini + + + + pokemini + + + + + + ports + Ports + Various + unknown + various + /storage/roms/ports + .sh .SH + /usr/bin/bash %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + ports + + + sc-3000 + SC-3000 + Sega + 1983 + computer + /storage/roms/sc-3000 + .bin .BIN .sg .SG .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + sc-3000 + sc-3000 + + + + bluemsx + + + + + + scummvm + ScummVM + Various + 2001 + game engine + /storage/.config/scummvm/games + .sh .SH .svm .SVM .scummvm + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + scummvm + + + + scummvm + + + + + SCUMMVMSA + + + + + + sega32x + Sega 32X + Sega + 1994 + console + /storage/roms/sega32x + .32x .32X .smd .SMD .bin .BIN .md .MD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + sega32x + sega32x + + + + picodrive + + + + + + segacd + Sega CD + Sega + 1991 + console + /storage/roms/segacd + .chd .CHD .cue .CUE .iso .ISO .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + segacd + segacd + + + + genesis_plus_gx + picodrive + + + + + + megacd + Sega Mega-CD + Sega + 1991 + console + /storage/roms/megacd + .chd .CHD .cue .CUE .iso .ISO .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + segacd + megacd + + + + genesis_plus_gx + picodrive + + + + + + genesis + Sega Genesis + Sega + 1989 + console + /storage/roms/genesis + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + genesis + genesis + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + genh + Sega Genesis (Hacks) + Sega + 1989 + console + /storage/roms/genh + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + genesis + genh + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + mastersystem + Sega Master System + Sega + 1985 + console + /storage/roms/mastersystem + .bin .BIN .sms .SMS .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + mastersystem + mastersystem + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + megadrive + Sega Mega Drive + Sega + 1990 + console + /storage/roms/megadrive + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + megadrive + megadrive + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + megaduck + Mega Duck + Welback Holdings + 1993 + portable + /storage/roms/megaduck + .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + megaduck + megaduck + + + + sameduck + + + + + + saturn + Sega Saturn + Sega + 1994 + console + /storage/roms/saturn + .cue .CUE .chd .CHD .iso .ISO + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + saturn + saturn + + + + yabasanshiro + + + + + + sg-1000 + SG-1000 + Sega + 1983 + console + /storage/roms/sg-1000 + .bin .BIN .sg .SG .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + sg-1000 + sg-1000 + + + + gearsystem + genesis_plus_gx + picodrive + + + + + + x1 + Sharp X1 + Sharp + 1982 + computer + /storage/roms/x1 + .dx1 .DX1 .2d .2D .2hd .2HD .tfd .TFD .d88 .D88 .88d .88D .hdm .HDM .xdf .XDF .dup .DUP .tap .TAP .cmd .CMD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + x1 + x1 + + + + x1 + + + + + + zxspectrum + Sinclair ZX Spectrum + Sinclair + 1982 + computer + /storage/roms/zxspectrum + .tzx .TZX .tap .TAP .z80 .Z80 .rzx .RZX .scl .SCL .trd .TRD .dsk .DSK .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + zxspectrum + zxspectrum + + + + fuse + + + + + + zx81 + Sinclair ZX81 + Sinclair + 1981 + computer + /storage/roms/zx81 + .tzx .TZX .p .P .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + zx81 + zx81 + + + + 81 + + + + + + supergrafx + Super Grafx + NEC + 1989 + console + /storage/roms/sgfx + .pce .PCE .sgx .SGX .cue .CUE .ccd .CCD .chd .CHD .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + supergrafx + supergrafx + + + + beetle_supergrafx + + + + + + snes + Super Nintendo + Nintendo + 1991 + console + /storage/roms/snes + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + snes + snes + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + snesh + Super Nintendo (Hacks) + Nintendo + 1991 + console + /storage/roms/snesh + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + snes + snesh + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + sfc + Super Famicom + Nintendo + 1990 + console + /storage/roms/sfc + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + snes + sfc + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + satellaview + Satellaview + Nintendo + 1995 + console + /storage/roms/satellaview + .smc .SMC .fig .FIG .bs .BS .sfc .SFC .bsx .BSX .swc .SWC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + satellaview + satellaview + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + + + + + + sufami + SuFami Turbo + Bandai + 1996 + console + /storage/roms/sufami + .st .ST .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + sufami + sufami + + + + snes9x + + + + + + solarus + Solarus + Solarus + 2020 + game engine + /storage/roms/solarus + .solarus + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + solarus + solarus + + + + solarus + + + + + + supervision + Watara Supervision + Watara + 1992 + portable + /storage/roms/supervision + .sv .SV .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + supervision + supervision + + + + potator + + + + + + tic-80 + TIC-80 + Nesbox + 2017 + computer + /storage/roms/tic-80 + .tic .TIC + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + tic80 + tic-80 + + + + tic80 + + + + + + tg16 + TurboGrafx-16 + NEC + 1989 + console + /storage/roms/tg16 + .pce .PCE .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pcengine + tg16 + + + + beetle_pce_fast + beetle_supergrafx + + + + + + tg16cd + TurboGrafx-CD + NEC + 1989 + console + /storage/roms/tg16cd + .cue .CUE .ccd .CCD .chd .CHD .toc .TOC .m3u .M3U + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pcenginecd + tg16cd + + + + beetle_pce_fast + beetle_supergrafx + + + + + + uzebox + Uzebox + belogic + 2008 + console + /storage/roms/uzebox + .uze .UZE + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + uzebox + uzebox + + + + uzem + + + + + + vectrex + Vectrex + Milton Bradley + 1982 + console + /storage/roms/vectrex + .bin .BIN .gam .GAM .vec .VEC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + vectrex + vectrex + + + + vecx + + + + + + videopac + VideoPac + Philips + 1978 + console + /storage/roms/videopac + .bin .BIN .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + videopac + videopac + + + + o2em + + + + + + virtualboy + Virtual Boy + Nintendo + 1995 + console + /storage/roms/virtualboy + .vb .VB .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + virtualboy + virtualboy + + + + beetle_vb + + + + + + wonderswan + Wonderswan + Bandai + 1999 + portable + /storage/roms/wonderswan + .ws .WS .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + wonderswan + wonderswan + + + + beetle_wswan + + + + + + wonderswancolor + Wonderswan Color + Bandai + 2000 + portable + /storage/roms/wonderswancolor + .wsc .WSC .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + wonderswancolor + wonderswancolor + + + + beetle_wswan + + + + + + x68000 + x68000 + Sharp + 1987 + computer + /storage/roms/x68000 + .dim .DIM .img .IMG .d88 .D88 .88d .88D .hdm .HDM .dup .DUP .2hd .2HD .xdf .XDF .hdf .HDF .cmd .CMD .m3u .M3U .zip .ZIP .7z .7Z + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + x68000 + x68000 + + + + px68k + + + + + + ecwolf + Wolfenstein 3D + id Software + 1992 + game engine + /storage/roms/ecwolf + .ecwolf + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + ecwolf + + + + ecwolf + + + + + + doom + Doom + id Software + 1993 + game engine + /storage/roms/doom + .doom + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + doom + + + + gzdoom + + + + + lzdoom + + + + + prboom + + + + + + build + Build Engine + 3D Realms + 1995 + game engine + /storage/roms/build + .build + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + build + + + + raze + + + + + + mplayer + MPlayer + Various + unknown + system + /storage/roms/mplayer + .mp4 .MP4 .mkv .MKV .avi .AVI .mov .MOV .wmv .WMV .m3u .M3U .mpg .MPG .ytb .YTB .twi .TWI .sh .SH + /usr/bin/runemu.sh %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + mplayer + mplayer + + + + mpv + + + + + + tools +  Tools + Various + unknown + system + /storage/.config/distribution/modules + .sh + /usr/bin/runemu.sh %ROM% -Pshell + tools + tools + + + Screenshots + imageviewer + Various + unknown + system + /roms/screenshots + .jpg .jpeg .png .bmp .psd .tga .gif .hdr .pic .ppm .pgm .mkv .pdf .mp4 .avi + /usr/bin/true + imageviewer + imageviewer + + diff --git a/packages/ui/emulationstation/config/scripts/es_env.sh b/packages/ui/emulationstation/config/scripts/es_env.sh new file mode 100755 index 000000000..e7eb67cb7 --- /dev/null +++ b/packages/ui/emulationstation/config/scripts/es_env.sh @@ -0,0 +1,4 @@ +HOME=/storage +LD_LIBRARY_PATH=/usr/lib:/usr/lib/pulseaudio +PATH=/usr/bin:/usr/sbin:/usr/local/bin:/storage/.config/emulationstation/scripts:/storage/bin +SDL_AUDIODRIVER=alsa diff --git a/packages/ui/emulationstation/package.mk b/packages/ui/emulationstation/package.mk new file mode 100644 index 000000000..3b3c21f09 --- /dev/null +++ b/packages/ui/emulationstation/package.mk @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +PKG_NAME="emulationstation" +PKG_GIT_CLONE_BRANCH="main" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/JustEnoughLinuxOS/emulationstation" +PKG_URL="$PKG_SITE.git" +PKG_VERSION="861fd6a" +PKG_DEPENDS_TARGET="boost toolchain SDL2 freetype curl freeimage bash rapidjson ${OPENGLES} SDL2_mixer fping p7zip vlc" +PKG_NEED_UNPACK="busybox" +PKG_SHORTDESC="Emulationstation emulator frontend" +PKG_BUILD_FLAGS="-gold" +GET_HANDLER_SUPPORT="git" + +PKG_PATCH_DIRS="${DEVICE}" + +# themes for Emulationstation +PKG_DEPENDS_TARGET="${PKG_DEPENDS_TARGET} es-theme-art-book-next" + +PKG_CMAKE_OPTS_TARGET=" -DENABLE_EMUELEC=1 -DGLES2=1 -DDISABLE_KODI=1 -DENABLE_FILEMANAGER=0 -DCEC=0" + +pre_configure_target() { + if [ -f ~/developer_settings.conf ]; then + . ~/developer_settings.conf + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/locale + cp -rf $PKG_BUILD/locale/lang/* $INSTALL/usr/config/locale/ + + mkdir -p $INSTALL/usr/lib + ln -sf /storage/.config/emulationstation/locale $INSTALL/usr/lib/locale + + mkdir -p $INSTALL/usr/config/emulationstation/resources + cp -rf $PKG_BUILD/resources/* $INSTALL/usr/config/emulationstation/resources/ + rm -rf $INSTALL/usr/config/emulationstation/resources/logo.png + + mkdir -p $INSTALL/usr/lib/python2.7 + cp -rf $PKG_DIR/bluez/* $INSTALL/usr/lib/python2.7 + + mkdir -p $INSTALL/usr/bin + ln -sf /storage/.config/emulationstation/resources $INSTALL/usr/bin/resources + cp -rf $PKG_BUILD/emulationstation $INSTALL/usr/bin + + mkdir -p $INSTALL/etc/emulationstation/ + ln -sf /storage/.config/emulationstation/themes $INSTALL/etc/emulationstation/ + ln -sf /usr/config/emulationstation/es_systems.cfg $INSTALL/etc/emulationstation/es_systems.cfg + + cp -rf $PKG_DIR/config/*.cfg $INSTALL/usr/config/emulationstation + cp -rf $PKG_DIR/config/scripts $INSTALL/usr/config/emulationstation + + if [ "${DEVICE}" == "RG552" ] + then + sed -i 's###' $INSTALL/usr/config/emulationstation/es_settings.cfg + fi + + chmod +x $INSTALL/usr/config/emulationstation/scripts/* + find $INSTALL/usr/config/emulationstation/scripts/ -type f -exec chmod o+x {} \; + + if [[ ${DEVICE} =~ RG351 ]]; then + sed -i "s|, vertical||g" "$INSTALL/usr/config/emulationstation/es_features.cfg" + fi +} + +post_install() { + mkdir -p $INSTALL/usr/share + ln -sf /storage/.config/emulationstation/locale $INSTALL/usr/share/locale +} diff --git a/packages/ui/emulationstation/system.d/emustation.service b/packages/ui/emulationstation/system.d/emustation.service new file mode 100644 index 000000000..d89c2623b --- /dev/null +++ b/packages/ui/emulationstation/system.d/emustation.service @@ -0,0 +1,17 @@ +[Unit] +Description=EmulationStation emulator frontend +ConditionPathExists=/var/lock/start.games + +[Service] +Environment=HOME=/storage +EnvironmentFile=/storage/.config/emulationstation/scripts/es_env.sh +ExecStartPre=/usr/bin/emustation-config +ExecStart=/usr/bin/emulationstation --log-path /var/log +KillMode=process +TimeoutStopSec=3 +Restart=always +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=jelos.target diff --git a/packages/ui/emulationstation/themes/alekfull-nx/package.mk b/packages/ui/emulationstation/themes/alekfull-nx/package.mk new file mode 100644 index 000000000..245bb81bb --- /dev/null +++ b/packages/ui/emulationstation/themes/alekfull-nx/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +PKG_NAME="alekfull-nx" +PKG_REV="1" +PKG_VERSION="c365f69a9d9ad70e288de0d5c796f19c729c064f" +PKG_ARCH="any" +PKG_LICENSE="unknown" +PKG_SITE="https://github.com/fagnerpc/Alekfull-NX" +PKG_URL="$PKG_SITE.git" +GET_HANDLER_SUPPORT="git" +PKG_SHORTDESC="ALEKFULL NX theme" +PKG_LONGDESC="ALEKFULL NX theme" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + cp -rf * $INSTALL/usr/config/emulationstation/themes/$PKG_NAME +} diff --git a/packages/ui/emulationstation/themes/es-theme-art-book-3-2/package.mk b/packages/ui/emulationstation/themes/es-theme-art-book-3-2/package.mk new file mode 100644 index 000000000..0dcdb2a97 --- /dev/null +++ b/packages/ui/emulationstation/themes/es-theme-art-book-3-2/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020 Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) + +PKG_NAME="es-theme-art-book-3-2" +PKG_REV="1" +PKG_VERSION="5b27f5548c7a4ec23408d7e6fddd3983b894838d" +PKG_ARCH="any" +PKG_LICENSE="CUSTOM" +PKG_SITE="https://github.com/anthonycaccese/es-theme-art-book-3-2" +PKG_URL="$PKG_SITE.git" +GET_HANDLER_SUPPORT="git" +PKG_SHORTDESC="ArtBook" +PKG_LONGDESC="Art Book - 351ELEC default theme for RG351P/M" +PKG_TOOLCHAIN="manual" + +if [ "${DEVICE}" == "RG351P" ] || [ "${DEVICE}" == "RG552" ] +then + makeinstall_target() { + mkdir -p $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + cp -rf * $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + } +fi diff --git a/packages/ui/emulationstation/themes/es-theme-art-book-4-3/package.mk b/packages/ui/emulationstation/themes/es-theme-art-book-4-3/package.mk new file mode 100644 index 000000000..b5a946c37 --- /dev/null +++ b/packages/ui/emulationstation/themes/es-theme-art-book-4-3/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020 Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2021 351ELEC team (https://github.com/351ELEC/351ELEC) + +PKG_NAME="es-theme-art-book-4-3" +PKG_REV="1" +PKG_VERSION="6b4c29171887d43493db911d9d9e551649167829" +PKG_ARCH="any" +PKG_LICENSE="CUSTOM" +PKG_SITE="https://github.com/szalik-rg351/es-theme-art-book-4-3" +PKG_URL="$PKG_SITE.git" +GET_HANDLER_SUPPORT="git" +PKG_SHORTDESC="ArtBook" +PKG_LONGDESC="Art Book - 351ELEC default theme for the RG351V/MP" +PKG_TOOLCHAIN="manual" + + +if [ "${DEVICE}" = "RG351V" ] || [ "${DEVICE}" = "RG351MP" ]; then + makeinstall_target() { + mkdir -p $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + cp -rf * $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + } +fi diff --git a/packages/ui/emulationstation/themes/es-theme-art-book-next/package.mk b/packages/ui/emulationstation/themes/es-theme-art-book-next/package.mk new file mode 100644 index 000000000..643210ec9 --- /dev/null +++ b/packages/ui/emulationstation/themes/es-theme-art-book-next/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020 Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020 351ELEC team (https://github.com/fewtarius/351ELEC) + +PKG_NAME="es-theme-art-book-next" +PKG_REV="1" +PKG_VERSION="d3f07e9" +PKG_ARCH="any" +PKG_LICENSE="CUSTOM" +PKG_SITE="https://github.com/anthonycaccese/es-theme-art-book-next" +PKG_URL="$PKG_SITE.git" +GET_HANDLER_SUPPORT="git" +PKG_SHORTDESC="ArtBook" +PKG_LONGDESC="Art Book theme" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/emulationstation/themes/$PKG_NAME + cp -rf * $INSTALL/usr/config/emulationstation/themes/$PKG_NAME +} diff --git a/packages/virtual/alsa/package.mk b/packages/virtual/alsa/package.mk new file mode 100644 index 000000000..cff4e25ac --- /dev/null +++ b/packages/virtual/alsa/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="alsa" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.alsa-project.org/" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain alsa-lib alsa-utils" +PKG_SECTION="virtual" +PKG_LONGDESC="Matapackage to install all alsa components." diff --git a/packages/virtual/arm32/package.mk b/packages/virtual/arm32/package.mk new file mode 100644 index 000000000..2890eec66 --- /dev/null +++ b/packages/virtual/arm32/package.mk @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2022 - Fewtarius + +PKG_NAME="arm32" +PKG_LICENSE="GPL" +PKG_SITE="www.jelos.org" +PKG_DEPENDS_TARGET="toolchain squashfs-tools:host dosfstools:host fakeroot:host kmod:host mtools:host populatefs:host libc gcc linux linux-drivers linux-firmware unzip socat p7zip file ${OPENGLES} SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf retroarch pcsx_rearmed parallel-n64 parallel-n64_gln64" +PKG_SECTION="virtual" +PKG_LONGDESC="Root package used to build and create 32-bit userland" diff --git a/packages/virtual/autotools/package.mk b/packages/virtual/autotools/package.mk new file mode 100644 index 000000000..e201e386b --- /dev/null +++ b/packages/virtual/autotools/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="autotools" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_HOST="ccache:host autoconf:host automake:host intltool:host libtool:host autoconf-archive:host" +PKG_SECTION="virtual" +PKG_LONGDESC="autotools: Metapackage" diff --git a/packages/virtual/corefonts/package.mk b/packages/virtual/corefonts/package.mk new file mode 100644 index 000000000..c269c60b3 --- /dev/null +++ b/packages/virtual/corefonts/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="corefonts" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain" +PKG_SECTION="virtual" +PKG_LONGDESC="corefonts is a Metapackage for installing fonts" + +if [ -n "$CUSTOM_FONTS" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $CUSTOM_FONTS" +else + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET liberation-fonts-ttf" +fi diff --git a/packages/virtual/debug/package.mk b/packages/virtual/debug/package.mk new file mode 100644 index 000000000..49b0aa1d1 --- /dev/null +++ b/packages/virtual/debug/package.mk @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="debug" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain gdb apitrace valgrind strace edid-decode memtester" +PKG_SECTION="virtual" +PKG_LONGDESC="debug is a Metapackage for installing debugging tools" + +# configure GPU drivers and dependencies: + get_graphicdrivers + +if [ "$VDPAU_SUPPORT" = "yes" -a "$DISPLAYSERVER" = "x11" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET vdpauinfo" +fi + +if [ "$VAAPI_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libva-utils" +fi + +if build_with_debug && [ "$VALGRIND" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET valgrind" +fi diff --git a/packages/virtual/image/package.mk b/packages/virtual/image/package.mk new file mode 100644 index 000000000..cc3bd840b --- /dev/null +++ b/packages/virtual/image/package.mk @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="image" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_DEPENDS_TARGET="toolchain squashfs-tools:host dosfstools:host fakeroot:host kmod:host mtools:host populatefs:host libc gcc linux linux-drivers linux-firmware ${BOOTLOADER} busybox util-linux corefonts network misc-packages debug usb-modeswitch unzip poppler socat p7zip file jelos" +PKG_SECTION="virtual" +PKG_LONGDESC="Root package used to build and create complete image" + +# Graphic support +[ ! "$DISPLAYSERVER" = "no" ] && PKG_DEPENDS_TARGET+=" $DISPLAYSERVER" + +# Multimedia support +[ ! "$MEDIACENTER" = "no" ] && PKG_DEPENDS_TARGET+=" mediacenter" + +# Sound support +[ "$ALSA_SUPPORT" = "yes" ] && PKG_DEPENDS_TARGET+=" alsa" + +# Automounter support +[ "$UDEVIL" = "yes" ] && PKG_DEPENDS_TARGET+=" udevil" + +# EXFAT support +[ "$EXFAT" = "yes" ] && PKG_DEPENDS_TARGET+=" exfat exfatprogs" + +# NTFS 3G support +[ "$NTFS3G" = "yes" ] && PKG_DEPENDS_TARGET+=" ntfs-3g_ntfsprogs" + +# Remote support +[ "$REMOTE_SUPPORT" = "yes" ] && PKG_DEPENDS_TARGET+=" remote" + +# Virtual image creation support +[ "$PROJECT" = "Generic" ] && PKG_DEPENDS_TARGET+=" virtual" + +# Installer support +[ "$INSTALLER_SUPPORT" = "yes" ] && PKG_DEPENDS_TARGET+=" installer" + +# Devtools... (not for Release) +[ "$TESTING" = "yes" ] && PKG_DEPENDS_TARGET+=" testing" + +# OEM packages +[ "$OEM_SUPPORT" = "yes" ] && PKG_DEPENDS_TARGET+=" oem" + +# htop +[ "$HTOP_TOOL" = "yes" ] && PKG_DEPENDS_TARGET+=" htop" + +true diff --git a/packages/virtual/initramfs/package.mk b/packages/virtual/initramfs/package.mk new file mode 100644 index 000000000..3b656a13e --- /dev/null +++ b/packages/virtual/initramfs/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="initramfs" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain libc:init busybox:init linux:init plymouth-lite:init util-linux:init e2fsprogs:init dosfstools:init exfat:init fakeroot:host terminus-font:init" +PKG_SECTION="virtual" +PKG_LONGDESC="debug is a Metapackage for installing initramfs" + +if [ "$ISCSI_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET open-iscsi:init" +fi + +if [ "$INITRAMFS_PARTED_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET parted:init" +fi + +post_install() { + ( cd $BUILD/initramfs + if [ "$TARGET_ARCH" = "x86_64" ]; then + ln -sfn /usr/lib $BUILD/initramfs/lib64 + mkdir -p $BUILD/initramfs/usr + ln -sfn /usr/lib $BUILD/initramfs/usr/lib64 + fi + + ln -sfn /usr/lib $BUILD/initramfs/lib + ln -sfn /usr/bin $BUILD/initramfs/bin + ln -sfn /usr/sbin $BUILD/initramfs/sbin + + mkdir -p $BUILD/image/ + fakeroot -- sh -c \ + "mkdir -p dev; mknod -m 600 dev/console c 5 1; find . | cpio -H newc -ov -R 0:0 > $BUILD/image/initramfs.cpio" + ) +} diff --git a/packages/virtual/libc/package.mk b/packages/virtual/libc/package.mk new file mode 100644 index 000000000..01f646d18 --- /dev/null +++ b/packages/virtual/libc/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libc" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain glibc tz libidn2" +PKG_DEPENDS_INIT="toolchain glibc:init" +PKG_SECTION="virtual" +PKG_LONGDESC="Meta package for installing various tools and libs needed for libc" + +if [ "${TARGET_ARCH}" = "arm" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET arm-mem" + PKG_DEPENDS_INIT="$PKG_DEPENDS_INIT arm-mem:init" +fi diff --git a/packages/virtual/linux-drivers/package.mk b/packages/virtual/linux-drivers/package.mk new file mode 100644 index 000000000..5933bc45e --- /dev/null +++ b/packages/virtual/linux-drivers/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="linux-drivers" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain $ADDITIONAL_DRIVERS" +PKG_SECTION="virtual" +PKG_LONGDESC="linux-drivers is a Meta package to install additional drivers" + +if [ "$DRIVER_ADDONS_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $DRIVER_ADDONS driverselect" +fi diff --git a/packages/virtual/linux-firmware/package.mk b/packages/virtual/linux-firmware/package.mk new file mode 100644 index 000000000..fa377ebba --- /dev/null +++ b/packages/virtual/linux-firmware/package.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="linux-firmware" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain $FIRMWARE" +PKG_SECTION="virtual" +PKG_LONGDESC="linux-firmware is a meta-package to install various free firmware drivers" diff --git a/packages/virtual/mediacenter/package.mk b/packages/virtual/mediacenter/package.mk new file mode 100644 index 000000000..b23705c80 --- /dev/null +++ b/packages/virtual/mediacenter/package.mk @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="mediacenter" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain $MEDIACENTER" +PKG_SECTION="virtual" +PKG_LONGDESC="Mediacenter: Metapackage" + +if [ "$MEDIACENTER" = "kodi" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $MEDIACENTER-theme-$SKIN_DEFAULT" + + for i in $SKINS; do + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $MEDIACENTER-theme-$i" + done + +# python-based tool for kodi management + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET texturecache.py" + +# some python stuff needed for various addons + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET Pillow \ + simplejson \ + pycryptodome" + +# settings addon + if [ -n "$DISTRO_PKG_SETTINGS" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $DISTRO_PKG_SETTINGS" + fi + +# other packages + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xmlstarlet" + + if [ "$JOYSTICK_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET peripheral.joystick" + fi + + get_graphicdrivers + if listcontains "$GRAPHIC_DRIVERS" "(i915|i965)"; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET intel-vaapi-driver" + fi + +fi diff --git a/packages/virtual/misc-packages/package.mk b/packages/virtual/misc-packages/package.mk new file mode 100644 index 000000000..a5084bbf5 --- /dev/null +++ b/packages/virtual/misc-packages/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="misc-packages" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain Python3 ${ADDITIONAL_PACKAGES}" +PKG_SECTION="virtual" +PKG_LONGDESC="misc-packages: Metapackage for miscellaneous packages" + +# Entware support +if [ "$ENTWARE_SUPPORT" = "yes" ]; then + ln -sf /storage/.opt $INSTALL/opt + PKG_DEPENDS_TARGET+=" entware" +fi diff --git a/packages/virtual/network/package.mk b/packages/virtual/network/package.mk new file mode 100644 index 000000000..049465b51 --- /dev/null +++ b/packages/virtual/network/package.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +PKG_NAME="network" +PKG_VERSION="" +PKG_LICENSE="various" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain connman netbase ethtool openssh iw rsync" +PKG_SECTION="virtual" +PKG_LONGDESC="Metapackage for various packages to install network support" + +if [ "$BLUETOOTH_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET bluez" +fi + +if [ "$SAMBA_SERVER" = "yes" ] || [ "$SAMBA_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET samba" +fi + +if [ "$OPENVPN_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET openvpn" +fi + +if [ "$WIREGUARD_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET wireguard-tools wireguard-linux-compat" +fi + +# nss needed by inputstream.adaptive, chromium etc. +if [ "$TARGET_ARCH" = "x86_64" ] || [ "$TARGET_ARCH" = "arm" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET nss" +fi diff --git a/packages/virtual/remote/package.mk b/packages/virtual/remote/package.mk new file mode 100644 index 000000000..4483f4029 --- /dev/null +++ b/packages/virtual/remote/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="remote" +PKG_VERSION="1" +PKG_LICENSE="GPL" +PKG_SITE="http://www.openelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain libirman v4l-utils" +PKG_SECTION="virtual" +PKG_LONGDESC="Meta package for installing various tools needed for remote support" + +if [ "$AMREMOTE_SUPPORT" = "yes" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET amremote" +fi diff --git a/packages/virtual/toolchain/package.mk b/packages/virtual/toolchain/package.mk new file mode 100644 index 000000000..2231b828b --- /dev/null +++ b/packages/virtual/toolchain/package.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="toolchain" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="https://libreelec.tv" +PKG_URL="" +PKG_DEPENDS_HOST="autoconf:host autoconf-archive:host automake:host bison:host configtools:host cmake:host flex:host intltool:host libtool:host ninja:host make:host meson:host p7zip:host pigz:host sed:host xmlstarlet:host xz:host" +PKG_DEPENDS_TARGET="toolchain:host gcc:host" +PKG_SECTION="virtual" +PKG_LONGDESC="LibreELEC.tv' toolchain to compile all packages" diff --git a/packages/virtual/virtual/package.mk b/packages/virtual/virtual/package.mk new file mode 100644 index 000000000..a6cfaef8d --- /dev/null +++ b/packages/virtual/virtual/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="virtual" +PKG_VERSION="" +PKG_LICENSE="GPL" +PKG_SITE="http://www.libreelec.tv" +PKG_URL="" +PKG_DEPENDS_TARGET="qemu:host" +PKG_SECTION="virtual" +PKG_LONGDESC="virtual is a Meta package to install Virtual project extra dependencies" + +get_graphicdrivers + +listcontains "$GRAPHIC_DRIVERS" "vmware" && PKG_DEPENDS_TARGET+=" open-vm-tools" || true diff --git a/packages/virtual/x11/package.mk b/packages/virtual/x11/package.mk new file mode 100644 index 000000000..bd18d16ab --- /dev/null +++ b/packages/virtual/x11/package.mk @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="x11" +PKG_VERSION="" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="" +PKG_DEPENDS_TARGET="toolchain xorg-server" +PKG_SECTION="virtual" +PKG_LONGDESC="X11 is the Windowing system" + +# Additional packages we need for using xorg-server: +# Fonts + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET encodings font-xfree86-type1 font-bitstream-type1 font-misc-misc" + +# Server + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xkeyboard-config xkbcomp" + +# Tools + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xrandr setxkbmap" + +if [ -n "$WINDOWMANAGER" -a "$WINDOWMANAGER" != "none" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $WINDOWMANAGER" +fi + +get_graphicdrivers + +# Drivers +if [ -n "$LIBINPUT" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xf86-input-libinput" +else + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xf86-input-evdev xf86-input-synaptics" +fi + +for drv in $XORG_DRIVERS; do + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET xf86-video-$drv" +done diff --git a/packages/wayland/libinput/package.mk b/packages/wayland/libinput/package.mk new file mode 100644 index 000000000..739fa4189 --- /dev/null +++ b/packages/wayland/libinput/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="libinput" +PKG_VERSION="1.19.2" +PKG_SHA256="0fc39f0af3ee1a77c60c34bc45391a4d0879169f7c0f7bbbeb5eef590b98b883" +PKG_LICENSE="GPL" +PKG_SITE="http://www.freedesktop.org/wiki/Software/libinput/" +PKG_URL="http://www.freedesktop.org/software/libinput/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain systemd libevdev mtdev" +PKG_LONGDESC="libinput is a library to handle input devices in Wayland compositors and to provide a generic X.Org input driver." + +PKG_MESON_OPTS_TARGET="-Dlibwacom=false \ + -Ddebug-gui=false \ + -Dtests=false \ + -Ddocumentation=false" diff --git a/packages/wayland/libxkbcommon/package.mk b/packages/wayland/libxkbcommon/package.mk new file mode 100644 index 000000000..aa3c3d676 --- /dev/null +++ b/packages/wayland/libxkbcommon/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxkbcommon" +PKG_VERSION="1.3.1" +PKG_SHA256="b3c710d27a2630054e1e1399c85b7f330ef03359b460f0c1b3b587fd01fe9234" +PKG_LICENSE="MIT" +PKG_SITE="http://xkbcommon.org" +PKG_URL="http://xkbcommon.org/download/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain xkeyboard-config libxml2" +PKG_LONGDESC="xkbcommon is a library to handle keyboard descriptions." + +PKG_MESON_OPTS_TARGET="-Denable-docs=false" + +if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_MESON_OPTS_TARGET+=" -Denable-x11=true \ + -Denable-wayland=false" +elif [ "${DISPLAYSERVER}" = "weston" ]; then + PKG_MESON_OPTS_TARGET+=" -Denable-x11=false \ + -Denable-wayland=true" +else + PKG_MESON_OPTS_TARGET+=" -Denable-x11=false \ + -Denable-wayland=false" +fi + +pre_configure_target() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + TARGET_LDFLAGS="${LDFLAGS} -lXau -lxcb" + fi +} diff --git a/packages/wayland/mtdev/package.mk b/packages/wayland/mtdev/package.mk new file mode 100644 index 000000000..5ccb990ed --- /dev/null +++ b/packages/wayland/mtdev/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="mtdev" +PKG_VERSION="1.1.6" +PKG_SHA256="15d7b28da8ac71d8bc8c9287c2045fd174267bc740bec10cfda332dc1204e0e0" +PKG_LICENSE="MIT" +PKG_SITE="http://bitmath.org" +PKG_URL="http://bitmath.org/code/mtdev/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="The mtdev is a stand-alone library which transforms all variants of kernel MT events to the slotted type B protocol." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/wayland/wayland-protocols/package.mk b/packages/wayland/wayland-protocols/package.mk new file mode 100644 index 000000000..4f5ccba24 --- /dev/null +++ b/packages/wayland/wayland-protocols/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wayland-protocols" +PKG_VERSION="1.24" +PKG_SHA256="bff0d8cffeeceb35159d6f4aa6bab18c807b80642c9d50f66cba52ecf7338bc2" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://wayland.freedesktop.org/releases/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain wayland:host" +PKG_LONGDESC="Specifications of extended Wayland protocols" + +PKG_MESON_OPTS_TARGET="-Dtests=false" + +post_makeinstall_target() { + safe_remove ${INSTALL} +} diff --git a/packages/wayland/wayland/package.mk b/packages/wayland/wayland/package.mk new file mode 100644 index 000000000..aadbfc47b --- /dev/null +++ b/packages/wayland/wayland/package.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="wayland" +PKG_VERSION="1.20.0" +PKG_SHA256="b8a034154c7059772e0fdbd27dbfcda6c732df29cae56a82274f6ec5d7cd8725" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://wayland.freedesktop.org/releases/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="libffi:host expat:host libxml2:host" +PKG_DEPENDS_TARGET="toolchain wayland:host libffi expat libxml2" +PKG_LONGDESC="a display server protocol" + +PKG_MESON_OPTS_HOST="-Dlibraries=false \ + -Dscanner=true \ + -Ddocumentation=false \ + -Ddtd_validation=false" + +PKG_MESON_OPTS_TARGET="-Dlibraries=true \ + -Dscanner=false \ + -Ddocumentation=false \ + -Ddtd_validation=false" + +pre_configure_target() { + # wayland does not build with NDEBUG (requires assert for tests) + export TARGET_CFLAGS=$(echo ${TARGET_CFLAGS} | sed -e "s|-DNDEBUG||g") +} + +post_makeinstall_host() { + cp ${TOOLCHAIN}/lib/pkgconfig/wayland-scanner.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig/ +} diff --git a/packages/wayland/waylandpp/package.mk b/packages/wayland/waylandpp/package.mk new file mode 100644 index 000000000..d7ef51f5a --- /dev/null +++ b/packages/wayland/waylandpp/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="waylandpp" +PKG_VERSION="0.2.8" +PKG_SHA256="e7f486165d3568c3558b5c7099133aea4a285b82820eeafad329fc10271c654d" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/NilsBrause/waylandpp" +PKG_URL="https://github.com/NilsBrause/waylandpp/archive/${PKG_VERSION}.tar.gz" +PKG_DEPENDS_HOST="toolchain:host pugixml:host" +PKG_DEPENDS_TARGET="toolchain pugixml:host waylandpp:host wayland" +PKG_LONGDESC="Wayland C++ bindings" + +configure_package() { + if [ "${OPENGL_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL}" + elif [ "${OPENGLES_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGLES}" + fi +} + +PKG_CMAKE_OPTS_HOST="-DBUILD_SCANNER=ON \ + -DBUILD_LIBRARIES=OFF" + +PKG_CMAKE_OPTS_TARGET="-DBUILD_SCANNER=OFF \ + -DBUILD_LIBRARIES=ON \ + -DCMAKE_CROSSCOMPILING=ON \ + -DWAYLAND_SCANNERPP=${TOOLCHAIN}/bin/wayland-scanner++" diff --git a/packages/wayland/weston/config/weston.ini b/packages/wayland/weston/config/weston.ini new file mode 100644 index 000000000..196e43484 --- /dev/null +++ b/packages/wayland/weston/config/weston.ini @@ -0,0 +1,16 @@ +[core] +idle-time=0 + +[shell] +locking=false +background-color=0x00000000 +background-image=/usr/share/weston/splash-2160.png +background-type=scale-crop + +[launcher] +path=/usr/lib/kodi/kodi.bin +icon=/usr/share/kodi/media/icon16x16.png + +[launcher] +icon=/usr/share/weston/terminal.png +path=/usr/bin/weston-terminal diff --git a/packages/wayland/weston/package.mk b/packages/wayland/weston/package.mk new file mode 100644 index 000000000..c729a35fb --- /dev/null +++ b/packages/wayland/weston/package.mk @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="weston" +PKG_VERSION="9.0.0" +PKG_SHA256="5cf5d6ce192e0eb15c1fc861a436bf21b5bb3b91dbdabbdebe83e1f83aa098fe" +PKG_LICENSE="OSS" +PKG_SITE="https://wayland.freedesktop.org/" +PKG_URL="https://wayland.freedesktop.org/releases/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain wayland wayland-protocols libdrm libxkbcommon libinput cairo libjpeg-turbo dbus" +PKG_LONGDESC="Reference implementation of a Wayland compositor" + +PKG_MESON_OPTS_TARGET="-Dbackend-drm-screencast-vaapi=false \ + -Dbackend-headless=false \ + -Dbackend-rdp=false \ + -Dscreenshare=false \ + -Dbackend-x11=false \ + -Dbackend-fbdev=false \ + -Dweston-launch=false \ + -Dxwayland=false \ + -Dremoting=false \ + -Dpipewire=false \ + -Dshell-fullscreen=false \ + -Dshell-ivi=false \ + -Dcolor-management-lcms=false \ + -Dcolor-management-colord=false \ + -Dimage-webp=false \ + -Ddemo-clients=false \ + -Dsimple-clients=egl \ + -Dresize-pool=false \ + -Dwcap-decode=false \ + -Dtest-junit-xml=false" + +pre_configure_target() { + # weston does not build with NDEBUG (requires assert for tests) + export TARGET_CFLAGS=$(echo ${TARGET_CFLAGS} | sed -e "s|-DNDEBUG||g") +} + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/lib/weston + cp ${PKG_DIR}/scripts/weston-config ${INSTALL}/usr/lib/weston + + mkdir -p ${INSTALL}/usr/share/weston + cp ${PKG_DIR}/config/weston.ini ${INSTALL}/usr/share/weston + find_file_path "splash/splash-2160.png" && cp ${FOUND_PATH} ${INSTALL}/usr/share/weston + + safe_remove ${INSTALL}/usr/share/wayland-sessions + safe_remove ${INSTALL}/usr/bin/weston-calibrator + safe_remove ${INSTALL}/usr/bin/weston-simple-* + safe_remove ${INSTALL}/usr/bin/weston-touch-calibrator +} + +post_install() { + enable_service weston.service +} diff --git a/packages/wayland/weston/profile.d/04-weston.conf b/packages/wayland/weston/profile.d/04-weston.conf new file mode 100644 index 000000000..52ed075aa --- /dev/null +++ b/packages/wayland/weston/profile.d/04-weston.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +export XDG_RUNTIME_DIR=/var/run/0-runtime-dir diff --git a/packages/wayland/weston/scripts/weston-config b/packages/wayland/weston/scripts/weston-config new file mode 100755 index 000000000..db28264db --- /dev/null +++ b/packages/wayland/weston/scripts/weston-config @@ -0,0 +1,15 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +export XDG_RUNTIME_DIR=/var/run/0-runtime-dir + +if [ ! -d "$XDG_RUNTIME_DIR" ]; then + mkdir "$XDG_RUNTIME_DIR" + chmod 0700 "$XDG_RUNTIME_DIR" +fi + +if [ ! -f /storage/.config/weston.ini ]; then + cp /usr/share/weston/weston.ini /storage/.config/weston.ini +fi diff --git a/packages/wayland/weston/system.d/weston.service b/packages/wayland/weston/system.d/weston.service new file mode 100644 index 000000000..a776af3df --- /dev/null +++ b/packages/wayland/weston/system.d/weston.service @@ -0,0 +1,18 @@ +[Unit] +Description=Weston Launcher +Before=graphical.target +After=multi-user.target +ConditionKernelCommandLine=!installer + +[Service] +Environment=HOME=/storage +Environment=XDG_RUNTIME_DIR=/var/run/0-runtime-dir +WorkingDirectory=/storage +ExecStartPre=-/usr/lib/weston/weston-config +ExecStart=/usr/bin/weston --tty=1 --log=/var/log/weston.log +Restart=always +RestartSec=10 + +[Install] +Alias=display-manager.service +WantedBy=graphical.target diff --git a/packages/web/curl/package.mk b/packages/web/curl/package.mk new file mode 100644 index 000000000..dd1725f64 --- /dev/null +++ b/packages/web/curl/package.mk @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="curl" +PKG_VERSION="7.80.0" +PKG_SHA256="a132bd93188b938771135ac7c1f3ac1d3ce507c1fcbef8c471397639214ae2ab" +PKG_LICENSE="MIT" +PKG_SITE="https://curl.haxx.se" +PKG_URL="https://curl.haxx.se/download/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain zlib openssl rtmpdump libidn2 nghttp2" +PKG_LONGDESC="Client and library for (HTTP, HTTPS, FTP, ...) transfers." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_lib_rtmp_RTMP_Init=yes \ + ac_cv_header_librtmp_rtmp_h=yes \ + --disable-debug \ + --enable-optimize \ + --enable-warnings \ + --disable-curldebug \ + --disable-ares \ + --enable-largefile \ + --enable-http \ + --enable-ftp \ + --enable-file \ + --disable-ldap \ + --disable-ldaps \ + --enable-rtsp \ + --enable-proxy \ + --disable-dict \ + --disable-telnet \ + --disable-tftp \ + --disable-pop3 \ + --disable-imap \ + --disable-smb \ + --disable-smtp \ + --disable-gopher \ + --disable-mqtt \ + --disable-manual \ + --enable-libgcc \ + --enable-ipv6 \ + --enable-versioned-symbols \ + --enable-nonblocking \ + --enable-threaded-resolver \ + --enable-verbose \ + --disable-sspi \ + --enable-crypto-auth \ + --enable-cookies \ + --enable-symbol-hiding \ + --disable-soname-bump \ + --with-gnu-ld \ + --without-krb4 \ + --without-spnego \ + --without-gssapi \ + --with-zlib \ + --without-brotli \ + --without-zstd \ + --without-egd-socket \ + --enable-thread \ + --with-random=/dev/urandom \ + --without-gnutls \ + --with-ssl \ + --without-mbedtls \ + --without-nss \ + --with-ca-bundle=/run/libreelec/cacert.pem \ + --without-ca-path \ + --without-libpsl \ + --without-libssh2 \ + --with-librtmp \ + --with-libidn2 \ + --with-nghttp2" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share/zsh + + rm -rf ${INSTALL}/usr/bin/${PKG_NAME}-config + cp ${PKG_NAME}-config ${TOOLCHAIN}/bin + sed -e "s:\(['= ]\)/usr:\\1${PKG_ORIG_SYSROOT_PREFIX}/usr:g" -i ${TOOLCHAIN}/bin/${PKG_NAME}-config + chmod +x ${TOOLCHAIN}/bin/${PKG_NAME}-config +} diff --git a/packages/web/libmicrohttpd/package.mk b/packages/web/libmicrohttpd/package.mk new file mode 100644 index 000000000..40d9aae6e --- /dev/null +++ b/packages/web/libmicrohttpd/package.mk @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libmicrohttpd" +PKG_VERSION="0.9.73" +PKG_SHA256="a37b2f1b88fd1bfe74109586be463a434d34e773530fc2a74364cfcf734c032e" +PKG_LICENSE="LGPLv2.1" +PKG_SITE="http://www.gnu.org/software/libmicrohttpd/" +PKG_URL="http://ftpmirror.gnu.org/libmicrohttpd/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain gnutls" +PKG_LONGDESC="A small C library that is supposed to make it easy to run an HTTP server as part of another application." + +PKG_CONFIGURE_OPTS_TARGET="--disable-shared \ + --enable-static \ + --disable-curl \ + --enable-https" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/web/nghttp2/package.mk b/packages/web/nghttp2/package.mk new file mode 100644 index 000000000..3b7ae3e9d --- /dev/null +++ b/packages/web/nghttp2/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="nghttp2" +PKG_VERSION="1.45.1" +PKG_SHA256="abdc4addccadbc7d89abe27c4d6427d78e57d139f69c1f45749227393c68bf79" +PKG_LICENSE="MIT" +PKG_SITE="http://www.linuxfromscratch.org/blfs/view/cvs/basicnet/nghttp2.html" +PKG_URL="https://github.com/nghttp2/nghttp2/releases/download/v${PKG_VERSION}/nghttp2-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="nghttp2 is an implementation of HTTP/2 and its header compression algorithm, HPACK." +PKG_TOOLCHAIN="configure" + +PKG_CONFIGURE_OPTS_TARGET="--enable-lib-only" + +post_makeinstall_target() { + rm -r "${INSTALL}/usr/share" +} diff --git a/packages/x11/app/setxkbmap/package.mk b/packages/x11/app/setxkbmap/package.mk new file mode 100644 index 000000000..8c757e90f --- /dev/null +++ b/packages/x11/app/setxkbmap/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="setxkbmap" +PKG_VERSION="1.3.2" +PKG_SHA256="8ff27486442725e50b02d7049152f51d125ecad71b7ce503cfa09d5d8ceeb9f5" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/app/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libX11 libxkbfile" +PKG_LONGDESC="Setxkbmap sets the keyboard using the X Keyboard Extension." diff --git a/packages/x11/app/setxkbmap/udev.d/98-xorg-xkb.rules b/packages/x11/app/setxkbmap/udev.d/98-xorg-xkb.rules new file mode 100644 index 000000000..b6811876f --- /dev/null +++ b/packages/x11/app/setxkbmap/udev.d/98-xorg-xkb.rules @@ -0,0 +1,8 @@ +ACTION!="add|change", GOTO="xorg_xkb_end" +SUBSYSTEM!="input", GOTO="xorg_xkb_end" +KERNEL!="event*", GOTO="xorg_xkb_end" + +ENV{ID_INPUT_KEY}=="?*", IMPORT{file}="/storage/.cache/xkb/layout" + +LABEL="xorg_xkb_end" + diff --git a/packages/x11/app/xkbcomp/package.mk b/packages/x11/app/xkbcomp/package.mk new file mode 100644 index 000000000..c5e2b2859 --- /dev/null +++ b/packages/x11/app/xkbcomp/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xkbcomp" +PKG_VERSION="1.4.5" +PKG_SHA256="6851086c4244b6fd0cc562880d8ff193fb2bbf1e141c73632e10731b31d4b05e" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/app/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libxkbfile" +PKG_LONGDESC="The xkbcomp keymap compiler converts a description of an XKB keymap into one of several output formats." + +PKG_CONFIGURE_OPTS_TARGET="--with-xkb-config-root=${XORG_PATH_XKB}" diff --git a/packages/x11/app/xrandr/package.mk b/packages/x11/app/xrandr/package.mk new file mode 100644 index 000000000..375dd67e1 --- /dev/null +++ b/packages/x11/app/xrandr/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xrandr" +PKG_VERSION="1.5.1" +PKG_SHA256="7bc76daf9d72f8aff885efad04ce06b90488a1a169d118dea8a2b661832e8762" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/app/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros libXrandr" +PKG_LONGDESC="Xrandr is a primitive command line interface to the RandR extension and used to set the screen size, orientation and/or reflection." + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin/xkeystone +} diff --git a/packages/x11/data/xkeyboard-config/package.mk b/packages/x11/data/xkeyboard-config/package.mk new file mode 100644 index 000000000..46752d53f --- /dev/null +++ b/packages/x11/data/xkeyboard-config/package.mk @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xkeyboard-config" +PKG_VERSION="2.34" +PKG_SHA256="b321d27686ee7e6610ffe7b56e28d5bbf60625a1f595124cd320c0caa717b8ce" +PKG_LICENSE="MIT" +PKG_SITE="http://www.X.org" +PKG_URL="http://www.x.org/releases/individual/data/${PKG_NAME}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="X keyboard extension data files." +PKG_TOOLCHAIN="autotools" + +configure_package() { + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_DEPENDS_TARGET+=" xkbcomp" + fi +} + +pre_configure_target() { + PKG_CONFIGURE_OPTS_TARGET="--without-xsltproc \ + --enable-compat-rules \ + --disable-runtime-deps \ + --enable-nls \ + --disable-rpath \ + --with-gnu-ld" + + if [ "${DISPLAYSERVER}" = "x11" ]; then + PKG_CONFIGURE_OPTS_TARGET+=" XKBCOMP=/usr/bin/xkbcomp \ + --with-xkb-base=${XORG_PATH_XKB} \ + --with-xkb-rules-symlink=xorg" + fi +} diff --git a/packages/x11/data/xkeyboard-config/patches/xkeyboard-config-0001-dont-require-util-macros.patch b/packages/x11/data/xkeyboard-config/patches/xkeyboard-config-0001-dont-require-util-macros.patch new file mode 100644 index 000000000..a75bc1343 --- /dev/null +++ b/packages/x11/data/xkeyboard-config/patches/xkeyboard-config-0001-dont-require-util-macros.patch @@ -0,0 +1,39 @@ +diff -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2018-01-31 11:06:08.000000000 -0800 ++++ b/configure.ac 2018-12-05 16:32:04.016734637 -0800 +@@ -2,13 +2,6 @@ + AC_CONFIG_SRCDIR(rules/base.xml.in) + AM_INIT_AUTOMAKE([foreign dist-bzip2]) + +-# Require X.Org macros 1.12 or later for XORG_WITH_XSLTPROC +-m4_ifndef([XORG_MACROS_VERSION], +- [m4_fatal([must install xorg-macros 1.12 or later before +- running autoconf/autogen])]) +-XORG_MACROS_VERSION(1.12) +-XORG_MANPAGE_SECTIONS +-XORG_WITH_XSLTPROC + AC_PROG_SED + + AC_SUBST(VERSION) +diff -Naur a/man/Makefile.am b/man/Makefile.am +--- a/man/Makefile.am 2018-01-31 11:06:08.000000000 -0800 ++++ b/man/Makefile.am 2018-12-05 16:35:35.787618428 -0800 +@@ -1,18 +1,2 @@ + EXTRA_DIST = man.xsl + +-if HAVE_XSLTPROC +-miscmandir = $(MISC_MAN_DIR) +-miscman_PRE = xkeyboard-config.man +-miscman_DATA = $(miscman_PRE:man=@MISC_MAN_SUFFIX@) +-CLEANFILES = $(miscman_DATA) $(miscman_PRE) +-SUFFIXES = .$(MISC_MAN_SUFFIX) .man +-MAN_SUBSTS += -e 's|__xkb_base__|$(xkb_base)|g' +- +-xkeyboard-config.man: $(top_srcdir)/rules/evdev.xml $(srcdir)/man.xsl +- $(XSLTPROC) -nonet $(srcdir)/man.xsl $(top_srcdir)/rules/evdev.xml > $@ +- +-# First sed swaps @appmansuffix@ back to __appmansuffix__ for the MAN_SUBSTS +-.man.$(MISC_MAN_SUFFIX): +- $(SED) -e 's|@\(\<[a-z_]*\>\)@|__\1__|g' < $< | $(SED) $(MAN_SUBSTS) > $@ +- +-endif diff --git a/packages/x11/driver/xf86-input-evdev/package.mk b/packages/x11/driver/xf86-input-evdev/package.mk new file mode 100644 index 000000000..eacc3dfa6 --- /dev/null +++ b/packages/x11/driver/xf86-input-evdev/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-input-evdev" +PKG_VERSION="2.10.6" +PKG_SHA256="8726073e81861bc7b2321e76272cbdbd33c7e1a121535a9827977265b9033ec0" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain xorg-server util-macros libevdev mtdev systemd" +PKG_LONGDESC="Evdev is an Xorg input driver for Linux's generic event devices." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-silent-rules \ + --with-xorg-module-dir=${XORG_PATH_MODULES} \ + --with-gnu-ld" diff --git a/packages/x11/driver/xf86-input-libinput/package.mk b/packages/x11/driver/xf86-input-libinput/package.mk new file mode 100644 index 000000000..ee24fc971 --- /dev/null +++ b/packages/x11/driver/xf86-input-libinput/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-input-libinput" +PKG_VERSION="1.2.0" +PKG_SHA256="f80da3c514fe1cbf57fa1b1bd6ff97f6b0a1f87466ad89247bac59cd0a5869f6" +PKG_LICENSE="MIT" +PKG_SITE="http://www.freedesktop.org/wiki/Software/libinput/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libinput" +PKG_LONGDESC="This is an X driver based on libinput." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--with-xorg-module-dir=${XORG_PATH_MODULES}" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/X11/xorg.conf.d + cp ${PKG_BUILD}/conf/*-libinput.conf ${INSTALL}/usr/share/X11/xorg.conf.d +} diff --git a/packages/x11/driver/xf86-input-synaptics/package.mk b/packages/x11/driver/xf86-input-synaptics/package.mk new file mode 100644 index 000000000..cf98ea8f3 --- /dev/null +++ b/packages/x11/driver/xf86-input-synaptics/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-input-synaptics" +PKG_VERSION="1.9.1" +PKG_SHA256="7af83526eff1c76e8b9e1553b34245c203d029028d8044dd9dcf71eef1001576" +PKG_LICENSE="GPL" +PKG_SITE="http://lists.freedesktop.org/mailman/listinfo/xorg" +PKG_URL="http://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain xorg-server libXi libXext libevdev" +PKG_LONGDESC="Synaptics touchpad driver for X.Org." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--with-xorg-module-dir=${XORG_PATH_MODULES}" diff --git a/packages/x11/driver/xf86-video-amdgpu/package.mk b/packages/x11/driver/xf86-video-amdgpu/package.mk new file mode 100644 index 000000000..b332c6f67 --- /dev/null +++ b/packages/x11/driver/xf86-video-amdgpu/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-amdgpu" +PKG_VERSION="21.0.0" +PKG_SHA256="607823034defba6152050e5eb1c4df94b38819ef764291abadd81b620bc2ad88" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/wiki/RadeonFeature/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libdrm xorg-server" +PKG_LONGDESC="Xorg driver for AMD Radeon GPUs using the amdgpu kernel driver." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-udev \ + --enable-glamor \ + --with-xorg-module-dir=${XORG_PATH_MODULES}" + +post_makeinstall_target() { + rm -r ${INSTALL}/usr/share + mkdir -p ${INSTALL}/etc/X11 + cp ${PKG_BUILD}/conf/10-amdgpu.conf ${INSTALL}/etc/X11/xorg-amdgpu.conf +} diff --git a/packages/x11/driver/xf86-video-ati/config/xorg-radeon.conf b/packages/x11/driver/xf86-video-ati/config/xorg-radeon.conf new file mode 100644 index 000000000..b5de54afa --- /dev/null +++ b/packages/x11/driver/xf86-video-ati/config/xorg-radeon.conf @@ -0,0 +1,8 @@ +Section "Device" + Identifier "AMD Graphics" + Driver "radeon" + + # uncomment the following options to use DRI3 and glamor, otherwise DRI2 and exa + # Option "DRI3" "1" + # Option "AccelMethod" "glamor" +Endsection diff --git a/packages/x11/driver/xf86-video-ati/package.mk b/packages/x11/driver/xf86-video-ati/package.mk new file mode 100644 index 000000000..ea8e0839c --- /dev/null +++ b/packages/x11/driver/xf86-video-ati/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-ati" +PKG_VERSION="19.1.0" +PKG_SHA256="659f5a1629eea5f5334d9b39b18e6807a63aa1efa33c1236d9cc53acbb223c49" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/wiki/RadeonFeature/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain xorg-server" +PKG_LONGDESC="ATI/AMD Radeon video driver for the Xorg X server." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-glamor \ + --with-xorg-module-dir=${XORG_PATH_MODULES}" + +post_makeinstall_target() { + mkdir -p ${INSTALL}/etc/X11 + cp ${PKG_DIR}/config/*.conf ${INSTALL}/etc/X11 +} diff --git a/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.01-fix-gcc-10.patch b/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.01-fix-gcc-10.patch new file mode 100644 index 000000000..e0375b082 --- /dev/null +++ b/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.01-fix-gcc-10.patch @@ -0,0 +1,33 @@ +From f223035f4ffcff2a9296d1e907a5193f8e8845a3 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Tue, 4 Feb 2020 16:38:06 -0500 +Subject: [PATCH] Fix link failure with gcc 10 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without the 'extern' this looks like a definition not just a +declaration, in every file that includes the header. gcc 10 is stricter +about this kind of multiple definition. + +Reviewed-by: Michel Dänzer +--- + src/drmmode_display.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/drmmode_display.h b/src/drmmode_display.h +index 96eaef0a..8cd8a0a6 100644 +--- a/src/drmmode_display.h ++++ b/src/drmmode_display.h +@@ -262,7 +262,7 @@ Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, + uint64_t *ust, uint32_t *result_seq); + + +-miPointerSpriteFuncRec drmmode_sprite_funcs; ++extern miPointerSpriteFuncRec drmmode_sprite_funcs; + + + #endif +-- +2.26.2 + diff --git a/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.02-cleanup-terminology-to-use-primary-secondary.patch b/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.02-cleanup-terminology-to-use-primary-secondary.patch new file mode 100644 index 000000000..e680b2f5b --- /dev/null +++ b/packages/x11/driver/xf86-video-ati/patches/xf86-video-ati-999.02-cleanup-terminology-to-use-primary-secondary.patch @@ -0,0 +1,365 @@ +From 8da3e4561ef82bb78c9a17b8cd8bf139b9cfd680 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Mon, 13 Jul 2020 09:11:28 +1000 +Subject: [PATCH] ati: cleanup terminology to use primary/secondary + +The X server changed some API/ABIs here. + +Based on amdgpu patch by Michel +--- + man/radeon.man | 2 +- + src/compat-api.h | 6 ++++ + src/drmmode_display.c | 4 +-- + src/evergreen_state.h | 2 +- + src/r600_state.h | 2 +- + src/radeon.h | 10 +++--- + src/radeon_exa.c | 2 +- + src/radeon_glamor.c | 2 +- + src/radeon_kms.c | 74 +++++++++++++++++++++---------------------- + 9 files changed, 55 insertions(+), 49 deletions(-) + +diff --git a/man/radeon.man b/man/radeon.man +index dcebf537..247dcdb7 100644 +--- a/man/radeon.man ++++ b/man/radeon.man +@@ -290,7 +290,7 @@ on. If this option is set, the default value of the property is 'on' or 'off' + accordingly. If this option isn't set, the default value of the property is + .B auto, + which means that TearFree is on for rotated outputs, outputs with RandR +-transforms applied and for RandR 1.4 slave outputs, otherwise off. ++transforms applied and for RandR 1.4 secondary outputs, otherwise off. + .TP + .BI "Option \*qAccelMethod\*q \*q" "string" \*q + Chooses between available acceleration architectures. Valid values are +diff --git a/src/compat-api.h b/src/compat-api.h +index f4e7524f..def6d3e4 100644 +--- a/src/compat-api.h ++++ b/src/compat-api.h +@@ -34,4 +34,10 @@ + #define BLOCKHANDLER_ARGS pScreen, pTimeout, pReadmask + #endif + ++#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(25, 2) ++#define current_primary current_master ++#define primary_pixmap master_pixmap ++#define secondary_dst slave_dst ++#endif ++ + #endif +diff --git a/src/drmmode_display.c b/src/drmmode_display.c +index 72f96a0c..3099a729 100644 +--- a/src/drmmode_display.c ++++ b/src/drmmode_display.c +@@ -720,7 +720,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, + xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, + ent) { + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { +- dirty->slave_dst = ++ dirty->secondary_dst = + drmmode_crtc->scanout[scanout_id].pixmap; + break; + } +@@ -1356,7 +1356,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) + + xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { +- PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); ++ PixmapStopDirtyTracking(dirty->src, dirty->secondary_dst); + break; + } + } +diff --git a/src/evergreen_state.h b/src/evergreen_state.h +index 7e54e1c7..34ba87b6 100644 +--- a/src/evergreen_state.h ++++ b/src/evergreen_state.h +@@ -350,7 +350,7 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, + int *new_pitch); + extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv); + extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix); +-extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p); ++extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle_p); + extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle); + + #endif +diff --git a/src/r600_state.h b/src/r600_state.h +index 34345996..567c3ca2 100644 +--- a/src/r600_state.h ++++ b/src/r600_state.h +@@ -321,6 +321,6 @@ extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, + int *new_pitch); + extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv); + extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix); +-extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p); ++extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle_p); + extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle); + #endif +diff --git a/src/radeon.h b/src/radeon.h +index e4a2ba66..68d7756a 100644 +--- a/src/radeon.h ++++ b/src/radeon.h +@@ -182,18 +182,18 @@ typedef enum { + + + static inline ScreenPtr +-radeon_master_screen(ScreenPtr screen) ++radeon_primary_screen(ScreenPtr screen) + { +- if (screen->current_master) +- return screen->current_master; ++ if (screen->current_primary) ++ return screen->current_primary; + + return screen; + } + + static inline ScreenPtr +-radeon_dirty_master(PixmapDirtyUpdatePtr dirty) ++radeon_dirty_primary(PixmapDirtyUpdatePtr dirty) + { +- return radeon_master_screen(dirty->slave_dst->drawable.pScreen); ++ return radeon_primary_screen(dirty->secondary_dst->drawable.pScreen); + } + + static inline DrawablePtr +diff --git a/src/radeon_exa.c b/src/radeon_exa.c +index 268155ed..320ff992 100644 +--- a/src/radeon_exa.c ++++ b/src/radeon_exa.c +@@ -282,7 +282,7 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) + free(driverPriv); + } + +-Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) ++Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr seconndary, void **fd_handle) + { + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); + +diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c +index f1098381..ccf99941 100644 +--- a/src/radeon_glamor.c ++++ b/src/radeon_glamor.c +@@ -366,7 +366,7 @@ radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap) + + + static Bool +-radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, ++radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr secondary, + void **handle_p) + { + ScreenPtr screen = pixmap->drawable.pScreen; +diff --git a/src/radeon_kms.c b/src/radeon_kms.c +index b3db7c41..62962d61 100644 +--- a/src/radeon_kms.c ++++ b/src/radeon_kms.c +@@ -559,8 +559,8 @@ dirty_region(PixmapDirtyUpdatePtr dirty) + if (dirty->rotation != RR_Rotate_0) { + dstregion = transform_region(damageregion, + &dirty->f_inverse, +- dirty->slave_dst->drawable.width, +- dirty->slave_dst->drawable.height); ++ dirty->secondary_dst->drawable.width, ++ dirty->secondary_dst->drawable.height); + } else + #endif + { +@@ -568,7 +568,7 @@ dirty_region(PixmapDirtyUpdatePtr dirty) + + dstregion = RegionDuplicate(damageregion); + RegionTranslate(dstregion, -dirty->x, -dirty->y); +- PixmapRegionInit(&pixregion, dirty->slave_dst); ++ PixmapRegionInit(&pixregion, dirty->secondary_dst); + RegionIntersect(dstregion, dstregion, &pixregion); + RegionUninit(&pixregion); + } +@@ -585,8 +585,8 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) + if (RegionNil(region)) + goto out; + +- if (dirty->slave_dst->master_pixmap) +- DamageRegionAppend(&dirty->slave_dst->drawable, region); ++ if (dirty->secondary_dst->primary_pixmap) ++ DamageRegionAppend(&dirty->secondary_dst->drawable, region); + + #ifdef HAS_DIRTYTRACKING_ROTATION + PixmapSyncDirtyHelper(dirty); +@@ -595,8 +595,8 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) + #endif + + radeon_cs_flush_indirect(src_scrn); +- if (dirty->slave_dst->master_pixmap) +- DamageRegionProcessPending(&dirty->slave_dst->drawable); ++ if (dirty->secondary_dst->primary_pixmap) ++ DamageRegionProcessPending(&dirty->secondary_dst->drawable); + + out: + DamageEmpty(dirty->damage); +@@ -613,12 +613,12 @@ radeon_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) + void + radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr master_screen = radeon_dirty_master(dirty); ++ ScreenPtr primary_screen = radeon_dirty_primary(dirty); + PixmapDirtyUpdatePtr ent; + RegionPtr region; + +- xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) { +- if (!radeon_dirty_src_equals(dirty, ent->slave_dst)) ++ xorg_list_for_each_entry(ent, &primary_screen->pixmap_dirty_list, ent) { ++ if (!radeon_dirty_src_equals(dirty, ent->secondary_dst)) + continue; + + region = dirty_region(ent); +@@ -631,45 +631,45 @@ radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) + #if HAS_SYNC_SHARED_PIXMAP + + static Bool +-master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) ++primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr master_screen = radeon_dirty_master(dirty); ++ ScreenPtr primary_screen = radeon_dirty_primary(dirty); + +- return !!master_screen->SyncSharedPixmap; ++ return !!primary_screen->SyncSharedPixmap; + } + + static Bool +-slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) ++secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen; ++ ScreenPtr secondary_screen = dirty->secondary_dst->drawable.pScreen; + +- return !!slave_screen->SyncSharedPixmap; ++ return !!secondary_screen->SyncSharedPixmap; + } + + static void + call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr master_screen = radeon_dirty_master(dirty); ++ ScreenPtr primary_screen = radeon_dirty_primary(dirty); + +- master_screen->SyncSharedPixmap(dirty); ++ primary_screen->SyncSharedPixmap(dirty); + } + + #else /* !HAS_SYNC_SHARED_PIXMAP */ + + static Bool +-master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) ++primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) + { +- ScrnInfoPtr master_scrn = xf86ScreenToScrn(radeon_dirty_master(dirty)); ++ ScrnInfoPtr primary_scrn = xf86ScreenToScrn(radeon_dirty_primary(dirty)); + +- return master_scrn->driverName == scrn->driverName; ++ return primary_scrn->driverName == scrn->driverName; + } + + static Bool +-slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) ++secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) + { +- ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); ++ ScrnInfoPtr secondary_scrn = xf86ScreenToScrn(dirty->secondary_dst->drawable.pScreen); + +- return slave_scrn->driverName == scrn->driverName; ++ return secondary_scrn->driverName == scrn->driverName; + } + + static void +@@ -684,12 +684,12 @@ call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) + static xf86CrtcPtr + radeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ++ ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + +- /* Find the CRTC which is scanning out from this slave pixmap */ ++ /* Find the CRTC which is scanning out from this secondary pixmap */ + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; +@@ -714,7 +714,7 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) + if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { + RegionPtr region; + +- if (master_has_sync_shared_pixmap(scrn, dirty)) ++ if (primary_has_sync_shared_pixmap(scrn, dirty)) + call_sync_shared_pixmap(dirty); + + region = dirty_region(dirty); +@@ -727,7 +727,7 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) + radeon_cs_flush_indirect(scrn); + RegionCopy(&drmmode_crtc->scanout_last_region, region); + RegionTranslate(region, -crtc->x, -crtc->y); +- dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap; ++ dirty->secondary_dst = drmmode_crtc->scanout[scanout_id].pixmap; + } + + redisplay_dirty(dirty, region); +@@ -754,7 +754,7 @@ radeon_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t u + static void + radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) + { +- ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ++ ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); +@@ -818,7 +818,7 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) + static void + radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) + { +- ScreenPtr screen = ent->slave_dst->drawable.pScreen; ++ ScreenPtr screen = ent->secondary_dst->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent); +@@ -893,11 +893,11 @@ radeon_dirty_update(ScrnInfoPtr scrn) + if (screen->isGPU) { + PixmapDirtyUpdatePtr region_ent = ent; + +- if (master_has_sync_shared_pixmap(scrn, ent)) { +- ScreenPtr master_screen = radeon_dirty_master(ent); ++ if (primary_has_sync_shared_pixmap(scrn, ent)) { ++ ScreenPtr primary_screen = radeon_dirty_primary(ent); + +- xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) { +- if (radeon_dirty_src_equals(ent, region_ent->slave_dst)) ++ xorg_list_for_each_entry(region_ent, &primary_screen->pixmap_dirty_list, ent) { ++ if (radeon_dirty_src_equals(ent, region_ent->secondary_dst)) + break; + } + } +@@ -921,7 +921,7 @@ radeon_dirty_update(ScrnInfoPtr scrn) + + RegionDestroy(region); + } else { +- if (slave_has_sync_shared_pixmap(scrn, ent)) ++ if (secondary_has_sync_shared_pixmap(scrn, ent)) + continue; + + region = dirty_region(ent); +@@ -1216,7 +1216,7 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) + (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); + pScreen->BlockHandler = RADEONBlockHandler_KMS; + +- if (!xf86ScreenToScrn(radeon_master_screen(pScreen))->vtSema) ++ if (!xf86ScreenToScrn(radeon_primary_screen(pScreen))->vtSema) + return; + + if (!pScreen->isGPU) +@@ -2584,7 +2584,7 @@ CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + +- if (xf86ScreenToScrn(radeon_master_screen(screen))->vtSema) ++ if (xf86ScreenToScrn(radeon_primary_screen(screen))->vtSema) + return 0; + + /* Unreference the all-black FB created by RADEONLeaveVT_KMS. After diff --git a/packages/x11/driver/xf86-video-intel/package.mk b/packages/x11/driver/xf86-video-intel/package.mk new file mode 100644 index 000000000..e1ba8b180 --- /dev/null +++ b/packages/x11/driver/xf86-video-intel/package.mk @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-intel" +PKG_VERSION="31486f40f8e8f8923ca0799aea84b58799754564" +PKG_SHA256="e47eb678c681d80df138e897ee27c79f9b42e3517d55b1f0684e9a70361c8218" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="https://www.x.org/wiki/IntelGraphicsDriver/" +PKG_URL="https://gitlab.freedesktop.org/xorg/driver/${PKG_NAME}/-/archive/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain libXcomposite libXxf86vm libXdamage libdrm util-macros systemd xorg-server" +PKG_LONGDESC="Open-source Xorg graphics driver for Intel graphics." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-backlight \ + --disable-backlight-helper \ + --disable-gen4asm \ + --enable-udev \ + --disable-tools \ + --enable-dri \ + --disable-dri1 \ + --enable-dri2 \ + --enable-dri3 \ + --enable-kms --enable-kms-only \ + --disable-ums --disable-ums-only \ + --enable-sna \ + --enable-uxa \ + --disable-xvmc \ + --disable-xaa \ + --disable-dga \ + --disable-tear-free \ + --disable-create2 \ + --disable-async-swap \ + --with-default-dri=2 \ + --with-xorg-module-dir=${XORG_PATH_MODULES}" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/share/polkit-1 +} diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/config/xorg-nvidia-legacy.conf b/packages/x11/driver/xf86-video-nvidia-legacy/config/xorg-nvidia-legacy.conf new file mode 100644 index 000000000..cd1c69a43 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/config/xorg-nvidia-legacy.conf @@ -0,0 +1,33 @@ +Section "Device" + Identifier "nvidia" + Driver "nvidia" + Option "DynamicTwinView" "False" + Option "NoFlip" "false" + Option "NoLogo" "true" + Option "ConnectToAcpid" "0" + Option "ModeValidation" "NoVesaModes, NoXServerModes" + Option "HWCursor" "false" + # To put Xorg in debug mode change "false" to "true" in the line below: + Option "ModeDebug" "false" + # To use a local edid.bin file uncomment the 4 lines below (change DFP-0 to match your card) +# Option "ConnectedMonitor" "DFP-0" +# Option "CustomEDID" "DFP-0:/storage/.config/edid.bin" +# Option "IgnoreEDID" "false" +# Option "UseEDID" "true" +EndSection + +Section "Screen" + Identifier "screen" + Device "nvidia" + DefaultDepth 24 + Option "ColorRange" "Full" +# Option "ColorRange" "Limited" +# Option "ColorSpace" "RGB" + SubSection "Display" + Depth 24 + EndSubSection +EndSection + +Section "Extensions" + Option "Composite" "false" +EndSection diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/package.mk b/packages/x11/driver/xf86-video-nvidia-legacy/package.mk new file mode 100644 index 000000000..c1ec61732 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/package.mk @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-nvidia-legacy" +PKG_VERSION="340.108" +PKG_SHA256="995d44fef587ff5284497a47a95d71adbee0c13020d615e940ac928f180f5b77" +PKG_ARCH="x86_64" +PKG_LICENSE="nonfree" +PKG_SITE="https://www.nvidia.com/en-us/drivers/unix/" +PKG_URL="http://us.download.nvidia.com/XFree86/Linux-x86_64/${PKG_VERSION}/NVIDIA-Linux-x86_64-${PKG_VERSION}-no-compat32.run" +PKG_DEPENDS_TARGET="util-macros xorg-server libvdpau" +PKG_NEED_UNPACK="${LINUX_DEPENDS}" +PKG_LONGDESC="The Xorg driver for NVIDIA GPUs supporting the GeForce 500 Series & older devices." + +PKG_TOOLCHAIN="manual" + +PKG_IS_KERNEL_PKG="yes" + +unpack() { + [ -d ${PKG_BUILD} ] && rm -rf ${PKG_BUILD} + + sh ${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME} --extract-only --target ${PKG_BUILD} +} + +make_target() { + unset LDFLAGS + + cd kernel + make module CC=${CC} LD=${LD} SYSSRC=$(kernel_path) SYSOUT=$(kernel_path) + ${STRIP} --strip-debug nvidia.ko + cd .. +} + +makeinstall_target() { + mkdir -p ${INSTALL}/${XORG_PATH_MODULES}/drivers + cp -P nvidia_drv.so ${INSTALL}/${XORG_PATH_MODULES}/drivers/nvidia-legacy_drv.so + ln -sf /var/lib/nvidia_drv.so ${INSTALL}/${XORG_PATH_MODULES}/drivers/nvidia_drv.so + + mkdir -p ${INSTALL}/${XORG_PATH_MODULES}/extensions + # rename to not conflicting with Mesa libGL.so + cp -P libglx.so* ${INSTALL}/${XORG_PATH_MODULES}/extensions/libglx_nvidia-legacy.so + + mkdir -p ${INSTALL}/etc/X11 + cp ${PKG_DIR}/config/*.conf ${INSTALL}/etc/X11 + + mkdir -p ${INSTALL}/usr/lib + cp -P libnvidia-glcore.so.${PKG_VERSION} ${INSTALL}/usr/lib + cp -P libnvidia-ml.so.${PKG_VERSION} ${INSTALL}/usr/lib + ln -sf /var/lib/libnvidia-ml.so.1 ${INSTALL}/usr/lib/libnvidia-ml.so.1 + cp -P tls/libnvidia-tls.so.${PKG_VERSION} ${INSTALL}/usr/lib + # rename to not conflicting with Mesa libGL.so + cp -P libGL.so* ${INSTALL}/usr/lib/libGL_nvidia-legacy.so.1 + + mkdir -p ${INSTALL}/$(get_full_module_dir)/nvidia + ln -sf /var/lib/nvidia.ko ${INSTALL}/$(get_full_module_dir)/nvidia/nvidia.ko + + mkdir -p ${INSTALL}/usr/lib/nvidia-legacy + cp kernel/nvidia.ko ${INSTALL}/usr/lib/nvidia-legacy + + mkdir -p ${INSTALL}/usr/bin + ln -s /var/lib/nvidia-smi ${INSTALL}/usr/bin/nvidia-smi + cp nvidia-smi ${INSTALL}/usr/bin/nvidia-legacy-smi + ln -s /var/lib/nvidia-xconfig ${INSTALL}/usr/bin/nvidia-xconfig + cp nvidia-xconfig ${INSTALL}/usr/bin/nvidia-legacy-xconfig + + mkdir -p ${INSTALL}/usr/lib/vdpau + cp libvdpau_nvidia.so* ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia-legacy.so.1 + ln -sf /var/lib/libvdpau_nvidia.so ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia.so + ln -sf /var/lib/libvdpau_nvidia.so.1 ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia.so.1 +} diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0001-fix-5.6-rc1.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0001-fix-5.6-rc1.patch new file mode 100644 index 000000000..eb34358dd --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0001-fix-5.6-rc1.patch @@ -0,0 +1,487 @@ +diff --git a/kernel/Makefile b/kernel/Makefile +index 125a690..a36cc63 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -108,12 +108,14 @@ COMPILE_TESTS = \ + acquire_console_sem \ + console_lock \ + kmem_cache_create \ ++ kmem_cache_create_usercopy \ + outer_flush_all \ + on_each_cpu \ + smp_call_function \ + nvmap_support \ + acpi_evaluate_integer \ + ioremap_cache \ ++ ioremap_nocache \ + ioremap_wc \ + proc_dir_entry \ + INIT_WORK \ +@@ -122,6 +124,7 @@ COMPILE_TESTS = \ + pci_domain_nr \ + pci_dma_mapping_error \ + file_operations \ ++ proc_ops \ + sg_alloc_table \ + sg_init_table \ + pci_get_domain_bus_and_slot \ +diff --git a/kernel/conftest.sh b/kernel/conftest.sh +index b7a85f0..83700ad 100755 +--- a/kernel/conftest.sh ++++ b/kernel/conftest.sh +@@ -914,6 +914,21 @@ compile_test() { + fi + ;; + ++ kmem_cache_create_usercopy) ++ # ++ # Determine if the kmem_cache_create_usercopy function exists. ++ # ++ # This function was added by: ++ # 2017-06-10 8eb8284b412906181357c2b0110d879d5af95e52 ++ CODE=" ++ #include ++ void kmem_cache_create_usercopy(void) { ++ kmem_cache_create_usercopy(); ++ }" ++ ++ compile_check_conftest "$CODE" "NV_KMEM_CACHE_CREATE_USERCOPY_PRESENT" "" "functions" ++ ;; ++ + smp_call_function) + # + # Determine if the smp_call_function() function is +@@ -1188,6 +1203,22 @@ compile_test() { + compile_check_conftest "$CODE" "NV_IOREMAP_CACHE_PRESENT" "" "functions" + ;; + ++ ioremap_nocache) ++ # ++ # Determine if the ioremap_nocache() function is present. ++ # ++ # Removed by commit 4bdc0d676a64 ("remove ioremap_nocache and ++ # devm_ioremap_nocache") in v5.6 (2020-01-06) ++ # ++ CODE=" ++ #include ++ void conftest_ioremap_nocache(void) { ++ ioremap_nocache(); ++ }" ++ ++ compile_check_conftest "$CODE" "NV_IOREMAP_NOCACHE_PRESENT" "" "functions" ++ ;; ++ + ioremap_wc) + # + # Determine if the ioremap_wc() function is present. +@@ -1371,6 +1402,16 @@ compile_test() { + compile_check_conftest "$CODE" "NV_FILE_OPERATIONS_HAS_COMPAT_IOCTL" "" "types" + ;; + ++ proc_ops) ++ CODE=" ++ #include ++ int conftest_proc_ops(void) { ++ return offsetof(struct proc_ops, proc_open); ++ }" ++ ++ compile_check_conftest "$CODE" "NV_HAVE_PROC_OPS" "" "types" ++ ;; ++ + sg_init_table) + # + # Determine if the sg_init_table() function is present. +diff --git a/kernel/dkms.conf b/kernel/dkms.conf +index 79a02ae..3140f03 100644 +--- a/kernel/dkms.conf ++++ b/kernel/dkms.conf +@@ -1,7 +1,13 @@ ++if [ -x /usr/bin/nproc ]; then ++ num_cpu_cores=$(nproc) ++else ++ num_cpu_cores=1 ++fi ++ + PACKAGE_NAME="nvidia" + PACKAGE_VERSION="340.108" + BUILT_MODULE_NAME[0]="$PACKAGE_NAME" + DEST_MODULE_LOCATION[0]="/kernel/drivers/video" +-MAKE[0]="make module KERNEL_UNAME=${kernelver}" ++MAKE[0]="make -j$num_cpu_cores module KERNEL_UNAME=${kernelver}" + CLEAN="make clean" + AUTOINSTALL="yes" +diff --git a/kernel/nv-drm.c b/kernel/nv-drm.c +index 0d1cdbf..2e4b867 100644 +--- a/kernel/nv-drm.c ++++ b/kernel/nv-drm.c +@@ -50,6 +50,60 @@ + #if defined(NV_DRM_LEGACY_PCI_INIT_PRESENT) + #define nv_drm_pci_init drm_legacy_pci_init + #define nv_drm_pci_exit drm_legacy_pci_exit ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++int nv_drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) ++{ ++ struct pci_dev *pdev = NULL; ++ const struct pci_device_id *pid; ++ int i; ++ ++ DRM_DEBUG("\n"); ++ ++ if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY))) ++ return -EINVAL; ++ ++ /* If not using KMS, fall back to stealth mode manual scanning. */ ++ INIT_LIST_HEAD(&driver->legacy_dev_list); ++ for (i = 0; pdriver->id_table[i].vendor != 0; i++) { ++ pid = &pdriver->id_table[i]; ++ ++ /* Loop around setting up a DRM device for each PCI device ++ * matching our ID and device class. If we had the internal ++ * function that pci_get_subsys and pci_get_class used, we'd ++ * be able to just pass pid in instead of doing a two-stage ++ * thing. ++ */ ++ pdev = NULL; ++ while ((pdev = ++ pci_get_subsys(pid->vendor, pid->device, pid->subvendor, ++ pid->subdevice, pdev)) != NULL) { ++ if ((pdev->class & pid->class_mask) != pid->class) ++ continue; ++ ++ /* stealth mode requires a manual probe */ ++ pci_dev_get(pdev); ++ drm_get_pci_dev(pdev, pid, driver); ++ } ++ } ++ return 0; ++} ++ ++void nv_drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) ++{ ++ struct drm_device *dev, *tmp; ++ DRM_DEBUG("\n"); ++ ++ if (!(driver->driver_features & DRIVER_LEGACY)) { ++ WARN_ON(1); ++ } else { ++ list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list, ++ legacy_dev_list) { ++ list_del(&dev->legacy_dev_list); ++ drm_put_dev(dev); ++ } ++ } ++ DRM_INFO("Module unloaded\n"); ++} + #else + #define nv_drm_pci_init drm_pci_init + #define nv_drm_pci_exit drm_pci_exit +diff --git a/kernel/nv-linux.h b/kernel/nv-linux.h +index a1d2c68..83e6433 100644 +--- a/kernel/nv-linux.h ++++ b/kernel/nv-linux.h +@@ -688,11 +688,16 @@ extern nv_spinlock_t km_lock; + VM_ALLOC_RECORD(ptr, size, "vm_ioremap"); \ + } + ++#if defined(NV_IOREMAP_NOCACHE_PRESENT) + #define NV_IOREMAP_NOCACHE(ptr, physaddr, size) \ + { \ + (ptr) = ioremap_nocache(physaddr, size); \ + VM_ALLOC_RECORD(ptr, size, "vm_ioremap_nocache"); \ + } ++#else ++#define NV_IOREMAP_NOCACHE(ptr, physaddr, size) \ ++ NV_IOREMAP(ptr, physaddr, size) ++#endif + + #if defined(NV_IOREMAP_CACHE_PRESENT) + #define NV_IOREMAP_CACHE(ptr, physaddr, size) \ +@@ -774,6 +779,17 @@ extern nv_spinlock_t km_lock; + #error "NV_KMEM_CACHE_CREATE() undefined (kmem_cache_create() unavailable)!" + #endif + ++#if defined(NV_KMEM_CACHE_CREATE_USERCOPY_PRESENT) ++#define NV_KMEM_CACHE_CREATE_USERCOPY(kmem_cache, name, type) \ ++ { \ ++ kmem_cache = kmem_cache_create_usercopy(name, sizeof(type), \ ++ 0, 0, 0, sizeof(type), NULL); \ ++ } ++#else ++#define NV_KMEM_CACHE_CREATE_USERCOPY(kmem_cache, name, type) \ ++ NV_KMEM_CACHE_CREATE(kmem_cache, name, type) ++#endif ++ + #define NV_KMEM_CACHE_ALLOC(ptr, kmem_cache, type) \ + { \ + (ptr) = kmem_cache_alloc(kmem_cache, GFP_KERNEL); \ +@@ -1971,6 +1987,19 @@ extern NvU32 nv_assign_gpu_count; + }) + #endif + ++#if defined(NV_HAVE_PROC_OPS) ++#define NV_CREATE_PROC_FILE(filename,parent,__name,__data) \ ++ ({ \ ++ struct proc_dir_entry *__entry; \ ++ int mode = (S_IFREG | S_IRUGO); \ ++ const struct proc_ops *fops = &nv_procfs_##__name##_fops; \ ++ if (fops->proc_write != 0) \ ++ mode |= S_IWUSR; \ ++ __entry = NV_CREATE_PROC_ENTRY(filename, mode, parent, fops, \ ++ __data); \ ++ __entry; \ ++ }) ++#else + #define NV_CREATE_PROC_FILE(filename,parent,__name,__data) \ + ({ \ + struct proc_dir_entry *__entry; \ +@@ -1982,6 +2011,7 @@ extern NvU32 nv_assign_gpu_count; + __data); \ + __entry; \ + }) ++#endif + + /* + * proc_mkdir_mode exists in Linux 2.6.9, but isn't exported until Linux 3.0. +@@ -2023,6 +2053,24 @@ extern NvU32 nv_assign_gpu_count; + remove_proc_entry(entry->name, entry->parent); + #endif + ++#if defined(NV_HAVE_PROC_OPS) ++#define NV_DEFINE_PROCFS_SINGLE_FILE(__name) \ ++ static int nv_procfs_open_##__name( \ ++ struct inode *inode, \ ++ struct file *filep \ ++ ) \ ++ { \ ++ return single_open(filep, nv_procfs_read_##__name, \ ++ NV_PDE_DATA(inode)); \ ++ } \ ++ \ ++ static const struct proc_ops nv_procfs_##__name##_fops = { \ ++ .proc_open = nv_procfs_open_##__name, \ ++ .proc_read = seq_read, \ ++ .proc_lseek = seq_lseek, \ ++ .proc_release = single_release, \ ++ }; ++#else + #define NV_DEFINE_PROCFS_SINGLE_FILE(__name) \ + static int nv_procfs_open_##__name( \ + struct inode *inode, \ +@@ -2040,6 +2088,7 @@ extern NvU32 nv_assign_gpu_count; + .llseek = seq_lseek, \ + .release = single_release, \ + }; ++#endif + + #endif /* CONFIG_PROC_FS */ + +diff --git a/kernel/nv-procfs.c b/kernel/nv-procfs.c +index ebca3e8..9365c3c 100644 +--- a/kernel/nv-procfs.c ++++ b/kernel/nv-procfs.c +@@ -409,6 +409,15 @@ done: + return ((status < 0) ? status : (int)count); + } + ++#if defined(NV_HAVE_PROC_OPS) ++static struct proc_ops nv_procfs_registry_fops = { ++ .proc_open = nv_procfs_open_registry, ++ .proc_read = seq_read, ++ .proc_write = nv_procfs_write_file, ++ .proc_lseek = seq_lseek, ++ .proc_release = nv_procfs_close_registry, ++}; ++#else + static struct file_operations nv_procfs_registry_fops = { + .owner = THIS_MODULE, + .open = nv_procfs_open_registry, +@@ -417,6 +426,7 @@ static struct file_operations nv_procfs_registry_fops = { + .llseek = seq_lseek, + .release = nv_procfs_close_registry, + }; ++#endif + + static int + nv_procfs_read_unbind_lock( +@@ -538,6 +548,15 @@ done: + return rc; + } + ++#if defined(NV_HAVE_PROC_OPS) ++static struct proc_ops nv_procfs_unbind_lock_fops = { ++ .proc_open = nv_procfs_open_unbind_lock, ++ .proc_read = seq_read, ++ .proc_write = nv_procfs_write_file, ++ .proc_lseek = seq_lseek, ++ .proc_release = nv_procfs_close_unbind_lock, ++}; ++#else + static struct file_operations nv_procfs_unbind_lock_fops = { + .owner = THIS_MODULE, + .open = nv_procfs_open_unbind_lock, +@@ -546,6 +565,7 @@ static struct file_operations nv_procfs_unbind_lock_fops = { + .llseek = seq_lseek, + .release = nv_procfs_close_unbind_lock, + }; ++#endif + + static int + nv_procfs_read_text_file( +diff --git a/kernel/nv-time.h b/kernel/nv-time.h +index a34ceb2..780f8bc 100644 +--- a/kernel/nv-time.h ++++ b/kernel/nv-time.h +@@ -28,7 +28,12 @@ + #include + #endif + +-static inline void nv_gettimeofday(struct timeval *tv) ++struct nv_timeval { ++ __kernel_long_t tv_sec; ++ __kernel_suseconds_t tv_usec; ++}; ++ ++static inline void nv_gettimeofday(struct nv_timeval *tv) + { + #ifdef NV_DO_GETTIMEOFDAY_PRESENT + do_gettimeofday(tv); +@@ -37,7 +42,7 @@ static inline void nv_gettimeofday(struct timeval *tv) + + ktime_get_real_ts64(&now); + +- *tv = (struct timeval) { ++ *tv = (struct nv_timeval) { + .tv_sec = now.tv_sec, + .tv_usec = now.tv_nsec/1000, + }; +diff --git a/kernel/nv.c b/kernel/nv.c +index a167be9..a218f83 100644 +--- a/kernel/nv.c ++++ b/kernel/nv.c +@@ -752,7 +752,7 @@ int __init nvidia_init_module(void) + NV_SPIN_LOCK_INIT(&km_lock); + #endif + +- NV_KMEM_CACHE_CREATE(nv_stack_t_cache, NV_STACK_CACHE_STR, nv_stack_t); ++ NV_KMEM_CACHE_CREATE_USERCOPY(nv_stack_t_cache, NV_STACK_CACHE_STR, nv_stack_t); + if (nv_stack_t_cache == NULL) + { + nv_printf(NV_DBG_ERRORS, "NVRM: stack cache allocation failed!\n"); +diff --git a/kernel/os-interface.c b/kernel/os-interface.c +index 7190b26..0c0dc05 100644 +--- a/kernel/os-interface.c ++++ b/kernel/os-interface.c +@@ -439,7 +439,7 @@ RM_STATUS NV_API_CALL os_get_current_time( + NvU32 *useconds + ) + { +- struct timeval tm; ++ struct nv_timeval tm; + + nv_gettimeofday(&tm); + +@@ -474,7 +474,7 @@ RM_STATUS NV_API_CALL os_delay_us(NvU32 MicroSeconds) + unsigned long usec; + + #ifdef NV_CHECK_DELAY_ACCURACY +- struct timeval tm1, tm2; ++ struct nv_timeval tm1, tm2; + + nv_gettimeofday(&tm1); + #endif +@@ -514,9 +514,9 @@ RM_STATUS NV_API_CALL os_delay(NvU32 MilliSeconds) + unsigned long MicroSeconds; + unsigned long jiffies; + unsigned long mdelay_safe_msec; +- struct timeval tm_end, tm_aux; ++ struct nv_timeval tm_end, tm_aux; + #ifdef NV_CHECK_DELAY_ACCURACY +- struct timeval tm_start; ++ struct nv_timeval tm_start; + #endif + + nv_gettimeofday(&tm_aux); +diff --git a/kernel/uvm/Makefile b/kernel/uvm/Makefile +index 0cad8ff..043a08d 100644 +--- a/kernel/uvm/Makefile ++++ b/kernel/uvm/Makefile +@@ -207,6 +207,7 @@ ccflags-y += $(EXTRA_CFLAGS) + + RM_MODULE_SYMVERS:= $(RM_OUT_DIR)/Module.symvers + UVM_MODULE_SYMVERS:= $(obj)/Module.symvers ++KBUILD_EXTRA_SYMBOLS:= $(UVM_MODULE_SYMVERS) + + module $(MODULE_NAME).ko: $(UVM_MODULE_SYMVERS) debug_diagnostics_printing + +diff --git a/kernel/uvm/nvidia_uvm_lite.c b/kernel/uvm/nvidia_uvm_lite.c +index 6943e7c..9a7e3b6 100644 +--- a/kernel/uvm/nvidia_uvm_lite.c ++++ b/kernel/uvm/nvidia_uvm_lite.c +@@ -131,8 +131,8 @@ static + RM_STATUS _preexisting_error_on_channel(UvmGpuMigrationTracking *pMigTracker, + UvmCommitRecord *pRecord); + +-static void _set_timeout_in_usec(struct timeval *src, +- struct timeval *result, ++static void _set_timeout_in_usec(struct nv_timeval *src, ++ struct nv_timeval *result, + unsigned long timeoutInUsec) + { + if (!src || !result) +@@ -820,7 +820,13 @@ done: + } + + #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++vm_fault_t _fault(struct vm_fault *vmf) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++int _fault(struct vm_fault *vmf) ++#else + int _fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++#endif + { + #if defined(NV_VM_FAULT_HAS_ADDRESS) + unsigned long vaddr = vmf->address; +@@ -828,8 +834,15 @@ int _fault(struct vm_area_struct *vma, struct vm_fault *vmf) + unsigned long vaddr = (unsigned long)vmf->virtual_address; + #endif + struct page *page = NULL; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++ vm_fault_t retval; ++#else + int retval; + ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++ struct vm_area_struct *vma = vmf->vma; ++#endif + retval = _fault_common(vma, vaddr, &page, vmf->flags); + + vmf->page = page; +@@ -868,7 +881,13 @@ static struct vm_operations_struct uvmlite_vma_ops = + // it's dealing with anonymous mapping (see handle_pte_fault). + // + #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) ++vm_fault_t _sigbus_fault(struct vm_fault *vmf) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++int _sigbus_fault(struct vm_fault *vmf) ++#else + int _sigbus_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++#endif + { + vmf->page = NULL; + return VM_FAULT_SIGBUS; +@@ -1992,9 +2011,9 @@ void umvlite_destroy_per_process_gpu_resources(UvmGpuUuid *gpuUuidStruct) + static RM_STATUS _check_ecc_errors(UvmGpuMigrationTracking *pMigTracker, + NvBool *pIsEccErrorSet) + { +- struct timeval eccErrorStartTime = {0}; +- struct timeval eccErrorCurrentTime = {0}; +- struct timeval eccTimeout = {0}; ++ struct nv_timeval eccErrorStartTime = {0}; ++ struct nv_timeval eccErrorCurrentTime = {0}; ++ struct nv_timeval eccTimeout = {0}; + NvBool bEccErrorTimeout = NV_FALSE; + NvBool bEccIncomingError = NV_FALSE; + unsigned rmInterruptSet = 0; diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0002-fix-5.7-rc1.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0002-fix-5.7-rc1.patch new file mode 100644 index 000000000..f5901701c --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0002-fix-5.7-rc1.patch @@ -0,0 +1,37 @@ +From 514f68b5dd8f84a4b6f215a0808ba1aef9568366 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 13 Apr 2020 01:24:35 +0100 +Subject: [PATCH] fix build with 5.7-rc1 + +legacy variant of: https://gitlab.com/snippets/1965550 + +credit: Isaak I. Aleksandrov +--- + kernel/conftest.sh | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/conftest.sh b/kernel/conftest.sh +index 83700ad..5a0ce4d 100755 +--- a/kernel/conftest.sh ++++ b/kernel/conftest.sh +@@ -177,6 +177,7 @@ test_headers() { + FILES="$FILES linux/file.h" + + FILES_ARCH="$FILES_ARCH asm/set_memory.h" ++ FILES_ARCH="$FILES_ARCH asm/pgtable.h" + + translate_and_find_header_files $HEADERS $FILES + translate_and_find_header_files $HEADERS_ARCH $FILES_ARCH +@@ -440,6 +441,9 @@ compile_test() { + # Determine if the set_memory_array_uc() function is present. + # + CODE=" ++ #if defined(NV_ASM_PGTABLE_H_PRESENT) ++ #include ++ #endif + #if defined(NV_ASM_SET_MEMORY_H_PRESENT) + #include + #else +-- +2.20.1 + diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0003-fix-5.7-rc1-reinstate-legacy-support.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0003-fix-5.7-rc1-reinstate-legacy-support.patch new file mode 100644 index 000000000..0e01a9296 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0003-fix-5.7-rc1-reinstate-legacy-support.patch @@ -0,0 +1,156 @@ +From a955b00bb4fc5f60f2b17f33e96d110bf0a605e1 Mon Sep 17 00:00:00 2001 +From: MilhouseVH +Date: Mon, 13 Apr 2020 01:47:06 +0100 +Subject: [PATCH] HACK: implement the pci/agp support marked legacy in 5.7-rc1 + +drm_get_pci_dev: https://github.com/torvalds/linux/commit/c393fbae0226e9ad8719a516bec66bb2b8bbfcb6 +drm_pci_agp_init: https://github.com/torvalds/linux/commit/ee21ec7767621c1adb0a388e0e7d841674cdc43f +--- + kernel/nv-drm.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 131 insertions(+) + +diff --git a/kernel/nv-drm.c b/kernel/nv-drm.c +index 2e4b867..059f258 100644 +--- a/kernel/nv-drm.c ++++ b/kernel/nv-drm.c +@@ -51,6 +51,137 @@ + #define nv_drm_pci_init drm_legacy_pci_init + #define nv_drm_pci_exit drm_legacy_pci_exit + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) ++#include ++ ++struct drm_agp_mem { ++ unsigned long handle; ++ struct agp_memory *memory; ++ unsigned long bound; ++ int pages; ++ struct list_head head; ++}; ++ ++/** ++ * drm_legacy_agp_clear - Clear AGP resource list ++ * @dev: DRM device ++ * ++ * Iterate over all AGP resources and remove them. But keep the AGP head ++ * intact so it can still be used. It is safe to call this if AGP is disabled or ++ * was already removed. ++ * ++ * Cleanup is only done for drivers who have DRIVER_LEGACY set. ++ */ ++void drm_legacy_agp_clear(struct drm_device *dev) ++{ ++ struct drm_agp_mem *entry, *tempe; ++ ++ if (!dev->agp) ++ return; ++ if (!drm_core_check_feature(dev, DRIVER_LEGACY)) ++ return; ++ ++ list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { ++ if (entry->bound) ++ agp_unbind_memory(entry->memory); ++ agp_free_memory(entry->memory); ++ kfree(entry); ++ } ++ INIT_LIST_HEAD(&dev->agp->memory); ++ ++ if (dev->agp->acquired) ++ drm_agp_release(dev); ++ ++ dev->agp->acquired = 0; ++ dev->agp->enabled = 0; ++} ++ ++static void drm_pci_agp_init(struct drm_device *dev) ++{ ++ if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { ++ if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP)) ++ dev->agp = drm_agp_init(dev); ++ if (dev->agp) { ++ dev->agp->agp_mtrr = arch_phys_wc_add( ++ dev->agp->agp_info.aper_base, ++ dev->agp->agp_info.aper_size * ++ 1024 * 1024); ++ } ++ } ++} ++ ++void drm_pci_agp_destroy(struct drm_device *dev) ++{ ++ if (dev->agp) { ++ arch_phys_wc_del(dev->agp->agp_mtrr); ++ drm_legacy_agp_clear(dev); ++ kfree(dev->agp); ++ dev->agp = NULL; ++ } ++} ++ ++/** ++ * drm_get_pci_dev - Register a PCI device with the DRM subsystem ++ * @pdev: PCI device ++ * @ent: entry from the PCI ID table that matches @pdev ++ * @driver: DRM device driver ++ * ++ * Attempt to gets inter module "drm" information. If we are first ++ * then register the character device and inter module information. ++ * Try and register, if we fail to register, backout previous work. ++ * ++ * NOTE: This function is deprecated, please use drm_dev_alloc() and ++ * drm_dev_register() instead and remove your &drm_driver.load callback. ++ * ++ * Return: 0 on success or a negative error code on failure. ++ */ ++int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ++ struct drm_driver *driver) ++{ ++ struct drm_device *dev; ++ int ret; ++ ++ DRM_DEBUG("\n"); ++ ++ dev = drm_dev_alloc(driver, &pdev->dev); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ ret = pci_enable_device(pdev); ++ if (ret) ++ goto err_free; ++ ++ dev->pdev = pdev; ++#ifdef __alpha__ ++ dev->hose = pdev->sysdata; ++#endif ++ ++ if (drm_core_check_feature(dev, DRIVER_MODESET)) ++ pci_set_drvdata(pdev, dev); ++ ++ drm_pci_agp_init(dev); ++ ++ ret = drm_dev_register(dev, ent->driver_data); ++ if (ret) ++ goto err_agp; ++ ++ /* No locking needed since shadow-attach is single-threaded since it may ++ * only be called from the per-driver module init hook. */ ++ if (drm_core_check_feature(dev, DRIVER_LEGACY)) ++ list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list); ++ ++ return 0; ++ ++err_agp: ++ drm_pci_agp_destroy(dev); ++ pci_disable_device(pdev); ++err_free: ++ drm_dev_put(dev); ++ return ret; ++} ++#endif ++ + int nv_drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) + { + struct pci_dev *pdev = NULL; +-- +2.20.1 + diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0004-fix-5.8.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0004-fix-5.8.patch new file mode 100644 index 000000000..7e61f58e0 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0004-fix-5.8.patch @@ -0,0 +1,57 @@ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nvidia-modules-common.mk NVIDIA-Linux-x86_64-340.108-new/kernel/nvidia-modules-common.mk +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nvidia-modules-common.mk 2019-12-11 23:04:24.000000000 +0100 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nvidia-modules-common.mk 2020-08-04 16:18:14.073333322 +0200 +@@ -222,6 +222,7 @@ + define BUILD_MODULE_RULE + $(1): build-sanity-checks $(3) + @echo "NVIDIA: calling KBUILD..."; \ ++ touch .nv-kernel.o.cmd; \ + $$(MAKE) "CC=$$(CC)" NV_MODULE_SUFFIX=$$(strip $(2)) $$(KBUILD_PARAMS) modules; \ + echo "NVIDIA: left KBUILD."; \ + if ! [ -f $(1) ]; then \ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h 2020-08-01 20:34:33.900000000 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h 2020-08-03 13:10:17.693333317 +0200 +@@ -669,11 +669,19 @@ + # define KM_FREE_RECORD(a,b,c) + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) ++#define NV_VMALLOC(ptr, size) \ ++ { \ ++ (ptr) = __vmalloc(size, GFP_KERNEL); \ ++ VM_ALLOC_RECORD(ptr, size, "vm_vmalloc"); \ ++ } ++#else + #define NV_VMALLOC(ptr, size) \ + { \ + (ptr) = __vmalloc(size, GFP_KERNEL, PAGE_KERNEL); \ + VM_ALLOC_RECORD(ptr, size, "vm_vmalloc"); \ + } ++#endif + + #define NV_VFREE(ptr, size) \ + { \ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/os-mlock.c NVIDIA-Linux-x86_64-340.108-new/kernel/os-mlock.c +--- NVIDIA-Linux-x86_64-340.108-old/kernel/os-mlock.c 2019-12-11 23:04:24.000000000 +0100 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/os-mlock.c 2020-08-03 13:11:06.536666663 +0200 +@@ -44,11 +44,19 @@ + return rmStatus; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) ++ down_read(&mm->mmap_lock); ++ ret = NV_GET_USER_PAGES((unsigned long)address, ++ page_count, write, force, user_pages, NULL); ++ up_read(&mm->mmap_lock); ++ pinned = ret; ++#else + down_read(&mm->mmap_sem); + ret = NV_GET_USER_PAGES((unsigned long)address, + page_count, write, force, user_pages, NULL); + up_read(&mm->mmap_sem); + pinned = ret; ++#endif + + if (ret < 0) + { diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0005-fix-5.9.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0005-fix-5.9.patch new file mode 100644 index 000000000..d3cc5b9c2 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0005-fix-5.9.patch @@ -0,0 +1,76 @@ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv.c NVIDIA-Linux-x86_64-340.108-new/kernel/nv.c +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv.c 2020-08-26 14:28:09.350000000 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv.c 2020-08-26 14:35:42.856666666 +0200 +@@ -2785,8 +2785,12 @@ + + #if defined(CONFIG_VGA_ARB) + #if defined(VGA_DEFAULT_DEVICE) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ vga_get(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK, 0); ++#else + vga_tryget(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK); + #endif ++#endif + vga_set_legacy_decoding(dev, VGA_RSRC_NONE); + #endif + +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv-drm.c NVIDIA-Linux-x86_64-340.108-new/kernel/nv-drm.c +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv-drm.c 2020-08-26 14:28:09.506666667 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-drm.c 2020-08-26 14:48:58.443333335 +0200 +@@ -373,7 +373,11 @@ + .set_busid = drm_pci_set_busid, + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ .gem_free_object_unlocked = nv_gem_free, ++#else + .gem_free_object = nv_gem_free, ++#endif + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .gem_prime_export = drm_gem_prime_export, +@@ -470,8 +474,14 @@ + #if defined(NV_DRM_GEM_OBJECT_PUT_UNLOCKED_PRESENT) + drm_gem_object_put_unlocked(&nv_obj->base); + #else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) ++ drm_gem_object_put(&nv_obj->base); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ drm_gem_object_put_locked(&nv_obj->base); ++#else + drm_gem_object_unreference_unlocked(&nv_obj->base); + #endif ++#endif + + status = RM_OK; + +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h 2020-08-26 14:28:09.583333333 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h 2020-08-26 14:53:45.693333299 +0200 +@@ -136,8 +136,10 @@ + + #if defined(NVCPU_X86_64) && !defined(HAVE_COMPAT_IOCTL) + #include /* sys_ioctl() */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) + #include /* register_ioctl32_conversion() */ + #endif ++#endif + + #if !defined(NV_FILE_OPERATIONS_HAS_IOCTL) && \ + !defined(NV_FILE_OPERATIONS_HAS_UNLOCKED_IOCTL) +@@ -2249,10 +2251,13 @@ + pages, vmas, NULL); + + #else +- ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ return get_user_pages_remote(mm, start, nr_pages, flags, ++ pages, vmas, NULL); ++#else + return get_user_pages_remote(tsk, mm, start, nr_pages, flags, + pages, vmas); +- ++#endif + #endif + + } diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0006-fix-5.10.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0006-fix-5.10.patch new file mode 100644 index 000000000..983b88341 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0006-fix-5.10.patch @@ -0,0 +1,14 @@ +--- NVIDIA-Linux-x86_64-340.108-orig/kernel/nv-drm.c 2020-12-14 19:58:21.951120294 +0100 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-drm.c 2020-12-14 20:30:05.855962292 +0100 +@@ -365,7 +365,11 @@ + struct nv_gem_object *nv_obj = container_of(obj, struct nv_gem_object, base); + int page_count = obj->size >> PAGE_SHIFT; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) ++ return drm_prime_pages_to_sg(obj->dev, nv_obj->pages, page_count); ++#else + return drm_prime_pages_to_sg(nv_obj->pages, page_count); ++#endif + } + + static void* nv_gem_prime_vmap( diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0007-fix-5.14.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0007-fix-5.14.patch new file mode 100644 index 000000000..dc8770d07 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-0007-fix-5.14.patch @@ -0,0 +1,231 @@ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/conftest.sh NVIDIA-Linux-x86_64-340.108-new/kernel/conftest.sh +--- NVIDIA-Linux-x86_64-340.108-old/kernel/conftest.sh 2021-05-24 20:08:18.743742335 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/conftest.sh 2021-05-24 20:13:18.019314390 +0200 +@@ -1578,21 +1578,21 @@ + #include + #endif + +- #if defined(NV_DRM_DRM_PRIME_H_PRESENT) +- #include +- #endif +- + #if !defined(CONFIG_DRM) && !defined(CONFIG_DRM_MODULE) + #error DRM not enabled + #endif ++ + void conftest_drm_available(void) { + struct drm_driver drv; +- drv.gem_prime_pin = 0; +- drv.gem_prime_get_sg_table = 0; +- drv.gem_prime_vmap = 0; +- drv.gem_prime_vunmap = 0; +- (void)drm_gem_prime_import; +- (void)drm_gem_prime_export; ++ ++ /* 2013-10-02 1bb72532ac260a2d3982b40bdd4c936d779d0d16 */ ++ (void)drm_dev_alloc; ++ ++ /* 2013-10-02 c22f0ace1926da399d9a16dfaf09174c1b03594c */ ++ (void)drm_dev_register; ++ ++ /* 2013-10-02 c3a49737ef7db0bdd4fcf6cf0b7140a883e32b2a */ ++ (void)drm_dev_unregister; + }" + + compile_check_conftest "$CODE" "NV_DRM_AVAILABLE" "" "generic" +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv-drm.c NVIDIA-Linux-x86_64-340.108-new/kernel/nv-drm.c +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv-drm.c 2021-05-24 20:08:18.779739237 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-drm.c 2021-05-24 20:42:13.443288819 +0200 +@@ -52,7 +52,9 @@ + #define nv_drm_pci_exit drm_legacy_pci_exit + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) ++#include "linux/dma-buf.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + #include + + struct drm_agp_mem { +@@ -168,8 +170,10 @@ + + /* No locking needed since shadow-attach is single-threaded since it may + * only be called from the per-driver module init hook. */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0) + if (drm_core_check_feature(dev, DRIVER_LEGACY)) + list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list); ++#endif + + return 0; + +@@ -193,8 +197,10 @@ + if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY))) + return -EINVAL; + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0) + /* If not using KMS, fall back to stealth mode manual scanning. */ + INIT_LIST_HEAD(&driver->legacy_dev_list); ++#endif + for (i = 0; pdriver->id_table[i].vendor != 0; i++) { + pid = &pdriver->id_table[i]; + +@@ -219,7 +219,9 @@ + + /* stealth mode requires a manual probe */ + pci_dev_get(pdev); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + drm_get_pci_dev(pdev, pid, driver); ++#endif + } + } + return 0; +@@ -227,11 +233,13 @@ + if (!(driver->driver_features & DRIVER_LEGACY)) { + WARN_ON(1); + } else { ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0) + list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list, + legacy_dev_list) { + list_del(&dev->legacy_dev_list); + drm_put_dev(dev); + } ++#endif + } + DRM_INFO("Module unloaded\n"); + } +@@ -254,6 +262,8 @@ + { + nv_linux_state_t *nvl; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) ++ /* dev->pdev is no longer avaialble in 5.14 */ + for (nvl = nv_linux_devices; nvl != NULL; nvl = nvl->next) + { + if (nvl->dev == dev->pdev) +@@ -262,6 +272,7 @@ + return 0; + } + } ++#endif + + return -ENODEV; + } +@@ -278,6 +289,8 @@ + { + nv_linux_state_t *nvl; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) ++ /* dev->pdev is no longer avaialble in 5.14 */ + for (nvl = nv_linux_devices; nvl != NULL; nvl = nvl->next) + { + if (nvl->dev == dev->pdev) +@@ -287,6 +300,7 @@ + return 0; + } + } ++#endif + + return -ENODEV; + } +@@ -359,6 +373,39 @@ + .llseek = noop_llseek, + }; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) ++struct sg_table *nv_drm_gem_prime_get_sg_table(struct drm_gem_object *gem) ++{ ++ return nv_gem_prime_get_sg_table(gem); ++} ++ ++static int nv_drm_gem_vmap(struct drm_gem_object *gem, ++ struct dma_buf_map *map) ++{ ++ map->vaddr = nv_gem_prime_vmap(gem); ++ if (map->vaddr == NULL) { ++ return -ENOMEM; ++ } ++ map->is_iomem = true; ++ return 0; ++} ++ ++static void nv_drm_gem_vunmap(struct drm_gem_object *gem, ++ struct dma_buf_map *map) ++{ ++ nv_gem_prime_vunmap(gem, map->vaddr); ++ map->vaddr = NULL; ++} ++ ++static struct drm_gem_object_funcs nv_drm_gem_object_funcs = { ++ .free = nv_gem_free, ++ .export = drm_gem_prime_export, ++ .get_sg_table = nv_drm_gem_prime_get_sg_table, ++ .vmap = nv_drm_gem_vmap, ++ .vunmap = nv_drm_gem_vunmap, ++}; ++#endif ++ + static struct drm_driver nv_drm_driver = { + + .driver_features = DRIVER_GEM +@@ -377,17 +424,19 @@ + .set_busid = drm_pci_set_busid, + #endif + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) +- .gem_free_object_unlocked = nv_gem_free, +-#else ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 8, 0) + .gem_free_object = nv_gem_free, ++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0) ++ .gem_free_object_unlocked = nv_gem_free, + #endif + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0) + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = nv_gem_prime_get_sg_table, + .gem_prime_vmap = nv_gem_prime_vmap, + .gem_prime_vunmap = nv_gem_prime_vunmap, ++#endif + + .name = "nvidia-drm", + .desc = "NVIDIA DRM driver", +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h +--- NVIDIA-Linux-x86_64-340.108-old/kernel/nv-linux.h 2021-05-24 20:08:18.775739581 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/nv-linux.h 2021-05-24 20:09:18.748287771 +0200 +@@ -119,7 +119,9 @@ + #include /* flush_tlb(), flush_tlb_all() */ + #include /* CPU hotplug support */ + #endif +-#include /* page table entry lookup */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) ++ #include /* page table entry lookup */ ++#endif + + #include /* pci_find_class, etc */ + #include /* tasklets, interrupt helpers */ +diff -Naur NVIDIA-Linux-x86_64-340.108-old/kernel/uvm/nvidia_uvm_linux.h NVIDIA-Linux-x86_64-340.108-new/kernel/uvm/nvidia_uvm_linux.h +--- NVIDIA-Linux-x86_64-340.108-old/kernel/uvm/nvidia_uvm_linux.h 2021-05-24 20:08:18.775739581 +0200 ++++ NVIDIA-Linux-x86_64-340.108-new/kernel/uvm/nvidia_uvm_linux.h 2021-05-24 20:09:18.749287739 +0200 +@@ -141,7 +141,9 @@ + #if !defined(NV_VMWARE) + #include /* flush_tlb(), flush_tlb_all() */ + #endif +-#include /* page table entry lookup */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) ++ #include /* page table entry lookup */ ++#endif + + #include /* tasklets, interrupt helpers */ + #include +--- a/kernel/os-interface.c 2021-09-04 22:01:56.175807486 +1000 ++++ b/kernel/os-interface.c 2021-09-04 22:01:56.175807486 +1000 +@@ -549,7 +549,7 @@ + // the requested timeout has expired, loop until less + // than a jiffie of the desired delay remains. + // +- current->state = TASK_INTERRUPTIBLE; ++ current->__state = TASK_INTERRUPTIBLE; + do + { + schedule_timeout(jiffies); diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/udev.d b/packages/x11/driver/xf86-video-nvidia-legacy/udev.d new file mode 120000 index 000000000..386fe9fc6 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/udev.d @@ -0,0 +1 @@ +../xf86-video-nvidia/udev.d/ \ No newline at end of file diff --git a/packages/x11/driver/xf86-video-nvidia/config/xorg-nvidia.conf b/packages/x11/driver/xf86-video-nvidia/config/xorg-nvidia.conf new file mode 100644 index 000000000..cd1c69a43 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/config/xorg-nvidia.conf @@ -0,0 +1,33 @@ +Section "Device" + Identifier "nvidia" + Driver "nvidia" + Option "DynamicTwinView" "False" + Option "NoFlip" "false" + Option "NoLogo" "true" + Option "ConnectToAcpid" "0" + Option "ModeValidation" "NoVesaModes, NoXServerModes" + Option "HWCursor" "false" + # To put Xorg in debug mode change "false" to "true" in the line below: + Option "ModeDebug" "false" + # To use a local edid.bin file uncomment the 4 lines below (change DFP-0 to match your card) +# Option "ConnectedMonitor" "DFP-0" +# Option "CustomEDID" "DFP-0:/storage/.config/edid.bin" +# Option "IgnoreEDID" "false" +# Option "UseEDID" "true" +EndSection + +Section "Screen" + Identifier "screen" + Device "nvidia" + DefaultDepth 24 + Option "ColorRange" "Full" +# Option "ColorRange" "Limited" +# Option "ColorSpace" "RGB" + SubSection "Display" + Depth 24 + EndSubSection +EndSection + +Section "Extensions" + Option "Composite" "false" +EndSection diff --git a/packages/x11/driver/xf86-video-nvidia/package.mk b/packages/x11/driver/xf86-video-nvidia/package.mk new file mode 100644 index 000000000..9561c8124 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/package.mk @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-nvidia" +# Remember to run "python3 packages/x11/driver/xf86-video-nvidia/scripts/make_nvidia_udev.py" and commit +# changes to "packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules" whenever bumping version. +# The build host may require installation of python3-lxml and python3-requests packages. +PKG_VERSION="460.91.03" +PKG_SHA256="448156cfcef182ed6997c2754c472fd681bf7139b821d2adce1d847220c6c933" +PKG_ARCH="x86_64" +PKG_LICENSE="nonfree" +PKG_SITE="https://www.nvidia.com/en-us/drivers/unix/" +PKG_URL="http://us.download.nvidia.com/XFree86/Linux-x86_64/${PKG_VERSION}/NVIDIA-Linux-x86_64-${PKG_VERSION}-no-compat32.run" +PKG_DEPENDS_TARGET="util-macros xorg-server libvdpau libglvnd" +PKG_LONGDESC="The Xorg driver for NVIDIA GPUs supporting the GeForce 600 Series & above." +PKG_TOOLCHAIN="manual" + +PKG_IS_KERNEL_PKG="yes" + +unpack() { + [ -d ${PKG_BUILD} ] && rm -rf ${PKG_BUILD} + + sh ${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME} --extract-only --target ${PKG_BUILD} +} + +make_target() { + unset LDFLAGS + + cd kernel + make module CC=${CC} LD=${LD} SYSSRC=$(kernel_path) SYSOUT=$(kernel_path) + ${STRIP} --strip-debug nvidia.ko + cd .. +} + +makeinstall_target() { + mkdir -p ${INSTALL}/${XORG_PATH_MODULES}/drivers + cp -P nvidia_drv.so ${INSTALL}/${XORG_PATH_MODULES}/drivers/nvidia-main_drv.so + ln -sf /var/lib/nvidia_drv.so ${INSTALL}/${XORG_PATH_MODULES}/drivers/nvidia_drv.so + + mkdir -p ${INSTALL}/${XORG_PATH_MODULES}/extensions + # rename to avoid conflicts with X.Org-Server module libglx.so + cp -P libglxserver_nvidia.so.${PKG_VERSION} ${INSTALL}/${XORG_PATH_MODULES}/extensions/libglx_nvidia.so + + mkdir -p ${INSTALL}/etc/X11 + cp ${PKG_DIR}/config/*.conf ${INSTALL}/etc/X11 + + mkdir -p ${INSTALL}/usr/lib + cp -P libnvidia-glcore.so.${PKG_VERSION} ${INSTALL}/usr/lib + cp -P libnvidia-ml.so.${PKG_VERSION} ${INSTALL}/usr/lib + ln -sf /var/lib/libnvidia-ml.so.1 ${INSTALL}/usr/lib/libnvidia-ml.so.1 + cp -P libnvidia-tls.so.${PKG_VERSION} ${INSTALL}/usr/lib + cp -P libGLX_nvidia.so.${PKG_VERSION} ${INSTALL}/usr/lib/libGLX_nvidia.so.0 + + mkdir -p ${INSTALL}/$(get_full_module_dir)/nvidia + ln -sf /var/lib/nvidia.ko ${INSTALL}/$(get_full_module_dir)/nvidia/nvidia.ko + cp -P kernel/nvidia-uvm.ko ${INSTALL}/$(get_full_module_dir)/nvidia + cp -P kernel/nvidia-modeset.ko ${INSTALL}/$(get_full_module_dir)/nvidia + + mkdir -p ${INSTALL}/usr/lib/nvidia + cp -P kernel/nvidia.ko ${INSTALL}/usr/lib/nvidia + + mkdir -p ${INSTALL}/usr/bin + ln -s /var/lib/nvidia-smi ${INSTALL}/usr/bin/nvidia-smi + cp nvidia-smi ${INSTALL}/usr/bin/nvidia-main-smi + ln -s /var/lib/nvidia-xconfig ${INSTALL}/usr/bin/nvidia-xconfig + cp nvidia-xconfig ${INSTALL}/usr/bin/nvidia-main-xconfig + + mkdir -p ${INSTALL}/usr/lib/vdpau + cp libvdpau_nvidia.so* ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia-main.so.1 + ln -sf /var/lib/libvdpau_nvidia.so ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia.so + ln -sf /var/lib/libvdpau_nvidia.so.1 ${INSTALL}/usr/lib/vdpau/libvdpau_nvidia.so.1 +} diff --git a/packages/x11/driver/xf86-video-nvidia/patches/nvidia-fix-linux-5.14.patch b/packages/x11/driver/xf86-video-nvidia/patches/nvidia-fix-linux-5.14.patch new file mode 100644 index 000000000..22da726f0 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/patches/nvidia-fix-linux-5.14.patch @@ -0,0 +1,63 @@ +From f18c541edc5e122b06b0c1e65d0a422f0b8109e7 Mon Sep 17 00:00:00 2001 +From: Joan Bruguera +Date: Fri, 2 Jul 2021 02:09:58 +0200 +Subject: [PATCH] Tentative fix for NVIDIA 465.31 driver for Linux 5.14-rc1 + +--- + kernel/common/inc/nv-time.h | 6 ++++++ + kernel/nvidia-drm/nvidia-drm-drv.c | 4 ++++ + 2 files changed, 10 insertions(+) + +diff --git a/kernel/common/inc/nv-time.h b/kernel/common/inc/nv-time.h +index dc80806..cc343a5 100644 +--- a/kernel/common/inc/nv-time.h ++++ b/kernel/common/inc/nv-time.h +@@ -23,6 +23,7 @@ + #ifndef __NV_TIME_H__ + #define __NV_TIME_H__ + ++#include + #include "conftest.h" + #include + #include +@@ -205,7 +206,12 @@ static inline NV_STATUS nv_sleep_ms(unsigned int ms) + // the requested timeout has expired, loop until less + // than a jiffie of the desired delay remains. + // ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) + current->state = TASK_INTERRUPTIBLE; ++#else ++ // Rel. commit "sched: Change task_struct::state" (Peter Zijlstra, Jun 11 2021) ++ WRITE_ONCE(current->__state, TASK_INTERRUPTIBLE); ++#endif + do + { + schedule_timeout(jiffies); +diff --git a/kernel/nvidia-drm/nvidia-drm-drv.c b/kernel/nvidia-drm/nvidia-drm-drv.c +index 84d4479..99ea552 100644 +--- a/kernel/nvidia-drm/nvidia-drm-drv.c ++++ b/kernel/nvidia-drm/nvidia-drm-drv.c +@@ -20,6 +20,7 @@ + * DEALINGS IN THE SOFTWARE. + */ + ++#include + #include "nvidia-drm-conftest.h" /* NV_DRM_AVAILABLE and NV_DRM_DRM_GEM_H_PRESENT */ + + #include "nvidia-drm-priv.h" +@@ -903,9 +904,12 @@ static void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info) + + dev->dev_private = nv_dev; + nv_dev->dev = dev; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) ++ // Rel. commit "drm: Remove pdev field from struct drm_device" (Thomas Zimmermann, 3 May 2021) + if (device->bus == &pci_bus_type) { + dev->pdev = to_pci_dev(device); + } ++#endif + + /* Register DRM device to DRM sub-system */ + +-- +2.32.0 + diff --git a/packages/x11/driver/xf86-video-nvidia/scripts/compare_nvidia.py b/packages/x11/driver/xf86-video-nvidia/scripts/compare_nvidia.py new file mode 100755 index 000000000..43525b8c1 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/scripts/compare_nvidia.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv + +import re +import os +import requests +import sys + +try: + from lxml import html +except: + print('lxml module not installed.\n\nOn Ubuntu, use "sudo apt install python3-lxml"') + sys.exit(1) + +category = { + 1: 'Nvidia Geforce GPUs', + 2: 'Nvidia Quadro GPUs', + 3: 'Nvidia NVS GPUs', + 4: 'Nvidia Tesla GPUs', + } + +versions = [] +unique_ids = {} +all_ids = {i: [] for i in range(1, len(category))} + +def id_in_version(id, ids): + if any(id == value for value in ids): + return "x" + else: + return " " + +if len(sys.argv) <= 1: + print("Usage: python compare_nvidia.py ...") + exit() + +for version in sys.argv[1:]: + versions.append(version) + +for version in versions: + url = 'http://us.download.nvidia.com/XFree86/Linux-x86_64/' + version + '/README/supportedchips.html' + + headers = { + 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1', + } + + page = requests.get(url, headers=headers) + tree = html.fromstring(page.content) + + # These are the tables we want to use (gpu's supported by the current driver) + # NVIDIA GeForce GPUs = 1 + # NVIDIA Quadro GPUs = 2 + # NVIDIA NVS GPUs = 3 + # NVIDIA Tesla GPUs = 4 + + ids = {} + unique_ids[version] = {} + + for table in range(1, len(category)): + new_ids = tree.xpath('//html/body/div[@class="appendix"]/div[@class="informaltable"][' + str(table) + ']/table/tbody/tr[starts-with(@id, "devid")]/td[2]//text()') + new_labels = tree.xpath('//html/body/div[@class="appendix"]/div[@class="informaltable"][' + str(table) + ']/table/tbody/tr[starts-with(@id, "devid")]/td[1]//text()') + + # nvidia seems to like to change the way they do things... + if not new_ids: + new_ids = tree.xpath('//html/body/div[@class="appendix"]/div[@class="informaltable"][' + str(table) + ']/table/tbody/tr[starts-with(@id, "0x")]/td[2]//text()') + new_labels = tree.xpath('//html/body/div[@class="appendix"]/div[@class="informaltable"][' + str(table) + ']/table/tbody/tr[starts-with(@id, "0x")]/td[1]//text()') + + # just to make sure we get the raw id without 0x in front + new_ids = [re.sub(r"^0x", '', id) for id in new_ids] + + # If three IDs are listed, the first is the PCI Device ID, the second is the PCI Subsystem Vendor ID, and the third is the PCI Subsystem Device ID. + # We only want the PCI Device ID (the first value) + new_ids = [id.split()[0].lower() for id in new_ids] + + # Sort and remove duplicate ID's + ids[table] = sorted(set(zip(new_ids, new_labels))) + + # Add ids to list of all ids from all drivers being queried + all_ids[table].extend(ids[table]) + + # Add the ids for the specific driver version + unique_ids[version] = ids + +print("%s\t" % ("ID"), end='') +for version in versions: + print("%s\t" % (version), end='') +print("Card Name") + +print("-----------------------------------------------------------------------------------------------") + +for table in all_ids: + all_ids[table] = sorted(set(all_ids[table])) + print("%s" % (category[table])) + print("-----------------------------------------------------------------------------------------------") + for id in all_ids[table]: + print("%s\t" % (id[0]), end='') + for version in versions: + print("%s\t" % (id_in_version(id, unique_ids[version][table])), end='') + print("%s\t" % (id[1]), end='') + print("") + print("-----------------------------------------------------------------------------------------------\n") diff --git a/packages/x11/driver/xf86-video-nvidia/scripts/make_nvidia_udev.py b/packages/x11/driver/xf86-video-nvidia/scripts/make_nvidia_udev.py new file mode 100755 index 000000000..1ce12e00f --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/scripts/make_nvidia_udev.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import os, sys +import requests + +try: + from lxml import html +except: + print('lxml module not installed.\n\nOn Ubuntu, use "sudo apt install python3-lxml"') + sys.exit(1) + +__cwd__ = os.path.dirname(os.path.realpath(__file__)) +__rules__ = __cwd__ + '/../udev.d/96-nvidia.rules' +__package__ = __cwd__ + '/../package.mk' + +# Get the Nvidia driver version currently being used +for line in open(__package__, 'r'): + if "PKG_VERSION" in line: + __version__ = line.split('=')[1].replace('"','').strip() + break + +url = 'http://us.download.nvidia.com/XFree86/Linux-x86_64/' + __version__ + '/README/supportedchips.html' + +headers = { + 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1', +} + +page = requests.get(url, headers=headers) +tree = html.fromstring(page.content) + +# These are the tables we want to use (gpu's supported by the current driver) +# NVIDIA GeForce GPUs = 1 +# NVIDIA Quadro GPUs = 2 +# NVIDIA NVS GPUs = 3 +# NVIDIA Tesla GPUs = 4 + +ids = [] +for table in range(1, 5): + ids = ids + tree.xpath('//html/body/div[@class="appendix"]/div[@class="informaltable"][' + str(table) + ']/table/tbody/tr[starts-with(@id, "devid")]/td[2]//text()') + +# If three IDs are listed, the first is the PCI Device ID, the second is the PCI Subsystem Vendor ID, and the third is the PCI Subsystem Device ID. +# We only want the PCI Device ID (the first value) +unique_ids = [] +for id in ids: + unique_ids.append(id.split()[0].lower()) + +# Sort and remove duplicate ID's +unique_ids = sorted(set(unique_ids)) + +# Write the rules to the file +with open(__rules__, 'w') as f: + f.write('ACTION!="add|change", GOTO="end_video"\n') + f.write('SUBSYSTEM=="pci", ATTR{class}=="0x030000", ATTR{vendor}=="0x10de", GOTO="subsystem_pci"\n') + f.write('GOTO="end_video"\n\n') + f.write('LABEL="subsystem_pci"\n') + for id in unique_ids: + f.write('ATTR{device}=="0x' + str(id) + '", GOTO="configure_nvidia"\n') + f.write('GOTO="configure_nvidia-legacy"\n\n') + f.write('LABEL="configure_nvidia"\n') + f.write('ENV{xorg_driver}="nvidia", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@nvidia.service"\n') + f.write('GOTO="end_video"\n\n') + f.write('LABEL="configure_nvidia-legacy"\n') + f.write('ENV{xorg_driver}="nvidia", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@nvidia-legacy.service"\n') + f.write('GOTO="end_video"\n\n') + f.write('LABEL="end_video"\n') diff --git a/packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules b/packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules new file mode 100644 index 000000000..71c8f3eb9 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/udev.d/96-nvidia.rules @@ -0,0 +1,364 @@ +ACTION!="add|change", GOTO="end_video" +SUBSYSTEM=="pci", ATTR{class}=="0x030000", ATTR{vendor}=="0x10de", GOTO="subsystem_pci" +GOTO="end_video" + +LABEL="subsystem_pci" +ATTR{device}=="0x0fc0", GOTO="configure_nvidia" +ATTR{device}=="0x0fc1", GOTO="configure_nvidia" +ATTR{device}=="0x0fc2", GOTO="configure_nvidia" +ATTR{device}=="0x0fc6", GOTO="configure_nvidia" +ATTR{device}=="0x0fc8", GOTO="configure_nvidia" +ATTR{device}=="0x0fc9", GOTO="configure_nvidia" +ATTR{device}=="0x0fd2", GOTO="configure_nvidia" +ATTR{device}=="0x0fe3", GOTO="configure_nvidia" +ATTR{device}=="0x0ff3", GOTO="configure_nvidia" +ATTR{device}=="0x0ff9", GOTO="configure_nvidia" +ATTR{device}=="0x0ffa", GOTO="configure_nvidia" +ATTR{device}=="0x0ffd", GOTO="configure_nvidia" +ATTR{device}=="0x0ffe", GOTO="configure_nvidia" +ATTR{device}=="0x0fff", GOTO="configure_nvidia" +ATTR{device}=="0x1001", GOTO="configure_nvidia" +ATTR{device}=="0x1004", GOTO="configure_nvidia" +ATTR{device}=="0x1005", GOTO="configure_nvidia" +ATTR{device}=="0x1007", GOTO="configure_nvidia" +ATTR{device}=="0x1008", GOTO="configure_nvidia" +ATTR{device}=="0x100a", GOTO="configure_nvidia" +ATTR{device}=="0x100c", GOTO="configure_nvidia" +ATTR{device}=="0x1021", GOTO="configure_nvidia" +ATTR{device}=="0x1022", GOTO="configure_nvidia" +ATTR{device}=="0x1023", GOTO="configure_nvidia" +ATTR{device}=="0x1024", GOTO="configure_nvidia" +ATTR{device}=="0x1026", GOTO="configure_nvidia" +ATTR{device}=="0x1027", GOTO="configure_nvidia" +ATTR{device}=="0x1028", GOTO="configure_nvidia" +ATTR{device}=="0x1029", GOTO="configure_nvidia" +ATTR{device}=="0x102a", GOTO="configure_nvidia" +ATTR{device}=="0x102d", GOTO="configure_nvidia" +ATTR{device}=="0x103a", GOTO="configure_nvidia" +ATTR{device}=="0x103c", GOTO="configure_nvidia" +ATTR{device}=="0x1180", GOTO="configure_nvidia" +ATTR{device}=="0x1183", GOTO="configure_nvidia" +ATTR{device}=="0x1184", GOTO="configure_nvidia" +ATTR{device}=="0x1185", GOTO="configure_nvidia" +ATTR{device}=="0x1187", GOTO="configure_nvidia" +ATTR{device}=="0x1188", GOTO="configure_nvidia" +ATTR{device}=="0x1189", GOTO="configure_nvidia" +ATTR{device}=="0x118e", GOTO="configure_nvidia" +ATTR{device}=="0x118f", GOTO="configure_nvidia" +ATTR{device}=="0x1193", GOTO="configure_nvidia" +ATTR{device}=="0x1194", GOTO="configure_nvidia" +ATTR{device}=="0x1195", GOTO="configure_nvidia" +ATTR{device}=="0x1199", GOTO="configure_nvidia" +ATTR{device}=="0x11b4", GOTO="configure_nvidia" +ATTR{device}=="0x11ba", GOTO="configure_nvidia" +ATTR{device}=="0x11c0", GOTO="configure_nvidia" +ATTR{device}=="0x11c2", GOTO="configure_nvidia" +ATTR{device}=="0x11c3", GOTO="configure_nvidia" +ATTR{device}=="0x11c4", GOTO="configure_nvidia" +ATTR{device}=="0x11c5", GOTO="configure_nvidia" +ATTR{device}=="0x11c6", GOTO="configure_nvidia" +ATTR{device}=="0x11c8", GOTO="configure_nvidia" +ATTR{device}=="0x11cb", GOTO="configure_nvidia" +ATTR{device}=="0x11e3", GOTO="configure_nvidia" +ATTR{device}=="0x11fa", GOTO="configure_nvidia" +ATTR{device}=="0x1280", GOTO="configure_nvidia" +ATTR{device}=="0x1281", GOTO="configure_nvidia" +ATTR{device}=="0x1282", GOTO="configure_nvidia" +ATTR{device}=="0x1284", GOTO="configure_nvidia" +ATTR{device}=="0x1286", GOTO="configure_nvidia" +ATTR{device}=="0x1287", GOTO="configure_nvidia" +ATTR{device}=="0x1288", GOTO="configure_nvidia" +ATTR{device}=="0x1289", GOTO="configure_nvidia" +ATTR{device}=="0x128b", GOTO="configure_nvidia" +ATTR{device}=="0x1290", GOTO="configure_nvidia" +ATTR{device}=="0x1292", GOTO="configure_nvidia" +ATTR{device}=="0x1295", GOTO="configure_nvidia" +ATTR{device}=="0x1299", GOTO="configure_nvidia" +ATTR{device}=="0x1340", GOTO="configure_nvidia" +ATTR{device}=="0x1341", GOTO="configure_nvidia" +ATTR{device}=="0x1344", GOTO="configure_nvidia" +ATTR{device}=="0x1346", GOTO="configure_nvidia" +ATTR{device}=="0x1347", GOTO="configure_nvidia" +ATTR{device}=="0x1348", GOTO="configure_nvidia" +ATTR{device}=="0x1349", GOTO="configure_nvidia" +ATTR{device}=="0x134b", GOTO="configure_nvidia" +ATTR{device}=="0x134d", GOTO="configure_nvidia" +ATTR{device}=="0x134e", GOTO="configure_nvidia" +ATTR{device}=="0x134f", GOTO="configure_nvidia" +ATTR{device}=="0x137a", GOTO="configure_nvidia" +ATTR{device}=="0x137b", GOTO="configure_nvidia" +ATTR{device}=="0x137d", GOTO="configure_nvidia" +ATTR{device}=="0x1380", GOTO="configure_nvidia" +ATTR{device}=="0x1381", GOTO="configure_nvidia" +ATTR{device}=="0x1382", GOTO="configure_nvidia" +ATTR{device}=="0x1390", GOTO="configure_nvidia" +ATTR{device}=="0x1391", GOTO="configure_nvidia" +ATTR{device}=="0x1392", GOTO="configure_nvidia" +ATTR{device}=="0x1393", GOTO="configure_nvidia" +ATTR{device}=="0x1398", GOTO="configure_nvidia" +ATTR{device}=="0x1399", GOTO="configure_nvidia" +ATTR{device}=="0x139a", GOTO="configure_nvidia" +ATTR{device}=="0x139b", GOTO="configure_nvidia" +ATTR{device}=="0x139c", GOTO="configure_nvidia" +ATTR{device}=="0x139d", GOTO="configure_nvidia" +ATTR{device}=="0x13b0", GOTO="configure_nvidia" +ATTR{device}=="0x13b1", GOTO="configure_nvidia" +ATTR{device}=="0x13b2", GOTO="configure_nvidia" +ATTR{device}=="0x13b3", GOTO="configure_nvidia" +ATTR{device}=="0x13b4", GOTO="configure_nvidia" +ATTR{device}=="0x13b6", GOTO="configure_nvidia" +ATTR{device}=="0x13b9", GOTO="configure_nvidia" +ATTR{device}=="0x13ba", GOTO="configure_nvidia" +ATTR{device}=="0x13bb", GOTO="configure_nvidia" +ATTR{device}=="0x13bc", GOTO="configure_nvidia" +ATTR{device}=="0x13c0", GOTO="configure_nvidia" +ATTR{device}=="0x13c2", GOTO="configure_nvidia" +ATTR{device}=="0x13d7", GOTO="configure_nvidia" +ATTR{device}=="0x13d8", GOTO="configure_nvidia" +ATTR{device}=="0x13d9", GOTO="configure_nvidia" +ATTR{device}=="0x13da", GOTO="configure_nvidia" +ATTR{device}=="0x13f0", GOTO="configure_nvidia" +ATTR{device}=="0x13f1", GOTO="configure_nvidia" +ATTR{device}=="0x13f2", GOTO="configure_nvidia" +ATTR{device}=="0x13f3", GOTO="configure_nvidia" +ATTR{device}=="0x13f8", GOTO="configure_nvidia" +ATTR{device}=="0x13f9", GOTO="configure_nvidia" +ATTR{device}=="0x13fa", GOTO="configure_nvidia" +ATTR{device}=="0x13fb", GOTO="configure_nvidia" +ATTR{device}=="0x1401", GOTO="configure_nvidia" +ATTR{device}=="0x1402", GOTO="configure_nvidia" +ATTR{device}=="0x1406", GOTO="configure_nvidia" +ATTR{device}=="0x1407", GOTO="configure_nvidia" +ATTR{device}=="0x1427", GOTO="configure_nvidia" +ATTR{device}=="0x1430", GOTO="configure_nvidia" +ATTR{device}=="0x1431", GOTO="configure_nvidia" +ATTR{device}=="0x1436", GOTO="configure_nvidia" +ATTR{device}=="0x15f0", GOTO="configure_nvidia" +ATTR{device}=="0x15f7", GOTO="configure_nvidia" +ATTR{device}=="0x15f8", GOTO="configure_nvidia" +ATTR{device}=="0x15f9", GOTO="configure_nvidia" +ATTR{device}=="0x1617", GOTO="configure_nvidia" +ATTR{device}=="0x1618", GOTO="configure_nvidia" +ATTR{device}=="0x1619", GOTO="configure_nvidia" +ATTR{device}=="0x161a", GOTO="configure_nvidia" +ATTR{device}=="0x1667", GOTO="configure_nvidia" +ATTR{device}=="0x174d", GOTO="configure_nvidia" +ATTR{device}=="0x174e", GOTO="configure_nvidia" +ATTR{device}=="0x179c", GOTO="configure_nvidia" +ATTR{device}=="0x17c2", GOTO="configure_nvidia" +ATTR{device}=="0x17c8", GOTO="configure_nvidia" +ATTR{device}=="0x17f0", GOTO="configure_nvidia" +ATTR{device}=="0x17f1", GOTO="configure_nvidia" +ATTR{device}=="0x17fd", GOTO="configure_nvidia" +ATTR{device}=="0x1b00", GOTO="configure_nvidia" +ATTR{device}=="0x1b02", GOTO="configure_nvidia" +ATTR{device}=="0x1b06", GOTO="configure_nvidia" +ATTR{device}=="0x1b30", GOTO="configure_nvidia" +ATTR{device}=="0x1b38", GOTO="configure_nvidia" +ATTR{device}=="0x1b80", GOTO="configure_nvidia" +ATTR{device}=="0x1b81", GOTO="configure_nvidia" +ATTR{device}=="0x1b82", GOTO="configure_nvidia" +ATTR{device}=="0x1b83", GOTO="configure_nvidia" +ATTR{device}=="0x1b84", GOTO="configure_nvidia" +ATTR{device}=="0x1b87", GOTO="configure_nvidia" +ATTR{device}=="0x1ba0", GOTO="configure_nvidia" +ATTR{device}=="0x1ba1", GOTO="configure_nvidia" +ATTR{device}=="0x1ba2", GOTO="configure_nvidia" +ATTR{device}=="0x1bb0", GOTO="configure_nvidia" +ATTR{device}=="0x1bb1", GOTO="configure_nvidia" +ATTR{device}=="0x1bb3", GOTO="configure_nvidia" +ATTR{device}=="0x1bb4", GOTO="configure_nvidia" +ATTR{device}=="0x1bb5", GOTO="configure_nvidia" +ATTR{device}=="0x1bb6", GOTO="configure_nvidia" +ATTR{device}=="0x1bb7", GOTO="configure_nvidia" +ATTR{device}=="0x1bb8", GOTO="configure_nvidia" +ATTR{device}=="0x1bb9", GOTO="configure_nvidia" +ATTR{device}=="0x1bbb", GOTO="configure_nvidia" +ATTR{device}=="0x1bc7", GOTO="configure_nvidia" +ATTR{device}=="0x1be0", GOTO="configure_nvidia" +ATTR{device}=="0x1be1", GOTO="configure_nvidia" +ATTR{device}=="0x1c02", GOTO="configure_nvidia" +ATTR{device}=="0x1c03", GOTO="configure_nvidia" +ATTR{device}=="0x1c04", GOTO="configure_nvidia" +ATTR{device}=="0x1c06", GOTO="configure_nvidia" +ATTR{device}=="0x1c07", GOTO="configure_nvidia" +ATTR{device}=="0x1c09", GOTO="configure_nvidia" +ATTR{device}=="0x1c20", GOTO="configure_nvidia" +ATTR{device}=="0x1c21", GOTO="configure_nvidia" +ATTR{device}=="0x1c22", GOTO="configure_nvidia" +ATTR{device}=="0x1c23", GOTO="configure_nvidia" +ATTR{device}=="0x1c30", GOTO="configure_nvidia" +ATTR{device}=="0x1c31", GOTO="configure_nvidia" +ATTR{device}=="0x1c60", GOTO="configure_nvidia" +ATTR{device}=="0x1c61", GOTO="configure_nvidia" +ATTR{device}=="0x1c62", GOTO="configure_nvidia" +ATTR{device}=="0x1c81", GOTO="configure_nvidia" +ATTR{device}=="0x1c82", GOTO="configure_nvidia" +ATTR{device}=="0x1c83", GOTO="configure_nvidia" +ATTR{device}=="0x1c8c", GOTO="configure_nvidia" +ATTR{device}=="0x1c8d", GOTO="configure_nvidia" +ATTR{device}=="0x1c8f", GOTO="configure_nvidia" +ATTR{device}=="0x1c90", GOTO="configure_nvidia" +ATTR{device}=="0x1c91", GOTO="configure_nvidia" +ATTR{device}=="0x1c92", GOTO="configure_nvidia" +ATTR{device}=="0x1c94", GOTO="configure_nvidia" +ATTR{device}=="0x1c96", GOTO="configure_nvidia" +ATTR{device}=="0x1cb1", GOTO="configure_nvidia" +ATTR{device}=="0x1cb2", GOTO="configure_nvidia" +ATTR{device}=="0x1cb3", GOTO="configure_nvidia" +ATTR{device}=="0x1cb6", GOTO="configure_nvidia" +ATTR{device}=="0x1cba", GOTO="configure_nvidia" +ATTR{device}=="0x1cbb", GOTO="configure_nvidia" +ATTR{device}=="0x1cbc", GOTO="configure_nvidia" +ATTR{device}=="0x1cbd", GOTO="configure_nvidia" +ATTR{device}=="0x1cfa", GOTO="configure_nvidia" +ATTR{device}=="0x1cfb", GOTO="configure_nvidia" +ATTR{device}=="0x1d01", GOTO="configure_nvidia" +ATTR{device}=="0x1d02", GOTO="configure_nvidia" +ATTR{device}=="0x1d10", GOTO="configure_nvidia" +ATTR{device}=="0x1d11", GOTO="configure_nvidia" +ATTR{device}=="0x1d12", GOTO="configure_nvidia" +ATTR{device}=="0x1d13", GOTO="configure_nvidia" +ATTR{device}=="0x1d16", GOTO="configure_nvidia" +ATTR{device}=="0x1d33", GOTO="configure_nvidia" +ATTR{device}=="0x1d34", GOTO="configure_nvidia" +ATTR{device}=="0x1d52", GOTO="configure_nvidia" +ATTR{device}=="0x1d81", GOTO="configure_nvidia" +ATTR{device}=="0x1db1", GOTO="configure_nvidia" +ATTR{device}=="0x1db3", GOTO="configure_nvidia" +ATTR{device}=="0x1db4", GOTO="configure_nvidia" +ATTR{device}=="0x1db5", GOTO="configure_nvidia" +ATTR{device}=="0x1db6", GOTO="configure_nvidia" +ATTR{device}=="0x1db7", GOTO="configure_nvidia" +ATTR{device}=="0x1db8", GOTO="configure_nvidia" +ATTR{device}=="0x1dba", GOTO="configure_nvidia" +ATTR{device}=="0x1df0", GOTO="configure_nvidia" +ATTR{device}=="0x1df2", GOTO="configure_nvidia" +ATTR{device}=="0x1df5", GOTO="configure_nvidia" +ATTR{device}=="0x1df6", GOTO="configure_nvidia" +ATTR{device}=="0x1e02", GOTO="configure_nvidia" +ATTR{device}=="0x1e04", GOTO="configure_nvidia" +ATTR{device}=="0x1e07", GOTO="configure_nvidia" +ATTR{device}=="0x1e09", GOTO="configure_nvidia" +ATTR{device}=="0x1e30", GOTO="configure_nvidia" +ATTR{device}=="0x1e36", GOTO="configure_nvidia" +ATTR{device}=="0x1e78", GOTO="configure_nvidia" +ATTR{device}=="0x1e81", GOTO="configure_nvidia" +ATTR{device}=="0x1e82", GOTO="configure_nvidia" +ATTR{device}=="0x1e84", GOTO="configure_nvidia" +ATTR{device}=="0x1e87", GOTO="configure_nvidia" +ATTR{device}=="0x1e89", GOTO="configure_nvidia" +ATTR{device}=="0x1e90", GOTO="configure_nvidia" +ATTR{device}=="0x1e91", GOTO="configure_nvidia" +ATTR{device}=="0x1e93", GOTO="configure_nvidia" +ATTR{device}=="0x1eb0", GOTO="configure_nvidia" +ATTR{device}=="0x1eb1", GOTO="configure_nvidia" +ATTR{device}=="0x1eb5", GOTO="configure_nvidia" +ATTR{device}=="0x1eb6", GOTO="configure_nvidia" +ATTR{device}=="0x1eb8", GOTO="configure_nvidia" +ATTR{device}=="0x1ec2", GOTO="configure_nvidia" +ATTR{device}=="0x1ec7", GOTO="configure_nvidia" +ATTR{device}=="0x1ed0", GOTO="configure_nvidia" +ATTR{device}=="0x1ed1", GOTO="configure_nvidia" +ATTR{device}=="0x1ed3", GOTO="configure_nvidia" +ATTR{device}=="0x1ef5", GOTO="configure_nvidia" +ATTR{device}=="0x1f02", GOTO="configure_nvidia" +ATTR{device}=="0x1f06", GOTO="configure_nvidia" +ATTR{device}=="0x1f07", GOTO="configure_nvidia" +ATTR{device}=="0x1f08", GOTO="configure_nvidia" +ATTR{device}=="0x1f09", GOTO="configure_nvidia" +ATTR{device}=="0x1f0a", GOTO="configure_nvidia" +ATTR{device}=="0x1f0b", GOTO="configure_nvidia" +ATTR{device}=="0x1f10", GOTO="configure_nvidia" +ATTR{device}=="0x1f11", GOTO="configure_nvidia" +ATTR{device}=="0x1f12", GOTO="configure_nvidia" +ATTR{device}=="0x1f14", GOTO="configure_nvidia" +ATTR{device}=="0x1f15", GOTO="configure_nvidia" +ATTR{device}=="0x1f36", GOTO="configure_nvidia" +ATTR{device}=="0x1f42", GOTO="configure_nvidia" +ATTR{device}=="0x1f47", GOTO="configure_nvidia" +ATTR{device}=="0x1f50", GOTO="configure_nvidia" +ATTR{device}=="0x1f51", GOTO="configure_nvidia" +ATTR{device}=="0x1f54", GOTO="configure_nvidia" +ATTR{device}=="0x1f55", GOTO="configure_nvidia" +ATTR{device}=="0x1f76", GOTO="configure_nvidia" +ATTR{device}=="0x1f82", GOTO="configure_nvidia" +ATTR{device}=="0x1f91", GOTO="configure_nvidia" +ATTR{device}=="0x1f95", GOTO="configure_nvidia" +ATTR{device}=="0x1f96", GOTO="configure_nvidia" +ATTR{device}=="0x1f97", GOTO="configure_nvidia" +ATTR{device}=="0x1f98", GOTO="configure_nvidia" +ATTR{device}=="0x1f99", GOTO="configure_nvidia" +ATTR{device}=="0x1f9c", GOTO="configure_nvidia" +ATTR{device}=="0x1f9d", GOTO="configure_nvidia" +ATTR{device}=="0x1fb0", GOTO="configure_nvidia" +ATTR{device}=="0x1fb1", GOTO="configure_nvidia" +ATTR{device}=="0x1fb2", GOTO="configure_nvidia" +ATTR{device}=="0x1fb8", GOTO="configure_nvidia" +ATTR{device}=="0x1fb9", GOTO="configure_nvidia" +ATTR{device}=="0x1fba", GOTO="configure_nvidia" +ATTR{device}=="0x1fbb", GOTO="configure_nvidia" +ATTR{device}=="0x1fbc", GOTO="configure_nvidia" +ATTR{device}=="0x1fdd", GOTO="configure_nvidia" +ATTR{device}=="0x1ff9", GOTO="configure_nvidia" +ATTR{device}=="0x20b0", GOTO="configure_nvidia" +ATTR{device}=="0x20b1", GOTO="configure_nvidia" +ATTR{device}=="0x20b2", GOTO="configure_nvidia" +ATTR{device}=="0x20b6", GOTO="configure_nvidia" +ATTR{device}=="0x20b7", GOTO="configure_nvidia" +ATTR{device}=="0x20f1", GOTO="configure_nvidia" +ATTR{device}=="0x2182", GOTO="configure_nvidia" +ATTR{device}=="0x2184", GOTO="configure_nvidia" +ATTR{device}=="0x2187", GOTO="configure_nvidia" +ATTR{device}=="0x2188", GOTO="configure_nvidia" +ATTR{device}=="0x2189", GOTO="configure_nvidia" +ATTR{device}=="0x2191", GOTO="configure_nvidia" +ATTR{device}=="0x2192", GOTO="configure_nvidia" +ATTR{device}=="0x21c4", GOTO="configure_nvidia" +ATTR{device}=="0x21d1", GOTO="configure_nvidia" +ATTR{device}=="0x2204", GOTO="configure_nvidia" +ATTR{device}=="0x2206", GOTO="configure_nvidia" +ATTR{device}=="0x2208", GOTO="configure_nvidia" +ATTR{device}=="0x2216", GOTO="configure_nvidia" +ATTR{device}=="0x2230", GOTO="configure_nvidia" +ATTR{device}=="0x2231", GOTO="configure_nvidia" +ATTR{device}=="0x2235", GOTO="configure_nvidia" +ATTR{device}=="0x2236", GOTO="configure_nvidia" +ATTR{device}=="0x2237", GOTO="configure_nvidia" +ATTR{device}=="0x2482", GOTO="configure_nvidia" +ATTR{device}=="0x2484", GOTO="configure_nvidia" +ATTR{device}=="0x2486", GOTO="configure_nvidia" +ATTR{device}=="0x2488", GOTO="configure_nvidia" +ATTR{device}=="0x2489", GOTO="configure_nvidia" +ATTR{device}=="0x249c", GOTO="configure_nvidia" +ATTR{device}=="0x249d", GOTO="configure_nvidia" +ATTR{device}=="0x24b0", GOTO="configure_nvidia" +ATTR{device}=="0x24b6", GOTO="configure_nvidia" +ATTR{device}=="0x24b7", GOTO="configure_nvidia" +ATTR{device}=="0x24b8", GOTO="configure_nvidia" +ATTR{device}=="0x24dc", GOTO="configure_nvidia" +ATTR{device}=="0x24dd", GOTO="configure_nvidia" +ATTR{device}=="0x2503", GOTO="configure_nvidia" +ATTR{device}=="0x2504", GOTO="configure_nvidia" +ATTR{device}=="0x2520", GOTO="configure_nvidia" +ATTR{device}=="0x2523", GOTO="configure_nvidia" +ATTR{device}=="0x2560", GOTO="configure_nvidia" +ATTR{device}=="0x2563", GOTO="configure_nvidia" +ATTR{device}=="0x25a0", GOTO="configure_nvidia" +ATTR{device}=="0x25a2", GOTO="configure_nvidia" +ATTR{device}=="0x25a5", GOTO="configure_nvidia" +ATTR{device}=="0x25b8", GOTO="configure_nvidia" +ATTR{device}=="0x25e0", GOTO="configure_nvidia" +ATTR{device}=="0x25e2", GOTO="configure_nvidia" +ATTR{device}=="0x25e5", GOTO="configure_nvidia" +GOTO="configure_nvidia-legacy" + +LABEL="configure_nvidia" +ENV{xorg_driver}="nvidia", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@nvidia.service" +GOTO="end_video" + +LABEL="configure_nvidia-legacy" +ENV{xorg_driver}="nvidia", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@nvidia-legacy.service" +GOTO="end_video" + +LABEL="end_video" diff --git a/packages/x11/driver/xf86-video-vmware/package.mk b/packages/x11/driver/xf86-video-vmware/package.mk new file mode 100644 index 000000000..001e22605 --- /dev/null +++ b/packages/x11/driver/xf86-video-vmware/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xf86-video-vmware" +PKG_VERSION="13.3.0" +PKG_SHA256="47971924659e51666a757269ad941a059ef5afe7a47b5101c174a6022ac4066c" +PKG_ARCH="x86_64" +PKG_LICENSE="OSS" +PKG_SITE="http://www.vmware.com" +PKG_URL="http://xorg.freedesktop.org/releases/individual/driver/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain mesa libX11 xorg-server" +PKG_LONGDESC="xf86-video-vmware: The Xorg driver for vmware video" +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--enable-vmwarectrl-client \ + --with-xorg-module-dir=${XORG_PATH_MODULES}" diff --git a/packages/x11/font/encodings/package.mk b/packages/x11/font/encodings/package.mk new file mode 100644 index 000000000..a8722acdc --- /dev/null +++ b/packages/x11/font/encodings/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="encodings" +PKG_VERSION="1.0.5" +PKG_SHA256="bd96e16143a044b19e87f217cf6a3763a70c561d1076aad6f6d862ec41774a31" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros font-util:host" +PKG_LONGDESC="X font encoding meta files." + +PKG_CONFIGURE_OPTS_TARGET="--enable-gzip-small-encodings \ + --enable-gzip-large-encodings \ + --with-fontrootdir=/usr/share/fonts" diff --git a/packages/x11/font/font-bitstream-type1/package.mk b/packages/x11/font/font-bitstream-type1/package.mk new file mode 100644 index 000000000..7d9dc612f --- /dev/null +++ b/packages/x11/font/font-bitstream-type1/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="font-bitstream-type1" +PKG_VERSION="1.0.3" +PKG_SHA256="c6ea0569adad2c577f140328dc3302e729cb1b1ea90cd0025caf380625f8a688" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros font-xfree86-type1" +PKG_LONGDESC="Bitstream font family." + +PKG_CONFIGURE_OPTS_TARGET="--with-fontrootdir=/usr/share/fonts" + +post_install() { + mkfontdir ${INSTALL}/usr/share/fonts/Type1 + mkfontscale ${INSTALL}/usr/share/fonts/Type1 +} diff --git a/packages/x11/font/font-cursor-misc/package.mk b/packages/x11/font/font-cursor-misc/package.mk new file mode 100644 index 000000000..144e7e77a --- /dev/null +++ b/packages/x11/font/font-cursor-misc/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="font-cursor-misc" +PKG_VERSION="1.0.3" +PKG_SHA256="17363eb35eece2e08144da5f060c70103b59d0972b4f4d77fd84c9a7a2dba635" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros font-util:host" +PKG_LONGDESC="X11 cursor fonts." + +PKG_CONFIGURE_OPTS_TARGET="--with-fontrootdir=/usr/share/fonts" + +post_install() { + mkfontdir ${INSTALL}/usr/share/fonts/misc + mkfontscale ${INSTALL}/usr/share/fonts/misc +} diff --git a/packages/x11/font/font-misc-misc/package.mk b/packages/x11/font/font-misc-misc/package.mk new file mode 100644 index 000000000..623552ae8 --- /dev/null +++ b/packages/x11/font/font-misc-misc/package.mk @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="font-misc-misc" +PKG_VERSION="1.1.2" +PKG_SHA256="b8e77940e4e1769dc47ef1805918d8c9be37c708735832a07204258bacc11794" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros font-util font-cursor-misc" +PKG_LONGDESC="A misc. public domain font." + +PKG_CONFIGURE_OPTS_TARGET="--with-fontrootdir=/usr/share/fonts \ + --disable-silent-rules \ + --enable-iso8859-1 \ + --enable-iso8859-2 \ + --disable-iso8859-3 \ + --disable-iso8859-4 \ + --enable-iso8859-5 \ + --enable-iso8859-7 \ + --enable-iso8859-8 \ + --enable-iso8859-9 \ + --disable-iso8859-10 \ + --disable-iso8859-11 \ + --disable-iso8859-13 \ + --enable-iso8859-14 \ + --enable-iso8859-15 \ + --disable-iso8859-16 \ + --disable-koi8-r \ + --disable-jisx0201" + +PKG_MAKE_OPTS_TARGET="UTIL_DIR=${SYSROOT_PREFIX}/usr/share/fonts/util/" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/fonts/misc + cp 6x13-ISO8859-1.pcf.gz ${INSTALL}/usr/share/fonts/misc +} + +post_install() { + mkfontdir ${INSTALL}/usr/share/fonts/misc + mkfontscale ${INSTALL}/usr/share/fonts/misc +} diff --git a/packages/x11/font/font-util/package.mk b/packages/x11/font/font-util/package.mk new file mode 100644 index 000000000..6a6a07d82 --- /dev/null +++ b/packages/x11/font/font-util/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="font-util" +PKG_VERSION="1.3.2" +PKG_SHA256="3ad880444123ac06a7238546fa38a2a6ad7f7e0cc3614de7e103863616522282" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_DEPENDS_HOST="util-macros" +PKG_LONGDESC="X.org font utilities." + +PKG_CONFIGURE_OPTS_TARGET="--with-fontrootdir=/usr/share/fonts \ + --with-mapdir=/usr/share/fonts/util" + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin +} diff --git a/packages/x11/font/font-xfree86-type1/package.mk b/packages/x11/font/font-xfree86-type1/package.mk new file mode 100644 index 000000000..9a2df9ec4 --- /dev/null +++ b/packages/x11/font/font-xfree86-type1/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="font-xfree86-type1" +PKG_VERSION="1.0.4" +PKG_SHA256="caebf42aec7be7f3bd40e0f232d6f34881b853dc84acfcdf7458358701fbe34a" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/releases/individual/font/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="A Xfree86 Inc. Type1 font." + +PKG_CONFIGURE_OPTS_TARGET="--with-fontrootdir=/usr/share/fonts" + +post_install() { + mkfontdir ${INSTALL}/usr/share/fonts/Type1 + mkfontscale ${INSTALL}/usr/share/fonts/Type1 +} diff --git a/packages/x11/font/liberation-fonts-ttf/package.mk b/packages/x11/font/liberation-fonts-ttf/package.mk new file mode 100644 index 000000000..9fa15a47b --- /dev/null +++ b/packages/x11/font/liberation-fonts-ttf/package.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="liberation-fonts-ttf" +PKG_VERSION="2.1.5" +PKG_SHA256="7191c669bf38899f73a2094ed00f7b800553364f90e2637010a69c0e268f25d0" +PKG_LICENSE="OFL1_1" +PKG_SITE="https://github.com/liberationfonts/liberation-fonts" +PKG_URL="https://github.com/liberationfonts/liberation-fonts/files/7261482/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="This packages included the high-quality and open-sourced TrueType vector fonts." +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p ${INSTALL}/usr/share/fonts/liberation + cp *.ttf ${INSTALL}/usr/share/fonts/liberation +} + +post_install() { + mkfontdir ${INSTALL}/usr/share/fonts/liberation + mkfontscale ${INSTALL}/usr/share/fonts/liberation +} diff --git a/packages/x11/lib/libICE/package.mk b/packages/x11/lib/libICE/package.mk new file mode 100644 index 000000000..acfa60613 --- /dev/null +++ b/packages/x11/lib/libICE/package.mk @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libICE" +PKG_VERSION="1.0.10" +PKG_SHA256="6f86dce12cf4bcaf5c37dddd8b1b64ed2ddf1ef7b218f22b9942595fb747c348" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros xtrans" +PKG_LONGDESC="X Inter-Client Exchange (ICE) protocol library." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-ipv6 \ + --without-xmlto" diff --git a/packages/x11/lib/libSM/package.mk b/packages/x11/lib/libSM/package.mk new file mode 100644 index 000000000..a2b16ef52 --- /dev/null +++ b/packages/x11/lib/libSM/package.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libSM" +PKG_VERSION="1.2.3" +PKG_SHA256="2d264499dcb05f56438dee12a1b4b71d76736ce7ba7aa6efbf15ebb113769cbb" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros util-linux libICE" +PKG_LONGDESC="This package provides the main interface to the X11 Session Management library." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --with-libuuid \ + --without-xmlto \ + --without-fop" diff --git a/packages/x11/lib/libX11/package.mk b/packages/x11/lib/libX11/package.mk new file mode 100644 index 000000000..d03961af3 --- /dev/null +++ b/packages/x11/lib/libX11/package.mk @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2017 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libX11" +PKG_VERSION="1.7.2" +PKG_SHA256="1cfa35e37aaabbe4792e9bb690468efefbfbf6b147d9c69d6f90d13c3092ea6c" +PKG_LICENSE="OSS" +PKG_SITE="http://www.x.org/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros xtrans libXau libxcb xorgproto" +PKG_LONGDESC="LibX11 is the main X11 library containing all the client-side code to access the X11 windowing system." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="--disable-loadable-i18n \ + --disable-loadable-xcursor \ + --enable-xthreads \ + --disable-xcms \ + --enable-xlocale \ + --disable-xlocaledir \ + --enable-xkb \ + --with-keysymdefdir=${SYSROOT_PREFIX}/usr/include/X11 \ + --disable-xf86bigfont \ + --enable-malloc0returnsnull \ + --disable-specs \ + --without-xmlto \ + --without-fop \ + --enable-composecache \ + --disable-lint-library \ + --disable-ipv6 \ + --without-launchd \ + --without-lint" diff --git a/packages/x11/lib/libX11/patches/libX11-disable_nls_tests.patch b/packages/x11/lib/libX11/patches/libX11-disable_nls_tests.patch new file mode 100644 index 000000000..3afa79a75 --- /dev/null +++ b/packages/x11/lib/libX11/patches/libX11-disable_nls_tests.patch @@ -0,0 +1,18 @@ +diff -Naur libX11-1.6.0/nls/Makefile.am libX11-1.6.0.patch/nls/Makefile.am +--- libX11-1.6.0/nls/Makefile.am 2013-06-04 04:21:16.000000000 +0200 ++++ libX11-1.6.0.patch/nls/Makefile.am 2013-06-04 17:07:11.962522739 +0200 +@@ -36,10 +36,10 @@ + < locale.dir.l1 > locale.dir.l2 + cat locale.dir.l2 locale.dir.l1 > locale.dir + +-if HAVE_PERL +-LOG_COMPILER = $(PERL) +-TESTS = compose-check.pl +-endif HAVE_PERL ++# if HAVE_PERL ++# LOG_COMPILER = $(PERL) ++# TESTS = compose-check.pl ++# endif HAVE_PERL + + + # Per-locale data files diff --git a/packages/x11/lib/libXau/package.mk b/packages/x11/lib/libXau/package.mk new file mode 100644 index 000000000..8753221c2 --- /dev/null +++ b/packages/x11/lib/libXau/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXau" +PKG_VERSION="1.0.9" +PKG_SHA256="ccf8cbf0dbf676faa2ea0a6d64bcc3b6746064722b606c8c52917ed00dcb73ec" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros xorgproto" +PKG_LONGDESC="X authorization file management libary" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --enable-xthreads" diff --git a/packages/x11/lib/libXcomposite/package.mk b/packages/x11/lib/libXcomposite/package.mk new file mode 100644 index 000000000..8dbc06068 --- /dev/null +++ b/packages/x11/lib/libXcomposite/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXcomposite" +PKG_VERSION="0.4.5" +PKG_SHA256="b3218a2c15bab8035d16810df5b8251ffc7132ff3aa70651a1fba0bfe9634e8f" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libXfixes libXext libX11" +PKG_LONGDESC="X Composite Library" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/libXdamage/package.mk b/packages/x11/lib/libXdamage/package.mk new file mode 100644 index 000000000..b077f3d75 --- /dev/null +++ b/packages/x11/lib/libXdamage/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXdamage" +PKG_VERSION="1.1.5" +PKG_SHA256="b734068643cac3b5f3d2c8279dd366b5bf28c7219d9e9d8717e1383995e0ea45" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libXfixes" +PKG_LONGDESC="LibXdamage provides an X Window System client interface to the DAMAGE extension to the X protocol." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/libXext/package.mk b/packages/x11/lib/libXext/package.mk new file mode 100644 index 000000000..9433d1d4a --- /dev/null +++ b/packages/x11/lib/libXext/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXext" +PKG_VERSION="1.3.4" +PKG_SHA256="59ad6fcce98deaecc14d39a672cf218ca37aba617c9a0f691cac3bcd28edf82b" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11" +PKG_LONGDESC="LibXext provides an X Window System client interface to several extensions to the X protocol." + +PKG_CONFIGURE_OPTS_TARGET="--enable-malloc0returnsnull --without-xmlto" diff --git a/packages/x11/lib/libXfixes/package.mk b/packages/x11/lib/libXfixes/package.mk new file mode 100644 index 000000000..78592b34e --- /dev/null +++ b/packages/x11/lib/libXfixes/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXfixes" +PKG_VERSION="6.0.0" +PKG_SHA256="a7c1a24da53e0b46cac5aea79094b4b2257321c621b258729bc3139149245b4c" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11" +PKG_LONGDESC="X Fixes Library" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/libXfont2/package.mk b/packages/x11/lib/libXfont2/package.mk new file mode 100644 index 000000000..536ebca02 --- /dev/null +++ b/packages/x11/lib/libXfont2/package.mk @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXfont2" +PKG_VERSION="2.0.5" +PKG_SHA256="aa7c6f211cf7215c0ab4819ed893dc98034363d7b930b844bb43603c2e10b53e" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros xtrans freetype libfontenc" +PKG_LONGDESC="X font Library" + +PKG_CONFIGURE_OPTS_TARGET="--disable-ipv6 \ + --enable-freetype \ + --enable-builtins \ + --disable-pcfformat \ + --disable-bdfformat \ + --disable-snfformat \ + --enable-fc \ + --with-gnu-ld \ + --without-xmlto" diff --git a/packages/x11/lib/libXi/package.mk b/packages/x11/lib/libXi/package.mk new file mode 100644 index 000000000..ef39d7286 --- /dev/null +++ b/packages/x11/lib/libXi/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXi" +PKG_VERSION="1.8" +PKG_SHA256="2ed181446a61c7337576467870bc5336fc9e222a281122d96c4d39a3298bba00" +PKG_LICENSE="OSS" +PKG_SITE="http://www.x.org/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libXfixes libXext" +PKG_LONGDESC="LibXi provides an X Window System client interface to the XINPUT extension to the X protocol." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared \ + --enable-malloc0returnsnull \ + --disable-silent-rules \ + --disable-docs \ + --disable-specs \ + --without-xmlto \ + --without-fop \ + --without-xsltproc \ + --without-asciidoc \ + --with-gnu-ld" diff --git a/packages/x11/lib/libXinerama/package.mk b/packages/x11/lib/libXinerama/package.mk new file mode 100644 index 000000000..a07df8219 --- /dev/null +++ b/packages/x11/lib/libXinerama/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXinerama" +PKG_VERSION="1.1.4" +PKG_SHA256="0008dbd7ecf717e1e507eed1856ab0d9cf946d03201b85d5dcf61489bb02d720" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libXext" +PKG_LONGDESC="libXinerama is the Xinerama library." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --enable-malloc0returnsnull" diff --git a/packages/x11/lib/libXmu/package.mk b/packages/x11/lib/libXmu/package.mk new file mode 100644 index 000000000..8e08bdfd5 --- /dev/null +++ b/packages/x11/lib/libXmu/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXmu" +PKG_VERSION="1.1.3" +PKG_SHA256="9c343225e7c3dc0904f2122b562278da5fed639b1b5e880d25111561bac5b731" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libXext libX11 libXt" +PKG_LONGDESC="LibXmu provides a set of miscellaneous utility convenience functions for X libraries to use." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --with-gnu-ld --without-xmlto" diff --git a/packages/x11/lib/libXrandr/package.mk b/packages/x11/lib/libXrandr/package.mk new file mode 100644 index 000000000..2d9683f11 --- /dev/null +++ b/packages/x11/lib/libXrandr/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXrandr" +PKG_VERSION="1.5.2" +PKG_SHA256="8aea0ebe403d62330bb741ed595b53741acf45033d3bda1792f1d4cc3daee023" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libXrender libXext" +PKG_LONGDESC="Xrandr is a simple library designed to interface the X Resize and Rotate Extension." + +PKG_CONFIGURE_OPTS_TARGET="--enable-malloc0returnsnull" diff --git a/packages/x11/lib/libXrender/package.mk b/packages/x11/lib/libXrender/package.mk new file mode 100644 index 000000000..4f23c859d --- /dev/null +++ b/packages/x11/lib/libXrender/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXrender" +PKG_VERSION="0.9.10" +PKG_SHA256="c06d5979f86e64cabbde57c223938db0b939dff49fdb5a793a1d3d0396650949" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11" +PKG_LONGDESC="The X Rendering Extension introduces digital image composition within the X Window System." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --enable-malloc0returnsnull" diff --git a/packages/x11/lib/libXt/package.mk b/packages/x11/lib/libXt/package.mk new file mode 100644 index 000000000..dd7c40603 --- /dev/null +++ b/packages/x11/lib/libXt/package.mk @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXt" +PKG_VERSION="1.2.1" +PKG_SHA256="679cc08f1646dbd27f5e48ffe8dd49406102937109130caab02ca32c083a3d60" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libSM" +PKG_LONGDESC="libXt provides the X Toolkit Intrinsics library, an abstract widget library upon which other toolkits are based." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --with-gnu-ld \ + --enable-malloc0returnsnull" + +pre_make_target() { + make -C util CC=${HOST_CC} \ + CFLAGS="${HOST_CFLAGS} " \ + LDFLAGS="${HOST_LDFLAGS}" \ + makestrs +} diff --git a/packages/x11/lib/libXtst/package.mk b/packages/x11/lib/libXtst/package.mk new file mode 100644 index 000000000..177207d5f --- /dev/null +++ b/packages/x11/lib/libXtst/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXtst" +PKG_VERSION="1.2.3" +PKG_SHA256="4655498a1b8e844e3d6f21f3b2c4e2b571effb5fd83199d428a6ba7ea4bf5204" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libXext libXi libX11" +PKG_LONGDESC="The Xtst Library" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --with-gnu-ld --without-xmlto" diff --git a/packages/x11/lib/libXxf86vm/package.mk b/packages/x11/lib/libXxf86vm/package.mk new file mode 100644 index 000000000..5aacc5622 --- /dev/null +++ b/packages/x11/lib/libXxf86vm/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libXxf86vm" +PKG_VERSION="1.1.4" +PKG_SHA256="afee27f93c5f31c0ad582852c0fb36d50e4de7cd585fcf655e278a633d85cd57" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11 libXext" +PKG_LONGDESC="The libxxf86vm provides an interface to the server extension XFree86-VidModeExtension." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared --enable-malloc0returnsnull" diff --git a/packages/x11/lib/libfontenc/package.mk b/packages/x11/lib/libfontenc/package.mk new file mode 100644 index 000000000..42cc822e9 --- /dev/null +++ b/packages/x11/lib/libfontenc/package.mk @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libfontenc" +PKG_VERSION="1.1.4" +PKG_SHA256="2cfcce810ddd48f2e5dc658d28c1808e86dcf303eaff16728b9aa3dbc0092079" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros zlib font-util xorgproto" +PKG_LONGDESC="Libfontenc is a library which helps font libraries portably determine and deal with different encodings of fonts." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/libpciaccess/package.mk b/packages/x11/lib/libpciaccess/package.mk new file mode 100644 index 000000000..1e4cacf3a --- /dev/null +++ b/packages/x11/lib/libpciaccess/package.mk @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libpciaccess" +PKG_VERSION="0.16" +PKG_SHA256="214c9d0d884fdd7375ec8da8dcb91a8d3169f263294c9a90c575bf1938b9f489" +PKG_LICENSE="OSS" +PKG_SITE="http://freedesktop.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros zlib" +PKG_LONGDESC="X.org libpciaccess library." + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_header_asm_mtrr_h=set \ + --with-pciids-path=/usr/share \ + --with-zlib " + +pre_configure_target() { + CFLAGS+=" -D_LARGEFILE64_SOURCE" +} diff --git a/packages/x11/lib/libxcb/package.mk b/packages/x11/lib/libxcb/package.mk new file mode 100644 index 000000000..a62dbe797 --- /dev/null +++ b/packages/x11/lib/libxcb/package.mk @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxcb" +PKG_VERSION="1.14" +PKG_SHA256="a55ed6db98d43469801262d81dc2572ed124edc3db31059d4e9916eb9f844c34" +PKG_LICENSE="OSS" +PKG_SITE="http://xcb.freedesktop.org" +PKG_URL="http://xcb.freedesktop.org/dist/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain util-macros Python3:host xcb-proto libpthread-stubs libXau" +PKG_LONGDESC="X C-language Bindings library." +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static \ + --disable-shared \ + --disable-screensaver \ + --disable-xprint \ + --disable-selinux \ + --disable-xvmc" + +pre_configure_target() { + PYTHON_LIBDIR=${SYSROOT_PREFIX}/usr/lib/${PKG_PYTHON_VERSION} + PYTHON_TOOLCHAIN_PATH=${PYTHON_LIBDIR}/site-packages + + PKG_CONFIG+=" --define-variable=pythondir=${PYTHON_TOOLCHAIN_PATH}" + PKG_CONFIG+=" --define-variable=xcbincludedir=${SYSROOT_PREFIX}/usr/share/xcb" +} diff --git a/packages/x11/lib/libxcvt/package.mk b/packages/x11/lib/libxcvt/package.mk new file mode 100644 index 000000000..1f2278337 --- /dev/null +++ b/packages/x11/lib/libxcvt/package.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxcvt" +PKG_VERSION="0.1.0" +PKG_SHA256="90a4d4814935109890aa6c8101bf98ffbdc293000772f5db3d206f27d8a61976" +PKG_LICENSE="OSS" +PKG_SITE="https://gitlab.freedesktop.org/xorg/lib/libxcvt" +PKG_URL="https://gitlab.freedesktop.org/xorg/lib/${PKG_NAME}/-/archive/${PKG_NAME}-${PKG_VERSION}/${PKG_NAME}-${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain" +PKG_LONGDESC="libxcvt is a library providing a standalone version of the X server implementation of the VESA CVT standard timing modelines generator." +PKG_BUILD_FLAGS="+pic" diff --git a/packages/x11/lib/libxkbfile/package.mk b/packages/x11/lib/libxkbfile/package.mk new file mode 100644 index 000000000..ced64b060 --- /dev/null +++ b/packages/x11/lib/libxkbfile/package.mk @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxkbfile" +PKG_VERSION="1.1.0" +PKG_SHA256="758dbdaa20add2db4902df0b1b7c936564b7376c02a0acd1f2a331bd334b38c7" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros libX11" +PKG_LONGDESC="Libxkbfile provides an interface to read and manipulate description files for XKB, the X11 keyboard configuration extension." + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/libxshmfence/package.mk b/packages/x11/lib/libxshmfence/package.mk new file mode 100644 index 000000000..aaef33288 --- /dev/null +++ b/packages/x11/lib/libxshmfence/package.mk @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="libxshmfence" +PKG_VERSION="1.3" +PKG_SHA256="b884300d26a14961a076fbebc762a39831cb75f92bed5ccf9836345b459220c7" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros xorgproto" +PKG_LONGDESC="libxshmfence is the Shared memory 'SyncFence' synchronization primitive." +PKG_TOOLCHAIN="autotools" +PKG_BUILD_FLAGS="+pic" + +PKG_CONFIGURE_OPTS_TARGET="--enable-static --disable-shared" diff --git a/packages/x11/lib/pixman/package.mk b/packages/x11/lib/pixman/package.mk new file mode 100644 index 000000000..19ddcbfbe --- /dev/null +++ b/packages/x11/lib/pixman/package.mk @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="pixman" +PKG_VERSION="0.40.0" +PKG_SHA256="da8ed9fe2d1c5ef8ce5d1207992db959226bd4e37e3f88acf908fd9a71e2704e" +PKG_LICENSE="OSS" +PKG_SITE="http://www.x.org/" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_HOST="toolchain:host" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="Pixman is a generic library for manipulating pixel regions, contains low-level pixel manipulation routines." +PKG_TOOLCHAIN="configure" + +if [ "${TARGET_ARCH}" = arm ]; then + if target_has_feature neon; then + PIXMAN_NEON="--enable-arm-neon" + else + PIXMAN_NEON="--disable-arm-neon" + fi + PIXMAN_CONFIG="--disable-mmx --disable-sse2 --disable-vmx --enable-arm-simd ${PIXMAN_NEON} --disable-arm-iwmmxt" +elif [ "${TARGET_ARCH}" = aarch64 ]; then + PIXMAN_CONFIG="--disable-mmx --disable-sse2 --disable-vmx --disable-arm-simd --disable-arm-neon --disable-arm-iwmmxt" +elif [ "${TARGET_ARCH}" = x86_64 ]; then + PIXMAN_CONFIG="--enable-mmx --enable-sse2 --disable-ssse3 --disable-vmx --disable-arm-simd --disable-arm-neon" +fi + +PKG_CONFIGURE_OPTS_TARGET="--disable-openmp \ + --disable-loongson-mmi \ + ${PIXMAN_CONFIG} \ + --disable-mips-dspr2 \ + --enable-gcc-inline-asm \ + --disable-timers \ + --disable-gtk \ + --disable-libpng \ + --with-gnu-ld" + +post_makeinstall_target() { + cp ${SYSROOT_PREFIX}/usr/lib/pkgconfig/pixman-1.pc \ + ${SYSROOT_PREFIX}/usr/lib/pkgconfig/pixman.pc + cp -rf ${SYSROOT_PREFIX}/usr/include/pixman-1 \ + ${SYSROOT_PREFIX}/usr/include/pixman +} diff --git a/packages/x11/lib/xtrans/package.mk b/packages/x11/lib/xtrans/package.mk new file mode 100644 index 000000000..a5c43997b --- /dev/null +++ b/packages/x11/lib/xtrans/package.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xtrans" +PKG_VERSION="1.4.0" +PKG_SHA256="377c4491593c417946efcd2c7600d1e62639f7a8bbca391887e2c4679807d773" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="http://xorg.freedesktop.org/archive/individual/lib/${PKG_NAME}-${PKG_VERSION}.tar.bz2" +PKG_DEPENDS_TARGET="toolchain util-macros" +PKG_LONGDESC="Abstract network code for X." + +PKG_CONFIGURE_OPTS_TARGET="--without-xmlto" + +post_makeinstall_target() { + mkdir -p ${SYSROOT_PREFIX}/usr/lib/pkgconfig + cp xtrans.pc ${SYSROOT_PREFIX}/usr/lib/pkgconfig +} diff --git a/packages/x11/other/fluxbox/config/apps b/packages/x11/other/fluxbox/config/apps new file mode 100644 index 000000000..fac0e6d4b --- /dev/null +++ b/packages/x11/other/fluxbox/config/apps @@ -0,0 +1,3 @@ +[app] (name=.*) + [maximized] {yes} +[end] diff --git a/packages/x11/other/fluxbox/config/init b/packages/x11/other/fluxbox/config/init new file mode 100644 index 000000000..0cb0ef025 --- /dev/null +++ b/packages/x11/other/fluxbox/config/init @@ -0,0 +1,13 @@ +! If you're looking for settings to configure, they won't be saved here until +! you change something in the fluxbox configuration menu. + +session.keyFile: /storage/.fluxbox/keys +session.configVersion: 13 +session.screen0.defaultDeco: NONE +session.screen0.rootCommand: fbsetroot -solid black +session.screen0.autoRaise: True +session.screen0.fullMaximization: True +session.screen0.workspaces: 0 +session.screen0.focusModel: StrictMouseFocus +session.screen0.focusNewWindows: True +session.screen0.focusLastWindow: True diff --git a/packages/x11/other/fluxbox/config/keys b/packages/x11/other/fluxbox/config/keys new file mode 100644 index 000000000..31ed93445 --- /dev/null +++ b/packages/x11/other/fluxbox/config/keys @@ -0,0 +1,19 @@ +# This is all we need +# alt-tab +Mod1 Tab :NextWindow {groups} (workspace=[current]) +Mod1 Shift Tab :PrevWindow {groups} (workspace=[current]) + +# current window commands +Mod1 F10 :Maximize +Mod1 F11 :Fullscreen +Mod1 Escape :Close + +# Normal window movement +OnTitlebar Move1 :StartMoving +OnLeftGrip Move1 :StartResizing bottomleft +OnRightGrip Move1 :StartResizing bottomright +OnWindowBorder Move1 :StartMoving + +# alt + left/right click to move/resize a window +OnWindow Mod1 Mouse1 :MacroCmd {Raise} {Focus} {StartMoving} +OnWindow Mod1 Mouse3 :MacroCmd {Raise} {Focus} {StartResizing NearestCorner} diff --git a/packages/x11/other/fluxbox/package.mk b/packages/x11/other/fluxbox/package.mk new file mode 100644 index 000000000..cfc1381b7 --- /dev/null +++ b/packages/x11/other/fluxbox/package.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) + +PKG_NAME="fluxbox" +# dont bump or go back to ratpoison then f*** all 3rdparty stuff. +PKG_VERSION="1.3.7" +PKG_SHA256="fc8c75fe94c54ed5a5dd3fd4a752109f8949d6df67a48e5b11a261403c382ec0" +PKG_LICENSE="OSS" +PKG_SITE="http://fluxbox.org/" +PKG_URL="http://sourceforge.net/projects/fluxbox/files/fluxbox/${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +PKG_DEPENDS_TARGET="toolchain libX11 libXrandr libXext libXrender" +PKG_LONGDESC="Fluxbox is a windowmanager for X that was based on the Blackbox 0.61.1 code." +PKG_TOOLCHAIN="autotools" + +PKG_CONFIGURE_OPTS_TARGET="ac_cv_func_realloc_0_nonnull=yes \ + ac_cv_func_malloc_0_nonnull=yes \ + --disable-toolbar \ + --disable-slit \ + --disable-systray \ + --enable-ewmh \ + --disable-xpm \ + --disable-xft \ + --disable-fribidi \ + --disable-debug \ + --disable-test \ + --disable-nls \ + --disable-imlib2" + +post_install() { + enable_service windowmanager.service +} + +post_makeinstall_target() { + rm -rf ${INSTALL}/usr/bin/fbrun + rm -rf ${INSTALL}/usr/bin/fbsetbg + rm -rf ${INSTALL}/usr/bin/fluxbox-generate_menu + rm -rf ${INSTALL}/usr/bin/fluxbox-remote + rm -rf ${INSTALL}/usr/bin/startfluxbox + + rm -rf ${INSTALL}/usr/share/fluxbox/styles + + cp ${PKG_DIR}/config/apps ${INSTALL}/usr/share/fluxbox/ + cp ${PKG_DIR}/config/init ${INSTALL}/usr/share/fluxbox/ + cp ${PKG_DIR}/config/keys ${INSTALL}/usr/share/fluxbox/ +} diff --git a/packages/x11/other/fluxbox/patches/fluxbox-01_hack-avoid-potential-SIGFPE-in-Menu-updateMenu.patch b/packages/x11/other/fluxbox/patches/fluxbox-01_hack-avoid-potential-SIGFPE-in-Menu-updateMenu.patch new file mode 100644 index 000000000..36bb56285 --- /dev/null +++ b/packages/x11/other/fluxbox/patches/fluxbox-01_hack-avoid-potential-SIGFPE-in-Menu-updateMenu.patch @@ -0,0 +1,20 @@ +From 540dc69955cddd5db24a8a9e16db8162fc0ddd10 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 25 Apr 2014 13:02:35 +0300 +Subject: [PATCH] hack: avoid potential SIGFPE in Menu::updateMenu() + +--- + src/FbTk/Menu.cc | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff -Naur fluxbox-1.3.7/src/FbTk/Menu.cc fluxbox-1.3.7.patch/src/FbTk/Menu.cc +--- fluxbox-1.3.7/src/FbTk/Menu.cc 2015-02-08 11:44:45.357187009 +0100 ++++ fluxbox-1.3.7.patch/src/FbTk/Menu.cc 2015-02-15 21:37:37.322872231 +0100 +@@ -390,6 +390,7 @@ + } + + void Menu::updateMenu() { ++ return; // because nobody cares + + int bevel = theme()->bevelWidth(); + int bw = theme()->borderWidth(); diff --git a/packages/x11/other/fluxbox/patches/fluxbox-02_hide-useless-errors.patch b/packages/x11/other/fluxbox/patches/fluxbox-02_hide-useless-errors.patch new file mode 100644 index 000000000..170d9fd93 --- /dev/null +++ b/packages/x11/other/fluxbox/patches/fluxbox-02_hide-useless-errors.patch @@ -0,0 +1,39 @@ +From 86981018ce0963d93a45270abe379a705a055edf Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Mon, 16 Jun 2014 19:55:02 +0300 +Subject: [PATCH] hide useless errors + +--- + src/FbTk/Resource.cc | 2 -- + src/FbTk/Resource.hh | 2 -- + 2 files changed, 0 insertions(+), 4 deletions(-) + +diff --git a/src/FbTk/Resource.cc b/src/FbTk/Resource.cc +index 4be85de..f7c7273 100644 +--- a/src/FbTk/Resource.cc ++++ b/src/FbTk/Resource.cc +@@ -91,8 +91,6 @@ bool ResourceManager::load(const char *filename) { + resource->setFromString(value.addr); + else { + _FB_USES_NLS; +- cerr<<_FBTK_CONSOLETEXT(Error, FailedRead, "Failed to read", "Couldn't load a resource (following)")<<": "<name()<setDefaultValue(); + } + } +diff --git a/src/FbTk/Resource.hh b/src/FbTk/Resource.hh +index 8c9d645..348f7e2 100644 +--- a/src/FbTk/Resource.hh ++++ b/src/FbTk/Resource.hh +@@ -216,8 +216,6 @@ void ResourceManager::addResource(Resource &r) { + r.altName().c_str(), &value_type, &value)) { + r.setFromString(value.addr); + } else { +- std::cerr<<"Failed to read: "< +Date: Thu, 20 Feb 2014 16:34:57 +0200 +Subject: [PATCH] dont check for libsystemd-daemon + +--- + configure.ac | 3 --- + 1 files changed, 0 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index ceb8dd8..bc199c5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -20,9 +20,6 @@ AC_CHECK_LIB([rt], [main], , + AC_MSG_ERROR([librt is required but was not found])) + + PKG_CHECK_MODULES([SYSTEMD], [systemd]) +-PKG_CHECK_MODULES([LIBSYSTEMD_DAEMON], [libsystemd-daemon]) +-AC_SUBST(LIBSYSTEMD_DAEMON_CFLAGS) +-AC_SUBST(LIBSYSTEMD_DAEMON_LIBS) + + AC_ARG_WITH([systemduserunitdir], AC_HELP_STRING([--with-systemduserunitdir=DIR], + [path to systemd user service directory]), [path_systemduserunit=${withval}], +-- +1.7.2.5 + diff --git a/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-increase-timeout.patch b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-increase-timeout.patch new file mode 100644 index 000000000..77dbc10a3 --- /dev/null +++ b/packages/x11/util/xorg-launch-helper/patches/xorg-launch-helper-increase-timeout.patch @@ -0,0 +1,33 @@ +From 1e220cb2947f5c9ec5d5e35c7e2eb8b7dd728fca Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 22 Nov 2013 14:18:56 +0200 +Subject: [PATCH] increase timeout + +--- + src/main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/main.c b/src/main.c +index 49e2d43..3c556b5 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -85,14 +85,14 @@ int main(int argc, char **argv) + + /* setup sighandler for main thread */ + clock_gettime(CLOCK_REALTIME, &tv); +- tv.tv_sec += 10; ++ tv.tv_sec += 30; + + pthread_mutex_lock(¬ify_mutex); + err = pthread_cond_timedwait(¬ify_condition, ¬ify_mutex, &tv); + pthread_mutex_unlock(¬ify_mutex); + + if (err == ETIMEDOUT) { +- fprintf(stderr, "X server startup timed out (10secs). This indicates an" ++ fprintf(stderr, "X server startup timed out (30secs). This indicates an" + "an issue in the server configuration or drivers.\n"); + exit(EXIT_FAILURE); + } +-- +1.7.2.5 + diff --git a/packages/x11/util/xorg-launch-helper/scripts/xorg-launch b/packages/x11/util/xorg-launch-helper/scripts/xorg-launch new file mode 100755 index 000000000..9e6c71978 --- /dev/null +++ b/packages/x11/util/xorg-launch-helper/scripts/xorg-launch @@ -0,0 +1,27 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +# wait for xorg-configure@.service +# max 10 seconds +ARGS_FILE="/run/libreelec/xorg-settings.conf" +for i in $(seq 1 40) ; do + if [ -e "$ARGS_FILE" ] ; then + break + fi + usleep 250000 +done + +if [ -e "$ARGS_FILE" ] ; then + . /run/libreelec/xorg-settings.conf + exec xorg-launch-helper $@ $XORG_ARGS +else + echo "" > /dev/tty1 + echo "failed to start xorg." > /dev/tty1 + echo "is your GPU supported?" > /dev/tty1 + echo "" > /dev/tty1 + lspci -nn > /dev/tty1 + echo "" > /dev/tty1 + sleep 30 +fi diff --git a/packages/x11/xserver/xorg-server/debug.d/xorg.conf b/packages/x11/xserver/xorg-server/debug.d/xorg.conf new file mode 100644 index 000000000..43d981329 --- /dev/null +++ b/packages/x11/xserver/xorg-server/debug.d/xorg.conf @@ -0,0 +1 @@ +XORG_DEBUG="-logverbose 6 -verbose 6" diff --git a/packages/x11/xserver/xorg-server/package.mk b/packages/x11/xserver/xorg-server/package.mk new file mode 100644 index 000000000..8c5c07603 --- /dev/null +++ b/packages/x11/xserver/xorg-server/package.mk @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="xorg-server" +PKG_VERSION="21.1.1" +PKG_SHA256="915edd49f394283cc587b88a68b5e13e6e2d7f0276edabc9249afb2e22adf634" +PKG_LICENSE="OSS" +PKG_SITE="http://www.X.org" +PKG_URL="https://github.com/freedesktop/xorg-xserver/archive/refs/tags/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_DEPENDS_TARGET="toolchain util-macros font-util xorgproto libpciaccess libX11 libXfont2 libXinerama libxcvt libxshmfence libxkbfile libdrm openssl freetype pixman systemd xorg-launch-helper" +PKG_NEED_UNPACK="$(get_pkg_directory xf86-video-nvidia) $(get_pkg_directory xf86-video-nvidia-legacy)" +PKG_LONGDESC="X.Org Server is the free and open-source implementation of the X Window System display server." + +get_graphicdrivers + +PKG_MESON_OPTS_TARGET="-Dxorg=true \ + -Dxephyr=false \ + -Dxnest=false \ + -Dxvfb=false \ + -Dxwin=false \ + -Dxquartz=false \ + -Dbuilder_addr=${BUILDER_NAME} \ + -Dlog_dir="/var/log" \ + -Dmodule_dir=${XORG_PATH_MODULES} \ + -Ddefault_font_path="/usr/share/fonts/misc,built-ins" \ + -Dxdmcp=false \ + -Dxdm-auth-1=false \ + -Dsecure-rpc=false \ + -Dipv6=false \ + -Dinput_thread=true \ + -Dxkb_dir=${XORG_PATH_XKB} \ + -Dxkb_output_dir="/var/cache/xkb" \ + -Dvendor_name="LibreELEC" \ + -Dvendor_name_short="LE" \ + -Dvendor_web="https://libreelec.tv/" \ + -Dlisten_tcp=false \ + -Dlisten_unix=true \ + -Dlisten_local=false \ + -Dint10=x86emu \ + -Dpciaccess=true \ + -Dudev=true \ + -Dudev_kms=true \ + -Dhal=false \ + -Dsystemd_logind=false \ + -Dvgahw=true \ + -Ddpms=true \ + -Dxf86bigfont=false \ + -Dscreensaver=false \ + -Dxres=true \ + -Dxace=false \ + -Dxselinux=false \ + -Dxinerama=true \ + -Dxcsecurity=false \ + -Dxv=true \ + -Dxvmc=false \ + -Ddga=true \ + -Dlinux_apm=false \ + -Dlinux_acpi=false \ + -Dmitshm=true \ + -Dsha1="libcrypto" \ + -Ddri2=true \ + -Ddri3=true \ + -Ddrm=true \ + -Dxpbproxy=false \ + -Dlibunwind=false \ + -Ddocs=false \ + -Ddevel-docs=false" + +if [ ! "${OPENGL}" = "no" ]; then + PKG_DEPENDS_TARGET+=" ${OPENGL} libepoxy" + PKG_MESON_OPTS_TARGET+=" -Dglx=true \ + -Ddri1=true \ + -Dglamor=true" +else + PKG_MESON_OPTS_TARGET+=" -Dglx=false \ + -Ddri1=false \ + -Dglamor=false" +fi + +if [ "${COMPOSITE_SUPPORT}" = "yes" ]; then + PKG_DEPENDS_TARGET+=" libXcomposite" +fi + +post_makeinstall_target() { + rm -rf ${INSTALL}/var/cache/xkb + + mkdir -p ${INSTALL}/usr/lib/xorg + cp -P ${PKG_DIR}/scripts/xorg-configure ${INSTALL}/usr/lib/xorg + sed -i -e "s|@NVIDIA_VERSION@|$(get_pkg_version xf86-video-nvidia)|g" ${INSTALL}/usr/lib/xorg/xorg-configure + sed -i -e "s|@NVIDIA_LEGACY_VERSION@|$(get_pkg_version xf86-video-nvidia-legacy)|g" ${INSTALL}/usr/lib/xorg/xorg-configure + + if [ ! "${OPENGL}" = "no" ]; then + if [ -f ${INSTALL}/usr/lib/xorg/modules/extensions/libglx.so ]; then + mv ${INSTALL}/usr/lib/xorg/modules/extensions/libglx.so \ + ${INSTALL}/usr/lib/xorg/modules/extensions/libglx_mesa.so # rename for cooperate with nvidia drivers + ln -sf /var/lib/libglx.so ${INSTALL}/usr/lib/xorg/modules/extensions/libglx.so + fi + fi + + mkdir -p ${INSTALL}/etc/X11 + if find_file_path config/xorg.conf; then + cp ${FOUND_PATH} ${INSTALL}/etc/X11 + fi +} + +post_install() { + enable_service xorg.service +} diff --git a/packages/x11/xserver/xorg-server/patches/xorg-server-100.01-detect-radeon.patch b/packages/x11/xserver/xorg-server/patches/xorg-server-100.01-detect-radeon.patch new file mode 100644 index 000000000..a8bee6c42 --- /dev/null +++ b/packages/x11/xserver/xorg-server/patches/xorg-server-100.01-detect-radeon.patch @@ -0,0 +1,22 @@ +From 7b147dfef7a2ce8247710660d2b95d84100aaad7 Mon Sep 17 00:00:00 2001 +From: SupervisedThinking +Date: Tue, 19 Oct 2021 18:22:38 +0200 +Subject: [PATCH] Detect GPUs as "radeon" instead "ati" + +--- + hw/xfree86/common/xf86pciBus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c +index aeeed8be66..5c22bd4080 100644 +--- a/hw/xfree86/common/xf86pciBus.c ++++ b/hw/xfree86/common/xf86pciBus.c +@@ -1106,7 +1106,7 @@ xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md) + driverList[0] = "ast"; + break; + case 0x1002: +- driverList[0] = "ati"; ++ driverList[0] = "radeon"; + break; + case 0x102c: + driverList[0] = "chips"; diff --git a/packages/x11/xserver/xorg-server/patches/xorg-server-100.02-add-fedora-extra-modes-list.patch b/packages/x11/xserver/xorg-server/patches/xorg-server-100.02-add-fedora-extra-modes-list.patch new file mode 100644 index 000000000..a44f945d2 --- /dev/null +++ b/packages/x11/xserver/xorg-server/patches/xorg-server-100.02-add-fedora-extra-modes-list.patch @@ -0,0 +1,90 @@ +From aff7aded0cc546491b29b37b093846921ab7378a Mon Sep 17 00:00:00 2001 +From: SupervisedThinking +Date: Tue, 19 Oct 2021 18:23:20 +0200 +Subject: [PATCH] Fedora extra modes list added by Adam Jackson + + +--- + hw/xfree86/common/extramodes | 59 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/hw/xfree86/common/extramodes b/hw/xfree86/common/extramodes +index 006b5cba17..3caa3bf015 100644 +--- a/hw/xfree86/common/extramodes ++++ b/hw/xfree86/common/extramodes +@@ -3,16 +3,75 @@ + // + // $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $ + // ++// NOTE: Please keep all video modes sorted in order of X res, then Y res for ++// ease of maintenance and readability. + + # 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz + ModeLine "832x624" 57.284 832 864 928 1152 624 625 628 667 -Hsync -Vsync + ++# 1152x864 @ 60.00 Hz (GTF) hsync: 53.70 kHz; pclk: 81.62 MHz ++Modeline "1152x864" 81.62 1152 1216 1336 1520 864 865 868 895 -HSync +Vsync ++ ++# 1152x864 @ 70.00 Hz (GTF) hsync: 63.00 kHz; pclk: 96.77 MHz ++Modeline "1152x864" 96.77 1152 1224 1344 1536 864 865 868 900 -HSync +Vsync ++ ++# 1152x864 @ 75.00 Hz (GTF) hsync: 67.65 kHz; pclk: 104.99 MHz ++Modeline "1152x864" 104.99 1152 1224 1352 1552 864 865 868 902 -HSync +Vsync ++ ++# 1152x864 @ 85.00 Hz (GTF) hsync: 77.10 kHz; pclk: 119.65 MHz ++Modeline "1152x864" 119.65 1152 1224 1352 1552 864 865 868 907 -HSync +Vsync ++ ++# 1152x864 @ 85Hz (Red Hat custom modeline) ++ModeLine "1152x864" 121.5 1152 1216 1344 1568 864 865 868 911 +hsync -vsync ++ ++# 1152x864 @ 100.00 Hz (GTF) hsync: 91.50 kHz; pclk: 143.47 MHz ++Modeline "1152x864" 143.47 1152 1232 1360 1568 864 865 868 915 -HSync +Vsync ++ ++# 1360x768 59.96 Hz (CVT) hsync: 47.37 kHz; pclk: 72.00 MHz ++Modeline "1360x768" 72.00 1360 1408 1440 1520 768 771 781 790 +hsync -vsync ++ ++# 1360x768 59.80 Hz (CVT) hsync: 47.72 kHz; pclk: 84.75 MHz ++Modeline "1360x768" 84.75 1360 1432 1568 1776 768 771 781 798 -hsync +vsync ++ + # 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz + ModeLine "1400x1050" 122.0 1400 1488 1640 1880 1050 1052 1064 1082 +hsync +vsync + ++# 1400x1050 @ 70.00 Hz (GTF) hsync: 76.51 kHz; pclk: 145.06 MHz ++Modeline "1400x1050" 145.06 1400 1496 1648 1896 1050 1051 1054 1093 -HSync +Vsync ++ + # 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz + ModeLine "1400x1050" 155.8 1400 1464 1784 1912 1050 1052 1064 1090 +hsync +vsync + ++# 1400x1050 @ 85.00 Hz (GTF) hsync: 93.76 kHz; pclk: 179.26 MHz ++Modeline "1400x1050" 179.26 1400 1504 1656 1912 1050 1051 1054 1103 -HSync +Vsync ++ ++# 1440x900 @ 60.00 Hz (CVT) field rate 59.89 Hz; hsync: 55.93 kHz; pclk: 106.50 MHz ++Modeline "1440x900" 106.50 1440 1520 1672 1904 900 903 909 934 -HSync +Vsync ++ ++# 1600x1024 for SGI 1600 SW ++ModeLine "1600x1024" 103.125 1600 1600 1656 1664 1024 1024 1029 1030 +Hsync +Vsync ++ ++# 1680x1050 59.88 Hz (CVT 1.76MA-R) hsync: 64.67 kHz; pclk: 119.00 MHz ++Modeline "1680x1050" 119.00 1680 1728 1760 1840 1050 1053 1059 1080 +hsync -vsync ++ ++# 1680x1050 59.95 Hz (CVT 1.76MA) hsync: 65.29 kHz; pclk: 146.25 MHz ++Modeline "1680x1050" 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync ++ ++# 1680x1050 69.88 Hz (CVT) hsync: 76.58 kHz; pclk: 174.00 MHz ++Modeline "1680x1050" 174.00 1680 1800 1976 2272 1050 1053 1059 1096 -hsync +vsync ++ ++# 1680x1050 74.89 Hz (CVT 1.76MA) hsync: 82.31 kHz; pclk: 187.00 MHz ++Modeline "1680x1050" 187.00 1680 1800 1976 2272 1050 1053 1059 1099 -hsync +vsync ++ ++# 1680x1050 84.94 Hz (CVT 1.76MA) hsync: 93.86 kHz; pclk: 214.75 MHz ++Modeline "1680x1050" 214.75 1680 1808 1984 2288 1050 1053 1059 1105 -hsync +vsync ++ ++# 1920x1080 59.93 Hz (CVT 2.07M9-R) hsync: 66.59 kHz; pclk: 138.50 MHz ++Modeline "1920x1080" 138.50 1920 1968 2000 2080 1080 1083 1088 1111 +hsync -vsync ++ ++# 1920x1200 59.95 Hz (CVT 2.30MA-R) hsync: 74.04 kHz; pclk: 154.00 MHz ++Modeline "1920x1200" 154.00 1920 1968 2000 2080 1200 1203 1209 1235 +hsync -vsync ++ + # 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz + Modeline "1920x1440" 341.35 1920 2072 2288 2656 1440 1441 1444 1512 -hsync +vsync + diff --git a/packages/x11/xserver/xorg-server/profile.d/11-xorg-server.conf b/packages/x11/xserver/xorg-server/profile.d/11-xorg-server.conf new file mode 100644 index 000000000..f206206cb --- /dev/null +++ b/packages/x11/xserver/xorg-server/profile.d/11-xorg-server.conf @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +DISPLAY=":0.0" +export DISPLAY + diff --git a/packages/x11/xserver/xorg-server/scripts/xorg-configure b/packages/x11/xserver/xorg-server/scripts/xorg-configure new file mode 100755 index 000000000..02774711e --- /dev/null +++ b/packages/x11/xserver/xorg-server/scripts/xorg-configure @@ -0,0 +1,98 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +################################################################################ +# creating needed directories and symlinks +################################################################################ + +mkdir -p /var/lib +mkdir -p /var/run + +# HACK. we have xorg-configure@%. so nice race +# can happen on multi-gpu setups +if [ -e /var/run/xorg-configure.done ] ; then + exit 0 +fi + +touch /var/run/xorg-configure.done +logger -t Xorg "creating needed directories and symlinks for driver: "${1}"" + +############################################################################## +# setup xorg.conf paths +############################################################################## + +logger -t Xorg "### setup xorg.conf paths ###" + + XORG_CONF_USER="/storage/.config/xorg.conf" + XORG_CONF_USER_DRV="/storage/.config/xorg-${1}.conf" + XORG_CONF_DEFAULT="/etc/X11/xorg.conf" + XORG_CONF_DEFAULT_DRV="/etc/X11/xorg-${1}.conf" + +############################################################################## +# creating start options +############################################################################## + +logger -t Xorg "### creating start options ###" + + XORG_ARGS="-s 0 -noreset -allowMouseOpenFail" + + # load user defined xorg.conf, if exist + if [ -f "${XORG_CONF_USER}" ]; then + XORG_ARGS="${XORG_ARGS} -config ${XORG_CONF_USER}" + elif [ -f "${XORG_CONF_USER_DRV}" ]; then + XORG_ARGS="${XORG_ARGS} -config ${XORG_CONF_USER_DRV}" + elif [ -f "${XORG_CONF_DEFAULT}" ]; then + XORG_ARGS="${XORG_ARGS} -config ${XORG_CONF_DEFAULT}" + elif [ -f "$XORG_CONF_DEFAULT_DRV" ]; then + XORG_ARGS="${XORG_ARGS} -config ${XORG_CONF_DEFAULT_DRV}" + fi + +############################################################################## +# creating needed directories and symlinks +############################################################################## + +logger -t Xorg "### creating needed directories and symlinks ###" + + # Used to support GeForce 600 Series & newer + if [ "${1}" = "nvidia" ]; then + ln -sf /usr/lib/libGL_glvnd.so.1 /var/lib/libGL.so + ln -sf /usr/lib/xorg/modules/extensions/libglx_nvidia.so /var/lib/libglx.so + ln -sf /usr/lib/libnvidia-ml.so.@NVIDIA_VERSION@ /var/lib/libnvidia-ml.so.1 + ln -sf /usr/lib/xorg/modules/drivers/nvidia-main_drv.so /var/lib/nvidia_drv.so + ln -sf /usr/lib/nvidia/nvidia.ko /var/lib/nvidia.ko + ln -sf /usr/lib/vdpau/libvdpau_nvidia-main.so.1 /var/lib/libvdpau_nvidia.so.1 + ln -sf /usr/lib/vdpau/libvdpau_nvidia-main.so.1 /var/lib/libvdpau_nvidia.so + ln -sf /usr/bin/nvidia-main-smi /var/lib/nvidia-smi + ln -sf /usr/bin/nvidia-main-xconfig /var/lib/nvidia-xconfig + insmod /var/lib/nvidia.ko + XORG_ARGS="${XORG_ARGS} -ignoreABI" + # Used to support GeForce 500 Series & older + elif [ "${1}" = "nvidia-legacy" ]; then + ln -sf /usr/lib/libGL_nvidia-legacy.so.1 /var/lib/libGL.so + ln -sf /usr/lib/xorg/modules/extensions/libglx_nvidia-legacy.so /var/lib/libglx.so + ln -sf /usr/lib/libnvidia-ml.so.@NVIDIA_LEGACY_VERSION@ /var/lib/libnvidia-ml.so.1 + ln -sf /usr/lib/xorg/modules/drivers/nvidia-legacy_drv.so /var/lib/nvidia_drv.so + ln -sf /usr/lib/nvidia-legacy/nvidia.ko /var/lib/nvidia.ko + ln -sf /usr/lib/vdpau/libvdpau_nvidia-legacy.so.1 /var/lib/libvdpau_nvidia.so.1 + ln -sf /usr/lib/vdpau/libvdpau_nvidia-legacy.so.1 /var/lib/libvdpau_nvidia.so + ln -sf /usr/bin/nvidia-legacy-smi /var/lib/nvidia-smi + ln -sf /usr/bin/nvidia-legacy-xconfig /var/lib/nvidia-xconfig + insmod /var/lib/nvidia.ko + XORG_ARGS="${XORG_ARGS} -ignoreABI" + # Used for AMD & Intel GPUs supported by MESA 3D + else + ln -sf /usr/lib/libGL_glvnd.so.1 /var/lib/libGL.so + ln -sf /usr/lib/xorg/modules/extensions/libglx_mesa.so /var/lib/libglx.so + fi + +################################################################################ +# setup xorg-settings.conf +################################################################################ + +logger -t Xorg "### starting Xorg with '${DISPLAY} vt01 ${XORG_ARGS}' ###" + mkdir -p /run/libreelec + echo "XORG_ARGS=\"${XORG_ARGS}\"" > /run/libreelec/xorg-settings.conf + diff --git a/packages/x11/xserver/xorg-server/system.d/xorg-configure@.service b/packages/x11/xserver/xorg-server/system.d/xorg-configure@.service new file mode 100644 index 000000000..25725f647 --- /dev/null +++ b/packages/x11/xserver/xorg-server/system.d/xorg-configure@.service @@ -0,0 +1,9 @@ +[Unit] +Description=configure Xorg Server for %i + +ConditionKernelCommandLine=!installer + +[Service] +Type=oneshot +ExecStart=/usr/lib/xorg/xorg-configure %i +RemainAfterExit=yes diff --git a/packages/x11/xserver/xorg-server/system.d/xorg.service b/packages/x11/xserver/xorg-server/system.d/xorg.service new file mode 100644 index 000000000..a9dbde689 --- /dev/null +++ b/packages/x11/xserver/xorg-server/system.d/xorg.service @@ -0,0 +1,16 @@ +[Unit] +Description=Xorg Server +Before=graphical.target kodi.service +After=multi-user.target +ConditionKernelCommandLine=!installer + +[Service] +Type=notify +EnvironmentFile=-/run/libreelec/debug/xorg.conf +ExecStart=/usr/bin/xorg-launch -nolisten tcp vt01 $XORG_DEBUG +Restart=always +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=graphical.target diff --git a/packages/x11/xserver/xorg-server/tmpfiles.d/z_90_xorg-server.conf b/packages/x11/xserver/xorg-server/tmpfiles.d/z_90_xorg-server.conf new file mode 100644 index 000000000..673e6de5d --- /dev/null +++ b/packages/x11/xserver/xorg-server/tmpfiles.d/z_90_xorg-server.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +d /var/cache/xkb 0755 root root - - diff --git a/packages/x11/xserver/xorg-server/udev.d/97-xorg.rules b/packages/x11/xserver/xorg-server/udev.d/97-xorg.rules new file mode 100644 index 000000000..5a6326023 --- /dev/null +++ b/packages/x11/xserver/xorg-server/udev.d/97-xorg.rules @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end_video" + +# xorg_start only does something for subsystem "pci" and "video" class. +SUBSYSTEM=="pci", ATTR{class}=="0x030000", GOTO="subsystem_pci" +GOTO="end_video" + +# check for drivers using the pci substem +LABEL="subsystem_pci" +DRIVER=="i915", ENV{xorg_driver}="i915", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@i915.service" +DRIVER=="amdgpu", ENV{xorg_driver}="amdgpu", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@amdgpu.service" +DRIVER=="radeon", ENV{xorg_driver}="radeon", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@radeon.service" +DRIVER=="vmwgfx", ENV{xorg_driver}="vmware", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@vmware.service" +DRIVER=="virtio-pci", ENV{xorg_driver}="modesetting", TAG+="systemd", ENV{SYSTEMD_WANTS}+="xorg-configure@modesetting.service" +GOTO="end_video" + +LABEL="end_video" diff --git a/projects/Rockchip/bootloader/canupdate.sh b/projects/Rockchip/bootloader/canupdate.sh new file mode 100644 index 000000000..b9b32ca91 --- /dev/null +++ b/projects/Rockchip/bootloader/canupdate.sh @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# Allow upgrades between arm and aarch64 +if [ "$1" = "@PROJECT@.arm" -o "$1" = "@PROJECT@.aarch64" ]; then + exit 0 +else + exit 1 +fi diff --git a/projects/Rockchip/bootloader/install b/projects/Rockchip/bootloader/install new file mode 100644 index 000000000..34025de53 --- /dev/null +++ b/projects/Rockchip/bootloader/install @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2021 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2021-present Fewtarius + +PKG_RKBIN="$(get_build_dir rkbin)" +source ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/options + +if [ -n "$PKG_DATAFILE" -a -n "$PKG_LOADER" ]; then + tools/mkimage -n ${PKG_SOC} -T rksd -d "${PKG_DATAFILE}" idbloader.img + cat "$PKG_LOADER" >> idbloader.img + cp -av idbloader.img $INSTALL/usr/share/bootloader +fi + +if [ ! -n "${PKG_LOAD_ADDR}" ]; then + PKG_LOAD_ADDR="0x00200000" +fi + +$PKG_RKBIN/tools/loaderimage --pack --uboot u-boot-dtb.bin uboot.img ${PKG_LOAD_ADDR} +cp -av uboot.img $INSTALL/usr/share/bootloader + +if [ -n "$PKG_BL31" ]; then + cat >trust.ini <$INSTALL/usr/share/bootloader/boot.ini <"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/uboot.img" ]; then + echo "image: burn uboot.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/uboot.img" of="$DISK" bs=64k seek=128 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/trust.img" ]; then + echo "image: burn trust.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/trust.img" of="$DISK" bs=64k seek=192 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/boot.ini" ]; then + cp "$RELEASE_DIR/3rdparty/bootloader/boot.ini" "${LE_TMP}/boot.ini" + mcopy -so "${LE_TMP}/boot.ini" :: +fi + +#if [ -f "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" ]; then +# cp "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" "${LE_TMP}/logo.bmp" +# mcopy -so "${LE_TMP}/logo.bmp" :: +#fi + +mkdir -p "${LE_TMP}/extlinux" + +# copy device trees to part1 +#for dtb in $RELEASE_DIR/3rdparty/bootloader/*.dtb; do +# [ -e "$dtb" ] && mcopy -o "$dtb" :: +#done +if [ -e "${DEVICE_DTB}.dtb" ] +then + mcopy -o "${DEVICE_DTB}.dtb" :: +fi + +mkdir -p "${LE_TMP}/extlinux" + +cat << EOF > "${LE_TMP}/extlinux/extlinux.conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /${DEVICE_DTB}.dtb + APPEND boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} ${EXTRA_CMDLINE} +EOF + +mcopy -so "${LE_TMP}/extlinux" :: diff --git a/projects/Rockchip/bootloader/release b/projects/Rockchip/bootloader/release new file mode 100644 index 000000000..b64af762c --- /dev/null +++ b/projects/Rockchip/bootloader/release @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2021 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2021-present Fewtarius + +mkdir -p $RELEASE_DIR/3rdparty/bootloader +if [ -n "$UBOOT_SYSTEM" ]; then + BOOTLOADER_DIR=$(get_build_dir $BOOTLOADER) + if [ -f $BOOTLOADER_DIR/idbloader.img ]; then + cp -a $BOOTLOADER_DIR/idbloader.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/uboot.img ]; then + cp -a $BOOTLOADER_DIR/uboot.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/trust.img ]; then + cp -a $BOOTLOADER_DIR/trust.img $RELEASE_DIR/3rdparty/bootloader + fi +fi + +if [ -f $INSTALL/usr/share/bootloader/logo.bmp ]; then + cp -a $INSTALL/usr/share/bootloader/logo.bmp $RELEASE_DIR/3rdparty/bootloader +fi + +if [ -f $INSTALL/usr/share/bootloader/boot.ini ]; then + cp -a $INSTALL/usr/share/bootloader/boot.ini $RELEASE_DIR/3rdparty/bootloader +fi + +LINUX_DTS_DIR=$(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/ +for dtb in $(find $LINUX_DTS_DIR -name "*.dtb") ; do + if [ -f $dtb ]; then + cp -a $dtb $RELEASE_DIR/3rdparty/bootloader + fi +done diff --git a/projects/Rockchip/bootloader/update.sh b/projects/Rockchip/bootloader/update.sh new file mode 100644 index 000000000..3da5281bf --- /dev/null +++ b/projects/Rockchip/bootloader/update.sh @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2021 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2021-present Fewtarius + +[ -z "$SYSTEM_ROOT" ] && SYSTEM_ROOT="" +[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/flash" +[ -z "$BOOT_PART" ] && BOOT_PART=$(df "$BOOT_ROOT" | tail -1 | awk {' print $1 '}) +if [ -z "$BOOT_DISK" ]; then + case $BOOT_PART in + /dev/sd[a-z][0-9]*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,[0-9]*,,g") + ;; + /dev/mmcblk*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,p[0-9]*,,g") + ;; + esac +fi + +# mount $BOOT_ROOT r/w + mount -o remount,rw $BOOT_ROOT + + +for arg in $(cat /proc/cmdline); do + case $arg in + boot=*) + boot="${arg#*=}" + case $boot in + /dev/mmc*) + BOOT_UUID="$(blkid $boot | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + BOOT_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $boot " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + BOOT_UUID="$(blkid ${boot#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + disk=*) + disk="${arg#*=}" + case $disk in + /dev/mmc*) + DISK_UUID="$(blkid $disk | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + DISK_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $disk " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + DISK_UUID="$(blkid ${disk#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + esac +done + +CONFS=$SYSTEM_ROOT/usr/share/bootloader/extlinux/*.conf + +for all_conf in $CONFS; do + conf="$(basename ${all_conf})" + echo "Updating ${conf}..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/extlinux/${conf} $BOOT_ROOT/extlinux/${conf} &>/dev/null + sed -e "s/@BOOT_UUID@/$BOOT_UUID/" \ + -e "s/@DISK_UUID@/$DISK_UUID/" \ + -i $BOOT_ROOT/extlinux/${conf} +done + +if [ -f $SYSTEM_ROOT/usr/share/bootloader/boot.ini ]; then + echo "Updating boot.ini..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/boot.ini $BOOT_ROOT/boot.ini &>/dev/null +fi + +# update device tree + for all_dtb in $SYSTEM_ROOT/usr/share/bootloader/*.dtb; do + dtb=$(basename $all_dtb) + echo -n "Updating $dtb... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/$dtb $BOOT_ROOT &>/dev/null + echo "done" + done + +# update bootloader + if [ -f $SYSTEM_ROOT/usr/share/bootloader/idbloader.img ]; then + echo -n "Updating idbloader.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/idbloader.img of=$BOOT_DISK bs=32k seek=1 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/uboot.img ]; then + echo -n "Updating uboot.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/uboot.img of=$BOOT_DISK bs=64k seek=128 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/trust.img ]; then + echo -n "Updating trust.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/trust.img of=$BOOT_DISK bs=64k seek=192 conv=fsync &>/dev/null + echo "done" + fi + + if [ -f $SYSTEM_ROOT/usr/share/bootloader/logo.bmp ]; then + echo -n "Updating uboot logo... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/logo.bmp $BOOT_ROOT &>/dev/null + echo "done" + fi + +# mount $BOOT_ROOT r/o + sync + mount -o remount,ro $BOOT_ROOT &>/dev/null + +# Leave a hint that we just did an update +echo "UPDATE" > /storage/.config/boot.hint + +sync diff --git a/projects/Rockchip/devices/RG351MP/device.config b/projects/Rockchip/devices/RG351MP/device.config new file mode 100644 index 000000000..abcaf8a9d --- /dev/null +++ b/projects/Rockchip/devices/RG351MP/device.config @@ -0,0 +1,51 @@ +# Device definition file for the Anbernic RG351MP + +# Device Features +DEVICE_HAS_FAN=false +DEVICE_FAKE_JACKSENSE=true +DEVICE_VOLUMECTL=true +DEVICE_POWER_LED=true +DEVICE_AUDIO_MIXER="Playback" +DEVICE_VOLUME_DEV="/dev/input/by-path/platform-rg351-keys-event" +DEVICE_CONTROLLER_DEV="/dev/input/event2" +DEVICE_BRIGHTNESS="70" +DISPLAY_ROTATED=false + +# GPIOS +DEVICE_WIFI="5" +DEVICE_LED="77" +DEVICE_PWM_MOTOR="pwmchip0" +#DEVICE_PWM_FAN="" +DEVICE_JACK="/sys/class/gpio/gpio86/value" + +# FREQ governors +CPU_FREQ="/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" +GPU_FREQ="/sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu.gpu/governor" +DMC_FREQ="/sys/devices/platform/dmc/devfreq/dmc/governor" + +# Affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="${SLOW_CORES}" + +# Volume Keys +#DEVICE_KEY_VOLUMEDOWN= +#DEVICE_KEY_VOLUMEUP= + +# Controller +DEVICE_BTN_SOUTH="0" # B +DEVICE_BTN_EAST="1" # A +DEVICE_BTN_NORTH="2" # X +DEVICE_BTN_WEST="3" # Y +DEVICE_BTN_TL="4" +DEVICE_BTN_TR="5" +DEVICE_BTN_TL2="6" +DEVICE_BTN_TR2="7" +DEVICE_BTN_SELECT="8" +DEVICE_BTN_START="9" +DEVICE_BTN_MODE="10" +DEVICE_BTN_THUMBL="11" +DEVICE_BTN_THUMBR="12" +DEVICE_BTN_DPAD_UP="13" +DEVICE_BTN_DPAD_DOWN="14" +DEVICE_BTN_DPAD_LEFT="15" +DEVICE_BTN_DPAD_RIGHT="16" diff --git a/projects/Rockchip/devices/RG351MP/device.init b/projects/Rockchip/devices/RG351MP/device.init new file mode 100644 index 000000000..b8ba1d284 --- /dev/null +++ b/projects/Rockchip/devices/RG351MP/device.init @@ -0,0 +1,15 @@ +# Enable GPIO 77 for power LED manipulation +echo ${DEVICE_LED} > /sys/class/gpio/export 2>/dev/null + +# Enable WIFI GPIO for WIFI manipulation +echo ${DEVICE_WIFI} > /sys/class/gpio/export 2>/dev/null + +# Power up the WIFI device +echo out > /sys/class/gpio/gpio${DEVICE_WIFI}/direction 2>/dev/null +echo 1 > /sys/class/gpio/gpio${DEVICE_WIFI}/value 2>/dev/null + +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period 2>/dev/null +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle 2>/dev/null diff --git a/projects/Rockchip/devices/RG351MP/linux/linux.aarch64.conf b/projects/Rockchip/devices/RG351MP/linux/linux.aarch64.conf new file mode 100644 index 000000000..bdf94f86d --- /dev/null +++ b/projects/Rockchip/devices/RG351MP/linux/linux.aarch64.conf @@ -0,0 +1,4647 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.4.189 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_SHIFT=4 +CONFIG_NO_IOPORT_MAP=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="@DISTRONAME@" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_PIDS is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_MEMCG is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_INITRD_ASYNC is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_MEMBARRIER=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +CONFIG_PROFILING=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_RK_PARTITION=y +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_EXYNOS7 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_ROCKCHIP_ODROIDGOA=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_DOMAINS_GENERIC is not set +# CONFIG_PCI_SYSCALL is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_MMU_NOTIFIER=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_SECCOMP=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_UAO=y +CONFIG_ARM64_MODULE_CMODEL_LARGE=y +# CONFIG_RANDOMIZE_BASE is not set + +# +# Boot options +# +CONFIG_CMDLINE="" +# CONFIG_EFI is not set +# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_KEYS_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_ROCKCHIP_CPUFREQ=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=y +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_TCP_CONG="reno" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +# CONFIG_NF_TABLES_BRIDGE is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_MRP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_HWMON=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_SOCKET=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_HSR is not set +CONFIG_NET_SWITCHDEV=y +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_6LOWPAN is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_RTKBTUSB=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_QCA is not set +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_MINSTREL_VHT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_LWTUNNEL=y +CONFIG_DST_CACHE=y +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_DEVRES=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set + +# +# Bus devices +# +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND_IDS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_ROCKCHIP_SCR is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_USB_CAM_GPIO is not set +# CONFIG_GPIO_DET is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_EEH is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_TUN_VNET_CROSS_LE=y +CONFIG_VETH=m +CONFIG_NLMON=m + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_ETHERNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_TERANETICS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=m +CONFIG_PPPOPNS=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +# CONFIG_USB_LAN78XX is not set +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +CONFIG_USB_NET_CDC_MBIM=m +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USB_NET_CH9200 is not set +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +# CONFIG_ATH6KL_USB is not set +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_WCN36XX is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +CONFIG_HOSTAP=m +# CONFIG_HOSTAP_FIRMWARE is not set +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_P54_SPI is not set +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8XXXU=m +# CONFIG_RTL8XXXU_UNTESTED is not set +CONFIG_WL_ROCKCHIP=y +CONFIG_WIFI_BUILD_MODULE=y +CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +# CONFIG_AP6XXX is not set +# CONFIG_CYW_BCMDHD is not set +CONFIG_RTL_WIRELESS_SOLUTION=y +CONFIG_RTL8188EU=m +CONFIG_RTL8188FU=m +# CONFIG_RTL8189ES is not set +# CONFIG_RTL8189FS is not set +# CONFIG_RTL8723BS is not set +CONFIG_RTL8723BU=m +# CONFIG_RTL8723CS is not set +# CONFIG_RTL8723DS is not set +# CONFIG_MVL88W8977 is not set + +# +# SouthSV 6XXX WLAN support +# +# CONFIG_SSV6051 is not set +CONFIG_WL_TI=y +CONFIG_WL1251=m +# CONFIG_WL1251_SPI is not set +# CONFIG_WL1251_SDIO is not set +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +# CONFIG_WLCORE_SPI is not set +# CONFIG_WLCORE_SDIO is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_USB=m +CONFIG_CW1200=m +# CONFIG_CW1200_WLAN_SDIO is not set +# CONFIG_CW1200_WLAN_SPI is not set +CONFIG_RSI_91X=m +CONFIG_RSI_DEBUGFS=y +CONFIG_RSI_SDIO=m +CONFIG_RSI_USB=m +CONFIG_RTL8812AU=m +CONFIG_RTL8822BU=m +CONFIG_RTL8821CU=m +CONFIG_ESP8089=m +CONFIG_ESP8089_DEBUG_FS=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_IEEE802154_DRIVERS=m +# CONFIG_IEEE802154_FAKELB is not set +# CONFIG_IEEE802154_AT86RF230 is not set +# CONFIG_IEEE802154_MRF24J40 is not set +# CONFIG_IEEE802154_CC2520 is not set +# CONFIG_IEEE802154_ATUSB is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=m +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_ROCKCHIP=y +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +# CONFIG_JOYSTICK_IFORCE_232 is not set +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_AS5011=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ADC=y +CONFIG_JOYSTICK_ODROIDGO2=y +CONFIG_JOYSTICK_ODROIDGO3=y +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set + +# +# handle all sensors +# +# CONFIG_SENSOR_DEVICE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYCHORD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_RK8XX_PWRKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=m +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_INGENIC is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_ROCKCHIP is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +CONFIG_TCG_TPM=y +# CONFIG_TCG_TIS_I2C_ATMEL is not set +CONFIG_TCG_TIS_I2C_INFINEON=y +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_TIS_ST33ZP24 is not set +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +CONFIG_I2C_RK3X=y +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=m +# CONFIG_SPI_CADENCE is not set +CONFIG_SPI_GPIO=m +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_ROCKCHIP=m +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_RK805=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +CONFIG_GPIO_RK8XX=y + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# SPI or I2C GPIO expanders +# +# CONFIG_GPIO_MCP23S08 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=y +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25700 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_SY6982C is not set +# CONFIG_CHARGER_UNIVERSAL is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_EC is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_RK816 is not set +CONFIG_BATTERY_RK817=y +CONFIG_CHARGER_RK817=y +# CONFIG_BATTERY_RK818 is not set +# CONFIG_CHARGER_RK818 is not set +# CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_POWER_AVS=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_IMX_THERMAL is not set +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_RK_VIRTUAL_THERMAL is not set +# CONFIG_RK3368_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set +CONFIG_MFD_RK808=y +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_RK1000 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_FUSB_30X is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8752 is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8865 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +CONFIG_REGULATOR_RK818=y +# CONFIG_REGULATOR_SYR82X is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS549B22 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_XZ3216 is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_IGNORE_IOTCL_PERMIT=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +# CONFIG_DRM_DP_CEC is not set +# CONFIG_DRM_SCDC_HELPER is not set +CONFIG_DRM_DMA_SYNC=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_VGEM is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_ROCKCHIP_DRM_DEBUG is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_MIPI_CSI_TX is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_LVDS is not set +# CONFIG_ROCKCHIP_DRM_TVE is not set +# CONFIG_ROCKCHIP_RGB is not set +# CONFIG_ROCKCHIP_DRM_BACKLIGHT is not set +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +# CONFIG_DRM_UDL is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_ODROID_ST7701S is not set +CONFIG_DRM_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LONTIUM_LT8912 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_POWERVR_ROGUE_M is not set +# CONFIG_MALI400 is not set +CONFIG_MALI_MIDGARD_FOR_ANDROID=y +# CONFIG_MALI_MIDGARD_FOR_LINUX is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MALI_CORESTACK is not set +CONFIG_MALI_PWRSOFT_765=y +# CONFIG_MALI_KUTF is not set +# CONFIG_MALI_BIFROST_FOR_ANDROID is not set +CONFIG_MALI_BIFROST_FOR_LINUX=y +CONFIG_MALI_BIFROST=y +# CONFIG_MALI_BIFROST_GATOR_SUPPORT is not set +# CONFIG_MALI_BIFROST_ENABLE_TRACE is not set +CONFIG_MALI_BIFROST_DEVFREQ=y +# CONFIG_MALI_BIFROST_DMA_FENCE is not set +CONFIG_MALI_PLATFORM_NAME="rk" +CONFIG_MALI_BIFROST_EXPERT=y +# CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY is not set +# CONFIG_MALI_BIFROST_DEBUG is not set +# CONFIG_MALI_BIFROST_NO_MALI is not set +# CONFIG_MALI_BIFROST_TRACE_TIMELINE is not set +# CONFIG_MALI_BIFROST_SYSTEM_TRACE is not set +# CONFIG_MALI_JOB_DUMP is not set +# CONFIG_MALI_2MB_ALLOC is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set + +# +# Rockchip Misc Video driver +# +# CONFIG_FB_ROCKCHIP is not set +# CONFIG_LCDC_RK3368 is not set +CONFIG_LCD_GENERAL=y +# CONFIG_LCD_MIPI is not set +# CONFIG_RK_TRSM is not set +# CONFIG_RK_HDMI is not set + +# +# RGA +# +# CONFIG_ROCKCHIP_RGA is not set + +# +# RGA2 +# +CONFIG_ROCKCHIP_RGA2=y + +# +# VCODEC +# +CONFIG_RK_VCODEC=y + +# +# IEP +# +# CONFIG_IEP is not set +# CONFIG_IEP_MMU is not set + +# +# DP +# + +# +# ROCKCHIP_MPP +# +CONFIG_ROCKCHIP_MPP_SERVICE=y +CONFIG_ROCKCHIP_MPP_DEVICE=y +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=y +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +CONFIG_SND_SOC_ROCKCHIP=y +# CONFIG_SND_SOC_ROCKCHIP_FORCE_SRAM is not set +CONFIG_SND_SOC_ROCKCHIP_I2S=y +# CONFIG_SND_SOC_ROCKCHIP_I2S_TDM is not set +CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS=y +CONFIG_SND_SOC_ROCKCHIP_PDM=y +# CONFIG_SND_SOC_ROCKCHIP_SPDIF is not set +# CONFIG_SND_SOC_ROCKCHIP_SPDIFRX is not set +# CONFIG_SND_SOC_ROCKCHIP_VAD is not set +# CONFIG_SND_SOC_ROCKCHIP_DA7219 is not set +# CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5651_TC358749 is not set +# CONFIG_SND_SOC_ROCKCHIP_CDNDP is not set + +# +# Allwinner SoC Audio support +# +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set +# CONFIG_SND_SOC_DUMMY_CODEC is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8323 is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_GVA_CODEC is not set +# CONFIG_SND_SOC_FM1288 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK312X is not set +# CONFIG_SND_SOC_RK3228 is not set +# CONFIG_SND_SOC_RK3308 is not set +# CONFIG_SND_SOC_RK3328 is not set +CONFIG_SND_SOC_RK817=y +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5651 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TC358749X is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=y +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_RKVR is not set +# CONFIG_HID_ALPS is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEFAULT_PERSIST is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_DWC2=m +CONFIG_USB_DWC2_HOST=y + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP210X=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +# CONFIG_USB_SERIAL_QCAUX is not set +CONFIG_USB_SERIAL_QUALCOMM=m +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=y +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +# CONFIG_USB_CONFIGFS_SERIAL is not set +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +# CONFIG_USB_CONFIGFS_EEM is not set +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_MTP is not set +# CONFIG_USB_CONFIGFS_F_ACC is not set +# CONFIG_USB_CONFIGFS_UEVENT is not set +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set + +# +# ROCKCHIP USB Support +# +# CONFIG_USB20_HOST is not set +# CONFIG_USB20_OTG is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=y +# CONFIG_MMC_SIMULATE_MAX_SPEED is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_FAKE is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RK808=y +# CONFIG_RTC_DRV_RK_TIMER is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +CONFIG_PL330_DMA=y +# CONFIG_DW_DMAC is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTLLIB is not set +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +CONFIG_R8723AU=m +CONFIG_8723AU_AP_MODE=y +CONFIG_8723AU_BT_COEXIST=y +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7606 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# CONFIG_INV_MPU_IIO is not set + +# +# Light sensors +# +CONFIG_SENSORS_ISL29018=y +# CONFIG_SENSORS_ISL29028 is not set +CONFIG_TSL2583=y +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ASHMEM is not set +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_SYNC is not set +# CONFIG_ION is not set +CONFIG_FIQ_DEBUGGER=y +CONFIG_FIQ_DEBUGGER_NO_SLEEP=y +# CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON is not set +CONFIG_FIQ_DEBUGGER_CONSOLE=y +CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y +# CONFIG_FIQ_DEBUGGER_TRUST_ZONE is not set +# CONFIG_FIQ_DEBUGGER_UART_OVERLAY is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_RK_CONSOLE_THREAD is not set +# CONFIG_STAGING_BOARD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_WILC1000_DRIVER is not set +# CONFIG_MOST is not set +# CONFIG_POWERVR_ROGUE_N is not set + +# +# Qualcomm Atheros CLD WLAN module +# +# CONFIG_QCA_CLD_WLAN is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_VERSATILE is not set +CONFIG_COMMON_CLK_RK808=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# +# CONFIG_HWSPINLOCK_ROCKCHIP is not set + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_IOVA=y +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_ROCKCHIP_IOMMU=y +# CONFIG_RK_IOMMU is not set +# CONFIG_ARM_SMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# + +# +# Rockchip CPU selection +# +CONFIG_CPU_PX30=y +# CONFIG_CPU_RK1808 is not set +# CONFIG_CPU_RK3308 is not set +CONFIG_CPU_RK3328=y +# CONFIG_CPU_RK3366 is not set +CONFIG_CPU_RK3368=y +CONFIG_CPU_RK3399=y +CONFIG_ANDROID_VERSION=0x07010000 +CONFIG_ROCKCHIP_CPUINFO=y +# CONFIG_ROCKCHIP_DEVICEINFO is not set +CONFIG_ROCKCHIP_IPA=y +CONFIG_ROCKCHIP_OPP=y +# CONFIG_ROCKCHIP_PM_TEST is not set +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +CONFIG_ROCKCHIP_PVTM=y +CONFIG_ROCKCHIP_SUSPEND_MODE=y +CONFIG_ROCKCHIP_SYSTEM_MONITOR=y +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y + +# +# DEVFREQ Drivers +# +# CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_BUFFER_CB is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MXC4005 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD799X is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_GPIO_MUXADC is not set +# CONFIG_HI8435 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +CONFIG_ROCKCHIP_SARADC=y +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_VF610_ADC is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Chemical Sensors +# +# CONFIG_VZ89X is not set + +# +# Hid Sensor IIO Common +# + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set +# CONFIG_HDC100X is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9960 is not set +# CONFIG_BH1750 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_ISL29125 is not set +# CONFIG_JSA1212 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR501 is not set +# CONFIG_OPT3001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_STK3310 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +CONFIG_SENSORS_TSL2563=y +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VL6180 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_MAG3110 is not set +# CONFIG_MMC35240 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +CONFIG_IIO_SYSFS_TRIGGER=y + +# +# Digital potentiometers +# +# CONFIG_MCP4531 is not set + +# +# Pressure sensors +# +# CONFIG_BMP280 is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set + +# +# Proximity sensors +# +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set + +# +# Temperature sensors +# +# CONFIG_MLX90614 is not set +# CONFIG_TMP006 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_ROCKCHIP=y +# CONFIG_PWM_ROCKCHIP_I2S is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V3=y +CONFIG_PARTITION_PERCPU=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_XGENE is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PHY_ROCKCHIP_INNO_COMBPHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_INNO_USB3 is not set +# CONFIG_PHY_ROCKCHIP_EMMC is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_INNO_MIPI_DPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI_PHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_VIDEO_PHY is not set +CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y +# CONFIG_PHY_ROCKCHIP_TYPEC is not set +# CONFIG_PHY_ROCKCHIP_PCIE is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_RAS=y + +# +# Android +# +CONFIG_ANDROID=y +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_LIBNVDIMM is not set +CONFIG_NVMEM=y +# CONFIG_ROCKCHIP_EFUSE is not set +CONFIG_ROCKCHIP_OTP=y +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set + +# +# FPGA Configuration Support +# +# CONFIG_FPGA is not set +# CONFIG_TEE is not set +CONFIG_RK_FLASH=y + +# +# Rockchip Flash Devices +# +# CONFIG_RK_NANDC_NAND is not set +CONFIG_RK_SFC_NAND=y +CONFIG_RK_SFC_NOR=y +CONFIG_RK_SFC_NOR_MTD=y +# CONFIG_RK_NAND is not set + +# +# Headset device support +# +# CONFIG_RK_HEADSET is not set + +# +# Gator module for ARM streamline +# + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_ROCKCHIP_SIP=y + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_FS_DAX is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +CONFIG_OVERLAY_FS=y + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +# CONFIG_CACHEFILES is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_VIRTUAL_XATTR=y +CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:exfat:s0" +# CONFIG_EXFAT_DEBUG is not set +# CONFIG_EXFAT_UEVENT is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_UID=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_SDCARD_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +CONFIG_SQUASHFS_LZO=y +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +# CONFIG_PSTORE_PMSG is not set +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +CONFIG_HAVE_KVM_IRQFD=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_ARM_VGIC_V3=y +CONFIG_KVM=y +CONFIG_KVM_ARM_HOST=y +CONFIG_VHOST_NET=m +CONFIG_VHOST=m +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_PROCESS is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_KASAN is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y +CONFIG_HARDLOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_CREDENTIALS=y + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_GPU_TRACEPOINTS=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_TEE_SUPPORT is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_HEH is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V2 is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +# CONFIG_CRYPTO_POLY_HASH_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_CRC32_ARM64 is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_CLZ_TAB=y +CONFIG_CORDIC=m +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_SG_SPLIT is not set +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/projects/Rockchip/devices/RG351MP/options b/projects/Rockchip/devices/RG351MP/options new file mode 100644 index 000000000..e44cb04cc --- /dev/null +++ b/projects/Rockchip/devices/RG351MP/options @@ -0,0 +1,234 @@ +################################################################################ +# setup device defaults +################################################################################ + + # The TARGET_CPU variable controls which processor should be targeted for + # generated code. + case $TARGET_ARCH in + aarch64) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc+fp+simd" + TARGET_FPU="fp-armv8" + TARGET_FEATURES="64bit" + ;; + arm) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc" + TARGET_FPU="crypto-neon-fp-armv8" + TARGET_FEATURES="32bit" + ;; + esac + + # Kernel target + KERNEL_TARGET="Image" + LINUX="RG351MP" + BOOTLOADER="u-boot" + DEVICE_DTB="rk3326-rg351mp-linux" + UBOOT_SYSTEM="rg351mp" + PKG_SOC="px30" + PKG_DATAFILE="$PKG_RKBIN/bin/rk33/rk3326_ddr_333MHz_v1.15.bin" + PKG_LOADER="$PKG_RKBIN/bin/rk33/rk3326_miniloader_v1.20.bin" + PKG_BL31="$PKG_RKBIN/bin/rk33/rk3326_bl31_v1.21.elf" + PKG_LOAD_ADDR="0x00200000" + BOOT_INI=true + + # Additional kernel make parameters (for example to specify the u-boot loadaddress) + KERNEL_MAKE_EXTRACMD="" + KERNEL_MAKE_EXTRACMD+=" rockchip/${DEVICE_DTB}.dtb" + + # Mali GPU family + MALI_FAMILY="g31" + OPENGLES="libmali" + MALIDRIVER="libmali-bifrost-g31-rxp0-gbm" + + # Define the CPU + HW_CPU="Rockchip RK3326" + + # kernel serial console + EXTRA_CMDLINE="quiet console=ttyFIQ0 console=tty0 net.iframes=0 fbcon=rotate:0 ssh consoleblank=0 systemd.show_status=0 loglevel=0 panic=20" + + # additional packages to install + # ADDITIONAL_PACKAGES="" + + # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware) + # Space separated list is supported, + # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware" + FIRMWARE="misc-firmware wlan-firmware" #rockchip-firmware + + # additional drivers to install: + # for a list of additional drivers see packages/linux-drivers + # Space separated list is supported, + # e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2" + ADDITIONAL_DRIVERS="RTL8812AU" #RTL8188EU RTL8814AU RTL8192DU RTL8812AU RTL8821CU RTL8192CU RTL8192EU + + # build and install driver addons (yes / no) + DRIVER_ADDONS_SUPPORT="no" + + # driver addons to install: + # for a list of additinoal drivers see packages/linux-driver-addons + # Space separated list is supported, + DRIVER_ADDONS="" #dvb-latest + + # debug tty path + DEBUG_TTY="/dev/ttyFIQ0" + + + # Skins to install (Estuary) + # Space separated list is supported, + # e.g. SKINS="Estuary" + SKINS="Estuary" + + # Default Skin (Estuary) + SKIN_DEFAULT="Estuary" + + # Select whether to use default (upstream xbmc/xbmc) repo, or specific vendor repo + KODI_VENDOR="default" + + # install extra subtitle Fonts for KODI (yes / no) + KODI_EXTRA_FONTS="yes" + + # build and install PulseAudio support (yes / no) + PULSEAUDIO_SUPPORT="yes" + + # build and install espeak support (yes / no) + ESPEAK_SUPPORT="no" + + # build and install with BluRay support (yes / no) + KODI_BLURAY_SUPPORT="no" + + # build and install with BD+ support + # (BD+ decryption support in KODI) (yes / no) + BLURAY_BDPLUS_SUPPORT="no" + + # build and install with AACS support + # (BD decryption support in KODI) (yes / no) + BLURAY_AACS_SUPPORT="no" + + # build and install with DVDCSS support + # (DVD decryption support in KODI) (yes / no) + KODI_DVDCSS_SUPPORT="no" + + # build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="no" + + # build and install with KODI webfrontend (yes / no) + KODI_WEBSERVER_SUPPORT="no" + + # build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="no" + + # build with UPnP support (yes / no) + KODI_UPNP_SUPPORT="no" + + # build with MySQL support (mysql / mariadb / none) + KODI_MYSQL_SUPPORT="none" + + # build xbmc with optical drive support (yes / no) + KODI_OPTICAL_SUPPORT="no" + + # build with AirPlay support (stream videos from iDevices to KODI) (yes / no) + KODI_AIRPLAY_SUPPORT="no" + + # build with AirTunes support (stream music from iDevices to KODI) (yes / no) + KODI_AIRTUNES_SUPPORT="no" + + # build with libnfs support (mounting nfs shares with KODI) (yes / no) + KODI_NFS_SUPPORT="no" + + # build with Samba Client support (mounting SAMBA shares with KODI) (yes / no) + KODI_SAMBA_SUPPORT="no" + + # build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="no" + + # build with Samba Client support (mounting samba shares via the OS) (yes / no) + SAMBA_SUPPORT="no" + + # build and install Samba Server (yes / no) + SAMBA_SERVER="yes" + + # build and install SFTP Server (yes / no) + SFTP_SERVER="yes" + + # build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + + # build and install diskmounter support (udevil) + # this service provide auto mounting support for external drives in the + # mediacenter also automount internally drives at boottime via udev (yes / no) + UDEVIL="yes" + + # build and install exFAT fuse support (yes / no) + EXFAT="yes" + + # build and install NTFS-3G fuse support (yes / no) + NTFS3G="no" + + # build and install hfs filesystem utilities (yes / no) + HFSTOOLS="no" + + # build and install remote support (yes / no) + REMOTE_SUPPORT="no" + + # build and install CEC adapter support (yes / no) + CEC_SUPPORT="no" + + # build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="no" + + # build and install iSCSI support - iscsistart (yes / no) + ISCSI_SUPPORT="no" + + # Support for partitioning and formating disks in initramfs (yes / no) + # This adds support for parted and mkfs.ext3/4 to initramfs for OEM usage + INITRAMFS_PARTED_SUPPORT="no" + + # build with swap support (yes / no) + SWAP_SUPPORT="yes" + + # swap support enabled per default (yes / no) + SWAP_ENABLED_DEFAULT="yes" + + # swapfile size if SWAP_SUPPORT=yes in MB + SWAPFILESIZE="384" + + # cron support (yes / no) + CRON_SUPPORT="no" + + # Distribution Specific source location + #DISTRO_MIRROR="http://sources.libreelec.tv/mirror" + #DISTRO_SRC="http://sources.libreelec.tv/$LIBREELEC_VERSION" + + # Addon Server Url + ADDON_SERVER_URL="" + + # Addon ID of the default addon repository + ADDON_REPO_ID="" + + # Name of the default addon repository + ADDON_REPO_NAME="" + + # Version of the default addon repository + ADDON_REPO_VERSION="" + + # set the addon dirs + ADDON_PATH="" + ADDON_URL="" + + # Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + + # IR remote protocols supported in default config + IR_REMOTE_PROTOCOLS="" + + # IR remote keymaps supported in default config + IR_REMOTE_KEYMAPS="" + + # htop tool (yes / no) + HTOP_TOOL="yes" diff --git a/projects/Rockchip/devices/RG351P/bootloader/canupdate.sh b/projects/Rockchip/devices/RG351P/bootloader/canupdate.sh new file mode 100644 index 000000000..b9b32ca91 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/bootloader/canupdate.sh @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# Allow upgrades between arm and aarch64 +if [ "$1" = "@PROJECT@.arm" -o "$1" = "@PROJECT@.aarch64" ]; then + exit 0 +else + exit 1 +fi diff --git a/projects/Rockchip/devices/RG351P/bootloader/install b/projects/Rockchip/devices/RG351P/bootloader/install new file mode 100644 index 000000000..43168ceaf --- /dev/null +++ b/projects/Rockchip/devices/RG351P/bootloader/install @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_RKBIN="$(get_build_dir rkbin)" +PKG_SOC="px30" + +PKG_DATAFILE="$PKG_RKBIN/bin/rk33/rk3326_ddr_333MHz_v1.15.bin" +PKG_LOADER="$PKG_RKBIN/bin/rk33/rk3326_miniloader_v1.20.bin" +PKG_BL31="$PKG_RKBIN/bin/rk33/rk3326_bl31_v1.21.elf" +PKG_BL32="$PKG_RKBIN/bin/rk33/rk3326_bl32_v1.15.bin" + +PKG_LOAD_ADDR="0x00200000" + + +if [ -n "$PKG_DATAFILE" -a -n "$PKG_LOADER" ]; then + tools/mkimage -n $PKG_SOC -T rksd -d "$PKG_DATAFILE" idbloader.img + cat "$PKG_LOADER" >> idbloader.img + cp -av idbloader.img $INSTALL/usr/share/bootloader +fi + +if [ -n "$PKG_LOAD_ADDR" ]; then + $PKG_RKBIN/tools/loaderimage --pack --uboot u-boot-dtb.bin uboot.img $PKG_LOAD_ADDR + cp -av uboot.img $INSTALL/usr/share/bootloader +fi + +cat >$INSTALL/usr/share/bootloader/boot.ini <trust.ini <trust.ini < "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=@BOOT_UUID@ disk=UUID=@DISK_UUID@ quiet ${EXTRA_CMDLINE} +EOF + +cp -a "${LE_TMP}/extlinux/$(basename ${dtb}).conf" $INSTALL/usr/share/bootloader/extlinux +done diff --git a/projects/Rockchip/devices/RG351P/bootloader/mkimage b/projects/Rockchip/devices/RG351P/bootloader/mkimage new file mode 100644 index 000000000..357ce44ae --- /dev/null +++ b/projects/Rockchip/devices/RG351P/bootloader/mkimage @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/idbloader.img" ]; then + echo "image: burn idbloader.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/idbloader.img" of="$DISK" bs=32k seek=1 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/uboot.img" ]; then + echo "image: burn uboot.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/uboot.img" of="$DISK" bs=64k seek=128 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/trust.img" ]; then + echo "image: burn trust.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/trust.img" of="$DISK" bs=64k seek=192 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/boot.ini" ]; then + cp "$RELEASE_DIR/3rdparty/bootloader/boot.ini" "${LE_TMP}/boot.ini" +fi + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" ]; then + cp "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" "${LE_TMP}/logo.bmp" +fi + +mkdir -p "${LE_TMP}/extlinux" + +# copy device trees to part1 +for dtb in $RELEASE_DIR/3rdparty/bootloader/*.dtb; do + +cat << EOF > "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} quiet ${EXTRA_CMDLINE} +EOF + + [ -e "$dtb" ] && mcopy -o "$dtb" :: +done + mcopy -so "${LE_TMP}/boot.ini" :: + mcopy -so "${LE_TMP}/extlinux" :: + mcopy -so "${LE_TMP}/logo.bmp" :: diff --git a/projects/Rockchip/devices/RG351P/bootloader/release b/projects/Rockchip/devices/RG351P/bootloader/release new file mode 100644 index 000000000..67fc93306 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/bootloader/release @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +mkdir -p $RELEASE_DIR/3rdparty/bootloader + if [ -n "$UBOOT_SYSTEM" ]; then + BOOTLOADER_DIR=$(get_build_dir $BOOTLOADER) + if [ -f $BOOTLOADER_DIR/idbloader.img ]; then + cp -a $BOOTLOADER_DIR/idbloader.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/uboot.img ]; then + cp -a $BOOTLOADER_DIR/uboot.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/trust.img ]; then + cp -a $BOOTLOADER_DIR/trust.img $RELEASE_DIR/3rdparty/bootloader + fi + fi + + if [ -f $INSTALL/usr/share/bootloader/logo.bmp ]; then + cp -a $INSTALL/usr/share/bootloader/logo.bmp $RELEASE_DIR/3rdparty/bootloader + fi + + if [ -f $INSTALL/usr/share/bootloader/boot.ini ]; then + cp -a $INSTALL/usr/share/bootloader/boot.ini $RELEASE_DIR/3rdparty/bootloader + fi + + LINUX_DTS_DIR=$(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/ + for dtb in $(find $LINUX_DTS_DIR -name "*.dtb") ; do + if [ -f $dtb ]; then + cp -a $dtb $RELEASE_DIR/3rdparty/bootloader + fi + done + UBOOT_DTS_DIR=$(get_build_dir u-boot)/arch/arm/dts/ + if [ "$DEVICE" == "RG351P" ]; then + cp -f $UBOOT_DTS_DIR/rg351p-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + elif [ "$DEVICE" == "RG351V" ]; then + cp -f $UBOOT_DTS_DIR/rg351v-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + elif [ "$DEVICE" == "RG351MP" ]; then + cp -f $UBOOT_DTS_DIR/rg351mp-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + fi + +LE_TMP=$(mktemp -d) +mkdir -p "${LE_TMP}/extlinux" +mkdir -p $RELEASE_DIR/3rdparty/bootloader + +LINUX_DTS_DIR=$(get_build_dir linux)/.install_pkg/usr/share/bootloader + for dtb in $(find $LINUX_DTS_DIR -name "*.dtb") + do +cat << EOF > "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=@BOOT_UUID@ disk=UUID=@DISK_UUID@ quiet ${EXTRA_CMDLINE} +EOF + +cp -a "${LE_TMP}/extlinux/$(basename ${dtb}).conf" $RELEASE_DIR/3rdparty/bootloader +done diff --git a/projects/Rockchip/devices/RG351P/bootloader/update.sh b/projects/Rockchip/devices/RG351P/bootloader/update.sh new file mode 100644 index 000000000..7da8248b2 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/bootloader/update.sh @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +[ -z "$SYSTEM_ROOT" ] && SYSTEM_ROOT="" +[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/flash" +[ -z "$BOOT_PART" ] && BOOT_PART=$(df "$BOOT_ROOT" | tail -1 | awk {' print $1 '}) +if [ -z "$BOOT_DISK" ]; then + case $BOOT_PART in + /dev/sd[a-z][0-9]*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,[0-9]*,,g") + ;; + /dev/mmcblk*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,p[0-9]*,,g") + ;; + esac +fi + +# mount $BOOT_ROOT r/w + mount -o remount,rw $BOOT_ROOT + + +for arg in $(cat /proc/cmdline); do + case $arg in + boot=*) + boot="${arg#*=}" + case $boot in + /dev/mmc*) + BOOT_UUID="$(blkid $boot | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + BOOT_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $boot " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + BOOT_UUID="$(blkid ${boot#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + disk=*) + disk="${arg#*=}" + case $disk in + /dev/mmc*) + DISK_UUID="$(blkid $disk | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + DISK_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $disk " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + DISK_UUID="$(blkid ${disk#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + esac +done + +CONFS=$SYSTEM_ROOT/usr/share/bootloader/extlinux/*.conf + +for all_conf in $CONFS; do + conf="$(basename ${all_conf})" + echo "Updating ${conf}..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/extlinux/${conf} $BOOT_ROOT/extlinux/${conf} &>/dev/null + sed -e "s/@BOOT_UUID@/$BOOT_UUID/" \ + -e "s/@DISK_UUID@/$DISK_UUID/" \ + -i $BOOT_ROOT/extlinux/${conf} +done + +if [ -f $SYSTEM_ROOT/usr/share/bootloader/boot.ini ]; then + echo "Updating boot.ini..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/boot.ini $BOOT_ROOT/boot.ini &>/dev/null +fi + +# update device tree + for all_dtb in $SYSTEM_ROOT/usr/share/bootloader/*.dtb; do + dtb=$(basename $all_dtb) + echo -n "Updating $dtb... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/$dtb $BOOT_ROOT &>/dev/null + echo "done" + done + +# update bootloader + if [ -f $SYSTEM_ROOT/usr/share/bootloader/idbloader.img ]; then + echo -n "Updating idbloader.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/idbloader.img of=$BOOT_DISK bs=32k seek=1 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/uboot.img ]; then + echo -n "Updating uboot.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/uboot.img of=$BOOT_DISK bs=64k seek=128 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/trust.img ]; then + echo -n "Updating trust.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/trust.img of=$BOOT_DISK bs=64k seek=192 conv=fsync &>/dev/null + echo "done" + fi + + if [ -f $SYSTEM_ROOT/usr/share/bootloader/logo.bmp ]; then + echo -n "Updating uboot logo... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/logo.bmp $BOOT_ROOT &>/dev/null + echo "done" + fi + +# mount $BOOT_ROOT r/o + sync + mount -o remount,ro $BOOT_ROOT &>/dev/null + +# Leave a hint that we just did an update +echo "UPDATE" > /storage/.config/boot.hint + +sync diff --git a/projects/Rockchip/devices/RG351P/device.config b/projects/Rockchip/devices/RG351P/device.config new file mode 100644 index 000000000..067b51278 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/device.config @@ -0,0 +1,51 @@ +# Device definition file for the Anbernic RG351P + +# Device Features +DEVICE_HAS_FAN=false +DEVICE_FAKE_JACKSENSE=true +DEVICE_VOLUMECTL=true +DEVICE_POWER_LED=true +DEVICE_AUDIO_MIXER="Playback" +DEVICE_VOLUME_DEV="/dev/input/by-path/platform-rg351-keys-event" +DEVICE_CONTROLLER_DEV="/dev/input/event3" +DEVICE_BRIGHTNESS="70" +DISPLAY_ROTATED=true + +# GPIOS +DEVICE_WIFI="5" +DEVICE_LED="77" +DEVICE_PWM_MOTOR="pwmchip0" +#DEVICE_PWM_FAN="" +DEVICE_JACK="/sys/class/gpio/gpio86/value" + +# FREQ governors +CPU_FREQ="/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" +GPU_FREQ="/sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu.gpu/governor" +DMC_FREQ="/sys/devices/platform/dmc/devfreq/dmc/governor" + +# Affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="${SLOW_CORES}" + +# Volume Keys +#DEVICE_KEY_VOLUMEDOWN= +#DEVICE_KEY_VOLUMEUP= + +# Controller +DEVICE_BTN_SOUTH="1" # B +DEVICE_BTN_EAST="0" # A +DEVICE_BTN_NORTH="2" # X +DEVICE_BTN_WEST="3" # Y +DEVICE_BTN_TL="10" +DEVICE_BTN_TR="11" +DEVICE_BTN_TL2="4" +DEVICE_BTN_TR2="5" +DEVICE_BTN_SELECT="7" +DEVICE_BTN_START="6" +DEVICE_BTN_MODE="7" +DEVICE_BTN_THUMBL="8" +DEVICE_BTN_THUMBR="9" +DEVICE_BTN_DPAD_UP="0.1" +DEVICE_BTN_DPAD_DOWN="0.4" +DEVICE_BTN_DPAD_LEFT="0.8" +DEVICE_BTN_DPAD_RIGHT="0.2" diff --git a/projects/Rockchip/devices/RG351P/device.init b/projects/Rockchip/devices/RG351P/device.init new file mode 100644 index 000000000..b8ba1d284 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/device.init @@ -0,0 +1,15 @@ +# Enable GPIO 77 for power LED manipulation +echo ${DEVICE_LED} > /sys/class/gpio/export 2>/dev/null + +# Enable WIFI GPIO for WIFI manipulation +echo ${DEVICE_WIFI} > /sys/class/gpio/export 2>/dev/null + +# Power up the WIFI device +echo out > /sys/class/gpio/gpio${DEVICE_WIFI}/direction 2>/dev/null +echo 1 > /sys/class/gpio/gpio${DEVICE_WIFI}/value 2>/dev/null + +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period 2>/dev/null +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle 2>/dev/null diff --git a/projects/Rockchip/devices/RG351P/linux/linux.aarch64.conf b/projects/Rockchip/devices/RG351P/linux/linux.aarch64.conf new file mode 100644 index 000000000..bdf94f86d --- /dev/null +++ b/projects/Rockchip/devices/RG351P/linux/linux.aarch64.conf @@ -0,0 +1,4647 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.4.189 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_SHIFT=4 +CONFIG_NO_IOPORT_MAP=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="@DISTRONAME@" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_PIDS is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_MEMCG is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_INITRD_ASYNC is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_MEMBARRIER=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +CONFIG_PROFILING=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_RK_PARTITION=y +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_EXYNOS7 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_ROCKCHIP_ODROIDGOA=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_DOMAINS_GENERIC is not set +# CONFIG_PCI_SYSCALL is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_MMU_NOTIFIER=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_SECCOMP=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_UAO=y +CONFIG_ARM64_MODULE_CMODEL_LARGE=y +# CONFIG_RANDOMIZE_BASE is not set + +# +# Boot options +# +CONFIG_CMDLINE="" +# CONFIG_EFI is not set +# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_KEYS_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_ROCKCHIP_CPUFREQ=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=y +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_TCP_CONG="reno" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +# CONFIG_NF_TABLES_BRIDGE is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_MRP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_HWMON=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_SOCKET=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_HSR is not set +CONFIG_NET_SWITCHDEV=y +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_6LOWPAN is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_RTKBTUSB=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_QCA is not set +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_MINSTREL_VHT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_LWTUNNEL=y +CONFIG_DST_CACHE=y +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_DEVRES=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set + +# +# Bus devices +# +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND_IDS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_ROCKCHIP_SCR is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_USB_CAM_GPIO is not set +# CONFIG_GPIO_DET is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_EEH is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_TUN_VNET_CROSS_LE=y +CONFIG_VETH=m +CONFIG_NLMON=m + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_ETHERNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_TERANETICS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=m +CONFIG_PPPOPNS=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +# CONFIG_USB_LAN78XX is not set +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +CONFIG_USB_NET_CDC_MBIM=m +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USB_NET_CH9200 is not set +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +# CONFIG_ATH6KL_USB is not set +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_WCN36XX is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +CONFIG_HOSTAP=m +# CONFIG_HOSTAP_FIRMWARE is not set +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_P54_SPI is not set +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8XXXU=m +# CONFIG_RTL8XXXU_UNTESTED is not set +CONFIG_WL_ROCKCHIP=y +CONFIG_WIFI_BUILD_MODULE=y +CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +# CONFIG_AP6XXX is not set +# CONFIG_CYW_BCMDHD is not set +CONFIG_RTL_WIRELESS_SOLUTION=y +CONFIG_RTL8188EU=m +CONFIG_RTL8188FU=m +# CONFIG_RTL8189ES is not set +# CONFIG_RTL8189FS is not set +# CONFIG_RTL8723BS is not set +CONFIG_RTL8723BU=m +# CONFIG_RTL8723CS is not set +# CONFIG_RTL8723DS is not set +# CONFIG_MVL88W8977 is not set + +# +# SouthSV 6XXX WLAN support +# +# CONFIG_SSV6051 is not set +CONFIG_WL_TI=y +CONFIG_WL1251=m +# CONFIG_WL1251_SPI is not set +# CONFIG_WL1251_SDIO is not set +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +# CONFIG_WLCORE_SPI is not set +# CONFIG_WLCORE_SDIO is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_USB=m +CONFIG_CW1200=m +# CONFIG_CW1200_WLAN_SDIO is not set +# CONFIG_CW1200_WLAN_SPI is not set +CONFIG_RSI_91X=m +CONFIG_RSI_DEBUGFS=y +CONFIG_RSI_SDIO=m +CONFIG_RSI_USB=m +CONFIG_RTL8812AU=m +CONFIG_RTL8822BU=m +CONFIG_RTL8821CU=m +CONFIG_ESP8089=m +CONFIG_ESP8089_DEBUG_FS=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_IEEE802154_DRIVERS=m +# CONFIG_IEEE802154_FAKELB is not set +# CONFIG_IEEE802154_AT86RF230 is not set +# CONFIG_IEEE802154_MRF24J40 is not set +# CONFIG_IEEE802154_CC2520 is not set +# CONFIG_IEEE802154_ATUSB is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=m +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_ROCKCHIP=y +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +# CONFIG_JOYSTICK_IFORCE_232 is not set +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_AS5011=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ADC=y +CONFIG_JOYSTICK_ODROIDGO2=y +CONFIG_JOYSTICK_ODROIDGO3=y +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set + +# +# handle all sensors +# +# CONFIG_SENSOR_DEVICE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYCHORD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_RK8XX_PWRKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=m +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_INGENIC is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_ROCKCHIP is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +CONFIG_TCG_TPM=y +# CONFIG_TCG_TIS_I2C_ATMEL is not set +CONFIG_TCG_TIS_I2C_INFINEON=y +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_TIS_ST33ZP24 is not set +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +CONFIG_I2C_RK3X=y +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=m +# CONFIG_SPI_CADENCE is not set +CONFIG_SPI_GPIO=m +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_ROCKCHIP=m +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_RK805=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +CONFIG_GPIO_RK8XX=y + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# SPI or I2C GPIO expanders +# +# CONFIG_GPIO_MCP23S08 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=y +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25700 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_SY6982C is not set +# CONFIG_CHARGER_UNIVERSAL is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_EC is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_RK816 is not set +CONFIG_BATTERY_RK817=y +CONFIG_CHARGER_RK817=y +# CONFIG_BATTERY_RK818 is not set +# CONFIG_CHARGER_RK818 is not set +# CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_POWER_AVS=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_IMX_THERMAL is not set +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_RK_VIRTUAL_THERMAL is not set +# CONFIG_RK3368_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set +CONFIG_MFD_RK808=y +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_RK1000 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_FUSB_30X is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8752 is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8865 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +CONFIG_REGULATOR_RK818=y +# CONFIG_REGULATOR_SYR82X is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS549B22 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_XZ3216 is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_IGNORE_IOTCL_PERMIT=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +# CONFIG_DRM_DP_CEC is not set +# CONFIG_DRM_SCDC_HELPER is not set +CONFIG_DRM_DMA_SYNC=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_VGEM is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_ROCKCHIP_DRM_DEBUG is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_MIPI_CSI_TX is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_LVDS is not set +# CONFIG_ROCKCHIP_DRM_TVE is not set +# CONFIG_ROCKCHIP_RGB is not set +# CONFIG_ROCKCHIP_DRM_BACKLIGHT is not set +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +# CONFIG_DRM_UDL is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_ODROID_ST7701S is not set +CONFIG_DRM_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LONTIUM_LT8912 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_POWERVR_ROGUE_M is not set +# CONFIG_MALI400 is not set +CONFIG_MALI_MIDGARD_FOR_ANDROID=y +# CONFIG_MALI_MIDGARD_FOR_LINUX is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MALI_CORESTACK is not set +CONFIG_MALI_PWRSOFT_765=y +# CONFIG_MALI_KUTF is not set +# CONFIG_MALI_BIFROST_FOR_ANDROID is not set +CONFIG_MALI_BIFROST_FOR_LINUX=y +CONFIG_MALI_BIFROST=y +# CONFIG_MALI_BIFROST_GATOR_SUPPORT is not set +# CONFIG_MALI_BIFROST_ENABLE_TRACE is not set +CONFIG_MALI_BIFROST_DEVFREQ=y +# CONFIG_MALI_BIFROST_DMA_FENCE is not set +CONFIG_MALI_PLATFORM_NAME="rk" +CONFIG_MALI_BIFROST_EXPERT=y +# CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY is not set +# CONFIG_MALI_BIFROST_DEBUG is not set +# CONFIG_MALI_BIFROST_NO_MALI is not set +# CONFIG_MALI_BIFROST_TRACE_TIMELINE is not set +# CONFIG_MALI_BIFROST_SYSTEM_TRACE is not set +# CONFIG_MALI_JOB_DUMP is not set +# CONFIG_MALI_2MB_ALLOC is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set + +# +# Rockchip Misc Video driver +# +# CONFIG_FB_ROCKCHIP is not set +# CONFIG_LCDC_RK3368 is not set +CONFIG_LCD_GENERAL=y +# CONFIG_LCD_MIPI is not set +# CONFIG_RK_TRSM is not set +# CONFIG_RK_HDMI is not set + +# +# RGA +# +# CONFIG_ROCKCHIP_RGA is not set + +# +# RGA2 +# +CONFIG_ROCKCHIP_RGA2=y + +# +# VCODEC +# +CONFIG_RK_VCODEC=y + +# +# IEP +# +# CONFIG_IEP is not set +# CONFIG_IEP_MMU is not set + +# +# DP +# + +# +# ROCKCHIP_MPP +# +CONFIG_ROCKCHIP_MPP_SERVICE=y +CONFIG_ROCKCHIP_MPP_DEVICE=y +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=y +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +CONFIG_SND_SOC_ROCKCHIP=y +# CONFIG_SND_SOC_ROCKCHIP_FORCE_SRAM is not set +CONFIG_SND_SOC_ROCKCHIP_I2S=y +# CONFIG_SND_SOC_ROCKCHIP_I2S_TDM is not set +CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS=y +CONFIG_SND_SOC_ROCKCHIP_PDM=y +# CONFIG_SND_SOC_ROCKCHIP_SPDIF is not set +# CONFIG_SND_SOC_ROCKCHIP_SPDIFRX is not set +# CONFIG_SND_SOC_ROCKCHIP_VAD is not set +# CONFIG_SND_SOC_ROCKCHIP_DA7219 is not set +# CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5651_TC358749 is not set +# CONFIG_SND_SOC_ROCKCHIP_CDNDP is not set + +# +# Allwinner SoC Audio support +# +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set +# CONFIG_SND_SOC_DUMMY_CODEC is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8323 is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_GVA_CODEC is not set +# CONFIG_SND_SOC_FM1288 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK312X is not set +# CONFIG_SND_SOC_RK3228 is not set +# CONFIG_SND_SOC_RK3308 is not set +# CONFIG_SND_SOC_RK3328 is not set +CONFIG_SND_SOC_RK817=y +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5651 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TC358749X is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=y +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_RKVR is not set +# CONFIG_HID_ALPS is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEFAULT_PERSIST is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_DWC2=m +CONFIG_USB_DWC2_HOST=y + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP210X=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +# CONFIG_USB_SERIAL_QCAUX is not set +CONFIG_USB_SERIAL_QUALCOMM=m +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=y +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +# CONFIG_USB_CONFIGFS_SERIAL is not set +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +# CONFIG_USB_CONFIGFS_EEM is not set +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_MTP is not set +# CONFIG_USB_CONFIGFS_F_ACC is not set +# CONFIG_USB_CONFIGFS_UEVENT is not set +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set + +# +# ROCKCHIP USB Support +# +# CONFIG_USB20_HOST is not set +# CONFIG_USB20_OTG is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=y +# CONFIG_MMC_SIMULATE_MAX_SPEED is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_FAKE is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RK808=y +# CONFIG_RTC_DRV_RK_TIMER is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +CONFIG_PL330_DMA=y +# CONFIG_DW_DMAC is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTLLIB is not set +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +CONFIG_R8723AU=m +CONFIG_8723AU_AP_MODE=y +CONFIG_8723AU_BT_COEXIST=y +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7606 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# CONFIG_INV_MPU_IIO is not set + +# +# Light sensors +# +CONFIG_SENSORS_ISL29018=y +# CONFIG_SENSORS_ISL29028 is not set +CONFIG_TSL2583=y +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ASHMEM is not set +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_SYNC is not set +# CONFIG_ION is not set +CONFIG_FIQ_DEBUGGER=y +CONFIG_FIQ_DEBUGGER_NO_SLEEP=y +# CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON is not set +CONFIG_FIQ_DEBUGGER_CONSOLE=y +CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y +# CONFIG_FIQ_DEBUGGER_TRUST_ZONE is not set +# CONFIG_FIQ_DEBUGGER_UART_OVERLAY is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_RK_CONSOLE_THREAD is not set +# CONFIG_STAGING_BOARD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_WILC1000_DRIVER is not set +# CONFIG_MOST is not set +# CONFIG_POWERVR_ROGUE_N is not set + +# +# Qualcomm Atheros CLD WLAN module +# +# CONFIG_QCA_CLD_WLAN is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_VERSATILE is not set +CONFIG_COMMON_CLK_RK808=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# +# CONFIG_HWSPINLOCK_ROCKCHIP is not set + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_IOVA=y +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_ROCKCHIP_IOMMU=y +# CONFIG_RK_IOMMU is not set +# CONFIG_ARM_SMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# + +# +# Rockchip CPU selection +# +CONFIG_CPU_PX30=y +# CONFIG_CPU_RK1808 is not set +# CONFIG_CPU_RK3308 is not set +CONFIG_CPU_RK3328=y +# CONFIG_CPU_RK3366 is not set +CONFIG_CPU_RK3368=y +CONFIG_CPU_RK3399=y +CONFIG_ANDROID_VERSION=0x07010000 +CONFIG_ROCKCHIP_CPUINFO=y +# CONFIG_ROCKCHIP_DEVICEINFO is not set +CONFIG_ROCKCHIP_IPA=y +CONFIG_ROCKCHIP_OPP=y +# CONFIG_ROCKCHIP_PM_TEST is not set +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +CONFIG_ROCKCHIP_PVTM=y +CONFIG_ROCKCHIP_SUSPEND_MODE=y +CONFIG_ROCKCHIP_SYSTEM_MONITOR=y +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y + +# +# DEVFREQ Drivers +# +# CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_BUFFER_CB is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MXC4005 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD799X is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_GPIO_MUXADC is not set +# CONFIG_HI8435 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +CONFIG_ROCKCHIP_SARADC=y +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_VF610_ADC is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Chemical Sensors +# +# CONFIG_VZ89X is not set + +# +# Hid Sensor IIO Common +# + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set +# CONFIG_HDC100X is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9960 is not set +# CONFIG_BH1750 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_ISL29125 is not set +# CONFIG_JSA1212 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR501 is not set +# CONFIG_OPT3001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_STK3310 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +CONFIG_SENSORS_TSL2563=y +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VL6180 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_MAG3110 is not set +# CONFIG_MMC35240 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +CONFIG_IIO_SYSFS_TRIGGER=y + +# +# Digital potentiometers +# +# CONFIG_MCP4531 is not set + +# +# Pressure sensors +# +# CONFIG_BMP280 is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set + +# +# Proximity sensors +# +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set + +# +# Temperature sensors +# +# CONFIG_MLX90614 is not set +# CONFIG_TMP006 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_ROCKCHIP=y +# CONFIG_PWM_ROCKCHIP_I2S is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V3=y +CONFIG_PARTITION_PERCPU=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_XGENE is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PHY_ROCKCHIP_INNO_COMBPHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_INNO_USB3 is not set +# CONFIG_PHY_ROCKCHIP_EMMC is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_INNO_MIPI_DPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI_PHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_VIDEO_PHY is not set +CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y +# CONFIG_PHY_ROCKCHIP_TYPEC is not set +# CONFIG_PHY_ROCKCHIP_PCIE is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_RAS=y + +# +# Android +# +CONFIG_ANDROID=y +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_LIBNVDIMM is not set +CONFIG_NVMEM=y +# CONFIG_ROCKCHIP_EFUSE is not set +CONFIG_ROCKCHIP_OTP=y +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set + +# +# FPGA Configuration Support +# +# CONFIG_FPGA is not set +# CONFIG_TEE is not set +CONFIG_RK_FLASH=y + +# +# Rockchip Flash Devices +# +# CONFIG_RK_NANDC_NAND is not set +CONFIG_RK_SFC_NAND=y +CONFIG_RK_SFC_NOR=y +CONFIG_RK_SFC_NOR_MTD=y +# CONFIG_RK_NAND is not set + +# +# Headset device support +# +# CONFIG_RK_HEADSET is not set + +# +# Gator module for ARM streamline +# + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_ROCKCHIP_SIP=y + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_FS_DAX is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +CONFIG_OVERLAY_FS=y + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +# CONFIG_CACHEFILES is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_VIRTUAL_XATTR=y +CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:exfat:s0" +# CONFIG_EXFAT_DEBUG is not set +# CONFIG_EXFAT_UEVENT is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_UID=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_SDCARD_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +CONFIG_SQUASHFS_LZO=y +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +# CONFIG_PSTORE_PMSG is not set +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +CONFIG_HAVE_KVM_IRQFD=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_ARM_VGIC_V3=y +CONFIG_KVM=y +CONFIG_KVM_ARM_HOST=y +CONFIG_VHOST_NET=m +CONFIG_VHOST=m +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_PROCESS is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_KASAN is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y +CONFIG_HARDLOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_CREDENTIALS=y + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_GPU_TRACEPOINTS=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_TEE_SUPPORT is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_HEH is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V2 is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +# CONFIG_CRYPTO_POLY_HASH_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_CRC32_ARM64 is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_CLZ_TAB=y +CONFIG_CORDIC=m +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_SG_SPLIT is not set +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/projects/Rockchip/devices/RG351P/options b/projects/Rockchip/devices/RG351P/options new file mode 100644 index 000000000..50e2240d0 --- /dev/null +++ b/projects/Rockchip/devices/RG351P/options @@ -0,0 +1,227 @@ +################################################################################ +# setup device defaults +################################################################################ + + # The TARGET_CPU variable controls which processor should be targeted for + # generated code. + case $TARGET_ARCH in + aarch64) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc+fp+simd" + TARGET_FPU="fp-armv8" + TARGET_FEATURES="64bit" + ;; + arm) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc" + TARGET_FPU="crypto-neon-fp-armv8" + TARGET_FEATURES="32bit" + ;; + esac + + # Kernel target + KERNEL_TARGET="Image" + + # Additional kernel make parameters (for example to specify the u-boot loadaddress) + KERNEL_MAKE_EXTRACMD="" + KERNEL_MAKE_EXTRACMD+=" rockchip/rk3326-rg351p-linux.dtb" + KERNEL_MAKE_EXTRACMD+=" rockchip/rk3326-rg351p-linux-oc.dtb" + + # Mali GPU family + MALI_FAMILY="g31" + OPENGLES="libmali" + + # Define the CPU + HW_CPU="Rockchip RK3326" + + # kernel serial console + EXTRA_CMDLINE="console=ttyFIQ0 console=tty0 net.iframes=0 fbcon=rotate:3 ssh consoleblank=0 systemd.show_status=0 loglevel=0 panic=20" + + LINUX="RG351P" + UBOOT_SYSTEM="rg351p" + + # additional packages to install + ADDITIONAL_PACKAGES="dtc jelos" + + # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware) + # Space separated list is supported, + # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware" + FIRMWARE="misc-firmware wlan-firmware" #rockchip-firmware + + # additional drivers to install: + # for a list of additional drivers see packages/linux-drivers + # Space separated list is supported, + # e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2" + ADDITIONAL_DRIVERS="RTL8812AU" #RTL8188EU RTL8814AU RTL8192DU RTL8812AU RTL8821CU RTL8192CU RTL8192EU + + # build and install driver addons (yes / no) + DRIVER_ADDONS_SUPPORT="no" + + # driver addons to install: + # for a list of additinoal drivers see packages/linux-driver-addons + # Space separated list is supported, + DRIVER_ADDONS="" #dvb-latest + + # debug tty path + DEBUG_TTY="/dev/ttyFIQ0" + + + # Skins to install (Estuary) + # Space separated list is supported, + # e.g. SKINS="Estuary" + SKINS="Estuary" + + # Default Skin (Estuary) + SKIN_DEFAULT="Estuary" + + # Select whether to use default (upstream xbmc/xbmc) repo, or specific vendor repo + KODI_VENDOR="default" + + # install extra subtitle Fonts for KODI (yes / no) + KODI_EXTRA_FONTS="yes" + + # build and install PulseAudio support (yes / no) + PULSEAUDIO_SUPPORT="yes" + + # build and install espeak support (yes / no) + ESPEAK_SUPPORT="no" + + # build and install with BluRay support (yes / no) + KODI_BLURAY_SUPPORT="no" + + # build and install with BD+ support + # (BD+ decryption support in KODI) (yes / no) + BLURAY_BDPLUS_SUPPORT="no" + + # build and install with AACS support + # (BD decryption support in KODI) (yes / no) + BLURAY_AACS_SUPPORT="no" + + # build and install with DVDCSS support + # (DVD decryption support in KODI) (yes / no) + KODI_DVDCSS_SUPPORT="no" + + # build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="no" + + # build and install with KODI webfrontend (yes / no) + KODI_WEBSERVER_SUPPORT="no" + + # build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="no" + + # build with UPnP support (yes / no) + KODI_UPNP_SUPPORT="no" + + # build with MySQL support (mysql / mariadb / none) + KODI_MYSQL_SUPPORT="none" + + # build xbmc with optical drive support (yes / no) + KODI_OPTICAL_SUPPORT="no" + + # build with AirPlay support (stream videos from iDevices to KODI) (yes / no) + KODI_AIRPLAY_SUPPORT="no" + + # build with AirTunes support (stream music from iDevices to KODI) (yes / no) + KODI_AIRTUNES_SUPPORT="no" + + # build with libnfs support (mounting nfs shares with KODI) (yes / no) + KODI_NFS_SUPPORT="no" + + # build with Samba Client support (mounting SAMBA shares with KODI) (yes / no) + KODI_SAMBA_SUPPORT="no" + + # build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="no" + + # build with Samba Client support (mounting samba shares via the OS) (yes / no) + SAMBA_SUPPORT="no" + + # build and install Samba Server (yes / no) + SAMBA_SERVER="yes" + + # build and install SFTP Server (yes / no) + SFTP_SERVER="yes" + + # build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + + # build and install diskmounter support (udevil) + # this service provide auto mounting support for external drives in the + # mediacenter also automount internally drives at boottime via udev (yes / no) + UDEVIL="yes" + + # build and install exFAT fuse support (yes / no) + EXFAT="yes" + + # build and install NTFS-3G fuse support (yes / no) + NTFS3G="no" + + # build and install hfs filesystem utilities (yes / no) + HFSTOOLS="no" + + # build and install remote support (yes / no) + REMOTE_SUPPORT="no" + + # build and install CEC adapter support (yes / no) + CEC_SUPPORT="no" + + # build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="no" + + # build and install iSCSI support - iscsistart (yes / no) + ISCSI_SUPPORT="no" + + # Support for partitioning and formating disks in initramfs (yes / no) + # This adds support for parted and mkfs.ext3/4 to initramfs for OEM usage + INITRAMFS_PARTED_SUPPORT="no" + + # build with swap support (yes / no) + SWAP_SUPPORT="yes" + + # swap support enabled per default (yes / no) + SWAP_ENABLED_DEFAULT="yes" + + # swapfile size if SWAP_SUPPORT=yes in MB + SWAPFILESIZE="384" + + # cron support (yes / no) + CRON_SUPPORT="no" + + # Distribution Specific source location + #DISTRO_MIRROR="http://sources.libreelec.tv/mirror" + #DISTRO_SRC="http://sources.libreelec.tv/$LIBREELEC_VERSION" + + # Addon Server Url + ADDON_SERVER_URL="" + + # Addon ID of the default addon repository + ADDON_REPO_ID="" + + # Name of the default addon repository + ADDON_REPO_NAME="" + + # Version of the default addon repository + ADDON_REPO_VERSION="" + + # set the addon dirs + ADDON_PATH="" + ADDON_URL="" + + # Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + + # IR remote protocols supported in default config + IR_REMOTE_PROTOCOLS="" + + # IR remote keymaps supported in default config + IR_REMOTE_KEYMAPS="" + + # htop tool (yes / no) + HTOP_TOOL="yes" diff --git a/projects/Rockchip/devices/RG351P/packages/python-evdev/package.mk b/projects/Rockchip/devices/RG351P/packages/python-evdev/package.mk new file mode 100644 index 000000000..66d506a1e --- /dev/null +++ b/projects/Rockchip/devices/RG351P/packages/python-evdev/package.mk @@ -0,0 +1,44 @@ +PKG_NAME="python-evdev" +PKG_VERSION="5ac66502adc219f816ba833032a5207982eb4861" +#PKG_SHA256="b1c649b4fed7252711011da235782b2c260b32e004058d62473471e5cd30634d" +PKG_LICENSE="OSS" +PKG_SITE="https://pypi.org/project/evdev" +PKG_URL="https://files.pythonhosted.org/packages/89/83/5f5635fd0d91a08ac355dd9ca9bde34bfa6b29a5c59f703ad83d1ad0bf34/evdev-1.3.0.tar.gz" +PKG_DEPENDS_TARGET="toolchain Python3:host distutilscross:host" +PKG_LONGDESC="Userspace evdev events" +PKG_TOOLCHAIN="manual" + +pre_make_target() { + export PYTHONXCPREFIX="${SYSROOT_PREFIX}/usr" + export LDFLAGS="${LDFLAGS} -L${SYSROOT_PREFIX}/usr/lib -L${SYSROOT_PREFIX}/lib" + export LDSHARED="${CC} -shared" + find . -name setup.py -exec sed -i "s:/usr/include/linux/input.h :${SYSROOT_PREFIX}/usr/include/linux/input.h:g" \{} \; + find . -name setup.py -exec sed -i "s:/usr/include/linux/input-event-codes.h :${SYSROOT_PREFIX}/usr/include/linux/input-event-codes.h:g" \{} \; +} + +make_target() { + python3 setup.py build \ + build_ecodes --evdev-headers ${SYSROOT_PREFIX}/usr/include/linux/input.h:${SYSROOT_PREFIX}/usr/include/linux/input-event-codes.h +} + +makeinstall_target() { + python3 setup.py install --root=${INSTALL} --prefix=/usr +} + +post_makeinstall_target() { + # Seems like there's an issue in the build system. + # C Modules get built using the correct target toolchain but the generated *.so + # files use the arch from the host system + # tried to solve it but couldn't so I move them to the correct names for python + # to grab them + mv ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_ecodes.cpython-38-* \ + ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_ecodes.cpython-38-arm-linux-gnueabihf.so + mv ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_input.cpython-38-* \ + ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_input.cpython-38-arm-linux-gnueabihf.so + mv ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_uinput.cpython-38-* \ + ${INSTALL}/usr/lib/python3.8/site-packages/evdev/_uinput.cpython-38-arm-linux-gnueabihf.so +} + +# post_makeinstall_target() { + # find ${INSTALL}/usr/lib/python*/site-packages/ -name "*.py" -exec rm -rf {} ";" +# } diff --git a/projects/Rockchip/devices/RG351V/bootloader/canupdate.sh b/projects/Rockchip/devices/RG351V/bootloader/canupdate.sh new file mode 100644 index 000000000..b9b32ca91 --- /dev/null +++ b/projects/Rockchip/devices/RG351V/bootloader/canupdate.sh @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +# Allow upgrades between arm and aarch64 +if [ "$1" = "@PROJECT@.arm" -o "$1" = "@PROJECT@.aarch64" ]; then + exit 0 +else + exit 1 +fi diff --git a/projects/Rockchip/devices/RG351V/bootloader/install b/projects/Rockchip/devices/RG351V/bootloader/install new file mode 100644 index 000000000..b909746ec --- /dev/null +++ b/projects/Rockchip/devices/RG351V/bootloader/install @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_RKBIN="$(get_build_dir rkbin)" +PKG_SOC="px30" + +PKG_DATAFILE="$PKG_RKBIN/bin/rk33/rk3326_ddr_333MHz_v1.15.bin" +PKG_LOADER="$PKG_RKBIN/bin/rk33/rk3326_miniloader_v1.20.bin" +PKG_BL31="$PKG_RKBIN/bin/rk33/rk3326_bl31_v1.21.elf" +PKG_BL32="$PKG_RKBIN/bin/rk33/rk3326_bl32_v1.15.bin" + +PKG_LOAD_ADDR="0x00200000" + + +if [ -n "$PKG_DATAFILE" -a -n "$PKG_LOADER" ]; then + tools/mkimage -n $PKG_SOC -T rksd -d "$PKG_DATAFILE" idbloader.img + cat "$PKG_LOADER" >> idbloader.img + cp -av idbloader.img $INSTALL/usr/share/bootloader +fi + +if [ -n "$PKG_LOAD_ADDR" ]; then + $PKG_RKBIN/tools/loaderimage --pack --uboot u-boot-dtb.bin uboot.img $PKG_LOAD_ADDR + cp -av uboot.img $INSTALL/usr/share/bootloader +fi + +cat >$INSTALL/usr/share/bootloader/boot.ini <trust.ini <trust.ini < "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=@BOOT_UUID@ disk=UUID=@DISK_UUID@ quiet ${EXTRA_CMDLINE} +EOF + +cp -a "${LE_TMP}/extlinux/$(basename ${dtb}).conf" $INSTALL/usr/share/bootloader/extlinux +done diff --git a/projects/Rockchip/devices/RG351V/bootloader/mkimage b/projects/Rockchip/devices/RG351V/bootloader/mkimage new file mode 100644 index 000000000..357ce44ae --- /dev/null +++ b/projects/Rockchip/devices/RG351V/bootloader/mkimage @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/idbloader.img" ]; then + echo "image: burn idbloader.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/idbloader.img" of="$DISK" bs=32k seek=1 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/uboot.img" ]; then + echo "image: burn uboot.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/uboot.img" of="$DISK" bs=64k seek=128 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi +if [ -f "$RELEASE_DIR/3rdparty/bootloader/trust.img" ]; then + echo "image: burn trust.img to image..." + dd if="$RELEASE_DIR/3rdparty/bootloader/trust.img" of="$DISK" bs=64k seek=192 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error +fi + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/boot.ini" ]; then + cp "$RELEASE_DIR/3rdparty/bootloader/boot.ini" "${LE_TMP}/boot.ini" +fi + +if [ -f "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" ]; then + cp "$RELEASE_DIR/3rdparty/bootloader/logo.bmp" "${LE_TMP}/logo.bmp" +fi + +mkdir -p "${LE_TMP}/extlinux" + +# copy device trees to part1 +for dtb in $RELEASE_DIR/3rdparty/bootloader/*.dtb; do + +cat << EOF > "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} quiet ${EXTRA_CMDLINE} +EOF + + [ -e "$dtb" ] && mcopy -o "$dtb" :: +done + mcopy -so "${LE_TMP}/boot.ini" :: + mcopy -so "${LE_TMP}/extlinux" :: + mcopy -so "${LE_TMP}/logo.bmp" :: diff --git a/projects/Rockchip/devices/RG351V/bootloader/release b/projects/Rockchip/devices/RG351V/bootloader/release new file mode 100644 index 000000000..67fc93306 --- /dev/null +++ b/projects/Rockchip/devices/RG351V/bootloader/release @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +mkdir -p $RELEASE_DIR/3rdparty/bootloader + if [ -n "$UBOOT_SYSTEM" ]; then + BOOTLOADER_DIR=$(get_build_dir $BOOTLOADER) + if [ -f $BOOTLOADER_DIR/idbloader.img ]; then + cp -a $BOOTLOADER_DIR/idbloader.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/uboot.img ]; then + cp -a $BOOTLOADER_DIR/uboot.img $RELEASE_DIR/3rdparty/bootloader + fi + if [ -f $BOOTLOADER_DIR/trust.img ]; then + cp -a $BOOTLOADER_DIR/trust.img $RELEASE_DIR/3rdparty/bootloader + fi + fi + + if [ -f $INSTALL/usr/share/bootloader/logo.bmp ]; then + cp -a $INSTALL/usr/share/bootloader/logo.bmp $RELEASE_DIR/3rdparty/bootloader + fi + + if [ -f $INSTALL/usr/share/bootloader/boot.ini ]; then + cp -a $INSTALL/usr/share/bootloader/boot.ini $RELEASE_DIR/3rdparty/bootloader + fi + + LINUX_DTS_DIR=$(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/ + for dtb in $(find $LINUX_DTS_DIR -name "*.dtb") ; do + if [ -f $dtb ]; then + cp -a $dtb $RELEASE_DIR/3rdparty/bootloader + fi + done + UBOOT_DTS_DIR=$(get_build_dir u-boot)/arch/arm/dts/ + if [ "$DEVICE" == "RG351P" ]; then + cp -f $UBOOT_DTS_DIR/rg351p-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + elif [ "$DEVICE" == "RG351V" ]; then + cp -f $UBOOT_DTS_DIR/rg351v-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + elif [ "$DEVICE" == "RG351MP" ]; then + cp -f $UBOOT_DTS_DIR/rg351mp-uboot.dtb $RELEASE_DIR/3rdparty/bootloader + fi + +LE_TMP=$(mktemp -d) +mkdir -p "${LE_TMP}/extlinux" +mkdir -p $RELEASE_DIR/3rdparty/bootloader + +LINUX_DTS_DIR=$(get_build_dir linux)/.install_pkg/usr/share/bootloader + for dtb in $(find $LINUX_DTS_DIR -name "*.dtb") + do +cat << EOF > "${LE_TMP}/extlinux/$(basename ${dtb}).conf" +LABEL ${DISTRO} + LINUX /${KERNEL_NAME} + FDT /$(basename ${dtb}) + APPEND boot=UUID=@BOOT_UUID@ disk=UUID=@DISK_UUID@ quiet ${EXTRA_CMDLINE} +EOF + +cp -a "${LE_TMP}/extlinux/$(basename ${dtb}).conf" $RELEASE_DIR/3rdparty/bootloader +done diff --git a/projects/Rockchip/devices/RG351V/bootloader/update.sh b/projects/Rockchip/devices/RG351V/bootloader/update.sh new file mode 100644 index 000000000..7da8248b2 --- /dev/null +++ b/projects/Rockchip/devices/RG351V/bootloader/update.sh @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +[ -z "$SYSTEM_ROOT" ] && SYSTEM_ROOT="" +[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/flash" +[ -z "$BOOT_PART" ] && BOOT_PART=$(df "$BOOT_ROOT" | tail -1 | awk {' print $1 '}) +if [ -z "$BOOT_DISK" ]; then + case $BOOT_PART in + /dev/sd[a-z][0-9]*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,[0-9]*,,g") + ;; + /dev/mmcblk*) + BOOT_DISK=$(echo $BOOT_PART | sed -e "s,p[0-9]*,,g") + ;; + esac +fi + +# mount $BOOT_ROOT r/w + mount -o remount,rw $BOOT_ROOT + + +for arg in $(cat /proc/cmdline); do + case $arg in + boot=*) + boot="${arg#*=}" + case $boot in + /dev/mmc*) + BOOT_UUID="$(blkid $boot | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + BOOT_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $boot " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + BOOT_UUID="$(blkid ${boot#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + disk=*) + disk="${arg#*=}" + case $disk in + /dev/mmc*) + DISK_UUID="$(blkid $disk | sed 's/.* UUID="//;s/".*//g')" + ;; + UUID=*|LABEL=*) + DISK_UUID="$(blkid | sed 's/"//g' | grep -m 1 -i " $disk " | sed 's/.* UUID=//;s/ .*//g')" + ;; + FOLDER=*) + DISK_UUID="$(blkid ${disk#*=} | sed 's/.* UUID="//;s/".*//g')" + ;; + esac + ;; + esac +done + +CONFS=$SYSTEM_ROOT/usr/share/bootloader/extlinux/*.conf + +for all_conf in $CONFS; do + conf="$(basename ${all_conf})" + echo "Updating ${conf}..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/extlinux/${conf} $BOOT_ROOT/extlinux/${conf} &>/dev/null + sed -e "s/@BOOT_UUID@/$BOOT_UUID/" \ + -e "s/@DISK_UUID@/$DISK_UUID/" \ + -i $BOOT_ROOT/extlinux/${conf} +done + +if [ -f $SYSTEM_ROOT/usr/share/bootloader/boot.ini ]; then + echo "Updating boot.ini..." + cp -p $SYSTEM_ROOT/usr/share/bootloader/boot.ini $BOOT_ROOT/boot.ini &>/dev/null +fi + +# update device tree + for all_dtb in $SYSTEM_ROOT/usr/share/bootloader/*.dtb; do + dtb=$(basename $all_dtb) + echo -n "Updating $dtb... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/$dtb $BOOT_ROOT &>/dev/null + echo "done" + done + +# update bootloader + if [ -f $SYSTEM_ROOT/usr/share/bootloader/idbloader.img ]; then + echo -n "Updating idbloader.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/idbloader.img of=$BOOT_DISK bs=32k seek=1 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/uboot.img ]; then + echo -n "Updating uboot.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/uboot.img of=$BOOT_DISK bs=64k seek=128 conv=fsync &>/dev/null + echo "done" + fi + if [ -f $SYSTEM_ROOT/usr/share/bootloader/trust.img ]; then + echo -n "Updating trust.img... " + dd if=$SYSTEM_ROOT/usr/share/bootloader/trust.img of=$BOOT_DISK bs=64k seek=192 conv=fsync &>/dev/null + echo "done" + fi + + if [ -f $SYSTEM_ROOT/usr/share/bootloader/logo.bmp ]; then + echo -n "Updating uboot logo... " + cp -p $SYSTEM_ROOT/usr/share/bootloader/logo.bmp $BOOT_ROOT &>/dev/null + echo "done" + fi + +# mount $BOOT_ROOT r/o + sync + mount -o remount,ro $BOOT_ROOT &>/dev/null + +# Leave a hint that we just did an update +echo "UPDATE" > /storage/.config/boot.hint + +sync diff --git a/projects/Rockchip/devices/RG351V/device.config b/projects/Rockchip/devices/RG351V/device.config new file mode 100644 index 000000000..92ff0c59e --- /dev/null +++ b/projects/Rockchip/devices/RG351V/device.config @@ -0,0 +1,51 @@ +# Device definition file for the Anbernic RG351V + +# Device Features +DEVICE_HAS_FAN=false +DEVICE_FAKE_JACKSENSE=true +DEVICE_VOLUMECTL=true +DEVICE_POWER_LED=true +DEVICE_AUDIO_MIXER="Playback" +DEVICE_VOLUME_DEV="/dev/input/by-path/platform-rg351-keys-event" +DEVICE_CONTROLLER_DEV="/dev/input/event3" +DEVICE_BRIGHTNESS="70" +DISPLAY_ROTATED=false + +# GPIOS +DEVICE_WIFI="5" +DEVICE_LED="77" +DEVICE_PWM_MOTOR="pwmchip0" +#DEVICE_PWM_FAN="" +DEVICE_JACK="/sys/class/gpio/gpio86/value" + +# FREQ governors +CPU_FREQ="/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" +GPU_FREQ="/sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu.gpu/governor" +DMC_FREQ="/sys/devices/platform/dmc/devfreq/dmc/governor" + +# Affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="${SLOW_CORES}" + +# Volume Keys +#DEVICE_KEY_VOLUMEDOWN= +#DEVICE_KEY_VOLUMEUP= + +# Controller +DEVICE_BTN_SOUTH="1" # B +DEVICE_BTN_EAST="0" # A +DEVICE_BTN_NORTH="2" # X +DEVICE_BTN_WEST="3" # Y +DEVICE_BTN_TL="10" +DEVICE_BTN_TR="11" +DEVICE_BTN_TL2="4" +DEVICE_BTN_TR2="5" +DEVICE_BTN_SELECT="7" +DEVICE_BTN_START="6" +DEVICE_BTN_MODE="7" +DEVICE_BTN_THUMBL="8" +DEVICE_BTN_THUMBR="9" +DEVICE_BTN_DPAD_UP="0.1" +DEVICE_BTN_DPAD_DOWN="0.4" +DEVICE_BTN_DPAD_LEFT="0.8" +DEVICE_BTN_DPAD_RIGHT="0.2" diff --git a/projects/Rockchip/devices/RG351V/device.init b/projects/Rockchip/devices/RG351V/device.init new file mode 100644 index 000000000..b8ba1d284 --- /dev/null +++ b/projects/Rockchip/devices/RG351V/device.init @@ -0,0 +1,15 @@ +# Enable GPIO 77 for power LED manipulation +echo ${DEVICE_LED} > /sys/class/gpio/export 2>/dev/null + +# Enable WIFI GPIO for WIFI manipulation +echo ${DEVICE_WIFI} > /sys/class/gpio/export 2>/dev/null + +# Power up the WIFI device +echo out > /sys/class/gpio/gpio${DEVICE_WIFI}/direction 2>/dev/null +echo 1 > /sys/class/gpio/gpio${DEVICE_WIFI}/value 2>/dev/null + +# Enable PWM for rumble and turn rumble off during startup. +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period 2>/dev/null +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle 2>/dev/null diff --git a/projects/Rockchip/devices/RG351V/linux/linux.aarch64.conf b/projects/Rockchip/devices/RG351V/linux/linux.aarch64.conf new file mode 100644 index 000000000..bdf94f86d --- /dev/null +++ b/projects/Rockchip/devices/RG351V/linux/linux.aarch64.conf @@ -0,0 +1,4647 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.4.189 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_SHIFT=4 +CONFIG_NO_IOPORT_MAP=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="@DISTRONAME@" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_PIDS is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_MEMCG is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_INITRD_ASYNC is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_MEMBARRIER=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +CONFIG_PROFILING=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_RK_PARTITION=y +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_EXYNOS7 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_ROCKCHIP_ODROIDGOA=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_DOMAINS_GENERIC is not set +# CONFIG_PCI_SYSCALL is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_MMU_NOTIFIER=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_SECCOMP=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_UAO=y +CONFIG_ARM64_MODULE_CMODEL_LARGE=y +# CONFIG_RANDOMIZE_BASE is not set + +# +# Boot options +# +CONFIG_CMDLINE="" +# CONFIG_EFI is not set +# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_KEYS_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_ROCKCHIP_CPUFREQ=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=y +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_TCP_CONG="reno" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +# CONFIG_NF_TABLES_BRIDGE is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_MRP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_HWMON=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_SOCKET=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_HSR is not set +CONFIG_NET_SWITCHDEV=y +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_6LOWPAN is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_RTKBTUSB=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_QCA is not set +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_MINSTREL_VHT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_LWTUNNEL=y +CONFIG_DST_CACHE=y +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_DEVRES=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set + +# +# Bus devices +# +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND_IDS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_ROCKCHIP_SCR is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_USB_CAM_GPIO is not set +# CONFIG_GPIO_DET is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_EEH is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_TUN_VNET_CROSS_LE=y +CONFIG_VETH=m +CONFIG_NLMON=m + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_ETHERNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_TERANETICS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=m +CONFIG_PPPOPNS=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +# CONFIG_USB_LAN78XX is not set +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +CONFIG_USB_NET_CDC_MBIM=m +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USB_NET_CH9200 is not set +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +# CONFIG_ATH6KL_USB is not set +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_WCN36XX is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +CONFIG_HOSTAP=m +# CONFIG_HOSTAP_FIRMWARE is not set +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_P54_SPI is not set +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8XXXU=m +# CONFIG_RTL8XXXU_UNTESTED is not set +CONFIG_WL_ROCKCHIP=y +CONFIG_WIFI_BUILD_MODULE=y +CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +# CONFIG_AP6XXX is not set +# CONFIG_CYW_BCMDHD is not set +CONFIG_RTL_WIRELESS_SOLUTION=y +CONFIG_RTL8188EU=m +CONFIG_RTL8188FU=m +# CONFIG_RTL8189ES is not set +# CONFIG_RTL8189FS is not set +# CONFIG_RTL8723BS is not set +CONFIG_RTL8723BU=m +# CONFIG_RTL8723CS is not set +# CONFIG_RTL8723DS is not set +# CONFIG_MVL88W8977 is not set + +# +# SouthSV 6XXX WLAN support +# +# CONFIG_SSV6051 is not set +CONFIG_WL_TI=y +CONFIG_WL1251=m +# CONFIG_WL1251_SPI is not set +# CONFIG_WL1251_SDIO is not set +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +# CONFIG_WLCORE_SPI is not set +# CONFIG_WLCORE_SDIO is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_USB=m +CONFIG_CW1200=m +# CONFIG_CW1200_WLAN_SDIO is not set +# CONFIG_CW1200_WLAN_SPI is not set +CONFIG_RSI_91X=m +CONFIG_RSI_DEBUGFS=y +CONFIG_RSI_SDIO=m +CONFIG_RSI_USB=m +CONFIG_RTL8812AU=m +CONFIG_RTL8822BU=m +CONFIG_RTL8821CU=m +CONFIG_ESP8089=m +CONFIG_ESP8089_DEBUG_FS=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_IEEE802154_DRIVERS=m +# CONFIG_IEEE802154_FAKELB is not set +# CONFIG_IEEE802154_AT86RF230 is not set +# CONFIG_IEEE802154_MRF24J40 is not set +# CONFIG_IEEE802154_CC2520 is not set +# CONFIG_IEEE802154_ATUSB is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=m +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_ROCKCHIP=y +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +# CONFIG_JOYSTICK_IFORCE_232 is not set +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_AS5011=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ADC=y +CONFIG_JOYSTICK_ODROIDGO2=y +CONFIG_JOYSTICK_ODROIDGO3=y +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set + +# +# handle all sensors +# +# CONFIG_SENSOR_DEVICE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYCHORD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_RK8XX_PWRKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=m +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_INGENIC is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_ROCKCHIP is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +CONFIG_TCG_TPM=y +# CONFIG_TCG_TIS_I2C_ATMEL is not set +CONFIG_TCG_TIS_I2C_INFINEON=y +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_TIS_ST33ZP24 is not set +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +CONFIG_I2C_RK3X=y +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=m +# CONFIG_SPI_CADENCE is not set +CONFIG_SPI_GPIO=m +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_ROCKCHIP=m +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_RK805=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +CONFIG_GPIO_RK8XX=y + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# SPI or I2C GPIO expanders +# +# CONFIG_GPIO_MCP23S08 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=y +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25700 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_SY6982C is not set +# CONFIG_CHARGER_UNIVERSAL is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_EC is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_RK816 is not set +CONFIG_BATTERY_RK817=y +CONFIG_CHARGER_RK817=y +# CONFIG_BATTERY_RK818 is not set +# CONFIG_CHARGER_RK818 is not set +# CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_POWER_AVS=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_IMX_THERMAL is not set +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_RK_VIRTUAL_THERMAL is not set +# CONFIG_RK3368_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set +CONFIG_MFD_RK808=y +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_RK1000 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_FUSB_30X is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8752 is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8865 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +CONFIG_REGULATOR_RK818=y +# CONFIG_REGULATOR_SYR82X is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS549B22 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_XZ3216 is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_IGNORE_IOTCL_PERMIT=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +# CONFIG_DRM_DP_CEC is not set +# CONFIG_DRM_SCDC_HELPER is not set +CONFIG_DRM_DMA_SYNC=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_VGEM is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_ROCKCHIP_DRM_DEBUG is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_MIPI_CSI_TX is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_LVDS is not set +# CONFIG_ROCKCHIP_DRM_TVE is not set +# CONFIG_ROCKCHIP_RGB is not set +# CONFIG_ROCKCHIP_DRM_BACKLIGHT is not set +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +# CONFIG_DRM_UDL is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_ODROID_ST7701S is not set +CONFIG_DRM_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LONTIUM_LT8912 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_POWERVR_ROGUE_M is not set +# CONFIG_MALI400 is not set +CONFIG_MALI_MIDGARD_FOR_ANDROID=y +# CONFIG_MALI_MIDGARD_FOR_LINUX is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MALI_CORESTACK is not set +CONFIG_MALI_PWRSOFT_765=y +# CONFIG_MALI_KUTF is not set +# CONFIG_MALI_BIFROST_FOR_ANDROID is not set +CONFIG_MALI_BIFROST_FOR_LINUX=y +CONFIG_MALI_BIFROST=y +# CONFIG_MALI_BIFROST_GATOR_SUPPORT is not set +# CONFIG_MALI_BIFROST_ENABLE_TRACE is not set +CONFIG_MALI_BIFROST_DEVFREQ=y +# CONFIG_MALI_BIFROST_DMA_FENCE is not set +CONFIG_MALI_PLATFORM_NAME="rk" +CONFIG_MALI_BIFROST_EXPERT=y +# CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY is not set +# CONFIG_MALI_BIFROST_DEBUG is not set +# CONFIG_MALI_BIFROST_NO_MALI is not set +# CONFIG_MALI_BIFROST_TRACE_TIMELINE is not set +# CONFIG_MALI_BIFROST_SYSTEM_TRACE is not set +# CONFIG_MALI_JOB_DUMP is not set +# CONFIG_MALI_2MB_ALLOC is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set + +# +# Rockchip Misc Video driver +# +# CONFIG_FB_ROCKCHIP is not set +# CONFIG_LCDC_RK3368 is not set +CONFIG_LCD_GENERAL=y +# CONFIG_LCD_MIPI is not set +# CONFIG_RK_TRSM is not set +# CONFIG_RK_HDMI is not set + +# +# RGA +# +# CONFIG_ROCKCHIP_RGA is not set + +# +# RGA2 +# +CONFIG_ROCKCHIP_RGA2=y + +# +# VCODEC +# +CONFIG_RK_VCODEC=y + +# +# IEP +# +# CONFIG_IEP is not set +# CONFIG_IEP_MMU is not set + +# +# DP +# + +# +# ROCKCHIP_MPP +# +CONFIG_ROCKCHIP_MPP_SERVICE=y +CONFIG_ROCKCHIP_MPP_DEVICE=y +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=y +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +CONFIG_SND_SOC_ROCKCHIP=y +# CONFIG_SND_SOC_ROCKCHIP_FORCE_SRAM is not set +CONFIG_SND_SOC_ROCKCHIP_I2S=y +# CONFIG_SND_SOC_ROCKCHIP_I2S_TDM is not set +CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS=y +CONFIG_SND_SOC_ROCKCHIP_PDM=y +# CONFIG_SND_SOC_ROCKCHIP_SPDIF is not set +# CONFIG_SND_SOC_ROCKCHIP_SPDIFRX is not set +# CONFIG_SND_SOC_ROCKCHIP_VAD is not set +# CONFIG_SND_SOC_ROCKCHIP_DA7219 is not set +# CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5651_TC358749 is not set +# CONFIG_SND_SOC_ROCKCHIP_CDNDP is not set + +# +# Allwinner SoC Audio support +# +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set +# CONFIG_SND_SOC_DUMMY_CODEC is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8323 is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_GVA_CODEC is not set +# CONFIG_SND_SOC_FM1288 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK312X is not set +# CONFIG_SND_SOC_RK3228 is not set +# CONFIG_SND_SOC_RK3308 is not set +# CONFIG_SND_SOC_RK3328 is not set +CONFIG_SND_SOC_RK817=y +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5651 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TC358749X is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=y +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_RKVR is not set +# CONFIG_HID_ALPS is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEFAULT_PERSIST is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_DWC2=m +CONFIG_USB_DWC2_HOST=y + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP210X=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +# CONFIG_USB_SERIAL_QCAUX is not set +CONFIG_USB_SERIAL_QUALCOMM=m +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=y +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +# CONFIG_USB_CONFIGFS_SERIAL is not set +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +# CONFIG_USB_CONFIGFS_EEM is not set +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_MTP is not set +# CONFIG_USB_CONFIGFS_F_ACC is not set +# CONFIG_USB_CONFIGFS_UEVENT is not set +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set + +# +# ROCKCHIP USB Support +# +# CONFIG_USB20_HOST is not set +# CONFIG_USB20_OTG is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=y +# CONFIG_MMC_SIMULATE_MAX_SPEED is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_FAKE is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RK808=y +# CONFIG_RTC_DRV_RK_TIMER is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +CONFIG_PL330_DMA=y +# CONFIG_DW_DMAC is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTLLIB is not set +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +CONFIG_R8723AU=m +CONFIG_8723AU_AP_MODE=y +CONFIG_8723AU_BT_COEXIST=y +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7606 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# CONFIG_INV_MPU_IIO is not set + +# +# Light sensors +# +CONFIG_SENSORS_ISL29018=y +# CONFIG_SENSORS_ISL29028 is not set +CONFIG_TSL2583=y +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ASHMEM is not set +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_SYNC is not set +# CONFIG_ION is not set +CONFIG_FIQ_DEBUGGER=y +CONFIG_FIQ_DEBUGGER_NO_SLEEP=y +# CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON is not set +CONFIG_FIQ_DEBUGGER_CONSOLE=y +CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y +# CONFIG_FIQ_DEBUGGER_TRUST_ZONE is not set +# CONFIG_FIQ_DEBUGGER_UART_OVERLAY is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_RK_CONSOLE_THREAD is not set +# CONFIG_STAGING_BOARD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_WILC1000_DRIVER is not set +# CONFIG_MOST is not set +# CONFIG_POWERVR_ROGUE_N is not set + +# +# Qualcomm Atheros CLD WLAN module +# +# CONFIG_QCA_CLD_WLAN is not set +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_VERSATILE is not set +CONFIG_COMMON_CLK_RK808=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# +# CONFIG_HWSPINLOCK_ROCKCHIP is not set + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_IOVA=y +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_ROCKCHIP_IOMMU=y +# CONFIG_RK_IOMMU is not set +# CONFIG_ARM_SMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# + +# +# Rockchip CPU selection +# +CONFIG_CPU_PX30=y +# CONFIG_CPU_RK1808 is not set +# CONFIG_CPU_RK3308 is not set +CONFIG_CPU_RK3328=y +# CONFIG_CPU_RK3366 is not set +CONFIG_CPU_RK3368=y +CONFIG_CPU_RK3399=y +CONFIG_ANDROID_VERSION=0x07010000 +CONFIG_ROCKCHIP_CPUINFO=y +# CONFIG_ROCKCHIP_DEVICEINFO is not set +CONFIG_ROCKCHIP_IPA=y +CONFIG_ROCKCHIP_OPP=y +# CONFIG_ROCKCHIP_PM_TEST is not set +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +CONFIG_ROCKCHIP_PVTM=y +CONFIG_ROCKCHIP_SUSPEND_MODE=y +CONFIG_ROCKCHIP_SYSTEM_MONITOR=y +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y + +# +# DEVFREQ Drivers +# +# CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_BUFFER_CB is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MXC4005 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD799X is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_GPIO_MUXADC is not set +# CONFIG_HI8435 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +CONFIG_ROCKCHIP_SARADC=y +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_VF610_ADC is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Chemical Sensors +# +# CONFIG_VZ89X is not set + +# +# Hid Sensor IIO Common +# + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set +# CONFIG_HDC100X is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9960 is not set +# CONFIG_BH1750 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_ISL29125 is not set +# CONFIG_JSA1212 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR501 is not set +# CONFIG_OPT3001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_STK3310 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +CONFIG_SENSORS_TSL2563=y +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VL6180 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_MAG3110 is not set +# CONFIG_MMC35240 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +CONFIG_IIO_SYSFS_TRIGGER=y + +# +# Digital potentiometers +# +# CONFIG_MCP4531 is not set + +# +# Pressure sensors +# +# CONFIG_BMP280 is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set + +# +# Proximity sensors +# +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set + +# +# Temperature sensors +# +# CONFIG_MLX90614 is not set +# CONFIG_TMP006 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_ROCKCHIP=y +# CONFIG_PWM_ROCKCHIP_I2S is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V3=y +CONFIG_PARTITION_PERCPU=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_XGENE is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PHY_ROCKCHIP_INNO_COMBPHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_INNO_USB3 is not set +# CONFIG_PHY_ROCKCHIP_EMMC is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_INNO_MIPI_DPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI_PHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_VIDEO_PHY is not set +CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y +# CONFIG_PHY_ROCKCHIP_TYPEC is not set +# CONFIG_PHY_ROCKCHIP_PCIE is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_RAS=y + +# +# Android +# +CONFIG_ANDROID=y +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_LIBNVDIMM is not set +CONFIG_NVMEM=y +# CONFIG_ROCKCHIP_EFUSE is not set +CONFIG_ROCKCHIP_OTP=y +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set + +# +# FPGA Configuration Support +# +# CONFIG_FPGA is not set +# CONFIG_TEE is not set +CONFIG_RK_FLASH=y + +# +# Rockchip Flash Devices +# +# CONFIG_RK_NANDC_NAND is not set +CONFIG_RK_SFC_NAND=y +CONFIG_RK_SFC_NOR=y +CONFIG_RK_SFC_NOR_MTD=y +# CONFIG_RK_NAND is not set + +# +# Headset device support +# +# CONFIG_RK_HEADSET is not set + +# +# Gator module for ARM streamline +# + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_ROCKCHIP_SIP=y + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_FS_DAX is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +CONFIG_OVERLAY_FS=y + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +# CONFIG_CACHEFILES is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_VIRTUAL_XATTR=y +CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:exfat:s0" +# CONFIG_EXFAT_DEBUG is not set +# CONFIG_EXFAT_UEVENT is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_UID=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_SDCARD_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +CONFIG_SQUASHFS_LZO=y +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +# CONFIG_PSTORE_PMSG is not set +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +CONFIG_HAVE_KVM_IRQFD=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_ARM_VGIC_V3=y +CONFIG_KVM=y +CONFIG_KVM_ARM_HOST=y +CONFIG_VHOST_NET=m +CONFIG_VHOST=m +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_PROCESS is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_KASAN is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y +CONFIG_HARDLOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_CREDENTIALS=y + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_GPU_TRACEPOINTS=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_TEE_SUPPORT is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_HEH is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V2 is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +# CONFIG_CRYPTO_POLY_HASH_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_CRC32_ARM64 is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_CLZ_TAB=y +CONFIG_CORDIC=m +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_SG_SPLIT is not set +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/projects/Rockchip/devices/RG351V/options b/projects/Rockchip/devices/RG351V/options new file mode 100644 index 000000000..81858c4f9 --- /dev/null +++ b/projects/Rockchip/devices/RG351V/options @@ -0,0 +1,227 @@ +################################################################################ +# setup device defaults +################################################################################ + + # The TARGET_CPU variable controls which processor should be targeted for + # generated code. + case $TARGET_ARCH in + aarch64) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc+fp+simd" + TARGET_FPU="fp-armv8" + TARGET_FEATURES="64bit" + ;; + arm) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_FLOAT="hard" + TARGET_CPU="cortex-a35" + TARGET_CPU_FLAGS="+crc" + TARGET_FPU="crypto-neon-fp-armv8" + TARGET_FEATURES="32bit" + ;; + esac + + # Kernel target + KERNEL_TARGET="Image" + + # Additional kernel make parameters (for example to specify the u-boot loadaddress) + KERNEL_MAKE_EXTRACMD="" + KERNEL_MAKE_EXTRACMD+=" rockchip/rk3326-rg351v-linux.dtb" + KERNEL_MAKE_EXTRACMD+=" rockchip/rk3326-rg351v-linux-oc.dtb" + + # Mali GPU family + MALI_FAMILY="g31" + OPENGLES="libmali" + + # Define the CPU + HW_CPU="Rockchip RK3326" + + # kernel serial console + EXTRA_CMDLINE="console=ttyFIQ0 console=tty0 net.iframes=0 fbcon=rotate:0 ssh consoleblank=0 systemd.show_status=0 loglevel=0 panic=20" + + LINUX="RG351V" + UBOOT_SYSTEM="rg351v" + + # additional packages to install + ADDITIONAL_PACKAGES="dtc jelos" + + # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware) + # Space separated list is supported, + # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware" + FIRMWARE="misc-firmware wlan-firmware" #rockchip-firmware + + # additional drivers to install: + # for a list of additional drivers see packages/linux-drivers + # Space separated list is supported, + # e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2" + ADDITIONAL_DRIVERS="RTL8812AU" #RTL8188EU RTL8814AU RTL8192DU RTL8812AU RTL8821CU RTL8192CU RTL8192EU + + # build and install driver addons (yes / no) + DRIVER_ADDONS_SUPPORT="no" + + # driver addons to install: + # for a list of additinoal drivers see packages/linux-driver-addons + # Space separated list is supported, + DRIVER_ADDONS="" #dvb-latest + + # debug tty path + DEBUG_TTY="/dev/ttyFIQ0" + + + # Skins to install (Estuary) + # Space separated list is supported, + # e.g. SKINS="Estuary" + SKINS="Estuary" + + # Default Skin (Estuary) + SKIN_DEFAULT="Estuary" + + # Select whether to use default (upstream xbmc/xbmc) repo, or specific vendor repo + KODI_VENDOR="default" + + # install extra subtitle Fonts for KODI (yes / no) + KODI_EXTRA_FONTS="yes" + + # build and install PulseAudio support (yes / no) + PULSEAUDIO_SUPPORT="yes" + + # build and install espeak support (yes / no) + ESPEAK_SUPPORT="no" + + # build and install with BluRay support (yes / no) + KODI_BLURAY_SUPPORT="no" + + # build and install with BD+ support + # (BD+ decryption support in KODI) (yes / no) + BLURAY_BDPLUS_SUPPORT="no" + + # build and install with AACS support + # (BD decryption support in KODI) (yes / no) + BLURAY_AACS_SUPPORT="no" + + # build and install with DVDCSS support + # (DVD decryption support in KODI) (yes / no) + KODI_DVDCSS_SUPPORT="no" + + # build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="no" + + # build and install with KODI webfrontend (yes / no) + KODI_WEBSERVER_SUPPORT="no" + + # build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="no" + + # build with UPnP support (yes / no) + KODI_UPNP_SUPPORT="no" + + # build with MySQL support (mysql / mariadb / none) + KODI_MYSQL_SUPPORT="none" + + # build xbmc with optical drive support (yes / no) + KODI_OPTICAL_SUPPORT="no" + + # build with AirPlay support (stream videos from iDevices to KODI) (yes / no) + KODI_AIRPLAY_SUPPORT="no" + + # build with AirTunes support (stream music from iDevices to KODI) (yes / no) + KODI_AIRTUNES_SUPPORT="no" + + # build with libnfs support (mounting nfs shares with KODI) (yes / no) + KODI_NFS_SUPPORT="no" + + # build with Samba Client support (mounting SAMBA shares with KODI) (yes / no) + KODI_SAMBA_SUPPORT="no" + + # build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="no" + + # build with Samba Client support (mounting samba shares via the OS) (yes / no) + SAMBA_SUPPORT="no" + + # build and install Samba Server (yes / no) + SAMBA_SERVER="yes" + + # build and install SFTP Server (yes / no) + SFTP_SERVER="yes" + + # build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + + # build and install diskmounter support (udevil) + # this service provide auto mounting support for external drives in the + # mediacenter also automount internally drives at boottime via udev (yes / no) + UDEVIL="yes" + + # build and install exFAT fuse support (yes / no) + EXFAT="yes" + + # build and install NTFS-3G fuse support (yes / no) + NTFS3G="no" + + # build and install hfs filesystem utilities (yes / no) + HFSTOOLS="no" + + # build and install remote support (yes / no) + REMOTE_SUPPORT="no" + + # build and install CEC adapter support (yes / no) + CEC_SUPPORT="no" + + # build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="no" + + # build and install iSCSI support - iscsistart (yes / no) + ISCSI_SUPPORT="no" + + # Support for partitioning and formating disks in initramfs (yes / no) + # This adds support for parted and mkfs.ext3/4 to initramfs for OEM usage + INITRAMFS_PARTED_SUPPORT="no" + + # build with swap support (yes / no) + SWAP_SUPPORT="yes" + + # swap support enabled per default (yes / no) + SWAP_ENABLED_DEFAULT="yes" + + # swapfile size if SWAP_SUPPORT=yes in MB + SWAPFILESIZE="384" + + # cron support (yes / no) + CRON_SUPPORT="no" + + # Distribution Specific source location + #DISTRO_MIRROR="http://sources.libreelec.tv/mirror" + #DISTRO_SRC="http://sources.libreelec.tv/$LIBREELEC_VERSION" + + # Addon Server Url + ADDON_SERVER_URL="" + + # Addon ID of the default addon repository + ADDON_REPO_ID="" + + # Name of the default addon repository + ADDON_REPO_NAME="" + + # Version of the default addon repository + ADDON_REPO_VERSION="" + + # set the addon dirs + ADDON_PATH="" + ADDON_URL="" + + # Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + + # IR remote protocols supported in default config + IR_REMOTE_PROTOCOLS="" + + # IR remote keymaps supported in default config + IR_REMOTE_KEYMAPS="" + + # htop tool (yes / no) + HTOP_TOOL="yes" diff --git a/projects/Rockchip/devices/RG552/device.config b/projects/Rockchip/devices/RG552/device.config new file mode 100644 index 000000000..efeadb766 --- /dev/null +++ b/projects/Rockchip/devices/RG552/device.config @@ -0,0 +1,49 @@ +# Device definition file for the Anbernic RG552 + +# Device Features +DEVICE_HAS_FAN=true +DEVICE_FAKE_JACKSENSE=false +DEVICE_VOLUMECTL=true +DEVICE_AUDIO_MIXER="Master" +DEVICE_VOLUME_DEV="/dev/input/by-path/platform-volume-keys-event" +DEVICE_CONTROLLER_DEV="/dev/input/by-path/platform-singleadc-joypad-event-joystick" +DEVICE_BRIGHTNESS="50" +DISPLAY_ROTATED=true + +# GPIOS +DEVICE_WIFI="113" +DEVICE_PWM_MOTOR="pwmchip3" +DEVICE_PWM_FAN="/sys/class/hwmon/hwmon0/pwm1" +#DEVICE_JACK="" + +# FREQ governors +CPU_FREQ="/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" +GPU_FREQ="/sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/governor" +DMC_FREQ="/sys/devices/platform/dmc/devfreq/dmc/governor" + +# Affinity +SLOW_CORES="taskset -c 0-3" +FAST_CORES="taskset -c 4-5" + +# Volume Keys +#DEVICE_KEY_VOLUMEDOWN= +#DEVICE_KEY_VOLUMEUP= + +# Controller +DEVICE_BTN_SOUTH="0" # B +DEVICE_BTN_EAST="1" # A +DEVICE_BTN_NORTH="2" # X +DEVICE_BTN_WEST="3" # Y +DEVICE_BTN_TL="4" +DEVICE_BTN_TR="5" +DEVICE_BTN_TL2="6" +DEVICE_BTN_TR2="7" +DEVICE_BTN_SELECT="8" +DEVICE_BTN_START="9" +DEVICE_BTN_MODE="10" +DEVICE_BTN_THUMBL="11" +DEVICE_BTN_THUMBR="12" +DEVICE_BTN_DPAD_UP="13" +DEVICE_BTN_DPAD_DOWN="14" +DEVICE_BTN_DPAD_LEFT="15" +DEVICE_BTN_DPAD_RIGHT="16" diff --git a/projects/Rockchip/devices/RG552/device.init b/projects/Rockchip/devices/RG552/device.init new file mode 100644 index 000000000..0c057ef6d --- /dev/null +++ b/projects/Rockchip/devices/RG552/device.init @@ -0,0 +1,10 @@ +# Silence PWM +echo 0 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/export 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/period 2>/dev/null +echo 1 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/enable 2>/dev/null +echo 1000000 > /sys/class/pwm/${DEVICE_PWM_MOTOR}/pwm0/duty_cycle 2>/dev/null +# Enable WIFI +echo ${DEVICE_WIFI} > /sys/class/gpio/export 2>/dev/null +echo out > /sys/class/gpio/gpio${DEVICE_WIFI}/direction 2>/dev/null +echo 1 > /sys/class/gpio/gpio${DEVICE_WIFI}/value 2>/dev/null +fbset -g 1152 1920 1152 1920 32 2>/dev/null diff --git a/projects/Rockchip/devices/RG552/linux/linux.aarch64.conf b/projects/Rockchip/devices/RG552/linux/linux.aarch64.conf new file mode 100644 index 000000000..64d1f384b --- /dev/null +++ b/projects/Rockchip/devices/RG552/linux/linux.aarch64.conf @@ -0,0 +1,6246 @@ +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_SHIFT=4 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="@DISTRONAME@" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_SCHED_WALT is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_PIDS is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_PAGE_COUNTER=y +CONFIG_MEMCG=y +# CONFIG_MEMCG_SWAP is not set +# CONFIG_MEMCG_KMEM is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_TUNE is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_INITRD_ASYNC is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_PCI_QUIRKS=y +CONFIG_MEMBARRIER=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_SYSFS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_RK_PARTITION=y +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_EXYNOS7 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +CONFIG_ARCH_ROCKCHIP=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_DEBUG=y +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_LABEL=y + +# +# PCI host controller drivers +# +# CONFIG_PCIE_DW_ROCKCHIP is not set +# CONFIG_ROCKCHIP_PCIE_DMA_OBJ is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCIE_IPROC is not set +# CONFIG_PCI_HISI is not set +CONFIG_PCIE_ROCKCHIP=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_POWERSAVE=y +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=6 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_MMU_NOTIFIER=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +CONFIG_FRONTSWAP=y +# CONFIG_CMA is not set +CONFIG_ZSWAP=y +CONFIG_ZPOOL=y +CONFIG_ZBUD=y +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_FRAME_VECTOR=y +CONFIG_SECCOMP=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_UAO=y +CONFIG_ARM64_MODULE_CMODEL_LARGE=y +# CONFIG_RANDOMIZE_BASE is not set + +# +# Boot options +# +# CONFIG_ARM64_ACPI_PARKING_PROTOCOL is not set +CONFIG_CMDLINE="" +# CONFIG_EFI is not set +# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_KEYS_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=100 +CONFIG_PM_WAKELOCKS_GC=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_WAKE_BOOST=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPU_FREQ_TIMES=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ12 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ13 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ14 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ15 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ18 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ20 is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_MRFIXEDFREQ22 is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ12 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ13 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ14 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ15 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ18 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ20 is not set +# CONFIG_CPU_FREQ_GOV_MRFIXEDFREQ22 is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_ROCKCHIP_CPUFREQ=y +# CONFIG_ACPI_CPPC_CPUFREQ is not set +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_UDP_TUNNEL=m +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_TCP_CONG="reno" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_ANDROID_PARANOID_NETWORK is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=y +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +# CONFIG_IP_VS_FTP is not set +CONFIG_IP_VS_NFCT=y +# CONFIG_IP_VS_PE_SIP is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_LOG_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_HAVE_NET_DSA=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +CONFIG_NET_SCH_CODEL=y +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_CLS_CGROUP=y +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=m +CONFIG_OPENVSWITCH_VXLAN=m +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=m +# CONFIG_MPLS_ROUTING is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +CONFIG_CAN=y +CONFIG_CAN_RAW=y +CONFIG_CAN_BCM=y +CONFIG_CAN_GW=y + +# +# CAN Device Drivers +# +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_SLCAN is not set +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +# CONFIG_CAN_GRCAN is not set +# CONFIG_CAN_XILINXCAN is not set +CONFIG_CAN_SJA1000=y +# CONFIG_CAN_SJA1000_ISA is not set +# CONFIG_CAN_SJA1000_PLATFORM is not set +# CONFIG_CAN_EMS_PCMCIA is not set +# CONFIG_CAN_EMS_PCI is not set +# CONFIG_CAN_PEAK_PCMCIA is not set +# CONFIG_CAN_PEAK_PCI is not set +# CONFIG_CAN_KVASER_PCI is not set +CONFIG_CAN_PLX_PCI=y +# CONFIG_CAN_C_CAN is not set +# CONFIG_CAN_M_CAN is not set +# CONFIG_CAN_CC770 is not set + +# +# CAN SPI interfaces +# +# CONFIG_CAN_MCP251X is not set + +# +# CAN USB interfaces +# +# CONFIG_CAN_EMS_USB is not set +# CONFIG_CAN_ESD_USB2 is not set +# CONFIG_CAN_GS_USB is not set +# CONFIG_CAN_KVASER_USB is not set +# CONFIG_CAN_PEAK_USB is not set +# CONFIG_CAN_8DEV_USB is not set +# CONFIG_CAN_SOFTING is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=y +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=y +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=y +CONFIG_BT_BCM=y +CONFIG_BT_RTL=y +CONFIG_BT_RTKBTUSB=y +CONFIG_BT_HCIBTUSB=y +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_BCSP is not set +CONFIG_BT_HCIUART_ATH3K=y +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_QCA is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +CONFIG_BT_HCIBFUSB=y +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBTUART is not set +CONFIG_BT_HCIVHCI=y +CONFIG_BT_MRVL=y +CONFIG_BT_MRVL_SDIO=y +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_BCM4359 is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_MINSTREL_VHT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_MESSAGE_TRACING is not set +CONFIG_MAC80211_DEBUG_MENU=y +# CONFIG_MAC80211_NOINLINE is not set +CONFIG_MAC80211_VERBOSE_DEBUG=y +# CONFIG_MAC80211_MLME_DEBUG is not set +# CONFIG_MAC80211_STA_DEBUG is not set +# CONFIG_MAC80211_HT_DEBUG is not set +# CONFIG_MAC80211_OCB_DEBUG is not set +# CONFIG_MAC80211_IBSS_DEBUG is not set +# CONFIG_MAC80211_PS_DEBUG is not set +# CONFIG_MAC80211_TDLS_DEBUG is not set +# CONFIG_MAC80211_DEBUG_COUNTERS is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set +# CONFIG_NFC is not set +CONFIG_LWTUNNEL=y +CONFIG_DST_CACHE=y +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_DEVRES=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set + +# +# Bus devices +# +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_CONFIGFS=y +# CONFIG_PARPORT is not set +CONFIG_PCCARD=y +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +# CONFIG_YENTA is not set +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set +CONFIG_PCMCIA_PLX9052=y +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_DRBD=m +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_BLK_DEV_RBD=m +# CONFIG_BLK_DEV_RSXX is not set +CONFIG_BLK_DEV_NVME=m + +# +# Misc devices +# +CONFIG_ROCKCHIP_SCR=y +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +# CONFIG_MEMORY_STATE_TIME is not set +# CONFIG_USB_CAM_GPIO is not set +# CONFIG_GPIO_DET is not set +CONFIG_ROCKPI_MCU=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=y +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_EEH is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=m +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT3SAS=m +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +CONFIG_SCSI_MPT3SAS_MAX_SGE=128 +CONFIG_SCSI_MPT2SAS=m +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +# CONFIG_SATA_ZPODD is not set +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y +# CONFIG_AHCI_CEVA is not set +# CONFIG_AHCI_QORIQ is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SIL=m +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_PCMCIA is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_ACPI is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_MQ_DEFAULT is not set +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +CONFIG_DM_RAID=y +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +CONFIG_MACVLAN=y +# CONFIG_MACVTAP is not set +CONFIG_IPVLAN=y +CONFIG_VXLAN=m +# CONFIG_GENEVE is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=m +# CONFIG_TUN_VNET_CROSS_LE is not set +CONFIG_VETH=y +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +CONFIG_ETHERNET=y +CONFIG_MDIO=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_ALTERA_TSE is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_AURORA is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_EXAR is not set +CONFIG_NET_VENDOR_FUJITSU=y +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=y +CONFIG_E1000=y +CONFIG_E1000E=y +CONFIG_IGB=y +CONFIG_IGB_HWMON=y +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +CONFIG_IXGBE=y +CONFIG_IXGBE_HWMON=y +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_JME is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_FEALNX is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_SFC is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y +CONFIG_DWMAC_GENERIC=y +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LPC18XX is not set +# CONFIG_DWMAC_MESON is not set +CONFIG_DWMAC_ROCKCHIP=y +# CONFIG_DWMAC_RK_AUTO_DELAYLINE is not set +# CONFIG_DWMAC_SOCFPGA is not set +# CONFIG_DWMAC_STI is not set +# CONFIG_DWMAC_SUNXI is not set +# CONFIG_STMMAC_PCI is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_NET_VENDOR_XIRCOM=y +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_NET_SB1000 is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_TERANETICS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_FILTER is not set +# CONFIG_PPP_MPPE is not set +# CONFIG_PPP_MULTILINK is not set +CONFIG_PPPOE=m +# CONFIG_PPTP is not set +CONFIG_PPPOLAC=m +CONFIG_PPPOPNS=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +CONFIG_USB_RTL8150=y +CONFIG_USB_RTL8152=y +# CONFIG_USB_LAN78XX is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_AX88179_178A=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +CONFIG_USB_NET_CDC_MBIM=y +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +CONFIG_USB_NET_RNDIS_HOST=y +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USB_NET_CH9200 is not set +CONFIG_WLAN=y +# CONFIG_PCMCIA_RAYCS is not set +CONFIG_LIBERTAS_THINFIRM=y +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +# CONFIG_LIBERTAS_THINFIRM_USB is not set +# CONFIG_ATMEL is not set +CONFIG_AT76C50X_USB=y +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_NET_RNDIS_WLAN=y +# CONFIG_ADM8211 is not set +CONFIG_RTL8180=m +CONFIG_RTL8187=y +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_MWL8K is not set +CONFIG_ATH_COMMON=y +CONFIG_ATH_CARDS=y +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH5K=y +# CONFIG_ATH5K_DEBUG is not set +# CONFIG_ATH5K_TRACER is not set +CONFIG_ATH5K_PCI=y +CONFIG_ATH9K_HW=y +CONFIG_ATH9K_COMMON=y +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=y +CONFIG_ATH9K_PCI=y +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +# CONFIG_ATH9K_HTC is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=y +# CONFIG_ATH6KL_SDIO is not set +CONFIG_ATH6KL_USB=y +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_ATH6KL_TRACING is not set +CONFIG_AR5523=y +# CONFIG_WIL6210 is not set +CONFIG_ATH10K=y +# CONFIG_ATH10K_PCI is not set +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_ATH10K_TRACING is not set +CONFIG_WCN36XX=y +# CONFIG_WCN36XX_DEBUGFS is not set +CONFIG_B43=y +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +# CONFIG_B43_SDIO is not set +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=y +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=y +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_PROTO_MSGBUF=y +# CONFIG_BRCMFMAC_SDIO is not set +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +CONFIG_LIBERTAS=y +CONFIG_LIBERTAS_USB=y +# CONFIG_LIBERTAS_CS is not set +# CONFIG_LIBERTAS_SDIO is not set +# CONFIG_LIBERTAS_SPI is not set +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +# CONFIG_HERMES is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=y +# CONFIG_RT2400PCI is not set +# CONFIG_RT2500PCI is not set +# CONFIG_RT61PCI is not set +# CONFIG_RT2800PCI is not set +CONFIG_RT2500USB=y +CONFIG_RT73USB=y +CONFIG_RT2800USB=y +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=y +CONFIG_RT2X00_LIB_USB=y +CONFIG_RT2X00_LIB=y +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=y +CONFIG_RTL_CARDS=y +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_PCI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8723_COMMON=m +CONFIG_RTLBTCOEXIST=m +CONFIG_RTL8XXXU=y +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_WL_ROCKCHIP=y +# CONFIG_WIFI_BUILD_MODULE is not set +CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +CONFIG_AP6XXX=y +# CONFIG_BCMDHD is not set +# CONFIG_ESP8089 is not set +CONFIG_RTL_WIRELESS_SOLUTION=y +CONFIG_RTL8188EU=m +CONFIG_RTL8188FU=y +CONFIG_RTL8189ES=m +CONFIG_RTL8189FS=m +CONFIG_RTL8192DU=m +CONFIG_RTL8723AU=m +CONFIG_RTL8723BS=m +# CONFIG_RTL8723BS_VQ0 is not set +CONFIG_RTL8723BU=m +CONFIG_RTL8723CS=m +CONFIG_RTL8723DS=m +CONFIG_RTL8812AU=m +CONFIG_RTL8822BE=m +CONFIG_MVL88W8977=m + +# +# SouthSV 6XXX WLAN support +# +# CONFIG_SSV6051 is not set +# CONFIG_WL_TI is not set +CONFIG_ZD1211RW=y +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=y +CONFIG_MWIFIEX_SDIO=y +# CONFIG_MWIFIEX_PCIE is not set +CONFIG_MWIFIEX_USB=y +# CONFIG_CW1200 is not set +# CONFIG_RSI_91X is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_FUJITSU_ES is not set +# CONFIG_LTE is not set +CONFIG_ISDN=y +CONFIG_ISDN_I4L=y +# CONFIG_ISDN_PPP is not set +# CONFIG_ISDN_AUDIO is not set + +# +# ISDN feature submodules +# +# CONFIG_ISDN_DIVERSION is not set + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=y + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_DEBUG=y + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=y +CONFIG_HISAX_ELSA_CS=y +CONFIG_HISAX_AVM_A1_CS=y +CONFIG_HISAX_TELES_CS=y + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=y +CONFIG_HISAX_HFCUSB=y +CONFIG_HISAX_HFC4S8S=y +CONFIG_HISAX_FRITZ_PCIPNP=y + +# +# Active cards +# +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_DRV_GIGASET is not set + +# +# Passive cards +# + +# +# D-channel protocol features +# + +# +# HiSax supported cards +# + +# +# HiSax PCMCIA card service modules +# + +# +# HiSax sub driver modules +# +# CONFIG_HYSDN is not set +# CONFIG_MISDN is not set +CONFIG_ISDN_HDLC=y +CONFIG_NVM=y +# CONFIG_NVM_DEBUG is not set +# CONFIG_NVM_GENNVM is not set +# CONFIG_NVM_RRPC is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADC=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_ROCKCHIP=y +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_KEYBOARD_CROS_EC=y +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +CONFIG_MOUSE_CYAPA=y +CONFIG_MOUSE_ELAN_I2C=y +CONFIG_MOUSE_ELAN_I2C_I2C=y +# CONFIG_MOUSE_ELAN_I2C_SMBUS is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=y +CONFIG_JOYSTICK_A3D=y +CONFIG_JOYSTICK_ADI=y +CONFIG_JOYSTICK_COBRA=y +CONFIG_JOYSTICK_GF2K=y +CONFIG_JOYSTICK_GRIP=y +CONFIG_JOYSTICK_GRIP_MP=y +CONFIG_JOYSTICK_GUILLEMOT=y +CONFIG_JOYSTICK_INTERACT=y +CONFIG_JOYSTICK_SIDEWINDER=y +CONFIG_JOYSTICK_TMDC=y +CONFIG_JOYSTICK_IFORCE=y +CONFIG_JOYSTICK_IFORCE_USB=y +# CONFIG_JOYSTICK_IFORCE_232 is not set +CONFIG_JOYSTICK_WARRIOR=y +CONFIG_JOYSTICK_MAGELLAN=y +CONFIG_JOYSTICK_SPACEORB=y +CONFIG_JOYSTICK_SPACEBALL=y +CONFIG_JOYSTICK_STINGER=y +CONFIG_JOYSTICK_TWIDJOY=y +CONFIG_JOYSTICK_ZHENHUA=y +CONFIG_JOYSTICK_AS5011=y +CONFIG_JOYSTICK_JOYDUMP=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +# CONFIG_JOYSTICK_XPAD_LEDS is not set +CONFIG_JOYSTICK_SINGLEADCJOY=y +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_GTCO is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CY8C40XX is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FT6236 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GSLX6801 is not set +# CONFIG_TOUCHSCREEN_GSLX680A is not set +# CONFIG_TOUCHSCREEN_GSLX680_D708 is not set +# CONFIG_TOUCHSCREEN_GSLX680_PAD is not set +# CONFIG_TOUCHSCREEN_GSLX680_VR is not set +# CONFIG_TOUCHSCREEN_GSLX680_FIREFLY is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set +# CONFIG_TOUCHSCREEN_GT9XX is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +CONFIG_TOUCHSCREEN_USB_COMPOSITE=y +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_VTL_CT36X is not set +# CONFIG_TOUCHSCREEN_GT1X is not set +# CONFIG_TOUCHSCREEN_ROCKPI_FT5406 is not set +# CONFIG_TOUCHSCREEN_CST1XXX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_TS is not set +CONFIG_ROCKCHIP_REMOTECTL=y +CONFIG_ROCKCHIP_REMOTECTL_PWM=y + +# +# handle all sensors +# +CONFIG_SENSOR_DEVICE=y +# CONFIG_ANGLE_DEVICE is not set +CONFIG_GSENSOR_DEVICE=y +CONFIG_GS_MMA8452=y +# CONFIG_STK8BAXX_ACC is not set +CONFIG_MPU6880_ACC=y +CONFIG_MPU6500_ACC=y +# CONFIG_GS_KXTIK is not set +# CONFIG_GS_KXTJ9 is not set +CONFIG_GS_LIS3DH=y +CONFIG_GS_MMA7660=y +# CONFIG_GS_MC3230 is not set +# CONFIG_GS_MXC6225 is not set +# CONFIG_GS_DMT10 is not set +CONFIG_GS_LSM303D=y +# CONFIG_GS_BMA023 is not set +CONFIG_LSM330_ACC=y +# CONFIG_BMA2XX_ACC is not set +CONFIG_COMPASS_DEVICE=y +CONFIG_COMPASS_AK8975=y +CONFIG_COMPASS_AK8963=y +# CONFIG_COMPASS_AK09911 is not set +# CONFIG_COMPASS_MMC328X is not set +CONFIG_GYROSCOPE_DEVICE=y +CONFIG_GYRO_L3G4200D=y +# CONFIG_GYRO_K3G is not set +CONFIG_GYRO_L3G20D=y +CONFIG_GYRO_EWTSA=y +# CONFIG_GYRO_MPU6500 is not set +CONFIG_GYRO_MPU6880=y +CONFIG_GYRO_LSM330=y +CONFIG_LIGHT_DEVICE=y +CONFIG_LS_CM3217=y +CONFIG_LS_CM3218=y +# CONFIG_LS_CM3232 is not set +# CONFIG_LS_AL3006 is not set +# CONFIG_LS_STK3171 is not set +# CONFIG_LS_ISL29023 is not set +# CONFIG_LS_AP321XX is not set +# CONFIG_LS_US5152 is not set +# CONFIG_LS_STK3410 is not set +# CONFIG_PROXIMITY_DEVICE is not set +# CONFIG_TEMPERATURE_DEVICE is not set +# CONFIG_PRESSURE_DEVICE is not set +CONFIG_HALL_DEVICE=y +# CONFIG_HS_OCH165T is not set +CONFIG_HS_MH248=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYCHORD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_RK8XX_PWRKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=y +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_FM801 is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_CS is not set +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_FINTEK is not set +# CONFIG_SERIAL_8250_INGENIC is not set +# CONFIG_SERIAL_8250_MID is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_SERIAL_DEV_BUS is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_ROCKCHIP is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +CONFIG_TCG_TPM=y +# CONFIG_TCG_TIS_I2C_ATMEL is not set +CONFIG_TCG_TIS_I2C_INFINEON=y +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_ATMEL is not set +# CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_TIS_ST33ZP24 is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# ACPI drivers +# +# CONFIG_I2C_SCMI is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +CONFIG_I2C_RK3X=y +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_CROS_EC_TUNNEL=y +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_ROCKCHIP=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_RK805=y +# CONFIG_PINCTRL_BAYTRAIL is not set +# CONFIG_PINCTRL_CHERRYVIEW is not set +# CONFIG_PINCTRL_BROXTON is not set +# CONFIG_PINCTRL_SUNRISEPOINT is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIO_ACPI=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_AMDPT is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +CONFIG_GPIO_RK8XX=y +# CONFIG_GPIO_TPS6586X is not set + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# SPI or I2C GPIO expanders +# +# CONFIG_GPIO_MCP23S08 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +CONFIG_BATTERY_SBS=y +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=y +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +CONFIG_CHARGER_BQ24735=y +# CONFIG_CHARGER_BQ25700 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_SY6982C is not set +CONFIG_CHARGER_UNIVERSAL=y +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_EC is not set +# CONFIG_BATTERY_CW2015 is not set +CONFIG_CW2015_FUEL_GAUGE=y +# CONFIG_BATTERY_RK816 is not set +CONFIG_BATTERY_RK817=y +CONFIG_CHARGER_RK817=y +# CONFIG_BATTERY_RK818 is not set +# CONFIG_CHARGER_RK818 is not set +# CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_POWER_AVS=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +CONFIG_SENSORS_PWM_FAN=y +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_IMX_THERMAL is not set +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_RK_VIRTUAL_THERMAL is not set +# CONFIG_RK3368_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +CONFIG_DW_WATCHDOG=y +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_BCM7038_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=y +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_SDIOHOST_POSSIBLE=y +# CONFIG_SSB_SDIOHOST is not set +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +# CONFIG_SSB_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_PCI=y +# CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMA_DRIVER_PCI=y +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +CONFIG_MFD_CROS_EC=y +# CONFIG_MFD_CROS_EC_I2C is not set +CONFIG_MFD_CROS_EC_SPI=y +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set +CONFIG_MFD_RK808=y +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +CONFIG_MFD_TPS6586X=y +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_RK1000 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +CONFIG_FUSB_30X=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_REGULATOR_ACT8865=y +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +CONFIG_REGULATOR_LP8752=y +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +CONFIG_REGULATOR_MP8865=y +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +CONFIG_REGULATOR_RK818=y +# CONFIG_REGULATOR_SYR82X is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS549B22 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_TPS6586X=y +CONFIG_REGULATOR_XZ3216=y +CONFIG_CEC_CORE=y +CONFIG_CEC_NOTIFIER=y +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +# CONFIG_MEDIA_RADIO_SUPPORT is not set +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CEC_SUPPORT=y +CONFIG_MEDIA_CEC_RC=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_V4L2_FWNODE=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEOBUF2_DMA_SG=m +CONFIG_VIDEOBUF2_DVB=m +CONFIG_DVB_CORE=y +CONFIG_DVB_NET=y +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_MAX_ADAPTERS=8 +# CONFIG_DVB_DYNAMIC_MINORS is not set + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_LIRC=y +CONFIG_RC_DECODERS=y +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +# CONFIG_IR_IMON_DECODER is not set +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_ENE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_ITE_CIR is not set +# CONFIG_IR_FINTEK is not set +# CONFIG_IR_NUVOTON is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=y +# CONFIG_IR_GPIO_TX is not set +# CONFIG_IR_PWM_TX is not set +# CONFIG_IR_SERIAL is not set +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=y +# CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set +# CONFIG_USB_GSPCA is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +CONFIG_VIDEO_USBTV=m +# CONFIG_NPU_USB_ACM is not set + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +# CONFIG_VIDEO_AU0828_RC is not set +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_USB=y +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +# CONFIG_SMS_USB_DRV is not set +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set +CONFIG_DVB_AS102=m + +# +# Webcam, TV (analog/digital) USB devices +# +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=m + +# +# Software defined radio USB devices +# +CONFIG_USB_AIRSPY=m +CONFIG_USB_HACKRF=m +CONFIG_USB_MSI2500=m + +# +# USB HDMI CEC adapters +# +CONFIG_USB_PULSE8_CEC=m +CONFIG_USB_RAINSHADOW_CEC=m +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture support +# +# CONFIG_VIDEO_SOLO6X10 is not set +# CONFIG_VIDEO_TW68 is not set + +# +# Media capture/analog/hybrid TV support +# +# CONFIG_VIDEO_CX18 is not set +CONFIG_VIDEO_CX23885=m +# CONFIG_MEDIA_ALTERA_CI is not set +CONFIG_VIDEO_CX25821=m +# CONFIG_VIDEO_CX25821_ALSA is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_SAA7164 is not set + +# +# Media digital TV PCI Adapters +# +# CONFIG_DVB_AV7110 is not set +# CONFIG_DVB_BUDGET_CORE is not set +# CONFIG_DVB_B2C2_FLEXCOP_PCI is not set +# CONFIG_DVB_PLUTO2 is not set +# CONFIG_DVB_DM1105 is not set +# CONFIG_DVB_PT1 is not set +# CONFIG_DVB_PT3 is not set +# CONFIG_MANTIS_CORE is not set +# CONFIG_DVB_NGENE is not set +# CONFIG_DVB_DDBRIDGE is not set +# CONFIG_DVB_SMIPCIE is not set +# CONFIG_DVB_NETUP_UNIDVB is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +CONFIG_SOC_CAMERA=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_VIDEO_XILINX is not set +# CONFIG_VIDEO_RK_CIF_ISP10 is not set +# CONFIG_VIDEO_ROCKCHIP_CIF is not set +CONFIG_VIDEO_ROCKCHIP_ISP1=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set +# CONFIG_VIDEO_ROCKCHIP_RGA is not set +# CONFIG_VIDEO_ROCKCHIP_VPU is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_DVB_PLATFORM_DRIVERS=y +# CONFIG_ROCKCHIP_TSP is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_SMS_SDIO_DRV is not set +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_DVB_B2C2_FLEXCOP=m + +# +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) +# +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_MEDIA_ATTACH=y +# CONFIG_VIDEO_IR_I2C is not set + +# +# I2C Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7181D is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_TC35874X is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +CONFIG_VIDEO_CX25840=m + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_AD9389B is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_THS8200 is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_IMX214 is not set +CONFIG_VIDEO_IMX219=y +# CONFIG_VIDEO_IMX258 is not set +# CONFIG_VIDEO_IMX291 is not set +# CONFIG_VIDEO_IMX307 is not set +# CONFIG_VIDEO_IMX317 is not set +# CONFIG_VIDEO_IMX323 is not set +# CONFIG_VIDEO_IMX327 is not set +# CONFIG_VIDEO_VIRT_CAMERA is not set +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV2680 is not set +# CONFIG_VIDEO_OV2685 is not set +# CONFIG_VIDEO_OV2718 is not set +# CONFIG_VIDEO_OV2735 is not set +CONFIG_VIDEO_OV4689=m +# CONFIG_VIDEO_OV5640 is not set +CONFIG_VIDEO_OV5645=y +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV5648 is not set +# CONFIG_VIDEO_OV5670 is not set +# CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV7251 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV7725 is not set +# CONFIG_VIDEO_OV7750 is not set +# CONFIG_VIDEO_OV8858 is not set +# CONFIG_VIDEO_OV9281 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_OV9750 is not set +CONFIG_VIDEO_OV13850=m +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_AR0144 is not set +# CONFIG_VIDEO_AR0230 is not set +# CONFIG_VIDEO_AR0330 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_S5K4H8 is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIDEO_GC0403 is not set +# CONFIG_VIDEO_GC2155 is not set +# CONFIG_VIDEO_GC0312 is not set +# CONFIG_VIDEO_GC2053 is not set +# CONFIG_VIDEO_GC2145 is not set +CONFIG_VIDEO_GC2355=y +# CONFIG_VIDEO_GC2385 is not set +# CONFIG_VIDEO_GC5025 is not set +# CONFIG_VIDEO_GC5035 is not set +# CONFIG_VIDEO_GC8034 is not set +CONFIG_VIDEO_SC031GS=y +# CONFIG_VIDEO_SC132GS is not set +# CONFIG_VIDEO_GC0329 is not set +# CONFIG_VIDEO_GC2035 is not set +# CONFIG_VIDEO_BF20A2 is not set +# CONFIG_VIDEO_BF3925 is not set +# CONFIG_VIDEO_JX_H65 is not set +# CONFIG_VIDEO_XC7080_XC530 is not set +# CONFIG_VIDEO_PS5268 is not set +# CONFIG_VIDEO_HM2056 is not set +# CONFIG_VIDEO_PREISP_DUMMY_SENSOR is not set + +# +# Flash devices +# +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_AS3645A is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set +# CONFIG_VIDEO_SGM3784 is not set + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Camera lens devices +# +# CONFIG_VIDEO_VM149C is not set +# CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_FP5510 is not set + +# +# Audio/Video compression chips +# +# CONFIG_VIDEO_SAA6752HS is not set + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_NVP6324 is not set + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set + +# +# SPI helper chips +# +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_IMX327_SPI is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +CONFIG_MEDIA_TUNER=y + +# +# Customize TV tuners +# +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MSI001=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_M88RS6000T=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_SI2157=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m +CONFIG_MEDIA_TUNER_MXL301RF=m +CONFIG_MEDIA_TUNER_QM1D1C0042=m + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_M88DS3103=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m +CONFIG_DVB_SI2165=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_CX24120=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_TS2020=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_S5H1432=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DIB9000=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_HD29L2=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_CXD2841ER=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +CONFIG_DVB_SI2168=m +CONFIG_DVB_AS102_FE=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT3306A=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +# CONFIG_DVB_AU8522_V4L is not set +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +CONFIG_DVB_TC90522=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_DRX39XYJ=m +CONFIG_DVB_LNBH25=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_SP2=m +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m +CONFIG_DVB_HORUS3A=m +CONFIG_DVB_ASCOT2E=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set +# CONFIG_CAMSYS_DRV is not set +# CONFIG_ROCK_CHIP_SOC_CAMERA is not set + +# +# RockChip preisp driver +# +# CONFIG_RKPREISP_DRV is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +CONFIG_DRM=y +CONFIG_DRM_IGNORE_IOTCL_PERMIT=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +# CONFIG_DRM_DP_CEC is not set +CONFIG_DRM_TTM=m +# CONFIG_DRM_SCDC_HELPER is not set +CONFIG_DRM_DMA_SYNC=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set +# CONFIG_DRM_VGEM is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_ROCKCHIP_DRM_DEBUG is not set +# CONFIG_ROCKCHIP_DRM_RGA is not set +CONFIG_ROCKCHIP_CDN_DP=y +CONFIG_ROCKCHIP_DW_HDMI=y +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_MIPI_CSI_TX is not set +CONFIG_ROCKCHIP_ANALOGIX_DP=y +CONFIG_ROCKCHIP_INNO_HDMI=y +CONFIG_ROCKCHIP_LVDS=y +CONFIG_ROCKCHIP_DRM_TVE=y +CONFIG_ROCKCHIP_RGB=y +CONFIG_ROCKCHIP_DRM_BACKLIGHT=y +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +CONFIG_DRM_UDL=y +CONFIG_DRM_AST=m +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_BOCHS is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +CONFIG_DRM_PANEL_TOSHIBA_TC358762=y +CONFIG_DRM_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LONTIUM_LT8912 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +CONFIG_DRM_ANALOGIX_DP=y +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +CONFIG_DRM_DW_HDMI=y +# CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set +CONFIG_DRM_DW_HDMI_I2S_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=y +# CONFIG_POWERVR_ROGUE_M is not set +CONFIG_MALI400=y +CONFIG_MALI450=y +# CONFIG_MALI470 is not set +# CONFIG_MALI400_DEBUG is not set +# CONFIG_MALI400_PROFILING is not set +# CONFIG_MALI400_UMP is not set +CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y +CONFIG_MALI_SHARED_INTERRUPTS=y +# CONFIG_MALI_PMU_PARALLEL_POWER_UP is not set +CONFIG_MALI_DT=y +CONFIG_MALI_DEVFREQ=y +# CONFIG_MALI_QUIET is not set +# CONFIG_MALI_MIDGARD_FOR_ANDROID is not set +CONFIG_MALI_MIDGARD_FOR_LINUX=y +CONFIG_MALI_MIDGARD=y +CONFIG_MALI_MIDGARD_R18=y +# CONFIG_MALI_GATOR_SUPPORT is not set +# CONFIG_MALI_MIDGARD_ENABLE_TRACE is not set +CONFIG_MALI_DMA_FENCE=y +CONFIG_MALI_EXPERT=y +# CONFIG_MALI_CORESTACK is not set +# CONFIG_MALI_PRFCNT_SET_SECONDARY is not set +# CONFIG_MALI_PLATFORM_FAKE is not set +# CONFIG_MALI_PLATFORM_DEVICETREE is not set +CONFIG_MALI_PLATFORM_THIRDPARTY=y +CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk" +CONFIG_MALI_DEBUG=y +# CONFIG_MALI_NO_MALI is not set +# CONFIG_MALI_TRACE_TIMELINE is not set +# CONFIG_MALI_SYSTEM_TRACE is not set +# CONFIG_MALI_GPU_MMU_AARCH64 is not set +CONFIG_MALI_PWRSOFT_765=y +# CONFIG_MALI_KUTF is not set +# CONFIG_MALI_BIFROST is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SM712 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set + +# +# Rockchip Misc Video driver +# +# CONFIG_FB_ROCKCHIP is not set +# CONFIG_LCDC_RK3368 is not set +CONFIG_LCD_GENERAL=y +# CONFIG_LCD_MIPI is not set +# CONFIG_RK_TRSM is not set +# CONFIG_RK_HDMI is not set + +# +# RGA +# +# CONFIG_ROCKCHIP_RGA is not set + +# +# RGA2 +# +CONFIG_ROCKCHIP_RGA2=y + +# +# VCODEC +# +CONFIG_RK_VCODEC=y + +# +# IEP +# +# CONFIG_IEP is not set +# CONFIG_IEP_MMU is not set + +# +# DP +# + +# +# ROCKCHIP_MPP +# +CONFIG_ROCKCHIP_MPP_SERVICE=y +CONFIG_ROCKCHIP_MPP_DEVICE=y +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y +CONFIG_HDMI_NOTIFIERS=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_PCM_ELD=y +CONFIG_SND_PCM_IEC958=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=y +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_PCI is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_PCMCIA=y +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +CONFIG_SND_SOC_ROCKCHIP=y +# CONFIG_SND_SOC_ROCKCHIP_FORCE_SRAM is not set +CONFIG_SND_SOC_ROCKCHIP_I2S=y +CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=y +# CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS is not set +CONFIG_SND_SOC_ROCKCHIP_PDM=y +CONFIG_SND_SOC_ROCKCHIP_SPDIF=y +# CONFIG_SND_SOC_ROCKCHIP_SPDIFRX is not set +# CONFIG_SND_SOC_ROCKCHIP_VAD is not set +# CONFIG_SND_SOC_ROCKCHIP_DA7219 is not set +CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG=y +CONFIG_SND_SOC_ROCKCHIP_HDMI_DP=y +CONFIG_SND_SOC_ROCKCHIP_MAX98090=y +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +CONFIG_SND_SOC_ROCKCHIP_RT5645=y +# CONFIG_SND_SOC_ROCKCHIP_RT5651_TC358749 is not set +CONFIG_SND_SOC_ROCKCHIP_CDNDP=y + +# +# Allwinner SoC Audio support +# +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set +# CONFIG_SND_SOC_DUMMY_CODEC is not set +# CONFIG_SND_SOC_BT_SCO is not set +CONFIG_SND_SOC_ES8316=y +CONFIG_SND_SOC_ES8323=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_ES8328=y +CONFIG_SND_SOC_ES8328_I2C=y +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_GVA_CODEC is not set +# CONFIG_SND_SOC_FM1288 is not set +CONFIG_SND_SOC_MAX98090=y +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK312X is not set +# CONFIG_SND_SOC_RK3228 is not set +CONFIG_SND_SOC_RK3308=y +CONFIG_SND_SOC_RK3328=y +CONFIG_SND_SOC_RK817=y +CONFIG_SND_SOC_RL6231=y +CONFIG_SND_SOC_RT5616=y +# CONFIG_SND_SOC_RT5631 is not set +CONFIG_SND_SOC_RT5640=y +CONFIG_SND_SOC_RT5645=y +CONFIG_SND_SOC_RT5651=y +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +CONFIG_SND_SOC_SPDIF=y +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TC358749X is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_TS3A227E=y +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y + +# +# HID support +# +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=y +# CONFIG_HID_ACRUX_FF is not set +CONFIG_HID_APPLE=y +CONFIG_HID_APPLEIR=y +CONFIG_HID_AUREAL=y +CONFIG_HID_BELKIN=y +CONFIG_HID_BETOP_FF=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CORSAIR=y +CONFIG_HID_PRODIKEYS=y +CONFIG_HID_CP2112=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=y +CONFIG_HID_ELECOM=y +CONFIG_HID_ELO=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GEMBIRD=y +CONFIG_HID_GFRM=y +CONFIG_HID_HOLTEK=y +CONFIG_HOLTEK_FF=y +CONFIG_HID_GT683R=y +CONFIG_HID_KEYTOUCH=y +CONFIG_HID_KYE=y +CONFIG_HID_UCLOGIC=y +CONFIG_HID_WALTOP=y +CONFIG_HID_GYRATION=y +CONFIG_HID_ICADE=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=y +CONFIG_HID_LENOVO=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=y +CONFIG_HID_LOGITECH_HIDPP=y +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=y +CONFIG_HID_PANTHERLORD=y +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=y +CONFIG_HID_PETALYNX=y +# CONFIG_HID_PICOLCD is not set +CONFIG_HID_PLANTRONICS=y +CONFIG_HID_PRIMAX=y +CONFIG_HID_ROCCAT=y +CONFIG_HID_SAITEK=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +# CONFIG_SONY_FF is not set +CONFIG_HID_SPEEDLINK=y +CONFIG_HID_STEELSERIES=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_RMI=y +CONFIG_HID_GREENASIA=y +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THINGM=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=y +CONFIG_HID_WIIMOTE=y +CONFIG_HID_XINMO=y +CONFIG_HID_ZEROPLUS=y +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=y +CONFIG_HID_SENSOR_HUB=y +CONFIG_HID_SENSOR_CUSTOM_SENSOR=y +CONFIG_HID_RKVR=y +CONFIG_HID_ALPS=y + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEFAULT_PERSIST is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PCI is not set +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=y +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_STORAGE_ENE_UB6250=y +CONFIG_USB_UAS=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +# CONFIG_USB_DWC3_PCI is not set +CONFIG_USB_DWC3_OF_SIMPLE=y +CONFIG_USB_DWC3_ROCKCHIP=y +CONFIG_USB_DWC3_ROCKCHIP_INNO=y +CONFIG_USB_DWC2=y +# CONFIG_USB_DWC2_HOST is not set + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PERIPHERAL is not set +CONFIG_USB_DWC2_DUAL_ROLE=y +# CONFIG_USB_DWC2_PCI is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +CONFIG_USB_SERIAL_CH341=y +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP210X=y +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=y +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN=y +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=y +CONFIG_USB_SERIAL_OTI6858=y +# CONFIG_USB_SERIAL_QCAUX is not set +CONFIG_USB_SERIAL_QUALCOMM=y +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=y +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=y +CONFIG_USB_SERIAL_OPTION=y +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=y +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +CONFIG_USB_GADGET_DEBUG_FILES=y +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_F_ACM=y +CONFIG_USB_U_SERIAL=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_F_FS=y +CONFIG_USB_CONFIGFS=y +# CONFIG_USB_CONFIGFS_SERIAL is not set +CONFIG_USB_CONFIGFS_ACM=y +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_EEM is not set +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_MTP is not set +# CONFIG_USB_CONFIGFS_F_ACC is not set +CONFIG_USB_CONFIGFS_UEVENT=y +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_UVC is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# ROCKCHIP USB Support +# +# CONFIG_USB20_HOST is not set +# CONFIG_USB20_OTG is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +# CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=y +# CONFIG_MMC_SIMULATE_MAX_SPEED is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +# CONFIG_MMC_SDHCI_ACPI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_SDRICOH_CS is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_DW_PCI is not set +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +CONFIG_LEDS_IS31FL32XX=y + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_MULTI_CTRL is not set +CONFIG_SWITCH=m +CONFIG_SWITCH_GPIO=m +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_FAKE is not set +CONFIG_RTC_DRV_HYM8563=y +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RK808=y +# CONFIG_RTC_DRV_RK_TIMER is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_TPS6586X is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ACPI=y +CONFIG_DMA_OF=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +CONFIG_PL330_DMA=y +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_R8723AU is not set +# CONFIG_RTS5208 is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7606 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# CONFIG_INV_MPU_IIO is not set + +# +# Light sensors +# +CONFIG_SENSORS_ISL29018=y +# CONFIG_SENSORS_ISL29028 is not set +CONFIG_TSL2583=y +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_XGI is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ASHMEM is not set +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_SYNC is not set +# CONFIG_ANDROID_VSOC is not set +# CONFIG_ION is not set +# CONFIG_FIQ_DEBUGGER is not set +# CONFIG_FIQ_WATCHDOG is not set +# CONFIG_RK_CONSOLE_THREAD is not set +# CONFIG_STAGING_BOARD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_WILC1000_DRIVER is not set +# CONFIG_MOST is not set +# CONFIG_POWERVR_ROGUE_N is not set +# CONFIG_GOLDFISH is not set +CONFIG_CHROME_PLATFORMS=y +# CONFIG_CROS_EC_CHARDEV is not set +CONFIG_CROS_EC_PROTO=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +CONFIG_COMMON_CLK_DEBUGFS=y +# CONFIG_COMMON_CLK_VERSATILE is not set +CONFIG_COMMON_CLK_RK808=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_CLK_QORIQ is not set +CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# +# CONFIG_HWSPINLOCK_ROCKCHIP is not set + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_ACPI=y +CONFIG_CLKSRC_PROBE=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +CONFIG_MAILBOX=y +# CONFIG_ARM_MHU is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PCC is not set +# CONFIG_ALTERA_MBOX is not set +# CONFIG_MAILBOX_TEST is not set +# CONFIG_RK3368_MBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_IOVA=y +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_ROCKCHIP_IOMMU=y +CONFIG_RK_IOMMU=y +CONFIG_RK_IOVMM=y +# CONFIG_RK_IOMMU_DEBUG is not set +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# + +# +# Rockchip CPU selection +# +# CONFIG_CPU_PX30 is not set +# CONFIG_CPU_RK1808 is not set +# CONFIG_CPU_RK3308 is not set +# CONFIG_CPU_RK3328 is not set +# CONFIG_CPU_RK3366 is not set +# CONFIG_CPU_RK3368 is not set +CONFIG_CPU_RK3399=y +CONFIG_ANDROID_VERSION=0x07010000 +CONFIG_ROCKCHIP_CPUINFO=y +# CONFIG_ROCKCHIP_DEVICEINFO is not set +CONFIG_ROCKCHIP_IPA=y +CONFIG_ROCKCHIP_OPP=y +# CONFIG_ROCKCHIP_PM_TEST is not set +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +# CONFIG_ROCKCHIP_PVTM is not set +CONFIG_ROCKCHIP_SUSPEND_MODE=y +# CONFIG_STATE_NOTIFIER is not set +CONFIG_ROCKCHIP_SYSTEM_MONITOR=y +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +# CONFIG_DEVFREQ_GOV_MRFIXEDFREQ5 is not set +# CONFIG_DEVFREQ_GOV_MRFIXEDFREQ6 is not set +# CONFIG_DEVFREQ_GOV_MRFIXEDFREQ7 is not set +# CONFIG_DEVFREQ_GOV_MRFIXEDFREQ8 is not set +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +# CONFIG_MALI_FREQ_DEFAULT_GOV_SIMPLE_ONDEMAND is not set +CONFIG_MALI_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_MALI_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_MALI_FREQ_DEFAULT_GOV_MRFIXEDFREQ5 is not set +# CONFIG_MALI_FREQ_DEFAULT_GOV_MRFIXEDFREQ6 is not set +# CONFIG_MALI_FREQ_DEFAULT_GOV_MRFIXEDFREQ7 is not set +# CONFIG_MALI_FREQ_DEFAULT_GOV_MRFIXEDFREQ8 is not set + +# +# DEVFREQ Drivers +# +# CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_BUFFER_CB is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_HID_SENSOR_ACCEL_3D is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MXC4005 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD799X is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_GPIO_MUXADC is not set +# CONFIG_HI8435 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +CONFIG_ROCKCHIP_SARADC=y +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_VF610_ADC is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Chemical Sensors +# +# CONFIG_VZ89X is not set + +# +# Hid Sensor IIO Common +# +# CONFIG_HID_SENSOR_IIO_COMMON is not set + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_HID_SENSOR_GYRO_3D is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set +# CONFIG_HDC100X is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ACPI_ALS is not set +# CONFIG_ADJD_S311 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9960 is not set +# CONFIG_BH1750 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_ISL29125 is not set +# CONFIG_HID_SENSOR_ALS is not set +# CONFIG_HID_SENSOR_PROX is not set +# CONFIG_JSA1212 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR501 is not set +# CONFIG_OPT3001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_STK3310 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +CONFIG_SENSORS_TSL2563=y +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VL6180 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_MAG3110 is not set +# CONFIG_HID_SENSOR_MAGNETOMETER_3D is not set +# CONFIG_MMC35240 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# +# CONFIG_HID_SENSOR_INCLINOMETER_3D is not set +# CONFIG_HID_SENSOR_DEVICE_ROTATION is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +CONFIG_IIO_SYSFS_TRIGGER=y + +# +# Digital potentiometers +# +# CONFIG_MCP4531 is not set + +# +# Pressure sensors +# +# CONFIG_BMP280 is not set +# CONFIG_HID_SENSOR_PRESS is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set + +# +# Proximity sensors +# +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set + +# +# Temperature sensors +# +# CONFIG_MLX90614 is not set +# CONFIG_TMP006 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +# CONFIG_NTB is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_CROS_EC is not set +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_ROCKCHIP=y +# CONFIG_PWM_ROCKCHIP_I2S is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_PARTITION_PERCPU=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_XGENE is not set +CONFIG_PHY_ROCKCHIP_USB=y +# CONFIG_PHY_ROCKCHIP_INNO_COMBPHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_INNO_USB3=y +CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_DP=y +CONFIG_PHY_ROCKCHIP_MIPI_RX=y +CONFIG_PHY_ROCKCHIP_INNO_MIPI_DPHY=y +CONFIG_PHY_ROCKCHIP_INNO_HDMI_PHY=y +# CONFIG_PHY_ROCKCHIP_INNO_VIDEO_PHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY is not set +CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_PHY_ROCKCHIP_PCIE=m +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set + +# +# Android +# +CONFIG_ANDROID=y +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_LIBNVDIMM is not set +CONFIG_NVMEM=y +# CONFIG_RK628_EFUSE is not set +CONFIG_ROCKCHIP_EFUSE=y +# CONFIG_ROCKCHIP_OTP is not set +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set + +# +# FPGA Configuration Support +# +# CONFIG_FPGA is not set +# CONFIG_TEE is not set +# CONFIG_RK_FLASH is not set +# CONFIG_RK_NAND is not set + +# +# Headset device support +# +# CONFIG_RK_HEADSET is not set + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_ISCSI_IBFT is not set +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_ROCKCHIP_SIP=y +CONFIG_ACPI=y +CONFIG_ACPI_GENERIC_GSI=y +CONFIG_ACPI_CCA_REQUIRED=y +# CONFIG_ACPI_DEBUGGER is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_CONTAINER=y +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_CUSTOM_METHOD is not set +CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +# CONFIG_PMIC_OPREGION is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_XFS_FS=y +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_FS_DAX is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +CONFIG_OVERLAY_FS=y + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +# CONFIG_CACHEFILES is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_EXFAT_VIRTUAL_XATTR=y +CONFIG_EXFAT_VIRTUAL_XATTR_SELINUX_LABEL="u:object_r:exfat:s0" +# CONFIG_EXFAT_DEBUG is not set +# CONFIG_EXFAT_UEVENT is not set +# CONFIG_NTFS_FS is not set + + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_UID=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_SDCARD_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +# CONFIG_PSTORE_PMSG is not set +# CONFIG_PSTORE_FTRACE is not set +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_AUFS_FS=y +CONFIG_AUFS_BRANCH_MAX_127=y +# CONFIG_AUFS_BRANCH_MAX_511 is not set +# CONFIG_AUFS_BRANCH_MAX_1023 is not set +# CONFIG_AUFS_BRANCH_MAX_32767 is not set +CONFIG_AUFS_SBILIST=y +# CONFIG_AUFS_HNOTIFY is not set +# CONFIG_AUFS_EXPORT is not set +# CONFIG_AUFS_XATTR is not set +# CONFIG_AUFS_FHSM is not set +# CONFIG_AUFS_RDU is not set +# CONFIG_AUFS_SHWH is not set +# CONFIG_AUFS_BR_RAMFS is not set +# CONFIG_AUFS_BR_FUSE is not set +CONFIG_AUFS_BDEV_LOOP=y +# CONFIG_AUFS_DEBUG is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_V4 is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +CONFIG_HAVE_KVM_IRQFD=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_ARM_VGIC_V3=y +CONFIG_KVM=y +CONFIG_KVM_ARM_HOST=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_PROCESS is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_DYNAMIC_DEBUG=y + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_GDB_SCRIPTS is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_KASAN is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y +CONFIG_HARDLOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y +# CONFIG_PANIC_ON_RT_THROTTLING is not set +CONFIG_SCHEDSTATS=y +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +CONFIG_TIMER_STATS=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_CREDENTIALS=y + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_GPU_TRACEPOINTS=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_TRACER=y +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_PROBE_EVENTS is not set +CONFIG_DYNAMIC_FTRACE=y +# CONFIG_FUNCTION_PROFILER is not set +CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_TRACE_ENUM_MAP_FILE is not set +CONFIG_TRACING_EVENTS_GPIO=y + +# +# Runtime Testing +# +CONFIG_LKDTM=y +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_HASH is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +CONFIG_ENCRYPTED_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_TEE_SUPPORT is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ASYNC_PQ=y +CONFIG_ASYNC_RAID6_RECOV=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_HEH is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_LZ4=y +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP_V2 is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_POLY_HASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +CONFIG_CRYPTO_CRC32_ARM64=y +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_LRU_CACHE=m +CONFIG_CLZ_TAB=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_SG_SPLIT is not set +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/projects/Rockchip/devices/RG552/options b/projects/Rockchip/devices/RG552/options new file mode 100644 index 000000000..fbea10141 --- /dev/null +++ b/projects/Rockchip/devices/RG552/options @@ -0,0 +1,230 @@ +################################################################################ +# setup device defaults +################################################################################ + + # The TARGET_CPU variable controls which processor should be targeted for + # generated code. + case $TARGET_ARCH in + aarch64) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_CPU="cortex-a72.cortex-a53" + TARGET_CPU_FLAGS="+crc+crypto" + TARGET_FPU="fp-armv8" + TARGET_FLOAT="hard" + TARGET_FEATURES="64bit" + ;; + arm) + TARGET_KERNEL_ARCH="arm64" + TARGET_PATCH_ARCH="aarch64" + TARGET_CPU="cortex-a72.cortex-a53" + TARGET_CPU_FLAGS="+crc" + TARGET_FPU="crypto-neon-fp-armv8" + TARGET_FLOAT="hard" + TARGET_FEATURES="32bit" + ;; + esac + + # Kernel target + KERNEL_TARGET="Image" + LINUX="RG552" + BOOTLOADER="u-boot" + DEVICE_DTB="rk3399-rg552-linux" + UBOOT_SYSTEM="rg552" + PKG_SOC="rk3399" + PKG_DATAFILE="$PKG_RKBIN/bin/rk33/rk3399_ddr_933MHz_v1.25.bin" + PKG_LOADER="$PKG_RKBIN/bin/rk33/rk3399_miniloader_v1.26.bin" + PKG_BL31="$PKG_RKBIN/bin/rk33/rk3399_bl31_v1.35.elf" + BOOT_INI=false + + # Additional kernel make parameters (for example to specify the u-boot loadaddress) + KERNEL_MAKE_EXTRACMD="" + KERNEL_MAKE_EXTRACMD+=" rockchip/${DEVICE_DTB}.dtb" + + # Define the CPU + HW_CPU="Rockchip RK3399" + + # Mali GPU family + MALI_FAMILY="t860" + OPENGLES="libmali" + MALIDRIVER="libmali-midgard-t86x-r18p0-gbm" + GRAPHIC_DRIVERS="" + + # kernel serial console + EXTRA_CMDLINE="quiet video=DSI-1:1152x1920p60 fbcon=rotate:3 ssh consoleblank=0 systemd.show_status=0 loglevel=0 panic=20" + + # additional packages to install + #ADDITIONAL_PACKAGES="" + + # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware) + # Space separated list is supported, + # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware" + FIRMWARE="misc-firmware wlan-firmware" #rockchip-firmware + + # additional drivers to install: + # for a list of additional drivers see packages/linux-drivers + # Space separated list is supported, + # e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2" + ADDITIONAL_DRIVERS="RTL8812AU RTL8188EU" #RTL8188FU RTL8188EU RTL8814AU RTL8192DU RTL8812AU RTL8821CU RTL8192CU RTL8192EU + + # build and install driver addons (yes / no) + DRIVER_ADDONS_SUPPORT="no" + + # driver addons to install: + # for a list of additinoal drivers see packages/linux-driver-addons + # Space separated list is supported, + DRIVER_ADDONS="" #dvb-latest + + # debug tty path + DEBUG_TTY="/dev/ttyFIQ0" + + + # Skins to install (Estuary) + # Space separated list is supported, + # e.g. SKINS="Estuary" + SKINS="Estuary" + + # Default Skin (Estuary) + SKIN_DEFAULT="Estuary" + + # Select whether to use default (upstream xbmc/xbmc) repo, or specific vendor repo + KODI_VENDOR="default" + + # install extra subtitle Fonts for KODI (yes / no) + KODI_EXTRA_FONTS="yes" + + # build and install PulseAudio support (yes / no) + PULSEAUDIO_SUPPORT="yes" + + # build and install espeak support (yes / no) + ESPEAK_SUPPORT="no" + + # build and install with BluRay support (yes / no) + KODI_BLURAY_SUPPORT="no" + + # build and install with BD+ support + # (BD+ decryption support in KODI) (yes / no) + BLURAY_BDPLUS_SUPPORT="no" + + # build and install with AACS support + # (BD decryption support in KODI) (yes / no) + BLURAY_AACS_SUPPORT="no" + + # build and install with DVDCSS support + # (DVD decryption support in KODI) (yes / no) + KODI_DVDCSS_SUPPORT="no" + + # build and install bluetooth support (yes / no) + BLUETOOTH_SUPPORT="no" + + # build and install with KODI webfrontend (yes / no) + KODI_WEBSERVER_SUPPORT="no" + + # build and install Avahi (Zeroconf) daemon (yes / no) + AVAHI_DAEMON="no" + + # build with UPnP support (yes / no) + KODI_UPNP_SUPPORT="no" + + # build with MySQL support (mysql / mariadb / none) + KODI_MYSQL_SUPPORT="none" + + # build xbmc with optical drive support (yes / no) + KODI_OPTICAL_SUPPORT="no" + + # build with AirPlay support (stream videos from iDevices to KODI) (yes / no) + KODI_AIRPLAY_SUPPORT="no" + + # build with AirTunes support (stream music from iDevices to KODI) (yes / no) + KODI_AIRTUNES_SUPPORT="no" + + # build with libnfs support (mounting nfs shares with KODI) (yes / no) + KODI_NFS_SUPPORT="no" + + # build with Samba Client support (mounting SAMBA shares with KODI) (yes / no) + KODI_SAMBA_SUPPORT="no" + + # build with NFS support (mounting nfs shares via the OS) (yes / no) + NFS_SUPPORT="no" + + # build with Samba Client support (mounting samba shares via the OS) (yes / no) + SAMBA_SUPPORT="no" + + # build and install Samba Server (yes / no) + SAMBA_SERVER="yes" + + # build and install SFTP Server (yes / no) + SFTP_SERVER="yes" + + # build and install OpenVPN support (yes / no) + OPENVPN_SUPPORT="no" + + # build and install diskmounter support (udevil) + # this service provide auto mounting support for external drives in the + # mediacenter also automount internally drives at boottime via udev (yes / no) + UDEVIL="yes" + + # build and install exFAT fuse support (yes / no) + EXFAT="yes" + + # build and install NTFS-3G fuse support (yes / no) + NTFS3G="no" + + # build and install hfs filesystem utilities (yes / no) + HFSTOOLS="no" + + # build and install remote support (yes / no) + REMOTE_SUPPORT="no" + + # build and install CEC adapter support (yes / no) + CEC_SUPPORT="no" + + # build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="no" + + # build and install iSCSI support - iscsistart (yes / no) + ISCSI_SUPPORT="no" + + # Support for partitioning and formating disks in initramfs (yes / no) + # This adds support for parted and mkfs.ext3/4 to initramfs for OEM usage + INITRAMFS_PARTED_SUPPORT="no" + + # build with swap support (yes / no) + SWAP_SUPPORT="yes" + + # swap support enabled per default (yes / no) + SWAP_ENABLED_DEFAULT="yes" + + # swapfile size if SWAP_SUPPORT=yes in MB + SWAPFILESIZE="384" + + # cron support (yes / no) + CRON_SUPPORT="no" + + # Addon Server Url + ADDON_SERVER_URL="" + + # Addon ID of the default addon repository + ADDON_REPO_ID="" + + # Name of the default addon repository + ADDON_REPO_NAME="" + + # Version of the default addon repository + ADDON_REPO_VERSION="" + + # set the addon dirs + ADDON_PATH="" + ADDON_URL="" + + # Settings package name - blank if not required + DISTRO_PKG_SETTINGS="" + + # IR remote protocols supported in default config + IR_REMOTE_PROTOCOLS="" + + # IR remote keymaps supported in default config + IR_REMOTE_KEYMAPS="" + + # htop tool (yes / no) + HTOP_TOOL="yes" diff --git a/projects/Rockchip/options b/projects/Rockchip/options new file mode 100644 index 000000000..3641938ed --- /dev/null +++ b/projects/Rockchip/options @@ -0,0 +1,87 @@ +################################################################################ +# setup system defaults +################################################################################ + + # Bootloader to use (syslinux / u-boot / bcm2835-bootloader) + BOOTLOADER="u-boot" + + # Kernel extra targets to build + KERNEL_UBOOT_EXTRA_TARGET="" + + # Kernel to use. values can be: + # default: default mainline kernel + LINUX="${LINUX:-rockchip-4.4}" + +################################################################################ +# setup build defaults +################################################################################ + + # Project FLAGS + PROJECT_CFLAGS="" + + # SquashFS compression method (gzip / lzo / xz) + SQUASHFS_COMPRESSION="lzo" + +################################################################################ +# setup project defaults +################################################################################ + + # build and install ALSA Audio support (yes / no) + ALSA_SUPPORT="yes" + + # OpenGL(X) implementation to use (no / mesa) + OPENGL="no" + + # OpenGL-ES implementation to use (no / bcm2835-driver / gpu-viv-bin-mx6q) + OPENGLES="libmali" + + # include uvesafb support (yes / no) + UVESAFB_SUPPORT="no" + + # Displayserver to use (weston / no) + DISPLAYSERVER="no" + + # Windowmanager to use (fluxbox / none) + WINDOWMANAGER="none" + + # Xorg Graphic drivers to use (all / i915,i965,r200,r300,r600,nvidia) + # Space separated list is supported, + # e.g. GRAPHIC_DRIVERS="i915 i965 r300 r600 radeonsi nvidia" + GRAPHIC_DRIVERS="" + + # Use a vendor specific KODI repo + KODI_VENDOR="rockchip" + + # KODI Player implementation to use (default / bcm2835-driver / libfslvpuwrap) + KODIPLAYER_DRIVER="$OPENGLES" + + # Modules to install in initramfs for early boot + INITRAMFS_MODULES="" + + # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware) + # Space separated list is supported, + # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware" + FIRMWARE="misc-firmware wlan-firmware dvb-firmware rockchip-firmware" + + # additional packages to install + # ADDITIONAL_PACKAGES="" + + # build and install CEC framework support (yes / no) + CEC_FRAMEWORK_SUPPORT="yes" + + # build with installer (yes / no) + INSTALLER_SUPPORT="no" + + # Start boot partition at 16MiB, same as https://github.com/rockchip-linux/build images + SYSTEM_PART_START=32768 + + # build and install driver addons (yes / no) + DRIVER_ADDONS_SUPPORT="yes" + + # driver addons to install: + # for a list of additinoal drivers see packages/linux-driver-addons + # Space separated list is supported, + DRIVER_ADDONS="dvb-latest" + + # debug tty path + DEBUG_TTY="/dev/ttyS2" diff --git a/projects/Rockchip/packages/linux/package.mk b/projects/Rockchip/packages/linux/package.mk new file mode 100644 index 000000000..a4281c569 --- /dev/null +++ b/projects/Rockchip/packages/linux/package.mk @@ -0,0 +1,296 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2021-present 351ELEC (https://github.com/351ELEC) + +PKG_NAME="linux" +PKG_URL="https://github.com/JustEnoughLinuxOS/rockchip-kernel.git" +PKG_VERSION="547dedc" +PKG_LICENSE="GPL" +PKG_SITE="http://www.kernel.org" +PKG_DEPENDS_HOST="ccache:host openssl:host" +PKG_DEPENDS_TARGET="toolchain linux:host cpio:host kmod:host xz:host wireless-regdb keyutils $KERNEL_EXTRA_DEPENDS_TARGET" +PKG_DEPENDS_INIT="toolchain" +PKG_NEED_UNPACK="$LINUX_DEPENDS $(get_pkg_directory busybox)" +PKG_LONGDESC="This package contains the kernel for the RG351P/M/V/MP" +PKG_IS_KERNEL_PKG="yes" +PKG_STAMP="$KERNEL_TARGET $KERNEL_MAKE_EXTRACMD" +PKG_PATCH_DIRS+="${DEVICE}" +GET_HANDLER_SUPPORT="git" + +PKG_KERNEL_CFG_FILE=$(kernel_config_path) || die + +if [ -n "$KERNEL_TOOLCHAIN" ]; then + PKG_DEPENDS_HOST="$PKG_DEPENDS_HOST gcc-arm-$KERNEL_TOOLCHAIN:host" + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET gcc-arm-$KERNEL_TOOLCHAIN:host" + HEADERS_ARCH=$TARGET_ARCH +fi + +if [ "$PKG_BUILD_PERF" != "no" ] && grep -q ^CONFIG_PERF_EVENTS= $PKG_KERNEL_CFG_FILE ; then + PKG_BUILD_PERF="yes" + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET binutils elfutils libunwind zlib openssl" +fi + +if [ "$TARGET_ARCH" = "x86_64" ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET intel-ucode:host kernel-firmware elfutils:host pciutils" +fi + +if [[ "$KERNEL_TARGET" = uImage* ]]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET u-boot-tools:host" +fi + +post_patch() { + cp $PKG_KERNEL_CFG_FILE $PKG_BUILD/.config + + sed -i -e "s|^CONFIG_INITRAMFS_SOURCE=.*$|CONFIG_INITRAMFS_SOURCE=\"$BUILD/image/initramfs.cpio\"|" $PKG_BUILD/.config + sed -i -e '/^CONFIG_INITRAMFS_SOURCE=*./ a CONFIG_INITRAMFS_ROOT_UID=0\nCONFIG_INITRAMFS_ROOT_GID=0' $PKG_BUILD/.config + + # set default hostname based on $DISTRONAME + sed -i -e "s|@DISTRONAME@|$DISTRONAME|g" $PKG_BUILD/.config + + # disable swap support if not enabled + if [ ! "$SWAP_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_SWAP=.*$|# CONFIG_SWAP is not set|" $PKG_BUILD/.config + fi + + # disable nfs support if not enabled + if [ ! "$NFS_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_NFS_FS=.*$|# CONFIG_NFS_FS is not set|" $PKG_BUILD/.config + fi + + # disable cifs support if not enabled + if [ ! "$SAMBA_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_CIFS=.*$|# CONFIG_CIFS is not set|" $PKG_BUILD/.config + fi + + # disable iscsi support if not enabled + if [ ! "$ISCSI_SUPPORT" = yes ]; then + sed -i -e "s|^CONFIG_SCSI_ISCSI_ATTRS=.*$|# CONFIG_SCSI_ISCSI_ATTRS is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_TCP=.*$|# CONFIG_ISCSI_TCP is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_BOOT_SYSFS=.*$|# CONFIG_ISCSI_BOOT_SYSFS is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_IBFT_FIND=.*$|# CONFIG_ISCSI_IBFT_FIND is not set|" $PKG_BUILD/.config + sed -i -e "s|^CONFIG_ISCSI_IBFT=.*$|# CONFIG_ISCSI_IBFT is not set|" $PKG_BUILD/.config + fi + + # install extra dts files + for f in $PROJECT_DIR/$PROJECT/config/*-overlay.dts; do + [ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays || true + done + if [ -n "$DEVICE" ]; then + for f in $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/*-overlay.dts; do + [ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays || true + done + fi +} + +make_host() { + make \ + ARCH=${HEADERS_ARCH:-$TARGET_KERNEL_ARCH} \ + HOSTCC="$TOOLCHAIN/bin/host-gcc" \ + HOSTCXX="$TOOLCHAIN/bin/host-g++" \ + HOSTCFLAGS="$HOST_CFLAGS" \ + HOSTCXXFLAGS="$HOST_CXXFLAGS" \ + HOSTLDFLAGS="$HOST_LDFLAGS" \ + headers_check +} + +makeinstall_host() { + make \ + ARCH=${HEADERS_ARCH:-$TARGET_KERNEL_ARCH} \ + HOSTCC="$TOOLCHAIN/bin/host-gcc" \ + HOSTCXX="$TOOLCHAIN/bin/host-g++" \ + HOSTCFLAGS="$HOST_CFLAGS" \ + HOSTCXXFLAGS="$HOST_CXXFLAGS" \ + HOSTLDFLAGS="$HOST_LDFLAGS" \ + INSTALL_HDR_PATH=dest \ + headers_install + mkdir -p $SYSROOT_PREFIX/usr/include + cp -R dest/include/* $SYSROOT_PREFIX/usr/include +} + +pre_make_target() { + if [ "$TARGET_ARCH" = "x86_64" ]; then + # copy some extra firmware to linux tree + mkdir -p $PKG_BUILD/external-firmware + cp -a $(get_build_dir kernel-firmware)/{amdgpu,amd-ucode,i915,radeon,e100,rtl_nic} $PKG_BUILD/external-firmware + + cp -a $(get_build_dir intel-ucode)/intel-ucode $PKG_BUILD/external-firmware + + FW_LIST="$(find $PKG_BUILD/external-firmware \( -type f -o -type l \) \( -iname '*.bin' -o -iname '*.fw' -o -path '*/intel-ucode/*' \) | sed 's|.*external-firmware/||' | sort | xargs)" + sed -i "s|CONFIG_EXTRA_FIRMWARE=.*|CONFIG_EXTRA_FIRMWARE=\"${FW_LIST}\"|" $PKG_BUILD/.config + fi + + # Add EXFat, kinda gross but I don't want it as a module. + PREEXF=`pwd` + cd $PKG_BUILD/fs + git clone https://github.com/arter97/exfat-linux.git + cd exfat-linux + git checkout old + cd $PKG_BUILD/fs + if [ -d "exfat" ] + then + rm -rf exfat + fi + mv exfat-linux exfat + sed -i '/source "fs\/fat\/Kconfig"/a source "fs\/exfat\/Kconfig"' Kconfig + sed -i '/obj-$(CONFIG_FAT_FS).*+= fat\//a obj-$(CONFIG_EXFAT_FS)\t\t+= exfat\/' Makefile + cd ${PREEXF} + + kernel_make oldconfig + + # regdb (backward compatability with pre-4.15 kernels) + if grep -q ^CONFIG_CFG80211_INTERNAL_REGDB= $PKG_BUILD/.config ; then + cp $(get_build_dir wireless-regdb)/db.txt $PKG_BUILD/net/wireless/db.txt + fi +} + +make_target() { + kernel_make modules + kernel_make INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) modules_install + rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/build + rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/source + + if [ "$PKG_BUILD_PERF" = "yes" ] ; then + ( cd tools/perf + + # arch specific perf build args + case "$TARGET_ARCH" in + x86_64) + PERF_BUILD_ARGS="ARCH=x86" + ;; + aarch64) + PERF_BUILD_ARGS="ARCH=arm64" + ;; + *) + PERF_BUILD_ARGS="ARCH=$TARGET_ARCH" + ;; + esac + + WERROR=0 \ + NO_LIBPERL=1 \ + NO_LIBPYTHON=1 \ + NO_SLANG=1 \ + NO_GTK2=1 \ + NO_LIBNUMA=1 \ + NO_LIBAUDIT=1 \ + NO_LZMA=1 \ + NO_SDT=1 \ + CROSS_COMPILE="$TARGET_PREFIX" \ + JOBS="$CONCURRENCY_MAKE_LEVEL" \ + make $PERF_BUILD_ARGS + mkdir -p $INSTALL/usr/bin + cp perf $INSTALL/usr/bin + ) + fi + + ( cd $ROOT + rm -rf $BUILD/initramfs + $SCRIPTS/install initramfs + ) + pkg_lock_status "ACTIVE" "linux:target" "build" + + # arm64 target does not support creating uImage. + # Build Image first, then wrap it using u-boot's mkimage. + if [[ "$TARGET_KERNEL_ARCH" == "arm64" && "$KERNEL_TARGET" == uImage* ]]; then + if [ -z "$KERNEL_UIMAGE_LOADADDR" -o -z "$KERNEL_UIMAGE_ENTRYADDR" ]; then + die "ERROR: KERNEL_UIMAGE_LOADADDR and KERNEL_UIMAGE_ENTRYADDR have to be set to build uImage - aborting" + fi + KERNEL_UIMAGE_TARGET="$KERNEL_TARGET" + KERNEL_TARGET="${KERNEL_TARGET/uImage/Image}" + fi + + # the modules target is required to get a proper Module.symvers + # file with symbols from built-in and external modules. + # Without that it'll contain only the symbols from the kernel + kernel_make $KERNEL_TARGET $KERNEL_MAKE_EXTRACMD modules + + if [ -n "$KERNEL_UIMAGE_TARGET" ] ; then + # determine compression used for kernel image + KERNEL_UIMAGE_COMP=${KERNEL_UIMAGE_TARGET:7} + KERNEL_UIMAGE_COMP=${KERNEL_UIMAGE_COMP:-none} + + # calculate new load address to make kernel Image unpack to memory area after compressed image + if [ "$KERNEL_UIMAGE_COMP" != "none" ] ; then + COMPRESSED_SIZE=$(stat -t "arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_TARGET" | awk '{print $2}') + # align to 1 MiB + COMPRESSED_SIZE=$(( (($COMPRESSED_SIZE - 1 >> 20) + 1) << 20 )) + PKG_KERNEL_UIMAGE_LOADADDR=$(printf '%X' "$(( $KERNEL_UIMAGE_LOADADDR + $COMPRESSED_SIZE ))") + PKG_KERNEL_UIMAGE_ENTRYADDR=$(printf '%X' "$(( $KERNEL_UIMAGE_ENTRYADDR + $COMPRESSED_SIZE ))") + else + PKG_KERNEL_UIMAGE_LOADADDR=${KERNEL_UIMAGE_LOADADDR} + PKG_KERNEL_UIMAGE_ENTRYADDR=${KERNEL_UIMAGE_ENTRYADDR} + fi + + mkimage -A $TARGET_KERNEL_ARCH \ + -O linux \ + -T kernel \ + -C $KERNEL_UIMAGE_COMP \ + -a $PKG_KERNEL_UIMAGE_LOADADDR \ + -e $PKG_KERNEL_UIMAGE_ENTRYADDR \ + -d arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_TARGET \ + arch/$TARGET_KERNEL_ARCH/boot/$KERNEL_UIMAGE_TARGET + + KERNEL_TARGET="${KERNEL_UIMAGE_TARGET}" + fi +} + +makeinstall_target() { + if [ "$BOOTLOADER" = "u-boot" ]; then + mkdir -p $INSTALL/usr/share/bootloader + for dtb in arch/$TARGET_KERNEL_ARCH/boot/dts/*.dtb arch/$TARGET_KERNEL_ARCH/boot/dts/*/*.dtb; do + if [ -f $dtb ]; then + cp -v $dtb $INSTALL/usr/share/bootloader + fi + done + elif [ "$BOOTLOADER" = "bcm2835-bootloader" ]; then + mkdir -p $INSTALL/usr/share/bootloader/overlays + + # install platform dtbs, but remove upstream kernel dtbs (i.e. without downstream + # drivers and decent USB support) as these are not required by LibreELEC + cp -p arch/$TARGET_KERNEL_ARCH/boot/dts/*.dtb $INSTALL/usr/share/bootloader + rm -f $INSTALL/usr/share/bootloader/bcm283*.dtb + + # install overlay dtbs + for dtb in arch/$TARGET_KERNEL_ARCH/boot/dts/overlays/*.dtbo; do + cp $dtb $INSTALL/usr/share/bootloader/overlays 2>/dev/null || : + done + cp -p arch/$TARGET_KERNEL_ARCH/boot/dts/overlays/README $INSTALL/usr/share/bootloader/overlays + fi +} + +make_init() { + : # reuse make_target() +} + +makeinstall_init() { + if [ -n "$INITRAMFS_MODULES" ]; then + mkdir -p $INSTALL/etc + mkdir -p $INSTALL/usr/lib/modules + + for i in $INITRAMFS_MODULES; do + module=`find .install_pkg/$(get_full_module_dir)/kernel -name $i.ko` + if [ -n "$module" ]; then + echo $i >> $INSTALL/etc/modules + cp $module $INSTALL/usr/lib/modules/`basename $module` + fi + done + fi + + if [ "$UVESAFB_SUPPORT" = yes ]; then + mkdir -p $INSTALL/usr/lib/modules + uvesafb=`find .install_pkg/$(get_full_module_dir)/kernel -name uvesafb.ko` + cp $uvesafb $INSTALL/usr/lib/modules/`basename $uvesafb` + fi +} + +post_install() { + if [ ! -d $INSTALL/$(get_full_firmware_dir) ] + then + mkdir -p $INSTALL/$(get_full_firmware_dir)/ + fi + + # regdb and signature is now loaded as firmware by 4.15+ + if grep -q ^CONFIG_CFG80211_REQUIRE_SIGNED_REGDB= $PKG_BUILD/.config; then + cp $(get_build_dir wireless-regdb)/regulatory.db{,.p7s} $INSTALL/$(get_full_firmware_dir) + fi +} diff --git a/projects/Rockchip/packages/linux/patches/RG351V/001-vdeadzone.patch b/projects/Rockchip/packages/linux/patches/RG351V/001-vdeadzone.patch new file mode 100644 index 000000000..61feff5ce --- /dev/null +++ b/projects/Rockchip/packages/linux/patches/RG351V/001-vdeadzone.patch @@ -0,0 +1,32 @@ +From 98863b2f24c77615c181d466220d593d730c89c0 Mon Sep 17 00:00:00 2001 +From: YonKuma +Date: Sat, 23 Oct 2021 20:56:35 -0400 +Subject: [PATCH] Fix for V Deadzone + +--- + drivers/input/evdev.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index 632e3797d98f..c7674d0be1c3 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -15,12 +15,12 @@ + #define EVDEV_MIN_BUFFER_SIZE 64U + #define EVDEV_BUF_PACKETS 8 + +-#define RG351P_ABS_Z_MIN 500 ++#define RG351P_ABS_Z_MIN 700 + #define RG351P_ABS_Z_MAX 3500 + #define RG351P_ABS_RY_MIN 500 + #define RG351P_ABS_RY_MAX 3500 +-#define RG351P_ABS_RX_MIN 500 +-#define RG351P_ABS_RX_MAX 3200 ++#define RG351P_ABS_RX_MIN 700 ++#define RG351P_ABS_RX_MAX 3500 + #define RG351P_ABS_RZ_MIN 500 + #define RG351P_ABS_RZ_MAX 3200 + +-- +2.25.1 + diff --git a/projects/Rockchip/packages/linux/sysctl.d/network.conf b/projects/Rockchip/packages/linux/sysctl.d/network.conf new file mode 100644 index 000000000..3518d6d96 --- /dev/null +++ b/projects/Rockchip/packages/linux/sysctl.d/network.conf @@ -0,0 +1 @@ +net.ipv4.tcp_no_metrics_save=1 diff --git a/projects/Rockchip/packages/linux/sysctl.d/qdisc.conf b/projects/Rockchip/packages/linux/sysctl.d/qdisc.conf new file mode 100644 index 000000000..ffd7273d3 --- /dev/null +++ b/projects/Rockchip/packages/linux/sysctl.d/qdisc.conf @@ -0,0 +1 @@ +net.core.default_qdisc = fq_codel diff --git a/projects/Rockchip/packages/linux/udev.d/30-disable-wakeup.rules b/projects/Rockchip/packages/linux/udev.d/30-disable-wakeup.rules new file mode 100644 index 000000000..c4769477e --- /dev/null +++ b/projects/Rockchip/packages/linux/udev.d/30-disable-wakeup.rules @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end" + +DRIVER=="ehci-pci|xhci_hcd", RUN+="/usr/bin/sh -c 'echo disabled > /sys/$devpath/power/wakeup'" + +LABEL="end" diff --git a/projects/Rockchip/packages/linux/udev.d/40-modeswitch.rules b/projects/Rockchip/packages/linux/udev.d/40-modeswitch.rules new file mode 100644 index 000000000..8d3b1720c --- /dev/null +++ b/projects/Rockchip/packages/linux/udev.d/40-modeswitch.rules @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) + +ACTION!="add|change", GOTO="end_modeswitch" +KERNEL!="sr[0-9]*", GOTO="end_modeswitch" +SUBSYSTEM!="block", GOTO="end_modeswitch" + +# Atheros Wireless / Netgear WNDA3200 +ATTRS{idVendor}=="0cf3", ATTRS{idProduct}=="20ff", RUN+="/usr/bin/eject '/dev/%k'" + +LABEL="end_modeswitch" diff --git a/projects/Rockchip/packages/linux/udev.d/99-powertargets.rules b/projects/Rockchip/packages/linux/udev.d/99-powertargets.rules new file mode 100644 index 000000000..095a96cda --- /dev/null +++ b/projects/Rockchip/packages/linux/udev.d/99-powertargets.rules @@ -0,0 +1,2 @@ +ACTION=="change", SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/bin/sh -c 'echo out | /usr/bin/tee /sys/class/gpio/gpio77/direction'" +ACTION=="change", SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="/bin/sh -c 'echo in | /usr/bin/tee /sys/class/gpio/gpio77/direction'" diff --git a/projects/Rockchip/packages/sleep/package.mk b/projects/Rockchip/packages/sleep/package.mk new file mode 100644 index 000000000..445ec89b7 --- /dev/null +++ b/projects/Rockchip/packages/sleep/package.mk @@ -0,0 +1,19 @@ +PKG_NAME="sleep" +PKG_VERSION="" +PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="OSS" +PKG_DEPENDS_TARGET="systemd" +PKG_SITE="" +PKG_URL="" +PKG_LONGDESC="Sleep configuration" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/config/sleep.conf.d + cp sleep.conf $INSTALL/usr/config/sleep.conf.d/sleep.conf + + mkdir -p $INSTALL/usr/lib/systemd/system-sleep/ + cp sleep.sh $INSTALL/usr/lib/systemd/system-sleep/sleep + chmod +x $INSTALL/usr/lib/systemd/system-sleep/sleep +} diff --git a/projects/Rockchip/packages/sleep/sources/sleep.conf b/projects/Rockchip/packages/sleep/sources/sleep.conf new file mode 100644 index 000000000..2d6a0969a --- /dev/null +++ b/projects/Rockchip/packages/sleep/sources/sleep.conf @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See systemd-sleep.conf(5) for details + +[Sleep] +AllowSuspend=yes +#AllowHibernation=yes +#AllowSuspendThenHibernate=yes +#AllowHybridSleep=yes +#SuspendMode=suspend +SuspendState=mem standby freeze +#HibernateMode=platform shutdown +#HibernateState=disk +#HybridSleepMode=suspend platform shutdown +#HybridSleepState=disk +#HibernateDelaySec=180min \ No newline at end of file diff --git a/projects/Rockchip/packages/sleep/sources/sleep.sh b/projects/Rockchip/packages/sleep/sources/sleep.sh new file mode 100755 index 000000000..7cb3e9dd9 --- /dev/null +++ b/projects/Rockchip/packages/sleep/sources/sleep.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +case $1 in + pre) + # Store system brightness + cat /sys/class/backlight/backlight/brightness > /storage/.brightness + # Store sound state. Try to avoid having max volume after resume + alsactl store -f /tmp/asound.state + # workaround until dwc2 is fixed + #modprobe -r dwc2 + # stop hotkey service + systemctl stop headphones + + # This file is used by ES to determine if we just woke up from sleep + touch /run/.last_sleep_time + + ;; + post) + # Restore pre-sleep sound state + alsactl restore -f /tmp/asound.state + VOL=$(get_setting "audio.volume" 2>/dev/null) + MIXER="Master" + amixer set "${MIXER}" ${VOL}% 2>&1 >/dev/null + # workaround until dwc2 is fixed + #(echo $(lsmod 2>/dev/null) | grep dwc2 >/dev/null) && modprobe -r dwc2 + #modprobe -i dwc2 + # Restore system brightness + cat /storage/.brightness > /sys/class/backlight/backlight/brightness + + # re-detect and reapply sound, brightness and hp state + systemctl start headphones + ;; +esac diff --git a/projects/Rockchip/packages/system-utils/package.mk b/projects/Rockchip/packages/system-utils/package.mk new file mode 100644 index 000000000..f4e5f20cf --- /dev/null +++ b/projects/Rockchip/packages/system-utils/package.mk @@ -0,0 +1,25 @@ +# Copyright (C) 2021-present Fewtarius + +PKG_NAME="system-utils" +PKG_VERSION="" +PKG_SHA256="" +PKG_ARCH="any" +PKG_LICENSE="mix" +PKG_DEPENDS_TARGET="toolchain sleep" +PKG_SITE="" +PKG_URL="" +PKG_LONGDESC="Support scripts for Rockchip/Anbernic devices" +PKG_TOOLCHAIN="manual" + +makeinstall_target() { + mkdir -p $INSTALL/usr/bin + cp fancontrol ${INSTALL}/usr/bin + cp headphone_sense ${INSTALL}/usr/bin + cp system_utils ${INSTALL}/usr/bin + cp volume_sense ${INSTALL}/usr/bin + cp battery ${INSTALL}/usr/bin + chmod 0755 ${INSTALL}/usr/bin/* + + mkdir -p $INSTALL/usr/config + cp fancontrol.conf $INSTALL/usr/config +} diff --git a/projects/Rockchip/packages/system-utils/sources/battery b/projects/Rockchip/packages/system-utils/sources/battery new file mode 100755 index 000000000..c67f98569 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/battery @@ -0,0 +1,57 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +# Simple script to watch the battery capacity and +# turn the power LED red when it reaches 25% + +. /etc/profile + +function set_led() { + case $1 in + red) + echo out >/sys/class/gpio/gpio${DEVICE_LED}/direction + echo 1 >/sys/class/gpio/gpio${DEVICE_LED}/value + ;; + green) + echo out >/sys/class/gpio/gpio${DEVICE_LED}/direction + echo 0 >/sys/class/gpio/gpio${DEVICE_LED}/value + ;; + yellow) + echo in >/sys/class/gpio/gpio${DEVICE_LED}/direction + ;; + esac +} + + +while true +do + CAP=$(cat /sys/class/power_supply/battery/capacity) + STAT=$(cat /sys/class/power_supply/battery/status) + if [ ${STAT} == "Discharging" ] + then + if (( ${CAP} <= 10 )) + then + for ctr in $(seq 1 1 5) + do + set_led yellow + sleep .5 + set_led red + sleep .5 + done + continue + elif (( ${CAP} <= 20 )) + then + set_led red + elif (( ${CAP} <= 30 )) + then + set_led yellow + else + set_led green + fi + elif (( ${CAP} >= 95 )) + then + set_led green + fi + sleep 15 +done diff --git a/projects/Rockchip/packages/system-utils/sources/fancontrol b/projects/Rockchip/packages/system-utils/sources/fancontrol new file mode 100755 index 000000000..a54d12a53 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/fancontrol @@ -0,0 +1,37 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2021-present Fewtarius (https://github.com/fewtarius) + +. /etc/profile + +if [ -e "/storage/.config/fancontrol.conf" ] +then + DEBUG && echo "Loading configuration file" + source /storage/.config/fancontrol.conf +else + DEBUG && echo "Configuration not found, loading defaults" + FAN_PWM="${DEVICE_PWM_FAN}" + SPEEDS=(255 127 85 0) + TEMPS=(75000 65000 55000 0) +fi + +while true +do + INDEX=0 + CPU_TEMP=$(printf "%.0f" $(cat /sys/devices/virtual/thermal/thermal_zone*/temp | awk '{ total += $1; count++ } END { print total/count }')) + $DEBUG && echo "CPU TEMP: ${CPU_TEMP}" + for TEMP in "${TEMPS[@]}" + do + $DEBUG && echo "INDEX: ${INDEX}" + $DEBUG && echo "CHK: ${TEMP}" + if (( "${CPU_TEMP}" > "${TEMP}" )) + then + $DEBUG && echo "Setting PWM FAN to ${SPEEDS[${INDEX}]} (${TEMP})" + echo ${SPEEDS[${INDEX}]} >${FAN_PWM} + break + fi + INDEX=$(( $INDEX + 1 )) + done + sleep 2 + $DEBUG && echo "Loop" +done diff --git a/projects/Rockchip/packages/system-utils/sources/fancontrol.conf b/projects/Rockchip/packages/system-utils/sources/fancontrol.conf new file mode 100644 index 000000000..8360dbfc9 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/fancontrol.conf @@ -0,0 +1,19 @@ +# Set to true or export it as a variable if you want debug output. +# To test: +# +# systemctl stop fancontrol +# /usr/bin/fancontrol +# +# To re-enable: +# +# systemctl start fancontrol + +# This is the location of the PWM control, you don't need to change it. +FAN_PWM="/sys/class/hwmon/hwmon0/pwm1" + +## Fan speeds range from off (0) to full (255). +## Define a speed for each temperature that you define. Order matters. +SPEEDS=(255 127 85 0) + +## Temperatures, 75000=75C. Map each to a speed above. +TEMPS=(75000 65000 55000 0) diff --git a/projects/Rockchip/packages/system-utils/sources/headphone_sense b/projects/Rockchip/packages/system-utils/sources/headphone_sense new file mode 100755 index 000000000..8b416407f --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/headphone_sense @@ -0,0 +1,35 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +# Source predefined functions and variables +. /etc/profile + +# Switch to headphones if we have them already connected at boot +GPIO=$(cat ${DEVICE_JACK}) +[[ "$GPIO" == "0" ]] && set_setting "audio.device" "headphone" || set_setting "audio.device" "speakers" + +if [ -e "/storage/.config/distribution/configs/distribution.conf" ]; then +/usr/bin/system_utils setaudio $(get_setting "audio.device") +/usr/bin/system_utils vol $(get_setting "audio.volume") +fi + +# Headphone sensing +DEVICE="${DEVICE_VOLUME_DEV}" + +HP_ON='*(SW_HEADPHONE_INSERT), value 0*' +HP_OFF='*(SW_HEADPHONE_INSERT), value 1*' + +evtest "${DEVICE}" | while read line; do + case $line in + (${HP_ON}) + amixer cset name='Playback Path' HP + set_setting "audio.device" "headphone" + ;; + (${HP_OFF}) + amixer cset name='Playback Path' SPK + set_setting "audio.device" "speakers" + ;; + esac +done diff --git a/projects/Rockchip/packages/system-utils/sources/system_utils b/projects/Rockchip/packages/system-utils/sources/system_utils new file mode 100755 index 000000000..e4e73a5e0 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/system_utils @@ -0,0 +1,86 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Shanti Gilbert (https://github.com/shantigilbert) + +# THESE NEEDS TO BE CLEANED UP, MAYBE WITH CASE OR FUNCTIONS + +# Source predefined functions and variables +. /etc/profile + +if [ "${1}" == "toggleaudio" ];then +# Toggle audio output +CURRENTAUDIO=$(get_setting "audio.device") + case "${CURRENTAUDIO}" in + "headphone") + echo "setting speakers" + amixer cset name='Playback Path' SPK + set_setting "audio.device" "speakers" + ;; + "auto"|"speakers"|*) + echo "setting headphones" + amixer cset name='Playback Path' HP + set_setting "audio.device" "headphone" + ;; + esac +fi + +if [ "${1}" == "setaudio" ];then +# Set audio output second parameter is either headphones or speakers + case "${2}" in + "headphone") + echo "setting headphones" + amixer cset name='Playback Path' HP + set_setting "audio.device" "headphone" + ;; + "auto"|"speakers"|*) + echo "setting speakers" + amixer cset name='Playback Path' SPK + set_setting "audio.device" "speakers" + ;; + esac +fi + +if [ "${1}" == "vol" ];then +VOLSTEP=1 +if [ -n "${3}" ]; then + VOLSTEP="${3}" +fi + +CURRENTVOL=$(get_setting "audio.volume") +MAXVOL=100 +MINVOL=0 + if [ "${2}" == "+" ]; then + STEPVOL=$(($CURRENTVOL+$VOLSTEP)) + elif [ "${2}" == "-" ]; then + STEPVOL=$(($CURRENTVOL-$VOLSTEP)) + else + STEPVOL=${2} + fi + [ "$STEPVOL" -ge "$MAXVOL" ] && STEPVOL="$MAXVOL" + [ "$STEPVOL" -le "$MINVOL" ] && STEPVOL="$MINVOL" + amixer set "${DEVICE_AUDIO_MIXER}" ${STEPVOL}% + alsactl store -f /storage/.config/asound.state + set_setting "audio.volume" ${STEPVOL} + fi + +if [ "${1}" == "bright" ]; then +STEPS="5" +CURRENTBRIGHT=$(cat /sys/class/backlight/backlight/brightness) +MAXBRIGHT="100" #$(cat /sys/class/backlight/backlight/max_brightness) +MINBRIGHT="2" + if [ "${2}" == "+" ]; then + STEPBRIGHT=$(($CURRENTBRIGHT+$STEPS)) + elif [ "${2}" == "-" ]; then + STEPBRIGHT=$(($CURRENTBRIGHT-$STEPS)) + else + STEPBRIGHT=${2} + fi + [ "$STEPBRIGHT" -ge "$MAXBRIGHT" ] && STEPBRIGHT="$MAXBRIGHT" + [ "$STEPBRIGHT" -le "$MINBRIGHT" ] && STEPBRIGHT="$MINBRIGHT" + #echo "Setting bright to $STEPBRIGHT" + echo "${STEPBRIGHT}" > /sys/class/backlight/backlight/brightness + set_setting "system.brightness" $(cat /sys/class/backlight/backlight/brightness) +fi + + diff --git a/projects/Rockchip/packages/system-utils/sources/volume_sense b/projects/Rockchip/packages/system-utils/sources/volume_sense new file mode 100755 index 000000000..02a884316 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/sources/volume_sense @@ -0,0 +1,139 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-present Fewtarius +# 2021-present pkegg + +. /etc/profile + +set -e +set -o pipefail + +### Summary +# This script listens to volume keys on the RG351MP and adjusts volume +# Fn + Volume up/down will adjust brightness +### + + +# Event examples for reference +# type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1 +# type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1 + + +DEVICE='/dev/input/by-path/platform-volume-keys-event' # Device for volume key events + +CONTROLLER_DEVICE='/dev/input/by-path/platform-singleadc-joypad-event-joystick' # Joystick events (for Fn key) + +VOL_EVENT='*(KEY_VOLUME*, value *' # This matches all volume events + +VOL_UP='*UP), value *' # Differentiate 'up' volume event +VOL_DOWN='*DOWN), value *' #Differentiate 'down' volume event + +V_FUNC_KEY_EVENT='*(BTN_MODE), value *' # Matches all RG351MP Fn key events + +# Matches if a button was pressed (1), released (0) or held down (2) +PRESS='*value 1' +RELEASE='*value 0' +REPEAT_PRESS="* value 2" + +# Volume repeat +VOLUME_REPEAT_MOD=4 + +# Brightness repeat +BRIGHTNESS_REPEAT_MOD=4 + +# Variable to keep track of Fn being currently pressed +FUNC_PRESSED=no + +CONTROLLER_DISCONNECTED="*error reading: No such device" + +# Logic: +# - Listen to both: +# - 'rg351' events to get volume keys (not part of the joystick api) +# - 'joystick' events - as the V's 'fn' key is mapped to the joystick +# - Switch statement keeps high level cases to only 'volume' and 'V function key' +# this is to avoid processing for other events or creating a lot of cases as this will be called +# for all button pushes +# - Using 'read' means the loop is idle when no button is pressed + +# Wait for controller in case of restart, etc +while true; do +sleep 1 +if [[ ! -e "${CONTROLLER_DEVICE}" ]]; then + continue +else + break +fi + +done +( + evtest "${DEVICE}" & + evtest "${CONTROLLER_DEVICE}" 2>&1 & + wait +) | while read line; do + case $line in + (${CONTROLLER_DISCONNECTED}) + echo "Reloading due to controller reattach..." + exit 0 + ;; + (${VOL_EVENT}) + + # We don't care when you 'let go' ('release') the volume button + if [[ "$line" == ${RELEASE} ]]; then + REPEAT_NUM=0 + continue + fi + + # Setup for 'brightness' if Fn pressed + if [[ "${FUNC_PRESSED}" == "yes" ]]; then + COMMAND=/usr/bin/brightness + UP="up" + DOWN="down" + REPEAT_MOD=${BRIGHTNESS_REPEAT_MOD} + # Default to 'volume' if Fn is not pressed + else + COMMAND="/usr/bin/system_utils vol" + UP="+" + DOWN="-" + REPEAT_MOD=${VOLUME_REPEAT_MOD} + fi + + REPEAT_NUM=$(( ${REPEAT_NUM} + 1 )) + + # This isn't time to evaluate repeat so just skip + if [[ "$line" == ${REPEAT_PRESS} && $(( ${REPEAT_NUM} % ${REPEAT_MOD} )) != "0" ]]; then + continue + fi + + INCREMENT_AMOUNT=1 + if [[ "${REPEAT_NUM}" -gt "75" ]]; then + INCREMENT_AMOUNT=10 + elif [[ "${REPEAT_NUM}" -gt "25" ]]; then + INCREMENT_AMOUNT=5 + fi + # Run the commands to adjust volume/brightness + if [[ "${line}" == ${VOL_UP} ]]; then + ${COMMAND} ${UP} ${INCREMENT_AMOUNT} > /dev/null + elif [[ "${line}" == ${VOL_DOWN} ]]; then + ${COMMAND} ${DOWN} ${INCREMENT_AMOUNT} > /dev/null + fi + ;; + + (${V_FUNC_KEY_EVENT}) + + # We don't care about 'Fn' key repeats - continue + if [[ "$line" == ${REPEAT_PRESS} ]]; then + continue + fi + + #Reset the number of repeats when Fn is pressed/release + # as repeat speed is different between volume/brightness + REPEAT_NUM=0 + + if [[ "${line}" == ${PRESS} ]]; then + FUNC_PRESSED=yes + elif [[ "${line}" == ${RELEASE} ]]; then + FUNC_PRESSED=no + fi + ;; + esac +done diff --git a/projects/Rockchip/packages/system-utils/system.d/battery.service b/projects/Rockchip/packages/system-utils/system.d/battery.service new file mode 100644 index 000000000..128b15dd2 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/system.d/battery.service @@ -0,0 +1,13 @@ +[Unit] +Description=RG351 Low Power monitor +ConditionPathExists=/sys/class/power_supply/battery/capacity +Before=jelos.target + +[Service] +Environment=HOME=/storage +EnvironmentFile=/storage/.config/emulationstation/scripts/es_env.sh +ExecStart=/usr/bin/battery +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/projects/Rockchip/packages/system-utils/system.d/fancontrol.service b/projects/Rockchip/packages/system-utils/system.d/fancontrol.service new file mode 100644 index 000000000..e18831c8c --- /dev/null +++ b/projects/Rockchip/packages/system-utils/system.d/fancontrol.service @@ -0,0 +1,13 @@ +[Unit] +Description=Simple Fan Control Service +ConditionPathExists=/sys/class/hwmon/hwmon0/pwm1 +Before=jelos.target + +[Service] +Environment=HOME=/storage +EnvironmentFile=/etc/profile +ExecStart=/usr/bin/fancontrol +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/projects/Rockchip/packages/system-utils/system.d/headphones.service b/projects/Rockchip/packages/system-utils/system.d/headphones.service new file mode 100644 index 000000000..c399a76c7 --- /dev/null +++ b/projects/Rockchip/packages/system-utils/system.d/headphones.service @@ -0,0 +1,12 @@ +[Unit] +Description=Headphone Sense +Before=jelos.target + +[Service] +Environment=HOME=/storage +EnvironmentFile=/etc/profile +ExecStart=/usr/bin/headphone_sense +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/projects/Rockchip/packages/system-utils/system.d/volume.service b/projects/Rockchip/packages/system-utils/system.d/volume.service new file mode 100644 index 000000000..d3e30ea6c --- /dev/null +++ b/projects/Rockchip/packages/system-utils/system.d/volume.service @@ -0,0 +1,15 @@ +[Unit] +Description=Volume button service +After=headphones.service +Before=jelos.target +StartLimitIntervalSec=0 + +[Service] +Environment=HOME=/storage +EnvironmentFile=/etc/profile +ExecStart=/usr/bin/volume_sense +Restart=always +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/projects/Rockchip/packages/u-boot/package.mk b/projects/Rockchip/packages/u-boot/package.mk new file mode 100644 index 000000000..d383bcb95 --- /dev/null +++ b/projects/Rockchip/packages/u-boot/package.mk @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +PKG_NAME="u-boot" +PKG_ARCH="arm aarch64" +PKG_LICENSE="GPL" +PKG_SITE="https://github.com/rockchip-linux/u-boot" +PKG_DEPENDS_TARGET="toolchain swig:host rkbin" +PKG_LONGDESC="Rockchip U-Boot is a bootloader for embedded systems." +PKG_URL="https://github.com/JustEnoughLinuxOS/rockchip-uboot.git" +PKG_VERSION="543c8d3" +GET_HANDLER_SUPPORT="git" +PKG_GIT_CLONE_DEPTH="1" + +PKG_IS_KERNEL_PKG="yes" +PKG_STAMP="$UBOOT_SYSTEM" + +[ -n "$ATF_PLATFORM" ] && PKG_DEPENDS_TARGET+=" atf" + +PKG_NEED_UNPACK="$PROJECT_DIR/$PROJECT/bootloader" +[ -n "$DEVICE" ] && PKG_NEED_UNPACK+=" $PROJECT_DIR/$PROJECT/devices/$DEVICE/bootloader" + +PKG_PATCH_DIRS="patches/${DEVICE}" + +post_patch() { + if [ -n "$UBOOT_SYSTEM" ] && find_file_path bootloader/config; then + PKG_CONFIG_FILE="$PKG_BUILD/configs/$($ROOT/$SCRIPTS/uboot_helper $PROJECT $DEVICE $UBOOT_SYSTEM config)" + if [ -f "$PKG_CONFIG_FILE" ]; then + cat $FOUND_PATH >> "$PKG_CONFIG_FILE" + fi + fi +} + +make_target() { + if [ -z "$UBOOT_SYSTEM" ]; then + echo "UBOOT_SYSTEM must be set to build an image" + echo "see './scripts/uboot_helper' for more information" + else + [ "${BUILD_WITH_DEBUG}" = "yes" ] && PKG_DEBUG=1 || PKG_DEBUG=0 + [ -n "${ATF_PLATFORM}" ] && cp -av $(get_build_dir atf)/bl31.bin . + DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm make mrproper + DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm make $($ROOT/$SCRIPTS/uboot_helper $PROJECT $DEVICE $UBOOT_SYSTEM config) + DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm _python_sysroot="$TOOLCHAIN" _python_prefix=/ _python_exec_prefix=/ make HOSTCC="$HOST_CC" HOSTLDFLAGS="-L$TOOLCHAIN/lib" HOSTSTRIP="true" CONFIG_MKIMAGE_DTC_PATH="scripts/dtc/dtc" + fi +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/bootloader + # Only install u-boot.img et al when building a board specific image + if [ -n "${UBOOT_SYSTEM}" ]; then + find_file_path bootloader/install && . ${FOUND_PATH} + fi + + # Always install the update script + find_file_path bootloader/update.sh && cp -av ${FOUND_PATH} $INSTALL/usr/share/bootloader + + # Always install the canupdate script + if find_file_path bootloader/canupdate.sh; then + cp -av ${FOUND_PATH} $INSTALL/usr/share/bootloader + sed -e "s/@PROJECT@/${DEVICE:-$PROJECT}/g" \ + -i $INSTALL/usr/share/bootloader/canupdate.sh + fi +} diff --git a/projects/Rockchip/patches/libdrm/libdrm-0001-add-rochchip-10bits-formats.patch b/projects/Rockchip/patches/libdrm/libdrm-0001-add-rochchip-10bits-formats.patch new file mode 100644 index 000000000..a31a51062 --- /dev/null +++ b/projects/Rockchip/patches/libdrm/libdrm-0001-add-rochchip-10bits-formats.patch @@ -0,0 +1,16 @@ +--- ./include/drm/drm_fourcc.h 2017-09-04 10:45:05.812784940 -0700 ++++ ./include/drm/drm_fourcc.h 2017-09-04 10:45:27.831516420 -0700 +@@ -116,6 +116,13 @@ + #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ + #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ + ++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2') /* 2x2 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV21_10 fourcc_code('N', 'A', '2', '1') /* 2x2 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV16_10 fourcc_code('N', 'A', '1', '6') /* 2x1 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV61_10 fourcc_code('N', 'A', '6', '1') /* 2x1 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV24_10 fourcc_code('N', 'A', '2', '4') /* non-subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV42_10 fourcc_code('N', 'A', '4', '2') /* non-subsampled Cb:Cr plane */ ++ + /* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y diff --git a/scripts/autoreconf b/scripts/autoreconf new file mode 100755 index 000000000..26cc2ca1b --- /dev/null +++ b/scripts/autoreconf @@ -0,0 +1,35 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +if [ ! -f "${PKG_BUILD}/configure.in" \ + -a ! -f "${PKG_BUILD}/configure.ac" ]; then + die "configure.in or configure.ac not found" +fi + +if [ ! -f "${PKG_BUILD}/.autoreconf-done" ]; then + PARENT_PKG="${2}" + + # lock package during autoreconf otherwise it is racy, eg. glib:host/glib:target building concurrently + pkg_lock "${PKG_NAME}" "reconf" "${PARENT_PKG}" + + if [ ! -f "${PKG_BUILD}/.autoreconf-done" ]; then + pkg_lock_status "ACTIVE" "${PKG_NAME}" "reconf" + + touch "${PKG_BUILD}/NEWS" "${PKG_BUILD}/AUTHORS" "${PKG_BUILD}/ChangeLog" + mkdir -p "${PKG_BUILD}/m4" + + build_msg "CLR_AUTORECONF" "AUTORECONF" "${PKG_NAME}" "indent" + + do_autoreconf "${PKG_BUILD}" + touch "${PKG_BUILD}/.autoreconf-done" + + pkg_lock_status "UNLOCK" "${PKG_NAME}" "reconf" "configured" + else + pkg_lock_status "UNLOCK" "${PKG_NAME}" "reconf" "already configured" + fi +fi diff --git a/scripts/build b/scripts/build new file mode 100755 index 000000000..7eed9b895 --- /dev/null +++ b/scripts/build @@ -0,0 +1,496 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +if [ -z "${1}" ]; then + die "usage: ${0} package_name[:] [parent_pkg]" +fi + +if [ "${1}" = "--all" ]; then + if [ -n "${2}" ]; then + for build_dir in $(ls -1d ${ROOT}/build.*); do + load_build_config ${build_dir} && ${SCRIPTS}/build "${2}" + done + fi + exit 0 +fi + +if [ -z "${PKG_NAME}" ]; then + die "$(print_color CLR_ERROR "${1}: no package.mk file found")" +fi + +if [ -n "${PKG_ARCH}" ]; then + listcontains "${PKG_ARCH}" "!${TARGET_ARCH}" && exit 0 + listcontains "${PKG_ARCH}" "${TARGET_ARCH}" || listcontains "${PKG_ARCH}" "any" || exit 0 +fi + +if [ "${1//:/}" != "${1}" ]; then + TARGET="${1#*:}" +else + TARGET= +fi +TARGET="${TARGET:-target}" +PARENT_PKG="${2:-${PKG_NAME}:${TARGET}}" + +pkg_lock "${PKG_NAME}:${TARGET}" "build" "${PARENT_PKG}" + +mkdir -p ${STAMPS}/${PKG_NAME} +STAMP=${STAMPS}/${PKG_NAME}/build_${TARGET} +if [ -f ${STAMP} ]; then + . ${STAMP} + PKG_DEEPHASH=$(calculate_stamp) + + if [ "${PKG_DEEPHASH}" = "${STAMP_PKG_DEEPHASH}" -a "${BUILD_WITH_DEBUG}" = "${STAMP_BUILD_WITH_DEBUG}" ]; then + # stamp matched: already built, do nothing + pkg_lock_status "UNLOCK" "${PKG_NAME}:${TARGET}" "build" "already built" + exit 0 + fi + + rm -f ${STAMP} +fi + +${SCRIPTS}/unpack "${PKG_NAME}" "${PARENT_PKG}" + +# build dependencies, only when PKG_DEPENDS_? is filled +unset _pkg_depends +case "${TARGET}" in + "target") _pkg_depends="${PKG_DEPENDS_TARGET}";; + "host") _pkg_depends="${PKG_DEPENDS_HOST}";; + "init") _pkg_depends="${PKG_DEPENDS_INIT}";; + "bootstrap") _pkg_depends="${PKG_DEPENDS_BOOTSTRAP}";; +esac +for p in ${_pkg_depends}; do + ${SCRIPTS}/build "${p}" "${PARENT_PKG}" +done + +# virtual packages are not built as they only contain dependencies, so dont go further here +if [ "${PKG_SECTION}" = "virtual" ]; then + PKG_DEEPHASH=$(calculate_stamp) + for i in PKG_NAME PKG_DEEPHASH BUILD_WITH_DEBUG; do + echo "STAMP_${i}=\"${!i}\"" >> ${STAMP} + done + + pkg_lock_status "UNLOCK" "${PKG_NAME}:${TARGET}" "build" "built" + exit 0 +fi + +# build this package +if [ "${BUILD_WITH_DEBUG}" = "yes" ]; then + build_msg "CLR_BUILD" "BUILD" "${PKG_NAME} $(print_color "CLR_TARGET" "(${TARGET})") [DEBUG]" "indent" +else + build_msg "CLR_BUILD" "BUILD" "${PKG_NAME} $(print_color "CLR_TARGET" "(${TARGET})")" "indent" +fi + +setup_toolchain ${TARGET} + +# configure install directory +if [ "${TARGET}" = "target" ]; then + INSTALL="${PKG_BUILD}/.install_pkg" +elif [ "${TARGET}" = "init" ]; then + INSTALL="${PKG_BUILD}/.install_init" +else + unset INSTALL +fi +# remove previous install files +if [ -n "${INSTALL}" -a -d "${INSTALL}" ]; then + rm -rf "${INSTALL}" +fi + +# configure debug build defaults +if [ "${BUILD_WITH_DEBUG}" = "yes" ]; then + CMAKE_BUILD_TYPE="Debug" + MESON_BUILD_TYPE="debug" +else + CMAKE_BUILD_TYPE="MinSizeRel" + MESON_BUILD_TYPE="plain" +fi + +CMAKE_GENERATOR_NINJA="-GNinja \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" + +# configure TARGET build defaults +TARGET_CONFIGURE_OPTS="--host=${TARGET_NAME} \ + --build=${HOST_NAME} \ + --prefix=/usr \ + --bindir=/usr/bin \ + --sbindir=/usr/sbin \ + --sysconfdir=/etc \ + --libdir=/usr/lib \ + --libexecdir=/usr/lib \ + --localstatedir=/var \ + --disable-static \ + --enable-shared" + +TARGET_CMAKE_OPTS="-DCMAKE_TOOLCHAIN_FILE=${CMAKE_CONF} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + +TARGET_MESON_OPTS="--prefix=/usr \ + --bindir=/usr/bin \ + --sbindir=/usr/sbin \ + --sysconfdir=/etc \ + --libdir=/usr/lib \ + --libexecdir=/usr/lib \ + --localstatedir=/var \ + --buildtype=${MESON_BUILD_TYPE}" + +# configure HOST build defaults +HOST_CONFIGURE_OPTS="--host=${HOST_NAME} \ + --build=${HOST_NAME} \ + --prefix=${TOOLCHAIN} \ + --bindir=${TOOLCHAIN}/bin \ + --sbindir=${TOOLCHAIN}/sbin \ + --sysconfdir=${TOOLCHAIN}/etc \ + --libexecdir=${TOOLCHAIN}/lib \ + --localstatedir=${TOOLCHAIN}/var \ + --disable-static \ + --enable-shared" + +HOST_CMAKE_OPTS="${CMAKE_GENERATOR} \ + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CONF} \ + -DCMAKE_INSTALL_PREFIX=${TOOLCHAIN}" + +HOST_MESON_OPTS="--prefix=${TOOLCHAIN} \ + --bindir=${TOOLCHAIN}/bin \ + --sbindir=${TOOLCHAIN}/sbin \ + --sysconfdir=${TOOLCHAIN}/etc \ + --libdir=${TOOLCHAIN}/lib \ + --libexecdir=${TOOLCHAIN}/lib \ + --localstatedir=${TOOLCHAIN}/var \ + --buildtype=plain" + +# configure INIT build defaults +INIT_CONFIGURE_OPTS="${TARGET_CONFIGURE_OPTS}" +INIT_CMAKE_OPTS="${TARGET_CMAKE_OPTS}" +INIT_MESON_OPTS="${TARGET_MESON_OPTS}" + +# configure BOOTSTRAP build defaults +BOOTSTRAP_CONFIGURE_OPTS="${HOST_CONFIGURE_OPTS}" +BOOTSTRAP_CMAKE_OPTS="${HOST_CMAKE_OPTS}" +BOOTSTRAP_MESON_OPTS="${HOST_MESON_OPTS}" + +# setup configure scripts +PKG_CONFIGURE_SCRIPT="${PKG_CONFIGURE_SCRIPT:-${PKG_BUILD}/configure}" +PKG_CMAKE_SCRIPT="${PKG_CMAKE_SCRIPT:-${PKG_BUILD}/CMakeLists.txt}" +PKG_MESON_SCRIPT="${PKG_MESON_SCRIPT:-${PKG_BUILD}/meson.build}" + +# auto detect toolchain +_auto_toolchain="" +if [ -z "${PKG_TOOLCHAIN}" -o "${PKG_TOOLCHAIN}" = "auto" ]; then + if [ -f "${PKG_MESON_SCRIPT}" ]; then + PKG_TOOLCHAIN="meson" + elif [ -f "${PKG_CMAKE_SCRIPT}" ]; then + PKG_TOOLCHAIN="cmake" + elif [ -f "${PKG_CONFIGURE_SCRIPT}" ]; then + PKG_TOOLCHAIN="configure" + elif [ -f "${PKG_BUILD}/Makefile" ]; then + PKG_TOOLCHAIN="make" + else + die "Not possible to detect toolchain automatically. Add PKG_TOOLCHAIN= to package.mk" + fi + _auto_toolchain=" (auto-detect)" +fi +if ! listcontains "meson cmake cmake-make configure ninja make autotools manual" "${PKG_TOOLCHAIN}"; then + die "$(print_color "CLR_ERROR" "ERROR:") unknown toolchain ${PKG_TOOLCHAIN}" +fi +build_msg "CLR_TOOLCHAIN" "TOOLCHAIN" "${PKG_TOOLCHAIN}${_auto_toolchain}" + +# make autoreconf +if [ "${PKG_TOOLCHAIN}" = "autotools" ]; then + ${SCRIPTS}/autoreconf "${PKG_NAME}" "${PARENT_PKG}" +fi + +pkg_lock_status "ACTIVE" "${PKG_NAME}:${TARGET}" "build" + +# include build template and build +pkg_call_exists pre_build_${TARGET} && pkg_call pre_build_${TARGET} + +# ensure ${PKG_BUILD} is there. (installer? PKG_URL="") +mkdir -p "${PKG_BUILD}" + +cd "${PKG_BUILD}" + +if [ -f "${PKG_CONFIGURE_SCRIPT}" -o -f "${PKG_CMAKE_SCRIPT}" -o -f "${PKG_MESON_SCRIPT}" ]; then + case "${TARGET}" in + "target") PKG_REAL_BUILD="${PKG_BUILD}/.${TARGET_NAME}" ;; + "host") PKG_REAL_BUILD="${PKG_BUILD}/.${HOST_NAME}" ;; + "init") PKG_REAL_BUILD="${PKG_BUILD}/.${TARGET_NAME}-${TARGET}" ;; + "bootstrap") PKG_REAL_BUILD="${PKG_BUILD}/.${HOST_NAME}-${TARGET}" ;; + esac + mkdir -p "${PKG_REAL_BUILD}" + cd "${PKG_REAL_BUILD}" + + MESON_CONF="${PKG_REAL_BUILD}/meson.conf" +fi + +# configure +pkg_call_exists pre_configure && pkg_call pre_configure +pkg_call_exists pre_configure_${TARGET} && pkg_call pre_configure_${TARGET} + +if pkg_call_exists configure_${TARGET}; then + pkg_call configure_${TARGET} +else + case "${PKG_TOOLCHAIN}:${TARGET}" in + # meson builds + "meson:target") + create_meson_conf ${TARGET} ${MESON_CONF} + echo "Executing (target): meson ${TARGET_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_TARGET} $(dirname ${PKG_MESON_SCRIPT})" | tr -s " " + CC="${HOST_CC}" CXX="${HOST_CXX}" meson ${TARGET_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_TARGET} $(dirname ${PKG_MESON_SCRIPT}) + ;; + "meson:host") + create_meson_conf ${TARGET} ${MESON_CONF} + echo "Executing (host): meson ${HOST_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_HOST} $(dirname ${PKG_MESON_SCRIPT})" | tr -s " " + meson ${HOST_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_HOST} $(dirname ${PKG_MESON_SCRIPT}) + ;; + "meson:init") + create_meson_conf ${TARGET} ${MESON_CONF} + echo "Executing (init): meson ${INIT_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_INIT} $(dirname ${PKG_MESON_SCRIPT})" | tr -s " " + meson ${INIT_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_INIT} $(dirname ${PKG_MESON_SCRIPT}) + ;; + "meson:bootstrap") + create_meson_conf ${TARGET} ${MESON_CONF} + echo "Executing (bootstrap): meson ${BOOTSTRAP_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_BOOTSTRAP} $(dirname ${PKG_MESON_SCRIPT})" | tr -s " " + meson ${BOOTSTRAP_MESON_OPTS} --cross-file=${MESON_CONF} ${PKG_MESON_OPTS_BOOTSTRAP} $(dirname ${PKG_MESON_SCRIPT}) + ;; + + # cmake builds with ninja + "cmake:target") + echo "Executing (target): cmake ${CMAKE_GENERATOR_NINJA} ${TARGET_CMAKE_OPTS} ${PKG_CMAKE_OPTS_TARGET} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${CMAKE_GENERATOR_NINJA} ${TARGET_CMAKE_OPTS} ${PKG_CMAKE_OPTS_TARGET} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake:host") + echo "Executing (host): cmake ${CMAKE_GENERATOR_NINJA} ${HOST_CMAKE_OPTS} ${PKG_CMAKE_OPTS_HOST} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${CMAKE_GENERATOR_NINJA} ${HOST_CMAKE_OPTS} ${PKG_CMAKE_OPTS_HOST} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake:init") + echo "Executing (init): cmake ${CMAKE_GENERATOR_NINJA} ${INIT_CMAKE_OPTS} ${PKG_CMAKE_OPTS_INIT} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${CMAKE_GENERATOR_NINJA} ${INIT_CMAKE_OPTS} ${PKG_CMAKE_OPTS_INIT} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake:bootstrap") + echo "Executing (bootstrap): cmake ${CMAKE_GENERATOR_NINJA} ${BOOTSTRAP_CMAKE_OPTS} ${PKG_CMAKE_OPTS_BOOTSTRAP} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${CMAKE_GENERATOR_NINJA} ${BOOTSTRAP_CMAKE_OPTS} ${PKG_CMAKE_OPTS_BOOTSTRAP} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + + # cmake builds with make + "cmake-make:target") + echo "Executing (target): cmake ${TARGET_CMAKE_OPTS} ${PKG_CMAKE_OPTS_TARGET} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${TARGET_CMAKE_OPTS} ${PKG_CMAKE_OPTS_TARGET} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake-make:host") + echo "Executing (host): cmake ${HOST_CMAKE_OPTS} ${PKG_CMAKE_OPTS_HOST} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${HOST_CMAKE_OPTS} ${PKG_CMAKE_OPTS_HOST} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake-make:init") + echo "Executing (init): cmake ${INIT_CMAKE_OPTS} ${PKG_CMAKE_OPTS_INIT} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${INIT_CMAKE_OPTS} ${PKG_CMAKE_OPTS_INIT} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + "cmake-make:bootstrap") + echo "Executing (bootstrap): cmake ${BOOTSTRAP_CMAKE_OPTS} ${PKG_CMAKE_OPTS_BOOTSTRAP} $(dirname ${PKG_CMAKE_SCRIPT})" | tr -s " " + cmake ${BOOTSTRAP_CMAKE_OPTS} ${PKG_CMAKE_OPTS_BOOTSTRAP} $(dirname ${PKG_CMAKE_SCRIPT}) + ;; + + # configure builds + "configure:target"|"autotools:target") + echo "Executing (target): ${PKG_CONFIGURE_SCRIPT} ${TARGET_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_TARGET}" | tr -s " " + ${PKG_CONFIGURE_SCRIPT} ${TARGET_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_TARGET} + ;; + "configure:host"|"autotools:host") + echo "Executing (host): ${PKG_CONFIGURE_SCRIPT} ${HOST_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_HOST}" | tr -s " " + ${PKG_CONFIGURE_SCRIPT} ${HOST_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_HOST} + ;; + "configure:init"|"autotools:init") + echo "Executing (init): ${PKG_CONFIGURE_SCRIPT} ${INIT_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_INIT}" | tr -s " " + ${PKG_CONFIGURE_SCRIPT} ${INIT_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_INIT} + ;; + "configure:bootstrap"|"autotools:bootstrap") + echo "Executing (bootstrap): ${PKG_CONFIGURE_SCRIPT} ${BOOTSTRAP_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_BOOTSTRAP}" | tr -s " " + ${PKG_CONFIGURE_SCRIPT} ${BOOTSTRAP_CONFIGURE_OPTS} ${PKG_CONFIGURE_OPTS_BOOTSTRAP} + ;; + esac +fi + +pkg_call_exists post_configure_${TARGET} && pkg_call post_configure_${TARGET} + +# make +pkg_call_exists pre_make_${TARGET} && pkg_call pre_make_${TARGET} + +if pkg_call_exists make_${TARGET}; then + pkg_call make_${TARGET} +else + case "${PKG_TOOLCHAIN}:${TARGET}" in + # ninja based builds + "meson:target"|"cmake:target"|"ninja:target") + echo "Executing (target): ninja ${PKG_MAKE_OPTS_TARGET}" | tr -s " " + ninja ${NINJA_OPTS} ${PKG_MAKE_OPTS_TARGET} + ;; + "meson:host"|"cmake:host"|"ninja:host") + echo "Executing (host): ninja ${PKG_MAKE_OPTS_HOST}" | tr -s " " + ninja ${NINJA_OPTS} ${PKG_MAKE_OPTS_HOST} + ;; + "meson:init"|"cmake:init"|"ninja:init") + echo "Executing (init): ninja ${PKG_MAKE_OPTS_INIT}" | tr -s " " + ninja ${NINJA_OPTS} ${PKG_MAKE_OPTS_INIT} + ;; + "meson:bootstrap"|"cmake:bootstrap"|"ninja:bootstrap") + echo "Executing (bootstrap): ninja ${PKG_MAKE_OPTS_BOOTSTRAP}" | tr -s " " + ninja ${NINJA_OPTS} ${PKG_MAKE_OPTS_BOOTSTRAP} + ;; + + # make based builds + "configure:target"|"cmake-make:target"|"autotools:target"|"make:target") + echo "Executing (target): make ${PKG_MAKE_OPTS_TARGET}" | tr -s " " + make ${PKG_MAKE_OPTS_TARGET} + ;; + "configure:host"|"cmake-make:host"|"autotools:host"|"make:host") + echo "Executing (host): make ${PKG_MAKE_OPTS_HOST}" | tr -s " " + make ${PKG_MAKE_OPTS_HOST} + ;; + "configure:init"|"cmake-make:init"|"autotools:init"|"make:init") + echo "Executing (init): make ${PKG_MAKE_OPTS_INIT}" | tr -s " " + make ${PKG_MAKE_OPTS_INIT} + ;; + "configure:bootstrap"|"cmake-make:bootstrap"|"autotools:bootstrap"|"make:bootstrap") + echo "Executing (bootstrap): make ${PKG_MAKE_OPTS_BOOTSTRAP}" | tr -s " " + make ${PKG_MAKE_OPTS_BOOTSTRAP} + ;; + esac +fi + +pkg_call_exists post_make_${TARGET} && pkg_call post_make_${TARGET} + +# Hack around directly writing/modifying the content of a shared sysroot +# by temporarily installing new files to a package specific sysroot +PKG_ORIG_SYSROOT_PREFIX="${SYSROOT_PREFIX}" +export SYSROOT_PREFIX="${BUILD}/.sysroot/${PKG_NAME}.${TARGET}" +rm -rf "${SYSROOT_PREFIX}" + +# Create common sysroot directories as some packages expect them to exist. +# TODO: Fix those packages so we don't need to pre-create directories. +for d in /usr/lib /usr/include /usr/bin /usr/lib/pkgconfig; do + mkdir -p "${SYSROOT_PREFIX}${d}" +done + +# make install +pkg_call_exists pre_makeinstall_${TARGET} && pkg_call pre_makeinstall_${TARGET} + +if pkg_call_exists makeinstall_${TARGET}; then + pkg_call makeinstall_${TARGET} +else + case "${PKG_TOOLCHAIN}:${TARGET}" in + # ninja based builds + "meson:target"|"cmake:target") + DESTDIR=${SYSROOT_PREFIX} ninja install ${PKG_MAKEINSTALL_OPTS_TARGET} + DESTDIR=${INSTALL} ninja install ${PKG_MAKEINSTALL_OPTS_TARGET} + ;; + "meson:host"|"cmake:host") + ninja install ${PKG_MAKEINSTALL_OPTS_HOST} + ;; + "meson:init"|"cmake:init") + DESTDIR=${INSTALL} ninja install ${PKG_MAKEINSTALL_OPTS_INIT} + ;; + "meson:bootstrap"|"cmake:bootstrap") + ninja install ${PKG_MAKEINSTALL_OPTS_BOOTSTRAP} + ;; + + # make based builds + "configure:target"|"cmake-make:target"|"autotools:target"|"make:target") + make install DESTDIR=${SYSROOT_PREFIX} -j1 ${PKG_MAKEINSTALL_OPTS_TARGET} + make install DESTDIR=${INSTALL} ${PKG_MAKEINSTALL_OPTS_TARGET} + ;; + "configure:host"|"cmake-make:host"|"autotools:host"|"make:host") + make install ${PKG_MAKEINSTALL_OPTS_HOST} + ;; + "configure:init"|"cmake-make:init"|"autotools:init"|"make:init") + make install DESTDIR=${INSTALL} ${PKG_MAKEINSTALL_OPTS_INIT} + ;; + "configure:bootstrap"|"cmake-make:bootstrap"|"autotools:bootstrap"|"make:bootstrap") + make install ${PKG_MAKEINSTALL_OPTS_BOOTSTRAP} + ;; + esac +fi + +pkg_call_exists post_makeinstall_${TARGET} && pkg_call post_makeinstall_${TARGET} + +# Fixup temporary sysroot references to the shared sysroot +for i in $(find "${SYSROOT_PREFIX}/usr/lib" -type f -name "*.la" 2>/dev/null); do + sed -e "s:\(['= ]\)/usr:\\1${PKG_ORIG_SYSROOT_PREFIX}/usr:g" -i "${i}" +done +for i in $(find "${SYSROOT_PREFIX}/usr/bin" -type f -name "*-config" 2>/dev/null); do + sed -e "s#${SYSROOT_PREFIX}/usr#${PKG_ORIG_SYSROOT_PREFIX}/usr#g" -i "${i}" +done +for i in $(find "${SYSROOT_PREFIX}/usr/lib" -type f -name "*.pc" 2>/dev/null); do + sed -e "s#${SYSROOT_PREFIX}/usr#${PKG_ORIG_SYSROOT_PREFIX}/usr#g" -i "${i}" +done +for i in $(find "${SYSROOT_PREFIX}/usr"/{lib,share} -type f -name "*.cmake" 2>/dev/null); do + sed -e "s#${SYSROOT_PREFIX}/usr#${PKG_ORIG_SYSROOT_PREFIX}/usr#g" -i "${i}" +done +for i in $(find "${SYSROOT_PREFIX}" -type l 2>/dev/null); do + _tmp="$(readlink -m "${i}")" + [[ ${_tmp} =~ ^/usr ]] && _tmp="${SYSROOT_PREFIX}${_tmp}" + if [[ ${_tmp} =~ ^${SYSROOT_PREFIX}/ ]]; then + ln -sfn "${_tmp/${SYSROOT_PREFIX}\//${PKG_ORIG_SYSROOT_PREFIX}\/}" "${i}" + fi +done + +# Transfer the new sysroot content to the shared sysroot +mkdir -p "${PKG_ORIG_SYSROOT_PREFIX}" +cp -PRf "${SYSROOT_PREFIX}"/* "${PKG_ORIG_SYSROOT_PREFIX}" +rm -rf "${SYSROOT_PREFIX}" + +export SYSROOT_PREFIX="${PKG_ORIG_SYSROOT_PREFIX}" + +if [ "${TARGET}" = "target" -o "${TARGET}" = "init" ]; then + if [ -d ${INSTALL} ]; then + rm -rf ${INSTALL}/{usr/,}include + rm -rf ${INSTALL}/{usr/,}lib/cmake + rm -rf ${INSTALL}/{usr/,}lib/pkgconfig + rm -rf ${INSTALL}/{usr/,}man + rm -rf ${INSTALL}/{usr/,}share/aclocal + rm -rf ${INSTALL}/{usr/,}share/bash-completion + rm -rf ${INSTALL}/{usr/,}share/doc + rm -rf ${INSTALL}/{usr/,}share/gtk-doc + rm -rf ${INSTALL}/{usr/,}share/info + rm -rf ${INSTALL}/{usr/,}share/locale + rm -rf ${INSTALL}/{usr/,}share/man + rm -rf ${INSTALL}/{usr/,}share/pkgconfig + rm -rf ${INSTALL}/{usr/,}share/zsh + rm -rf ${INSTALL}/{usr/,}var + find ${INSTALL} \( -name "*.orig" \ + -o -name "*.rej" \ + -o -name "*.a" \ + -o -name "*.la" \ + -o -name "*.o" \ + -o -name "*.in" \ + -o -name ".git*" \) \ + -exec rm -f {} \; 2>/dev/null || : + find ${INSTALL} -type d -exec rmdir -p {} \; 2>/dev/null || : + + if [ ! "${BUILD_WITH_DEBUG}" = "yes" ]; then + ${STRIP} $(find ${INSTALL} \ + -type f -name "*.so*" \ + ! -name "ld-*.so" \ + ! -name "libc-*.so" \ + ! -name "libpthread-*.so" \ + ! -name "libthread_db-*so" \ + 2>/dev/null) 2>/dev/null || : + if [ "${TARGET}" = "init" ]; then + ${STRIP} $(find ${INSTALL} -type f -name "*.so*" 2>/dev/null) 2>/dev/null || : + fi + ${STRIP} $(find ${INSTALL} ! -name "*.so*" ! -name "*.ko" \ + -type f -executable 2>/dev/null) 2>/dev/null || : + fi + fi +fi + +cd ${ROOT} + +PKG_DEEPHASH=$(calculate_stamp) +for i in PKG_NAME PKG_DEEPHASH BUILD_WITH_DEBUG; do + echo "STAMP_${i}=\"${!i}\"" >> ${STAMP} +done + +pkg_lock_status "UNLOCK" "${PKG_NAME}:${TARGET}" "build" "built" diff --git a/scripts/build_distro b/scripts/build_distro new file mode 100755 index 000000000..95467e88c --- /dev/null +++ b/scripts/build_distro @@ -0,0 +1,58 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +### +### Simple script to build JELOS +### + +if [ !"${ARCH}" == true ] +then + echo "export ARCH before building." + exit 1 +fi + +export OS_VERSION=$(date +%Y%m%d) +export BUILD_DATE=$(date) +export DISTRO=JELOS +export PROJECT=Rockchip + +echo "Building ${DISTRO} for ${DEVICE}" +if [ ! -d "target" ] +then + mkdir target +fi + +# If this variable exists in the environment, expand it and clean those packages too. +PKG_CLEAN="${PKG_CLEAN} emulationstation retroarch lib32 jelos" + +# Clean a few packages to ensure the build date and version are updated +for package in ${PKG_CLEAN} +do + ./scripts/clean ${package} +done + +if [ "${ARCH}" == "aarch64" ] +then + make image +elif [ "${ARCH}" == "arm" ] +then + make system + scripts/install arm32 +fi + +if [ ! $? == 0 ] +then + echo "Build failed..exiting." + exit 1 +fi + +if [ "${ARCH}" == "aarch64" ] +then + if [ -d "release/${ARCH}/${DEVICE}" ] + then + rm -rf "release/${ARCH}/${DEVICE}" + fi +mkdir -p release/${ARCH}/${DEVICE} +mv target/* "release/${ARCH}/${DEVICE}/" +fi diff --git a/scripts/build_mt b/scripts/build_mt new file mode 100755 index 000000000..d7b35168d --- /dev/null +++ b/scripts/build_mt @@ -0,0 +1,16 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +. config/options "" +. config/multithread + +${SCRIPTS}/checkdeps + +# Setup both toolchain cmake configs to avoid potentially racy behaviour later. +# Use a fork for host to isolate any variable modifications. +( setup_toolchain host ) +setup_toolchain target + +MTADDONBUILD=no start_multithread_build ${@} diff --git a/scripts/ccache_stats b/scripts/ccache_stats new file mode 100755 index 000000000..8aadc6149 --- /dev/null +++ b/scripts/ccache_stats @@ -0,0 +1,9 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +. config/options "" + +${TOOLCHAIN}/bin/ccache -s diff --git a/scripts/checkdeps b/scripts/checkdeps new file mode 100755 index 000000000..8267d7895 --- /dev/null +++ b/scripts/checkdeps @@ -0,0 +1,186 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +. config/options "" + +get_deps() { + need=() + need_pkg=() + + for i in "${!deps[@]}"; do + dep=${deps[${i}]} + dep_pkg=${deps_pkg[${i}]} + if ! command -v "${dep}" >/dev/null; then + need+=(${dep}) + need_pkg+=("${dep_pkg}") + fi + done + + for i in "${!files[@]}"; do + file=${files[${i}]} + file_pkg=${files_pkg[${i}]} + if [ ! -f "${file}" ]; then + need+=(${file}) + need_pkg+=("${file_pkg}") + fi + done + + for i in "${!perl_mod[@]}"; do + mod=${perl_mod[${i}]} + pkg=${perl_pkg[${i}]} + + if ! perl -M"${mod}" -e exit 2>/dev/null; then + need+=(perl::${mod}) + need_pkg+=(${pkg}) + fi + done +} + +get_yes_no() +{ + local ans + read -p "Would you like to install the needed tools? (y/n) " ans + [ "${ans,,}" = "y" ] && return 0 + [ "${ans,,}" = "yes" ] && return 0 + return 1 +} + +if [ -f /etc/lsb-release ]; then + DISTRO=$(grep DISTRIB_ID /etc/lsb-release | cut -d "=" -f 2) +fi + +if [ -f /etc/os-release ]; then + DISTRO=$(grep ^ID= /etc/os-release | cut -d "=" -f 2) +fi + +DISTRO=${DISTRO,,} + +deps=(wget bash bc gcc sed patch lsdiff tar bzip2 gzip perl gawk gperf zip unzip diff lzop go) +deps_pkg=(wget bash bc gcc sed patch patchutils tar bzip2 gzip perl gawk gperf zip unzip diffutils lzop golang curl libssl-dev patchelf) + +files=(/usr/include/stdio.h /usr/include/ncurses.h) +files_pkg=(libc6-dev libncurses5-dev) + +perl_mod=(JSON XML::Parser) + +case "${DISTRO}" in + fedora|centos|rhel) + deps+=(g++ mkfontscale mkfontdir bdftopcf xsltproc java python) + deps_pkg+=(gcc-c++ xorg-x11-font-utils xorg-x11-font-utils xorg-x11-font-utils libxslt java-1.7.0-openjdk python2) + if [[ ! $(rpm -qa glibc-static) ]]; then + deps+=(glibc-static) + deps_pkg+=(glibc-static) + fi + if [[ ! $(rpm -qa libstdc++-static) ]]; then + deps+=(libstdc++-static) + deps_pkg+=(libstdc++-static) + fi + files_pkg=(glibc-headers ncurses-devel) + perl_pkg=(perl-JSON perl-XML-parser) + ;; + gentoo|sabayon) + deps+=(g++ mkfontscale mkfontdir bdftopcf xsltproc java python) + deps_pkg+=("gcc[cxx]" mkfontscale mkfontdir bdftopcf libxslt virtual/jre python) + files_pkg=(glibc ncurses) + perl_pkg=(JSON XML-Parser) + ;; + arch|manjaro) + deps+=(g++ mkfontscale mkfontdir bdftopcf xsltproc java python) + deps_pkg+=(g++ xorg-mkfontscale xorg-mkfontdir xorg-bdftopcf libxslt "java-runtime-common jdk8-openjdk" python2) + perl_pkg=(perl-json perl-xml-parser) + ;; + opensuse) + deps+=( g++ mkfontscale mkfontdir bdftopcf xsltproc java python) + deps_pkg+=(gcc-c++ mkfontscale mkfontdir bdftopcf libxslt-tools java-1_8_0-openjdk python) + if [[ ! $(rpm -qa glibc-devel-static) ]]; then + deps+=(glibc-devel-static) + deps_pkg+=(glibc-devel-static) + fi + perl_pkg=(perl-JSON perl-XML-Parser) + ;; + *) + deps+=(g++ mkfontscale mkfontdir bdftopcf xsltproc java python) + deps_pkg+=(g++ xfonts-utils xsltproc default-jre python) + perl_pkg=(libjson-perl libxml-parser-perl) + ;; +esac + +# project specific dependencies +if [ -n "${EXTRA_DEPS}" ] ; then + deps+=(${EXTRA_DEPS}) +fi +if [ -n "${EXTRA_DEPS_PKG}" ] ; then + deps_pkg+=(${EXTRA_DEPS_PKG}) +fi + +# distro specific dependencies +if [ -n "${DISTRO_DEPS}" ] ; then + deps+=(${DISTRO_DEPS}) +fi +if [ -n "${DISTRO_DEPS_PKG}" ] ; then + deps_pkg+=(${DISTRO_DEPS_PKG}) +fi + +# aarch64 dependencies +if [ "$(uname -m)" == "aarch64" ]; then + deps+=(qemu-x86_64) + deps_pkg+=(qemu-user-binfmt) +fi + +get_deps + +if [ "${#need[@]}" -gt 0 ]; then + echo "**** Your system lacks the following tools needed to build ${DISTRONAME} ****" + for i in "${!need[@]}"; do + echo "${need[${i}]} provided by ${need_pkg[${i}]}" + done + echo "**** You seem to use a ${DISTRO} system ****" + + if command -v sudo >/dev/null; then + case "${DISTRO}" in + ubuntu|debian|linuxmint|\"elementary\") + get_yes_no && sudo apt-get install "${need_pkg[@]}" + ;; + fedora|centos|rhel) + command -v dnf >/dev/null && YUM=dnf || YUM=yum + get_yes_no && sudo ${YUM} install "${need_pkg[@]}" + ;; + gentoo) + get_yes_no && sudo emerge --ask --deep "${need_pkg[@]}" + ;; + sabayon) + get_yes_no && sudo equo install --ask "${need_pkg[@]}" + ;; + mageia) + get_yes_no && sudo urpmi "${need_pkg[@]}" + ;; + arch|manjaro) + get_yes_no && sudo pacman -Sy "${need_pkg[@]}" + ;; + opensuse) + get_yes_no && sudo zypper install -y --no-recommends "${need_pkg[@]}" + ;; + *) + echo "**** unsupported distro ${DISTRO} ****" + exit 1 + ;; + esac + else + echo "The command 'sudo' was not found. Please install necessary packages manually." + fi +fi + +get_deps + +if [ "${#need[@]}" -gt 0 ]; then + echo "**** The following packages were not installed correctly ****" + for i in "${!need[@]}"; do + echo "${need[${i}]} provided by ${need_pkg[${i}]}" + done + echo "********" + exit 1 +fi diff --git a/scripts/clean b/scripts/clean new file mode 100755 index 000000000..36ac2394d --- /dev/null +++ b/scripts/clean @@ -0,0 +1,44 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +clean_package() { + build_msg "CLR_CLEAN" "CLEAN" "${1}" "indent" + + if [ "${CLEAN_SOURCES}" = "true" ]; then + rm -rf "${SOURCES}/${1}" + return + fi + + # Use a wilcard here to remove all versions of the package + for i in "${BUILD}/${1}-"*; do + if [ -d "${i}" -a -f "${i}/.libreelec-unpack" ]; then + . "${i}/.libreelec-unpack" + if [ "${STAMP_PKG_NAME}" = "${1}" ]; then + build_msg "CLR_WARNING" "*" "$(print_color "CLR_WARNING_DIM" "Removing ${i} ...")" + rm -rf "${i}" + fi + elif [ -d "${i}" -a -f "${i}/.libreelec-package" ]; then + # force clean if no stamp found (previous unpack failed) + . "${i}/.libreelec-package" + if [ "${INFO_PKG_NAME}" = "${1}" ]; then + build_msg "" "" "* Removing ${i} ..." + rm -rf "${i}" + fi + fi + done + rm -f "${STAMPS}/${1}/build_"* +} + +if [ "${1}" = "--all" -a -n "${2}" ]; then + for build_dir in $(ls -1d "${ROOT}/build."*); do + load_build_config "${build_dir}" && "${SCRIPTS}/clean" "${2}" + done +elif [ -n "${1}" ]; then + clean_package "${1}" +fi + diff --git a/scripts/create_addon b/scripts/create_addon new file mode 100755 index 000000000..4dbea2760 --- /dev/null +++ b/scripts/create_addon @@ -0,0 +1,188 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +. config/options "" +. config/multithread + +usage() { + cat - >&2 < ./script/create_addon all + + build audio encoders and decoders, only + > ./script/create_addon audioencoder.* audiodecoder.* + + build all, but not binary + > ./script/create_addon all -binary +EOF + exit ${1:-0} +} + +# Get list of addon packages +get_addons() { + local paths filter + local pkgpath exited + local count=0 validpkg + + case ${1} in + binary) paths="^${ROOT}/packages/mediacenter/kodi-binary-addons/";; + official) paths="^${ROOT}/packages/addons/";; + all) paths="^${ROOT}/packages/|^${ROOT}/projects/.*/packages/";; + *) paths="^${ROOT}/packages/|^${ROOT}/projects/.*/packages/"; filter="${1}";; + esac + + exit() { exited=1; } + + for pkgpath in $(cat "${_CACHE_PACKAGE_LOCAL}" "${_CACHE_PACKAGE_GLOBAL}" | grep -E "${paths}"); do + if [ -n "${filter}" ]; then + [[ ${pkgpath} =~ ^.*/${filter}@?+?@ ]] || continue + fi + + exited=0 + source_package "${pkgpath%%@*}/package.mk" &>/dev/null + [ ${exited} -eq 1 ] && continue + + validpkg="no" + VERIFY_FAIL= + # Should only build embedded addons when they are explictly specified in the addon list + if [ "${PKG_IS_ADDON}" = "embedded" ]; then + if [ -n "${filter}" ]; then + verify_addon && validpkg="yes" + fi + elif [ "${PKG_IS_ADDON}" = "yes" ]; then + verify_addon && validpkg="yes" + fi + + if [ "${validpkg}" = "yes" ]; then + echo "${PKG_NAME}" + count=$((count + 1)) + elif [ -n "${VERIFY_FAIL}" -a -n "${filter}" ]; then + echo "$(print_color CLR_ERROR "${PKG_NAME}"): ${VERIFY_FAIL}" >&2 + fi + done + + unset -f exit + + if [ ${count} -eq 0 -a -n "${filter}" ]; then + echo "$(print_color CLR_ERROR "ERROR: no addons matched for filter ${filter}")" >&2 + echo "For more information type: ./scripts/create_addon --help" >&2 + die + fi +} + +# Return 0 if package is a suitable addon, 1 otherwise +verify_addon() { + if [ -n "${PKG_ARCH}" ]; then + VERIFY_FAIL="Incompatible arch: \"${TARGET_ARCH}\" not in [ ${PKG_ARCH} ]" + listcontains "${PKG_ARCH}" "!${TARGET_ARCH}" && return 1 + listcontains "${PKG_ARCH}" "${TARGET_ARCH}" || listcontains "${PKG_ARCH}" "any" || return 1 + fi + + if [ -n "${PKG_ADDON_PROJECTS}" ]; then + [ "${DEVICE}" = "RPi" ] && _DEVICE="RPi1" || _DEVICE="${DEVICE}" + + VERIFY_FAIL="Incompatible project or device: \"${_DEVICE:-${PROJECT}}\" not in [ ${PKG_ADDON_PROJECTS} ]" + + if listcontains "${PKG_ADDON_PROJECTS}" "!${_DEVICE:-${PROJECT}}" || + listcontains "${PKG_ADDON_PROJECTS}" "!${PROJECT}"; then + return 1 + fi + + if ! listcontains "${PKG_ADDON_PROJECTS}" "${_DEVICE:-${PROJECT}}" && + ! listcontains "${PKG_ADDON_PROJECTS}" "${PROJECT}" && + ! listcontains "${PKG_ADDON_PROJECTS}" "any"; then + return 1 + fi + fi + + return 0 +} + +# need parameter +if [ $# -eq 0 ]; then + usage 1 +fi + +# check environment and configure toolchains +${SCRIPTS}/checkdeps + +(setup_toolchain host) +setup_toolchain target + +# collect list of addons for building +addons= +addons_drop= +show_only="no" + +# read addons from parameter list +while [ $# -gt 0 ]; do + case ${1} in + --help) usage 0;; + --show-only) show_only="yes";; + --*) usage 1;; + -*) addons_drop+=" $(get_addons ${1:1})";; + *) addons+=" $(get_addons ${1})";; + esac + shift +done + +# Build a new list containing only those addons we want to build +wanted_addons= +for addon in $(echo ${addons} | tr ' ' '\n' | sort -u); do + listcontains "${addons_drop}" "${addon}" || wanted_addons+=" ${addon}" +done + +if [ "${show_only}" = "yes" ]; then + for addon in ${wanted_addons}; do + echo ${addon} + done + exit 0 +fi + +# Build all addons at once using a single plan +if MTADDONBUILD=yes start_multithread_build "${wanted_addons:1}"; then + echo + echo "$(print_color CLR_INFO "ALL ADDONS BUILT SUCCESSFULLY")" + exit 0 +elif [ -f "${THREAD_CONTROL}/addons.failed" ]; then + echo >&2 + print_color CLR_ERROR "FAILED ADDONS:\n" >&2 + while read -r addon logfile; do + if [ -n "${addon}" ]; then + if [ -n "${logfile}" ]; then + echo " $(print_color CLR_ERROR "${addon}"): ${logfile}" >&2 + else + echo " $(print_color CLR_ERROR "${addon}")" >&2 + fi + fi + done < "${THREAD_CONTROL}/addons.failed" + die +else + die "$(print_color CLR_ERROR "UNKNOWN BUILD FAILURE OR INABILITY TO GENERATE PLAN")" +fi diff --git a/scripts/create_docker_package b/scripts/create_docker_package new file mode 100755 index 000000000..14c87769c --- /dev/null +++ b/scripts/create_docker_package @@ -0,0 +1,184 @@ +#!/bin/sh + +FIRST_LABEL=30002 + +LABEL_DEVICE="D" +LABEL_ENV="E_" +LABEL_PORT="P_" +LABEL_VOLUME="V" + +STRING_DEVICE="-d " +STRING_ENV="-e " +STRING_PORT="-p " +STRING_VOLUME="-v " + +add_default() { + defaults="${defaults} \n" +} + +add_device() { + add_label + default="${1%:*}" + docker="${1#*:}" + id="${LABEL_DEVICE}${docker//\//_}" + add_default "${id}" "${default}" + add_option "--device=\"\$${id}\"" + add_setting "" + add_string "${STRING_DEVICE}${docker}" +} + +add_env() { + add_label + default="${1#*=}" + docker="${1%%=*}" + id="${LABEL_ENV}${docker}" + add_default "${id}" "${default}" + add_option "-e ${docker}=\"${id}\"" + add_setting "" + add_string "${STRING_ENV}${docker}" +} + +add_label() { + if [ -z ${label} ]; then + label=${FIRST_LABEL} + else + label=$((label+1)) + fi +} + +add_option() { + if [ ! -z "${options}" ]; then + options="${options} "'\\\n' + fi + options="${options} ${1}" +} + +add_port() { + add_label + default="${1%:*}" + docker="${1#*:}" + port="${docker%/*}" + id="${LABEL_PORT}${port}" + add_default "${id}" "${default}" + add_option "-p \"\$${id}\":${docker}" + add_setting "" + add_string "${STRING_PORT}${port}" +} + +add_setting() { + settings="${settings} ${1}\n" +} + +add_string() { + strings="${strings}\nmsgctxt \"${label}\"\nmsgid \"${1}\"\nmsgstr \"\"\n" +} + +add_volume() { + add_label + default="${1%:*}" + docker="${1#*:}" + id="${LABEL_VOLUME}${docker//\//_}" + add_default "${id}" "${default}" + add_option "-v \"\$${id}\":${docker}" + add_setting "" + add_string "${STRING_VOLUME}${docker}" +} + + +case "${ARCH}" in + arm) + projects="imx6 RPi RPi2" + ;; + x86_64) + projects="Generic" + ;; + *) + echo "Unkown project" + exit 1 + ;; +esac + +while [[ $# -gt 0 ]]; do + option="${1}" + shift + case "${option}" in + --device=*) + add_device "${option#--device=}" + ;; + --name=*) + ;; + --port=*) + add_port "${option#--port=}" + ;; + --volume=*) + add_volume "${option#--volume=}" + ;; + -e) + add_env "${1}" + shift + ;; + + -p) + add_port "${1}" + shift + ;; + -v) + add_volume "${1}" + shift + ;; + -*) + add_option "${option}" + ;; + */*) + add_option "${option}" + image="${option%:*}" + version="${option#*:}" + if [ "${version}" = "${option}" ]; then + version="latest" + fi + if [ ! -z "$*" ]; then + add_option "$*" + fi + break + ;; + *) + add_option "${option}" + ;; + esac +done + +if [ -z "${image}" ]; then + echo "Failed to parse image" + exit 1 +fi + +name="${image//\//.}" +dir="packages/addons/docker/${name}" + +if [ -d "${dir}" ]; then + echo "Package already exists" + exit 1 +fi + +cp -R config/docker "${dir}" + +sed -e "s|@NAME@|${name}|g" \ + -e "s|@VERSION@|${version}|g" \ + -e "s|@ARCH@|${arch}|g" \ + -e "s|@IMAGE@|${image}|g" \ + -e "s|@PROJECTS@|${projects}|g" \ + -i "${dir}/package.mk" + + +defaults="$(echo -en "${defaults}" | sort)" +echo -en "\n${defaults}\n" > "${dir}/source/settings-default.xml" + +echo -en "${options}" >> "${dir}/source/bin/docker" + +sed -e "s|@SETTINGS@|${settings}|g" \ + -i "${dir}/source/resources/settings.xml" + +echo -en "${strings}" >> "${dir}/source/resources/language/English/strings.po" + +mv "${dir}/source/bin/docker" "${dir}/source/bin/docker.${name}" +mv "${dir}/source/system.d/docker.service" "${dir}/source/system.d/docker.${name}.service" diff --git a/scripts/extract b/scripts/extract new file mode 100755 index 000000000..927d9a7e0 --- /dev/null +++ b/scripts/extract @@ -0,0 +1,77 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +if [ -z "${2}" ]; then + die "usage: ${0} package_name target_dir" +fi + +[ -z "${PKG_URL}" -o -z "${PKG_SOURCE_NAME}" ] && die "${PKG_NAME}: PKG_URL or PKG_SOURCE_NAME undefined" +[ ! -d "${SOURCES}/${1}" ] && die "${PKG_NAME}: ${SOURCES}/${1} not found" +[ ! -d "${2}" ] && die "${PKG_NAME}: target ${2} not found" + +if [[ ${PKG_URL} =~ ^file:// ]]; then + FULL_SOURCE_PATH="${PKG_SOURCE_NAME}" +else + FULL_SOURCE_PATH="${SOURCES}/${1}/${PKG_SOURCE_NAME}" +fi + +if [ ! -f "${FULL_SOURCE_PATH}" -a ! -d "${FULL_SOURCE_PATH}" ]; then + echo "error: File ${PKG_SOURCE_NAME} doesn't exist for package ${1}" + echo "Have you called scripts/extract before scripts/get ?" + die +fi + +# The build system expects packages to be extracted to +# ${PKG_BUILD.} +# Try to strip the top level dir from the archive and extract to +# the correct directory if possible so packages don't need to +# set PKG_SOURCE_DIR and scripts/unpack doesn't need to rename +# the directory. +# Currently this is only supported for tar archives. +# If PKG_SOURCE_DIR is set don't apply any directory mangling +# so advanced renaming (eg stripping more than one directory level) +# can be performed by scripts/unpack. +if [ -z "${PKG_SOURCE_DIR}" ]; then + TAR_OPTS="--strip-components=1" + DESTDIR="${2}/${PKG_NAME}-${PKG_VERSION}" +else + TAR_OPTS="" + DESTDIR="${2}" +fi + +case ${PKG_SOURCE_NAME} in + *.tar | *.tar.bz2 | *.tbz | *.tar.gz | *.tgz | *.tar.xz | *.txz) + mkdir -p "${DESTDIR}" + tar xf ${FULL_SOURCE_PATH} ${TAR_OPTS} -C "${DESTDIR}" + ;; + *.7z) + mkdir -p ${2}/${1} + 7zr x -o${2}/${1} ${FULL_SOURCE_PATH} + ;; + *.zip) + unzip -oq ${FULL_SOURCE_PATH} -d ${2} + ;; + *.diff | *.patch) + cat ${FULL_SOURCE_PATH} | patch -d ${2} -p1 + ;; + *.diff.bz2 | *.patch.bz2 | patch-*.bz2) + bzcat ${FULL_SOURCE_PATH} | patch -d ${2} -p1 + ;; + *.diff.gz | *.patch.gz | patch-*.gz) + zcat ${FULL_SOURCE_PATH} | patch -d ${2} -p1 + ;; + *.rar) + unrar x ${FULL_SOURCE_PATH} ${2} + ;; + *) + FULL_DEST_PATH="${2}/${PKG_NAME}-${PKG_VERSION}" + mkdir ${FULL_DEST_PATH} + tar cf - -C ${FULL_SOURCE_PATH} ${PKG_TAR_COPY_OPTS} . | \ + tar xf - -C ${FULL_DEST_PATH} + ;; +esac diff --git a/scripts/genbuildplan.py b/scripts/genbuildplan.py new file mode 100755 index 000000000..3922f886a --- /dev/null +++ b/scripts/genbuildplan.py @@ -0,0 +1,388 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +from __future__ import print_function +import sys, os, codecs, json, argparse, re + +ROOT_PKG = "__root__" + +class LibreELEC_Package: + def __init__(self, name, section): + self.name = name + self.section = section + self.deps = {"bootstrap": [], + "init": [], + "host": [], + "target": []} + self.wants = [] + self.wantedby = [] + + def __repr__(self): + s = "%-9s: %s" % ("name", self.name) + s = "%s\n%-9s: %s" % (s, "section", self.section) + + for t in self.deps: + s = "%s\n%-9s: %s" % (s, t, self.deps[t]) + + s = "%s\n%-9s: %s" % (s, "NEEDS", self.wants) + s = "%s\n%-9s: %s" % (s, "WANTED BY", self.wantedby) + + return s + + def addDependencies(self, target, packages): + for d in " ".join(packages.split()).split(): + self.deps[target].append(d) + name = d.split(":")[0] + if name not in self.wants and name != self.name: + self.wants.append(name) + + def delDependency(self, target, package): + if package in self.deps[target]: + self.deps[target].remove(package) + name = package.split(":")[0] + if name in self.wants: + self.wants.remove(name) + + def addReference(self, package): + name = package.split(":")[0] + if name not in self.wantedby: + self.wantedby.append(name) + + def delReference(self, package): + name = package.split(":")[0] + if name in self.wantedby: + self.wantedby.remove(name) + + def isReferenced(self): + return False if self.wants == [] else True + + def isWanted(self): + return False if self.wantedby == [] else True + + def references(self, package): + return package in self.wants + +# Reference material: +# https://www.electricmonk.nl/docs/dependency_resolving_algorithm/dependency_resolving_algorithm.html +class Node: + def __init__(self, name, target, section): + self.name = name + self.target = target + self.section = section + self.fqname = "%s:%s" % (name, target) + self.edges = [] + + def appendEdges(self, node): + # Add the node itself... + if node not in self.edges: + self.edges.append(node) + # as well as its edges + for e in node.edges: + if e not in self.edges: + self.edges.append(e) + + # Return True if the dependencies of the specified node are met by this node + def satisfies(self, node): + for e in node.edges: + if e not in self.edges: + return False + return True + + def __repr__(self): + s = "%-9s: %s" % ("name", self.name) + s = "%s\n%-9s: %s" % (s, "target", self.target) + s = "%s\n%-9s: %s" % (s, "fqname", self.fqname) + s = "%s\n%-9s: %s" % (s, "common", self.commonName()) + s = "%s\n%-9s: %s" % (s, "section", self.section) + + for e in self.edges: + s = "%s\nEDGE: %s" % (s, e.fqname) + + return s + + def commonName(self): + return self.name if self.target == "target" else "%s:%s" % (self.name, self.target) + + def addEdge(self, node): + self.edges.append(node) + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + +# Read a JSON list of all possible packages from stdin +def loadPackages(): + jdata = json.loads("[%s]" % sys.stdin.read().replace('\n','')[:-1]) + + map = {} + + # Load "global" packages first + for pkg in jdata: + if pkg["hierarchy"] == "global": + map[pkg["name"]] = initPackage(pkg) + + # Then the "local" packages, as these will replace any matching "global" packages + for pkg in jdata: + if pkg["hierarchy"] == "local": + map[pkg["name"]] = initPackage(pkg) + + return map + +# Create a fully formed LibreELEC_Package object +def initPackage(package): + pkg = LibreELEC_Package(package["name"], package["section"]) + + for target in ["bootstrap", "init", "host", "target"]: + pkg.addDependencies(target, package[target]) + + return pkg + +# Split name:target into components +def split_package(name): + parts = name.split(":") + pn = parts[0] + pt = parts[1] if len(parts) != 1 else "target" + return (pn, pt) + +# Return a list of packages of the specified type +def get_packages_by_target(target, list): + newlist = [] + + for p in list: + (pn, pt) = split_package(p) + if target in ["target", "init"] and pt in ["target", "init"]: + newlist.append(p) + elif target in ["bootstrap", "host"] and pt in ["bootstrap", "host"]: + newlist.append(p) + + return newlist + +# For the specified node iterate over the list of scheduled nodes and return the first +# position where we could possibly build this node (ie. all dependencies satisfied). +def findbuildpos(node, list): + + # Keep a running total of all dependencies as we progress through the list + alldeps = Node("", "", "") + + candidate = None + for n in list: + alldeps.appendEdges(n) + if alldeps.satisfies(node): + if len(n.edges) > len(node.edges): + if candidate == None: + candidate = n + break + candidate = n + + return list.index(candidate) + 1 if candidate else -1 + +# Resolve dependencies for a node +def dep_resolve(node, resolved, unresolved, noreorder): + unresolved.append(node) + + for edge in node.edges: + if edge not in resolved: + if edge in unresolved: + raise Exception('Circular reference detected: %s -> %s\nRemove %s from %s package.mk::PKG_DEPENDS_%s' % \ + (node.fqname, edge.commonName(), edge.commonName(), node.name, node.target.upper())) + dep_resolve(edge, resolved, unresolved, noreorder) + + if node not in resolved: + pos = -1 if noreorder else findbuildpos(node, resolved) + if pos != -1: + resolved.insert(pos, node) + else: + resolved.append(node) + + unresolved.remove(node) + +# Return a list of build steps for the trigger packages +def get_build_steps(args, nodes, trigger_pkgs, built_pkgs): + resolved = [] + unresolved = [] + + # When building the image the :target packages must be installed. + # + # However, if we are not building the image then only build the packages + # and don't install them as it's likely we will be building discrete add-ons + # which are installed outside of the image. + # + install = True if "image" in args.build else False + + for pkgname in [x for x in trigger_pkgs if x]: + if pkgname.find(":") == -1: + pkgname = "%s:target" % pkgname + + if pkgname in nodes: + dep_resolve(nodes[pkgname], resolved, unresolved, args.no_reorder) + + # Abort if any references remain unresolved + if unresolved != []: + eprint("The following dependencies have not been resolved:") + for dep in unresolved: + eprint(" %s" % dep) + raise("Unresolved references") + + # Output list of resolved dependencies + for pkg in resolved: + if pkg.fqname not in built_pkgs: + built_pkgs.append(pkg.fqname) + task = "build" if pkg.fqname.endswith(":host") or not install else "install" + yield(task, pkg.fqname) + +# Reduce the complete list of packages to a map of those packages that will +# be needed for the build. +def processPackages(args, packages, build): + # Add dummy package to ensure build/install dependencies are not culled + pkg = { + "name": ROOT_PKG, + "section": "virtual", + "hierarchy": "global", + "bootstrap": "", + "init": "", + "host": " ".join(get_packages_by_target("host", build)), + "target": " ".join(get_packages_by_target("target", build)) + } + + packages[pkg["name"]] = initPackage(pkg) + + # Resolve reverse references that we can use to ignore unreferenced packages + for pkgname in packages: + for opkgname in packages: + opkg = packages[opkgname] + if opkg.references(pkgname): + if pkgname in packages: + packages[pkgname].addReference(opkgname) + + # Identify unused packages + while True: + changed = False + for pkgname in packages: + pkg = packages[pkgname] + if pkg.isWanted(): + for opkgname in pkg.wantedby: + if opkgname != ROOT_PKG: + if not packages[opkgname].isWanted(): + pkg.delReference(opkgname) + changed = True + if not changed: + break + + # Create a new map of "needed" packages + needed_map = {} + for pkgname in packages: + pkg = packages[pkgname] + if pkg.isWanted() or pkgname == ROOT_PKG: + needed_map[pkgname] = pkg + + # Validate package dependency references + for pkgname in needed_map: + pkg = needed_map[pkgname] + for t in pkg.deps: + for d in pkg.deps[t]: + if split_package(d)[0] not in needed_map and not args.ignore_invalid: + msg = 'Invalid package reference: dependency %s in package %s::PKG_DEPENDS_%s is not valid' % (d, pkgname, t.upper()) + if args.warn_invalid: + eprint("WARNING: %s" % msg) + else: + raise Exception(msg) + + node_map = {} + + # Convert all packages to target-specific nodes + for pkgname in needed_map: + pkg = needed_map[pkgname] + for target in pkg.deps: + if pkg.deps[target]: + node = Node(pkgname, target, pkg.section) + node_map[node.fqname] = node + + # Ensure all referenced dependencies exist as a basic node + for pkgname in needed_map: + pkg = needed_map[pkgname] + for target in pkg.deps: + for dep in pkg.deps[target]: + dfq = dep if dep.find(":") != -1 else "%s:target" % dep + if dfq not in node_map: + (dfq_p, dfq_t) = split_package(dfq) + if dfq_p in packages: + dpkg = packages[dfq_p] + node_map[dfq] = Node(dfq_p, dfq_t, dpkg.section) + elif not args.ignore_invalid: + raise Exception("Invalid package! Package %s cannot be found for this PROJECT/DEVICE/ARCH" % dfq_p) + + # To each target-specific node, add the corresponding + # target-specific dependency nodes ("edges") + for name in node_map: + node = node_map[name] + if node.name not in needed_map: + if args.warn_invalid: + continue + else: + raise Exception("Invalid package! Package %s cannot be found for this PROJECT/DEVICE/ARCH" % node.name) + for dep in needed_map[node.name].deps[node.target]: + dfq = dep if dep.find(":") != -1 else "%s:target" % dep + if dfq in node_map: + node.addEdge(node_map[dfq]) + + return node_map + +#--------------------------------------------- +parser = argparse.ArgumentParser(description="Generate package dependency list for the requested build/install packages. \ + Package data will be read from stdin in JSON format.", \ + formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=25,width=90)) + +parser.add_argument("-b", "--build", nargs="+", metavar="PACKAGE", required=True, \ + help="Space-separated list of build trigger packages, either for host or target. Required property - specify at least one package.") + +parser.add_argument("--warn-invalid", action="store_true", \ + help="Warn about invalid/missing dependency packages, perhaps excluded by a PKG_ARCH incompatability. Default is to abort.") + +parser.add_argument("--no-reorder", action="store_true", default="True", \ + help="Do not resequence steps based on dependencies. This is the default.") + +parser.add_argument("--reorder", action="store_false", dest="no_reorder", \ + help="Disable --no-reorder and resequence packages to try and reduce stalls etc.") + +parser.add_argument("--show-wants", action="store_true", \ + help="Output \"wants\" dependencies for each step.") + +parser.add_argument("--hide-wants", action="store_false", dest="show_wants", default="True", \ + help="Disable --show-wants.") + +parser.add_argument("--ignore-invalid", action="store_true", \ + help="Ignore invalid packages.") + +args = parser.parse_args() + +ALL_PACKAGES = loadPackages() + +loaded = len(ALL_PACKAGES) + +REQUIRED_PKGS = processPackages(args, ALL_PACKAGES, args.build) + +# Output list of packages to build/install +built_pkgs = [] +steps = [] + +for step in get_build_steps(args, REQUIRED_PKGS, args.build, built_pkgs): + steps.append(step) + +eprint("Packages loaded : %d" % loaded) +eprint("Build trigger(s): %d [%s]" % (len(args.build), " ".join(args.build))) +eprint("Package steps : %d" % len(steps)) +eprint("") + +# Output build/install steps +if args.show_wants: + for step in steps: + wants = [] + node = (REQUIRED_PKGS[step[1]]) + for e in node.edges: + wants.append(e.fqname) + print("%-7s %-25s (wants: %s)" % (step[0], step[1].replace(":target",""), ", ".join(wants).replace(":target",""))) +else: + for step in steps: + print("%-7s %s" % (step[0], step[1].replace(":target",""))) diff --git a/scripts/get b/scripts/get new file mode 100755 index 000000000..ee51aca4e --- /dev/null +++ b/scripts/get @@ -0,0 +1,54 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +if [ -z "${1}" ]; then + for i in $(find "${PACKAGES}/" -type f -name "package.mk"); do + GET_PKG=$(grep "^PKG_NAME=" "${i}" | sed -e "s,\",,g" -e "s,PKG_NAME=,,") + "${SCRIPTS}"/get "${GET_PKG}" + done +fi + +# Avoid concurrent processing of the same package +lock_source_dir() { + exec 99<"${SOURCES}/${1}" + if ! flock --nonblock --exclusive 99; then + echo "Project/Device ${DEVICE:-${PROJECT}} waiting, to avoid concurrent processing of ${1}..." + flock --exclusive 99 + fi +} + +if [ -n "${PKG_URL}" -a -n "${PKG_SOURCE_NAME}" ]; then + mkdir -p "${SOURCES}/${1}" + + PACKAGE="${SOURCES}/${1}/${PKG_SOURCE_NAME}" + + STAMP_URL="${PACKAGE}.url" + STAMP_SHA="${PACKAGE}.sha256" + + # determine get handler based on protocol and/or filename + case "${PKG_URL}" in + git://*|*.git) + get_handler="git";; + file://*) + get_handler="file";; + *) + get_handler="archive";; + esac + + if ! listcontains "${GET_HANDLER_SUPPORT}" "${get_handler}"; then + die "ERROR: get handler \"${get_handler}\" is not supported, unable to get package ${1} - aborting!" + else + get_handler="${SCRIPTS}/get_${get_handler}" + if [ ! -f "${get_handler}" ]; then + die "ERROR: get handler \"${get_handler}\" does not exist, unable to get package ${1} - aborting!" + fi + + . "${get_handler}" + fi +fi + +exit 0 diff --git a/scripts/get_archive b/scripts/get_archive new file mode 100755 index 000000000..15c6a09f7 --- /dev/null +++ b/scripts/get_archive @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +_get_file_already_downloaded() { + [ ! -f "${PACKAGE}" -o ! -f "${STAMP_URL}" -o ! -f "${STAMP_SHA}" ] && return 1 + [ -n "${PKG_SHA256}" -a "$(cat ${STAMP_SHA} 2>/dev/null)" != "${PKG_SHA256}" ] && return 1 + return 0 +} + +# Latest file already present, exit now... +_get_file_already_downloaded && exit 0 + +lock_source_dir "${1}" + +# Check again in case of concurrent access - if nothing needs to be downloaded, exit now... +_get_file_already_downloaded && exit 0 + +# At this point, we need to download something... +build_msg "CLR_GET" "GET" "${1} (archive)" "indent" + +pkg_lock_status "GETPKG" "${PKG_NAME}" "unpack" "downloading package..." + +PACKAGE_MIRROR="${DISTRO_MIRROR}/${PKG_NAME}/${PKG_SOURCE_NAME}" +[ "${VERBOSE}" != "yes" ] && WGET_OPT=-q +WGET_CMD="wget --output-file=- --timeout=30 --tries=3 --passive-ftp --no-check-certificate -c ${WGET_OPT} --progress=bar:force --show-progress -O ${PACKAGE}" + +# unset LD_LIBRARY_PATH to stop wget from using toolchain/lib and loading libssl.so/libcrypto.so instead of host libraries +unset LD_LIBRARY_PATH + +rm -f "${STAMP_URL}" "${STAMP_SHA}" + +NBWGET=10 +while [ ${NBWGET} -gt 0 ]; do + for url in "${PKG_URL}" "${PACKAGE_MIRROR}"; do + if [[ "$PKG_USETOKEN" == "yes" ]]; then + if [[ $url == https://github.com/* ]] && [[ -n $COREELEC_GHTOKEN ]]; then + WGET_HEADER=--header="Authorization: token $COREELEC_GHTOKEN" + fi + else + WGET_HEADER=--header="" + fi + + rm -f "${PACKAGE}" + if ${WGET_CMD} "$WGET_HEADER" "${url}"; then + CALC_SHA256=$(sha256sum "${PACKAGE}" | cut -d" " -f1) + + [ -z "${PKG_SHA256}" -o "${PKG_SHA256}" = "${CALC_SHA256}" ] && break 2 + + build_msg "CLR_WARNING" "WARNING" "Incorrect checksum calculated on downloaded file: got ${CALC_SHA256} wanted ${PKG_SHA256}" + fi + done + NBWGET=$((NBWGET - 1)) +done + +if [ ${NBWGET} -eq 0 ]; then + die "\nCannot get ${1} sources : ${PKG_URL}\nTry later!" +else + build_msg "CLR_INFO" "INFO" "Calculated checksum: ${CALC_SHA256}" + echo "${PKG_URL}" > "${STAMP_URL}" + echo "${CALC_SHA256}" > "${STAMP_SHA}" +fi diff --git a/scripts/get_file b/scripts/get_file new file mode 100755 index 000000000..02c0021df --- /dev/null +++ b/scripts/get_file @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +build_msg "CLR_GET" "GET" "${1} (file)" "indent" + +pkg_lock_status "GETPKG" "${PKG_NAME}" "unpack" "processing package file..." diff --git a/scripts/get_git b/scripts/get_git new file mode 100755 index 000000000..f1c96e0a9 --- /dev/null +++ b/scripts/get_git @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +# Handler for git +# Usage (in package.mk): +# PKG_URL (mandatory) must point to a git repository (git://... or https://example.com/repo.git) +# PKG_VERSION (mandatory) must point to a commit SHA, e.g. a1b2c3d +# PKG_GIT_SHA (optional) full hash of git commit +# PKG_GIT_CLONE_BRANCH (optional) clone specific branch +# PKG_GIT_CLONE_SINGLE (optional) clone single branch only (set to yes) +# PKG_GIT_CLONE_DEPTH (optional) history to clone, must be a number +# PKG_GIT_SUBMODULE_DEPTH (optional) history of submodules to clone, must be a number + +_get_repo_already_downloaded() { + if [ -d "${PACKAGE}" ]; then + ( + cd "${PACKAGE}" + _get_repo_clean + [ -n "$(git ls-remote . | grep -m1 HEAD | awk "/^${PKG_VERSION}/ {print \$1;}")" ] || die "ERROR: ${PACKAGE}: failed to determine git HEAD" + [ "${PKG_URL}" = "$(git remote get-url origin)" ] || die "ERROR: ${PACKAGE}: failed to obtain URL of origin" + [ -z "${PKG_GIT_CLONE_BRANCH}" ] && exit 0 + [ "${PKG_GIT_CLONE_BRANCH}" = "$(git branch | grep ^\* | cut -d ' ' -f2)" ] || die "ERROR: ${PACKAGE}: failed to determine current git branch" + exit 0 + ) + return + else + return 1 + fi +} + +_get_repo_clean() { + git clean -fdx + git checkout -- . +} + +# Latest file already present, exit now... +_get_repo_already_downloaded && exit 0 + +lock_source_dir "${1}" + +# Check again in case of concurrent access - if nothing needs to be downloaded, exit now... +_get_repo_already_downloaded && exit 0 + +# At this point, we need to download something... +build_msg "CLR_GET" "GET" "${1} (git)" "indent" + +pkg_lock_status "GETPKG" "${PKG_NAME}" "unpack" "processing package repository..." + +rm -f "${STAMP_URL}" "${STAMP_SHA}" + +GIT_CLONE_PARAMS="--recursive" +GIT_SUBMODULE_PARAMS="" + +[ -n "${PKG_GIT_CLONE_BRANCH}" ] && GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --branch ${PKG_GIT_CLONE_BRANCH}" +[ "${PKG_GIT_CLONE_SINGLE}" = "yes" ] && GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --single-branch" + +if [ -n "${PKG_GIT_CLONE_DEPTH}" ]; then + if [[ "${PKG_GIT_CLONE_DEPTH}" =~ ^[0-9]+$ ]]; then + GIT_CLONE_PARAMS="${GIT_CLONE_PARAMS} --depth ${PKG_GIT_CLONE_DEPTH}" + else + die "ERROR: PKG_GIT_CLONE_DEPTH is not a number! (${PKG_GIT_CLONE_DEPTH})" + fi +fi + +if [ -n "${PKG_GIT_SUBMODULE_DEPTH}" ]; then + if [[ "${PKG_GIT_SUBMODULE_DEPTH}" =~ ^[0-9]+$ ]]; then + GIT_SUBMODULE_PARAMS="${GIT_SUBMODULE_PARAMS} --depth ${PKG_GIT_SUBMODULE_DEPTH}" + else + die "ERROR: PKG_GIT_SUBMODULE_DEPTH is not a number! (${PKG_GIT_SUBMODULE_DEPTH})" + fi +fi + +GIT_FOUND="no" +opwd="$(pwd)" +for d in "${SOURCES}/${1}/${1}-"* ; do + if [ -d "${d}/.git" ]; then + if [ "${GIT_FOUND}" = "no" ]; then + cd "${d}" + if [ "${PKG_URL}" = "$(git remote get-url origin)" ]; then + if [[ -z "${PKG_GIT_CLONE_BRANCH}" ]] || [[ $(git branch | grep "^\* ${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]]; then + GIT_FOUND="yes" + GIT_DIR="${d}" + _get_repo_clean + elif [ $(git branch | grep "^ ${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]; then + GIT_FOUND="yes" + GIT_DIR="${d}" + _get_repo_clean + git checkout "${PKG_GIT_CLONE_BRANCH}" + elif [ $(git branch -a | grep "^ remotes/origin/${PKG_GIT_CLONE_BRANCH}$" | wc -l) -eq 1 ]; then + GIT_FOUND="yes" + GIT_DIR="${d}" + _get_repo_clean + git checkout -b "${PKG_GIT_CLONE_BRANCH}" "origin/${PKG_GIT_CLONE_BRANCH}" + else + build_msg "CLR_CLEAN" "DELETE" "(${d})" + cd "${opwd}" + rm -rf "${d}" + fi + if [ "${GIT_FOUND}" = "yes" ]; then + build_msg "CLR_GET" "GIT PULL" "${1}" + + # If there is an error with 'git pull' or updating the submodules, just reclone + # NOTE: we run the submodule update twice if the clone already + # exists - but deduplicating would complicate the logic quite a lot and + # the second time is almost a no-op + if ! git pull || ! git submodule update --init --recursive ${GIT_SUBMODULE_PARAMS}; then + cd "${opwd}" + build_msg "CLR_CLEAN" "DELETE" "(${d})" + GIT_FOUND=NO + rm -rf "${d}" + fi + cd "${opwd}" + fi + else + build_msg "CLR_CLEAN" "DELETE" "(${d})" + cd "${opwd}" + rm -rf "${d}" + fi + fi + else + build_msg "CLR_CLEAN" "DELETE" "(${d})" + rm -rf "${d}" + fi +done +cd "${opwd}" + +if [ "${GIT_FOUND}" = "no" ]; then + build_msg "CLR_GET" "GIT CLONE" "${1}" + git clone ${GIT_CLONE_PARAMS} "${PKG_URL}" "${PACKAGE}" +elif [ ! "${GIT_DIR}" = "${PACKAGE}" ]; then + mv "${GIT_DIR}" "${PACKAGE}" +fi + +( cd "${PACKAGE}" + [ $(git log --oneline --pretty=tformat:"%H" | grep "^${PKG_VERSION}" | wc -l) -eq 1 ] || die "There is no commit '${PKG_VERSION}' on branch '$(git branch | grep ^\* | cut -d ' ' -f2)' of package '${1}'! Aborting!" + git reset --hard "${PKG_VERSION}" + build_msg "CLR_GET" "GIT SUBMODULE" "${1}" + git submodule update --init --recursive ${GIT_SUBMODULE_PARAMS} +) + +GIT_SHA="$(git ls-remote "${PACKAGE}" | grep -m1 HEAD | awk '{print $1;}')" + +if [ -n "${PKG_GIT_SHA}" -a "${PKG_GIT_SHA}" != "${GIT_SHA}" ]; then + build_msg "CLR_WARNING" "WARNING" "Incorrect git hash in repository: got ${GIT_SHA}, wanted ${PKG_GIT_SHA}" +fi diff --git a/scripts/image b/scripts/image new file mode 100755 index 000000000..b16ac2676 --- /dev/null +++ b/scripts/image @@ -0,0 +1,466 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +unset _CACHE_PACKAGE_LOCAL _CACHE_PACKAGE_GLOBAL _DEBUG_DEPENDS_LIST _DEBUG_PACKAGE_LIST + +. config/options "" +. config/multithread +. config/show_config + +show_config + +${SCRIPTS}/checkdeps + +# Setup both toolchain cmake configs to avoid potentially racy behaviour later. +# Use a fork for host to isolate any variable modifications. +( setup_toolchain host ) +setup_toolchain target + +function do_mkimage() { + # Variables used in mkimage script must be passed + env \ + ROOT="${ROOT}" \ + SCRIPTS="${SCRIPTS}" \ + TOOLCHAIN="${TOOLCHAIN}" \ + PROJECT_DIR="${PROJECT_DIR}" \ + PROJECT="${PROJECT}" \ + DEVICE="${DEVICE}" \ + DISTRO="${DISTRO}" \ + TARGET_IMG="${TARGET_IMG}" \ + BUILD_NAME="${IMAGE_NAME}" \ + IMAGE_NAME="${1:-${IMAGE_NAME}}" \ + BOOTLOADER="${BOOTLOADER}" \ + KERNEL_NAME="${KERNEL_NAME}" \ + TARGET_KERNEL_ARCH="${TARGET_KERNEL_ARCH}" \ + RELEASE_DIR="${RELEASE_DIR}" \ + UUID_SYSTEM="${UUID_SYSTEM}" \ + UUID_STORAGE="${UUID_STORAGE}" \ + DISTRO_BOOTLABEL="${DISTRO_BOOTLABEL}" \ + DISTRO_DISKLABEL="${DISTRO_DISKLABEL}" \ + UBOOT_SYSTEM="${UBOOT_SYSTEM}" \ + UBOOT_VERSION="${UBOOT_VERSION}" \ + EXTRA_CMDLINE="${EXTRA_CMDLINE}" \ + SYSTEM_SIZE="${SYSTEM_SIZE}" \ + SYSTEM_PART_START="${SYSTEM_PART_START}" \ + OVA_SIZE="${OVA_SIZE}" \ + SUBDEVICE="${SUBDEVICE}" \ + ${SCRIPTS}/mkimage +} + +if [ -n "${CUSTOM_GIT_HASH}" ]; then + GIT_HASH="${CUSTOM_GIT_HASH}" +else + GIT_HASH=$(git rev-parse HEAD) +fi + +if [ "${OS_VERSION}" = "devel" ]; then + GIT_ABBREV=${GIT_HASH:0:7} + DEVEL_VERSION=${OS_VERSION} + case "${BUILD_PERIODIC}" in + nightly) OS_VERSION=nightly-$(date +%Y%m%d)-${GIT_ABBREV};; + daily) OS_VERSION=daily-$(date +%Y%j)-${GIT_ABBREV};; + weekly) OS_VERSION=weekly-$(date +%G%V)-${GIT_ABBREV};; + monthly) OS_VERSION=monthly-$(date +%Y%m)-${GIT_ABBREV};; + *) OS_VERSION=devel-$(date +%s);; + esac +fi + +# Get origin url, fix git:// and git@github.com: urls if necessary +ORIGIN_URL="$(git remote -v | awk '$1 == "origin" { print $2 }' | head -1 | sed 's#\.git$##;s#^git:#https:#;s#^git@github\.com:#https://github.com/#')" + +if [ -n "${CUSTOM_VERSION}" ]; then + export OS_VERSION="${CUSTOM_VERSION}" +fi + +LIBREELEC_ARCH="${DEVICE:-${PROJECT}}.${TARGET_ARCH}" +TARGET_VERSION="${LIBREELEC_ARCH}-${OS_VERSION}" + +if [ -n "${CUSTOM_IMAGE_NAME}" ]; then + IMAGE_NAME="${CUSTOM_IMAGE_NAME}" +else + if [ "${DEVEL_VERSION}" = "devel" ]; then + IMAGE_NAME="${DISTRONAME}-${LIBREELEC_ARCH}-${OS_VERSION}-${OS_VERSION}" + else + IMAGE_NAME="${DISTRONAME}-${TARGET_VERSION}" + fi + + if [ -n "${UBOOT_SYSTEM}" ] && [ "${UBOOT_SYSTEM}" != "${DEVICE:-${PROJECT}}" ]; then + IMAGE_NAME="${IMAGE_NAME}" + fi +fi + +if [ -n "${IMAGE_SUFFIX}" ]; then + IMAGE_NAME="${IMAGE_NAME}-${IMAGE_SUFFIX}" +fi + +echo "${IMAGE_NAME}" > ${BUILD}/BUILD_FILENAME + +# Setup fakeroot +rm -rf ${FAKEROOT_SCRIPT} # remove ${FAKEROOT_SCRIPT} if it exist +touch ${FAKEROOT_SCRIPT} # create an empty ${FAKEROOT_SCRIPT} +chmod +x ${FAKEROOT_SCRIPT} # make ${FAKEROOT_SCRIPT} executable +echo "chown -R 0:0 ${INSTALL}" >> ${FAKEROOT_SCRIPT} + +# Clean old install dirs +rm -rf ${INSTALL} +rm -rf ${STAMPS_INSTALL} +mkdir -p ${INSTALL} + +# Create base layout of LibreELEC read-only file system +for directory in etc dev proc run sys tmp usr var flash storage; do + mkdir -p ${INSTALL}/${directory} +done + +# Build image contents +if [ "${TARGET_ARCH}" = "arm" ]; +then + MTADDONBUILD=no start_multithread_build arm32 || die "Parallel build failure - see log for details. Time of failure: $(date)" + exit 0 +else + MTADDONBUILD=no start_multithread_build image || die "Parallel build failure - see log for details. Time of failure: $(date)" +fi + +echo "Successful build! Building image root..." >&2 + +# Create legacy sym links +ln -sfn /var/media ${INSTALL}/media +ln -sfn /usr/lib ${INSTALL}/lib +ln -sfn /usr/bin ${INSTALL}/bin +ln -sfn /usr/sbin ${INSTALL}/sbin + +if [ "${TARGET_ARCH}" = "x86_64" ]; then + ln -sfn /usr/lib ${INSTALL}/lib64 + ln -sfn /usr/lib ${INSTALL}/usr/lib64 +fi + +echo "${TARGET_VERSION}" > ${INSTALL}/etc/release + +# Create /etc/os-release +cat <${INSTALL}/etc/os-release +OS_NAME="${DISTRONAME}" +OS_VERSION="${OS_VERSION}" +HW_DEVICE="${DEVICE}" +HW_ARCH="${ARCH}" +HW_CPU="${HW_CPU}" +HOME_URL="${HOME_URL}" +WIKI_URL="${WIKI_URL}" +BUG_REPORT_URL="${BUG_REPORT_URL}" +BUILD_ID="${GIT_HASH}" +BUILD_DATE="${BUILD_DATE}" +EOF + +# Add release notes / changelog + +if [ -n "${RELEASE_NOTES}" ] && [ -f "${RELEASE_NOTES}" ]; then + cp "${RELEASE_NOTES}" ${INSTALL}/etc/release-notes +else + echo "" > ${INSTALL}/etc/release-notes +fi + +# Copy PROJECT related files to filesystem +if [ -d "${PROJECT_DIR}/${PROJECT}/filesystem" ]; then + cp -PR ${PROJECT_DIR}/${PROJECT}/filesystem/* ${INSTALL} + # Install project specific systemd services + for service in ${PROJECT_DIR}/${PROJECT}/filesystem/usr/lib/systemd/system/*.service; do + if [ -f "${service}" ]; then + enable_service $(basename ${service}) + fi + done +fi + +# Copy DEVICE related files to filesystem +if [ -n "${DEVICE}" -a -d "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem" ]; then + cp -PR ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem/* ${INSTALL} + # Install device specific systemd services + for service in ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem/usr/lib/systemd/system/*.service; do + if [ -f "${service}" ]; then + enable_service $(basename ${service}) + fi + done +fi + +# Run depmod for base overlay modules +MODVER=$(basename $(ls -d ${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/*)) +find ${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/ -name *.ko | \ + sed -e "s,${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/,," \ + > ${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/modules.order +${TOOLCHAIN}/bin/depmod -b ${INSTALL}/usr/lib/kernel-overlays/base -a -e -F "${BUILD}/linux-$(kernel_version)/System.map" ${MODVER} 2>&1 + +# Strip kernel modules +for MOD in $(find ${INSTALL}/usr/lib/kernel-overlays/ -type f -name *.ko); do + ${TARGET_KERNEL_PREFIX}strip --strip-debug ${MOD} +done + +# Symlink overlayed modules to /usr/lib/modules +ln -sT /var/lib/modules ${INSTALL}/usr/lib/modules + +# Symlink overlayed firmware to /usr/lib/firmware +ln -sT /var/lib/firmware ${INSTALL}/usr/lib/firmware + +if [ "${1}" = "system" -o "${1}" = "mkimage" -o "${1}" = "noobs" ] +then + echo "Creating image..." >&2 + + # Make target dir + mkdir -p ${TARGET_IMG} + rm -rf ${TARGET_IMG}/${IMAGE_NAME}.kernel + + # Copy kernel to target dir + cp -PR ${BUILD}/linux-$(kernel_version)/arch/${TARGET_KERNEL_ARCH}/boot/${KERNEL_TARGET} ${TARGET_IMG}/${IMAGE_NAME}.kernel + chmod 0644 ${TARGET_IMG}/${IMAGE_NAME}.kernel + + # Set mksquashfs options for each compression method + if [ -z "${SQUASHFS_COMPRESSION_OPTION}" ]; then + if [ "${SQUASHFS_COMPRESSION:-gzip}" = "gzip" ]; then + SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 9 -b 262144" + elif [ "${SQUASHFS_COMPRESSION}" = "lzo" ]; then + SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 9 -b 524288" + elif [ "${SQUASHFS_COMPRESSION}" = "zstd" ]; then + SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 22 -b 262144" + fi + fi + + # Create squashfs file, default to gzip if no compression configured + echo "rm -rf \"${TARGET_IMG}/${IMAGE_NAME}.system\"" >> ${FAKEROOT_SCRIPT} + echo "${TOOLCHAIN}/bin/mksquashfs \"${BUILD}/image/system\" \"${TARGET_IMG}/${IMAGE_NAME}.system\" -noappend -comp ${SQUASHFS_COMPRESSION:-gzip} ${SQUASHFS_COMPRESSION_OPTION}" >> ${FAKEROOT_SCRIPT} + + # Run fakeroot + ${TOOLCHAIN}/bin/fakeroot -- ${FAKEROOT_SCRIPT} + rm -rf ${FAKEROOT_SCRIPT} + + # Set permissions + chmod 0644 ${TARGET_IMG}/${IMAGE_NAME}.system +fi + +if [ "${1}" = "release" -o "${1}" = "mkimage" -o "${1}" = "noobs" ]; then + + RELEASE_DIR="target/${IMAGE_NAME}" + + # Cleanup + rm -rf ${RELEASE_DIR} + + # Create release dir + mkdir -p ${RELEASE_DIR} + + # Remove any previously created release images + rm -rf ${TARGET_IMG}/${IMAGE_NAME}.img.gz + + if [ -n "${BOOTLOADER}" ]; then + + BOOTLOADER_DIR="$(get_pkg_directory "${BOOTLOADER}")" + + if [ -d ${BOOTLOADER_DIR}/files ]; then + cp -R ${BOOTLOADER_DIR}/files/* ${RELEASE_DIR} + fi + + if find_file_path bootloader/release ${BOOTLOADER_DIR}/release; then + echo "Running ${FOUND_PATH}" + . ${FOUND_PATH} + fi + fi + + cp ${ROOT}/README* ${RELEASE_DIR} + echo "${TARGET_VERSION}" > ${RELEASE_DIR}/RELEASE + + if [ ! "${MEDIACENTER}" = "no" ]; then + echo "Kodi commit: $(get_pkg_version ${MEDIACENTER})" >> ${RELEASE_DIR}/RELEASE + fi + + mkdir -p ${RELEASE_DIR}/licenses + cp ${ROOT}/licenses/* ${RELEASE_DIR}/licenses + + mkdir -p ${RELEASE_DIR}/target + cp ${TARGET_IMG}/${IMAGE_NAME}.system ${RELEASE_DIR}/target/SYSTEM + cp ${TARGET_IMG}/${IMAGE_NAME}.kernel ${RELEASE_DIR}/target/KERNEL + + # Create md5sum's + ( cd ${RELEASE_DIR}; + md5sum -t target/SYSTEM > target/SYSTEM.md5; + md5sum -t target/KERNEL > target/KERNEL.md5; + ) + + # Create target directory + mkdir -p ${TARGET_IMG} + + # Remove any previously created release tarballs + rm -rf ${TARGET_IMG}/${IMAGE_NAME}.tar + + # Create release tarball + tar cf ${TARGET_IMG}/${IMAGE_NAME}.tar -C target ${IMAGE_NAME} + + # Create sha256 checksum of tarball + ( cd ${TARGET_IMG} + sha256sum ${IMAGE_NAME}.tar > ${IMAGE_NAME}.tar.sha256 + ) + + # Create image files if requested + if [[ ( "${1}" = "noobs" || "${1}" = "mkimage" ) && -n "${BOOTLOADER}" ]]; then + UUID_SYSTEM="$(date '+%d%m')-$(date '+%M%S')" + UUID_STORAGE="$(uuidgen)" + + DEVICE_BOARDS=$(${SCRIPTS}/uboot_helper "${PROJECT}" "${DEVICE}") + + if [ "${BOOTLOADER}" = "u-boot" -a -z "${UBOOT_SYSTEM}" -a -n "${DEVICE}" -a -n "${DEVICE_BOARDS}" ]; then + for UBOOT_SYSTEM in ${DEVICE_BOARDS}; do + + # Re-install u-boot package + rm ${STAMPS_INSTALL}/u-boot/install_target + UBOOT_SYSTEM="${UBOOT_SYSTEM}" ${SCRIPTS}/install u-boot + + # Re-run bootloader/release + if find_file_path bootloader/release ${BOOTLOADER_DIR}/release; then + echo "Running ${FOUND_PATH}" + . ${FOUND_PATH} + fi + + do_mkimage "${IMAGE_NAME}-${UBOOT_SYSTEM}" + done + else + if [ -n "${SUBDEVICES}" ]; then + [ "${PROJECT}" = "Amlogic" -o "${PROJECT}" = "Amlogic-ng" ] && SUBDEVICES+=" Generic" + for SUBDEVICE in ${SUBDEVICES}; do + do_mkimage "${IMAGE_NAME}" + done + else + do_mkimage + fi + fi + fi + + # Cleanup release dir + rm -rf ${RELEASE_DIR} + + if [ "${1}" = "noobs" ]; then + echo "Creating \"${1}\" release tarball..." + + RELEASE_DIR="${TARGET_IMG}/${IMAGE_NAME}-${1}" + + # eg. LibreELEC_RPi, LibreELEC_RPi2 etc. + NOOBS_DISTRO="${DISTRONAME}_${DEVICE:-${PROJECT}}" + + # Create release dir + mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO} + + if [ -f ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}_40x40.png ]; then + cp -PR ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}_40x40.png ${RELEASE_DIR}/${NOOBS_DISTRO}/${NOOBS_DISTRO}.png + else + cp -PR ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}.png ${RELEASE_DIR}/${NOOBS_DISTRO}/${NOOBS_DISTRO}.png + fi + cp -PR ${ROOT}/config/noobs/os.json ${RELEASE_DIR}/${NOOBS_DISTRO} + cp -PR ${ROOT}/config/noobs/partition_setup.sh ${RELEASE_DIR}/${NOOBS_DISTRO} + cp -PR ${ROOT}/config/noobs/partitions.json ${RELEASE_DIR}/${NOOBS_DISTRO} + if [ -d ${DISTRO_DIR}/${DISTRO}/noobs/marketing ]; then + tar cf ${RELEASE_DIR}/${NOOBS_DISTRO}/marketing.tar -C ${DISTRO_DIR}/${DISTRO}/noobs/marketing . + else + tar cf ${RELEASE_DIR}/${NOOBS_DISTRO}/marketing.tar -C ${ROOT}/config/noobs/marketing . + fi + cp ${ROOT}/README* ${RELEASE_DIR}/${NOOBS_DISTRO} + + if [ -n "${NOOBS_HEX}" ]; then + sed -e "s%@NOOBS_HEX@%${NOOBS_HEX}%g" \ + -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json + else + sed -e "/@NOOBS_HEX@/d" \ + -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json + fi + + sed -e "s%@DISTRONAME@%${DISTRONAME}%g" \ + -e "s%@PROJECT@%${DEVICE:-${PROJECT}}%g" \ + -e "s%@OS_VERSION@%${OS_VERSION}%g" \ + -e "s%@RELEASE_DATE@%$(date +%F)%g" \ + -e "s%@KERNEL_VERSION@%$(kernel_version)%g" \ + -e "s%@DESCRIPTION@%${DESCRIPTION}%g" \ + -e "s%@ROOT_PASSWORD@%${ROOT_PASSWORD}%g" \ + -e "s%@NOOBS_SUPPORTED_MODELS@%${NOOBS_SUPPORTED_MODELS}%g" \ + -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json + + sed -e "s%@DISTRONAME@%${DISTRONAME}%g" \ + -e "s%@PROJECT@%${DEVICE:-${PROJECT}}%g" \ + -e "s%@SYSTEM_SIZE@%${SYSTEM_SIZE}%g" \ + -i ${RELEASE_DIR}/${NOOBS_DISTRO}/partitions.json + + # Create System dir + mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System + + # Copy Bootloader + cp -PR ${INSTALL}/usr/share/bootloader/config.txt ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + cp -PR ${INSTALL}/usr/share/bootloader/distroconfig.txt ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + cp -PR ${INSTALL}/usr/share/bootloader/LICENCE* ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + cp -PR ${INSTALL}/usr/share/bootloader/bootcode.bin ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + cp -PR ${INSTALL}/usr/share/bootloader/fixup.dat ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + cp -PR ${INSTALL}/usr/share/bootloader/start.elf ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ + [ -f ${INSTALL}/usr/share/bootloader/dt-blob.bin ] && cp -PR ${INSTALL}/usr/share/bootloader/dt-blob.bin ${RELEASE_DIR}/${NOOBS_DISTRO}/System/dt-blob.bin + + # Copy system files + cp ${TARGET_IMG}/${IMAGE_NAME}.system ${RELEASE_DIR}/${NOOBS_DISTRO}/System/SYSTEM + cp ${TARGET_IMG}/${IMAGE_NAME}.kernel ${RELEASE_DIR}/${NOOBS_DISTRO}/System/kernel.img + + for dtb in ${INSTALL}/usr/share/bootloader/*.dtb; do + if [ -f ${dtb} ]; then + cp -PR ${dtb} ${RELEASE_DIR}/${NOOBS_DISTRO}/System + fi + done + + for overlay in ${INSTALL}/usr/share/bootloader/overlays/*; do + if [ -f ${overlay} ]; then + mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System/overlays + cp -PR ${overlay} ${RELEASE_DIR}/${NOOBS_DISTRO}/System/overlays + fi + done + + # Create md5sum's + ( cd ${RELEASE_DIR}/${NOOBS_DISTRO}/System; + md5sum -t SYSTEM > SYSTEM.md5; + md5sum -t kernel.img > kernel.img.md5; + ) + + # Copy additional files + mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System/licenses + cp ${ROOT}/licenses/* ${RELEASE_DIR}/${NOOBS_DISTRO}/System/licenses + + # Create Storage dir + mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage + + # Remove any previously created release tarball + rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/System.tar.xz + rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage.tar.xz + + # Create filesystem tarballs + ${TOOLCHAIN}/bin/fakeroot tar cJf ${RELEASE_DIR}/${NOOBS_DISTRO}/System.tar.xz -C ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ . + ${TOOLCHAIN}/bin/fakeroot tar cJf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage.tar.xz -C ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage/ . + + # Remove filesystem dirs + rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/System + rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage + + # Remove any previously created release tarball + rm -rf ${TARGET_IMG}/${IMAGE_NAME}-${1}.tar + + # Create release tarball + tar cf ${TARGET_IMG}/${IMAGE_NAME}-${1}.tar -C ${TARGET_IMG} ${IMAGE_NAME}-${1} + + # Create sha256 checksum of tarball + ( cd ${TARGET_IMG} + sha256sum ${IMAGE_NAME}-${1}.tar > ${IMAGE_NAME}-${1}.tar.sha256 + ) + fi + + if [ -d ${RELEASE_DIR} ]; then + # Cleanup release dir + rm -rf ${RELEASE_DIR} + fi +fi + +# remove unneeded files in target folder +if [ "$COREELEC_TARGET_REMOVE" = "kernel_system" ]; then + rm -f ${TARGET_IMG}/*.kernel + rm -f ${TARGET_IMG}/*.system +elif [ "$COREELEC_TARGET_REMOVE" = "kernel_system_sha256" ]; then + rm -f ${TARGET_IMG}/*.kernel + rm -f ${TARGET_IMG}/*.system + rm -f ${TARGET_IMG}/*.sha256 +fi diff --git a/scripts/install b/scripts/install new file mode 100755 index 000000000..819a1951e --- /dev/null +++ b/scripts/install @@ -0,0 +1,152 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv) +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +. config/options "${1}" + +if [ -z "${1}" ]; then + die "usage: ${0} package_name [parent_pkg]" +fi + +if [ -z "${PKG_NAME}" ]; then + die "$(print_color CLR_ERROR "${1}: no package.mk file found")" +fi + +if [ -z "${INSTALL}" ] ; then + die "error: '\${INSTALL}' not set! this script is not intended to be run manually" +fi + +if [ -n "${PKG_ARCH}" ]; then + listcontains "${PKG_ARCH}" "!${TARGET_ARCH}" && exit 0 + listcontains "${PKG_ARCH}" "${TARGET_ARCH}" || listcontains "${PKG_ARCH}" "any" || exit 0 +fi + +# set defaults +if [ "${1//:/}" != "${1}" ]; then + TARGET="${1#*:}" +else + TARGET= +fi +[ -z "${TARGET}" ] && TARGET="target" +PARENT_PKG="${2:-${PKG_NAME}:${TARGET}}" + +pkg_lock "${PKG_NAME}:${TARGET}" "install" "${PARENT_PKG}" + +STAMP=${STAMPS_INSTALL}/${PKG_NAME}/install_${TARGET} +if [ -f ${STAMP} ]; then + pkg_lock_status "UNLOCK" "${PKG_NAME}:${TARGET}" "install" "already installed" + exit 0 +fi + +mkdir -p ${STAMPS_INSTALL}/${PKG_NAME} + +${SCRIPTS}/build "${1}" "${PARENT_PKG}" + +if [ "${TARGET}" = "target" ] ; then + for p in ${PKG_DEPENDS_TARGET}; do + ${SCRIPTS}/install "${p}" "${PARENT_PKG}" + done +elif [ "${TARGET}" = "init" ] ; then + for p in ${PKG_DEPENDS_INIT}; do + ${SCRIPTS}/install "${p}" "${PARENT_PKG}" + done + INSTALL=${BUILD}/initramfs +fi + +pkg_lock_status "ACTIVE" "${PKG_NAME}:${TARGET}" "install" + +build_msg "CLR_INSTALL" "INSTALL" "${PKG_NAME} $(print_color CLR_TARGET "(${TARGET})")" "indent" + +mkdir -p ${INSTALL} + +if [ "${TARGET}" = "target" ] ; then + for PKG_TMP_DIR in ${PKG_DIR} \ + ${PROJECT_DIR}/${PROJECT}/packages/${PKG_NAME} \ + ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/packages/${PKG_NAME} \ + ; do + + [ -d ${PKG_TMP_DIR} ] || continue + + if [ -d ${PKG_TMP_DIR}/profile.d ]; then + mkdir -p ${INSTALL}/etc/profile.d + cp ${PKG_TMP_DIR}/profile.d/* ${INSTALL}/etc/profile.d + fi + + if [ -d ${PKG_TMP_DIR}/tmpfiles.d ]; then + mkdir -p ${INSTALL}/usr/lib/tmpfiles.d + cp ${PKG_TMP_DIR}/tmpfiles.d/* ${INSTALL}/usr/lib/tmpfiles.d + fi + + if [ -d ${PKG_TMP_DIR}/system.d ]; then + mkdir -p ${INSTALL}/usr/lib/systemd/system + cp -Pr ${PKG_TMP_DIR}/system.d/*.* ${INSTALL}/usr/lib/systemd/system + fi + + if [ -d ${PKG_TMP_DIR}/udev.d ]; then + mkdir -p ${INSTALL}/usr/lib/udev/rules.d + cp ${PKG_TMP_DIR}/udev.d/*.rules ${INSTALL}/usr/lib/udev/rules.d + fi + + if [ -d ${PKG_TMP_DIR}/hwdb.d ]; then + mkdir -p ${INSTALL}/usr/lib/udev/hwdb.d + cp ${PKG_TMP_DIR}/hwdb.d/*.hwdb ${INSTALL}/usr/lib/udev/hwdb.d + fi + + if [ -d ${PKG_TMP_DIR}/sleep.d ]; then + mkdir -p ${INSTALL}/usr/lib/systemd/system-sleep + cp ${PKG_TMP_DIR}/sleep.d/* ${INSTALL}/usr/lib/systemd/system-sleep + fi + + if [ -d ${PKG_TMP_DIR}/sleep.d.serial ]; then + mkdir -p ${INSTALL}/usr/lib/systemd/system-sleep.serial + cp ${PKG_TMP_DIR}/sleep.d.serial/* ${INSTALL}/usr/lib/systemd/system-sleep.serial + fi + + if [ -d ${PKG_TMP_DIR}/sysctl.d ]; then + mkdir -p ${INSTALL}/usr/lib/sysctl.d + cp ${PKG_TMP_DIR}/sysctl.d/*.conf ${INSTALL}/usr/lib/sysctl.d + fi + + if [ -d ${PKG_TMP_DIR}/modules-load.d ]; then + mkdir -p ${INSTALL}/usr/lib/modules-load.d + cp ${PKG_TMP_DIR}/modules-load.d/*.conf ${INSTALL}/usr/lib/modules-load.d + fi + + if [ -d ${PKG_TMP_DIR}/sysconf.d ]; then + mkdir -p ${INSTALL}/etc/sysconf.d + cp ${PKG_TMP_DIR}/sysconf.d/*.conf ${INSTALL}/etc/sysconf.d + fi + + if [ -d ${PKG_TMP_DIR}/debug.d ]; then + mkdir -p ${INSTALL}/usr/share/debugconf + cp ${PKG_TMP_DIR}/debug.d/*.conf ${INSTALL}/usr/share/debugconf + fi + + if [ -d ${PKG_TMP_DIR}/modprobe.d ]; then + mkdir -p ${INSTALL}/usr/lib/modprobe.d + cp ${PKG_TMP_DIR}/modprobe.d/*.conf ${INSTALL}/usr/lib/modprobe.d + fi + done +fi + +# install +if [ "${TARGET}" = "target" ] ; then + pkg_call_exists pre_install && pkg_call pre_install +fi + +if [ "${TARGET}" = "target" -a -d ${PKG_BUILD}/.install_pkg ]; then + cp -PR ${PKG_BUILD}/.install_pkg/* ${INSTALL} +elif [ "${TARGET}" = "init" -a -d ${PKG_BUILD}/.install_init ]; then + cp -PR ${PKG_BUILD}/.install_init/* ${INSTALL} +fi + +if [ "${TARGET}" = "target" ] ; then + pkg_call_exists post_install && pkg_call post_install +fi + +touch ${STAMP} + +pkg_lock_status "UNLOCK" "${PKG_NAME}:${TARGET}" "install" "installed" diff --git a/scripts/install_addon b/scripts/install_addon new file mode 100755 index 000000000..24895dead --- /dev/null +++ b/scripts/install_addon @@ -0,0 +1,91 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2017-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +. config/options "${1}" + +pkg_lock "${PKG_NAME}" "packadd" +pkg_lock_status "ACTIVE" "${PKG_NAME}" "packadd" + +# cleanup old install path +rm -rf "${ADDON_BUILD}" + +# install addon parts +if pkg_call_exists addon; then + pkg_call addon +else + install_binary_addon "${PKG_ADDON_ID}" +fi + +# Make sure we have a value for STRIP +setup_toolchain target + +ADDON_DIRECTORY="${ADDON_BUILD}/${PKG_ADDON_ID}" + +install_addon_files "${ADDON_DIRECTORY}" + +debug_strip "${ADDON_DIRECTORY}" + +# pack_addon() +ADDON_INSTALL_DIR="${TARGET_IMG}/${ADDONS}/${ADDON_VERSION}/${PROJECT}/${TARGET_ARCH}/${PKG_ADDON_ID}" +ADDONVER="$(xmlstarlet sel -t -v "/addon/@version" ${ADDON_BUILD}/${PKG_ADDON_ID}/addon.xml)" + +if [ -f ${ADDON_INSTALL_DIR}/${PKG_ADDON_ID}-${ADDONVER}.zip ]; then + if [ "${ADDON_OVERWRITE}" = "yes" ]; then + rm ${ADDON_INSTALL_DIR}/${PKG_ADDON_ID}-${ADDONVER}.zip + else + build_msg "CLR_WARNING" "*** WARNING: ${PKG_ADDON_ID}-${ADDONVER}.zip already exists. Not overwriting it. ***" + pkg_lock_status "UNLOCK" "${PKG_NAME}" "packadd" "already packed" + exit 0 + fi +fi + +cd ${ADDON_BUILD} +build_msg "CLR_INFO" "*** compressing addon ${PKG_ADDON_ID} ... ***" +${TOOLCHAIN}/bin/7za a -l -mx9 -bsp0 -bso0 -tzip ${PKG_ADDON_ID}-${ADDONVER}.zip ${PKG_ADDON_ID} +cd - &>/dev/null + +mkdir -p ${ADDON_INSTALL_DIR} +cp ${ADDON_BUILD}/${PKG_ADDON_ID}-${ADDONVER}.zip ${ADDON_INSTALL_DIR} +if [ -f ${ADDON_BUILD}/${PKG_ADDON_ID}/changelog.txt ]; then + cp ${ADDON_BUILD}/${PKG_ADDON_ID}/changelog.txt ${ADDON_INSTALL_DIR}/changelog-${ADDONVER}.txt +fi +if [ -f ${ADDON_BUILD}/${PKG_ADDON_ID}/resources/icon.png ]; then + mkdir -p ${ADDON_INSTALL_DIR}/resources + cp ${ADDON_BUILD}/${PKG_ADDON_ID}/resources/icon.png ${ADDON_INSTALL_DIR}/resources/icon.png +fi + +# workaround for kodi pvr addons +if [ -f ${ADDON_BUILD}/${PKG_ADDON_ID}/icon.png ]; then + cp ${ADDON_BUILD}/${PKG_ADDON_ID}/icon.png ${ADDON_INSTALL_DIR}/icon.png +fi + +if [ -f ${ADDON_BUILD}/${PKG_ADDON_ID}/resources/fanart.png ]; then + mkdir -p ${ADDON_INSTALL_DIR}/resources + cp ${ADDON_BUILD}/${PKG_ADDON_ID}/resources/fanart.png ${ADDON_INSTALL_DIR}/resources/fanart.png +fi +for f in ${ADDON_BUILD}/${PKG_ADDON_ID}/resources/screenshot-*.{jpg,png}; do + if [ -f "${f}" ]; then + mkdir -p ${ADDON_INSTALL_DIR}/resources + cp ${f} ${ADDON_INSTALL_DIR}/resources + fi +done + +# Jenkins add-on build +if [ "${ADDON_JENKINS}" = "yes" ]; then + ADDON_JENKINS_DIR="${TARGET_IMG}/jenkins" + ADDON_JENKINS_ADDON_NAME="${ADDON_VERSION}-${DEVICE:-${PROJECT}}-${TARGET_ARCH}-${PKG_ADDON_ID}-${ADDONVER}" + mkdir -p "${ADDON_JENKINS_DIR}" + cd ${ADDON_INSTALL_DIR} + ${TOOLCHAIN}/bin/7za a -l -mx0 -bsp0 -bso0 -tzip ${ADDON_JENKINS_DIR}/${ADDON_JENKINS_ADDON_NAME}.zip ${PKG_ADDON_ID}-${ADDONVER}.zip resources/ + ( cd ${ADDON_JENKINS_DIR} + sha256sum ${ADDON_JENKINS_ADDON_NAME}.zip > ${ADDON_JENKINS_ADDON_NAME}.zip.sha256 + ) + build_msg "CLR_INFO" "*** creating ${ADDON_JENKINS_ADDON_NAME}.zip for Jenkins complete ***" +else + build_msg "CLR_INFO" "*** creating ${PKG_ADDON_ID} complete ***" +fi + +pkg_lock_status "UNLOCK" "${PKG_NAME}" "packadd" "packed" diff --git a/scripts/mkimage b/scripts/mkimage new file mode 100755 index 000000000..282f02774 --- /dev/null +++ b/scripts/mkimage @@ -0,0 +1,333 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2016-2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +################################################################################ +# variables such as ${ROOT} ${PATH} etc... that are required for this +# script to work must be passed via env ... in scripts/image +################################################################################ + +# set variables +LE_TMP=$(mktemp -d) +SAVE_ERROR="${LE_TMP}/save_error" + +if [ -z "${SYSTEM_SIZE}" -o -z "${SYSTEM_PART_START}" ]; then + echo "mkimage: SYSTEM_SIZE and SYSTEM_PART_START must be configured!" + exit 1 +fi + +if [ "${BOOTLOADER}" = "syslinux" ]; then + DISK_LABEL=gpt +else + DISK_LABEL=msdos +fi + +STORAGE_SIZE=32 # STORAGE_SIZE must be >= 32 ! + +DISK_START_PADDING=$(( (${SYSTEM_PART_START} + 2048 - 1) / 2048 )) +DISK_GPT_PADDING=1 +DISK_SIZE=$(( ${DISK_START_PADDING} + ${SYSTEM_SIZE} + ${STORAGE_SIZE} + ${DISK_GPT_PADDING} )) +DISK_BASENAME="${TARGET_IMG}/${IMAGE_NAME}" +if [ -n "${SUBDEVICE}" ]; then + DISK_BASENAME="${DISK_BASENAME}-${SUBDEVICE}" +fi +DISK="${DISK_BASENAME}.img" + +# functions +cleanup() { + echo -e "image: cleanup...\n" + rm -rf "${LE_TMP}" +} + +show_error() { + echo "image: An error has occurred..." + echo + if [ -s "${SAVE_ERROR}" ]; then + cat "${SAVE_ERROR}" + else + echo "Folder ${LE_TMP} might be out of free space..." + fi + echo + cleanup + exit 1 +} + +trap cleanup SIGINT + +# create an image +echo -e "\nimage: creating file $(basename ${DISK})..." +dd if=/dev/zero of="${DISK}" bs=1M count="${DISK_SIZE}" conv=fsync >"${SAVE_ERROR}" 2>&1 || show_error + +# write a disklabel +echo "image: creating ${DISK_LABEL} partition table..." +parted -s "${DISK}" mklabel ${DISK_LABEL} +sync + +# create part1 +echo "image: creating part1..." +SYSTEM_PART_END=$(( ${SYSTEM_PART_START} + (${SYSTEM_SIZE} * 1024 * 1024 / 512) - 1 )) +if [ "${DISK_LABEL}" = "gpt" ]; then + parted -s "${DISK}" -a min unit s mkpart system fat32 ${SYSTEM_PART_START} ${SYSTEM_PART_END} + parted -s "${DISK}" set 1 legacy_boot on +else + parted -s "${DISK}" -a min unit s mkpart primary fat32 ${SYSTEM_PART_START} ${SYSTEM_PART_END} + parted -s "${DISK}" set 1 boot on +fi +sync + +# create part2 +echo "image: creating part2..." +STORAGE_PART_START=$(( ${SYSTEM_PART_END} + 1 )) +STORAGE_PART_END=$(( ${STORAGE_PART_START} + (${STORAGE_SIZE} * 1024 * 1024 / 512) - 1 )) +if [ "${DISK_LABEL}" = "gpt" ]; then + parted -s "${DISK}" -a min unit s mkpart storage ext4 ${STORAGE_PART_START} ${STORAGE_PART_END} +else + parted -s "${DISK}" -a min unit s mkpart primary ext4 ${STORAGE_PART_START} ${STORAGE_PART_END} +fi +sync + +if [ "${BOOTLOADER}" = "syslinux" ]; then + # write mbr + echo "image: writing mbr..." + MBR="${TOOLCHAIN}/share/syslinux/gptmbr.bin" + if [ -n "${MBR}" ]; then + dd bs=440 count=1 conv=fsync,notrunc if="${MBR}" of="${DISK}" >"${SAVE_ERROR}" 2>&1 || show_error + fi +fi + +# create filesystem on part1 +echo "image: creating filesystem on part1..." +OFFSET=$(( ${SYSTEM_PART_START} * 512 )) +HEADS=4 +TRACKS=32 +SECTORS=$(( ${SYSTEM_SIZE} * 1024 * 1024 / 512 / ${HEADS} / ${TRACKS} )) + +shopt -s expand_aliases # enables alias expansion in script +alias mformat="mformat -i ${DISK}@@${OFFSET} -h ${HEADS} -t ${TRACKS} -s ${SECTORS}" +alias mcopy="mcopy -i ${DISK}@@${OFFSET}" +alias mmd="mmd -i ${DISK}@@${OFFSET}" + +if [ "${BOOTLOADER}" = "syslinux" -o "${BOOTLOADER}" = "bcm2835-bootloader" -o "${BOOTLOADER}" = "u-boot" ]; then + mformat -v "${DISTRO_BOOTLABEL}" -N "${UUID_SYSTEM//-/}" :: +fi +sync + +if [ "${BOOTLOADER}" = "syslinux" ]; then + # create bootloader configuration + echo "image: creating bootloader configuration..." + cat << EOF > "${LE_TMP}/syslinux.cfg" +SAY Wait for installer mode to start automatically in 5 seconds... +SAY +SAY Options +SAY ======= +SAY installer: permanently install ${DISTRO} to HDD/SSD +SAY live: boot ${DISTRO} using RAM for temporary storage +SAY run: boot ${DISTRO} using this USB memory device for storage +SAY +DEFAULT installer +TIMEOUT 50 +PROMPT 1 + +LABEL installer + KERNEL /${KERNEL_NAME} + APPEND boot=UUID=${UUID_SYSTEM} installer quiet systemd.debug_shell vga=current + +LABEL live + KERNEL /${KERNEL_NAME} + APPEND boot=UUID=${UUID_SYSTEM} live quiet vga=current + +LABEL run + KERNEL /${KERNEL_NAME} + APPEND boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} portable quiet +EOF + + cat << EOF > "${LE_TMP}/grub.cfg" +set timeout="25" +set default="Installer" +menuentry "Installer" { + search --set -f /KERNEL + linux /KERNEL boot=UUID=${UUID_SYSTEM} installer quiet systemd.debug_shell vga=current +} +menuentry "Live" { + search --set -f /KERNEL + linux /KERNEL boot=UUID=${UUID_SYSTEM} grub_live quiet vga=current +} +menuentry "Run" { + search --set -f /KERNEL + linux /KERNEL boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} grub_portable quiet +} +EOF + + mcopy "${LE_TMP}/syslinux.cfg" :: + + # install syslinux + echo "image: installing syslinux to part1..." + syslinux.mtools --offset "${OFFSET}" -i "${DISK}" + + # copy files + echo "image: copying files to part1..." + mcopy "${TARGET_IMG}/${BUILD_NAME}.kernel" "::/${KERNEL_NAME}" + mcopy "${TARGET_IMG}/${BUILD_NAME}.system" ::/SYSTEM + mcopy "${RELEASE_DIR}/target/KERNEL.md5" "::/${KERNEL_NAME}.md5" + mcopy "${RELEASE_DIR}/target/SYSTEM.md5" ::/SYSTEM.md5 + + mmd EFI EFI/BOOT + mcopy "${TOOLCHAIN}/share/syslinux/bootx64.efi" ::/EFI/BOOT + mcopy "${TOOLCHAIN}/share/syslinux/ldlinux.e64" ::/EFI/BOOT + mcopy "${TOOLCHAIN}/share/grub/bootia32.efi" ::/EFI/BOOT + mcopy "${LE_TMP}/grub.cfg" ::/EFI/BOOT + +elif [ "${BOOTLOADER}" = "bcm2835-bootloader" ]; then + # create bootloader configuration + echo "image: creating bootloader configuration..." + cat << EOF > "${LE_TMP}/cmdline.txt" +boot=UUID=${UUID_SYSTEM} disk=UUID=${UUID_STORAGE} quiet ${EXTRA_CMDLINE} +EOF + + mcopy "${LE_TMP}/cmdline.txt" :: + + # copy files + echo "image: copying files to part1..." + mcopy "${TARGET_IMG}/${BUILD_NAME}.kernel" "::/${KERNEL_NAME}" + mcopy "${TARGET_IMG}/${BUILD_NAME}.system" ::/SYSTEM + mcopy "${RELEASE_DIR}/target/KERNEL.md5" "::/${KERNEL_NAME}.md5" + mcopy "${RELEASE_DIR}/target/SYSTEM.md5" ::/SYSTEM.md5 + + mcopy "${RELEASE_DIR}/3rdparty/bootloader/bootcode.bin" :: + mcopy "${RELEASE_DIR}/3rdparty/bootloader/fixup.dat" :: + mcopy "${RELEASE_DIR}/3rdparty/bootloader/start.elf" :: + mcopy "${RELEASE_DIR}/3rdparty/bootloader/config.txt" :: + mcopy "${RELEASE_DIR}/3rdparty/bootloader/distroconfig.txt" :: + + if [ -f "${RELEASE_DIR}/3rdparty/bootloader/dt-blob.bin" ]; then + mcopy "${RELEASE_DIR}/3rdparty/bootloader/dt-blob.bin" :: + fi + + for dtb in "${RELEASE_DIR}/3rdparty/bootloader/"*.dtb ; do + if [ -f "${dtb}" ]; then + mcopy "${dtb}" ::/$(basename "${dtb}") + fi + done + + if [ -d "${RELEASE_DIR}/3rdparty/bootloader/overlays" ]; then + mcopy -s "${RELEASE_DIR}/3rdparty/bootloader/overlays" :: + fi + +elif [ "${BOOTLOADER}" = "u-boot" -a \( -n "${UBOOT_SYSTEM}" -o "${UBOOT_VERSION}" = "vendor" \) ]; then + # create bootloader configuration + echo "image: creating bootloader configuration... (u-boot)" + + if [ "${UBOOT_VERSION}" != "vendor" ]; then + DTB="$(${SCRIPTS}/uboot_helper ${PROJECT} ${DEVICE} ${UBOOT_SYSTEM} dtb)" + if [ -f "${RELEASE_DIR}/3rdparty/bootloader/${DTB}" ]; then + mcopy "${RELEASE_DIR}/3rdparty/bootloader/${DTB}" :: + fi + fi + + if [ -f "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader/mkimage" ]; then + . "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/bootloader/mkimage" + elif [ -f "${PROJECT_DIR}/${PROJECT}/bootloader/mkimage" ]; then + . "${PROJECT_DIR}/${PROJECT}/bootloader/mkimage" + else + echo "image: skipping u-boot. no mkimage script found" + fi + + echo "image: copying files to part1..." + mcopy "${TARGET_IMG}/${BUILD_NAME}.kernel" "::/${KERNEL_NAME}" + mcopy "${TARGET_IMG}/${BUILD_NAME}.system" ::/SYSTEM + mcopy "${RELEASE_DIR}/target/KERNEL.md5" "::/${KERNEL_NAME}.md5" + mcopy "${RELEASE_DIR}/target/SYSTEM.md5" ::/SYSTEM.md5 + +elif [ "${BOOTLOADER}" = "u-boot" ]; then + echo "to make an image using u-boot UBOOT_SYSTEM must be set" + cleanup + exit +fi # bootloader + +# extract part2 from image to format and copy files +echo "image: extracting part2 from image..." +STORAGE_PART_COUNT=$(( ${STORAGE_PART_END} - ${STORAGE_PART_START} + 1 )) +sync +dd if="${DISK}" of="${LE_TMP}/part2.ext4" bs=512 skip="${STORAGE_PART_START}" count="${STORAGE_PART_COUNT}" conv=fsync >"${SAVE_ERROR}" 2>&1 || show_error + +# create filesystem on part2 +echo "image: creating filesystem on part2..." +mke2fs -F -q -t ext4 -m 0 "${LE_TMP}/part2.ext4" +tune2fs -L "${DISTRO_DISKLABEL}" -U ${UUID_STORAGE} "${LE_TMP}/part2.ext4" >"${SAVE_ERROR}" 2>&1 || show_error +e2fsck -n "${LE_TMP}/part2.ext4" >"${SAVE_ERROR}" 2>&1 || show_error +sync + +# add resize mark +mkdir "${LE_TMP}/part2.fs" +touch "${LE_TMP}/part2.fs/.please_resize_me" +echo "image: populating filesystem on part2..." +populatefs -U -d "${LE_TMP}/part2.fs" "${LE_TMP}/part2.ext4" >"${SAVE_ERROR}" 2>&1 || show_error +sync +e2fsck -n "${LE_TMP}/part2.ext4" >"${SAVE_ERROR}" 2>&1 || show_error + +# merge part2 back to disk image +echo "image: merging part2 back to image..." +dd if="${LE_TMP}/part2.ext4" of="${DISK}" bs=512 seek="${STORAGE_PART_START}" conv=fsync,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + +# extract part1 from image to run fsck +echo "image: extracting part1 from image..." +SYSTEM_PART_COUNT=$(( ${SYSTEM_PART_END} - ${SYSTEM_PART_START} + 1 )) +sync +dd if="${DISK}" of="${LE_TMP}/part1.fat" bs=512 skip="${SYSTEM_PART_START}" count="${SYSTEM_PART_COUNT}" conv=fsync >"${SAVE_ERROR}" 2>&1 || show_error +echo "image: checking filesystem on part1..." +fsck.fat -n "${LE_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error + +# create virtual image +if [ "${PROJECT}" = "Generic" ]; then + echo "image: creating open virtual appliance..." + # duplicate ${DISK} so anything we do to it directly doesn't effect original + dd if="${DISK}" of="${DISK_BASENAME}.tmp" bs=1M >"${SAVE_ERROR}" 2>&1 || show_error + # change syslinux default to 'run' + echo "image: modifying fs on part1 for open virtual appliance..." + sed -e "/DEFAULT/ s/installer/run/" -i "${LE_TMP}/syslinux.cfg" + sed -e "/set default=/s/\"Installer\"/\"Run\"/" -i "${LE_TMP}/grub.cfg" + # FIXME: an unalias should work here, but it does not; call mcopy directly + "${TOOLCHAIN}"/bin/mcopy -i "${LE_TMP}/part1.fat" -o "${LE_TMP}/syslinux.cfg" :: + "${TOOLCHAIN}"/bin/mcopy -i "${LE_TMP}/part1.fat" -o "${LE_TMP}/grub.cfg" ::/EFI/BOOT + sync + # merge modified part1 back to tmp disk image + echo "image: merging part1 back to open virtual appliance..." + dd if="${LE_TMP}/part1.fat" of="${DISK_BASENAME}.tmp" bs=512 seek="${SYSTEM_PART_START}" conv=fsync,notrunc >"${SAVE_ERROR}" 2>&1 || show_error + # create vmdk from tmp ${DISK} + qemu-img convert -O vmdk -o subformat=streamOptimized "${DISK_BASENAME}.tmp" "${DISK_BASENAME}.vmdk" + # generate ovf from template + sed -e "s,@DISTRO@,${DISTRO},g" -e "s,@DISK@,${IMAGE_NAME},g" \ + -e "s,@OVA_SIZE@,$((${OVA_SIZE}*1024*1024)),g" \ + "${PROJECT_DIR}/${PROJECT}/config/ovf.template" > "${DISK_BASENAME}.ovf" + # combine ovf and vmdk into official ova + tar -C "${TARGET_IMG}" -cf "${DISK_BASENAME}.ova" "${IMAGE_NAME}.ovf" "${IMAGE_NAME}.vmdk" + # create sha256 checksum of ova image + ( cd "${TARGET_IMG}" + sha256sum "${IMAGE_NAME}.ova" > "${IMAGE_NAME}.ova.sha256" + ) + echo "image: cleaning up..." + # remove tmp ${DISK}, vmdk and ovf + rm "${DISK_BASENAME}.tmp" "${DISK_BASENAME}.vmdk" "${DISK_BASENAME}.ovf" + # set owner + [ -n "${SUDO_USER}" ] && chown "${SUDO_USER}:" "${DISK_BASENAME}.ova" +fi + +# gzip +echo "image: compressing..." +pigz --best --force "${DISK}" + +# set owner +if [ -n "${SUDO_USER}" ]; then + chown "${SUDO_USER}:" "${DISK}.gz" +fi +# create sha256 checksum of image +( cd "${TARGET_IMG}" + sha256sum $(basename "${DISK}").gz > $(basename "${DISK}").gz.sha256 +) + +# cleanup +cleanup +exit diff --git a/scripts/uboot_helper b/scripts/uboot_helper new file mode 100755 index 000000000..c6402d04a --- /dev/null +++ b/scripts/uboot_helper @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +import sys + +devices = { +# 'project' : { +# 'device' : { +# 'board_name' : { 'dtb' : 'board_name.dtb', 'config' : 'board_name_defconfig' }, +# }, +# }, + 'Allwinner' : { + 'A64' : { + 'pine64' : { 'dtb' : 'sun50i-a64-pine64.dtb', 'config' : 'pine64_plus_defconfig' }, + 'pine64_plus' : { 'dtb' : 'sun50i-a64-pine64-plus.dtb', 'config' : 'pine64_plus_defconfig' }, + 'pine64_lts' : { 'dtb' : 'sun50i-a64-pine64-lts.dtb', 'config' : 'pine64-lts_defconfig' }, + 'orangepi_win' : { 'dtb' : 'sun50i-a64-orangepi-win.dtb', 'config' : 'orangepi_win_defconfig' }, + }, + 'H3' : { + 'bananapi_m2p' : { 'dtb' : 'sun8i-h3-bananapi-m2-plus.dtb', 'config' : 'bananapi_m2_plus_h3_defconfig' }, + 'beelink_x2' : { 'dtb' : 'sun8i-h3-beelink-x2.dtb', 'config' : 'beelink_x2_defconfig' }, + 'libretech_h3' : { 'dtb' : 'sun8i-h3-libretech-all-h3-cc.dtb', 'config' : 'libretech_all_h3_cc_h3_defconfig' }, + 'nanopi_m1' : { 'dtb' : 'sun8i-h3-nanopi-m1.dtb', 'config' : 'nanopi_m1_defconfig' }, + 'orangepi_2' : { 'dtb' : 'sun8i-h3-orangepi-2.dtb', 'config' : 'orangepi_2_defconfig' }, + 'orangepi_pc': { 'dtb': 'sun8i-h3-orangepi-pc.dtb', 'config': 'orangepi_pc_defconfig' }, + 'orangepi_pc_plus': { 'dtb': 'sun8i-h3-orangepi-pc-plus.dtb', 'config': 'orangepi_pc_plus_defconfig' }, + 'orangepi_plus2e': { 'dtb': 'sun8i-h3-orangepi-plus2e.dtb', 'config': 'orangepi_plus2e_defconfig' }, + 'orangepi_plus': { 'dtb': 'sun8i-h3-orangepi-plus.dtb', 'config': 'orangepi_plus_defconfig' }, + }, + 'H6' : { + 'pine_h64' : { 'dtb' : 'sun50i-h6-pine-h64.dtb', 'config' : 'pine_h64_defconfig' }, + 'orangepi_3' : { 'dtb' : 'sun50i-h6-orangepi-3.dtb', 'config' : 'orangepi_3_defconfig' }, + 'orangepi_one_plus' : { 'dtb' : 'sun50i-h6-orangepi-one-plus.dtb', 'config' : 'orangepi_one_plus_defconfig' }, + }, + }, + 'Rockchip' : { + 'MiQi' : { 'rk3288' : { 'dtb' : 'rk3288-miqi.dtb', 'config' : 'miqi-rk3288_config' }, }, + 'RG351P' : { + 'rg351p' : { 'dtb' : 'rk3326-rg351p-linux.dtb', 'config' : 'odroidgoa_defconfig' }, + 'rg351p-oc' : { 'dtb' : 'rk3326-rg351p-linux-oc.dtb', 'config' : 'odroidgoa_defconfig' }, + }, + 'RG351V' : { + 'rg351v' : { 'dtb' : 'rk3326-rg351v-linux.dtb', 'config' : 'odroidgoa_defconfig' }, + 'rg351v-oc' : { 'dtb' : 'rk3326-rg351v-linux-oc.dtb', 'config' : 'odroidgoa_defconfig' }, + }, + 'RG351MP' : { + 'rg351mp' : { 'dtb' : 'rk3326-rg351mp-linux.dtb', 'config' : 'odroidgoa_defconfig' }, + 'rg351mp-oc' : { 'dtb' : 'rk3326-rg351mp-linux-oc.dtb', 'config' : 'odroidgoa_defconfig' }, + }, + 'RG552' : { + 'rg552': { 'dtb': 'rk3399-rg552-linux.dtb', 'config': 'evb-rk3399_defconfig' }, + }, + 'RK3328' : { + 'box' : { 'dtb' : 'rk3328-box.dtb', 'config' : 'evb-rk3328_defconfig' }, + 'box-trn9' : { 'dtb' : 'rk3328-box-trn9.dtb', 'config' : 'evb-rk3328_defconfig' }, + 'box-z28' : { 'dtb' : 'rk3328-box-z28.dtb', 'config' : 'evb-rk3328_defconfig' }, + 'roc-cc' : { 'dtb' : 'rk3328-roc-cc.dtb', 'config' : 'evb-rk3328_defconfig' }, + 'rock64' : { 'dtb' : 'rk3328-rock64.dtb', 'config' : 'evb-rk3328_defconfig' }, + 'rockbox' : { 'dtb' : 'rk3328-rockbox.dtb', 'config' : 'evb-rk3328_defconfig' }, + }, + 'RK3399' : { + 'khadas-edge' : { 'dtb' : 'rk3399-khadas-edge.dtb', 'config' : 'evb-rk3399_config' }, + 'rock960' : { 'dtb' : 'rk3399-rock960.dtb', 'config' : 'evb-rk3399_config' }, + 'rock-pi-4' : { 'dtb' : 'rk3399-rock-pi-4.dtb', 'config' : 'evb-rk3399_config' }, + 'rockpro64' : { 'dtb' : 'rk3399-rockpro64.dtb', 'config' : 'evb-rk3399_config' }, + 'sapphire' : { 'dtb' : 'rk3399-sapphire.dtb', 'config' : 'evb-rk3399_config' }, + }, + 'rockpro64': { 'dtb': 'rk3399-rockpro64.dtb', 'config': 'evb-rk3399_defconfig'}, + 'TinkerBoard' : { 'rk3288' : { 'dtb' : 'rk3288-miniarm.dtb', 'config' : 'tinker-rk3288_config' }, }, + }, +} + +def usage(): + print(' '.join(['Usage:', sys.argv[0], '', '', '', 'dtb|config'])) + print(' '.join([' ', sys.argv[0], '', ''])) + print(' '.join([' ', sys.argv[0], '']) + '\n') + print('Projects:' + '\n') + for project in devices: + print(' ' + project + ':') + for soc in devices[project]: + print(' ' + soc + ':') + for board in devices[project][soc]: + print(' ' + board) + print('') + print('') + +# Get dtb or u-boot config for a given project, soc, and board +# ./scripts/uboot_helper project device board_name dtb +if len(sys.argv) == 5: + if sys.argv[1] in devices: + if sys.argv[2] in devices[sys.argv[1]]: + if sys.argv[3] in devices[sys.argv[1]][sys.argv[2]]: + if sys.argv[4] in ['dtb', 'config']: + print(devices[sys.argv[1]][sys.argv[2]][sys.argv[3]][sys.argv[4]]) + sys.exit(0) + +# List boards supported by a given project and soc +# ./scripts/uboot_helper project device +elif len(sys.argv) == 3: + if sys.argv[1] in devices: + if sys.argv[2] in devices[sys.argv[1]]: + boards = [] + for board in devices[sys.argv[1]][sys.argv[2]]: + boards.append(board) + print(' '.join(boards)) + sys.exit(0) + +# List socs supported by a given project +# ./scripts/uboot_helper project +elif len(sys.argv) == 2: + if sys.argv[1] in ['help', 'usage']: + usage() + elif sys.argv[1] in devices: + socs = [] + for soc in devices[sys.argv[1]]: + socs.append(soc) + print(' '.join(socs)) + sys.exit(0) + +# List projects +# ./scripts/uboot_helper +elif len(sys.argv) == 1: + projects = [] + for project in devices: + projects.append(project) + print(' '.join(projects)) + sys.exit(0) + +usage() diff --git a/scripts/unpack b/scripts/unpack new file mode 100755 index 000000000..365a589bb --- /dev/null +++ b/scripts/unpack @@ -0,0 +1,219 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2018 Team LibreELEC (https://libreelec.tv) +# Copyright (C) 2018-present Team CoreELEC (https://coreelec.org) + +. config/options "${1}" + +if [ -z "${1}" ]; then + die "usage: ${0} package_name [parent_pkg]" +fi + +if [ -z "${PKG_NAME}" ]; then + die "$(print_color CLR_ERROR "${1}: no package.mk file found")" +fi +PARENT_PKG="${2:-${PKG_NAME}}" + +pkg_lock "${PKG_NAME}" "unpack" "${PARENT_PKG}" + +${SCRIPTS}/get "${PKG_NAME}" + +if [ -n "${PKG_DEPENDS_UNPACK}" ]; then + for p in ${PKG_DEPENDS_UNPACK}; do + ${SCRIPTS}/unpack "${p}" "${PARENT_PKG}" + done +fi + +STAMP="${PKG_BUILD}/.libreelec-unpack" + +mkdir -p ${BUILD} + +# Perform a wildcard match on the package to ensure old versions are cleaned too +PKG_DEEPHASH= +for i in ${BUILD}/${PKG_NAME}-*; do + if [ -d ${i} -a -f "${i}/.libreelec-unpack" ] ; then + . "${i}/.libreelec-unpack" + if [ "${STAMP_PKG_NAME}" = "${PKG_NAME}" ]; then + [ -z "${PKG_DEEPHASH}" ] && PKG_DEEPHASH=$(calculate_stamp) + if [ ! "${PKG_DEEPHASH}" = "${STAMP_PKG_DEEPHASH}" ] ; then + ${SCRIPTS}/clean "${PKG_NAME}" + [ "${PKG_NAME}" = "linux" -a "${KERNEL_EXTRA_DEPENDS_TARGET}" = "device-trees-amlogic" ] && ${SCRIPTS}/clean "device-trees-amlogic" + fi + fi + fi +done + +if [ -d "${PKG_BUILD}" -a ! -f "${STAMP}" ]; then + # stale pkg build dir + ${SCRIPTS}/clean "${PKG_NAME}" +fi + +if [ -f "${STAMP}" ]; then + pkg_lock_status "UNLOCK" "${PKG_NAME}" "unpack" "already unpacked" + exit 0 +fi + +pkg_lock_status "ACTIVE" "${PKG_NAME}" "unpack" + +if [ -d "${SOURCES}/${PKG_NAME}" -o -d "${PKG_DIR}/sources" ] || pkg_call_exists unpack; then + build_msg "CLR_UNPACK" "UNPACK" "${PKG_NAME}" "indent" + + # unpack into a unique location as unpacking into a single ${BUILD} directory is not thread-safe + PKG_UNPACK_DIR="${BUILD}/.unpack/${PKG_NAME}" + rm -rf "${PKG_UNPACK_DIR}" + mkdir -p "${PKG_UNPACK_DIR}" + + # Save PKG_BUILD and point at our private unpack directory so that any + # modifications to the content of ${PKG_BUILD} will be "safe". + PKG_BUILD_ORIG="${PKG_BUILD}" + PKG_BUILD="${PKG_UNPACK_DIR}/${PKG_NAME}-${PKG_VERSION}" + + pkg_call_exists pre_unpack && pkg_call pre_unpack + + if pkg_call_exists unpack; then + pkg_call unpack + else + if [ -n "${PKG_URL}" ]; then + ${SCRIPTS}/extract "${PKG_NAME}" "${PKG_UNPACK_DIR}" + fi + fi + + if [ -z "${PKG_SOURCE_DIR}" -a -d "${PKG_UNPACK_DIR}/${PKG_NAME}-${PKG_VERSION}"* ]; then + mv "${PKG_UNPACK_DIR}/${PKG_NAME}-${PKG_VERSION}"* "${PKG_UNPACK_DIR}/.intermediate" + fi + + if [ ! -d "${PKG_UNPACK_DIR}/.intermediate" ]; then + if [ -n "${PKG_SOURCE_DIR}" ]; then + if [ -d "${PKG_UNPACK_DIR}"/${PKG_SOURCE_DIR} ]; then + mv "${PKG_UNPACK_DIR}"/${PKG_SOURCE_DIR} "${PKG_UNPACK_DIR}/.intermediate" + else + # fallback + mv "${BUILD}"/${PKG_SOURCE_DIR} "${PKG_UNPACK_DIR}/.intermediate" + fi + fi + fi + + [ ! -d "${PKG_UNPACK_DIR}/.intermediate" ] && mkdir -p "${PKG_UNPACK_DIR}/.intermediate" + + if [ -d "${PKG_DIR}/sources" ]; then + cp -PRf "${PKG_DIR}/sources/"* "${PKG_UNPACK_DIR}/.intermediate" + fi + + # Add a tag to the unpacked folder before transferring into the shared build folder + echo "INFO_PKG_NAME=\"${PKG_NAME}\"" > "${PKG_UNPACK_DIR}/.intermediate/.libreelec-package" + + # Restore original PKG_BUILD, and transfer the unpacked folder + PKG_BUILD="${PKG_BUILD_ORIG}" + rm -fr "${PKG_BUILD}" + mv "${PKG_UNPACK_DIR}/.intermediate" "${PKG_BUILD}" + + # cleanup + rm -rf "${PKG_UNPACK_DIR}" + + pkg_call_exists post_unpack && pkg_call post_unpack + + if [ "${PKG_SKIP_PATCHES}" != "yes" ]; then + pkg_call_exists pre_patch && pkg_call pre_patch + + if [ "${TARGET_ARCH}" = "x86_64" ]; then + PATCH_ARCH="x86" + else + #PATCH_ARCH="${TARGET_PATCH_ARCH:-${TARGET_ARCH}}" + PATCH_ARCH="${TARGET_ARCH}" + fi + + PATCH_DIRS_PKG="" + PATCH_DIRS_PRJ="" + if [ -n "${PKG_PATCH_DIRS}" ]; then + for patch_dir in ${PKG_PATCH_DIRS}; do + if [[ ${patch_dir} =~ ^/ ]]; then + [ -f ${patch_dir} ] && PATCH_DIRS_PKG+=" ${patch_dir}" + [ -d ${patch_dir} ] && PATCH_DIRS_PKG+=" ${patch_dir}/*.patch" + else + [ -d ${PKG_DIR}/patches/${patch_dir} ] && PATCH_DIRS_PKG+=" ${PKG_DIR}/patches/${patch_dir}/*.patch" + [ -d ${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${patch_dir} ] && PATCH_DIRS_PRJ+=" ${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${patch_dir}/*.patch" + [ -d ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/patches/${PKG_NAME}/${patch_dir} ] && PATCH_DIRS_PRJ+=" ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/patches/${PKG_NAME}/${patch_dir}/*.patch" + fi + done + fi + + for i in ${PKG_DIR}/patches/*.patch \ + ${PKG_DIR}/patches/${PATCH_ARCH}/*.patch \ + ${PATCH_DIRS_PKG} \ + ${PKG_DIR}/patches/${PKG_VERSION}/*.patch \ + ${PKG_DIR}/patches/${PKG_VERSION}/${PATCH_ARCH}/*.patch \ + ${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/*.patch \ + ${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${PATCH_ARCH}/*.patch \ + ${PATCH_DIRS_PRJ} \ + ${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${PKG_VERSION}/*.patch \ + ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/patches/${PKG_NAME}/*.patch; do + + thisdir="$(dirname "${i}")" + if [ "${thisdir}" = "${PKG_DIR}/patches" ]; then + PATCH_DESC="(common)" + elif [ "${thisdir}" = "${PKG_DIR}/patches/${PATCH_ARCH}" ]; then + PATCH_DESC="(common - ${PATCH_ARCH})" + elif [ "${thisdir}" = "${PKG_DIR}/patches/${PKG_VERSION}" ]; then + PATCH_DESC="(common - ${PKG_VERSION})" + elif [ "${thisdir}" = "${PKG_DIR}/patches/${PKG_VERSION}/${PATCH_ARCH}" ]; then + PATCH_DESC="(${PKG_VERSION} - ${PATCH_ARCH})" + elif [ "${thisdir}" = "${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}" ]; then + PATCH_DESC="(project)" + elif [ "${thisdir}" = "${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${PATCH_ARCH}" ]; then + PATCH_DESC="(project - ${PATCH_ARCH})" + elif [ "${thisdir}" = "${PROJECT_DIR}/${PROJECT}/patches/${PKG_NAME}/${PKG_VERSION}" ]; then + PATCH_DESC="(project - ${PKG_VERSION})" + elif [ "${thisdir}" = "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/patches/${PKG_NAME}" ]; then + PATCH_DESC="(device)" + else + if [[ "${thisdir}" =~ ^${PKG_DIR}/.* ]]; then + PATCH_DESC="(common - $(basename "${thisdir}"))" + elif [[ "${thisdir}" =~ ^${PROJECT_DIR}/.*/devices/.* ]]; then + PATCH_DESC="(device - $(basename "${thisdir}"))" + elif [[ "${thisdir}" =~ ^${PROJECT_DIR}/.* ]]; then + PATCH_DESC="(project - $(basename "${thisdir}"))" + else + PATCH_DESC="(absolute - ${i})" + fi + fi + + if [ -f "${i}" ]; then + build_msg "CLR_APPLY_PATCH" "APPLY PATCH $(print_color "CLR_PATCH_DESC" "${PATCH_DESC}")" "${i#${ROOT}/}" + if grep -qE '^GIT binary patch$|^rename from|^rename to' ${i}; then + cat ${i} | git apply --directory=$(echo "${PKG_BUILD}" | cut -f1 -d\ ) -p1 --verbose --whitespace=nowarn --unsafe-paths >&${VERBOSE_OUT} + else + cat ${i} | patch -d $(echo "${PKG_BUILD}" | cut -f1 -d\ ) -p1 >&${VERBOSE_OUT} + fi + fi + done + + pkg_call_exists post_patch && pkg_call post_patch + fi + + if [ ! "${PKG_NAME}" = "configtools" ] ; then + for config in $(find "${PKG_BUILD}" -name config.guess | sed 's/config.guess//'); do + build_msg "CLR_FIXCONFIG" "FIXCONFIG" "${config}" + + [ -f "${config}/config.guess" -a -f ${TOOLCHAIN}/configtools/config.guess ] && \ + cp -f ${TOOLCHAIN}/configtools/config.guess ${config} + [ -f "${config}/config.sub" -a -f ${TOOLCHAIN}/configtools/config.sub ] && \ + cp -f ${TOOLCHAIN}/configtools/config.sub ${config} + done + fi +fi + +if [ "${PKG_SECTION}" != "virtual" ]; then + mkdir -p "${PKG_BUILD}" + echo "INFO_PKG_NAME=\"${PKG_NAME}\"" > "${PKG_BUILD}/.libreelec-package" + + rm -f ${STAMPS}/${PKG_NAME}/build_* + + PKG_DEEPHASH=$(calculate_stamp) + for i in PKG_NAME PKG_DEEPHASH; do + echo "STAMP_${i}=\"${!i}\"" >> ${STAMP} + done +fi + +pkg_lock_status "UNLOCK" "${PKG_NAME}" "unpack" "unpacked" diff --git a/scripts/update_packages b/scripts/update_packages new file mode 100755 index 000000000..c56235d78 --- /dev/null +++ b/scripts/update_packages @@ -0,0 +1,65 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Fewtarius + +# Based on work by ToKe79 and Shanti Gilbert + +OPTIONS="distributions/JELOS/options" +DISTPACKAGE="packages/jelos/package.mk" +RAPACKAGES="retroarch retroarch-assets libretro-database core-info glsl-shaders" +EMUPACKAGES="$LIBRETRO_CORES advancemame PPSSPPSDL amiberry hatarisa openbor scummvmsa solarus lzdoom mupen64plussa-audio-sdl mupen64plussa-core mupen64plussa-input-sdl mupen64plussa-rsp-hle mupen64plussa-ui-console mupen64plussa-video-glide64mk2 mupen64plussa-video-rice" +BLOCKLIST="config/blocklist" + +source "${OPTIONS}" +source "${DISTPACKAGE}" + +if [ ! "${1}" ] +then + PACKAGES_ALL=" ${RAPACKAGES} ${LIBRETRO_CORES} ${EMUPACKAGES}" +else + PACKAGES_ALL="$*" +fi + +for p in $PACKAGES_ALL +do + PKG_PATH="./packages" + echo "Operating on ${p}" + f=$(find ${PKG_PATH} -wholename */${p}/package.mk) + if [ "$(grep ${p} ${BLOCKLIST})" ] + then + echo "Skipping ${p}" + continue + fi + echo "${p}: ${f}" + source config/options "${p}" + source "${f}" + PKG_SITE=$(echo ${PKG_URL} | sed 's/\/archive.*//g') + [ -n "${PKG_GIT_BRANCH}" ] && PKG_GIT_CLONE_BRANCH="${PKG_GIT_BRANCH}" + [ -n "${PKG_GIT_CLONE_BRANCH}" ] && GIT_HEAD="heads/${PKG_GIT_CLONE_BRANCH}" || GIT_HEAD="HEAD" + UPS_VERSION=`git ls-remote ${PKG_SITE} | grep ${GIT_HEAD}$ | awk '{ print substr($1,1,40) }'` + if [ "${UPS_VERSION}" == "${PKG_VERSION}" ]; then + echo "${PKG_NAME} is up to date (${UPS_VERSION})" + else + echo "${PKG_NAME} updated from ${PKG_VERSION} to ${UPS_VERSION}" + sed -i "s/PKG_VERSION=\"${PKG_VERSION}/PKG_VERSION=\"${UPS_VERSION}/" $f + fi + + if [ "${GET_HANDLER_SUPPORT}" != "git" ]; then + + if grep -q PKG_SHA256 "${f}"; then + echo "PKG_SHA256 exists on ${f}, clearing" + sed -i "s/PKG_SHA256=.*\$/PKG_SHA256=\"\"/" ${f} + else + echo "PKG_SHA256 does not exists on ${f}, creating" + sed -i -e "s/PKG_VERSION=\"${UPS_VERSION}\(.*\)\"/PKG_VERSION=\"${UPS_VERSION}\1\"\nPKG_SHA256=\"\"/g" ${f} + fi + source "${f}" + ./scripts/get "${PKG_NAME}" >/dev/null + if [ "${p}" != "linux" ]; then + SHA=$(cat ./sources/${PKG_NAME}/${PKG_NAME}-${UPS_VERSION}.*.sha256) + else + SHA=$(cat ./sources/${PKG_NAME}/linux-$LINUX-${UPS_VERSION}.tar.gz.sha256) + fi + sed -e "/PKG_VERSION=\"${UPS_VERSION}\"/{ N; s/PKG_VERSION=\"${UPS_VERSION}\".*PKG_SHA256=\"\"/PKG_VERSION=\"${UPS_VERSION}\"\nPKG_SHA256=\"${SHA}\"/;}" -i ${f} + fi +done diff --git a/tools/dashboard b/tools/dashboard new file mode 100755 index 000000000..b4af0df6e --- /dev/null +++ b/tools/dashboard @@ -0,0 +1,46 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +cd "$(readlink -f "$(dirname "$0")")/.." + +if [ -n "${PROJECT}" -a "$1" != "auto" ]; then + . config/options "" +fi + +_find_latest_tcdir() { + local IFS=$'\n' + + if [ -n "${THREAD_CONTROL}" ]; then + echo "${THREAD_CONTROL}" + else + for dir in $(ls -1td "${PWD}"/build.*/.threads 2>/dev/null); do + [ -f "${dir}/parallel.pid" ] && echo "${dir}" && break + done + fi + return 0 +} + +while [ : ]; do + echo "Waiting for build to start..." + + while [ : ]; do + tcdir="$(_find_latest_tcdir)" + + if [ -n "${tcdir}" ]; then + pid="$(cat "${tcdir}/parallel.pid" 2>/dev/null || true)" + [ -n "${pid}" ] && ps -p ${pid} &>/dev/null && break + fi + + sleep 1.0 + done + + if [ "${THREADCOUNT}" = "0" ]; then + tail -Fn+0 --pid=${pid} "${tcdir}/status" 2>/dev/null | grep -vE "STALLED|IDLE" + else + tail -Fn+0 --pid=${pid} "${tcdir}/status" 2>/dev/null + fi + + echo +done diff --git a/tools/docker/README.md b/tools/docker/README.md new file mode 100644 index 000000000..bb4b8dba4 --- /dev/null +++ b/tools/docker/README.md @@ -0,0 +1,26 @@ +# Build container + +## Clone repo + +_(You've likely already done this if you're reading this from a local repo...)_ + + - `git clone https://github.com/fewtarius/351ELEC.git 351ELEC` + +## Build the container + + - `cd 351ELEC` + - `docker build --pull -t 351elec-build tools/docker/ubuntu-focal` + +## Build image inside container + + - `docker run --rm -v "$(pwd)":/var/351elec-build -w /var/351elec-build 351elec-build make` + +### NOTE + +The build process requires a substantial amount of resources, for CPU cores, RAM, and disk volume space. + +While most of the process will simply scale with your available computer resources and power, the volume space is a pretty hard requirement. + +At the time of writing this, the build process alone took ~95GB of volume storage space. + +If you run into any errors such as "no space left on device" or similar, you'll likely need to tweak your Docker configuration to allow for more space to be allocated. diff --git a/tools/docker/aarch64/README.md b/tools/docker/aarch64/README.md new file mode 100644 index 000000000..4be133184 --- /dev/null +++ b/tools/docker/aarch64/README.md @@ -0,0 +1,68 @@ +# Build container on CoreELEC + +These instructions are for creating a Docker container and building a CoreELEC image on a device running CoreELEC. +If you are using another operating system, you should use the README.md one directory level up. + +* It is highly recommended to avoid building on a micro SD card, please use an external SSD/HDD or internal eMMC. +You may need to modify the paths provided in this guide (`~/ce-builder`, `/storage/.swapfile`) to suit your particular setup. +* A full build requires 40GB of free space. If you want to build add-ons, an additional 20GB of free space is required. + +## Install prerequisites + +* Install the `Services - Docker` add-on in Kodi. + +Log in to CoreELEC via SSH and run the following commands + +* `installentware` +* Type `y` when prompted to reboot. +* Stop Kodi to free up resources: `systemctl stop kodi` +* `opkg update` +* `opkg install git` + +## Create swap file + +You may need to create a swap file in order to avoid the system from locking up during the build process. +On S922X you will need a total of 6GB of memory, meaning a 2GB swap if your device has 4GB of RAM and 4GB swap if it has 2GB of RAM. +On S905* devices, you will need 4GB of memory, meaning no swap is necessary if your device has 4GB of RAM and 2GB swap is required if it has 2GB of RAM. +Run the following commands to create and activate a 2GB swap file. Change the `count` value to adjust the swap file size. + +```sh +dd if=/dev/zero of=/storage/.swapfile bs=1M count=2000 +chmod 600 /storage/.swapfile +mkswap /storage/.swapfile +swapon /storage/.swapfile +``` + +You can place the following code in `/storage/.config/autosart.sh` to make the swap file persist across reboots. + +```sh +#!/bin/bash + +if [ ! -f /storage/.swapfile ]; then + dd if=/dev/zero of=/storage/.swapfile bs=1M count=2000 + chmod 600 /storage/.swapfile +fi +mkswap /storage/.swapfile +swapon /storage/.swapfile +``` + +## Prepare your environment + +* If you are using an external (USB) drive, you need to mount it with execute permissions: +`mount -o remount,exec /path-to-external-drive-partition` +* `mkdir -p ~/ce-builder` +* `cd ~/ce-builder` +* `git clone git://github.com/CoreELEC/CoreELEC.git CoreELEC` +* `chown -R 1000 ~/ce-builder` + +## Build the container + +* `cd ~/ce-builder/CoreELEC` +* `docker build --pull -t coreelec tools/docker/aarch64/bionic` + +## Build image inside container + +* `docker run -v ~/ce-builder:/home/docker -h coreelec -it coreelec` +* `cd ~/CoreELEC` +* `time(PROJECT=Amlogic-ng ARCH=arm make image)` +Use `PROJECT=Amlogic` to build images for older S912 and S905/X/D devices diff --git a/tools/docker/aarch64/bionic/Dockerfile b/tools/docker/aarch64/bionic/Dockerfile new file mode 100644 index 000000000..1f00f5043 --- /dev/null +++ b/tools/docker/aarch64/bionic/Dockerfile @@ -0,0 +1,33 @@ +FROM arm64v8/ubuntu:bionic + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get dist-upgrade -y \ + && apt-get install -y locales sudo \ + && rm -rf /var/lib/apt/lists/* + +RUN locale-gen en_US.UTF-8 \ + && update-locale LANG=en_US.UTF-8 LANGUAGE=en_US:en +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +RUN adduser --disabled-password --gecos '' docker \ + && adduser docker sudo \ + && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +RUN apt-get update && apt-get install -y \ + wget bash bc gcc sed patch patchutils tar bzip2 gzip perl gawk gperf zip unzip diffutils texinfo lzop python python3 \ + g++ xfonts-utils xfonts-utils xfonts-utils xsltproc default-jre-headless \ + libc6-dev libncurses5-dev \ + u-boot-tools \ + xz-utils make file libxml-parser-perl \ + libjson-perl \ + golang-go \ + git openssh-client \ + qemu-user-binfmt \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +USER docker diff --git a/tools/docker/ubuntu-focal/Dockerfile b/tools/docker/ubuntu-focal/Dockerfile new file mode 100644 index 000000000..df617fdfa --- /dev/null +++ b/tools/docker/ubuntu-focal/Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:focal + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get dist-upgrade -y \ + && apt-get install -y locales sudo \ + && rm -rf /var/lib/apt/lists/* + +RUN locale-gen en_US.UTF-8 \ + && update-locale LANG=en_US.UTF-8 LANGUAGE=en_US:en +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +RUN adduser --disabled-password --gecos '' docker \ + && adduser docker sudo \ + && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +RUN apt-get update && apt-get install -y \ + bash bc binutils bsdmainutils build-essential bzip2 cmake cpp curl \ + default-jre default-jre-headless device-tree-compiler diffutils dpkg-dev \ + file fonts-droid-fallback g++ g++-multilib gawk gcc gcc-7 git golang \ + golang-go gperf gzip libasound2-dev libboost-all-dev libc-dev libc6-dev \ + libcurl4-openssl-dev libfreeimage-dev libfreetype6-dev libgl1-mesa-dev \ + libjson-perl libncurses5-dev libsdl2-dev libsdl2-mixer-dev libssl-dev \ + libvlc-dev libvlccore-dev libxml-parser-perl libzip-dev lzop make \ + openssh-client p7zip patch patchelf patchutils perl premake4 python \ + python3 rapidjson-dev rsync sed tar texinfo u-boot-tools unzip vlc-bin \ + wget xfonts-utils xmlstarlet xsltproc xz-utils zip libparse-yapp-perl \ + unrar \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +USER docker diff --git a/tools/pkgcheck b/tools/pkgcheck new file mode 100755 index 000000000..55282dc9b --- /dev/null +++ b/tools/pkgcheck @@ -0,0 +1,165 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) + +TXRED="$(tput setaf 1 bold)" +TXGREEN="$(tput setaf 2 bold)" +TXYELLOW="$(tput setaf 3 bold)" +TXBLUE="$(tput setaf 4 bold)" +TXMAGENTA="$(tput setaf 5 bold)" +TXCYAN="$(tput setaf 6 bold)" +TXRESET="$(tput sgr0)" +TXCLR="$(tput el)" + +log() { + local filename="$1" lc=$2 level="$3" msg="$4" data="$5" + local txcolour flc colw + + [ "${level}" = "FAIL" ] && txcolour="${TXRED}" || txcolour="${TXYELLOW}" + [[ ${filename} =~ ^\./ ]] && filename="${filename:2}" + [ ${lc} -eq 0 ] && flc="---" || flc="$(printf "%03d" ${lc})" + [[ ${filename} =~ packages/addons/addon-depends ]] && colw=80 || colw=50 + + printf "[%s] %3s: %-*s: %-25s: %s\n" "${txcolour}${level}${TXRESET}" "${flc}" ${colw} "${filename}" "${msg}" "${data}" +} + +process_line() { + local filename="$1" lc="$2" line="$3" inassign="$4" funcname="$5" + local var matches assignallowed=Y + + if [ -n "${funcname}" -a "${funcname}" != "configure_package" -a "${inassign}" = "Y" ]; then + if [[ ${line} =~ PKG_DEPENDS_.*= ]]; then + log "${filename}" ${lc} "WARN" "ignored depends assign" "${funcname}() => ${line//[[:space:]]*PKG_DEPENDS_/PKG_DEPENDS_}" + fi + fi + + [ -n "${funcname}" ] && return 0 + + rightside="${line#*=}" + + for var in PKG_SHORTDESC PKG_LONGDESC PKG_IS_ADDON PKG_NEED_UNPACK PKG_SOURCE_NAME PKG_ADDON_IS_STANDALONE \ + PKG_CONFIGURE_SCRIPT PKG_CMAKE_SCRIPT PKG_MESON_SCRIPT \ + PKG_DIR PKG_ADDON_ID PKG_BUILD \ + DESTIMAGE CC CXX CPP LD AS AR NM \ + RANLIB OBJCOPY OBJDUMP STRIP \ + CPPFLAGS CFLAGS CXXFLAGS LDFLAGS \ + PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PKG_CONFIG_SYSROOT_DIR PKG_CONFIG_ALLOW_SYSTEM_CFLAGS PKG_CONFIG_ALLOW_SYSTEM_LIBS \ + CMAKE_CONF CMAKE \ + HOST_CC HOST_CXX HOSTCC HOSTCXX \ + CC_FOR_BUILD CXX_FOR_BUILD BUILD_CC BUILD_CXX \ + _python_sysroot _python_prefix _python_exec_prefix \ + TARGET_CONFIGURE_OPTS CMAKE_GENERATOR_NINJA TARGET_CMAKE_OPTS TARGET_MESON_OPTS \ + HOST_CONFIGURE_OPTS HOST_CMAKE_OPTS HOST_MESON_OPTS \ + INIT_CONFIGURE_OPTS INIT_CMAKE_OPTS INIT_MESON_OPTS \ + BOOTSTRAP_CONFIGURE_OPTS BOOTSTRAP_CMAKE_OPTS BOOTSTRAP_MESON_OPTS \ + ; do + + # After PKG_DIR, treat assigns to var as invalid + [ "${var}" = "PKG_DIR" ] && assignallowed=N + + if [ "${assignallowed}" = "N" ]; then + if [[ ${line} =~ (^|[[:space:]])${var}= ]]; then + [ "${inassign}" = "N" ] && matches+=", assign to ${var}" + fi + fi + + if [[ ${line} =~ \$\{${var}} ]] || [[ ${line} =~ \$${var}[^A-Za-z0-9_] ]]; then + matches+=", ref ${var}" + fi + + if [[ ${line} =~ (^|[[:space:]])unset\ ${var}($|[[:space:]]) ]]; then + matches+=", unset ${var}" + fi + done + + [ -n "${matches}" ] && log "${filename}" ${lc} "FAIL" "late binding violation" "${matches:2}" +} + +init_target_funcs() { + local f t funcs + + for t in target host init bootstrap; do + for f in pre_build \ + pre_configure configure post_configure \ + pre_make make post_make \ + pre_makeinstall makeinstall post_makeinstall \ + ; do + funcs+=" ${f}_${t}" + done + done + echo "${funcs:1}" +} + +check_func_name() { + local filename="$1" lc="$2" line="$3" + local f + + for f in configure_package \ + pre_unpack unpack post_unpack \ + pre_patch post_patch \ + pre_configure \ + ${TARGET_FUNCS} \ + pre_install post_install \ + addon \ + ; do + [[ ${line} =~ ^${f} ]] && return 0 + done + + log "${filename}" ${lc} "WARN" "unknown function" "${line// *{*/}" +} + +process_pkg() { + local filename="$1" + local lc=0 isassign=N funcname= fc=0 intertwined=N + + while IFS= read -r line; do + lc=$((lc + 1)) + [[ ${line} =~ ^[[:space:]]*$ ]] && continue + [[ ${line} =~ ^(|[[:space:]]*)# ]] && continue + + if [[ "${line}" =~ ^[^#]*\(\)[[:space:]]*$ ]]; then + log "${filename}" ${lc} "FAIL" "bad func - missing brace" "${line}" + fi + + if [[ "${line}" =~ \(\)[[:space:]]*\{ ]]; then + funcname="${line//(*/}" + fc=$((fc+1)) + check_func_name "${filename}" "${lc}" "${line}" + fi + + if [ "${intertwined}" = "N" -a -z "${funcname}" -a ${fc} -ge 1 ]; then + log "${filename}" ${lc} "WARN" "intertwined vars & funcs" "${line}" + intertwined=Y + fi + + [[ "${line}" =~ ^[[:space:]]*PKG_.*=\" ]] && isassign=Y + + process_line "$1" "${lc}" "${line}" "${isassign}" "${funcname}" + + [[ "${line}" =~ (\"$|\"[[:space:]]*$|\"[[:space:]]*#.*$) ]] && isassign=N + [[ "${line}" =~ (^}|^[[:space:]]*}) ]] && funcname= + done < "${filename}" + + # Duplicate function check + while read -r count line; do + [ -n "${line}" ] && log "${filename}" 0 "FAIL" "duplicate function def" "${line}" + done <<< "$(grep -E ".*() {" "${filename}" | sed 's/[[:space:]]*{.*//' | sort | uniq -c | grep -v ^[[:space:]]*1[[:space:]])" +} + +TARGET_FUNCS="$(init_target_funcs)" + +if [ $# -ne 0 ]; then + for arg in ${@}; do + for p in $(find packages projects -type f -path */${arg}/package.mk | sort); do + echo -en "${TXCLR}${p}...\r" >&2 + process_pkg "${p}" + done + done +else + for p in $(find packages projects -type f -name package.mk | sort); do + echo -en "${TXCLR}${p}...\r" >&2 + process_pkg "${p}" + done +fi +echo -en "${TXCLR}" >&2 diff --git a/tools/pkginfo b/tools/pkginfo new file mode 100755 index 000000000..bcdd66484 --- /dev/null +++ b/tools/pkginfo @@ -0,0 +1,27 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +STRIP=no +if [ "$1" = "--strip" -o "$1" = "-s" ]; then + shift + STRIP=yes +fi + +. config/options "$1" + +shift + +echo "PROJECT=${PROJECT}, DEVICE=${DEVICE}, ARCH=${ARCH}" + +for v in PKG_NAME PKG_VERSION PKG_SITE PKG_URL PKG_DIR \ + PKG_NEED_UNPACK PKG_DEPENDS_UNPACK \ + PKG_DEPENDS_BOOTSTRAP PKG_DEPENDS_INIT PKG_DEPENDS_HOST PKG_DEPENDS_TARGET \ + PKG_IS_ADDON PKG_IS_KERNEL_PKG $@; do + if [ "${STRIP}" = "yes" ]; then + echo "${v}=\"${!v}\"" | sed "s#${ROOT}/##g" + else + echo "${v}=\"${!v}\"" + fi +done diff --git a/tools/sync b/tools/sync new file mode 100755 index 000000000..ecf6dd5d1 --- /dev/null +++ b/tools/sync @@ -0,0 +1,16 @@ +#!/bin/bash +HOST="www.jelos.org" +USER="root" +WWWPATH="/var/www/html/releases" + +if [ ! -z "${ARCH}" ] || [ ! -z "${DEVICE}" ] || [ ! -z "${DISTRO}" ] +then + export DISTRO=JELOS + export ARCH=aarch64 + export DEVICE=RG552 +fi + +ssh ${USER}@${HOST} mkdir -p ${WWWPATH}/${DEVICE}/{distribution,sources} +ssh ${USER}@${HOST} rm -f ${WWWPATH}/${DEVICE}/distribution/* +rsync -av --delete --progress --stats release/${ARCH}/${DEVICE}/{*img*,*tar*} ${USER}@${HOST}:${WWWPATH}/${DEVICE}/distribution/ +rsync -av --delete --progress --stats --exclude="j/jelos-*" --include="*.tar.gz" build.${DISTRO}-${DEVICE}.${ARCH}-sources/* ${USER}@${HOST}:${WWWPATH}/${DEVICE}/sources diff --git a/tools/viewplan b/tools/viewplan new file mode 100755 index 000000000..09fdc889b --- /dev/null +++ b/tools/viewplan @@ -0,0 +1,29 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) + +unset _CACHE_PACKAGE_LOCAL _CACHE_PACKAGE_GLOBAL _DEBUG_DEPENDS_LIST _DEBUG_PACKAGE_LIST + +. config/options "" +. config/multithread + +# Fake the parallel command if GNU parallel is not available - slow, but works. +fake_parallel() { + while read -r line; do + json_worker "${line}" + done +} + +PARALLEL_BIN=${TOOLCHAIN}/bin/parallel + +[ -x ${PARALLEL_BIN} ] || PARALLEL_BIN=parallel +command -v ${PARALLEL_BIN} >/dev/null || PARALLEL_BIN=fake_parallel + +# pipefail: return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status +set -o pipefail + +cat ${_CACHE_PACKAGE_GLOBAL} ${_CACHE_PACKAGE_LOCAL} | \ + ${PARALLEL_BIN} --plain --no-notice --max-args 30 --halt now,fail=1 json_worker | \ + ${SCRIPTS}/genbuildplan.py --no-reorder --show-wants --build ${@:-image} --warn-invalid ${GENFLAGS} || \ + die "FAILURE: Unable to generate plan"

      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%0Awg+UYIUP- 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/retrorun.jpg b/metadata/RG351V/packages/retrorun.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c38db10a59393c0c1f265a7fe20e93dbda48365e GIT binary patch literal 22115 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/smw.jpg b/metadata/RG351V/packages/smw.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4db91b817e4df5d48d7473a1913d5aaddc636f GIT binary patch literal 31434 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/solarus.jpg b/metadata/RG351V/packages/solarus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b6676b4f333977584694beb0ffcdd96ea454d37 GIT binary patch literal 32114 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/supertux.jpg b/metadata/RG351V/packages/supertux.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d91e99f5992acdf692829bf59b719cf1a836fff3 GIT binary patch literal 30092 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 K0Q5)wga6ro?M5pA literal 0 HcmV?d00001 diff --git a/metadata/RG351V/packages/uqm.jpg b/metadata/RG351V/packages/uqm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..983d5f22260cf645164c03c5b0e0df8bda87900f GIT binary patch literal 37461 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%0Awg+UYIUP- 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/retrorun.jpg b/metadata/RG351P/packages/retrorun.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c38db10a59393c0c1f265a7fe20e93dbda48365e GIT binary patch literal 22115 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/smw.jpg b/metadata/RG351P/packages/smw.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4db91b817e4df5d48d7473a1913d5aaddc636f GIT binary patch literal 31434 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/solarus.jpg b/metadata/RG351P/packages/solarus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b6676b4f333977584694beb0ffcdd96ea454d37 GIT binary patch literal 32114 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/supertux.jpg b/metadata/RG351P/packages/supertux.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d91e99f5992acdf692829bf59b719cf1a836fff3 GIT binary patch literal 30092 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 K0Q5)wga6ro?M5pA literal 0 HcmV?d00001 diff --git a/metadata/RG351P/packages/uqm.jpg b/metadata/RG351P/packages/uqm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..983d5f22260cf645164c03c5b0e0df8bda87900f GIT binary patch literal 37461 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Airen.jpg b/metadata/RG351P/themes/Airen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c06646d050e123d1a78ed13e1d06af379aa070a5 GIT binary patch literal 41246 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 literal 0 HcmV?d00001 diff --git a/metadata/RG351P/themes/Alekfull.jpg b/metadata/RG351P/themes/Alekfull.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59df3438669a6ac9e5dcecff3523dafb1f4c0778 GIT binary patch literal 61149 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